<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)
    {
    }
  ,
};

phoxy._RenderSubsystem._.birth =
{
  Decision: function()
    {
      var args = arguments;
      for (var i = 0; i < 2; i++)
        if (Array.isArray(args[i]))
        {
          args[i] = phoxy.ConstructURL(args[i]);
          return phoxy._.render.Decision.apply(this, args);
        }

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

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

      if (typeof args[1] === 'undefined')
        return phoxy._.birth.Fortune(args[0], callback);
      if (typeof args[1] !== 'object')
        return phoxy._.birth.Hope(args[0], args[1], callback);
      return phoxy._.birth.Fate(args[0]. args[1], callback);
    }
  ,
  Fortune: function(word, callback)
    {
      if (typeof(word) === 'undefined')
        return phoxy._.birth.Vision(callback);
      else if (typeof(word) === 'string')
        return phoxy._.birth.Prophecy(word);
      else if (typeof(word) !== 'object')
        return phoxy._.birth.Presage(word);
      phoxy.Log(0, "birth.Fortune", word, "(Failed object recognize)");
    }
  ,
  Hope: function()
    {
      var args = arguments;
      var idea = args[1];

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

      if (typeof(idea) === 'string')
        return phoxy._.birth.Desire(idea, DataLoadedCallback);
      else if (typeof(idea) === 'function')
      {
        var data = phoxy._.birth.Pray(args[1], DataLoadedCallback);
        if (typeof(data) === 'object')
          DataLoadedCallback(data);
      }
      else
        phoxy.Log(0, "birth.Hope", idea, "(Failed data receive)");
    }
  ,
  Fate: function(design, data, callback)
    {
      if (typeof(design) === 'undefined')
        return phoxy._.birth.Vision(callback, design, data);
      else if (typeof(design) === 'function')
        design = phoxy._.birth.Mutation.apply(phoxy._.birth, arguments);

      if (typeof(design) === 'string')
        return phoxy._.birth.Conceive(design, data, callback, raw_output);
    }
  ,
  Vision: function(cb, design, data)
    {
      return cb(design, data);
    }
  ,
  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);
    }
}<commit_msg>Link Fancy with Decision<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()
    {
      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 (){};

      return phoxy._.birth.Decision(args[0], args[1], callback);
    }
  ,
};

