<commit_before>describe('modules.Filters', function() {

  var clone = function(obj) {
    var copy = {};
    for (var i in obj) {
      copy[i] = obj[i];
    }
    return copy;
  }

  //===================================================
  // Filters
  //===================================================
  describe('cdb.admin.models.Filters', function() {

    var filters, table;
    beforeEach(function() {
      table = TestUtil.createTable('test');
      filters = new cdb.admin.models.Filters(null, {
        table: table
      });
    });

    it("should generate correct model for column type", function() {
      filters.reset([{
        'column_type': 'number',
        'column': 'test'
      }, {
        'column_type': 'string',
        'column': 'teststr'
      }]);

      expect(filters.models[0] instanceof cdb.admin.models.Filter).toEqual(true);
      expect(filters.models[1] instanceof cdb.admin.models.FilterDiscrete).toEqual(true);

    });
  });

  //===================================================
  // Filter
  //===================================================
  describe('cdb.admin.models.Filter (numeric)', function() {

    var model, table, hist, bounds;

    beforeEach(function() {
      hist = [];
      bounds = {}

      bounds.upper = 10;
      bounds.lower = 3;
      bounds.bucket_size = 1
      for(var i = 0; i < 10; ++i) {
        hist.push(i);
      }
      table = TestUtil.createTable('test');

      spyOn(table.data(), 'histogram').and.callFake(function(a, b, callback){
        callback(hist, clone(bounds));
      })

      model = new cdb.admin.models.Filter({
        table: table,
        column_type: "number",
        column: 'c'
      });

    });

    it("should have a table", function() {
      expect(model.table).toEqual(table);
      expect(model.get('table')).toEqual(undefined);
    });

    it("should set bounds", function() {
      expect(model.get('lower')).toEqual(3);
      expect(model.get('upper')).toEqual(10);
    });

    it("should return the condition", function() {
      expect(model.getSQLCondition()).toEqual(" (c >= 3 AND c <= 10) ");
    });

    it("should fecth data when the table is saved", function() {
      spyOn(model, '_fetchHist');
      table.trigger('data:saved');
      expect(model._fetchHist).toHaveBeenCalled();
    });

    it("should adjust the bounds", function() {
      model.set({
        bounds: {
          lower: 2,
          upper: 10
        },
        lower: 3,
        upper: 9
      })
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(3);
      expect(model.get('upper')).toEqual(9);

      // Bounds have been expanded on the lower and upper side
      bounds.lower = 1;
      bounds.upper = 11;
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(1);
      expect(model.get('upper')).toEqual(11);
    });

    it("should raise an error when histogram can't be generated", function() {
      spy = sinon.spy()
      model.bind('error', spy);
      table.data().histogram.and.callFake(function(a, b, callback){
        callback(null, null);
      });
      table.trigger('data:saved');
      expect(spy.called).toEqual(true);
    });

    it("should serialize to json", function() {
      expect(model.toJSON()).toEqual({
        column: 'c',
        upper: 10,
        tz: undefined,
        lower: 3,
        column_type: 'number'
      });
    });

  });

  describe('cdb.admin.models.Filter (date)', function() {

    var model, table, hist, bounds;

    beforeEach(function() {
      hist = [];
      bounds = {}

      bounds.lower = 360000000; // Mon Jan 31 1994 08:06:40 GMT+0100 (CET)
      bounds.upper = 760000000; // Fri May 29 1981 18:00:00 GMT+0200 (CEST)

      bounds.bucket_size = 1

      for (var i = 0; i < 10; ++i) {
        hist.push(bounds.upper + i*10000);
      };

      table = TestUtil.createTable('test');

      spyOn(table.data(), 'date_histogram').and.callFake(function(a, b, callback){
        callback(hist, clone(bounds));
      })

      model = new cdb.admin.models.Filter({
        table: table,
        column_type: "date",
        column: 'c',
        bounds: bounds,
        lower: bounds.lower * 1000,
        upper: bounds.upper * 1000,
        lower_limit: bounds.lower * 1000,
        upper_limit: bounds.upper * 1000,
        tz: "1981-05-29T18:00:00+0000"
      });

    });

    it("should have a table", function() {
      expect(model.table).toEqual(table);
      expect(model.get('table')).toEqual(undefined);
    });

    it("should return the condition", function() {

      var lower = moment(360000000000).format("YYYY-MM-DDTHH:mm:ssZ").toString();
      var upper = moment(760000000000).format("YYYY-MM-DDTHH:mm:ssZ").toString();
      // Tests the selection of the full range
      expect(model.getSQLCondition()).toEqual(" (c >= ('"+ lower+ "') AND c <= ('"+ upper +"')) ");

      // Tests the selection of a small range
      upper = moment(bounds.upper - 61*1000).format("YYYY-MM-DDTHH:mm:ssZ").toString();
      model.set("upper_limit", bounds.upper - 61*1000);
      expect(model.getSQLCondition()).toEqual(" (c >= ('"+ lower+ "') AND c <= ('"+ upper +"')) ");
    });

    it("should transform a timestamp to a date", function() {
      var timestamp = 361670400000;
      var date = model._getDateFromTimestamp(timestamp);

      expect(date.toString()).toEqual(new Date(timestamp).toString());
    });

    it("should adjust the bounds", function() {
      model.set({
        bounds: {
          lower: 360000000,
          upper: 760000000
        },
        lower: 400000000000,
        upper: 700000000000
      })
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(400000000000);
      expect(model.get('upper')).toEqual(700000000000);

      // Bounds have been expanded on the lower and upper side
      bounds.lower = 300000000;
      bounds.upper = 800000000;
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(300000000000);
      expect(model.get('upper')).toEqual(800000000000);
    });

  });

  describe('FilterDiscrete (boolean)', function() {
    var model_true, model, model_true_null, model_true_false_null, table, hist, stub;

    beforeEach(function() {

      // Creates a stub table with the specified rows and returns the associated model
      function generateModel(rows) {

        hist = { };

        hist.rows = rows;

        table = TestUtil.createTable('test');
        stub  = sinon.stub(table.data(), 'discreteHistogram')

        stub.yields(hist);

        return new cdb.admin.models.FilterDiscrete({
          table: table,
          column: 'c',
          column_type: 'boolean'
        });
      }

      // Model for true and false values
      var rows = [
        { bucket: false, value: 100 },
        { bucket: true, value: 200 }
      ];

      model = generateModel(rows);

      // Model for true values
      rows = [
        { bucket: true, value: 200 }
      ];

      model_true = generateModel(rows);

      // Model for true and null values
      rows = [
        { bucket: null, value: 100 },
        { bucket: true, value: 200 }
      ];

      model_true_null = generateModel(rows);

      // Model for true, false and null values
      rows = [
        { bucket: null, value: 100 },
        { bucket: true, value: 200 },
        { bucket: false, value: 20 }
      ];

      model_true_false_null = generateModel(rows);

    });

    it("should return a valid SQL in boolean mode for true and false values", function() {
      model.set({ list_view : true });
      var sql = model.getSQLCondition();
      expect(sql).toEqual("c IN (false,true) ");
    });

    it("should return a valid SQL in boolean mode for true values", function() {
      model_true.set({ list_view : true });
      var sql = model_true.getSQLCondition();
      expect(sql).toEqual("c IN (true) ");
    });

    it("should return a valid SQL in boolean mode for true and null values ", function() {
      model_true_null.set({ list_view : true });
      var sql = model_true_null.getSQLCondition();
      expect(sql).toEqual("c IN (true) OR c IS NULL ");
    });

    it("should return a valid SQL in boolean mode for true, false and null values ", function() {
      model_true_false_null.set({ list_view : true });
      var sql = model_true_false_null.getSQLCondition();
      expect(sql).toEqual("c IN (true,false) OR c IS NULL ");
    });

  });

  describe('FilterDiscrete (null)', function() {
    var model, table, hist, stub;

    beforeEach(function() {

      hist = { };

      hist.rows = [
        { bucket: 'test1' },
        { bucket: null },
        { bucket: 'test3' }
      ];

      table = TestUtil.createTable('test');
      stub  = sinon.stub(table.data(), 'discreteHistogram')

      stub.yields(hist);

      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'd',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: null,
          selected: true
        }, {
          bucket: 'test3',
          selected: false
        }]
      });

    });

    it("should handle the null buckets", function() {
      var sql = model.getSQLCondition();
      expect(sql).toEqual("d IN ('test1','null') OR d IS NULL ");
    });

  });

  describe('FilterDiscrete', function() {
    var model, model2, table, hist, stub;

    beforeEach(function() {

      hist = { };

      hist.rows = [
        { bucket: 'test1' },
        { bucket: 'test2' },
        { bucket: 'test3' }
      ];

      table = TestUtil.createTable('test');
      stub  = sinon.stub(table.data(), 'discreteHistogram')

      stub.yields(hist);

      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: 'test2',
          selected: true
        }, {
          bucket: 'test3',
          selected: false
        }]
      });

      model2 = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: 'test2',
          selected: true
        }, {
          bucket: 'test3',
          selected: true
        }]
      });

    });

    it("should return a 'partial' SQL condition when some of the items are selected", function() {
      var sql = model.getSQLCondition();
      expect(sql).toEqual("c IN ('test1','test2') ");
    });

    it("should return a full SQL condition when all the items are selected", function() {
      sql = model2.getSQLCondition();
      expect(sql).toEqual(" (true) ");

    });

    it("should return SQL with free_text", function() {
      model.set({ free_text: "Valladolid", list_view : false });

      var sql = model.getSQLCondition();
      expect(model.get("column")).toEqual("c");
      expect(sql).toEqual("c ILIKE '%Valladolid%' ");
    });

    it("shouldn't return a free_text query in list_view mode", function() {
      model.set({ free_text: "Valladolid", list_view : true });

      var sql = model.getSQLCondition();
      expect(model.get("column")).toEqual("c");
      expect(sql).toEqual("c IN ('test1','test2') ");
    });

    it("should return a valid SQL when free_text is empty", function() {
      model.set({ free_text: "", list_view : false });
      var sql = model.getSQLCondition();
      expect(sql).toEqual(" (true) ");
    });

    it("should return sql condition with selected only", function() {
      model.items.models[0].set('selected', false);
      var sql = model.getSQLCondition();
      expect(sql).toEqual("c IN ('test2') ");
    });

    it("should raise an error when histogram can't be generated", function() {
      spy = sinon.spy()
      model.bind('error', spy);
      stub.yields(null);
      table.trigger('data:saved');
      expect(spy.called).toEqual(true);
    });

    it("should keep selected values", function() {
      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test',
          selected: false
        }]
      });

      hist = {};
      hist.rows = [
        {bucket: 'test'},
      ];

      stub.yields(hist);
      table.trigger('data:saved');
      expect(model.items.where({ bucket: 'test'})[0].get('selected')).toEqual(true)

    });

    it("should serialize to json", function() {
      expect(model.toJSON()).toEqual({
        reached_limit: undefined,
        column: 'c',
        items: [
          { bucket: 'test1', selected: true },
          { bucket: 'test2', selected: true },
          { bucket: 'test3', selected: false }
        ],
        free_text : undefined,
        column_type : undefined,
        list_view : true
      });
    });

  });

  describe('FilterDiscrete: null', function() {
    var model, table, hist, stub;

    beforeEach(function() {

      hist = { };

      hist.rows = [
        { bucket: 'test1'},
        { bucket: 'test2'},
        { bucket: 'test3'},
        { bucket: null }
      ];

      table = TestUtil.createTable('test');
      stub  = sinon.stub(table.data(), 'discreteHistogram')

      stub.yields(hist);

      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: 'test2',
          selected: true
        }, {
          bucket: 'test3',
          selected: false
        }, {
          bucket: null,
          selected: false
        }]
      });

    });

    it("shouldn't select the NULL value in the query it'is unchecked", function() {
      var sql = model.getSQLCondition();
      expect(model.get("column")).toEqual("c");
      expect(sql).toEqual("c IN ('test1','test2') AND c IS NOT NULL ");
    });

  });

});

