Tuesday, 24 March 2015

Changing the background color of table rows depending on cell values using JQuery/DataTables/Bootstrap

 Here the final table we would like to generate : different properties appear on that table like changing color row column depending on the value of the colums, applying color on columns values depending of the  inconsistency of the values (for instance) and adding a column with a dropdown menu for different actions:



As clicking on action, we can access different buttons triggering different actions on the row (within a dropdown menu ) 



The change of row color is based on conditions relative to the column values ; this changing will be done with the  "rowCallBack" function(row, data)  on Datatables options - cf. https://datatables.net/reference/option/rowCallback

If you want to specify conditions based on column values, you have to apply conditions based on  row["column value"] :(cf. Column option on Datatables) ; As with Bootstrap, the color of the row can be specify by applying value for the "class" attribute within the <td> tag , here we will be $(row).addClass jQuery function (cf. http://api.jquery.com/addclass/) to alter the coilor of the rows:

Here is the function that we have defined :
        "rowCallback": function( row, data ) {
              if (row["status_fraud"].substring(0,3)=="0" && row["Statut_Cmd"].substring(0,1)!=="0") {
                //$(row).css({"background-color":"#FFDCDC"});
                 $(row).addClass( 'danger' )
            }
              return row;
        },

You can also change the background cell (here below for the fifth column cell) only using this command :
$('td', row).eq(5).addClass('danger');


The dropdown menu action is based on Bootstrap  using various classes such as "btn-group", "dropdown-menu" etc... (cf. http://getbootstrap.com/components/#btn-dropdowns-split), This way we can re-define column value using "render" function ( data, type, row ) on columnDefs  "datatables" option.

"columnDefs":[ 
                {
                "render": function ( data, type, row ) {
                   var BtnReader='<a target="_blank" class="btn btn-success btn-sm"  role="button" href="view.php?id=' + data  + '"> Read' + "</a>" ;      
                    var BtnDelete = '<a  target="_blank" class="btn btn-danger btn-sm"  role="button" href="delete.php?id=' + data + '"> Delete ' + ' </a>';

                    var DropDownAction= '<div class="btn-group">'
                    +
                    '<button class="btn btn-warning btn-sm dropdown-toggle" data-toggle="dropdown" type="button" aria-expanded="false">'
                    +
                    '<i class="fa fa-gear"></i><span class="caret"></span>'
                    +
                    '</button><ul class="dropdown-menu" role="menu">';
                    DropDownAction += '<li>' + BtnReader+ '</li>';
                    DropDownAction += '<li>' + BtnDelete + '</li>';
                    DropDownAction +=' </ul></div>';

                    return DropDownAction;


                },
                "targets": [7]
            }
]

The code for adding action using buttons within table rows has been shown on a previous post as well as the way to show color labels depending on the row properties:

"columnDefs":[ 
              {
                "render": function ( data, type, row ) {
                    if (data === undefined || data === null)  '<span  class="label label-danger">' +  data + '</span>';
                    if (row === undefined || row === null)  '<span  class="label label-danger">' +  data + '</span>';
                    
                    if (row["PSN"].substring(0,3)=="0" && row["Statut_Cmd"].substring(0,1)!=="0")
                      return  '<span  class="label label-danger">' +  data + '</span>';
                    else return '<span  class="label label-success" >' + data + '</span>';
                    
                },
                "targets": [5]
               }
]



These are the HTML and JS files for this post :

HTML FILE:
[..]

  <div class="col-lg-6">
                    <a name="tb" >
                        <div class="panel panel-info">

                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-table fa-fw"></i> Paiements en retard</h3>

                                <div class="panel-body">
                                    <table  id="tb" class="table table-bordered table-hover table-striped">

                                        <thead>
                                            <th>PSN </th>
                                            <th>Date commande</th>
                                            <th>Date de dernière modification</th>
                                            <th>Status fraud</th>
                                            <th>Status Bank</th>
                                            <th>Status Cmd</th>
                                            <th>Order Origin ?</th>
                                            <th>Action</th>
                                        </thead>
                                        <tbody>
                                        </tbody>
                                    </table>
                                </div> <!-- /panel-body -->
                            </div> <!-- /panel-heading -->
                        </div> <!-- /panel-info -->        
                    </a>
                </div> <!-- /col-lg-6 -->

[..]


JS FILE :
var table_blocage_fraud_synchro =  $('#tb').dataTable( {
        "language": {
            "url": "http://localhost/boot/js/DataTables.French.json"
        },
        "ajax": {
            "url": "http://localhost/boot/payment.php?function=controle_paiement_retard&param=json",
            "dataSrc": ""
        },
        "columns": [        
            { "data": "PSN" }, //0
            { "data": "date_create" }, //1
            { "data": "date_mod" }, //2
            { "data": "status_fraud" }, //3
            { "data": "status_bank" }, //4
            { "data": "Statut_Cmd" },//5
            { "data": "Order_origin" },//6
           { "data": "PSN" }, //7
        ],
        "rowCallback": function( row, data ) {
            var obj = eval(data);
            //console.log(objdata);
              if ((obj["status_fraud"].substring(0,3)=="0" && obj["Statut_Cmd"].substring(0,1)!=="0")) {
                //$(row).css({"background-color":"#FFDCDC"});
                 $(row).addClass( 'danger' )
            }
              return row;
        },
        "columnDefs":[
              {
                "render": function ( data, type, row ) {
                    if (data === undefined || data === null)  '<span  class="label label-danger">' +  data + '</span>';
                    if (row === undefined || row === null)  '<span  class="label label-danger">' +  data + '</span>';
                    
                    if (row["PSN"].substring(0,3)=="0" && row["Statut_Cmd"].substring(0,1)!=="0")
                      return  '<span  class="label label-danger">' +  data + '</span>';
                    else return '<span  class="label label-success" >' + data + '</span>';
                    
                },
                "targets": [5]
               },
                {
                "render": function ( data, type, row ) {
                   var BtnReader='<a target="_blank" class="btn btn-success btn-sm"  role="button" href="view.php?id=' + data  + '"> Read' + "</a>" ;      
                    var BtnDelete = '<a  target="_blank" class="btn btn-danger btn-sm"  role="button" href="delete.php?id=' + data + '"> Delete ' + ' </a>';

                    var DropDownAction= '<div class="btn-group">'
                    +
                    '<button class="btn btn-warning btn-sm dropdown-toggle" data-toggle="dropdown" type="button" aria-expanded="false">'
                    +
                    '<i class="fa fa-gear"></i><span class="caret"></span>'
                    +
                    '</button><ul class="dropdown-menu" role="menu">';
                    DropDownAction += '<li>' + BtnReader+ '</li>';
                    DropDownAction += '<li>' + BtnDelete + '</li>';
                    DropDownAction +=' </ul></div>';

                    return DropDownAction;


                },
                "targets": [7]
            }
            ]
    } );      
 

Thursday, 19 March 2015

"Hello World" in Symfony 2.0

This tutorial is about Symfony 2.and is based on that of  Alexandre Bacco at http://uploads.siteduzero.com/pdf/517569-developpez-votre-site-web-avec-le-framework-symfony2.pdf .

The main difference with Symfony version 1 is about the architecture with the bundles (see http://michelsalib.com/2011/07/10/a-symfony1-4-to-symfony2-migration-why-you-should-learn-symfony2/)

In Symfony 2, at first, you will have to generate a bundle executingin MS DOS prompt (after adding the PHP folder in your PATH environment variable) the following command :

php app/console generate:bundle  (we need to be within your Symfony web root)

A namespace of the bundle is then required : give it the following a name with a"Bundle" suffix -for example : [yoursite]\BlogBundle for a Blog (if you wish to make different website)

For the bundle name, it will provide you a default name in brackets, if you agree, you just have to type ENTER

Idem for the target directory

For the configuration format, I personally prefer the YML format : write "yml" and type ENTER

To the question generate the whole directory structure, say "yes" and type ENTER

And type ENTER for the following question


The bundle is now generated.



Take now your favorite IDE and open your symfony project (personally, I used Sublime Text (see http://www.sublimetext.com/) ; as Symfony is MVC framework, we will define a route then  make a controller with a view :

1 - Go to src/[yoursite]/BlogBundle\ressources\config\routing.yml and add at the end of the file the following code to insert the route of your web site:

[yoursite]_blog_helloWorld:
    path:     /hello-world
    defaults: { _controller: [yoursite]BlogBundle:Blog:index}

Bundle called "BlogBundle", Controller being "Blog" and the action being "index"
2- Add the corresponding controller in a new file called :  src/[yoursite]/BlogBundle\ressources\Controller\BlogController.php with the following code :

<?php
namespace [yoursite]\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class BlogController extends Controller
{
public function indexAction()
{
// return new Response("Hello World !");
return $this->render('[yoursite]BlogBundle:Blog:index.html.twig');
}
}
?>
3- Add the associated view in a new file  src/[yoursite]/BlogBundle\ressources\views\Blog\index.html.twig

4- In this file add the following content :
<!DOCTYPE html>
<html>
   <head>
   <title>Hello!</title>
    </head>
    <body>
          <h1>Hello World !</h1>
    </body>
</html>

5- Go to the following URL : http://localhost/symfony/web/app_dev.php/hello-world ; then, you should get this kind of screen

Adding a parameter in the controller : that means making some slightly changes to the route, the controller and the view :
  • First thing to change is the route to :

[yoursite]_blog_helloWorld:
    path:     /greeting/{name}
    defaults: { _controller: SdzBlogBundle:Blog:index}
  • The controller needs to be updated  :

[..]
class BlogController extends Controller
{
public function indexAction($name)
{
return $this->render('[yoursite]BlogBundle:Blog:index.html.twig', array('name' => $name));
}
}
  • The view needs also to be updated  :  

<!DOCTYPE html>
<html>
   <head>
   <title>Hello!</title>
    </head> 
    <body>
          <h1>Hello {{name}} !</h1>
    </body>
</html>


The URL call will then be "http://localhost/symfony/web/app_dev.php/greeting/john":




Tuesday, 17 March 2015

installing Symfony 2.3 under Windows (XAMPP)

These are the steps for the installation of Symfony 2.3 under Windows: (see http://uploads.siteduzero.com/pdf/517569-developpez-votre-site-web-avec-le-framework-symfony2.pdf)

  1. Add the folder of you "php.exe" in the value of your Path entry within the Windows environment variables ( Open the Start Menu and right click on Computer -  Select Properties - Select Advanced system settings - In the Advanced tab, select Environment Variables. Find the path entry and add at the end : ";C:\[php_folder]\php" )
  2. Launch the command prompt
  3. Go to the web folder used by your local webserver (when using Xampp under MS Windows, that shoud be [xampp_folder]\htdocs)
  4. Install composer using the following command : php -r "readfile('https://getcomposer.org/installer');" | php
  5. Install Symfony with Composer using the following command : php composer.phar create-project symfony/framework-standard-edition [name_web_appli] for example : 
    php composer.phar create-project symfony/framework-standard-edition sf3
  6. Different questions will be asked during the installation (put the default values):
Would you like to install Acme demo bundle ? y/N => y
Database driver : pdo_mysql
Database host : localhost
Database port : null
Database name : symfony
Database user : root
Database password : null
Mailer transport : smtp
Mailer host: localhost
Mailer user: null
Mailer password: null
locale: fr (or 'en') 
Secret: 123456789

  1. Type the following URL : http://localhost/[name_web_appli]/web/app_dev.php
  2. You should have the following screen if your installation is fine : 
To update symfony with new bundles, you should go to composer.json under the symfony directory (sf3 here above) and the bundle in the "require" list :  

    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.0.*",
        "doctrine/orm": "^2.5",
        "doctrine/doctrine-bundle": "^1.6",
        "doctrine/doctrine-cache-bundle": "^1.2",
        "symfony/swiftmailer-bundle": "^2.3",
        "symfony/monolog-bundle": "^2.8",
        "sensio/distribution-bundle": "^5.0",
        "sensio/framework-extra-bundle": "^3.0.2",
        "incenteev/composer-parameter-handler": "^2.0",
        "nelmio/api-doc-bundle":"^2.11"
    },


php ../composer.phar update


add the following code in  sf3/app/config/routing.yml
NelmioApiDocBundle:
    resource: "@NelmioApiDocBundle/Resources/config/routing.yml"
    prefix:   /api/doc

and the following one within "AppKernel.php" :    "new Nelmio\ApiDocBundle\NelmioApiDocBundle()," dans la liste des bundles

Next, all you need is to go that URL, to ensure that everything is working properly:
http://localhost/sf3/web/app_dev.php/api/doc



Under Linux, the installation can be done using the following command (on a Linux server with a LAMP stack) :

composer create-project symfony/framework-standard-edition [name_web_appli]  "3.0.*"

And go to :
http://[server_host]:[port_number]/[name_web_appli]/web/app_dev.php

Notice :  in order to have an access to this URL, you may have to delete some part of the file web/app_dev.php (for example, when using Docker) , especially, from ligne 13 to 19 :

if (isset($_SERVER['HTTP_CLIENT_IP'])
    || isset($_SERVER['HTTP_X_FORWARDED_FOR'])
    || !(in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1']) || php_sapi_name() === 'cli-server')
) {
    header('HTTP/1.0 403 Forbidden');
    exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}

Thursday, 12 March 2015

Node.js : allowing you to execute JavaScript code in Backend context (outside web browsers)

A very good description of Node.js is shown on that web site : http://www.nodebeginner.org/ (or http://nodejs.developpez.com/tutoriels/javascript/node-js-livre-debutant for the french equivalent).

What is Node.js ?... it's a server-side JavaScript

The first incarnations of JavaScript lived in browsers (on frontend with DHTML first, then, more recently, with frameworks like jQuery). But this is just the context. It defines what you can do with the language, but it doesn't say much about what the language itself can do. JavaScript is a "complete" language: you can use it in many contexts and achieve everything with it you can achieve with any other "complete" language.

Node.js really is just another context: it allows you to run JavaScript code in the backend, outside a browser.

In order to execute the JavaScript you intend to run in the backend, it needs to be interpreted and, well, executed. This is what Node.js does, by making use of Google's V8 VM, the same runtime environment for JavaScript that Google Chrome uses.

Plus, Node.js ships with a lot of useful modules, so you don't have to write everything from scratch, like for example something that outputs a string on the console.

Thus, Node.js is really two things: a runtime environment and a library.

You will find the official installation instruction on that side: https://github.com/joyent/node/wiki/Installation. (I will take here the MS Windows version)


The "hello world" example code using Node.js as a simple web-server

Once, you have downloaded and executed the installation, the first thing that I will suggest is to create a folder ; let's call it "node" ; in that folder, you will put your JavaScript scripts.

let's  create a new file server.js in that folder and paste the following code in that file :

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8080);

If this port is already used, you just have to change it!

All you need now, it's to launch the "Node.js command prompt" and type : 'node node\server.js' and press the Enter key.

Then, go and type on a web browser the following URL : http://localhost:8080/

You should see the following display on the web page : "Hello World"

Creating our Node.js server module

It's common to have a main file called index.js which is used to start our application ;
We will show about how to make server.js a real Node.js module that can be used by our yet-to-be-written index.js main file.
About our server.js, we don't have to change that much. Making some code a module means we need to export those parts of its functionality that we want to provide to scripts that require our module.

For now, the functionality our HTTP server needs to export is simple: scripts requiring our server module simply need to start the server.

To make this possible, we will put our server code into a function named start, and we will export this function:

server.js
var http = require("http");
var url = require("url");

exports.start = function () {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");
    console.log("Request received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }
  http.createServer(onRequest).listen(8080);
  console.log("Server has started.");
};

Notice, here above, that we added a new module module (url) to track the path name of the URL (request); 
This way, we can now create our main file index.js, and start our HTTP there, although the code for the server is still in our server.js file.

Create a file index.js with the following content:

index.js
var server = require("./server");
server.start();

As you can see, we can use our server module just like any internal module: by requiring its file and assigning it to a variable, its exported functions become available to us.
That's it. We can now start our app via our main script, and it still does exactly the same:

node index.js

(Note that our server will probably write "Request received." to STDOUT two times upon opening the page in a browser. That's because most browsers will try to load the favicon by requesting http://localhost:8888/favicon.ico whenever you open http://localhost:8888/).

Accessing MySQL Databases

"Most traditional server-side technologies have a built-in means of connecting to and querying a database. With Node.js, you have to install a library. For this tutorial, I've picked the stable and easy to use node-mysql. The full name of this module is mysql@2.0.0-alpha2 (everything after the @ is the version number). Open your console, navigate to the directory where you've stored your scripts, and execute the following command:  npm install mysql@2.0.0-alpha2

This downloads and installs the module, and it also creates the node_modules folder in the current directory. " (cf. http://code.tutsplus.com/tutorials/nodejs-for-beginners--net-26314)
Now let's look at how we can use this module to export  json  results from a sql query ;  here, is an example :
var mysql      = require('mysql');
var psn_id = 376257924;

var connection = mysql.createConnection({
  host     : 'host_name',
  user     : 'user_name',
  password : 'password',
  database : 'db_name',
});
var queryString = "SELECT * FROM your_table WHERE id = ? " ;
var http      = require('http');
var rep = "";
connection.query(queryString, psn_id, function (error, rows, fields) { 
// Rows variable holds the result of the query. 
rep = JSON.stringify(rows); 
}); 
// Create the http server. 
http.createServer(function (request, response) { 
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write(rep);
  response.end();
// Listen on the 8080 port. 

}).listen(8080);

Monday, 2 March 2015

Dealing with events with Google Charts / Tables

Here are the web references I have used for this articles

  • https://developers.google.com/chart/interactive/docs/gallery
  • https://developers.google.com/chart/interactive/docs/events
  • https://developers.google.com/chart/interactive/docs/basic_interactivity
  • https://google-developers.appspot.com/chart/interactive/docs/gallery/table


Let's take the previous example, with pie chart (adding  'pieHole': 0.5 option to get a like-donut pie chart) ; if you would like to add a listener to catch the click event, you will have to add the following code in 'orange' :

<html>
    <head>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script type="text/javascript" src="http://www.google.com/jsapi"></script>

        <script type='text/javascript'>

            //https://google-developers.appspot.com/chart/interactive/docs/quick_start
            //https://google-developers.appspot.com/chart/interactive/docs/gallery/table
            //https://developers.google.com/chart/interactive/docs/gallery
         
            function drawChart() {
                var json = $.ajax({
                    url: "http://localhost/angularjs/get_repartition_order_status_todaygoogle_pie.php?type=graph",
                    dataType:"json",
                    async: false
                }).responseText;
                jsondata = eval(json);
                // Create the data table.
                var data = new google.visualization.DataTable();
                data.addColumn('string', 'Topping');
                data.addColumn('number', 'Slices');
                data.addRows(jsondata);

                // Set chart options
                var options = {'title':'Order Status for today ',
                    'width':500, 'pieHole': 0.5,
                    'height':400};
                //var options = {'title':'Order Status for today ','width':600, 'pieHole': 0.5,'height':600, 'is3D': true};
                // Instantiate and draw our chart, passing in some options.
                var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
                chart.draw(data, options);
           
                google.visualization.events.addListener(chart, 'select', selectHandler);

                // Notice that e is not used or needed.
                function selectHandler(e) {
                    var selectedItem = chart.getSelection()[0];
                    if (selectedItem) {
                        var value = data.getValue(selectedItem.row, 0);
                        alert('The user selected ' + value);
                    };
                }
            }
     
            // Set a callback to run when the Google Visualization API is loaded.
            google.setOnLoadCallback(drawChart);
            // Load the Visualization API and the piechart package.
            google.load('visualization', '1.0', {'packages':['corechart']});
        </script>
    </head>

    <body>
        <!--Div that will hold the pie chart-->
        <div id="chart_div"></div>
        <div id="table_div"></div>
    </body>
</html>


Now, I would like to trigger a draw of an associated table according to the selected value:

<html>
    <head>
        <!--Load the AJAX API-->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script type="text/javascript" src="http://www.google.com/jsapi"></script>

        <script type='text/javascript'>
         
            function drawChart() {
                var json = $.ajax({
                    url: "http://localhost/angularjs/get_repartition_order_status_todaygoogle_pie.php?type=graph",
                    dataType:"json",
                    async: false
                }).responseText;
                jsondata = eval(json);
                // Create the data table.
                var data = new google.visualization.DataTable();
                data.addColumn('string', 'Topping');
                data.addColumn('number', 'Slices');
                data.addRows(jsondata);

                // Set chart options
                var options = {'title':'Order Status for today ',
                    'width':500, 'pieHole': 0.5,
                    'height':400,'margin' : 0};
                //var options = {'title':'Order Status for today ','width':600, 'pieHole': 0.5,'height':600, 'is3D': true};
                // Instantiate and draw our chart, passing in some options.
                var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
                chart.draw(data, options);
                // orgChart is my global orgchart chart variable.
                google.visualization.events.addListener(chart, 'select', selectHandler);

                // Notice that e is not used or needed.
                function selectHandler(e) {
                    var selectedItem = chart.getSelection()[0];
                    if (selectedItem) {
                        var value = data.getValue(selectedItem.row, 0);
                        // alert('The user selected ' + value);
                        google.setOnLoadCallback(drawTable(value));
                    };
                }
            }
            function drawTable(etat) {
                var json = $.ajax({
                    url: "http://localhost/angularjs/get_repartition_order_status_todaygoogle_pie.php?type=table&status=" + etat,
                    dataType:"json",
                    async: false
                }).responseText;
                JSONObject = eval(json);  
                var new_json = "[";
                for (var key in JSONObject) {
                    if (JSONObject.hasOwnProperty(key)) {
                        new_json += "['" + JSONObject[key]["order_id"] + "'";
                        new_json += ",'" + JSONObject[key]["store_id"] + "'";
                        new_json += ",'" + JSONObject[key]["purchase_serial_number"] + "'";
                        new_json += ",'" + JSONObject[key]["purchase_creation_date"]  + "'";
                        new_json += ",'" + JSONObject[key]["lastmod"]  + "'";
                        new_json += ",'" + JSONObject[key]["status"]  + "'],";
                    }
                }
                //console.log(new_json.length);
                new_json=new_json.substring(0,new_json.length - 1)
                new_json += "]";
                //console.log(eval(new_json));
                var options = {'showRowNumber': true};
                
                var data = new google.visualization.DataTable();
                data.addColumn('string', 'order_id');
                data.addColumn('string', 'store_id');
                data.addColumn('string', 'PSN');
                data.addColumn('string', 'Creation Date');
                data.addColumn('string', 'Modif. Date');
                data.addColumn('string', 'Status');

                data.addRows(eval(new_json));

                var table = new google.visualization.Table(document.getElementById('table_div'));
                
                table.draw(data, options);
            }
            // Set a callback to run when the Google Visualization API is loaded.
            google.setOnLoadCallback(drawChart);
            // Load the Visualization API and the piechart package.
            google.load('visualization', '1.0', {'packages':['corechart','table']});
        </script>
    </head>

    <body>
        <!--Div that will hold the pie chart-->
        <div id="chart_div"></div>
        <div id="table_div"></div>
    </body>
</html>


The result is the following one :


Display Live data with Google Charts, Ajax (through JSON file), and AngularJS

The Google-developers website is the good place to start in order to know how to use of Google-charts within a HTML page :
see https://google-developers.appspot.com/chart/
The on-line JavaScript library that you will need for Google chart is http://www.google.com/jsapi

If you want to use ajax, the best way is to use jquery (the on-line JavaScript library is http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js)


To draw a pie chart (cf. https://google-developers.appspot.com/chart/interactive/docs/quick_start), here is an example of HTML/JS file :
       
<html>
    <head>
        <!--Load the AJAX API-->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script type="text/javascript" src="http://www.google.com/jsapi"></script>

    <script type='text/javascript'>

            function drawChart() {
                var json = $.ajax({
                    url: "http://localhost/angularjs/get_repartition_order_status_todaygoogle_pie.php?type=graph",
                    dataType:"json",
                    async: false
                }).responseText;
                jsondata = eval(json);
                // Create the data table.
                var data = new google.visualization.DataTable();
                data.addColumn('string', 'Topping');
                data.addColumn('number', 'Slices');
                data.addRows(jsondata);

                // Set chart options
                var options = {'title':'Order Status for today ',
                    'width':400,
                    'height':300};

                // Instantiate and draw our chart, passing in some options.
                var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
                chart.draw(data, options);
            }

            // Set a callback to run when the Google Visualization API is loaded.
            google.setOnLoadCallback(drawChart);
            // Load the Visualization API and the piechart package.
            google.load('visualization', '1.0', {'packages':['corechart']});

            // Callback that creates and populates a data table,
            // instantiates the pie chart, passes in the data and
            // draws it.
        </script>
    </head>

    <body>
        <!--Div that will hold the pie chart-->
        <div id="chart_div"></div>
    </body>
</html>

You may have noticed that I had to convert the JSON output in order to pass the data through addRows method using eval();

The format of the json data is  ([ ["label",value]....] ):
[
   ["new",2955],["processing",721],["shipped",162],[],["cancelled",109],["restocking",11]

]

Now, if you would like to introduce a Google Chart when using AngularJS,

<!DOCTYPE html>
<html>
    <script type="text/javascript" src="http://code.angularjs.org/1.1.0/angular.min.js"></script>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type='text/javascript'>
        //http://snippetrepo.com/snippets/google-charts-with-angularjs
        var app = angular.module('myApp', []);
        app.directive('chart', function() {
            return {
                restrict: 'A',
                link: function($scope, $elm, $attr) {
                    var json = $.ajax({
                        url: "http://localhost/angularjs/get_repartition_order_status_todaygoogle_pie.php?type=graph",
                        dataType:"json",
                        async: false
                    }).responseText;
                    jsonData = eval(json);
                    // Create the data table.
                    var data = new google.visualization.DataTable();
                    data.addColumn('string', 'Topping');
                    data.addColumn('number', 'Slices');
                   
                    data.addRows(jsonData);
                    // Set chart options
                    var options = {'title':'Order Status for today ',
                        'width':400,
                        'height':300};

                    // Instantiate and draw our chart, passing in some options.
                    var chart = new google.visualization.PieChart($elm[0]);
                    chart.draw(data, options);
                }
            }
        });

        google.setOnLoadCallback(function() {
            angular.bootstrap(document.body, ['myApp']);
        });
        google.load('visualization', '1', {packages: ['corechart']});

    </script>
    <body> 
        <!--Div that will hold the pie chart-->
            <div chart></div>

    </body>

</html>

I've shown in "aqua" the few lines that need to be changed when integrating the pie chart within AngularJS: in both cases, the output will look like the above graph.

You can also add 3D effects changing the options value, doing so:
 
var options = {'title':'Order Status for today ',
                        'width':400,
                        'height':300,'is3D': true};


Nota : You can also change the location of the legend (by adding : 'legend':'left')










Another way is presented at http://www.frangular.com/2013/01/google-chart-tools-avec-angularjs.html (that seems more complex at least right now!!) :

Here below, you will fact respectively, the HTML, and JS files giving the same output than above (with 3D option graph):

<!DOCTYPE html>
<html ng-app="angularjs-starter">

    <head lang="en">
        <meta charset="utf-8">
        <title>GoogleCharts in AngularJS</title>

    </head>

    <body ng-controller="MainCtrl">        

        <div style="float: left; width: 600px" ng:model="data"  qn:columns="[{type:'string', name: 'Topping'}, {type:'number', name: 'Slices'}]" qn:piechart="{legend : {alignment: 'center'}, chartArea: {height: 400},backgroundColor: '#F7F7F7'}"></div>
           
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>    
        <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script src="pieGCharts.js"></script>
        <script type="text/javascript" src="https://www.google.com/jsapi"> </script>
        <script type="text/javascript">
            google.load('visualization', '1.0', { 'packages': ['corechart'] });
        </script>
    </body>

</html>


with pieGCharts.js :
var app = angular.module('angularjs-starter', [
    'charts.pie'
]); 

app.controller('MainCtrl', function($scope) {
    var json = $.ajax({
        url: "http://localhost/angularjs/get_repartition_order_status_todaygoogle_pie.php?type=graph",
        dataType:"json",
        async: false
    }).responseText;
    $scope.data = eval(json);
});

angular.module('charts.pie', [
])
.directive('qnPiechart', [
    function() {
        return {
            require: '?ngModel',
            link: function(scope, element, attr, controller) {
                var settings = {
                    is3D: true
                };

                var getOptions = function() {
                    return angular.extend({ }, settings, scope.$eval(attr.qnPiechart));
                };

                // creates instance of datatable and adds columns from settings
                var getDataTable = function() {
                    var columns = scope.$eval(attr.qnColumns);
                    var data = new google.visualization.DataTable();
                    angular.forEach(columns, function(column) {
                        data.addColumn(column.type, column.name);
                    });
                    return data;
                };

                var init = function() {
                    var options = getOptions();
                    if (controller) {

                        var drawChart = function() {
                            var data = getDataTable();
                            // set model
                            data.addRows(controller.$viewValue);

                            // Instantiate and draw our chart, passing in some options.
                            var pie = new google.visualization.PieChart(element[0]);
                            pie.draw(data, options);
                        };

                        controller.$render = function() {
                            drawChart();
                        };
                    }

                    if (controller) {
                        // Force a render to override
                        controller.$render();
                    }
                };

                // Watch for changes to the directives options
                scope.$watch(getOptions, init, true);
                scope.$watch(getDataTable, init, true);
            }
        };
    }

]);