Project

General

Profile

Browse Widget Enhancements

Quick-Out: How to Enable All Enhanced Browse Functionality

Put this under /server/default/ or /server/<server_name>/:

<node class="container" name="enhancedBrowse">
   <node class="container" name="desktop">
      <node class="boolean" name="enableAll">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="string" name="adminAccounts">
         <node-attribute name="value" value="everybody"/>
      </node>
   </node>
   <node class="container" name="embedded">
      <node class="boolean" name="enableAll">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="string" name="adminAccounts">
         <node-attribute name="value" value="everybody"/>
      </node>
   </node>
</node>  

OR here is a version with individual parameters:

<node class="container" name="enhancedBrowse">
   <node class="container" name="desktop">
      <node class="boolean" name="enableAll">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="applyLayout">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="string" name="changeLayout">
         <node-attribute name="value" value="ENABLED_ALL_USERS"/>
      </node>
      <node class="boolean" name="exporting">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="hyperlinking">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="enhancedSorting">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="enhancedFiltering">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="string" name="adminAccounts">
         <node-attribute name="value" value="everybody"/>
      </node>
   </node>
   <node class="container" name="embedded">
      <node class="boolean" name="enableAll">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="applyLayout">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="string" name="changeLayout">
         <node-attribute name="value" value="ENABLED_ALL_USERS"/>
      </node>
      <node class="boolean" name="exporting">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="hyperlinking">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="enhancedSorting">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="boolean" name="enhancedFiltering">
         <node-attribute name="value" value="TRUE"/>
      </node>
      <node class="string" name="adminAccounts">
         <node-attribute name="value" value="everybody"/>
      </node>
   </node>
</node>  

FWD provides multiple enhancements for the browse widget:

Changing Browse Layout

One can visually adjust look and layout of a specific browse or all browses the application. The following elements can be adjusted:
  • column visibility;
  • column order;
  • column width;
  • row height;
  • labels area height;
  • cell and label fonts for browse or specific browse column (changing browse cells font updates browse layout basing on the size of the new font);
  • text color, background color, label text color and label background color for browse or specific browse column;
  • visibility and color of row separators.
  • rows can be made "striped" by setting alternating row background color for browse or specific browse column.

Browse layout can be adjusted through the popup menu which is called using mouse right click. In order to enable it, set this under /server/{default|<server_name>}/enhancedBrowse/{desktop|embedded}/:

<node class="boolean" name="applyLayout">
   <node-attribute name="value" value="TRUE"/>
</node>
<node class="string" name="changeLayout">
   <node-attribute name="value" value="ENABLED_ALL_USERS"/>
</node>

or

<node class="boolean" name="applyLayout">
   <node-attribute name="value" value="TRUE"/>
</node>
<node class="string" name="changeLayout">
   <node-attribute name="value" value="ENABLED_ADMIN_USERS"/>
</node>

depending on which group of users should be able to adjust browse layout.

applyLayout parameter controls if enhanced browse layout saved in the directory is applied to the designated browses and if browse layout can be visually adjusted. changeLayout separately controls if browse layout can be visually adjusted by specific group of users, it is taken in consideration only if applyLayout is true. It can take the following string values: ENABLED_ADMIN_USERS, ENABLED_ALL_USERS, DISABLED. Default value is ENABLED_ALL_USERS.

Security Model

Enhanced configurations have the following lookup levels:

  • Global Default (configuration affects all users and all browses);
  • Browse-Specific Default (configuration affects a specific browse but for all users);
  • User Default (configuration affects all browses for a specific user);
  • Browse-Specific User Settings (configuration affects a specific browse for a specific user).

The levels are listed from the less prioritized to the most prioritized. When we search for an enhanced configuration to apply, we search them in the order of priority, the first found configuration is applied.

Only users with admin rights can save configurations at Global Default and Browse-Specific Default levels. The comma separated list of admin users and groups can be set using adminAccounts parameter under /server/{default|<server_name>}/enhancedBrowse/{desktop|embedded}/:

<node class="string" name="adminAccounts">
   <node-attribute name="value" value="bogus,admins"/>
</node>

Setting Directory Access Rights for Enabling Saving Options

TODO: replace this section