<commit_msg>Use _.clone instead of reinventing the wheel<commit_after>describe('modules.Filters', function() {

  //===================================================
  // Filters
  //===================================================
  describe('cdb.admin.models.Filters', function() {

    var filters, table;
    beforeEach(function() {
      table = TestUtil.createTable('test');
      filters = new cdb.admin.models.Filters(null, {
        table: table
      });
    });

    it("should generate correct model for column type", function() {
      filters.reset([{
        'column_type': 'number',
        'column': 'test'
      }, {
        'column_type': 'string',
        'column': 'teststr'
      }]);

      expect(filters.models[0] instanceof cdb.admin.models.Filter).toEqual(true);
      expect(filters.models[1] instanceof cdb.admin.models.FilterDiscrete).toEqual(true);

    });
  });

  //===================================================
  // Filter
  //===================================================
  describe('cdb.admin.models.Filter (numeric)', function() {

    var model, table, hist, bounds;

    beforeEach(function() {
      hist = [];
      bounds = {}

      bounds.upper = 10;
      bounds.lower = 3;
      bounds.bucket_size = 1
      for(var i = 0; i < 10; ++i) {
        hist.push(i);
      }
      table = TestUtil.createTable('test');

      spyOn(table.data(), 'histogram').and.callFake(function(a, b, callback){
        callback(hist, _.clone(bounds));
      })

      model = new cdb.admin.models.Filter({
        table: table,
        column_type: "number",
        column: 'c'
      });

    });

    it("should have a table", function() {
      expect(model.table).toEqual(table);
      expect(model.get('table')).toEqual(undefined);
    });

    it("should set bounds", function() {
      expect(model.get('lower')).toEqual(3);
      expect(model.get('upper')).toEqual(10);
    });

    it("should return the condition", function() {
      expect(model.getSQLCondition()).toEqual(" (c >= 3 AND c <= 10) ");
    });

    it("should fecth data when the table is saved", function() {
      spyOn(model, '_fetchHist');
      table.trigger('data:saved');
      expect(model._fetchHist).toHaveBeenCalled();
    });

    it("should adjust the bounds", function() {
      model.set({
        bounds: {
          lower: 2,
          upper: 10
        },
        lower: 3,
        upper: 9
      })
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(3);
      expect(model.get('upper')).toEqual(9);

      // Bounds have been expanded on the lower and upper side
      bounds.lower = 1;
      bounds.upper = 11;
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(1);
      expect(model.get('upper')).toEqual(11);
    });

    it("should raise an error when histogram can't be generated", function() {
      spy = sinon.spy()
      model.bind('error', spy);
      table.data().histogram.and.callFake(function(a, b, callback){
        callback(null, null);
      });
      table.trigger('data:saved');
      expect(spy.called).toEqual(true);
    });

    it("should serialize to json", function() {
      expect(model.toJSON()).toEqual({
        column: 'c',
        upper: 10,
        tz: undefined,
        lower: 3,
        column_type: 'number'
      });
    });

  });

  describe('cdb.admin.models.Filter (date)', function() {

    var model, table, hist, bounds;

    beforeEach(function() {
      hist = [];
      bounds = {}

      bounds.lower = 360000000; // Mon Jan 31 1994 08:06:40 GMT+0100 (CET)
      bounds.upper = 760000000; // Fri May 29 1981 18:00:00 GMT+0200 (CEST)

      bounds.bucket_size = 1

      for (var i = 0; i < 10; ++i) {
        hist.push(bounds.upper + i*10000);
      };

      table = TestUtil.createTable('test');

      spyOn(table.data(), 'date_histogram').and.callFake(function(a, b, callback){
        callback(hist, _.clone(bounds));
      })

      model = new cdb.admin.models.Filter({
        table: table,
        column_type: "date",
        column: 'c',
        bounds: bounds,
        lower: bounds.lower * 1000,
        upper: bounds.upper * 1000,
        lower_limit: bounds.lower * 1000,
        upper_limit: bounds.upper * 1000,
        tz: "1981-05-29T18:00:00+0000"
      });

    });

    it("should have a table", function() {
      expect(model.table).toEqual(table);
      expect(model.get('table')).toEqual(undefined);
    });

    it("should return the condition", function() {

      var lower = moment(360000000000).format("YYYY-MM-DDTHH:mm:ssZ").toString();
      var upper = moment(760000000000).format("YYYY-MM-DDTHH:mm:ssZ").toString();
      // Tests the selection of the full range
      expect(model.getSQLCondition()).toEqual(" (c >= ('"+ lower+ "') AND c <= ('"+ upper +"')) ");

      // Tests the selection of a small range
      upper = moment(bounds.upper - 61*1000).format("YYYY-MM-DDTHH:mm:ssZ").toString();
      model.set("upper_limit", bounds.upper - 61*1000);
      expect(model.getSQLCondition()).toEqual(" (c >= ('"+ lower+ "') AND c <= ('"+ upper +"')) ");
    });

    it("should transform a timestamp to a date", function() {
      var timestamp = 361670400000;
      var date = model._getDateFromTimestamp(timestamp);

      expect(date.toString()).toEqual(new Date(timestamp).toString());
    });

    it("should adjust the bounds", function() {
      model.set({
        bounds: {
          lower: 360000000,
          upper: 760000000
        },
        lower: 400000000000,
        upper: 700000000000
      })
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(400000000000);
      expect(model.get('upper')).toEqual(700000000000);

      // Bounds have been expanded on the lower and upper side
      bounds.lower = 300000000;
      bounds.upper = 800000000;
      table.trigger('data:saved');
      expect(model.get('lower')).toEqual(300000000000);
      expect(model.get('upper')).toEqual(800000000000);
    });

  });

  describe('FilterDiscrete (boolean)', function() {
    var model_true, model, model_true_null, model_true_false_null, table, hist, stub;

    beforeEach(function() {

      // Creates a stub table with the specified rows and returns the associated model
      function generateModel(rows) {

        hist = { };

        hist.rows = rows;

        table = TestUtil.createTable('test');
        stub  = sinon.stub(table.data(), 'discreteHistogram')

        stub.yields(hist);

        return new cdb.admin.models.FilterDiscrete({
          table: table,
          column: 'c',
          column_type: 'boolean'
        });
      }

      // Model for true and false values
      var rows = [
        { bucket: false, value: 100 },
        { bucket: true, value: 200 }
      ];

      model = generateModel(rows);

      // Model for true values
      rows = [
        { bucket: true, value: 200 }
      ];

      model_true = generateModel(rows);

      // Model for true and null values
      rows = [
        { bucket: null, value: 100 },
        { bucket: true, value: 200 }
      ];

      model_true_null = generateModel(rows);

      // Model for true, false and null values
      rows = [
        { bucket: null, value: 100 },
        { bucket: true, value: 200 },
        { bucket: false, value: 20 }
      ];

      model_true_false_null = generateModel(rows);

    });

    it("should return a valid SQL in boolean mode for true and false values", function() {
      model.set({ list_view : true });
      var sql = model.getSQLCondition();
      expect(sql).toEqual("c IN (false,true) ");
    });

    it("should return a valid SQL in boolean mode for true values", function() {
      model_true.set({ list_view : true });
      var sql = model_true.getSQLCondition();
      expect(sql).toEqual("c IN (true) ");
    });

    it("should return a valid SQL in boolean mode for true and null values ", function() {
      model_true_null.set({ list_view : true });
      var sql = model_true_null.getSQLCondition();
      expect(sql).toEqual("c IN (true) OR c IS NULL ");
    });

    it("should return a valid SQL in boolean mode for true, false and null values ", function() {
      model_true_false_null.set({ list_view : true });
      var sql = model_true_false_null.getSQLCondition();
      expect(sql).toEqual("c IN (true,false) OR c IS NULL ");
    });

  });

  describe('FilterDiscrete (null)', function() {
    var model, table, hist, stub;

    beforeEach(function() {

      hist = { };

      hist.rows = [
        { bucket: 'test1' },
        { bucket: null },
        { bucket: 'test3' }
      ];

      table = TestUtil.createTable('test');
      stub  = sinon.stub(table.data(), 'discreteHistogram')

      stub.yields(hist);

      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'd',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: null,
          selected: true
        }, {
          bucket: 'test3',
          selected: false
        }]
      });

    });

    it("should handle the null buckets", function() {
      var sql = model.getSQLCondition();
      expect(sql).toEqual("d IN ('test1','null') OR d IS NULL ");
    });

  });

  describe('FilterDiscrete', function() {
    var model, model2, table, hist, stub;

    beforeEach(function() {

      hist = { };

      hist.rows = [
        { bucket: 'test1' },
        { bucket: 'test2' },
        { bucket: 'test3' }
      ];

      table = TestUtil.createTable('test');
      stub  = sinon.stub(table.data(), 'discreteHistogram')

      stub.yields(hist);

      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: 'test2',
          selected: true
        }, {
          bucket: 'test3',
          selected: false
        }]
      });

      model2 = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: 'test2',
          selected: true
        }, {
          bucket: 'test3',
          selected: true
        }]
      });

    });

    it("should return a 'partial' SQL condition when some of the items are selected", function() {
      var sql = model.getSQLCondition();
      expect(sql).toEqual("c IN ('test1','test2') ");
    });

    it("should return a full SQL condition when all the items are selected", function() {
      sql = model2.getSQLCondition();
      expect(sql).toEqual(" (true) ");

    });

    it("should return SQL with free_text", function() {
      model.set({ free_text: "Valladolid", list_view : false });

      var sql = model.getSQLCondition();
      expect(model.get("column")).toEqual("c");
      expect(sql).toEqual("c ILIKE '%Valladolid%' ");
    });

    it("shouldn't return a free_text query in list_view mode", function() {
      model.set({ free_text: "Valladolid", list_view : true });

      var sql = model.getSQLCondition();
      expect(model.get("column")).toEqual("c");
      expect(sql).toEqual("c IN ('test1','test2') ");
    });

    it("should return a valid SQL when free_text is empty", function() {
      model.set({ free_text: "", list_view : false });
      var sql = model.getSQLCondition();
      expect(sql).toEqual(" (true) ");
    });

    it("should return sql condition with selected only", function() {
      model.items.models[0].set('selected', false);
      var sql = model.getSQLCondition();
      expect(sql).toEqual("c IN ('test2') ");
    });

    it("should raise an error when histogram can't be generated", function() {
      spy = sinon.spy()
      model.bind('error', spy);
      stub.yields(null);
      table.trigger('data:saved');
      expect(spy.called).toEqual(true);
    });

    it("should keep selected values", function() {
      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test',
          selected: false
        }]
      });

      hist = {};
      hist.rows = [
        {bucket: 'test'},
      ];

      stub.yields(hist);
      table.trigger('data:saved');
      expect(model.items.where({ bucket: 'test'})[0].get('selected')).toEqual(true)

    });

    it("should serialize to json", function() {
      expect(model.toJSON()).toEqual({
        reached_limit: undefined,
        column: 'c',
        items: [
          { bucket: 'test1', selected: true },
          { bucket: 'test2', selected: true },
          { bucket: 'test3', selected: false }
        ],
        free_text : undefined,
        column_type : undefined,
        list_view : true
      });
    });

  });

  describe('FilterDiscrete: null', function() {
    var model, table, hist, stub;

    beforeEach(function() {

      hist = { };

      hist.rows = [
        { bucket: 'test1'},
        { bucket: 'test2'},
        { bucket: 'test3'},
        { bucket: null }
      ];

      table = TestUtil.createTable('test');
      stub  = sinon.stub(table.data(), 'discreteHistogram')

      stub.yields(hist);

      model = new cdb.admin.models.FilterDiscrete({
        table: table,
        column: 'c',
        items: [{
          bucket: 'test1',
          selected: true
        }, {
          bucket: 'test2',
          selected: true
        }, {
          bucket: 'test3',
          selected: false
        }, {
          bucket: null,
          selected: false
        }]
      });

    });

    it("shouldn't select the NULL value in the query it'is unchecked", function() {
      var sql = model.getSQLCondition();
      expect(model.get("column")).toEqual("c");
      expect(sql).toEqual("c IN ('test1','test2') AND c IS NOT NULL ");
    });

  });

});

