In table, preview and report widgets, you can optionally add a toolbar that has input and selection fields. 


As an administrator, you can add the toolbar to widget configurations. Users can create their own widget configurations and assign a pre-configured toolbar to a preview or report widget.

Users want to filter the results of asset lists or asset structures presented in tables, reports or product previews. They can use a free text field, a list of values or toggles. The controls are placed in a header in the respective widget. The toolbar transformation provides this functionality for a specific table or report. 

The toolbar itself is created outside the respective widget in a transformation asset. The fields filter the content displayed in these widgets, for example by type, user or language. This article describes the concept of the toolbar transformation and gives some examples which can be used out of the box or adapted according to your needs.

Prerequisites

You should be familiar with XSL transformations and metadata in censhare Web.

Introduction

Table and report widgets display asset structures with configurable asset properties in a table view. Depending on the configuration of the widget tables can contain a huge amount of data. These can be, for example, long lists of assets or a great number of columns (i.e. the number of displayed asset properties). A toolbar gives users the option to filter the widget content. For example, in a table that shows all users, the data can be filtered by domain or role.

In the preview widget, any asset details of the current asset or related assets can be displayed. For example, in product assets in censhare PIM, product details (title, text blocks and images) are shown for a specific context. In this asset, a toolbar gives users the option to view the widget content for a specific context, for example, a language or channel.

To configure a filter or context selector, you first define a toolbar transformation asset. This asset can then be selected in the widget configuration of the respective table, preview or report widget. The toolbar only works in combination with XSLT queries, but has no effect with XML-based query assets.

Creating a transformation asset

To add a new toolbar transformation, proceed as follows:

  1. Create a “Module / Transformation” asset.

  2. Enter a name and a resource key.

  3. Select the fields “Enabled” and “In cached tables”.

  4. In the field “Usage”, select “Toolbar transformation”.

  5. Click OK to save.

  6. Upload an XSL file to the asset. The file appears then as "Master file" in the respective widget. The XSL snippet defines the parameters and the UI elements to be displayed in the header bar of the table widget. See the following section for the basic concept and the “Example” section for an example configuration.

Basic concept

The following snippet shows the basic structure of the XSL file. Use this code as base to build your own toolbar transformations. 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:cs="http://www.censhare.com/xml/3.0.0/xpath-functions"
                xmlns:corpus="http://www.censhare.com/xml/3.0.0/corpus"
                xmlns:csc="http://www.censhare.com/censhare-custom"
                exclude-result-prefixes="cs corpus csc">

<!-- import -->
    <xsl:import href="censhare:///service/assets/asset;
          censhare:resource-key=censhare:transformation.include/storage/master/file"/>

<!-- output -->
    <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes"/>

<!-- root match -->
  <xsl:template match="/">
    <result>

<!-- config contains option parameters -->
    <config></config>

 <!-- content expects html snippet that is rendered in the widget -->
      <content>
        <div class="cs-toolbar" ng-init="params = {{ filter: '' }}">
          <div class="cs-toolbar-slot-1">
            <div class="cs-toolbar-item">
              <cs-input class="cs-is-small" 
                                  placeholder="Filter" 
                                  ng-model="params.filter" 
                                  ng-change="onChange({{ queryParam: params }})">
               </cs-input>
            </div>
          </div>
        </div>
      </content>
    </result>
  </xsl:template>

</xsl:stylesheet>
CODE

The toolbar transformation generates an HTML snippet with the interactive elements for filtering. Therefore, do not change the <xsl:output> element.

The <content> section creates the HTML output. When a user selects a filter or output option from the toolbar controls, the transformation creates the respective HTML snippet, which is displayed in the widget.

Place the filter parameters in the <config> element. The toolbar filters the table by these parameters, for example language, features or feature groups.

You can place multiple filters in one toolbar by using the CSS consecutively numbered classes “cs-toolbar-slot-1”, “cs-toolbar-slot-2” and so forth. censhare supports all types of filter options in the toolbar, like Input field (text field), selection or check boxes, toggles or buttons.

