<commit_before>var mongoose = require('mongoose');
var schema = require('validate');
var gcm = require('node-gcm');
var config = rootRequire('config/config');

/**
* The Device model
*/
var Device = mongoose.model('Device', {
  id: String
});

/**
* Validate a device object
* @param Device {type: String, id: String}
* @return An array of error messages
*/
var validate = function (device) {
  var test = schema({
    id: {
      type: 'string',
      required: true,
      message: 'You must provide a device ID'
    }
  });
  return test.validate(device);
};

/**
* Push a message to all developers
* @param title: String
* @param body: String
*/
var push = function (title, body) {
  Device
    .find()
    .exec(function (err, devices) {
      if (err) return;
      var ids = devices.map(function (device) {
        return device.id;
      });
      dispatch(title, body, ids);
    });
};

/**
* Dispatch a notification to all devices
* @param title: String
* @param body: String
* @param ids: [String]
*/
function dispatch(title, body, ids) {

  // Extend array with chunk function
  Array.prototype.chunk = function(chunkSize) {
    var array=this;
    return [].concat.apply([],
      array.map(function(elem,i) {
        return i%chunkSize ? [] : [array.slice(i,i+chunkSize)];
      })
    );
  };

  // Split into groups of 1000
  var regIdSets = ids.chunk(1000);

  // Set up the actual notification
  var message = new gcm.Message({
    notification: {
      title: title,
      body: body
    }
  });

  // Send the message to each group
  var sender = new gcm.Sender(config.gcm.apiKey);
  regIdSets.forEach(function (regIds) {
    sender.send(message, {registrationIds: regIds}, 10, function (err, result) {
      if (err) return;
      cleanup(regIds, result);
    });
  });

}

/**
* Clean up bad registrations from the database
* @param regIds
* @param result
*/
function cleanup(regIds, result) {
  console.log(result);

  if (result.failure > 0) {
    // we have some errors
    // populate a list with bad registration ids
    var toRemove = [];
    for (var i = 0; i < result.results.length; i++) {
      var resObj = result.results[i];
      if ('error' in resObj) {
        toRemove.push(regIds[i]);
      }
    }

    console.log(toRemove);

    // delete the bad ids from the database
    Device
      .find({id: {$in: toRemove}})
      .remove()
      .exec();
  }
}

module.exports = Device;
module.exports.validate = validate;
module.exports.push = push;<commit_msg>Remove log statement<commit_after>var mongoose = require('mongoose');
var schema = require('validate');
var gcm = require('node-gcm');
var config = rootRequire('config/config');

/**
* The Device model
*/
var Device = mongoose.model('Device', {
  id: String
});

/**
* Validate a device object
* @param Device {type: String, id: String}
* @return An array of error messages
*/
var validate = function (device) {
  var test = schema({
    id: {
      type: 'string',
      required: true,
      message: 'You must provide a device ID'
    }
  });
  return test.validate(device);
};

/**
* Push a message to all developers
* @param title: String
* @param body: String
*/
var push = function (title, body) {
  Device
    .find()
    .exec(function (err, devices) {
      if (err) return;
      var ids = devices.map(function (device) {
        return device.id;
      });
      dispatch(title, body, ids);
    });
};

/**
* Dispatch a notification to all devices
* @param title: String
* @param body: String
* @param ids: [String]
*/
function dispatch(title, body, ids) {

  // Extend array with chunk function
  Array.prototype.chunk = function(chunkSize) {
    var array=this;
    return [].concat.apply([],
      array.map(function(elem,i) {
        return i%chunkSize ? [] : [array.slice(i,i+chunkSize)];
      })
    );
  };

  // Split into groups of 1000
  var regIdSets = ids.chunk(1000);

  // Set up the actual notification
  var message = new gcm.Message({
    notification: {
      title: title,
      body: body
    }
  });

  // Send the message to each group
  var sender = new gcm.Sender(config.gcm.apiKey);
  regIdSets.forEach(function (regIds) {
    sender.send(message, {registrationIds: regIds}, 10, function (err, result) {
      if (err) return;
      cleanup(regIds, result);
    });
  });

}

/**
* Clean up bad registrations from the database
* @param regIds
* @param result
*/
function cleanup(regIds, result) {
  console.log(result);

  if (result.failure > 0) {
    // we have some errors
    // populate a list with bad registration ids
    var toRemove = [];
    for (var i = 0; i < result.results.length; i++) {
      var resObj = result.results[i];
      if ('error' in resObj) {
        toRemove.push(regIds[i]);
      }
    }

    // delete the bad ids from the database
    Device
      .find({id: {$in: toRemove}})
      .remove()
      .exec();
  }
}

module.exports = Device;
module.exports.validate = validate;
module.exports.push = push;<|endoftext|>


<commit_before><commit_msg>fix url encoding if it contains parameters<commit_after><|endoftext|>


