Skip to content
1 change: 1 addition & 0 deletions news/1981.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The `@controlpanel` service now includes `searchable_text` for each control panel. @Manik-Khajuria-5
19 changes: 19 additions & 0 deletions src/plone/restapi/controlpanels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from zope.interface import implementer
from zope.publisher.interfaces import NotFound

import zope.schema


@implementer(IControlpanel)
class RegistryConfigletPanel:
Expand Down Expand Up @@ -38,6 +40,23 @@ def __init__(self, context, request):
self.title = self.configlet["title"]
self.group = self._get_group_title()

def get_searchable_text(self):

text_parts = []

if self.title:
text_parts.append(self.title)

if self.group:
text_parts.append(self.group)

if self.schema is not None:
for name, field in zope.schema.getFields(self.schema).items():
if field.title:
text_parts.append(field.title)

return [text for text in text_parts if text]

def add(self, names):
raise NotFound(self.context, names, self.request)

Expand Down
7 changes: 7 additions & 0 deletions src/plone/restapi/controlpanels/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ def update(names):
def delete(names):
"""Remove controlpanel children by names"""

def get_searchable_text():
"""Return searchable text for this control panel.

Schema-based control panels return text from field titles and descriptions.
Other control panels can return custom text.
"""


class IDexterityTypesControlpanel(IControlpanel):
"""Dexterity Types Control panel"""
Expand Down
15 changes: 15 additions & 0 deletions src/plone/restapi/controlpanels/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ class ContentRulesControlpanel(RegistryConfigletPanel):
def publishTraverse(self, request, name):
return self.context.restrictedTraverse("++rule++" + name)

def get_searchable_text(self):
text_parts = super().get_searchable_text()

cpanel = queryMultiAdapter(
(self.context, self.request), name="rules-controlpanel"
)
if cpanel:
registered_rules = cpanel.registeredRules()
for rule in registered_rules:
if isinstance(rule, dict):
if rule.get("title"):
text_parts.append(rule["title"])

return text_parts

def add(self, names):
data = json_body(self.request)
rules = queryMultiAdapter((self.context, self.request), name="+rule")
Expand Down
13 changes: 13 additions & 0 deletions src/plone/restapi/controlpanels/types.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from plone.dexterity.interfaces import IDexterityFTI
from plone.i18n.normalizer import idnormalizer
from plone.restapi.controlpanels import RegistryConfigletPanel
from plone.restapi.controlpanels.interfaces import IDexterityTypesControlpanel
Expand All @@ -7,6 +8,7 @@
from plone.restapi.interfaces import ISerializeToJson
from zExceptions import BadRequest
from zope.component import adapter
from zope.component import getAllUtilitiesRegisteredFor
from zope.component import queryMultiAdapter
from zope.interface import alsoProvides
from zope.interface import implementer
Expand All @@ -22,6 +24,17 @@ class DexterityTypesControlpanel(RegistryConfigletPanel):
configlet_id = "dexterity-types"
configlet_category_id = "plone-content"

def get_searchable_text(self):

text_parts = super().get_searchable_text()

ftis = getAllUtilitiesRegisteredFor(IDexterityFTI)
for fti in ftis:
if fti.Title():
text_parts.append(fti.Title())

return text_parts

def add(self, names):
data = json_body(self.request)

Expand Down
13 changes: 12 additions & 1 deletion src/plone/restapi/serializer/controlpanels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, controlpanel):
self.controlpanel = controlpanel

