Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
65eb4ba
initial test setup
erral Jul 17, 2025
e4a726d
fix
erral Jul 17, 2025
31a1d02
tests
erral Jul 17, 2025
61642d2
lint & format
erral Jul 17, 2025
0d4c427
lint
erral Jul 17, 2025
714cdfe
remove unneeded file
erral Jul 18, 2025
5ec0960
add namespaces
erral Jul 18, 2025
158204e
adjust python version to run tests
erral Jul 18, 2025
02b2f2b
Revert "adjust python version to run tests"
erral Jul 18, 2025
e041695
don't be explicit about the python version
erral Jul 18, 2025
e467f72
fix: set python version in Makefile, and let it come from environment…
erral Jul 24, 2025
be12b86
fix syntax
erral Jul 24, 2025
37e9dd2
explicitely run on the created venv
erral Jul 24, 2025
bb517f0
restore
erral Jul 24, 2025
62f94d6
change env var check
erral Jul 24, 2025
0cec8e8
explicitely activate the venv
erral Jul 24, 2025
51a8f6a
do not be exoplicit
erral Jul 24, 2025
86cd9ba
ignore python versions
erral Jul 24, 2025
4aa7b2c
adjust deps
erral Jul 24, 2025
cd10dea
remove dependency
erral Jul 24, 2025
85c95d0
feat: make browser view registrations conditional on being Plone 6.1 …
erral Jul 25, 2025
33daeb9
feat: support Plone 6.0 configuring the RelatedItems widget
erral Jul 25, 2025
a959a9c
internal: lint and format
erral Jul 25, 2025
f87f632
internal: add releasing features
erral Jul 25, 2025
a97693d
internal: lint and format
erral Jul 25, 2025
a4ba29b
fix: tests
erral Jul 25, 2025
2ed9180
feat: register dynamic view for PloneSite and LRFs
erral Aug 14, 2025
6b1d24a
feat: name the view
erral Aug 14, 2025
439d9b8
feat: view for INavigationRoot
erral Aug 27, 2025
653358e
lint and format
erral Aug 27, 2025
be209b6
fix: change vocabulary to find views using the interface
erral Sep 12, 2025
d74cb94
fix: remove plone domain
erral Sep 12, 2025
bab1631
docs
erral Sep 12, 2025
d52d4c8
feat: handle row widths using a controlpanel
erral Sep 12, 2025
e113b64
Add upgrade_step: Add row width field in the controlpanel
erral Sep 12, 2025
43ef039
use datagridfield
erral Sep 12, 2025
ee0c257
upgrade step
erral Sep 12, 2025
a817c43
feat: change controlpanel name
erral Sep 12, 2025
d29b301
Add upgrade_step: Change Control Panel name in registry
erral Sep 12, 2025
6737bbf
feat: rename control panels
erral Sep 12, 2025
d1ac0e0
format
erral Sep 12, 2025
ea4c1ae
fix: create the dynamic page folder only if the user is editing the s…
erral Sep 15, 2025
553dd68
fix: change the registry record name
erral Sep 15, 2025
3b96881
feat: register a text indexer extender
erral Sep 15, 2025
76d971d
make lint
erral Sep 15, 2025
f32b4af
fix: controlpanel interfaces
erral Sep 15, 2025
a6d14b7
internal: bump profile version number for tests
erral Sep 15, 2025
adf2369
Merge branch 'develop' into erral-index-contents
erral Sep 15, 2025
bfc1c26
fix: controlpanel interfaces
erral Sep 15, 2025
fcb7270
Merge branch 'develop' into erral-index-contents
erral Sep 15, 2025
fe9327c
fix: remove unneeded upgrade function
erral Sep 15, 2025
9c660ac
fix: add missing dep
erral Sep 15, 2025
1368b6e
columns 1
libargutxi Sep 16, 2025
8bd7090
feat: add utility functions to easily add views and enable behaviors …
erral Sep 18, 2025
10d9f45
extra_class field for each row
libargutxi Sep 18, 2025
bbe0028
format and lint
libargutxi Sep 18, 2025
bdc1791
Merge pull request #2 from codesyntax/erral-index-contents
erral Sep 18, 2025
ccc6350
internal: i18n
erral Sep 18, 2025
4f3f5e1
Add upgrade_step: Add a new default behavior to the row
erral Sep 18, 2025
c5b1f6c
feat: add an upgrade step to set the new behavior for the DynamicPageRow
erral Sep 18, 2025
85f38cb
fix: change profiel version number for tests
erral Sep 18, 2025
96cdf38
format
erral Sep 18, 2025
b851a34
internal: metadata
erral Sep 18, 2025
566bef3
changlog
erral Sep 18, 2025
22bcccf
internal: docs
erral Sep 18, 2025
1a9c740
defautl preview-mode
libargutxi Sep 24, 2025
d59a759
add translations
erral Oct 8, 2025
4a6ee3c
format
erral Oct 8, 2025
9efa308
feat: add check
erral Oct 8, 2025
2fe2261
syntax error
erral Oct 8, 2025
8c1f2d3
syntax error
erral Oct 8, 2025
2dae288
translations
erral Oct 8, 2025
52dab3a
remove unneeded behaviors
erral Oct 8, 2025
8d8efec
Add upgrade_step: Remove unneeded behaviors
erral Oct 8, 2025
439e9af
upgrade step to remove unneeded behaviors
erral Oct 8, 2025
074ee62
feat: translate review states and transitions
erral Oct 8, 2025
2fbd9a9
format
erral Oct 8, 2025
908c3f5
lint
erral Oct 8, 2025
749afa5
remove license and keep classifier
erral Oct 8, 2025
8fb856b
whitespace
erral Oct 8, 2025
25b1e18
update profile version number
erral Oct 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,30 @@ jobs:
python-version: ${{ needs.config.outputs.python-version }}
plone-version: ${{ needs.config.outputs.plone-version }}