<commit_before>angular.module('gdgXBoomerang')
.controller('EventsController', function ($http, $log, $filter, Config, NavService) {
    var vm = this;
    NavService.setNavTab(2);
    vm.chapterName = Config.name;
    vm.loading = true;
    vm.dateFormat = Config.dateFormat;
    vm.events = { past:[], future:[] };

    var url = 'https://hub.gdgx.io/api/v1/chapters/' + Config.id + '/events/upcoming?callback=JSON_CALLBACK';
    var headers = { 'headers': { 'Accept': 'application/json;' }, 'timeout': 2000 };
    $http.jsonp(url, headers)
        .success(function (data) {
            for (var i = data.items.length - 1; i >= 0; i--) {
                if (data.items[i].about) {
                    data.items[i].about =
                        data.items[i].about.replace(/

/g, '

');
                } else {
                    data.items[i].about = '';
                }
                vm.events.future.push(data.items[i]);
            }
            vm.events.future = $filter('orderBy')(vm.events.future, 'start', false);
            vm.loading = false;
            vm.status = 'ready';
        })
        .error(function (response, errror) {
            vm.upcomingError = 'Sorry, we failed to retrieve the upcoming events from the GDG-X Hub API.';
            vm.loading = false;
            vm.status = 'ready';
            $log.debug('Sorry, we failed to retrieve the upcoming events from the GDG-X Hub API: ' + response + error);
        });

    var getPastEventsPage = function(page) {
        var url = 'https://hub.gdgx.io/api/v1/chapters/' + Config.id +
            '/events/past?callback=JSON_CALLBACK&page=' + page;
        var headers = { 'headers': {'Accept': 'application/json;'}, 'timeout': 2000 };
        $http.jsonp(url, headers)
            .success(function (data) {
                var i;
                for (i = data.items.length - 1; i >= 0; i--) {
                    if (data.items[i].about) {
                        data.items[i].about =
                            data.items[i].about.replace(/

/g, '

');
                    } else {
                        data.items[i].about = '';
                    }
                    vm.events.past.push(data.items[i]);
                }
                if (data.pages === page) {
                    vm.events.past = $filter('orderBy')(vm.events.past, 'start', true);
                    vm.loading = false;
                    vm.status = 'ready';
                } else {
                    getPastEventsPage(page + 1);
                }
            })
            .error(function (response) {
                vm.pastError = 'Sorry, we failed to retrieve the past events from the GDG-X Hub API.';
                vm.loading = false;
                vm.status = 'ready';
                $log.debug('Sorry, we failed to retrieve the past events from the GDG-X Hub API: ' + response);
            });
    };
    getPastEventsPage(1);
});
<commit_msg>fix typo<commit_after>angular.module('gdgXBoomerang')
.controller('EventsController', function ($http, $log, $filter, Config, NavService) {
    var vm = this;
    NavService.setNavTab(2);
    vm.chapterName = Config.name;
    vm.loading = true;
    vm.dateFormat = Config.dateFormat;
    vm.events = { past:[], future:[] };

    var url = 'https://hub.gdgx.io/api/v1/chapters/' + Config.id + '/events/upcoming?callback=JSON_CALLBACK';
    var headers = { 'headers': { 'Accept': 'application/json;' }, 'timeout': 2000 };
    $http.jsonp(url, headers)
        .success(function (data) {
            for (var i = data.items.length - 1; i >= 0; i--) {
                if (data.items[i].about) {
                    data.items[i].about =
                        data.items[i].about.replace(/

/g, '

');
                } else {
                    data.items[i].about = '';
                }
                vm.events.future.push(data.items[i]);
            }
            vm.events.future = $filter('orderBy')(vm.events.future, 'start', false);
            vm.loading = false;
            vm.status = 'ready';
        })
        .error(function (response) {
            vm.upcomingError = 'Sorry, we failed to retrieve the upcoming events from the GDG-X Hub API.';
            vm.loading = false;
            vm.status = 'ready';
            $log.debug('Sorry, we failed to retrieve the upcoming events from the GDG-X Hub API: ' + response);
        });

    var getPastEventsPage = function(page) {
        var url = 'https://hub.gdgx.io/api/v1/chapters/' + Config.id +
            '/events/past?callback=JSON_CALLBACK&page=' + page;
        var headers = { 'headers': {'Accept': 'application/json;'}, 'timeout': 2000 };
        $http.jsonp(url, headers)
            .success(function (data) {
                var i;
                for (i = data.items.length - 1; i >= 0; i--) {
                    if (data.items[i].about) {
                        data.items[i].about =
                            data.items[i].about.replace(/

/g, '

');
                    } else {
                        data.items[i].about = '';
                    }
                    vm.events.past.push(data.items[i]);
                }
                if (data.pages === page) {
                    vm.events.past = $filter('orderBy')(vm.events.past, 'start', true);
                    vm.loading = false;
                    vm.status = 'ready';
                } else {
                    getPastEventsPage(page + 1);
                }
            })
            .error(function (response) {
                vm.pastError = 'Sorry, we failed to retrieve the past events from the GDG-X Hub API.';
                vm.loading = false;
                vm.status = 'ready';
                $log.debug('Sorry, we failed to retrieve the past events from the GDG-X Hub API: ' + response);
            });
    };
    getPastEventsPage(1);
});
<|endoftext|>


<commit_before><commit_msg>Add tractor and weed groups<commit_after><|endoftext|>


<commit_before>phoxy._RenderSubsystem =
{
  DeferRender : function (ejs, data, rendered_callback, tag)
    {
      phoxy.Log(4, "phoxy.DeferRender", arguments);
      if (tag === undefined)
        tag = '<defer_render>';
      var canvas = phoxy._.render.PrepareCanvas(tag);
      var id = canvas.id;

      phoxy._.render.RenderReplace(id, ejs, data, rendered_callback);

      if (tag === null)
        return canvas;
      return canvas.html;
    }
  ,
};

phoxy._RenderSubsystem._ = {};
phoxy._RenderSubsystem._.render =
{
  PrepareCanvas : function(tag)
    {
      if (tag === undefined)
        tag = '<div>';
      var vanilla_tag = tag.substring(1, tag.length - 1);

      var id =  phoxy._.internal.GenerateUniqueID();
      var obj = document.createElement(vanilla_tag);
      obj.setAttribute('id', id);
      var div = obj.outerHTML;

      return { id: id, obj: obj, html: div };
    }
  ,
  AsyncRender_Strategy : function (target, ejs, data, rendered_callback, difference)
    { // AsyncRender strategy: for production
      phoxy._.render.Fancy(ejs, data, function(obj, ejs, data)
      {
        if (typeof obj === 'undefined')
        {
          phoxy.Log(3, 'phoxy.Reality', 'Design render skiped. (No design was choosed?)', document.getElementById(target));
          return; // And break dependencies execution
        }

        // Potential cascade memleak
        // Should clear listeners with callback
        phoxy._.time.Appeared(target, function()
        {
          difference.call(phoxy, target, obj.html, arguments);
          for (var k in obj.defer)
              obj.defer[k]();
        }, undefined, -1);

        obj.on_complete = function()
        {
          if (typeof(rendered_callback) !== 'undefined')
            rendered_callback.call(obj.across, ejs, data, obj.html);
        };
      }, true);
    }
  ,
  SyncRender_Strategy : function (target, ejs, data, rendered_callback, difference)
    { // SyncRender strategy: for debug/develop purposes
      phoxy._.time.Appeared(target, function()
      {
        phoxy._.render.Fancy(ejs, data, function(obj, ejs, data)
        {
          if (typeof obj === 'undefined')
          {
            phoxy.Log(3, 'phoxy.Reality', 'Design render skiped. (No design was choosed?)', document.getElementById(target));
            return; // And break dependencies execution
          }

          difference.call(phoxy, target, obj.html, arguments);

          obj.on_complete = function()
          {
            if (typeof(rendered_callback) !== 'undefined')
              rendered_callback.call(obj.across, ejs, data, obj.html);
          };
        }, true);
      }, undefined, -1);
    }
  ,
  RenderStrategy : "Will be replaced by selected strategy after compilation."
  ,
  RenderInto : function (target, ejs, data, rendered_callback)
    {
      var args = Array.prototype.slice.call(arguments);
      args.push(function(target, html)
      {
        document.getElementById(target).innerHTMl = html;
      });
      phoxy._.render.RenderStrategy.apply(this, args);
    }
  ,
  RenderReplace : function (target, ejs, data, rendered_callback)
    {
      var args = Array.prototype.slice.call(arguments);
      args.push(function(target, html)
      {
        var that = document.getElementById(target);
        that.insertAdjacentHTML("afterEnd", html);
        that.parentNode.removeChild(that);
      });
      phoxy._.render.RenderStrategy.apply(this, args);
    }
  ,
  Render : function (design, data, callback, is_phoxy_internal_call)
    {
      if (data === undefined)
        data = {};

      phoxy.Log(5, "phoxy.Render", arguments);
      var html;
      if (design.indexOf(".ejs") === -1)
        design += ".ejs";
      var ejs;
      //if (!phoxy.ForwardDownload(design))
        ejs = new EJS({'url' : design});
      //else
//        ejs = new EJS({'text' : phoxy.ForwardDownload(design), 'name' : design});

      var obj = ejs.prepare(data);
      obj.on_complete = callback;
      ejs.execute(obj);
      html = obj.html;

      if (typeof phoxy === 'undefined' || typeof phoxy.state === 'undefined')
        throw "EJS render failed. Phoxy is missing. Is .ejs file exsists? Is your .htacess right? Check last AJAX request.";

      if (is_phoxy_internal_call)
        return obj;
      return html;
    }
  ,
  HandleServerAnswerAndInvokeCallback : function(answer, cb)
    {
      var obj = EJS.IsolateContext(answer);

      // Those removed because we dont need to render anything
      delete obj.design;
      // Those ignored since it phoxy.Fancy.(low level rendering) Place to render already choosed
      delete obj.result;
      delete obj.replace;
      phoxy.ApiAnswer(obj, function()
      {
        cb(answer);
      });
    }
  ,
  FancyServerRequest : function(url, cb)
  {
    phoxy.AJAX(url, function(obj)
    {
      phoxy._.render.HandleServerAnswerAndInvokeCallback(obj, cb);
    });
  }
  ,
  Fancy : function(design, data, callback, raw_output)
    {
      var args = arguments;
      for (var i = 0; i < 2; i++)
        if (Array.isArray(args[i]))
        {
          args[i] = phoxy.ConstructURL(args[i]);
          return phoxy._.render.Fancy.apply(this, args);
        }

      phoxy.Log(6, "phoxy.Fancy", arguments);

      var callback = args[2];
      if (typeof(callback) === 'undefined')
        callback = function (){};

      /*
       * [a0] phoxy.Fancy(string, undefined, anytype)
       * * Then it full RPC call, with fixed render place
       * * (result/replace keywords ignoring)
       *
       * [a1] phoxy.Fancy(object, undefined, anytype)
       * * Then params already constructed with object
       * * NOTICE: All keywoards ARE interprenting
       */
      if (typeof(args[1]) === 'undefined')
      {
        if (typeof(args[0]) === 'undefined')
          return callback(undefined, undefined, undefined);

        if (typeof(args[0]) === 'string')
// [a0] ////////
          return phoxy._.birth.Prophecy.apply(phoxy._.birth, arguments);

        if (typeof(args[0]) !== 'object')
          throw "Failed phoxy.Fancy object recognize";

// [a1] ////////
        phoxy._.birth.Presage.apply(phoxy._.birth, args);
        return;
      }

      /* Data preparing
       * [b0] phoxy.Fancy(anytype, function, anytype)
       * * Generating data through function
       * * Data could be returned directly (object only)
       * *  or could be returned asynchronously with callback, as soon as it will be ready.
       *
       * [b1] phoxy.Fancy(anytype, string, anytype)
       * * Requesting data with RPC
       * * NOTICE: Every keywoards except data ARE ignored.
       *
       * [b2] phoxy.Fancy(anytype, object, anytype)
       * * Serving with constructed object. Ready to render!
       */

      function DataLoadedCallback(data)
      {
        data = data || {};
        phoxy._.render.Fancy(args[0], data, args[2], args[3]);
      }

      if (typeof(args[1]) === 'function')
      {
// [b0] ////////
        var data_load_functor = args[1];
        data = data_load_functor(DataLoadedCallback);
        if (typeof(data) !== 'object')
          return; // data will be returned async
      }
      else if (typeof(args[1]) === 'string')
      {
// [b1] ////////
        phoxy._.birth.Desire(args[1], DataLoadedCallback);
        return;
      }
      else if (typeof(args[1]) !== 'object')
        throw "Failed phoxy.Fancy data receive";
      else
// [b2] ////////
        data = args[1];

      var html;

      /* Rendering
       * [c0] phoxy.Fancy(undefined, NOT undefined, anytype)
       * * Only invoking callback with prepared data
       * * Used when design determining dynamically
       *
       * [c1] phoxy.Fancy(string, NOT undefined, anytype)
       * * First parameter is EJS string, same as in 'design' keyword
       *
       * [c2] phoxy.Fancy(function, NOT undefined, anytype)
       * * First paremeter if method which determine design in runtime
       * * Just same as [b0] for data preparing do.
       */

      if (typeof(args[0]) === 'undefined')
// [c0] ////////
        return callback(html, design, data);

      if (typeof(args[0]) === 'string')
// [c1] ////////
        design = args[0];
      else if (typeof(args[0]) === 'function')
      {
// [c2] ////////
        var mutation = phoxy._.birth.Mutation.apply(phoxy._.birth, arguments);

        if (typeof(mutation) !== 'string')
          return; // Will be rendered later (async design determine)
      }

      phoxy._.birth.Conceive(design, data, callback, raw_output);
    }
  ,
};

phoxy._RenderSubsystem._.birth =
{
  Prophecy: function(rpc)
  {
    var args = arguments;
    phoxy._.render.FancyServerRequest(rpc, function(obj)
    {
      phoxy._.render.Fancy(obj, args[1], args[2], args[3]);
    });
  }
  ,
  Presage: function(obj)
  {
    var obj = args[0];

    // Maybe its wrong. Maybe i should ignore other params
    var design = obj.design;
    var data = obj.data || {};

    phoxy._.render.HandleServerAnswerAndInvokeCallback(obj, function()
    {
      phoxy._.render.Fancy(design, data, callback, args[3]);
    })
  }
  ,
  Desire: function(rpc, DataLoadedCallback)
  {
    phoxy._.render.FancyServerRequest(rpc, function(json)
    {
      DataLoadedCallback(json.data);
    });
  }
  ,
  Mutation: function(design, data)
  {
    function DetermineAsync(design)
    {
      phoxy._.render.Fancy(design, data, args[2], args[3]);
    }

    return design(data, DetermineAsync);
  }
  ,
  Conceive: function(design, data, callback, raw_output)
  {
    var ejs_location = phoxy.Config()['ejs_dir'] + "/" + design;
    var html = phoxy._.render.Render(ejs_location, data, undefined, true);

    if (!raw_output)
      html = html.html;
    callback(html, design, data);
  }
};<commit_msg>Sublime pray from Fancy<commit_after>phoxy._RenderSubsystem =
{
  DeferRender : function (ejs, data, rendered_callback, tag)
    {
      phoxy.Log(4, "phoxy.DeferRender", arguments);
      if (tag === undefined)
        tag = '<defer_render>';
      var canvas = phoxy._.render.PrepareCanvas(tag);
      var id = canvas.id;

      phoxy._.render.RenderReplace(id, ejs, data, rendered_callback);

      if (tag === null)
        return canvas;
      return canvas.html;
    }
  ,
};

phoxy._RenderSubsystem._ = {};
phoxy._RenderSubsystem._.render =
{
  PrepareCanvas : function(tag)
    {
      if (tag === undefined)
        tag = '<div>';
      var vanilla_tag = tag.substring(1, tag.length - 1);

      var id =  phoxy._.internal.GenerateUniqueID();
      var obj = document.createElement(vanilla_tag);
      obj.setAttribute('id', id);
      var div = obj.outerHTML;

      return { id: id, obj: obj, html: div };
    }
  ,
  AsyncRender_Strategy : function (target, ejs, data, rendered_callback, difference)
    { // AsyncRender strategy: for production
      phoxy._.render.Fancy(ejs, data, function(obj, ejs, data)
      {
        if (typeof obj === 'undefined')
        {
          phoxy.Log(3, 'phoxy.Reality', 'Design render skiped. (No design was choosed?)', document.getElementById(target));
          return; // And break dependencies execution
        }

        // Potential cascade memleak
        // Should clear listeners with callback
        phoxy._.time.Appeared(target, function()
        {
          difference.call(phoxy, target, obj.html, arguments);
          for (var k in obj.defer)
              obj.defer[k]();
        }, undefined, -1);

        obj.on_complete = function()
        {
          if (typeof(rendered_callback) !== 'undefined')
            rendered_callback.call(obj.across, ejs, data, obj.html);
        };
      }, true);
    }
  ,
  SyncRender_Strategy : function (target, ejs, data, rendered_callback, difference)
    { // SyncRender strategy: for debug/develop purposes
      phoxy._.time.Appeared(target, function()
      {
        phoxy._.render.Fancy(ejs, data, function(obj, ejs, data)
        {
          if (typeof obj === 'undefined')
          {
            phoxy.Log(3, 'phoxy.Reality', 'Design render skiped. (No design was choosed?)', document.getElementById(target));
            return; // And break dependencies execution
          }

          difference.call(phoxy, target, obj.html, arguments);

          obj.on_complete = function()
          {
            if (typeof(rendered_callback) !== 'undefined')
              rendered_callback.call(obj.across, ejs, data, obj.html);
          };
        }, true);
      }, undefined, -1);
    }
  ,
  RenderStrategy : "Will be replaced by selected strategy after compilation."
  ,
  RenderInto : function (target, ejs, data, rendered_callback)
    {
      var args = Array.prototype.slice.call(arguments);
      args.push(function(target, html)
      {
        document.getElementById(target).innerHTMl = html;
      });
      phoxy._.render.RenderStrategy.apply(this, args);
    }
  ,
  RenderReplace : function (target, ejs, data, rendered_callback)
    {
      var args = Array.prototype.slice.call(arguments);
      args.push(function(target, html)
      {
        var that = document.getElementById(target);
        that.insertAdjacentHTML("afterEnd", html);
        that.parentNode.removeChild(that);
      });
      phoxy._.render.RenderStrategy.apply(this, args);
    }
  ,
  Render : function (design, data, callback, is_phoxy_internal_call)
    {
      if (data === undefined)
        data = {};

      phoxy.Log(5, "phoxy.Render", arguments);
      var html;
      if (design.indexOf(".ejs") === -1)
        design += ".ejs";
      var ejs;
      //if (!phoxy.ForwardDownload(design))
        ejs = new EJS({'url' : design});
      //else
//        ejs = new EJS({'text' : phoxy.ForwardDownload(design), 'name' : design});

      var obj = ejs.prepare(data);
      obj.on_complete = callback;
      ejs.execute(obj);
      html = obj.html;

      if (typeof phoxy === 'undefined' || typeof phoxy.state === 'undefined')
        throw "EJS render failed. Phoxy is missing. Is .ejs file exsists? Is your .htacess right? Check last AJAX request.";

      if (is_phoxy_internal_call)
        return obj;
      return html;
    }
  ,
  HandleServerAnswerAndInvokeCallback : function(answer, cb)
    {
      var obj = EJS.IsolateContext(answer);

      // Those removed because we dont need to render anything
      delete obj.design;
      // Those ignored since it phoxy.Fancy.(low level rendering) Place to render already choosed
      delete obj.result;
      delete obj.replace;
      phoxy.ApiAnswer(obj, function()
      {
        cb(answer);
      });
    }
  ,
  FancyServerRequest : function(url, cb)
  {
    phoxy.AJAX(url, function(obj)
    {
      phoxy._.render.HandleServerAnswerAndInvokeCallback(obj, cb);
    });
  }
  ,
  Fancy : function(design, data, callback, raw_output)
    {
      var args = arguments;
      for (var i = 0; i < 2; i++)
        if (Array.isArray(args[i]))
        {
          args[i] = phoxy.ConstructURL(args[i]);
          return phoxy._.render.Fancy.apply(this, args);
        }

      phoxy.Log(6, "phoxy.Fancy", arguments);

      var callback = args[2];
      if (typeof(callback) === 'undefined')
        callback = function (){};

      /*
       * [a0] phoxy.Fancy(string, undefined, anytype)
       * * Then it full RPC call, with fixed render place
       * * (result/replace keywords ignoring)
       *
       * [a1] phoxy.Fancy(object, undefined, anytype)
       * * Then params already constructed with object
       * * NOTICE: All keywoards ARE interprenting
       */
      if (typeof(args[1]) === 'undefined')
      {
        if (typeof(args[0]) === 'undefined')
          return callback(undefined, undefined, undefined);

        if (typeof(args[0]) === 'string')
// [a0] ////////
          return phoxy._.birth.Prophecy.apply(phoxy._.birth, arguments);

        if (typeof(args[0]) !== 'object')
          throw "Failed phoxy.Fancy object recognize";

// [a1] ////////
        phoxy._.birth.Presage.apply(phoxy._.birth, args);
        return;
      }

      /* Data preparing
       * [b0] phoxy.Fancy(anytype, function, anytype)
       * * Generating data through function
       * * Data could be returned directly (object only)
       * *  or could be returned asynchronously with callback, as soon as it will be ready.
       *
       * [b1] phoxy.Fancy(anytype, string, anytype)
       * * Requesting data with RPC
       * * NOTICE: Every keywoards except data ARE ignored.
       *
       * [b2] phoxy.Fancy(anytype, object, anytype)
       * * Serving with constructed object. Ready to render!
       */

      function DataLoadedCallback(data)
      {
        data = data || {};
        phoxy._.render.Fancy(args[0], data, args[2], args[3]);
      }

      if (typeof(args[1]) === 'function')
      {
// [b0] ////////
        data = phoxy._.birth.Pray(args[1], DataLoadedCallback);
        if (typeof(data) !== 'object')
          return; // data will be returned async
      }
      else if (typeof(args[1]) === 'string')
      {
// [b1] ////////
        phoxy._.birth.Desire(args[1], DataLoadedCallback);
        return;
      }
      else if (typeof(args[1]) !== 'object')
        throw "Failed phoxy.Fancy data receive";
      else
// [b2] ////////
        data = args[1];

      var html;

      /* Rendering
       * [c0] phoxy.Fancy(undefined, NOT undefined, anytype)
       * * Only invoking callback with prepared data
       * * Used when design determining dynamically
       *
       * [c1] phoxy.Fancy(string, NOT undefined, anytype)
       * * First parameter is EJS string, same as in 'design' keyword
       *
       * [c2] phoxy.Fancy(function, NOT undefined, anytype)
       * * First paremeter if method which determine design in runtime
       * * Just same as [b0] for data preparing do.
       */

      if (typeof(args[0]) === 'undefined')
// [c0] ////////
        return callback(html, design, data);

      if (typeof(args[0]) === 'string')
// [c1] ////////
        design = args[0];
      else if (typeof(args[0]) === 'function')
      {
// [c2] ////////
        var mutation = phoxy._.birth.Mutation.apply(phoxy._.birth, arguments);

        if (typeof(mutation) !== 'string')
          return; // Will be rendered later (async design determine)
      }

      phoxy._.birth.Conceive(design, data, callback, raw_output);
    }
  ,
};

phoxy._RenderSubsystem._.birth =
{
  Prophecy: function(rpc)
  {
    var args = arguments;
    phoxy._.render.FancyServerRequest(rpc, function(obj)
    {
      phoxy._.render.Fancy(obj, args[1], args[2], args[3]);
    });
  }
  ,
  Presage: function(obj)
  {
    var obj = args[0];

    // Maybe its wrong. Maybe i should ignore other params
    var design = obj.design;
    var data = obj.data || {};

    phoxy._.render.HandleServerAnswerAndInvokeCallback(obj, function()
    {
      phoxy._.render.Fancy(design, data, callback, args[3]);
    })
  }
  ,
  Desire: function(rpc, DataLoadedCallback)
  {
    phoxy._.render.FancyServerRequest(rpc, function(json)
    {
      DataLoadedCallback(json.data);
    });
  }
  ,
  Pray: function(data_load_functor, DataLoadedCallback)
  {
    return data_load_functor(DataLoadedCallback);
  }
  ,
  Mutation: function(design, data)
  {
    function DetermineAsync(design)
    {
      phoxy._.render.Fancy(design, data, args[2], args[3]);
    }

    return design(data, DetermineAsync);
  }
  ,
  Conceive: function(design, data, callback, raw_output)
  {
    var ejs_location = phoxy.Config()['ejs_dir'] + "/" + design;
    var html = phoxy._.render.Render(ejs_location, data, undefined, true);

    if (!raw_output)
      html = html.html;
    callback(html, design, data);
  }
};<|endoftext|>


<commit_before>import React from 'react'
import { Link } from 'react-router'
import {TableRow, TableRowColumn} from 'material-ui/Table'
import moment from 'moment'
import RaisedButton from 'material-ui/RaisedButton';

function doneSince(endTime) {
  const endDate = new Date(endTime).getTime()
  return moment(endDate).fromNow()
}

const HarvestRow = ({harvest, catalog}) => {
  const color = harvest.status === "successful" ? "green" : "red"

  return (
    <TableRow hoverable={true}>
      <TableRowColumn>
        <div className={`ui ${color} circular label`} >
          {harvest.status}

      </TableRowColumn>
      <TableRowColumn>{harvest.itemsFound}</TableRowColumn>
      <TableRowColumn>{doneSince(harvest.finished) || 'N/A' }</TableRowColumn>
      <TableRowColumn>
        <Link to={`/catalogs/${catalog.id}/harvest/${harvest._id}`}>
          <RaisedButton label="More" primary={true} />
        </Link>
      </TableRowColumn>
    </TableRow>
      )
}

export default HarvestRow
<commit_msg>doneSince Error Handling<commit_after>import React from 'react'
import { Link } from 'react-router'
import {TableRow, TableRowColumn} from 'material-ui/Table'
import moment from 'moment'
import RaisedButton from 'material-ui/RaisedButton';

function doneSince(endTime) {
  const endDate = new Date(endTime).getTime()
  return moment(endDate).fromNow() || 'N/A'
}

const HarvestRow = ({harvest, catalog}) => {
  const color = harvest.status === "successful" ? "green" : "red"

  return (
    <TableRow hoverable={true}>
      <TableRowColumn>
        <div className={`ui ${color} circular label`} >
          {harvest.status}

      </TableRowColumn>
      <TableRowColumn>{harvest.itemsFound}</TableRowColumn>
      <TableRowColumn>{doneSince(harvest.finished)}</TableRowColumn>
      <TableRowColumn>
        <Link to={`/catalogs/${catalog.id}/harvest/${harvest._id}`}>
          <RaisedButton label="More" primary={true} />
        </Link>
      </TableRowColumn>
    </TableRow>
      )
}

export default HarvestRow
<|endoftext|>


<commit_before>/**
 * Controller
 * @return
 */

export default class extends THINK.Controller {
    //构造方法
    init(http){
        //调用父类构造方法
        super.init(http);
    }
    //所有该控制器(含子类)方法前置方法
    __before(){
        console.log('__before');
    }
    //URI定位到该控制器,如果该控制器不存在某个方法时自动调用
    __empty(){
        return this.json('can\'t find action');
    }
    //indexAction前置方法
    _before_index(){
        console.log('_before_index');
    }
    //控制器默认方法
    indexAction () {
        return this.display()
        // return this.redirect(this.http.runType.toLowerCase() + "://" + this.http.hostname + ":8080");
    }

}<commit_msg>for jenkins test 6<commit_after>/**
 * Controller
 * @return
 */

export default class extends THINK.Controller {
    //构造方法
    init(http){
        //调用父类构造方法
        super.init(http);
    }
    //所有该控制器(含子类)方法前置方法
    __before(){
        console.log('__before');
    }
    //URI定位到该控制器,如果该控制器不存在某个方法时自动调用
    __empty(){
        return this.json('can\'t find action');
    }
    //indexAction前置方法
    _before_index(){
        console.log('_before_index');
    }
    //控制器默认方法
    indexAction () {
        return this.display();
        // return this.redirect(this.http.runType.toLowerCase() + "://" + this.http.hostname + ":8080");
    }

}<|endoftext|>


<commit_before>define(
    [
        'dojo/_base/declare',
        'dojo/_base/lang',
        'dojo/_base/array',
        'dojo/Deferred',
        'dojo/promise/all',

        'JBrowse/Util',
        'JBrowse/ConfigAdaptor/AdaptorUtil'
    ],
    function(
        declare,
        lang,
        array,
        Deferred,
        all,

        Util,
        AdaptorUtil
    ) {

return declare(null,

/**
 * @lends JBrowse.ConfigManager.prototype
 */
{

/**
 * @constructs
 */
constructor: function( args ) {
    this.bootConfig = lang.clone( args.bootConfig || {} );
    this.defaults = lang.clone( args.defaults || {} );
    this.browser = args.browser;
    this.skipValidation = args.skipValidation;

    this.bootConfig = (this._regularizeIncludes ([ this.bootConfig ])) [0];
    var thisB = this;
    this._getConfigAdaptor( this.bootConfig )
        .then( function( adaptor ) {
            thisB.bootConfig = adaptor.regularizeTrackConfigs ( thisB.bootConfig );
    });

    // this.topLevelIncludes = this._fillTemplates(
    //     lang.clone( this.config.include || this.defaults.include ),
    //     this._applyDefaults( lang.clone( this.config ), this.defaults )
    // );
    // delete this.defaults.include;
    // delete this.config.include;
},

/**
 * @param callback {Function} callback, receives a single arguments,
 * which is the final processed configuration object
 */
getFinalConfig: function() {
    return this.finalConfig || ( this.finalConfig = function() {
        var thisB = this;
        var bootstrapConf = this._applyDefaults( lang.clone( this.bootConfig ), this.defaults );
        return this._loadIncludes( this._fillTemplates( bootstrapConf, bootstrapConf ) )
            .then( function( includedConfig ) {

                       // merge the boot config *into* the included config last, so
                       // that values in the boot config override the others
                       var finalConf = thisB._mergeConfigs( includedConfig, thisB.bootConfig );

                       thisB._fillTemplates( finalConf, finalConf );

                       finalConf = AdaptorUtil.evalHooks( finalConf );

                       if( ! thisB.skipValidation )
                           thisB._validateConfig( finalConf );

                       return finalConf;
                   });
    }.call(this) );
},

/**
 * Instantiate the right config adaptor for a given configuration source.
 * @param {Object} config the configuraiton
 * @param {Function} callback called with the new config object
 * @returns {Object} the right configuration adaptor to use, or
 * undefined if one could not be found
 * @private
 */

_getConfigAdaptor: function( config_def, callback ) {
    var adaptor_name = "JBrowse/ConfigAdaptor/" + config_def.format;
    if( 'version' in config_def )
        adaptor_name += '_v'+config_def.version;
    adaptor_name.replace( /\W/g,'' );
    return Util.loadJS( [adaptor_name] )
        .then( function( modules ) {
                   return new (modules[0])( config_def );
               });
},

_fillTemplates: function( subconfig, config ) {
    // skip "menuTemplate" keys to prevent messing
    // up their feature-based {} interpolation
    //var skip = { menuTemplate: true };
    var skip = {};

    var type = typeof subconfig;
    if( lang.isArray( subconfig ) ) {
        for( var i = 0; i<subconfig.length; i++ )
            subconfig[i] = this._fillTemplates( subconfig[i], config );
    }
    else if( type == 'object' ) {
        for( var name in subconfig ) {
            if( subconfig.hasOwnProperty( name ) && !skip[name] )
                subconfig[name] = this._fillTemplates( subconfig[name], config );
        }
    }
    else if( type == 'string' ) {
        return Util.fillTemplate( subconfig, config );
    }

    return subconfig;
},

/**
 * Recursively fetch, parse, and merge all the includes in the given
 * config object.  Calls the callback with the resulting configuration
 * when finished.
 * @private
 */
_loadIncludes: function( inputConfig ) {
    var thisB = this;
    inputConfig = lang.clone( inputConfig );

    function _loadRecur( config, upstreamConf ) {
        var sourceUrl = config.sourceUrl || config.baseUrl;
        var newUpstreamConf = thisB._mergeConfigs( lang.clone( upstreamConf ), config );
        var includes = thisB._fillTemplates(
            thisB._regularizeIncludes( config.include || [] ),
            newUpstreamConf
        );
        delete config.include;

        var loads = array.map(
            includes, function( include ) {
                return thisB._loadInclude( include, sourceUrl )
                    .then( function( includedData ) {
                               return _loadRecur(
                                   includedData,
                                   newUpstreamConf
                               );
                           });
            });
        return all( loads )
            .then( function( includedDataObjects ) {
                       array.forEach( includedDataObjects, function( includedData ) {
                                          config = thisB._mergeConfigs( config, includedData );
                                      });
                       return config;
                   });
    }

    return _loadRecur( inputConfig, {} );
},

_loadInclude: function( include, baseUrl ) {
    var thisB = this;
    // instantiate the adaptor and load the config
    return this._getConfigAdaptor( include )
        .then( function( adaptor ) {
                   if( !adaptor )
                       throw new Error(
                           "Could not load config "+include.url+", "
                               + "no configuration adaptor found for config format "
                               +include.format+' version '+include.version
                       );

                   return adaptor.load(
                       { config: include,
                         baseUrl: baseUrl
                       });
               }
             )
    .then( null,
           function(error) {
               try {
                   if( error.response.status == 404 )
                       return {};
               } catch(e) {}

               throw error;
           });
},

_regularizeIncludes: function( includes ) {
    if( ! includes )
        return [];

    // coerce include to an array
    if( typeof includes != 'object' )
        includes = [ includes ];

    // include array might have undefined elements in it if
    // somebody left a trailing comma in and we are running under
    // IE
    includes = array.filter( includes, function(r) { return r; } );

    return array.map( includes, function( include ) {
        // coerce bare strings in the includes to URLs
        if( typeof include == 'string' )
            include = { url: include };

        // set defaults for format and version
        if( ! ('format' in include) ) {
            include.format = /\.conf$/.test( include.url ) ? 'conf' : 'JB_json';
        }
        if( include.format == 'JB_json' && ! ('version' in include) ) {
            include.version = 1;
        }
        return include;
   });
},

/**
 * @private
 */
_applyDefaults: function( config, defaults ) {
    return Util.deepUpdate( dojo.clone(defaults), config );
},

/**
 * Examine the loaded and merged configuration for errors.  Throws
 * exceptions if it finds anything amiss.
 * @private
 * @returns nothing meaningful
 */
_validateConfig: function( c ) {
    if( ! c.tracks )
        c.tracks = [];
    if( ! c.baseUrl ) {
        this._fatalError( 'Must provide a `baseUrl` in configuration' );
    }
    if( this.hasFatalErrors )
        throw "Errors in configuration, cannot start.";
},

/**
 * @private
 */
_fatalError: function( error ) {
    this.hasFatalErrors = true;
    // if( error.url )
    //     error = error + ' when loading '+error.url;
    this.browser.fatalError( error );
},

// list of config properties that should not be recursively merged
_noRecursiveMerge: function( propName ) {
    return propName == 'datasets';
},

/**
 * Merges config object b into a.  a <- b
 * @private
 */
_mergeConfigs: function( a, b ) {
    if( b === null )
        return null;

    if( a === null )
        a = {};

    for (var prop in b) {
        if( prop == 'tracks' && (prop in a) ) {
            a[prop] = this._mergeTrackConfigs( a[prop] || [], b[prop] || [] );
        }
        else if ( ! this._noRecursiveMerge( prop )
                  &&(prop in a)
                  && ("object" == typeof b[prop])
                  && ("object" == typeof a[prop]) ) {
            a[prop] = Util.deepUpdate( a[prop], b[prop] );
        } else if( typeof a[prop] == 'undefined' || typeof b[prop] != 'undefined' ){
            a[prop] = b[prop];
        }
    }
    return a;
},

/**
 * Special-case merging of two tracks configuration
 * arrays.
 * @private
 */
_mergeTrackConfigs: function( a, b ) {
    if( ! b.length )
        return a;

    // index the tracks in `a` by track label
    var aTracks = {};
    array.forEach( a, function(t,i) {
        t.index = i;
        aTracks[t.label] = t;
    });

    array.forEach( b, function(bT) {
        var aT = aTracks[bT.label];
        if( aT ) {
            this._mergeConfigs( aT, bT );
        } else {
            a.push( bT );
        }
    },this);

    return a;
}

});
});

<commit_msg>Fix problem with templates being filled in too early<commit_after>define(
    [
        'dojo/_base/declare',
        'dojo/_base/lang',
        'dojo/_base/array',
        'dojo/Deferred',
        'dojo/promise/all',

        'JBrowse/Util',
        'JBrowse/ConfigAdaptor/AdaptorUtil'
    ],
    function(
        declare,
        lang,
        array,
        Deferred,
        all,

        Util,
        AdaptorUtil
    ) {

return declare(null,

/**
 * @lends JBrowse.ConfigManager.prototype
 */
{

/**
 * @constructs
 */
constructor: function( args ) {
    this.bootConfig = lang.clone( args.bootConfig || {} );
    this.defaults = lang.clone( args.defaults || {} );
    this.browser = args.browser;
    this.skipValidation = args.skipValidation;

    this.bootConfig = (this._regularizeIncludes ([ this.bootConfig ])) [0];
    var thisB = this;
    this._getConfigAdaptor( this.bootConfig )
        .then( function( adaptor ) {
            thisB.bootConfig = adaptor.regularizeTrackConfigs ( thisB.bootConfig );
    });

    // this.topLevelIncludes = this._fillTemplates(
    //     lang.clone( this.config.include || this.defaults.include ),
    //     this._applyDefaults( lang.clone( this.config ), this.defaults )
    // );
    // delete this.defaults.include;
    // delete this.config.include;
},

/**
 * @param callback {Function} callback, receives a single arguments,
 * which is the final processed configuration object
 */
getFinalConfig: function() {
    return this.finalConfig || ( this.finalConfig = function() {
        var thisB = this;
        var bootstrapConf = this._applyDefaults( lang.clone( this.bootConfig ), this.defaults );
        return this._loadIncludes( bootstrapConf )
            .then( function( includedConfig ) {

                       // merge the boot config *into* the included config last, so
                       // that values in the boot config override the others
                       var finalConf = thisB._mergeConfigs( includedConfig, thisB.bootConfig );

                       thisB._fillTemplates( finalConf, finalConf );

                       finalConf = AdaptorUtil.evalHooks( finalConf );

                       if( ! thisB.skipValidation )
                           thisB._validateConfig( finalConf );

                       return finalConf;
                   });
    }.call(this) );
},

/**
 * Instantiate the right config adaptor for a given configuration source.
 * @param {Object} config the configuraiton
 * @param {Function} callback called with the new config object
 * @returns {Object} the right configuration adaptor to use, or
 * undefined if one could not be found
 * @private
 */

_getConfigAdaptor: function( config_def, callback ) {
    var adaptor_name = "JBrowse/ConfigAdaptor/" + config_def.format;
    if( 'version' in config_def )
        adaptor_name += '_v'+config_def.version;
    adaptor_name.replace( /\W/g,'' );
    return Util.loadJS( [adaptor_name] )
        .then( function( modules ) {
                   return new (modules[0])( config_def );
               });
},

_fillTemplates: function( subconfig, config ) {
    // skip "menuTemplate" keys to prevent messing
    // up their feature-based {} interpolation
    //var skip = { menuTemplate: true };
    var skip = {};

    var type = typeof subconfig;
    if( lang.isArray( subconfig ) ) {
        for( var i = 0; i<subconfig.length; i++ )
            subconfig[i] = this._fillTemplates( subconfig[i], config );
    }
    else if( type == 'object' ) {
        for( var name in subconfig ) {
            if( subconfig.hasOwnProperty( name ) && !skip[name] )
                subconfig[name] = this._fillTemplates( subconfig[name], config );
        }
    }
    else if( type == 'string' ) {
        return Util.fillTemplate( subconfig, config );
    }

    return subconfig;
},

/**
 * Recursively fetch, parse, and merge all the includes in the given
 * config object.  Calls the callback with the resulting configuration
 * when finished.
 * @private
 */
_loadIncludes: function( inputConfig ) {
    var thisB = this;
    inputConfig = lang.clone( inputConfig );

    function _loadRecur( config, upstreamConf ) {
        var sourceUrl = config.sourceUrl || config.baseUrl;
        var newUpstreamConf = thisB._mergeConfigs( lang.clone( upstreamConf ), config );
        var includes = thisB._fillTemplates(
            thisB._regularizeIncludes( config.include || [] ),
            newUpstreamConf
        );
        delete config.include;

        var loads = array.map(
            includes, function( include ) {
                return thisB._loadInclude( include, sourceUrl )
                    .then( function( includedData ) {
                               return _loadRecur(
                                   includedData,
                                   newUpstreamConf
                               );
                           });
            });
        return all( loads )
            .then( function( includedDataObjects ) {
                       array.forEach( includedDataObjects, function( includedData ) {
                                          config = thisB._mergeConfigs( config, includedData );
                                      });
                       return config;
                   });
    }

    return _loadRecur( inputConfig, {} );
},

_loadInclude: function( include, baseUrl ) {
    var thisB = this;
    // instantiate the adaptor and load the config
    return this._getConfigAdaptor( include )
        .then( function( adaptor ) {
                   if( !adaptor )
                       throw new Error(
                           "Could not load config "+include.url+", "
                               + "no configuration adaptor found for config format "
                               +include.format+' version '+include.version
                       );

                   return adaptor.load(
                       { config: include,
                         baseUrl: baseUrl
                       });
               }
             )
    .then( null,
           function(error) {
               try {
                   if( error.response.status == 404 )
                       return {};
               } catch(e) {}

               throw error;
           });
},

_regularizeIncludes: function( includes ) {
    if( ! includes )
        return [];

    // coerce include to an array
    if( typeof includes != 'object' )
        includes = [ includes ];

    // include array might have undefined elements in it if
    // somebody left a trailing comma in and we are running under
    // IE
    includes = array.filter( includes, function(r) { return r; } );

    return array.map( includes, function( include ) {
        // coerce bare strings in the includes to URLs
        if( typeof include == 'string' )
            include = { url: include };

        // set defaults for format and version
        if( ! ('format' in include) ) {
            include.format = /\.conf$/.test( include.url ) ? 'conf' : 'JB_json';
        }
        if( include.format == 'JB_json' && ! ('version' in include) ) {
            include.version = 1;
        }
        return include;
   });
},

/**
 * @private
 */
_applyDefaults: function( config, defaults ) {
    return Util.deepUpdate( dojo.clone(defaults), config );
},

/**
 * Examine the loaded and merged configuration for errors.  Throws
 * exceptions if it finds anything amiss.
 * @private
 * @returns nothing meaningful
 */
_validateConfig: function( c ) {
    if( ! c.tracks )
        c.tracks = [];
    if( ! c.baseUrl ) {
        this._fatalError( 'Must provide a `baseUrl` in configuration' );
    }
    if( this.hasFatalErrors )
        throw "Errors in configuration, cannot start.";
},

/**
 * @private
 */
_fatalError: function( error ) {
    this.hasFatalErrors = true;
    // if( error.url )
    //     error = error + ' when loading '+error.url;
    this.browser.fatalError( error );
},

// list of config properties that should not be recursively merged
_noRecursiveMerge: function( propName ) {
    return propName == 'datasets';
},

/**
 * Merges config object b into a.  a <- b
 * @private
 */
_mergeConfigs: function( a, b ) {
    if( b === null )
        return null;

    if( a === null )
        a = {};

    for (var prop in b) {
        if( prop == 'tracks' && (prop in a) ) {
            a[prop] = this._mergeTrackConfigs( a[prop] || [], b[prop] || [] );
        }
        else if ( ! this._noRecursiveMerge( prop )
                  &&(prop in a)
                  && ("object" == typeof b[prop])
                  && ("object" == typeof a[prop]) ) {
            a[prop] = Util.deepUpdate( a[prop], b[prop] );
        } else if( typeof a[prop] == 'undefined' || typeof b[prop] != 'undefined' ){
            a[prop] = b[prop];
        }
    }
    return a;
},

/**
 * Special-case merging of two tracks configuration
 * arrays.
 * @private
 */
_mergeTrackConfigs: function( a, b ) {
    if( ! b.length )
        return a;

    // index the tracks in `a` by track label
    var aTracks = {};
    array.forEach( a, function(t,i) {
        t.index = i;
        aTracks[t.label] = t;
    });

    array.forEach( b, function(bT) {
        var aT = aTracks[bT.label];
        if( aT ) {
            this._mergeConfigs( aT, bT );
        } else {
            a.push( bT );
        }
    },this);

    return a;
}

});
});

<|endoftext|>


<commit_before>define(
    [
        'dojo/_base/declare',
        'dojo/_base/lang',
        'dojo/_base/array',
        'dojo/Deferred',
        'dojo/promise/all',

        'JBrowse/Util',
        'JBrowse/ConfigAdaptor/AdaptorUtil'
    ],
    function(
        declare,
        lang,
        array,
        Deferred,
        all,

        Util,
        AdaptorUtil
    ) {

return declare(null,

/**
 * @lends JBrowse.ConfigManager.prototype
 */
{

/**
 * @constructs
 */
constructor: function( args ) {
    this.bootConfig = lang.clone( args.bootConfig || {} );
    this.defaults = lang.clone( args.defaults || {} );
    this.browser = args.browser;
    this.skipValidation = args.skipValidation;

    this.bootConfig = (this._regularizeIncludes ([ this.bootConfig ])) [0];
    var thisB = this;
    this._getConfigAdaptor( this.bootConfig )
        .then( function( adaptor ) {
            thisB.bootConfig = adaptor.regularizeTrackConfigs ( thisB.bootConfig );
    });

    // this.topLevelIncludes = this._fillTemplates(
    //     lang.clone( this.config.include || this.defaults.include ),
    //     this._applyDefaults( lang.clone( this.config ), this.defaults )
    // );
    // delete this.defaults.include;
    // delete this.config.include;
},

/**
 * @param callback {Function} callback, receives a single arguments,
 * which is the final processed configuration object
 */
getFinalConfig: function() {
    return this.finalConfig || ( this.finalConfig = function() {
        var thisB = this;
        var bootstrapConf = this._applyDefaults( lang.clone( this.bootConfig ), this.defaults );
        return this._loadIncludes( bootstrapConf )
            .then( function( includedConfig ) {

                       // merge the boot config *into* the included config last, so
                       // that values in the boot config override the others
                       var finalConf = thisB._mergeConfigs( includedConfig, thisB.bootConfig );

                       thisB._fillTemplates( finalConf, finalConf );

                       finalConf = AdaptorUtil.evalHooks( finalConf );

                       if( ! thisB.skipValidation )
                           thisB._validateConfig( finalConf );

                       return finalConf;
                   });
    }.call(this) );
},

/**
 * Instantiate the right config adaptor for a given configuration source.
 * @param {Object} config the configuraiton
 * @param {Function} callback called with the new config object
 * @returns {Object} the right configuration adaptor to use, or
 * undefined if one could not be found
 * @private
 */

_getConfigAdaptor: function( config_def, callback ) {
    var adaptor_name = "JBrowse/ConfigAdaptor/" + config_def.format;
    if( 'version' in config_def )
        adaptor_name += '_v'+config_def.version;
    adaptor_name.replace( /\W/g,'' );
    return Util.loadJS( [adaptor_name] )
        .then( function( modules ) {
                   return new (modules[0])( config_def );
               });
},

_fillTemplates: function( subconfig, config ) {
    // skip "menuTemplate" keys to prevent messing
    // up their feature-based {} interpolation
    //var skip = { menuTemplate: true };
    var skip = {};

    var type = typeof subconfig;
    if( lang.isArray( subconfig ) ) {
        for( var i = 0; i<subconfig.length; i++ )
            subconfig[i] = this._fillTemplates( subconfig[i], config );
    }
    else if( type == 'object' ) {
        for( var name in subconfig ) {
            if( subconfig.hasOwnProperty( name ) && !skip[name] )
                subconfig[name] = this._fillTemplates( subconfig[name], config );
        }
    }
    else if( type == 'string' ) {
        return Util.fillTemplate( subconfig, config );
    }

    return subconfig;
},

/**
 * Recursively fetch, parse, and merge all the includes in the given
 * config object.  Calls the callback with the resulting configuration
 * when finished.
 * @private
 */
_loadIncludes: function( inputConfig ) {
    var thisB = this;
    inputConfig = lang.clone( inputConfig );

    function _loadRecur( config, upstreamConf ) {
        var sourceUrl = config.sourceUrl || config.baseUrl;
        var newUpstreamConf = thisB._mergeConfigs( lang.clone( upstreamConf ), config );
        var includes = thisB._fillTemplates(
            thisB._regularizeIncludes( config.include || [] ),
            newUpstreamConf
        );
        delete config.include;

        var loads = array.map(
            includes, function( include ) {
                return thisB._loadInclude( include, sourceUrl )
                    .then( function( includedData ) {
                               return _loadRecur(
                                   includedData,
                                   newUpstreamConf
                               );
                           });
            });
        return all( loads )
            .then( function( includedDataObjects ) {
                       array.forEach( includedDataObjects, function( includedData ) {
                                          config = thisB._mergeConfigs( config, includedData );
                                      });
                       return config;
                   });
    }

    return _loadRecur( inputConfig, {} );
},

_loadInclude: function( include, baseUrl ) {
    var thisB = this;
    // instantiate the adaptor and load the config
    return this._getConfigAdaptor( include )
        .then( function( adaptor ) {
                   if( !adaptor )
                       throw new Error(
                           "Could not load config "+include.url+", "
                               + "no configuration adaptor found for config format "
                               +include.format+' version '+include.version
                       );

                   return adaptor.load(
                       { config: include,
                         baseUrl: baseUrl
                       });
               }
             )
    .then( null,
           function(error) {
               try {
                   if( error.response.status == 404 )
                       return {};
               } catch(e) {}

               throw error;
           });
},

_regularizeIncludes: function( includes ) {
    if( ! includes )
        return [];

    // coerce include to an array
    if( typeof includes != 'object' )
        includes = [ includes ];

    // include array might have undefined elements in it if
    // somebody left a trailing comma in and we are running under
    // IE
    includes = array.filter( includes, function(r) { return r; } );

    return array.map( includes, function( include ) {
        // coerce bare strings in the includes to URLs
        if( typeof include == 'string' )
            include = { url: include };

        // set defaults for format and version
        if( ! ('format' in include) ) {
            include.format = /\.conf$/.test( include.url ) ? 'conf' : 'JB_json';
        }
        if( include.format == 'JB_json' && ! ('version' in include) ) {
            include.version = 1;
        }
        return include;
   });
},

/**
 * @private
 */
_applyDefaults: function( config, defaults ) {
    return Util.deepUpdate( dojo.clone(defaults), config );
},

/**
 * Examine the loaded and merged configuration for errors.  Throws
 * exceptions if it finds anything amiss.
 * @private
 * @returns nothing meaningful
 */
_validateConfig: function( c ) {
    if( ! c.tracks )
        c.tracks = [];
    if( ! c.baseUrl ) {
        this._fatalError( 'Must provide a `baseUrl` in configuration' );
    }
    if( this.hasFatalErrors )
        throw "Errors in configuration, cannot start.";
},

/**
 * @private
 */
_fatalError: function( error ) {
    this.hasFatalErrors = true;
    // if( error.url )
    //     error = error + ' when loading '+error.url;
    this.browser.fatalError( error );
},

// list of config properties that should not be recursively merged
_noRecursiveMerge: function( propName ) {
    return propName == 'datasets';
},

/**
 * Merges config object b into a.  a <- b
 * @private
 */
_mergeConfigs: function( a, b ) {
    if( b === null )
        return null;

    if( a === null )
        a = {};

    for (var prop in b) {
        if( prop == 'tracks' && (prop in a) ) {
            a[prop] = this._mergeTrackConfigs( a[prop] || [], b[prop] || [] );
        }
        else if ( ! this._noRecursiveMerge( prop )
                  &&(prop in a)
                  && ("object" == typeof b[prop])
                  && ("object" == typeof a[prop]) ) {
            a[prop] = Util.deepUpdate( a[prop], b[prop] );
        } else if(prop == 'dataRoot') {
            if(typeof a[prop] == 'undefined' || a[prop] == 'data' && typeof b[prop] != 'undefined' ){
                a[prop] = b[prop];
            }
        } else if( typeof a[prop] == 'undefined' || typeof b[prop] != 'undefined' ){
            a[prop] = b[prop];
        }
    }
    return a;
},

/**
 * Special-case merging of two tracks configuration
 * arrays.
 * @private
 */
_mergeTrackConfigs: function( a, b ) {
    if( ! b.length )
        return a;

    // index the tracks in `a` by track label
    var aTracks = {};
    array.forEach( a, function(t,i) {
        t.index = i;
        aTracks[t.label] = t;
    });

    array.forEach( b, function(bT) {
        var aT = aTracks[bT.label];
        if( aT ) {
            this._mergeConfigs( aT, bT );
        } else {
            a.push( bT );
        }
    },this);

    return a;
}

});
});

<commit_msg>Compare direct types<commit_after>define(
    [
        'dojo/_base/declare',
        'dojo/_base/lang',
        'dojo/_base/array',
        'dojo/Deferred',
        'dojo/promise/all',

        'JBrowse/Util',
        'JBrowse/ConfigAdaptor/AdaptorUtil'
    ],
    function(
        declare,
        lang,
        array,
        Deferred,
        all,

        Util,
        AdaptorUtil
    ) {

return declare(null,

/**
 * @lends JBrowse.ConfigManager.prototype
 */
{

/**
 * @constructs
 */
constructor: function( args ) {
    this.bootConfig = lang.clone( args.bootConfig || {} );
    this.defaults = lang.clone( args.defaults || {} );
    this.browser = args.browser;
    this.skipValidation = args.skipValidation;

    this.bootConfig = (this._regularizeIncludes ([ this.bootConfig ])) [0];
    var thisB = this;
    this._getConfigAdaptor( this.bootConfig )
        .then( function( adaptor ) {
            thisB.bootConfig = adaptor.regularizeTrackConfigs ( thisB.bootConfig );
    });

    // this.topLevelIncludes = this._fillTemplates(
    //     lang.clone( this.config.include || this.defaults.include ),
    //     this._applyDefaults( lang.clone( this.config ), this.defaults )
    // );
    // delete this.defaults.include;
    // delete this.config.include;
},

/**
 * @param callback {Function} callback, receives a single arguments,
 * which is the final processed configuration object
 */
getFinalConfig: function() {
    return this.finalConfig || ( this.finalConfig = function() {
        var thisB = this;
        var bootstrapConf = this._applyDefaults( lang.clone( this.bootConfig ), this.defaults );
        return this._loadIncludes( bootstrapConf )
            .then( function( includedConfig ) {

                       // merge the boot config *into* the included config last, so
                       // that values in the boot config override the others
                       var finalConf = thisB._mergeConfigs( includedConfig, thisB.bootConfig );

                       thisB._fillTemplates( finalConf, finalConf );

                       finalConf = AdaptorUtil.evalHooks( finalConf );

                       if( ! thisB.skipValidation )
                           thisB._validateConfig( finalConf );

                       return finalConf;
                   });
    }.call(this) );
},

/**
 * Instantiate the right config adaptor for a given configuration source.
 * @param {Object} config the configuraiton
 * @param {Function} callback called with the new config object
 * @returns {Object} the right configuration adaptor to use, or
 * undefined if one could not be found
 * @private
 */

_getConfigAdaptor: function( config_def, callback ) {
    var adaptor_name = "JBrowse/ConfigAdaptor/" + config_def.format;
    if( 'version' in config_def )
        adaptor_name += '_v'+config_def.version;
    adaptor_name.replace( /\W/g,'' );
    return Util.loadJS( [adaptor_name] )
        .then( function( modules ) {
                   return new (modules[0])( config_def );
               });
},

_fillTemplates: function( subconfig, config ) {
    // skip "menuTemplate" keys to prevent messing
    // up their feature-based {} interpolation
    //var skip = { menuTemplate: true };
    var skip = {};

    var type = typeof subconfig;
    if( lang.isArray( subconfig ) ) {
        for( var i = 0; i<subconfig.length; i++ )
            subconfig[i] = this._fillTemplates( subconfig[i], config );
    }
    else if( type == 'object' ) {
        for( var name in subconfig ) {
            if( subconfig.hasOwnProperty( name ) && !skip[name] )
                subconfig[name] = this._fillTemplates( subconfig[name], config );
        }
    }
    else if( type == 'string' ) {
        return Util.fillTemplate( subconfig, config );
    }

    return subconfig;
},

/**
 * Recursively fetch, parse, and merge all the includes in the given
 * config object.  Calls the callback with the resulting configuration
 * when finished.
 * @private
 */
_loadIncludes: function( inputConfig ) {
    var thisB = this;
    inputConfig = lang.clone( inputConfig );

    function _loadRecur( config, upstreamConf ) {
        var sourceUrl = config.sourceUrl || config.baseUrl;
        var newUpstreamConf = thisB._mergeConfigs( lang.clone( upstreamConf ), config );
        var includes = thisB._fillTemplates(
            thisB._regularizeIncludes( config.include || [] ),
            newUpstreamConf
        );
        delete config.include;

        var loads = array.map(
            includes, function( include ) {
                return thisB._loadInclude( include, sourceUrl )
                    .then( function( includedData ) {
                               return _loadRecur(
                                   includedData,
                                   newUpstreamConf
                               );
                           });
            });
        return all( loads )
            .then( function( includedDataObjects ) {
                       array.forEach( includedDataObjects, function( includedData ) {
                                          config = thisB._mergeConfigs( config, includedData );
                                      });
                       return config;
                   });
    }

    return _loadRecur( inputConfig, {} );
},

_loadInclude: function( include, baseUrl ) {
    var thisB = this;
    // instantiate the adaptor and load the config
    return this._getConfigAdaptor( include )
        .then( function( adaptor ) {
                   if( !adaptor )
                       throw new Error(
                           "Could not load config "+include.url+", "
                               + "no configuration adaptor found for config format "
                               +include.format+' version '+include.version
                       );

                   return adaptor.load(
                       { config: include,
                         baseUrl: baseUrl
                       });
               }
             )
    .then( null,
           function(error) {
               try {
                   if( error.response.status == 404 )
                       return {};
               } catch(e) {}

               throw error;
           });
},

_regularizeIncludes: function( includes ) {
    if( ! includes )
        return [];

    // coerce include to an array
    if( typeof includes != 'object' )
        includes = [ includes ];

    // include array might have undefined elements in it if
    // somebody left a trailing comma in and we are running under
    // IE
    includes = array.filter( includes, function(r) { return r; } );

    return array.map( includes, function( include ) {
        // coerce bare strings in the includes to URLs
        if( typeof include == 'string' )
            include = { url: include };

        // set defaults for format and version
        if( ! ('format' in include) ) {
            include.format = /\.conf$/.test( include.url ) ? 'conf' : 'JB_json';
        }
        if( include.format == 'JB_json' && ! ('version' in include) ) {
            include.version = 1;
        }
        return include;
   });
},

/**
 * @private
 */
_applyDefaults: function( config, defaults ) {
    return Util.deepUpdate( dojo.clone(defaults), config );
},

/**
 * Examine the loaded and merged configuration for errors.  Throws
 * exceptions if it finds anything amiss.
 * @private
 * @returns nothing meaningful
 */
_validateConfig: function( c ) {
    if( ! c.tracks )
        c.tracks = [];
    if( ! c.baseUrl ) {
        this._fatalError( 'Must provide a `baseUrl` in configuration' );
    }
    if( this.hasFatalErrors )
        throw "Errors in configuration, cannot start.";
},

/**
 * @private
 */
_fatalError: function( error ) {
    this.hasFatalErrors = true;
    // if( error.url )
    //     error = error + ' when loading '+error.url;
    this.browser.fatalError( error );
},

// list of config properties that should not be recursively merged
_noRecursiveMerge: function( propName ) {
    return propName == 'datasets';
},

/**
 * Merges config object b into a.  a <- b
 * @private
 */
_mergeConfigs: function( a, b ) {
    if( b === null )
        return null;

    if( a === null )
        a = {};

    for (var prop in b) {
        if( prop == 'tracks' && (prop in a) ) {
            a[prop] = this._mergeTrackConfigs( a[prop] || [], b[prop] || [] );
        }
        else if ( ! this._noRecursiveMerge( prop )
                  &&(prop in a)
                  && ("object" == typeof b[prop])
                  && ("object" == typeof a[prop]) ) {
            a[prop] = Util.deepUpdate( a[prop], b[prop] );
        } else if(prop == 'dataRoot') {
            if(a[prop] === undefined || a[prop] == 'data' && b[prop] !== undefined ){
                a[prop] = b[prop];
            }
        } else if( a[prop] === undefined || b[prop] !== undefined ){
            a[prop] = b[prop];
        }
    }
    return a;
},

/**
 * Special-case merging of two tracks configuration
 * arrays.
 * @private
 */
_mergeTrackConfigs: function( a, b ) {
    if( ! b.length )
        return a;

    // index the tracks in `a` by track label
    var aTracks = {};
    array.forEach( a, function(t,i) {
        t.index = i;
        aTracks[t.label] = t;
    });

    array.forEach( b, function(bT) {
        var aT = aTracks[bT.label];
        if( aT ) {
            this._mergeConfigs( aT, bT );
        } else {
            a.push( bT );
        }
    },this);

    return a;
}

});
});

<|endoftext|>


<commit_before>const electron = require( 'electron' );

// global reference to the main window
var win = null;

/**
 *
 */
function activateWindow() {

    if ( win !== null ) {
        return;
    }

    win = new electron.BrowserWindow( {
        width: 1120,
        height: 680,
        webPreferences: {
            nodeIntegration: true,
            webSecurity: false // required to open local images in browser
        }
    });
    win.setMenu( null );

    // '../electron[.exe]' => host in development mode
    // '../hakuneko[.exe]' => host in distribution mode
    if( process.argv && process.argv.length > 0 && process.argv[0].match(/electron(?:\.exe)?$/i) ) {
        // local served app
        win.loadURL( 'http://127.0.0.1:8081' );
        // open dev tools
        win.webContents.openDevTools();
    } else {
        // official distributed app
        win.loadURL( 'http://hakuneko.ovh' );
    }

    /**
     * Replace any existing event listener function registered by previous browser window that would be released when reloding page.
     * This prevents the "Attempting to call a function in a renderer window that has been closed or released" error.
     */
    win.webContents.on( 'devtools-reload-page', ( e ) => {
        electron.session.defaultSession.webRequest.onBeforeSendHeaders( [], ( details, callback ) => {
            callback({
                cancel: false
            });
        });
    });

    win.on( 'closed', () => {
        win = null;
    });
}

/**
 * Quit aplication, except for OSX
 */
function closeWindow () {
    if( process.platform !== 'darwin' ) {
        electron.app.quit();
    }
}

// connect events
electron.app.on( 'ready', activateWindow );
electron.app.on( 'activate', activateWindow );
electron.app.on( 'window-all-closed', closeWindow );<commit_msg>close window even on darwin<commit_after>const electron = require( 'electron' );

// global reference to the main window
var win = null;

/**
 *
 */
function activateWindow() {

    if ( win !== null ) {
        return;
    }

    win = new electron.BrowserWindow( {
        width: 1120,
        height: 680,
        webPreferences: {
            nodeIntegration: true,
            webSecurity: false // required to open local images in browser
        }
    });
    win.setMenu( null );

    // '../electron[.exe]' => host in development mode
    // '../hakuneko[.exe]' => host in distribution mode
    if( process.argv && process.argv.length > 0 && process.argv[0].match(/electron(?:\.exe)?$/i) ) {
        // local served app
        win.loadURL( 'http://127.0.0.1:8081' );
        // open dev tools
        win.webContents.openDevTools();
    } else {
        // official distributed app
        win.loadURL( 'http://hakuneko.ovh' );
    }

    /**
     * Replace any existing event listener function registered by previous browser window that would be released when reloding page.
     * This prevents the "Attempting to call a function in a renderer window that has been closed or released" error.
     */
    win.webContents.on( 'devtools-reload-page', ( e ) => {
        electron.session.defaultSession.webRequest.onBeforeSendHeaders( [], ( details, callback ) => {
            callback({
                cancel: false
            });
        });
    });

    win.on( 'closed', () => {
        win = null;
    });
}

/**
 * Quit aplication, except for OSX
 */
function closeWindow () {
    //if( process.platform !== 'darwin' ) {
        electron.app.quit();
    //}
}

// connect events
electron.app.on( 'ready', activateWindow );
electron.app.on( 'activate', activateWindow );
electron.app.on( 'window-all-closed', closeWindow );<|endoftext|>


<commit_before><commit_msg>Update gulpfile.js<commit_after><|endoftext|>


<commit_before><commit_msg>Fix streaming API double-JSON-encoding status IDs for deletes (#5069)<commit_after><|endoftext|>


<commit_before>'use strict';

const P = require('bluebird');
const HyperSwitch = require('hyperswitch');
const URI = HyperSwitch.URI;
const Template = HyperSwitch.Template;
const mwUtil = require('../lib/mwUtil');
const BaseFeed = require('../lib/base_feed');

const PARTS_URIS = {
    tfa: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/page/featured/{{yyyy}}/{{mm}}/{{dd}}',
            query: {
                aggregated: true
            }
        }),
        renewable: true
    },
    mostread: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/page/most-read/{{yyyy}}/{{mm}}/{{dd}}',
            query: {
                aggregated: true
            }
        }),
        renewable: true
    },
    image: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/media/image/featured/{{yyyy}}/{{mm}}/{{dd}}',
            query: {
                aggregated: true
            }
        }),
        renewable: true
    },
    news: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/page/news',
            query: {
                aggregated: true
            }
        }),
        renewable: false
    },
    onthisday: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/feed/onthisday/selected/{{mm}}/{{dd}}'
        }),
        renewable: true
    }
};

