<commit_before>  if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(["require", "../deep", "../deep-stores"], function (require, deep) {

    return function(deep){
  //_____________________________________________________________________ COLLECTION STORE
        /**
         * A store based on simple array
         * @class deep.store.Collection
         * @constructor
         * @param {Array} arr a first array of objects to hold
         * @param {Object} options could contain 'schema'
         */
        deep.store.Collection = deep.compose.Classes(deep.Store,
        function (protocole, collection, schema, options) {
            if (collection)
                this.collection = collection;
            if(schema)
                this.schema = schema;
            if(options)
                deep.utils.up(options, this);
        },
        {
            /**
             * @method init
             */
            init: deep.compose.parallele(function () {
                var self = this;
                //console.log("deep.store.Collection.init : this.collection : ", this.collection, " - this.schema : ", this.schema);
                this.collection = this.collection || [];
                if (typeof this.collection === 'string' || typeof this.schema === 'string')
                    return deep(this)
                        .query("./[collection,schema]")
                        .load()
                        .done(function(success){
                             return self;
                        });
            }),
            /**
             * @method get
             * @param  {String} id the id of the object to retrieve. Could also be a (deep)query.
             * @param {Object} options an options object (here there is no options)
             * @return {Object} the retrieved object
             */
            get: function (id, options) {
                options = options || {};
                //console.log("deep.store.Collection.get : ",id," - stock : ", this.collection)
                var q = "";
                var queried = false;
                if(!id)
                {
                    q = "./*";
                    queried = true;
                }
                else if (id[0] == "*")
                {
                    q = "./"+id;
                    queried = true;
                }
                else if(id[0] == "?")
                {
                    q = "./*"+id;
                    queried = true;
                }
                else
                    q = "./*?id=" + id;
                //console.log("deep.store.Collection.get : q :",q);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var r = deep.query(col, q);
                //console.log("deep.store.Collection.get : res :",r);
                if (!queried && r instanceof Array)
                    r = r.shift();
                if(typeof r === 'undefined')
                    return deep.when(deep.errors.NotFound());
                return deep.when(r);
            },
            /**
             * @method put
             * @param  {Object} object the object to update
             * @param  {Object} options an options object : could contain 'id'
             * @return {Object} the updated object
             */
            put: function (object, options) {
                options = options || {};
                var id = options.id || object.id;
                if (!id)
                    return deep.when(deep.errors.Store("Collection store need id on put"));

                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();

                var r = deep.query(col, "./*?id=" + id, { resultType: "full" });
                if (!r || r.length === 0)
                    return deep.when(deep.errors.NotFound("no items found in collection with : " + id));
                r = r.shift();
                if(options.query)
                {
                    r.value = deep.utils.copy(r.value);
                    deep.utils.replace(r.value, options.query, object);
                }
                else
                {
                    if(!object.id)
                        object.id = options.id;
                    r.value = object;
                }

                var schema = this.schema;
                if(schema)
                {
                    if(schema._deep_ocm_)
                        schema = schema("put");
                    var report = deep.validate(r.value, schema);
                    if(!report.valid)
                        return deep.when(deep.errors.PreconditionFail(report));
                }

                if (r.ancestor)
                    r.ancestor.value[r.key] = r.value;
                return deep.when(r.value);
            },
            /**
             * @method post
             * @param  {Object} object
             * @param  {Object} options (optional)
             * @return {Object} the inserted object (decorated with it's id)
             */
            post: function (object, options) {
                //console.log("deep.store.Collection.post : ", object, options);
                options = options || {};
                options.id = options.id || object.id;
                if (!options.id)
                    object.id = options.id = "id"+new Date().valueOf(); // mongo styled id
                if(!object.id)
                    object.id = options.id;
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var res = deep.query(col, "./*?id=" + object.id);
                if (res && res.length > 0)
                    return deep.when(deep.errors.Store("deep.store.Collection.post : An object has the same id before post : please put in place : object : ", object));
                col.push(object);
                return deep.when(object);
            },
            /**
             * @method del
             * @param  {String} id
             * @param  {Object} options no options for the moment
             * @return {Object} the removed object
             */
            del: function (id, options) {
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var removed = deep(col).remove("./*?id=" + id).done();
                if (removed)
                    removed = removed.shift();
                return deep.when(removed);
            },
            /**
             * @method patch
             * @param  {Object} object  the update to apply to object
             * @param  {Object} options  could contain 'id'
             * @return {deep.Chain} a chain that hold the patched object and has injected values as success object.
             */

            /**
             * select a range in collection
             * @method range
             * @param  {Number} start
             * @param  {Number} end
             * @return {deep.Chain} a chain that hold the selected range and has injected values as success object.
             */
            range: function (start, end, query) {
                //console.log("deep.store.Collection.range : ", start, end);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                query = query || "";
                query += "&limit("+((end-start)+1)+","+start+")";
                var res = deep.query(col, "./*?"+query);
                return deep.utils.createRangeObject(start, end, this.collection.length, res.length, res, query);
            },
            flush:function(){
                this.collection = [];
            }
        });

        deep.store.Collection.create = function(protocole, collection, schema, options)
        {
            return new deep.store.Collection(protocole, collection, schema, options);
        };
        deep.utils.sheet(deep.store.ObjectSheet, deep.store.Collection.prototype);

        return deep.store.Collection;
    };
});
<commit_msg>collection init to after<commit_after>  if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(["require", "../deep", "../deep-stores"], function (require, deep) {

    return function(deep){
  //_____________________________________________________________________ COLLECTION STORE
        /**
         * A store based on simple array
         * @class deep.store.Collection
         * @constructor
         * @param {Array} arr a first array of objects to hold
         * @param {Object} options could contain 'schema'
         */
        deep.store.Collection = deep.compose.Classes(deep.Store,
        function (protocole, collection, schema, options) {
            if (collection)
                this.collection = collection;
            if(schema)
                this.schema = schema;
            if(options)
                deep.utils.up(options, this);
        },
        {
            /**
             * @method init
             */
            init: deep.compose.after(function () {
                var self = this;
                //console.log("deep.store.Collection.init : this.collection : ", this.collection, " - this.schema : ", this.schema);
                this.collection = this.collection || [];
                if (typeof this.collection === 'string' || typeof this.schema === 'string')
                    return deep(this)
                        .query("./[collection,schema]")
                        .load()
                        .done(function(success){
                             return self;
                        });
            }),
            /**
             * @method get
             * @param  {String} id the id of the object to retrieve. Could also be a (deep)query.
             * @param {Object} options an options object (here there is no options)
             * @return {Object} the retrieved object
             */
            get: function (id, options) {
                options = options || {};
                //console.log("deep.store.Collection.get : ",id," - stock : ", this.collection)
                var q = "";
                var queried = false;
                if(!id)
                {
                    q = "./*";
                    queried = true;
                }
                else if (id[0] == "*")
                {
                    q = "./"+id;
                    queried = true;
                }
                else if(id[0] == "?")
                {
                    q = "./*"+id;
                    queried = true;
                }
                else
                    q = "./*?id=" + id;
                //console.log("deep.store.Collection.get : q :",q);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var r = deep.query(col, q);
                //console.log("deep.store.Collection.get : res :",r);
                if (!queried && r instanceof Array)
                    r = r.shift();
                if(typeof r === 'undefined')
                    return deep.when(deep.errors.NotFound());
                return deep.when(r);
            },
            /**
             * @method put
             * @param  {Object} object the object to update
             * @param  {Object} options an options object : could contain 'id'
             * @return {Object} the updated object
             */
            put: function (object, options) {
                options = options || {};
                var id = options.id || object.id;
                if (!id)
                    return deep.when(deep.errors.Store("Collection store need id on put"));

                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();

                var r = deep.query(col, "./*?id=" + id, { resultType: "full" });
                if (!r || r.length === 0)
                    return deep.when(deep.errors.NotFound("no items found in collection with : " + id));
                r = r.shift();
                if(options.query)
                {
                    r.value = deep.utils.copy(r.value);
                    deep.utils.replace(r.value, options.query, object);
                }
                else
                {
                    if(!object.id)
                        object.id = options.id;
                    r.value = object;
                }

                var schema = this.schema;
                if(schema)
                {
                    if(schema._deep_ocm_)
                        schema = schema("put");
                    var report = deep.validate(r.value, schema);
                    if(!report.valid)
                        return deep.when(deep.errors.PreconditionFail(report));
                }

                if (r.ancestor)
                    r.ancestor.value[r.key] = r.value;
                return deep.when(r.value);
            },
            /**
             * @method post
             * @param  {Object} object
             * @param  {Object} options (optional)
             * @return {Object} the inserted object (decorated with it's id)
             */
            post: function (object, options) {
                //console.log("deep.store.Collection.post : ", object, options);
                options = options || {};
                options.id = options.id || object.id;
                if (!options.id)
                    object.id = options.id = "id"+new Date().valueOf(); // mongo styled id
                if(!object.id)
                    object.id = options.id;
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var res = deep.query(col, "./*?id=" + object.id);
                if (res && res.length > 0)
                    return deep.when(deep.errors.Store("deep.store.Collection.post : An object has the same id before post : please put in place : object : ", object));
                col.push(object);
                return deep.when(object);
            },
            /**
             * @method del
             * @param  {String} id
             * @param  {Object} options no options for the moment
             * @return {Object} the removed object
             */
            del: function (id, options) {
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var removed = deep(col).remove("./*?id=" + id).done();
                if (removed)
                    removed = removed.shift();
                return deep.when(removed);
            },
            /**
             * @method patch
             * @param  {Object} object  the update to apply to object
             * @param  {Object} options  could contain 'id'
             * @return {deep.Chain} a chain that hold the patched object and has injected values as success object.
             */

            /**
             * select a range in collection
             * @method range
             * @param  {Number} start
             * @param  {Number} end
             * @return {deep.Chain} a chain that hold the selected range and has injected values as success object.
             */
            range: function (start, end, query) {
                //console.log("deep.store.Collection.range : ", start, end);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                query = query || "";
                query += "&limit("+((end-start)+1)+","+start+")";
                var res = deep.query(col, "./*?"+query);
                return deep.utils.createRangeObject(start, end, this.collection.length, res.length, res, query);
            },
            flush:function(){
                this.collection = [];
            }
        });

        deep.store.Collection.create = function(protocole, collection, schema, options)
        {
            return new deep.store.Collection(protocole, collection, schema, options);
        };
        deep.utils.sheet(deep.store.ObjectSheet, deep.store.Collection.prototype);

        return deep.store.Collection;
    };
});
<|endoftext|>


