<commit_before>var expect = require('chai').expect,
    Runner = require('../../lib/runner/'),
    sdk = require('postman-collection');

describe('runner', function () {
    describe('Run', function () {
        it('should be a constructor', function () {
            expect(function () {
                return new Runner();
            }).to.not.throw();
        });

        it('should expose the run method', function () {
            var runner = new Runner();
            expect(runner.run).to.be.a('function');
        });

        describe('.run', function () {
            var collection = new sdk.Collection({
                item: [{
                    id: 'F2', // This is intended, so that id vs name match precedence can be tested
                    name: 'F1',
                    item: [{
                        name: 'F1.R1',
                        request: 'https://postman-echo.com/get'
                    }]
                }, {
                    name: 'F2',
                    item: [{
                        name: 'F1.R2',
                        request: 'https://postman-echo.com/get'
                    }]
                }]
            });

            describe('invalid entrypoint', function () {
                it('should bail out if options.abortOnError is set with entrypoint as string', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        entrypoint: {execute: 'random'},
                        abortOnError: true
                    }, function (err, run) {
                        expect(err.message).to.equal('Unable to find a folder or request: random');
                        expect(run).to.be.undefined;

                        done();
                    });
                });

                it('should bail out if options.abortOnError is set with entrypoint as object', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        entrypoint: {execute: 'random'},
                        abortOnError: true
                    }, function (err, run) {
                        expect(err.message).to.equal('Unable to find a folder or request: random');
                        expect(run).to.be.undefined;

                        done();
                    });
                });

                it('should NOT bail out if options.abortOnError is not set', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        entrypoint: 'random'
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.start).to.be.a('function');
                        done();
                    });
                });
            });

            describe('malformed collections', function () {
                it('should handle invalid collections correctly', function (done) {
                    var runner = new Runner();

                    runner.run('random', {}, function (err, run) {
                        expect(err).to.be.null;
                        expect(run).to.be.ok;
                        expect(run).to.deep.nested.include({
                            'state.items': []
                        });

                        done();
                    });
                });
            });

            describe('edge cases', function () {
                it('should handle malformed run options correctly', function (done) {
                    var runner = new Runner();

                    runner.run(collection, 'random', function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.start).to.be.a('function');
                        done();
                    });
                });

                it('should override prototype globals with those passed from the run options', function (done) {
                    var runner = new Runner({
                        globals: new sdk.VariableScope({}, [{key: 'alpha', value: 'foo'}])
                    });

                    runner.run(collection, {
                        globals: new sdk.VariableScope({}, [{key: 'beta', value: 'bar'}])
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.start).to.be.a('function');
                        done();
                    });
                });
            });

            describe('options parameter', function () {
                var runnerTimeout = 400,
                    runTimeout = 500,
                    defaultGlobalTimeout = 3 * 60 * 1000; // 3 minutes

                it('should handle timeout in runner options', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {
                                global: runnerTimeout,
                                script: runnerTimeout
                            }
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(runnerTimeout);
                        expect(run.options.timeout.script).to.equal(runnerTimeout);
                        expect(run.options.timeout.request).to.equal(Infinity);
                        done();
                    });
                });

                it('should handle timeout in run options', function (done) {
                    var runner = new Runner({});

                    runner.run(collection, {
                        timeout: {
                            global: runTimeout,
                            script: runTimeout
                        }
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(runTimeout);
                        expect(run.options.timeout.script).to.equal(runTimeout);
                        expect(run.options.timeout.request).to.equal(Infinity);
                        done();
                    });
                });

                it('should give more precedence to runner options', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {
                                global: runnerTimeout,
                                request: runnerTimeout,
                                script: runnerTimeout
                            }
                        }
                    });

                    runner.run(collection, {
                        timeout: {
                            global: runTimeout,
                            request: runTimeout,
                            script: runTimeout
                        }
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(runnerTimeout);
                        expect(run.options.timeout.script).to.equal(runnerTimeout);
                        expect(run.options.timeout.request).to.equal(runnerTimeout);
                        done();
                    });
                });

                it('should have proper defaults for timeout', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(defaultGlobalTimeout);
                        expect(run.options.timeout.script).to.equal(Infinity);
                        expect(run.options.timeout.request).to.equal(Infinity);
                        done();
                    });
                });

                it('should set default timeouts for null/undefined timeout values', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        timeout: {
                            global: null,
                            script: null,
                            request: undefined
                        }
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(defaultGlobalTimeout);
                        expect(run.options.timeout.script).to.equal(Infinity);
                        expect(run.options.timeout.request).to.equal(Infinity);
                        done();
                    });
                });

                it('should normalize 0 timeouts to infinity', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: 0}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(Infinity);
                        done();
                    });
                });

                it('should normalize negative values to Infinity', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: -1}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(Infinity);
                        done();
                    });
                });

                it('should normalize Infinty values to default', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: Infinity}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(defaultGlobalTimeout);
                        done();
                    });
                });

                it('should preserve finite timeouts', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: 100, script: 120, request: 180000}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.options.timeout.global).to.equal(100);
                        expect(run.options.timeout.script).to.equal(120);
                        expect(run.options.timeout.request).to.equal(180000);
                        done();
                    });
                });
            });
        });
    });

    describe('normaliseIterationData', function () {
        it('should handle insane arguments correctly', function () {
            expect(Runner.normaliseIterationData()).to.eql([{}]);
        });

        it('should trim the provided data set to the specified length', function () {
            expect(Runner.normaliseIterationData([{foo: 'alpha'}, {bar: 'beta'}], 1)).to.eql([{foo: 'alpha'}]);
        });

        it('should duplicate the last element of the data set if length is greater', function () {
            expect(Runner.normaliseIterationData([{foo: 'alpha'}], 2)).to.eql([{foo: 'alpha'}, {foo: 'alpha'}]);
        });
    });
});
<commit_msg>Update runner tests with nested.include chai helper<commit_after>var expect = require('chai').expect,
    Runner = require('../../lib/runner/'),
    sdk = require('postman-collection');

describe('runner', function () {
    describe('Run', function () {
        it('should be a constructor', function () {
            expect(function () {
                return new Runner();
            }).to.not.throw();
        });

        it('should expose the run method', function () {
            var runner = new Runner();
            expect(runner.run).to.be.a('function');
        });

        describe('.run', function () {
            var collection = new sdk.Collection({
                item: [{
                    id: 'F2', // This is intended, so that id vs name match precedence can be tested
                    name: 'F1',
                    item: [{
                        name: 'F1.R1',
                        request: 'https://postman-echo.com/get'
                    }]
                }, {
                    name: 'F2',
                    item: [{
                        name: 'F1.R2',
                        request: 'https://postman-echo.com/get'
                    }]
                }]
            });

            describe('invalid entrypoint', function () {
                it('should bail out if options.abortOnError is set with entrypoint as string', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        entrypoint: {execute: 'random'},
                        abortOnError: true
                    }, function (err, run) {
                        expect(err.message).to.equal('Unable to find a folder or request: random');
                        expect(run).to.be.undefined;

                        done();
                    });
                });

                it('should bail out if options.abortOnError is set with entrypoint as object', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        entrypoint: {execute: 'random'},
                        abortOnError: true
                    }, function (err, run) {
                        expect(err.message).to.equal('Unable to find a folder or request: random');
                        expect(run).to.be.undefined;

                        done();
                    });
                });

                it('should NOT bail out if options.abortOnError is not set', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        entrypoint: 'random'
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.start).to.be.a('function');
                        done();
                    });
                });
            });

            describe('malformed collections', function () {
                it('should handle invalid collections correctly', function (done) {
                    var runner = new Runner();

                    runner.run('random', {}, function (err, run) {
                        expect(err).to.be.null;
                        expect(run).to.be.ok;
                        expect(run).to.deep.nested.include({
                            'state.items': []
                        });

                        done();
                    });
                });
            });

            describe('edge cases', function () {
                it('should handle malformed run options correctly', function (done) {
                    var runner = new Runner();

                    runner.run(collection, 'random', function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.start).to.be.a('function');
                        done();
                    });
                });

                it('should override prototype globals with those passed from the run options', function (done) {
                    var runner = new Runner({
                        globals: new sdk.VariableScope({}, [{key: 'alpha', value: 'foo'}])
                    });

                    runner.run(collection, {
                        globals: new sdk.VariableScope({}, [{key: 'beta', value: 'bar'}])
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run.start).to.be.a('function');
                        done();
                    });
                });
            });

            describe('options parameter', function () {
                var runnerTimeout = 400,
                    runTimeout = 500,
                    defaultGlobalTimeout = 3 * 60 * 1000; // 3 minutes

                it('should handle timeout in runner options', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {
                                global: runnerTimeout,
                                script: runnerTimeout
                            }
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': runnerTimeout,
                            'timeout.script': runnerTimeout,
                            'timeout.request': Infinity
                        });
                        done();
                    });
                });

                it('should handle timeout in run options', function (done) {
                    var runner = new Runner({});

                    runner.run(collection, {
                        timeout: {
                            global: runTimeout,
                            script: runTimeout
                        }
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': runTimeout,
                            'timeout.script': runTimeout,
                            'timeout.request': Infinity
                        });
                        done();
                    });
                });

                it('should give more precedence to runner options', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {
                                global: runnerTimeout,
                                request: runnerTimeout,
                                script: runnerTimeout
                            }
                        }
                    });

                    runner.run(collection, {
                        timeout: {
                            global: runTimeout,
                            request: runTimeout,
                            script: runTimeout
                        }
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': runnerTimeout,
                            'timeout.script': runnerTimeout,
                            'timeout.request': runnerTimeout
                        });
                        done();
                    });
                });

                it('should have proper defaults for timeout', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': defaultGlobalTimeout,
                            'timeout.script': Infinity,
                            'timeout.request': Infinity
                        });
                        done();
                    });
                });

                it('should set default timeouts for null/undefined timeout values', function (done) {
                    var runner = new Runner();

                    runner.run(collection, {
                        timeout: {
                            global: null,
                            script: null,
                            request: undefined
                        }
                    }, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': defaultGlobalTimeout,
                            'timeout.script': Infinity,
                            'timeout.request': Infinity
                        });
                        done();
                    });
                });

                it('should normalize 0 timeouts to infinity', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: 0}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': Infinity
                        });
                        done();
                    });
                });

                it('should normalize negative values to Infinity', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: -1}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': Infinity
                        });
                        done();
                    });
                });

                it('should normalize Infinty values to default', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: Infinity}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': defaultGlobalTimeout
                        });
                        done();
                    });
                });

                it('should preserve finite timeouts', function (done) {
                    var runner = new Runner({
                        run: {
                            timeout: {global: 100, script: 120, request: 180000}
                        }
                    });

                    runner.run(collection, {}, function (err, run) {
                        expect(err).to.be.null;

                        expect(run).to.be.ok;
                        expect(run).to.have.property('options').that.nested.include({
                            'timeout.global': 100,
                            'timeout.script': 120,
                            'timeout.request': 180000
                        });
                        done();
                    });
                });
            });
        });
    });

    describe('normaliseIterationData', function () {
        it('should handle insane arguments correctly', function () {
            expect(Runner.normaliseIterationData()).to.eql([{}]);
        });

        it('should trim the provided data set to the specified length', function () {
            expect(Runner.normaliseIterationData([{foo: 'alpha'}, {bar: 'beta'}], 1)).to.eql([{foo: 'alpha'}]);
        });

        it('should duplicate the last element of the data set if length is greater', function () {
            expect(Runner.normaliseIterationData([{foo: 'alpha'}], 2)).to.eql([{foo: 'alpha'}, {foo: 'alpha'}]);
        });
    });
});
<|endoftext|>