class Feed extends BaseFeed {
    // TODO: this is temporary code to increase the size of the TFA thumbnail
    _hydrateResponse(hyper, req, res) {
        const rp = req.params;
        const fetchSummary = uri => mwUtil.fetchSummary(hyper, uri);
        if (res.body.tfa && res.body.tfa.$merge && res.body.tfa.$merge.length) {
            const summaryURI = res.body.tfa.$merge[0];
            const title = decodeURIComponent(
                summaryURI.substr(summaryURI.lastIndexOf('/') + 1));
            const highQualityThumbRequest = hyper.get({
                method: 'post',
                uri: new URI([rp.domain, 'sys', 'action', 'query']),
                body: {
                    prop: 'pageimages',
                    piprop: 'thumbnail|original',
                    pithumbsize: 640,
                    pilicense: 'any',
                    titles: title
                }
            });
            return P.join(
                mwUtil.hydrateResponse(res, fetchSummary),
                highQualityThumbRequest
            ).then((result) => {
                const thumbRes = result[1].body;
                if (thumbRes.items && thumbRes.items.length && thumbRes.items[0].thumbnail) {
                    const newThumb = thumbRes.items[0].thumbnail;
                    newThumb.source = newThumb.source.replace(/^http:/, 'https:');
                    result[0].body.tfa.thumbnail = newThumb;
                    if (thumbRes.items[0].original) {
                        const newOriginal = thumbRes.items[0].original;
                        newOriginal.source = newOriginal.source.replace(/^http:/, 'https:');
                        result[0].body.tfa.originalimage = newOriginal;
                    }
                }
                return result[0];
            });
        } else {
            return mwUtil.hydrateResponse(res, fetchSummary);
        }
    }