phoxy._RenderSubsystem._.birth =
{
  Decision: function(will, spirit, callback)
    {
      if (typeof spirit === 'undefined')
        return phoxy._.birth.Fortune(will, callback);
      if (typeof spirit !== 'object')
        return phoxy._.birth.Hope(will, spirit, callback);
      return phoxy._.birth.Fate(will, spirit, callback);
    }
  ,
  Fortune: function(word, callback)
    {
      if (typeof(word) === 'undefined')
        return phoxy._.birth.Vision(callback);
      else if (typeof(word) === 'string')
        return phoxy._.birth.Prophecy(word);
      else if (typeof(word) !== 'object')
        return phoxy._.birth.Presage(word);
      phoxy.Log(0, "birth.Fortune", word, "(Failed object recognize)");
    }
  ,
  Hope: function()
    {
      var args = arguments;
      var idea = args[1];

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

      if (typeof(idea) === 'string')
        return phoxy._.birth.Desire(idea, DataLoadedCallback);
      else if (typeof(idea) === 'function')
      {
        var data = phoxy._.birth.Pray(args[1], DataLoadedCallback);
        if (typeof(data) === 'object')
          DataLoadedCallback(data);
      }
      else
        phoxy.Log(0, "birth.Hope", idea, "(Failed data receive)");
    }
  ,
  Fate: function(design, data, callback)
    {
      if (typeof(design) === 'undefined')
        return phoxy._.birth.Vision(callback, design, data);
      else if (typeof(design) === 'function')
        design = phoxy._.birth.Mutation.apply(phoxy._.birth, arguments);

      if (typeof(design) === 'string')
        return phoxy._.birth.Conceive(design, data, callback, raw_output);
    }
  ,
  Vision: function(cb, design, data)
    {
      return cb(design, data);
    }
  ,
  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>'use strict';

angular.module('vlui')
  .service('Pills', function (ANY, consts, util, vl, cql) {
    var Pills = {
      // Functions
      isAnyChannel: isAnyChannel,
      getNextAnyChannelId: getNextAnyChannelId,
      getEmptyAnyChannelId: getEmptyAnyChannelId,
      isEnumeratedChannel: isEnumeratedChannel,
      isEnumeratedField: isEnumeratedField,

      get: get,
      // Event
      dragDrop: dragDrop,
      dragStart: dragStart,
      dragStop: dragStop,
      // Event, with handler in the listener

      /** Set a fieldDef for a channel */
      set: set,

      /** Remove a fieldDef from a channel */
      remove: remove,

      countFieldDef: {field: '*', aggregate: vl.aggregate.AggregateOp.COUNT, type: vl.type.QUANTITATIVE},

      // Data
      // TODO: split between encoding related and non-encoding related
      pills: {},
      highlighted: {},
      /** pill being dragged */
      dragging: null,
      isDraggingWildcard: null,
      /** channelId that's the pill is being dragged from */
      cidDragFrom: null,
      /** Listener  */
      listener: null
    };

    // Add listener type that Pills just pass arguments to its listener
    // FIXME: properly implement listener pattern
    [
      'add', 'parse', 'select', 'preview', 'update', 'reset',
      'rescale', 'sort', 'toggleFilterInvalid', 'transpose',
      'addWildcardField', 'addWildcard', 'removeWildcardField', 'removeWildcard'
    ].forEach(function(listenerType) {
      Pills[listenerType] = function() {
        if (Pills.listener && Pills.listener[listenerType]) {
          return Pills.listener[listenerType].apply(null, arguments);
        }
      };
    });

    /**
     * Returns whether the given channel id is an "any" channel
     *
     * @param {any} channelId
     */
    function isAnyChannel(channelId) {
      return channelId && channelId.indexOf(ANY) === 0; // prefix by ANY
    }

    function getEmptyAnyChannelId() {
      var anyChannels = util.keys(Pills.pills).filter(function(channelId) {
        return channelId.indexOf(ANY) === 0;
      });
      for (var i=0 ; i < anyChannels.length; i++) {
        var channelId = anyChannels[i];
        if (!Pills.pills[channelId].field) {
          return channelId;
        }
      }
      throw new Error('No empty any channel available!');
    }

    function getNextAnyChannelId() {
      var i = 0;
      while (Pills.pills[ANY + i]) {
        i++;
      }

      if (!consts.maxAnyShelf || i >= consts.maxAnyShelf) {
        return null;
      }

      return ANY + i;
    }

    /**
     * Set a fieldDef of a pill of a given channelId
     * @param channelId channel id of the pill to be updated
     * @param fieldDef fieldDef to to be updated
     * @param update whether to propagate change to the channel update listener
     */
    function set(channelId, fieldDef, update) {
      Pills.pills[channelId] = fieldDef;

      if (update && Pills.listener) {
        Pills.listener.set(channelId, fieldDef);
      }
    }

    /**
     * Get a fieldDef of a pill of a given channelId
     */
    function get(channelId) {
      return Pills.pills[channelId];
    }

    function isEnumeratedChannel(channelId) {
      if (Pills.listener && Pills.listener.isEnumeratedChannel) {
        return Pills.listener.isEnumeratedChannel(channelId, Pills.pills[channelId]);
      }
      return false;
    }

    function isEnumeratedField(channelId) {
      if (Pills.listener && Pills.listener.isEnumeratedField) {
        return Pills.listener.isEnumeratedField(channelId, Pills.pills[channelId]);
      }
      return false;
    }

    function remove(channelId) {
      delete Pills.pills[channelId];
      if (Pills.listener) {
        Pills.listener.remove(channelId);
      }
    }

    /**
     * @param {any} pill pill being dragged
     * @param {any} cidDragFrom channel id that the pill is dragged from
     */
    function dragStart(pill, cidDragFrom) {
      Pills.dragging = pill;
      Pills.isDraggingWildcard = cql.enumSpec.isEnumSpec(pill.field);
      Pills.cidDragFrom = cidDragFrom;
    }

    /** Stop pill dragging */
    function dragStop() {
      Pills.dragging = null;
    }

    /**
     * When a pill is dropped
     * @param cidDragTo  channelId that's the pill is being dragged to
     */
    function dragDrop(cidDragTo) {
      if (Pills.listener) {
        Pills.listener.dragDrop(cidDragTo, Pills.cidDragFrom);
      }
    }

    return Pills;
  });
<commit_msg>Make `getEmptyAnyChannelId` returns null<commit_after>'use strict';

angular.module('vlui')
  .service('Pills', function (ANY, consts, util, vl, cql) {
    var Pills = {
      // Functions
      isAnyChannel: isAnyChannel,
      getNextAnyChannelId: getNextAnyChannelId,
      getEmptyAnyChannelId: getEmptyAnyChannelId,
      isEnumeratedChannel: isEnumeratedChannel,
      isEnumeratedField: isEnumeratedField,

      get: get,
      // Event
      dragDrop: dragDrop,
      dragStart: dragStart,
      dragStop: dragStop,
      // Event, with handler in the listener

      /** Set a fieldDef for a channel */
      set: set,

      /** Remove a fieldDef from a channel */
      remove: remove,

      countFieldDef: {field: '*', aggregate: vl.aggregate.AggregateOp.COUNT, type: vl.type.QUANTITATIVE},

      // Data
      // TODO: split between encoding related and non-encoding related
      pills: {},
      highlighted: {},
      /** pill being dragged */
      dragging: null,
      isDraggingWildcard: null,
      /** channelId that's the pill is being dragged from */
      cidDragFrom: null,
      /** Listener  */
      listener: null
    };

    // Add listener type that Pills just pass arguments to its listener
    // FIXME: properly implement listener pattern
    [
      'add', 'parse', 'select', 'preview', 'update', 'reset',
      'rescale', 'sort', 'toggleFilterInvalid', 'transpose',
      'addWildcardField', 'addWildcard', 'removeWildcardField', 'removeWildcard'
    ].forEach(function(listenerType) {
      Pills[listenerType] = function() {
        if (Pills.listener && Pills.listener[listenerType]) {
          return Pills.listener[listenerType].apply(null, arguments);
        }
      };
    });

    /**
     * Returns whether the given channel id is an "any" channel
     *
     * @param {any} channelId
     */
    function isAnyChannel(channelId) {
      return channelId && channelId.indexOf(ANY) === 0; // prefix by ANY
    }

    function getEmptyAnyChannelId() {
      var anyChannels = util.keys(Pills.pills).filter(function(channelId) {
        return channelId.indexOf(ANY) === 0;
      });
      for (var i=0 ; i < anyChannels.length; i++) {
        var channelId = anyChannels[i];
        if (!Pills.pills[channelId].field) {
          return channelId;
        }
      }
      return null;
    }

    function getNextAnyChannelId() {
      var i = 0;
      while (Pills.pills[ANY + i]) {
        i++;
      }

      if (!consts.maxAnyShelf || i >= consts.maxAnyShelf) {
        return null;
      }

      return ANY + i;
    }

    /**
     * Set a fieldDef of a pill of a given channelId
     * @param channelId channel id of the pill to be updated
     * @param fieldDef fieldDef to to be updated
     * @param update whether to propagate change to the channel update listener
     */
    function set(channelId, fieldDef, update) {
      Pills.pills[channelId] = fieldDef;

      if (update && Pills.listener) {
        Pills.listener.set(channelId, fieldDef);
      }
    }

    /**
     * Get a fieldDef of a pill of a given channelId
     */
    function get(channelId) {
      return Pills.pills[channelId];
    }

    function isEnumeratedChannel(channelId) {
      if (Pills.listener && Pills.listener.isEnumeratedChannel) {
        return Pills.listener.isEnumeratedChannel(channelId, Pills.pills[channelId]);
      }
      return false;
    }

    function isEnumeratedField(channelId) {
      if (Pills.listener && Pills.listener.isEnumeratedField) {
        return Pills.listener.isEnumeratedField(channelId, Pills.pills[channelId]);
      }
      return false;
    }

    function remove(channelId) {
      delete Pills.pills[channelId];
      if (Pills.listener) {
        Pills.listener.remove(channelId);
      }
    }

    /**
     * @param {any} pill pill being dragged
     * @param {any} cidDragFrom channel id that the pill is dragged from
     */
    function dragStart(pill, cidDragFrom) {
      Pills.dragging = pill;
      Pills.isDraggingWildcard = cql.enumSpec.isEnumSpec(pill.field);
      Pills.cidDragFrom = cidDragFrom;
    }

    /** Stop pill dragging */
    function dragStop() {
      Pills.dragging = null;
    }

    /**
     * When a pill is dropped
     * @param cidDragTo  channelId that's the pill is being dragged to
     */
    function dragDrop(cidDragTo) {
      if (Pills.listener) {
        Pills.listener.dragDrop(cidDragTo, Pills.cidDragFrom);
      }
    }

    return Pills;
  });
<|endoftext|>


<commit_before>'use strict';

const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');

const myHook = options => { // always wrap in a function so you can pass options and for consistency.
  return hook => {

    console.log('Launching phantomjs run...');
    const spawn = require('child_process').spawn;

    const ls = spawn('phantomjs', ['/Users/thomas/Documents/Startups/Automation/tagzmahal/git/web_clicker.js']);
    //const ls = spawn('phantomjs /Users/thomas/Documents/Startups/Automation/tagzmahal/git/web_clicker.js');

    //const ls = spawn('ls', ['-lh', '/usr']);

    ls.stdout.on('data', (data) => {
      console.log(`${data}`);
    });

    ls.stderr.on('data', (data) => {
      console.log(`stderr: ${data}`);
    });

    ls.on('close', (code) => {
      console.log(`child process exited with code ${code}`);
    });

    return Promise.resolve(hook); // A good convention is to always return a promise.
  };
};

exports.before = {
  all: [],
  find: [],
  get: [],
  create: [myHook()],
  update: [],
  patch: [],
  remove: []
};

exports.after = {
  all: [],
  find: [],
  get: [],
  create: [],
  update: [],
  patch: [],
  remove: []
};
<commit_msg>test_run01<commit_after>'use strict';

const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');

const myHook = options => { // always wrap in a function so you can pass options and for consistency.
  return hook => {

    console.log('Launching phantomjs run...');
    const spawn = require('child_process').spawn;

    const ls = spawn('phantomjs', ['web_clicker.js']);
    //const ls = spawn('phantomjs', ['/Users/thomas/Documents/Startups/Automation/tagzmahal/git/web_clicker.js']);

    ls.stdout.on('data', (data) => {
      console.log(`${data}`);
    });

    ls.stderr.on('data', (data) => {
      console.log(`stderr: ${data}`);
    });

    ls.on('close', (code) => {
      console.log(`child process exited with code ${code}`);
    });

    return Promise.resolve(hook); // A good convention is to always return a promise.
  };
};

exports.before = {
  all: [],
  find: [],
  get: [],
  create: [myHook()],
  update: [],
  patch: [],
  remove: []
};

exports.after = {
  all: [],
  find: [],
  get: [],
  create: [],
  update: [],
  patch: [],
  remove: []
};
<|endoftext|>


<commit_before>import { Component } from 'substance'

// TODO: Replace fake tutorials with real documents
const tutorials = [
  {title: 'Five-Minute introduction', link: '/tutorials.html?archive=1'},
  {title: 'Introduction to Stencila Articles', link: '/tutorials.html?archive=2'},
  {title: 'Introduction to Stencila Sheets', link: '/tutorials.html?archive=3'},
  {title: 'Polyglot Programming', link: '/tutorials.html?archive=4'},
  {title: 'Big Data', link: '/tutorials.html?archive=5'}
]

/*
  TODO: This code is really in a bad shape. We should implement this properly soon.
*/

export default class FunctionHelpComponent extends Component {
  render($$) {
    const functionManager = this.context.host.functionManager
    const func = functionManager.getFunction(this.props.functionName)

    let el = $$('div').addClass('sc-function-help')

    if (func) {
      el.append(
        $$('div').addClass('se-name').append(func.name),
        $$('div').addClass('se-description').append(func.description)
      )

      // TODO: Currently only using the first method, allow for
      // multiple methods (ie. overloads with different parameter types)
      let method = Object.values(func.methods)[0]
      let params = method.params

      let syntaxEl = $$('div').addClass('se-syntax').append(
        $$('span').addClass('se-name').append(func.name),
        '('
      )
      if (params) {
        params.forEach((param, i) => {
          let paramEl = $$('span').addClass('se-signature-param').append(param.name)

          syntaxEl.append(paramEl);
          if (i < params.length - 1) {
            syntaxEl.append(',')
          }
        })
      }
      syntaxEl.append(')')

      el.append(
        $$('div').addClass('se-section-title').append('Signature'),
        syntaxEl
      )

      if (params) {
        params.forEach(param => {
          el.append(
            $$('div').addClass('se-param').append(
              $$('span').addClass('se-name').append(param.name),
              ' - ',
              $$('span').addClass('se-description').append(param.description)
            )
          )
        })
      }

      // Examples

      if(method.examples && method.examples.length > 0) {
        el.append(
          $$('div').addClass('se-section-title').append('Examples')
        )

        method.examples.forEach(example => {
          el.append(
            // $$('div').addClass('se-example-caption').append(example.caption),
            $$('pre').addClass('se-example-usage').append(example.usage)
          )
        })
      }

      el.append(
        $$('div').addClass('se-function-index').append(
          $$('a').attr({href: '#'}).append('← Function Index')
            .on('click', this._openFunctionHelp.bind(this, 'index'))
        )
      )

    } else {

      /*
      TODO: Write tutorials. Until they are done, not including these dead links

      const tutorialListEl = tutorials.map(t => $$('li').addClass('se-item').append(
        $$('a').attr('href',t.link).append(t.title)
      ))
      let tutorialsSection = $$('div').addClass('se-tutorials').append(
        $$('div').addClass('se-title').append('Getting started with Stencila'),
        $$('div').addClass('se-subtitle').append('Please read the following tutorials'),
        $$('div').addClass('se-tutorials-list').append(tutorialListEl)
      )
      */

      const functionList = functionManager.getFunctionNames()
      const functionListEl = functionList.map(func => $$('div').addClass('se-item').append(
        $$('a').attr({href: '#'})
          .append(func)
          .on('click', this._openFunctionHelp.bind(this, func))
      ))
      let functionsSection = $$('div').addClass('se-functions').append(
        $$('div').addClass('se-title').append('Functions'),
        $$('div').addClass('se-subtitle').append('Use these built-in functions'),
        $$('div').addClass('se-functions-list').append(functionListEl)
      )

      el.append(
        // tutorialsSection,
        functionsSection
      )
    }
    return el
  }

  _openFunctionHelp(funcName) {
    this.send('openHelp', `function/${funcName}`)
  }
}
<commit_msg>Remove lint<commit_after>import { Component } from 'substance'

// TODO: Replace fake tutorials with real documents
/*const tutorials = [
  {title: 'Five-Minute introduction', link: '/tutorials.html?archive=1'},
  {title: 'Introduction to Stencila Articles', link: '/tutorials.html?archive=2'},
  {title: 'Introduction to Stencila Sheets', link: '/tutorials.html?archive=3'},
  {title: 'Polyglot Programming', link: '/tutorials.html?archive=4'},
  {title: 'Big Data', link: '/tutorials.html?archive=5'}
]*/

/*
  TODO: This code is really in a bad shape. We should implement this properly soon.
*/

export default class FunctionHelpComponent extends Component {
  render($$) {
    const functionManager = this.context.host.functionManager
    const func = functionManager.getFunction(this.props.functionName)

    let el = $$('div').addClass('sc-function-help')

    if (func) {
      el.append(
        $$('div').addClass('se-name').append(func.name),
        $$('div').addClass('se-description').append(func.description)
      )

      // TODO: Currently only using the first method, allow for
      // multiple methods (ie. overloads with different parameter types)
      let method = Object.values(func.methods)[0]
      let params = method.params

      let syntaxEl = $$('div').addClass('se-syntax').append(
        $$('span').addClass('se-name').append(func.name),
        '('
      )
      if (params) {
        params.forEach((param, i) => {
          let paramEl = $$('span').addClass('se-signature-param').append(param.name)

          syntaxEl.append(paramEl);
          if (i < params.length - 1) {
            syntaxEl.append(',')
          }
        })
      }
      syntaxEl.append(')')

      el.append(
        $$('div').addClass('se-section-title').append('Signature'),
        syntaxEl
      )

      if (params) {
        params.forEach(param => {
          el.append(
            $$('div').addClass('se-param').append(
              $$('span').addClass('se-name').append(param.name),
              ' - ',
              $$('span').addClass('se-description').append(param.description)
            )
          )
        })
      }

      // Examples

      if(method.examples && method.examples.length > 0) {
        el.append(
          $$('div').addClass('se-section-title').append('Examples')
        )

        method.examples.forEach(example => {
          el.append(
            // $$('div').addClass('se-example-caption').append(example.caption),
            $$('pre').addClass('se-example-usage').append(example.usage)
          )
        })
      }

      el.append(
        $$('div').addClass('se-function-index').append(
          $$('a').attr({href: '#'}).append('← Function Index')
            .on('click', this._openFunctionHelp.bind(this, 'index'))
        )
      )

    } else {

      /*
      TODO: Write tutorials. Until they are done, not including these dead links

      const tutorialListEl = tutorials.map(t => $$('li').addClass('se-item').append(
        $$('a').attr('href',t.link).append(t.title)
      ))
      let tutorialsSection = $$('div').addClass('se-tutorials').append(
        $$('div').addClass('se-title').append('Getting started with Stencila'),
        $$('div').addClass('se-subtitle').append('Please read the following tutorials'),
        $$('div').addClass('se-tutorials-list').append(tutorialListEl)
      )
      */

      const functionList = functionManager.getFunctionNames()
      const functionListEl = functionList.map(func => $$('div').addClass('se-item').append(
        $$('a').attr({href: '#'})
          .append(func)
          .on('click', this._openFunctionHelp.bind(this, func))
      ))
      let functionsSection = $$('div').addClass('se-functions').append(
        $$('div').addClass('se-title').append('Functions'),
        $$('div').addClass('se-subtitle').append('Use these built-in functions'),
        $$('div').addClass('se-functions-list').append(functionListEl)
      )

      el.append(
        // tutorialsSection,
        functionsSection
      )
    }
    return el
  }

  _openFunctionHelp(funcName) {
    this.send('openHelp', `function/${funcName}`)
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Hippo B.V. (http://www.onehippo.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
    "use strict";

    angular.module('hippo.theme')

    /**
     * @ngdoc directive
     * @name hippo.theme.directive:selectBox
     * @restrict A
     *
     * @description
     * Converts a plain HTML select input field to a jQuery Chosen select box
     */
    .directive('hippo.theme.selectBox', [
        '$log',
        function($log) {
            return {
                restrict: 'A',
                link: function(scope, element, attrs) {
                    if (!angular.isDefined(attrs.options)) {
                        $log.warn("No 'data-options' attribute specified for hippo.theme.selectBox. Changes to the ng-options attribute value will not be reflected in the UI.");
                    }

                    scope.$watch(attrs.options, function() {
                        element.trigger('chosen:updated');
                        element.trigger('chosen:updated.chosen');
                    }, true);

                    element.chosen({
                        width: "100%",
                        no_results_text: attrs.noResultsText,
                        single_text: attrs.placeholder,
                        multiple_text: attrs.placeholder
                    });
                }
            };
        }
    ]);
}());
<commit_msg>CMS7-7828 SelectBox - update Chosen plugin when the ngModel changes<commit_after>/*
 * Copyright 2014 Hippo B.V. (http://www.onehippo.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
    "use strict";

    angular.module('hippo.theme')

    /**
     * @ngdoc directive
     * @name hippo.theme.directive:selectBox
     * @restrict A
     *
     * @description
     * Converts a plain HTML select input field to a jQuery Chosen select box
     */
    .directive('hippo.theme.selectBox', [
        '$log',
        function($log) {
            return {
                restrict: 'A',
                link: function(scope, element, attrs) {
                    if (!angular.isDefined(attrs.options)) {
                        $log.warn("No 'data-options' attribute specified for hippo.theme.selectBox. Changes to the ng-options attribute value will not be reflected in the UI.");
                    }

                    // watch options
                    scope.$watch(attrs.options, function() {
                        element.trigger('chosen:updated');
                        element.trigger('chosen:updated.chosen');
                    }, true);

                    // watch selected option
                    if (attrs.ngModel) {
                        scope.$watch(attrs.ngModel, function() {
                            element.trigger('chosen:updated');
                            element.trigger('chosen:updated.chosen');
                        }, true);
                    }

                    element.chosen({
                        width: "100%",
                        no_results_text: attrs.noResultsText,
                        single_text: attrs.placeholder,
                        multiple_text: attrs.placeholder
                    });
                }
            };
        }
    ]);
}());
<|endoftext|>