<|endoftext|>


<commit_before>/**
 * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
 * Version 0.4.9 - http://noelboss.github.io/featherlight/
 *
 * Copyright 2014, Noël Raoul Bossart (http://www.noelboss.com)
 * MIT Licensed.
**/
(function($) {
	"use strict";

	if('undefined' === typeof $) {
		if('console' in window){ window.console.info('Too much lightness, Featherlight needs jQuery.');
			if(!('featherlight' in $)){	window.console.info('Load the featherlight plugin before the gallery plugin'); }
		}
		return;
	}

	var isTouchAware = 'ontouchstart' in document.documentElement,
		jQueryConstructor = $.event && $.event.special.swipeleft && $,
		hammerConstructor = ('Hammer' in window) && function($el){ new window.Hammer(el[0]); },
		swipeAwareConstructor = isTouchAware && (jQueryConstructor || hammerConstructor);

	/* extend jQuery with selector featherlight method $(elm).featherlight(config, elm); */
	$.fn.featherlightGallery = function(config) {
		var flg = {
				gallery: {
					$gallery: this,
					$current: null         /* Current source */
				}
			},
			customAfterOpen = config && config.afterOpen,
			customAfterClose = config && config.afterClose,
			overrideCallbacks = {				/* provide an afterOpen function */
				afterClose: function(event){
					var self = this;
					self.$instance.off('next.'+self.namespace+' previous.'+self.namespace);
					if (swipeAwareConstructor) {
						self.$instance.off('swipeleft');
						self.$instance.off('swiperight');
					}
					if('function' === typeof customAfterClose) {
						customAfterClose.call(this, event);
					}
				},
				afterOpen: function(event){
					var self = this,
						config = this.gallery,
						$img = self.$instance.find('img');

					config.$current = $(event.currentTarget);

					self.$instance.on('next.'+self.namespace+' previous.'+self.namespace, function(event){
							var offset = event.type === 'next' ? +1 : -1;
							config.$current = config.$gallery.eq((config.$gallery.length + config.$gallery.index(config.$current) + offset) % config.$gallery.length);
							config.beforeImage.call(self, event);
							$.when(
								$.featherlight.contentFilters.image.process(config.$current.attr('href')),
								$img.fadeTo(config.fadeOut,0.2)
							).done(function($i) {
									$img[0].src = $i[0].src;
									config.afterImage.call(self, event);
									$img.fadeTo(config.fadeIn,1);
								});
							});

					if (swipeAwareConstructor) {
						swipeAwareConstructor(self.$instance)
							.on('swipeleft', function()  { self.$instance.trigger('next'); })
							.on('swiperight', function() { self.$instance.trigger('previous'); });
					} else {
						var createNav = function(target){
								return $(''+config[target]+'').click(function(){
									$(this).trigger(target+'.'+self.namespace);
								});
							};

						$img.after(createNav('previous'))
							.after(createNav('next'));
					}

					if('function' === typeof customAfterOpen) {
						customAfterOpen.call(self, event);
					}
					config.afterImage.call(self, event);
				}
			};
		this.featherlight($.extend(true, {}, $.featherlightGallery.defaults, flg, config, overrideCallbacks));
		return this;
	};

	/* extend jQuery with standalone featherlight method  $.featherlight(elm, config); */
	$.featherlightGallery = function($targets, config) {
		if('object' !== typeof $targets){
			$targets = $($targets);
		}
		$targets.featherlightGallery(config);
	};

	$.featherlightGallery.defaults = {
		gallery: {
			beforeImage: $.noop,   /* Callback before an image is changed */
			afterImage: $.noop,    /* Callback after an image is presented */
			previous: '◀',   /* Code that is used as previous icon */
			next: '▶',       /* Code that is used as next icon */
			fadeIn: 100,           /* fadeIn speed when image is loaded */
			fadeOut: 300           /* fadeOut speed before image is loaded */
		},
		type: 'image'
	};

}(jQuery));
<commit_msg>Gallery: fix unbinding when using Hammer<commit_after>/**
 * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
 * Version 0.4.9 - http://noelboss.github.io/featherlight/
 *
 * Copyright 2014, Noël Raoul Bossart (http://www.noelboss.com)
 * MIT Licensed.
**/
(function($) {
	"use strict";

	if('undefined' === typeof $) {
		if('console' in window){ window.console.info('Too much lightness, Featherlight needs jQuery.');
			if(!('featherlight' in $)){	window.console.info('Load the featherlight plugin before the gallery plugin'); }
		}
		return;
	}

	var isTouchAware = 'ontouchstart' in document.documentElement,
		jQueryConstructor = $.event && $.event.special.swipeleft && $,
		hammerConstructor = ('Hammer' in window) && function($el){ new window.Hammer(el[0]); },
		swipeAwareConstructor = isTouchAware && (jQueryConstructor || hammerConstructor);

	/* extend jQuery with selector featherlight method $(elm).featherlight(config, elm); */
	$.fn.featherlightGallery = function(config) {
		var flg = {
				gallery: {
					$gallery: this,
					$current: null         /* Current source */
				}
			},
			customAfterOpen = config && config.afterOpen,
			customAfterClose = config && config.afterClose,
			overrideCallbacks = {				/* provide an afterOpen function */
				afterClose: function(event){
					var self = this;
					self.$instance.off('next.'+self.namespace+' previous.'+self.namespace);
					if (swipeAwareConstructor) {
						swipeAwareConstructor(self.$instance).off('swipeleft', self._swipeleft); /* See http://stackoverflow.com/questions/17367198/hammer-js-cant-remove-event-listener */
						swipeAwareConstructor(self.$instance).off('swiperight', self._swiperight);
					}
					if('function' === typeof customAfterClose) {
						customAfterClose.call(this, event);
					}
				},
				afterOpen: function(event){
					var self = this,
						config = this.gallery,
						$img = self.$instance.find('img');

					config.$current = $(event.currentTarget);

					self.$instance.on('next.'+self.namespace+' previous.'+self.namespace, function(event){
							var offset = event.type === 'next' ? +1 : -1;
							config.$current = config.$gallery.eq((config.$gallery.length + config.$gallery.index(config.$current) + offset) % config.$gallery.length);
							config.beforeImage.call(self, event);
							$.when(
								$.featherlight.contentFilters.image.process(config.$current.attr('href')),
								$img.fadeTo(config.fadeOut,0.2)
							).done(function($i) {
									$img[0].src = $i[0].src;
									config.afterImage.call(self, event);
									$img.fadeTo(config.fadeIn,1);
								});
							});

					if (swipeAwareConstructor) {
						swipeAwareConstructor(self.$instance)
							.on('swipeleft', self._swipeleft = function()  { self.$instance.trigger('next'); })
							.on('swiperight', self._swiperight = function() { self.$instance.trigger('previous'); });
					} else {
						var createNav = function(target){
								return $(''+config[target]+'').click(function(){
									$(this).trigger(target+'.'+self.namespace);
								});
							};

						$img.after(createNav('previous'))
							.after(createNav('next'));
					}

					if('function' === typeof customAfterOpen) {
						customAfterOpen.call(self, event);
					}
					config.afterImage.call(self, event);
				}
			};
		this.featherlight($.extend(true, {}, $.featherlightGallery.defaults, flg, config, overrideCallbacks));
		return this;
	};

	/* extend jQuery with standalone featherlight method  $.featherlight(elm, config); */
	$.featherlightGallery = function($targets, config) {
		if('object' !== typeof $targets){
			$targets = $($targets);
		}
		$targets.featherlightGallery(config);
	};

	$.featherlightGallery.defaults = {
		gallery: {
			beforeImage: $.noop,   /* Callback before an image is changed */
			afterImage: $.noop,    /* Callback after an image is presented */
			previous: '◀',   /* Code that is used as previous icon */
			next: '▶',       /* Code that is used as next icon */
			fadeIn: 100,           /* fadeIn speed when image is loaded */
			fadeOut: 300           /* fadeOut speed before image is loaded */
		},
		type: 'image'
	};

}(jQuery));
<|endoftext|>