    _makeFeedRequests(hyper, req, isHistoric) {
        const props = {};
        let parts = Object.keys(PARTS_URIS);
        if (isHistoric) {
            parts = parts.filter(part => PARTS_URIS[part].renewable);
        }
        parts.forEach((part) => {
            props[part] = hyper.get(PARTS_URIS[part].reqTemplate.expand({
                options: this.options,
                request: req
            }))
            // Don't fail all if one of the parts failed.
            .catchReturn({});
        });
        return P.props(props);
    }

    getDateAndKey(req) {
        mwUtil.verifyDateParams(req);
        const date = mwUtil.getDateSafe(req.params);
        return {
            date,
            key: date.toISOString().split('T').shift()
        };
    }

    constructBody(result) {
        const body = {};
        Object.keys(result).forEach((key) => {
            if (result[key].body && Object.keys(result[key].body).length) {
                // TODO: temp code to support transition to new MCS response format
                if (key === 'onthisday' && result.onthisday.body.selected) {
                    body[key] = result.onthisday.body.selected;
                } else {
                    body[key] = result[key].body;
                }
            }
        });
        return body;
    }
}

const spec = HyperSwitch.utils.loadSpec(`${__dirname}/feed.yaml`);

module.exports = (options) => {
    options.name = 'feed.aggregated';
    // TODO: need a way to dynamically derive this
    options.content_type = 'application/json; charset=utf-8; ' +
        'profile="https://www.mediawiki.org/wiki/Specs/aggregated-feed/0.5.0"';
    options.spec = spec;
    options.storeHistory = false;

    return new Feed(options).getModuleDeclaration();
};
<commit_msg>Minor DRY fix: use _hydrateResponse from superclass in feed.js<commit_after>'use strict';

