Blog

Release announcements, helpful tips, and community discussion

7.3

Cerb (7.3) is a feature upgrade released on February 6, 2017. It contains over 178 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 September 1, 2016 then you can upgrade without renewing your license.

Important Release Notes

  • To honor our commitment to 3-4 major updates per year for annual subscriptions, we are backdating the release date of 7.3 for licensing purposes to September 1, 2016. Visit the project website to purchase or renewal a license.

  • Always make a backup before upgrading.

  • To upgrade your installation, follow these instructions.

  • Cerb 7.3+ now requires PHP 5.5+ and the openssl extension.

  • Virtual Attendants are now simply referred to as bots. The virtual_attendant database table and fields have been renamed to bot.

  • The new “Connected Account” functionality replaces standalone credentials for many plugins: Twitter, Twilio, Facebook, etc. The 7.3 update should migrate many of these automatically, but you should run the simulator on your affected bot behaviors to verify they’re still configured properly. The Freshbooks, JIRA, and Twitter plugins have new configuration options for synchronization which you can manage from Setup » Services.

Changes

Bots

Conversational behaviors

Bots can now implement conversational behaviors. This allows workers to request information and give instructions to bots through a live chat interface using natural language.

When conversational behaviors exist, a chat bubble appears in the lower right of browser. Clicking on the bubble opens a floating chat window. Specific bots can be addressed with @mentions.

Initially, these conversations are limited to workers, but the plan is to allow interactions in various channels: workers in browser, clients in support portal, workers in mobile apps, anonymous website visitors, etc. In the ‘worker browser’ channel, bots can open search popups, cards, etc. Conversational behaviors can be quickly built with the new classifiers feature to detect user intent and extract useful parameters (dates, times, workers, contacts, orgs, statuses, etc).

See:

Added cards for bot records

Implemented card popups for bot records.

On bot cards, a behavior count is now displayed as a clickable search button.

Bot cards now show a classifiers search button. Clicking this button displays a classifiers worklist.

Added search buttons to bot profiles

Removed unnecessary tabs on bot profiles and replaced them with search buttons. Previously, switching tabs lost any work in the current tab. The search buttons use popups and allow multitasking.

Added worklists, cards, and profile pages for bot behaviors

Implemented worklists for bot behaviors. Previously, all of a bot’s behaviors were displayed at the same time on a profile tab. With worklists, these behaviors can now be sorted, paged, filtered, quick searched, and subtotaled.

Implemented cards and profile pages for bot behaviors. Bot behavior trees can be edited directly from their card popup.

Custom fields on bot behavior records

Custom fields and fieldsets can now be set on bot behavior records. This makes it much easier to organize and group related behaviors.

Export behavior fragments

In bot behaviors, any node and its children can now be exported as a “behavior fragment”. This makes it much easier to share parts of a behavior between bot behaviors (even in different environments). We’ll be using this functionality to incrementally build behaviors in documentation/guides. Previously, behaviors could only be imported as a whole, which usually required deleting the old behavior being replaced.

Import behavior fragments

In bot behavior decision trees, behavior fragments can be imported on a new behavior of the same type on any appropriate node. For instance, an outcome can be added to any decision, a set of actions can be added to any behavior/loop/subroutine/outcome, etc. Behavior fragments also support prompted configuration during import, which helps tailor a behavior for your particular environment (e.g. linking connected accounts of the right type to the behavior).

Use choosers to configure imported behaviors and fragments

When importing bot behaviors and behavior fragments, the ‘configure’ option in the JSON object can now open choosers for any record type with a default quick search query and in single/multiple mode. This makes it especially easy for imported behaviors to link up connected accounts, delegate behaviors, etc.

Improved access control for bot behaviors

A ‘private’ behavior can now be used by anyone with write access to the behavior, where ‘public’ behaviors can be used by anyone with read access. Previously, ‘private’ meant that behavior could only be used within its parent bot. The change allows delegate bots to share specific behaviors between bots in either context (i.e. private delegates).

Bot behavior priorities

Added a ‘priority’ field to bot behaviors. This accepts a value from 1-99 to determine precedence when multiple behaviors respond to the same event. The field defaults to 50. Previously, the position of behaviors was determined by drag and drop, but this is no longer practical with the new behavior worklists. It also wasn’t very user friendly before since a single behavior could scroll multiple pages in the browser, making it difficult to drag behaviors around. Sorting a behavior worklist by priority is much more intuitive.

Loop nodes in bot behaviors