<commit_before>var Web3 = require("web3");
var LegacyWeb3 = require("legacy-web3");
var Config = require("truffle-config");
var Migrate = require("truffle-migrate");
var TestResolver = require("./testresolver");
var TestSource = require("./testsource");
var expect = require("truffle-expect");
var contract = require("truffle-contract");
var abi = require("web3-eth-abi");
var path = require("path");
var _ = require("lodash");
var async = require("async");
var fs = require("fs");

function TestRunner(options = {}) {
  expect.options(options, [
    "resolver",
    "provider",
    "contracts_build_directory"
  ]);

  this.config = Config.default().merge(options);

  this.logger = options.logger || console;
  this.initial_resolver = options.resolver;
  this.provider = options.provider;

  this.can_snapshot = false;
  this.first_snapshot = true;
  this.initial_snapshot = null;
  this.known_events = {};
  this.web3 = options.legacy ? new LegacyWeb3() : new Web3();
  this.web3.setProvider(options.provider);

  // For each test
  this.currentTestStartBlock = null;

  this.BEFORE_TIMEOUT = 120000;
  this.TEST_TIMEOUT = 300000;
}

TestRunner.prototype.initialize = function(callback) {
  var self = this;

  if (self.web3.sha3) {
    self.web3.utils = {};
    self.web3.utils.sha3 = self.web3.sha3;
  }

  var test_source = new TestSource(self.config);
  this.config.resolver = new TestResolver(
    self.initial_resolver,
    test_source,
    self.config.contracts_build_directory
  );

  var afterStateReset = function(err) {
    if (err) return callback(err);

    fs.readdir(self.config.contracts_build_directory, function(err, files) {
      if (err) return callback(err);

      files = _.filter(files, function(file) {
        return path.extname(file) === ".json";
      });

      async.map(
        files,
        function(file, finished) {
          fs.readFile(
            path.join(self.config.contracts_build_directory, file),
            "utf8",
            finished
          );
        },
        function(err, data) {
          if (err) return callback(err);

          var contracts = data.map(JSON.parse).map(contract);
          var abis = _.flatMap(contracts, "abi");

          abis.map(function(abi) {
            if (abi.type == "event") {
              var signature =
                abi.name + "(" + _.map(abi.inputs, "type").join(",") + ")";
              self.known_events[self.web3.utils.sha3(signature)] = {
                signature: signature,
                abi_entry: abi
              };
            }
          });
          callback();
        }
      );
    });
  };

  if (self.first_snapshot) {
    // // Make the initial deployment (full migration).
    // self.deploy(function(err) {
    //   if (err) return callback(err);

    self.snapshot(function(err, initial_snapshot) {
      if (err == null) {
        self.can_snapshot = true;
        self.initial_snapshot = initial_snapshot;
      }

      self.first_snapshot = false;

      afterStateReset();
    });
    //});
  } else {
    self.resetState(afterStateReset);
  }
};

TestRunner.prototype.deploy = function(callback) {
  Migrate.run(
    this.config.with({
      reset: true,
      quiet: true
    }),
    callback
  );
};

TestRunner.prototype.resetState = function(callback) {
  var self = this;
  if (this.can_snapshot) {
    this.revert(this.initial_snapshot, function(err) {
      if (err) return callback(err);
      self.snapshot(function(err, snapshot) {
        if (err) return callback(err);
        self.initial_snapshot = snapshot;
        callback();
      });
    });
  } else {
    this.deploy(callback);
  }
};

TestRunner.prototype.startTest = function(mocha, callback) {
  var self = this;
  if (self.config.legacy) {
    this.web3.eth.getBlockNumber(function(err, result) {
      if (err) return callback(err);

      result = web3.toBigNumber(result);

      // Add one in base 10
      self.currentTestStartBlock = result.plus(1, 10);

      callback();
    });
  } else {
    this.web3.eth
      .getBlockNumber()
      .then(result => {
        var one = self.web3.utils.toBN(1);
        result = self.web3.utils.toBN(result);

        // Add one in base 10
        self.currentTestStartBlock = result.add(one);

        callback();
      })
      .catch(callback);
  }
};

TestRunner.prototype.endTest = function(mocha, callback) {
  var self = this;

  // Skip logging if test passes and `show-events` option is not true
  if (mocha.currentTest.state != "failed" && !self.config["show-events"]) {
    return callback();
  }

  // There's no API for eth_getLogs?
  this.rpc(
    "eth_getLogs",
    [
      {
        fromBlock: "0x" + this.currentTestStartBlock.toString(16)
      }
    ],
    function(err, result) {
      if (err) return callback(err);

      var logs = result.result;

      if (logs.length == 0) {
        self.logger.log("    > No events were emitted");
        return callback();
      }

      self.logger.log("\n    Events emitted during test:");
      self.logger.log("    ---------------------------");
      self.logger.log("");

      logs.forEach(function(log) {
        var event = self.known_events[log.topics[0]];

        if (event == null) {
          return;
        }

        var types = event.abi_entry.inputs
          .map(function(input) {
            return input.indexed == true ? null : input.type;
          })
          .filter(function(type) {
            return type != null;
          });

        var values = abi.decodeLog(
          event.abi_entry.inputs,
          log.data,
          log.topics
        );
        var index = 0;

        var line = "    " + event.abi_entry.name + "(";
        line += event.abi_entry.inputs
          .map(function(input) {
            var value;
            if (input.indexed == true) {
              value = "<indexed>";
            } else {
              value = values[index];
            }
            index += 1;

            return input.name + ": " + `${value}`;
          })
          .join(", ");
        line += ")";
        self.logger.log(line);
      });
      self.logger.log("\n    ---------------------------");
      callback();
    }
  );
};

(TestRunner.prototype.snapshot = function(callback) {
  this.rpc("evm_snapshot", function(err, result) {
    if (err) return callback(err);
    callback(null, result.result);
  });
}),
  (TestRunner.prototype.revert = function(snapshot_id, callback) {
    this.rpc("evm_revert", [snapshot_id], callback);
  });

TestRunner.prototype.rpc = function(method, arg, cb) {
  var req = {
    jsonrpc: "2.0",
    method: method,
    id: new Date().getTime()
  };
  if (arguments.length == 3) {
    req.params = arg;
  } else {
    cb = arg;
  }

  var intermediary = function(err, result) {
    if (err != null) {
      cb(err);
      return;
    }

    if (result.error != null) {
      cb(new Error("RPC Error: " + (result.error.message || result.error)));
      return;
    }

    cb(null, result);
  };

  this.config.legacy
    ? this.provider.sendAsync(req, intermediary)
    : this.provider.send(req, intermediary);
};

module.exports = TestRunner;
<commit_msg>fix comma<commit_after>var Web3 = require("web3");
var LegacyWeb3 = require("legacy-web3");
var Config = require("truffle-config");
var Migrate = require("truffle-migrate");
var TestResolver = require("./testresolver");
var TestSource = require("./testsource");
var expect = require("truffle-expect");
var contract = require("truffle-contract");
var abi = require("web3-eth-abi");
var path = require("path");
var _ = require("lodash");
var async = require("async");
var fs = require("fs");

function TestRunner(options = {}) {
  expect.options(options, [
    "resolver",
    "provider",
    "contracts_build_directory"
  ]);

  this.config = Config.default().merge(options);

  this.logger = options.logger || console;
  this.initial_resolver = options.resolver;
  this.provider = options.provider;

  this.can_snapshot = false;
  this.first_snapshot = true;
  this.initial_snapshot = null;
  this.known_events = {};
  this.web3 = options.legacy ? new LegacyWeb3() : new Web3();
  this.web3.setProvider(options.provider);

  // For each test
  this.currentTestStartBlock = null;

  this.BEFORE_TIMEOUT = 120000;
  this.TEST_TIMEOUT = 300000;
}