<commit_before>cdb.geo.ui.Annotation = cdb.core.View.extend({

  className: "cartodb-overlay overlay-annotation",

  defaults: {
    minZoom: 0,
    maxZoom: 40,
    style: {
      textAlign: "left",
      zIndex: 5,
      color: "#ffffff",
      fontSize: "13",
      fontFamilyName: "Helvetica",
      boxColor: "#333333",
      boxOpacity: 0.7,
      boxPadding: 10,
      lineWidth: 50,
      lineColor: "#333333"
    }
  },

  template: cdb.core.Template.compile(
    '
\

{{{ text }}}
\

\

',
    'mustache'
  ),

  events: {
    "click": "stopPropagation"
  },

  stopPropagation: function(e) {
    e.stopPropagation();
  },

  initialize: function() {

    this.template = this.options.template || this.template;
    this.mapView  = this.options.mapView;

    this._cleanStyleProperties(this.options.style);

    _.defaults(this.options.style, this.defaults.style);

    this._setupModels();

    this._bindMap();

  },

  _setupModels: function() {

    this.model = new cdb.core.Model({
      display: true,
      hidden: false,
      text:    this.options.text,
      latlng:  this.options.latlng,
      minZoom: this.options.minZoom || this.defaults.minZoom,
      maxZoom: this.options.maxZoom || this.defaults.maxZoom
    });

    this.model.on("change:display", this._onChangeDisplay, this);
    this.model.on("change:text",    this._onChangeText, this);
    this.model.on('change:latlng',  this._place, this);

    this.style = new cdb.core.Model(this.options.style);

    this.style.on("change", this._applyStyle, this);

    this.add_related_model(this.style);

  },

  _bindMap: function() {

    this.mapView.map.bind('change', this._place, this);
    this.mapView.map.bind('change:zoom', this._applyZoomLevelStyle, this);

    this.mapView.bind('zoomstart', this.hide, this);
    this.mapView.bind('zoomend', this.show, this);

  },

  _onChangeDisplay: function() {

    if (this.model.get("display")) this.show();
    else this.hide();

  },

  _onChangeText: function(e) {
    this.$el.find(".text").html(this.model.get("text"));
  },

  _getStandardPropertyName: function(name) {

    if (!name) return;
    var parts = name.split("-");

    if (parts.length === 1) return name;
    else if (parts.length === 2) {
      return parts[0] + parts[1].slice(0, 1).toUpperCase() + parts[1].slice(1);
    }

  },

  _cleanStyleProperties: function(hash) {

    var standardProperties = {};

    _.each(hash, function(value, key) {
      standardProperties[this._getStandardPropertyName(key)] = value;
    }, this);

    this.options.style = standardProperties;

  },

  show: function(callback) {

    if (this.model.get("hidden")) return;

    var self = this;

    this.$el.stop().delay(500).fadeIn(150, function() {
      self.$el.css({ display: "inline-table" }); // tricks
      callback && callback();
    });

  },

  hide: function(callback) {
    this.$el.fadeOut(150, function() {
      callback && callback();
    });
  },

  _place: function() {

    var latlng     = this.model.get("latlng");

    var lineWidth  = this.style.get("lineWidth");
    var textAlign  = this.style.get("textAlign");

    var pos        = this.mapView.latLonToPixel(latlng);
    var size       = this.mapView.getSize();
    var top        = pos.y - this.$el.height()/2;
    var left       = pos.x + lineWidth;

    if (textAlign === "right") {
      left = pos.x - this.$el.width() - lineWidth;
    }

    this.$el.css({ top: top, left: left });

  },

  setStyle: function(property, value) {

    var standardProperty = this._getStandardPropertyName(property);

    if (standardProperty) {
      this.style.set(standardProperty, value);
    }

  },

  _applyStyle: function() {

    var textColor  = this.style.get("color");
    var textAlign  = this.style.get("textAlign");
    var boxColor   = this.style.get("boxColor");
    var boxOpacity = this.style.get("boxOpacity");
    var boxPadding = this.style.get("boxPadding");
    var lineWidth  = this.style.get("lineWidth");
    var lineColor  = this.style.get("lineColor");
    var fontFamily = this.style.get("fontFamilyName");

    this.$text = this.$el.find(".text");

    this.$text.css({ color: textColor, textAlign: textAlign });

    this.$el.find(".content").css("padding", boxPadding);
    this.$text.css("font-size", this.style.get("fontSize") + "px");
    this.$el.css("z-index", this.style.get("zIndex"));

    this.$el.find(".stick").css({ width: lineWidth, left: -lineWidth });

    var fontFamilyClass = "";

    if      (fontFamily  == "Droid Sans") fontFamilyClass = "droid";
    else if (fontFamily  == "Vollkorn")   fontFamilyClass = "vollkorn";
    else if (fontFamily  == "Open Sans")  fontFamilyClass = "open_sans";
    else if (fontFamily  == "Roboto")     fontFamilyClass = "roboto";

    this.$el
    .removeClass("droid")
    .removeClass("vollkorn")
    .removeClass("roboto")
    .removeClass("open_sans");

    this.$el.addClass(fontFamilyClass);

    if (textAlign === "right") {
      this.$el.addClass("align-right");
      this.$el.find(".stick").css({ left: "auto", right: -lineWidth });
    } else {
      this.$el.removeClass("align-right");
    }

    this._place();
    this._applyZoomLevelStyle();

  },

  _getRGBA: function(color, opacity) {
    return 'rgba(' + parseInt(color.slice(-6,-4),16)
    + ',' + parseInt(color.slice(-4,-2),16)
    + ',' + parseInt(color.slice(-2),16)
    + ',' + opacity + ' )';
  },

  _applyZoomLevelStyle: function() {

    var boxColor   = this.style.get("boxColor");
    var boxOpacity = this.style.get("boxOpacity");
    var lineColor  = this.style.get("lineColor");

    var minZoom    = this.model.get("minZoom");
    var maxZoom    = this.model.get("maxZoom");

    var currentZoom = this.mapView.map.get("zoom");

    if (currentZoom >= minZoom && currentZoom <= maxZoom) {

      var rgbaLineCol = this._getRGBA(lineColor, 1);
      var rgbaBoxCol  = this._getRGBA(boxColor, boxOpacity);

      this.$el.find(".text").animate({ opacity: 1 }, 150);

      this.$el.css("background-color", rgbaBoxCol);

      this.$el.find(".stick").css("background-color", rgbaLineCol);
      this.$el.find(".ball").css("background-color", rgbaLineCol);

      this.model.set("hidden", false);
      this.model.set("display", true);

    } else {
      this.model.set("hidden", true);
      this.model.set("display", false);
    }
  },

  render: function() {

    this.$el.html(this.template(this.model.attributes));

    this._applyStyle();

    var self = this;

    setTimeout(function() {
      self._applyStyle();
      self._applyZoomLevelStyle();
    }, 500);

    return this;

  }

});
<commit_msg>shows the overlay after it has loaded<commit_after>cdb.geo.ui.Annotation = cdb.core.View.extend({

  className: "cartodb-overlay overlay-annotation",

  defaults: {
    minZoom: 0,
    maxZoom: 40,
    style: {
      textAlign: "left",
      zIndex: 5,
      color: "#ffffff",
      fontSize: "13",
      fontFamilyName: "Helvetica",
      boxColor: "#333333",
      boxOpacity: 0.7,
      boxPadding: 10,
      lineWidth: 50,
      lineColor: "#333333"
    }
  },

  template: cdb.core.Template.compile(
    '
\

{{{ text }}}
\

\

',
    'mustache'
  ),

  events: {
    "click": "stopPropagation"
  },

  stopPropagation: function(e) {
    e.stopPropagation();
  },

  initialize: function() {

    this.template = this.options.template || this.template;
    this.mapView  = this.options.mapView;

    this._cleanStyleProperties(this.options.style);

    _.defaults(this.options.style, this.defaults.style);

    this._setupModels();

    this._bindMap();

  },

  _setupModels: function() {

    this.model = new cdb.core.Model({
      display: true,
      hidden: false,
      text:    this.options.text,
      latlng:  this.options.latlng,
      minZoom: this.options.minZoom || this.defaults.minZoom,
      maxZoom: this.options.maxZoom || this.defaults.maxZoom
    });

    this.model.on("change:display", this._onChangeDisplay, this);
    this.model.on("change:text",    this._onChangeText, this);
    this.model.on('change:latlng',  this._place, this);

    this.style = new cdb.core.Model(this.options.style);

    this.style.on("change", this._applyStyle, this);

    this.add_related_model(this.style);

  },

  _bindMap: function() {

    this.mapView.map.bind('change', this._place, this);
    this.mapView.map.bind('change:zoom', this._applyZoomLevelStyle, this);

    this.mapView.bind('zoomstart', this.hide, this);
    this.mapView.bind('zoomend', this.show, this);

  },

  _onChangeDisplay: function() {

    if (this.model.get("display")) this.show();
    else this.hide();

  },

  _onChangeText: function(e) {
    this.$el.find(".text").html(this.model.get("text"));
  },

  _getStandardPropertyName: function(name) {

    if (!name) return;
    var parts = name.split("-");

    if (parts.length === 1) return name;
    else if (parts.length === 2) {
      return parts[0] + parts[1].slice(0, 1).toUpperCase() + parts[1].slice(1);
    }

  },

  _cleanStyleProperties: function(hash) {

    var standardProperties = {};

    _.each(hash, function(value, key) {
      standardProperties[this._getStandardPropertyName(key)] = value;
    }, this);

    this.options.style = standardProperties;

  },

  show: function(callback) {

    if (this.model.get("hidden")) return;

    var self = this;

    this.$el.stop().delay(500).fadeIn(150, function() {
      self.$el.css({ display: "inline-table" }); // tricks
      callback && callback();
    });

  },

  hide: function(callback) {
    this.$el.fadeOut(150, function() {
      callback && callback();
    });
  },

  _place: function() {

    var latlng     = this.model.get("latlng");

    var lineWidth  = this.style.get("lineWidth");
    var textAlign  = this.style.get("textAlign");

    var pos        = this.mapView.latLonToPixel(latlng);
    var size       = this.mapView.getSize();
    var top        = pos.y - this.$el.height()/2;
    var left       = pos.x + lineWidth;

    if (textAlign === "right") {
      left = pos.x - this.$el.width() - lineWidth;
    }

    this.$el.css({ top: top, left: left });

  },

  setStyle: function(property, value) {

    var standardProperty = this._getStandardPropertyName(property);

    if (standardProperty) {
      this.style.set(standardProperty, value);
    }

  },

  _applyStyle: function() {

    var textColor  = this.style.get("color");
    var textAlign  = this.style.get("textAlign");
    var boxColor   = this.style.get("boxColor");
    var boxOpacity = this.style.get("boxOpacity");
    var boxPadding = this.style.get("boxPadding");
    var lineWidth  = this.style.get("lineWidth");
    var lineColor  = this.style.get("lineColor");
    var fontFamily = this.style.get("fontFamilyName");

    this.$text = this.$el.find(".text");

    this.$text.css({ color: textColor, textAlign: textAlign });

    this.$el.find(".content").css("padding", boxPadding);
    this.$text.css("font-size", this.style.get("fontSize") + "px");
    this.$el.css("z-index", this.style.get("zIndex"));

    this.$el.find(".stick").css({ width: lineWidth, left: -lineWidth });

    var fontFamilyClass = "";

    if      (fontFamily  == "Droid Sans") fontFamilyClass = "droid";
    else if (fontFamily  == "Vollkorn")   fontFamilyClass = "vollkorn";
    else if (fontFamily  == "Open Sans")  fontFamilyClass = "open_sans";
    else if (fontFamily  == "Roboto")     fontFamilyClass = "roboto";

    this.$el
    .removeClass("droid")
    .removeClass("vollkorn")
    .removeClass("roboto")
    .removeClass("open_sans");

    this.$el.addClass(fontFamilyClass);

    if (textAlign === "right") {
      this.$el.addClass("align-right");
      this.$el.find(".stick").css({ left: "auto", right: -lineWidth });
    } else {
      this.$el.removeClass("align-right");
    }

    this._place();
    this._applyZoomLevelStyle();

  },

  _getRGBA: function(color, opacity) {
    return 'rgba(' + parseInt(color.slice(-6,-4),16)
    + ',' + parseInt(color.slice(-4,-2),16)
    + ',' + parseInt(color.slice(-2),16)
    + ',' + opacity + ' )';
  },

  _applyZoomLevelStyle: function() {

    var boxColor   = this.style.get("boxColor");
    var boxOpacity = this.style.get("boxOpacity");
    var lineColor  = this.style.get("lineColor");

    var minZoom    = this.model.get("minZoom");
    var maxZoom    = this.model.get("maxZoom");

    var currentZoom = this.mapView.map.get("zoom");

    if (currentZoom >= minZoom && currentZoom <= maxZoom) {

      var rgbaLineCol = this._getRGBA(lineColor, 1);
      var rgbaBoxCol  = this._getRGBA(boxColor, boxOpacity);

      this.$el.find(".text").animate({ opacity: 1 }, 150);

      this.$el.css("background-color", rgbaBoxCol);

      this.$el.find(".stick").css("background-color", rgbaLineCol);
      this.$el.find(".ball").css("background-color", rgbaLineCol);

      this.model.set("hidden", false);
      this.model.set("display", true);

    } else {
      this.model.set("hidden", true);
      this.model.set("display", false);
    }
  },

  render: function() {

    this.$el.html(this.template(this.model.attributes));

    this._applyStyle();

    var self = this;

    setTimeout(function() {
      self._applyStyle();
      self._applyZoomLevelStyle();
      self.show();
    }, 500);

    return this;

  }

});
<|endoftext|>


