<commit_before>function ColorPickerController($scope) {

    $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;

    if ($scope.isConfigured) {

        for (var key in $scope.model.config.items) {
            if (!$scope.model.config.items[key].hasOwnProperty("value"))
                $scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
        }

        $scope.model.useLabel = isTrue($scope.model.config.useLabel);
        initActiveColor();
    }

    $scope.toggleItem = function (color) {

        var currentColor = $scope.model.value.hasOwnProperty("value")
            ? $scope.model.value.value
            : $scope.model.value;

        var newColor;
        if (currentColor === color.value) {
            // deselect
            $scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
            newColor = "";
        }
        else {
            // select
            $scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
            newColor = color.value;
        }

        // this is required to re-validate
        $scope.propertyForm.modelValue.$setViewValue(newColor);
    };

    // Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
    $scope.validateMandatory = function () {
        var isValid = !$scope.model.validation.mandatory || (
            $scope.model.value != null
            && $scope.model.value != ""
            && (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
        );
        return {
            isValid: isValid,
            errorMsg: "Value cannot be empty",
            errorKey: "required"
        };
    }
    $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;

    // A color is active if it matches the value and label of the model.
    // If the model doesn't store the label, ignore the label during the comparison.
    $scope.isActiveColor = function (color) {

        // no value
        if (!$scope.model.value)
            return false;

        // Complex color (value and label)?
        if (!$scope.model.value.hasOwnProperty("value"))
            return $scope.model.value === color.value;

        return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
    };

    // Finds the color best matching the model's color,
    // and sets the model color to that one. This is useful when
    // either the value or label was changed on the data type.
    function initActiveColor() {

        // no value
        if (!$scope.model.value)
            return;

        // Complex color (value and label)?
        if (!$scope.model.value.hasOwnProperty("value"))
            return;

        var modelColor = $scope.model.value.value;
        var modelLabel = $scope.model.value.label;

        // Check for a full match or partial match.
        var foundItem = null;

        // Look for a fully matching color.
        for (var key in $scope.model.config.items) {
            var item = $scope.model.config.items[key];
            if (item.value == modelColor && item.label == modelLabel) {
                foundItem = item;
                break;
            }
        }

        // Look for a color with a matching value.
        if (!foundItem) {
            for (var key in $scope.model.config.items) {
                var item = $scope.model.config.items[key];
                if (item.value == modelColor) {
                    foundItem = item;
                    break;
                }
            }
        }

        // Look for a color with a matching label.
        if (!foundItem) {
            for (var key in $scope.model.config.items) {
                var item = $scope.model.config.items[key];
                if (item.label == modelLabel) {
                    foundItem = item;
                    break;
                }
            }
        }

        // If a match was found, set it as the active color.
        if (foundItem) {
            $scope.model.value.value = foundItem.value;
            $scope.model.value.label = foundItem.label;
        }
    }

    // figures out if a value is trueish enough
    function isTrue(bool) {
        return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
    }
}

angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController);
<commit_msg>U4-10891 Color Picker Cannot read property 'hasOwnProperty' of null<commit_after>function ColorPickerController($scope) {

    $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;

    if ($scope.isConfigured) {

        for (var key in $scope.model.config.items) {
            if (!$scope.model.config.items[key].hasOwnProperty("value"))
                $scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
        }

        $scope.model.useLabel = isTrue($scope.model.config.useLabel);
        initActiveColor();
    }

    $scope.toggleItem = function (color) {

        var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
            ? $scope.model.value.value
            : $scope.model.value;

        var newColor;
        if (currentColor === color.value) {
            // deselect
            $scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
            newColor = "";
        }
        else {
            // select
            $scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
            newColor = color.value;
        }

        // this is required to re-validate
        $scope.propertyForm.modelValue.$setViewValue(newColor);
    };

    // Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
    $scope.validateMandatory = function () {
        var isValid = !$scope.model.validation.mandatory || (
            $scope.model.value != null
            && $scope.model.value != ""
            && (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
        );
        return {
            isValid: isValid,
            errorMsg: "Value cannot be empty",
            errorKey: "required"
        };
    }
    $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;

    // A color is active if it matches the value and label of the model.
    // If the model doesn't store the label, ignore the label during the comparison.
    $scope.isActiveColor = function (color) {

        // no value
        if (!$scope.model.value)
            return false;

        // Complex color (value and label)?
        if (!$scope.model.value.hasOwnProperty("value"))
            return $scope.model.value === color.value;

        return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
    };

    // Finds the color best matching the model's color,
    // and sets the model color to that one. This is useful when
    // either the value or label was changed on the data type.
    function initActiveColor() {

        // no value
        if (!$scope.model.value)
            return;

        // Complex color (value and label)?
        if (!$scope.model.value.hasOwnProperty("value"))
            return;

        var modelColor = $scope.model.value.value;
        var modelLabel = $scope.model.value.label;

        // Check for a full match or partial match.
        var foundItem = null;

        // Look for a fully matching color.
        for (var key in $scope.model.config.items) {
            var item = $scope.model.config.items[key];
            if (item.value == modelColor && item.label == modelLabel) {
                foundItem = item;
                break;
            }
        }

        // Look for a color with a matching value.
        if (!foundItem) {
            for (var key in $scope.model.config.items) {
                var item = $scope.model.config.items[key];
                if (item.value == modelColor) {
                    foundItem = item;
                    break;
                }
            }
        }

        // Look for a color with a matching label.
        if (!foundItem) {
            for (var key in $scope.model.config.items) {
                var item = $scope.model.config.items[key];
                if (item.label == modelLabel) {
                    foundItem = item;
                    break;
                }
            }
        }

        // If a match was found, set it as the active color.
        if (foundItem) {
            $scope.model.value.value = foundItem.value;
            $scope.model.value.label = foundItem.label;
        }
    }

    // figures out if a value is trueish enough
    function isTrue(bool) {
        return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
    }
}

angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController);
<|endoftext|>


<commit_before>
var Routine = Component.createComponent("Routine");

Routine.defineMethod("construct", function () {
  // Construct private container
  Object.defineProperty(this, "_container", {
    value: {
      paused: true
    }
  });
});

Routine.defineMethod("init", function (func, interval) {
  // Init execute method
  var container = this._container;
  this._execute = function _execute() {
    func();

    if (!container.paused) {
      container.timeout = setTimeout(function () {
        window.requestAnimationFrame(_execute);
      }, interval);
    }
  };
  // Start routine
  this.start();
  return [];
});

Routine.defineMethod("uninit", function () {
  // End routine
  this.end();
});

Object.defineProperty(Routine.prototype, "paused", {
  get: function () {
    return this._container.paused;
  },
  set: function (value) {
    this._container.paused = value;
  }
});

Routine.prototype.start = function () {
  if (this.paused) {
    // Unfreeze the routine
    this.paused = false;
    // Execute the routine
    this._execute();
  }
};

Routine.prototype.end = function () {
  // Pause the routine
  this.paused = true;
  // Cancel interval limit
  clearTimeout(this._container.timeout);
};

Routine.prototype.restart = function () {
  this.end();
  this.start();
};
<commit_msg>Option to start routine automatically<commit_after>
var Routine = Component.createComponent("Routine");

Routine.defineMethod("construct", function () {
  // Construct private container
  Object.defineProperty(this, "_container", {
    value: {
      paused: true
    }
  });
});

Routine.defineMethod("init", function (func, interval, start = true) {
  // Init execute method
  var container = this._container;
  this._execute = function _execute() {
    func();

    if (!container.paused) {
      container.timeout = setTimeout(function () {
        window.requestAnimationFrame(_execute);
      }, interval);
    }
  };
  // Start routine
  if (start) this.start();
  return [];
});

Routine.defineMethod("uninit", function () {
  // End routine
  this.end();
});

Object.defineProperty(Routine.prototype, "paused", {
  get: function () {
    return this._container.paused;
  },
  set: function (value) {
    this._container.paused = value;
  }
});

Routine.prototype.start = function () {
  if (this.paused) {
    // Unfreeze the routine
    this.paused = false;
    // Execute the routine
    this._execute();
  }
};

Routine.prototype.end = function () {
  // Pause the routine
  this.paused = true;
  // Cancel interval limit
  clearTimeout(this._container.timeout);
};

Routine.prototype.restart = function () {
  this.end();
  this.start();
};
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];
    expect(fourNumberArray.length).toBe(4);

    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);

  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(["peanut"]);
    expect(array.slice(0, 2)).toEqual(["peanut", "butter"]);
    expect(array.slice(2, 2)).toEqual([]]);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>Fixed AboutArrays.js. I had not previously finished this file as Jasmine hid the tests due to a silly syntax error involving parentheses. Learnt about slice, push, pop, unshift, and shift.<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];
    expect(fourNumberArray.length).toBe(4);

    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);

  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(["peanut"]);
    expect(array.slice(0, 2)).toEqual(["peanut", "butter"]);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(["and", "jelly"]);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(["jelly"]);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    //this makes a shallow copy, so assignedArray can manipulate array variable
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    //this makes a deep copy, so both arrays are stored separately in memory.
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1, 2,3]);
    //pop takes out the last element in array
    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1, 2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3,1,2]);
    //shift takes out the first element in array
    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1, 2]);
  });
});
<|endoftext|>


