<commit_before>var containercss = {
  position : "relative",
  // "margin" : "20px 0 0 0",
  // "background" : "gray",
  overflow : "hidden"
};

var canvascss = {
  position : "absolute",
  left : 0,
  top : 0,
  "z-index" : 100,
  cursor : "move"
};

function Annotation(type) {
  this.valid = false;
  this.pts = [{x:0,y:0}, {x:0,y:0}];
  this.type = type;
};

var att = new Annotation("rect");

// Canvas re-draw op
function repaint(g, $img) {
  var w = $img.width();
  var h = $img.height();

  // Drop shadow
  g.shadowColor = "#555";
  g.shadowBlur = 40;

  // Draw the image
  g.drawImage($img[0], -w/2, -h/2);

  // Annotation
  drawAtt(g);
};

// Annotation draw op
function drawAtt(g) {
  if (!att.valid) return;

  g.shadowColor = "#222";
  g.shadowBlur = 5;
  g.strokeStyle = "white";
  g.lineWidth = 1 / curScale;
  g.fillStyle = "white";

  // Box drawing (2-point)
  if (att.type == "rect") {
    var x0 = att.pts[0].x;
    var y0 = att.pts[0].y;
    var x1 = att.pts[1].x;
    var y1 = att.pts[1].y;

    var dx = Math.abs(x1-x0);
    var dy = Math.abs(y1-y0);
    var x = Math.min(x0, x1);
    var y = Math.min(y0, y1);

    g.strokeRect(x, y, dx, dy);

    drawPt(g, {x:x0, y:y0});
    drawPt(g, {x:x0, y:y1});
    drawPt(g, {x:x1, y:y0});
    drawPt(g, {x:x1, y:y1});
  }
  // Polygon drawing (n-point)
  else if (att.type == "poly") {
    g.beginPath();
    g.moveTo(att.pts[0].x, att.pts[0].y);

    for (var i = 1; i < att.pts.length; i++) {
      g.lineTo(att.pts[i].x, att.pts[i].y);
    }

    g.lineTo(att.pts[0].x, att.pts[0].y);
    g.stroke();

    for (var i = 0; i < att.pts.length; i++) {
      drawPt(g, att.pts[i]);
    }
  }
}

// Point drawing util
function drawPt(g, pt) {
  g.beginPath();
  g.arc(pt.x, pt.y, 2.5/curScale, 0, 2*Math.PI, false);
  g.fill();
}

// Transform info
var curScale = 0.9;
var xOffs = 0;
var yOffs = 0;

// General transform op
function doTransform(g, $img) {
  var w = $img.width();
  var h = $img.height();

  // Reset xform & clear
  g.setTransform(1,0,0,1,0,0);
  g.clearRect(0, 0, w, h);

  // To draw in position with scaling,
  // move to position (translate), then
  // scale before drawing at (0, 0)
  g.translate(w/2 + xOffs, h/2 + yOffs);
  g.scale(curScale, curScale);

  repaint(g, $img);
};

// Zoom op
function zoom(g, $img, scale) {
  // New scaling level
  curScale *= scale;

  if (curScale < 0.9) {
    curScale = 0.9;
  }

  doTransform(g, $img);
};

// Pan op
function pan(g, $img, x, y) {
  // New offset
  var margin = 100;

  xOffs += x;
  yOffs += y;

  var xLim = ($img.width()/2)*curScale;
  var yLim = ($img.height()/2)*curScale;

  if (xOffs >  xLim) xOffs =  xLim;
  if (xOffs < -xLim) xOffs = -xLim;
  if (yOffs >  yLim) yOffs =  yLim;
  if (yOffs < -yLim) yOffs = -yLim;

  doTransform(g, $img);
};

// Util - canvas to image space
function ptToImg($img, x, y) {
  var out = {
    x : 0, y : 0
  }

  out.x = (x-$img.width()/2-xOffs)/curScale;
  out.y = (y-$img.height()/2-yOffs)/curScale;

  return out;
};

