Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Advanced Team View Filters


Team View Filters allow supervisors to search or filter their agents by name or activity. You can also use custom, programmatically defined filter criteria, like teams or skills. This page describes the main concepts involved in customizing Team View Filters, and includes some sample code you can use to get started with the feature. For more information about using Team View Filters, check out the End User Guide!

(warning)

Warning

This feature is in pilot between version 1.18 and version 1.26.3 of the Flex UI. You can enable team view filters on the pre-release features page(link takes you to an external page) within Flex Admin. This feature is enabled by default for version 1.27.0 and upper.


Key Concepts

key-concepts page anchor

Flex uses the following objects and components to generate Team View Filters:

TeamFiltersPanel

teamfilterspanel page anchor

The portion of the Flex UI that shows the Team Filters. It is a child component of the Supervisor UI. By default, Flex allows you to filter by agent Activity, but you can add custom filters to the panel by modifying the defaultProps, like so:


_10
Flex.TeamsView.defaultProps.filters = [
_10
Flex.TeamsView.activitiesFilter,
_10
// ... custom filters here
_10
];

A FilterDefinition is a structure that tells Flex how to render the new filter label and field, and what to query the field value against. Each field will add a new condition to the Sync query that will render the agents (or workers) list to the UI. A FilterDefinition has the following structure:


_10
interface FilterDefinition {
_10
id: string;
_10
title: React.ReactChild;
_10
fieldName: string;
_10
type?: FiltersListItemType;
_10
options?: Array;
_10
customStructure?: CustomFilterItemStructure;
_10
condition?: string;
_10
}

FieldDescription
idRequired. A string representing the subject of your query. This identifies the values to filter for in the Flex app state based on your specified attribute or field. For example, "data.attributes.full_name" or "data.activity_name".
titleRequired. A string that is rendered as the filter display name on the Filters side panel. For example, "Names".
fieldNameRequired. A string representing the input name passed to the predefined filters. For example, "full_name".
typeRequired if customStructure isn't defined. Currently only supports "multiValue". This renders a list of checkboxes for each option you provide.
optionsRequired if type is "multiValue". An array of filter definition options used for rendering the checkbox fields, their values, their labels, and whether they are selected by default.
customStructureRequired if type isn't set. An object of type CustomFilterItemStructure used for rendering custom fields. This lets you add your own custom fields.
conditionAn optional parameter that represents the query comparison operator such as IN, NOT_IN, CONTAINS. See Query Operators to learn about other possible condition values.

This represents the condition to be used in building the query. For instance, data.activity_name IN ["available"] or data.attributes.full_name CONTAINS "John". In the latter example, "data.attributes.full_name" is the id, "CONTAINS" is the condition, and "John" is the value to filter for.

Describes the available options which can be used as a filter. For example, if you wanted to filter by agent languages, you could create an option for each language spoken in your contact center.


_10
interface FilterDefinitionOption {
_10
value: string;
_10
label: string;
_10
default?: boolean;
_10
}

FieldDescription
valueValue of the filter option. When using IN or NOT_IN to build your query and you are providing an array of options, you need to omit the first and the last instances of double quotes in your string. See example in Add a multivalue field

labelFriendly name of the option.
defaultA boolean value indicating whether the filter option should be selected by default.

CustomFilterItemStructure

customfilteritemstructure page anchor

To add a custom field and label to a filter, you'll need an object with a select field or an input field passed to the CustomFilterItemStructure.


_10
interface CustomFilterItemStructure {
_10
field: React.ReactElement;
_10
label: React.ReactElement;
_10
}

field is a React element that should render an input usable by the final customer. It inherits a few custom props from Flex.

FieldDescription
nameThe field name set in the FilterDefinition.
handleChangeA function that gets invoked on this custom field change event. It requires the new value of the filter to be passed as an argument, either as an array of strings or a string.
optionsThe same options passed in the FilterDefinition, if provided.
currentValueThe current value of the filter. It can either be an array of strings or a string, depending on what the props.handleChange function receives once invoked.

label is another React element that serves as the label of the filter. It should indicate the content of the filter when the accordion item is closed. It receives the following properties:

FieldDescription
currentValueThe current value of the filter.
activeOptionis the options array that is provided and returns the entire selected option. It will contain currentValue as value.

The filters array also accepts FiltersDefinitionFactories. A FilterDefinitionFactory is a simple function which returns a FilterDefinition. You can write a FilterDefinitionFactory that fetches data from the app state and dynamically renders values or options of a field.

Your factory must accept two arguments:

ArgumentDescription
appStateThe entire Flex Redux state. Use this to access information about activities, session, and more details about the current state of your Flex instance.
ownPropsThe props received by the TeamFiltersPanel.