<commit_before>module.exports = {
  test_page: 'tests/index.html?hidepassed',
  disable_watching: true,
  launch_in_ci: ['Chrome'],
  launch_in_dev: ['Chrome'],
  browser_args: {
    Chrome: {
      mode: 'ci',
      args: ['--disable-gpu', '--headless', '--remote-debugging-port=0', '--window-size=1440,900']
    }
  }
};
<commit_msg>Pass --no-sandbox to Chrome in CI<commit_after>module.exports = {
  test_page: 'tests/index.html?hidepassed',
  disable_watching: true,
  launch_in_ci: ['Chrome'],
  launch_in_dev: ['Chrome'],
  browser_args: {
    Chrome: {
      mode: 'ci',
      args: [
        process.env.CI ? '--no-sandbox' : null,
        '--disable-gpu',
        '--headless',
        '--remote-debugging-port=0',
        '--window-size=1440,900'
      ].filter(Boolean)
    }
  }
};
<|endoftext|>


<commit_before>module.exports = {
  test_page: 'tests/index.html?hidepassed',
  disable_watching: true,
  launch_in_ci: [
    'Chrome'
  ],
  launch_in_dev: [
    'Chrome'
  ],
  browser_args: {
    Chrome: {
      ci: [
        // --no-sandbox is needed when running Chrome inside a container
        process.env.CI ? '--no-sandbox' : null,
        '--headless',
        '--disable-gpu',
        '--disable-dev-shm-usage',
        '--disable-software-rasterizer',
        '--mute-audio',
        '--remote-debugging-port=0',
        '--window-size=1440,900'
      ].filter(Boolean)
    }
  }
};
<commit_msg>testem: disable gpu on CI only<commit_after>module.exports = {
  test_page: 'tests/index.html?hidepassed',
  disable_watching: true,
  launch_in_ci: [
    'Chrome'
  ],
  launch_in_dev: [
    'Chrome'
  ],
  browser_args: {
    Chrome: {
      ci: [
        // --no-sandbox is needed when running Chrome inside a container
        process.env.CI ? '--no-sandbox' : null,
        process.env.CI ? '--disable-gpu' : null,
        '--headless',
        '--disable-dev-shm-usage',
        '--disable-software-rasterizer',
        '--mute-audio',
        '--remote-debugging-port=0',
        '--window-size=1440,900'
      ].filter(Boolean)
    }
  }
};
<|endoftext|>