Examples

The following examples show some specific use cases of the toolbar transformation. Be aware that each example requires an accordingly configured widget (report, table or preview), where the data to be filtered are queried and displayed. Otherwise, the toolbar does not provide the desired functionality, although the controls are visible to the user.

Filter product table by type and string

The default product table shows top-level product categories, sub-categories, products, product families, product items and product item groups. This toolbar provides two filter options. First, it creates a drop-down list where user selects one of the asset types, for example, "Product categories". Second, it provides a search field where users can enter a search string, for example, "Hair dryer".

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:cs="http://www.censhare.com/xml/3.0.0/xpath-functions"
    xmlns:corpus="http://www.censhare.com/xml/3.0.0/corpus"
    xmlns:csc="http://www.censhare.com/censhare-custom"
    exclude-result-prefixes="cs corpus csc">
    
 <!-- import -->
    <xsl:import href="censhare:///service/assets/asset;
                            censhare:resource-key=censhare:transformation.include/storage/master/file"/>
    
<!-- output -->
    <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes"/>
    
<!-- root match -->
    <xsl:template match="/">
        <xsl:variable name="asset" select="asset[1]"/>
        <result>
<!-- config contains default values -->
            <config>
                <defaultValues>{"assetName": "", "assetType": "all"}</defaultValues>
            </config>
<!-- content expects html snippet that is rendered in the widget -->
            <content>
                <div class="cs-toolbar">
                    <div class="cs-toolbar-slot-1">
<!-- asset type -->
                        <xsl:variable name="assetTypes" 
                                                   as="element(asset_typedef)*">
                            <xsl:for-each select="('product.', 
                                                                          'product.category.', 
                                                                          'product.item.', 
                                                                          'product.item.group.', 
                                                                          'product.family.')">
                                <xsl:sequence select="cs:master-data('asset_typedef')[@asset_type=.]"/>
                            </xsl:for-each>
                        </xsl:variable>
                        <xsl:variable name="assetTypeString">
                            <xsl:for-each select="$assetTypes">
                                <xsl:sort select="@name"/>
                                <xsl:value-of select="concat(', {"name": "', @name, '", "value": "', @asset_type, '"}')"/>
                            </xsl:for-each>
                        </xsl:variable>
                        <div class="cs-toolbar-item">
                            <cs-select class="cs-is-small cs-is-alt" label="${type}" 
                                                 width="auto" 
                                                 ng-model="toolbarData.assetType" 
                                                 unerasable="unerasable"
                                                ng-options="item.value as item.name for item in [{{name: "${all}", value: "all"}}{$assetTypeString}]"
                                                ng-change="onChange({{ assetType: toolbarData.assetType }})">
                            </cs-select>
                        </div>
                    </div>
                    <div class="cs-toolbar-slot-2">
<!-- asset name -->
                        <div class="cs-toolbar-item">
                            <cs-input class="cs-is-small" 
                                                placeholder="${filterResults}" 
                                                ng-model="toolbarData.assetName" 
                                                ng-change="onChange({{ assetName: toolbarData.assetName }})"></cs-input>
                        </div>
                    </div>
                </div>
            </content>
        </result>
    </xsl:template>
    
</xsl:stylesheet>
CODE

Filter users by role

This transformation provides a drop-down list with available roles. The toolbar works with a report widget showing a matrix of users, roles and domains. For each user, a table row is created. Each role is represented by a column. The table cells display the domains, in which a certain user is working in a certain role. If a role is not assigned to a user, the respective cell is empty.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:cs="http://www.censhare.com/xml/3.0.0/xpath-functions"
  xmlns:corpus="http://www.censhare.com/xml/3.0.0/corpus"
  xmlns:csc="http://www.censhare.com/censhare-custom"
  exclude-result-prefixes="cs corpus csc">

  <!-- import -->
  <xsl:import href="censhare:///service/assets/asset;
              censhare:resource-key=censhare:transformation.include/storage/master/file"/>
  
  <!-- output -->
  <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes"/>

  <!-- root match -->
  <xsl:template match="/">
    <result>