def __call__(self):
return {
result = {
"@id": "{}/{}/{}".format(
self.controlpanel.context.absolute_url(),
SERVICE_ID,
Expand All @@ -36,6 +36,17 @@ def __call__(self):
"group": self.controlpanel.group,
}

if hasattr(self.controlpanel, "get_searchable_text"):
result["searchable_text"] = self.controlpanel.get_searchable_text()
else:
if self.controlpanel.title:
result["searchable_text"] = [
self.controlpanel.title,
self.controlpanel.description,
]

return result


def get_jsonschema_for_controlpanel(controlpanel, context, request, form=None):
"""Build a complete JSON schema for the given controlpanel."""
Expand Down
175 changes: 175 additions & 0 deletions src/plone/restapi/tests/http-examples/controlpanels_get.resp
Original file line number Diff line number Diff line change
Expand Up @@ -5,76 +5,251 @@ Content-Type: application/json
{
"@id": "http://localhost:55001/plone/@controlpanels/date-and-time",
"group": "General",
"searchable_text": [
"Date and Time",
"General",
"Portal default timezone",
"Available timezones",
"First weekday"
],
"title": "Date and Time"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/language",
"group": "General",
"searchable_text": [
"Language",
"General",
"Site language",
"Available languages",
"Show country-specific language variants",
"Show language flags",
"Always show language selector",
"Use the language of the content item",
"Use language codes in URL path for manual override",
"Use cookie for manual override",
"Authenticated users only",
"Set the language cookie always",
"Use subdomain",
"Use top-level domain",
"Use browser language request negotiation"
],
"title": "Language"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/mail",
"group": "General",
"searchable_text": [
"Mail",
"General",
"SMTP server",
"SMTP port",
"ESMTP username",
"ESMTP password",
"Site 'From' name",
"Site 'From' address",
"E-mail characterset"
],
"title": "Mail"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/navigation",
"group": "General",
"searchable_text": [
"Navigation",
"General",
"Navigation depth",
"Automatically generate tabs",
"Generate tabs for items other than folders.",
"Sort tabs on",
"Reversed sort order for tabs.",
"Displayed content types",
"Filter on workflow state",
"Show items normally excluded from navigation if viewing their children.",
"Root",
"Sitemap depth",
"Hide children of these types"
],
"title": "Navigation"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/search",
"group": "General",
"searchable_text": [
"Search",
"General",
"Enable LiveSearch",
"Select content types which should be excluded from search results",
"Crop the item description in search result listings after a number of characters.",
"Sort on",
"Show images in results",
"Image scale for results"
],
"title": "Search"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/site",
"group": "General",
"searchable_text": [
"Site",
"General",
"Site title",
"Site Logo",
"MIME type of the site favicon",
"Site Favicon",
"Expose Dublin Core metadata",
"Expose sitemap.xml.gz",
"JavaScript integrations included in head section",
"JavaScript integrations included after the footer",
"Display publication date",
"Icon visibility",
"Thumb visibility",
"No Thumbs in portlets",
"No thumbs in list views",
"No thumbs in summary views",
"No thumbs in table views",
"Thumb scale for portlets",
"Thumb scale for listings",
"Thumb scale for tables",
"Thumb scale for summary view",
"Toolbar position",
"Relative URL for the toolbar logo",
"robots.txt",
"Default page IDs",
"Roles that can add keywords"
],
"title": "Site"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/socialmedia",
"group": "General",
"searchable_text": [
"Social Media",
"General",
"Share social data",
"Twitter username",
"Facebook App ID",
"Facebook username"
],
"title": "Social Media"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/content-rules",
"group": "Content",
"searchable_text": [
"Content Rules",
"Content"
],
"title": "Content Rules"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/dexterity-types",
"group": "Content",
"searchable_text": [
"Content Types",
"Content",
"Plone Site",
"Collection",
"Page",
"Folder",
"Link",
"File",
"Image",
"News Item",
"Event",
"DX Test Document"
],
"title": "Content Types"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/discussion",
"group": "Content",
"searchable_text": [
"Discussion",
"Content",
"Globally enable comments",
"Enable anonymous comments",
"Enable anonymous email field",
"Enable comment moderation",
"Enable editing of comments",
"Enable deleting own comments",
"Comment text transform",
"Captcha",
"Show commenter image",
"Enable moderator email notification",
"Moderator Email Address",
"Enable user email notification"
],
"title": "Discussion"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/editing",
"group": "Content",
"searchable_text": [
"Editing",
"Content",
"Available editors",
"Default editor",
"Enable External Editor feature",
"Enable link integrity checks",
"Enable locking for through-the-web edits",
"Limit tags/keywords to the current navigation root"
],
"title": "Editing"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/imaging",
"group": "Content",
"searchable_text": [
"Image Handling",
"Content",
"Allowed image sizes",
"Scaled image quality",
"High pixel density mode",
"Image quality at 2x",
"Image quality at 3x",
"Picture variants",
"Enable image captioning"
],
"title": "Image Handling"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/markup",
"group": "Content",
"searchable_text": [
"Markup",
"Content",
"Default format",
"Alternative formats",
"Enabled markdown extensions"
],
"title": "Markup"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/usergroup",
"group": "Users",
"searchable_text": [
"User and Group Settings",
"Users",
"Many groups?",
"Many users?"
],
"title": "User and Group Settings"
},
{
"@id": "http://localhost:55001/plone/@controlpanels/security",
"group": "Security",
"searchable_text": [
"Security",
"Security",
"Enable self-registration",
"Let users select their own passwords",
"Enable User Folders",
"Allow anyone to view 'about' information",
"Use email address as login name",
"Use UUID user ids",
"Login user after password reset"
],
"title": "Security"
}
]