2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
はじめに
みなさん、こんにちは。
KDDIウェブコミュニケーションズのTwilioエバンジェリストの高橋です。
Twilio Flex Advent Calendar 2021の17日目の記事となります。
前回の記事では、Flexプラグインを使って着信音を鳴らす方法を紹介しました。着信音を鳴らすにはとくにUIに関するカスタマイズは不要でしたが、今回はいよいよUIをカスタマイズしていきましょう。
シナリオ
今回のカスタマイズの前提となるシナリオは以下のとおりです。
- 顧客DBには、顧客の電話番号や名前、住所が含まれています。
- 着信時に顧客情報を電話番号で検索します。
- 顧客が存在する場合のみ、以下の処理を行います。
- 着信者の名前を表示する。
- 顧客の住所を地図にプロットして表示する。
顧客DBとしては、こちらの記事で使用したGoogleSpreadsheetを流用し、住所情報を追加します。項目名は「住所」にしておいてください。
地図情報と、住所情報を緯度経度に変換する(ジオコーディング)には、Google MapsAPIとGeoCodingAPIを利用します。GeoCodingAPIについては有料のAPIとなりますが、月$200の無料枠があります。Google Mapsの料金についてはこちらを参照してください。
なおGoogle GeoCoding APIは規約上、GoogleMapと一緒に利用しなくてはいけないため、ジオコーディングはFlexプラグイン内で行うこととし、Studioフローでは住所情報をTaskのAttributesに追加するのみとします。
Flex UIコンポーネント
まずは地図情報をFlexのどこに表示するかを設計する必要があります。
Flex UIコンポーネント(エージェント画面)は以下のように定義されています。
※ https://www.twilio.com/docs/flex/developer/ui/components より引用
住所情報は、Taskに紐付いて通知されるため、⑪のTaskCanvasTabsに「位置情報」というタブを作って、そこに表示させるのが良さそうです。
タブの生成方法は以下の通りです。
flex.TaskCanvasTabs.Content.add(
<Tab label="位置情報" key="geolocation-tab">
<GeoLocation key="geolocation-component" />
</Tab>
);
このコードを、プラグインのinit()
の中に記載すればOKです。
なお、タブのコンテンツとなるGeoLocationは後ほどReactコンポーネントとして作成する必要があります。
ハンズオン
では早速プラグインを作成していきましょう。
プラグインの新規作成
CLIを使って、Flexプラグインプロジェクトの作成していきます。
どこか作業フォルダに移動して、以下のコマンドを入力します。
% twilio flex:plugins:create plugin-geolocation --install
・・・
% cd plugin-geolocation
GoogleのAPIキーを取得する
事前にGCP(Google Cloud Platform)のアカウントを取得しているものとします。
- Google Cloud Platformにログインします。
- APIとサービスの中のライブラリを選択します。
- 「Maps」でサービスを検索します。
- 「Maps JavaScript API」を選択します。
- 有効にするを押します。
Google Maps Platformの画面に遷移します。
- 認証情報を選択します。
- 画面上部にある認証情報を作成を押します。
- プルダウンメニューからAPIキーを選択します。
- APIキーが生成されるので、内容をメモ帳などにコピーしておきます。※必要に応じてキーの制限をかけておきましょう。
では次に、Geocoding APIを有効にします。
環境変数として登録
- Flexプラグインのプロジェクトフォルダの直下に
.env
という名前のファイルを作成します。 - 先程控えておいたAPIキーを
FLEX_APP_GOOGLE_API_KEY=XXXXXXXXXXXXXXXXXXXXX
と登録しておきます。
なお、Flexプラグイン内で環境変数にアクセスするためには、以下の手順を行っておく必要があります。
Flexプラグイン Tips(環境変数の利用)
Google Maps APIのライブラリをインストール
今回はReact用の高機能なライブラリである、@react-google-maps/apiを利用したいと思います。
ただし、このライブラリはReact16.8以上を必要とするため、FlexのReactバージョン(React16.5.2)では動作しません。そこでFlex側もReact16.13.1に上げておきましょう。
以下のコマンドを使って、それぞれをインストールします。
% npm i -S react@16.13.1 react-dom@16.13.1
% npm i -S @react-google-maps/api
package.json
は以下のようになります。
{
"name": "plugin-geolocation",
"version": "0.0.0",
"private": true,
"scripts": {
"postinstall": "flex-plugin pre-script-check"
},
"dependencies": {
"@react-google-maps/api": "^2.7.0",
"flex-plugin-scripts": "4.2.2",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"@twilio/flex-ui": "^1",
"dotenv-webpack": "^7.0.3",
"react-test-renderer": "16.5.2"
}
}
地図を表示するコンポーネントの作成
-
エディタを開き、
src/components
フォルダの配下に、GeoLocation
フォルダを新規作成します。 -
GeoLocation.jsに以下のコードを貼り付けます。
import React, { useCallback, useRef, useState } from 'react';
import { withTaskContext } from '@twilio/flex-ui';
import { GoogleMap, LoadScript, Marker } from "@react-google-maps/api";
const libraries = ["places"];
const mapContainerStyle = {
height: "60vh",
width: "100%",
}; // 地図の大きさ
const options = {
disableDefaultUI: true, // デフォルトUI(衛星写真オプションなど)をキャンセルします。
zoomControl: true,
};
const GeoLocation = (props) => {
if (!props.task) return null;
const [center, setCenter] = useState({ lat: 35.6802117, lng: 139.7576692 });
// 住所をtask.attributesから取得する
const { address = null } = props.task.attributes;
if (!address) return (<div>住所情報なし</div>);
const mapRef = useRef();
const onMapLoad = useCallback((map) => {
mapRef.current = map;
geoCode();
}, []);
// 住所から位置情報を取得
const geoCode = () => {
const geoCoder = new window.google.maps.Geocoder();
geoCoder.geocode({
address,
region: 'jp',
}, (results, status) => {
setCenter({
lat: results[0].geometry.location.lat(),
lng: results[0].geometry.location.lng(),
});
});
};
return (
<LoadScript googleMapsApiKey={process.env.FLEX_APP_GOOGLE_API_KEY}>
<GoogleMap
key="GeoLocation-map"
id="map"
mapContainerStyle={mapContainerStyle}
zoom={17}
center={center}
options={options}
onLoad={onMapLoad}
>
<Marker position={center} />
</GoogleMap>
</LoadScript>
)
};
export default withTaskContext(GeoLocation);
コードの解説
Flexプラグインのコンポーネント内から、TaskのAttributesを参照するためには、コンポーネントに対して@twilio/flex-ui
のwithTaskContext
をラップしてあげる必要があります。
コードの一番下に、
export default withTaskContext(GeoLocation);
と書かれている部分がそれです。
このようにすることで、コンポーネントのプロパティにtask
というオブジェクトが入ってきます。
コードの後半に地図を表示させる部分があります。
return (
<LoadScript googleMapsApiKey={process.env.FLEX_APP_GOOGLE_API_KEY}>
<GoogleMap
key="GeoLocation-map"
id="map"
mapContainerStyle={mapContainerStyle}
zoom={17}
center={center}
options={options}
onLoad={onMapLoad}
>
<Marker position={center} />
</GoogleMap>
</LoadScript>
)
まず、<LoadScript>
タグを使ってGoogleMapsAPIの認証を行うとともに、windowオブジェクト内にgoogleオブジェクトが生成されます。このgoogleオブジェクトを使ってジオコーディングを行います。
const geoCoder = new window.google.maps.Geocoder();
このようにしてジオコーダーのインスタンスを生成します。
実際のジオコーディングは、<GoogleMap>
がロードされたときのイベント内で実行するようにしています。
なお、ジオコーディングの公式ドキュメントはこちらにあります。
GeoLocationコンポーネント呼び出す
つぎに、src/GeolocationPlugin.js
をエディタで開きます。
import React from 'react';
import { VERSION, Tab } from '@twilio/flex-ui';
import { FlexPlugin } from 'flex-plugin';
import GeoLocation from './components/GeoLocation/GeoLocation';
import reducers, { namespace } from './states';
const PLUGIN_NAME = 'GeolocationPlugin';
export default class GeolocationPlugin extends FlexPlugin {
constructor() {
super(PLUGIN_NAME);
}
/**
* This code is run when your plugin is being started
* Use this to modify any UI components or attach to the actions framework
*
* @param flex { typeof import('@twilio/flex-ui') }
* @param manager { import('@twilio/flex-ui').Manager }
*/
async init(flex, manager) {
this.registerReducers(manager);
flex.TaskCanvasTabs.Content.add(
<Tab label='Location' key='GeoLocation-tab'>
<GeoLocation key='GeoLocation-component' />
</Tab>,
);
}
/**
* Registers the plugin reducers
*
* @param manager { Flex.Manager }
*/
registerReducers(manager) {
if (!manager.store.addReducer) {
// eslint-disable-next-line
console.error(
`You need FlexUI > 1.9.0 to use built-in redux; you are currently on ${VERSION}`,
);
return;
}
manager.store.addReducer(namespace, reducers);
}
}
自動的に作成される余計なコードを削除しています。
また、5行目でGeoLocation
コンポーネントをインポートしています。
TaskCanvasにタブを追加するのは25行目からです。
flex.TaskCanvasTabs.Content.add(
<Tab label='Location' key='GeoLocation-tab'>
<GeoLocation key='GeoLocation-component' />
</Tab>,
);
Studioフローの修正
では最後に、住所をTaskのAttributesに入れる部分を作りましょう。
今回は次のようなフローを作成しました。
- Run Functionウィジェットを使って、GoogleSpreadsheetから住所を取得します。
- Functionは、こちらの記事で作成したものをそのまま利用しています。
TaskRouterへの引き渡しは以下のとおりです。
- WORKFLOWは、「Assign to Anyone」にしていますが、どのワークフローでも構いません。
-
ATTRIBUTESの中で、
address
パラメータにFunctionで取得した住所(widgets.getCustomer.parsed['住所']
)を入れています。
電話番号への紐付け
今作成したStudioフローを着信番号に割り当てれば、とりあえず設定はすべて終了です。
テスト
- GoogleSpreadsheetに住所を設定します。
- ローカルでプラグインを起動してみましょう。
% twilio flex:plugins:start
localhost:3000でFlexが起動しますので、設定した電話番号からFlexに架電をしてみましょう。
- 着信が来たら、着信タスクをクリックします(着信ボタンを押さなくても位置情報は確認できます)。
- 右側にタスクの詳細パネルが開きます。
- LOCATIONタブを選択すると図のように住所に合わせた地図が表示されます。
なお、このプラグインを本番環境にデプロイしようとするとReactのバージョンが合わないがどうするかと聞かれてしまいます。
そのため、サーバー側もReactのバージョンを上げておく必要があります。
- 管理者権限を持ったユーザがFlexにログインします。
- ダッシュボードパネルから、DEVELOPER SETUPのEDITボタンを押します。
- Reactのバージョンを選択できるので、最新の「16.13.1」にあげておきましょう。
まとめ
今回はかなり大掛かりなカスタマイズでしたが、うまくいきましたでしょうか。
Flex UIがカスタマイズできるようになると、かなりいろいろなことができるのがおわかりいただけたかと思います。
Flexの魅力はなんといってもカスタマイズ性の高さになります。ReactやUIコンポーネントなど細かいところは色々と勉強しなくてはいけないですが、その可能性は非常に大きいです。
★次の記事
Twilio Flexで営業時間判定
Twilio(トゥイリオ)とは
https://cloudapi.kddi-web.com
Twilioは音声通話、メッセージング(SMS/チャット)、ビデオなどの 様々なコミュニケーション手段をアプリケーションやビジネスへ容易に組み込むことのできるクラウドAPIサービスです。初期費用不要な従量課金制で、各種開発言語に対応しているため、多くのハッカソンイベントやスタートアップなどにも、ご利用いただいております。