<commit_before>define([
	'compose',
], function(
	compose
){

	var jsonDateRx = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(Z|([+\-])(\d{2}):(\d{2}))$/;

	var serialize = JSON.stringify;
	var deserialize = function(json) {
		return json && JSON.parse(json, function(key, value) {
			var match;
			if (typeof value === 'string') {
				match = jsonDateRx.exec(value);
				if (match) {
					return new Date(Date.UTC(
						+match[1], +match[2] - 1, +match[3], +match[4], +match[5], +match[6])
					);
				}
			}
			return value;
		});
	};

	var LocalStorage = compose(function(nameSpace) {
		this._nameSpace = nameSpace;
	}, {
		get: function() {
			var key = this._nameSpace;
			var json = localStorage.getItem(key);
			return deserialize(json);
		},
		set: function(value) {
			// console.time('stringify');
			var json = serialize(value);
			// console.timeEnd('stringify');
			// console.time('store');
			localStorage.setItem(this._nameSpace, json);
			// console.timeEnd('store');
		}
	});

	var IncrementalLocalStorage = compose(function(nameSpace) {
		this._nameSpace = nameSpace;
	}, {
		get: function() {
			var nameSpace = this._nameSpace;
			var nameSpaceLength = nameSpace.length;
			var ret = {};
			Object.keys(localStorage).forEach(function(lsKey) {
				if (lsKey.slice(0, nameSpaceLength) === nameSpace) {
					var itemKey = lsKey.slice(nameSpaceLength+1);
					ret[itemKey] = deserialize(localStorage[lsKey]);
				}
			});
			return ret;
		},
		set: function(value) {
			var self = this;
			var nameSpace = this._nameSpace;
			var nameSpaceLength = nameSpace.length;
			Object.keys(localStorage).forEach(function(lsKey) {
				if (lsKey.slice(0, nameSpaceLength) === nameSpace) {
					var itemKey = lsKey.slice(nameSpaceLength+2);
					if (itemKey in value) {
						self.setItem(itemKey, value[itemKey]);
					} else {
						self.removeItem(itemKey);
					}
				}
			});
		},
		getItem: function(itemKey) {
			var nameSpace = this._nameSpace;
			var json = localStorage.getItem(nameSpace+'/'+itemKey);
			return deserialize(json);
		},
		setItem: function(itemKey, value) {
			// console.time('stringify');
			var json = serialize(value);
			// console.timeEnd('stringify');
			// console.time('store');
			localStorage.setItem(this._nameSpace+'/'+itemKey, json);
			// console.timeEnd('store');
		},
		removeItem: function(itemKey) {
			localStorage.removeItem(this._nameSpace+'/'+itemKey);
		},
	});

	var LocalStorageProvider = compose(function(nameSpace) {
		this._nameSpace = nameSpace;
	}, {
		item: function(itemKey) {
			return new LocalStorage(this._nameSpace + '/' + itemKey);
		},
		store: function(nameSpace) {
			return new IncrementalLocalStorage(this._nameSpace + '/' + nameSpace);
		}
	});
	return LocalStorageProvider;
});<commit_msg>LocalStorage#keys and LocalStorage#clear<commit_after>define([
	'compose',
], function(
	compose
){

	var jsonDateRx = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(Z|([+\-])(\d{2}):(\d{2}))$/;

	var serialize = JSON.stringify;
	var deserialize = function(json) {
		return json && JSON.parse(json, function(key, value) {
			var match;
			if (typeof value === 'string') {
				match = jsonDateRx.exec(value);
				if (match) {
					return new Date(Date.UTC(
						+match[1], +match[2] - 1, +match[3], +match[4], +match[5], +match[6])
					);
				}
			}
			return value;
		});
	};

	var LocalStorage = compose(function(nameSpace) {
		this._nameSpace = nameSpace;
	}, {
		get: function() {
			var key = this._nameSpace;
			var json = localStorage.getItem(key);
			return deserialize(json);
		},
		set: function(value) {
			// console.time('stringify');
			var json = serialize(value);
			// console.timeEnd('stringify');
			// console.time('store');
			localStorage.setItem(this._nameSpace, json);
			// console.timeEnd('store');
		}
	});

	var IncrementalLocalStorage = compose(function(nameSpace) {
		this._nameSpace = nameSpace;
	}, {
		get: function() {
			var self = this;
			var ret = {};
			this.keys().forEach(function(itemKey) {
				ret[itemKey] = self.getItem(itemKey);
			});
			return ret;
		},
		set: function(value) {
			var self = this;
			this.keys().forEach(function(itemKey) {
				if (itemKey in value) {
					self.setItem(itemKey, value[itemKey]);
				} else {
					self.removeItem(itemKey);
				}
			});
		},
		getItem: function(itemKey) {
			var nameSpace = this._nameSpace;
			var json = localStorage.getItem(nameSpace+'/'+itemKey);
			return deserialize(json);
		},
		setItem: function(itemKey, value) {
			var json = serialize(value);
			localStorage.setItem(this._nameSpace+'/'+itemKey, json);
		},
		removeItem: function(itemKey) {
			localStorage.removeItem(this._nameSpace+'/'+itemKey);
		},
		clear: function() {
			var self = this;
			this.keys().forEach(function(key) {
				self.removeItem(key);
			});
		},
		keys: function() {
			var nameSpace = this._nameSpace;
			var nameSpaceLength = nameSpace.length;
			return Object.keys(localStorage).reduce(function(itemKeys, lsKey) {
				if (lsKey.slice(0, nameSpaceLength) === nameSpace) {
					var itemKey = lsKey.slice(nameSpaceLength+1);
					itemKeys.push(itemKey);
				}
				return itemKeys;
			}, []);
		},
	});

	var LocalStorageProvider = compose(function(nameSpace) {
		this._nameSpace = nameSpace;
	}, {
		item: function(itemKey) {
			return new LocalStorage(this._nameSpace + '/' + itemKey);
		},
		store: function(nameSpace) {
			return new IncrementalLocalStorage(this._nameSpace + '/' + nameSpace);
		}
	});
	return LocalStorageProvider;
});<|endoftext|>