TestRunner.prototype.initialize = function(callback) {
  var self = this;

  if (self.web3.sha3) {
    self.web3.utils = {};
    self.web3.utils.sha3 = self.web3.sha3;
  }

  var test_source = new TestSource(self.config);
  this.config.resolver = new TestResolver(
    self.initial_resolver,
    test_source,
    self.config.contracts_build_directory
  );

  var afterStateReset = function(err) {
    if (err) return callback(err);

    fs.readdir(self.config.contracts_build_directory, function(err, files) {
      if (err) return callback(err);

      files = _.filter(files, function(file) {
        return path.extname(file) === ".json";
      });

      async.map(
        files,
        function(file, finished) {
          fs.readFile(
            path.join(self.config.contracts_build_directory, file),
            "utf8",
            finished
          );
        },
        function(err, data) {
          if (err) return callback(err);

          var contracts = data.map(JSON.parse).map(contract);
          var abis = _.flatMap(contracts, "abi");

          abis.map(function(abi) {
            if (abi.type == "event") {
              var signature =
                abi.name + "(" + _.map(abi.inputs, "type").join(",") + ")";
              self.known_events[self.web3.utils.sha3(signature)] = {
                signature: signature,
                abi_entry: abi
              };
            }
          });
          callback();
        }
      );
    });
  };

  if (self.first_snapshot) {
    // // Make the initial deployment (full migration).
    // self.deploy(function(err) {
    //   if (err) return callback(err);

    self.snapshot(function(err, initial_snapshot) {
      if (err == null) {
        self.can_snapshot = true;
        self.initial_snapshot = initial_snapshot;
      }

      self.first_snapshot = false;

      afterStateReset();
    });
    //});
  } else {
    self.resetState(afterStateReset);
  }
};

TestRunner.prototype.deploy = function(callback) {
  Migrate.run(
    this.config.with({
      reset: true,
      quiet: true
    }),
    callback
  );
};

TestRunner.prototype.resetState = function(callback) {
  var self = this;
  if (this.can_snapshot) {
    this.revert(this.initial_snapshot, function(err) {
      if (err) return callback(err);
      self.snapshot(function(err, snapshot) {
        if (err) return callback(err);
        self.initial_snapshot = snapshot;
        callback();
      });
    });
  } else {
    this.deploy(callback);
  }
};

TestRunner.prototype.startTest = function(mocha, callback) {
  var self = this;
  if (self.config.legacy) {
    this.web3.eth.getBlockNumber(function(err, result) {
      if (err) return callback(err);

      result = web3.toBigNumber(result);

      // Add one in base 10
      self.currentTestStartBlock = result.plus(1, 10);

      callback();
    });
  } else {
    this.web3.eth
      .getBlockNumber()
      .then(result => {
        var one = self.web3.utils.toBN(1);
        result = self.web3.utils.toBN(result);

        // Add one in base 10
        self.currentTestStartBlock = result.add(one);

        callback();
      })
      .catch(callback);
  }
};

TestRunner.prototype.endTest = function(mocha, callback) {
  var self = this;

  // Skip logging if test passes and `show-events` option is not true
  if (mocha.currentTest.state != "failed" && !self.config["show-events"]) {
    return callback();
  }

  // There's no API for eth_getLogs?
  this.rpc(
    "eth_getLogs",
    [
      {
        fromBlock: "0x" + this.currentTestStartBlock.toString(16)
      }
    ],
    function(err, result) {
      if (err) return callback(err);

      var logs = result.result;

      if (logs.length == 0) {
        self.logger.log("    > No events were emitted");
        return callback();
      }

      self.logger.log("\n    Events emitted during test:");
      self.logger.log("    ---------------------------");
      self.logger.log("");

      logs.forEach(function(log) {
        var event = self.known_events[log.topics[0]];

        if (event == null) {
          return;
        }

        var types = event.abi_entry.inputs
          .map(function(input) {
            return input.indexed == true ? null : input.type;
          })
          .filter(function(type) {
            return type != null;
          });

        var values = abi.decodeLog(
          event.abi_entry.inputs,
          log.data,
          log.topics
        );
        var index = 0;

        var line = "    " + event.abi_entry.name + "(";
        line += event.abi_entry.inputs
          .map(function(input) {
            var value;
            if (input.indexed == true) {
              value = "<indexed>";
            } else {
              value = values[index];
            }
            index += 1;

            return input.name + ": " + `${value}`;
          })
          .join(", ");
        line += ")";
        self.logger.log(line);
      });
      self.logger.log("\n    ---------------------------");
      callback();
    }
  );
};

TestRunner.prototype.snapshot = function(callback) {
  this.rpc("evm_snapshot", function(err, result) {
    if (err) return callback(err);
    callback(null, result.result);
  });
};

TestRunner.prototype.revert = function(snapshot_id, callback) {
  this.rpc("evm_revert", [snapshot_id], callback);
};

TestRunner.prototype.rpc = function(method, arg, cb) {
  var req = {
    jsonrpc: "2.0",
    method: method,
    id: new Date().getTime()
  };
  if (arguments.length == 3) {
    req.params = arg;
  } else {
    cb = arg;
  }

  var intermediary = function(err, result) {
    if (err != null) {
      cb(err);
      return;
    }

    if (result.error != null) {
      cb(new Error("RPC Error: " + (result.error.message || result.error)));
      return;
    }

    cb(null, result);
  };

  this.config.legacy
    ? this.provider.sendAsync(req, intermediary)
    : this.provider.send(req, intermediary);
};

module.exports = TestRunner;
<|endoftext|>


<commit_before>var fs = require('fs');
var clientFilePath = "../js/state_client.js";
var clientFileContents = fs.readFileSync(clientFilePath).toString();
eval(clientFileContents);

var devUpdateURL = 'http://localhost:8081/';
var io = require("socket.io-client");

var socketURL = devUpdateURL;

var clientId = 0;
function instantiateClient()
{
	clientId++;
	console.log("Instantiated client:" + clientId);
	new StateClient(global).init(socketURL,
		function onConnect()
		{
			console.log('connect');
		},
		function onReconnect()
		{
			console.log('reconnect');
			/*
			$.get("/current_state").done(function(data)
			{
				new StateData(JSON.parse(data)).apply()
			})
			*/
		},
		function onStateChange(data)
		{
			console.log('state change');
			//processState(JSON.parse(data));
		},
		function onDisconnect()
		{
			console.log("disconnect");
			//setFridgeStateUnknown();
		}
	)
}

instantiateClient();

var app = require("express")();
app.listen(8082, "127.0.0.1");
app.get("/dump", function(req, res) {
  res.send("test");
});<commit_msg>updated stress test to return basic data<commit_after>var fs = require('fs');
var clientFilePath = "../js/state_client.js";
var clientFileContents = fs.readFileSync(clientFilePath).toString();
var serverDateFormat = 'YYYY-MM-DD HH:mm:ss.SSS Z'
eval(clientFileContents);

var moment = require('moment')

var results = {};
var instances = 500;
var devUpdateURL = 'http://localhost:8081/state_changes';
//var devUpdateURL = 'http://node.fridge-cop.com/state_changes';

var io = require("socket.io-client");
var heartbeatMilliseconds = 5 * 1000;
var lastBroadcast = null;

function instantiateNew(instance)
{
	results[instance] = {};
	results[instance].startTryConnectTime = moment();
	var socket = io.connect(devUpdateURL, {"forceNew" : true});

	socket.on('connect', function()
	{
		results[instance].connectTime = moment();
		console.log("Instance " + instance + " connected.")
		socket.on('new_states', function (data)
		{
			if (instance == 1)
			{
				lastBroadcast = data;
			}
			results[instance].messageTime = moment();
		});

		socket.on('disconnect', function()
		{
		});
	});
}

function getInstance(i)
{
	return function()
	{
		instantiateNew(i);
	}
}

for (var i = 0; i < instances; i++)
{
	setTimeout(getInstance(i), parseInt((heartbeatMilliseconds / instances) * i));
}

var app = require("express")();
app.listen(8082, "127.0.0.1");
app.get("/dump", function(req, res)
{
	var output = "";
	var lastTime = moment(JSON.parse(lastBroadcast).t, serverDateFormat);
	output += lastTime.format();
	var connectionTimes = [];
	var messageTimes = [];
	for (var i = 0; i < instances; i++)
	{
		messageTimes.push(results[i].messageTime)
		connectionTimes.push(results[i].connectTime.diff(results[i].startTryConnectTime))
	}
	connectionTimes.sort(function(a,b)
	{
		return a - b;
	});
	messageTimes.sort(function(a,b)
	{
		return a.diff(b);
	});

	var min = messageTimes[0];
	var max = messageTimes[messageTimes.length - 1];

	var connectionTimesMean = 0;
	for (var i = 0; i < instances; i++)
	{
		connectionTimesMean += connectionTimes[i];
	}
	connectionTimesMean /= connectionTimes.length;

	var messageTimesMean = 0;
	for (var i = 0; i < instances; i++)
	{
		var difference = messageTimes[i].diff(min)
		messageTimesMean += difference;
	}
	messageTimesMean /= messageTimes.length

	output += "Mean time to connect: " + connectionTimesMean + " ms
";
	output += "Mean time to transmit message: " + messageTimesMean + " ms
";

	res.send(output)
});<|endoftext|>