(function( $ ) {
  // The annotator function - appplicable to any jQuery object collection
  $.fn.annotator = function(src, width, height) {
    return this.each(function() {
      var $zoomin, $zoomout, $pan, $annotate,
          $container, $img, $canvas, $type, g;

      // Check for annotator class
      $parent = $(this);

      // Update if we're passed an existing annotator
      if ($parent.hasClass("annotator")) {
        // Retrieve controls
        $zoomin     = $parent.find("#zoomin");
        $zoomout    = $parent.find("#zoomin");
        $pan        = $parent.find("#pan");
        $annotate   = $parent.find("#annot");

        $type       = $parent.find("#typesel");

        // Retrieve/resize container
        $container = $parent.find("div").width(width).height(height);

        // Reload the image
        $img = $parent.find("img").attr("src", src).width(width).height(height);

        // Retrieve canvas
        $canvas = $parent.find("canvas");

        // Reset pan/zoom
        curScale = 0.9;
        xOffs = 0;
        yOffs = 0;

        // Reset annotation
        att = new Annotation(att.type);
      }
      else {
        // Register and generate annotator components
        $parent.addClass("annotator");

        // Controls
    	  $zoomin    = $('<button id="zoomin">+</button>').appendTo($parent);
        $zoomout   = $('<button id="zoomout">-</button>').appendTo($parent);
        $pan       = $('<button id="pan">Pan</button>').appendTo($parent);
        $annotate  = $('<button id="annot">Annotate</button>').appendTo($parent);

        $type      = $('<select id="typesel"></select>')
                      .html('<option>Box</option><option>Polygon</option>')
                      .appendTo($parent);

        // Canvas container
        $container = $('

')
                    .css(containercss)
                    .width(width)
                    .height(width)
                    .appendTo($parent);

        // Load the image
        $img = $('')
                    .width(width)
                    .height(height)
                    .hide()
                    .appendTo($parent);

        // The drawing canvas
        $canvas = $('<canvas>Unsupported browser.</canvas>')
                    .css(canvascss)
                    .appendTo($container);

        if (typeof G_vmlCanvasManager != 'undefined') {
          console.log("um");
          canvas = G_vmlCanvasManager.initElement(canvas);
        }

        // Zoom control
        $zoomin.click(function(){zoom(g, $img, 1.25 );});
        $zoomout.click(function(){zoom(g, $img, 0.8  );});

        // Canvas operations
        var x0, x1;
        var y0, y1;
        var op = "pan";
        var active = false;
        var polyC = 0;

        // Operation selection
        $type.change(function(){
          var str = $(this).val();
          if (str == "Box") {
            att.type = "rect";
          }
          else if (str == "Polygon") {
            att.type = "poly";
          }
        });
        $pan.click(function(){
          op = "pan";
          $canvas.css("cursor", "move");
        });
        $annotate.click(function(){
          op = "annotate";
          $canvas.css("cursor", "crosshair");
        });

        // Mouse down - start drawing or panning
        $canvas.mousedown(function(e){
          if (!active) {
            var offset = $canvas.offset();
            x1 = x0 = e.pageX - offset.left;
            y1 = y0 = e.pageY - offset.top;
            active = true;

            if (op == "annotate") {
              att = new Annotation(att.type);
              att.valid = true;

              if (att.type == "poly") {
                att.pts[0] = ptToImg($img, x0, y0);
                polyC = 1;
              }
            }
          }
        });

        // Movement continues draw/pan as long as the mouse button is held
        $canvas.mousemove(function(e){
          if (!active) return;

          var offset = $canvas.offset();
          x1 = e.pageX - offset.left;
          y1 = e.pageY - offset.top;

          var dx = x1 - x0;
          var dy = y1 - y0;

          if (op == "pan") {
            // Panning the image
            pan(g, $img, dx, dy);
            x0 = x1;
            y0 = y1;
          }
          else if (op == "annotate") {
            // Annotation - in image space
            var pt1 = ptToImg($img, x0, y0);
            var pt2 = ptToImg($img, x1, y1);

            if (att.type == "rect") {
              att.pts[0] = pt1;
              att.pts[1] = pt2;
            }
            else if (att.type == "poly") {
              // Save next point
              att.pts[polyC] = pt2;
            }

            // Redraw
            doTransform(g, $img);
          }
        });

        // Operation end
        $canvas.mouseup(function(){
          // End ONLY if dragged
          if (op == "annotate") {
            if (x0 != x1 && y0 != y1) {
              if (att.type == "rect") active = false;
              else if (att.type == "poly") {
                x0 = x1;
                y0 = y1;
                polyC++;
              }
            }
            else if (att.type == "poly" && polyC > 1) {
              active = false;
            }
          }
          else {
            active = false;
          }
        });
      } // end of conditional update

      // Scale the canvas to the original image
      $canvas[0].width = width;
      $canvas[0].height = height;

      // 'g' is the graphics context for rendering
      g = $canvas[0].getContext("2d");

      // We have to wait for the image to load before we can use it
      $img.load(function(){
        doTransform(g, $img);
      });
    });
  };
}(jQuery));
<commit_msg>[semi-functional] multiple annotations<commit_after>var containercss = {
  position : "relative",
  // "margin" : "20px 0 0 0",
  // "background" : "gray",
  overflow : "hidden"
};

var canvascss = {
  position : "absolute",
  left : 0,
  top : 0,
  "z-index" : 100,
  cursor : "move"
};

function Annotation(type) {
  this.valid = false;
  this.pts = [{x:0,y:0}, {x:0,y:0}];
  this.type = type;
};

var att = new Annotation("rect");
var atts = [att];

// Canvas re-draw op
function repaint(g, $img) {
  var w = $img.width();
  var h = $img.height();

  // Drop shadow
  g.shadowColor = "#555";
  g.shadowBlur = 40;

  // Draw the image
  g.drawImage($img[0], -w/2, -h/2);

  // Annotation
  for (var i = 0; i < atts.length; i++) {
    drawAtt(g, atts[i]);
  }
};

// Annotation draw op
function drawAtt(g, att) {
  if (!att.valid) return;

  g.shadowColor = "#222";
  g.shadowBlur = 5;
  g.strokeStyle = "white";
  g.lineWidth = 1 / curScale;
  g.fillStyle = "white";

  // Box drawing (2-point)
  if (att.type == "rect") {
    var x0 = att.pts[0].x;
    var y0 = att.pts[0].y;
    var x1 = att.pts[1].x;
    var y1 = att.pts[1].y;

    var dx = Math.abs(x1-x0);
    var dy = Math.abs(y1-y0);
    var x = Math.min(x0, x1);
    var y = Math.min(y0, y1);

    g.strokeRect(x, y, dx, dy);

    drawPt(g, {x:x0, y:y0});
    drawPt(g, {x:x0, y:y1});
    drawPt(g, {x:x1, y:y0});
    drawPt(g, {x:x1, y:y1});
  }
  // Polygon drawing (n-point)
  else if (att.type == "poly") {
    g.beginPath();
    g.moveTo(att.pts[0].x, att.pts[0].y);

    for (var i = 1; i < att.pts.length; i++) {
      g.lineTo(att.pts[i].x, att.pts[i].y);
    }

    g.lineTo(att.pts[0].x, att.pts[0].y);
    g.stroke();

    for (var i = 0; i < att.pts.length; i++) {
      drawPt(g, att.pts[i]);
    }
  }
}

// Point drawing util
function drawPt(g, pt) {
  g.beginPath();
  g.arc(pt.x, pt.y, 2.5/curScale, 0, 2*Math.PI, false);
  g.fill();
}

// Transform info
var curScale = 0.9;
var xOffs = 0;
var yOffs = 0;

// General transform op
function doTransform(g, $img) {
  var w = $img.width();
  var h = $img.height();

  // Reset xform & clear
  g.setTransform(1,0,0,1,0,0);
  g.clearRect(0, 0, w, h);

  // To draw in position with scaling,
  // move to position (translate), then
  // scale before drawing at (0, 0)
  g.translate(w/2 + xOffs, h/2 + yOffs);
  g.scale(curScale, curScale);

  repaint(g, $img);
};

// Zoom op
function zoom(g, $img, scale) {
  // New scaling level
  curScale *= scale;

  if (curScale < 0.9) {
    curScale = 0.9;
  }

  doTransform(g, $img);
};

// Pan op
function pan(g, $img, x, y) {
  // New offset
  var margin = 100;

  xOffs += x;
  yOffs += y;

  var xLim = ($img.width()/2)*curScale;
  var yLim = ($img.height()/2)*curScale;

  if (xOffs >  xLim) xOffs =  xLim;
  if (xOffs < -xLim) xOffs = -xLim;
  if (yOffs >  yLim) yOffs =  yLim;
  if (yOffs < -yLim) yOffs = -yLim;

  doTransform(g, $img);
};

// Util - canvas to image space
function ptToImg($img, x, y) {
  var out = {
    x : 0, y : 0
  }

  out.x = (x-$img.width()/2-xOffs)/curScale;
  out.y = (y-$img.height()/2-yOffs)/curScale;

  return out;
};

(function( $ ) {
  // The annotator function - appplicable to any jQuery object collection
  $.fn.annotator = function(src, width, height) {
    return this.each(function() {
      var $zoomin, $zoomout, $pan, $annotate,
          $container, $img, $canvas, $type, g;

      // Check for annotator class
      $parent = $(this);

      // Update if we're passed an existing annotator
      if ($parent.hasClass("annotator")) {
        // Retrieve controls
        $zoomin     = $parent.find("#zoomin");
        $zoomout    = $parent.find("#zoomin");
        $pan        = $parent.find("#pan");
        $annotate   = $parent.find("#annot");

        $type       = $parent.find("#typesel");

        // Retrieve/resize container
        $container = $parent.find("div").width(width).height(height);

        // Reload the image
        $img = $parent.find("img").attr("src", src).width(width).height(height);

        // Retrieve canvas
        $canvas = $parent.find("canvas");

        // Reset pan/zoom
        curScale = 0.9;
        xOffs = 0;
        yOffs = 0;

        // Reset annotation
        att = new Annotation(att.type);
        atts = [att];
      }
      else {
        // Register and generate annotator components
        $parent.addClass("annotator");

        // Controls
    	  $zoomin    = $('<button id="zoomin">+</button>').appendTo($parent);
        $zoomout   = $('<button id="zoomout">-</button>').appendTo($parent);
        $pan       = $('<button id="pan">Pan</button>').appendTo($parent);
        $annotate  = $('<button id="annot">Annotate</button>').appendTo($parent);

        $type      = $('<select id="typesel"></select>')
                      .html('<option>Box</option><option>Polygon</option>')
                      .appendTo($parent);

        // Canvas container
        $container = $('

')
                    .css(containercss)
                    .width(width)
                    .height(width)
                    .appendTo($parent);

        // Load the image
        $img = $('')
                    .width(width)
                    .height(height)
                    .hide()
                    .appendTo($parent);

        // The drawing canvas
        $canvas = $('<canvas>Unsupported browser.</canvas>')
                    .css(canvascss)
                    .appendTo($container);

        if (typeof G_vmlCanvasManager != 'undefined') {
          console.log("um");
          canvas = G_vmlCanvasManager.initElement(canvas);
        }

        // Zoom control
        $zoomin.click(function(){zoom(g, $img, 1.25 );});
        $zoomout.click(function(){zoom(g, $img, 0.8  );});

        // Canvas operations
        var x0, x1;
        var y0, y1;
        var op = "pan";
        var active = false;
        var polyC = 0;

        // Operation selection
        $type.change(function(){
          var str = $(this).val();
          if (str == "Box") {
            att.type = "rect";
          }
          else if (str == "Polygon") {
            att.type = "poly";
          }
        });
        $pan.click(function(){
          op = "pan";
          $canvas.css("cursor", "move");
        });
        $annotate.click(function(){
          op = "annotate";
          $canvas.css("cursor", "crosshair");
        });

        // Mouse down - start drawing or panning
        $canvas.mousedown(function(e){
          if (!active) {
            var offset = $canvas.offset();
            x1 = x0 = e.pageX - offset.left;
            y1 = y0 = e.pageY - offset.top;
            active = true;

            if (op == "annotate") {
              att = new Annotation(att.type);
              att.valid = true;
              atts.push(att);

              if (att.type == "poly") {
                att.pts[0] = ptToImg($img, x0, y0);
                polyC = 1;
              }
            }
          }
        });

        // Movement continues draw/pan as long as the mouse button is held
        $canvas.mousemove(function(e){
          if (!active) return;

          var offset = $canvas.offset();
          x1 = e.pageX - offset.left;
          y1 = e.pageY - offset.top;

          var dx = x1 - x0;
          var dy = y1 - y0;

          if (op == "pan") {
            // Panning the image
            pan(g, $img, dx, dy);
            x0 = x1;
            y0 = y1;
          }
          else if (op == "annotate") {
            // Annotation - in image space
            var pt1 = ptToImg($img, x0, y0);
            var pt2 = ptToImg($img, x1, y1);

            if (att.type == "rect") {
              att.pts[0] = pt1;
              att.pts[1] = pt2;
            }
            else if (att.type == "poly") {
              // Save next point
              att.pts[polyC] = pt2;
            }

            // Redraw
            doTransform(g, $img);
          }
        });

        // Operation end
        $canvas.mouseup(function(){
          // End ONLY if dragged
          if (op == "annotate") {
            if (x0 != x1 && y0 != y1) {
              if (att.type == "rect") active = false;
              else if (att.type == "poly") {
                x0 = x1;
                y0 = y1;
                polyC++;
              }
            }
            else if (att.type == "poly" && polyC > 1) {
              active = false;
            }
          }
          else {
            active = false;
          }
        });
      } // end of conditional update

      // Scale the canvas to the original image
      $canvas[0].width = width;
      $canvas[0].height = height;

      // 'g' is the graphics context for rendering
      g = $canvas[0].getContext("2d");

      // We have to wait for the image to load before we can use it
      $img.load(function(){
        doTransform(g, $img);
      });
    });
  };
}(jQuery));
<|endoftext|>


<commit_before>var Q    = require('q')
   ,connect = require('connect')
   ,http = require('http')
   ,less = require('less')
   ,getBody = require('./get-body.js')
   ,parserOptions = require('./parser-options.js')
   ,sessions = require('./sessions.js')()
   ,Cache = require('./cache.js')
   ,DummyCache = require('./dummy-cache.js')
   ,cache = null
   ,l    = require('./log.js').log;

module.exports = function(config) {
   var app = connect()
   .use(denyNonPosts)
   .use(receiveBody)
   .use(connect.query())
   .use(extractParserOptions)
   .use('/session', createSession)
   .use(lookupSession)
   .use(convertLess)

   if (!config || !config.memcache) {
      cache = DummyCache;
      l("Using Dummy Cache");
   } else {
      l("Using memcache");
      cache = Cache(config);
   }

   return http.createServer(app)
}

function denyNonPosts(req, res, next) {
   if (req.method !== 'POST') {
      res.statusCode = 404;
      return res.end();
   }
   next();
}

function receiveBody(req, res, next) {
   req.time = process.hrtime();
   getBody(req).then(function(body) {
      req.body = body;
      next();
   })
}

function extractParserOptions(req, res, next) {
   if (req.query.options) {
      req.parserOptions = parserOptions(JSON.parse(req.query.options || null))
   }
   next();
}

function createSession(req, res, next) {
   sessions.create(req.body, req.parserOptions)
   .then(function(session) {
      res.end(session.token)
   }).catch(handleFailure(res, req));
}

function lookupSession(req, res, next) {
   if (req.query.session) {
      var session = sessions.get(req.query.session);
      if (!session || !session.ast) {
         var error = new Error("Session "+req.query.session+" not found!")
         return handleFailure(req, res)(error);
      }
      req.session = session;
   }
   next();
}

function convertLess(req, res, next) {
   getCssForRequest(req, res)
   .then(outputCss(req, res))
   .then(logRequest(req, res))
   .catch(handleFailure(req, res));
}

function getCssForRequest(req, res) {
   return cache.getCachedResponse(req)
   .then(function(cachedCss) {
      return cachedCss || parseAndRenderCss(req)
   })
}

function parseAndRenderCss(req) {
   return parseLess(req)
   .then(includeSessionContents(req))
   .then(renderCss(req))
   .then(storeInCache(req))
}

function handleFailure(req, res) {
   return function (err) {
      var message = less.formatError(err, {color:false})
      l("Got Error: " + req.url + "\n" +  message)
      l(err);
      res.statusCode = 500;
      res.end("" + message)
   }
}

function parseLess(req) {
   var deferred = Q.defer()
   var parser = new less.Parser(req.parserOptions);
   parser.parse(req.body, deferred.makeNodeResolver());
   return deferred.promise;
}

function includeSessionContents(req) {
   return function(ast) {
      if (req.session) {
         ast.rules = req.session.ast.rules.concat(ast.rules);
      }
      return ast;
   }
}

function outputCss(req, res) {
   return function (css) {
      res.writeHead(200, "Content-Type: text/css");
      res.end(css);
      return css;
   }
}

function renderCss(req) {
   return function (parseTree) {
      return parseTree.toCSS(req.parserOptions);
   };
}

function storeInCache(req) {
   return function(css) {
      return cache.setCachedResponse(req, css)
   };
}

function logRequest(req, res) {
   return function(css) {
      var time = process.hrtime(req.time);
      var ms = time[0]*1000 + time[1] / 1e6
      var outLength = Buffer.byteLength(css)
      var sizeMsg = round(req.body.length/1000) + "k -> " + round(outLength/1000) + "k"
      l("("+round(ms)+"ms - "+sizeMsg+"):" + req.url)
   }
}

function round(num, places) {
   var scale = Math.pow(10, places === undefined ? 1: places)
   return Math.round(num*scale)/scale
}

<commit_msg>Missing session: dont use Error<commit_after>var Q    = require('q')
   ,connect = require('connect')
   ,http = require('http')
   ,less = require('less')
   ,getBody = require('./get-body.js')
   ,parserOptions = require('./parser-options.js')
   ,sessions = require('./sessions.js')()
   ,Cache = require('./cache.js')
   ,DummyCache = require('./dummy-cache.js')
   ,cache = null
   ,l    = require('./log.js').log;

module.exports = function(config) {
   var app = connect()
   .use(denyNonPosts)
   .use(receiveBody)
   .use(connect.query())
   .use(extractParserOptions)
   .use('/session', createSession)
   .use(lookupSession)
   .use(convertLess)

   if (!config || !config.memcache) {
      cache = DummyCache;
      l("Using Dummy Cache");
   } else {
      l("Using memcache");
      cache = Cache(config);
   }

   return http.createServer(app)
}

function denyNonPosts(req, res, next) {
   if (req.method !== 'POST') {
      res.statusCode = 404;
      return res.end();
   }
   next();
}

function receiveBody(req, res, next) {
   req.time = process.hrtime();
   getBody(req).then(function(body) {
      req.body = body;
      next();
   })
}

function extractParserOptions(req, res, next) {
   if (req.query.options) {
      req.parserOptions = parserOptions(JSON.parse(req.query.options || null))
   }
   next();
}

function createSession(req, res, next) {
   sessions.create(req.body, req.parserOptions)
   .then(function(session) {
      res.end(session.token)
   }).catch(handleFailure(res, req));
}

function lookupSession(req, res, next) {
   if (req.query.session) {
      var session = sessions.get(req.query.session);
      if (!session || !session.ast) {
         var error = "Session "+req.query.session+" not found!";
         return handleFailure(req, res)(error);
      }
      req.session = session;
   }
   next();
}

function convertLess(req, res, next) {
   getCssForRequest(req, res)
   .then(outputCss(req, res))
   .then(logRequest(req, res))
   .catch(handleFailure(req, res));
}

function getCssForRequest(req, res) {
   return cache.getCachedResponse(req)
   .then(function(cachedCss) {
      return cachedCss || parseAndRenderCss(req)
   })
}

function parseAndRenderCss(req) {
   return parseLess(req)
   .then(includeSessionContents(req))
   .then(renderCss(req))
   .then(storeInCache(req))
}

function handleFailure(req, res) {
   return function (err) {
      var message = less.formatError(err, {color:false})
      l("Got Error: " + req.url + "\n" +  message)
      l(err);
      res.statusCode = 500;
      res.end("" + message)
   }
}

function parseLess(req) {
   var deferred = Q.defer()
   var parser = new less.Parser(req.parserOptions);
   parser.parse(req.body, deferred.makeNodeResolver());
   return deferred.promise;
}

function includeSessionContents(req) {
   return function(ast) {
      if (req.session) {
         ast.rules = req.session.ast.rules.concat(ast.rules);
      }
      return ast;
   }
}

function outputCss(req, res) {
   return function (css) {
      res.writeHead(200, "Content-Type: text/css");
      res.end(css);
      return css;
   }
}

function renderCss(req) {
   return function (parseTree) {
      return parseTree.toCSS(req.parserOptions);
   };
}

function storeInCache(req) {
   return function(css) {
      return cache.setCachedResponse(req, css)
   };
}

function logRequest(req, res) {
   return function(css) {
      var time = process.hrtime(req.time);
      var ms = time[0]*1000 + time[1] / 1e6
      var outLength = Buffer.byteLength(css)
      var sizeMsg = round(req.body.length/1000) + "k -> " + round(outLength/1000) + "k"
      l("("+round(ms)+"ms - "+sizeMsg+"):" + req.url)
   }
}

function round(num, places) {
   var scale = Math.pow(10, places === undefined ? 1: places)
   return Math.round(num*scale)/scale
}

<|endoftext|>


<commit_before>// vim: set sts=2 sw=2 ts=2 et:
/*
 * grunt-literate
 * https://github.com/phadej/grunt-quotmark
 *
 * Copyright (c) 2013 Oleg Grenrus
 * Licensed under the BSD3 license.
 */

/**

# grunt-literate

> Generate docs from your source

[![Build Status](https://travis-ci.org/phadej/grunt-literate.png)](https://travis-ci.org/phadej/grunt-literate)
[![Code Climate](https://codeclimate.com/github/phadej/grunt-literate.png)](https://codeclimate.com/github/phadej/grunt-literate)
[![NPM version](https://badge.fury.io/js/grunt-literate.png)](http://badge.fury.io/js/grunt-literate)
[![Dependency Status](https://gemnasium.com/phadej/grunt-literate.png)](https://gemnasium.com/phadej/grunt-literate)

## Getting Started

This plugin requires Grunt `~0.4.1`

If you haven't used [Grunt](http://gruntjs.com/) before,
be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide,
as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins.

Once you're familiar with that process, you may install this plugin with this command:

```sh
npm install grunt-literate --save-dev
```

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:

```js
grunt.loadNpmTasks('grunt-literate');
```

## The "literate" task

In your project's Gruntfile, add a section named `literate` to the data object passed into `grunt.initConfig()`.

```js
grunt.initConfig({
  literate: {
     "README.md": "lib/foobar.js"
  }
});
```

The source will be parsed as JavaScript, and `/** ... ` comments extracted to the destionation file.
This example uses markdown, but you are free to use any format, or even just plain text.

### Options

- `boolean code = false`, whether to include code parts or not

### Directives

Comments starting with triple slash `///` are directive comments. Currently supported directives are:

- `include` _filename_: include process _filename_ here.
- `plain` _filename_: include _filename_ here, without any processing, as is.

*/
/// include ../lib/*
/// include ../bin/ljs.js
/// plain ../beautiful-docs.md
/// plain ../CONTRIBUTING.md
/// plain ../CHANGELOG.md
/// plain ../footer.md
/// plain ../LICENSE

"use strict";

var literate = require("../lib/literate.js");
var assert = require("assert");

module.exports = function(grunt) {
  grunt.registerMultiTask("literate", "Generate docs from your source", function() {
    var options = this.options({
      code: false,
    });

    this.files.forEach(function (f) {
      assert(f.dest, "dest argument is required");
      var content = "";

      try {
      f.src.forEach(function (filename) {
        content += literate(filename, options);
      });
      } catch (e) {
        console.log(e.stack);
      }

      // Write file
      grunt.file.write(f.dest, content);
    });
  });
};
<commit_msg>Fix typo<commit_after>// vim: set sts=2 sw=2 ts=2 et:
/*
 * grunt-literate
 * https://github.com/phadej/grunt-quotmark
 *
 * Copyright (c) 2013 Oleg Grenrus
 * Licensed under the BSD3 license.
 */

/**

# grunt-literate

> Generate docs from your source

[![Build Status](https://travis-ci.org/phadej/grunt-literate.png)](https://travis-ci.org/phadej/grunt-literate)
[![Code Climate](https://codeclimate.com/github/phadej/grunt-literate.png)](https://codeclimate.com/github/phadej/grunt-literate)
[![NPM version](https://badge.fury.io/js/grunt-literate.png)](http://badge.fury.io/js/grunt-literate)
[![Dependency Status](https://gemnasium.com/phadej/grunt-literate.png)](https://gemnasium.com/phadej/grunt-literate)

## Getting Started

This plugin requires Grunt `~0.4.1`

If you haven't used [Grunt](http://gruntjs.com/) before,
be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide,
as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins.

Once you're familiar with that process, you may install this plugin with this command:

```sh
npm install grunt-literate --save-dev
```

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:

```js
grunt.loadNpmTasks('grunt-literate');
```

## The "literate" task

In your project's Gruntfile, add a section named `literate` to the data object passed into `grunt.initConfig()`.

```js
grunt.initConfig({
  literate: {
     "README.md": "lib/foobar.js"
  }
});
```

The source will be parsed as JavaScript, and `/** ... ` comments extracted to the destination file.
This example uses markdown, but you are free to use any format, or even just plain text.

### Options

- `boolean code = false`, whether to include code parts or not

### Directives

Comments starting with triple slash `///` are directive comments. Currently supported directives are:

- `include` _filename_: include process _filename_ here.
- `plain` _filename_: include _filename_ here, without any processing, as is.

*/
/// include ../lib/*
/// include ../bin/ljs.js
/// plain ../beautiful-docs.md
/// plain ../CONTRIBUTING.md
/// plain ../CHANGELOG.md
/// plain ../footer.md
/// plain ../LICENSE

"use strict";

var literate = require("../lib/literate.js");
var assert = require("assert");

module.exports = function(grunt) {
  grunt.registerMultiTask("literate", "Generate docs from your source", function() {
    var options = this.options({
      code: false,
    });

    this.files.forEach(function (f) {
      assert(f.dest, "dest argument is required");
      var content = "";

      try {
      f.src.forEach(function (filename) {
        content += literate(filename, options);
      });
      } catch (e) {
        console.log(e.stack);
      }

      // Write file
      grunt.file.write(f.dest, content);
    });
  });
};
<|endoftext|>


<commit_before>import React from 'react';
import CurrencyPair from './currency-pair';
import _ from 'lodash';

import transport from '../utils/transport';

//todo: hook up socket stream
let pairs = [];

const STALE_TIMEOUT = 5000;

/**
 * @class CurrencyPairs
 * @extends {React.Component}
 */
class CurrencyPairs extends React.Component {

  /**
   * @constructs CurrencyPair
   * @param {Object=} props
   * @param {Object=} context
   */
  constructor(props, context){
    super(props, context);
    this.state = {
      pairs: []
    };

    this.subscribed = [];
  }

  /**
   * Deals with socket comms for pairs - gets reference data, subscribes to each pair.
   */
  attachSubs(){
    transport.subscribe('reference.getCurrencyPairUpdatesStream', (referenceData) => {
      const update = _.debounce((src) => {
        this.setState({
          pairs: src || this.state.pairs
        });
      }, 500);

      // normalise the currency pair reference data
      const pairs = _.map(referenceData.Updates, (updatedPair) => {
        const pair = updatedPair.CurrencyPair;

        if (updatedPair.UpdateType == 0){

          return {
            //todo: accept rawPair.PipPosition and rawPair.RatePrecision
            pip: 5,
            precision: 5,
            pair: pair.Symbol,
            id: pair.Symbol,
            buy: undefined,
            sell: undefined
          };
        }
        else {
          // removed?
          console.log(updatedPair.UpdateType);
          update(this.state.pairs.filter((p) => p.id != pair.Symbol));
          transport.unsubscribe('pricing.getPriceUpdates', existing.handler, {id: pair.Symbol})
        }
      }, this);

      this.setState({
        pairs: pairs
      });

      // subscribe to individual streams
      this.state.pairs.forEach((pair) => {
        transport.subscribe('pricing.getPriceUpdates', pair.handler = (priceData) => {
          let found = _.findWhere(this.state.pairs, {id: priceData.symbol});

          if (!found){
            //todo: we should unsubscribe!
            return;
          }

          found.buy = Number(priceData.bid);
          found.sell = Number(priceData.ask);

          update();
        }, {
          symbol: pair.id
        })
      });
    });
  }

  componentWillMount(){
    if (transport.isOpen){
      this.attachSubs();
    }
    else {
      transport.on('open', () => this.attachSubs());
    }
    this.setState({
      pairs: pairs
    });
  }

  onACK(payload){
    const pairs = this.state.pairs,
          pair = _.findWhere(pairs, {pair: payload.pair});

    pair.state = 'listening';
    pair.response = payload;

    this.setState({
      pairs
    });
  }

  componentDidUpdate(){
    // silently remove last response
    this.state.pairs.forEach((pair)=>{
      delete pair.response;
    });
  }

  onExecute(payload){
    //todo: send to socket.
    if (this.props.onExecute){
      const pair = _.findWhere(this.state.pairs, {pair: payload.pair});
      pair.state = 'executing';

      payload.onACK = (...args) => this.onACK(...args);

      this.props.onExecute(payload);
    }
  }

  render(){
    // filter cps that have got pric data only.
    const p = this.state.pairs.filter((a) => {
      return a.buy && a.sell;
    });

    return

        ReactiveTrader

            Admin Cluster

{p.length ? 'online' : 'Waiting for pricing data...'}

        {p.length ? p.map((cp) => {
          return <CurrencyPair onExecute={(payload) => this.onExecute(payload)}
                               pair={cp.pair}
                               size="100m"
                               key={cp.id}
                               buy={cp.buy}
                               sell={cp.sell}
                               precision={cp.precision}
                               pip={cp.pip}
                               state={cp.state}
                               response={cp.response} />
        }) :

 }

  }
}

export default CurrencyPairs;
<commit_msg>stale connections marked again<commit_after>import React from 'react';
import CurrencyPair from './currency-pair';
import _ from 'lodash';

import transport from '../utils/transport';

//todo: hook up socket stream
let pairs = [];

const STALE_TIMEOUT = 4000;

/**
 * @class CurrencyPairs
 * @extends {React.Component}
 */
class CurrencyPairs extends React.Component {

  /**
   * @constructs CurrencyPair
   * @param {Object=} props
   * @param {Object=} context
   */
  constructor(props, context){
    super(props, context);
    this.state = {
      pairs: []
    };

    this.subscribed = [];
  }

  /**
   * Deals with socket comms for pairs - gets reference data, subscribes to each pair.
   */
  attachSubs(){
    transport.subscribe('reference.getCurrencyPairUpdatesStream', (referenceData) => {
      const update = _.debounce((src) => {
        const pairs = src || this.state.pairs;

        pairs.forEach((pair) => {
          pair.state = Date.now() - (pair.lastUpdated || 0) > STALE_TIMEOUT ? 'stale' : 'listening';
        });

        this.setState({
          pairs: pairs
        });
      }, 5);

      // normalise the currency pair reference data
      const pairs = _.map(referenceData.Updates, (updatedPair) => {
        const pair = updatedPair.CurrencyPair;

        if (updatedPair.UpdateType == 0){

          return {
            //todo: accept rawPair.PipPosition and rawPair.RatePrecision
            pip: 5,
            precision: 5,
            pair: pair.Symbol,
            id: pair.Symbol,
            buy: undefined,
            sell: undefined
          };
        }
        else {
          // removed?
          // console.log(updatedPair.UpdateType);
          update(this.state.pairs.filter((p) => p.id != pair.Symbol));
          transport.unsubscribe('pricing.getPriceUpdates', existing.handler, {id: pair.Symbol})
        }
      }, this);

      this.setState({
        pairs: pairs
      });

      // subscribe to individual streams
      this.state.pairs.forEach((pair) => {
        transport.subscribe('pricing.getPriceUpdates', pair.handler = (priceData) => {
          let existingPair = _.findWhere(this.state.pairs, {id: priceData.symbol});

          if (!existingPair){
            //todo: we should unsubscribe!
            return;
          }

          existingPair.buy = Number(priceData.bid);
          existingPair.sell = Number(priceData.ask);

          existingPair.lastUpdated = Date.now();

          update();
        }, {
          symbol: pair.id
        })
      });
    });
  }

  componentWillMount(){
    if (transport.isOpen){
      this.attachSubs();
    }
    else {
      transport.on('open', () => this.attachSubs());
    }
    this.setState({
      pairs: pairs
    });
  }

  onACK(payload){
    const pairs = this.state.pairs,
          pair = _.findWhere(pairs, {pair: payload.pair});

    pair.state = 'listening';
    pair.response = payload;

    this.setState({
      pairs
    });
  }

  componentDidUpdate(){
    // silently remove last response
    this.state.pairs.forEach((pair)=>{
      delete pair.response;
    });
  }

  onExecute(payload){
    //todo: send to socket.
    if (this.props.onExecute){
      const pair = _.findWhere(this.state.pairs, {pair: payload.pair});
      pair.state = 'executing';

      payload.onACK = (...args) => this.onACK(...args);

      this.props.onExecute(payload);
    }
  }

  render(){
    // filter cps that have got price data only.
    const p = this.state.pairs.filter((a) => {
      return a.buy && a.sell;
    });

    return

        ReactiveTrader

            Admin Cluster

{p.length ? 'online' : 'Waiting for pricing data...'}

        {p.length ? p.map((cp) => {
          return <CurrencyPair onExecute={(payload) => this.onExecute(payload)}
                               pair={cp.pair}
                               size="100m"
                               key={cp.id}
                               buy={cp.buy}
                               sell={cp.sell}
                               precision={cp.precision}
                               pip={cp.pip}
                               state={cp.state}
                               response={cp.response} />
        }) :

 }

  }
}

export default CurrencyPairs;
<|endoftext|>


<commit_before>"use strict";

const PORT        = process.env.PORT || 8080;
const ENV         = process.env.ENV || "development";
const express     = require("express");
const bodyParser  = require("body-parser");
const sass        = require("node-sass-middleware");
const app         = express();

const knexConfig  = require("./knexfile");
const knex        = require("knex")(knexConfig[ENV]);
const morgan      = require('morgan');
const knexLogger  = require('knex-logger');

// Seperated Routes for each Resource
const usersRoutes = require("./routes/users");

const accountSid = process.env.TWILIO_KEY;
const authToken =  process.env.TWILIO_SECRET;
const client = require('twilio')(accountSid, authToken);

app.use(morgan('dev'));

// Log knex SQL queries to STDOUT as well
app.use(knexLogger(knex));

app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/styles", sass({
  src: __dirname + "/styles",
  dest: __dirname + "/public/styles",
  debug: true,
  outputStyle: 'expanded'
}));
app.use(express.static("public"));