One has the options to change browse settings
  • for the current or default server;
  • for all users or specific user or group;
  • for all browses in the application or the current browse.

The list of available saving options is determined by the access rights which user has for the specific directory sections. This section describes how to set the access rights.

In order to save visual changes in enhanced mode, add the following to the /security/acl/directory/:

<node class="container" name="ACL_ID">
   <node class="strings" name="subjects">
      <node-attribute name="values" value="USERNAME"/>
   </node>
   <node class="directoryRights" name="rights">
      <node-attribute name="permissions" value="'00111111'B"/>
   </node>
      <node class="resource" name="resource-instance">
         <node-attribute name="reference" value="DIRECTORY_PATH_OR_SPEC_HERE"/>
         <node-attribute name="reftype" value="TRUE_IF_HARD_CODED_PATH_FALSE_FOR_SPEC"/>
      </node>
   </node>
</node>

This is an ACL for editing the directory. Change the values as follows:
  • ACL_ID must be a text value that makes this node unique compared to all others in this security/acl/directory/ container. The id should be a 6-digit numeric value such as 000050. The entire section should be placed in the proper numeric order under the security/acl/directory/ container. Do NOT duplicate any ACL_ID values in that container.
  • USERNAME is the FWD account or group name that is being granted these permissions. An operating system userid cannot be used here because this is the configuration for FWD security not operating system security. The special value all_others can be used to assign these permissions to all accounts that don't already have a preceding ACL for their FWD account or for one of the FWD groups to which their FWD account belongs.
  • DIRECTORY_PATH_OR_SPEC_HERE specifies the location in the directory that can be edited. The lookup processing checks in multiple directory locations. Defaults can set and user or group specific values can override the defaults. For more details on the lookup processing, see Utils.findDirectoryNodePath().
    • It can be a hard coded path (e.g. /server/{default|<SERVER_ID>}/runtime/{default|<FWD_ACCOUNT_OR_GROUP_ID>}/enhanced-browse-config/. The use of default allows setting/editing te default value for all servers. The use of a specific SERVER_ID (e.g. standard) will limit the edits to that specific FWD server's values. The default or FWD account or group is used to qualify the specific location below the .../runtime/ which is being referenced. /server/default/runtime/default/enhanced-browse-config would be the location that sets the location for all servers and all users. This will be honored unless there is saved configuration values found at the account or group level.
    • It can be a wildcard specification. To enable all directory editing access you can use .*, this is dangerous, so only use it for testing! You could also specify /server/default/runtime/.*/enhanced-browse-config to allow editing of the settings for all users/groups.
  • TRUE_IF_HARD_CODED_PATH_FALSE_FOR_SPEC is used to define the reftype. The value will depend on the value for reference. If reference was a hard coded path, then use TRUE. If reference was a wildcard specification, then use FALSE.

Use the right mouse press on the browse to get the context menu. Use "Change Layout" to edit the look and feel. If the ACLs are correct, then any values modified during Change Layout can be saved using the context menu. If you see no saving options, then the ACLs have not provided write access to the "enhanced-browse-configs" node under the specific branch for the current user.

Structure of the Directory Nodes Responsible for Storing Enhanced Browse Configurations

Enhanced browse configuration nodes are stored under the following paths: /server/{default|<server_name>}/enhancedBrowse/{desktop|embedded}/configurations/. Configurations names are arbitrary numbers. Sample configuration:

<node class="container" name="configurations">
   <node class="enhancedBrowseConfig" name="1">
      <node-attribute name="proc_name" value="test.p"/>
      <node-attribute name="browse_name" value="brws"/>
      <node-attribute name="fgcolor" value="#ff8040"/>
      <node-attribute name="bgcolor" value="7"/>
      <node-attribute name="alt_bgcolor" value="#f9f9b1"/>
      <node-attribute name="label_fgcolor" value="#004080"/>
      <node-attribute name="label_bgcolor" value="#d2a6ff"/>
      <node-attribute name="font" value="dejavu sans,11,false,false,false"/>
      <node-attribute name="label_font" value="dejavu sans,11,true,false,false"/>
      <node-attribute name="row_separators" value="TRUE"/>
      <node-attribute name="column_separators" value="TRUE"/>
      <node-attribute name="separators_color" value="#800080"/>
      <node-attribute name="row_height_px" value="17"/>
      <node-attribute name="labels_height_px" value="17"/>
      <node class="container" name="columns">
         <node class="enhancedColumnConfig" name="1">
            <node-attribute name="column_key" value="tt.f1"/>
            <node-attribute name="ordinal" value="0"/>
            <node-attribute name="visible" value="TRUE"/>
            <node-attribute name="width_px" value="70"/>
            <node-attribute name="fgcolor" value="#008000"/>
            <node-attribute name="bgcolor" value="#ffffb9"/>
            <node-attribute name="alt_bgcolor" value="#f9f9b1"/>
            <node-attribute name="label_fgcolor" value="#800000"/>
            <node-attribute name="label_bgcolor" value="#b7ffb7"/>
            <node-attribute name="font" value="dejavu sans,11,false,true,false"/>
            <node-attribute name="label_font" value="dejavu sans,11,true,true,false"/>
         </node>
         <node class="enhancedColumnConfig" name="2">
            <node-attribute name="column_key" value="tt.f2"/>
            <node-attribute name="ordinal" value="1"/>
            <node-attribute name="visible" value="TRUE"/>
            <node-attribute name="width_px" value="70"/>
         </node>
      </node>
   </node>
   ... 
</node>
Here is the list of attributes available for an enhancedBrowseConfig node. Browses are uniquely identified by the name of the parent procedure and the browse name.
  • proc_name - 4GL name of the parent procedure in which the browse was created. Not set if the configuration is applied to all browses.
  • browse_name - 4GL name of the browse. Not set if the configuration is applied to all browses.
  • fgcolor - browse foreground color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • bgcolor - browse background color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • alt_bgcolor - alternating browse background color for striped rows, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • label_fgcolor - labels foreground color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • label_bgcolor - labels background color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • font - browse font in format <font name>,<font size>,<is bold>,<is italic>,<is underlined>.
  • label_font - labels font in format <font name>,<font size>,<is bold>,<is italic>,<is underlined>.
  • row_separators - TRUE if row separators are enabled.
  • column_separators - TRUE if column separators are enabled.
  • separators_color - separators color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • row_height_px - row height, in pixels.
  • labels_height_px - labels area height, in pixels.
Here is the list of attributes available for an enhancedColumnConfig node. Columns are uniquely identified in a browse using "column keys". The name of an enhancedColumnConfig node is an arbitrary number. The "columns" section doesn't present if the configuration is for all browses.
  • column_key - column key uniquely identifying the column among the other columns in the browse. In most cases it matches the name of the underlying buffer field, but for computed and calculated columns, it is an expression describing column parameters.
  • ordinal - 0-based column ordinal, which defines position of the column among all columns in the browse.
  • visible - TRUE if the column is visible.
  • width_px - column width, in pixels.
  • fgcolor - column foreground color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • bgcolor - column background color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • alt_bgcolor - alternating column background color for striped rows, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • label_fgcolor - column label foreground color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • label_bgcolor - column label background color, it can be an RGB color in format #RRGGBB or an index in the color table of the parent window in numeric format.
  • font - column font in format <font name>,<font size>,<is bold>,<is italic>,<is underlined>.
  • label_font - column label font in format <font name>,<font size>,<is bold>,<is italic>,<is underlined>.

Browse Exporting

Introduction

One can make report out of a browse result set in PDF, CSV, XLS and XLSX formats. That can be done using the browse popup menu. In-browse formatting of the values is preserved. This means that any user-defined sorting, filtering or other customization will be honored in the exported report. Values generated in a ROW-DISPLAY trigger are preserved too.

The following is a screenshot of the Hotel GUI sample application running in the embedded mode web client. The right mouse button is pressed to display the popup menu:

Using the Export sub-menu looks like this:

Clicking on the Export to PDF will generate the PDF and load it down into a new tab in the browser:

From there the user can view, print or save the PDF locally.

The CSV, XLS and XLSX exports work similarly. The only issue with those formats is that browser's helper application for the associated MIME types must be configured for those to be automatically loaded. Otherwise the browser will display a prompt to save the file.

Here are the MIME types used:

Format MIME Type
CSV "text/csv"
PDF "application/pdf"
XLS "application/vnd.ms-excel"
XLSX "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

In a browser that has no action for the given XLS MIME type, the file can be saved/opened locally (outside of the browser tab):

Configuration

In order to enable this ability, one should set the following directory parameter, under /server/{default|<server_name>}/enhancedBrowse/{desktop|embedded}/:

<node class="boolean" name="exporting">
   <node-attribute name="value" value="TRUE"/>
</node>

Additional report functionality can be accessed using browse:REPORT attribute which is an com.goldencode.p2j.reporting.FwdReport object. E.g.:

browse brws:report:report-design = "CustomReport.jrxml".
browse brws:report:set-report-param("CustomTitle", "Custom Browse Report").

Report templates used for browse reporting are generic jrxml reports, but with only one column which is cloned for each browse column and each copy is adjusted to match the column properties like width, format etc.

The report may have ReportTitle report parameter which is always set to the browse title.

Hyperlinks in Cells

One can turn cells of the specific browse column into hyperlinks. By specifying the browse column option HYPERLINK "event-name" the associated column's cells turn into clickable links that when clicked will implicitly PUBLISH "event-name" and pass the cell's current value as a single character parameter. Sample:

DEFINE BROWSE br QUERY q 
DISPLAY 
     tt.f1 hyperlink "column1" 
     tt.f2 hyperlink "column2" 
     tt.f3
     WITH size-chars 60 by 10 TITLE "Static browse" separators.

PROCEDURE column1:
  DEFINE INPUT PARAMETER val AS CHARACTER NO-UNDO.

  MESSAGE "The cell from Column 1 was clicked: " + val.
END.

PROCEDURE column2:
  DEFINE INPUT PARAMETER val AS CHARACTER NO-UNDO.

  MESSAGE "The cell from Column 2 was clicked: " + val.
END.

subscribe to "column1" anywhere run-procedure "column1".
subscribe to "column2" anywhere run-procedure "column2".

The SUBSCRIBE does not need to be in the same program that is enabling the hyperlinking (and thus which is doing the PUBLISH). This works the same way that any named event (PUBLISH/SUBSCRIBE) works in the 4GL.

The conversion changes are not enough to enable this feature. In order to turn on this ability at runtime, one must set the following directory parameter which globally enables this ability for the application, under /server/{default|<server_name>}/enhancedBrowse/{desktop|embedded}/:

<node class="boolean" name="hyperlinking">
   <node-attribute name="value" value="TRUE"/>
</node>

If the browse is editable, then left click on a hyperlink cell starts editing of the cell, while ctrl+left click fires the hyperlink event.. In a non-editable browse, a single left click fires the hyperlink event.

Column Filtering and Sorting

Column Filtering

One can filter browse rows using column-level filtering. In order to enable this functionality, set this under /server/{default|<server_name>}/enhancedBrowse/{desktop|embedded}/:

<node class="boolean" name="enhancedFiltering">
   <node-attribute name="value" value="TRUE"/>
</node>

The line of column filters can be shown or hidden using the browse popup menu. Only columns backed by a field reference can be filtered.
One can explicitly disable column filtering for a browse or a column using NO-ENHANCED-FILTERING option or ENHANCED-FILTERING attribute:

DEF BROWSE br QUERY q 
DISPLAY 
     tt.f1 no-enhanced-filtering 
     tt.f2
   WITH size-chars 50 by 10 TITLE "Static browse" no-enhanced-filtering.

browse br:enhanced-filtering = false.
browse br:first-column:enhanced-filtering = false.

Column Sorting

One can sort browse rows using column-level sorting. In order to enable this functionality, set this under /server/{default|<server_name>}/enhancedBrowse/{desktop|embedded}/:

<node class="container" name="enhancedBrowse">
   <node class="boolean" name="enhancedSorting">
      <node-attribute name="value" value="TRUE"/>
   </node>
</node>

To sort the browse contents by a column, click on the column's label. You can add more granular sorting by clicking on the other labels. Only columns backed by a field reference can be sorted. START-SEARCH and END-SEARCH events are not generated is enhanced sorting is enabled.
Enhanced sorting does NOT work for browses with COLUMN-MOVABLE attribute set.
One can explicitly disable enhanced sorting for a browse or sorting by a specific column using NO-ENHANCED-SORTING option or ENHANCED-SORTING attribute:

DEF BROWSE br QUERY q 
DISPLAY 
     tt.f1 no-enhanced-sorting 
     tt.f2
   WITH size-chars 50 by 10 TITLE "Static browse" no-enhanced-sorting.

browse br:enhanced-sorting = false.
browse br:first-column:enhanced-sorting = false.

Column Mapping

Column mapping is a feature used for the case when a column contains visual representation of data, while the actual data is stored in another field (reachable from the browsed query). The column can display a visual representation of data provided by a field or an expression, or it can be a calculated column. The actual data we "map" the column to, can only be a buffer field.

Mapping can be specified for enhanced sorting using DB-SORT-FIELD-MAPPING attribute and for enhanced filtering using DB-FILTER-FIELD-MAPPING attribute. A field is specified using field-name or buffer-name.field-name notation.

Consider the case of displaying an arbitrary formatted date, like "7 Nov 2021". This can be implemented in one of the following ways:

  1. Render data into a character field and display it as a column. In this case the lexicographical order of the formatted date differs from actual date order, so we cannot sort on that date field by default.
  2. Use an expression as a column. For example, dynamic-function('formatdate', input date-field) @ date-field. Normally enhanced sorting/filtering is impossible for this type of column.
  3. Use a calculated column and render data in a ROW-DISPLAY trigger. Normally enhanced sorting/filtering is impossible for this type of columns.

In these different approached, one can specify the field containing the actual data (of the date type in this example) for this column:

column-handle:db-sort-field-mapping = "date-field-name".
column-handle:db-filter-field-mapping = "date-field-name".

This mapped field will be used for proper sorting or/and filtering.

In the filtering case, the input field above the column will have the data type of the mapped field (in the example above, it is a date input above the character column).

Enhanced Browse Attributes, Options and Functions

For report-related functionality see JasperReports Integration.

Attributes

Attribute Applies to Data Type Set Before Browse Becomes Visible Description
enhanced-sorting Browse/Column logical No Set to enable enhanced sorting. Can be applied only to columns which underlying data element is a buffer field (not a calc column or an expression).
enhanced-filtering Browse/Column logical No Set to enable enhanced filtering. Can be applied only to columns which underlying data element is a buffer field (not a calc column or an expression).
unique-key Browse character Yes Arbitrary key, which along with the browse name and the name of the currently executing procedure, should uniquely identify the browse in an application.
disable-cfg-edit Browse character Yes Set to disable the ability of a user to change any of the otherwise customizable enhanced configuration for the browse. Also makes the browse ignore any existing user-level enhanced configuration.
disable-row-striping Browse character Yes Set to disable row striping enhancement for the browse.
db-sort-field-mapping Column character No For enhanced sorting: name of data field, which this column is sorted by (e.g. buffer-name.field-name). This attribute is used for the case when the field which backs the current column is only a visual representation of data, while the actual data is another field from the browsed query. E.g. consider the current column is bound to a character field with an arbitrary formatted date, like "7 Nov 2021", while the field containing the date itself is not visible in browse, but reachable from the browsed query. The displayed data in this column is sorted by the last (date) field.
db-filter-field-mapping Column character No For enhanced filtering: name of data field, which this column is filtered by (e.g. buffer-name.field-name). This attribute is used for the case when the field which backs the current column is only a visual representation of data, while the actual data is another field from the browsed query. E.g. consider the current column is bound to a character field with an arbitrary formatted date, like "7 Nov 2021", while the field containing the date itself is not visible in browse, but reachable from the browsed query. The displayed data in this column is filtered by the last (date) field and the input filter field above the column has date data type.

Options

Option Applies to Description
disable-cfg-edit Browse Set to disable the ability of a user to change any of the otherwise customizable enhanced configuration for the browse. Also makes the browse ignore any existing user-level enhanced configuration.
disable-row-striping Browse Set to disable row striping enhancement for the browse.

© 2021 Golden Code Development Corporation. ALL RIGHTS RESERVED.