<commit_before>import { push } from 'react-router-redux';
import {
  mapValues,
  merge,
  omitBy,
  isNil,
  forEach,
  zipObject,
  pickBy,
  size,
} from 'lodash';

import {
  configurationSelector,
  currentSectorSelector,
  entitySelector,
  sidebarEditSelector,
  holdKeySelector,
  hoverKeySelector,
} from 'store/selectors/base.selectors';
import {
  getCurrentTopLevelEntities,
  getCurrentEntityType,
  getCurrentEntityId,
  getCurrentEntity,
} from 'store/selectors/entity.selectors';
import {
  generateEntity as generateEntityUtil,
  deleteEntity as deleteEntityUtil,
  getTopLevelEntity,
} from 'utils/entity';
import { coordinatesFromKey } from 'utils/common';
import { DEACTIVATE_SIDEBAR_EDIT } from 'store/actions/sidebar-edit.actions';
import { saveEntities, deleteEntities } from 'store/utils';

export const UPDATE_ENTITIES = 'UPDATE_ENTITIES';
export const DELETE_ENTITIES = 'DELETE_ENTITIES';
export const SAVE_SECTOR = 'SAVE_SECTOR';

export const generateEntity = (entity, parameters) => (dispatch, getState) => {
  const state = getState();
  const entities = generateEntityUtil({
    entity,
    currentSector: currentSectorSelector(state),
    configuration: configurationSelector(state),
    parameters,
  });
  dispatch({
    type: UPDATE_ENTITIES,
    entities,
  });

  const existingSector = state.entity.sector[state.sector.currentSector];
  const newSectorKeys = Object.keys(entities.sector || {});
  if (
    (!state.sector.currentSector || !existingSector) &&
    newSectorKeys.length
  ) {
    dispatch(push(`/sector/${newSectorKeys[0]}`));
  }
};

export const moveTopLevelEntity = () => (dispatch, getState) => {
  const state = getState();
  const topLevelEntities = getCurrentTopLevelEntities(state);
  const holdEntity = getTopLevelEntity(
    topLevelEntities,
    holdKeySelector(state),
  );
  const hoverKey = hoverKeySelector(state);
  const hoverEntity = getTopLevelEntity(topLevelEntities, hoverKey);
  const holdUpdate = { ...holdEntity.entity, ...coordinatesFromKey(hoverKey) };
  let entities = {
    [holdEntity.entityType]: { [holdEntity.entityId]: holdUpdate },
  };
  if (hoverEntity.entity) {
    const hoverUpdate = {
      ...hoverEntity.entity,
      x: holdEntity.entity.x,
      y: holdEntity.entity.y,
    };
    entities = {
      ...entities,
      [hoverEntity.entityType]: {
        ...(entities[hoverEntity.entityType] || {}),
        [hoverEntity.entityId]: hoverUpdate,
      },
    };
  }
  console.log(entities);
  dispatch({ type: UPDATE_ENTITIES, entities });
  return saveEntities({ state, entities }).then(dispatch);
};

export const deleteEntity = () => (dispatch, getState) => {
  const state = getState();
  const entity = getCurrentEntity(state);
  const currentSector = currentSectorSelector(state);
  if (!entity.parent) {
    dispatch(push('/'));
  } else if (entity.parent === currentSector) {
    dispatch(push(`/sector/${entity.parent}`));
  } else {
    dispatch(
      push(`/sector/${currentSector}/${entity.parentEntity}/${entity.parent}`),
    );
  }
  const deleted = deleteEntityUtil({
    entityType: getCurrentEntityType(state),
    entityId: getCurrentEntityId(state),
    entities: entitySelector(state),
  });
  dispatch({
    type: DELETE_ENTITIES,
    entities: deleted,
  });
  return deleteEntities({ state, deleted }).then(dispatch);
};

export const saveSector = () => (dispatch, getState) => {
  const state = getState();
  dispatch({ type: SAVE_SECTOR });
  return saveEntities({ state }).then(dispatch);
};

export const saveEntityEdit = () => (dispatch, getState) => {
  const state = getState();
  const currentEntityType = getCurrentEntityType(state);
  const currentEntityId = getCurrentEntityId(state);
  const { entity, children } = sidebarEditSelector(state);

  let createdEntities = {};
  const deletedEntities = {};
  let updatedEntities = mapValues(children, (entities, thisEntityType) =>
    omitBy(
      mapValues(
        entities,
        ({ isCreated, isDeleted, isUpdated, ...thisEntity }, thisEntityId) => {
          if (isCreated) {
            createdEntities = merge(
              createdEntities,
              generateEntityUtil({
                entityType: thisEntityType,
                currentSector: currentSectorSelector(state),
                configuration: configurationSelector(state),
                parameters: {
                  ...thisEntity,
                  parentEntity: currentEntityType,
                  parent: currentEntityId,
                },
              }),
            );
          } else if (isDeleted) {
            forEach(
              deleteEntityUtil({
                entityType: thisEntityType,
                entityId: thisEntityId,
                entities: entitySelector(state),
              }),
              (entityIdArray, deletedType) => {
                deletedEntities[deletedType] = [
                  ...(deletedEntities[deletedType] || []),
                  ...entityIdArray,
                ];
              },
            );
          }
          return isDeleted || isCreated || !isUpdated ? undefined : thisEntity;
        },
      ),
      isNil,
    ),
  );

  updatedEntities = merge(updatedEntities, createdEntities);
  if (entity.isUpdated) {
    updatedEntities = merge(updatedEntities, {
      [currentEntityType]: { [currentEntityId]: entity },
    });
  }

  const onlyUpdated = { ...updatedEntities };
  updatedEntities = merge(
    updatedEntities,
    mapValues(deletedEntities, deletedIds =>
      zipObject(deletedIds, deletedIds.map(() => null)),
    ),
  );

  const filteredUpdatedEntities = pickBy(updatedEntities, size);
  if (size(filteredUpdatedEntities)) {
    dispatch({
      type: UPDATE_ENTITIES,
      entities: filteredUpdatedEntities,
    });
    return saveEntities({
      state,
      entities: filteredUpdatedEntities,
      updated: onlyUpdated,
      deleted: deletedEntities,
    }).then(dispatch);
  }
  return dispatch({ type: DEACTIVATE_SIDEBAR_EDIT });
};
<commit_msg>Save sector when generating a non-sector entity<commit_after>import { push } from 'react-router-redux';
import {
  mapValues,
  merge,
  omitBy,
  isNil,
  forEach,
  zipObject,
  pickBy,
  size,
} from 'lodash';

import { DEACTIVATE_SIDEBAR_EDIT } from 'store/actions/sidebar-edit.actions';
import {
  configurationSelector,
  currentSectorSelector,
  entitySelector,
  sidebarEditSelector,
  holdKeySelector,
  hoverKeySelector,
} from 'store/selectors/base.selectors';
import {
  getCurrentTopLevelEntities,
  getCurrentEntityType,
  getCurrentEntityId,
  getCurrentEntity,
} from 'store/selectors/entity.selectors';

import {
  generateEntity as generateEntityUtil,
  deleteEntity as deleteEntityUtil,
  getTopLevelEntity,
} from 'utils/entity';
import { coordinatesFromKey } from 'utils/common';
import { saveEntities, deleteEntities } from 'store/utils';
import Entities from 'constants/entities';

export const UPDATE_ENTITIES = 'UPDATE_ENTITIES';
export const DELETE_ENTITIES = 'DELETE_ENTITIES';
export const SAVE_SECTOR = 'SAVE_SECTOR';

export const generateEntity = (entity, parameters) => (dispatch, getState) => {
  const state = getState();
  const entities = generateEntityUtil({
    entity,
    currentSector: currentSectorSelector(state),
    configuration: configurationSelector(state),
    parameters,
  });
  dispatch({
    type: UPDATE_ENTITIES,
    entities,
  });

  const existingSector = state.entity.sector[state.sector.currentSector];
  const newSectorKeys = Object.keys(entities.sector || {});
  if (
    (!state.sector.currentSector || !existingSector) &&
    newSectorKeys.length
  ) {
    dispatch(push(`/sector/${newSectorKeys[0]}`));
  }

  if (entity.entityType !== Entities.sector.key) {
    return saveEntities({ state, entities }).then(dispatch);
  }
  return Promise.resolve();
};

export const moveTopLevelEntity = () => (dispatch, getState) => {
  const state = getState();
  const topLevelEntities = getCurrentTopLevelEntities(state);
  const holdEntity = getTopLevelEntity(
    topLevelEntities,
    holdKeySelector(state),
  );
  const hoverKey = hoverKeySelector(state);
  const hoverEntity = getTopLevelEntity(topLevelEntities, hoverKey);
  const holdUpdate = { ...holdEntity.entity, ...coordinatesFromKey(hoverKey) };
  let entities = {
    [holdEntity.entityType]: { [holdEntity.entityId]: holdUpdate },
  };
  if (hoverEntity.entity) {
    const hoverUpdate = {
      ...hoverEntity.entity,
      x: holdEntity.entity.x,
      y: holdEntity.entity.y,
    };
    entities = {
      ...entities,
      [hoverEntity.entityType]: {
        ...(entities[hoverEntity.entityType] || {}),
        [hoverEntity.entityId]: hoverUpdate,
      },
    };
  }
  dispatch({ type: UPDATE_ENTITIES, entities });
  return saveEntities({ state, entities }).then(dispatch);
};