<commit_before>/**This module searches for new ip addresses and tests thhem for validity**/
//Main process tells you to stop searching
//you return -1 for no tested ip found but search is still on
//you return -2 for no tested ip found and all untested ips have been tested and search has stopped
//Exports important functions to calling program
module.exports = function(cb , urlObj , done) {
	console.log(cb);
	console.log('tester working');

	var request = require('request');
	var curl = require('curlrequest');
	var LineByLineReader = require('line-by-line');

	var goodIps = [];
	var goodIpIndex = 0;

	var untestedIps = [];
	var untestedIpIndex=0;

	//
	var STOP_SEARCH =false;

	//

    //Use fall back for the mean time before building your own what to do?
    //Read lines of ip use them to make request before resulting to gimmeproxy
	/*pl = new LineByLineReader('proxies.txt');
	pl.on('error', function (err) {
		console.log('error while reading file');
	});

	pl.on('line', function (line) {
		untestedIps.push(line.toString());
	});

	pl.on('end', function () {
	   console.log(untestedIps.length);
	   STOP_SEARCH = true;
	});*/

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

	function getIp(){
		if(!STOP_SEARCH){
			 request.get('http://gimmeproxy.com/api/getProxy' , function(err , response , body){
				 if(err){
					 //console.log('cannot get ip address');
					 getIp();
				 }
				 else {
					 if(untestedIps.length > 2500){
						 STOP_SEARCH = true;
					 }

	                 try {
						 var rawIp = JSON.parse(body);
						 if(rawIp.curl.indexOf('socks')<0){
						 	 untestedIps.push('http://'+rawIp.ip);
						 }

						 setTimeout(function(){
						 	getIp();
						 } ,500)
					 }
					 catch (err) {
						  // Handle the error here.
						   console.log(err+' =============================================================here');
						   setTimeout(function(){
						 	  getIp();
						   } ,500)
					 }

				 }
			 });
		}
		else{
			console.log('ip searching stopped');
			return;
		}
	};
    getIp();

	//
	var testIp = function(){
		if(untestedIpIndex<untestedIps.length){
			var raw = untestedIps[untestedIpIndex];
			console.log(raw);
		    var options = {
				url: 'https://fg1.herokuapp.com',
				retries: 5,
				headers: {
					'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
				},
				timeout: 15,
				proxy: raw
			 };

			 curl.request(options, function(err, res) {
				   if(err){
						 console.log('Cannot test proxy');
						 untestedIpIndex++;
						 return testIp();
					 }
					 else {
						 if(res){
							 console.log('test done');
							 goodIps.push(raw);
							 untestedIpIndex++;
							 cb(raw , urlObj.url , urlObj.selector);
							 return testIp();
						 }
						 else {
							 console.log('invalid proxy');
							 untestedIpIndex++;
							 return testIp();
						 }
					 }
			 });
		}
		else{
		    if(STOP_SEARCH && (untestedIpIndex==untestedIps.length)){
		    	 console.log('All ips have been tested stopping testing phase');
		    	 done();
				 return;
			}
			else{
			    console.log('No untested ips will retry in 30secs');
				return setTimeout(function(){
					return testIp();
				} , 30000);
			}

		}

	}
	//Kick start the testing process
	testIp();

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

	//
	var stopSearch = function(cb){
		STOP_SEARCH = true;
		cb();
	}

	//
	var getFound = function(){
		return {good:goodIps.length, tested:untestedIpIndex};
	}

	return {
	    getFound:getFound,
	    stopSearch : stopSearch
	}

};<commit_msg>Signed-off-by: codemuhammed <codemuhammed@gmail.com><commit_after>/**This module searches for new ip addresses and tests thhem for validity**/
//Main process tells you to stop searching
//you return -1 for no tested ip found but search is still on
//you return -2 for no tested ip found and all untested ips have been tested and search has stopped
//Exports important functions to calling program
module.exports = function(cb , urlObj , done) {
	console.log(cb);
	console.log('tester working');

	var request = require('request');
	var curl = require('curlrequest');
	var LineByLineReader = require('line-by-line');

	var goodIps = [];
	var goodIpIndex = 0;

	var untestedIps = [];
	var untestedIpIndex=0;

	//
	var STOP_SEARCH =false;

	//

    //Use fall back for the mean time before building your own what to do?
    //Read lines of ip use them to make request before resulting to gimmeproxy
	/*pl = new LineByLineReader('proxies.txt');
	pl.on('error', function (err) {
		console.log('error while reading file');
	});

	pl.on('line', function (line) {
		untestedIps.push(line.toString());
	});

	pl.on('end', function () {
	   console.log(untestedIps.length);
	   STOP_SEARCH = true;
	});*/

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

	function getIp(){
		if(!STOP_SEARCH){
			 request.get('http://gimmeproxy.com/api/getProxy' , function(err , response , body){
				 if(err){
					 //console.log('cannot get ip address');
					 getIp();
				 }
				 else {
					 if(untestedIps.length > 2500){
						 STOP_SEARCH = true;
					 }

	                 try {
						 var rawIp = JSON.parse(body);
						 if(rawIp.curl.indexOf('socks')<0){
						 	 untestedIps.push('http://'+rawIp.ip);
						 }

						 setTimeout(function(){
						 	getIp();
						 } ,500)
					 }
					 catch (err) {
						  // Handle the error here.
						   console.log(err+' =============================================================here');
						   setTimeout(function(){
						 	  getIp();
						   } ,500)
					 }

				 }
			 });
		}
		else{
			console.log('ip searching stopped');
			return;
		}
	};
    getIp();

	//
	var testIp = function(){
		if(untestedIpIndex<untestedIps.length){
			var raw = untestedIps[untestedIpIndex];
			console.log(raw);
		    var options = {
				url: 'https://fg1.herokuapp.com',
				retries: 5,
				headers: {
					'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
				},
				timeout: 15,
				proxy: raw
			 };

			 curl.request(options, function(err, res) {
				   if(err){
						 console.log('Cannot test proxy');
						 untestedIpIndex++;
						 return testIp();
					 }
					 else {
						 if(res){
							 console.log('test done');
							 goodIps.push(raw);
							 untestedIpIndex++;
							 cb(raw , urlObj.url , urlObj.selector);
							 return testIp();
						 }
						 else {
							 console.log('invalid proxy');
							 untestedIpIndex++;
							 return testIp();
						 }
					 }
			 });
		}
		else{
		    if(STOP_SEARCH && (untestedIpIndex==untestedIps.length)){
		    	 console.log('All ips have been tested stopping testing phase');
		    	 done();
				 return;
			}
			else{
			    console.log('No untested ips will retry in 30secs');
				return setTimeout(function(){
					return testIp();
				} , 30000);
			}

		}

	}
	//Kick start the testing process
	testIp();

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

	//
	var stopSearch = function(cb){
		STOP_SEARCH = true;
		cb();
	}

	//
	var getFound = function(){
		return {good:goodIps.length, tested:untestedIpIndex};
	}

	return {
	    getFound:getFound,
	    stopSearch : stopSearch
	}

};<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');
const async = require('async');
const log = require('util').log;
const handlebars = require("handlebars");