<commit_before>
(function () {
    var d = document,
        w = window,
        p = parseInt,
        dd = d.documentElement,
        db = d.body,
        dc = d.compatMode == 'CSS1Compat',
        dx = dc ? dd: db,
        ec = encodeURIComponent;

    w.CHAT = {
        msgObj:d.getElementById("message"),
        screenheight:w.innerHeight ? w.innerHeight : dx.clientHeight,
        username:null,
        userid:null,
        socket:null,
        meshight:document.body.scrollHeight-108,
        //让浏览器滚动条保持在最低部
        scrollToBottom:function(){
            this.msgObj.scrollTop=this.msgObj.scrollHeight-this.meshight;
        },
        //退出，本例只是一个简单的刷新
        logout:function(){
            //this.socket.disconnect();
            location.reload();
        },
        //提交聊天消息内容
        submit:function(){
            var content = d.getElementById("content").value;
            if(content != ''){
                var obj = {
                    userid: this.userid,
                    username: this.username,
                    content: content
                };
                this.socket.emit('message', obj);
                d.getElementById("content").value = '';
            }
            return false;
        },
        change:function(){
            var that=this;
            var sendImage= d.getElementById('sendImage');
            //检查是否有文件被选中
            if (sendImage.files.length != 0) {
                //获取文件并用FileReader进行读取
                var file = sendImage.files[0],
                    reader = new FileReader();
                if (!reader) {
                    that._displayNewMsg('system', '!your browser doesn\'t support fileReader', 'red');
                    sendImage.value = '';
                    return;
                };
                reader.onload = function(e) {
                    //读取成功，显示到页面并发送到服务器
                    sendImage.value = '';
                    var imgdata=e.target.result;
                    var obj={
                        userid: that.userid,
                        username: that.username,
                        imgdata: imgdata
                    }
                    that.socket.emit('img', obj);
                    //that._displayImage('me', obj);
                };
                reader.readAsDataURL(file);
            };

        },
        _displayImage: function(obj) {
            var isme = (obj.userid == CHAT.userid) ? true : false;
            var contentDiv = '

';
            var usernameDiv = ''+obj.username+'';

            var section = d.createElement('section');
            if(isme){
                section.className = 'user';
                section.innerHTML = contentDiv + usernameDiv;
            } else {
                section.className = 'service';
                section.innerHTML = usernameDiv + contentDiv;
            }
            CHAT.msgObj.appendChild(section);
            CHAT.scrollToBottom();
        },
        genUid:function(){
            return new Date().getTime()+""+Math.floor(Math.random()*899+100);
        },
        //更新系统消息，本例中在用户加入、退出的时候调用
        updateSysMsg:function(o, action){
            //当前在线用户列表
            var onlineUsers = o.onlineUsers;
            //当前在线人数
            var onlineCount = o.onlineCount;
            //新加入用户的信息
            var user = o.user;

            //更新在线人数
            var userhtml = '';
            var separator = '';
            for(key in onlineUsers) {
                if(onlineUsers.hasOwnProperty(key)){
                    userhtml += separator+onlineUsers[key];
                    separator = '、';
                }
            }
            d.getElementById("onlinecount").innerHTML = '当前共有 '+onlineCount+' 人在线，在线列表：'+userhtml;

            //添加系统消息
            var html = '';
            html += '
';
            html += user.username;
            html += (action == 'login') ? ' 加入了聊天室' : ' 退出了聊天室';
            html += '
';
            var section = d.createElement('section');
            section.className = 'system J-mjrlinkWrap J-cutMsg';
            section.innerHTML = html;
            this.msgObj.appendChild(section);
            this.scrollToBottom();
        },
        //第一个界面用户提交用户名
        usernameSubmit:function(){
            var username = d.getElementById("username").value;
            if(username != ""){
                d.getElementById("username").value = '';
                d.getElementById("loginbox").style.display = 'none';
                d.getElementById("chatbox").style.display = 'block';
                this.init(username);
            }
            return false;
        },
        init:function(username){
            var that=this;
            /*
             客户端根据时间和随机数生成uid,这样使得聊天室用户名称可以重复。
             实际项目中，如果是需要用户登录，那么直接采用用户的uid来做标识就可以
             */
            this.userid = this.genUid();
            this.username = username;

            d.getElementById("showusername").innerHTML = this.username;
            //this.msgObj.style.minHeight = (this.screenheight - db.clientHeight + this.msgObj.clientHeight) + "px";
            this.msgObj.style.maxHeight=this.meshight+'px';
            this.scrollToBottom();

            //连接websocket后端服务器
            this.socket = io.connect('http://raclen-wenzhang.coding.io');
            //this.socket = io.connect('http://localhost:3001');

            //告诉服务器端有用户登录
            this.socket.emit('login', {userid:this.userid, username:this.username});

            //监听新用户登录
            this.socket.on('login', function(o){
                CHAT.updateSysMsg(o, 'login');
            });

            //监听用户退出
            this.socket.on('logout', function(o){
                CHAT.updateSysMsg(o, 'logout');
            });

            //监听消息发送
            this.socket.on('message', function(obj){
                var isme = (obj.userid == CHAT.userid) ? true : false;
                var contentDiv = '
'+obj.content+'
';
                var usernameDiv = ''+obj.username+'';

                var section = d.createElement('section');
                if(isme){
                    section.className = 'user';
                    section.innerHTML = contentDiv + usernameDiv;
                } else {
                    section.className = 'service';
                    section.innerHTML = usernameDiv + contentDiv;
                }
                CHAT.msgObj.appendChild(section);
                CHAT.scrollToBottom();
            });

            this.socket.on('newImg', function(obj) {
                //that._displayImage(user, img);
                that._displayImage(obj);
            });

        }
    };
    //通过“回车”提交用户名
    d.getElementById("username").onkeydown = function(e) {
        e = e || event;
        if (e.keyCode === 13) {
            CHAT.usernameSubmit();
        }
    };
    //通过“回车”提交信息
    d.getElementById("content").onkeydown = function(e) {
        e = e || event;
        if (e.keyCode === 13) {
            CHAT.submit();
        }
    };
    d.getElementById('mjr_send').addEventListener('click',function(){
        CHAT.submit();
    })
    d.getElementById('go').addEventListener('click',function(){
        CHAT.usernameSubmit();
    })

    d.getElementById('sendImage').addEventListener('change', function() {
        CHAT.change();

    });
})();<commit_msg>优化在线聊天代码<commit_after>
(function () {
    var d = document,
        w = window,
        p = parseInt,
        dd = d.documentElement,
        db = d.body,
        dc = d.compatMode == 'CSS1Compat',
        dx = dc ? dd: db,
        ec = encodeURIComponent;

    w.CHAT = {
        msgObj:d.getElementById("message"),
        screenheight:w.innerHeight ? w.innerHeight : dx.clientHeight,
        username:null,
        userid:null,
        socket:null,
        meshight:document.body.scrollHeight-108,
        //让浏览器滚动条保持在最低部
        scrollToBottom:function(){
            this.msgObj.scrollTop=this.msgObj.scrollHeight-this.meshight;
        },
        //退出，本例只是一个简单的刷新
        logout:function(){
            //this.socket.disconnect();
            location.reload();
        },
        //提交聊天消息内容
        submit:function(){
            var content = d.getElementById("content").value;
            if(content != ''){
                var obj = {
                    userid: this.userid,
                    username: this.username,
                    content: content
                };
                this.socket.emit('message', obj);
                d.getElementById("content").value = '';
            }
            return false;
        },
        change:function(){
            var that=this;
            var sendImage= d.getElementById('sendImage');
            //检查是否有文件被选中
            if (sendImage.files.length != 0) {
                //获取文件并用FileReader进行读取
                var file = sendImage.files[0],
                    reader = new FileReader();
                if (!reader) {
                    console.log('读取图片失败');
                    sendImage.value = '';
                    return;
                };
                reader.onload = function(e) {
                    //读取成功，显示到页面并发送到服务器
                    sendImage.value = '';
                    var imgdata=e.target.result;
                    var obj={
                        userid: that.userid,
                        username: that.username,
                        imgdata: imgdata
                    }
                    that.socket.emit('img', obj);
                    //that._displayImage('me', obj);
                };
                reader.readAsDataURL(file);
            };

        },
        _displayImage: function(obj) {
            var isme = (obj.userid == CHAT.userid) ? true : false;
            var contentDiv = '

';
            var usernameDiv = ''+obj.username+'';

            var section = d.createElement('section');
            if(isme){
                section.className = 'user';
                section.innerHTML = contentDiv + usernameDiv;
            } else {
                section.className = 'service';
                section.innerHTML = usernameDiv + contentDiv;
            }
            CHAT.msgObj.appendChild(section);
            CHAT.scrollToBottom();
        },
        genUid:function(){
            return new Date().getTime()+""+Math.floor(Math.random()*899+100);
        },
        //更新系统消息，本例中在用户加入、退出的时候调用
        updateSysMsg:function(o, action){
            //当前在线用户列表
            var onlineUsers = o.onlineUsers;
            //当前在线人数
            var onlineCount = o.onlineCount;
            //新加入用户的信息
            var user = o.user;

            //更新在线人数
            var userhtml = '';
            var separator = '';
            for(key in onlineUsers) {
                if(onlineUsers.hasOwnProperty(key)){
                    userhtml += separator+onlineUsers[key];
                    separator = '、';
                }
            }
            d.getElementById("onlinecount").innerHTML = '当前共有 '+onlineCount+' 人在线，在线列表：'+userhtml;

            //添加系统消息
            var html = '';
            html += '
';
            html += user.username;
            html += (action == 'login') ? ' 加入了聊天室' : ' 退出了聊天室';
            html += '
';
            var section = d.createElement('section');
            section.className = 'system J-mjrlinkWrap J-cutMsg';
            section.innerHTML = html;
            this.msgObj.appendChild(section);
            this.scrollToBottom();
        },
        //第一个界面用户提交用户名
        usernameSubmit:function(){
            var username = d.getElementById("username").value;
            if(username != ""){
                d.getElementById("username").value = '';
                d.getElementById("loginbox").style.display = 'none';
                d.getElementById("chatbox").style.display = 'block';
                this.init(username);
            }
            return false;
        },
        init:function(username){
            var that=this;
            /*
             客户端根据时间和随机数生成uid,这样使得聊天室用户名称可以重复。
             实际项目中，如果是需要用户登录，那么直接采用用户的uid来做标识就可以
             */
            this.userid = this.genUid();
            this.username = username;

            d.getElementById("showusername").innerHTML = this.username;
            //this.msgObj.style.minHeight = (this.screenheight - db.clientHeight + this.msgObj.clientHeight) + "px";
            this.msgObj.style.maxHeight=this.meshight+'px';
            this.scrollToBottom();

            //连接websocket后端服务器
            this.socket = io.connect('http://raclen-wenzhang.coding.io');
            //this.socket = io.connect('http://localhost:3001');

            //告诉服务器端有用户登录
            this.socket.emit('login', {userid:this.userid, username:this.username});

            //监听新用户登录
            this.socket.on('login', function(o){
                CHAT.updateSysMsg(o, 'login');
            });

            //监听用户退出
            this.socket.on('logout', function(o){
                CHAT.updateSysMsg(o, 'logout');
            });

            //监听消息发送
            this.socket.on('message', function(obj){
                var isme = (obj.userid == CHAT.userid) ? true : false;
                var contentDiv = '
'+obj.content+'
';
                var usernameDiv = ''+obj.username+'';

                var section = d.createElement('section');
                if(isme){
                    section.className = 'user';
                    section.innerHTML = contentDiv + usernameDiv;
                } else {
                    section.className = 'service';
                    section.innerHTML = usernameDiv + contentDiv;
                }
                CHAT.msgObj.appendChild(section);
                CHAT.scrollToBottom();
            });

            this.socket.on('newImg', function(obj) {
                //that._displayImage(user, img);
                that._displayImage(obj);
            });

        }
    };
    //通过“回车”提交用户名
    d.getElementById("username").onkeydown = function(e) {
        e = e || event;
        if (e.keyCode === 13) {
            CHAT.usernameSubmit();
        }
    };
    //通过“回车”提交信息
    d.getElementById("content").onkeydown = function(e) {
        e = e || event;
        if (e.keyCode === 13) {
            CHAT.submit();
        }
    };
    d.getElementById('mjr_send').addEventListener('click',function(){
        CHAT.submit();
    })
    d.getElementById('go').addEventListener('click',function(){
        CHAT.usernameSubmit();
    })

    d.getElementById('sendImage').addEventListener('change', function() {
        CHAT.change();

    });
})();<|endoftext|>