// Mount all resource routes

app.post('/sms', function(req, res) {
  const MessagingResponse = require('twilio').twiml.MessagingResponse;
  var twiml = new MessagingResponse();

  knex('order').select('status').where('phone','=',req.body.From).asCallback((err,row) =>{
    if(err)console.error(err);
    var status = row[0].status;

    if(status==='ordered'){
      if(req.body.Body.toLowerCase() === 'confirm'){
        twiml.message('Thanks, your order is now being processed');
        res.writeHead(200, {'Content-Type': 'text/xml'});
        console.log(req.body.From);
        knex('order')
          .where('phone', '=', req.body.From)
          .update({
            status: 'confirmed',
          }).asCallback((err)=>{
            if(err)console.error(err);
            knex.select('*').from('order').asCallback((err,rows)=>{
              if(err)console.error(err);
              console.log(rows);
              res.end(twiml.toString());
            });
        });
      }else if(req.body.Body.toLowerCase()==='decline'){
        twiml.message('Your order has been cancelled');
        res.writeHead(200, {'Content-Type': 'text/xml'});
        knex('order')
          .where('phone', '=', req.body.from)
          .del().asCallback((err)=>{
            if(err)console.error(err);
            res.end(twiml.toString());
          });
      }
    }else if(status==='confirmed'){
      if(req.body.Body.toLowerCase() === 'receipt'){
        knex('order').select('receipt').where('phone','=',req.body.From).asCallback((err,row) =>{
          if(err)console.error(err);
          var receipt = row[0].receipt;
        });
        twiml.message(`Here is your current order: \n
          ${receipt}
          `);
        res.writeHead(200, {'Content-Type': 'text/xml'});
        console.log(req.body.From);
        knex('order')
          .where('phone', '=', req.body.From)
          .update({
            status: 'confirmed',
          }).asCallback((err)=>{
            if(err)console.error(err);
            knex.select('*').from('order').asCallback((err,rows)=>{
              if(err)console.error(err);
              console.log(rows);
            });
          res.end(twiml.toString());
        });
      }else if(req.body.Body.toLowerCase()==='decline'){
        twiml.message('Your order has been cancelled');
        res.writeHead(200, {'Content-Type': 'text/xml'});
        knex('order')
          .where('phone', '=', req.body.from)
          .del().asCallback((err)=>{
            if(err)console.error(err);
            res.end(twiml.toString());
          });
      }
    }
  });
});