export const deleteEntity = () => (dispatch, getState) => {
  const state = getState();
  const entity = getCurrentEntity(state);
  const currentSector = currentSectorSelector(state);
  if (!entity.parent) {
    dispatch(push('/'));
  } else if (entity.parent === currentSector) {
    dispatch(push(`/sector/${entity.parent}`));
  } else {
    dispatch(
      push(`/sector/${currentSector}/${entity.parentEntity}/${entity.parent}`),
    );
  }
  const deleted = deleteEntityUtil({
    entityType: getCurrentEntityType(state),
    entityId: getCurrentEntityId(state),
    entities: entitySelector(state),
  });
  dispatch({
    type: DELETE_ENTITIES,
    entities: deleted,
  });
  return deleteEntities({ state, deleted }).then(dispatch);
};

export const saveSector = () => (dispatch, getState) => {
  const state = getState();
  dispatch({ type: SAVE_SECTOR });
  return saveEntities({ state }).then(dispatch);
};

export const saveEntityEdit = () => (dispatch, getState) => {
  const state = getState();
  const currentEntityType = getCurrentEntityType(state);
  const currentEntityId = getCurrentEntityId(state);
  const { entity, children } = sidebarEditSelector(state);

  let createdEntities = {};
  const deletedEntities = {};
  let updatedEntities = mapValues(children, (entities, thisEntityType) =>
    omitBy(
      mapValues(
        entities,
        ({ isCreated, isDeleted, isUpdated, ...thisEntity }, thisEntityId) => {
          if (isCreated) {
            createdEntities = merge(
              createdEntities,
              generateEntityUtil({
                entityType: thisEntityType,
                currentSector: currentSectorSelector(state),
                configuration: configurationSelector(state),
                parameters: {
                  ...thisEntity,
                  parentEntity: currentEntityType,
                  parent: currentEntityId,
                },
              }),
            );
          } else if (isDeleted) {
            forEach(
              deleteEntityUtil({
                entityType: thisEntityType,
                entityId: thisEntityId,
                entities: entitySelector(state),
              }),
              (entityIdArray, deletedType) => {
                deletedEntities[deletedType] = [
                  ...(deletedEntities[deletedType] || []),
                  ...entityIdArray,
                ];
              },
            );
          }
          return isDeleted || isCreated || !isUpdated ? undefined : thisEntity;
        },
      ),
      isNil,
    ),
  );

  updatedEntities = merge(updatedEntities, createdEntities);
  if (entity.isUpdated) {
    updatedEntities = merge(updatedEntities, {
      [currentEntityType]: { [currentEntityId]: entity },
    });
  }

  const onlyUpdated = { ...updatedEntities };
  updatedEntities = merge(
    updatedEntities,
    mapValues(deletedEntities, deletedIds =>
      zipObject(deletedIds, deletedIds.map(() => null)),
    ),
  );

  const filteredUpdatedEntities = pickBy(updatedEntities, size);
  if (size(filteredUpdatedEntities)) {
    dispatch({
      type: UPDATE_ENTITIES,
      entities: filteredUpdatedEntities,
    });
    return saveEntities({
      state,
      entities: filteredUpdatedEntities,
      updated: onlyUpdated,
      deleted: deletedEntities,
    }).then(dispatch);
  }
  return dispatch({ type: DEACTIVATE_SIDEBAR_EDIT });
};
<|endoftext|>


<commit_before>import {expect} from 'chai'

describe('ES6 object literals', () => {

    let prototype = {
        'foo': function(){
            return 'bar'
        }
    }

    it('should allow prototype to be defined', () => {
        let object = {
            __proto__: prototype
        };

        expect(object.foo()).to.be.equal('bar')
    })

    it('should allow the use of the super keyword', () => {
        let object = {
            __proto__: prototype,
            superify(){
                return super.foo()
            }
        };

        expect(object.superify()).to.be.equal('bar')
    })

    it('should infer property name from nested method name', () => {
        let object = {
            foo() {
                return 'bar'
            }
        };

        expect(object.foo()).to.be.equal('bar')
    })

    it('should infer property name from method name', () => {
        let object = {
            foo
        };
        function foo() {
            return 'bar'
        }

        expect(object.foo()).to.be.equal('bar')
    })

    it('should allow properties name to be dinamically generated', () => {
        let object = {
            [generateName('Foo')]:42
        };
        function generateName(name) {
            return `property${name}`
        }

        expect(object).to.have.property('propertyFoo');
    })

})<commit_msg>fixed typo<commit_after>import {expect} from 'chai'

describe('ES6 object literals', () => {

    let prototype = {
        'foo': function(){
            return 'bar'
        }
    }

    it('should allow prototype to be defined', () => {
        let object = {
            __proto__: prototype
        };

        expect(object.foo()).to.be.equal('bar')
    })

    it('should allow the use of the super keyword', () => {
        let object = {
            __proto__: prototype,
            superify(){
                return super.foo()
            }
        };

        expect(object.superify()).to.be.equal('bar')
    })

    it('should infer property name from nested method name', () => {
        let object = {
            foo() {
                return 'bar'
            }
        };

        expect(object.foo()).to.be.equal('bar')
    })

    it('should infer property name from method name', () => {
        let object = {
            foo
        };
        function foo() {
            return 'bar'
        }

        expect(object.foo()).to.be.equal('bar')
    })

    it('should allow properties name to be dinamically generated', () => {
        let object = {
            [generateName('Foo')]: 42
        };
        function generateName(name) {
            return `property${name}`
        }

        expect(object).to.have.property('propertyFoo');
    })

})<|endoftext|>


<commit_before>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2022 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var BaseTween = require('../tween/BaseTween');
var Defaults = require('../tween/Defaults');
var GetAdvancedValue = require('../../utils/object/GetAdvancedValue');
var GetBoolean = require('./GetBoolean');
var GetEaseFunction = require('./GetEaseFunction');
var GetNewValue = require('./GetNewValue');
var GetProps = require('./GetProps');
var GetTargets = require('./GetTargets');
var GetValue = require('../../utils/object/GetValue');
var GetValueOp = require('./GetValueOp');
var Tween = require('../tween/Tween');
var TweenData = require('../tween/TweenData');

/**
 * Creates a new Tween.
 *
 * @function Phaser.Tweens.Builders.TweenBuilder
 * @since 3.0.0
 *
 * @param {(Phaser.Tweens.TweenManager|Phaser.Tweens.Timeline)} parent - The owner of the new Tween.
 * @param {Phaser.Types.Tweens.TweenBuilderConfig|object} config - Configuration for the new Tween.
 * @param {Phaser.Types.Tweens.TweenConfigDefaults} defaults - Tween configuration defaults.
 *
 * @return {Phaser.Tweens.Tween} The new tween.
 */
var TweenBuilder = function (parent, config, defaults)
{
    if (defaults === undefined)
    {
        defaults = Defaults;
    }

    //  Create arrays of the Targets and the Properties
    var targets = (defaults.targets) ? defaults.targets : GetTargets(config);

    var props = GetProps(config);

    //  Default Tween values
    var delay = GetNewValue(config, 'delay', defaults.delay);
    var duration = GetNewValue(config, 'duration', defaults.duration);
    var easeParams = GetValue(config, 'easeParams', defaults.easeParams);
    var ease = GetEaseFunction(GetValue(config, 'ease', defaults.ease), easeParams);
    var hold = GetNewValue(config, 'hold', defaults.hold);
    var repeat = GetNewValue(config, 'repeat', defaults.repeat);
    var repeatDelay = GetNewValue(config, 'repeatDelay', defaults.repeatDelay);
    var yoyo = GetBoolean(config, 'yoyo', defaults.yoyo);
    var flipX = GetBoolean(config, 'flipX', defaults.flipX);
    var flipY = GetBoolean(config, 'flipY', defaults.flipY);

    var data = [];

    var addTarget = function (target, t, key, value)
    {
        var ops = GetValueOp(key, value);

        var tweenData = TweenData(
            target,
            t,
            key,
            ops.getEnd,
            ops.getStart,
            ops.getActive,
            GetEaseFunction(GetValue(value, 'ease', ease), GetValue(value, 'easeParams', easeParams)),
            GetNewValue(value, 'delay', delay),
            GetNewValue(value, 'duration', duration),
            GetBoolean(value, 'yoyo', yoyo),
            GetNewValue(value, 'hold', hold),
            GetNewValue(value, 'repeat', repeat),
            GetNewValue(value, 'repeatDelay', repeatDelay),
            GetBoolean(value, 'flipX', flipX),
            GetBoolean(value, 'flipY', flipY)
        );

        data.push(tweenData);
    };

    //  Loop through every property defined in the Tween, i.e.: props { x, y, alpha }
    for (var p = 0; p < props.length; p++)
    {
        var key = props[p].key;
        var value = props[p].value;

        //  Create 1 TweenData per target, per property
        for (var t = 0; t < targets.length; t++)
        {
            //  Special-case for scale short-cut:
            if (key === 'scale' && !targets[t].hasOwnProperty('scale'))
            {
                addTarget(targets[t], t, 'scaleX', value);
                addTarget(targets[t], t, 'scaleY', value);
            }
            else
            {
                addTarget(targets[t], t, key, value);
            }
        }
    }

    var tween = new Tween(parent, data, targets);

    tween.offset = GetAdvancedValue(config, 'offset', null);
    tween.completeDelay = GetAdvancedValue(config, 'completeDelay', 0);
    tween.loop = Math.round(GetAdvancedValue(config, 'loop', 0));
    tween.loopDelay = Math.round(GetAdvancedValue(config, 'loopDelay', 0));
    tween.paused = GetBoolean(config, 'paused', false);
    tween.useFrames = GetBoolean(config, 'useFrames', false);
    tween.persist = GetBoolean(config, 'persist', false);

    //  Set the Callbacks
    var scope = GetValue(config, 'callbackScope', tween);
    var callbacks = BaseTween.TYPES;

    for (var i = 0; i < callbacks.length; i++)
    {
        var type = callbacks[i];

        var callback = GetValue(config, type, false);

        if (callback)
        {
            var callbackScope = GetValue(config, type + 'Scope', scope);
            var callbackParams = GetValue(config, type + 'Params', []);

            tween.setCallback(type, callback, callbackParams, callbackScope);
        }
    }

    return tween;
};