<commit_before>export const ChangeTheme = (color) => {
  const themeTypes = {
    green: {
      bg: '#EFF2E4',
      title: '#D3FFBE',
      logo: 'transparent',
      main: '#000000',
      logoTitle: '#4A8731',
      textBg: '#FFFFFF'
    },
    blue: {
      bg: '#D7ECFF',
      title: '#B7F2FF',
      logo: 'transparent',
      main: '#000000',
      logoTitle: '#4A8731',
      textBg: '#FFFFFF'
    },
    black: {
      bg: '#000000',
      title: '#616161',
      logo: '#FFFFFF',
      main: '#FFFFFF',
      logoTitle: '#FFFFFF',
      textBg: '#2B2B2B'
    },
    yellow: {
      bg: '#FFF4D7',
      title: '#FFE7B7',
      logo: 'transparent',
      main: '#000000',
      logoTitle: '#4A8731',
      textBg: '#FFFFFF'
    }
  };
  document.getElementById('bg').style.background = themeTypes[color]['bg'];
  document.getElementById('logo').style.background = themeTypes[color]['logo'];
  document.getElementById('main').style.color = themeTypes[color]['main'];
  document.getElementById('logoTitle').style.color = themeTypes[color]['logoTitle'];
  document.getElementById('ljTitle').style.background = themeTypes[color]['title'];
  document.getElementById('ljText').style.background = themeTypes[color]['textBg'];
  document.getElementById('dgTitle').style.background = themeTypes[color]['title'];
  document.getElementById('dgText').style.background = themeTypes[color]['textBg'];
  document.getElementById('diffedTitle').style.background = themeTypes[color]['title'];
  document.getElementById('diffedText').style.background = themeTypes[color]['textBg'];
};
<commit_msg>fix function name<commit_after>export const changeTheme = (color) => {
  const themeTypes = {
    green: {
      bg: '#EFF2E4',
      title: '#D3FFBE',
      logo: 'transparent',
      main: '#000000',
      logoTitle: '#4A8731',
      textBg: '#FFFFFF'
    },
    blue: {
      bg: '#D7ECFF',
      title: '#B7F2FF',
      logo: 'transparent',
      main: '#000000',
      logoTitle: '#4A8731',
      textBg: '#FFFFFF'
    },
    black: {
      bg: '#000000',
      title: '#616161',
      logo: '#FFFFFF',
      main: '#FFFFFF',
      logoTitle: '#FFFFFF',
      textBg: '#2B2B2B'
    },
    yellow: {
      bg: '#FFF4D7',
      title: '#FFE7B7',
      logo: 'transparent',
      main: '#000000',
      logoTitle: '#4A8731',
      textBg: '#FFFFFF'
    }
  };
  document.getElementById('bg').style.background = themeTypes[color]['bg'];
  document.getElementById('logo').style.background = themeTypes[color]['logo'];
  document.getElementById('main').style.color = themeTypes[color]['main'];
  document.getElementById('logoTitle').style.color = themeTypes[color]['logoTitle'];
  document.getElementById('ljTitle').style.background = themeTypes[color]['title'];
  document.getElementById('ljText').style.background = themeTypes[color]['textBg'];
  document.getElementById('dgTitle').style.background = themeTypes[color]['title'];
  document.getElementById('dgText').style.background = themeTypes[color]['textBg'];
  document.getElementById('diffedTitle').style.background = themeTypes[color]['title'];
  document.getElementById('diffedText').style.background = themeTypes[color]['textBg'];
};
<|endoftext|>


<commit_before>/**
 * Darkroom Kitchen Sink
 * A bit overkill but use-able
 */

import { Darkroom, Canvas, History, Toolbar, FilePicker, CropMenu } from '../components';
import { Transform } from '../utils';
import React from 'react';

const canvasWidth = 300;
const canvasHeight = 300;

function fileController(thread = {source: null}, action) {
  switch (action.type) {
    case 'SET_FILE':
      return Object.assign({}, thread, {
        source: action.file,
        angle: 0
      });
    default:
      return thread;
  }
}
function imageController(thread = {crop: false, source: null, angle: 0}, action) {
  switch (action.type) {
    case 'ROTATE_LEFT':
      return Object.assign({}, thread, {
        angle: thread.angle + 90
      });
    case 'ROTATE_RIGHT':
      return Object.assign({}, thread, {
        angle: thread.angle - 90
      });
    case 'START_CROPPING':
      return Object.assign({}, thread, {
        crop: true
      });
    case 'STOP_CROPPING':
      return Object.assign({}, thread, {
        crop: false
      });
    case 'CONFIRM_CROP':
      return Object.assign({}, thread, {
        crop: false,
        source: action.image
      });
    default:
      return thread;
  }
}
function readFile(file, done) {
  var reader = new FileReader();
  reader.onload = e => done(e.target.result);
  reader.readAsDataURL(file);
}

/**
 * Darkroom API methods
 *
 * Set image/width/height
 * Set Rotation
 * Use React.Children.foreach can iterate through each item
 * for a declarative API
 * Image rotation -> Should that be state?  Or should we set that
 * independantly and allow for image rotation to be easily set?
 *
 * Controls to be a separate and optional component for maximum
 * re-usability.
 */

export default class KitchenSink extends React.Component {

  constructor(props) {
    super(props);
    this.state = { step: 0, thread: [{crop: false, source: null, angle: 0}] };
    ['onFileChange',
      'update',
      'onRedo',
      'onUndo',
      'onRotateLeft',
      'onCropStart',
      'onCropConfirm',
      'onCropCancel',
      'onRotateRight'].forEach((method) => {
      this[method] = this[method].bind(this);
    });
  }

  componentDidUpdate() {
    console.timeEnd('State changed');
  }
  update(action) {
    const state = this.state;
    let nextThread;
    let nextStep = state.thread.length;
    let newState;
    let newThread;

    switch (action.type) {
      case "SET_FILE":
        nextThread = fileController(state.thread[state.step], action);
        break;

      case "UNDO":
        nextStep = state.step - 1;
        break;

      case "REDO":
        nextStep = state.step + 1;
        break;

      case "ROTATE_LEFT":
      case "ROTATE_RIGHT":
      case "START_CROPPING":
      case "STOP_CROPPING":
      case "CONFIRM_CROP":
        nextThread = imageController(state.thread[state.step], action);
        break;

    }

    if ((action.type !== "UNDO" && action.type !== "REDO") &&
    (state.step > 0 && state.step < state.thread.length - 1)) {
      newThread = [
        ...state.thread.slice(0, state.step),
        nextThread
      ];
      nextStep = newThread.length - 1;
    } else {
      newThread = nextThread ? [...state.thread, nextThread ] : [].concat(state.thread);
    }

    newState = Object.assign({}, state, {
      step: nextStep,
      thread: newThread
    });
    console.time('State changed');
    this.setState(newState);

  }

  onFileChange(e) {

    readFile(e.target.files[0], file => {
      this.update({type: 'SET_FILE', file });
    });
  }

  onUndo() {
    this.update({type: 'UNDO'});
  }

  onRedo() {
    this.update({type: 'REDO'});
  }

  onRotateLeft() {
    this.update({type: 'ROTATE_LEFT'});
  }

  onRotateRight() {
    this.update({type: 'ROTATE_RIGHT'});
  }

  onCropStart() {
    this.update({type: 'START_CROPPING'});
  }

  onCropCancel() {
    this.update({type: 'STOP_CROPPING'});
  }

  onCropConfirm() {

    let { source } = this.state.thread[this.state.step];
    let { x, y, width, height } = this.refs.canvasWrapper.cropBox;

    let newImage = Transform.cropImage(source, {x, y, width, height}, { width: canvasWidth, height: canvasHeight })
      .then(image => this.update({ type: 'CONFIRM_CROP', image }));

  }

  render() {
    let current = this.state.thread[this.state.step];
    let { angle, source, crop } = current;
    let hasFile = source !== null;

    let selectFile = () => {
      this.refs.fileselect.click();
    };

    return (

React Darkroom Kitchen Sink v0.3.5

            https://github.com/MattMcFarland/react-darkroom

          <Darkroom>
            <Toolbar>
              <button onClick={selectFile} data-tipsy="Select Image" className="tipsy tipsy--s">

                <input type="file" ref="fileselect" onChange={this.onFileChange} style={{display: 'none'}}/>
              </button>
              <History step={this.state.step} length={this.state.thread.length - 1}>
                <button
                  action="back"
                  onClick={this.onUndo}
                  data-ifEmpty="disable"
                  data-tipsy="Undo"
                  className="tipsy tipsy--sw">

                </button>
                <button
                  action="forward"
                  onClick={this.onRedo}
                  data-ifEmpty="disable"
                  data-tipsy="Redo"
                  className="tipsy tipsy--sw">

                </button>
              </History>
              <button
                disabled={!hasFile}
                onClick={this.onRotateLeft}
                data-tipsy="Rotate Left"
                className="tipsy tipsy--sw">

              </button>
              <button
                disabled={!hasFile}
                onClick={this.onRotateRight}
                data-tipsy="Rotate Right"
                className="tipsy tipsy--sw">

              </button>
              <CropMenu isCropping={crop}>
                <button
                  disabled={!hasFile}
                  data-showOnlyWhen='croppingIsOff'
                  onClick={this.onCropStart}
                  data-tipsy="Crop"
                  className="tipsy tipsy--sw">

                </button>
                <button disabled={!hasFile} showOnlyWhen='croppingIsOn' style={{color: 'cyan'}}>

                </button>
                <button
                  disabled={!hasFile}
                  data-showOnlyWhen='croppingIsOn'
                  onClick={this.onCropConfirm}
                  style={{color: 'green'}}
                  data-tipsy="Confirm"
                  className="tipsy tipsy--sw">

                </button>
                <button
                  disabled={!hasFile}
                  data-showOnlyWhen='croppingIsOn'
                  onClick={this.onCropCancel}
                  style={{color: 'red'}}
                  data-tipsy="Cancel"
                  className="tipsy tipsy--sw">

                </button>
              </CropMenu>
              <button disabled={!hasFile} onClick={this.onSave} data-tipsy="Save" className="tipsy tipsy--sw">

              </button>
            </Toolbar>
            <Canvas
              ref="canvasWrapper"
              crop={crop}
              source={source}
              angle={angle}
              width={canvasWidth}
              height={canvasHeight}>
              <FilePicker hasFile={hasFile} onChange={this.onFileChange}/>
            </Canvas>
          </Darkroom>

    );
  }
}
<commit_msg>Rotation of the image is switched<commit_after>/**
 * Darkroom Kitchen Sink
 * A bit overkill but use-able
 */

