お知らせ:

当社は、お客様により充実したサポート情報を迅速に提供するため、本ページのコンテンツは機械翻訳を用いて日本語に翻訳しています。正確かつ最新のサポート情報をご覧いただくには、本内容の英語版を参照してください。

クライアントディレクトリの設定

次に、クライアントコンポーネントを設定しましょう。クライアントディレクトリには以下が含まれています:

  • フロントエンドアプリケーションのHTMLコードを含むindex.htmlファイル
  • CSSコードを含むmain.cssファイル
  • JavaScriptコードを含むmain.jsファイル
  • client-package.json設定ファイル

index.htmlmain.jsmain.cssにコードを記述します。また、このディレクトリに新しいファイルlogin.htmlを作成し、コードを追加します。

Note: このセクションのコードを十分に理解してください。コードについてはこのセクションの最後で説明します。

以下のコードをコピーして、IDEを使用してプロジェクトのclient/ディレクトリにあるそれぞれのファイルに貼り付けて保存してください。

index.html
copy
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CRM Lead Manager</title>
<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>
<script src="https://static.zohocdn.com/catalyst/sdk/js/2.0.0/catalystWebSDK.js"></script>
<script src="/__catalyst/sdk/init.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<style>
#connect {
height: 260px;
width: 500px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
</style>
</head>
<body onload="getUserDetails()">
<br>
<center>
<h1>CRM Lead Manager</h1><br>
</center>
<div id="connect">
<center>
<p>Click here to connect to Zoho CRM</p>
<button onclick='navigate()'>
<img src="https://www.zohowebstatic.com/sites/default/files/styles/product-home-page/public/icon-crm_blue.png"
style="width: 180px;height: 130px;">
</button>
</center>
</div>
<div style="width: 200px;float: right; margin-right: 30px;"><label for="logoutbtn"
class="btn btn-success btn-block btn-outlined">Logout</label>
<button id="logoutbtn" onclick="logout()" style="display: none;"></button>
</div>
<div id="main">
<div class="container">
<ul class="nav nav-tabs nav-justified mb-3" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="check-tab" data-toggle="tab" href="#check" role="tab"
aria-controls="check" aria-selected="true">Add a Lead</a>
</li>
<li class="nav-item">
<a class="nav-link" id="report-tab" data-toggle="tab" href="#report" onclick="getLeads()" role="tab"
aria-controls="report" aria-selected="false">Manage Leads</a>
</li>
</ul><br>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="check" role="tabpanel" aria-labelledby="check-tab">
<div class="tab-pane fade show active" id="ex3-tabs-1" role="tabpanel" aria-labelledby="ex3-tab-1">
<div style="margin-left: 100px; margin-right:100px;">
<form id="leads">
<!-- 2 column grid layout with text inputs for the first and last names -->
<div class="row mb-4">
<div class="col">
<div class="form-outline">
<label class="form-label" for="form6Example1">First name</label>
<input type="text" id="firstName" class="form-control" />
</div>
</div>
<div class="col">
<div class="form-outline">
<label class="form-label" for="form6Example2">Last name</label>
<input type="text" id="lastName" class="form-control" required />
</div>
</div>
</div>
<!-- Text input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example3">Company name</label>
<input type="text" id="companyName" class="form-control" />
</div>
<!-- Email input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example5">Email</label>
<input type="email" id="email" class="form-control" />
</div>
<!-- Text input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example4">State</label>
<input type="text" id="state" class="form-control" />
</div>
<!-- Number input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example6">Phone</label>
<input type="number" id="phone" class="form-control" />
</div>
<!-- Number input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example6">Lead Source</label>
<input type="text" id="leadSource" class="form-control" />
</div>
<!-- Submit button -->
<center><button type="submit" onclick="createLead();return false;"
class="btn btn-primary btn-block mb-4" style="width: 100px;">Add Lead</button>
<div id="loader" style="display: none;">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</center>
</form>
</div>
</div>
</div>
<div class="tab-pane fade" id="report" role="tabpanel" aria-labelledby="report-tab">
<center>
<div id="loaders" style="display: none; padding-top: 200px;">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</center>
<p id="showData"></p>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="vertical-alignment-helper">
<div class="modal-dialog vertical-align-center">
<div class="modal-content">
<center>
<h4 class="modal-title" id="myModalLabel"></h4>
<div class="modal-body" id="message"></div>
<div class="modal-footer">
<button type="button" style="background-color: #007bff;color: white;"
class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</center>
</div>
</div>
</div>
</div>
<div class="modal fade" id="editForm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="vertical-alignment-helper">
<div class="modal-dialog vertical-align-center">
<div class="modal-content">
<div style="margin-left: 80px; margin-right:80px;">
<br>
<center>
<h2>Edit Lead</h2>
</center>
<br>
<form id="editLeads">
<!-- 2 column grid layout with text inputs for the first and last names -->
<div class="row mb-4">
<div class="col">
<div class="form-outline">
<label class="form-label" for="form6Example1">First name</label>
<input type="text" id="editfirstName" class="form-control" />
</div>
</div>
<div class="col">
<div class="form-outline">
<label class="form-label" for="form6Example2">Last name</label>
<input type="text" id="editlastName" class="form-control" required />
</div>
</div>
</div>
<!-- Text input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example3">Company name</label>
<input type="text" id="editcompanyName" class="form-control" />
</div>
<!-- Email input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example5">Email</label>
<input type="email" id="editemail" class="form-control" />
</div>
<!-- Text input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example4">State</label>
<input type="text" id="editstate" class="form-control" />
</div>
<!-- Number input -->
<div class="form-outline mb-4">
<label class="form-label" for="form6Example6">Phone</label>
<input type="number" id="editphone" class="form-control" />
</div>
<!-- Submit button -->
<center><button type="submit" id="editBtn" onclick="editLead();return false;"
class="btn btn-primary btn-block mb-4" style="width: 100px;">Edit</button>
<div id="loader" style="display: none;">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</center>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade right" id="ModalDanger" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-notify modal-danger modal-side modal-top-right" role="document">
<!--Content-->
<div class="modal-content">
<!--Header-->
<div class="modal-header">
<p class="heading">Lead Deletion</p>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true" class="white-text">×</span>
</button>
</div>
<!--Body-->
<div class="modal-body">
<div class="row">
<div class="col-9">
<p>Are you sure you want to delete the Lead?</p>
</div>
</div>
</div>
<!--Footer-->
<div class="modal-footer justify-content-center">
<a type="button" class="btn btn-danger" id="delete-btn" onclick="deleteLead()">Delete</a>
<a type="button" class="btn btn-outline-danger waves-effect" data-dismiss="modal">Cancel</a>
</div>
</div>
<!--/.Content-->
</div>
</div>
</div>
</body>
<script>
    //クライアントIDを追加する and Redirect URL here
    function navigate() {
       window.location.href = "https://accounts.zoho.com/oauth/v2/auth?scope=ZohoCRM.modules.ALL&client_id={{YOUR_CLIENT_ID}}&response_type=code&access_type=offline&redirect_uri="+location.protocol + '//' + location.host + "/server/crmcrud/generateToken";
    }
