Blog

Release announcements, helpful tips, and community discussion

9.3

Cerb (9.3) is a feature upgrade released on June 11, 2019. It includes more than 69 new features and improvements from community feedback.

To check if you qualify for this release as a free update, view Setup » Configure » License. If your software updates expire on or after May 31, 2019 then you can upgrade without renewing your license. Cerb Cloud subscribers will be upgraded automatically.

Important Release Notes

Intelligent Autocomplete Suggestions for Queries

Autocomplete suggestions in code editors

Code editors now provide syntax highlighting and intelligent autocompletion for search queries, data queries, and YAML when:

  • Using search menu popups and worklists

  • Configuring worklist or data query based widgets on profile and workspace dashboards

  • Configuring privileges and record owner queries in roles

  • Customizing the ‘Required query’ on a worklist

  • Using data queries in bot behaviors

  • Creating new saved searches

Autocompletion suggestions are presented as you type, based on the position of the text cursor (e.g. within a field/value, in a deep search of a particular record type, etc). The suggestion menu can also be opened manually with the <CTRL> + <SPACE> keyboard shortcut.

Suggestions are provided for deep searches to any depth (e.g. ticket:(messages.last:(sender:(org:().

Suggestions can be generated from existing record data (e.g. country names, first/last names, worker titles, email addresses).

Suggestions are scored so that the most frequently used combinations are recommended first (e.g. status: on tickets, email: on addresses).

Suggestions may include multiple lines of sample content along with fill-in placeholders that can be quickly replaced in sequence with <TAB>.

Quickly access saved searches

Saved searches may be quickly inserted into a query by typing # and using the suggestion menu.

Saved searches are also accessible from within the query: field in data queries, and in deep searches at any depth.

Dynamic suggestions for data queries by type

In data queries, suggestions automatically adapt in real-time to changes the type: and of:, including multiple series queries.

Sheets

Worklists are great, but they’re heavily tied to the database schema (i.e. one field per column) and force default cell formatting on you. They’re not responsive, they’re too elaborate and unwieldy for bots, and they can’t be used to view non-record data.

Sheets are a modern, automation-friendly data visualization that avoids the schematic rigidity of worklists. A sheet is still a collection of rows and columns, but its column are defined in a fully customizable YAML-based text schema. This text-based schema can live within a bot behavior or widget without having to be previously defined or saved.

Each column in a sheet has a type (e.g. card, date, link, slider, search, search_button, text, time_elapsed) with configurable options.

For instance, people have regularly asked for a way to change how dates are displayed in a specific worklist (absolute vs relative, 12h vs 24h, localized times, etc). We’ve also commonly been asked to allow things like colorizing the priority levels from a custom field. Sheets make these customizations really easy.

A cell (the intersection of a specific row and column) doesn’t have to relate to a schema field at all – it can be a synthetic or computed value, translation, interactive element, deep-linked field, arbitrary output, etc.

Sheets use placeholder dictionaries to render cells, and they receive their input from any data query that can generate dictionaries – including worklist.subtotals and a new worklist.records data query type that significantly simplifies fetching record data. This means that sheets can also easily format and display data from third-party APIs. The data query itself, being text, supports placeholders and bot scripting logic – so you can determine which columns are available, or what a cell displays, based not only on aspects of the record, but also based on who is looking at it, their permissions, etc.

State on sheets is maintained client-side, and paging/sorting/filtering is customized for the use case (e.g. bot interaction vs portal vs dashboard widget) – essentially just passing simple information to the input data query.

For example, this data query:


type:worklist.records
of:ticket
query:(status:open limit:5)
expand:[initial_message_sender_org_,owner_]
format:dictionaries

And this sheet schema:



layout:
  style: table
  headings: true
  paging: true
  title_column: _label
columns:
- card:
    key: _label
    label: Ticket
    params:
      bold: true
- card:
    key: initial_message_sender__label
    label: Requester
    params:
      underline: false
- text:
    key: initial_message_sender_org_country
    label: Country
- text:
    key: group__label
    label: Group / Bucket
    params:
      value_template: >-
        {{group__label}} / {{bucket__label}}
- card:
    key: owner__label
    label: Owner
    params:
      image: true
      underline: false
- slider:
    key: importance
- date:
    key: updated
    label: Updated
    params:
      format: Y-m-d


Will display this sheet:

Unlike a worklist that is limited to records, the results of the data query above could have come from anywhere (third-party API call, subtotals, computation). As text, sheets can be quickly modified and shared, retrieved from the API, or constructed dynamically by bots.

You’ll also notice that we’re displaying the country of the initial sender’s organization as a column. The group and bucket are displayed as a single column. We’re electing which columns to show cards and profile images for. We’re changing the date format. All of this wasn’t possible with worklists.

Read the sheets documentation for more information.

Form Interactions

Conversational bot interactions (e.g. chat bots) addressed a major need in having dynamic conversations with bots as automated workflow helpers, but chat has several big limitations.

One of the major things people have complained about with the chat approach is that you have to go back-and-forth so many times with a single question and response to do something common like creating a new record. Chat was meant to replace boring and rigid forms, but in several cases forms felt more efficient.

We drew inspiration from the best parts of chat bots in Cerb, while addressing the artificial constraints imposed by chat vs forms, and created form interactions. [#941]

Form interactions build dynamic multi-step web forms that adapt in real-time based on user input. They are similar to conversational interactions (they can do everything a chat bot does), but they display a collection of prompts (e.g. given name, family name, email address, phone number) and responses as a single step.

Data Queries

Load record data

Added type:worklist.records data queries for retrieving record dictionaries. This is how sheets load record data.


type:worklist.records
of:tickets
expand:[
  group_,
  bucket_,
  latest_message_sender_
]
query:(
  status:!d
  limit:10
  sort:id
)
page:0
format:dictionaries

Read the worklist.records data queries documentation for more info.

Improved data query tester

The Setup » Developers » Data Query Tester tool now supports autocompletion and the JSON results support syntax highlighting and code formatting.

Dictionary output in subtotal queries

In worklist.subtotals dictionaries, format:dictionaries is now supported. This returns subtotal stats as dictionaries which can be displayed in sheets or through the API.

A new expand:[] field controls key expansion in the dictionaries. This allows visualizations (like sheets) to expand record details, which wasn’t possible with ‘table’ widgets previously.

Improved validation

Data queries now return an error when an unknown parameter is given. This protects against issues like using qury: instead of query: and showing an unfiltered list.

Required queries

Data queries that accept a query: parameter now also accept a query.required: parameter, which establishes the subset of records that are visible regardless of user-level filtering.

The query.required: input should be protected against user-provided placeholders. This is important as data queries power more user-facing functionality (e.g. portals), and paging/sorting/filtering are provided as query: parameters.

Subtotal by date-based custom fields

In type:worklist.subtotals data queries, implemented the ability to subtotal by: on date-based custom fields.

Workspaces

Switch directly to a tab on a different workspace

In the workspace pages menu, it is now possible to jump directly to a specific tab on another workspace. Previously, you had to select the workspace page and then switch tabs as a second click.

Tab styles on workspaces

On workspace pages, the tab style may now be toggled between “Tab set” (the existing default) and “Dropdown menu”. This improves workflows on pages with many tabs where most are infrequently used. [#888]

Dashboards

Form interaction widgets

Implemented form interaction widgets for workspace dashboards. Multiple form interactions can be configured and the widget will display a button menu to select one. This improves maintainability since each interaction doesn’t require its own widget, and each interaction doesn’t need to perform multiple duties.

Sheet widgets

Implemented sheet widgets for workspace dashboards. The following column types are currently supported: card, date, link, search, search_button, slider, text, and time_elapsed.

Profiles

Form interaction widgets

Implemented form interaction widgets for profiles. Multiple form interactions can be configured and the widget will display a button menu to select one. This improves maintainability since each interaction doesn’t require its own widget, and each interaction doesn’t need to perform multiple duties. The widget can pass input variables to form interaction behaviors using placeholders from the current record.

Sheet widgets

Implemented sheet widgets for profiles. This uses placeholders from the current record to run a data query to populate the sheet. The following column types are currently supported: card, date, link, search, search_button, slider, text, and time_elapsed.

Bots

Record ID behavior variables

Bot behaviors may define ‘Record ID’ variables. These variables are configured as a specific record type (e.g. task) and store a single record ID.

When the variable name ends with an _id suffix, the records dictionary will be available for key expansion at that path.

For instance, a variable named var_ticket_id will provide placeholders like var_ticket_subject and var_ticket_group__label.

This drastically simplifies behaviors that receive a record ID; particularly bot interactions.

Variables in behavior dictionaries

Bot behavior dictionaries now include a variables key with information about its public/private variables (e.g. name, key, type).

This can be used by any functionality to discover a behavior’s inputs and build prompts for them.

Packages

Participants sheet on ticket profiles

On ticket profiles, the ‘Participants’ package now uses a sheet widget to display a list of participants. Previously this was a custom HTML widget which lacked paging, formatting, etc.

Sheet packages

Added sheet examples to the package library for workspace widgets.

Form interactions

Added a form interaction example to the package library for bot behaviors.

API

Meta for records API

In the API, retrieving and searching records supports the show_meta option again. This includes a _meta key in the results with labels and types dictionaries.

Platform

Cache

Lazy cache invalidation by tag

Implemented support for tag-based invalidation in the cache service. Tags are a gradual/eventual method of invalidation where a set of cache keys are large or unpredictable.

For instance, by tagging worker menu customizations as schema_workspaces, they will be “lazy” invalidated each time a change is made to workspace pages or tabs.

The cache keys are only validated or refreshed when loaded. In this example, only the cached menus of currently active workers would update (hence “gradual invalidation”).

This approach is also required when using localStorage to cache content in client browsers, as those caches can’t be invalidated when a worker isn’t online.

The alternative would be invalidating potentially hundreds of keys in real-time on every workspace-based record edit, which is inefficient or impractical in many cases.

When a cache key doesn’t contain tags, there is no difference in how the cache service works.