module.exports = TweenBuilder;
<commit_msg>Now supports tween interpolation<commit_after>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2022 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var BaseTween = require('../tween/BaseTween');
var Defaults = require('../tween/Defaults');
var GetAdvancedValue = require('../../utils/object/GetAdvancedValue');
var GetBoolean = require('./GetBoolean');
var GetEaseFunction = require('./GetEaseFunction');
var GetInterpolationFunction = require('./GetInterpolationFunction');
var GetNewValue = require('./GetNewValue');
var GetProps = require('./GetProps');
var GetTargets = require('./GetTargets');
var GetValue = require('../../utils/object/GetValue');
var GetValueOp = require('./GetValueOp');
var Tween = require('../tween/Tween');
var TweenData = require('../tween/TweenData');

/**
 * Creates a new Tween.
 *
 * @function Phaser.Tweens.Builders.TweenBuilder
 * @since 3.0.0
 *
 * @param {(Phaser.Tweens.TweenManager|Phaser.Tweens.Timeline)} parent - The owner of the new Tween.
 * @param {Phaser.Types.Tweens.TweenBuilderConfig|object} config - Configuration for the new Tween.
 * @param {Phaser.Types.Tweens.TweenConfigDefaults} defaults - Tween configuration defaults.
 *
 * @return {Phaser.Tweens.Tween} The new tween.
 */
var TweenBuilder = function (parent, config, defaults)
{
    if (defaults === undefined)
    {
        defaults = Defaults;
    }

    //  Create arrays of the Targets and the Properties
    var targets = (defaults.targets) ? defaults.targets : GetTargets(config);

    var props = GetProps(config);

    //  Default Tween values
    var delay = GetNewValue(config, 'delay', defaults.delay);
    var duration = GetNewValue(config, 'duration', defaults.duration);
    var easeParams = GetValue(config, 'easeParams', defaults.easeParams);
    var ease = GetEaseFunction(GetValue(config, 'ease', defaults.ease), easeParams);
    var hold = GetNewValue(config, 'hold', defaults.hold);
    var repeat = GetNewValue(config, 'repeat', defaults.repeat);
    var repeatDelay = GetNewValue(config, 'repeatDelay', defaults.repeatDelay);
    var yoyo = GetBoolean(config, 'yoyo', defaults.yoyo);
    var flipX = GetBoolean(config, 'flipX', defaults.flipX);
    var flipY = GetBoolean(config, 'flipY', defaults.flipY);
    var interpolation = GetInterpolationFunction(GetValue(config, 'interpolation'));

    var data = [];

    var addTarget = function (target, t, key, value)
    {
        var ops = GetValueOp(key, value);

        var tweenData = TweenData(
            target,
            t,
            key,
            ops.getEnd,
            ops.getStart,
            ops.getActive,
            GetEaseFunction(GetValue(value, 'ease', ease), GetValue(value, 'easeParams', easeParams)),
            GetNewValue(value, 'delay', delay),
            GetNewValue(value, 'duration', duration),
            GetBoolean(value, 'yoyo', yoyo),
            GetNewValue(value, 'hold', hold),
            GetNewValue(value, 'repeat', repeat),
            GetNewValue(value, 'repeatDelay', repeatDelay),
            GetBoolean(value, 'flipX', flipX),
            GetBoolean(value, 'flipY', flipY),
            GetInterpolationFunction(GetValue(value, 'interpolation', interpolation))
        );

        data.push(tweenData);
    };

    //  Loop through every property defined in the Tween, i.e.: props { x, y, alpha }
    for (var p = 0; p < props.length; p++)
    {
        var key = props[p].key;
        var value = props[p].value;

        //  Create 1 TweenData per target, per property
        for (var t = 0; t < targets.length; t++)
        {
            //  Special-case for scale short-cut:
            if (key === 'scale' && !targets[t].hasOwnProperty('scale'))
            {
                addTarget(targets[t], t, 'scaleX', value);
                addTarget(targets[t], t, 'scaleY', value);
            }
            else
            {
                addTarget(targets[t], t, key, value);
            }
        }
    }

    var tween = new Tween(parent, data, targets);

    tween.offset = GetAdvancedValue(config, 'offset', null);
    tween.completeDelay = GetAdvancedValue(config, 'completeDelay', 0);
    tween.loop = Math.round(GetAdvancedValue(config, 'loop', 0));
    tween.loopDelay = Math.round(GetAdvancedValue(config, 'loopDelay', 0));
    tween.paused = GetBoolean(config, 'paused', false);
    tween.useFrames = GetBoolean(config, 'useFrames', false);
    tween.persist = GetBoolean(config, 'persist', false);

    //  Set the Callbacks
    var scope = GetValue(config, 'callbackScope', tween);
    var callbacks = BaseTween.TYPES;

    for (var i = 0; i < callbacks.length; i++)
    {
        var type = callbacks[i];

        var callback = GetValue(config, type, false);

        if (callback)
        {
            var callbackScope = GetValue(config, type + 'Scope', scope);
            var callbackParams = GetValue(config, type + 'Params', []);

            tween.setCallback(type, callback, callbackParams, callbackScope);
        }
    }

    return tween;
};

module.exports = TweenBuilder;
<|endoftext|>


<commit_before>var C = require( '../constants/constants' ),
	EventEmitter = require( 'events' ).EventEmitter,
	utils = require( 'util' );

/**
 * This class is used to track the initialisation of
 * an individual dependency (cache connector, persistance connector,
 * message connector, logger)
 *
 * @param {Object} options deepstream options
 * @param {String} name    the key of the dependency within the options
 *
 * @constructor
 */
var DependencyInitialiser = function( options, name ) {
	this.isReady = false;

	this._options = options;
	this._dependency = options[ name ];
	this._name = name;
	this._timeout = null;

	if( this._dependency.isReady ) {
		this._onReady();
	} else {
		this._timeout = setTimeout( this._onTimeout.bind( this ), this._options.dependencyInitialisationTimeout );
		this._dependency.once( 'ready', this._onReady.bind( this ) );
		this._dependency.on( 'error', this._onError.bind( this ) );

		if( this._dependency.init ) {
			this._dependency.init();
		}
	}
};

utils.inherits( DependencyInitialiser, EventEmitter );

/**
 * Returns the underlying dependency (e.g. the Logger, StorageConnector etc.)
 *
 * @public
 * @returns {Dependency}
 */
DependencyInitialiser.prototype.getDependency = function() {
	return this._dependency;
};

/**
 * Callback for succesfully initialised dependencies
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._onReady = function() {
	if( this._timeout ) {
		clearTimeout( this._timeout );
	}

	this._options.logger.log( C.LOG_LEVEL.INFO, C.EVENT.INFO, this._name + ' ready' );
	process.nextTick( this._emitReady.bind( this ) );
};

/**
 * Callback for dependencies that weren't initialised in time
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._onTimeout = function() {
	this._logError( this._name + ' wasn\'t initialised in time' );
	process.exit();
};

/**
* Handles errors emitted by the dependency at startup.
*
* Plugin errors that occur at runtime are handled by the deepstream.io main class
*
* @param {Error|String} error
*
* @private
* @returns {void}
*/
DependencyInitialiser.prototype._onError = function( error ) {
	if( this.isReady !== true ) {
		this._logError( 'Error while initialising ' + this._name + ': ' + error.toString() );
		process.exit();
	}
};

/**
 * Emits the ready event after a one tick delay
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._emitReady = function() {
	this.isReady = true;
	this.emit( 'ready' );
};

/**
 * Logs error messages
 *
 * Since the logger is a dependency in its own right, it can't be relied upon
 * here. If it is available, it will be used, otherwise the error will be logged
 * straight to the console
 *
 * @param   {String} message the error message
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._logError = function( message ) {
	if( this._options.logger && this._options.logger.isReady ) {
		this._options.logger.log( C.LOG_LEVEL.ERROR, C.EVENT.PLUGIN_ERROR, message );
	} else {
		console.error( 'Error while initialising dependency' );
		console.error( message );
	}
};

module.exports = DependencyInitialiser;<commit_msg>proper error handling when shutting down server<commit_after>var C = require( '../constants/constants' ),
	EventEmitter = require( 'events' ).EventEmitter,
	utils = require( 'util' );

/**
 * This class is used to track the initialisation of
 * an individual dependency (cache connector, persistance connector,
 * message connector, logger)
 *
 * @param {Object} options deepstream options
 * @param {String} name    the key of the dependency within the options
 *
 * @constructor
 */
var DependencyInitialiser = function( options, name ) {
	this.isReady = false;

	this._options = options;
	this._dependency = options[ name ];
	this._name = name;
	this._timeout = null;

	if( this._dependency.isReady ) {
		this._onReady();
	} else {
		this._timeout = setTimeout( this._onTimeout.bind( this ), this._options.dependencyInitialisationTimeout );
		this._dependency.once( 'ready', this._onReady.bind( this ) );
		this._dependency.on( 'error', this._onError.bind( this ) );

		if( this._dependency.init ) {
			this._dependency.init();
		}
	}
};

utils.inherits( DependencyInitialiser, EventEmitter );

/**
 * Returns the underlying dependency (e.g. the Logger, StorageConnector etc.)
 *
 * @public
 * @returns {Dependency}
 */
DependencyInitialiser.prototype.getDependency = function() {
	return this._dependency;
};

/**
 * Callback for succesfully initialised dependencies
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._onReady = function() {
	if( this._timeout ) {
		clearTimeout( this._timeout );
	}

	this._options.logger.log( C.LOG_LEVEL.INFO, C.EVENT.INFO, this._name + ' ready' );
	process.nextTick( this._emitReady.bind( this ) );
};

/**
 * Callback for dependencies that weren't initialised in time
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._onTimeout = function() {
	this._logError( this._name + ' wasn\'t initialised in time' );
	process.exit( 1 );
};

/**
* Handles errors emitted by the dependency at startup.
*
* Plugin errors that occur at runtime are handled by the deepstream.io main class
*
* @param {Error|String} error
*
* @private
* @returns {void}
*/
DependencyInitialiser.prototype._onError = function( error ) {
	if( this.isReady !== true ) {
		this._logError( 'Error while initialising ' + this._name + ': ' + error.toString() );
		process.exit( 1 );
	}
};

/**
 * Emits the ready event after a one tick delay
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._emitReady = function() {
	this.isReady = true;
	this.emit( 'ready' );
};

/**
 * Logs error messages
 *
 * Since the logger is a dependency in its own right, it can't be relied upon
 * here. If it is available, it will be used, otherwise the error will be logged
 * straight to the console
 *
 * @param   {String} message the error message
 *
 * @private
 * @returns {void}
 */