<commit_before>import React from 'react';
import demand from 'must';
import EditFormHeader from '../EditFormHeader';
import { shallow } from 'enzyme';

import Toolbar from '../Toolbar';
import ToolbarSection from '../Toolbar/ToolbarSection';
import { Button, ResponsiveText, FormInput } from 'elemental';
import { Link } from 'react-router';

describe('<EditFormHeader />', () => {
	before(() => {
		global.Keystone = {
			adminPath: '',
			csrf: {},
		};
	});

	it('should render a Toolbar', () => {
		const component = shallow(<EditFormHeader data={{}} list={{}} />);
		demand(component.find(Toolbar).length).gt(0);
	});

	describe('Drilldown', () => {
		it('should render a Toolbar Section on the left', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(ToolbarSection).length).gt(0);
			demand(component.find(ToolbarSection).at(0).prop('left')).true();
		});

		it('should render a link back to the list if no items are specified', () => {
			const path = 'some/path';
			const component = shallow(
				<EditFormHeader
					data={{}}
					list={{
						path,
					}}
				/>
			);
			demand(component.find('.e2e-editform-header-back').length).eql(1);
			demand(component.find('.e2e-editform-header-back').at(0).prop('to')).eql('/' + path);
		});

		it('should render items passed in', () => {
			const items = [{
				href: 'some/item',
			}, {
				href: 'some/other/item',
			}];
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								items,
							}],
						},
					}}
					list={{}}
				/>
			);
			const BACKBUTTON = 1;
			demand(component.find(Link).length).eql(BACKBUTTON + items.length);
		});

		it('should render one less separator then there\'s items', () => {
			const items = [{
				href: 'some/item',
			}, {
				href: 'some/other/item',
			}];
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								items,
							}],
						},
					}}
					list={{}}
				/>
			);
			demand(component.find('.separator').length).eql(items.length - 1);
		});

		it('should render ... if there\'s more items', () => {
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								more: true,
								items: [],
							}],
						},
					}}
					list={{}}
				/>
			);
			demand(component.contains('...')).true();
		});

		it('should render a back button if there\'s items', () => {
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								more: true,
								items: [],
							}],
						},
					}}
					list={{}}
				/>
			);
			demand(component.find('.e2e-editform-header-back').length).eql(1);
		});

		it('should render a search form', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find('form.EditForm__header__search').length).eql(1);
		});

		it('should render a search input', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(FormInput).length).eql(1);
			demand(component.find(FormInput).at(0).prop('type')).eql('search');
		});
	});

	describe('Info', () => {
		it('should render a Toolbar Section on the right', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(ToolbarSection).length).gt(0);
			demand(component.find(ToolbarSection).at(1).prop('right')).true();
		});

		it('should render a create button', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(Button).find(ResponsiveText).at(0).prop('visibleXS')).eql('Create');
		});

		it('should not render a create button if the list is a nocreate', () => {
			const component = shallow(
				<EditFormHeader
					data={{}}
					list={{
						nocreate: true,
					}}
				/>
			);
			demand(component.find(Button).length).eql(0);
		});

		it('should change the href if the list is an autocreate', () => {
			const component = shallow(
				<EditFormHeader
					data={{}}
					list={{
						autocreate: true,
					}}
				/>
			);
			demand(component.find(Button).prop('href')).include('?new');
		});
	});
});
<commit_msg>Skipping invalid tests<commit_after>import React from 'react';
import demand from 'must';
import EditFormHeader from '../EditFormHeader';
import { shallow } from 'enzyme';

import Toolbar from '../Toolbar';
import ToolbarSection from '../Toolbar/ToolbarSection';
import { Button, ResponsiveText, FormInput } from 'elemental';
import { Link } from 'react-router';

describe('<EditFormHeader />', () => {
	before(() => {
		global.Keystone = {
			adminPath: '',
			csrf: {},
		};
	});

	it('should render a Toolbar', () => {
		const component = shallow(<EditFormHeader data={{}} list={{}} />);
		demand(component.find(Toolbar).length).gt(0);
	});

	describe('Drilldown', () => {
		it('should render a Toolbar Section on the left', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(ToolbarSection).length).gt(0);
			demand(component.find(ToolbarSection).at(0).prop('left')).true();
		});

		it('should render a link back to the list if no items are specified', () => {
			const path = 'some/path';
			const component = shallow(
				<EditFormHeader
					data={{}}
					list={{
						path,
					}}
				/>
			);
			demand(component.find('.e2e-editform-header-back').length).eql(1);
			demand(component.find('.e2e-editform-header-back').at(0).prop('to')).eql('/' + path);
		});

		it.skip('should render items passed in', () => {
			const items = [{
				href: 'some/item',
			}, {
				href: 'some/other/item',
			}];
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								items,
							}],
						},
					}}
					list={{}}
				/>
			);
			const BACKBUTTON = 1;
			demand(component.find(Link).length).eql(BACKBUTTON + items.length);
		});

		it.skip('should render one less separator then there\'s items', () => {
			const items = [{
				href: 'some/item',
			}, {
				href: 'some/other/item',
			}];
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								items,
							}],
						},
					}}
					list={{}}
				/>
			);
			demand(component.find('.separator').length).eql(items.length - 1);
		});

		it.skip('should render ... if there\'s more items', () => {
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								more: true,
								items: [],
							}],
						},
					}}
					list={{}}
				/>
			);
			demand(component.contains('...')).true();
		});

		it.skip('should render a back button if there\'s items', () => {
			const component = shallow(
				<EditFormHeader
					data={{
						drilldown: {
							items: [{
								list: {},
								more: true,
								items: [],
							}],
						},
					}}
					list={{}}
				/>
			);
			demand(component.find('.e2e-editform-header-back').length).eql(1);
		});

		it('should render a search form', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find('form.EditForm__header__search').length).eql(1);
		});

		it('should render a search input', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(FormInput).length).eql(1);
			demand(component.find(FormInput).at(0).prop('type')).eql('search');
		});
	});

	describe('Info', () => {
		it('should render a Toolbar Section on the right', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(ToolbarSection).length).gt(0);
			demand(component.find(ToolbarSection).at(1).prop('right')).true();
		});

		it.skip('should render a create button', () => {
			const component = shallow(<EditFormHeader data={{}} list={{}} />);
			demand(component.find(Button).find(ResponsiveText).at(0).prop('visibleXS')).eql('Create');
		});

		it('should not render a create button if the list is a nocreate', () => {
			const component = shallow(
				<EditFormHeader
					data={{}}
					list={{
						nocreate: true,
					}}
				/>
			);
			demand(component.find(Button).length).eql(0);
		});

		it.skip('should change the href if the list is an autocreate', () => {
			const component = shallow(
				<EditFormHeader
					data={{}}
					list={{
						autocreate: true,
					}}
				/>
			);
			demand(component.find(Button).prop('href')).include('?new');
		});
	});
});
<|endoftext|>