import { Darkroom, Canvas, History, Toolbar, FilePicker, CropMenu } from '../components';
import { Transform } from '../utils';
import React from 'react';

const canvasWidth = 300;
const canvasHeight = 300;

function fileController(thread = {source: null}, action) {
  switch (action.type) {
    case 'SET_FILE':
      return Object.assign({}, thread, {
        source: action.file,
        angle: 0
      });
    default:
      return thread;
  }
}
function imageController(thread = {crop: false, source: null, angle: 0}, action) {
  switch (action.type) {
    case 'ROTATE_LEFT':
      return Object.assign({}, thread, {
        angle: thread.angle - 90
      });
    case 'ROTATE_RIGHT':
      return Object.assign({}, thread, {
        angle: thread.angle + 90
      });
    case 'START_CROPPING':
      return Object.assign({}, thread, {
        crop: true
      });
    case 'STOP_CROPPING':
      return Object.assign({}, thread, {
        crop: false
      });
    case 'CONFIRM_CROP':
      return Object.assign({}, thread, {
        crop: false,
        source: action.image
      });
    default:
      return thread;
  }
}
function readFile(file, done) {
  var reader = new FileReader();
  reader.onload = e => done(e.target.result);
  reader.readAsDataURL(file);
}

/**
 * Darkroom API methods
 *
 * Set image/width/height
 * Set Rotation
 * Use React.Children.foreach can iterate through each item
 * for a declarative API
 * Image rotation -> Should that be state?  Or should we set that
 * independantly and allow for image rotation to be easily set?
 *
 * Controls to be a separate and optional component for maximum
 * re-usability.
 */

export default class KitchenSink extends React.Component {

  constructor(props) {
    super(props);
    this.state = { step: 0, thread: [{crop: false, source: null, angle: 0}] };
    ['onFileChange',
      'update',
      'onRedo',
      'onUndo',
      'onRotateLeft',
      'onCropStart',
      'onCropConfirm',
      'onCropCancel',
      'onRotateRight'].forEach((method) => {
      this[method] = this[method].bind(this);
    });
  }

  componentDidUpdate() {
    console.timeEnd('State changed');
  }
  update(action) {
    const state = this.state;
    let nextThread;
    let nextStep = state.thread.length;
    let newState;
    let newThread;

    switch (action.type) {
      case "SET_FILE":
        nextThread = fileController(state.thread[state.step], action);
        break;

      case "UNDO":
        nextStep = state.step - 1;
        break;

      case "REDO":
        nextStep = state.step + 1;
        break;

      case "ROTATE_LEFT":
      case "ROTATE_RIGHT":
      case "START_CROPPING":
      case "STOP_CROPPING":
      case "CONFIRM_CROP":
        nextThread = imageController(state.thread[state.step], action);
        break;

    }

    if ((action.type !== "UNDO" && action.type !== "REDO") &&
    (state.step > 0 && state.step < state.thread.length - 1)) {
      newThread = [
        ...state.thread.slice(0, state.step),
        nextThread
      ];
      nextStep = newThread.length - 1;
    } else {
      newThread = nextThread ? [...state.thread, nextThread ] : [].concat(state.thread);
    }

    newState = Object.assign({}, state, {
      step: nextStep,
      thread: newThread
    });
    console.time('State changed');
    this.setState(newState);

  }

  onFileChange(e) {

    readFile(e.target.files[0], file => {
      this.update({type: 'SET_FILE', file });
    });
  }

  onUndo() {
    this.update({type: 'UNDO'});
  }

  onRedo() {
    this.update({type: 'REDO'});
  }

  onRotateLeft() {
    this.update({type: 'ROTATE_LEFT'});
  }

  onRotateRight() {
    this.update({type: 'ROTATE_RIGHT'});
  }

  onCropStart() {
    this.update({type: 'START_CROPPING'});
  }

  onCropCancel() {
    this.update({type: 'STOP_CROPPING'});
  }

  onCropConfirm() {

    let { source } = this.state.thread[this.state.step];
    let { x, y, width, height } = this.refs.canvasWrapper.cropBox;

    let newImage = Transform.cropImage(source, {x, y, width, height}, { width: canvasWidth, height: canvasHeight })
      .then(image => this.update({ type: 'CONFIRM_CROP', image }));

  }

