Menu

Task Channel Definitions

All task channels that Flex UI handles are defined and registered with Task Channels API. Flex registers its default Task Channel definitions, but users and plugins can register their own. When task-based components are rendered, the first matching channel definition for a given task will be used. If there is more than one channel definition match for a task, then the most recently registered definition will be used. This allows you to register a more specific channel definition to override the behavior of a general one.

In a task channel definition you can specify:

  • callback to determine which tasks are applicable
  • strings (templates) to use in different Flex components based on task status
  • colors to be used in task list based on task status
  • icons to be shown in task list, tabs, and canvases based on task status
  • custom components to be added to task based components if channel is applicable
  • custom components to be replaced in task based components if channel is applicable

Steps to add a custom channel

To add a custom channel, you need to make changes in the following places:

  • Add a custom channel in TaskRouter
  • Trigger the custom channel to be routed to the agent
  • Define how the custom channel is rendered in the UI with Task Channel Definition API
const MyTaskChannel = Flex.DefaultTaskChannels.createDefaultTaskChannel("MyTaskChannel", (task) => {      
  return !!task.incomingTransferObject    
});    
Flex.TaskChannels.register(MyTaskChannel);

Example use cases

Adding a Tab to custom channel

const MyTaskChannel = Flex.DefaultTaskChannels.createDefaultTaskChannel("MyTaskChannel", (task) => { return !!task.incomingTransferObject });
MyTaskChannel.addedComponents = [
    {
        target: "TaskCanvasTabs",
        component: <MyTab
            key="myTab"
            icon={<img src="https://someimage.png" />}
            iconActive={<img src="someimage.png" />}
        />
    }
];
Flex.TaskChannels.register(MyTaskChannel); 

Replacing a component (e.g. TaskInfoPanel or MessagingCanvas)

const MyTaskChannel = Flex.DefaultTaskChannels.createDefaultTaskChannel("MyTaskChannel", (task) => { return !!task.incomingTransferObject }); 
const MyComponent = <div key="X">My Call Task Info Panel</div>; MyTaskChannel.replacedComponents = [
    { component: MyComponent, target: "TaskInfoPanel" }
]; 
Flex.TaskChannels.register(MyTaskChannel); 

Replace a component conditionally

const MyTaskChannel = Flex.DefaultTaskChannels.createDefaultTaskChannel("MyTaskChannel", (task) => {      
  return !!task.incomingTransferObject    
});    
const MyComponent = <div key="X">My Call Task Info Panel</div>;     MyTaskChannel.replacedComponents = [      
  { component: MyComponent, target: "TaskInfoPanel", options:          
    { if: (props) => props.task.status === "wrapping" }      
  }    
];
Flex.TaskChannels.register(MyTaskChannel);

Change strings based on task types (e.g., for end task button in the header):

myOwnChatChannel.templates.TaskCanvasHeader.endButton = {
    Assigned: "End Task",
    Reserved: undefined,
    Wrapping: "Wrap up",
    Completed: "Template1",
    Canceled: "Template2",
    Pending: "Template3"
};

Remove a component conditionally (e.g., remove action button from TaskListItem if task is in state "wrapping")

Flex.DefaultTaskChannels.Call.removedComponents = [{
    target: "TaskCanvasHeader",
    key: "actions",
    options: {
        if: (props) => props.task.status === "wrapping"
    }
}];

Complete TaskChannelDefinition Interface

export enum TaskChannelCapability {
    Info = "Info", // whether channel has info panel
    Call = "Call", // whether channel has call canvas capabilities
    Chat = "Chat", // whether channel has chat canvas capabilities
    Video = "Video", // whether channel has video calling capabilities
    Wrapup = "Wrapup" // whether channel needs to go to Wrapup state before can be completed
}

export type TaskCallbackType<T> = (
    task: ITask,
    componentType: React.ComponentType,
    ...args: Array<any>
) => T;
export type TaskStatusBasedTypeBase<T> = {
    Reserved?: T;
    Assigned?: T;
    Wrapping?: T;
    Completed?: T;
    Canceled?: T;
    Pending?: T;
};
export type TaskStatusBasedType<T = string> =
    | T
    | TaskCallbackType<T>
    | TaskStatusBasedTypeBase<T>;
