Skip to content
Open
Changes from 5 commits
Commits
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
106 changes: 72 additions & 34 deletions docs/developer-guide/create-control-panel.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,65 @@ This chapter describes how to create a control panel for your Plone add-on, whet

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.

[`plonecli`](https://pypi.org/project/plonecli/) automates all the manual steps to create a control panel.
This chapter will walk through all those steps as well.

## Creation approaches

There are two approaches to create a control panel for your Plone add-on:
## `plonecli`

- [`plonecli`](https://pypi.org/project/plonecli/)
- manual
You can install `plonecli` as any other Python package.
Since it's used for development, it's advantageous to install it in your user environment, thus making it available to all your Plone projects.

```shell
pip install plonecli --user
```

### `plonecli`

To add a control panel to your add-on, you can use [`plonecli`](https://pypi.org/project/plonecli/) as follows.
`plonecli` is primarily designed for scaffolding Plone add-ons. If you have an existing add-on created with `plonecli`, you can automatically create a control panel using the following command while in the add-on root directory:

```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.
It also goes through all the following steps to create a control panel.

### Using `plonecli` in a non-add-on project
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rohnsha0 Why would a developer create either a policy or custom theme package that is not an add-on? Is that the same as hacking on Plone core?

Also why would either a policy or custom theme package need a control panel? I can't think of such a scenario, but maybe you've done this?


If you're working on a Plone project that wasn't created as an add-on (for example, a custom policy package or a custom theme package), you have two options:

1. **Create the control panel manually**: Follow the steps in this chapter to create all necessary files by hand.

2. **Use `plonecli` partially**: You can use `plonecli` to generate the control panel code in a temporary add-on and then copy the relevant files to your project. For example:

```shell
# Create a temporary add-on
mkdir temp_addon
cd temp_addon
plonecli create addon temp.addon
cd temp.addon

# Generate the control panel
plonecli add controlpanel

# Examine and copy the generated files to your project
# You'll need to adapt paths and import statements
```

After generating the files, you'll need to adapt them to fit your project's structure and naming conventions.

### Manual

To manually create a control panel, go through the following steps.
## Steps to create a control panel

Whether performed automatically with `plonecli` or manually, the following steps are required to create a control panel.

- 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.
- Register the control panel in XML.


#### Define the settings interface and form
### 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.

Expand All @@ -59,34 +88,34 @@ 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',
title="My Setting",
description="Enter the value for my setting",
required=False,
default=u''
default=""
)

my_choice = schema.Choice(
title=u'My Choice',
description=u'Select a value for my choice',
title="My Choice",
description="Select a value for my choice",
required=False,
default=u'value3',
values=['value1', 'value2', 'value3']
default="value3",
values=["value1", "value2", "value3"]
)

class MyControlPanelForm(RegistryEditForm):
"""Control panel form."""

schema = IMyControlPanelSettings
schema_prefix = "my.addon"
label = u"My Addon Settings"
label = "My add-on 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
### 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.

Expand All @@ -107,7 +136,7 @@ Create a file {file}`mypackage/controlpanel/configure.zcml` with the following c
</configure>
```

Make sure to include the above file in your package's main {file}`mypackage/configure.zcml` as shown by the highlighted line below.
Include the above file in your package's main {file}`mypackage/configure.zcml`, as shown by the highlighted line below.

{emphasize-lines="9"}
```xml
Expand All @@ -124,7 +153,8 @@ Make sure to include the above file in your package's main {file}`mypackage/conf
</configure>
```

#### Add the control panel entry

### 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.

Expand All @@ -133,7 +163,7 @@ Create a {file}`mypackage/profiles/default/controlpanel.xml` in your package's G
<?xml version="1.0"?>
<object name="portal_controlpanel">
<configlet
title="My Addon Settings"
title="My add-on settings"
action_id="my-controlpanel"
appId="my.addon"
category="plone-general"
Expand Down Expand Up @@ -165,7 +195,7 @@ These values correspond to the groups in {guilabel}`Site Setup`.
: {guilabel}`Advanced`


#### Set default values in the registry
### Set default values in the registry

Define default values for your settings in {file}`mypackage/profiles/default/registry.xml`.

Expand All @@ -182,9 +212,9 @@ Define default values for your settings in {file}`mypackage/profiles/default/reg
```


#### Register a control panel
### Register the control panel

To manually register a view as a control panel, add the following registration to your {file}`/profiles/default/controlpanel.xml`.
To register the view as a control panel, add the following registration to your {file}`/profiles/default/controlpanel.xml`.

```xml
<?xml version="1.0"?>
Expand All @@ -207,7 +237,12 @@ To manually register a view as a control panel, add the following registration t
</object>
```

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:

## Load your control panel

After performing the above steps, 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}

Expand Down Expand Up @@ -249,6 +284,7 @@ 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.
Expand All @@ -265,6 +301,7 @@ 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.
Expand All @@ -275,26 +312,26 @@ from plone.supermodel import model
class IMyControlPanelSettings(Interface):

model.fieldset(
'advanced',
label=u"Advanced Settings",
fields=['advanced_setting1', 'advanced_setting2']
"advanced",
label="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',
title="My Setting",
description="Enter the value for my setting",
required=False
)

# Advanced settings
advanced_setting1 = schema.TextLine(
title=u'Advanced Setting 1',
title="Advanced Setting 1",
required=False
)

advanced_setting2 = schema.Bool(
title=u'Advanced Setting 2',
title="Advanced Setting 2",
default=False
)
```
Expand Down Expand Up @@ -368,6 +405,7 @@ mypackage/
└── 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.
Expand All @@ -391,7 +429,7 @@ class MyAddonControlPanel(RegistryConfigletPanel):
schema_prefix = "my.addon"
configlet_id = "my-controlpanel"
configlet_category_id = "plone-general"
title = _("My Addon Settings")
title = _("My add-on settings")
group = "General"
```

Expand Down