Customizing your Filters

customizing-your-filters page anchor

The TeamFiltersPanel includes activitiesFilter by default. To add a new filter to the TeamsFiltersPanel, you can overwrite the defaultProps.filters property with a new array of filter definitions before rendering your Flex instance.

This array can contain both FilterDefinitions and FilterDefinition factories. In this example, we are readding the default activity filter as the first item of the array.


_10
Flex.TeamsView.defaultProps.filters = [
_10
Flex.TeamsView.activitiesFilter,
_10
yourFilterDefinitionHere,
_10
your2ndFilterDefinitionHere,
_10
your3rdFilterDefinitionHere,
_10
];

Add a custom input field

add-a-custom-input-field page anchor

Initially, the FilterDefinition has one predefined type, which will output checkboxes: MultiValue. With custom input fields, you can add a different type of input, like a custom text input field.

7. Image - Agent Filter.

An example of a custom input field, name, where you can type and filter by names based on the condition that you specify

The following file describes the HTML for your custom field, as well as the JavaScript associated with its behavior. In this sample, the filter functionality is extended in the extendFilters function

Add a custom filter

add-a-custom-filter page anchor

_49
import React from "react";
_49
import { TeamsView } from "@twilio/flex-ui";
_49
_49
// Define an Input component; returns a simple input HTML element with logic to handle changes when users enter input
_49
const Input = ({ handleChange, currentValue = "", fieldName }) => {
_49
const _handleChange = (e) => {
_49
e.preventDefault();
_49
handleChange(e.target.value);
_49
};return (
_49
<input
_49
className="CustomInput"
_49
type="text"
_49
onChange={_handleChange}
_49
value={currentValue}
_49
name={fieldName}
_49
/>
_49
)
_49
};
_49
_49
// Define the label that supervisors will see when using our custom filter
_49
const CustomLabel = ({ currentValue }) => (
_49
<>{currentValue && currentValue.length ? `Containing "${currentValue}"` : "Any"}</>
_49
);
_49
_49
// Define a new filter that uses the custom field
_49
const nameFilter = {
_49
id: "data.attributes.full_name",
_49
fieldName: "full_name",
_49
title: "Names",
_49
customStructure: {
_49
field: <Input />,
_49
label: <CustomLabel />,
_49
},
_49
condition: "CONTAINS"
_49
};
_49
_49
// Export a function to be invoked in plugin's main entry-point
_49
export const extendFilter = (manager) => {
_49
manager.updateConfig({
_49
componentProps: {
_49
TeamsView: {
_49
filters:[
_49
TeamsView.activitiesFilter,
_49
nameFilter,
_49
]
_49
}
_49
}
_49
})
_49
};

The following example will filter by agents located in any of the options specified in the value field:


_30
import React from "react";
_30
import { TeamsView } from "@twilio/flex-ui";
_30
import { FiltersListItemType } from "@twilio/flex-ui";
_30
_30
// Define a new filter that uses the custom field
_30
_30
const teamFilter = {
_30
fieldName: "team_location",
_30
title: 'Team',
_30
id: 'data.attributes.squad',
_30
type: FiltersListItemType.multiValue,
_30
options: [
_30
{ label: 'Canada', value: 'CAN-1", "CAN-2", "ARC'}
_30
],
_30
condition: 'IN',
_30
};
_30
_30
// Export a function to be invoked in plugin's main entry-point
_30
export const extendFilter = (manager) => {
_30
manager.updateConfig({
_30
componentProps: {
_30
TeamsView: {
_30
filters: [
_30
TeamsView.activitiesFilter,
_30
teamFilter,
_30
]
_30
}
_30
}
_30
})
_30
};

Use a filter definition factory

use-a-filter-definition-factory page anchor

You can use a filter definition factory to dynamically render the options of the predefined checkboxes fields. For example, you could render the activities that are currently available on in the Flex Redux store.

Create a Filter Definition Factory Function

create-a-filter-definition-factory-function page anchor

_34
import React from "react";
_34
_34
import { FiltersListItemType } from "@twilio/flex-ui";
_34
_34
const customActivityFilter = (appState, teamFiltersPanelProps) => {
_34
const activitiesArray = Array.from(appState.worker.activities.values());
_34
_34
const activities = (activitiesArray).map((activity) => ({
_34
value: activity.name,
_34
label: activity.name,
_34
default: !!activity.available,
_34
}));
_34
_34
return {
_34
id: "data.activity_name",
_34
fieldName: "custom_activity_name",
_34
type: FiltersListItemType.multiValue,
_34
title: "Activities",
_34
options: activities
_34
};
_34
};
_34
_34
// Export a function to be invoked in plugin's main entry-point
_34
export const extendFilter = (manager) => {
_34
manager.updateConfig({
_34
componentProps: {
_34
TeamsView: {
_34
filters: [
_34
customActivityFilter,
_34
]
_34
}
_34
}
_34
})
_34
};