DependencyInitialiser.prototype._logError = function( message ) {
	if( this._options.logger && this._options.logger.isReady ) {
		this._options.logger.log( C.LOG_LEVEL.ERROR, C.EVENT.PLUGIN_ERROR, message );
	} else {
		console.error( 'Error while initialising dependency' );
		console.error( message );
	}
};

module.exports = DependencyInitialiser;
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @noflow
 */

import { expect } from 'chai';
import { parse } from '../../language';
import { validate, validateSDL } from '../validate';
import {
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLInterfaceType,
  GraphQLUnionType,
  GraphQLEnumType,
  GraphQLInputObjectType,
  GraphQLList,
  GraphQLNonNull,
  GraphQLInt,
  GraphQLFloat,
  GraphQLString,
  GraphQLBoolean,
  GraphQLID,
} from '../../type';
import {
  GraphQLDirective,
  GraphQLIncludeDirective,
  GraphQLSkipDirective,
} from '../../type/directives';
import { GraphQLScalarType } from '../../type/definition';

const Being = new GraphQLInterfaceType({
  name: 'Being',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
  }),
});

const Pet = new GraphQLInterfaceType({
  name: 'Pet',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
  }),
});

const Canine = new GraphQLInterfaceType({
  name: 'Canine',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
  }),
});

const DogCommand = new GraphQLEnumType({
  name: 'DogCommand',
  values: {
    SIT: { value: 0 },
    HEEL: { value: 1 },
    DOWN: { value: 2 },
  },
});

const Dog = new GraphQLObjectType({
  name: 'Dog',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    nickname: { type: GraphQLString },
    barkVolume: { type: GraphQLInt },
    barks: { type: GraphQLBoolean },
    doesKnowCommand: {
      type: GraphQLBoolean,
      args: {
        dogCommand: { type: DogCommand },
      },
    },
    isHousetrained: {
      type: GraphQLBoolean,
      args: {
        atOtherHomes: {
          type: GraphQLBoolean,
          defaultValue: true,
        },
      },
    },
    isAtLocation: {
      type: GraphQLBoolean,
      args: { x: { type: GraphQLInt }, y: { type: GraphQLInt } },
    },
  }),
  interfaces: [Being, Pet, Canine],
});

const Cat = new GraphQLObjectType({
  name: 'Cat',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    nickname: { type: GraphQLString },
    meows: { type: GraphQLBoolean },
    meowVolume: { type: GraphQLInt },
    furColor: { type: FurColor },
  }),
  interfaces: [Being, Pet],
});

const CatOrDog = new GraphQLUnionType({
  name: 'CatOrDog',
  types: [Dog, Cat],
});

const Intelligent = new GraphQLInterfaceType({
  name: 'Intelligent',
  fields: {
    iq: { type: GraphQLInt },
  },
});

const Human = new GraphQLObjectType({
  name: 'Human',
  interfaces: [Being, Intelligent],
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    pets: { type: GraphQLList(Pet) },
    relatives: { type: GraphQLList(Human) },
    iq: { type: GraphQLInt },
  }),
});

const Alien = new GraphQLObjectType({
  name: 'Alien',
  interfaces: [Being, Intelligent],
  fields: {
    iq: { type: GraphQLInt },
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    numEyes: { type: GraphQLInt },
  },
});

const DogOrHuman = new GraphQLUnionType({
  name: 'DogOrHuman',
  types: [Dog, Human],
});

const HumanOrAlien = new GraphQLUnionType({
  name: 'HumanOrAlien',
  types: [Human, Alien],
});

const FurColor = new GraphQLEnumType({
  name: 'FurColor',
  values: {
    BROWN: { value: 0 },
    BLACK: { value: 1 },
    TAN: { value: 2 },
    SPOTTED: { value: 3 },
    NO_FUR: { value: null },
    UNKNOWN: { value: undefined },
  },
});

const ComplexInput = new GraphQLInputObjectType({
  name: 'ComplexInput',
  fields: {
    requiredField: { type: GraphQLNonNull(GraphQLBoolean) },
    nonNullField: { type: GraphQLNonNull(GraphQLBoolean), defaultValue: false },
    intField: { type: GraphQLInt },
    stringField: { type: GraphQLString },
    booleanField: { type: GraphQLBoolean },
    stringListField: { type: GraphQLList(GraphQLString) },
  },
});

const ComplicatedArgs = new GraphQLObjectType({
  name: 'ComplicatedArgs',
  // TODO List
  // TODO Coercion
  // TODO NotNulls
  fields: () => ({
    intArgField: {
      type: GraphQLString,
      args: { intArg: { type: GraphQLInt } },
    },
    nonNullIntArgField: {
      type: GraphQLString,
      args: { nonNullIntArg: { type: GraphQLNonNull(GraphQLInt) } },
    },
    stringArgField: {
      type: GraphQLString,
      args: { stringArg: { type: GraphQLString } },
    },
    booleanArgField: {
      type: GraphQLString,
      args: { booleanArg: { type: GraphQLBoolean } },
    },
    enumArgField: {
      type: GraphQLString,
      args: { enumArg: { type: FurColor } },
    },
    floatArgField: {
      type: GraphQLString,
      args: { floatArg: { type: GraphQLFloat } },
    },
    idArgField: {
      type: GraphQLString,
      args: { idArg: { type: GraphQLID } },
    },
    stringListArgField: {
      type: GraphQLString,
      args: { stringListArg: { type: GraphQLList(GraphQLString) } },
    },
    stringListNonNullArgField: {
      type: GraphQLString,
      args: {
        stringListNonNullArg: {
          type: GraphQLList(GraphQLNonNull(GraphQLString)),
        },
      },
    },
    complexArgField: {
      type: GraphQLString,
      args: { complexArg: { type: ComplexInput } },
    },
    multipleReqs: {
      type: GraphQLString,
      args: {
        req1: { type: GraphQLNonNull(GraphQLInt) },
        req2: { type: GraphQLNonNull(GraphQLInt) },
      },
    },
    nonNullFieldWithDefault: {
      type: GraphQLString,
      args: {
        arg: { type: GraphQLNonNull(GraphQLInt), defaultValue: 0 },
      },
    },
    multipleOpts: {
      type: GraphQLString,
      args: {
        opt1: {
          type: GraphQLInt,
          defaultValue: 0,
        },
        opt2: {
          type: GraphQLInt,
          defaultValue: 0,
        },
      },
    },
    multipleOptAndReq: {
      type: GraphQLString,
      args: {
        req1: { type: GraphQLNonNull(GraphQLInt) },
        req2: { type: GraphQLNonNull(GraphQLInt) },
        opt1: {
          type: GraphQLInt,
          defaultValue: 0,
        },
        opt2: {
          type: GraphQLInt,
          defaultValue: 0,
        },
      },
    },
  }),
});

const InvalidScalar = new GraphQLScalarType({
  name: 'Invalid',
  serialize(value) {
    return value;
  },
  parseLiteral(node) {
    throw new Error('Invalid scalar is always invalid: ' + node.value);
  },
  parseValue(node) {
    throw new Error('Invalid scalar is always invalid: ' + node);
  },
});

const AnyScalar = new GraphQLScalarType({
  name: 'Any',
  serialize(value) {
    return value;
  },
  parseLiteral(node) {
    return node; // Allows any value
  },
  parseValue(value) {
    return value; // Allows any value
  },
});

const QueryRoot = new GraphQLObjectType({
  name: 'QueryRoot',
  fields: () => ({
    human: {
      args: { id: { type: GraphQLID } },
      type: Human,
    },
    alien: { type: Alien },
    dog: { type: Dog },
    cat: { type: Cat },
    pet: { type: Pet },
    catOrDog: { type: CatOrDog },
    dogOrHuman: { type: DogOrHuman },
    humanOrAlien: { type: HumanOrAlien },
    complicatedArgs: { type: ComplicatedArgs },
    invalidArg: {
      args: {
        arg: { type: InvalidScalar },
      },
      type: GraphQLString,
    },
    anyArg: {
      args: {
        arg: { type: AnyScalar },
      },
      type: GraphQLString,
    },
  }),
});

export const testSchema = new GraphQLSchema({
  query: QueryRoot,
  types: [Cat, Dog, Human, Alien],
  directives: [
    GraphQLIncludeDirective,
    GraphQLSkipDirective,
    new GraphQLDirective({
      name: 'onQuery',
      locations: ['QUERY'],
    }),
    new GraphQLDirective({
      name: 'onMutation',
      locations: ['MUTATION'],
    }),
    new GraphQLDirective({
      name: 'onSubscription',
      locations: ['SUBSCRIPTION'],
    }),
    new GraphQLDirective({
      name: 'onField',
      locations: ['FIELD'],
    }),
    new GraphQLDirective({
      name: 'onFragmentDefinition',
      locations: ['FRAGMENT_DEFINITION'],
    }),
    new GraphQLDirective({
      name: 'onFragmentSpread',
      locations: ['FRAGMENT_SPREAD'],
    }),
    new GraphQLDirective({
      name: 'onInlineFragment',
      locations: ['INLINE_FRAGMENT'],
    }),
    new GraphQLDirective({
      name: 'onVariableDefinition',
      locations: ['VARIABLE_DEFINITION'],
    }),
  ],
});

function expectValid(schema, rule, queryString, options = {}) {
  const errors = validate(schema, parse(queryString, options), [rule]);
  expect(errors).to.deep.equal([], 'Should validate');
}

function expectInvalid(
  schema,
  rule,
  queryString,
  expectedErrors,
  options = {},
) {
  const errors = validate(schema, parse(queryString, options), [rule]);
  expect(errors).to.have.length.of.at.least(1, 'Should not validate');
  expect(errors).to.deep.equal(expectedErrors);
  return errors;
}

export function expectPassesRule(rule, queryString, options = {}) {
  return expectValid(testSchema, rule, queryString, options);
}

export function expectFailsRule(rule, queryString, errors, options = {}) {
  return expectInvalid(testSchema, rule, queryString, errors, options);
}

export function expectPassesRuleWithSchema(schema, rule, queryString) {
  return expectValid(schema, rule, queryString);
}

export function expectFailsRuleWithSchema(schema, rule, queryString, errors) {
  return expectInvalid(schema, rule, queryString, errors);
}