<commit_before>//////////////////////////////////
//           SWOOP JS           //
//////////////////////////////////
// Get data from backend        //
// Get requests from frontend   //
// Match up data                //
// Send to front end            //
//////////////////////////////////
var http = require('http'); // http protocol
var express = require('express'); // web server
var bodyParser = require('body-parser'); // http body parser
var mongodb = require('mongodb');
var socketio = require('socket.io');
var request = require('request');
var fs = require('fs');
var Mongo = mongodb.MongoClient;
var ObjectID = mongodb.ObjectID;
var http = require('http').Server(app);
const MONGO_URL = 'mongodb://localhost:27017/swoop';
///////////////
// MONGO OPs //
///////////////
Mongo.connect(MONGO_URL, function (err, db) {
    if (err) log('error');
    else log('Mongo is active on port 27017');
    Mongo.ops = {};
    // TODO: Add needed Functions
    Mongo.ops.upsert = function(collection, query, json, callback) {
        db.collection(collection).updateOne(query, { $set: json }, { upsert: true }, function(err, result) {
            if (callback) callback(err, result);
        });
    };
    Mongo.ops.insert = function (collection, json, callback) {
        db.collection(collection).insert(json, function (err, result) {
            if (callback) callback(err, result);
        });
    };
});
////////////////////
// Cross Domains  //
////////////////////
function allowCrossDomain(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'Authorization');
    // end pre flights
}
//
var app = express();
// use middlewares
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));
app.use(allowCrossDomain);

///////////////
// SOCKET iO //
///////////////
var server = http.listen(8080, function () {
    console.log('socket on');
});
var io = socketio(server);
io.sockets.on('connection', function (socket) {
    log('new socket client: ', socket.id);
    socket.on('disconnect', function () {
        log('socket client disconnected: ', socket.id);
    });
    socket.on('addcar1', function (data) {
        log('car lat and long: ' + data.lat + ", " + data.long);
        socket.broadcast.emit('car1', data);
    })
    socket.on('addcar2', function (data) {
        log('car lat and long: ' + data.lat + ", " + data.long);
        socket.broadcast.emit('car2', data);
    })
    socket.on('addcar3', function (data) {
        log('car lat and long: ' + data.lat + ", " + data.long);
        socket.broadcast.emit('car3', data);
    })
});
///////////////
//  NodeJS   //
///////////////
var app = express();
// use middlewares
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));
//app.use('/', express.static('../client/'));
app.post('/car1', function (req, res, next) {
    log('/car1 req.body =' + JSON.stringify(req.body));
    var payload = req.body;
    io.sockets.emit('addcar1', payload);
    Mongo.ops.upsert('car1current', payload, function (err, response) { // NEED TO FIX THIS, NOT POSTING PROPERLY
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('/car1-current sent');
        }
    });
    Mongo.ops.insert('car1all', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('/car1all sent');
        }
    });
});
app.post('/car2', function (req, res, next) {
    log('/car2 req.body =' + JSON.stringify(req.body));
    var payload = req.body;
    io.sockets.emit('addcar2', payload);
    Mongo.ops.upsert('car2current', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car2-current sent');
        }
    });
    Mongo.ops.insert('car2all', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car2-all sent');
        }
    });
});
app.post('/car3', function (req, res, next) {
    log('/car3 req.body =' + JSON.stringify(req.body));
    var payload = req.body;
    io.sockets.emit('addcar3', payload);
    Mongo.ops.upsert('car3current', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car3-current sent');
        }
    });
    Mongo.ops.insert('car3all', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car3-all sent');
        }
    });
});
app.listen(3000, function () {
    log(' listening on port 3000');
});

///////////////
//    LOG    //
///////////////
function log(msg) {
    console.log(msg);
}<commit_msg>PreGPS Testing<commit_after>//////////////////////////////////
//           SWOOP JS           //
//////////////////////////////////
// Get data from backend        //
// Get requests from frontend   //
// Match up data                //
// Send to front end            //
//////////////////////////////////
var http = require('http'); // http protocol
var express = require('express'); // web server
var bodyParser = require('body-parser'); // http body parser
var mongodb = require('mongodb');
var socketio = require('socket.io');
var request = require('request');
var fs = require('fs');
var Mongo = mongodb.MongoClient;
var ObjectID = mongodb.ObjectID;
var http = require('http').Server(app);
const MONGO_URL = 'mongodb://localhost:27017/swoop';
///////////////
// MONGO OPs //
///////////////
Mongo.connect(MONGO_URL, function (err, db) {
    if (err) log('error');
    else log('Mongo is active on port 27017');
    Mongo.ops = {};
    // TODO: Add needed Functions
    Mongo.ops.upsert = function(collection, query, json, callback) {
        db.collection(collection).updateOne(query, { $set: json }, { upsert: true }, function(err, result) {
            if (callback) callback(err, result);
        });
    };
    Mongo.ops.insert = function (collection, json, callback) {
        db.collection(collection).insert(json, function (err, result) {
            if (callback) callback(err, result);
        });
    };
});
////////////////////
// Cross Domains  //
////////////////////
function allowCrossDomain(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'Authorization');
    // end pre flights
}
//
var app = express();
// use middlewares
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));
app.use(allowCrossDomain);

///////////////
// SOCKET iO //
///////////////
var server = http.listen(8080, function () {
    console.log('socket on');
});
var io = socketio(server);
io.sockets.on('connection', function (socket) {
    log('new socket client: ', socket.id);
    socket.on('disconnect', function () {
        log('socket client disconnected: ', socket.id);
    });
    socket.on('addcar1', function (data) {
        log('car lat and long: ' + data.lat + ", " + data.long);
        socket.broadcast.emit('car1', data);
    })
    socket.on('addcar2', function (data) {
        log('car lat and long: ' + data.lat + ", " + data.long);
        socket.broadcast.emit('car2', data);
    })
    socket.on('addcar3', function (data) {
        log('car lat and long: ' + data.lat + ", " + data.long);
        socket.broadcast.emit('car3', data);
    })
});
///////////////
//  NodeJS   //
///////////////
/*var app = express();
// use middlewares
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));*/
//app.use('/', express.static('../client/'));
app.post('/car1', function (req, res, next) {
    log('/car1 req.body =' + JSON.stringify(req.body));
    var payload = req.body;
    io.sockets.emit('addcar1', payload);
    Mongo.ops.upsert('car1current', payload, function (err, response) { // NEED TO FIX THIS, NOT POSTING PROPERLY
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('/car1-current sent');
        }
    });
    Mongo.ops.insert('car1all', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('/car1all sent');
        }
    });
});
app.post('/car2', function (req, res, next) {
    log('/car2 req.body =' + JSON.stringify(req.body));
    var payload = req.body;
    io.sockets.emit('addcar2', payload);
    Mongo.ops.upsert('car2current', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car2-current sent');
        }
    });
    Mongo.ops.insert('car2all', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car2-all sent');
        }
    });
});
app.post('/car3', function (req, res, next) {
    log('/car3 req.body =' + JSON.stringify(req.body));
    var payload = req.body;
    io.sockets.emit('addcar3', payload);
    Mongo.ops.upsert('car3current', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car3-current sent');
        }
    });
    Mongo.ops.insert('car3all', payload, function (err, response) {
        if (err) {
            console.log(err);
        }
        else {
            res.status(201).send('ok');
            console.log('car3-all sent');
        }
    });
});
app.listen(3000, function () {
    log(' listening on port 3000');
});

///////////////
//    LOG    //
///////////////
function log(msg) {
    console.log(msg);
}<|endoftext|>


<commit_before>/**
 * @copyright Copyright 2014 Google Inc. All rights reserved.
 *
 * 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.
 *
 * @fileoverview Model definition for a dashboard. Dashboards are
 * retrieved in the JSON format from a REST service (see DashboardDataService).
 * @author joemu@google.com (Joe Allan Muharsky)
 */

goog.provide('p3rf.perfkit.explorer.components.dashboard.DashboardInstance');
goog.provide('p3rf.perfkit.explorer.components.dashboard.DashboardModel');
goog.provide('p3rf.perfkit.explorer.components.dashboard.DashboardParam');

goog.require('p3rf.perfkit.explorer.components.container.ContainerWidgetConfig');
goog.require('p3rf.perfkit.explorer.components.container.ContainerWidgetModel');

// TODO(joemu): Factor out Bigquery config into extension model.
goog.require('p3rf.perfkit.explorer.ext.bigquery.BigqueryConfigModel');
goog.require('p3rf.perfkit.explorer.ext.bigquery.CurrentTimestampGranularity');
goog.require('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryTablePartitioning');

