--- title: "クライアントの設定" url: https://docs.catalyst.zoho.com/ja/tutorials/dialer-app/nodejs/configure-client/ description: "Catalyst Advanced I/O Functions、Catalyst CloudScale DataStoreおよびTwilioのVoice APIとの連携を使用して、営業チームと顧客間の発信通話接続を確立するダイヤラーアプリケーションを構築します。" last_updated: 2026-03-05T06:13:24Z service: All Services type: tutorial related_links: - name: "クライアントディレクトリ構造" url: /ja/cli/v1/project-directory-structure/introduction - name: "Webクライアントホスティング" url: /ja/cloud-scale/help/web-client-hosting/introduction --- # クライアントの設定 次に、Clientコンポーネントを設定しましょう。 [Clientディレクトリ](https://docs.catalyst.zoho.com/ja/cli/v1/project-directory-structure/client-directory/)には、以下が含まれています: * `index.html` フロントエンドアプリケーションのHTMLコードを含むファイル。 * `main.css` フロントエンドアプリケーションのCSSコードを含むファイル。 * `main.js` JavaScriptコードを含むファイル。 * `client-package.json` 設定ファイル。 `index.html`、`main.css`、および`main.js`のコーディングを行います。 > **注意 : ** このセクションで示されたコードを十分に理解できるよう確認してください。 以下のコードスニペットをコピーして、IDEを使用して`client`ディレクトリにある`index.html`、`main.css`、および`main.js`ファイルにそれぞれ貼り付け、ファイルを保存してください。 **index.html** ```xml <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Catalyst Dialer App</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <script src="main.js"></script> <script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"> </script> <script type="text/javascript" src="//media.twiliocdn.com/sdk/js/client/v1.3/twilio.min.js"> </script> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/css/mdb.min.css" rel="stylesheet"> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"> </script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"> </script> <script src="main.js"></script> <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> </head> <body onload="logButton()"> <center> <h1 class="display-4">Catalyst Dialer App ☏</h1><br><br> </center> <div style="width: 200px;float: right; margin-right: 50px;"><label for="switchbutton" id="btntext" class="btn btn-primary btn-block btn-outlined"></label> <button id="switchbutton" style="display: none;"></button> </div> <center> <div id="Dialer"> <br><br><br> <br><br> <div class="form-outline"> <label for="phoneNumber">Customer Phone Number </label> <input type="text" placeholder="(+91/Country Code)<112233445566>" name="phoneNumber" size="35" id="phoneNumber"> <br><br><br> <label for="salesNumber">Your Sales Phone Number </label> <input type="text" placeholder="(+91/Country Code)<8899773366>" name="salesNumber" size="35" id="salesNumber"> <br> </div> <br><br> <button type="submit" id='call-customer-button' class="btn btn-success" onclick="getFormDetails();return false;">Initiate Call</button> <br><br> <h2> <p class="info" id='call-status'></p> </h2> </div> </center> <div id="CallLogs" style="display: none;"> <h1 class="display-6">Call Logs : </h1><br><br> <p id="featData"></p> <div id="loader" style="display: none;"> <div class="spinner-border" role="status"> <span class="sr-only">Loading...</span> </div> </div> </div> </body> </html> ``` **main.css** ```css body { padding: 30px; } #loader { width: 100px; height: 100px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; } #dataTable { font-family: Arial, Helvetica, sans-serif; border-collapse: collapse; width: 100%; } #dataTable td, #dataTable th { border: 1px solid #ddd; padding: 8px; } #dataTable tr:nth-child(even) { background-color: #f2f2f2; } #dataTable tr:hover { background-color: #ddd; } #dataTable th { padding-top: 12px; padding-bottom: 12px; text-align: left; background-color: rgb(76, 175, 170); color: white; } ``` **main.js** ```javascript //クライアントから電話番号を取得し、バリデーションして発信通話を行う function getFormDetails() { let data = { phoneNumber: $('#phoneNumber').val(), salesNumber: $('#salesNumber').val() }; if (!validateData(data)) { return false; } $.ajax({ url: "/server/dialer/makeCall", method: "post", dataType: 'json', data: { phoneNumber: data.phoneNumber, salesNumber: data.salesNumber } }).done(function (data) { alert("Call Initiated. You can check the details in Call Logs once the Call is completed"); console.log(data); }).fail(function (error) { alert(JSON.stringify(error)); }); } //通話ログのWebページを描画する function logButton() { document.getElementById("btntext").innerHTML = "View Call Logs"; document.getElementById('switchbutton').setAttribute('onclick', 'showCallLogs()'); } //アプリケーションで通話ログタブを表示する function showCallLogs() { document.getElementById("btntext").innerHTML = "View Dialer"; $("#Dialer").hide(); $("#CallLogs").show(); document.getElementById('switchbutton').setAttribute('onclick', 'showDialer()'); loadLog(); } //アプリケーションでダイヤラータブを表示する function showDialer() { document.getElementById("btntext").innerHTML = "View Call Logs"; $("#Dialer").show(); $("#CallLogs").hide(); document.getElementById('switchbutton').setAttribute('onclick', 'showCallLogs()'); } //ユーザーが入力した営業担当者の連絡先番号と顧客の携帯番号をバリデーションする function validateData(data) { var regex = "[+][0-9]+$"; if (data.phoneNumber.length === 0) { alert('Customer Phone number cannot be empty'); return false; } if (!data.phoneNumber.startsWith('+')) { alert('Customer Phone number must start with country code'); return false; } if (data.salesNumber.length === 0) { alert('Sales Phone number cannot be empty'); return false; } if (!data.salesNumber.startsWith('+')) { alert('Sales Phone number must start with country code'); return false; } if (!data.phoneNumber.match(regex)) { alert('Enter a valid customer number'); return false; } if (!data.salesNumber.match(regex)) { alert('Enter a valid sales number'); return false; } return true; } //クライアント側でテーブルデータを描画する function renderTable(respData) { console.log("respData"); console.log(respData); debugger; var col = []; for (var i = 0; i < respData.length; i++) { for (var key in respData[i]) { if (col.indexOf(key) === -1) { col.push(key); } } } var table = document.createElement("table"); table.classList.add("ca-table-view"); table.setAttribute('id', 'dataTable'); var tr = table.insertRow(-1); for (var i = 0; i < col.length; i++) { var th = document.createElement("th"); th.innerHTML = col[i]; tr.appendChild(th); } for (var i = 0; i < respData.length; i++) { tr = table.insertRow(-1); for (var j = 0; j < col.length; j++) { var tabCell = tr.insertCell(-1); tabCell.innerHTML = respData[i][col[j]]; } } debugger; var divContainer = document.getElementById("featData"); divContainer.innerHTML = ""; divContainer.appendChild(table); } //通話ログデータを適切なカラムに格納する function getRequiredData(data) { var i; var resp = []; for (i = 0; i < data.length; i++) { var gulp = { "From Number": data[i].fromNumber, "To Number": data[i].toNumber, "Call Duration": data[i].callDuration, "Call Status": data[i].callStatus, "Time Of Call": data[i].timeOfCall, "Called Country": data[i].calledCountry } resp.push(gulp); } console.log(resp); return resp; } // /getLogsルートを呼び出して通話ログを取得し、クライアントにログデータを描画する function loadLog() { $("#loader").show(); $.ajax({ url: "/server/dialer/getLogs", method: "get" }).done(function (data) { $("#loader").hide(); var arr = []; for (i = 0; i < data.length; i++) { arr.push(data[i].CallLog); } var data = getRequiredData(arr); renderTable(data); }).fail(function (error) { alert(JSON.stringify(error)); }); } ``` Clientディレクトリの設定が完了しました。アプリケーションのAdvanced I/O Functionの動作を簡単に確認しましょう: 1. **`validateData()` - この関数で、営業チームの連絡先番号と顧客の番号の両方がバリデーションされます。入力された電話番号が空文字列でないこと、数字のみで構成され「+」記号が先頭に付いた標準的な電話番号形式に従っているかを確認するロジックが定義されています。 2. `getFormdetails()` - この関数は、ユーザーが入力した顧客と営業担当者の入力電話番号の詳細を取得します。電話番号は`validateData()`関数を呼び出してバリデーションされます。両方の電話番号のバリデーションが成功すると、`/makeCall`ルートへのajax呼び出しが行われます。営業チームの連絡先番号から顧客の携帯番号への発信通話を開始し、通話が開始されるとクライアントにレスポンスを返します。 3. `getRequiredData()` - この関数は、`/getLogs`ルートでDataStoreにクエリを実行して取得した通話データに対して、通話ログのカラムを設定するために使用されます。 4. `renderTable()` - この関数は、`getRequiredData()`関数からデータを取得し、通話ログを表示するためにクライアントに描画します。 5. `showDialer()`** - この関数は、**'View Dialer'**ボタンのクリック時に実行されます。 6. **`showCallLogs()`** - この関数は、**'View Call Logs'**ボタンのクリック時に実行され、**`loadLog()`関数をトリガーします。 7. `loadLog()` - この関数は、Advanced I/O Functionで定義された`/getLogs`ルートへのajax呼び出しを行い、通話ログの詳細を取得してクライアントに描画します。 Advanced I/O Functionは、さまざまなアクションを実行する以下のAPIを定義しています: 1. `/makeCall` `getFormDetails()`関数から営業チームの連絡先番号と顧客の電話番号データを取得します。DataStoreの`CallLog()`テーブルに電話番号の詳細を挿入します。TwilioのVoice APIを呼び出して発信通話が開始され、APIリクエストの一部として`/outbound`ルートで定義されたTwiML命令も送信されます。 2. `/outbound/:salesNumber`** 通話が初期化されたときに実行されるTwilioに送信されるTwiML命令を定義します。このダイヤラーアプリケーションでは、Twilioの**Dial()**動詞を使用してTwilioの電話番号から営業番号へ通話をルーティングしています。また、**Say()**動詞を使用して、営業担当者が顧客からの応答を待っている間に提示するメッセージを指定しています。 3. **`/statusCheck` 通話が完了すると、このルートは通話時間、通話ステータス、通話先の国、タイムスタンプなどの関連する通話情報をCallLogsテーブルの該当カラムに送信します。 4. `/getLogs`** ZCQLクエリを実行してCallLogsテーブルから通話データを取得します。クエリ結果には、営業チームの連絡先番号、顧客の携帯番号、通話時間、通話のタイムスタンプ、通話ステータス、および通話元の国が返されます。