const P = require('bluebird');
const HyperSwitch = require('hyperswitch');
const URI = HyperSwitch.URI;
const Template = HyperSwitch.Template;
const mwUtil = require('../lib/mwUtil');
const BaseFeed = require('../lib/base_feed');

const PARTS_URIS = {
    tfa: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/page/featured/{{yyyy}}/{{mm}}/{{dd}}',
            query: {
                aggregated: true
            }
        }),
        renewable: true
    },
    mostread: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/page/most-read/{{yyyy}}/{{mm}}/{{dd}}',
            query: {
                aggregated: true
            }
        }),
        renewable: true
    },
    image: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/media/image/featured/{{yyyy}}/{{mm}}/{{dd}}',
            query: {
                aggregated: true
            }
        }),
        renewable: true
    },
    news: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/page/news',
            query: {
                aggregated: true
            }
        }),
        renewable: false
    },
    onthisday: {
        reqTemplate: new Template({
            uri: '{{options.host}}/{{domain}}/v1/feed/onthisday/selected/{{mm}}/{{dd}}'
        }),
        renewable: true
    }
};

class Feed extends BaseFeed {
    // TODO: this is temporary code to increase the size of the TFA thumbnail
    _hydrateResponse(hyper, req, res) {
        const rp = req.params;
        if (res.body.tfa && res.body.tfa.$merge && res.body.tfa.$merge.length) {
            const summaryURI = res.body.tfa.$merge[0];
            const title = decodeURIComponent(
                summaryURI.substr(summaryURI.lastIndexOf('/') + 1));
            const highQualityThumbRequest = hyper.get({
                method: 'post',
                uri: new URI([rp.domain, 'sys', 'action', 'query']),
                body: {
                    prop: 'pageimages',
                    piprop: 'thumbnail|original',
                    pithumbsize: 640,
                    pilicense: 'any',
                    titles: title
                }
            });
            return P.join(
                super._hydrateResponse(hyper, req, res),
                highQualityThumbRequest
            ).then((result) => {
                const thumbRes = result[1].body;
                if (thumbRes.items && thumbRes.items.length && thumbRes.items[0].thumbnail) {
                    const newThumb = thumbRes.items[0].thumbnail;
                    newThumb.source = newThumb.source.replace(/^http:/, 'https:');
                    result[0].body.tfa.thumbnail = newThumb;
                    if (thumbRes.items[0].original) {
                        const newOriginal = thumbRes.items[0].original;
                        newOriginal.source = newOriginal.source.replace(/^http:/, 'https:');
                        result[0].body.tfa.originalimage = newOriginal;
                    }
                }
                return result[0];
            });
        } else {
            return super._hydrateResponse(hyper, req, res);
        }
    }

