Customizing Search Panel Settings¶
This section describes Brightspot’s search panel and how you can customize its behavior.
Hint
Before writing your own code to customize the search panel, consider using one of the @ToolUi
annotations described in Content Modeling Annotations. These annotations are already optimized for many use cases and require only one line of code to implement.
Understanding the Search Panel Loop¶
When you open the search panel the following events occur:
- Initialize—Receives a Search and ToolPageContext objects. Using the
initializeSearch
callback, you can override this event to examine the state of the application. - Write search filters—Displays the standard filters in the search panel. Using the
writeSearchFilters
callback, you can add additional filters to the search panel. - Update search query—Builds the search command based on the search text and filters. Using the
updateSearchQuery
callback, you can modify the search command so that it includes criteria different from what appears in the search panel. - Execute search—Performs the search based on the latest result of
updateSearchQuery
.
The standard search panel includes a field for full-text search and filters for content type, publish dates, and status.

Referring to the previous illustration, Brightspot performs a search using the following MySQL pattern:
SELECT fieldnames FROM datatable WHERE (contentType="Article")
AND (status="Published")
AND ((headline LIKE '%fermentation%') OR (body LIKE '%fermentation%'))
ORDER BY lastUpdateDate
LIMIT 10;
Customizing the Search Panel Loop¶
This section shows how to override the search panel’s callbacks to modify its default appearance and behavior. In this example, we develop a customized search panel and search query for users who are assigned a role other than the global role.
Step 1: Declare Modified Search Class
All of the search panel’s callbacks receive a Search object. When customizing the search panel, as a best practice modify the Search
object and save state variables for use with search results.
In this step, we create a CustomSearch
class that is a modification of Search
. This class has a single field that is one of the following:
null
if the current user has no specific role (equivalent to being a global user).- Populated with the user’s record.
package search;
import com.psddev.cms.db.ToolUser;
import com.psddev.cms.tool.Search;
import com.psddev.dari.db.Modification;
public class CustomSearch extends Modification<Search> {
private ToolUser nonGlobalUser;
public ToolUser getNonGlobalUser() {
return nonGlobalUser;
}
public void setNonGlobalUser(ToolUser nonGlobalUser) {
this.nonGlobalUser = nonGlobalUser;
}
}
The previous snippet is a class declaration only; the instantiation occurs in Step 3.
Step 2: Declare Class for Custom Search Settings
Declare a class that extends Tool.
import com.psddev.cms.tool.Tool;
public class CustomSearchSettings extends Tool {
}
Steps 3–5 detail how to implement methods in this new class to customize search settings.
Step 3: Initialize Search Environment
The Tool class includes an empty method initializeSearch
. The purpose of this method is to examine the search environment and set flags and values required for customization. The following snippet provides an example for overriding this method.
1 2 3 4 5 6 7 8 9 10 | @Override
public void initializeSearch(Search search, ToolPageContext page) {
if (page.getUser().getRole() != null) {
search.as(CustomSearch.class).setNonGlobalUser(page.getUser());
} else {
search.as(CustomSearch.class).setNonGlobalUser(null);
}
}
|
In the previous snippet, line 4 tests the current user’s role. Depending on the results of the test, a CustomSearch
object is instantiated accordingly.
Step 4: Display Customized Search Filters
The Tool class includes an empty method writeSearchFilters
. The purpose of this method is to display custom filters above the Advanced Query field in the search panel. The following snippet provides an example for overriding this method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Override
public void writeSearchFilters(Search search, ToolPageContext page) throws IOException {
if (search.as(CustomSearch.class).getNonGlobalUser() != null) {
String userName = search.as(CustomSearch.class).getNonGlobalUser().getName();
String userId = search.as(CustomSearch.class).getNonGlobalUser().getId().toString();
page.writeHtml("Editor:");
page.writeStart("select",
"placeholder", "Editor");
page.writeStart("option",
"value", userId,
"selected", "selected");
page.writeHtml(userName);
page.writeEnd(); /* option */
page.writeEnd(); /* select */
}
}
|
In the previous snippet—
- Line 4 examines the value of
CustomSearch#nonGlobalUser
. If the value is not null, the user is not a global user and we display custom filters. - Line 5 retrieves the current user’s name, and line 6 retrieves the current user’s ID.
- Line 7 displays a label
Editor
. - Lines 8–15 create an HTML
<select>
element and populate it with a single<option>
for the current user.
Step 5: Customize the Query Object
The Tool class includes an empty method updateSearchQuery
. The purpose of this method is to modify the default query object that reflects settings in the search filters. The following snippet provides an example for overriding this method.
1 2 3 4 5 6 7 8 9 | @Override
public void updateSearchQuery(Search search, Query<?> query) {
if (search.as(CustomSearch.class).getNonGlobalUser() != null) {
String userId = search.as(CustomSearch.class).getNonGlobalUser().getId().toString();
query.and("cms.content.publishUser = ?", userId);
}
}
|
In the previous snippet—
- Line 4 examines the value of
CustomSearch#nonGlobalUser
. If the value is not null, the user is not a global user and we modify the query string. - Line 5 retrieves the current user’s ID.
- Line 6 appends the condition
AND LastPublishedUser = userId
to the search string.
When this method is complete, Brightspot performs the actual retrieval and displays the results.
The following snippet is a complete implementation of the methods described in steps 2–5.
package search;
import com.psddev.cms.tool.Search;
import com.psddev.cms.tool.Tool;
import com.psddev.cms.tool.ToolPageContext;
import com.psddev.dari.db.Query;
import java.io.IOException;
public class CustomSearchSettings extends Tool {
@Override
public void initializeSearch(Search search, ToolPageContext page) {
if (page.getUser().getRole() != null) {
search.as(CustomSearch.class).setNonGlobalUser(page.getUser());
} else {
search.as(CustomSearch.class).setNonGlobalUser(null);
}
}
@Override
public void writeSearchFilters(Search search, ToolPageContext page) throws IOException {
if (search.as(CustomSearch.class).getNonGlobalUser() != null) {
String userName = search.as(CustomSearch.class).getNonGlobalUser().getName();
String userId = search.as(CustomSearch.class).getNonGlobalUser().getId().toString();
page.writeHtml("Editor:");
page.writeStart("select",
"placeholder", "Editor");
page.writeStart("option",
"value", userId,
"selected", "selected");
page.writeHtml(userName);
page.writeEnd(); /* option */
page.writeEnd(); /* select */
}
}
@Override
public void updateSearchQuery(Search search, Query<?> query) {
if (search.as(CustomSearch.class).getNonGlobalUser() != null) {
String userId = search.as(CustomSearch.class).getNonGlobalUser().getId().toString();
query.and("cms.content.publishUser = ?", userId);
}
}
}
The following illustration shows the effect of this customization sample on the search panel.