goog.scope(function() {
const explorer = p3rf.perfkit.explorer;
const ContainerWidgetConfig = explorer.components.container.ContainerWidgetConfig;
const ContainerWidgetModel = explorer.components.container.ContainerWidgetModel;
const BigqueryConfigModel = explorer.ext.bigquery.BigqueryConfigModel;
const CurrentTimestampGranularity = explorer.ext.bigquery.CurrentTimestampGranularity;
const QueryTablePartitioning = explorer.models.perfkit_simple_builder.QueryTablePartitioning;

/** @constructor */
explorer.components.dashboard.DashboardParam = function(name, value) {
  /**
   * @type {string}
   * @export
   */
  this.name = name || '';

  /**
   * @type {string}
   * @export
   */
  this.value = value || '';
};
const DashboardParam = explorer.components.dashboard.DashboardParam;

/** @constructor */
explorer.components.dashboard.DashboardModel = function() {
  /**
   * @type {?string}
   * @export
   */
  this.id = null;

  /**
   * @type {string}
   * @export
   */
  this.title = 'Untitled Dashboard';

  /**
   * @type {string}
   * @export
   */
  this.version = '';

  /**
   * @type {?string}
   * @export
   */
  this.owner = this.getDefaultOwner();

  /**
   * @type {Array.<!string>}
   * @export
   */
  this.writers = [];

  /**
   * @type {?string}
   * @export
   */
  this.type = 'dashboard';

  /**
   * Overrides the default project id that widget queries will connect to.
   * This may be further overridden by widget-level settings.
   * @type {?string}
   * @export
   */
  this.project_id = null;

  /**
   * Overrides the default dataset that widget queries will connect to.  This
   * may be overridden by widget-level settings.
   * @type {?string}
   * @export
   */
  this.dataset_name = null;

  /**
   * Overrides the default table that widget queries will connect to.  This
   * may be overridden by widget-level settings.
   * @type {?string}
   * @export
   */
  this.table_name = null;

  /**
   * Specifies the default type of partitioning used on the table.  This may
   * be overridden by widget-level seeings.  For more information, see the
   * docstring for QueryTablePartitioning.
   * @type {?QueryTablePartitioning}
   * @export
   */
  this.table_partition = QueryTablePartitioning.DEFAULT;

  /**
   * @type {!Array.<(ContainerWidgetConfig|ContainerWidgetModel)>}
   * @export
   */
  this.children = [];

  /**
   * @type {!Array.<!DashboardParam>}
   * @export
   */
  this.params = [];

  /**
   * @type {{string}, {*}}
   */
  this.config = {
    bigQuery: new BigqueryConfigModel()
  };

  this.config.bigQuery.optimizeCurrentTimestamp.enabled = false;
  this.config.bigQuery.optimizeCurrentTimestamp.granularity = CurrentTimestampGranularity.HOUR;
};
const DashboardModel = explorer.components.dashboard.DashboardModel;

/**
 * Returns the default owner for a dashboard.
 * @return {string} An email address if one exists, otherwise an empty string.
 */
DashboardModel.prototype.getDefaultOwner = function() {
  return CURRENT_USER_EMAIL;
};

/**
 * @constructor
 * @param {(Object|DashboardModel)=} opt_model JSON or WidgetModel.
 */
explorer.components.dashboard.DashboardInstance = function(opt_model) {
  /**
   * The persisted model of the dashboard. It's usually a simple JSON object
   * returned by the server but it respects the DashboardModel class
   * definition.
   *
   * Warning: Do not keep a reference on this property, it can be replaced by
   * an updated JSON at any time. Instead, keep a reference on the
   * DashboardInstance object that contains it.
   *
   * @type {!(Object|DashboardModel)}
   * @export
   */
  this.model = opt_model || new DashboardModel();
};
const DashboardInstance = explorer.components.dashboard.DashboardInstance;

});  // goog.scope
<commit_msg>Add TODO for BigQuery config refactoring.<commit_after>/**
 * @copyright Copyright 2014 Google Inc. All rights reserved.
 *
 * 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.
 *
 * @fileoverview Model definition for a dashboard. Dashboards are
 * retrieved in the JSON format from a REST service (see DashboardDataService).
 * @author joemu@google.com (Joe Allan Muharsky)
 */

goog.provide('p3rf.perfkit.explorer.components.dashboard.DashboardInstance');
goog.provide('p3rf.perfkit.explorer.components.dashboard.DashboardModel');
goog.provide('p3rf.perfkit.explorer.components.dashboard.DashboardParam');

goog.require('p3rf.perfkit.explorer.components.container.ContainerWidgetConfig');
goog.require('p3rf.perfkit.explorer.components.container.ContainerWidgetModel');

// TODO(joemu): Factor out Bigquery config into extension model.
goog.require('p3rf.perfkit.explorer.ext.bigquery.BigqueryConfigModel');
goog.require('p3rf.perfkit.explorer.ext.bigquery.CurrentTimestampGranularity');
goog.require('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryTablePartitioning');

goog.scope(function() {
const explorer = p3rf.perfkit.explorer;
const ContainerWidgetConfig = explorer.components.container.ContainerWidgetConfig;
const ContainerWidgetModel = explorer.components.container.ContainerWidgetModel;
const BigqueryConfigModel = explorer.ext.bigquery.BigqueryConfigModel;
const CurrentTimestampGranularity = explorer.ext.bigquery.CurrentTimestampGranularity;
const QueryTablePartitioning = explorer.models.perfkit_simple_builder.QueryTablePartitioning;

/** @constructor */
explorer.components.dashboard.DashboardParam = function(name, value) {
  /**
   * @type {string}
   * @export
   */
  this.name = name || '';

  /**
   * @type {string}
   * @export
   */
  this.value = value || '';
};
const DashboardParam = explorer.components.dashboard.DashboardParam;

/** @constructor */
explorer.components.dashboard.DashboardModel = function() {
  /**
   * @type {?string}
   * @export
   */
  this.id = null;

  /**
   * @type {string}
   * @export
   */
  this.title = 'Untitled Dashboard';

  /**
   * @type {string}
   * @export
   */
  this.version = '';

  /**
   * @type {?string}
   * @export
   */
  this.owner = this.getDefaultOwner();

  /**
   * @type {Array.<!string>}
   * @export
   */
  this.writers = [];

  /**
   * @type {?string}
   * @export
   */
  this.type = 'dashboard';

  /**
   * Overrides the default project id that widget queries will connect to.
   * This may be further overridden by widget-level settings.
   * @type {?string}
   * @export
   */
  this.project_id = null;

  /**
   * Overrides the default dataset that widget queries will connect to.  This
   * may be overridden by widget-level settings.
   * @type {?string}
   * @export
   */
  this.dataset_name = null;

  /**
   * Overrides the default table that widget queries will connect to.  This
   * may be overridden by widget-level settings.
   * @type {?string}
   * @export
   */
  this.table_name = null;

  /**
   * Specifies the default type of partitioning used on the table.  This may
   * be overridden by widget-level seeings.  For more information, see the
   * docstring for QueryTablePartitioning.
   * @type {?QueryTablePartitioning}
   * @export
   */
  this.table_partition = QueryTablePartitioning.DEFAULT;

  /**
   * @type {!Array.<(ContainerWidgetConfig|ContainerWidgetModel)>}
   * @export
   */
  this.children = [];

  /**
   * @type {!Array.<!DashboardParam>}
   * @export
   */
  this.params = [];

  /**
   * @dict
   */
  this.config = {
  };

  // TODO: Factor these and other BigQuery-related defaults into a dedicated service.
  this.config['bigQuery'] = new BigqueryConfigModel();
  this.config.bigQuery.optimizeCurrentTimestamp.enabled = false;
  this.config.bigQuery.optimizeCurrentTimestamp.granularity = CurrentTimestampGranularity.HOUR;
};
const DashboardModel = explorer.components.dashboard.DashboardModel;

/**
 * Returns the default owner for a dashboard.
 * @return {string} An email address if one exists, otherwise an empty string.
 */
DashboardModel.prototype.getDefaultOwner = function() {
  return CURRENT_USER_EMAIL;
};

/**
 * @constructor
 * @param {(Object|DashboardModel)=} opt_model JSON or WidgetModel.
 */
explorer.components.dashboard.DashboardInstance = function(opt_model) {
  /**
   * The persisted model of the dashboard. It's usually a simple JSON object
   * returned by the server but it respects the DashboardModel class
   * definition.
   *
   * Warning: Do not keep a reference on this property, it can be replaced by
   * an updated JSON at any time. Instead, keep a reference on the
   * DashboardInstance object that contains it.
   *
   * @type {!(Object|DashboardModel)}
   * @export
   */
  this.model = opt_model || new DashboardModel();
};
const DashboardInstance = explorer.components.dashboard.DashboardInstance;

});  // goog.scope
<|endoftext|>


<commit_before>// @flow

import { permissionLookup } from 'lib/permissions/thread-permissions';
import {
  threadFrozenDueToBlock,
  permissionsDisabledByBlock,
} from 'lib/shared/thread-utils';
import type {
  ThreadPermission,
  ThreadPermissionsBlob,
} from 'lib/types/thread-types';

import { dbQuery, SQL } from '../database/database';
import type { Viewer } from '../session/viewer';
import { fetchThreadInfos } from './thread-fetchers';
import { fetchKnownUserInfos } from './user-fetchers';

// Note that it's risky to verify permissions by inspecting the blob directly.
// There are other factors that can override permissions in the permissions
// blob, such as when one user blocks another. It's always better to go through
// checkThreads and friends, or by looking at the ThreadInfo through
// threadHasPermission.
async function fetchThreadPermissionsBlob(
  viewer: Viewer,
  threadID: string,
): Promise<?ThreadPermissionsBlob> {
  const viewerID = viewer.id;
  const query = SQL`
    SELECT permissions
    FROM memberships
    WHERE thread = ${threadID} AND user = ${viewerID}
  `;
  const [result] = await dbQuery(query);

  if (result.length === 0) {
    return null;
  }
  const row = result[0];
  return row.permissions;
}

function checkThreadPermission(
  viewer: Viewer,
  threadID: string,
  permission: ThreadPermission,
): Promise<boolean> {
  return checkThread(viewer, threadID, [{ check: 'permission', permission }]);
}

function viewerIsMember(viewer: Viewer, threadID: string): Promise<boolean> {
  return checkThread(viewer, threadID, [{ check: 'is_member' }]);
}

type Check =
  | {| +check: 'is_member' |}
  | {| +check: 'permission', +permission: ThreadPermission |};

function isThreadValid(
  permissions: ?ThreadPermissionsBlob,
  role: number,
  checks: $ReadOnlyArray<Check>,
): boolean {
  for (const check of checks) {
    if (check.check === 'is_member') {
      if (role <= 0) {
        return false;
      }
    } else if (check.check === 'permission') {
      if (!permissionLookup(permissions, check.permission)) {
        return false;
      }
    }
  }
  return true;
}

