Skip to content

Latest commit

 

History

History
409 lines (317 loc) · 12.3 KB

File metadata and controls

409 lines (317 loc) · 12.3 KB

七、构建实时呼叫跟踪仪表板

本章将向您展示如何实现实时呼叫跟踪仪表板。

我们将分两部分完成这项工作:第一部分是一个简单的 Node.js 文件,它接受来自 Twilio 的来电,然后将信息存储在 Flybase 应用中,第二部分是仪表板本身。

我们将显示两个统计数据,传入的 Twilio 电话号码和电话的始发城市。您可以稍后在此基础上进一步构建。

使用我们最初的仪表板,我们传递事件,实际上不存储任何信息。这一次,我们将存储信息,以便以后检索。

后端

让我们构建您的仪表板的后端部分。

首先,让我们设置我们的“package.json”文件:

{
  "name": "call-tracking",
  "version": "1.0.0",
  "description": "Example app demonstrating how to do call tracking with Twilio and Flybase",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/flybaseio/call-tracking.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/flybaseio/call-tracking/issues"
  },
  "homepage": "https://github.com/flybaseio/call-tracking#readme",
  "dependencies": {
    "body-parser": "^1.15.2",
    "compression": "^1.6.2",
    "cors": "^2.8.1",
    "ejs": "^2.5.2",
    "express": "^4.14.0",
    "flybase": "^1.7.8",
    "method-override": "^2.3.6",
    "serve-static": "^1.11.1"
  }
}

现在,让我们设置“index.js”文件作为后端运行:

var http = require('http');
var express = require('express');
var bodyParser = require('body-parser');
var flybase = require('flybase');
var path = require('path');

var cors = require('cors');
var compression = require('compression');
var serveStatic = require('serve-static');

var app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({     extended: true     }));
app.use(express.static( path.join(__dirname, 'public')));

var port = process.env.PORT || 5000; // set our port

var flybaseRef = flybase.init('YOUR-FLYBASE-APP-NAME', "calltracking", 'YOUR-FLYBASE-API-KEY');

//     backend

app.post('/call', function(req, res) {
     flybaseRef.push({
          time: Date.now()/1000,
          number: req.body.To,
          city: req.body.FromCity
     }).then( function( rec ){
          res.type('text/xml');
          res.render('twiml', { message: 'Your call has been recorded!' })
     }, function(err){
          res.type('text/xml');
          console.log(error);
          res.render('twiml', { message: 'Sorry, an error happened.' });
     });
});

现在,让我们添加前端处理程序。这只是同一个“index.js”文件的一部分:

```javascript
// frontend

function setCustomCacheControl(res, path) {
     if (serveStatic.mime.lookup(path) === 'text/html') {
          // Custom Cache-Control for HTML files
          res.setHeader('Cache-Control', 'public, max-age=0')
     }
}

app.use(compression());

app.use(serveStatic(__dirname + '/dashboard', {
     maxAge: '1d',
     setHeaders: setCustomCacheControl,
     'index': ['index.html'],
     fallthrough: true
}));

var server = http.createServer(app);
server.listen(process.env.PORT || 3000, function() {
     console.log('Express server started.');
});
```js

我在这里使用了 serve-static 模块,因为如果我们希望的话,仪表板可以是独立的,所以它只是静态提供的标准 HTML 页面,所以我们会告诉我们的应用显示dashboard文件夹中的任何文件。

最后,我们需要创建一个名为views的文件夹,并添加一个名为twiml.ejs的小文件:

<Response>
     <Say><%= message %></Say>
</Response>

这用于返回我们对传入呼叫的 TwiML (Twilio 标记语言)响应。你可以进一步玩这个,让它做一些事情,如将呼叫连接到另一个号码等等,但对于这个应用,我们只需要记录和跟踪。

前端

我们希望这个仪表板能够在任何地方运行,所以我们只需包含dashboard文件夹,并设置我们的 Node 应用来静态地为其提供服务。你可以上传dashboard文件夹到任何你想上传的地方,让它运行并显示你的电话追踪数据。

创建一个名为dashboard的文件夹。现在,在dashboard文件夹中创建一个名为index.html的文件:

<!doctype html>
<html>
     <head>
          <title>Call Tracking On the Fly</title>
          <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha256-7s5uDGW3AHqw6xtJmNNtr+OBRJUlgkNJEo78P4b0yRw= sha512-nNo+yCHEyn0smMxSswnf/OnX6/KwJuZTlNZBjauKhTK0c+zT+q5JOCx0UFhXQ6rJR9jg6Es8gPuD2uZcYDLqSw==" crossorigin="anonymous">
          <link href="https://cdnjs.cloudflare.com/ajax/libs/epoch/0.5.2/epoch.min.css" rel="stylesheet" />
          <link href="dashboard.css" rel="stylesheet" />
     </head>
     <body>
          <div class="navbar-nav navbar-inverse navbar-fixed-top">
                    <div class="container">
                    <div class="navbar-header">
                         <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                              <span class="icon-bar"></span>
                              <span class="icon-bar"></span>
                              <span class="icon-bar"></span>
                         </button>
                         <a class="navbar-brand" href="index.html">
                              Call Tracking Dashboard
                         </a>
                    </div>
                         <div class="navbar-collapse collapse">
                              <ul class="nav navbar-nav">
                                   <li class="active">
                                        <!-- <a href="index.html">
                                             <i class="icon-home icon-white"></i> Home
                                        </a> -->
                                   </li>
                              </ul>
                         </div><!--/.nav-collapse -->
                    </div>
          </div>

          <div class="container">

               <div class="row">

                    <div class="col-sm-12 col-lg-12">
                         <article class="widget">
                              <div class="widget-inner">

                                   <header>
                                        <h1>Calls</h1>
                                   </header>

                                   <section class="widget-body">
                                        <div id="calls" class="epoch" style="height: 200px;"></div>
                                   </section>

                              </div><!-- .widget-inner -->

                         </article>
                    </div>

               </div>

               <div class="row">

                    <div class="col-sm-6 col-lg-6">
                         <article class="widget">
                              <div class="widget-inner">

                                   <header>
                                        <h1>Incoming Number</h1>
                                   </header>

                                   <section class="widget-body">
                                        <div id="numbers" class="epoch" style="height: 200px;"></div>
                                   </section>

                              </div><!-- .widget-inner -->

                         </article>
                    </div>

                    <div class="col-sm-6 col-lg-6">
                         <article class="widget">
                              <div class="widget-inner">

                                   <header>
                                        <h1>City</h1>
                                   </header>

                                   <section class="widget-body">
                                        <div id="cities" class="epoch" style="height: 200px;"></div>
                                   </section>

                              </div><!-- .widget-inner -->

                         </article>
                    </div>
               </div>

          </div>

     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.10/d3.min.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/epoch/0.5.2/epoch.min.js"></script>
     <script src="https://cdn.flybase.io/flybase.js"></script>
     <script src="dashboard.js"></script>