In bots, added a new ‘Loop’ node type. A loop node is configured with a JSON object that describes its iterator, and its child nodes are then repeated once for each iteration. This enables the creation of many new behaviors that couldn’t be created before. For instance, a bot can now request data (like a Twitter or RSS feed) and then run the same multi-step behavior tree on each item within the results. In conversational bots, loop nodes can also be used to validate user input, re-request some information, and abort after a certain number of invalid responses.

Subroutine nodes in bot behaviors

In bots, “subroutines” may be added to reduce redundancy and improve reusability of behavioral elements. A new ‘subroutine’ node type has been added. Subroutines are detached decision tree branches within the behavior that can be run from a ‘Behavior call routine’ action. When the subroutine finishes, the behavior resumes from the action node where it was called. Subroutines share the same scope as the behavior, so they can read and write placeholders to exchange data.

Resumable bot behaviors

Implemented “resumable” behaviors. When enabled for a behavior, this adds a special ‘Resume at this point when new input is received’ option to the ‘Behavior exit’ action. For instance, conversational chat bots can ask a question and then wait for a user response before continuing. When the behavior resumes, it returns to the same state it previously exited in, rather than restarting. This radically simplifies the development of chat bots like virtual assistants using Cerb.

Node states in bot behaviors

In bot behaviors, each node (decision, outcome, action) now has a state: live, simulator only, or disabled. This allows changes to existing behaviors to be tested without them responding to live events. When a node is marked as simulator only or disabled, all of its children inherit the same status. By default, all existing nodes are migrated into the ‘live’ state.

Duplicate nodes and branches in bot behaviors

In bot behaviors, a new ‘Duplicate’ option is available in the menu for decisions, outcomes, actions, loops, and subroutines. This creates an exact copy of the node along with all of its children.

Exit a bot behavior

[CHD-3979] Added a new ‘Behavior exit’ action to all bot behaviors. This allows early termination from any node in the behavior, which simplifies the design of many behaviors.

Filter behavior worklists by usability

Added ‘usableBy.bot:’ and ‘usableBy.worker:’ filters to behavior worklists. This makes it easier for choosers to only show valid options.

[CHD-4509] When creating a comment from bot behaviors, links can now be added to the comment record (e.g. using list variables).

Comment list behavior variables

Bot behaviors can now include list variables for comments. This simplifies comment-based worklists, like summarizing all the comments on a record.

Card popups on scheduled behavior worklists

On scheduled behavior worklists, the ‘Bot’ and ‘On’ columns now display cards rather than linking directly to profile pages.

Scripting

  • Added a url_decode filter to bot scripts. The filter converts a URL-encoded string into an array or JSON object. This is helpful when working with APIs that return URL-encoded responses.

  • Added an is numeric test to bot scripts. This allows for tests like: {% if var is numeric %}, which is useful for validating user input.

  • New base64_encode and base64_decode filters are available. This makes it easier to work with remote APIs, create HTTP Basic Auth headers, etc.

  • Plugins can add new filters and functions to bot scripts.

Usability

  • Improved the usability of drag/drop when reorganizing a bot behavior tree. Previously, this could become unreliable on complex behaviors.

  • Improved the usability of the ‘Reorder’ operation on bot behaviors. Previously, all nodes were displayed the same. Now, the same icons and colors from the behavior tree are used.

  • Implemented autocomplete for bots in choosers.

  • Added an updated_at field to behavior records.

Connected Accounts

Connected accounts provide authentication, secure storage, and reuse of user credentials at third-party service providers. Various forms of authentication are supported: OAuth, API keys, tokens, HTTP Basic, user/password, etc.

Bots can use connected accounts to cryptographically sign (or otherwise authenticate) arbitrary HTTP requests. This opens up entire service provider API to bots, rather than only offering a few hand-picked actions.

In bot behaviors, when using the ‘Execute HTTP Request’ action, a list of permitted connected accounts is now displayed in a new ‘Authentication:’ section. This allows the signing of arbitrary HTTP requests using these credentials (e.g. OAuth, bearer tokens, etc).

See:

Classifiers

Classifiers drastically simplify the implementation of machine learning behaviors in bots. A classifier takes textual input and statistically predicts a most likely classification based on its accumulated learning from human-supervised training examples.

For instance, an “Intent Detection” classifier can learn to uncover the intent from a spoken command (e.g. “find my open tickets this year from ACME Widgets”, “show Kina’s completed tasks”, “remind me about the conference call tomorrow at 2pm”, “who works at Mutiny?”, “What’s Cameron Howe’s mobile?”).