<!-- config contains option parameters -->
      <config>
        <defaultValues>
            <xsl:value-of select="'{"role": "all"}'"/>.        
        </defaultValues>
      </config>

<!-- content expects html snippet that is rendered in the widget -->
      <content>
        <div class="cs-toolbar csReportWidget__toolbar">
          <div class="cs-toolbar-slot-1">

<!-- role -->
            <xsl:variable name="roles" select="cs:master-data('role')"/>
            <xsl:variable name="roleString">
              <xsl:for-each select="$roles">
                <xsl:sort select="@name"/>
                <xsl:value-of select="concat(', {"name": "', 
                           @name, '", "value": "', @role, '"}')"/>
              </xsl:for-each>
            </xsl:variable>
            <div class="cs-toolbar-item cs-m-r-s">
              <cs-select class="cs-is-small cs-is-alt" 
                                    label="${role}" 
                                    width="auto" 
                                    ng-model="toolbarData.role" 
                                    unerasable="unerasable"
                                    ng-options="item.value as item.name for item in 
                            [{{"name": "${all}", "value": "all"}}
                            {$roleString}]" ng-change="onChange({{ role: toolbarData.role }})">
              </cs-select>
            </div>
          </div>
        </div>
      </content>
    </result>
  </xsl:template>

</xsl:stylesheet>
CODE

Filter content by language

This transformation provides a drop-down list with available languages. By selecting a language, the preview shows texts in the selected language. The selection also works for images with a language property. The toolbar works with a preview widget showing product details such as title, main text, main image available in different languages.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:cs="http://www.censhare.com/xml/3.0.0/xpath-functions"
  xmlns:corpus="http://www.censhare.com/xml/3.0.0/corpus"
  xmlns:csc="http://www.censhare.com/censhare-custom"
  exclude-result-prefixes="cs corpus csc">

  <!-- import -->
  <xsl:import href="censhare:///service/assets/asset;
                  censhare:resource-key=censhare:transformation.include/storage/master/file"/>
  
  <!-- output -->
  <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes"/>

  <!-- root match -->
  <xsl:template match="/">
    <xsl:variable name="asset" select="asset[1]"/>
    <xsl:variable name="language" 
                               select="if ($asset/@language) 
                then $asset/@language else csc:getLoggedInPartyPreviewLanguagePreferenceValue()"/>
    <xsl:variable name="languageElements" 
                               select="cs:master-data('language_def')"/>
    <xsl:variable name="languageElementsSorted">
      <xsl:for-each select="$languageElements">
        <xsl:sort select="@name"/>
        <xsl:sequence select="."/>
      </xsl:for-each>
    </xsl:variable>
    <result>

<!-- config contains option parameters -->
      <config>
        <defaultValues><xsl:value-of select="concat('{"language": "', $language, '"}')"/></defaultValues>
      </config>

<!-- content expects html snippet that is rendered in the widget -->
      <content>
        <div class="cs-toolbar csReportWidget__toolbar">
          <div class="cs-toolbar-slot-1">

<!-- language -->
            <div class="cs-toolbar-item">
              <label class="cs-label cs-is-small">${language}</label>
              <cs-select class="cs-is-small cs-is-alt" 
                                    width="auto" 
                                    ng-model="toolbarData.language" 
                                    unerasable="unerasable"
                                    ng-options="item.value as item.name for item in 
                        [{string-join(for $x in $languageElementsSorted/language_def return 
                           concat('{"name": "', $x/@name, 
                           '", "value": "', $x/@id, '"}'), ', ')}]"
                                    ng-change="onChange({{ language: toolbarData.language }})">
              </cs-select>
            </div>
          </div>
          
        </div>
      </content>
    </result>
  </xsl:template>

</xsl:stylesheet>
CODE
Next steps
  • Add the toolbar configuration to a table widget configuration.

  • Add the toolbar to a preview widget configuration.

  • Add the toolbar to a report widget configuration.