</body>
</html>

接下来,您将创建一个名为dashboard.js的文件:

$( function() {
     var calls = $('#calls').epoch( {
          type: 'time.area', axes: ['left', 'bottom', 'right'],
          data: [ { values: [ { time: Date.now()/1000, y: 0 } ] } ]
     } );
     var numbers = $( '#numbers' ).epoch( { type: 'bar' } );
     var cities = $( '#cities' ).epoch( { type: 'bar' } );
     var stats = {
          cities: {},
          numbers: {}
     };

     var dashboard = new Flybase("YOUR-FLYBASE-API-KEY", "calltracking", "stats");

     dashboard.once('value', function (data) {
          updateStats( data );
     });

     dashboard.on( 'added', function (data ){
          updateStats( data );
     });

     function updateStats( data ){
          //     process the new data...
          data.forEach( function( snapshot ){
               var row = snapshot.value();

               calls.push( [ { time: row.time, y: 1 } ] );

               var cityCount = stats.cities[ row.city ] || 0;
               stats.cities[ row.city ] = ++cityCount;

               var numberCount = stats.numbers[ row.number ] || 0;
               stats.numbers[ row.number ] = ++numberCount;
          });

          var citiesData = [];
          for( var city in stats.cities ) {
               citiesData.push( { x: city, y: stats.cities[ city ] } );
          }
          cities.update( [ { values: citiesData } ] );

          var numbersData = [];
          for( var number in stats.numbers ) {
               numbersData.push( { x: number, y: stats.numbers[ number ] } );
          }
          numbers.update( [ { values: numbersData } ] );

     }
});

这是我们仪表板的大脑;它处理所有的电话,并显示在仪表板上。

最后,我们来添加一些 CSS。

创建一个名为“dashboard.css”的文件,并添加以下内容:

body {
  font: 400 0.95em/1 "Proxima Nova", Helvetica,sans-serif;
  font-size: .875em;
  background-color: #f0f0f0;

  padding-top: 90px;
}

.widget {
  -webkit-box-shadow: #f0f0f0 0 0 8px;
  -moz-box-shadow: #f0f0f0 0 0 8px;
  box-shadow: #f0f0f0 0 0 8px;
  background-color: #f0f0f0;

  margin-bottom: 30px;
}

.widget h1 {
  font-size: 1.0em;
  margin: 0 0 .4em;
  font-weight: bold;
}

.widget .widget-inner>header, .widget .widget-inner>footer {
  font-size: 12px;
  text-shadow: 1px 1px #0e0e0e;
}

.widget .widget-inner>header {
  background-color: #272727;
  text-transform: uppercase;
  padding: 16px 12px 16px 26px;
  font-weight: 700;
}

.widget .widget-inner {
  border: solid 1px #e5e5e5;
  background-color: #fff;
}

.widget .widget-inner>header {
  background-color: #f5f5f5;
}

.widget .widget-inner>header h1 {
  color: #8b8b8b;
  text-shadow: 1px 1px #fff;
  margin-bottom: 0;
}

.widget .widget-body {
  color: #666;

  height: 225px
}

.widget .widget-body {
  padding: 16px;
  color: #d3d4d4;
  font-family: Helvetica, Arial, sans-serif;
  z-index: 1;
}

.widget .widget-inner>footer {
  color: #8b8b8b;
  background-color: #f5f5f5;
  text-shadow: 1px 1px #fff;
}

.dash-unit {
  margin-bottom: 30px;
  padding-bottom: 10px;
  border: 1px solid #e5e5e5;
  /*background-image: url('../img/sep-half.png');*/
  background-color: #f5f5f5;
  color: #8b8b8b;
  height: 290px;
  text-align: center;
}

.dash-unit dtitle {
  font-size: 11px;
  text-transform: uppercase;
  margin: 8px;
  padding: 0px;
  height: inherit;
}

.dash-unit hr {
  border: 0;
  border-top: 1px solid #151515;
  border-top-style: dashed;
  margin-top: 3px;
}

摘要

你可以在任何地方运行它。您只需将您想要追踪的 Twilio 电话号码指向您添加到该网站的 URL,并以/call作为终点。在 GitHub 可以看到完整的代码库: https://github.com/flybaseio/call-tracking