    _makeFeedRequests(hyper, req, isHistoric) {
        const props = {};
        let parts = Object.keys(PARTS_URIS);
        if (isHistoric) {
            parts = parts.filter(part => PARTS_URIS[part].renewable);
        }
        parts.forEach((part) => {
            props[part] = hyper.get(PARTS_URIS[part].reqTemplate.expand({
                options: this.options,
                request: req
            }))
            // Don't fail all if one of the parts failed.
            .catchReturn({});
        });
        return P.props(props);
    }

    getDateAndKey(req) {
        mwUtil.verifyDateParams(req);
        const date = mwUtil.getDateSafe(req.params);
        return {
            date,
            key: date.toISOString().split('T').shift()
        };
    }

    constructBody(result) {
        const body = {};
        Object.keys(result).forEach((key) => {
            if (result[key].body && Object.keys(result[key].body).length) {
                // TODO: temp code to support transition to new MCS response format
                if (key === 'onthisday' && result.onthisday.body.selected) {
                    body[key] = result.onthisday.body.selected;
                } else {
                    body[key] = result[key].body;
                }
            }
        });
        return body;
    }
}

const spec = HyperSwitch.utils.loadSpec(`${__dirname}/feed.yaml`);

module.exports = (options) => {
    options.name = 'feed.aggregated';
    // TODO: need a way to dynamically derive this
    options.content_type = 'application/json; charset=utf-8; ' +
        'profile="https://www.mediawiki.org/wiki/Specs/aggregated-feed/0.5.0"';
    options.spec = spec;
    options.storeHistory = false;

    return new Feed(options).getModuleDeclaration();
};
<|endoftext|>