let importer = {

    /**
     * Function that fetches a config repository for any user defined custom files
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    get(options, cb) {
        log(`Fetching custom ${options.type} files ...`);
        let env = ((process.env.SOAJS_ENV) ? process.env.SOAJS_ENV.toLowerCase() : 'dev');

        // if config repo contains custom files, process them
        if (options.config &&
            options.config.setup &&
            options.config.setup[env] &&
            options.config.setup[env].nginx &&
            options.config.setup[env].nginx[options.type] &&
            options.config.setup[env].nginx[options.type].path) {

            let importPath = path.join(options.paths.configRepo.path, options.config.setup[env].nginx[options.type].path);
            if (options.isDirectory) {
                importPath = path.join(importPath, '/');
            }

            // check access to specified custom folder path
            fs.access(importPath, fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK, (error) => {
                if (error) {
                    log(`Custom ${options.type} detected but not reachable, skipping ...`);
                    log(`Unable to get custom ${options.type}, make sure the path specified in the config.json file is correct and that the folder/file exists ...`);
                    log(error);
                    return cb();
                }

                options.paths.import = { path: importPath };
                if (options.isDirectory) {
                    // Read the custom directory content
                    fs.readdir(options.paths.import.path, (error, files) => {
                        if (error) {
                            log(`Unable to read the content of ${options.type} directory ${options.paths.import.path}, aborting ...`);
                            log(error);
                            return cb();
                        }

                        options.files = files;
                        return importer.read(options, cb);
                    });
                }
                else {
                    let importPathArr = importPath.split('/');

                    options.paths.import.path = importPathArr.slice(0, importPathArr.length - 1).join('/');
                    options.files = [ importPathArr[importPathArr.length - 1] ];
                    return importer.read(options, cb);
                }
            });
        }
        else {
            // if config repo does not contain custom file, return
            log(`No custom ${options.type} detected, proceeding ...`);
            return cb();
        }
    },

    /**
     * Function that reads custom files from a given directory and passes them to another function to be processed
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    read(options, cb) {
        log(`Processing custom ${options.type} file(s) ...`);

        // read the contents of all custom files and pass them to the 'process' function
        async.map(options.files, (oneFile, callback) => {
            let onePath = path.join (options.paths.import.path, oneFile);
            fs.readFile(onePath, (error, fileData) => {
                if (error) {
                    log(`An error occured while reading ${onePath}, skipping file ...`);
                    log(error);
                    return callback();
                }

                return callback(null, fileData);
            });
        }, (error, importData) => {
            // no error will be returned, errors are only logged and files will be skipped
            options.data = { files: importData };
            return importer.process(options, cb);
        });
    },

    /**
     * Function that processes the contents of custom files, searches for placeholders and replaces them if applicable
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    process(options, cb) {

        // before processing, filter out all files that were not read properly because of an error
        async.filter(options.data.files, (oneEntry, callback) => {
            return callback(null, oneEntry);
        }, (error, importEntries) => {
            // convert each custom file from buffer to utf8 string and split based on space
            async.map(importEntries, (oneImport, callback) => {
                let importData = oneImport.toString('utf8');
                let dataArray = importData.split(' ');

                // go through every entry in array, search for placeholders and replace if applicable
                async.map(dataArray, (oneArrayEntry, callback) => {

                	//compile the incoming file content
                	let template = handlebars.compile(oneArrayEntry);

                	//use the compile version to render the env variables
	                let out = template(process.env);

	                //return the output via callback
	                return callback(null, out);

                    // let matches = oneArrayEntry.match(/{{[^}}]*}}/g);
                    // if (matches && matches.length > 0) {
                    //     for (let i = 0; i < matches.length; i++) {
                    //         let placeholder = matches[i].substring(2, matches[i].length - 2);
                    //         if (process.env[placeholder]) {
                    //             let replacementRegExp = new RegExp(matches[i], 'g');
                    //             oneArrayEntry = oneArrayEntry.replace(replacementRegExp, process.env[placeholder]);
                    //         }
                    //     }
                    // }
                    //
                    // return callback(null, oneArrayEntry);

                }, (error, updatedArrayEntries) => {
                    // no errors will be returned
                    // join the array back to a single string and return
                    return callback(null, updatedArrayEntries.join(' '));
                });
            }, (error, updatedFiles) => {
                // no errors will be returned
                options.data.updatedFiles = updatedFiles;
                return importer.write(options, cb);
            });
        });
    },

    /**
     * Function that writes processed custom files to the nginx target directory (or equivalent)
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    write(options, cb) {
        // at this point, all custom files were processed and all placeholders were replaced with equivalent environment variables if applicable
        // write the files to the nginx folder

        async.eachOf(options.data.updatedFiles, (oneFile, index, callback) => {
            let filePath = path.join (options.targetDir, `${options.type}-${index}.conf`);
            // nginx.conf file should preserve file name
            if (options.type === 'conf' && options.data.updatedFiles.length === 1) {
                filePath = path.join (options.targetDir, `nginx.conf`);
            }

            fs.writeFile(filePath, oneFile, (error) => {
                if (error) {
                    log(`An error occured while writing ${filePath}, skipping file ...`);
                    log(error);
                }

                return callback();
            });
        }, (error) => {
            // no errors will be returned, errors while writing files will be logged and the files will be skipped
            log(`Custom ${options.type} files were loaded, DONE`);
            return cb();
        });
    }

};

module.exports = {
    import: importer.get
};
<commit_msg>Updated importer.js process() function<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const async = require('async');
const log = require('util').log;
const handlebars = require("handlebars");

let importer = {

    /**
     * Function that fetches a config repository for any user defined custom files
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    get(options, cb) {
        log(`Fetching custom ${options.type} files ...`);
        let env = ((process.env.SOAJS_ENV) ? process.env.SOAJS_ENV.toLowerCase() : 'dev');

        // if config repo contains custom files, process them
        if (options.config &&
            options.config.setup &&
            options.config.setup[env] &&
            options.config.setup[env].nginx &&
            options.config.setup[env].nginx[options.type] &&
            options.config.setup[env].nginx[options.type].path) {

            let importPath = path.join(options.paths.configRepo.path, options.config.setup[env].nginx[options.type].path);
            if (options.isDirectory) {
                importPath = path.join(importPath, '/');
            }

            // check access to specified custom folder path
            fs.access(importPath, fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK, (error) => {
                if (error) {
                    log(`Custom ${options.type} detected but not reachable, skipping ...`);
                    log(`Unable to get custom ${options.type}, make sure the path specified in the config.json file is correct and that the folder/file exists ...`);
                    log(error);
                    return cb();
                }

                options.paths.import = { path: importPath };
                if (options.isDirectory) {
                    // Read the custom directory content
                    fs.readdir(options.paths.import.path, (error, files) => {
                        if (error) {
                            log(`Unable to read the content of ${options.type} directory ${options.paths.import.path}, aborting ...`);
                            log(error);
                            return cb();
                        }

                        options.files = files;
                        return importer.read(options, cb);
                    });
                }
                else {
                    let importPathArr = importPath.split('/');

                    options.paths.import.path = importPathArr.slice(0, importPathArr.length - 1).join('/');
                    options.files = [ importPathArr[importPathArr.length - 1] ];
                    return importer.read(options, cb);
                }
            });
        }
        else {
            // if config repo does not contain custom file, return
            log(`No custom ${options.type} detected, proceeding ...`);
            return cb();
        }
    },

    /**
     * Function that reads custom files from a given directory and passes them to another function to be processed
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    read(options, cb) {
        log(`Processing custom ${options.type} file(s) ...`);

        // read the contents of all custom files and pass them to the 'process' function
        async.map(options.files, (oneFile, callback) => {
            let onePath = path.join (options.paths.import.path, oneFile);
            fs.readFile(onePath, (error, fileData) => {
                if (error) {
                    log(`An error occured while reading ${onePath}, skipping file ...`);
                    log(error);
                    return callback();
                }

                return callback(null, fileData);
            });
        }, (error, importData) => {
            // no error will be returned, errors are only logged and files will be skipped
            options.data = { files: importData };
            return importer.process(options, cb);
        });
    },

    /**
     * Function that processes the contents of custom files, searches for placeholders and replaces them if applicable
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    process(options, cb) {

        // before processing, filter out all files that were not read properly because of an error
        async.filter(options.data.files, (oneEntry, callback) => {
            return callback(null, oneEntry);
        }, (error, importEntries) => {
            // convert each custom file from buffer to utf8 string and split based on space
            async.map(importEntries, (oneImport, callback) => {
                let importData = oneImport.toString('utf8');

                //compile the incoming file content
                let template = handlebars.compile(importData);

                //use the compile version to render the env variables
                let out = template(process.env);

                //return the output via callback
                return callback(null, out);
            }, (error, updatedFiles) => {
                // no errors will be returned
                options.data.updatedFiles = updatedFiles;
                return importer.write(options, cb);
            });
        });
    },

    /**
     * Function that writes processed custom files to the nginx target directory (or equivalent)
     * @param  {Object}   options An object that contains params passed to the function
     * @param  {Function} cb      Callback function
     *
     */
    write(options, cb) {
        // at this point, all custom files were processed and all placeholders were replaced with equivalent environment variables if applicable
        // write the files to the nginx folder

        async.eachOf(options.data.updatedFiles, (oneFile, index, callback) => {
            let filePath = path.join (options.targetDir, `${options.type}-${index}.conf`);
            // nginx.conf file should preserve file name
            if (options.type === 'conf' && options.data.updatedFiles.length === 1) {
                filePath = path.join (options.targetDir, `nginx.conf`);
            }

            fs.writeFile(filePath, oneFile, (error) => {
                if (error) {
                    log(`An error occured while writing ${filePath}, skipping file ...`);
                    log(error);
                }

                return callback();
            });
        }, (error) => {
            // no errors will be returned, errors while writing files will be logged and the files will be skipped
            log(`Custom ${options.type} files were loaded, DONE`);
            return cb();
        });
    }

};

module.exports = {
    import: importer.get
};
<|endoftext|>


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

// Query display
// =============

var GLYPHICON_DEFAULT = {color: '#1edcff'};
var GLYPHICON_HIGHLIGHT = {color: '#999999'};

var STATE_COLOR_MAP = {
    QUEUED: '#1b8f72',
    RUNNING: '#19874e',
    PLANNING: '#824b98',
    FINISHED: '#1a4629',
    BLOCKED: '#685b72',
    USER_ERROR: '#a67559',
    USER_CANCELED: '#858959',
    INSUFFICIENT_RESOURCES: '#7f5b72',
    EXTERNAL_ERROR: '#caa55c',
    UNKNOWN_ERROR: '#943524'
};

function getQueryStateColor(query)
{
    switch (query.state) {
        case "QUEUED":
            return STATE_COLOR_MAP.QUEUED;
        case "PLANNING":
            return STATE_COLOR_MAP.PLANNING;
        case "STARTING":
        case "RUNNING":
        case "FINISHING":
            return STATE_COLOR_MAP.RUNNING;
        case "FAILED":
            switch (query.errorType) {
                case "USER_ERROR":
                    if (query.errorCode.name === 'USER_CANCELED') {
                        return STATE_COLOR_MAP.USER_CANCELED;
                    }
                    return STATE_COLOR_MAP.USER_ERROR;
                case "EXTERNAL":
                    return STATE_COLOR_MAP.EXTERNAL_ERROR;
                case "INSUFFICIENT_RESOURCES":
                    return STATE_COLOR_MAP.INSUFFICIENT_RESOURCES;
                default:
                    return STATE_COLOR_MAP.UNKNOWN_ERROR;
            }
        case "FINISHED":
            return STATE_COLOR_MAP.FINISHED;
        default:
            return STATE_COLOR_MAP.QUEUED;
    }
}

function getStageStateColor(state)
{
    switch (state) {
        case "PLANNED":
            return STATE_COLOR_MAP.QUEUED;
        case "SCHEDULING":
        case "SCHEDULING_SPLITS":
        case "SCHEDULED":
            return STATE_COLOR_MAP.PLANNING;
        case "RUNNING":
            return STATE_COLOR_MAP.RUNNING;
        case "FINISHED":
            return STATE_COLOR_MAP.FINISHED;
        case "CANCELED":
        case "ABORTED":
        case "FAILED":
            return STATE_COLOR_MAP.UNKNOWN_ERROR;
        default:
            return "#b5b5b5"
    }
}