app.post("/order", (req, res) => {
    client.messages.create({
    to: process.env.VERIFIED_NUMBER,
    from: process.env.TWILIO_NUMBER,
    body: `Your order has been placed ${req.body.name}: \n${req.body.receipt.replace(/<\/tr>/g,'\n').replace(/<[^>]*>/g,'')}\n
    text "confirm" to start the order or text "cancel" to undo`,
  }).then((message) => {
      knex('order').insert({
        name: req.body.name || 'kyle',
        phone: process.env.VERIFIED_NUMBER,
        receipt: req.body.receipt.replace(/<\/tr]/g,'\n').replace(/<[^>]*>/g,''),
        status: 'ordered'

      }).asCallback((err)=>{
          if(err)console.error(err);
          res.send(message.sid);
      })

    });
  });

var receipt =function(){ app.post('/receipt', (req, res) => {
  const VoiceResponse = require('twilio').twiml.VoiceResponse;
  const twiml = new VoiceResponse();
  twiml.say('Kyle has placed an order');
  res.writeHead(200, { 'Content-Type': 'text/xml' });
  res.end(twiml.toString());

})};

app.use("/api/users", usersRoutes(knex));

// Home page
app.get("/", (req, res) => {
  res.redirect('/menu');
});

app.get("/menu", (req, res) => {
 knex.select('name','price','type').from('dishes').asCallback((err,rows)=>{
    if (err) return console.error(err);
      let templateVars = {
        dishes:rows,
        dish:{},
        addons:{}
      }
      knex.select('*').from('dishes').where('name','Billionaire Burger').asCallback((err,row)=>{
         if (err) return console.error(err);
           templateVars.dish = row;
          knex.select('name','price','pic').from('dishes').where('type','sides').asCallback((err,sides)=>{
            templateVars.addons = sides;
            console.log(templateVars);
            res.render('index',templateVars)
          });
    });
  });

app.get("/menu/:name",(req, res) => {
  console.log(req.params.name);
  knex.select('*').from('dishes').where('name',req.params.name).asCallback((err,row)=>{
     if (err) return console.error(err);
       res.json({
         dish:row[0]
       });
     })
   });
});