</script>
</html>

View more

Note: index.htmlをクライアントフォルダに追加した後、navigate()関数内の{{YOUR_CLIENT_ID}}を実際のZoho Client IDに置き換えてください。
main.js
copy
function createLead() {
    debugger;
    $("#loader").show();
    var firstName = $("#firstName").val();
    var lastName = $("#lastName").val();
    if (lastName == "") {
        alert("Kindly Enter the Last Name");
        $("#loader").hide();
        return;
    }
    var companyName = $("#companyName").val();
    var email = $("#email").val();
    var state = $("#state").val();
    var phone = $("#phone").val();
    var leadSource = $("#leadSource").val();
    $.ajax({
        url: "/server/crmcrud/crmData",
        type: "post",
        contentType: "application/json",
        data: JSON.stringify({
            "First_Name": firstName,
            "Last_Name": lastName,
            "Company": companyName,
            "Email": email,
            "State": state,
            "Phone": phone,
            "Lead_Source": leadSource,
        }),
        success: function (data) {
            debugger;
            $('#leads').trigger("reset");
            $("#myModalLabel").html("
Success"); $("#message").html("Lead Created Successfully"); $("#loader").hide(); $('#myModal').modal('show'); }, error: function (error) { $('#leads').trigger("reset"); $("#myModalLabel").html("
Failure"); $("#message").html("Please try again after Sometime"); $("#loader").hide(); $('#myModal').modal('show'); } }); } function logout() { var redirectURL = "http://localhost:3000/app/login.html"; //Add your app domain var auth = catalyst.auth; auth.signOut(redirectURL); } function getUserDetails() { $("#main").hide(); $("#connect").hide(); catalyst.auth.isUserAuthenticated().then(result => { $("#loader").show(); $.ajax({ url: "/server/crmcrud/getUserDetails", type: "get", success: function (data) { $("#loader").hide(); if (data.userId) { $("#main").show(); $("#connect").hide(); } else { $("#connect").show(); $("#main").hide(); } }, error: function (error) { $("#myModalLabel").html("
Failure"); $("#message").html("Please try again after Sometime"); $("#loader").hide(); $('#myModal').modal('show'); } }); }).catch(err => { document.body.innerHTML = 'You are not logged in. Please log in to continue. Redirecting you to the login page..'; setTimeout(function () { window.location.href = "login.html"; }, 3000); }); } function getLeads() { debugger; var tableContainer = document.getElementById("showData"); tableContainer.innerHTML = ""; $("#loaders").show(); $.ajax({ url: "/server/crmcrud/crmData", type: "get", success: function (data) { debugger; var reqData = getRequiredData(data.data); $("#loaders").hide(); renderTable(reqData); }, error: function (error) { $("#myModalLabel").html("
Failure"); $("#message").html("Please try again after Sometime"); $("#loader").hide(); $('#myModal').modal('show'); } }); } function showDeletePopup(leadID) { $('#ModalDanger').modal('show'); var deleteBtn = document.getElementById("delete-btn"); deleteBtn.value = leadID; } function deleteLead() { var leadID = document.getElementById('delete-btn').value; $.ajax({ url: "/server/crmcrud/crmData/" + leadID, type: "delete", success: function (data) { debugger; $('#ModalDanger').modal('toggle'); $("#myModalLabel").html("
Success"); $("#message").html("Lead Deleted Successfully"); $('#myModal').modal('show'); setTimeout(function () { location.reload(); }, 3000); }, error: function (error) { $("#myModalLabel").html("
Failure"); $("#message").html("Please try again after Sometime"); $("#loader").hide(); $('#myModal').modal('show'); } }); } function showEditPopup(leadID) { $.ajax({ url: "/server/crmcrud/crmData/" + leadID, type: "get", success: function (data) { debugger; var respData = data.data; $('#editfirstName').val(respData[0].First_Name); $('#editlastName').val(respData[0].Last_Name); $('#editcompanyName').val(respData[0].Company); $('#editemail').val(respData[0].Email); $('#editstate').val(respData[0].State); $('#editphone').val(respData[0].Phone); $('#editleadSource').val(respData[0].Lead_Source); $('#editBtn').val(respData[0].id); $('#editfirstName').html(respData[0].First_Name); $('#editlastName').html(respData[0].Last_Name); $('#editcompanyName').html(respData[0].Company); $('#editemail').html(respData[0].Email); $('#editstate').html(respData[0].State); $('#editphone').html(respData[0].Phone); $('#editleadSource').html(respData[0].Lead_Source); $('#editForm').modal('show'); }, error: function (error) { $("#myModalLabel").html("
Failure"); $("#message").html("Please try again after Sometime"); $("#loader").hide(); $('#myModal').modal('show'); } }); } function editLead() { var firstName = $("#editfirstName").val(); var lastName = $("#editlastName").val(); if (lastName == "") { alert("Kindly Enter the Last Name"); return; } var companyName = $("#editcompanyName").val(); var email = $("#editemail").val(); var state = $("#editstate").val(); var phone = $("#editphone").val(); var leadSource = $("#editleadSource").val(); var leadID = $("#editBtn").val(); $.ajax({ url: "/server/crmcrud/crmData/" + leadID, type: "put", contentType: "application/json", data: JSON.stringify({ "First_Name": firstName, "Last_Name": lastName, "Company": companyName, "Email": email, "State": state, "Phone": phone, "Lead_Source": leadSource }), success: function (data) { debugger; $('#editForm').modal('toggle'); $("#myModalLabel").html("
Success"); $("#message").html("Lead Edited Successfully"); $('#myModal').modal('show'); setTimeout(function () { location.reload(); }, 3000); }, error: function (error) { $('#leads').trigger("reset"); $("#myModalLabel").html("
Failure"); $("#message").html("Please try again after Sometime"); $("#loader").hide(); $('#myModal').modal('show'); } }); } function getRequiredData(data) { var i; var resp = []; for (i = 0; i < data.length; i++) { var gulp = { "First Name": data[i].First_Name, "Last Name": data[i].Last_Name, "Phone": data[i].Phone, "Email": data[i].Email, "Company": data[i].Company, "Edit": '<center><a href="javascript:showEditPopup(\'' + data[i].id + '\')">✎︎</a></center>', "Delete": '<center><a href="javascript:showDeletePopup(\'' + data[i].id + '\')">🗑︎</a></center>' } resp.push(gulp); } console.log(resp); return resp; } function renderTable(respData) { 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.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]]; } } var divContainer = document.getElementById("showData"); divContainer.innerHTML = ""; divContainer.appendChild(table); }

View more

main.css
copy
#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: #007bff; color: white; }

.vertical-alignment-helper { display: table; height: 100%; width: 100%; pointer-events: none; }

.vertical-align-center { display: table-cell; vertical-align: middle; pointer-events: none; }

.modal-content { width: inherit; max-width: inherit; height: inherit; margin: 0 auto; pointer-events: all; }

View more

login.html
copy
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>CRM Lead Manager</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Bootstrap -->
  <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">
  <!-- Catalyst SDK -->
  <script src="https://static.zohocdn.com/catalyst/sdk/js/4.6.1/catalystWebSDK.js"></script>
  <script src="/__catalyst/sdk/init.js"></script>
  <style>
    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden; /* No page scroll */
      background-color: #f8f9fa;
      font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    }
    body {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }
    h1 {
      margin-bottom: 30px;
      color: #333;
    }
    /* Bigger height to avoid internal iframe scroll */
    #login {
      width: 90%;
      max-width: 500px;
      height: 500px; /* increased from 260px */
      overflow: hidden; /* hides any internal scrollbars */
      border-radius: 8px;
      background: #fff;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
      padding: 20px;
    }
  </style>
</head>
<body>
  <h1>CRM Lead Manager</h1>
  <div id="login"></div>
  <script>
    // Catalystログインウィジェットの初期化
    catalyst.auth.signIn("login");
  </script>
  <!-- Optional JS dependencies -->
  <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>
</body>
</html>

View more

クライアントディレクトリの設定が完了しました。

関数とクライアントコンポーネントの動作について簡単に確認しましょう:

  • クライアントコンポーネントのlogin.htmlファイルは、Catalyst Authenticationのログインを有効にします。これはZohoサインイン機能ではなく、Catalystのログインのみを処理します。

  • index.htmlはクライアントのフロントエンドのコードを含んでいます。Client IDやスコープなどの必要な認可情報を渡してCRMアカウントへの接続を可能にする関数navigate()を定義しています。

  • Advanced I/O関数は、さまざまなアクションを実行する以下のAPIを定義しています:

    • /generateToken: getRefreshToken()関数を呼び出してリフレッシュトークンを取得し、現在のユーザーのuserIDとともにData Storeの_Token_テーブルに挿入します。その後、クライアントのインデックスページにリダイレクトします。

    • /getUserDetails: getUserDetails()関数を呼び出してユーザー詳細を取得します。テーブルにレコードがない場合、userIDのみを含むJSONレスポンスが送信されます。テーブルにレコードが存在する場合、userIDとともに送信されます。

    • /crmData: このルートはリードモジュール内のすべてのリードのパスを定義します。Node関数はこのルートを使用して、HTTP GETおよびPOST操作を実行し、すべてのリードの取得または新しいリードの作成をそれぞれ行います。

    • /crmData/:id: このルートはリードモジュール内の特定のリードのパスを定義します。idはCRM内のリードの一意のIDを表します。関数はこのルートを使用して、HTTP PUTおよびDELETE操作を実行し、リードの編集または削除をそれぞれ行います。

    • Advanced I/O関数には、APIから呼び出される以下の関数が含まれています:

    • getRefreshToken(): Client ID、Client Secret、リダイレクトURIおよびその他の必要な値をクエリ文字列パラメータとして渡してリフレッシュトークンを取得します。

    • getAccessToken(): ZCQLを使用してTokenテーブルからクエリしたリフレッシュトークンおよびその他の必要なパラメータを渡してアクセストークンを取得します。アクセストークンは、リードの追加や編集など、CRMモジュールで操作を実行する必要があるたびに取得されます。

    • getResponse(): 取得したアクセストークンを渡して、CRMモジュールで各アクションを実行するために必要な認可を取得します。この関数は、各/crmDataおよび/crmData/:id APIでリクエストを認可するために呼び出されます。

    • getUserDetails(): userIDを渡して、リフレッシュトークンを含む_Token_テーブルからレコードを取得します。

    • main.jsは、関数から取得したJSONレスポンスを解析し、index.htmlページにレンダリングするクライアントコンポーネントのJavaScript関数です。この関数は、クライアントアプリケーション内のすべてのUI要素のアクションを定義します。例えば、getLeads()は関数のレスポンスからすべてのリードを取得してクライアントにレンダリングし、showEditPopup()はリードの編集アクションを定義します。

最終更新日 2026-03-24 17:38:39 +0530 IST