// This relies on the fact that BasicQueryInfo and QueryInfo have all the fields
// necessary to compute this string, and that these fields are consistently named.
function getHumanReadableState(query)
{
    if (query.state == "RUNNING") {
        if (query.scheduled && query.queryStats.totalDrivers > 0 && query.queryStats.runningDrivers >= 0) {
            return "RUNNING";
        }

        if (query.queryStats.fullyBlocked) {
            return "BLOCKED (" + query.queryStats.blockedReasons.join(", ") + ")";
        }

        if (query.memoryPool === "reserved") {
            return "RUNNING (RESERVED)";
        }
    }

    if (query.state == "FAILED") {
        switch (query.errorType) {
            case "USER_ERROR":
                if (query.errorCode.name === "USER_CANCELED") {
                    return "USER CANCELED";
                }
                return "USER ERROR";
            case "INTERNAL_ERROR":
                return "INTERNAL ERROR";
            case "INSUFFICIENT_RESOURCES":
                return "INSUFFICIENT RESOURCES";
            case "EXTERNAL":
                return "EXTERNAL ERROR";
        }
    }

    return query.state;
}

function isProgressMeaningful(query)
{
    return query.scheduled && query.state == "RUNNING" && query.queryStats.totalDrivers > 0 && query.queryStats.completedDrivers > 0;
}

function getProgressBarPercentage(query)
{
    if (isProgressMeaningful(query)) {
        return Math.round((query.queryStats.completedDrivers * 100.0) / query.queryStats.totalDrivers);
    }

    // progress bars should appear 'full' when query progress is not meaningful
    return 100;
}

function getProgressBarTitle(query)
{
    if (isProgressMeaningful(query)) {
        return getHumanReadableState(query) + " (" + getProgressBarPercentage(query) + "%)"
    }

    return getHumanReadableState(query)
}

// Sparkline-related functions
// ===========================

// display at most 5 minutes worth of data on the sparklines
var MAX_HISTORY = 60 * 5;
 // alpha param of exponentially weighted moving average. picked arbitrarily - lower values means more smoothness
var MOVING_AVERAGE_ALPHA = 0.2;

function addToHistory (value, valuesArray) {
    if (valuesArray.length == 0) {
        return valuesArray.concat([value]);
    }
    return valuesArray.concat([value]).slice(Math.max(valuesArray.length - MAX_HISTORY, 0));
}

function addExponentiallyWeightedToHistory (value, valuesArray) {
    if (valuesArray.length == 0) {
        return valuesArray.concat([value]);
    }

    var movingAverage = (value * MOVING_AVERAGE_ALPHA) + (valuesArray[valuesArray.length - 1] * (1 - MOVING_AVERAGE_ALPHA));
    if (value < 1) {
        movingAverage = 0;
    }

    return valuesArray.concat([movingAverage]).slice(Math.max(valuesArray.length - MAX_HISTORY, 0));
}

// DagreD3 Graph-related functions
// ===============================

function initializeGraph()
{
    return new dagreD3.graphlib.Graph({compound: true})
        .setGraph({rankdir: 'BT'})
        .setDefaultEdgeLabel(function () { return {}; });
}

function initializeSvg(selector)
{
    const svg = d3.select(selector);
    svg.append("g");

    return svg;
}

function computeSources(nodeInfo)
{
    let sources = [];
    let remoteSources = []; // TODO: put remoteSources in node-specific section
    switch (nodeInfo['@type']) {
        case 'output':
        case 'explainAnalyze':
        case 'project':
        case 'filter':
        case 'aggregation':
        case 'sort':
        case 'markDistinct':
        case 'window':
        case 'rowNumber':
        case 'topnRowNumber':
        case 'limit':
        case 'distinctlimit':
        case 'topn':
        case 'sample':
        case 'tablewriter':
        case 'delete':
        case 'metadatadelete':
        case 'tablecommit':
        case 'groupid':
        case 'unnest':
        case 'scalar':
            sources = [nodeInfo.source];
            break;
        case 'join':
            sources = [nodeInfo.left, nodeInfo.right];
            break;
        case 'semijoin':
            sources = [nodeInfo.source, nodeInfo.filteringSource];
            break;
        case 'indexjoin':
            sources = [nodeInfo.probeSource, nodeInfo.filterSource];
            break;
        case 'union':
        case 'exchange':
            sources = nodeInfo.sources;
            break;
        case 'remoteSource':
            remoteSources = nodeInfo.sourceFragmentIds;
            break;
        case 'tablescan':
        case 'values':
        case 'indexsource':
            break;
        default:
            console.log("NOTE: Unhandled PlanNode: " + nodeInfo['@type']);
    }

    return [sources, remoteSources];
}

// Utility functions
// =================

function truncateString(inputString, length) {
    if (inputString && inputString.length > length) {
        return inputString.substring(0, length) + "...";
    }

    return inputString;
}

function getStageId(stageId) {
    return stageId.slice(stageId.indexOf('.') + 1, stageId.length)
}

function getTaskIdSuffix(taskId) {
    return taskId.slice(taskId.indexOf('.') + 1, taskId.length)
}

function getTaskIdInStage(taskId) {
    return Number.parseInt(getTaskIdSuffix(getTaskIdSuffix(taskId)));
}

function formatState(state, fullyBlocked) {
    if (fullyBlocked && state == "RUNNING") {
        return "BLOCKED";
    }
    else {
        return state;
    }
}

function getHostname(url) {
    var hostname = new URL(url).hostname;
    if ((hostname.charAt(0) == '[') && (hostname.charAt(hostname.length - 1) == ']')) {
        hostname = hostname.substr(1, hostname.length - 2);
    }
    return hostname;
}

function getPort(url) {
    return new URL(url).port;
}

function getHostAndPort(url) {
    var url = new URL(url);
    return url.hostname + ":" + url.port;
}

function computeRate(count, ms) {
    if (ms == 0) {
        return 0;
    }
    return (count / ms) * 1000.0;
}

function precisionRound(n) {
    if (n < 10) {
        return n.toFixed(2);
    }
    if (n < 100) {
        return n.toFixed(1);
    }
    return Math.round(n);
}

function formatDuration(duration) {
    var unit = "ms";
    if (duration > 1000) {
        duration /= 1000;
        unit = "s";
    }
    if (unit == "s" && duration > 60) {
        duration /= 60;
        unit = "m";
    }
    if (unit == "m" && duration > 60) {
        duration /= 60;
        unit = "h";
    }
    if (unit == "h" && duration > 24) {
        duration /= 24;
        unit = "d";
    }
    if (unit == "d" && duration > 7) {
        duration /= 7;
        unit = "w";
    }
    return precisionRound(duration) + unit;
}

function formatCount(count) {
    var unit = "";
    if (count > 1000) {
        count /= 1000;
        unit = "K";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "M";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "B";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "T";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "Q";
    }
    return precisionRound(count) + unit;
}

function formatDataSizeBytes(size) {
    return formatDataSizeMinUnit(size, "");
}

function formatDataSize(size) {
    return formatDataSizeMinUnit(size, "B");
}

function formatDataSizeMinUnit(size, minUnit) {
    var unit = minUnit;
    if (size == 0) {
        return "0" + unit;
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "K";
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "M";
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "G";
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "T";
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "P";
    }
    return precisionRound(size) + unit;
}

function parseDataSize(value) {
    var DATA_SIZE_PATTERN = /^\s*(\d+(?:\.\d+)?)\s*([a-zA-Z]+)\s*$/
    var match = DATA_SIZE_PATTERN.exec(value);
    if (match == null) {
        return null;
    }
    var number = parseFloat(match[1]);
    switch (match[2]) {
        case "B":
            return number;
        case "kB":
            return number * Math.pow(2, 10);
        case "MB":
            return number * Math.pow(2, 20);
        case "GB":
            return number * Math.pow(2, 30);
        case "TB":
            return number * Math.pow(2, 40);
        case "PB":
            return number * Math.pow(2, 50);
        default:
            return null;
    }
}

function parseDuration(value) {
    var DURATION_PATTERN = /^\s*(\d+(?:\.\d+)?)\s*([a-zA-Z]+)\s*$/

    var match = DURATION_PATTERN.exec(value);
    if (match == null) {
        return null;
    }
    var number = parseFloat(match[1]);
    switch (match[2]) {
        case "ns":
            return number / 1000000.0;
        case "us":
            return number / 1000.0;
        case "ms":
            return number;
        case "s":
            return number * 1000;
        case "m":
            return number * 1000 * 60;
        case "h":
            return number * 1000 * 60 * 60;
        case "d":
            return number * 1000 * 60 * 60 * 24;
        default:
            return null;
    }
}

function formatStackTrace(info) {
    return doFormatStackTrace(info, [], "", "");
}

function doFormatStackTrace(info, parentStack, prefix, linePrefix) {
    var s = linePrefix + prefix + failureInfoToString(info) + "\n";

    if (info.stack != null) {
        var sharedStackFrames = 0;
        if (parentStack != null) {
            sharedStackFrames = countSharedStackFrames(info.stack, parentStack);
        }

        for (var i = 0; i < info.stack.length - sharedStackFrames; i++) {
            s += linePrefix + "\tat " + info.stack[i] + "\n";
        }
        if (sharedStackFrames !== 0) {
            s += linePrefix + "\t... " + sharedStackFrames + " more" + "\n";
        }
    }

    if (info.suppressed != null) {
        for (var i = 0; i < info.suppressed.length; i++) {
            s += doFormatStackTrace(info.suppressed[i], info.stack, "Suppressed: ", linePrefix + "\t");
        }
    }

    if (info.cause != null) {
        s += doFormatStackTrace(info.cause, info.stack, "Caused by: ", linePrefix);
    }

    return s;
}