app.post("/cart",(req, res) => {
  if(!req.body.name)return console.error('param does not exist');
  console.log(req.body.name);

  knex('menu_cart').insert({
    cart_id: knex.select('id').from('cart').where('owner','Kyle'),
    menu_id: knex.select('id').from('dishes').where('name',req.body.name),
    quantity: req.body.quantity
  }).asCallback((err)=>{
    if (err) return console.error(err);
    knex.countDistinct("menu_id").from('menu_cart').where('cart_id',knex.select('id').from('cart').where('owner','Kyle')).asCallback((err,row)=>{
      if (err) return console.error(err);
          res.json({
            items: row[0]
          });
        });
      });
    });

app.get("/cart", (req, res) => {
  knex('dishes')
  .leftJoin('menu_cart','dishes.id','menu_cart.menu_id')
  .leftJoin('cart','menu_cart.cart_id','cart.id')
  .select('name','price', 'menu_cart.quantity as quantity').distinct()
  .whereNotNull('quantity')
  .asCallback((err,rows)=>{
    console.log(rows)
    let templateVars = {
      cart : rows
    }
     res.json(templateVars);
  })
});
app.listen(PORT, () => {
  console.log("Example app listening on port " + PORT);
});
<commit_msg>removed useless code<commit_after>"use strict";

const PORT        = process.env.PORT || 8080;
const ENV         = process.env.ENV || "development";
const express     = require("express");
const bodyParser  = require("body-parser");
const sass        = require("node-sass-middleware");
const app         = express();

const knexConfig  = require("./knexfile");
const knex        = require("knex")(knexConfig[ENV]);
const morgan      = require('morgan');
const knexLogger  = require('knex-logger');

// Seperated Routes for each Resource
const usersRoutes = require("./routes/users");

const accountSid = process.env.TWILIO_KEY;
const authToken =  process.env.TWILIO_SECRET;
const client = require('twilio')(accountSid, authToken);

app.use(morgan('dev'));

// Log knex SQL queries to STDOUT as well
app.use(knexLogger(knex));

app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/styles", sass({
  src: __dirname + "/styles",
  dest: __dirname + "/public/styles",
  debug: true,
  outputStyle: 'expanded'
}));
app.use(express.static("public"));

// Mount all resource routes

app.post('/sms', function(req, res) {
  const MessagingResponse = require('twilio').twiml.MessagingResponse;
  var twiml = new MessagingResponse();

  knex('order').select('status').where('phone','=',req.body.From).asCallback((err,row) => {
    if(err)console.error(err);
    var status = row[0].status;
  }).then(function(){
    if(status==='ordered'){
      if(req.body.Body.toLowerCase() === 'confirm'){
        twiml.message('Thanks, your order is now being processed');
        res.writeHead(200, {'Content-Type': 'text/xml'});
        console.log(req.body.From);
        knex('order')
          .where('phone', '=', req.body.From)
          .update({
            status: 'confirmed',
          }).asCallback((err)=>{
            if(err)console.error(err);
            knex.select('*').from('order').asCallback((err,rows)=>{
              if(err)console.error(err);
              console.log(rows);
              res.end(twiml.toString());
            });
        });
      }else if(req.body.Body.toLowerCase()==='decline'){
        twiml.message('Your order has been cancelled');
        res.writeHead(200, {'Content-Type': 'text/xml'});
        knex('order')
          .where('phone', '=', req.body.from)
          .del().asCallback((err)=>{
            if(err)console.error(err);
            res.end(twiml.toString());
          });
      }
    }else if(status==='confirmed'){
      if(req.body.Body.toLowerCase() === 'receipt'){
        knex('order').select('receipt').where('phone','=',req.body.From).asCallback((err,row) =>{
          if(err)console.error(err);
          var receipt = row[0].receipt;
        }).then(function(){
        twiml.message(`Here is your current order: \n
          ${receipt}
          `);
        res.writeHead(200, {'Content-Type': 'text/xml'});
        console.log(req.body.From);
        knex('order')
          .where('phone', '=', req.body.From)
          .update({
            status: 'confirmed',
          }).asCallback((err)=>{
            if(err)console.error(err);
            knex.select('*').from('order').asCallback((err,rows)=>{
              if(err)console.error(err);
              console.log(rows);
            });
          res.end(twiml.toString());
        });
      }else if(req.body.Body.toLowerCase()==='decline'){
        twiml.message('Your order has been cancelled');
        res.writeHead(200, {'Content-Type': 'text/xml'});
        knex('order')
          .where('phone', '=', req.body.from)
          .del().asCallback((err)=>{
            if(err)console.error(err);
            res.end(twiml.toString());
          });
      }
    });
    }
  });
});

app.post("/order", (req, res) => {
    client.messages.create({
    to: process.env.VERIFIED_NUMBER,
    from: process.env.TWILIO_NUMBER,
    body: `Your order has been placed ${req.body.name}: \n${req.body.receipt.replace(/<\/tr>/g,'\n').replace(/<[^>]*>/g,'')}\n
    text "confirm" to start the order or text "cancel" to undo`,
  }).then((message) => {
      knex('order').insert({
        name: req.body.name || 'kyle',
        phone: process.env.VERIFIED_NUMBER,
        receipt: req.body.receipt.replace(/<\/tr]/g,'\n').replace(/<[^>]*>/g,''),
        status: 'ordered'
      }).asCallback((err)=>{
          if(err)console.error(err);
          res.send(message.sid);
      });
    });
  });
app.use("/api/users", usersRoutes(knex));

// Home page
app.get("/", (req, res) => {
  res.redirect('/menu');
});

app.get("/menu", (req, res) => {
 knex.select('name','price','type').from('dishes').asCallback((err,rows)=>{
    if (err) return console.error(err);
      let templateVars = {
        dishes:rows,
        dish:{},
        addons:{}
      }
      knex.select('*').from('dishes').where('name','Billionaire Burger').asCallback((err,row)=>{
         if (err) return console.error(err);
           templateVars.dish = row;
          knex.select('name','price','pic').from('dishes').where('type','sides').asCallback((err,sides)=>{
            templateVars.addons = sides;
            console.log(templateVars);
            res.render('index',templateVars)
          });
    });
  });

app.get("/menu/:name",(req, res) => {
  console.log(req.params.name);
  knex.select('*').from('dishes').where('name',req.params.name).asCallback((err,row)=>{
     if (err) return console.error(err);
       res.json({
         dish:row[0]
       });
     })
   });
});

app.post("/cart",(req, res) => {
  if(!req.body.name)return console.error('param does not exist');
  console.log(req.body.name);

  knex('menu_cart').insert({
    cart_id: knex.select('id').from('cart').where('owner','Kyle'),
    menu_id: knex.select('id').from('dishes').where('name',req.body.name),
    quantity: req.body.quantity
  }).asCallback((err)=>{
    if (err) return console.error(err);
    knex.countDistinct("menu_id").from('menu_cart').where('cart_id',knex.select('id').from('cart').where('owner','Kyle')).asCallback((err,row)=>{
      if (err) return console.error(err);
          res.json({
            items: row[0]
          });
        });
      });
    });

app.get("/cart", (req, res) => {
  knex('dishes')
  .leftJoin('menu_cart','dishes.id','menu_cart.menu_id')
  .leftJoin('cart','menu_cart.cart_id','cart.id')
  .select('name','price', 'menu_cart.quantity as quantity').distinct()
  .whereNotNull('quantity')
  .asCallback((err,rows)=>{
    console.log(rows)
    let templateVars = {
      cart : rows
    }
     res.json(templateVars);
  })
});
app.listen(PORT, () => {
  console.log("Example app listening on port " + PORT);
});
<|endoftext|>


<commit_before>var s2 = require('s2'),
    normalize = require('geojson-normalize'),
    geojsonExtent = require('geojson-extent'),
    constants = require('./constants');

var serialization = 'toToken';

module.exports.constants = function(_constants) {
    if (!arguments.length) return constants;
    constants = _constants;
};

module.exports.bboxQueryIndexes = function(bbox) {
    var latLngRect = new s2.S2LatLngRect(
        new s2.S2LatLng(bbox[1], bbox[0]),
        new s2.S2LatLng(bbox[3], bbox[2]));

    var cover_options = {
        min: constants.QUERY_MIN_LEVEL,
        max: constants.QUERY_MAX_LEVEL,
        max_cells: constants.MAX_INDEX_CELLS
    };

    return s2.getCover(latLngRect, cover_options).map(function(cell) {
        return [
            cell.id().rangeMin().toToken(),
            cell.id().rangeMax().toToken()
        ];
    });
};

module.exports.bboxCellGeoJSON = function(bbox) {
    var latLngRect = new s2.S2LatLngRect(
        new s2.S2LatLng(bbox[1], bbox[0]),
        new s2.S2LatLng(bbox[3], bbox[2]));

    var cover_options = {
        min: constants.QUERY_MIN_LEVEL,
        max: constants.QUERY_MAX_LEVEL,
        max_cells: constants.MAX_INDEX_CELLS
    };
    return s2.getCover(latLngRect, cover_options).map(function(c) {
        return c.toGeoJSON();
    });
};

module.exports.geometry = function(input) {
    var geom = normalize(input).features[0].geometry;
    switch (geom.type) {
        case 'Point':
            return pointIndex(geom.coordinates);
        case 'Polygon':
            return polygonIndex(geom);
        default:
            return [];
    }
};

function pointIndex(coords) {
    var id = new s2.S2CellId(new s2.S2LatLng(coords[1], coords[0]));
    return [id.parent(constants.INDEX_POINT_LEVEL).toToken()];
}

