Customizing baseline queries in Dovetail Agent
In my last post, I covered the Query Filter Config files, and how they’re used to define a query.
Now, lets have a look at how we can override the baseline queries, customizing them for your specific implementation.
Customizing a filter config doesn’t mean you have to write rewrite the existing ones. You can write a config file just describing the customizations you need.
We call these Filter Overrides.
Using filter overrides, we can:
- remove a Column
- remove a Facet
- remove a Field
- add a Facet
- add a Field
- add a Column
- add a Join
Example Filter Override
This is an example of a custom filter override file.
We’ll override the Cases query, which is part of My Work, and adhoc queries on Work Items.
<filter overrides="Cases"> <!-- Remove priority as a facet and as a output column --> <removeFacet key="priority" /> <removeColumn key="priority" /> <!-- Remove the created column. We'll re-add it later with a different template --> <removeColumn key="created" /> <!-- Remove the contact column. We'll re-add it later with a different template --> <removeColumn key="contact" /> <query from="case"> <!-- Add Alternate Contact first name and last name to the query using labels --> <addFacet key="alt_first_name" label="Alternate First Name" field="alt_first_name" dataType="string" /> <addFacet key="alt_last_name" label="Alternate Last Name" field="alt_last_name" dataType="string" /> <!-- Add hangup time to the query --> <addFacet key="hangup_time" field="hangup_time" dataType="dateTime" /> <!-- Add contact objid to the query, but don't have it as an available facet to the end user --> <addJoin relationship="case_reporter2contact"> <addField key="case_reporter2contact" field="objid" dataType="int"/> </addJoin> </query> <!-- Combine the Alternate Contact first and last name into a single value --> <values> <addValue key="altContact" value="{alt_first_name} {alt_last_name}" /> </values> <columns> <!-- Add hangup time as an output column --> <addColumn key="hangup_time" template="timeAgo" label="Hangup Time" index="-1" width="140"/> <!-- Add the alternate contact as an output column --> <addColumn key="altContact" template="string" index="-2" label="Alt. Contact" width="120"/> <!-- add back in the created column, but with a dateTime template (as opposed to a timeAgo template) --> <!-- We'll also change its column heading (label) --> <addColumn key="created" template="dateTime" label="Case Create Date" index="0"/> <!-- add back in the contact column, but with a link template, so that it links to the contact page --> <addColumn key="contact" template="entityLink" entity="Contact" idField="case_reporter2contact" index="-3" width="200"> <sorts> <addSort key="contactLastName" /> <addSort key="contactFirstName" /> </sorts> </addColumn> </columns> </filter>
Lets walk through the different elements and see how they’re used.
Filter
The filter element allows us to define which filter we’re over-riding.
If we look at $app\Filters\workItems\cases.filter.config, we’ll see that the baseline filter config is names Cases.
<filter name="Cases" entity="Case">
So our filter override file will contain a filter element, and its overrides attribute should match the name of the baseline filter that we’re over-riding.
<filter overrides="Cases">
Remove Facets and Columns
We can easily remove facets and columns. Lets say we don’t use the Case Priority in our implementation, so lets remove it.
<removeFacet key="priority" /> <removeColumn key="priority" />
Remove Column
If we want to override a column, we can remove it and then re-add it later.
<!-- Remove the created column. We'll re-add it later with a different template --> <removeColumn key="created" /> <!-- Remove the contact column. We'll re-add it later with a different template --> <removeColumn key="contact" />
Add Facets
We can add facets, which allow users to filter on these columns.
<!-- Add Alternate Contact first name and last name --> <addFacet key="alt_first_name" label="Alternate First Name" field="alt_first_name" dataType="string" /> <addFacet key="alt_last_name" label="Alternate Last Name" field="alt_last_name" dataType="string" />
<!-- Add hangup time to the query --> <addFacet key="hangup_time" field="hangup_time" dataType="dateTime" />
Add Join
We can add joins, and add facets or fields from the joined in table.
A field is a database column that is returned as part of the query, but hidden from users. Here we want the contact Objid, but users’s should never see it. We’ll use it in just a bit.
<!-- Add contact objid to the query, but don't have it as an available facet to the end user --> <addJoin relationship="case_reporter2contact"> <addField key="case_reporter2contact" field="objid" dataType="int"/> </addJoin>
Values
We can use Values to combine multiple pieces of data together.
<!-- Combine the Alternate Contact first and last name into a single value --> <values> <addValue key="altContact" value="{alt_first_name} {alt_last_name}" /> </values>
Add Columns
Add Date column
Add hangup time as an output column.
- Render it using the timeAgo format
- Set its column header label to be “Hangup Time”
- Set its index be –1, which will push it to the left of the first default column.
- Set its default width to 140 px
<addColumn key="hangup_time" template="timeAgo" label="Hangup Time" index="-1" width="140"/>
Add Column with multiple pieces of data
Add the alternate contact as an output column. Notice that its key is altContact, which is the key we defined as a value above. So when this column renders, it will contain both the first and last name together.
<addColumn key="altContact" template="string" index="-2" label="Alt. Contact" width="120"/>
Add Column with a different template
Add back in the created column, but with a dateTime template (as opposed to a timeAgo template). Also, change its column heading (label).
<addColumn key="created" template="dateTime" label="Case Create Date" index="0"/>
Add Column that is a hyperlink
Add back in the contact column, but with a entity link template, so that it links to the contact page
We’ll also define how this single column with multiple pieces of data is sorted.
<addColumn key="contact" template="entityLink" entity="Contact" idField="case_reporter2contact" index="-3" width="200"> <sorts> <addSort key="contactLastName" /> <addSort key="contactFirstName" /> </sorts> </addColumn>
Compare
Lets compare the baseline cases query results to results with our overrides applied.
Baseline:
With overrides:
Notice:
- Contact column is now a hyperlink to the contact page
- The Alt. Contact column has been added
- The Hangup Time column has been added (with a Time Ago format)
- The Created column has been renamed to Case Create Date
- The Case Create Date shows in a Date Time format, as opposed to a Time Ago format.
- We’ve set our new columns to show up first. (Probably not what you want in production, but it does highlight the capabilities)
We were able to make these changes without modifying any code, and without modifying the baseline filter config files.
This means that when we do an Agent upgrade, we don’t have to worry about merging our code customizations into upgraded code. So our upgrades are much simpler.
File naming and directories
Filter overrides (just like baseline filter config files) must have a file name that ends in .filter.config. Example: cases.overrides.filter.config
The application will automatically pick up any files that have this file naming convention.
Customer config override files should live in source\Web\Filters\custom\
They don’t have to live there, but it will make your life easier.
Caching
There is an application setting that controls whether filter configs are cached or not.
<add key="FilterSettings.EnableCache" value="false"/>
During development, if you are changing these filter config files, set this to false. To test your changes, simply refresh the page in the browser, and your changes will automatically be picked up. This makes development a lot easier and faster.
In production, set this setting to true. Filter configs will get loaded at application startup time, and cached in memory. If you need to push a filter config change to production, the Admin – Refresh Cache link will force these configs to be reloaded.
Summary
This new query configuration is pretty powerful, and allows for a good deal of configuration and customization without having to modify any code. It also makes upgrades to newer versions of Dovetail Agent much easier.
The Dovetail Agent documentation has tons more specifics on filter config and filter override files, and all the available elements and attributes. Check out the Developer Resource – Filter Overrides section in the docs.
Next up, I’ll continue this series on Query configurations with how to add custom filter configs to query other tables/views in the system, including your custom tables.
Stay tuned.
Dig This?
Sign up to get information like this delivered right to your inbox.