function countSharedStackFrames(stack, parentStack) {
    var n = 0;
    var minStackLength = Math.min(stack.length, parentStack.length);
    while (n < minStackLength && stack[stack.length - 1 - n] === parentStack[parentStack.length - 1 - n]) {
        n++;
    }
    return n;
}

function failureInfoToString(t) {
    return (t.message != null) ? (t.type + ": " + t.message) : t.type;
}

function formatShortTime(date) {
    var hours = (date.getHours() % 12) || 12;
    var minutes = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes();
    return hours + ":" + minutes + (date.getHours() >= 12 ? "pm" : "am");
}

function formatShortDateTime(date) {
    var year = date.getFullYear();
    var month = "" + (date.getMonth() + 1);
    var dayOfMonth  = "" + date.getDate();
    return year + "-" + (month[1] ? month : "0" + month[0]) + "-" + (dayOfMonth[1] ? dayOfMonth: "0" + dayOfMonth[0]) + " " + formatShortTime(date);
}

function removeQueryId(id) {
    var pos = id.indexOf('.');
    if (pos != -1) {
        return id.substring(pos + 1);
    }
    return id;
}
<commit_msg>Fix formatDataSize to include min unit<commit_after>/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Query display
// =============

var GLYPHICON_DEFAULT = {color: '#1edcff'};
var GLYPHICON_HIGHLIGHT = {color: '#999999'};

var STATE_COLOR_MAP = {
    QUEUED: '#1b8f72',
    RUNNING: '#19874e',
    PLANNING: '#824b98',
    FINISHED: '#1a4629',
    BLOCKED: '#685b72',
    USER_ERROR: '#a67559',
    USER_CANCELED: '#858959',
    INSUFFICIENT_RESOURCES: '#7f5b72',
    EXTERNAL_ERROR: '#caa55c',
    UNKNOWN_ERROR: '#943524'
};

function getQueryStateColor(query)
{
    switch (query.state) {
        case "QUEUED":
            return STATE_COLOR_MAP.QUEUED;
        case "PLANNING":
            return STATE_COLOR_MAP.PLANNING;
        case "STARTING":
        case "RUNNING":
        case "FINISHING":
            return STATE_COLOR_MAP.RUNNING;
        case "FAILED":
            switch (query.errorType) {
                case "USER_ERROR":
                    if (query.errorCode.name === 'USER_CANCELED') {
                        return STATE_COLOR_MAP.USER_CANCELED;
                    }
                    return STATE_COLOR_MAP.USER_ERROR;
                case "EXTERNAL":
                    return STATE_COLOR_MAP.EXTERNAL_ERROR;
                case "INSUFFICIENT_RESOURCES":
                    return STATE_COLOR_MAP.INSUFFICIENT_RESOURCES;
                default:
                    return STATE_COLOR_MAP.UNKNOWN_ERROR;
            }
        case "FINISHED":
            return STATE_COLOR_MAP.FINISHED;
        default:
            return STATE_COLOR_MAP.QUEUED;
    }
}

function getStageStateColor(state)
{
    switch (state) {
        case "PLANNED":
            return STATE_COLOR_MAP.QUEUED;
        case "SCHEDULING":
        case "SCHEDULING_SPLITS":
        case "SCHEDULED":
            return STATE_COLOR_MAP.PLANNING;
        case "RUNNING":
            return STATE_COLOR_MAP.RUNNING;
        case "FINISHED":
            return STATE_COLOR_MAP.FINISHED;
        case "CANCELED":
        case "ABORTED":
        case "FAILED":
            return STATE_COLOR_MAP.UNKNOWN_ERROR;
        default:
            return "#b5b5b5"
    }
}

// This relies on the fact that BasicQueryInfo and QueryInfo have all the fields
// necessary to compute this string, and that these fields are consistently named.
function getHumanReadableState(query)
{
    if (query.state == "RUNNING") {
        if (query.scheduled && query.queryStats.totalDrivers > 0 && query.queryStats.runningDrivers >= 0) {
            return "RUNNING";
        }

        if (query.queryStats.fullyBlocked) {
            return "BLOCKED (" + query.queryStats.blockedReasons.join(", ") + ")";
        }

        if (query.memoryPool === "reserved") {
            return "RUNNING (RESERVED)";
        }
    }

    if (query.state == "FAILED") {
        switch (query.errorType) {
            case "USER_ERROR":
                if (query.errorCode.name === "USER_CANCELED") {
                    return "USER CANCELED";
                }
                return "USER ERROR";
            case "INTERNAL_ERROR":
                return "INTERNAL ERROR";
            case "INSUFFICIENT_RESOURCES":
                return "INSUFFICIENT RESOURCES";
            case "EXTERNAL":
                return "EXTERNAL ERROR";
        }
    }

    return query.state;
}

function isProgressMeaningful(query)
{
    return query.scheduled && query.state == "RUNNING" && query.queryStats.totalDrivers > 0 && query.queryStats.completedDrivers > 0;
}

function getProgressBarPercentage(query)
{
    if (isProgressMeaningful(query)) {
        return Math.round((query.queryStats.completedDrivers * 100.0) / query.queryStats.totalDrivers);
    }

    // progress bars should appear 'full' when query progress is not meaningful
    return 100;
}

function getProgressBarTitle(query)
{
    if (isProgressMeaningful(query)) {
        return getHumanReadableState(query) + " (" + getProgressBarPercentage(query) + "%)"
    }

    return getHumanReadableState(query)
}

// Sparkline-related functions
// ===========================

// display at most 5 minutes worth of data on the sparklines
var MAX_HISTORY = 60 * 5;
 // alpha param of exponentially weighted moving average. picked arbitrarily - lower values means more smoothness
var MOVING_AVERAGE_ALPHA = 0.2;

function addToHistory (value, valuesArray) {
    if (valuesArray.length == 0) {
        return valuesArray.concat([value]);
    }
    return valuesArray.concat([value]).slice(Math.max(valuesArray.length - MAX_HISTORY, 0));
}

function addExponentiallyWeightedToHistory (value, valuesArray) {
    if (valuesArray.length == 0) {
        return valuesArray.concat([value]);
    }

    var movingAverage = (value * MOVING_AVERAGE_ALPHA) + (valuesArray[valuesArray.length - 1] * (1 - MOVING_AVERAGE_ALPHA));
    if (value < 1) {
        movingAverage = 0;
    }

    return valuesArray.concat([movingAverage]).slice(Math.max(valuesArray.length - MAX_HISTORY, 0));
}

// DagreD3 Graph-related functions
// ===============================

function initializeGraph()
{
    return new dagreD3.graphlib.Graph({compound: true})
        .setGraph({rankdir: 'BT'})
        .setDefaultEdgeLabel(function () { return {}; });
}

function initializeSvg(selector)
{
    const svg = d3.select(selector);
    svg.append("g");

    return svg;
}

function computeSources(nodeInfo)
{
    let sources = [];
    let remoteSources = []; // TODO: put remoteSources in node-specific section
    switch (nodeInfo['@type']) {
        case 'output':
        case 'explainAnalyze':
        case 'project':
        case 'filter':
        case 'aggregation':
        case 'sort':
        case 'markDistinct':
        case 'window':
        case 'rowNumber':
        case 'topnRowNumber':
        case 'limit':
        case 'distinctlimit':
        case 'topn':
        case 'sample':
        case 'tablewriter':
        case 'delete':
        case 'metadatadelete':
        case 'tablecommit':
        case 'groupid':
        case 'unnest':
        case 'scalar':
            sources = [nodeInfo.source];
            break;
        case 'join':
            sources = [nodeInfo.left, nodeInfo.right];
            break;
        case 'semijoin':
            sources = [nodeInfo.source, nodeInfo.filteringSource];
            break;
        case 'indexjoin':
            sources = [nodeInfo.probeSource, nodeInfo.filterSource];
            break;
        case 'union':
        case 'exchange':
            sources = nodeInfo.sources;
            break;
        case 'remoteSource':
            remoteSources = nodeInfo.sourceFragmentIds;
            break;
        case 'tablescan':
        case 'values':
        case 'indexsource':
            break;
        default:
            console.log("NOTE: Unhandled PlanNode: " + nodeInfo['@type']);
    }

    return [sources, remoteSources];
}

// Utility functions
// =================

function truncateString(inputString, length) {
    if (inputString && inputString.length > length) {
        return inputString.substring(0, length) + "...";
    }

    return inputString;
}

function getStageId(stageId) {
    return stageId.slice(stageId.indexOf('.') + 1, stageId.length)
}

function getTaskIdSuffix(taskId) {
    return taskId.slice(taskId.indexOf('.') + 1, taskId.length)
}

function getTaskIdInStage(taskId) {
    return Number.parseInt(getTaskIdSuffix(getTaskIdSuffix(taskId)));
}

function formatState(state, fullyBlocked) {
    if (fullyBlocked && state == "RUNNING") {
        return "BLOCKED";
    }
    else {
        return state;
    }
}

function getHostname(url) {
    var hostname = new URL(url).hostname;
    if ((hostname.charAt(0) == '[') && (hostname.charAt(hostname.length - 1) == ']')) {
        hostname = hostname.substr(1, hostname.length - 2);
    }
    return hostname;
}

function getPort(url) {
    return new URL(url).port;
}