<commit_before>import { get as objGet, each, isFunction, isString, isArray } from "lodash";
import validators from "../utils/validators";
import { slugifyFormID } from "../utils/schema";

function convertValidator(validator) {
	if (isString(validator)) {
		if (validators[validator] != null)
			return validators[validator];
		else {
			console.warn(`'${validator}' is not a validator function!`);
			return null; // caller need to handle null
		}
	}
	return validator;
}

export default {
	props: [
		"model",
		"schema",
		"formOptions",
		"disabled",
	],

	data() {
		return {
			errors: []
		};
	},

	computed: {
		value: {
			cache: false,
			get() {
				let val;
				if (isFunction(this.schema.get))
					val = this.schema.get(this.model);

				else if (this.model && this.schema.model)
					val = objGet(this.model, this.schema.model);

				if (isFunction(this.formatValueToField))
					val = this.formatValueToField(val);

				return val;
			},

			set(newValue) {
				let oldValue = this.value;

				if (isFunction(this.formatValueToModel))
					newValue = this.formatValueToModel(newValue);

				let changed = false;
				if (isFunction(this.schema.set)) {
					this.schema.set(this.model, newValue);
					changed = true;

				} else if (this.schema.model) {
					this.setModelValueByPath(this.schema.model, newValue);
					changed = true;
				}

				if (changed) {
					this.$emit("model-updated", newValue, this.schema.model);

					if (isFunction(this.schema.onChanged)) {
						this.schema.onChanged.call(this, this.model, newValue, oldValue, this.schema);
					}

					if (this.$parent.options && this.$parent.options.validateAfterChanged === true){
						this.validate();
					}
				}
			}
		}
	},

	methods: {
		validate(calledParent) {
			this.clearValidationErrors();

			if (this.schema.validator && this.schema.readonly !== true && this.disabled !== true) {

				let validators = [];
				if (!isArray(this.schema.validator)) {
					validators.push(convertValidator(this.schema.validator).bind(this));
				} else {
					each(this.schema.validator, (validator) => {
						validators.push(convertValidator(validator).bind(this));
					});
				}

				each(validators, (validator) => {
					let addErrors = err => {
						if (isArray(err))
							Array.prototype.push.apply(this.errors, err);
						else if (isString(err))
							this.errors.push(err);
					};

					let res = validator(this.value, this.schema, this.model);
					if (res && isFunction(res.then)) {
						// It is a Promise, async validator
						res.then(err => {
							if (err) {
								addErrors(err);
								let isValid = this.errors.length == 0;
								this.$emit("validated", isValid, this.errors, this);
							}
						});
					} else {
						if (res)
							addErrors(res);
					}
				});

			}

			if (isFunction(this.schema.onValidated)) {
				this.schema.onValidated.call(this, this.model, this.errors, this.schema);
			}

			let isValid = this.errors.length == 0;
			if (!calledParent)
				this.$emit("validated", isValid, this.errors, this);

			return this.errors;
		},

		clearValidationErrors() {
			this.errors.splice(0);
		},

		setModelValueByPath(path, value) {
			// convert array indexes to properties
			let s = path.replace(/\[(\w+)\]/g, ".$1");

			// strip a leading dot
			s = s.replace(/^\./, "");

			let o = this.model;
			const a = s.split(".");
			let i = 0;
			const n = a.length;
			while (i < n) {
				let k = a[i];
				if (i < n - 1)
					if (o[k] !== undefined) {
						// Found parent property. Step in
						o = o[k];
					} else {
						// Create missing property (new level)
						this.$root.$set(o, k, {});
						o = o[k];
					}
				else {
					// Set final property value
					this.$root.$set(o, k, value);
					return;
				}

				++i;
			}
		},

		getFieldID(schema) {
			const idPrefix = this.formOptions && this.formOptions.fieldIdPrefix ? this.formOptions.fieldIdPrefix : "";
			return slugifyFormID(schema, idPrefix);
		},

		getFieldClasses() {
			return this.schema.fieldClasses || [];
		}

	}
};
<commit_msg>removed unnecessary semi-colon to fix travis<commit_after>import { get as objGet, each, isFunction, isString, isArray } from "lodash";
import validators from "../utils/validators";
import { slugifyFormID } from "../utils/schema";

function convertValidator(validator) {
	if (isString(validator)) {
		if (validators[validator] != null)
			return validators[validator];
		else {
			console.warn(`'${validator}' is not a validator function!`);
			return null; // caller need to handle null
		}
	}
	return validator;
}

export default {
	props: [
		"model",
		"schema",
		"formOptions",
		"disabled",
	],

	data() {
		return {
			errors: []
		};
	},

	computed: {
		value: {
			cache: false,
			get() {
				let val;
				if (isFunction(this.schema.get))
					val = this.schema.get(this.model);

				else if (this.model && this.schema.model)
					val = objGet(this.model, this.schema.model);

				if (isFunction(this.formatValueToField))
					val = this.formatValueToField(val);

				return val;
			},

			set(newValue) {
				let oldValue = this.value;

				if (isFunction(this.formatValueToModel))
					newValue = this.formatValueToModel(newValue);

				let changed = false;
				if (isFunction(this.schema.set)) {
					this.schema.set(this.model, newValue);
					changed = true;

				} else if (this.schema.model) {
					this.setModelValueByPath(this.schema.model, newValue);
					changed = true;
				}

				if (changed) {
					this.$emit("model-updated", newValue, this.schema.model);

					if (isFunction(this.schema.onChanged)) {
						this.schema.onChanged.call(this, this.model, newValue, oldValue, this.schema);
					}

					if (this.$parent.options && this.$parent.options.validateAfterChanged === true){
						this.validate();
					}
				}
			}
		}
	},

	methods: {
		validate(calledParent) {
			this.clearValidationErrors();

			if (this.schema.validator && this.schema.readonly !== true && this.disabled !== true) {

				let validators = [];
				if (!isArray(this.schema.validator)) {
					validators.push(convertValidator(this.schema.validator).bind(this));
				} else {
					each(this.schema.validator, (validator) => {
						validators.push(convertValidator(validator).bind(this));
					});
				}

				each(validators, (validator) => {
					let addErrors = err => {
						if (isArray(err))
							Array.prototype.push.apply(this.errors, err);
						else if (isString(err))
							this.errors.push(err);
					};

					let res = validator(this.value, this.schema, this.model);
					if (res && isFunction(res.then)) {
						// It is a Promise, async validator
						res.then(err => {
							if (err) {
								addErrors(err);
								let isValid = this.errors.length == 0;
								this.$emit("validated", isValid, this.errors, this);
							}
						});
					} else {
						if (res)
							addErrors(res);
					}
				});

			}

			if (isFunction(this.schema.onValidated)) {
				this.schema.onValidated.call(this, this.model, this.errors, this.schema);
			}

			let isValid = this.errors.length == 0;
			if (!calledParent)
				this.$emit("validated", isValid, this.errors, this);

			return this.errors;
		},

		clearValidationErrors() {
			this.errors.splice(0);
		},

		setModelValueByPath(path, value) {
			// convert array indexes to properties
			let s = path.replace(/\[(\w+)\]/g, ".$1");

			// strip a leading dot
			s = s.replace(/^\./, "");

			let o = this.model;
			const a = s.split(".");
			let i = 0;
			const n = a.length;
			while (i < n) {
				let k = a[i];
				if (i < n - 1)
					if (o[k] !== undefined) {
						// Found parent property. Step in
						o = o[k];
					} else {
						// Create missing property (new level)
						this.$root.$set(o, k, {});
						o = o[k];
					}
				else {
					// Set final property value
					this.$root.$set(o, k, value);
					return;
				}

				++i;
			}
		},

		getFieldID(schema) {
			const idPrefix = this.formOptions && this.formOptions.fieldIdPrefix ? this.formOptions.fieldIdPrefix : "";
			return slugifyFormID(schema, idPrefix);
		},

		getFieldClasses() {
			return this.schema.fieldClasses || [];
		}

	}
}
<|endoftext|>


<commit_before>#!/usr/bin/env seed

// Configuration

var tiles_w = 15;
var tiles_h = 10;
var tile_size = 50;
var offset = tile_size/2;

var max_colors = 2;
var fly_score = true;

Seed.import_namespace("Gtk");
Seed.import_namespace("Clutter", "0.9");
Seed.import_namespace("GtkClutter", "0.9");
Seed.import_namespace("GdkPixbuf");
Seed.import_namespace("GConf");
Seed.import_namespace("GLib");
Seed.import_namespace("Pango");

GtkClutter.init(null, null);
GConf.init(null, null);

Seed.include("light.js");
Seed.include("board.js");
Seed.include("score.js");

var score = 0;
var timelines = [];

var gb = new Gtk.Builder();
gb.add_from_file("same-seed.ui");

var window = gb.get_object("main_window");
var clutter = gb.get_object("clutter");
var stage = clutter.get_stage();

window.signal.hide.connect(function () { Gtk.main_quit(); });

stage.color = {alpha: 0};
stage.set_size((tiles_w * tile_size),(tiles_h * tile_size));

var board = new Board();
stage.add_actor(board);

gb.get_object("new_game_item").signal.activate.connect(function () { board.new_game(); });
gb.get_object("quit_item").signal.activate.connect(function () { Gtk.main_quit(); });