Use a custom filter structure with a filter definition factory

use-a-custom-filter-structure-with-a-filter-definition-factory page anchor

You can use custom filter input components and filter definition factories together. The following code sample dynamically renders the options of a select field from the current Redux store.

Combine Filter Definition Factor and Custom Filters

combine-filter-definition-factor-and-custom-filters page anchor

_64
import React from "react";
_64
_64
// Create your custom field
_64
const CustomField = ({ handleChange, currentValue, fieldName, options }) => {
_64
const _handleChange = (e) => {
_64
e.preventDefault();
_64
handleChange(e.target.value);
_64
};
_64
_64
return (
_64
<select
_64
className="CustomInput"
_64
onChange={_handleChange}
_64
value={currentValue}
_64
name={fieldName}
_64
>
_64
<option value="" key="default">All activities</option>
_64
{options.map(opt => (
_64
<option value={opt.value} key={opt.value}>{opt.label}</option>
_64
))}
_64
</select>
_64
)
_64
};
_64
_64
// Define the label that will be displayed when filter is active
_64
const CustomLabel = ({ currentValue }) => (
_64
<>{currentValue || "All activities"}</>
_64
);
_64
_64
// Define the available properties upon which to filter based on application state
_64
const customActivityFilter = (appState, teamFiltersPanelProps) => {
_64
_64
const activitiesArray = Array.from(appState.worker.activities.values());
_64
_64
const activities = (activitiesArray).map((activity) => ({
_64
value: activity.name,
_64
label: activity.name,
_64
default: !!activity.available,
_64
}));
_64
_64
return {
_64
id: "data.activity_name",
_64
fieldName: "custom_activity_name",
_64
title: "Activities",
_64
customStructure: {
_64
label: <CustomLabel />,
_64
field: <CustomField />,
_64
},
_64
options: activities
_64
};
_64
};
_64
_64
// Add new filter to TeamFiltersPanel in the Flex UI
_64
export const extendFilter = (manager) => {
_64
manager.updateConfig({
_64
componentProps: {
_64
TeamsView: {
_64
filters: [
_64
customActivityFilter,
_64
]
_64
}
_64
}
_64
})
_64
};


Once you've configured your filter(s), you can enable them in Flex manager from within the base Plugin file. In this example, the extendFilters function is imported and passed to the Flex Manager.

Extend Filters with a Plugin

extend-filters-with-a-plugin page anchor

_20
import Flex from '@twilio/flex-ui';
_20
import { FlexPlugin } from 'flex-plugin';
_20
import { extendFilter } from "./CustomFilters";
_20
_20
const PLUGIN_NAME = 'SamplePlugin';
_20
_20
export default class SamplePlugin extends FlexPlugin {
_20
constructor() {
_20
super(PLUGIN_NAME);
_20
}
_20
_20
/**
_20
*
_20
* @param flex
_20
* @param {Manager} manager
_20
*/
_20
init(flex, manager) {
_20
extendFilter(manager);
_20
}
_20
}


The following code samples demonstrate writing and calling the same extendFilters functions, but in the context of self-hosted Flex.

Define a Custom Filter (Self-Hosted)

define-a-custom-filter-self-hosted page anchor

_46
import React from "react";
_46
import Flex from "@twilio/flex-ui";
_46
_46
// Define an Input component; returns a simple input HTML element with logic to handle changes when users enter input
_46
const Input = ({ handleChange, currentValue = "", fieldName }) => {
_46
const _handleChange = (e) => {
_46
e.preventDefault();
_46
handleChange(e.target.value);
_46
};
_46
_46
return (
_46
<input
_46
className="CustomInput"
_46
type="text"
_46
onChange={_handleChange}
_46
value={currentValue}
_46
name={fieldName}
_46
/>
_46
)
_46
};
_46
_46
// Define the label that supervisors will see when using our custom filter
_46
const CustomLabel = ({ currentValue }) => (
_46
<>{currentValue && currentValue.length ? `Containing "${currentValue}"` : "Any"}</>
_46
);
_46
_46
_46
// Define a new filter that uses the custom field
_46
const nameFilter = {
_46
id: "data.attributes.full_name",
_46
fieldName: "full_name",
_46
title: "Names",
_46
customStructure: {
_46
field: <Input />,
_46
label: <CustomLabel />,
_46
},
_46
condition: "CONTAINS"
_46
};
_46
_46
// Add the filter to the list of filters in the TeamFiltersPanel
_46
export const extendFilter = () => {
_46
Flex.TeamsView.defaultProps.filters = [
_46
Flex.TeamsView.activitiesFilter,
_46
nameFilter,
_46
];
_46
};