<commit_before>module.exports = '2018-04-06';
<commit_msg>bump version<commit_after>module.exports = '2018-04-08';
<|endoftext|>


<commit_before>(function (enyo, scope) {

	/**
	* Canvas is a UI library for Enyo 2.
	*
	* The library is mainly intended as a demonstration, rather than a complete
	* tool for canvas manipulation, and there are no changes or additional
	* features planned.
	*
	* @namespace enyo.canvas
	*/

	if (enyo && enyo.version) {
		enyo.version.canvas = "2.6.0-zzz.1.dev";
	}

})(enyo, this);
<commit_msg>Update version string to 2.6.0-pre.4<commit_after>(function (enyo, scope) {

	/**
	* Canvas is a UI library for Enyo 2.
	*
	* The library is mainly intended as a demonstration, rather than a complete
	* tool for canvas manipulation, and there are no changes or additional
	* features planned.
	*
	* @namespace enyo.canvas
	*/

	if (enyo && enyo.version) {
		enyo.version.canvas = "2.6.0-pre.4";
	}

})(enyo, this);
<|endoftext|>


<commit_before>if (enyo && enyo.version) {
	enyo.version.spotlight = "2.5.3-zzz.3";
}
<commit_msg>Update version string to 2.5.3-zzz.4<commit_after>if (enyo && enyo.version) {
	enyo.version.spotlight = "2.5.3-zzz.4";
}
<|endoftext|>


