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

../../../_images/standard-filter.png

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.

../../../_images/customized-search-panel.svg