diff --git a/.github/workflows/rtd-pr-preview.yml b/.github/workflows/rtd-pr-preview.yml index bf7bd5aef..e2e349aeb 100644 --- a/.github/workflows/rtd-pr-preview.yml +++ b/.github/workflows/rtd-pr-preview.yml @@ -18,5 +18,5 @@ jobs: steps: - uses: readthedocs/actions/preview@v1 with: - project-slug: "plone6" + project-slug: "plone-training" single-version: "true" diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1e964baa9..4ce807b46 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -18,7 +18,7 @@ build: # If there are no changes (git diff exits with 0) we force the command to return with 183. # This is a special exit code on Read the Docs that will cancel the build immediately. - | - if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && git diff --quiet origin/main -- docs/ .readthedocs.yaml requirements.txt; + if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && git diff --quiet origin/main -- docs/ .github/workflows/rtd-pr-preview.yml .readthedocs.yaml requirements.txt; then exit 183; fi diff --git a/Makefile b/Makefile index 0b9a2aac0..7ec44279e 100644 --- a/Makefile +++ b/Makefile @@ -29,13 +29,9 @@ clean: ## Clean build directory cd $(DOCS_DIR) && rm -rf $(BUILDDIR)/* .PHONY: distclean -distclean: ## Clean docs build directory and Python virtual environment, then install requirements +distclean: ## Clean docs build directory and Python virtual environment + rm -rf venv cd $(DOCS_DIR) && rm -rf $(BUILDDIR)/ - python3 -m venv venv --clear - venv/bin/python -m pip install --upgrade pip - venv/bin/pip install -r requirements.txt - @echo - @echo "Installation of requirements completed." venv/bin/python: ## Set up training: Install requirements python3 -m venv venv diff --git a/docs/conf.py b/docs/conf.py index f9259e774..4ff1f501c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -132,7 +132,19 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] +exclude_patterns = [ + "mastering-plone-5/timing.md", + "theming/diazo-notes.md", + "voltohandson/blocksdownload.md", + "voltohandson/blocksedit.md", + "voltohandson/contenttypesviews.md", + "voltohandson/contenttypesviews.md", + "voltohandson/contenttypeview.md", + "voltohandson/eventlistingtemplate.md", + "voltohandson/highlight.md", + "voltohandson/highlightsblock.md", + "voltohandson/introtovolto.md", +] # -- Options for HTML output ------------------------------------------------- diff --git a/docs/contributing/setup-build.md b/docs/contributing/setup-build.md index 328c2b911..723e5ac4c 100644 --- a/docs/contributing/setup-build.md +++ b/docs/contributing/setup-build.md @@ -142,13 +142,6 @@ make vale See the output on the console for suggestions. -You can also pass options to vale in the `VALEOPTS` environment variable. -In the following example, vale will not return a non-zero exit code when there are errors and will display warnings or errors only, not suggestions. - -```shell -make vale VALEOPTS="--no-exit --minAlertLevel='warning'" -``` - ### `html_meta` @@ -158,3 +151,29 @@ See {ref}`authors-html-meta-data-label` for more info. ```shell make html_meta ``` + + +## Overriding configuration options + +Both Sphinx and vale support overriding configuration options. +The following examples serve as tips for spotting mistakes in your training. + +In Sphinx, you can use the `SPHINXOPTS` environment variable to set [configuration options](https://www.sphinx-doc.org/en/master/usage/configuration.html) of [`sphinx-build`](https://www.sphinx-doc.org/en/master/man/sphinx-build.html). +Syntax is in the following form. + +```shell +make SPHINXOPTS="OPTION VALUE" BUILDER +``` + +The following example shows how to clean then build a live HTML preview of the trainings while suppressing syntax highlighting failures. + +```shell +make SPHINXOPTS="-D suppress_warnings=['misc.highlighting_failure']" clean livehtml +``` + +You can also pass options to vale in the `VALEOPTS` environment variable. +In the following example, vale will not return a non-zero exit code when there are errors and will display warnings or errors only, not suggestions. + +```shell +make vale VALEOPTS="--no-exit --minAlertLevel='warning'" +``` diff --git a/docs/effective-volto/addons.md b/docs/effective-volto/addons.md index 562fc2120..1dd4802c3 100644 --- a/docs/effective-volto/addons.md +++ b/docs/effective-volto/addons.md @@ -10,12 +10,10 @@ myst: # Add-ons ```{toctree} ---- -caption: Add-ons -name: toc-effective-volto-addons -maxdepth: 2 -numbered: true ---- +:caption: Add-ons +:name: toc-effective-volto-addons +:maxdepth: 2 +:numbered: addons/what-is-an-addon addons/bootstrap diff --git a/docs/effective-volto/addons/use-repo-addon.md b/docs/effective-volto/addons/use-repo-addon.md index 730b48c2b..94e9e963a 100644 --- a/docs/effective-volto/addons/use-repo-addon.md +++ b/docs/effective-volto/addons/use-repo-addon.md @@ -123,17 +123,13 @@ you'll have to set your addon package as a "Yarn workspace". You do this by adding a `workspaces` key to the the `package.json` of your Volto project: ```json -... "workspaces": ["src/addons/my-volto-addon"], -... ``` It is common practice to use a star glob pattern for the workspaces: ```json -... "workspaces": ["src/addons/*"], -... ``` If you do this, make sure to always cleanup the `src/addons` folder whenever diff --git a/docs/effective-volto/architecture.md b/docs/effective-volto/architecture.md index 494538655..89c5479e1 100644 --- a/docs/effective-volto/architecture.md +++ b/docs/effective-volto/architecture.md @@ -12,12 +12,10 @@ myst: Intro ```{toctree} ---- -caption: Architecture -name: toc-effective-volto-architecture -maxdepth: 2 -numbered: true ---- +:caption: Architecture +:name: toc-effective-volto-architecture +:maxdepth: 2 +:numbered: architecture/client-ssr architecture/razzle diff --git a/docs/effective-volto/architecture/CORS.md b/docs/effective-volto/architecture/CORS.md index 0e52e7a58..303410eb3 100644 --- a/docs/effective-volto/architecture/CORS.md +++ b/docs/effective-volto/architecture/CORS.md @@ -42,7 +42,7 @@ However, the recommendation is that you forget that CORS exists and "play well" These scenarios are: - Our frontend and backend are in the same domain (thus, avoiding the cross-domain issue), or -- Using the internal proxy provided by Volto's NodeJS SSR server +- Using the internal proxy provided by Volto's Node.js SSR server During development, the last one is the one you are going to use. The default backend will live in `http://localhost:8080/Plone` and the frontend in `http://localhost:3000`. If your Plone site is not named `Plone` (so its url is something like `http://localhost:8080/mysite`, you can still use Seamless mode by creating a file called `.env.development` in the Volto project root with something like this: diff --git a/docs/effective-volto/architecture/bootstrap-volto.md b/docs/effective-volto/architecture/bootstrap-volto.md index 3e63b5109..96c3b5b6a 100644 --- a/docs/effective-volto/architecture/bootstrap-volto.md +++ b/docs/effective-volto/architecture/bootstrap-volto.md @@ -14,12 +14,12 @@ For the most up-to-date information on how to get started with Volto, the offici A copy of this information is placed here, with the caveat that it may be out of date by the time you're reading this. ``` -## Install nvm (NodeJS version manager) +## Install nvm (Node.js version manager) If you have a working Node JavaScript development already set up on your machine or you prefer another management tool to install/maintain node this step is not needed. If you have less experience with setting up JavaScript, it's a good idea to integrate nvm for development, as -it provides easy access to any NodeJS released version. +it provides easy access to any Node.js released version. 1. Open a terminal console and type: @@ -42,7 +42,7 @@ it provides easy access to any NodeJS released version. nvm version ``` -4. Install any active LTS version of NodeJS (https://github.com/nodejs/release#release-schedule): +4. Install any active LTS version of Node.js (https://github.com/nodejs/release#release-schedule): ```bash nvm install 18 diff --git a/docs/effective-volto/backend.md b/docs/effective-volto/backend.md index d77c28306..7f7b75068 100644 --- a/docs/effective-volto/backend.md +++ b/docs/effective-volto/backend.md @@ -12,12 +12,10 @@ myst: Intro ```{toctree} ---- -caption: Backend -name: toc-effective-volto-backend -maxdepth: 2 -numbered: true ---- +:caption: Backend +:name: toc-effective-volto-backend +:maxdepth: 2 +:numbered: backend/plone-restapi-endpoints backend/writing-endpoint diff --git a/docs/effective-volto/deployment.md b/docs/effective-volto/deployment.md index 7c97c331f..44c712f3d 100644 --- a/docs/effective-volto/deployment.md +++ b/docs/effective-volto/deployment.md @@ -10,12 +10,10 @@ myst: # Deployment ```{toctree} ---- -caption: Deployment -name: toc-effective-volto-deployment -maxdepth: 2 -numbered: true ---- +:caption: Deployment +:name: toc-effective-volto-deployment +:maxdepth: 2 +:numbered: deployment/seamlessmode deployment/simple diff --git a/docs/effective-volto/development.md b/docs/effective-volto/development.md index 92ed9708e..8b850a055 100644 --- a/docs/effective-volto/development.md +++ b/docs/effective-volto/development.md @@ -11,12 +11,10 @@ myst: ```{toctree} ---- -caption: Development tools -name: toc-effective-volto-development -maxdepth: 2 -numbered: true ---- +:caption: Development tools +:name: toc-effective-volto-development +:maxdepth: 2 +:numbered: development/setup development/environmentvariables diff --git a/docs/effective-volto/getting-started.md b/docs/effective-volto/getting-started.md index 2ad6ab8d6..5106325be 100644 --- a/docs/effective-volto/getting-started.md +++ b/docs/effective-volto/getting-started.md @@ -17,12 +17,10 @@ So, we will be bootstrapping a Full Plone 6 project in order to follow the train ```{toctree} ---- -caption: Getting Started -name: toc-effective-volto-getting-started -maxdepth: 2 -numbered: true ---- +:caption: Getting Started +:name: toc-effective-volto-getting-started +:maxdepth: 2 +:numbered: getting-started/project getting-started/add-on diff --git a/docs/effective-volto/index.md b/docs/effective-volto/index.md index 5183bdaad..e4d0e1520 100644 --- a/docs/effective-volto/index.md +++ b/docs/effective-volto/index.md @@ -22,11 +22,9 @@ Tips and tricks will be also covered, providing a good amount of insights for th This training is intended for an intermediate audience that already has some contact with Volto and tried it out, or has a decent amount of experience with it. Even experienced Volto developers will find this training useful, as less known areas of Volto are exposed. ```{toctree} ---- -caption: Effective Volto -name: toc-effective-volto -maxdepth: 3 ---- +:caption: Effective Volto +:name: toc-effective-volto +:maxdepth: 3 about_effective_volto getting-started diff --git a/docs/effective-volto/testing.md b/docs/effective-volto/testing.md index 2ef003f53..2d1623a33 100644 --- a/docs/effective-volto/testing.md +++ b/docs/effective-volto/testing.md @@ -10,12 +10,10 @@ myst: # Testing ```{toctree} ---- -caption: Testing -name: toc-effective-volto-testing -maxdepth: 2 -numbered: true ---- +:caption: Testing +:name: toc-effective-volto-testing +:maxdepth: 2 +:numbered: testing/acceptance testing/jest diff --git a/docs/index.md b/docs/index.md index f404ba87b..5be95ee4f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -18,9 +18,9 @@ A collection of trainings developed and created by the Plone community. mastering-plone/index mastering-plone-5/index +volto-customization/index voltohandson/index voltoaddons/index -volto_customization/index effective-volto/index testing/index theming/index @@ -44,74 +44,76 @@ teaching/index {ref}`mastering-plone-label` -: Best practices of Plone development, backend and frontend. +: Best practices of Plone development for both the backend and frontend. {ref}`mastering-plone5-label` -: *Mastering Plone 5 development training* is the predecessor of the Plone 6 version. It includes also *Plone Classic* topics like viewlets, views, portlets, etc.. +: Mastering Plone 5 development training is the predecessor of the Plone 6 version. + It includes also Plone Classic UI topics including viewlets, views, portlets, and other customizations. {doc}`testing/index` -: Best practices for testing Plone add-ons. +: Best practices for testing Plone add-ons. ## Volto, React, and Javascript -{doc}`voltohandson/index` +{doc}`volto-customization/index` -: Learn how to quickly bootstrap and customize a Volto project +: Are you new to JavaScript development and eager to explore the world of Volto customization? + Unlock the power of Volto, the modern React-based CMS framework for Plone, by joining our comprehensive half-day training designed specifically for JavaScript beginners. -{doc}`voltoaddons/index` +{doc}`voltohandson/index` -: Build custom Volto add-ons, explore more advanced Volto topics. +: Learn how to quickly bootstrap and customize a Volto project -{doc}`volto_customization/index` +{doc}`voltoaddons/index` -: Are you new to JavaScript development and eager to explore the world of Volto customization? Unlock the power of Volto, the modern React-based CMS framework for Plone, by joining our comprehensive half day training designed specifically for JavaScript beginners. +: Build custom Volto add-ons, explore more advanced Volto topics. {doc}`effective-volto/index` -: Learn proven practices of Plone frontend development. - The training covers essential concepts, as well as good practices and notions of how Volto works under the hood. - Tips and tricks are also covered, providing a good amount of insights for those who want to learn more beyond the Volto basics. - Training for intermediate/advanced developers. +: Learn proven practices of Plone frontend development. + The training covers essential concepts, as well as good practices and notions of how Volto works under the hood. + Tips and tricks are also covered, providing a good amount of insights for those who want to learn more beyond the Volto basics. + Training for intermediate/advanced developers. [Use, Integrate and develop Patterns for Plone 6 Classic](https://patternslib.github.io/patternslib-training) -: Use, create and integrate JavaScript functionality based on [Patternslib](https://patternslib.com/) into Plone 6. +: Use, create and integrate JavaScript functionality based on [Patternslib](https://patternslib.com/) into Plone 6. ## Theming {doc}`theming/index` -: Theming Plone 6 Classic UI +: Theming Plone 6 Classic UI ## Deployment {doc}`plone-deployment/index` -: Deploying Plone 6 for production purposes with Ansible and Docker +: Deploying Plone 6 for production purposes with Ansible and Docker ## Other {doc}`workflow/index` -: How to create and make optimum use of custom Plone workflows +: How to create and make optimum use of custom Plone workflows {doc}`migrations/index` -: Upgrading and migrating Plone sites using `collective.exportimport` and other methods. +: Upgrading and migrating Plone sites using `collective.exportimport` and other methods. {doc}`contributing/index` -: All about contributing to documentation +: All about contributing to documentation {doc}`teaching/index` -: How To Give Technical Trainings +: How To Give Technical Trainings ## Archived trainings diff --git a/docs/mastering-plone-5/add-ons.md b/docs/mastering-plone-5/add-ons.md index f22ae6c90..f98c47c95 100644 --- a/docs/mastering-plone-5/add-ons.md +++ b/docs/mastering-plone-5/add-ons.md @@ -107,7 +107,7 @@ Once you found an add-on you like you should ask the community if you made a goo - Message Board: - Chat: -There is also a talk that discusses in depth how to find the right add-on: +There is also a talk that discusses in depth how to find the right add-on: (plone5-add-ons-installing-label)= diff --git a/docs/mastering-plone-5/index.md b/docs/mastering-plone-5/index.md index 14f2a82e5..13aa20a21 100644 --- a/docs/mastering-plone-5/index.md +++ b/docs/mastering-plone-5/index.md @@ -21,12 +21,10 @@ Mastering Plone is intended as a week-long training for people who are new to Pl At conferences a shortened 2-day version of the advanced training with a slightly modified order is held. ```{toctree} ---- -caption: Mastering Plone 5 Development -name: toc-mastering5 -maxdepth: 3 -numbered: 2 ---- +:caption: Mastering Plone 5 Development +:name: toc-mastering5 +:maxdepth: 3 +:numbered: 2 about_mastering intro diff --git a/docs/mastering-plone-5/instructions_plone5/index.md b/docs/mastering-plone-5/instructions_plone5/index.md index 7664194ea..fc3bf22c9 100644 --- a/docs/mastering-plone-5/instructions_plone5/index.md +++ b/docs/mastering-plone-5/instructions_plone5/index.md @@ -157,7 +157,7 @@ If you point your browser at you see that Plone is runni A running plone instance. ``` -There is no Plone site yet - we will create one in {doc}`/mastering-plone-5/instructions_plone5/features`. +There is no Plone site yet - we will create one in {doc}`/mastering-plone-5/features`. Now you have a working Plone site up and running and can continue with the next chapter. diff --git a/docs/mastering-plone-5/instructions_plone5/what_vagrant_does.md b/docs/mastering-plone-5/instructions_plone5/what_vagrant_does.md index dcfd04e9c..28dd18f6e 100644 --- a/docs/mastering-plone-5/instructions_plone5/what_vagrant_does.md +++ b/docs/mastering-plone-5/instructions_plone5/what_vagrant_does.md @@ -5,6 +5,7 @@ myst: "property=og:description": "" "property=og:title": "" "keywords": "" +orphan: --- # What Vagrant is and does diff --git a/docs/mastering-plone-5/views_2.md b/docs/mastering-plone-5/views_2.md index d19c33aed..0f4ac9cdd 100644 --- a/docs/mastering-plone-5/views_2.md +++ b/docs/mastering-plone-5/views_2.md @@ -113,7 +113,7 @@ class DemoView(BrowserView): 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',)}, {'title': 'Diazo is a powerful tool for theming!', diff --git a/docs/mastering-plone-5/what_is_plone.md b/docs/mastering-plone-5/what_is_plone.md index 38d994667..c7f2951eb 100644 --- a/docs/mastering-plone-5/what_is_plone.md +++ b/docs/mastering-plone-5/what_is_plone.md @@ -165,5 +165,5 @@ Written by smart people: - ... ```{seealso} -- The Keynote by Cris Ewing at PyCon 2016: +- The Keynote by Cris Ewing at PyCon 2016: ``` diff --git a/docs/mastering-plone-5/zpt.md b/docs/mastering-plone-5/zpt.md index 791163ee0..fd5ac6d26 100644 --- a/docs/mastering-plone-5/zpt.md +++ b/docs/mastering-plone-5/zpt.md @@ -549,7 +549,7 @@ Modify the following template and one by one solve the following problems: 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -587,7 +587,7 @@ Modify the following template and one by one solve the following problems: 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -625,7 +625,7 @@ Modify the following template and one by one solve the following problems: 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -668,7 +668,7 @@ Modify the following template and one by one solve the following problems: 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -721,7 +721,7 @@ if the ordinal index of the current iteration is an odd number). 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -767,7 +767,7 @@ if the ordinal index of the current iteration is an odd number). 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -809,7 +809,7 @@ if the ordinal index of the current iteration is an odd number). 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -852,7 +852,7 @@ if the ordinal index of the current iteration is an odd number). 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', @@ -933,7 +933,7 @@ Here also added the css-class `listing` to the table. It is one of many css-clas 'subjects': ('content-types', 'dexterity')}, {'title': 'Mosaic will be the next big thing.', 'subjects': ('layout', 'deco', 'views'), - 'url': 'https://www.youtube.com/watch?v=QSNufxaYb1M'}, + 'url': 'https://www.youtube-nocookie.com/embed/QSNufxaYb1M?privacy_mode=1'}, {'title': 'The State of Plone', 'subjects': ('keynote',) }, {'title': 'Diazo is a powerful tool for theming!', diff --git a/docs/mastering-plone/about_mastering.md b/docs/mastering-plone/about_mastering.md index 272c450fc..825012686 100644 --- a/docs/mastering-plone/about_mastering.md +++ b/docs/mastering-plone/about_mastering.md @@ -44,8 +44,8 @@ If you want to have an on-site training or want to attend a public training, ple At Ploneconf 2021 the Mastering Plone Development training has been recorded. It's a shortened version of the training, given by Philip Bauer and Katja Süss. -[Part 1 – Mastering Plone Development Training](https://www.youtube.com/watch?v=Jzuw3uWtzzI) -[Part 2 – Mastering Plone Development Training](https://www.youtube.com/watch?v=IEcGKzo3PO0) +[Part 1 – Mastering Plone Development Training](https://www.youtube-nocookie.com/embed/Jzuw3uWtzzI?privacy_mode=1) +[Part 2 – Mastering Plone Development Training](https://www.youtube-nocookie.com/embed/IEcGKzo3PO0?privacy_mode=1) (about-trainers-label)= diff --git a/docs/mastering-plone/add-ons.md b/docs/mastering-plone/add-ons.md index ffbd0c688..0bc642334 100644 --- a/docs/mastering-plone/add-ons.md +++ b/docs/mastering-plone/add-ons.md @@ -88,7 +88,7 @@ Here are some tips. - Once you found an add-on you like, you can ask the community if you made a good choice or if you missed something: - Message Board: - - There is also a talk that discusses in depth how to find the right add-on: + - There is also a talk that discusses in depth how to find the right add-on: - Either extend an existing add-on to fit your needs or create a new add-on that does exactly what you need. diff --git a/docs/mastering-plone/api.md b/docs/mastering-plone/api.md index 417fb4b9f..53df399d1 100644 --- a/docs/mastering-plone/api.md +++ b/docs/mastering-plone/api.md @@ -184,8 +184,8 @@ It aggregates tracebacks from many sources and (here comes the killer feature) e ```{seealso} -- ["What You Need To Know About Python Debugging" by Philip Bauer](https://www.youtube.com/watch?v=_OB6VlYKZkU&feature=youtu.be) -- ["PDB Like a Pro" by Philip Bauer](https://www.youtube.com/watch?v=yOG36Ae_TJ0&feature=youtu.be) +- ["What You Need To Know About Python Debugging" by Philip Bauer](https://www.youtube-nocookie.com/embed/_OB6VlYKZkU?privacy_mode=1) +- ["PDB Like a Pro" by Philip Bauer](https://www.youtube-nocookie.com/embed/yOG36Ae_TJ0?privacy_mode=1) ``` diff --git a/docs/mastering-plone/index.md b/docs/mastering-plone/index.md index 65ed29c8d..7b0b5df55 100644 --- a/docs/mastering-plone/index.md +++ b/docs/mastering-plone/index.md @@ -31,12 +31,10 @@ For Plone Classic see training {doc}`/theming/index`, training {doc}`/mastering- ``` ```{toctree} ---- -caption: Mastering Plone 6 Development -name: toc-mastering -maxdepth: 3 -numbered: 2 ---- +:caption: Mastering Plone 6 Development +:name: toc-mastering +:maxdepth: 3 +:numbered: 2 about_mastering intro diff --git a/docs/mastering-plone/volto_testing.md b/docs/mastering-plone/volto_testing.md index 886e8bd4b..3b448e557 100644 --- a/docs/mastering-plone/volto_testing.md +++ b/docs/mastering-plone/volto_testing.md @@ -103,7 +103,7 @@ For example you see that the heading is the talk title with preceding type of ta {file}`packages/volto-ploneconf/src/components/Views/__snapshots__/Talk.test.js.snap` -```html +```js // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders a talk view component with only required props 1`] = ` diff --git a/docs/mastering-plone/what_is_plone.md b/docs/mastering-plone/what_is_plone.md index dcf2556ff..4b0155984 100644 --- a/docs/mastering-plone/what_is_plone.md +++ b/docs/mastering-plone/what_is_plone.md @@ -333,7 +333,7 @@ Here are some basics that you need to understand if you are new to Volto: - You create a new Plone instance in an already set up Zope environment via the backend. This is by now not possible in Volto. - Volto takes advantage of [Semantic UI React components](https://react.semantic-ui.com/) to compose most of the views. -- The Volto default theme is based on Semantic UI theme and is called [Pastanaga](https://www.youtube.com/watch?v=wW9mTl1Tavc&t=133s). +- The Volto default theme is based on Semantic UI theme and is called [Pastanaga](https://www.youtube-nocookie.com/embed/wW9mTl1Tavc&t=133s&privacy_mode=1). - Same as Plone Classic, Volto is highly extendable with add-ons for further features. - Existing Volto components are customizable with a technology similar to `z3c.jbot` called {ref}`volto-overrides-componentshadowing-label`. - Volto provides server side rendering (SSR), important for SEO-purposes. diff --git a/docs/migrations/exportimport.md b/docs/migrations/exportimport.md index 4b6cdd07f..84ae3acb1 100644 --- a/docs/migrations/exportimport.md +++ b/docs/migrations/exportimport.md @@ -618,9 +618,9 @@ Keep in mind though that in a very strict sense you are lying to the users since Talks: -* [A new hope for migrations and upgrades](https://www.youtube.com/watch?v=6xoXXyGnk4U) - Talk at Ploneconf 2021 (online). -* [collective.exportimport: Tips, tricks and deploying staging content](https://www.youtube.com/watch?v=SfHPKgeA0I0) - Talk at Ploneconf 2021 (online). -* [Make Plone Migrations fun again with collective.exportimport](https://www.youtube.com/watch?v=HEBF5VqlUc8) - Talk at World Plone Day 2021 +* [A new hope for migrations and upgrades](https://www.youtube-nocookie.com/embed/6xoXXyGnk4U?privacy_mode=1) - Talk at Ploneconf 2021 (online). +* [collective.exportimport: Tips, tricks and deploying staging content](https://www.youtube-nocookie.com/embed/SfHPKgeA0I0?privacy_mode=1) - Talk at Ploneconf 2021 (online). +* [Make Plone Migrations fun again with collective.exportimport](https://www.youtube-nocookie.com/embed/HEBF5VqlUc8?privacy_mode=1) - Talk at World Plone Day 2021 [Migrating Content with Transmogrifier](https://2022.training.plone.org/transmogrifier/index.html) ``` diff --git a/docs/migrations/inplace.md b/docs/migrations/inplace.md index 466a1e744..750b43d2c 100644 --- a/docs/migrations/inplace.md +++ b/docs/migrations/inplace.md @@ -388,7 +388,7 @@ More complex migrations need to be separated into several steps that need to be In the following example, we assume to migrate a Plone 4.3 with multilingual Archetypes content to Plone 6.0 (Classic UI). ```{note} -Most of this information is also contained in the talk [Migrations! Migrations! Migrations!](https://www.youtube.com/watch?v=ZIN1qmhMHJ4) that deals with in-place migrations and the helper package https://github.com/collective/collective.migrationhelpers. +Most of this information is also contained in the talk [Migrations! Migrations! Migrations!](https://www.youtube-nocookie.com/embed/ZIN1qmhMHJ4?privacy_mode=1) that deals with in-place migrations and the helper package https://github.com/collective/collective.migrationhelpers. ``` The plan is to write upgrade steps for each step, once you know what needs to be done. @@ -509,7 +509,7 @@ After packing the database you can: * The migration can take a long time, especially the migration from Archetypes to Dexterity can take up to 12 hours. Consider using an export/import migration instead since that is much faster. -* Your site raises errors due to invalid data. See [Growing pains: PosKeyErrors and other malaises](https://www.youtube.com/watch?v=SwxN3BBxAM8) and https://www.starzel.de/blog/zodb-debugging +* Your site raises errors due to invalid data. See [Growing pains: PosKeyErrors and other malaises](https://www.youtube-nocookie.com/embed/SwxN3BBxAM8?privacy_mode=1) and https://www.starzel.de/blog/zodb-debugging * Migrations are hungry for resources. You might run out of disk space or memory. @@ -529,8 +529,8 @@ Helper Packages: Talks: -* [Migrations! Migrations! Migrations!](https://www.youtube.com/watch?v=ZIN1qmhMHJ4) - Talk at Ploneconf 2019 in Ferrara. -* [How to upgrade sites to Plone 5](https://www.youtube.com/watch?v=bQ-IpO-7F00) - Talk at Ploneconf 2015 in Bucharest. +* [Migrations! Migrations! Migrations!](https://www.youtube-nocookie.com/embed/ZIN1qmhMHJ4?privacy_mode=1) - Talk at Ploneconf 2019 in Ferrara. +* [How to upgrade sites to Plone 5](https://www.youtube-nocookie.com/embed/bQ-IpO-7F00?privacy_mode=1) - Talk at Ploneconf 2015 in Bucharest. * [Archetypes to Dexterity Migration](https://vimeo.com/110992921) - Talk at Ploneconf 2014 in Bristol. -* [Migrations, Upgrades and Relaunches](https://www.youtube.com/watch?v=1Qx0JALp3lQ) - Talk at Ploneconf 2013 in Brazilia. +* [Migrations, Upgrades and Relaunches](https://www.youtube-nocookie.com/embed/1Qx0JALp3lQ?privacy_mode=1) - Talk at Ploneconf 2013 in Brazilia. ``` \ No newline at end of file diff --git a/docs/plone-deployment/project-edit.md b/docs/plone-deployment/project-edit.md index 53f6ca44c..e8062ed27 100644 --- a/docs/plone-deployment/project-edit.md +++ b/docs/plone-deployment/project-edit.md @@ -28,11 +28,11 @@ Edit {file}`frontend/src/addons/volto-ploneconf2023/package.json` and append `@p ```json "addons": [ - ..., + "...more add-ons", "@plonegovbr/volto-code-block" ], "dependencies": { - ..., + "...more dependencies": "*", "@plonegovbr/volto-code-block": "*" } ``` diff --git a/docs/plone-deployment/server-setup.md b/docs/plone-deployment/server-setup.md index 3dcfbbf1e..84c21bc29 100644 --- a/docs/plone-deployment/server-setup.md +++ b/docs/plone-deployment/server-setup.md @@ -29,7 +29,7 @@ cp .env_dist .env Customize the {file}`.env` file to match your specific deployment environment. Here’s an example configuration: -```plaintext +```shell DEPLOY_ENV=prod DEPLOY_HOST=ploneconf2023-.tangrama.com.br DEPLOY_PORT=22 diff --git a/docs/teaching/after.md b/docs/teaching/after.md index 23085657b..586f15d41 100644 --- a/docs/teaching/after.md +++ b/docs/teaching/after.md @@ -1,10 +1,10 @@ --- myst: html_meta: - "description": "" - "property=og:description": "" - "property=og:title": "" - "keywords": "" + "description": "After the training: Aftercare, keep in touch, learn, improve" + "property=og:description": "After the training: Aftercare, keep in touch, learn, improve" + "property=og:title": "After the training: Aftercare, keep in touch, learn, improve" + "keywords": "Plone, Training, aftercare, keep in touch, learn, improve" --- (trainthetrainers-after-the-training-label)= @@ -17,8 +17,8 @@ This chapter is a work in progress You're done with your training. Or so you think: -> - Aftercare -> - Keep in Touch -> - Evaluate -> - Improve training material -> - Get quotes +- Aftercare +- Keep in Touch +- Evaluate +- Improve training material +- Get quotes diff --git a/docs/teaching/before.md b/docs/teaching/before.md index 1e2e60682..1a3ffae56 100644 --- a/docs/teaching/before.md +++ b/docs/teaching/before.md @@ -1,15 +1,15 @@ --- myst: html_meta: - "description": "" - "property=og:description": "" - "property=og:title": "" - "keywords": "" + "description": "Before the training: Create material, invite trainees, preparation" + "property=og:description": "Before the training: Create material, invite trainees, preparation" + "property=og:title": "Before the training: Create material, invite trainees, preparation" + "keywords": "Plone, Training, material, invite, trainees, preparation" --- (trainthetrainers-before-the-training-label)= -# Before the training: Create material, invite trainees, preparation +# Before the training: Create material, invite trainees, preparation ```{warning} This chapter is a first version. diff --git a/docs/teaching/during.md b/docs/teaching/during.md index cce449376..79d8b6968 100644 --- a/docs/teaching/during.md +++ b/docs/teaching/during.md @@ -1,15 +1,15 @@ --- myst: html_meta: - "description": "" - "property=og:description": "" - "property=og:title": "" - "keywords": "" + "description": "During training days: what to expect, do's and don'ts" + "property=og:description": "During training days: what to expect, do's and don'ts" + "property=og:title": "During training days: what to expect, do's and don'ts" + "keywords": "Training, Plone" --- (trainthetrainers-during-training-day-label)= -# During training day(s): what to expect, do's and don'ts +# During training days: what to expect, do's and don'ts ```{warning} This chapter is a work in progress @@ -17,14 +17,14 @@ This chapter is a work in progress This chapter will touch on subjects like: -> - How to structure your training day -> - Getting your trainees 'in sync' -> - Correcting students when they stray or get noisy -> - Using material, beamers, etc -> - breaks and attention span -> - What if you run out of time -> - Student and trainer fatigue -> - Trainers high +- How to structure your training day +- Getting your trainees 'in sync' +- Correcting students when they stray or get noisy +- Using material, beamers, etc +- breaks and attention span +- What if you run out of time +- Student and trainer fatigue +- Trainers high ## Structure of your training day diff --git a/docs/teaching/index.md b/docs/teaching/index.md index 346993327..b823a23b8 100644 --- a/docs/teaching/index.md +++ b/docs/teaching/index.md @@ -1,10 +1,10 @@ --- myst: html_meta: - "description": "" - "property=og:description": "" - "property=og:title": "" - "keywords": "" + "description": "Teaching Plone Trainings" + "property=og:description": "Teaching Plone Trainings" + "property=og:title": "Teaching Plone Trainings" + "keywords": "Teaching, training" --- (teaching-index-label)= diff --git a/docs/teaching/theory.md b/docs/teaching/theory.md index 6ac65fdac..99f8e24d3 100644 --- a/docs/teaching/theory.md +++ b/docs/teaching/theory.md @@ -1,10 +1,10 @@ --- myst: html_meta: - "description": "" - "property=og:description": "" - "property=og:title": "" - "keywords": "" + "description": "Training theory: education, how people learn and process information" + "property=og:description": "Training theory: education, how people learn and process information" + "property=og:title": "Training theory: education, how people learn and process information" + "keywords": "Training, theory, education, learn, process, information, Plone" --- (trainthetrainers-training-theory-label)= diff --git a/docs/theming/index.md b/docs/theming/index.md index 3979b388e..f11875736 100644 --- a/docs/theming/index.md +++ b/docs/theming/index.md @@ -35,7 +35,7 @@ A linux based laptop (Ubuntu, macOS) with code editor of your choice (we recomme ```{toctree} :caption: Plone Theming :maxdepth: 1 -:numbered: true +:numbered: preparation ttw_customizations diff --git a/docs/volto_customization/_static/variations.png b/docs/volto-customization/_static/variations.png similarity index 100% rename from docs/volto_customization/_static/variations.png rename to docs/volto-customization/_static/variations.png diff --git a/docs/volto_customization/blocks.md b/docs/volto-customization/blocks.md similarity index 77% rename from docs/volto_customization/blocks.md rename to 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 similarity index 90% rename from docs/volto_customization/custom_block.md rename to 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 similarity index 92% rename from docs/volto_customization/data_adapters.md rename to 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/index.md b/docs/volto-customization/index.md similarity index 98% rename from docs/volto_customization/index.md rename to docs/volto-customization/index.md index e8c55a48d..b336ce8ca 100644 --- a/docs/volto_customization/index.md +++ b/docs/volto-customization/index.md @@ -43,7 +43,7 @@ Prerequisites: :caption: Volto Customization for JavaScript Beginners :name: toc-voltocustomization :maxdepth: 3 -:numbered: true +:numbered: intro installation @@ -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 new file mode 100644 index 000000000..92959f329 --- /dev/null +++ b/docs/volto-customization/installation.md @@ -0,0 +1,198 @@ +--- +myst: + html_meta: + "description": "Volto and Plone development - installation steps for JavaScript Beginners" + "property=og:description": "Volto and Plone development - installation steps for JavaScript Beginners" + "property=og:title": "Installation steps for JavaScript Beginners" + "keywords": "Plone, Volto, Training, Installation" +--- + +# Installation + +```{warning} +For the most up-to-date information on how to get started with Volto you can check the [official documentation](https://6.docs.plone.org/volto/index.html). +``` + +Getting started with Volto involves setting up a development environment, understanding its core concepts, and exploring its features. Here's a step-by-step guide to help you begin your journey with Volto: + +## Prerequisites + +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 Plone stack + +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 +pipx run cookieplone project +``` + +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 +[11/17] Volto Addon Name (volto-project-title): volto-teaser-tutorial +``` + +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. + +## Install the project + +To work on your project, you need to install both the frontend and backend. + +Change your current working directory to `project-title`. + +```shell +cd project-title +``` + +To install both the Plone backend and frontend, use the following command. + +```shell +make install +``` + +## Start Plone + +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. + +### Start Plone backend + +In the currently open session, issue the following command. + +```shell +make backend-start +``` + +### Start Plone frontend + +Create a second shell session in a new window. +Start the Plone frontend with the following command. + +```shell +make frontend-start +``` + +Open a browser at the following URL to visit your Plone site. + +http://localhost:3000 + +You can then login with admin/admin at http://localhost:3000/login + +## Volto addon + +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. + +```{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. +``` + +## Workspaces + +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. + +We can define workspaces using the `pnpm-workspace.yaml` file in root of our project. This is taken care for us by Cookieplone. + +```yaml +packages: + # all packages in direct subdirs of packages/ + - "core/packages/*" + - "packages/*" +``` + +All the packages in the {file}`packages` directory will be included in the workspace. + +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 + "dependencies": { + "@plone/volto": "workspace:*", + "@plone/registry": "workspace:*", + "volto-teaser-tutorial": "workspace:*" + }, +``` + +```{note} +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 + +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 +pnpm --filter volto-teaser-tutorial add papaparse +``` + +## Addons - first look + +Volto add-ons are just plain JavaScript packages with an +additional feature: they provide helper functions that mutate Volto's +configuration registry. + +Their `main` entry in `package.json` should point to `src/index.js`, +which should be an ES6 module with a default export. +Here is the default add-on configuration loader: + +```js +export default (config) => { + return config; +}; +``` + +### TypeScript configuration + +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. + +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. + +```js +{ + "compilerOptions": { + "paths": { + "@plone/volto/*": ["../../core/packages/volto/src/*"], + "volto-teaser-tutorial/*": ["./src/*"] + } + }, +} +``` + +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](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](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 similarity index 72% rename from docs/volto_customization/intro.md rename to docs/volto-customization/intro.md index ebed63877..3565e210e 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-nocookie.com/embed/playlist?list=PLGN9BI-OAQkTVkkJfSMHu-l-_AVW_uoRf&privacy_mode=1) 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/schema.md b/docs/volto-customization/schema.md similarity index 86% rename from docs/volto_customization/schema.md rename to 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 } > -
+
{(href.hasPreviewImage || href.image_field || image) && (
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 similarity index 91% rename from docs/volto_customization/shadowing.md rename to 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 similarity index 88% rename from docs/volto_customization/styling.md rename to 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 similarity index 96% rename from docs/volto_customization/teaser_variations.md rename to 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 } > -
+
{(href.hasPreviewImage || href.image_field || image) && (
{ @@ -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` 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) => {props.alt; - -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 ( -
- <> - {!href && isEditMode && ( - -
- -

{intl.formatMessage(messages.PleaseChooseContent)}

-
-
- )} - {href && ( - -
- {(href.hasPreviewImage || href.image_field || image) && ( -
- -
- )} -
- {data?.head_title && ( -
{data.head_title}
- )} -

{data?.title}

- {data.creationDate &&

{formattedDate}

} - {!data.hide_description &&

{data?.description}

} -
-
-
- )} - -
- ); -}; - -TeaserBlockImageDefault.propTypes = { - data: PropTypes.objectOf(PropTypes.any).isRequired, - isEditMode: PropTypes.bool, -}; - -export default TeaserBlockImageDefault; -``` - -TeaserBlockImageRight: - -```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) => {props.alt; - -const TeaserBlockImageRight = (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 ( -
- <> - {!href && isEditMode && ( - -
- -

{intl.formatMessage(messages.PleaseChooseContent)}

-
-
- )} - {href && ( - -
-
- {data?.head_title && ( -
{data.head_title}
- )} -

{data?.title}

- {data.creationDate &&

{formattedDate}

} - {!data.hide_description &&

{data?.description}

} -
- {(href.hasPreviewImage || href.image_field || image) && ( -
- -
- )} -
-
- )} - -
- ); -}; - -TeaserBlockImageRight.propTypes = { - data: PropTypes.objectOf(PropTypes.any).isRequired, - isEditMode: PropTypes.bool, -}; - -export default TeaserBlockImageRight; -``` - -TeaserBlockImageOverlay: - -```jsx -import React from "react"; -import PropTypes from "prop-types"; -import { Message } from "semantic-ui-react"; -import { defineMessages, useIntl } from "react-intl"; -import cloneDeep from "lodash/cloneDeep"; -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) => {props.alt; - -const TeaserBlockImageOverlay = (props) => { - const { className, data, isEditMode, extension = "cardTemplates" } = 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 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 Image = config.getComponent("Image").component || DefaultImage; - const { openExternalLinkInNewTab } = config.settings; - - return ( -
- <> - {!href && isEditMode && ( - -
- -

{intl.formatMessage(messages.PleaseChooseContent)}

-
-
- )} - {href && ( - -
- {(href.hasPreviewImage || href.image_field || image) && ( -
- -
- )} - -
- {data?.head_title && ( -
{data.head_title}
- )} -
-

{data?.title}

- {!data.hide_description &&

{data?.description}

} - {data?.creationDate && ( -

{formattedDate}

- )} -
-
-
-
- )} - -
- ); -}; - -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/installation.md b/docs/volto_customization/installation.md deleted file mode 100644 index 128ebd9d5..000000000 --- a/docs/volto_customization/installation.md +++ /dev/null @@ -1,256 +0,0 @@ ---- -myst: - html_meta: - "description": "Volto and Plone development - installation steps for JavaScript Beginners" - "property=og:description": "Volto and Plone development - installation steps for JavaScript Beginners" - "property=og:title": "Installation steps for JavaScript Beginners" - "keywords": "Plone, Volto, Training, Installation" ---- - -# Installation - -```{warning} -For the most up-to-date information on how to get started with Volto you can check the [official documentation](https://6.docs.plone.org/volto/index.html). -``` - -Getting started with Volto involves setting up a development environment, understanding its core concepts, and exploring its features. Here's a step-by-step guide to help you begin your journey with Volto: - -## 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 | - -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 - -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): - -```shell -npm install -g yo -npm install -g @plone/generator-volto -``` - -Then you can bootstrap the project with: - -```shell -yo @plone/volto volto-tutorial-project -``` - -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`. - -Now you can start your newly created Volto project: - -```shell -cd volto-tutorial-project -yarn start -``` - -You can then login with admin/admin at http://localhost:3000/login. - -## Bootstrap an add-on - -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): - -```shell -yo @plone/volto:addon -``` - -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. - -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`. - -Back to the project, you can edit `jsconfig.json` and add your add-on: - -```json -{ - "compilerOptions": { - "baseUrl": "src", - "paths": { - "volto-teaser-tutorial": ["addons/volto-teaser-tutorial/src"] - } - } -} -``` - -```{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. -``` - -### Volto addon script - -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. - -```shell -npx -p @plone/scripts addon clone [options] [destination] -``` - -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. - -```shell -npx -p @plone/scripts addon clone https://github.com/kitconcept/volto-teaser-tutorial.git --branch main -``` - -### (Optional) Use mrs-developer to sync add-on to GitHub - -You can also immediately push the package to GitHub, then use `[mrs-developer]` -to manage the package and `jsconfig.json` changes. - -Install mrs-developer as a development dependency by running: - -```shell -yarn add -W -D mrs-developer -``` - -Create a `mrs.developer.json` in your project with the following content (adjust it according -to your names and repository location): - -```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`. - -### Add the add-on as workspace - -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. - -You could treat workspaces as major "working environment" for your project. So a yarn install would also install dependencies from `src/addons/*` - -Change the Volto project's `package.json` to include something like: - -```json -{ - "private": "true", - "workspaces": [ - "src/addons/volto-teaser-tutorial" // or simply src/addons/* - ] -} -``` - -```{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. -``` - -### Managing add-on dependencies - -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"] -// ... -``` - -## Add-ons - first look - -Volto add-ons are just plain JavaScript packages with an -additional feature: they provide helper functions that mutate Volto's -configuration registry. - -Their `main` entry in `package.json` should point to `src/index.js`, -which should be an ES6 module with a default export. -Here is the default add-on configuration loader: - -```js -export default (config) => { - return config; -}; -``` - -**Pro-Tip 💡** - -```{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. -``` - -```js -export function simpleLink(config) { - return installSimpleLink(config); -} - -export function tableButton(config) { - return installTableButton(config); -} -``` - -```js - ... -"addons": [ - "volto-slate:tableButton,simpleLink", - "@eeacms/volto-tabs-block", -] -... - -``` - -## Documentation and Resources - -Refer to the official Volto documentation 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. - -```{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/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/voltoaddons/about/index.md b/docs/voltoaddons/about/index.md index 49e499de7..ec6977079 100644 --- a/docs/voltoaddons/about/index.md +++ b/docs/voltoaddons/about/index.md @@ -38,5 +38,5 @@ in collaboration with [Víctor Fernández de Alba](https://x.com/sneridagh). The first editions were recorded as part of the Plone Conference 2020 and are available online: -- [Volto Addons - part 1](https://www.youtube.com/watch?v=LyYG2hDmIAk) -- [Volto Addons - part 2](https://www.youtube.com/watch?v=5JtKHRk5H0U) +- [Volto add-ons - part 1](https://www.youtube-nocookie.com/embed/LyYG2hDmIAk?privacy_mode=1) +- [Volto add-ons - part 2](https://www.youtube-nocookie.com/embed/5JtKHRk5H0U?privacy_mode=1) diff --git a/docs/voltoaddons/index.md b/docs/voltoaddons/index.md index 44c793f07..1eed9668d 100644 --- a/docs/voltoaddons/index.md +++ b/docs/voltoaddons/index.md @@ -24,7 +24,7 @@ ReactJS and Volto. ```{toctree} :caption: Volto Add-ons Development :maxdepth: 1 -:numbered: true +:numbered: intro diff --git a/docs/voltohandson/index.md b/docs/voltohandson/index.md index d11103c77..d33059209 100644 --- a/docs/voltohandson/index.md +++ b/docs/voltohandson/index.md @@ -23,7 +23,7 @@ which is intended as a half to full day training for people who already know the ```{toctree} :caption: Volto Hands-On :maxdepth: 2 -:numbered: true +:numbered: intro quickstart diff --git a/requirements.txt b/requirements.txt index fc82d99ed..2b7ff98b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ -c constraints.txt Sphinx -lesscpy linkify-it-py myst-parser nuclia