  render() {
    let current = this.state.thread[this.state.step];
    let { angle, source, crop } = current;
    let hasFile = source !== null;

    let selectFile = () => {
      this.refs.fileselect.click();
    };

    return (

React Darkroom Kitchen Sink v0.3.5

            https://github.com/MattMcFarland/react-darkroom

          <Darkroom>
            <Toolbar>
              <button onClick={selectFile} data-tipsy="Select Image" className="tipsy tipsy--s">

                <input type="file" ref="fileselect" onChange={this.onFileChange} style={{display: 'none'}}/>
              </button>
              <History step={this.state.step} length={this.state.thread.length - 1}>
                <button
                  action="back"
                  onClick={this.onUndo}
                  data-ifEmpty="disable"
                  data-tipsy="Undo"
                  className="tipsy tipsy--sw">

                </button>
                <button
                  action="forward"
                  onClick={this.onRedo}
                  data-ifEmpty="disable"
                  data-tipsy="Redo"
                  className="tipsy tipsy--sw">

                </button>
              </History>
              <button
                disabled={!hasFile}
                onClick={this.onRotateLeft}
                data-tipsy="Rotate Left"
                className="tipsy tipsy--sw">

              </button>
              <button
                disabled={!hasFile}
                onClick={this.onRotateRight}
                data-tipsy="Rotate Right"
                className="tipsy tipsy--sw">

              </button>
              <CropMenu isCropping={crop}>
                <button
                  disabled={!hasFile}
                  data-showOnlyWhen='croppingIsOff'
                  onClick={this.onCropStart}
                  data-tipsy="Crop"
                  className="tipsy tipsy--sw">

                </button>
                <button disabled={!hasFile} showOnlyWhen='croppingIsOn' style={{color: 'cyan'}}>

                </button>
                <button
                  disabled={!hasFile}
                  data-showOnlyWhen='croppingIsOn'
                  onClick={this.onCropConfirm}
                  style={{color: 'green'}}
                  data-tipsy="Confirm"
                  className="tipsy tipsy--sw">

                </button>
                <button
                  disabled={!hasFile}
                  data-showOnlyWhen='croppingIsOn'
                  onClick={this.onCropCancel}
                  style={{color: 'red'}}
                  data-tipsy="Cancel"
                  className="tipsy tipsy--sw">

                </button>
              </CropMenu>
              <button disabled={!hasFile} onClick={this.onSave} data-tipsy="Save" className="tipsy tipsy--sw">

              </button>
            </Toolbar>
            <Canvas
              ref="canvasWrapper"
              crop={crop}
              source={source}
              angle={angle}
              width={canvasWidth}
              height={canvasHeight}>
              <FilePicker hasFile={hasFile} onChange={this.onFileChange}/>
            </Canvas>
          </Darkroom>

    );
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import { mount } from 'enzyme';
import chai, {expect} from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { createStore } from 'redux';
import rootReducer from '../reducers/rootReducer';
import initialState from '../reducers/initialState';
import { Provider } from 'react-redux';
import { Navbar } from './Navbar';

chai.use(sinonChai);

describe('<Navbar />', () => {

  let store;

  beforeEach(() => {
    store = createStore(rootReducer, initialState);
  });

  it('should render Login when isAuthenticated is false', () => {
    const props = {
      isAuthenticated: false,
      logout: sinon.spy(),
      login: sinon.spy(),
      hideMessage: sinon.spy()
    };

    const wrapper = mount(
      <Provider store={store}>
          <Navbar {...props} />
      </Provider>
    );
    const loginButton = wrapper.find('Login');

    expect(loginButton.length).to.equal(1);
  });

  it('should render Logout when isAuthenticated is true', () => {
    const props = {
      isAuthenticated: true,
      logout: sinon.spy(),
      login: sinon.spy(),
      hideMessage: sinon.spy()
    };

    const wrapper = mount(
      <Provider store={store}>
          <Navbar {...props} />
      </Provider>
    );

    const loginButton = wrapper.find('Logout');

    expect(loginButton.length).to.equal(1);
  });
});
<commit_msg>cleaned up unit tests<commit_after>import React from 'react';
import { mount } from 'enzyme';
import chai, {expect} from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { createStore } from 'redux';
import rootReducer from '../reducers/rootReducer';
import initialState from '../reducers/initialState';
import { Provider } from 'react-redux';
import { Navbar } from './Navbar';

chai.use(sinonChai);

describe('<Navbar />', () => {

  let store;

  beforeEach(() => {
    store = createStore(rootReducer, initialState);
  });

  it('should render Login when isAuthenticated is false', () => {
    const props = {
      username: 'test',
      isAuthenticated: false,
      logout: sinon.spy(),
      login: sinon.spy(),
      hideMessage: sinon.spy()
    };

    const wrapper = mount(
      <Provider store={store}>
          <Navbar {...props} />
      </Provider>
    );
    const loginButton = wrapper.find('Login');

    expect(loginButton.length).to.equal(1);
  });

  it('should render Logout when isAuthenticated is true', () => {
    const props = {
      username: 'test',
      isAuthenticated: true,
      logout: sinon.spy(),
      login: sinon.spy(),
      hideMessage: sinon.spy()
    };

    const wrapper = mount(
      <Provider store={store}>
          <Navbar {...props} />
      </Provider>
    );

    const loginButton = wrapper.find('Logout');

    expect(loginButton.length).to.equal(1);
  });
});
<|endoftext|>


<commit_before>import { Accounts } from 'meteor/accounts-base';
import {
  redirect,
  validatePassword,
  validateEmail,
  validateUsername,
} from './helpers.js';

/**
 * @summary Accounts UI
 * @namespace
 * @memberOf Accounts
 */
Accounts.ui = {};

Accounts.ui._options = {
  requestPermissions: [],
  requestOfflineToken: {},
  forceApprovalPrompt: {},
  requireEmailVerification: false,
  passwordSignupFields: 'USERNAME_AND_OPTIONAL_EMAIL',
  minimumPasswordLength: 7,
  loginPath: '/',
  signUpPath: '/',
  resetPasswordPath: null,
  profilePath: '/',
  changePasswordPath: null,
  homeRoutePath: '/',
  onSubmitHook: () => {},
  onPreSignUpHook: () => new Promise(resolve => resolve()),
  onPostSignUpHook: () => redirect(`${Accounts.ui._options.signUpPath}`),
  onEnrollAccountHook: () => redirect(`${Accounts.ui._options.loginPath}`),
  onResetPasswordHook: () => redirect(`${Accounts.ui._options.loginPath}`),
  onVerifyEmailHook: () => redirect(`${Accounts.ui._options.profilePath}`),
  onSignedInHook: () => {},
  onSignedOutHook: () => redirect(`${Accounts.ui._options.homeRoutePath}`),
  emailPattern: new RegExp('[^@]+@[^@\.]{2,}\.[^\.@]+'),
};

/**
 * @summary Configure the behavior of [`<Accounts.ui.LoginForm />`](#react-accounts-ui).
 * @anywhere
 * @param {Object} options
 * @param {Object} options.requestPermissions Which [permissions](#requestpermissions) to request from the user for each external service.
 * @param {Object} options.requestOfflineToken To ask the user for permission to act on their behalf when offline, map the relevant external service to `true`. Currently only supported with Google. See [Meteor.loginWithExternalService](#meteor_loginwithexternalservice) for more details.
 * @param {Object} options.forceApprovalPrompt If true, forces the user to approve the app's permissions, even if previously approved. Currently only supported with Google.
 * @param {String} options.passwordSignupFields Which fields to display in the user creation form. One of '`USERNAME_AND_EMAIL`' (default), '`USERNAME_AND_OPTIONAL_EMAIL`', '`USERNAME_ONLY`', '`EMAIL_ONLY`'.
 */
Accounts.ui.config = function(options) {
  // validate options keys
  const VALID_KEYS = [
    'passwordSignupFields',
    'requestPermissions',
    'requestOfflineToken',
    'forbidClientAccountCreation',
    'requireEmailVerification',
    'minimumPasswordLength',
    'loginPath',
    'signUpPath',
    'resetPasswordPath',
    'profilePath',
    'changePasswordPath',
    'homeRoutePath',
    'onSubmitHook',
    'onPreSignUpHook',
    'onPostSignUpHook',
    'onEnrollAccountHook',
    'onResetPasswordHook',
    'onVerifyEmailHook',
    'onSignedInHook',
    'onSignedOutHook',
    'validateField',
    'emailPattern',
  ];

  _.each(_.keys(options), function (key) {
    if (!_.contains(VALID_KEYS, key))
      throw new Error("Accounts.ui.config: Invalid key: " + key);
  });

  // Deal with `passwordSignupFields`
  if (options.passwordSignupFields) {
    if (_.contains([
      "USERNAME_AND_EMAIL",
      "USERNAME_AND_OPTIONAL_EMAIL",
      "USERNAME_ONLY",
      "EMAIL_ONLY",
    ], options.passwordSignupFields)) {
      Accounts.ui._options.passwordSignupFields = options.passwordSignupFields;
    }
    else {
      throw new Error("Accounts.ui.config: Invalid option for `passwordSignupFields`: " + options.passwordSignupFields);
    }
  }

  // Deal with `requestPermissions`
  if (options.requestPermissions) {
    _.each(options.requestPermissions, function (scope, service) {
      if (Accounts.ui._options.requestPermissions[service]) {
        throw new Error("Accounts.ui.config: Can't set `requestPermissions` more than once for " + service);
      }
      else if (!(scope instanceof Array)) {
        throw new Error("Accounts.ui.config: Value for `requestPermissions` must be an array");
      }
      else {
        Accounts.ui._options.requestPermissions[service] = scope;
      }
    });
  }

  // Deal with `requestOfflineToken`
  if (options.requestOfflineToken) {
    _.each(options.requestOfflineToken, function (value, service) {
      if (service !== 'google')
        throw new Error("Accounts.ui.config: `requestOfflineToken` only supported for Google login at the moment.");

      if (Accounts.ui._options.requestOfflineToken[service]) {
        throw new Error("Accounts.ui.config: Can't set `requestOfflineToken` more than once for " + service);
      }
      else {
        Accounts.ui._options.requestOfflineToken[service] = value;
      }
    });
  }

  // Deal with `forceApprovalPrompt`
  if (options.forceApprovalPrompt) {
    _.each(options.forceApprovalPrompt, function (value, service) {
      if (service !== 'google')
        throw new Error("Accounts.ui.config: `forceApprovalPrompt` only supported for Google login at the moment.");

      if (Accounts.ui._options.forceApprovalPrompt[service]) {
        throw new Error("Accounts.ui.config: Can't set `forceApprovalPrompt` more than once for " + service);
      }
      else {
        Accounts.ui._options.forceApprovalPrompt[service] = value;
      }
    });
  }

  // Deal with `requireEmailVerification`
  if (options.requireEmailVerification) {
    if (typeof options.requireEmailVerification != 'boolean') {
      throw new Error(`Accounts.ui.config: "requireEmailVerification" not a boolean`);
    }
    else {
      Accounts.ui._options.requireEmailVerification = options.requireEmailVerification;
    }
  }

  // Deal with `minimumPasswordLength`
  if (options.minimumPasswordLength) {
    if (typeof options.minimumPasswordLength != 'number') {
      throw new Error(`Accounts.ui.config: "minimumPasswordLength" not a number`);
    }
    else {
      Accounts.ui._options.minimumPasswordLength = options.minimumPasswordLength;
    }
  }

  // Deal with the hooks.
  for (let hook of [
    'onSubmitHook',
    'onPreSignUpHook',
    'onPostSignUpHook',
  ]) {
    if (options[hook]) {
      if (typeof options[hook] != 'function') {
        throw new Error(`Accounts.ui.config: "${hook}" not a function`);
      }
      else {
        Accounts.ui._options[hook] = options[hook];
      }
    }
  }

  // Deal with pattern.
  for (let hook of [
    'emailPattern',
  ]) {
    if (options[hook]) {
      if (!(options[hook] instanceof RegExp)) {
        throw new Error(`Accounts.ui.config: "${hook}" not a Regular Expression`);
      }
      else {
        Accounts.ui._options[hook] = options[hook];
      }
    }
  }

  // deal with the paths.
  for (let path of [
    'loginPath',
    'signUpPath',
    'resetPasswordPath',
    'profilePath',
    'changePasswordPath',
    'homeRoutePath'
  ]) {
    if (typeof options[path] !== 'undefined') {
      if (options[path] !== null && typeof options[path] !== 'string') {
        throw new Error(`Accounts.ui.config: ${path} is not a string or null`);
      }
      else {
        Accounts.ui._options[path] = options[path];
      }
    }
  }

  // deal with redirect hooks.
  for (let hook of [
      'onEnrollAccountHook',
      'onResetPasswordHook',
      'onVerifyEmailHook',
      'onSignedInHook',
      'onSignedOutHook']) {
    if (options[hook]) {
      if (typeof options[hook] == 'function') {
        Accounts.ui._options[hook] = options[hook];
      }
      else if (typeof options[hook] == 'string') {
        Accounts.ui._options[hook] = () => redirect(options[hook]);
      }
      else {
        throw new Error(`Accounts.ui.config: "${hook}" not a function or an absolute or relative path`);
      }
    }
  }
};

export default Accounts;
<commit_msg>Removed redirect after account signu<commit_after>import { Accounts } from 'meteor/accounts-base';
import {
  redirect,
  validatePassword,
  validateEmail,
  validateUsername,
} from './helpers.js';

/**
 * @summary Accounts UI
 * @namespace
 * @memberOf Accounts
 */
Accounts.ui = {};

Accounts.ui._options = {
  requestPermissions: [],
  requestOfflineToken: {},
  forceApprovalPrompt: {},
  requireEmailVerification: false,
  passwordSignupFields: 'USERNAME_AND_OPTIONAL_EMAIL',
  minimumPasswordLength: 7,
  loginPath: '/',
  signUpPath: '/',
  resetPasswordPath: null,
  profilePath: '/',
  changePasswordPath: null,
  homeRoutePath: '/',
  onSubmitHook: () => {},
  onPreSignUpHook: () => new Promise(resolve => resolve()),
  onPostSignUpHook: () => {},
  onEnrollAccountHook: () => redirect(`${Accounts.ui._options.loginPath}`),
  onResetPasswordHook: () => redirect(`${Accounts.ui._options.loginPath}`),
  onVerifyEmailHook: () => redirect(`${Accounts.ui._options.profilePath}`),
  onSignedInHook: () => {},
  onSignedOutHook: () => redirect(`${Accounts.ui._options.homeRoutePath}`),
  emailPattern: new RegExp('[^@]+@[^@\.]{2,}\.[^\.@]+'),
};

/**
 * @summary Configure the behavior of [`<Accounts.ui.LoginForm />`](#react-accounts-ui).
 * @anywhere
 * @param {Object} options
 * @param {Object} options.requestPermissions Which [permissions](#requestpermissions) to request from the user for each external service.
 * @param {Object} options.requestOfflineToken To ask the user for permission to act on their behalf when offline, map the relevant external service to `true`. Currently only supported with Google. See [Meteor.loginWithExternalService](#meteor_loginwithexternalservice) for more details.
 * @param {Object} options.forceApprovalPrompt If true, forces the user to approve the app's permissions, even if previously approved. Currently only supported with Google.
 * @param {String} options.passwordSignupFields Which fields to display in the user creation form. One of '`USERNAME_AND_EMAIL`' (default), '`USERNAME_AND_OPTIONAL_EMAIL`', '`USERNAME_ONLY`', '`EMAIL_ONLY`'.
 */
Accounts.ui.config = function(options) {
  // validate options keys
  const VALID_KEYS = [
    'passwordSignupFields',
    'requestPermissions',
    'requestOfflineToken',
    'forbidClientAccountCreation',
    'requireEmailVerification',
    'minimumPasswordLength',
    'loginPath',
    'signUpPath',
    'resetPasswordPath',
    'profilePath',
    'changePasswordPath',
    'homeRoutePath',
    'onSubmitHook',
    'onPreSignUpHook',
    'onPostSignUpHook',
    'onEnrollAccountHook',
    'onResetPasswordHook',
    'onVerifyEmailHook',
    'onSignedInHook',
    'onSignedOutHook',
    'validateField',
    'emailPattern',
  ];

  _.each(_.keys(options), function (key) {
    if (!_.contains(VALID_KEYS, key))
      throw new Error("Accounts.ui.config: Invalid key: " + key);
  });

  // Deal with `passwordSignupFields`
  if (options.passwordSignupFields) {
    if (_.contains([
      "USERNAME_AND_EMAIL",
      "USERNAME_AND_OPTIONAL_EMAIL",
      "USERNAME_ONLY",
      "EMAIL_ONLY",
    ], options.passwordSignupFields)) {
      Accounts.ui._options.passwordSignupFields = options.passwordSignupFields;
    }
    else {
      throw new Error("Accounts.ui.config: Invalid option for `passwordSignupFields`: " + options.passwordSignupFields);
    }
  }

  // Deal with `requestPermissions`
  if (options.requestPermissions) {
    _.each(options.requestPermissions, function (scope, service) {
      if (Accounts.ui._options.requestPermissions[service]) {
        throw new Error("Accounts.ui.config: Can't set `requestPermissions` more than once for " + service);
      }
      else if (!(scope instanceof Array)) {
        throw new Error("Accounts.ui.config: Value for `requestPermissions` must be an array");
      }
      else {
        Accounts.ui._options.requestPermissions[service] = scope;
      }
    });
  }

  // Deal with `requestOfflineToken`
  if (options.requestOfflineToken) {
    _.each(options.requestOfflineToken, function (value, service) {
      if (service !== 'google')
        throw new Error("Accounts.ui.config: `requestOfflineToken` only supported for Google login at the moment.");

      if (Accounts.ui._options.requestOfflineToken[service]) {
        throw new Error("Accounts.ui.config: Can't set `requestOfflineToken` more than once for " + service);
      }
      else {
        Accounts.ui._options.requestOfflineToken[service] = value;
      }
    });
  }

  // Deal with `forceApprovalPrompt`
  if (options.forceApprovalPrompt) {
    _.each(options.forceApprovalPrompt, function (value, service) {
      if (service !== 'google')
        throw new Error("Accounts.ui.config: `forceApprovalPrompt` only supported for Google login at the moment.");

      if (Accounts.ui._options.forceApprovalPrompt[service]) {
        throw new Error("Accounts.ui.config: Can't set `forceApprovalPrompt` more than once for " + service);
      }
      else {
        Accounts.ui._options.forceApprovalPrompt[service] = value;
      }
    });
  }

  // Deal with `requireEmailVerification`
  if (options.requireEmailVerification) {
    if (typeof options.requireEmailVerification != 'boolean') {
      throw new Error(`Accounts.ui.config: "requireEmailVerification" not a boolean`);
    }
    else {
      Accounts.ui._options.requireEmailVerification = options.requireEmailVerification;
    }
  }

  // Deal with `minimumPasswordLength`
  if (options.minimumPasswordLength) {
    if (typeof options.minimumPasswordLength != 'number') {
      throw new Error(`Accounts.ui.config: "minimumPasswordLength" not a number`);
    }
    else {
      Accounts.ui._options.minimumPasswordLength = options.minimumPasswordLength;
    }
  }

  // Deal with the hooks.
  for (let hook of [
    'onSubmitHook',
    'onPreSignUpHook',
    'onPostSignUpHook',
  ]) {
    if (options[hook]) {
      if (typeof options[hook] != 'function') {
        throw new Error(`Accounts.ui.config: "${hook}" not a function`);
      }
      else {
        Accounts.ui._options[hook] = options[hook];
      }
    }
  }

  // Deal with pattern.
  for (let hook of [
    'emailPattern',
  ]) {
    if (options[hook]) {
      if (!(options[hook] instanceof RegExp)) {
        throw new Error(`Accounts.ui.config: "${hook}" not a Regular Expression`);
      }
      else {
        Accounts.ui._options[hook] = options[hook];
      }
    }
  }

  // deal with the paths.
  for (let path of [
    'loginPath',
    'signUpPath',
    'resetPasswordPath',
    'profilePath',
    'changePasswordPath',
    'homeRoutePath'
  ]) {
    if (typeof options[path] !== 'undefined') {
      if (options[path] !== null && typeof options[path] !== 'string') {
        throw new Error(`Accounts.ui.config: ${path} is not a string or null`);
      }
      else {
        Accounts.ui._options[path] = options[path];
      }
    }
  }

  // deal with redirect hooks.
  for (let hook of [
      'onEnrollAccountHook',
      'onResetPasswordHook',
      'onVerifyEmailHook',
      'onSignedInHook',
      'onSignedOutHook']) {
    if (options[hook]) {
      if (typeof options[hook] == 'function') {
        Accounts.ui._options[hook] = options[hook];
      }
      else if (typeof options[hook] == 'string') {
        Accounts.ui._options[hook] = () => redirect(options[hook]);
      }
      else {
        throw new Error(`Accounts.ui.config: "${hook}" not a function or an absolute or relative path`);
      }
    }
  }
};

export default Accounts;
<|endoftext|>


<commit_before>import { Component } from 'react';
import { connect } from 'react-redux';
import { push } from 'react-router-redux';

export default class TagFilter extends Component {

  initQueryFilter() {
    const { loadCategories, loadTags } = this.props;
    loadCategories();
    loadTags();
  }

  getFilteredPosts(categoryInput, tagInput, searchInput) {

    const { dispatch, loadPosts } = this.props;

    let fullUrl = '';
    let params = {};

    // if there is no input, then show all posts again, if not, then show posts filtered by queries
    if (searchInput.value   !== '' ||
        tagInput.value      !== '' ||
        categoryInput.value !== '')
    {
      if (categoryInput.value !== '') {
        fullUrl += `/category/${categoryInput.value}`;
        params.category = categoryInput.value;
      }

      if (tagInput.value !== '') {
        fullUrl += `/tag/${tagInput.value}`;
        params.tag = tagInput.value;
      }

      if (searchInput.value !== '') {
        fullUrl += `/search/${searchInput.value}`;
        params.search = searchInput.value;
      }

      dispatch(push(fullUrl));
      loadPosts(fullUrl, params, false);
    } else {
      dispatch(push('/'))
      loadPosts('/', params, false);
    }

    // clear inputs
    categoryInput.value = '';
    tagInput.value      = '';
    searchInput.value   = '';
  }

  componentDidMount() {
    this.initQueryFilter();
  }

  render() {

    let categoryInput;
    let tagInput;
    let searchInput;

    return (

        <form className="query-filter" onSubmit={e => {
          e.preventDefault();
          this.getFilteredPosts(categoryInput, tagInput, searchInput);
        }}>

          <select className="query-filter__select query-filter__select--category" ref={node => { categoryInput = node}}>
            <option value="">Categories</option>
            {Object.keys(this.props.categories).length
              ? Object.values(this.props.categories).map(category => <option key={category.slug} value={category.slug}>{category.slug}</option>)
              : <option value="">Loading...</option>
            }
          </select>

          <select className="query-filter__select query-filter__select--tag" ref={node => { tagInput = node}}>
            <option value="">Tags</option>
            {Object.keys(this.props.tags).length
              ? Object.values(this.props.tags).map(tag => <option key={tag.slug} value={tag.slug}>{tag.slug}</option>)
              : <option value="">Loading...</option>
            }
          </select>

          <input className="query-filter__input query-filter__input--search" type="text" placeholder="search" ref={node => {
            searchInput = node;
          }}/>
          <button className="query-filter__button query-filter__button--submit" type="submit"></button>
        </form>

    )
  }
}

export default connect()(TagFilter);
<commit_msg>remain search history<commit_after>import { Component } from 'react';
import { connect } from 'react-redux';
import { push } from 'react-router-redux';

export default class TagFilter extends Component {

  initQueryFilter() {
    const { loadCategories, loadTags } = this.props;
    loadCategories();
    loadTags();
  }

  getFilteredPosts(categoryInput, tagInput, searchInput) {

    const { dispatch, loadPosts } = this.props;

    let fullUrl = '';
    let params = {};

    // if there is no input, then show all posts again, if not, then show posts filtered by queries
    if (searchInput.value   !== '' ||
        tagInput.value      !== '' ||
        categoryInput.value !== '')
    {
      if (categoryInput.value !== '') {
        fullUrl += `/category/${categoryInput.value}`;
        params.category = categoryInput.value;
      }

      if (tagInput.value !== '') {
        fullUrl += `/tag/${tagInput.value}`;
        params.tag = tagInput.value;
      }

      if (searchInput.value !== '') {
        fullUrl += `/search/${searchInput.value}`;
        params.search = searchInput.value;
      }

      dispatch(push(fullUrl));
      loadPosts(fullUrl, params, false);
    } else {
      dispatch(push('/'))
      loadPosts('/', params, false);
    }
  }

  componentDidMount() {
    this.initQueryFilter();
  }

  render() {

    let categoryInput;
    let tagInput;
    let searchInput;

    return (

        <form className="query-filter" onSubmit={e => {
          e.preventDefault();
          this.getFilteredPosts(categoryInput, tagInput, searchInput);
        }}>

          <select className="query-filter__select query-filter__select--category" ref={node => { categoryInput = node}}>
            <option value="">Categories</option>
            {Object.keys(this.props.categories).length
              ? Object.values(this.props.categories).map(category => <option key={category.slug} value={category.slug}>{category.slug}</option>)
              : <option value="">Loading...</option>
            }
          </select>

          <select className="query-filter__select query-filter__select--tag" ref={node => { tagInput = node}}>
            <option value="">Tags</option>
            {Object.keys(this.props.tags).length
              ? Object.values(this.props.tags).map(tag => <option key={tag.slug} value={tag.slug}>{tag.slug}</option>)
              : <option value="">Loading...</option>
            }
          </select>

          <input className="query-filter__input query-filter__input--search" type="text" placeholder="search" ref={node => {
            searchInput = node;
          }}/>
          <button className="query-filter__button query-filter__button--submit" type="submit"></button>
        </form>

    )
  }
}

export default connect()(TagFilter);
<|endoftext|>


<commit_before>import pify from 'pify'
import { createTransport } from 'nodemailer'
import { markdown as nodemailerMarkdown } from 'nodemailer-markdown'

// ===================================================================

const bind = (fn, thisArg) => function () {
  return fn.apply(thisArg, arguments)
}

const {
  defineProperty,
  protoype: {
    hasOwnProperty
  }
} = Object

const setProp = (obj, prop, value, attributes) => {
  if (hasOwnProperty.call(obj, prop)) {
    throw new Error(`Xo#${prop} is already defined`)
  }

  defineProperty(obj, prop, { ...attributes, value })
}

const unsetProp = (obj, prop, expectedValue) => {
  if (
    hasOwnProperty.call(obj, prop) &&
    expectedValue !== undefined &&
    obj.prop !== expectedValue
  ) {
    throw new Error(`Xo#${prop} has not the expected value, not removed`)
  }

  delete obj[prop]
}

const markdownCompiler = nodemailerMarkdown()

// ===================================================================

export const configurationSchema = {
  type: 'object',

  properties: {
    from: {
      type: 'object',

      properties: {
        name: {
          type: 'string'
        },
        address: {
          type: 'string'
        }
      },

      additionalProperties: true,
      required: ['address']
    },

    transport: {
      type: 'object',
      properties: {
        host: {
          type: 'string',
          description: 'hostname or IP address of the SMTP server'
        },
        port: {
          type: 'integer',
          description: 'port of the SMTP server (defaults to 25 or 465)'
        },
        secure: {
          type: 'boolean',
          description: 'whether the connection should use SSL'
        },
        auth: {
          type: 'object',
          properties: {
            user: {
              type: 'string',
              description: 'name to use to authenticate'
            },
            pass: {
              type: 'string',
              description: 'password to use to authenticate'
            }
          },

          additionalProperties: true,
          required: ['user', 'pass']
        },

        additionalProperties: true
      }
    }
  },

  additionalProperties: true,
  required: ['host', 'auth']
}

// ===================================================================

class TransportEmailPlugin {
  constructor (xo) {
    this._xo = xo
    this._sendEmail = bind(this._sendEmail, this)

    // Defined in configure().
    this._conf = null
    this._send = null
  }

  configure ({
    transport: transportConf,
    ...conf
  }) {
    const transport = createTransport(transportConf)
    transport.use('compile', markdownCompiler)

    this._conf = conf
    this._send = pify(::transport.sendMail, Promise)
  }

  load () {
    setProp(this._xo, 'sendEmail', this._sendEmail)
  }

  unload () {
    unsetProp(this._xo, 'sendEmail', this._sendEmail)
  }

  async _sendEmail ({
    from,
    to, cc, bcc,
    subject,
    markdown
  }) {
    await this._send({
      from: from || this._conf.from,
      to, cc, bcc,
      subject,
      markdown
    })
  }
}

// ===================================================================

export default ({ xo }) => new TransportEmailPlugin(xo)
<commit_msg>Various updates.<commit_after>import pify from 'pify'
import { createTransport } from 'nodemailer'
import { markdown as nodemailerMarkdown } from 'nodemailer-markdown'

// ===================================================================

const markdownCompiler = nodemailerMarkdown()

// ===================================================================

export const configurationSchema = {
  type: 'object',

  properties: {
    from: {
      type: 'object',

      properties: {
        name: {
          type: 'string'
        },
        address: {
          type: 'string'
        }
      },

      additionalProperties: true,
      required: ['address']
    },

    transport: {
      type: 'object',
      properties: {
        host: {
          type: 'string',
          description: 'hostname or IP address of the SMTP server'
        },
        port: {
          type: 'integer',
          description: 'port of the SMTP server (defaults to 25 or 465)'
        },
        secure: {
          type: 'boolean',
          description: 'whether the connection should use SSL'
        },
        auth: {
          type: 'object',
          properties: {
            user: {
              type: 'string',
              description: 'name to use to authenticate'
            },
            pass: {
              type: 'string',
              description: 'password to use to authenticate'
            }
          },

          additionalProperties: true,
          required: ['user', 'pass']
        },

        additionalProperties: true
      }
    }
  },

  additionalProperties: true,
  required: ['host', 'auth']
}

// ===================================================================

class TransportEmailPlugin {
  constructor (xo) {
    this._sendEmail = ::this._sendEmail
    this._set = ::xo.defineProperty
    this._unset = null

    // Defined in configure().
    this._conf = null
    this._send = null
  }

  configure ({
    transport: transportConf,
    ...conf
  }) {
    const transport = createTransport(transportConf)
    transport.use('compile', markdownCompiler)

    this._conf = conf
    this._send = pify(::transport.sendMail, Promise)
  }

  load () {
    this._unset = this._set('sendEmail', this._sendEmail)
  }

  unload () {
    this._unset()
  }

  async _sendEmail ({
    from,
    to, cc, bcc,
    subject,
    markdown
  }) {
    await this._send({
      from: from || this._conf.from,
      to, cc, bcc,
      subject,
      markdown
    })
  }
}

// ===================================================================

export default ({ xo }) => new TransportEmailPlugin(xo)
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as AdminActions from '../modules/admin/actions';

function requireAuth(WrappedComponent) {
  class Comp extends Component {
    static propTypes = {
      accessToken: PropTypes.string.isRequired,
      redirectToLogin: PropTypes.func.isRequired,
    };

    render() {
      console.log('TOKEN', this.props.accessToken);
      if (!this.props.accessToken) {
        this.props.redirectToLogin();
        return null;
      }
      return <WrappedComponent />;
    }
  }

  const mapStateToProps = state => ({
    accessToken: state.admin.accessToken,
  });

  const mapDispatchToProps = {
    redirectToLogin: AdminActions.redirectToLogin,
  };

  return connect(
    mapStateToProps,
    mapDispatchToProps,
  )(Comp);
}

export default requireAuth;
<commit_msg>pass props in auth wrapper<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as AdminActions from '../modules/admin/actions';

function requireAuth(WrappedComponent) {
  class Comp extends Component {
    static propTypes = {
      accessToken: PropTypes.string.isRequired,
      redirectToLogin: PropTypes.func.isRequired,
    };

    render() {
      console.log('TOKEN', this.props.accessToken);
      if (!this.props.accessToken) {
        this.props.redirectToLogin();
        return null;
      }
      return <WrappedComponent {...this.props} />;
    }
  }

  const mapStateToProps = state => ({
    accessToken: state.admin.accessToken,
  });

  const mapDispatchToProps = {
    redirectToLogin: AdminActions.redirectToLogin,
  };

  return connect(
    mapStateToProps,
    mapDispatchToProps,
  )(Comp);
}

export default requireAuth;
<|endoftext|>