function lineIndex(coords) {
    return polygonIndex(geojsonExtent.polygon(geometry));
}

function polygonIndex(geometry) {

    var rings = geometry.coordinates;

    var cover_options = {
        min: constants.INDEX_MIN_LEVEL,
        max: constants.INDEX_MAX_LEVEL,
        max_cells: constants.MAX_INDEX_CELLS,
        type: 'polygon'
    };

    // GeoJSON
    var llRings = rings.map(function(ring){
        return ring.map(function(c){
            var latLng = (new s2.S2LatLng(c[1], c[0])).normalized();
            return latLng.toPoint();
        }).slice(1)
    })

    return s2.getCover(llRings, cover_options).map(function(cell) {
        return cell.id().toToken();
    });
}
<commit_msg>formatting<commit_after>var s2 = require('s2'),
    normalize = require('geojson-normalize'),
    geojsonExtent = require('geojson-extent'),
    constants = require('./constants');

var serialization = 'toToken';

module.exports.constants = function(_constants) {
    if (!arguments.length) return constants;
    constants = _constants;
};

module.exports.bboxQueryIndexes = function(bbox) {
    var latLngRect = new s2.S2LatLngRect(
        new s2.S2LatLng(bbox[1], bbox[0]),
        new s2.S2LatLng(bbox[3], bbox[2]));

    var cover_options = {
        min: constants.QUERY_MIN_LEVEL,
        max: constants.QUERY_MAX_LEVEL,
        max_cells: constants.MAX_INDEX_CELLS
    };

    return s2.getCover(latLngRect, cover_options).map(function(cell) {
        return [
            cell.id().rangeMin().toToken(),
            cell.id().rangeMax().toToken()
        ];
    });
};

module.exports.bboxCellGeoJSON = function(bbox) {
    var latLngRect = new s2.S2LatLngRect(
        new s2.S2LatLng(bbox[1], bbox[0]),
        new s2.S2LatLng(bbox[3], bbox[2]));

    var cover_options = {
        min: constants.QUERY_MIN_LEVEL,
        max: constants.QUERY_MAX_LEVEL,
        max_cells: constants.MAX_INDEX_CELLS
    };
    return s2.getCover(latLngRect, cover_options).map(function(c) {
        return c.toGeoJSON();
    });
};

module.exports.geometry = function(input) {
    var geom = normalize(input).features[0].geometry;
    switch (geom.type) {
        case 'Point':
            return pointIndex(geom.coordinates);
        case 'Polygon':
            return polygonIndex(geom);
        default:
            return [];
    }
};

function pointIndex(coords) {
    var id = new s2.S2CellId(new s2.S2LatLng(coords[1], coords[0]));
    return [id.parent(constants.INDEX_POINT_LEVEL).toToken()];
}

function lineIndex(coords) {
    return polygonIndex(geojsonExtent.polygon(geometry));
}

function polygonIndex(geometry) {

    var rings = geometry.coordinates;

    var cover_options = {
        min: constants.INDEX_MIN_LEVEL,
        max: constants.INDEX_MAX_LEVEL,
        max_cells: constants.MAX_INDEX_CELLS,
        type: 'polygon'
    };

    // GeoJSON
    var llRings = rings.map(function(ring){
        return ring.map(function(c){
            var latLng = (new s2.S2LatLng(c[1], c[0])).normalized();
            return latLng.toPoint();
        }).slice(1);
    });

    return s2.getCover(llRings, cover_options).map(function(cell) {
        return cell.id().toToken();
    });
}
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var CachingWriter = require('broccoli-caching-writer');
var path = require('path');
var walkSync = require('walk-sync');
var fs = require('fs');
var mkdirp = require('mkdirp');
var funnel = require('broccoli-funnel');

var Processor = CachingWriter.extend({
    updateCache: function(srcPaths, destDir) {
//         console.log('updateCache:', srcPaths[0], destDir);
        var paths = walkSync(srcPaths[0]);

        var first = true;
        for (var i = 0, l = paths.length; i < l; i++) {
            var filepath = paths[i];

            // Check that it's not a directory
            if (filepath[filepath.length-1] !== '/' && !filepath.match(new RegExp(/metadata/))) {
                var fileContents = fs.readFileSync(path.join(srcPaths[0], filepath)).toString();

                var match = fileContents.match(/Tomahawk\.resolver\.instance\s*=\s*(.*)\s*;/);
                if(match && match[1]) {

                    var importString = "";
                    importString += 'import Tomahawk from \'' + this.tomahawkGlobal + '\';';
                    importString += 'import { TomahawkResolver, TomahawkResolverCapability } from \'' + this.tomahawkGlobal + '\';';

                    fileContents = importString + fileContents.replace(match[0], 'export default ' + match[1]);

                    var split = filepath.split('/');
                    var filename = split[split.length-1];
                    var destPath = path.join(destDir, 'tomahawk-javascript-plugin-compiler', 'resolvers', filename);
                    mkdirp.sync(path.dirname(destPath));
                    fs.writeFileSync(destPath, fileContents);
                }
            }
        }
    }
});

module.exports = {
    name: 'tomahawk-javascript-plugin-compiler',

    treeForApp: function (app) {
        if(!this.app) return;

        var processor = new Processor(funnel(this.resolverTree, {
            include: this.includeResolverRegExps
        }));

        processor.tomahawkGlobal = this.tomahawkGlobal;

        return processor;
    },

    treeForPublic: function(app) {
        return funnel(this.resolverTree, {
            include: this.includeIconRegExps,
            exclude: [new RegExp(/metadata/)],
            getDestinationPath: function(relativePath) {
                var split = relativePath.split('/');
                var newPath = 'icons/resolvers/' + split[split.length-1];

//                 console.log('relativePath:', newPath);

                return newPath;
            }
        });

    },

    included: function(app) {
        this._super.included.apply(this, arguments);
        this.app = app;

        this.includeResolverRegExps = [];
        this.includeIconRegExps = [];
        this.includeResolvers = this.app.project.config().includeResolvers || [];
        for(var resolver in this.includeResolvers) {
            this.includeResolverRegExps.push(new RegExp(resolver));
            this.includeIconRegExps.push(new RegExp(this.includeResolvers[resolver].icon+'$'));
        }

        this.tomahawkGlobal = this.app.project.config().tomahawkGlobal || 'tomahawk-javascript-plugin-compiler/tomahawk';
        this.resolverTree = this.app.project.config().resolverTree || path.join(this.app.bowerDirectory, 'tomahawk-resolvers');
    },

    isDevelopingAddon: function () {
        return true;
    }
};
<commit_msg>Put icons in /assets/<commit_after>/* jshint node: true */
'use strict';

var CachingWriter = require('broccoli-caching-writer');
var path = require('path');
var walkSync = require('walk-sync');
var fs = require('fs');
var mkdirp = require('mkdirp');
var funnel = require('broccoli-funnel');

var Processor = CachingWriter.extend({
    updateCache: function(srcPaths, destDir) {
//         console.log('updateCache:', srcPaths[0], destDir);
        var paths = walkSync(srcPaths[0]);

        var first = true;
        for (var i = 0, l = paths.length; i < l; i++) {
            var filepath = paths[i];

            // Check that it's not a directory
            if (filepath[filepath.length-1] !== '/' && !filepath.match(new RegExp(/metadata/))) {
                var fileContents = fs.readFileSync(path.join(srcPaths[0], filepath)).toString();

                var match = fileContents.match(/Tomahawk\.resolver\.instance\s*=\s*(.*)\s*;/);
                if(match && match[1]) {

                    var importString = "";
                    importString += 'import Tomahawk from \'' + this.tomahawkGlobal + '\';';
                    importString += 'import { TomahawkResolver, TomahawkResolverCapability } from \'' + this.tomahawkGlobal + '\';';

                    fileContents = importString + fileContents.replace(match[0], 'export default ' + match[1]);

                    var split = filepath.split('/');
                    var filename = split[split.length-1];
                    var destPath = path.join(destDir, 'tomahawk-javascript-plugin-compiler', 'resolvers', filename);
                    mkdirp.sync(path.dirname(destPath));
                    fs.writeFileSync(destPath, fileContents);
                }
            }
        }
    }
});

module.exports = {
    name: 'tomahawk-javascript-plugin-compiler',

    treeForApp: function (app) {
        if(!this.app) return;

        var processor = new Processor(funnel(this.resolverTree, {
            include: this.includeResolverRegExps
        }));

        processor.tomahawkGlobal = this.tomahawkGlobal;

        return processor;
    },

    treeForPublic: function(app) {
        return funnel(this.resolverTree, {
            include: this.includeIconRegExps,
            exclude: [new RegExp(/metadata/)],
            getDestinationPath: function(relativePath) {
                var split = relativePath.split('/');
                var newPath = '/assets/icons/resolvers/' + split[split.length-1];

//                 console.log('relativePath:', newPath);

                return newPath;
            }
        });

    },

    included: function(app) {
        this._super.included.apply(this, arguments);
        this.app = app;

        this.includeResolverRegExps = [];
        this.includeIconRegExps = [];
        this.includeResolvers = this.app.project.config().includeResolvers || [];
        for(var resolver in this.includeResolvers) {
            this.includeResolverRegExps.push(new RegExp(resolver));
            this.includeIconRegExps.push(new RegExp(this.includeResolvers[resolver].icon+'$'));
        }

        this.tomahawkGlobal = this.app.project.config().tomahawkGlobal || 'tomahawk-javascript-plugin-compiler/tomahawk';
        this.resolverTree = this.app.project.config().resolverTree || path.join(this.app.bowerDirectory, 'tomahawk-resolvers');
    },

    isDevelopingAddon: function () {
        return true;
    }
};
<|endoftext|>


<commit_before>var express = require('express');
var favicon = require('connect-favicons');
var morgan  = require('morgan');
var path    = require('path');
var fs      = require('fs');
var os 		= require('os');

var host, kaliteUrl, wikiUrl;
var port = process.env.NODE_PORT || 3000;
var ifaces = os.networkInterfaces();

Object.keys(ifaces).forEach(function (ifname) {
  var alias = 0;

  ifaces[ifname].forEach(function (iface) {
    if ('IPv4' !== iface.family || iface.internal !== false) {
      // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
      return;
    }

    if (alias >= 1) {
      // this single interface has multiple ipv4 addresses
      console.log(ifname + ':' + alias, iface.address);
    } else {
      // this interface has only one ipv4 adress
      console.log(ifname, iface.address);
    }
    host = null;
	kaliteUrl = 'http://' + add + ':8008';
	wikiUrl   = 'http://' + add + ':8080';
  });
});

var app = express();