See:

Custom entities on classifiers

Implemented custom ‘list’ and ‘token regexp’ entities for classifiers. Previously, classifiers could only recognize the built-in types: dates, times, durations, contacts, orgs, workers, etc. New types can now be added using custom entities: countries, IP address, email address, on/off state, floors and rooms of a structure, ticket masks, etc.

Bulk import classifier training data

Added an ‘Import’ button to classifier cards to bulk import training examples in CSV format.

Search

Filtered fulltext search for tickets and messages

When using fulltext search on a ticket or message worklist, the other filters on the worklist will now be properly reduce the search scope. Previously, the fulltext search ran independent of all other filters, and those filters only were applied to the subset of records matching the fulltext query up to the max results (usually 1,000-10,000).

Now the most recent 20,000 filtered tickets from the current worklist will be scanned by a fulltext search. However, unlike before this limitation can be worked around by using date or ID filters to fetch less than 20,000 results per set.

In most cases, the limitations of full text search were felt when filtering much smaller lists, like the ticket history of a particular client. A fulltext search with no other filters will still match up to 20,000 tickets. This prevents very common terms (like ‘password’ or the local organization name) from bogging down the search.

Improved fulltext search stats

When using a fulltext search filter on a worklist, the stats displayed above the worklist have been improved. It shows the record type being searched (as there was some confusion on ‘messages’ vs ‘tickets’), whether the results were cached, and the max results. The stats will also be displayed every time a fulltext-filtered worklist is opened or refreshed.

Previously the stats only displayed on the first refresh. Additionally, the new stats approach is more efficient. In some cases the old approach could cause the search to run an additional time.

Quick search improvements

Quick search menu expansion

When using quick search on worklists, the helper menu now has nested submenus to simplify selection. Previously, every option was shown in an autocomplete menu, including potentially hundreds of placeholders.

Quick search helpers

Quick search on worklists now provides default examples for boolean, dates, and numbers.

Quick search behaviors by event

The ‘event:’ quick search filter on behavior worklists now provides a list of possible values.

Quick search calendars by owner

On calendar worklists, added ‘owner.bot’ and ‘owner.bot.id’ quick search filters.

Quick search calendar recurring events by timezone

Improved the ‘timezone:’ filter on calendar recurring event worklists. It now provides a series of submenus with valid timezones by region.

Quick search contacts by timezone

Improved the ‘timezone:’ filter on contact worklists. It now provides a series of submenus with valid timezones by region.

Quick search custom fieldsets by owner

On custom fieldset worklists, added ‘owner.bot’ and ‘owner.bot.id’ quick search filters.

Quick search email addresses by hostname

Added a ‘host:’ quick search filter on email address records. This contains the hostname of the email address (the part after the ‘@’). This makes it much more efficient to search email addresses by hostname rather than using leading wildcards.

Quick search messages by attachments

Added an ‘attachments:’ quick search filter to message worklists. This makes it easy to filter messages based on their attachments. You can filter attachments using another nested quick search, like attachments:(name:"screen shot*.png" size:<50000) – messages with PNG images less than 50KB that have filenames starting with “screen shot”.

Quick search messages by size

Improved the ‘size:’ filter on failed message worklists in Setup » Mail » Failed. This now accepts a human-readable file size (e.g. “>5KB”) rather than an integer number of bytes.

Quick search notifications by activity

The ‘activity:’ quick search filter to notification worklists now provides hints about the possible values.

Quick search records by linked record types

When using quick search on worklists, a ‘links:’ filter is now available to find records that link to a specific type of record (e.g. links:[ticket,task]).

Quick search translation text by language

The ‘lang:’ quick search filter on translation worklists now provides a list of the possible values based on the available translations.

Quick search workers by timezone

Improved the ‘timezone:’ filter on worker worklists. It now provides a series of submenus with valid timezones by region.

Deep quick search helpers

On worklists, the quick search menu can now open search popups and choosers to assist with constructing a query. Previously, many complex filters ‘links.ticket:’ expected the worker to figure out their possible options. This would have been especially difficult when doing deeply nested quick searches.

Deep quick search addresses by contact

Added a ‘contact:’ quick search filter to email address worklists. This makes it easy to filter email addresses based on the contact they are assigned to. You can filter contacts using another nested quick search, like contact:(firstName:C* timezone:America/Los_Angeles) – email addresses assigned to contacts whose name begins with the letter ‘C’ who are in the Los Angeles timezone.