clutter.set_size_request(stage.width, stage.height);
window.show_all();

Gtk.main();

<commit_msg>Somehow I accidentally committed with 2 colors on.<commit_after>#!/usr/bin/env seed

// Configuration

var tiles_w = 15;
var tiles_h = 10;
var tile_size = 50;
var offset = tile_size/2;

var max_colors = 4;
var fly_score = true;

Seed.import_namespace("Gtk");
Seed.import_namespace("Clutter", "0.9");
Seed.import_namespace("GtkClutter", "0.9");
Seed.import_namespace("GdkPixbuf");
Seed.import_namespace("GConf");
Seed.import_namespace("GLib");
Seed.import_namespace("Pango");

GtkClutter.init(null, null);
GConf.init(null, null);

Seed.include("light.js");
Seed.include("board.js");
Seed.include("score.js");

var score = 0;
var timelines = [];

var gb = new Gtk.Builder();
gb.add_from_file("same-seed.ui");

var window = gb.get_object("main_window");
var clutter = gb.get_object("clutter");
var stage = clutter.get_stage();

window.signal.hide.connect(function () { Gtk.main_quit(); });

stage.color = {alpha: 0};
stage.set_size((tiles_w * tile_size),(tiles_h * tile_size));

var board = new Board();
stage.add_actor(board);

gb.get_object("new_game_item").signal.activate.connect(function () { board.new_game(); });
gb.get_object("quit_item").signal.activate.connect(function () { Gtk.main_quit(); });

clutter.set_size_request(stage.width, stage.height);
window.show_all();

Gtk.main();

<|endoftext|>


<commit_before>module.exports = {
  // sockets
  SOCKET_REQUEST_CONNECT: 'user/SOCKET_REQUEST_CONNECT',
  SOCKET_AUTH_ERROR: 'user/SOCKET_AUTH_ERROR',
  // library
  LIBRARY_FILTER_STRING: 'library/FILTER_KEYWORD',
  LIBRARY_FILTER_STRING_RESET: 'library/FILTER_KEYWORD_CLEAR',
  LIBRARY_FILTER_TOGGLE_STARRED: 'library/TOGGLE_FILTER_STARRED',
  TOGGLE_ARTIST_EXPANDED: 'library/TOGGLE_ARTIST_EXPANDED',
  TOGGLE_ARTIST_RESULT_EXPANDED: 'library/TOGGLE_ARTIST_RESULT_EXPANDED',
  SCROLL_ARTISTS: 'library/SCROLL_ARTISTS',
  LIBRARY_SONG_INFO_REQUEST: 'library/SONG_INFO_REQUEST',
  LIBRARY_SONG_INFO_CLOSE: 'library/SONG_INFO_CLOSE',
  SONG_STARRED: 'library/SONG_STARRED',
  SONG_UNSTARRED: 'library/SONG_UNSTARRED',
  STAR_COUNTS_PUSH: 'library/STAR_COUNTS_PUSH',
  LIBRARY_PUSH: 'library/PUSH',
  LIBRARY_PUSH_SONG: 'library/PUSH_SONG',
  // queue
  QUEUE_PUSH: 'queue/PUSH',
  QUEUE_ADD: 'server/QUEUE_ADD',
  QUEUE_REMOVE: 'server/QUEUE_REMOVE',
  // player commands
  PLAYER_PLAY_REQUEST: 'server/PLAYER_PLAY_REQUEST',
  PLAYER_PAUSE_REQUEST: 'server/PLAYER_PAUSE_REQUEST',
  PLAYER_NEXT_REQUEST: 'server/PLAYER_NEXT_REQUEST',
  PLAYER_VOLUME_REQUEST: 'server/PLAYER_VOLUME_REQUEST',
  PLAYER_BG_ALPHA_REQUEST: 'server/PLAYER_BG_ALPHA_REQUEST',
  PLAYER_VISUALIZER_REQUEST: 'server/PLAYER_VISUALIZER_REQUEST',
  PLAYER_VISUALIZER_PRESET_REQUEST: 'server/PLAYER_VISUALIZER_PRESET_REQUEST',
  // from server to player
  PLAYER_NEXT: 'player/NEXT',
  PLAYER_PAUSE: 'player/PAUSE',
  PLAYER_PLAY: 'player/PLAY',
  PLAYER_VOLUME: 'player/VOLUME',
  PLAYER_BG_ALPHA: 'player/BG_ALPHA',
  PLAYER_VISUALIZER: 'player/VISUALIZER',
  PLAYER_VISUALIZER_PRESET: 'player/VISUALIZER_PRESET',
  // from player to server
  PLAYER_STATUS_REQUEST: 'server/PLAYER_STATUS_REQUEST',
  PLAYER_ERROR_REQUEST: 'server/PLAYER_ERROR_REQUEST',
  PLAYER_LEAVE_REQUEST:  'server/PLAYER_LEAVE_REQUEST',
  // from server to clients
  PLAYER_STATUS: 'status/PLAYER_STATUS',
  PLAYER_ERROR: 'status/PLAYER_ERROR',
  PLAYER_LEAVE: 'status/PLAYER_LEAVE',
  // player informational
  PLAYER_MEDIA_REQUEST: 'player/MEDIA_REQUEST',
  PLAYER_MEDIA_REQUEST_SUCCESS: 'player/MEDIA_REQUEST_SUCCESS',
  PLAYER_MEDIA_REQUEST_ERROR: 'player/MEDIA_REQUEST_ERROR',
  // user
  LOGIN: 'user/LOGIN',
  LOGOUT: 'user/LOGOUT',
  CREATE_ACCOUNT: 'user/CREATE_ACCOUNT',
  UPDATE_ACCOUNT: 'user/UPDATE_ACCOUNT',
  REQUEST_ACCOUNT: 'user/REQUEST_ACCOUNT',
  REQUEST_ROOMS: 'rooms/REQUEST_ROOMS',
  ROOM_UPDATE: 'rooms/UPDATE',
  ROOM_CREATE: 'rooms/CREATE',
  ROOM_REMOVE: 'rooms/REMOVE',
  ROOM_EDITOR_OPEN: 'rooms/EDITOR_OPEN',
  ROOM_EDITOR_CLOSE: 'rooms/EDITOR_CLOSE',
  STAR_SONG: 'server/STAR_SONG',
  UNSTAR_SONG: 'server/UNSTAR_SONG',
  STARS_PUSH: 'user/STARS_PUSH',
  // misc
  _SUCCESS: '_SUCCESS',
  _ERROR: '_ERROR',
  // prefs
  PREFS_REQUEST: 'prefs/REQUEST',
  PREFS_SET: 'prefs/SET',
  PREFS_RECEIVE: 'prefs/RECEIVE',
  PREFS_REQUEST_SCAN: 'prefs/REQUEST_SCAN',
  PREFS_REQUEST_SCAN_CANCEL: 'prefs/REQUEST_SCAN_CANCEL',
  // ui
  HEADER_HEIGHT_CHANGE: 'ui/HEADER_HEIGHT_CHANGE',
  FOOTER_HEIGHT_CHANGE: 'ui/FOOTER_HEIGHT_CHANGE',
  SHOW_ERROR_MESSAGE: 'ui/SHOW_ERROR_MESSAGE',
  CLEAR_ERROR_MESSAGE: 'ui/CLEAR_ERROR_MESSAGE',
  // IPC messages
  SCANNER_WORKER_SCAN: 'scannerWorker/SCAN',
  SCANNER_WORKER_STATUS: 'scannerWorker/STATUS',
  SCANNER_WORKER_DONE: 'scannerWorker/DONE',
  SERVER_WORKER_STATUS: 'serverWorker/STATUS',
  SERVER_WORKER_ERROR: 'serverWorker/ERROR',
  MEDIA_ADD: 'scannerWorker/MEDIA_ADD',
  MEDIA_CLEANUP: 'scannerWorker/MEDIA_CLEANUP',
  MEDIA_REMOVE: 'scannerWorker/MEDIA_REMOVE',
  MEDIA_UPDATE: 'scannerWorker/MEDIA_UPDATE',
}
<commit_msg>Add action type<commit_after>module.exports = {
  // sockets
  SOCKET_REQUEST_CONNECT: 'user/SOCKET_REQUEST_CONNECT',
  SOCKET_AUTH_ERROR: 'user/SOCKET_AUTH_ERROR',
  // library
  LIBRARY_FILTER_STRING: 'library/FILTER_KEYWORD',
  LIBRARY_FILTER_STRING_RESET: 'library/FILTER_KEYWORD_CLEAR',
  LIBRARY_FILTER_TOGGLE_STARRED: 'library/TOGGLE_FILTER_STARRED',
  TOGGLE_ARTIST_EXPANDED: 'library/TOGGLE_ARTIST_EXPANDED',
  TOGGLE_ARTIST_RESULT_EXPANDED: 'library/TOGGLE_ARTIST_RESULT_EXPANDED',
  SCROLL_ARTISTS: 'library/SCROLL_ARTISTS',
  LIBRARY_SONG_INFO_REQUEST: 'library/SONG_INFO_REQUEST',
  LIBRARY_SONG_INFO_CLOSE: 'library/SONG_INFO_CLOSE',
  SONG_STARRED: 'library/SONG_STARRED',
  SONG_UNSTARRED: 'library/SONG_UNSTARRED',
  STAR_COUNTS_PUSH: 'library/STAR_COUNTS_PUSH',
  LIBRARY_PUSH: 'library/PUSH',
  LIBRARY_PUSH_SONG: 'library/PUSH_SONG',
  // queue
  QUEUE_PUSH: 'queue/PUSH',
  QUEUE_ADD: 'server/QUEUE_ADD',
  QUEUE_REMOVE: 'server/QUEUE_REMOVE',
  // player commands
  PLAYER_PLAY_REQUEST: 'server/PLAYER_PLAY_REQUEST',
  PLAYER_PAUSE_REQUEST: 'server/PLAYER_PAUSE_REQUEST',
  PLAYER_NEXT_REQUEST: 'server/PLAYER_NEXT_REQUEST',
  PLAYER_VOLUME_REQUEST: 'server/PLAYER_VOLUME_REQUEST',
  PLAYER_BG_ALPHA_REQUEST: 'server/PLAYER_BG_ALPHA_REQUEST',
  PLAYER_VISUALIZER_REQUEST: 'server/PLAYER_VISUALIZER_REQUEST',
  PLAYER_VISUALIZER_PRESET_REQUEST: 'server/PLAYER_VISUALIZER_PRESET_REQUEST',
  // from server to player
  PLAYER_NEXT: 'player/NEXT',
  PLAYER_PAUSE: 'player/PAUSE',
  PLAYER_PLAY: 'player/PLAY',
  PLAYER_VOLUME: 'player/VOLUME',
  PLAYER_BG_ALPHA: 'player/BG_ALPHA',
  PLAYER_VISUALIZER: 'player/VISUALIZER',
  PLAYER_VISUALIZER_PRESET: 'player/VISUALIZER_PRESET',
  // from player to server
  PLAYER_STATUS_REQUEST: 'server/PLAYER_STATUS_REQUEST',
  PLAYER_ERROR_REQUEST: 'server/PLAYER_ERROR_REQUEST',
  PLAYER_LEAVE_REQUEST:  'server/PLAYER_LEAVE_REQUEST',
  // from server to clients
  PLAYER_STATUS: 'status/PLAYER_STATUS',
  PLAYER_ERROR: 'status/PLAYER_ERROR',
  PLAYER_LEAVE: 'status/PLAYER_LEAVE',
  // player informational
  PLAYER_MEDIA_CHANGE: 'player/MEDIA_CHANGE',
  PLAYER_MEDIA_REQUEST: 'player/MEDIA_REQUEST',
  PLAYER_MEDIA_REQUEST_SUCCESS: 'player/MEDIA_REQUEST_SUCCESS',
  PLAYER_MEDIA_REQUEST_ERROR: 'player/MEDIA_REQUEST_ERROR',
  // user
  LOGIN: 'user/LOGIN',
  LOGOUT: 'user/LOGOUT',
  CREATE_ACCOUNT: 'user/CREATE_ACCOUNT',
  UPDATE_ACCOUNT: 'user/UPDATE_ACCOUNT',
  REQUEST_ACCOUNT: 'user/REQUEST_ACCOUNT',
  REQUEST_ROOMS: 'rooms/REQUEST_ROOMS',
  ROOM_UPDATE: 'rooms/UPDATE',
  ROOM_CREATE: 'rooms/CREATE',
  ROOM_REMOVE: 'rooms/REMOVE',
  ROOM_EDITOR_OPEN: 'rooms/EDITOR_OPEN',
  ROOM_EDITOR_CLOSE: 'rooms/EDITOR_CLOSE',
  STAR_SONG: 'server/STAR_SONG',
  UNSTAR_SONG: 'server/UNSTAR_SONG',
  STARS_PUSH: 'user/STARS_PUSH',
  // misc
  _SUCCESS: '_SUCCESS',
  _ERROR: '_ERROR',
  // prefs
  PREFS_REQUEST: 'prefs/REQUEST',
  PREFS_SET: 'prefs/SET',
  PREFS_RECEIVE: 'prefs/RECEIVE',
  PREFS_REQUEST_SCAN: 'prefs/REQUEST_SCAN',
  PREFS_REQUEST_SCAN_CANCEL: 'prefs/REQUEST_SCAN_CANCEL',
  // ui
  HEADER_HEIGHT_CHANGE: 'ui/HEADER_HEIGHT_CHANGE',
  FOOTER_HEIGHT_CHANGE: 'ui/FOOTER_HEIGHT_CHANGE',
  SHOW_ERROR_MESSAGE: 'ui/SHOW_ERROR_MESSAGE',
  CLEAR_ERROR_MESSAGE: 'ui/CLEAR_ERROR_MESSAGE',
  // IPC messages
  SCANNER_WORKER_SCAN: 'scannerWorker/SCAN',
  SCANNER_WORKER_STATUS: 'scannerWorker/STATUS',
  SCANNER_WORKER_DONE: 'scannerWorker/DONE',
  SERVER_WORKER_STATUS: 'serverWorker/STATUS',
  SERVER_WORKER_ERROR: 'serverWorker/ERROR',
  MEDIA_ADD: 'scannerWorker/MEDIA_ADD',
  MEDIA_CLEANUP: 'scannerWorker/MEDIA_CLEANUP',
  MEDIA_REMOVE: 'scannerWorker/MEDIA_REMOVE',
  MEDIA_UPDATE: 'scannerWorker/MEDIA_UPDATE',
}
<|endoftext|>