app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(favicon(path.join(__dirname, 'public', 'images')));

app.set('view engine', 'ejs');

app.get('/', function (req, res) {
    getI18N(function (err, languages) {
        if (err){
            console.log(err);
        }
        var custom = 'en';
        var selected = req.query.lang || custom;
        var customStrings;
        var selectedStrings;
        for (var i=0; i<languages.length; i++){
            if (languages[i].id == selected){
                selectedStrings = languages[i].strings;
            }
            if (languages[i].id == custom){
                customStrings = languages[i].strings;
            }
        }
        res.render('index.ejs', {
            languages : languages,
            strings : selectedStrings || customStrings,
            kalite : kaliteUrl,
            wiki : wikiUrl
        });
    });
});

function getI18N(done){
    var dir = path.join(__dirname, 'public', 'i18n');
    var languages = [];

    fs.readdir(dir,function(err, files){
        if (err){
            return done(err, languages);
        }
        var count = 0;
        files.forEach(function(file){
            fs.readFile(path.join(dir, file),'utf-8',function(err, language){
                if (err){
                    return done(err, languages);
                }
                var json = JSON.parse(language);
                languages.push(json);
                if (++count == files.length){
                    return done(null, languages);
                }
            });
        });
    });
}

var server = app.listen(port, function () {
  	var host = server.address().address;
  	var port = server.address().port;
  	console.log('Fabulinus Index Server listening at http://%s:%s', host, port);
});
<commit_msg>added dynamic ip address determination<commit_after>var express = require('express');
var favicon = require('connect-favicons');
var morgan  = require('morgan');
var path    = require('path');
var fs      = require('fs');
var os 		= require('os');

var port = process.env.NODE_PORT || 3000;
var host = os.networkInterfaces()['wlan0'][0].address;
var kaliteUrl = 'http://' + host + ':8008';
var wikiUrl   = 'http://' + host + ':8080';

var app = express();

app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(favicon(path.join(__dirname, 'public', 'images')));

app.set('view engine', 'ejs');

app.get('/', function (req, res) {
    getI18N(function (err, languages) {
        if (err){
            console.log(err);
        }
        var custom = 'en';
        var selected = req.query.lang || custom;
        var customStrings;
        var selectedStrings;
        for (var i=0; i<languages.length; i++){
            if (languages[i].id == selected){
                selectedStrings = languages[i].strings;
            }
            if (languages[i].id == custom){
                customStrings = languages[i].strings;
            }
        }
        res.render('index.ejs', {
            languages : languages,
            strings : selectedStrings || customStrings,
            kalite : kaliteUrl,
            wiki : wikiUrl
        });
    });
});

function getI18N(done){
    var dir = path.join(__dirname, 'public', 'i18n');
    var languages = [];

    fs.readdir(dir,function(err, files){
        if (err){
            return done(err, languages);
        }
        var count = 0;
        files.forEach(function(file){
            fs.readFile(path.join(dir, file),'utf-8',function(err, language){
                if (err){
                    return done(err, languages);
                }
                var json = JSON.parse(language);
                languages.push(json);
                if (++count == files.length){
                    return done(null, languages);
                }
            });
        });
    });
}

app.listen(port);
console.log('Fabulinus Index Server listening at http://%s:%s', host, port);
<|endoftext|>


<commit_before>/*
 * grunt-stylecow
 * https://github.com/oscarotero/grunt-stylecow
 *
 * Copyright (c) 2014 oscarotero
 * Licensed under the MIT license.
 */

'use strict';

var stylecow = require('stylecow');