async function checkThreads(
  viewer: Viewer,
  threadIDs: $ReadOnlyArray<string>,
  checks: $ReadOnlyArray<Check>,
): Promise<Set<string>> {
  const query = SQL`
    SELECT thread, permissions, role
    FROM memberships
    WHERE thread IN (${threadIDs}) AND user = ${viewer.userID}
  `;

  const permissionsToCheck = [];
  for (const check of checks) {
    if (check.check === 'permission') {
      permissionsToCheck.push(check.permission);
    }
  }

  const [[result], disabledThreadIDs] = await Promise.all([
    dbQuery(query),
    checkThreadsFrozen(viewer, permissionsToCheck, threadIDs),
  ]);

  return new Set(
    result
      .filter(
        (row) =>
          isThreadValid(row.permissions, row.role, checks) &&
          !disabledThreadIDs.has(row.thread.toString()),
      )
      .map((row) => row.thread.toString()),
  );
}

async function checkThreadsFrozen(
  viewer: Viewer,
  permissionsToCheck: $ReadOnlyArray<ThreadPermission>,
  threadIDs: $ReadOnlyArray<string>,
) {
  const threadIDsWithDisabledPermissions = new Set();

  const permissionMightBeDisabled = permissionsToCheck.some((permission) =>
    permissionsDisabledByBlock.has(permission),
  );
  if (!permissionMightBeDisabled) {
    return threadIDsWithDisabledPermissions;
  }

  const [{ threadInfos }, userInfos] = await Promise.all([
    fetchThreadInfos(viewer, SQL`t.id IN (${[...threadIDs]})`),
    fetchKnownUserInfos(viewer),
  ]);

  for (const threadID in threadInfos) {
    const blockedThread = threadFrozenDueToBlock(
      threadInfos[threadID],
      viewer.id,
      userInfos,
    );
    if (blockedThread) {
      threadIDsWithDisabledPermissions.add(threadID);
    }
  }
  return threadIDsWithDisabledPermissions;
}

async function checkIfThreadIsBlocked(
  viewer: Viewer,
  threadID: string,
  permission: ThreadPermission,
) {
  const disabledThreadIDs = await checkThreadsFrozen(
    viewer,
    [permission],
    [threadID],
  );

  return disabledThreadIDs.has(threadID);
}

async function checkThread(
  viewer: Viewer,
  threadID: string,
  checks: $ReadOnlyArray<Check>,
): Promise<boolean> {
  const validThreads = await checkThreads(viewer, [threadID], checks);
  return validThreads.has(threadID);
}

export {
  fetchThreadPermissionsBlob,
  checkThreadPermission,
  viewerIsMember,
  checkThreads,
  checkThread,
  checkIfThreadIsBlocked,
};
<commit_msg>[server] Have script viewers automatically pass checkThreads<commit_after>// @flow

import { permissionLookup } from 'lib/permissions/thread-permissions';
import {
  threadFrozenDueToBlock,
  permissionsDisabledByBlock,
} from 'lib/shared/thread-utils';
import type {
  ThreadPermission,
  ThreadPermissionsBlob,
} from 'lib/types/thread-types';

import { dbQuery, SQL } from '../database/database';
import type { Viewer } from '../session/viewer';
import { fetchThreadInfos } from './thread-fetchers';
import { fetchKnownUserInfos } from './user-fetchers';

// Note that it's risky to verify permissions by inspecting the blob directly.
// There are other factors that can override permissions in the permissions
// blob, such as when one user blocks another. It's always better to go through
// checkThreads and friends, or by looking at the ThreadInfo through
// threadHasPermission.
async function fetchThreadPermissionsBlob(
  viewer: Viewer,
  threadID: string,
): Promise<?ThreadPermissionsBlob> {
  const viewerID = viewer.id;
  const query = SQL`
    SELECT permissions
    FROM memberships
    WHERE thread = ${threadID} AND user = ${viewerID}
  `;
  const [result] = await dbQuery(query);

  if (result.length === 0) {
    return null;
  }
  const row = result[0];
  return row.permissions;
}

function checkThreadPermission(
  viewer: Viewer,
  threadID: string,
  permission: ThreadPermission,
): Promise<boolean> {
  return checkThread(viewer, threadID, [{ check: 'permission', permission }]);
}

function viewerIsMember(viewer: Viewer, threadID: string): Promise<boolean> {
  return checkThread(viewer, threadID, [{ check: 'is_member' }]);
}

type Check =
  | {| +check: 'is_member' |}
  | {| +check: 'permission', +permission: ThreadPermission |};

function isThreadValid(
  permissions: ?ThreadPermissionsBlob,
  role: number,
  checks: $ReadOnlyArray<Check>,
): boolean {
  for (const check of checks) {
    if (check.check === 'is_member') {
      if (role <= 0) {
        return false;
      }
    } else if (check.check === 'permission') {
      if (!permissionLookup(permissions, check.permission)) {
        return false;
      }
    }
  }
  return true;
}

async function checkThreads(
  viewer: Viewer,
  threadIDs: $ReadOnlyArray<string>,
  checks: $ReadOnlyArray<Check>,
): Promise<Set<string>> {
  if (viewer.isScriptViewer) {
    // script viewers are all-powerful
    return new Set(threadIDs);
  }

  const query = SQL`
    SELECT thread, permissions, role
    FROM memberships
    WHERE thread IN (${threadIDs}) AND user = ${viewer.userID}
  `;

  const permissionsToCheck = [];
  for (const check of checks) {
    if (check.check === 'permission') {
      permissionsToCheck.push(check.permission);
    }
  }

  const [[result], disabledThreadIDs] = await Promise.all([
    dbQuery(query),
    checkThreadsFrozen(viewer, permissionsToCheck, threadIDs),
  ]);

  return new Set(
    result
      .filter(
        (row) =>
          isThreadValid(row.permissions, row.role, checks) &&
          !disabledThreadIDs.has(row.thread.toString()),
      )
      .map((row) => row.thread.toString()),
  );
}

async function checkThreadsFrozen(
  viewer: Viewer,
  permissionsToCheck: $ReadOnlyArray<ThreadPermission>,
  threadIDs: $ReadOnlyArray<string>,
) {
  const threadIDsWithDisabledPermissions = new Set();

  const permissionMightBeDisabled = permissionsToCheck.some((permission) =>
    permissionsDisabledByBlock.has(permission),
  );
  if (!permissionMightBeDisabled) {
    return threadIDsWithDisabledPermissions;
  }

  const [{ threadInfos }, userInfos] = await Promise.all([
    fetchThreadInfos(viewer, SQL`t.id IN (${[...threadIDs]})`),
    fetchKnownUserInfos(viewer),
  ]);

  for (const threadID in threadInfos) {
    const blockedThread = threadFrozenDueToBlock(
      threadInfos[threadID],
      viewer.id,
      userInfos,
    );
    if (blockedThread) {
      threadIDsWithDisabledPermissions.add(threadID);
    }
  }
  return threadIDsWithDisabledPermissions;
}

async function checkIfThreadIsBlocked(
  viewer: Viewer,
  threadID: string,
  permission: ThreadPermission,
) {
  const disabledThreadIDs = await checkThreadsFrozen(
    viewer,
    [permission],
    [threadID],
  );

  return disabledThreadIDs.has(threadID);
}

async function checkThread(
  viewer: Viewer,
  threadID: string,
  checks: $ReadOnlyArray<Check>,
): Promise<boolean> {
  const validThreads = await checkThreads(viewer, [threadID], checks);
  return validThreads.has(threadID);
}

export {
  fetchThreadPermissionsBlob,
  checkThreadPermission,
  viewerIsMember,
  checkThreads,
  checkThread,
  checkIfThreadIsBlocked,
};
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe(FILL_ME_IN); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(FILL_ME_IN);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(FILL_ME_IN);
    expect(multiTypeArray[2]).toBe(FILL_ME_IN);
    expect(multiTypeArray[3]()).toBe(FILL_ME_IN);
    expect(multiTypeArray[4].value1).toBe(FILL_ME_IN);
    expect(multiTypeArray[4]["value2"]).toBe(FILL_ME_IN);
    expect(multiTypeArray[5][0]).toBe(FILL_ME_IN);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, FILL_ME_IN]);

    array.push(3);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>made Arrays tests pass<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(['peanut']);
    expect(array.slice(0, 2)).toEqual(['peanut', 'butter']);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(['and', 'jelly']);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(['jelly']);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1, 2, 3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1, 2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3, 1, 2]);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1, 2]);
  });
});
<|endoftext|>


<commit_before>var async = require('async');
var exec = require('child_process').exec;
var NodeRunner = require('../src/RunWrappers/Node');
var CmdHelper = require('../src/CmdHelper');
var RunListHelper = require('../src/RunListHelper');
var _ = require('lodash');
var green = '\u001b[42m \u001b[0m';
var red = '\u001b[41m \u001b[0m';
var reposToInstall = [];

function isYarnUsed(bosco, repoPath) {
  var yarnrcFile = [repoPath, '.yarnrc'].join('/');
  var yarnLockFile = [repoPath, 'yarn.lock'].join('/');
  return bosco.exists(yarnrcFile) || bosco.exists(yarnLockFile);
}

function getPackageManager(bosco, repoPath, interpreter) {
  var nvm = interpreter && bosco.options.nvmUse || bosco.options.nvmUseDefault;
  var name;
  var command;
  if (isYarnUsed(bosco, repoPath)) {
    name = 'Yarn';
    command = 'yarn --pure-lockfile';
  } else {
    name = 'NPM';
    command = 'npm';
    if (bosco.config.get('npm:registry')) {
      command += ' --no-package-lock --registry ' + bosco.config.get('npm:registry');
    }
    command += ' install';
  }
  return {name: name, command: nvm + command};
}