<commit_before>define(function(require) {

  var React = require('react/addons'),
    Backbone = require('backbone'),
    _ = require('underscore'),
    modals = require('modals'),
    stores = require('stores'),

    BootstrapModalMixin = require('components/mixins/BootstrapModalMixin.react'),
    BreadcrumbNav = require('components/common/breadcrumb/BreadcrumbNav.react'),

    ImageSelectStep = require('./launch/steps/ImageSelectStep.react'),
    NameIdentityVersionStep = require('./launch/steps/NameIdentityVersionStep.react'),
    SizeSelectStep = require('./launch/steps/SizeSelectStep.react'),
    ProjectSelectStep = require('./launch/steps/ProjectSelectStep.react'),
    UserOptionsStep = require('./launch/steps/UserOptionsStep.react'),
    AdministratorOptionsStep = require('./launch/steps/AdminOptionsStep.react'),
    LicensingStep = require('./launch/steps/LicensingStep.react'),
    ReviewLaunchStep = require('./launch/steps/ReviewLaunchStep.react');

  var IMAGE_STEP = 0,
      INFORMATION_STEP = 1,
      SIZE_STEP = 2,
      PROJECT_STEP = 3,
      OPTIONS_STEP = 4,
      LICENSE_STEP = 5,
      REVIEW_STEP = 6;

  return React.createClass({
    mixins: [BootstrapModalMixin],
    displayName: "InstanceLaunchWizardModal",

    propTypes: {
      image: React.PropTypes.instanceOf(Backbone.Model),
      project: React.PropTypes.instanceOf(Backbone.Model),
      onConfirm: React.PropTypes.func.isRequired,
    },

    onRequestResources: function(){
      // Launching a resource request modal will eat the current modal. We need to pass this.cancel as a prop
      // in order to properly unmount the whole modal, not just the current step component.
      this.cancel();
      modals.HelpModals.requestMoreResources();
    },

    isLicenseStepActive: function() {
      state = this.getState();
      if (state.version
        && state.version.get('licenses')
        && state.version.get('licenses').length > 0) {
        return true;
      } else {
        return false;
      }
    },
    isOptionsStepActive: function() {
      state = this.getState();
      if (state.showOptions === true) {
        return true;
      } else {
        return false;
      }
    },
    renderImageSelect: function() {
      return (
                <ImageSelectStep
                    image={this.state.image}
                            onPrevious={this.cancel}
                            onNext={this.onNext}
                />
      );
    },
    renderNameStep: function() {
      return (
                <NameIdentityVersionStep
                    image={this.state.image}
                    name={this.state.name}
                    identity={this.state.identity}
                    version={this.state.version}
                    onRequestResources={this.onRequestResources}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
      );
    },
    renderSizeStep: function() {
        return (
                <SizeSelectStep
                    image={this.state.image}
                    identity={this.state.identity}
                    size={this.state.size}
                    onRequestResources={this.onRequestResources}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
      );
    },
    renderProjectStep: function() {
        return (
                <ProjectSelectStep
                    project={this.state.project}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
              );
    },
    renderUserOptionsStep: function() {
      var allScripts = this.state.scripts || stores.ScriptStore.getAll(),
      requiredScripts = (this.state.version ? this.state.version.get('scripts') : null) || [],
      activeScripts = this.state.activeScripts || new Backbone.Collection();
      return (
                <UserOptionsStep
                    launchOptions={this.state.launchOptions}
                    scripts={allScripts}
                    activeScripts={activeScripts}
                    requiredScripts={requiredScripts}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
              );
    },
    renderStaffOptionsStep: function() {
      return (
        <AdministratorOptionsStep
          launchOptions={this.state.launchOptions}
          onPrevious={this.onPrevious}
          onNext={this.onNext}
          onFinished={this.toReview}
        />
      );
    },
    renderReviewLaunchStep: function() {
      return (
        <ReviewLaunchStep
          launchData={this.state}
          onPrevious={this.onPrevious}
          onNext={this.onCompleted}
          onRequestResources={this.onRequestResources}
          toAdvancedOptions={this.toAdvancedOptions}
        />
      );
    },
    renderLicenseStep: function() {
      return (
        <LicensingStep
          licenses={this.state.version.get('licenses')}
          onPrevious={this.onPrevious}
          onNext={this.onNext}
        />
      );
    },
    renderBody: function() {
      var step = this.state.step;
        switch(step) {
	       case IMAGE_STEP:
          return this.renderImageSelect();
        case INFORMATION_STEP:
          return this.renderNameStep();
        case SIZE_STEP:
          return this.renderSizeStep();
        case PROJECT_STEP:
          return this.renderProjectStep();
        case OPTIONS_STEP:
            return this.renderUserOptionsStep();
        case LICENSE_STEP:
          return this.renderLicenseStep();
        case REVIEW_STEP:
          return this.renderReviewLaunchStep();
      }
    },

    hoverTitleChange: function(text) {
      this.setState({title: text});
    },

    changeTitleBack: function() {
      this.setState({title: this.state.breadcrumbs[this.state.step].name});
    },

    renderBreadCrumbTrail: function() {
        var self = this;
        var breadcrumbs = this.state.breadcrumbs;

        //Add pseudo-property 'state'
        breadcrumbs.map(function(breadcrumb, index, array){
            var state;
            if(
                (typeof breadcrumb.active === "boolean" && !breadcrumb.active) ||
                (typeof breadcrumb.active === "function" && !breadcrumb.active())
              ) {
                state = "inactive"
            } else if(breadcrumb.step === self.state.step) {
                state = "active"
            } else if (breadcrumb.step < self.state.step) {
                state = "available"
            } else {
                state = ""
            }
            breadcrumb.state = state;
        });
        return (<BreadcrumbNav
            breadcrumbs={breadcrumbs}
            onMouseOn={this.hoverTitleChange}
            onMouseOff={this.changeTitleBack}
            step = {this.state.step}
            onCrumbClick={self.toStep}
            />
        );
    },
    render: function() {
      return (

                {this.renderCloseButton()}
                Instance Launch Wizard- {this.state.title}

                    {this.renderBreadCrumbTrail()}

                {this.renderBody()}

      );
    },

    //
    // Mounting & State
    // ----------------
    //
    getInitialState: function(){
      var image = this.props.image,
        project = this.props.project;
      return {
        image: image,
        project: project,
        step: image ? INFORMATION_STEP : IMAGE_STEP,
        title: "Image",
        breadcrumbs: [
          {name:"Image",step:IMAGE_STEP, active:this.props.image ? false : true},
          {name:"Version & Provider",step:INFORMATION_STEP, active: true},
          {name:"Size",step:SIZE_STEP, active: true},
          {name:"Project",step:PROJECT_STEP, active:this.props.project ? false : true},
          {name:"Options",step:OPTIONS_STEP, active: false},
          {name:"Licensing",step:LICENSE_STEP, active:this.isLicenseStepActive},
          {name:"Review",step:REVIEW_STEP, active: true}
        ],
      };
    },

    getState: function() {
      return this.state;
    },

    updateState: function() {
      if (this.isMounted()) this.setState(this.getState());
    },

    componentDidMount: function() {
      stores.ProviderStore.addChangeListener(this.updateState);
      stores.IdentityStore.addChangeListener(this.updateState);
      stores.SizeStore.addChangeListener(this.updateState);
      stores.ProjectStore.addChangeListener(this.updateState);
      stores.ProjectVolumeStore.addChangeListener(this.updateState);
      stores.ProjectInstanceStore.addChangeListener(this.updateState);
      stores.InstanceStore.addChangeListener(this.updateState);
      stores.ImageVersionStore.addChangeListener(this.updateState);
      stores.MaintenanceMessageStore.addChangeListener(this.updateState);
      stores.ScriptStore.addChangeListener(this.updateState);
      stores.LicenseStore.addChangeListener(this.updateState);
    },

    componentWillUnmount: function() {
      stores.ProviderStore.removeChangeListener(this.updateState);
      stores.IdentityStore.removeChangeListener(this.updateState);
      stores.SizeStore.removeChangeListener(this.updateState);
      stores.ProjectStore.removeChangeListener(this.updateState);
      stores.ProjectVolumeStore.removeChangeListener(this.updateState);
      stores.ProjectInstanceStore.removeChangeListener(this.updateState);
      stores.InstanceStore.removeChangeListener(this.updateState);
      stores.ImageVersionStore.removeChangeListener(this.updateState);
      stores.MaintenanceMessageStore.removeChangeListener(this.updateState);
      stores.ScriptStore.removeChangeListener(this.updateState);
      stores.LicenseStore.removeChangeListener(this.updateState);
    },

    //
    // Internal Modal Callbacks
    // ------------------------
    //

    cancel: function() {
      this.hide();
    },
    onCompleted: function(launch_data) {
      this.hide();
      this.props.onConfirm(launch_data);
    },
    onPrevious: function(data) {
        var previousStep = this.getPrevStep(this.state.step);
        if (previousStep === undefined) {
            this.cancel();
            return;
        }
        var data = data || {},
            state = _.extend({step: previousStep}, data);
        if(this.state.step == REVIEW_STEP) {
            //TODO: Remove this when re-adding User/Admin Options
            if(this.props.project) {
                //Skip 'Project Selection' step if project provided.
                state.step = SIZE_STEP;
            } else {
                state.step = PROJECT_STEP;
            }
        }
        state.title = this.state.breadcrumbs[state.step].name;
        this.setState(state);
    },
    getPrevStep: function(current_step) {
      var prevStep = current_step,
          breadcrumb;

      while(true) {
        prevStep = prevStep - 1;
        if (prevStep < 0) {
            return undefined;
          // throw "Unexpected behavior: prev step < 0";
        }
        breadcrumb = this.state.breadcrumbs[prevStep];
        if(
          (typeof breadcrumb.active === "boolean" && !breadcrumb.active) ||
          (typeof breadcrumb.active === "function" && !breadcrumb.active())
        ) {
          //Skip this, it's inactive
          continue;
        }
        return breadcrumb.step;
      }
    },
    getNextStep: function(current_step) {
      var nextStep = current_step + 1,
          final_step = this.state.breadcrumbs.length - 1,
          breadcrumb,
          active;

      do {
        if (nextStep > final_step) {
          throw "Unexpected behavior: 'next' step > final step";
        }
        breadcrumb = this.state.breadcrumbs[nextStep];
        active =
            typeof breadcrumb.active === "boolean"
            ? breadcrumb.active
            : breadcrumb.active();

        if (active)
            return breadcrumb.step;
      } while (nextStep++)

    },
    onNext: function (data) {
      var nextStep = this.getNextStep(this.state.step),
        data = data || {},
        state = _.extend({step: nextStep}, data);

      state.title = this.state.breadcrumbs[nextStep].name;
      this.setState(state);
    },
    toReview: function(data) {
        var state = _.extend({step: REVIEW_STEP}, data);
        this.setState(state);
    },
    activateBreadcrumb: function(index, activeTruth) {
      var breadcrumbs = this.state.breadcrumbs,
      crumb = breadcrumbs[index];
      crumb.state = activeTruth ? "active" : "inactive";
      this.state.breadcrumbs[index] = crumb;
      return crumb;
    },
    toAdvancedOptions: function(data) {
      var crumb = this.activateBreadcrumb(OPTIONS_STEP, true);
      var state = _.extend(data, {step: OPTIONS_STEP, title: crumb.name});
      this.setState(state);
    },
    toStep: function(breadcrumb) {
       this.setState({title: breadcrumb.name});
       this.setState({step: breadcrumb.step});
    }
  });

});
<commit_msg>pass version as prop to size select step<commit_after>define(function(require) {

  var React = require('react/addons'),
    Backbone = require('backbone'),
    _ = require('underscore'),
    modals = require('modals'),
    stores = require('stores'),

    BootstrapModalMixin = require('components/mixins/BootstrapModalMixin.react'),
    BreadcrumbNav = require('components/common/breadcrumb/BreadcrumbNav.react'),

    ImageSelectStep = require('./launch/steps/ImageSelectStep.react'),
    NameIdentityVersionStep = require('./launch/steps/NameIdentityVersionStep.react'),
    SizeSelectStep = require('./launch/steps/SizeSelectStep.react'),
    ProjectSelectStep = require('./launch/steps/ProjectSelectStep.react'),
    UserOptionsStep = require('./launch/steps/UserOptionsStep.react'),
    AdministratorOptionsStep = require('./launch/steps/AdminOptionsStep.react'),
    LicensingStep = require('./launch/steps/LicensingStep.react'),
    ReviewLaunchStep = require('./launch/steps/ReviewLaunchStep.react');

  var IMAGE_STEP = 0,
      INFORMATION_STEP = 1,
      SIZE_STEP = 2,
      PROJECT_STEP = 3,
      OPTIONS_STEP = 4,
      LICENSE_STEP = 5,
      REVIEW_STEP = 6;

  return React.createClass({
    mixins: [BootstrapModalMixin],
    displayName: "InstanceLaunchWizardModal",

    propTypes: {
      image: React.PropTypes.instanceOf(Backbone.Model),
      project: React.PropTypes.instanceOf(Backbone.Model),
      onConfirm: React.PropTypes.func.isRequired,
    },

    onRequestResources: function(){
      // Launching a resource request modal will eat the current modal. We need to pass this.cancel as a prop
      // in order to properly unmount the whole modal, not just the current step component.
      this.cancel();
      modals.HelpModals.requestMoreResources();
    },

    isLicenseStepActive: function() {
      state = this.getState();
      if (state.version
        && state.version.get('licenses')
        && state.version.get('licenses').length > 0) {
        return true;
      } else {
        return false;
      }
    },
    isOptionsStepActive: function() {
      state = this.getState();
      if (state.showOptions === true) {
        return true;
      } else {
        return false;
      }
    },
    renderImageSelect: function() {
      return (
                <ImageSelectStep
                    image={this.state.image}
                            onPrevious={this.cancel}
                            onNext={this.onNext}
                />
      );
    },
    renderNameStep: function() {
      return (
                <NameIdentityVersionStep
                    image={this.state.image}
                    name={this.state.name}
                    identity={this.state.identity}
                    version={this.state.version}
                    onRequestResources={this.onRequestResources}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
      );
    },
    renderSizeStep: function() {
        return (
                <SizeSelectStep
                    image={this.state.image}
                    identity={this.state.identity}
                    version={this.state.version}
                    size={this.state.size}
                    onRequestResources={this.onRequestResources}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
      );
    },
    renderProjectStep: function() {
        return (
                <ProjectSelectStep
                    project={this.state.project}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
              );
    },
    renderUserOptionsStep: function() {
      var allScripts = this.state.scripts || stores.ScriptStore.getAll(),
      requiredScripts = (this.state.version ? this.state.version.get('scripts') : null) || [],
      activeScripts = this.state.activeScripts || new Backbone.Collection();
      return (
                <UserOptionsStep
                    launchOptions={this.state.launchOptions}
                    scripts={allScripts}
                    activeScripts={activeScripts}
                    requiredScripts={requiredScripts}
                    onPrevious={this.onPrevious}
                    onNext={this.onNext}
                />
              );
    },
    renderStaffOptionsStep: function() {
      return (
        <AdministratorOptionsStep
          launchOptions={this.state.launchOptions}
          onPrevious={this.onPrevious}
          onNext={this.onNext}
          onFinished={this.toReview}
        />
      );
    },
    renderReviewLaunchStep: function() {
      return (
        <ReviewLaunchStep
          launchData={this.state}
          onPrevious={this.onPrevious}
          onNext={this.onCompleted}
          onRequestResources={this.onRequestResources}
          toAdvancedOptions={this.toAdvancedOptions}
        />
      );
    },
    renderLicenseStep: function() {
      return (
        <LicensingStep
          licenses={this.state.version.get('licenses')}
          onPrevious={this.onPrevious}
          onNext={this.onNext}
        />
      );
    },
    renderBody: function() {
      var step = this.state.step;
        switch(step) {
	       case IMAGE_STEP:
          return this.renderImageSelect();
        case INFORMATION_STEP:
          return this.renderNameStep();
        case SIZE_STEP:
          return this.renderSizeStep();
        case PROJECT_STEP:
          return this.renderProjectStep();
        case OPTIONS_STEP:
            return this.renderUserOptionsStep();
        case LICENSE_STEP:
          return this.renderLicenseStep();
        case REVIEW_STEP:
          return this.renderReviewLaunchStep();
      }
    },

    hoverTitleChange: function(text) {
      this.setState({title: text});
    },

    changeTitleBack: function() {
      this.setState({title: this.state.breadcrumbs[this.state.step].name});
    },

    renderBreadCrumbTrail: function() {
        var self = this;
        var breadcrumbs = this.state.breadcrumbs;

        //Add pseudo-property 'state'
        breadcrumbs.map(function(breadcrumb, index, array){
            var state;
            if(
                (typeof breadcrumb.active === "boolean" && !breadcrumb.active) ||
                (typeof breadcrumb.active === "function" && !breadcrumb.active())
              ) {
                state = "inactive"
            } else if(breadcrumb.step === self.state.step) {
                state = "active"
            } else if (breadcrumb.step < self.state.step) {
                state = "available"
            } else {
                state = ""
            }
            breadcrumb.state = state;
        });
        return (<BreadcrumbNav
            breadcrumbs={breadcrumbs}
            onMouseOn={this.hoverTitleChange}
            onMouseOff={this.changeTitleBack}
            step = {this.state.step}
            onCrumbClick={self.toStep}
            />
        );
    },
    render: function() {
      return (

                {this.renderCloseButton()}
                Instance Launch Wizard- {this.state.title}

                    {this.renderBreadCrumbTrail()}

                {this.renderBody()}

      );
    },

    //
    // Mounting & State
    // ----------------
    //
    getInitialState: function(){
      var image = this.props.image,
        project = this.props.project;
      return {
        image: image,
        project: project,
        step: image ? INFORMATION_STEP : IMAGE_STEP,
        title: "Image",
        breadcrumbs: [
          {name:"Image",step:IMAGE_STEP, active:this.props.image ? false : true},
          {name:"Version & Provider",step:INFORMATION_STEP, active: true},
          {name:"Size",step:SIZE_STEP, active: true},
          {name:"Project",step:PROJECT_STEP, active:this.props.project ? false : true},
          {name:"Options",step:OPTIONS_STEP, active: false},
          {name:"Licensing",step:LICENSE_STEP, active:this.isLicenseStepActive},
          {name:"Review",step:REVIEW_STEP, active: true}
        ],
      };
    },

    getState: function() {
      return this.state;
    },

    updateState: function() {
      if (this.isMounted()) this.setState(this.getState());
    },

    componentDidMount: function() {
      stores.ProviderStore.addChangeListener(this.updateState);
      stores.IdentityStore.addChangeListener(this.updateState);
      stores.SizeStore.addChangeListener(this.updateState);
      stores.ProjectStore.addChangeListener(this.updateState);
      stores.ProjectVolumeStore.addChangeListener(this.updateState);
      stores.ProjectInstanceStore.addChangeListener(this.updateState);
      stores.InstanceStore.addChangeListener(this.updateState);
      stores.ImageVersionStore.addChangeListener(this.updateState);
      stores.MaintenanceMessageStore.addChangeListener(this.updateState);
      stores.ScriptStore.addChangeListener(this.updateState);
      stores.LicenseStore.addChangeListener(this.updateState);
    },

    componentWillUnmount: function() {
      stores.ProviderStore.removeChangeListener(this.updateState);
      stores.IdentityStore.removeChangeListener(this.updateState);
      stores.SizeStore.removeChangeListener(this.updateState);
      stores.ProjectStore.removeChangeListener(this.updateState);
      stores.ProjectVolumeStore.removeChangeListener(this.updateState);
      stores.ProjectInstanceStore.removeChangeListener(this.updateState);
      stores.InstanceStore.removeChangeListener(this.updateState);
      stores.ImageVersionStore.removeChangeListener(this.updateState);
      stores.MaintenanceMessageStore.removeChangeListener(this.updateState);
      stores.ScriptStore.removeChangeListener(this.updateState);
      stores.LicenseStore.removeChangeListener(this.updateState);
    },

    //
    // Internal Modal Callbacks
    // ------------------------
    //

    cancel: function() {
      this.hide();
    },
    onCompleted: function(launch_data) {
      this.hide();
      this.props.onConfirm(launch_data);
    },
    onPrevious: function(data) {
        var previousStep = this.getPrevStep(this.state.step);
        if (previousStep === undefined) {
            this.cancel();
            return;
        }
        var data = data || {},
            state = _.extend({step: previousStep}, data);
        if(this.state.step == REVIEW_STEP) {
            //TODO: Remove this when re-adding User/Admin Options
            if(this.props.project) {
                //Skip 'Project Selection' step if project provided.
                state.step = SIZE_STEP;
            } else {
                state.step = PROJECT_STEP;
            }
        }
        state.title = this.state.breadcrumbs[state.step].name;
        this.setState(state);
    },
    getPrevStep: function(current_step) {
      var prevStep = current_step,
          breadcrumb;

      while(true) {
        prevStep = prevStep - 1;
        if (prevStep < 0) {
            return undefined;
          // throw "Unexpected behavior: prev step < 0";
        }
        breadcrumb = this.state.breadcrumbs[prevStep];
        if(
          (typeof breadcrumb.active === "boolean" && !breadcrumb.active) ||
          (typeof breadcrumb.active === "function" && !breadcrumb.active())
        ) {
          //Skip this, it's inactive
          continue;
        }
        return breadcrumb.step;
      }
    },
    getNextStep: function(current_step) {
      var nextStep = current_step + 1,
          final_step = this.state.breadcrumbs.length - 1,
          breadcrumb,
          active;

      do {
        if (nextStep > final_step) {
          throw "Unexpected behavior: 'next' step > final step";
        }
        breadcrumb = this.state.breadcrumbs[nextStep];
        active =
            typeof breadcrumb.active === "boolean"
            ? breadcrumb.active
            : breadcrumb.active();

        if (active)
            return breadcrumb.step;
      } while (nextStep++)

    },
    onNext: function (data) {
      var nextStep = this.getNextStep(this.state.step),
        data = data || {},
        state = _.extend({step: nextStep}, data);

      state.title = this.state.breadcrumbs[nextStep].name;
      this.setState(state);
    },
    toReview: function(data) {
        var state = _.extend({step: REVIEW_STEP}, data);
        this.setState(state);
    },
    activateBreadcrumb: function(index, activeTruth) {
      var breadcrumbs = this.state.breadcrumbs,
      crumb = breadcrumbs[index];
      crumb.state = activeTruth ? "active" : "inactive";
      this.state.breadcrumbs[index] = crumb;
      return crumb;
    },
    toAdvancedOptions: function(data) {
      var crumb = this.activateBreadcrumb(OPTIONS_STEP, true);
      var state = _.extend(data, {step: OPTIONS_STEP, title: crumb.name});
      this.setState(state);
    },
    toStep: function(breadcrumb) {
       this.setState({title: breadcrumb.name});
       this.setState({step: breadcrumb.step});
    }
  });

});
<|endoftext|>