<commit_before>if (enyo && enyo.version) {
	enyo.version.extra = "2.5.2-pre.3";
}
<commit_msg>Update version string to 2.5.2-pre.5<commit_after>if (enyo && enyo.version) {
	enyo.version.extra = "2.5.2-pre.5";
}
<|endoftext|>


<commit_before>(function (enyo, scope) {
	/**
		A library of UI widgets designed for use alongside Enyo core in the
		development of smart TV applications.

		@namespace moon
	*/
	var moon = scope.moon = scope.moon || {};

	if (enyo && enyo.version) {
		enyo.version.moonstone = "2.5.4-pre.1.lite.1";
	}

	/**
	* Global *design-time* configuration options for Moonstone
	*
	* @param {Boolean} accelerate `true` to prefer CSS transforms over position properties
	* @type {Object}
	*/
	moon.config = enyo.mixin({
		accelerate: false
	}, moon.config);
})(enyo, this);
<commit_msg>Update version string to 2.5.4-pre.1.lite.2<commit_after>(function (enyo, scope) {
	/**
		A library of UI widgets designed for use alongside Enyo core in the
		development of smart TV applications.

		@namespace moon
	*/
	var moon = scope.moon = scope.moon || {};

	if (enyo && enyo.version) {
		enyo.version.moonstone = "2.5.4-pre.1.lite.2";
	}

	/**
	* Global *design-time* configuration options for Moonstone
	*
	* @param {Boolean} accelerate `true` to prefer CSS transforms over position properties
	* @type {Object}
	*/
	moon.config = enyo.mixin({
		accelerate: false
	}, moon.config);
})(enyo, this);
<|endoftext|>


<commit_before>{"text":"V1","color":"00cc33"}
<commit_msg>this is version 2<commit_after>{"text":"V2","color":"0099cc"}
<|endoftext|>


<commit_before>/* vsb.xhtml - Main program UI
 * This file is a part of Visual struct Builder
 *
 * Copyright © 2013, Kirn Gill II <segin2005@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

var typesList = [
	"char_arr",
	"int8_t",
	"uint8_t",
	"int16_t",
	"uint16_t",
	"int32_t",
	"uint32_t",
	"int64_t",
	"uint64_t"
];

var typesName = [
	"char[]",
	"int8_t",
	"uint8_t",
	"int16_t",
	"uint16_t",
	"int32_t",
	"uint32_t",
	"int64_t",
	"uint64_t"
];

function addElem() {
	var elem = document.createElement("span");
	elem.className = "elem";
	var types = document.createElement("select");
	types.className = "etype";
	for(var i = 0; i < typesList.length; i++) {
		var item = new Option();
		item.value = typesList[i];
		item.text = typesName[i];
		types.options.add(item);
	}
	elem.appendChild(types);
	var lbl = document.createElement("label");
	lbl.textContent = "Length:";
	elem.appendChild(lbl);
	var classes = [ "elen", "ename" ];
	for(var i = 0; i < classes.length; i++) {
		var input = document.createElement("input");
		input.className = classes[i];
		input.type = "text";
		elem.appendChild(input);
	}
}

function resetElemList() {
	var elemlist = document.getElementsByClassName("elem");
	for (var x = 0; x < elemlist.length; x++) {
		document.getElementById("elems").removeChild(elemlist[x]);
	}
}
<commit_msg>vsb: Added hiding of charater array length field/fieldlabel if not char[] type select.<commit_after>/* vsb.xhtml - Main program UI
 * This file is a part of Visual struct Builder
 *
 * Copyright © 2013, Kirn Gill II <segin2005@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

var typesList = [
	"char_arr",
	"int8_t",
	"uint8_t",
	"int16_t",
	"uint16_t",
	"int32_t",
	"uint32_t",
	"int64_t",
	"uint64_t"
];

var typesName = [
	"char[]",
	"int8_t",
	"uint8_t",
	"int16_t",
	"uint16_t",
	"int32_t",
	"uint32_t",
	"int64_t",
	"uint64_t"
];

function addElem() {
	var elem = document.createElement("span");
	elem.className = "elem";
	var types = document.createElement("select");
	types.className = "etype";
	types.onchange = function() {
		if(types.value == "char_arr") {
			var lbl = types.parentElement.getElementsByTagName("label");
			lbl[0].hidden = false;
			var len = types.parentElement.getElementsByClassName("elen");
			len[0].hidden = false;
		} else {
			var lbl = types.parentElement.getElementsByTagName("label");
			lbl[0].hidden = true;
			var len = types.parentElement.getElementsByClassName("elen");
			len[0].hidden = true;
		}
	};
	for(var i = 0; i < typesList.length; i++) {
		var item = new Option();
		item.value = typesList[i];
		item.text = typesName[i];
		types.options.add(item);
	}
	elem.appendChild(types);
	var lbl = document.createElement("label");
	lbl.textContent = "Length:";
	elem.appendChild(lbl);
	var classes = [ "elen", "ename" ];
	for(var i = 0; i < classes.length; i++) {
		var input = document.createElement("input");
		input.className = classes[i];
		input.type = "text";
		elem.appendChild(input);
	}
}

function resetElemList() {
	var elemlist = document.getElementsByClassName("elem");
	for (var x = 0; x < elemlist.length; x++) {
		document.getElementById("elems").removeChild(elemlist[x]);
	}
}
<|endoftext|>


<commit_before>module.exports = function (wallaby) {
	var typescriptOptions = {
		module: 'commonjs',
		target: 'es5',
		transpileOnly: true,
	};

	return {
		files: [
			{ pattern: 'src/**/*.ts', load: false },
		],

		tests: [
			{ pattern: 'tests/**/*.ts' },
		],

		compilers: {
			'**/*.ts': wallaby.compilers.typeScript(typescriptOptions),
		},

		testFramework: 'mocha',

		env: {
			type: 'node',
			runner: 'node',
		},
	};
};<commit_msg>Fix config<commit_after>module.exports = function (wallaby) {
	var typescriptOptions = {
		module: 'commonjs',
		target: 'es5',
		transpileOnly: true,
	};

	return {
		files: [
			{ pattern: 'src/**/*.ts', load: false },
			{ pattern: 'tests/**/*.ts', load: false, instrument: false },
			{ pattern: 'tests/**/*.spec.ts', ignore: true },
		],

		tests: [
			{ pattern: 'tests/**/*.spec.ts' },
		],

		compilers: {
			'**/*.ts': wallaby.compilers.typeScript(typescriptOptions),
		},

		testFramework: 'mocha',

		env: {
			type: 'node',
			runner: 'node',
		},
	};
};<|endoftext|>