function cleanModulesIfVersionChanged(bosco, repoPath, repo, next) {
  NodeRunner.getVersion(bosco, {cwd: repoPath}, function(err, currentVersion) {
    if (err) { return next(err); }
    var nodeVersionKey = 'teams:' + bosco.getTeam() + ':nodes:' + repo;
    var lastVersion = bosco.config.get(nodeVersionKey);
    if (lastVersion && lastVersion !== currentVersion) {
      bosco.prompt.start();
      var confirmationDescription = 'Node version in '.white + repo.cyan + ' has changed from '.white + lastVersion.green + ' to '.white + currentVersion.green + ', should I clear node_modules (y/N)?'.white;
      bosco.prompt.get({
        properties: {
          confirm: {
            description: confirmationDescription,
          },
        },
      }, function(err, result) {
        if (!result || (result.confirm !== 'Y' && result.confirm !== 'y')) {
          return next();
        }

        exec('rm -rf ./node_modules', {cwd: repoPath}, function(err, stdout, stderr) {
          if (err) {
            bosco.error('Failed to clear node_modules for ' + repoPath.blue + ' >> ' + stderr);
          } else {
            bosco.log('Node version in ' + repo.green + ' updated to ' + currentVersion.green);
            bosco.config.set(nodeVersionKey, currentVersion);
          }
          next();
        });
      });
    } else {
      bosco.log('Node version in ' + repo.green + ' is OK at ' + currentVersion.green);
      bosco.config.set(nodeVersionKey, currentVersion);
      next();
    }
  });
}

function shouldInstallRepo(bosco, repoPath, repo, next) {
  NodeRunner.getHashes(bosco, ['package.json', '.nvmrc', 'yarn.lock', 'package-lock.json'], {cwd: repoPath}, function(err, currentHash) {
    if (err) { return next(err); }
    var nodeHashKey = 'teams:' + bosco.getTeam() + ':hashes:' + repo;
    var lastHash = bosco.config.get(nodeHashKey);
    if (lastHash !== currentHash) {
      reposToInstall.push(repo);
      bosco.config.set(nodeHashKey, currentHash);
    }
    next();
  });
}

function install(bosco, progressbar, bar, repoPath, repo, next) {
  var packageJson = [repoPath, 'package.json'].join('/');
  if (!bosco.exists(packageJson)) {
    if (progressbar) bar.tick();
    return next();
  }

  NodeRunner.getInterpreter(bosco, {name: repo, cwd: repoPath}, function(err, interpreter) {
    if (err) {
      bosco.error(err);
      return next();
    }

    var packageManager = getPackageManager(bosco, repoPath, interpreter);
    exec(packageManager.command, {
      cwd: repoPath,
    }, function(err, stdout, stderr) {
      if (progressbar) bar.tick();
      if (err) {
        if (progressbar) bosco.console.log('');
        bosco.error(repoPath.blue + ' >> ' + stderr);
      } else {
        if (!progressbar) {
          if (!stdout) {
            bosco.log(packageManager.name + ' install for ' + repoPath.blue + ': ' + 'No changes'.green);
          } else {
            bosco.log(packageManager.name + ' install for ' + repoPath.blue);
            bosco.console.log(stdout);
            if (stderr) {
              bosco.error(stderr);
            }
          }
        }
      }
      next();
    });
  });
}

function cmd(bosco, args, next) {
  var repoPattern = bosco.options.repo;
  var repoRegex = new RegExp(repoPattern);

  var repos = bosco.getRepos();
  if (!repos) return bosco.error('You are repo-less :( You need to initialise bosco first, try \'bosco clone\'.');

  bosco.log('Running install across repos ...');

  function setRunRepos(cb) {
    if (!CmdHelper.checkInService(bosco)) {
      return cb();
    }

    RunListHelper.getRepoRunList(bosco, bosco.getRepos(), repoRegex, '$^', null, false, function(err, runRepos) {
      repos = _.chain(runRepos)
              .filter(function(repo) { return repo.type !== 'docker'; })
              .map('name')
              .value();
      cb(err);
    });
  }

  function shouldInstallRepos(cb) {
    async.mapSeries(repos, function repoCheck(repo, repoCb) {
      if (!repo.match(repoRegex)) { return repoCb(); }
      var repoPath = bosco.getRepoPath(repo);
      shouldInstallRepo(bosco, repoPath, repo, repoCb);
    }, function() {
      if (reposToInstall.length > 0) {
        bosco.log('The following repos had changes in key files, so will trigger an install: ');
        bosco.log(reposToInstall.join(', ').cyan);
      }
      cb();
    });
  }

  function checkRepos(cb) {
    async.mapSeries(reposToInstall, function repoCheck(repo, repoCb) {
      if (!repo.match(repoRegex)) return repoCb();
      var repoPath = bosco.getRepoPath(repo);
      cleanModulesIfVersionChanged(bosco, repoPath, repo, repoCb);
    }, function() {
      cb();
    });
  }

  function installRepos(cb) {
    var progressbar = bosco.config.get('progress') === 'bar';
    var total = repos.length;

    var bar = progressbar ? new bosco.Progress('Doing npm install [:bar] :percent :etas', {
      complete: green,
      incomplete: red,
      width: 50,
      total: total,
    }) : null;

    async.mapLimit(reposToInstall, bosco.concurrency.cpu, function repoInstall(repo, repoCb) {
      if (!repo.match(repoRegex)) return repoCb();
      var repoPath = bosco.getRepoPath(repo);
      install(bosco, progressbar, bar, repoPath, repo, repoCb);
    }, function() {
      cb();
    });
  }

  function saveConfig(cb) {
    bosco.config.save(cb);
  }

  async.series([
    setRunRepos,
    shouldInstallRepos,
    checkRepos,
    installRepos,
    saveConfig,
  ], function() {
    bosco.log('npm install complete');
    if (next) next();
  });
}

module.exports = {
  name: 'install',
  description: 'Runs npm install against all repos',
  usage: '[-r <repoPattern>]',
  requiresNvm: true,
  cmd: cmd,
};
<commit_msg>Add --no-package-lock to npm install - but put it in the right place<commit_after>var async = require('async');
var exec = require('child_process').exec;
var NodeRunner = require('../src/RunWrappers/Node');
var CmdHelper = require('../src/CmdHelper');
var RunListHelper = require('../src/RunListHelper');
var _ = require('lodash');
var green = '\u001b[42m \u001b[0m';
var red = '\u001b[41m \u001b[0m';
var reposToInstall = [];

function isYarnUsed(bosco, repoPath) {
  var yarnrcFile = [repoPath, '.yarnrc'].join('/');
  var yarnLockFile = [repoPath, 'yarn.lock'].join('/');
  return bosco.exists(yarnrcFile) || bosco.exists(yarnLockFile);
}

function getPackageManager(bosco, repoPath, interpreter) {
  var nvm = interpreter && bosco.options.nvmUse || bosco.options.nvmUseDefault;
  var name;
  var command;
  if (isYarnUsed(bosco, repoPath)) {
    name = 'Yarn';
    command = 'yarn --pure-lockfile';
  } else {
    name = 'NPM';
    command = 'npm';
    if (bosco.config.get('npm:registry')) {
      command += '--registry ' + bosco.config.get('npm:registry');
    }
    command += ' --no-package-lock install';
  }
  return {name: name, command: nvm + command};
}

function cleanModulesIfVersionChanged(bosco, repoPath, repo, next) {
  NodeRunner.getVersion(bosco, {cwd: repoPath}, function(err, currentVersion) {
    if (err) { return next(err); }
    var nodeVersionKey = 'teams:' + bosco.getTeam() + ':nodes:' + repo;
    var lastVersion = bosco.config.get(nodeVersionKey);
    if (lastVersion && lastVersion !== currentVersion) {
      bosco.prompt.start();
      var confirmationDescription = 'Node version in '.white + repo.cyan + ' has changed from '.white + lastVersion.green + ' to '.white + currentVersion.green + ', should I clear node_modules (y/N)?'.white;
      bosco.prompt.get({
        properties: {
          confirm: {
            description: confirmationDescription,
          },
        },
      }, function(err, result) {
        if (!result || (result.confirm !== 'Y' && result.confirm !== 'y')) {
          return next();
        }

        exec('rm -rf ./node_modules', {cwd: repoPath}, function(err, stdout, stderr) {
          if (err) {
            bosco.error('Failed to clear node_modules for ' + repoPath.blue + ' >> ' + stderr);
          } else {
            bosco.log('Node version in ' + repo.green + ' updated to ' + currentVersion.green);
            bosco.config.set(nodeVersionKey, currentVersion);
          }
          next();
        });
      });
    } else {
      bosco.log('Node version in ' + repo.green + ' is OK at ' + currentVersion.green);
      bosco.config.set(nodeVersionKey, currentVersion);
      next();
    }
  });
}

function shouldInstallRepo(bosco, repoPath, repo, next) {
  NodeRunner.getHashes(bosco, ['package.json', '.nvmrc', 'yarn.lock', 'package-lock.json'], {cwd: repoPath}, function(err, currentHash) {
    if (err) { return next(err); }
    var nodeHashKey = 'teams:' + bosco.getTeam() + ':hashes:' + repo;
    var lastHash = bosco.config.get(nodeHashKey);
    if (lastHash !== currentHash) {
      reposToInstall.push(repo);
      bosco.config.set(nodeHashKey, currentHash);
    }
    next();
  });
}

