diff --git a/docs/backend/control-panels.md b/docs/backend/control-panels.md deleted file mode 100644 index 602a90f75..000000000 --- a/docs/backend/control-panels.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -myst: - html_meta: - "description": "How to add a Control Panel" - "property=og:description": "How to add a Control Panel" - "property=og:title": "Control panels" - "keywords": "Plone, Add, Control Panel" ---- - -(backend-controlpanels-label)= - -# Control panels - -## Adding a control panel -To add a control panel to your add-on, you can use [`plonecli`](https://pypi.org/project/plonecli/) as follows: - -```shell -plonecli add controlpanel -``` - -This will create the control panel Python file in the control panel's folder where you can define your control panel schema fields. - -## Registering a Control panel -To manually register a view as a control panel, add the following registration to your `/profiles/default/controlpanel.xml`. - -```xml - - - - Manage portal - - -``` - -```{seealso} -See the chapter {ref}`training:controlpanel-label` from the Mastering Plone 6 Training. -``` - -```{todo} -Contribute to this documentation! -See issue [Backend > Control Panels needs content](https://github.com/plone/documentation/issues/1304). -``` \ No newline at end of file diff --git a/docs/backend/index.md b/docs/backend/index.md index 3e7dd3278..7bea7cfd5 100644 --- a/docs/backend/index.md +++ b/docs/backend/index.md @@ -21,7 +21,6 @@ annotations behaviors configuration-registry content-types/index -control-panels fields global-utils indexing diff --git a/docs/developer-guide/create-control-panel.md b/docs/developer-guide/create-control-panel.md new file mode 100644 index 000000000..7f9d660f1 --- /dev/null +++ b/docs/developer-guide/create-control-panel.md @@ -0,0 +1,437 @@ +--- +myst: + html_meta: + "description": "How to create a control panel in Plone for Classic UI and Volto" + "property=og:description": "How to create a control panel in Plone for Classic UI and Volto" + "property=og:title": "Create a control panel in Plone for Classic UI and Volto" + "keywords": "Plone, create, control panel, plonecli, registry, Classic UI, Volto, frontend, backend" +--- + +(backend-controlpanels-label)= + +# Create a control panel + +This chapter describes how to create a control panel for your Plone add-on, whether accessed through either the Classic UI or Volto frontend. + +It also covers advanced topics—including how to group fields in your control panel—and provides a schema field reference, troubleshooting tips, control panel file structure, and a Plone REST API compatibility reference. + + +## Creation approaches + +There are two approaches to create a control panel for your Plone add-on: + +- [`plonecli`](https://pypi.org/project/plonecli/) +- manual + + +### `plonecli` + +To add a control panel to your add-on, you can use [`plonecli`](https://pypi.org/project/plonecli/) as follows. + +```shell +plonecli add controlpanel +``` + +This creates the control panel Python file in the control panel's folder where you can define your control panel schema fields. + + +### Manual + +To manually create a control panel, go through the following steps. + +- Define the settings interface and form. +- Register the control panel view in ZCML. +- Add the control panel to the Plone control panel listing. +- Set default values in the registry. + +#### Define the settings interface and form + +Create a Python module, {file}`mypackage/controlpanel/settings.py`, that defines your control panel's settings interface and form class as follows. + +```python +# mypackage/controlpanel/settings.py +from zope import schema +from zope.interface import Interface +from plone.app.registry.browser.controlpanel import RegistryEditForm, ControlPanelFormWrapper +from plone.z3cform import layout + +class IMyControlPanelSettings(Interface): + """Schema for the control panel form.""" + + my_setting = schema.TextLine( + title=u'My Setting', + description=u'Enter the value for my setting', + required=False, + default=u'' + ) + + my_choice = schema.Choice( + title=u'My Choice', + description=u'Select a value for my choice', + required=False, + default=u'value3', + values=['value1', 'value2', 'value3'] + ) + +class MyControlPanelForm(RegistryEditForm): + """Control panel form.""" + + schema = IMyControlPanelSettings + schema_prefix = "my.addon" + label = u"My Addon Settings" + +# Wrap the form with plone.z3cform's ControlPanelFormWrapper to get the Plone +# control panel look and feel +MyControlPanelView = layout.wrap_form(MyControlPanelForm, ControlPanelFormWrapper) +``` + + +#### Register the control panel view + +Create a file {file}`mypackage/controlpanel/configure.zcml` with the following content to register the control panel view in ZCML. + +```xml + + + + + + +``` + +Make sure to include the above file in your package's main {file}`mypackage/configure.zcml` as shown by the highlighted line below. + +{emphasize-lines="9"} +```xml + + + + + + + + +``` + +#### Add the control panel entry + +Create a {file}`mypackage/profiles/default/controlpanel.xml` in your package's GenericSetup profile with the following content to add your control panel to the Plone control panel listing. + +```xml + + + + + Manage portal + + +``` + +The category attribute can be one of the following values. +These values correspond to the groups in {guilabel}`Site Setup`. + +`plone-general` +: {guilabel}`General` + +`plone-content` +: {guilabel}`Content` + +`plone-users` +: {guilabel}`Users` + +`plone-security` +: {guilabel}`Security` + +`plone-advanced` +: {guilabel}`Advanced` + + +#### Set default values in the registry + +Define default values for your settings in {file}`mypackage/profiles/default/registry.xml`. + +```xml + + + + + default value + value3 + + +``` + + +#### Register a control panel + +To manually register a view as a control panel, add the following registration to your {file}`/profiles/default/controlpanel.xml`. + +```xml + + + + Manage portal + + +``` + +After you perform the above steps for the manual process, you must restart the Plone site. To stop a running Plone instance, press {kbd}`ctrl-c` in the terminal where Plone is running. To start it again, use the appropriate command based on your installation method: + +`````{tab-set} + +````{tab-item} buildout +```shell +bin/instance fg +``` +```` + +````{tab-item} pip +```shell +bin/runwsgi -v instance/etc/zope.ini +``` +```` + +````{tab-item} Cookieplone +For a backend add-on only, use the following command. + +```shell +make backend-start +``` + +For both a backend and frontend add-on project, open two separate terminal sessions. + +In the first session, start the backend. + +```shell +make backend-start +``` + +In the second session, start the frontent. + +```shell +make frontend-start +``` +```` + +````` + +Your control panel should now appear in {guilabel}`Site Setup`. + +## Access your settings in code + +You can access your settings in Python code as follows. + +```python +from plone.registry.interfaces import IRegistry +from zope.component import getUtility + +registry = getUtility(IRegistry) +settings = registry.forInterface(IMyControlPanelSettings, prefix="my.addon") + +# Now you can access the settings +my_setting_value = settings.my_setting +my_choice_value = settings.my_choice +``` + +## Use `FieldSet` to group fields + +For complex control panels, you can group fields together as in the following example. + +```python +from plone.supermodel import model + +class IMyControlPanelSettings(Interface): + + model.fieldset( + 'advanced', + label=u"Advanced Settings", + fields=['advanced_setting1', 'advanced_setting2'] + ) + + # Basic settings + my_setting = schema.TextLine( + title=u'My Setting', + description=u'Enter the value for my setting', + required=False + ) + + # Advanced settings + advanced_setting1 = schema.TextLine( + title=u'Advanced Setting 1', + required=False + ) + + advanced_setting2 = schema.Bool( + title=u'Advanced Setting 2', + default=False + ) +``` + + +## Common schema fields + +The following is a list of commonly used schema field types. + +`schema.TextLine` +: For single-line text + +`schema.Text` +: For multi-line text + +`schema.Bool` +: For boolean values + +`schema.Int` +: For integer values + +`schema.Float` +: For floating-point values + +`schema.Choice` +: For selection from a list of values + +`schema.Datetime` +: For date and time values + +`schema.List` +: For list of values + + +## Modify control panel fields + +When you modify the fields in your control panel settings interface, the changes won't be automatically reflected in existing sites. +You'll need to perform one or more of the following steps. + +- Run the appropriate upgrade steps. +- Reinstall your add-on. +- Test with a fresh site installation. + + +## Troubleshooting + +If your control panel doesn't appear or doesn't work as expected: + +- Verify that all ZCML is properly registered. +- Check for errors in the Plone error log. +- Ensure your GenericSetup profiles are correctly installed. +- Validate that the interface path in {file}`registry.xml` matches your actual Python path. + + +## Example file structure + +Below is a complete example file structure for a basic add-on with a control panel. + +``` +mypackage/ +├── __init__.py +├── configure.zcml +├── controlpanel/ +│ ├── __init__.py +│ ├── configure.zcml +│ └── settings.py +└── profiles/ + └── default/ + ├── controlpanel.xml + ├── metadata.xml + └── registry.xml +``` + +## REST API compatibility + +For better integration between Plone's backend and its frontend Volto, you can create REST API compatible control panels using the adapter pattern. +This approach is particularly useful when developing control panels that need to work seamlessly with Volto. + +Create a Python module {file}`mypackage/controlpanel.py` as follows. + +```python +from plone.restapi.controlpanels import RegistryConfigletPanel +from zope.component import adapter +from zope.interface import Interface +from zope.i18nmessageid import MessageFactory + +_ = MessageFactory("mypackage") + +@adapter(Interface, Interface) +class MyAddonControlPanel(RegistryConfigletPanel): + """Volto-compatible REST API control panel for my add-on settings.""" + + schema = IMyControlPanelSettings + schema_prefix = "my.addon" + configlet_id = "my-controlpanel" + configlet_category_id = "plone-general" + title = _("My Addon Settings") + group = "General" +``` + +Then register the adapter in your ZCML configuration file. + +```xml + + + + + + +``` + +The `group` property in the control panel class corresponds to the control panel category in Volto. + +`General` +: General settings (corresponds to `plone-general`) + +`Content` +: Content-related settings (corresponds to `plone-content`) + +`Users` +: Users and groups settings (corresponds to `plone-users`) + +`Security` +: Security settings (corresponds to `plone-security`) + +`Advanced` +: Advanced settings (corresponds to `plone-advanced`) + +With this approach, your control panel will be automatically available through the REST API at the endpoint `@controlpanels/my-controlpanel`, making it easy to integrate with Volto without additional configuration. + +You will still need to set up {file}`registry.xml` with default values as described earlier. + +```{seealso} +See the chapter {ref}`training:controlpanel-label` from the Mastering Plone 6 Training. +``` diff --git a/docs/developer-guide/index.md b/docs/developer-guide/index.md index dfc6d8c50..7fa3d26b8 100644 --- a/docs/developer-guide/index.md +++ b/docs/developer-guide/index.md @@ -21,6 +21,7 @@ You can help consolidate all of development documentation here, even if it is to ```{toctree} :maxdepth: 2 +create-control-panel create-a-distribution standardize-python-project-configuration ```