module.exports = function(grunt) {

    grunt.registerMultiTask('stylecow', 'Execute stylecow plugins with grunt', function() {
        var options = this.options(stylecow.defaults);

        stylecow.setConfig(options);

        this.files.forEach(function(f) {
            var src = f.src.filter(function(filepath) {
                if (!grunt.file.exists(filepath)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).map(function(filepath) {
                return stylecow.convertFromFile(filepath).toCode();
            }).join('');

            grunt.file.write(f.dest, src);

            grunt.log.writeln('File "' + f.dest + '" created.');
        });
    });
};
<commit_msg>sourcemaps<commit_after>/*
 * grunt-stylecow
 * https://github.com/oscarotero/grunt-stylecow
 *
 * Copyright (c) 2014 oscarotero
 * Licensed under the MIT license.
 */

'use strict';

var stylecow = require('stylecow');

module.exports = function(grunt) {

    grunt.registerMultiTask('stylecow', 'Execute stylecow plugins with grunt', function() {
        var options = this.options(stylecow.defaults);

        stylecow.setConfig(options);

        this.files.forEach(function(f) {
            var css;

            f.src.filter(function(filepath) {
                if (!grunt.file.exists(filepath)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).forEach(function(filepath) {
                var parsed = stylecow.createFromFile(filepath);

                if (!css) {
                    css = parsed;
                } else {
                    stylecow.merge(css, parsed);
                }
            });

            css.executeTasks(stylecow.tasks);

            var code = new stylecow.Code(css, {
                file: f.dest,
                style: options.code,
                sourceMap: options.sourceMap,
                sourceMapFile: options.sourceMapFile
            });

            grunt.file.write(f.dest, code.code);
            grunt.log.writeln('File "' + f.dest + '" created.');

            if (options.sourceMapFile) {
                grunt.file.write(f.dest, code.mapString);
                grunt.log.writeln('File "' + options.sourceMapFile + '" created.');
            }
        });
    });
};
<|endoftext|>


<commit_before>(function () {

    // Arreglo del bug de actualización de la cache
    self.addEventListener('install', function (event) {
        const cacheName = 'TC.offline.map.common';
        event.waitUntil(
            caches.has(cacheName).then(function (hasCache) {
                if (hasCache) {
                    caches.open(cacheName).then(function (cache) {
                        cache.keys().then(function (keys) {
                            console.log("Revisando cache...");
                            if (keys.length) {
                                return fetch(keys[0]).then(function () {
                                    // Estamos online, borramos cache
                                    caches.delete(cacheName).then(function () {
                                        console.log("Cache con bug (" + cacheName + ") borrada");
                                    });
                                }, function (e) {
                                    console.log(e);
                                });
                            }
                            return self.skipWaiting();
                        });
                    });
                }
            })
        );
    });

    //self.addEventListener('install', function (event) {
    // No hacemos nada en la instalaci\u00f3n del service worker
    //    event.waitUntil(self.skipWaiting());
    //});

    self.addEventListener('activate', function (event) {
        // Reclamamos el control inmediatamente, para evitar tener que recargar la página
        event.waitUntil(self.clients.claim());
    });

    self.addEventListener('fetch', function (event) {
        // Si está la petición en la cache se responde de ella, si no, se pide a la red
        event.respondWith(
            caches.match(event.request)
                .then(function (response) {
                    if (response) {
                        return response;
                    }

                    return fetch(event.request).catch(function (reason) {
                        console.log('[fetch] Could not fetch ' + event.request.url + ': ' + reason);
                    });
                })
        );
    });

    // Diccionario de estados de cacheo de mapas. Necesario para poder cancelar cacheos.
    const currentMapStates = {};

    const postMessage = function (msg) {
        self.clients.matchAll({ includeUncontrolled: true })
            .then(function (clientList) {
                clientList.forEach(function (client) {
                    client.postMessage(msg);
                });
            });
    };

    self.addEventListener('message', function (event) {
        // Procesamos las solicitudes de cacheo y borrado

        const action = event.data.action;
        const name = event.data.name;
        const silent = event.data.silent;
        const urlList = event.data.list;
        switch (action) {
            case 'create':
                currentMapStates[name] = action;
                caches.delete(name).finally(function () {
                    caches.open(name)
                        .then(function (cache) {
                            const addToCache = function (idx) {
                                if (!currentMapStates[name]) { // Se ha cancelado la creación de la cache
                                    return;
                                }
                                if (idx === urlList.length) {
                                    if (!silent) {
                                        postMessage({
                                            action: action,
                                            name: name,
                                            event: 'cached'
                                        });
                                    }
                                    return;
                                }
                                const count = idx + 1;
                                const url = urlList[idx];
                                cache.add(url)
                                    .then(
                                        function () {
                                            if (!silent) {
                                                postMessage({
                                                    action: action,
                                                    name: name,
                                                    event: 'progress',
                                                    count: count,
                                                    total: urlList.length
                                                });
                                            }
                                        },
                                        function () {
                                            postMessage({
                                                action: action,
                                                name: name,
                                                event: 'error',
                                                url: url
                                            });
                                        }
                                    )
                                    .finally(function () {
                                        addToCache(count);
                                    });
                            };
                            addToCache(0);
                        });
                });
                break;
            case 'delete':
                delete currentMapStates[name];
                caches.delete(name).then(
                    function () {
                        if (!silent) {
                            postMessage({
                                action: action,
                                name: name,
                                event: 'deleted'
                            });
                        }
                    },
                    function () {
                        postMessage({
                            action: action,
                            name: name,
                            event: 'error'
                        });
                    }
                );
            default:
                break;
        }
    });

})();<commit_msg>Add notificationclick event handler<commit_after>(function () {

    // Arreglo del bug de actualización de la cache
    self.addEventListener('install', function (event) {
        const cacheName = 'TC.offline.map.common';
        event.waitUntil(
            caches.has(cacheName).then(function (hasCache) {
                if (hasCache) {
                    caches.open(cacheName).then(function (cache) {
                        cache.keys().then(function (keys) {
                            console.log("Revisando cache...");
                            if (keys.length) {
                                return fetch(keys[0]).then(function () {
                                    // Estamos online, borramos cache
                                    caches.delete(cacheName).then(function () {
                                        console.log("Cache con bug (" + cacheName + ") borrada");
                                    });
                                }, function (e) {
                                    console.log(e);
                                });
                            }
                            return self.skipWaiting();
                        });
                    });
                }
            })
        );
    });

    //self.addEventListener('install', function (event) {
    // No hacemos nada en la instalaci\u00f3n del service worker
    //    event.waitUntil(self.skipWaiting());
    //});

    self.addEventListener('activate', function (event) {
        // Reclamamos el control inmediatamente, para evitar tener que recargar la página
        event.waitUntil(self.clients.claim());
    });

    self.addEventListener('fetch', function (event) {
        // Si está la petición en la cache se responde de ella, si no, se pide a la red
        event.respondWith(
            caches.match(event.request)
                .then(function (response) {
                    if (response) {
                        return response;
                    }

                    return fetch(event.request).catch(function (reason) {
                        console.log('[fetch] Could not fetch ' + event.request.url + ': ' + reason);
                    });
                })
        );
    });

    // Diccionario de estados de cacheo de mapas. Necesario para poder cancelar cacheos.
    const currentMapStates = {};

    const postMessage = function (msg) {
        self.clients.matchAll({ includeUncontrolled: true })
            .then(function (clientList) {
                clientList.forEach(function (client) {
                    client.postMessage(msg);
                });
            });
    };

    self.addEventListener('message', function (event) {
        // Procesamos las solicitudes de cacheo y borrado

        const action = event.data.action;
        const name = event.data.name;
        const silent = event.data.silent;
        const urlList = event.data.list;
        switch (action) {
            case 'create':
                currentMapStates[name] = action;
                caches.delete(name).finally(function () {
                    caches.open(name)
                        .then(function (cache) {
                            const addToCache = function (idx) {
                                if (!currentMapStates[name]) { // Se ha cancelado la creación de la cache
                                    return;
                                }
                                if (idx === urlList.length) {
                                    if (!silent) {
                                        postMessage({
                                            action: action,
                                            name: name,
                                            event: 'cached'
                                        });
                                    }
                                    return;
                                }
                                const count = idx + 1;
                                const url = urlList[idx];
                                cache.add(url)
                                    .then(
                                        function () {
                                            if (!silent) {
                                                postMessage({
                                                    action: action,
                                                    name: name,
                                                    event: 'progress',
                                                    count: count,
                                                    total: urlList.length
                                                });
                                            }
                                        },
                                        function () {
                                            postMessage({
                                                action: action,
                                                name: name,
                                                event: 'error',
                                                url: url
                                            });
                                        }
                                    )
                                    .finally(function () {
                                        addToCache(count);
                                    });
                            };
                            addToCache(0);
                        });
                });
                break;
            case 'delete':
                delete currentMapStates[name];
                caches.delete(name).then(
                    function () {
                        if (!silent) {
                            postMessage({
                                action: action,
                                name: name,
                                event: 'deleted'
                            });
                        }
                    },
                    function () {
                        postMessage({
                            action: action,
                            name: name,
                            event: 'error'
                        });
                    }
                );
            default:
                break;
        }
    });

    self.addEventListener('notificationclick', function (event) {
        var notification = event.notification;
        var action = event.action;
        if (action === "back") {
            notification.close();
            var promise = Promise.resolve();
            promise =
                promise.then(function () { return firstWindowClient(notification.data.url); })
                    .then(function (client) { return client ? client.focus() : null; });
            event.waitUntil(promise);
        }
    });
    function firstWindowClient(url) {
        return self.clients.matchAll({ includeUncontrolled: true, type: 'window' }).then(function (windowClients) {
            return windowClients.length ? windowClients.find(function (wc) {
                return wc.url === url;
            }) : null;
        });
    }

})();<|endoftext|>


<commit_before>import classNames from 'classnames/dedupe';
import GeminiScrollbar from 'react-gemini-scrollbar';
import React from 'react';
import {StoreMixin} from 'mesosphere-shared-reactjs';

import GeminiUtil from '../utils/GeminiUtil';
import InternalStorageMixin from '../mixins/InternalStorageMixin';
import NewPageHeader from '../components/NewPageHeader';
import SidebarToggle from '../components/SidebarToggle';
import TemplateUtil from '../utils/TemplateUtil';

const PageHeader = ({actions, addButton, breadcrumbs, tabs}) => {
  return (
    <NewPageHeader
      actions={actions}
      addButton={addButton}
      breadcrumbs={breadcrumbs}
      tabs={tabs} />
  );
};

TemplateUtil.defineChildren(PageHeader, {
  Breadcrumbs: NewPageHeader.Breadcrumbs,
  Actions: NewPageHeader.Actions,
  Tabs: NewPageHeader.Actions
});

PageHeader.defaultProps = {
  actions: [],
  tabs: []
};

PageHeader.propTypes = {
  actions: React.PropTypes.array,
  addButton: React.PropTypes.oneOfType([
    React.PropTypes.arrayOf(React.PropTypes.object),
    React.PropTypes.object
  ]),
  breadcrumbs: React.PropTypes.node,
  tabs: React.PropTypes.array
};

var Page = React.createClass({

  displayName: 'Page',

  mixins: [InternalStorageMixin, StoreMixin],

  propTypes: {
    className: React.PropTypes.oneOfType([
      React.PropTypes.array,
      React.PropTypes.object,
      React.PropTypes.string
    ]),
    dontScroll: React.PropTypes.bool,
    navigation: React.PropTypes.oneOfType([
      React.PropTypes.object,
      React.PropTypes.string
    ]),
    title: React.PropTypes.oneOfType([
      React.PropTypes.object,
      React.PropTypes.string
    ])
  },

  componentWillMount() {
    this.store_listeners = [
      {
        name: 'sidebar',
        events: ['widthChange']
      }
    ];
  },

  componentDidMount() {
    this.internalStorage_set({
      rendered: true
    });
    this.forceUpdate();
  },

  onSidebarStoreWidthChange() {
    GeminiUtil.updateWithRef(this.refs.gemini);
  },

  getChildren() {
    var data = this.internalStorage_get();
    if (data.rendered === true) {
      // Avoid rendering template children twice
      return TemplateUtil.filterTemplateChildren(
        this.constructor, this.props.children
      );
    }
    return null;
  },

  getNavigation(navigation) {
    if (!navigation) {
      return null;
    }

    return (

        {navigation}

    );
  },

  getPageHeader() {
    return TemplateUtil.getChildOfType(
      this.props.children, this.constructor.Header
    );
  },

  getTitle(title) {
    if (!title) {
      return null;
    }

    if (React.isValidElement(title)) {
      return title;
    }

    return (

        <SidebarToggle />

          {title}

    );
  },

  getContent() {
    let {dontScroll} = this.props;
    let contentClassSet = classNames('page-body-content pod flex',
      'flex-direction-top-to-bottom flex-item-grow-1', {
        'flex-item-shrink-1': dontScroll
      });

    let content = (

        {this.getChildren()}

    );

    if (dontScroll) {
      return content;
    }

    return (
      <GeminiScrollbar
        autoshow={true}
        className="page-body flex flex-direction-top-to-bottom
          flex-direction-left-to-right-screen-large flex-item-grow-1
          flex-item-shrink-1 gm-scrollbar-container-flex"
        ref="gemini">
        {content}
      </GeminiScrollbar>
    );
  },

  render() {
    let {className, navigation, dontScroll, title} = this.props;

    let classSet = classNames(
      'page flex flex-direction-top-to-bottom flex-item-grow-1', {
        'flex-item-shrink-1': dontScroll
      }, className
    );

    return (

        {this.getPageHeader(title, navigation)}
        {this.getContent()}

    );
  }
});

TemplateUtil.defineChildren(Page, {Header: PageHeader});

module.exports = Page;
<commit_msg>Changed page-body-content to pod-tall<commit_after>import classNames from 'classnames/dedupe';
import GeminiScrollbar from 'react-gemini-scrollbar';
import React from 'react';
import {StoreMixin} from 'mesosphere-shared-reactjs';

import GeminiUtil from '../utils/GeminiUtil';
import InternalStorageMixin from '../mixins/InternalStorageMixin';
import NewPageHeader from '../components/NewPageHeader';
import SidebarToggle from '../components/SidebarToggle';
import TemplateUtil from '../utils/TemplateUtil';

const PageHeader = ({actions, addButton, breadcrumbs, tabs}) => {
  return (
    <NewPageHeader
      actions={actions}
      addButton={addButton}
      breadcrumbs={breadcrumbs}
      tabs={tabs} />
  );
};

TemplateUtil.defineChildren(PageHeader, {
  Breadcrumbs: NewPageHeader.Breadcrumbs,
  Actions: NewPageHeader.Actions,
  Tabs: NewPageHeader.Actions
});

PageHeader.defaultProps = {
  actions: [],
  tabs: []
};

PageHeader.propTypes = {
  actions: React.PropTypes.array,
  addButton: React.PropTypes.oneOfType([
    React.PropTypes.arrayOf(React.PropTypes.object),
    React.PropTypes.object
  ]),
  breadcrumbs: React.PropTypes.node,
  tabs: React.PropTypes.array
};

var Page = React.createClass({

  displayName: 'Page',

  mixins: [InternalStorageMixin, StoreMixin],

  propTypes: {
    className: React.PropTypes.oneOfType([
      React.PropTypes.array,
      React.PropTypes.object,
      React.PropTypes.string
    ]),
    dontScroll: React.PropTypes.bool,
    navigation: React.PropTypes.oneOfType([
      React.PropTypes.object,
      React.PropTypes.string
    ]),
    title: React.PropTypes.oneOfType([
      React.PropTypes.object,
      React.PropTypes.string
    ])
  },

  componentWillMount() {
    this.store_listeners = [
      {
        name: 'sidebar',
        events: ['widthChange']
      }
    ];
  },

  componentDidMount() {
    this.internalStorage_set({
      rendered: true
    });
    this.forceUpdate();
  },

  onSidebarStoreWidthChange() {
    GeminiUtil.updateWithRef(this.refs.gemini);
  },

  getChildren() {
    var data = this.internalStorage_get();
    if (data.rendered === true) {
      // Avoid rendering template children twice
      return TemplateUtil.filterTemplateChildren(
        this.constructor, this.props.children
      );
    }
    return null;
  },

  getNavigation(navigation) {
    if (!navigation) {
      return null;
    }

    return (

        {navigation}

    );
  },

  getPageHeader() {
    return TemplateUtil.getChildOfType(
      this.props.children, this.constructor.Header
    );
  },

  getTitle(title) {
    if (!title) {
      return null;
    }

    if (React.isValidElement(title)) {
      return title;
    }

    return (

        <SidebarToggle />

          {title}

    );
  },

  getContent() {
    let {dontScroll} = this.props;
    let contentClassSet = classNames('page-body-content pod pod-tall flex',
      'flex-direction-top-to-bottom flex-item-grow-1', {
        'flex-item-shrink-1': dontScroll
      });

    let content = (

        {this.getChildren()}

    );

    if (dontScroll) {
      return content;
    }

    return (
      <GeminiScrollbar
        autoshow={true}
        className="page-body flex flex-direction-top-to-bottom
          flex-direction-left-to-right-screen-large flex-item-grow-1
          flex-item-shrink-1 gm-scrollbar-container-flex"
        ref="gemini">
        {content}
      </GeminiScrollbar>
    );
  },

  render() {
    let {className, navigation, dontScroll, title} = this.props;

    let classSet = classNames(
      'page flex flex-direction-top-to-bottom flex-item-grow-1', {
        'flex-item-shrink-1': dontScroll
      }, className
    );

    return (

        {this.getPageHeader(title, navigation)}
        {this.getContent()}

    );
  }
});

TemplateUtil.defineChildren(Page, {Header: PageHeader});

module.exports = Page;
<|endoftext|>