<commit_before>const tokenIntrospectionGenerator = require('./token-introspector');
const BearerStrategy = require('passport-http-bearer');
const passport = require('passport');
const uuid = require('uuid/v4');
const db = require("../../db");

module.exports = function (actionParams) {
  actionParams.session = false;
  const scannedTokens = [];
  const tokenIntrospection = tokenIntrospectionGenerator(actionParams);
  const strategyName = `bearer-introspect-${uuid()}`;

  passport.use(strategyName, new BearerStrategy({ passReqToCallback: true }, (req, accessToken, done) => {
    const requestedScopes = req.egContext.apiEndpoint.scopes;

    const scopeCheck = (tokenData, done) => {
      const avaiableScopes = tokenData.scopes ? tokenData.scopes.split(' ') : [];

      if (requestedScopes.every(scope => avaiableScopes.includes(scope))) {
        return done(null, tokenData);
      }

      return done(null, false);
    };

    db.get("accesstoken." + accessToken)
      .then(result => {

        if (result) {
          return scopeCheck(JSON.parse(result), done);
        } else {
          return tokenIntrospection(accessToken, 'access_token')
          .then(tokenData => {
            db.set("accesstoken." + accessToken, JSON.stringify(tokenData));

            var expireInSeconds = actionParams.ttl;
            if (tokenData.exp &&
              expireInSeconds > (tokenData.exp - Date.now() / 1000)) {
                expireInSeconds = tokenData.exp - Date.now() / 1000;
              }
            db.expire("accesstoken." + accessToken, expireInSeconds);
            return scopeCheck(tokenData, done);
          })
          .catch(() => { done(null, false); });
        }
      });

  }));

  return (req, res, next) => {
    passport.authenticate(strategyName, actionParams, actionParams.getCommonAuthCallback(req, res, next))(req, res, next);
  };
};
<commit_msg>Resolved format checks<commit_after>const tokenIntrospectionGenerator = require('./token-introspector');
const BearerStrategy = require('passport-http-bearer');
const passport = require('passport');
const uuid = require('uuid/v4');
const db = require("../../db");