Deep quick search addresses by organization

Improved the ‘org:’ quick search filter on email address worklists. This makes it easy to filter email addresses based on the organization they are assigned to. You can filter orgs using another nested quick search, like org:(sla.level:Enterprise) – email addresses assigned to organizations with an Enterprise SLA (a picklist custom field).

Deep quick search addresses by ticket participants

Added a ‘ticket:’ quick search filter to email address worklists. This makes it easy to filter email addresses based on tickets they are a participant on. You can filter tickets using another nested quick search, like ticket:(status:w mask:ABC group:support) – email addresses who are participants on waiting tickets in the Support group with a mask starting with ‘ABC’.

Deep quick search behaviors by bot

Added a ‘bot:’ quick search filter to behavior worklists. This makes it easy to filter behaviors based on attributes of their parent bot. You can filter bots using another nested quick search, like bot:(disabled:yes owner:app) – behaviors on disabled app-owned bots.

Deep quick search buckets by group

Improved the ‘group:’ quick search filter on bucket worklists. This makes it easy to filter buckets based on the associated group. You can filter groups using another nested quick search, like group:(private:no) – buckets in groups that are public.

Deep quick search calendars by owner

Improved the ‘owner:’ quick search filter on calendar worklists. This makes it easy to filter calendars based on the associated owner. You can filter owners using another nested quick search, like owner.worker:(Kina) OR owner.bot:(Facebook) – calendars owned by workers matching ‘Kina’ or owned by bots matching ‘Facebook’. You can also filter by types of owners, like ‘owner:[app,bot,worker]’.

Deep quick search calendar events by calendar

Improved the ‘calendar:’ quick search filter on calendar event worklists. This makes it easy to filter events based on attributes of their parent calendar. You can filter calendars using another nested quick search, like calendar:(owner:bot) – events on bot-owned calendars.

Deep quick search calendar recurring events by calendar

Improved the ‘calendar:’ quick search filter on calendar recurring event worklists. This makes it easy to filter recurring events based on attributes of their parent calendar. You can filter calendars using another nested quick search, like calendar:(owner:app name:holidays) – recurring events on app-owned calendars matching ‘Holidays’.

Deep quick search contacts by email

Improved the ‘email:’ quick search filter on contact worklists. This makes it easy to filter contacts based on their email address. You can filter email addresses using another nested quick search, like email:(ticket:(importance:>90 status:o group:sales)) – contacts with an email address as a participant on an open ticket in the Sales group with an importance higher than 90/100.

Deep quick search contacts by organization

Added an ‘org:’ quick search filter to contact worklists. This makes it easy to filter contacts based on the organization they belong to. You can filter organizations using another nested quick search, like org:(country:France) – contacts whose organization is based in France.

Deep quick search custom fieldsets by owner

Improved the ‘owner:’ quick search filter on custom fieldset worklists. This makes it easy to filter custom fieldsets based on the associated owner. You can filter owners using another nested quick search, like owner.worker:(Kina) OR owner.bot:(Facebook) – custom fieldsets owned by workers matching ‘Kina’ or owned by bots matching ‘Facebook’. You can also filter by types of owners, like ‘owner:[app,bot,worker]’.

Deep quick search drafts by worker

Added a ‘worker:’ quick search filter to draft worklists. This makes it easy to filter drafts based on the worker who authored them. You can filter workers using another nested quick search, like language:"nl_NL" group:sales – drafts from workers who speak Dutch and are members of the Sales group.

Deep quick search feedback by email

Added an email:’ quick search filter to feedback worklists. This makes it easy to filter feedback based on attributes of the author’s email address. You can filter email addresses using another nested quick search, like email:(isBanned:y OR isDefunct:y) – feedback authored by email addresses that are flagged as either banned or defunct.

Deep quick search feedback by worker

Added a ‘worker:’ quick search filter to feedback worklists. This makes it easy to filter feedback entries based on attributes of the worker who reported them. You can filter workers using another nested quick search, like worker:(group:(sales) gender:f) – feedback captured by female members of the Sales group.

Deep quick search file bundles by owner

Added an ‘owner:’ quick search filter to file bundle worklists. This makes it easy to filter file bundles based on their owner. You can filter owners using another nested quick search, like owner:app OR owner.worker:kina – file bundles owned by Cerb, or by workers matching ‘Kina’.

Deep quick search groups by members