i18n:
name: "Missing i18n:translate"
runs-on: ubuntu-latest
needs:
- config

steps:
- uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v6

- name: Check for untranslated strings
shell: bash
run: |
uvx i18ndude find-untranslated -n src/
test:
name: "Backend: Test"
needs:
- config
uses: plone/meta/.github/workflows/[email protected]
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
plone-version: ['6.1-latest', '6.0-latest']
python-version: ["3.10", "3.11", "3.12", "3.13"]
plone-version: ["6.1-latest", "6.0-latest"]
with:
python-version: ${{ matrix.python-version }}
plone-version: ${{ matrix.plone-version }}
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Contributors

- Lur Ibargutxi [[email protected]]
- Mikel Larreategi [[email protected]]
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cs_dynamicpages Copyright 2025, Lur Ibargutxi
cs_dynamicpages Copyright 2025, CodeSyntax

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
Expand Down
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ requirements-mxdev.txt: pyproject.toml mx.ini ## Generate constraints file

$(VENV_FOLDER): requirements-mxdev.txt ## Install dependencies
@echo "$(GREEN)==> Install environment$(RESET)"
@uv venv --python=3.10 $(VENV_FOLDER)
@uv venv $(VENV_FOLDER)
@uv pip install -r requirements-mxdev.txt

.PHONY: sync
Expand Down Expand Up @@ -131,4 +131,10 @@ test-coverage: $(VENV_FOLDER) ## run tests with coverage

## Add bobtemplates features (check bobtemplates.plone's documentation to get the list of available features)
add: $(VENV_FOLDER)
/home/lur/plonecli_azkena/bin/plonecli add $(filter-out $@,$(MAKECMDGOALS))
@uvx plonecli add -b .mrbob.ini $(filter-out $@,$(MAKECMDGOALS))

.PHONY: release
release: $(VENV_FOLDER) ## Create a release
@echo "$(GREEN)==> Create a release$(RESET)"
@uv pip install -e ".[release]"
@uv run fullrelease
68 changes: 55 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
# cs_dynamicpages

An addon to create dynamic pages for Plone
A new addon for Plone to create web-based dynamic pages.

## Features
The concept is pretty similar that of Volto blocks:

TODO: List our awesome features
- You can build a page using reusable items.
- Each item can have different fields
- Each item can have different views

## Provided Content Types

- DynamicPageFolder: this content type will be created in a given folder, and will be the container
where all the rows will be added.

- DynamicPageRow: this content type will be the one that will be rendered in a separate row in the view

- DynamicPageRowFeatured: this content type can be used to save static information that can be shown in a
row. For instance: each of the items of a slider need a title, a description or an image. They can be added
using this content-type

## Provided View

There is just one view `dynamic_view` registered for Folders and Naviation roots

### Different fields

To provide different fields, you should register standard `behaviors` to the `DynamicPageRow`
content type.

### Custom views

To provide different views, you should register standard views (using `zcml`).

Those views must be registered for implementers of `cs_dynamicpages.content.dynamic_page_row.IDynamicPageRow`
and their name _must_ start by `cs_dynamicpages-`.

To ease installation of such views in your products, `cs_dynamicpages.utils` contains 2 utility functions:

- `add_custom_view`: function to add a given view to the list of available row types
- `enable_behavior`: function to enable the given behavior in the `DynamicPageRow` content type

### Restrict fields in the row edit view