function getHostAndPort(url) {
    var url = new URL(url);
    return url.hostname + ":" + url.port;
}

function computeRate(count, ms) {
    if (ms == 0) {
        return 0;
    }
    return (count / ms) * 1000.0;
}

function precisionRound(n) {
    if (n < 10) {
        return n.toFixed(2);
    }
    if (n < 100) {
        return n.toFixed(1);
    }
    return Math.round(n);
}

function formatDuration(duration) {
    var unit = "ms";
    if (duration > 1000) {
        duration /= 1000;
        unit = "s";
    }
    if (unit == "s" && duration > 60) {
        duration /= 60;
        unit = "m";
    }
    if (unit == "m" && duration > 60) {
        duration /= 60;
        unit = "h";
    }
    if (unit == "h" && duration > 24) {
        duration /= 24;
        unit = "d";
    }
    if (unit == "d" && duration > 7) {
        duration /= 7;
        unit = "w";
    }
    return precisionRound(duration) + unit;
}

function formatCount(count) {
    var unit = "";
    if (count > 1000) {
        count /= 1000;
        unit = "K";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "M";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "B";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "T";
    }
    if (count > 1000) {
        count /= 1000;
        unit = "Q";
    }
    return precisionRound(count) + unit;
}

function formatDataSizeBytes(size) {
    return formatDataSizeMinUnit(size, "");
}

function formatDataSize(size) {
    return formatDataSizeMinUnit(size, "B");
}

function formatDataSizeMinUnit(size, minUnit) {
    var unit = minUnit;
    if (size == 0) {
        return "0" + unit;
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "K" + minUnit;
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "M" + minUnit;
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "G" + minUnit;
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "T" + minUnit;
    }
    if (size >= 1024) {
        size /= 1024;
        unit = "P" + minUnit;
    }
    return precisionRound(size) + unit;
}

function parseDataSize(value) {
    var DATA_SIZE_PATTERN = /^\s*(\d+(?:\.\d+)?)\s*([a-zA-Z]+)\s*$/
    var match = DATA_SIZE_PATTERN.exec(value);
    if (match == null) {
        return null;
    }
    var number = parseFloat(match[1]);
    switch (match[2]) {
        case "B":
            return number;
        case "kB":
            return number * Math.pow(2, 10);
        case "MB":
            return number * Math.pow(2, 20);
        case "GB":
            return number * Math.pow(2, 30);
        case "TB":
            return number * Math.pow(2, 40);
        case "PB":
            return number * Math.pow(2, 50);
        default:
            return null;
    }
}

function parseDuration(value) {
    var DURATION_PATTERN = /^\s*(\d+(?:\.\d+)?)\s*([a-zA-Z]+)\s*$/

    var match = DURATION_PATTERN.exec(value);
    if (match == null) {
        return null;
    }
    var number = parseFloat(match[1]);
    switch (match[2]) {
        case "ns":
            return number / 1000000.0;
        case "us":
            return number / 1000.0;
        case "ms":
            return number;
        case "s":
            return number * 1000;
        case "m":
            return number * 1000 * 60;
        case "h":
            return number * 1000 * 60 * 60;
        case "d":
            return number * 1000 * 60 * 60 * 24;
        default:
            return null;
    }
}

function formatStackTrace(info) {
    return doFormatStackTrace(info, [], "", "");
}

function doFormatStackTrace(info, parentStack, prefix, linePrefix) {
    var s = linePrefix + prefix + failureInfoToString(info) + "\n";

    if (info.stack != null) {
        var sharedStackFrames = 0;
        if (parentStack != null) {
            sharedStackFrames = countSharedStackFrames(info.stack, parentStack);
        }

        for (var i = 0; i < info.stack.length - sharedStackFrames; i++) {
            s += linePrefix + "\tat " + info.stack[i] + "\n";
        }
        if (sharedStackFrames !== 0) {
            s += linePrefix + "\t... " + sharedStackFrames + " more" + "\n";
        }
    }

    if (info.suppressed != null) {
        for (var i = 0; i < info.suppressed.length; i++) {
            s += doFormatStackTrace(info.suppressed[i], info.stack, "Suppressed: ", linePrefix + "\t");
        }
    }

    if (info.cause != null) {
        s += doFormatStackTrace(info.cause, info.stack, "Caused by: ", linePrefix);
    }

    return s;
}

function countSharedStackFrames(stack, parentStack) {
    var n = 0;
    var minStackLength = Math.min(stack.length, parentStack.length);
    while (n < minStackLength && stack[stack.length - 1 - n] === parentStack[parentStack.length - 1 - n]) {
        n++;
    }
    return n;
}

function failureInfoToString(t) {
    return (t.message != null) ? (t.type + ": " + t.message) : t.type;
}

function formatShortTime(date) {
    var hours = (date.getHours() % 12) || 12;
    var minutes = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes();
    return hours + ":" + minutes + (date.getHours() >= 12 ? "pm" : "am");
}

function formatShortDateTime(date) {
    var year = date.getFullYear();
    var month = "" + (date.getMonth() + 1);
    var dayOfMonth  = "" + date.getDate();
    return year + "-" + (month[1] ? month : "0" + month[0]) + "-" + (dayOfMonth[1] ? dayOfMonth: "0" + dayOfMonth[0]) + " " + formatShortTime(date);
}

function removeQueryId(id) {
    var pos = id.indexOf('.');
    if (pos != -1) {
        return id.substring(pos + 1);
    }
    return id;
}
<|endoftext|>


<commit_before>frappe.listview_settings['Purchase Order'] = {
	add_fields: ["grand_total", "company", "currency", "supplier",
		"supplier_name", "per_received", "per_billed"]
};
<commit_msg>Fix for "Stopped" status indicator in Purchase Order List View Issue #2368<commit_after>frappe.listview_settings['Purchase Order'] = {
	add_fields: ["grand_total", "company", "currency", "supplier",
		"supplier_name", "per_received", "per_billed", "status"]
};
<|endoftext|>


<commit_before>const showPopup          = require('./popup');
const elementTextContent = require('../../../_common/common_functions').elementTextContent;
const getElementById     = require('../../../_common/common_functions').getElementById;
const urlFor             = require('../../../_common/url').urlFor;

const alert = (options) => (
    new Promise((resolve) => {
        showPopup({
            url               : urlFor('dialog'),
            popup_id          : options.id,
            form_id           : '#frm_confirm',
            content_id        : '#dialog_content',
            additionalFunction: () => {
                const el_dialog = getElementById(options.id);
                const el_btn_ok = getElementById('btn_ok');

                elementTextContent(getElementById('dialog_message'), options.message);

                getElementById('btn_cancel').classList.add('invisible');

                el_btn_ok.addEventListener('click', () => {
                    if (el_dialog) {
                        el_dialog.remove();
                    }
                    if (typeof options.onConfirm === 'function') {
                        options.onConfirm();
                    }
                    resolve(true);
                });
            },
        });
    })
);

const confirm = (options) => (
    new Promise((resolve) => {
        showPopup({
            url               : urlFor('dialog'),
            popup_id          : options.id,
            form_id           : '#frm_confirm',
            content_id        : '#dialog_content',
            additionalFunction: () => {
                const el_dialog = getElementById(options.id);
                const el_btn_ok = getElementById('btn_ok');
                const el_btn_cancel = getElementById('btn_cancel');

                elementTextContent(getElementById('dialog_message'), options.message);

                el_btn_cancel.addEventListener('click', () => {
                    if (el_dialog) {
                        el_dialog.remove();
                    }
                    if (typeof options.onAbort === 'function') {
                        options.onAbort();
                    }
                    resolve(false);

                });
                el_btn_ok.addEventListener('click', () => {
                    if (el_dialog) {
                        el_dialog.remove();
                    }
                    if (typeof options.onConfirm === 'function') {
                        options.onConfirm();
                    }
                    resolve(true);
                });
            },
        });
    })
);

module.exports = {
    alert,
    confirm,
};<commit_msg>Simplify dialog<commit_after>const showPopup          = require('./popup');
const elementTextContent = require('../../../_common/common_functions').elementTextContent;
const getElementById     = require('../../../_common/common_functions').getElementById;
const urlFor             = require('../../../_common/url').urlFor;

const dialog = (() => {
    const BaseDialog = (options, is_alert = false) => (
        new Promise((resolve) => {
            showPopup({
                url               : urlFor('dialog'),
                popup_id          : options.id,
                form_id           : '#frm_confirm',
                content_id        : '#dialog_content',
                additionalFunction: () => {
                    const el_dialog     = getElementById(options.id);
                    const el_btn_ok     = getElementById('btn_ok');
                    const el_btn_cancel = getElementById('btn_cancel');

                    if (!el_dialog) return;

                    elementTextContent(getElementById('dialog_message'), options.message);

                    if (is_alert) {
                        el_btn_cancel.classList.add('invisible');
                    } else {
                        el_btn_cancel.addEventListener('click', () => {
                            el_dialog.remove();
                            if (typeof options.onAbort === 'function') {
                                options.onAbort();
                            }
                            resolve(false);

                        });
                    }
                    el_btn_ok.addEventListener('click', () => {
                        el_dialog.remove();
                        if (typeof options.onConfirm === 'function') {
                            options.onConfirm();
                        }
                        resolve(true);
                    });
                },
            });
        })
    );

    return {
        alert  : (options) => new BaseDialog(options, true),
        confirm: (options) => new BaseDialog(options),
    };
})();

module.exports = dialog;<|endoftext|>