module.exports = function (actionParams) {
  actionParams.session = false;
  const tokenIntrospection = tokenIntrospectionGenerator(actionParams);
  const strategyName = `bearer-introspect-${uuid()}`;

  passport.use(strategyName, new BearerStrategy({ passReqToCallback: true }, (req, accessToken, done) => {
    const requestedScopes = req.egContext.apiEndpoint.scopes;

    const scopeCheck = (tokenData, done) => {
      const avaiableScopes = tokenData.scopes ? tokenData.scopes.split(' ') : [];

      if (requestedScopes.every(scope => avaiableScopes.includes(scope))) {
        return done(null, tokenData);
      }

      return done(null, false);
    };

    db.get('accesstoken.' + accessToken)
      .then(result => {

        if (result) {
          return scopeCheck(JSON.parse(result), done);
        } else {
          return tokenIntrospection(accessToken, 'access_token')
            .then(tokenData => {
              db.set('accesstoken.' + accessToken, JSON.stringify(tokenData));
              let expireInSeconds = actionParams.ttl;
              if (tokenData.exp &&
                expireInSeconds > (tokenData.exp - Date.now() / 1000)) {
                expireInSeconds = tokenData.exp - Date.now() / 1000;
              }
              db.expire("accesstoken." + accessToken, expireInSeconds);
              return scopeCheck(tokenData, done);
            })
            .catch(() => { done(null, false); });
        }
      });

  }));

  return (req, res, next) => {
    passport.authenticate(strategyName, actionParams, actionParams.getCommonAuthCallback(req, res, next))(req, res, next);
  };
};
<|endoftext|>