You may register several behaviors for `DynamicPageRow` objects but only use some of the fields
provided by them in a given view.

You can restrict which fields are shown in the edit form of the `DynamicPageRow` going to the
Dynamic Pages Controlpanel, and setting there the list of fields that will be shown when editing
each of the row types.

## Installation

Expand All @@ -22,23 +65,23 @@ make create-site

## Contribute

- [Issue tracker](https://github.com/cs/cs_dynamicpages/issues)
- [Source code](https://github.com/cs/cs_dynamicpages/)
- [Issue tracker](https://github.com/codesyntax/cs_dynamicpages/issues)
- [Source code](https://github.com/codesyntax/cs_dynamicpages/)

### Prerequisites ✅

- An [operating system](https://6.docs.plone.org/install/create-project-cookieplone.html#prerequisites-for-installation) that runs all the requirements mentioned.
- [uv](https://6.docs.plone.org/install/create-project-cookieplone.html#uv)
- [Make](https://6.docs.plone.org/install/create-project-cookieplone.html#make)
- [Git](https://6.docs.plone.org/install/create-project-cookieplone.html#git)
- [Docker](https://docs.docker.com/get-started/get-docker/) (optional)
- An [operating system](https://6.docs.plone.org/install/create-project-cookieplone.html#prerequisites-for-installation) that runs all the requirements mentioned.
- [uv](https://6.docs.plone.org/install/create-project-cookieplone.html#uv)
- [Make](https://6.docs.plone.org/install/create-project-cookieplone.html#make)
- [Git](https://6.docs.plone.org/install/create-project-cookieplone.html#git)
- [Docker](https://docs.docker.com/get-started/get-docker/) (optional)

### Installation 🔧

1. Clone this repository, then change your working directory.

```shell
git clone [email protected]:cs/cs_dynamicpages.git
git clone [email protected]:codesyntax/cs_dynamicpages.git
cd cs_dynamicpages
```

Expand All @@ -48,7 +91,6 @@ make create-site
make install
```


### Add features using `plonecli` or `bobtemplates.plone`

This package provides markers as strings (`<!-- extra stuff goes here -->`) that are compatible with [`plonecli`](https://github.com/plone/plonecli) and [`bobtemplates.plone`](https://github.com/plone/bobtemplates.plone).
Expand Down Expand Up @@ -83,4 +125,4 @@ The project is licensed under GPLv2.

## Credits and acknowledgements 🙏

Generated using [Cookieplone (0.9.7)](https://github.com/plone/cookieplone) and [cookieplone-templates (6782781)](https://github.com/plone/cookieplone-templates/commit/6782781dae4bafb227467828066ab16b84c23750) on 2025-07-07 09:25:15.108762. A special thanks to all contributors and supporters!
Generated using [Cookieplone (0.9.7)](https://github.com/plone/cookieplone) and [cookieplone-templates (4d55553)](https://github.com/plone/cookieplone-templates/commit/4d55553d61416df56b3360914b398d675b3f72a6) on 2025-07-17 11:59:12.982862. A special thanks to all contributors and supporters!
1 change: 1 addition & 0 deletions news/+1.internal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Initial release @codesyntax
57 changes: 32 additions & 25 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,49 +1,55 @@
[project]
name = "cs_dynamicpages"
dynamic = ["version"]
description = "An addon to create dynamic pages for Plone"
description = "A new addon for Plone"
readme = "README.md"
license = "GPL-2.0-only"
requires-python = ">=3.10"
authors = [
{ name = "Lur Ibargutxi", email = "[email protected]" },
]
keywords = [
"CMS",
"Plone",
"Python",
]
authors = [{ name = "CodeSyntax", email = "[email protected]" }]
keywords = ["CMS", "Plone", "Python"]
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Web Environment",
"Framework :: Plone","Framework :: Plone :: 6.0","Framework :: Plone :: 6.1",
"Framework :: Plone",
"Framework :: Plone :: 6.0",
"Framework :: Plone :: 6.1",
"Framework :: Plone :: Addon",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
"Operating System :: OS Independent",
"Programming Language :: Python","Programming Language :: Python :: 3.10","Programming Language :: Python :: 3.11","Programming Language :: Python :: 3.12","Programming Language :: Python :: 3.13",
"Programming Language :: Python",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"Products.CMFPlone",
"plone.api",
"z3c.jbot",
"collective.z3cform.datagridfield",
"plone.app.upgrade",
]

[project.optional-dependencies]
test = [
"horse-with-no-namespace",
"plone.app.testing",
"plone.classicui","plone.restapi[test]",
"plone.app.contenttypes[test]",
"plone.classicui",
"plone.restapi[test]",
"pytest",
"pytest-cov",
"pytest-plone>=0.5.0",
]
release = [
"zest.releaser[recommended]",
"zestreleaser.towncrier",
"zest.pocompile",
]

[project.urls]
Homepage = "https://github.com/cs/cs_dynamicpages"
Homepage = "https://github.com/codesyntax/cs_dynamicpages"
PyPI = "https://pypi.org/project/cs_dynamicpages"
Source = "https://github.com/cs/cs_dynamicpages"
Tracker = "https://github.com/cs/cs_dynamicpages/issues"
Source = "https://github.com/codesyntax/cs_dynamicpages"
Tracker = "https://github.com/codesyntax/cs_dynamicpages/issues"


[project.entry-points."plone.autoinclude.plugin"]
Expand All @@ -63,9 +69,7 @@ build-backend = "hatchling.build"
strict-naming = true

[tool.hatch.build.targets.sdist]
exclude = [
"/.github",
]
exclude = ["/.github"]

[tool.hatch.build.targets.wheel]
packages = ["src/cs_dynamicpages"]
Expand All @@ -76,7 +80,7 @@ filename = "CHANGELOG.md"
start_string = "<!-- towncrier release notes start -->\n"
title_format = "## {version} ({project_date})"
template = "news/.changelog_template.jinja"
issue_format = "[#{issue}](https://github.com/cs/cs_dynamicpages/issues/{issue})"
issue_format = "[#{issue}](https://github.com/collective/cs_dynamicpages/issues/{issue})"
underlines = ["", "", ""]

[[tool.towncrier.type]]
Expand Down Expand Up @@ -131,7 +135,8 @@ lint.select = [
# mccabe
"C90",
# pycodestyle
"E", "W",
"E",
"W",
# pyflakes
"F",
# pygrep-hooks
Expand Down Expand Up @@ -168,6 +173,8 @@ testpaths = ["tests"]
source_pkgs = ["cs_dynamicpages", "tests"]
branch = true
parallel = true
omit = [
"src/cs_dynamicpages/locales/*.py",
]
omit = ["src/cs_dynamicpages/locales/*.py"]


[tool.zest-releaser]
python-file-with-version = "src/cs_dynamicpages/__init__.py"
45 changes: 27 additions & 18 deletions src/cs_dynamicpages/behaviors/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,33 @@

<!-- -*- extra stuff goes here -*- -->

<plone:behavior
name="cs_dynamicpages.row_width"
title="RowWidth"
description="This behavior provides..."
provides=".row_width.IRowWidth"
factory=".row_width.RowWidth"
marker=".row_width.IRowWidthMarker"
/>


<plone:behavior
name="cs_dynamicpages.row_columns"
title="RowColumns"
description="This behavior provides..."
provides=".row_columns.IRowColumns"
factory=".row_columns.RowColumns"
marker=".row_columns.IRowColumnsMarker"
/>
<plone:behavior
name="cs_dynamicpages.row_width"
title="RowWidth"
description="This behavior provides..."
factory=".row_width.RowWidth"
provides=".row_width.IRowWidth"
marker=".row_width.IRowWidthMarker"
/>

<plone:behavior
name="cs_dynamicpages.extra_class"
title="ExtraClass"
description="This behavior provides..."
factory=".extra_class.ExtraClass"
provides=".extra_class.IExtraClass"
marker=".extra_class.IExtraClassMarker"
/>


<plone:behavior
name="cs_dynamicpages.row_columns"
title="RowColumns"
description="This behavior provides..."
factory=".row_columns.RowColumns"
provides=".row_columns.IRowColumns"
marker=".row_columns.IRowColumnsMarker"
/>


<plone:behavior
Expand Down
41 changes: 41 additions & 0 deletions src/cs_dynamicpages/behaviors/extra_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from cs_dynamicpages import _
from plone import schema
from plone.autoform.interfaces import IFormFieldProvider
from plone.supermodel import model
from Products.CMFPlone.utils import safe_hasattr
from zope.component import adapter
from zope.interface import implementer
from zope.interface import Interface
from zope.interface import provider


class IExtraClassMarker(Interface):
pass


@provider(IFormFieldProvider)
class IExtraClass(model.Schema):
""" """

extra_class = schema.TextLine(
title=_("Extra CSS class"),
description=_("Enter an extra CSS class that will be added to the row"),
required=False,
)


@implementer(IExtraClass)
@adapter(IExtraClassMarker)
class ExtraClass:
def __init__(self, context):
self.context = context

@property
def extra_class(self):
if safe_hasattr(self.context, "extra_class"):
return self.context.extra_class
return None

@extra_class.setter
def extra_class(self, value):
self.context.extra_class = value
Loading