Create a Filter Definition Factory (Self-Hosted)

create-a-filter-definition-factory-self-hosted page anchor

_27
import React from "react";
_27
import Flex from "@twilio/flex-ui";
_27
_27
const customActivityFilter = (appState, teamFiltersPanelProps) => {
_27
const activitiesArray = Array.from(appState.worker.activities.values());
_27
_27
const activities = (activitiesArray).map((activity) => ({
_27
value: activity.name,
_27
label: activity.name,
_27
default: !!activity.available,
_27
}));
_27
_27
return {
_27
id: "data.activity_name",
_27
fieldName: "custom_activity_name",
_27
type: Flex.FiltersListItemType.multiValue,
_27
title: "Activities",
_27
options: activities
_27
};
_27
};
_27
_27
_27
export const extendFilter = () => {
_27
Flex.TeamsView.defaultProps.filters = [
_27
customActivityFilter,
_27
];
_27
};

Combine Filter Definition Factories and Custom Input (Self-Hosted)

combine-filter-definition-factories-and-custom-input-self-hosted page anchor

_59
import React from "react";
_59
import Flex from "@twilio/flex-ui";
_59
_59
// Create your custom field
_59
const CustomField = ({ handleChange, currentValue, fieldName, options }) => {
_59
const _handleChange = (e) => {
_59
e.preventDefault();
_59
handleChange(e.target.value);
_59
};
_59
_59
return (
_59
<select
_59
className="CustomInput"
_59
onChange={_handleChange}
_59
value={currentValue}
_59
name={fieldName}
_59
>
_59
<option value="" key="default">All activities</option>
_59
{options.map(opt => (
_59
<option value={opt.value} key={opt.value}>{opt.label}</option>
_59
))}
_59
</select>
_59
)
_59
};
_59
_59
// Define the label that will be displayed when filter is active
_59
const CustomLabel = ({ currentValue }) => (
_59
<>{currentValue || "All activities"}</>
_59
);
_59
_59
// Define the available properties upon which to filter based on application state
_59
const customActivityFilter = (appState, teamFiltersPanelProps) => {
_59
_59
const activitiesArray = Array.from(appState.worker.activities.values());
_59
_59
const activities = (activitiesArray).map((activity) => ({
_59
value: activity.name,
_59
label: activity.name,
_59
default: !!activity.available,
_59
}));
_59
_59
return {
_59
id: "data.activity_name",
_59
fieldName: "custom_activity_name",
_59
title: "Activities",
_59
customStructure: {
_59
label: <CustomLabel />,
_59
field: <CustomField />,
_59
},
_59
options: activities
_59
};
_59
};
_59
_59
// Add new filter to TeamFiltersPanel in the Flex UI
_59
export const extendFilter = () => {
_59
Flex.TeamsView.defaultProps.filters = [
_59
customActivityFilter,
_59
];
_59
};

Extend Filters in Self-Hosted Flex

extend-filters-in-self-hosted-flex page anchor

_25
import { extendFilter } from "./CustomFilters";
_25
_25
export function run(config) {
_25
const container = document.getElementById("container");
_25
_25
return Flex
_25
.progress("#container")
_25
.provideLoginInfo(config, "#container")
_25
.then(() => Flex.Manager.create(config))
_25
.then(manager => {
_25
_25
// Extending the filter functionality
_25
extendFilter();
_25
_25
ReactDOM.render(
_25
<Flex.ContextProvider manager={manager}>
_25
<Flex.RootContainer />
_25
</Flex.ContextProvider>,
_25
container
_25
);
_25
})
_25
.catch((e) => {
_25
console.log("Failed to run Flex", e);
_25
});
_25
}


(warning)

Warning

The hidden filter feature is only available in @twilio/flex-ui@1.21.0 and later.

You can programmatically apply a filter that is hidden from the user, i.e. the user cannot disable it. You could use this feature to restrict supervisors to seeing only their team members on the page. However, note that this is not a security feature. Supervisors still have access to all agent activity using the underlying APIs.

In the following example, we use live query to set up Team View to only show agents with a specific team_name attribute (you can set user attributes via your SSO provider):


_10
Flex.TeamsView.defaultProps.hiddenFilter = 'data.attributes.team_name CONTAINS "sales"'


Rate this page: