diff --git a/docs/volto_customization/blocks.md b/docs/volto_customization/blocks.md
index e8f3f698c..e070bacd8 100644
--- a/docs/volto_customization/blocks.md
+++ b/docs/volto_customization/blocks.md
@@ -7,10 +7,10 @@ myst:
"keywords": "Volto, Training, Extend block"
---
-# Extend volto blocks
+# Extend Volto blocks
There are various ways of extending Volto blocks.
-Component shadowing (see last chapter) is a very basic to customize components in volto.
+Component shadowing (see last chapter) is a very basic to customize components in Volto.
But it comes with its own problems like keeping the shadowed component up to date with latest fixes and features of newer Volto versions.
Instead of shadowing components we can:
@@ -18,10 +18,10 @@ Instead of shadowing components we can:
- Extend blocks by adding new block-variations
- Write add schemaEnhancer to modify blocks schema
-Let us first change the View of the teaser block which we already have in volto core by changing the block-configuration.
-In our addon `volto-teaser-tutorial` we will step by step extend each component that we have in volto core.
+Let us first change the View of the teaser block which we already have in Volto core by changing the block-configuration.
+In our add-on `volto-teaser-tutorial` we will step by step extend each component that we have in Volto core.
-The most simple customization is the View of the Teaser. The volto core teaser block configration (in `omelette/src/config/Blocks.jsx`) looks like:
+The most simple customization is the View of the Teaser. The Volto core teaser block configration (in `/frontend/core/packages/volto/src/config/Blocks.jsx`) looks like:
```js
teaser: {
@@ -48,7 +48,7 @@ The most simple customization is the View of the Teaser. The volto core teaser b
```
Every block in Volto has Edit and View components.
-You can customize these individually by either shadowing or directly in the confuguration (`index.js` of your addon) like this:
+You can customize these individually by either shadowing or directly in the confuguration (`index.js` of your add-on) like this:
```js
import MyTeaserView from "volto-teaser-tutorial/components/Blocks/Teaser/View";
@@ -61,11 +61,10 @@ const applyConfig = (config) => {
export default applyConfig;
```
-Of course we need to add our custom `MyTeaserView` component in our addon.
-From the root of the project that is `src/addon/volto-teaser-tutorial/src/components/Blocks/Teaser/View.jsx`:
+Of course we need to add our custom `MyTeaserView` component in our add-on.
+From the root of the project that is `packages/volto-teaser-tutorial/src/components/Blocks/Teaser/View.jsx`:
```jsx
-import React from "react";
import TeaserBody from "@plone/volto/components/manage/Blocks/Teaser/Body";
import { withBlockExtensions } from "@plone/volto/helpers";
diff --git a/docs/volto_customization/custom_block.md b/docs/volto_customization/custom_block.md
index bb8537822..b3889b426 100644
--- a/docs/volto_customization/custom_block.md
+++ b/docs/volto_customization/custom_block.md
@@ -9,9 +9,9 @@ myst:
# Volto Weather Block (custom block)
-Let's create a volto block that will display weather information for Eibar. For this we can use Open-Meteo API. Open-Meteo is an open-source weather API and offers free access for non-commercial use. No API key required.
+Let's create a Volto block that will display weather information for Brasilia. For this we can use [Open-Meteo API](https://open-meteo.com/). Open-Meteo is an open-source weather API and offers free access for non-commercial use. No API key required.
-Creating a basic block in Volto involves several steps. Below, I'll outline the steps to create a Volto block that displays the weather forecast in Eibar.
+Creating a basic block in Volto involves several steps. Below, I'll outline the steps to create a Volto block that displays the weather forecast in Brasilia.
1. **Setup Your Volto Project:** If you haven't already, set up a Volto project. You can use the instructions presented in [Installation -> Bootstrap a new Volto project](installation.md) section.
@@ -47,7 +47,7 @@ export const weatherBlockSchema = (props) => {
location: {
title: "Location",
description:
- "Enter the name of the location for which you want to display the weather (e.g., Eibar, Basque Country).",
+ "Enter the name of the location for which you want to display the weather (e.g., Brasilia, Brazil).",
widget: "text",
},
},
@@ -65,12 +65,12 @@ import React, { useEffect, useState } from "react";
const View = (props) => {
const { data = {} } = props;
- const location = data.location || "Eibar, Basque Country";
+ const location = data.location || "Brasilia, Brazil";
const [weatherData, setWeatherData] = useState(null);
useEffect(() => {
- const latitude = data.latitude || "43.1849"; // Default Eibar latitude if no latitude is provided
- const longitude = data.longitude || "-2.4716"; // Default to longitude if no longitude is provided
+ const latitude = data.latitude || "-15.7797"; // Default latitude if no latitude is provided
+ const longitude = data.longitude || "-47.9297"; // Default to longitude if no longitude is provided
const abortController = new AbortController(); // creating an AbortController
diff --git a/docs/volto_customization/data_adapters.md b/docs/volto_customization/data_adapters.md
index 444df07da..6358f8114 100644
--- a/docs/volto_customization/data_adapters.md
+++ b/docs/volto_customization/data_adapters.md
@@ -70,7 +70,7 @@ We can register our own dataAdapter in place of this by maintaining the same def
In order for dataAdapters to work make sure the code of your block allows and consumes it in its implementation.
```
-The above Adapter gets consumed in Data component of teaser block.
+The above Adapter gets consumed in [`Data`](https://github.com/plone/volto/blob/9667cf735e5c3e848de852d615941d98193e0a5e/src/components/manage/Blocks/Teaser/Data.jsx#L47) component of teaser block.
Let's register a new `dataAdapter` our config:
diff --git a/docs/volto_customization/extending_teasers.md b/docs/volto_customization/extending_teasers.md
deleted file mode 100644
index c2339cb1c..000000000
--- a/docs/volto_customization/extending_teasers.md
+++ /dev/null
@@ -1,594 +0,0 @@
----
-myst:
- html_meta:
- "description": "How to support extensions per teaser block"
- "property=og:description": "How to support extensions per teaser block"
- "property=og:title": "Block Extensions"
- "keywords": "Volto, Block, Variations"
----
-
-# Extending Teasers per type
-
-The basic scenario is to add variations to a block so that it can give control over its look and feel. Sometimes its also possible for a need to have control over individual elements. For instance, Consider we have a teaaser grid in which we can have a base variation of its layout. Then we would left with styling and adjusting individual teasers. This is where extensions come into play.
-
-In this chapter we will tweak our newly created variation to also support extensions per teaser block and then later we will add grid support to teasers.
-
-## Block Extensions
-
-Block extensions are the way to display a new form of your block for a particular block type. For instance if you have a teaserGrid, with block extensions you can control the styling and behaviour of individual teasers. The split of responsibilites is as follows: "the variation will control how the teasers layout and extension will control the individual rendering."
-
-We already learn about the block variation in the former chapters. We will now add the teaser block extensions the same way we do for variations.
-
-```js
-import TeaserBlockImageDefault from "volto-teaser-tutorial/components/extensions/TeaserBlockImageDefault";
-import TeaserBlockImageRight from "volto-teaser-tutorial/components/extensions/TeaserBlockImageRight";
-import TeaserBlockImageOverlay from "volto-teaser-tutorial/components/extensions/TeaserBlockImageOverlay";
-
-config.blocks.blocksConfig.teaser.extensions = {
- ...(config.blocks.blocksConfig.teaser.extensions || {}),
- cardTemplates: {
- items: [
- {
- id: "card",
- isDefault: true,
- title: "Card (default)",
- template: TeaserBlockImageDefault,
- },
- {
- id: "imageOnRight",
- isDefault: false,
- title: "Image Right",
- template: TeaserBlockImageRight,
- },
- {
- id: "imageOverlay",
- isDefault: false,
- title: "Image Overlay",
- template: TeaserBlockImageOverlay,
- },
- ],
- },
-};
-```
-
-As for the training we created only three extensions namely `TeaserBlockImageDefault`, `TeaserBlockImageRight` and `TeaserBlockImageOverlay` into our addons `components/extensions` folder.
-
-In order to support these extension first we need to add a special fieldset to our variation schema so that we can seperate the concerns about individual teasers and put these extensions under it.
-
-Luckily, In order to do that we have a helper in volto which automatic adds a select field where we want in the schema to display variations/extensions from a particualar block. As its a standalone method we can also add a variation from a completely different block like we do in SearchBlock in volto.
-
-Go ahead and register that in index.js in our variation schemaEnhancer:
-
-```jsx
-import { addExtensionFieldToSchema } from '@plone/volto/helpers/Extensions/withBlockSchemaEnhancer';
-
-config.blocks.blocksConfig.teaser.variations = [
- ...config.blocks.blocksConfig.teaser.variations,
- {
- id: 'image-top-variation',
- title: 'Image(Top) variation',
- template: TeaserBlockImageVariation,
- isDefault: false,
- schemaEnhancer: ({ schema, FormData, intl }) => {
- const extension = 'cardTemplates';
- schema.fieldsets.push({
- id: 'Cards',
- title: 'Cards',
- fields: [],
- });
- addExtensionFieldToSchema({
- schema,
- name: extension,
- items: config.blocks.blocksConfig.teaser.extensions[extension]?.items,
- intl,
- title: { id: 'Card Type' },
- insertFieldToOrder: (schema, extension) => {
- const cardFieldSet = schema.fieldsets.find(
- (item) => item.id === 'Cards',
- ).fields;
- if (cardFieldSet.indexOf(extension) === -1)
- cardFieldSet.unshift(extension);
- },
- });
- ...
-```
-
-Notice first we added a new fieldSet where our extensions will recide and the method `addExtensionFieldToSchema` imported volto core. This method as mentioned above adds a new field in the given fieldSet with the given extenionName `cardTemplates`.
-
-```{note}
-By default `addExtensionFieldToSchema` adds the extewnsion field to default fieldSet, in order to ovverride that you can pass `insertFieldToOrder` method to specifiy where it should be added.
-
-```
-
-Woot. We will now have our extensions loaded into the schema. We will have to refactor our intial Variation code to adapt the extension now.
-
-```{note}
-The concept of extensions are only possible if the code of your block allows it. That is the reason why we created a variation out of a teaser block at the first place.
-```
-
-So our `TeaserBlockImageVariation` can be simplified now as:
-
-```jsx
-import React from "react";
-import PropTypes from "prop-types";
-import { useIntl } from "react-intl";
-import cloneDeep from "lodash/cloneDeep";
-import config from "@plone/volto/registry";
-
-const TeaserBlockImageVariation = (props) => {
- const { data, extension = "cardTemplates" } = props;
- const intl = useIntl();
-
- const teaserExtenstions =
- config.blocks.blocksConfig?.teaser?.extensions[extension].items;
- let activeItem = teaserExtenstions.find(
- (item) => item.id === data[extension]
- );
- const extenionSchemaEnhancer = activeItem?.schemaEnhancer;
- if (extenionSchemaEnhancer)
- extenionSchemaEnhancer({
- schema: cloneDeep(config.blocks.blocksConfig?.teaser?.blockSchema),
- data,
- intl,
- });
- const ExtensionToRender = activeItem?.template;
-
- return ExtensionToRender ? (
-
-
-
- ) : null;
-};
-
-TeaserBlockImageVariation.propTypes = {
- data: PropTypes.objectOf(PropTypes.any).isRequired,
- isEditMode: PropTypes.bool,
-};
-
-export default TeaserBlockImageVariation;
-```
-
-We have added the "active extension" logic to this code and removed the templating code to their individual components under `extensions/` folder.
-Notice that we can also add more schema Enhancers to our base variation schema if each extensions can provide it.
-
-The `ExtensionToRender` will be selected extensions from `extensions/` folder.
-
-Create a folder named `extensions/` within `components` and add three components provided below:
-
-TeaserBlockImageDefault:
-
-```jsx
-import React from "react";
-import PropTypes from "prop-types";
-import { Message } from "semantic-ui-react";
-import { defineMessages, useIntl } from "react-intl";
-
-import imageBlockSVG from "@plone/volto/components/manage/Blocks/Image/block-image.svg";
-
-import {
- flattenToAppURL,
- isInternalURL,
- addAppURL,
-} from "@plone/volto/helpers";
-import { MaybeWrap } from "@plone/volto/components";
-import { formatDate } from "@plone/volto/helpers/Utils/Date";
-import { UniversalLink } from "@plone/volto/components";
-import cx from "classnames";
-import config from "@plone/volto/registry";
-
-const messages = defineMessages({
- PleaseChooseContent: {
- id: "Please choose an existing content as source for this element",
- defaultMessage:
- "Please choose an existing content as source for this element",
- },
-});
-
-const DefaultImage = (props) => ;
-
-const TeaserBlockImageDefault = (props) => {
- const { className, data, isEditMode } = props;
- const locale = config.settings.dateLocale || "en";
- const intl = useIntl();
- const href = data.href?.[0];
- const image = data.preview_image?.[0];
- const align = data?.styles?.align;
- const creationDate = data.href?.[0]?.CreationDate;
- const formattedDate = formatDate({
- date: creationDate,
- format: {
- year: "numeric",
- month: "short",
- day: "2-digit",
- },
- locale: locale,
- });
-
- const Image = config.getComponent("Image").component || DefaultImage;
- const { openExternalLinkInNewTab } = config.settings;
-
- return (
-
- );
-};
-
-TeaserBlockImageOverlay.propTypes = {
- data: PropTypes.objectOf(PropTypes.any).isRequired,
- isEditMode: PropTypes.bool,
-};
-
-export default TeaserBlockImageOverlay;
-```
-
-The styles have to be added as well:
-
-```{code-block} less
-:force: true
-.gradiant {
- h2 {
- color: white;
- }
- position: absolute;
- bottom: 30px;
- display: flex;
- width: 100%;
- height: 200px;
- align-items: flex-end;
- padding: 1.5rem;
- background-image: linear-gradient(
- 13.39deg,
- rgba(46, 62, 76, 0.65) 38.6%,
- rgba(46, 62, 76, 0.169) 59.52%,
- rgba(69, 95, 106, 0) 79.64%
- );
-}
-
-.teaser-item.overlay {
- display: flex;
-
- .image-wrapper {
- width: 100%;
- }
-}
-
-.has--objectFit--contain {
- img {
- object-fit: contain !important;
- }
-}
-
-.has--objectFit--cover {
- img {
- object-fit: cover !important;
- }
-}
-
-.has--objectFit--fill {
- img {
- object-fit: fill !important;
- }
-}
-
-.has--objectFit--scale-down {
- img {
- object-fit: scale-down !important;
- }
-}
-```
-
-Great. We now have extension per teaser in our block which controls each item individually.
-
-## Grid support to Teasers
-
-As mentioned before we will configure the grid-block to also use our extended teaser-block.
-We need to override the grid-block configuration with our teaser block.
-
-In your volto-teaser-tutorial addon's `index.js`:
-
-```js
-//This ensures that grid block uses our overridden teaser
-config.blocks.blocksConfig.gridBlock.blocksConfig.teaser =
- config.blocks.blocksConfig.teaser;
-```
-
-Woot. We will now have a grid block with our teaser variations so that each teaser can now have its own set of extensions.
diff --git a/docs/volto_customization/index.md b/docs/volto_customization/index.md
index e8c55a48d..b30c67b30 100644
--- a/docs/volto_customization/index.md
+++ b/docs/volto_customization/index.md
@@ -55,8 +55,6 @@ schema
teaser_variations
data_adapters
styling
-extending_teasers
-listing_block
```
diff --git a/docs/volto_customization/installation.md b/docs/volto_customization/installation.md
index 128ebd9d5..92959f329 100644
--- a/docs/volto_customization/installation.md
+++ b/docs/volto_customization/installation.md
@@ -17,150 +17,125 @@ Getting started with Volto involves setting up a development environment, unders
## Prerequisites
-Before you start working with Volto, ensure you have the following prerequisites:
-
-- Node.js LTS (16.x) - (see instructions for installation)
-- Python - See below for specific versions.
-- Docker (if using the Plone docker images - see instructions for installation and usage)
-
-The versions of Python that are supported in Volto depend on the version of Plone that you use.
-
-| Plone | Python | Volto |
-| ----- | ------------ | ------------ |
-| 6.0 | 3.8-3.11 | 16.0 or 17.0 |
-| 5.2 | 2.7, 3.6-3.8 | 15.0 |
+Before you start working with this training, ensure you have the following prerequisites:
+
+- [Node.js LTS (>=20.x)](https://nodejs.org/en) [see instructions for installation](https://6.docs.plone.org/install/install-from-packages.html#nvm)
+- [Python](https://www.python.org/) - See below for specific versions.
+- [pipx](https://pipx.pypa.io/stable/)
+- [nvm](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating)
+- [GNU make](https://www.gnu.org/software/make/)
+- [Docker](https://www.docker.com/get-started)(if using the Plone docker images - [see instructions for installation and usage](https://6.docs.plone.org/install/containers/index.html))
+ Follow the guide in Plone 6 Documentation, {ref}`create-project-cookieplone-prerequisites-for-installation-label`.
+ The versions of Python that are supported in Volto depend on the version of Plone that you use.
+
+| Plone | Python | Volto |
+| ----- | --------- | -------------- |
+| 6.1 | 3.10-3.12 | 18.0 |
+| 6.0 | 3.8-3.12 | 16.0,17.0,18.0 |
Depending on the operating system that you are using, some of the following pre-requisites might change.
They assume you have a macOS/Linux machine.
-## Bootstrap a new Volto project
+## Bootstrap a new Plone stack
-To bootstrap a new Volto project, you can use Yeoman [@plone/generator-volto](https://github.com/plone/generator-volto).
-First, install it as a global tool (see instructions for installation):
+To bootstrap a new Plone project(with both backend and frontend), you can use [Cookieplone](https://github.com/plone/cookieplone).
+You can use pipx to run Cookieplone to generate a project.
```shell
-npm install -g yo
-npm install -g @plone/generator-volto
+pipx run cookieplone project
```
-Then you can bootstrap the project with:
+You will be presented with a series of prompts.
+You can also specify the add-ons you want to install along with the project.
+When prompted for {guilabel}`Volto Addon Name`, enter `volto-teaser-tutorial`.
```shell
-yo @plone/volto volto-tutorial-project
+[11/17] Volto Addon Name (volto-project-title): volto-teaser-tutorial
```
-The yo-based generator partially integrates add-ons (it can generate a
-`package.json` with add-ons and workspaces already specified). When prompted
-to add add-ons, choose `false`.
+You can accept the rest of the default values in square brackets (`[default-option]`) by hitting the {kbd}`Enter` key, or enter your preferred values.
+For the training, we will use the default values for the rest of the prompts.
-Now you can start your newly created Volto project:
+## Install the project
-```shell
-cd volto-tutorial-project
-yarn start
-```
+To work on your project, you need to install both the frontend and backend.
-You can then login with admin/admin at http://localhost:3000/login.
+Change your current working directory to `project-title`.
-## Bootstrap an add-on
+```shell
+cd project-title
+```
-Let's start creating an add-on. We'll create a new package:
-`volto-teaser-tutorial`. Inside your Volto project, bootstrap
-the add-on by running (in the Volto project root):
+To install both the Plone backend and frontend, use the following command.
```shell
-yo @plone/volto:addon
+make install
```
-Note: You can also use the namespace like `@plone-collective/volto-teaser-tutorial` (or any other) is not required and is
-optional. We're using namespaces for scoped package under some organisation.
+## Start Plone
-Use `volto-teaser-tutorial` as the package name. After the
-scaffolding of the add-on completes, you can check the created files in
-`src/addons/volto-teaser-tutorial`.
+Plone 6 has two servers: one for the frontend, and one for the backend.
+As such, we need to maintain two active shell sessions, one for each server, to start your Plone site.
-Back to the project, you can edit `jsconfig.json` and add your add-on:
+### Start Plone backend
-```json
-{
- "compilerOptions": {
- "baseUrl": "src",
- "paths": {
- "volto-teaser-tutorial": ["addons/volto-teaser-tutorial/src"]
- }
- }
-}
-```
+In the currently open session, issue the following command.
-```{note}
-The `jsconfig.json` file is needed by Volto to identify development
-packages. You are not strictly limited to Volto add-ons in its use, you
-could, for example, use this to make it easier to debug third-party
-JavaScript packages that are shipped transpiled.
+```shell
+make backend-start
```
-### Volto addon script
+### Start Plone frontend
-Alternatively, if you already have an addon pushed to a remote repository and you want to create a volto development stack with it, you can use our addon script to easily scaffold a dev environment without creating a project externally.
+Create a second shell session in a new window.
+Start the Plone frontend with the following command.
```shell
-npx -p @plone/scripts addon clone [options] [destination]
+make frontend-start
```
-This command downloads the volto-teaser-tutorial add-on from its git repository's main branch, and will generate a project with the latest Volto version.
+Open a browser at the following URL to visit your Plone site.
-```shell
-npx -p @plone/scripts addon clone https://github.com/kitconcept/volto-teaser-tutorial.git --branch main
-```
+http://localhost:3000
-### (Optional) Use mrs-developer to sync add-on to GitHub
+You can then login with admin/admin at http://localhost:3000/login
-You can also immediately push the package to GitHub, then use `[mrs-developer]`
-to manage the package and `jsconfig.json` changes.
+## Volto addon
-Install mrs-developer as a development dependency by running:
+Using Cookieplone we should already have a working Volto project with provided add-on. You can find the add-on in packages/volto-teaser-tutorial.
-```shell
-yarn add -W -D mrs-developer
+```{note}
+You might have noticed that we have {file}`volto.config.js` in the root of the project. This is the Volto configuration file allowing us to configure Volto and register add-ons. The add-ons list points to the add-on we just installed. Cookieplone takes care of registering the add-on for us.
```
-Create a `mrs.developer.json` in your project with the following content (adjust it according
-to your names and repository location):
+## Workspaces
-```json
-{
- "volto-teaser-tutorial": {
- "url": "https://github.com//volto-teaser-tutorial.git",
- "path": "src",
- "package": "volto-teaser-tutorial",
- "branch": "main"
- }
-}
-```
-
-Then run `yarn develop`, which will bring the package in `src/addons` and
-adjust `jsconfig.json`.
+pnpm workspaces are a way to manage multiple packages in a single repository. Volto is a monorepo, so we use workspaces to manage the Volto project and its add-ons along with other packages.
-### Add the add-on as workspace
+We can define workspaces using the `pnpm-workspace.yaml` file in root of our project. This is taken care for us by Cookieplone.
-The Volto project becomes a monorepo, with the Volto project being the "workspace root" and each add-on needs to be a "workspace", so that yarn knows that it should include that add-on location as a package and install its dependencies.
+```yaml
+packages:
+ # all packages in direct subdirs of packages/
+ - "core/packages/*"
+ - "packages/*"
+```
-You could treat workspaces as major "working environment" for your project. So a yarn install would also install dependencies from `src/addons/*`
+All the packages in the {file}`packages` directory will be included in the workspace.
-Change the Volto project's `package.json` to include something like:
+The dependencies section maps the package names to the workspace. The `workspace:*` specifier tells pnpm to resolve these dependencies from other packages within the same workspace rather than fetching them from the npm registry.
```json
-{
- "private": "true",
- "workspaces": [
- "src/addons/volto-teaser-tutorial" // or simply src/addons/*
- ]
-}
+ "dependencies": {
+ "@plone/volto": "workspace:*",
+ "@plone/registry": "workspace:*",
+ "volto-teaser-tutorial": "workspace:*"
+ },
```
```{note}
-Don't be scared by that `"private": "true"` in the Volto project `package.json`.
-It's only needed to make sure you can't accidentally publish the package to NPM.
+We don't need to pin a specific workspace before we publish or release our project. pnpm takes care of dynamically updating the versions of these packages when you do `pnpm pack` or `pnpm publish`.
+
```
### Managing add-on dependencies
@@ -169,41 +144,10 @@ To be able to add dependencies to the add-on, you need to add them via the
workspaces machinery by running something like (at the Volto project root):
```shell
-yarn workspaces info
-yarn workspace volto-teaser-tutorial add papaparse
-```
-
-````{note}
-There are several other add-on templates, such as
-voltocli or
-eea/volto-addon-template.
-You could very well decide not to use any of them, and instead bootstrap a new
-add-on by running:
-
-```shell
-mkdir -p src/addons/volto-teaser-tutorial
-cd src/addons/volto-teaser-tutorial
-npm init
-```
-
-Remember, an add-on is just a JavaScript package that exports
-a configuration loader. Just make sure to point the `main` in
-`package.json` to `src/index.js`.
-
-````
-
-### Load the add-on in Volto
-
-To tell Volto about our new add-on, add it to the `addons` key of the Volto
-project `package.json`:
-
-```js
-// ...
-"addons": ["volto-teaser-tutorial"]
-// ...
+pnpm --filter volto-teaser-tutorial add papaparse
```
-## Add-ons - first look
+## Addons - first look
Volto add-ons are just plain JavaScript packages with an
additional feature: they provide helper functions that mutate Volto's
@@ -219,37 +163,35 @@ export default (config) => {
};
```
-**Pro-Tip 💡**
+### TypeScript configuration
-```{note}
-If you want to register a specific profile of an addon, wrap the configuration in a function and provide it after a colon(:) next to addon name. You can also provde a comma seperated multiple loaders profiles. Note the main configuration will be loaded always.
-```
+Every add-on supports custom typescript configuration using `tsconfig.json` in the root of the add-on package. This file defines how the typeScript compiler should process the code in our add-on.
-```js
-export function simpleLink(config) {
- return installSimpleLink(config);
-}
+You can inspect the tsconfig.json file in the volto-teaser-tutorial package.
+
+The basic ones are self explanatory. Note that we have path mapping inside `compilerOptions` for all the packages that this add-on depends on.
-export function tableButton(config) {
- return installTableButton(config);
+```js
+{
+ "compilerOptions": {
+ "paths": {
+ "@plone/volto/*": ["../../core/packages/volto/src/*"],
+ "volto-teaser-tutorial/*": ["./src/*"]
+ }
+ },
}
```
-```js
- ...
-"addons": [
- "volto-slate:tableButton,simpleLink",
- "@eeacms/volto-tabs-block",
-]
-...
+This option allows you to set up module resolution paths. The mappings provided allow typescript to resolve modules using custom paths:
-```
+`@plone/volto/*` maps to files in `../../core/packages/volto/src/*`, allowing us to import from this directory using the @plone/volto prefix.
+`volto-teaser-tutorial/*` maps to `./src/*`, allowing local imports from the src directory of the volto-teaser-tutorial package.
## Documentation and Resources
-Refer to the official Volto documentation for in-depth guides, tutorials, and examples.
+Refer to the [official Volto documentation](https://6.docs.plone.org/volto/index.html) for in-depth guides, tutorials, and examples.
-Join the Volto community, participate in discussions, and ask questions on the Volto GitHub repository or the Plone community chat on Discord.
+Join the Volto community, participate in discussions, and ask questions on the Volto GitHub repository or the [Plone community chat on Discord](https://plone.org/news-and-events/news/2021/join-plone-chat-now-at-discord)
```{warning}
Getting started with Volto may seem complex at first, but with practice and exploration, you'll become more comfortable with its features and capabilities. It offers a powerful and flexible platform for building modern web applications with React and Plone.
diff --git a/docs/volto_customization/intro.md b/docs/volto_customization/intro.md
index ebed63877..d67505145 100644
--- a/docs/volto_customization/intro.md
+++ b/docs/volto_customization/intro.md
@@ -25,14 +25,14 @@ Additionally, if you have any specific questions, challenges, or expectations fo
Some technologies and tools we use during the training:
-- React https://react.dev/
-- Yarn https://yarnpkg.com
+- React https://react.dev/
+- Yarn https://yarnpkg.com
- JSX
-- Volto https://github.com/plone/volto
-- Volto Generator
+- Volto https://github.com/plone/volto
+- Cookieplone https://github.com/plone/cookieplone
- Plone 6!
-Before we dive into the content of this training, I'd like to make a helpful suggestion. If you're new to Volto and React or feel like you could benefit from a refresher, it might be a great idea to explore some existing Volto and React training resources that can provide you with a solid foundation. These resources can serve as valuable supplements to what we'll cover here.
+Before we dive into the content of this training, I'd like to make a helpful suggestion. If you're new to Volto and React or feel like you could benefit from a refresher, it might be a great idea to [explore some existing Volto and React training resources](https://www.youtube.com/playlist?list=PLGN9BI-OAQkTVkkJfSMHu-l-_AVW_uoRf) that can provide you with a solid foundation. These resources can serve as valuable supplements to what we'll cover here.
We have designed this training to be beginner-friendly, but having some prior exposure to these technologies can be advantageous. It will help you grasp the concepts more quickly and make the learning experience even more enjoyable.
@@ -44,7 +44,7 @@ Of course, if you're already familiar with Volto and React, that's fantastic, an
To follow the training as smoothly as possible it is recommended that you have the following software installed on your computer:
-- node.js >= 16
-- yarn
-- node version manager
-- docker
+- [node.js](https://nodejs.org/en/)>= 20
+- [pnpm](https://pnpm.io/installation)
+- [node version manager](https://github.com/nvm-sh/nvm)
+- [docker](https://www.docker.com/get-started/)
diff --git a/docs/volto_customization/listing_block.md b/docs/volto_customization/listing_block.md
deleted file mode 100644
index 7ee3b2655..000000000
--- a/docs/volto_customization/listing_block.md
+++ /dev/null
@@ -1,227 +0,0 @@
----
-myst:
- html_meta:
- "description": "How to create a block variation"
- "property=og:description": "How to create a block variation"
- "property=og:title": "Create a simple listing block variation"
- "keywords": "Volto, Training, Block variation"
----
-
-# Create a simple listing block variation
-
-We will create a variation for listing block, the approach is the same we did for teasers. A new variation which will control the layout and extensions which will take care of individual items styling.
-
-First of all let's add a styling fieldset in the current schema of volto's default listing block .
-
-In your addon config:
-
-```js
-import { addStylingFieldset } from "volto-teaser-tutorial/components/helpers";
-
-if (config.blocks.blocksConfig.listing) {
- config.blocks.blocksConfig.listing.title = "Listing (Tutorial)";
- config.blocks.blocksConfig.listing.schemaEnhancer = addStylingFieldset;
-}
-```
-
-Create a file named `helpers.js` inside `components/` folder and add the relevant schema enhancer for it:
-
-```js
-import { cloneDeep } from "lodash";
-import imageNarrowSVG from "@plone/volto/icons/image-narrow.svg";
-import imageFitSVG from "@plone/volto/icons/image-fit.svg";
-import imageWideSVG from "@plone/volto/icons/image-wide.svg";
-import imageFullSVG from "@plone/volto/icons/image-full.svg";
-
-export const ALIGN_INFO_MAP = {
- narrow_width: [imageNarrowSVG, "Narrow width"],
- container_width: [imageFitSVG, "Container width"],
- wide_width: [imageWideSVG, "Wide width"],
- full: [imageFullSVG, "Full width"],
-};
-
-export const addStylingFieldset = ({ schema }) => {
- const applied = schema?.properties?.styles;
-
- if (!applied) {
- const resSchema = cloneDeep(schema);
-
- resSchema.fieldsets.push({
- id: "styling",
- fields: ["styles"],
- title: "Styling",
- });
- resSchema.properties.styles = {
- widget: "object",
- title: "Styling",
- schema: {
- fieldsets: [
- {
- id: "default",
- title: "Default",
- fields: ["size"],
- },
- ],
- properties: {
- size: {
- widget: "align",
- title: "Section size",
- actions: Object.keys(ALIGN_INFO_MAP),
- actionsInfoMap: ALIGN_INFO_MAP,
- },
- },
- required: [],
- },
- };
- return resSchema;
- }
-
- return schema;
-};
-```
-
-This function will inject styles field into the schema if isn't present already. We can add relevant styling here. Volto will build classNames based on the styles as mentioned in the earlier chapters. We will have to provide our own css for the generated classNames.
-
-```less
-:force: true
-
-#main .has--size--narrow_width,
-#main .narrow_width,
-[class~="narrow_view"] [id="page-document"] > * {
- max-width: var(--narrow-text-width, 500px) !important;
-}
-
-#main .container_width,
-#main .has--size--container_width,
-.view-wrapper > *,
-[class~="view-defaultview"] [id="page-document"] > *,
-[class~="view-viewview"] [id="page-document"] > * {
- max-width: var(--container-text-width, 1120px) !important;
-}
-```
-
-In order to have a control over individual items in the listing let's create a sample variation of listing block.
-
-```js
-import ListingVariation from "volto-teaser-tutorial/components/ListingBlockVariation";
-
-config.blocks.blocksConfig.listing.variations = [
- ...(config.blocks.blocksConfig.listing.variations || []),
- {
- id: "tutorial",
- isDefault: false,
- title: "Sample Variation",
- template: ListingVariation,
- schemaEnhancer: ({ schema, FormData, intl }) => {
- const extension = "cardTemplates";
- schema.fieldsets.push({
- id: "Cards",
- title: "Cards",
- fields: [],
- });
- addExtensionFieldToSchema({
- schema,
- name: extension,
- items: config.blocks.blocksConfig.teaser.extensions[extension]?.items,
- intl,
- title: { id: "Card Type" },
- insertFieldToOrder: (schema, extension) => {
- const cardFieldSet = schema.fieldsets.find(
- (item) => item.id === "Cards"
- ).fields;
- if (cardFieldSet.indexOf(extension) === -1)
- cardFieldSet.unshift(extension);
- },
- });
- return schema;
- },
- },
-];
-```
-
-Notice that here we will keep the schemaEnhancer configuration of teaser extensions. For better readability we can also move these lines of code into a `baseSchemaEnhancer` which will serve for both listing and teaser block extensions. But we can leave it up to the user for now.
-
-Finally we write our own variation for ListingBlock:
-
-ListingBlockVariation.jsx
-
-```jsx
-import React from "react";
-import PropTypes from "prop-types";
-import cloneDeep from "lodash/cloneDeep";
-import { useIntl } from "react-intl";
-import { ConditionalLink, UniversalLink } from "@plone/volto/components";
-import { flattenToAppURL } from "@plone/volto/helpers";
-import config from "@plone/volto/registry";
-
-import { isInternalURL } from "@plone/volto/helpers/Url/Url";
-
-const ListingVariation = (props) => {
- const {
- items,
- linkTitle,
- linkHref,
- isEditMode,
- data,
- extension = "cardTemplates",
- } = props;
- let link = null;
- let href = linkHref?.[0]?.["@id"] || "";
-
- if (isInternalURL(href)) {
- link = (
-
- {linkTitle || href}
-
- );
- } else if (href) {
- link = {linkTitle || href};
- }
-
- const intl = useIntl();
-
- const teaserExtenstions =
- config.blocks.blocksConfig?.teaser?.extensions[extension].items;
- let activeItem = teaserExtenstions.find(
- (item) => item.id === props?.[extension]
- );
- const extenionSchemaEnhancer = activeItem?.schemaEnhancer;
- if (extenionSchemaEnhancer)
- extenionSchemaEnhancer({
- schema: cloneDeep(config.blocks.blocksConfig?.teaser?.blockSchema),
- data: data || props,
- intl,
- });
- const ExtensionToRender = activeItem?.template;
-
- return (
- <>
-
- {items.map((item) => (
-
-
-
- ))}
-
-
- {link &&
{link}
}
- >
- );
-};
-
-ListingVariation.propTypes = {
- items: PropTypes.arrayOf(PropTypes.any).isRequired,
- linkMore: PropTypes.any,
- isEditMode: PropTypes.bool,
-};
-export default ListingVariation;
-```
-
-We will now have the per listing item styling support like we have for teaser blocks. We can also add more styling schema with the help of its individual schema extenders.
diff --git a/docs/volto_customization/schema.md b/docs/volto_customization/schema.md
index 8050b9ca0..e10226d75 100644
--- a/docs/volto_customization/schema.md
+++ b/docs/volto_customization/schema.md
@@ -11,7 +11,7 @@ myst:
In the previous chapter we just replaced or enhanced our View component by directly mutating the View in the Blocks engine. Now since all the blocks in principle should be schema based and should use `BlockDataForm` we do have another concept of extending Blocks with respect to schema.
-The `BlockDataForm` renders a schemaEnhanced form ready to be used along with the variations support.
+The `BlockDataForm` renders a schemaEnhanced form ready to be used with support for validations and variations.
The variations are various "View" mode options that your block might have whether its layout, the designs or a completely enhanced form of a block.
@@ -49,7 +49,7 @@ So in the default schema for teaser block we have:
},
```
-Notice the _variations_ key, in which we can have multiple view templates for a given block. Right now its going to use the default one which is the TeaserBlockDefaultBody.
+Notice the _variations_ key, in which we can have multiple view templates for a given block. Right now its going to use the default one which is the [`TeaserBlockDefaultBody`](https://github.com/plone/volto/blob/985e419396b4d00567d12e7e309ea420012e9cc7/src/components/manage/Blocks/Teaser/DefaultBody.jsx#L1).
We are going to create a new variation of this teaser block. This variation is essential because using it we will create block extensions per teaser. Later we can also enhance this variation with the new schema.
@@ -137,7 +137,14 @@ const TeaserBlockImageDefault = (props) => {
: null
}
>
-
Body component in Teaser block also supports adding variations from component registry. You can read more about component registry in following chapters.
+The [`Body`](https://github.com/plone/volto/blob/9667cf735e5c3e848de852d615941d98193e0a5e/src/components/manage/Blocks/Teaser/Body.jsx#L13) component in Teaser block also supports adding variations from component registry. You can read more about component registry in following chapters.
```
diff --git a/docs/volto_customization/shadowing.md b/docs/volto_customization/shadowing.md
index e43cbd4cf..99610509f 100644
--- a/docs/volto_customization/shadowing.md
+++ b/docs/volto_customization/shadowing.md
@@ -21,7 +21,7 @@ To avoid duplication we simply follow the chapter {ref}`volto-overrides-label` o
In that chapter you learn how to override the logo, the footer, the news-item view and the default listing-block.
-The only difference is whenever we add new files instead of adding them to the project we add the to our addon.
+The only difference is whenever we add new files instead of adding them to the project we add the to our add-on.
For example when we customize the News Item View instead of adding the override as:
@@ -29,9 +29,9 @@ For example when we customize the News Item View instead of adding the override
we add it as
-`src/addon/volto-teaser-tutorial/src/customizations/volto/components/theme/View/NewsItemView.jsx`.
+`packages/volto-teaser-tutorial/src/customizations/volto/components/theme/View/NewsItemView.jsx`.
-Both paths work fine though, we just want to go all-in with the addon-approach.
+Both paths work fine though, we just want to go all-in with the add-on approach.
```{seealso}
- {ref}`voltohandson-header-component-label` (Volto Hands-On Training)
diff --git a/docs/volto_customization/styling.md b/docs/volto_customization/styling.md
index 3e78f4d6d..4f333e3e6 100644
--- a/docs/volto_customization/styling.md
+++ b/docs/volto_customization/styling.md
@@ -13,12 +13,12 @@ Its essential to also control the styling of Blocks and most importantly if the
## StyleWrapper(Styling Schemas)
-In Volto we have a central wrapper named `StyleWrapper` which wraps around all the View template of Blocks. The job of stylewrapper is to build and inject style classNames into its children.
+In Volto we have a central wrapper named [`StyleWrapper`](https://github.com/plone/volto/blob/9667cf735e5c3e848de852d615941d98193e0a5e/src/components/manage/Blocks/Block/StyleWrapper.jsx#L1) which wraps around all the View template of Blocks. The job of stylewrapper is to build and inject style classNames into its children.
-In the schema at any point in time, we can call a volto helper which adds `styles` fields. Which then gets converted into classNames with the prefix `--has`. Its upto the theme owner in which way they want to add css for it.
+In the schema at any point in time, we can call a Volto helper which adds `styles` fields. Which then gets converted into classNames with the prefix `--has`. Its upto the theme owner in which way they want to add css for it.
Simply, the job of StyleWrapper is to inject classNames(build from schema) into their children.
-We see that in our Teaser config volto already calls the addStyling in the schema. The job of this function is to add styles field in the styling fieldset in schema provided.
+We see that in our Teaser config Volto already calls the [`addStyling`](https://github.com/plone/volto/blob/9667cf735e5c3e848de852d615941d98193e0a5e/src/helpers/Extensions/withBlockSchemaEnhancer.js#L297) in the schema. The job of this function is to add styles field in the styling fieldset in schema provided.
```jsx
export const TeaserSchema = ({ intl }) => {
diff --git a/docs/volto_customization/teaser_variations.md b/docs/volto_customization/teaser_variations.md
index f22cf7390..1f4f1ae92 100644
--- a/docs/volto_customization/teaser_variations.md
+++ b/docs/volto_customization/teaser_variations.md
@@ -130,7 +130,14 @@ const TeaserBlockImageDefault = (props) => {
: null
}
>
-
{
@@ -38,11 +38,11 @@ export default applyConfig;
```
```{note}
-The `...` is a use of the spread-syntax that "expands" the configuration into its elements and allows to change existing values and add new ones.
+The `...` is a use of the [spread-syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) that "expands" the configuration into its elements and allows to change existing values and add new ones.
```
```{note}
-If you instead make your changes in the project (i.e. not using a addon) you make the same changes in the file `config.js` of the project.
+If you instead make your changes in the project (i.e. not using a add-on) you make the same changes in the file `config.js` of the project.
```
Some of the settings are duplicates of settings that exist in the Plone backend.
@@ -70,7 +70,7 @@ export default applyConfig;
Here are some more setting you might use in your projects:
-- `contentIcons` - configure Content Types icons. See documentation.
+- `contentIcons` - configure Content Types icons. See [documentation](https://6.docs.plone.org/volto/configuration/settings-reference.html#term-contentIcons).
- `navDepth` - Navigation levels depth used in the navigation endpoint calls. Increasing this is useful for implementing fat navigation menus.
- `workflowMapping` - Configure colors for workflow states/transitions - if you have a custom workflow or want to change the default colors.
- `openExternalLinkInNewTab` - Kind of self-explaining, isn't it?
@@ -78,7 +78,7 @@ Here are some more setting you might use in your projects:
- `maxFileUploadSize` - Limit the size of uploads
- `nonContentRoutes` - A list of path strings which are considered to be outside of plone-restapi's content serialization. For example: `/controlpanel, /login,/sitemap,/personal-information` are all nonContentRoutes.
-You can find all existing options in the file config/index.js of Volto itself which is available in your projects in `frontend/omelette/src/config/index.js`.
+You can find all existing options in the file [`config/index.js`](https://github.com/plone/volto/blob/main/packages/volto/src/config/index.js#L73) of Volto itself which is available in your projects in `frontend/core/packages/volto/src/config/index.js`.
```{seealso}
Many options are explained in the {doc}`plone6docs:volto/configuration/settings-reference`