Added a ‘member:’ quick search filter to group worklists. This makes it easy to filter groups based on their members. You can filter members using another nested quick search, like member:(gender:F) AND member:(gender:M) – groups that contain both male and female members.

Deep quick search messages by sender

Added a ‘sender:’ quick search filter to message worklists. This makes it easy to filter messages based on attributes of their sender email address. You can filter senders using another nested quick search, like sender:(org:(sla.level:Priority)) – messages sent from email addresses associated with organizations that have a Priority SLA.

Deep quick search messages by ticket

Added a ‘ticket:’ quick search filter to message worklists. This makes it easy to filter messages based on attributes of their parent ticket. You can filter tickets using another nested quick search, like ticket:(status:[w] org:(Dobbus)) – messages on waiting tickets from organizations matching ‘Dobbus’.

Deep quick search messages by worker

Added a ‘worker:’ quick search filter to message worklists. This makes it easy to filter outgoing messages based on attributes of the worker who sent them. You can filter workers using another nested quick search, like worker:(isAdmin:yes links.jira_issue:(key:*)) – messages sent by workers who are admins and watching at least one JIRA issue.

Deep quick search notifications by worker

Added a ‘worker:’ quick search filter to notification worklists. This makes it easy to filter notifications based on attributes of the worker who received them. You can filter workers using another nested quick search, like worker:(isAdmin:no timezone:Europe/*) – notifications for workers who are in European timezones and are not admins.

Deep quick search organizations by email

Improved the ‘email:’ quick search filter on organization worklists. This makes it easy to filter orgs based on their email address. You can filter email addresses using another nested quick search, like email:(isDefunct:yes spam:>0) – organizations with an email address that is marked defunct that previously sent at least one spam message.

Deep quick search records by linked records

When filtering a worklist by linked records, people have asked for the ability to filter by attributes of the linked records.

For instance, listing ‘‘open’’ time tracking records that are linked specifically to ‘‘closed’’ tickets. Previously, there was no effective way to handle this. We’ve added links.<alias>: filters to every worklist that allow you to perform a nested quick search to filter the linked records. The alias can be a descriptive term for any record type (e.g. ticket, tasks, contact, org, opp).

For example, from a time tracking worklist you can now use links.ticket:(status:o) to find only time slips linked to ‘‘open’’ tickets. You can use any ticket-based quick search filter within the links() filter, including AND/OR grouping and nested links() filters (e.g. find open time slips, that link to orgs which start with the letter ‘W’, which link to closed tickets). This makes many new reports possible and should save a lot of time.

Deep quick search scheduled behavior by behavior

Added a ‘behavior:’ quick search filter to scheduled behavior worklists. This makes it easy to filter scheduled behavior based on attributes of its behavior. You can filter behaviors using another nested quick search, like behavior:(bot:(owner:group) disabled:n) – scheduled behaviors from live behaviors on group-owned bots.

Deep quick search scheduled behavior by bots

Added a ‘bot:’ quick search filter to scheduled behavior worklists. This makes it easy to filter scheduled behavior based on attributes of its behavior’s bot. You can filter bots using another nested quick search, like owner:[worker,group] – scheduled behavior associated with a group- or worker-owned bot.

Deep quick search scheduled behavior by target

Added an ‘on:’ quick search filter to scheduled behavior worklists. This makes it easy to filter scheduled behaviors based on the records they are attached to. You can filter target records using another nested quick search, like on:[ticket,task] – scheduled behavior on ticket or task records.

Deep quick search sessions by worker

Added a ‘worker:’ quick search filter to session worklists in Setup. This makes it easy to filter sessions based on their associated worker account. You can filter workers using another nested quick search, like worker:(group:(sales)) – sessions from workers who are a member of the Sales group.

Deep quick search skills by skillset

Added a ‘skillset:’ quick search filter to skill worklists. This makes it easy to filter skills based on attributes of their parent skillset. You can filter skillsets using another nested quick search, like skillset:(sales) – skills in skillsets matching ‘sales’.

Deep quick search snippets by owner

Added an ‘owner:’ quick search filter to snippet worklists. This makes it easy to filter snippet based on their owner. You can filter owners using another nested quick search, like owner.group:(isPrivate:n) OR owner.worker:milo – snippets owned by public groups, or by workers matching ‘Milo’.

Deep quick search tasks by owner

Added an ‘owner:’ quick search filter to task worklists. This makes it easy to filter tasks based on attributes of the worker who owns them. You can filter workers using another nested quick search, like owner:(gender:F isAvailable:"now to +2 hours") – tasks owned by female workers who have calendar availability for the next 2 hours.

Deep quick search tickets by bucket

Improved the ‘bucket:’ quick search filter on ticket worklists. This makes it easy to filter ticket based on attributes of their bucket. You can filter buckets using another nested quick search, like bucket:(name:"Inbox") – tickets in bucket named ‘Inbox’.

Deep quick search tickets by group

Improved the ‘group:’ quick search filter on ticket worklists. This makes it easy to filter ticket based on attributes of their group. You can filter groups using another nested quick search, like group:(private:yes) – tickets in private groups.

Deep quick search tickets by messages

Added a ‘messages:’ quick search filter on ticket worklists. This makes it easy to filter tickets based on attributes of their messages. You can filter messages using another nested quick search, like messages:(sender:(isBanned:yes)) status:o – open tickets with messages from senders who are banned.

Deep quick search tickets by organization

Improved the ‘org:’ quick search filter on ticket worklists. This makes it easy to filter tickets based on the associated organization. You can filter organizations using another nested quick search, like org:(links.domain:("example.com")) – tickets associated with organizations that are linked to domain records matching ‘example.com’.

Deep quick search tickets by owner

Added an ‘owner:’ quick search filter on ticket worklists. This makes it easy to filter tickets based on attributes of the worker who owns them. You can filter workers using another nested quick search, like owner:(firstName:K*) – tickets opened by a worker whose name begins with the letter ‘K’.

Deep quick search tickets by participants

Improved the ‘participants:’ quick search filter on ticket worklists. This makes it easy to filter tickets based on attributes of any of their participants. You can filter participants using another nested quick search, like participant:(contact:(org:(country:Canada))) – tickets with any participant contact from an organization based in Canada.

Deep quick search time tracking by worker

Added a ‘worker:’ quick search filter to time tracking worklists. This makes it easy to filter time slips based on attributes of the associated worker. You can filter workers using another nested quick search, like worker:(timezone:Australia/* gender:f) – time slips by female workers in Australian timezones.

Deep quick search Web API credential worklists by worker

Added a ‘worker:’ quick search filter to API credentials worklists. This makes it easy to filter API credentials based on the worker who created them. You can filter workers using another nested quick search, like worker:(title:engineer) – API credentials created by workers with ‘Engineer’ in their job title.

Deep quick search workers by email

Improved the ‘email:’ quick search filter on worker worklists. This makes it easy to filter workers based on their email address. You can filter email addresses using another nested quick search, like email:(*@example.com) – workers with an @example.com email address.

Deep quick search workers by group

Improved the ‘group:’ quick search filter on worker worklists. This makes it easy to filter workers based on their group memberships. You can filter groups using another nested quick search, like group:(name:S* private:n) – workers in public groups starting with the letter ‘S’.

Deep quick search workspace pages by owner

Added an ‘owner:’ quick search filter to workspace page worklists. This makes it easy to filter pages based on their owner. You can filter owners using another nested quick search, like owner.worker:(firstName:m*) OR owner:app – pages owned by workers with a first name starting with M, or by Cerb.

Mail

Improved the performance of ticket worklists

Improved the performance of ticket worklists. Previously, ticket worklists joined the email address table twice – once each for the first/last senders. With potentially millions of rows in each table, these joins reduced performance and could lead the MySQL query planner to use less efficient indexes (and in some versions, full scans with no index at all). Now, only the IDs for the senders are returned. When the ticket worklist displays sender information, it does a ‘lazy load’ to look it up by its primary key for the current page of results; which is far more efficient.

Improved the performance of ticket worklists by “lazy loading” organization data only when it’s explicitly needed, and only for the current page of results.

Contact names in ticket worklists

On ticket worklists, the ‘First Wrote’ and ‘Last Wrote’ columns now display the contact’s name (if known) in addition to their email address.

Added search button shortcuts to ticket cards and profiles

On ticket cards, added a search button for comments.

On ticket profiles, added search buttons for attachments, comments, and messages.

Cards

[CHD-2119] Record links can now be added and removed directly from card popups. Previously, the popup only displayed links and you had to view the full profile to make changes.

Improved the profile picture editor

When using the profile picture editor on cards, ‘white’ is now available in the color swatch presets.

When using the profile picture editor on cards, the background color will automatically be set to white as a default when loading an image by URL. Previously the background color was random.

Profiles

Record aliases

Implemented aliases for contacts, orgs, and workers. For instance, these names all refer to the same organization: “UC Berkeley”, “University of California, Berkeley”, “Berkeley”, “UCB”, “berkeley.edu”, etc. With aliases, there’s a lot more flexibility in the way workers can refer to an organization (particularly in conversational bot behaviors).

Improved the usability of record links on profiles. Previously, a worker had to switch to the ‘Links’ tab to manage links. To add a link, they had to click into one of two dropdowns (find or create), select a record type, pick the appropriate records, save, then switch back to whatever they were doing. If a worker attempted to do this while writing a reply then it would save as a draft and they’d lose their place. Now links can be added directly from the top of the profile page. Links can now also be added directly to related records (like the sender or organization of a ticket) in the same way without leaving the page. Links can also be quickly removed while viewing a profile by clicking on that record type within the Links section, selecting rows, and clicking the ‘Unlink’ button. All of this can be done while in the middle of a reply on a ticket profile, etc. Links are also displayed in a more condensed format on profiles.

Multi-context owner chooser

Added a new multi-context ‘Owner’ chooser. Previously, on records like snippets which could be owned by various record types (e.g. app, bot, group, worker), the possible owners were presented in a long dropdown. Now, owners are selected from a menu with submenus for each record type. A ‘me’ shortcut is available at the top-level of the menu. When an owner is selected, the menu hides. When the owner is removed, the menu reappears.

Implemented the new owner chooser when editing bot records. Also, the ‘owner’ column on Bot worklists is now clickable and displays the owner’s card.

Implemented the new owner chooser when editing snippet records. Also, the ‘owner’ column on Snippet worklists is now clickable and displays the owner’s card.

Implemented the new owner chooser when editing page records. Also, the ‘owner’ column on page worklists is now clickable and displays the owner’s card.

Added the new ‘owner’ picker menu to the custom fieldset editor.

On a bucket profile page, record links for its parent group are now also displayed.

On a contact profile page, record links for their email address and organization are now also displayed.

Improved schedule behaviors on profiles

On the profile summary, clicking the bot name opens its card. On the scheduled behavior popup, clicking the behavior opens its card which displays the decision tree.

On profiles, when a record links to a bot (e.g. owner) its profile picture is now displayed next to its name in the properties.

Attachments

Attachment worklists

Added worklists for attachment records. Attachments can now be searched from the global ‘Search’ menu.

Profile pages for attachments

[CHD-4507] Added profile pages for attachment records.

Cards for attachments

Implemented card popups for attachment records.

Quick search attachments by target record

Added an ‘on:’ quick search filter to attachment worklists. This makes it easy to filter attachments based on the record they’re linked on (like on:comments). You can also do nested searches, like on.comment:(author.worker:(gender:f firstName:k*)) – attachments on comments authored by female workers whose name starts with the letter ‘K’.

Comments

Comment worklists

[CHD-4497] Added worklists for comment records. Comments can now be searched from the global ‘Search’ menu.

Cards for comments

Implemented card popups for comment records.

Comment profile pages

Added profile pages for comment records.

Search buttons on attachment cards and profiles

On attachment cards and profiles, search buttons are shown for quickly finding records that reference the file.

Quick search comment worklists by author

Added an ‘author:’ quick search filter to comment worklists. This can be used like author:bot to find all comments by bots, or author.workers:(firstName:j* gender:f) to find all comments by female workers whose name begins with the letter ‘K’. When using the author.<record-type>: filters, any quick search filter for that record type can be used.

Quick search comment worklists by target

Added an on: quick search filter to comment worklists by the records being commented on. This can be used like on:[task,ticket] to find all comments on tasks and tickets, or on.ticket:(status:o group:sales) to find all comments on open tickets in the Sales group. When using the on.<record-type>: filters, any quick search filter for that record type can be used.

Quick search comment worklists by attachments

Added an ‘attachments:’ quick search filter to comment worklists. This makes it easy to filter comments based on their attachments. You can filter attachments using another nested quick search, like attachments:(mimetype:image/png size:>500000) – comments with PNG image attachments that are larger than 500KB.

Activity Log

Card popups for new comment activity

Activity log entries about new comments now include a link to the comment’s card. The full text of the comment is no longer duplicated in the activity log, which saves space in the database and makes those queries more efficient.

Quick search activity log entries by actor

Added actor quick search filters to activity log worklists. You can use ‘actor:[worker,bot]’ to filter by record types, or ‘actor.worker:(kina isDisabled:n gender:f)’ to search a specific record type using any filters from that record’s quick search syntax. The new filters also work with AND/OR grouping.

Quick search activity log entries by target

Added target quick search filters to activity log worklists. You can use ‘target:[task,ticket]’ to filter by record types, or ‘target.ticket:(mask:ABC* status:[o,w])’ to search a specific record type using any filters from that record’s quick search syntax. The new filters also work with AND/OR grouping.

Quick search activity log by activity

Improved the ‘activity:’ quick search filter on activity log worklists. Previously this matched arbitrary text and required the worker to know the possible values. Now there’s a helper with a series of sub-menus for the possible activities. Multiple activities can be specified using the “[this,that]” bracket syntax.

Calendars

Quickly add new events to calendars

When viewing a calendar, new events can be quickly added by clicking on the day number. This opens the event editor and automatically pre-fills the calendar and start date.

Cards for calendars

[CHD-4429] Implemented card popups for calendar records.

Implemented card popups for calendar event records.

Implemented card popups for calendar recurring event records.

On calendar cards and profiles, search buttons now display the total number of events and recurring events on the calendar. Clicking the button displays a worklist of those records. Adding a new record from that worklist will set default fields based on the filters.

Start of week for calendar widgets

Calendar widgets on dashboards now properly display with Sunday/Monday as the first day of the week based on each calendar’s configuration.

Knowledgebase

Image attachment placeholders in knowledgebase articles

Previously, when using attached images in knowledgebase articles, the URL of the Cerb installation was embedded. This caused problems if Cerb was moved to a new hostname or path. These URLs are now dynamically generated using a new {{cerb_file_url(…)}} placeholder. The placeholder is inserted automatically by the ‘upload image’ button. The generated URLs will automatically adapt to articles being displayed in the worker UI or the Support Center.

Malformed knowledgebase articles no longer break profiles

[CHD-4194] Fixed an issue where malformed HTML could cause a knowledgebase article to become non-editable from its profile page.

Roles

Worklists for roles

Implemented worklists for role records.

Card popups for roles

Implemented card popups for worker role records.

Role profile pages

Added profile pages for worker role records.

Snippets

Cards for snippets

[CHD-4431] Implemented card popups for snippet records.

Snippet profile pages

Added profile pages for snippet records.

Time Tracking

Cards for time tracking entries

Implemented cards for time tracking records.

Web API

There’s a new ‘links’ placeholder on all record dictionaries. This retrieves a list of context:id pairs that link to the current record. This can be used in the Web API with the ‘expand’ parameter, and in bots/snippets with ‘links’ or ‘_links'.

Search activity log entries from the API

[CHD-3742] Added the ability to search activity log entries from the REST API. The results should be filtered using quick search syntax. See: http://cerbweb.com/book/latest/developer_guide/rest_api/activity_log.html

Platform

Performance

  • Added proper cache headers for WOFF2 font files. This ensures browsers cache the files instead of requesting them constantly.

Developers

  • Implemented DevblocksPlatform:: getEncryptionService() for simple and secure key-based encryption. This allows encryption-at-rest for database data (OAuth tokens, etc). https://github.com/defuse/php-encryption

  • The DevblocksPlatform::getPluginSettings() and ::setPluginSettings() methods now include an optional argument for automatic at-rest encryption. This makes it much easier to store credentials (like OAuth consumer key/secret tokens).

  • Added a DevblocksPlatform::translate($token, $format) convenience method for working with translations and post-processing their text (capitalize, upper, lower) in a single line.

  • Added a DevblocksPlatform::strStartsWith() convenience method for comparing the prefix in any text. Also added ::strEndsWith() to compare suffixes.

  • Overhauled context-based permissions for records. Now we use Context_::isReadableByActor($models, $actor) and Context_::isWriteableByActor($models, $actor). An abstract helper is available on CerberusContexts. The $actor can be an ID, a Model_* instance, or a dictionary. The $models can be any of the same, as well as a single instance or an array. When given an array of models, the return value will be an array of ids => true/false. This allows an entire set of records to be efficiently checked for permissions at once (e.g. pages of a worklist, API results, bot list variables).

  • Added a Devblocks.playAudioUrl() function to the Javascript environment.

  • On chooser widgets, autocompletes can now provide a quick search query in the data-autocomplete attribute for filtering the results.

Libraries

  • Added the rangy Javascript library by Tim Down to Devblocks (MIT license). This allows for script-based manipulation of text selection ranges.

  • Added the defuse-crypto library by Taylor Hornby and Scott Arciszewski (MIT license). This provides secure, key-based encryption functionality.