export type TaskChannelApplicableCb = (task: ITask) => boolean;

export type TaskChannelComponentRegistration = {
    target: keyof FlexComponents;
    component: React.ReactChild;
    options?: ContentFragmentProps;
};

export type TaskChannelComponentRemoveRequest = {
    target: keyof FlexComponents;
    key: React.Key;
    options?: RemoveComponentCallOptions;
};

/**
 * Defines a task channel
 *
 * @export
 * @interface TaskChannelDefinition
 */
export interface TaskChannelDefinition {
    // for internal usage, will be set to an array of callbacks to invoke to unregister custom components
    name: string;

  /**
   * Used in TaskList, TaskCard, Canvases
   */
    colors?: {
        main?: TaskStatusBasedType<string>;
    };

  /**
   * Returns whether this task channel is applicable for a given task.
   * @param task task instance to evaluate the channel for
   */
    isApplicable: TaskChannelApplicableCb;

  /**
   * Icons to render to the task channel
   */
    icons?: {
    /**
     * List icon to be used in TaskList and TaskCardList
     */
        list?: TaskStatusBasedType<string | React.ReactNode>;
    /**
     * Icon to be used in Tab headers if tab is not selected
     */
        main?: TaskStatusBasedType<string | React.ReactNode>;
    /**
     * Icon to be used in Tab headers if tab is selected and in Task Canvases as the main icon
     */
        active?: TaskStatusBasedType<string | React.ReactNode>;
    };

  /**
   * Templates for components
   */
    templates?: {
        IncomingTaskCanvas?: {
            firstLine?: TaskStatusBasedType<string>;
            secondLine?: TaskStatusBasedType<string>;
        };
        CallCanvas?: {
            firstLine?: TaskStatusBasedType<string>;
            secondLine?: TaskStatusBasedType<string>;
        };
        TaskListItem?: {
            firstLine?: TaskStatusBasedType<string>;
            secondLine?: TaskStatusBasedType<string>;
            extraInfo?: TaskStatusBasedType<string>;
        };
        TaskCanvasHeader?: {
            title?: TaskStatusBasedType<string>;
            endButton?: TaskStatusBasedType<string>;
        };
        TaskCard?: {
            firstLine?: TaskStatusBasedType<string>;
            secondLine?: TaskStatusBasedType<string>;
        };
        TaskInfoPanel?: {
            content: TaskStatusBasedType<string>;
        };
        Supervisor?: {
            TaskCanvasHeader?: {
                title?: TaskStatusBasedType<string>;
                endButton?: TaskStatusBasedType<string>;
            };
            TaskInfoPanel?: {
                content: TaskStatusBasedType<string>;
            };
            TaskOverviewCanvas: {
                firstLine?: TaskStatusBasedType<string>;
                secondLine?: TaskStatusBasedType<string>;
            };
        };
    };

  /**
   * Set of capabilities, used to render Tabs
   */
    capabilities: Set<TaskChannelCapability>;

  /**
   * Character limit of a message.
   */
    charLimit: number;

  /**
   * Custom components to be added for this task channel. E.g. custom Tabs.
   * Supports only components that have a static "Content" property
   */
    addedComponents?: Array<TaskChannelComponentRegistration>;

  /**
   * Custom components to be replaced for this task channel.
   * Supports only components that have a static "Content" property
   */
    replacedComponents?: Array<TaskChannelComponentRegistration>;

  /**
   * Custom components to be removed for this task channel
   */
    removedComponents?: Array<TaskChannelComponentRemoveRequest>;

  /**
   * Custom component props to be passed in if we have a matching task channel.
   * Works only for task based components.
   */
    // componentProps?: {
    //     [K in keyof FlexComponents]?: any;
    // };
} 

Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.

Thank you for your feedback!

Please select the reason(s) for your feedback. The additional information you provide helps us improve our documentation:

Sending your feedback...
🎉 Thank you for your feedback!
Something went wrong. Please try again.

Thanks for your feedback!

thanks-feedback-gif