function install(bosco, progressbar, bar, repoPath, repo, next) {
  var packageJson = [repoPath, 'package.json'].join('/');
  if (!bosco.exists(packageJson)) {
    if (progressbar) bar.tick();
    return next();
  }

  NodeRunner.getInterpreter(bosco, {name: repo, cwd: repoPath}, function(err, interpreter) {
    if (err) {
      bosco.error(err);
      return next();
    }

    var packageManager = getPackageManager(bosco, repoPath, interpreter);
    exec(packageManager.command, {
      cwd: repoPath,
    }, function(err, stdout, stderr) {
      if (progressbar) bar.tick();
      if (err) {
        if (progressbar) bosco.console.log('');
        bosco.error(repoPath.blue + ' >> ' + stderr);
      } else {
        if (!progressbar) {
          if (!stdout) {
            bosco.log(packageManager.name + ' install for ' + repoPath.blue + ': ' + 'No changes'.green);
          } else {
            bosco.log(packageManager.name + ' install for ' + repoPath.blue);
            bosco.console.log(stdout);
            if (stderr) {
              bosco.error(stderr);
            }
          }
        }
      }
      next();
    });
  });
}

function cmd(bosco, args, next) {
  var repoPattern = bosco.options.repo;
  var repoRegex = new RegExp(repoPattern);

  var repos = bosco.getRepos();
  if (!repos) return bosco.error('You are repo-less :( You need to initialise bosco first, try \'bosco clone\'.');

  bosco.log('Running install across repos ...');

  function setRunRepos(cb) {
    if (!CmdHelper.checkInService(bosco)) {
      return cb();
    }

    RunListHelper.getRepoRunList(bosco, bosco.getRepos(), repoRegex, '$^', null, false, function(err, runRepos) {
      repos = _.chain(runRepos)
              .filter(function(repo) { return repo.type !== 'docker'; })
              .map('name')
              .value();
      cb(err);
    });
  }

  function shouldInstallRepos(cb) {
    async.mapSeries(repos, function repoCheck(repo, repoCb) {
      if (!repo.match(repoRegex)) { return repoCb(); }
      var repoPath = bosco.getRepoPath(repo);
      shouldInstallRepo(bosco, repoPath, repo, repoCb);
    }, function() {
      if (reposToInstall.length > 0) {
        bosco.log('The following repos had changes in key files, so will trigger an install: ');
        bosco.log(reposToInstall.join(', ').cyan);
      }
      cb();
    });
  }

  function checkRepos(cb) {
    async.mapSeries(reposToInstall, function repoCheck(repo, repoCb) {
      if (!repo.match(repoRegex)) return repoCb();
      var repoPath = bosco.getRepoPath(repo);
      cleanModulesIfVersionChanged(bosco, repoPath, repo, repoCb);
    }, function() {
      cb();
    });
  }

  function installRepos(cb) {
    var progressbar = bosco.config.get('progress') === 'bar';
    var total = repos.length;

    var bar = progressbar ? new bosco.Progress('Doing npm install [:bar] :percent :etas', {
      complete: green,
      incomplete: red,
      width: 50,
      total: total,
    }) : null;

    async.mapLimit(reposToInstall, bosco.concurrency.cpu, function repoInstall(repo, repoCb) {
      if (!repo.match(repoRegex)) return repoCb();
      var repoPath = bosco.getRepoPath(repo);
      install(bosco, progressbar, bar, repoPath, repo, repoCb);
    }, function() {
      cb();
    });
  }

  function saveConfig(cb) {
    bosco.config.save(cb);
  }

  async.series([
    setRunRepos,
    shouldInstallRepos,
    checkRepos,
    installRepos,
    saveConfig,
  ], function() {
    bosco.log('npm install complete');
    if (next) next();
  });
}

module.exports = {
  name: 'install',
  description: 'Runs npm install against all repos',
  usage: '[-r <repoPattern>]',
  requiresNvm: true,
  cmd: cmd,
};
<|endoftext|>


<commit_before>var React = require('react');
var elemental = require('elemental'),
	Button = elemental.Button,
	FormField = elemental.FormField,
	FormInput = elemental.FormInput,
	Modal = elemental.Modal,
	ModalHeader = elemental.ModalHeader,
	ModalBody = elemental.ModalBody,
	ModalFooter = elemental.ModalFooter;

module.exports = React.createClass({

	displayName: 'cloudinaryInsertModal',

	getInitialState() {
		return {
			formProcessing: false,
			isOpen: false,
			email: '',
			password: ''
		};
	},

	show() {
		this.setState({ isOpen: true });
	},

	toggleModal() {
		var self = this;
		this.setState({
			isOpen: !this.state.isOpen
		}, function () {
			if (self.state.isOpen) {
				self.refs.first.getDOMNode().focus();
			}
		});
	},

	render: function() {
		return (
			<Modal isOpen={this.state.isOpen} onCancel={this.toggleModal} backdropClosesModal>
				<ModalHeader text="Insert Image" showCloseButton onClose={this.toggleModal} />
				<form action="#" onSubmit={this.submitForm} noValidate>
					<ModalBody>
						<FormField label="Email">
							<FormInput label="Email" type="email" name="email" ref="email" value={this.state.email} required />
						</FormField>
						<FormField label="Password">
							<FormInput label="Password" type="password" name="password" ref="password" value={this.state.password} required />
						</FormField>
					</ModalBody>
					<ModalFooter>
						<Button onClick={this.toggleModal} type="link-cancel" disabled={this.state.formProcessing}>Cancel</Button>
					</ModalFooter>
				</form>
			</Modal>
		);
						//{submitButton}
	}
});<commit_msg>Initial insertion values, styling. Debug: open the modal on load.<commit_after>var React = require('react');
var elemental = require('elemental'),
	Button = elemental.Button,
	FormField = elemental.FormField,
	FormInput = elemental.FormInput,
	FormRow = elemental.FormRow,
	Modal = elemental.Modal,
	ModalHeader = elemental.ModalHeader,
	ModalBody = elemental.ModalBody,
	ModalFooter = elemental.ModalFooter;

module.exports = React.createClass({

	displayName: 'cloudinaryInsertModal',

	getInitialState() {
		return {
			formProcessing: false,
			isOpen: true, //false,
			email: '',
			password: '',

			//defaultDescription: this.
		};
	},

	show() {
		this.setState({ isOpen: true });
	},

	toggleModal() {
		var self = this;
		this.setState({
			isOpen: !this.state.isOpen
		}, function () {
			if (self.state.isOpen) {
				self.refs.first.getDOMNode().focus();
			}
		});
	},

	render: function() {
		return (
			<Modal isOpen={this.state.isOpen} onCancel={this.toggleModal} backdropClosesModal>
				<ModalHeader text="Insert Image" showCloseButton onClose={this.toggleModal} />
				<form className="horizontal-form" action="#" onSubmit={this.submitForm} noValidate>
					<ModalBody>
						<FormField label="File">

Filename here

						</FormField>
						<FormField label="Description">
							<FormInput label="Description" type="text" name="description" ref="description" placeholder={this.state.defaultDescription} required size="sm" />
						</FormField>
						<FormField label="Size">
							<FormRow>
								<FormField label="Width">
									<FormInput label="Width" pattern="[0-9]+" name="width" ref="width" />
								</FormField>

x

								<FormField label="Height">
									<FormInput label="Height" pattern="[0-9]+" name="height" ref="height" />
								</FormField>
							</FormRow>
						</FormField>
					</ModalBody>
					<ModalFooter>
						<Button onClick={this.toggleModal} type="link-cancel" disabled={this.state.formProcessing}>Cancel</Button>
					</ModalFooter>
				</form>
			</Modal>
		);
						//{submitButton}
	}
});<|endoftext|>


<commit_before>/* TfL Bus Atrival Predictions */

/* Magic Mirror
 * Module: MMM-TFL-Arrivals
 * By Ricardo Gonzalez
 * MIT Licensed.
 */

var NodeHelper = require("node_helper");
var request = require("request");

module.exports = NodeHelper.create({
	start: function () {
		console.log("MMM-TFL-Arrivals helper started ...");
	},
	/* getTimetable()
	 * Requests new data from TfL API.
	 * Sends data back via socket on succesfull response.
	 */
	getTimetable: function(url) {
			var self = this;
			var retry = true;

			request({url:url, method: "GET"}, function(error, response, body) {
	            // Lets convert the body into JSON
	            var result = JSON.parse(body);

				if(!error && response.statusCode == 200) {
					self.sendSocketNotification("BUS_DATA", {"data": JSON.parse(body), "url": url});
				} else {
					self.sendSocketNotification("BUS_DATA", {"data": null, "url": url});
				}
			});
		},
	//Subclass socketNotificationReceived received.
	socketNotificationReceived: function(notification, payload) {
		if (notification === "GET_BUSARRIVALS") {
			this.getTimetable(payload.url);
		}
	}
});
<commit_msg>Extra checks<commit_after>/* TfL Bus Atrival Predictions */

/* Magic Mirror
 * Module: MMM-TFL-Arrivals
 * By Ricardo Gonzalez
 * MIT Licensed.
 */

var NodeHelper = require("node_helper");
var request = require("request");

module.exports = NodeHelper.create({
	start: function () {
		console.log("MMM-TFL-Arrivals helper started ...");
	},
	/* getTimetable()
	 * Requests new data from TfL API.
	 * Sends data back via socket on succesfull response.
	 */
	getTimetable: function(url) {
			var self = this;
			var retry = true;

			request({url:url, method: "GET"}, function(error, response, body) {
				if(!error && response.statusCode == 200 && body != null) {
					self.sendSocketNotification("BUS_DATA", {"data": JSON.parse(body), "url": url});
				} else {
					self.sendSocketNotification("BUS_DATA", {"data": null, "url": url});
				}
			});
		},
	//Subclass socketNotificationReceived received.
	socketNotificationReceived: function(notification, payload) {
		if (notification === "GET_BUSARRIVALS") {
			this.getTimetable(payload.url);
		}
	}
});
<|endoftext|>