export function expectSDLErrorsFromRule(rule, sdlString, schema) {
  const errors = validateSDL(parse(sdlString), schema, [rule]);
  return expect(errors);
}
<commit_msg>Validation tests: Remove unussed parser options (#1583)<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @noflow
 */

import { expect } from 'chai';
import { parse } from '../../language';
import { validate, validateSDL } from '../validate';
import {
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLInterfaceType,
  GraphQLUnionType,
  GraphQLEnumType,
  GraphQLInputObjectType,
  GraphQLList,
  GraphQLNonNull,
  GraphQLInt,
  GraphQLFloat,
  GraphQLString,
  GraphQLBoolean,
  GraphQLID,
} from '../../type';
import {
  GraphQLDirective,
  GraphQLIncludeDirective,
  GraphQLSkipDirective,
} from '../../type/directives';
import { GraphQLScalarType } from '../../type/definition';

const Being = new GraphQLInterfaceType({
  name: 'Being',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
  }),
});

const Pet = new GraphQLInterfaceType({
  name: 'Pet',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
  }),
});

const Canine = new GraphQLInterfaceType({
  name: 'Canine',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
  }),
});

const DogCommand = new GraphQLEnumType({
  name: 'DogCommand',
  values: {
    SIT: { value: 0 },
    HEEL: { value: 1 },
    DOWN: { value: 2 },
  },
});

const Dog = new GraphQLObjectType({
  name: 'Dog',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    nickname: { type: GraphQLString },
    barkVolume: { type: GraphQLInt },
    barks: { type: GraphQLBoolean },
    doesKnowCommand: {
      type: GraphQLBoolean,
      args: {
        dogCommand: { type: DogCommand },
      },
    },
    isHousetrained: {
      type: GraphQLBoolean,
      args: {
        atOtherHomes: {
          type: GraphQLBoolean,
          defaultValue: true,
        },
      },
    },
    isAtLocation: {
      type: GraphQLBoolean,
      args: { x: { type: GraphQLInt }, y: { type: GraphQLInt } },
    },
  }),
  interfaces: [Being, Pet, Canine],
});

const Cat = new GraphQLObjectType({
  name: 'Cat',
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    nickname: { type: GraphQLString },
    meows: { type: GraphQLBoolean },
    meowVolume: { type: GraphQLInt },
    furColor: { type: FurColor },
  }),
  interfaces: [Being, Pet],
});

const CatOrDog = new GraphQLUnionType({
  name: 'CatOrDog',
  types: [Dog, Cat],
});

const Intelligent = new GraphQLInterfaceType({
  name: 'Intelligent',
  fields: {
    iq: { type: GraphQLInt },
  },
});

const Human = new GraphQLObjectType({
  name: 'Human',
  interfaces: [Being, Intelligent],
  fields: () => ({
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    pets: { type: GraphQLList(Pet) },
    relatives: { type: GraphQLList(Human) },
    iq: { type: GraphQLInt },
  }),
});

const Alien = new GraphQLObjectType({
  name: 'Alien',
  interfaces: [Being, Intelligent],
  fields: {
    iq: { type: GraphQLInt },
    name: {
      type: GraphQLString,
      args: { surname: { type: GraphQLBoolean } },
    },
    numEyes: { type: GraphQLInt },
  },
});

const DogOrHuman = new GraphQLUnionType({
  name: 'DogOrHuman',
  types: [Dog, Human],
});

const HumanOrAlien = new GraphQLUnionType({
  name: 'HumanOrAlien',
  types: [Human, Alien],
});

const FurColor = new GraphQLEnumType({
  name: 'FurColor',
  values: {
    BROWN: { value: 0 },
    BLACK: { value: 1 },
    TAN: { value: 2 },
    SPOTTED: { value: 3 },
    NO_FUR: { value: null },
    UNKNOWN: { value: undefined },
  },
});

const ComplexInput = new GraphQLInputObjectType({
  name: 'ComplexInput',
  fields: {
    requiredField: { type: GraphQLNonNull(GraphQLBoolean) },
    nonNullField: { type: GraphQLNonNull(GraphQLBoolean), defaultValue: false },
    intField: { type: GraphQLInt },
    stringField: { type: GraphQLString },
    booleanField: { type: GraphQLBoolean },
    stringListField: { type: GraphQLList(GraphQLString) },
  },
});

const ComplicatedArgs = new GraphQLObjectType({
  name: 'ComplicatedArgs',
  // TODO List
  // TODO Coercion
  // TODO NotNulls
  fields: () => ({
    intArgField: {
      type: GraphQLString,
      args: { intArg: { type: GraphQLInt } },
    },
    nonNullIntArgField: {
      type: GraphQLString,
      args: { nonNullIntArg: { type: GraphQLNonNull(GraphQLInt) } },
    },
    stringArgField: {
      type: GraphQLString,
      args: { stringArg: { type: GraphQLString } },
    },
    booleanArgField: {
      type: GraphQLString,
      args: { booleanArg: { type: GraphQLBoolean } },
    },
    enumArgField: {
      type: GraphQLString,
      args: { enumArg: { type: FurColor } },
    },
    floatArgField: {
      type: GraphQLString,
      args: { floatArg: { type: GraphQLFloat } },
    },
    idArgField: {
      type: GraphQLString,
      args: { idArg: { type: GraphQLID } },
    },
    stringListArgField: {
      type: GraphQLString,
      args: { stringListArg: { type: GraphQLList(GraphQLString) } },
    },
    stringListNonNullArgField: {
      type: GraphQLString,
      args: {
        stringListNonNullArg: {
          type: GraphQLList(GraphQLNonNull(GraphQLString)),
        },
      },
    },
    complexArgField: {
      type: GraphQLString,
      args: { complexArg: { type: ComplexInput } },
    },
    multipleReqs: {
      type: GraphQLString,
      args: {
        req1: { type: GraphQLNonNull(GraphQLInt) },
        req2: { type: GraphQLNonNull(GraphQLInt) },
      },
    },
    nonNullFieldWithDefault: {
      type: GraphQLString,
      args: {
        arg: { type: GraphQLNonNull(GraphQLInt), defaultValue: 0 },
      },
    },
    multipleOpts: {
      type: GraphQLString,
      args: {
        opt1: {
          type: GraphQLInt,
          defaultValue: 0,
        },
        opt2: {
          type: GraphQLInt,
          defaultValue: 0,
        },
      },
    },
    multipleOptAndReq: {
      type: GraphQLString,
      args: {
        req1: { type: GraphQLNonNull(GraphQLInt) },
        req2: { type: GraphQLNonNull(GraphQLInt) },
        opt1: {
          type: GraphQLInt,
          defaultValue: 0,
        },
        opt2: {
          type: GraphQLInt,
          defaultValue: 0,
        },
      },
    },
  }),
});

const InvalidScalar = new GraphQLScalarType({
  name: 'Invalid',
  serialize(value) {
    return value;
  },
  parseLiteral(node) {
    throw new Error('Invalid scalar is always invalid: ' + node.value);
  },
  parseValue(node) {
    throw new Error('Invalid scalar is always invalid: ' + node);
  },
});

const AnyScalar = new GraphQLScalarType({
  name: 'Any',
  serialize(value) {
    return value;
  },
  parseLiteral(node) {
    return node; // Allows any value
  },
  parseValue(value) {
    return value; // Allows any value
  },
});

const QueryRoot = new GraphQLObjectType({
  name: 'QueryRoot',
  fields: () => ({
    human: {
      args: { id: { type: GraphQLID } },
      type: Human,
    },
    alien: { type: Alien },
    dog: { type: Dog },
    cat: { type: Cat },
    pet: { type: Pet },
    catOrDog: { type: CatOrDog },
    dogOrHuman: { type: DogOrHuman },
    humanOrAlien: { type: HumanOrAlien },
    complicatedArgs: { type: ComplicatedArgs },
    invalidArg: {
      args: {
        arg: { type: InvalidScalar },
      },
      type: GraphQLString,
    },
    anyArg: {
      args: {
        arg: { type: AnyScalar },
      },
      type: GraphQLString,
    },
  }),
});

export const testSchema = new GraphQLSchema({
  query: QueryRoot,
  types: [Cat, Dog, Human, Alien],
  directives: [
    GraphQLIncludeDirective,
    GraphQLSkipDirective,
    new GraphQLDirective({
      name: 'onQuery',
      locations: ['QUERY'],
    }),
    new GraphQLDirective({
      name: 'onMutation',
      locations: ['MUTATION'],
    }),
    new GraphQLDirective({
      name: 'onSubscription',
      locations: ['SUBSCRIPTION'],
    }),
    new GraphQLDirective({
      name: 'onField',
      locations: ['FIELD'],
    }),
    new GraphQLDirective({
      name: 'onFragmentDefinition',
      locations: ['FRAGMENT_DEFINITION'],
    }),
    new GraphQLDirective({
      name: 'onFragmentSpread',
      locations: ['FRAGMENT_SPREAD'],
    }),
    new GraphQLDirective({
      name: 'onInlineFragment',
      locations: ['INLINE_FRAGMENT'],
    }),
    new GraphQLDirective({
      name: 'onVariableDefinition',
      locations: ['VARIABLE_DEFINITION'],
    }),
  ],
});

function expectValid(schema, rule, queryString) {
  const errors = validate(schema, parse(queryString), [rule]);
  expect(errors).to.deep.equal([], 'Should validate');
}

function expectInvalid(schema, rule, queryString, expectedErrors) {
  const errors = validate(schema, parse(queryString), [rule]);
  expect(errors).to.have.length.of.at.least(1, 'Should not validate');
  expect(errors).to.deep.equal(expectedErrors);
  return errors;
}

export function expectPassesRule(rule, queryString) {
  return expectValid(testSchema, rule, queryString);
}

export function expectFailsRule(rule, queryString, errors) {
  return expectInvalid(testSchema, rule, queryString, errors);
}

export function expectPassesRuleWithSchema(schema, rule, queryString) {
  return expectValid(schema, rule, queryString);
}

export function expectFailsRuleWithSchema(schema, rule, queryString, errors) {
  return expectInvalid(schema, rule, queryString, errors);
}

export function expectSDLErrorsFromRule(rule, sdlString, schema) {
  const errors = validateSDL(parse(sdlString), schema, [rule]);
  return expect(errors);
}
<|endoftext|>