<commit_before>angular.module('mrlapp', [
    'ui.bootstrap',
    'mrlapp.service',
    'mrlapp.service.arduinogui',
    'mrlapp.service.clockgui'
])

        .service('ServiceControllerService', ['HelperService', function (HelperService) {

                /*function Message() {
                 this.msgID;
                 this.timestamp;
                 this.name;
                 this.sender;
                 this.sendingMethod;
                 this.historyList;
                 this.security;
                 this.status;
                 this.msgType;
                 this.method;
                 this.data;
                 }*/

                /*function Message(name, method, params) {
                 this.msgID = new Date().getTime();
                 this.timeStamp = this.msgID;
                 this.name = name;
                 this.sender = webguiName; // FIXME - named passed in
                 this.sendingMethod = method;
                 this.historyList = new Array(); // necessary?
                 this.method = method;
                 this.data = params;
                 }*/

                this.services = [];

                function Serv(name, servic) {
                    this.name = name;
                    this.servic = servic;
                    this.listener = [];
                }

                this.getServiceInst = function (name) {
                    if (HelperService.isUndefinedOrNull(this.services[name])) {
                        return null;
                    }
                    return this.services[name].servic;
                };

                this.addService = function (name, servic) {
                    this.services[name] = new Serv(name, servic);
                };

                this.removeService = function (name, servic) {
                    //TODO - fill in
                };

                this.addListener = function (name, listener, listener2) {
                    //TODO: right name?
                    //TODO - need to work on this
                    this.services[name].listener.push(listener);
                };

                this.removeListener = function () {
                    //TODO: right name?
                    //TODO - fill in
                };

                this.notify = function () {
                    //TODO: what did I want to do with this function?
                    //TODO - fill in
                };

                this.test = function (name) {
                    //TODO: remove
                    executeFunctionByName("pulse", this.services[name].servic.methods);
//                    this.services["clock"].servic["tester"].apply(this);
                };

//                TODO - delete
//                this.observers = [];
//
//                this.registerObserver = function (observer) {
//                    this.observers.push(observer);
//                };
//
//                this.notifyAll = function () {
//                    for (var index = 0; index < this.observers.length; ++index)
//                        this.observers[index].notify();
//                };
//
//                this.myData = ["some", "list", "of", "data"];
//
//                this.setData = function (newData) {
//                    myData = newData;
//                    notifyAll();
//                };
//
//                this.getData = function () {
//                    return myData;
//                };

                function executeFunctionByName(functionName, context /*, args */) {
                    var args = [].slice.call(arguments).splice(2);
                    var namespaces = functionName.split(".");
                    var func = namespaces.pop();
                    for (var i = 0; i < namespaces.length; i++) {
                        context = context[namespaces[i]];
                    }
                    return context[func].apply(this, args);
                }
            }])

        .service('HelperService', [function () {
                this.isUndefinedOrNull = function (val) {
                    return angular.isUndefined(val) || val === null;
                };
            }])

        .directive('serviceComponent', ['$document', function ($document) {
                return {
                    scope: {
                        //"=" -> binding to items in parent-scope specified by attribute
                        //"@" -> using passed attribute
                        index: '@index',
                        list: '=list',
                        reftomain: '=reftomain',
                        size: '=size'
                    },
                    templateUrl: 'views/service.html',
                    link: function (scope, element, attr) {
                        var startX = 0, startY = 0, x = 0, y = 0;
                        var offsetY = 200;
                        var headerY = 50;
                        var footerY = 50;

                        var outgenerallist = false;
                        var ingenerallist = false;

                        element.css({
                            position: 'relative'
                        });

                        element.on('mousedown', function (event) {
                            outgenerallist = event.pageY < 250;
                            startX = event.pageX - x;
                            startY = event.pageY - y;
                            var height = element.height();
                            if (startY < offsetY + headerY ||
                                    startY > offsetY + height - footerY) {
                                // Prevent default dragging of selected content
                                event.preventDefault();

                                //put panel in foreground
                                //TODO: worky, but sometimes buggy
                                var zindex = scope.list[scope.index].zindex;
                                console.log('zindex', zindex);
//                                var str1 = '';
//                                angular.forEach(scope.list, function (value, key) {
//                                    str1 = str1 + value.zindex + ", ";
//                                });
//                                console.log('zindex3', str1);
                                angular.forEach(scope.list, function (value, key) {
                                    //console.log("zindex2", key, value.zindex);
                                    if (value.zindex > zindex) {
                                        value.zindex--;
                                    }
                                });
                                scope.list[scope.index].zindex = scope.list.length;
//                                var str2 = '';
//                                angular.forEach(scope.list, function (value, key) {
//                                    str2 = str2 + value.zindex + ", ";
//                                });
//                                console.log('zindex3', str2);

                                element.css({
                                    cursor: 'move',
                                    'z-index': zindex
                                });
                                $document.on('mousemove', mousemove);
                                $document.on('mouseup', mouseup);
                            }
                        });

                        function mousemove(event) {
//                            console.log('mousemove', event.pageX, event.pageY);
                            ingenerallist = event.pageY < 250;
                            y = event.pageY - startY;
                            x = event.pageX - startX;
                            element.css({
                                top: y + 'px',
                                left: x + 'px'
                            });
                        }

                        function mouseup() {
                            $document.off('mousemove', mousemove);
                            $document.off('mouseup', mouseup);
                            element.css({
                                cursor: 'auto'
                            });
                            //move panel to different list (if it was moved there)
                            //TODO: worky, but sometimes buggy
                            if (ingenerallist && !outgenerallist) {
                                scope.reftomain.dragInGenerallist(scope.index, scope.list);
                            } else if (!ingenerallist && outgenerallist) {
                                scope.reftomain.dragOutGenerallist(scope.index);
                            }
                        }
                    }
                };
            }])

        .directive('tabComponent', [function () {
                return {
                    scope: {
                        //"=" -> binding to items in parent-scope specified by attribute
                        //"@" -> using passed attribute
                        index: '@index',
                        workspaces: '=workspaces',
                        reftomain: '=reftomain'
                    },
                    templateUrl: 'views/tab.html'
                };
            }])

        .directive('dropComponent', [function () {
                return {
                    scope: {
                        //"=" -> binding to items in parent-scope specified by attribute
                        //"@" -> using passed attribute
                        list: '=list',
                        size: '@size'
                    },
                    templateUrl: 'views/drop.html'
                };
            }])

        .filter('reverse', function () {
            return function (items) {
                return items.slice().reverse();
            };
        })

        .controller('MainCtrl', ['$scope', 'ServiceControllerService', function ($scope, ServiceControllerService) {

//                $scope.statusakt = 'I am going to be the new WebUI for MyRobotLab!';
                $scope.statuslist = [];

                $scope.addStatus = function (status) {
                    $scope.statuslist.push(status);
                };

                $scope.addStatus('And this is my status history!');
                $scope.addStatus('And this is my status history!');
                $scope.addStatus('And this is my status history!');
                $scope.addStatus('I am going to be the new WebUI for MyRobotLab!');

                $scope.allServices = [];

                $scope.generallist = [];

                var workspacecounter = 0;

                var setAllInactive = function () {
                    angular.forEach($scope.workspaces, function (workspace) {
                        workspace.active = false;
                    });
                };

                var addNewWorkspace = function () {
                    workspacecounter++;
                    $scope.workspaces.push({
                        name: "Workspace " + workspacecounter,
                        active: true,
                        dropdownisopen: false
                    });
                };

                $scope.workspaces = [];
                $scope.workspacesref = [];
                addNewWorkspace();
                addNewWorkspace();
                setAllInactive();
                $scope.workspaces[0].active = true;

                $scope.addWorkspace = function () {
                    setAllInactive();
                    addNewWorkspace();
                };

                $scope.removeWorkspace = function (index) {
                    console.log('removeworkspace, ', index);
                    if ($scope.workspaces.length > 1) {
                        $scope.workspaces.splice(index, 1);
                        $scope.workspacesref.splice(index, 1);
                    } else {
                        console.log('cant remove, not enough workspaces left');
                    }
                };

                //TODO: refactor this
                $scope.reftomain = {};

                $scope.reftomain.addRefToWorkspace = function (index, workspace) {
                    $scope.workspacesref[index] = workspace;
                };

                $scope.reftomain.dragInGenerallist = function (index, list) {
                    console.log('tab -> general');
                    $scope.generallist.push(list[index]);
                    list.splice(index, 1);
                };

                $scope.reftomain.dragOutGenerallist = function (index) {
                    console.log('general -> tab');
                    var ind = -1;
                    angular.forEach($scope.workspaces, function (value, key) {
                        if (value.active) {
                            ind = key;
                        }
                    });
                    $scope.workspacesref[ind].addDragToList($scope.generallist[index]);
                    $scope.generallist.splice(index, 1);
                };

                //TODO: not final method & location
                $scope.createService = function (name, type) {
                    //spawn service in first workspace
                    var spawnin = 0;
                    $scope.workspacesref[spawnin].addDragToList({
                        'name': name,
                        'type': type
                    });
                    $scope.allServices.push({
                        'name': name,
                        'type': type,
                        'workspace': spawnin
                    });
                };

                $scope.about = function () {
                    console.log('about');
                };

                var servicecounter = 0;

                $scope.help = function () {
                    console.log('help');
                    var servicetype;
                    if (servicecounter % 2 == 0) {
                        servicetype = 'clock';
                    } else {
                        servicetype = 'arduino';
                    }
                    $scope.createService("ser" + servicecounter, servicetype);
                    servicecounter++;
                };

                $scope.searchOnSelect = function (item, model, label) {
                    console.log('searchOnSelect');
                    //select the workspace containing the selected service
                    setAllInactive();
                    $scope.workspaces[item.workspace].active = true;
                    //TODO: scroll to selected service
                };

                var Connection = {};
                Connection.transport = 'websocket';
                Connection.socket = null;

                Connection.receivedMessage = function (message) {
                    console.log('Received Message: ', message);
                    //TODO - process message (& probably forward it to ServiceControllerService (in most cases))
//                    var packet = message;
//                    switch (packet.type) {
//                            case 'update':
//                                for (var i = 0; i < packet.data.length; i++) {
//                                    Game.updateSnake(packet.data[i].id, packet.data[i].body);
//                                }
//                                break;
//                            case 'join':
//                                for (var j = 0; j < packet.data.length; j++) {
//                                    Game.addSnake(packet.data[j].id, packet.data[j].color);
//                                }
//                                break;
//                            case 'leave':
//                                Game.removeSnake(packet.id);
//                                break;
//                            case 'dead':
//                                Console.log('Info: Your snake is dead, bad luck!');
//                                Game.direction = 'none';
//                                break;
//                            case 'kill':
//                                Console.log('Info: Head shot!');
//                                break;
//                        }
                };

                Connection.sendMessage = function (message) {
                    Connection.socket.push(message);
                    console.log('Sent message: ' + message);
                };

                Connection.connect = function (host) {
                    var request = {url: host,
                        transport: 'websocket',
                        enableProtocol: true,
                        trackMessageLength: true,
                        logLevel: 'debug'};

                    request.onOpen = function (response) {
                        // Socket open ...
                        console.log('Info: ' + Connection.transport + ' connection opened.');
                    };

                    request.onClose = function (response) {
                        console.log('websocket, onclose');
                        if (response.state == "unsubscribe") {
                            console.log('Info: ' + Connection.transport + ' closed.');
                        }
                    };

                    request.onTransportFailure = function (errorMsg, request) {
                        jQuery.atmosphere.info(errorMsg);
                        if (window.EventSource) {
                            request.fallbackTransport = "sse";
                        } else {
                            request.fallbackTransport = 'long-polling';
                        }
                        Connection.transport = request.fallbackTransport;

                        console.log('Error: falling back to ' + Connection.transport + ' ' + errorMsg);
                    };

                    request.onMessage = function (response) {
                        var message = response.responseBody;
                        var packet;
                        try {
                            packet = eval('(' + message + ')'); //jQuery.parseJSON(message);
                        } catch (e) {
                            if (message == 'X') {
                                console.log('heartbeat:', message);
                            } else {
                                console.log('Error Message: ', message);
                            }
                            return;
                        }

                        Connection.receivedMessage(packet);
                    };
                    Connection.socket = $.atmosphere.subscribe(request);
                };

                Connection.connect(document.location.origin.toString() + '/api');
//                Connection.connect(document.location.origin.toString() + '/api');
//                console.log($);
//                Connection.connect('/api');
            }])

        .controller('TabsChildCtrl', ['$scope', 'ServiceControllerService', 'HelperService', function ($scope, ServiceControllerService, HelperService) {

                console.log("scope,workspaces", $scope.workspaces);
                console.log("scope,index", $scope.index);

                if (!HelperService.isUndefinedOrNull($scope.index)) {
                    $scope.workspace = $scope.workspaces[$scope.index];
                }

                //TODO: refactor this
                $scope.reftotab = {};
                $scope.reftotab.addDragToList = function (panel) {
                    angular.forEach($scope.servicelist, function (value, key) {
                        value.zindex++;
                    });
                    panel.zindex = 1;
                    $scope.servicelist.push(panel);
                };

                $scope.reftomain.addRefToWorkspace($scope.index, $scope.reftotab);

                $scope.servicelist = [
//                    {'name': 'sera', 'drag': true, 'zindex': 1, 'type': 'clock'},
//                    {'name': 'serb', 'drag': true, 'zindex': 2, 'type': 'arduino'},
//                    {'name': 'serc', 'drag': true, 'zindex': 3, 'type': 'clock'},
//                    {'name': 'serd', 'drag': true, 'zindex': 4, 'type': 'arduino'},
//                    {'name': 'sere', 'drag': true, 'zindex': 5, 'type': 'clock'},
//                    {'name': 'serf', 'drag': true, 'zindex': 6, 'type': 'arduino'},
//                    {'name': 'serg', 'drag': true, 'zindex': 7, 'type': 'clock'},
//                    {'name': 'serh', 'drag': true, 'zindex': 8, 'type': 'arduino'},
//                    {'name': 'seri', 'drag': true, 'zindex': 9, 'type': 'clock'},
//                    {'name': 'serj', 'drag': true, 'zindex': 10, 'type': 'arduino'},
//                    {'name': 'serk', 'drag': true, 'zindex': 11, 'type': 'clock'},
//                    {'name': 'serl', 'drag': true, 'zindex': 12, 'type': 'arduino'},
//                    {'name': 'serm', 'drag': true, 'zindex': 13, 'type': 'clock'},
//                    {'name': 'sern', 'drag': true, 'zindex': 14, 'type': 'arduino'},
//                    {'name': 'sero', 'drag': true, 'zindex': 15, 'type': 'clock'}
                ];
            }]);<commit_msg>some cleanup<commit_after>angular.module('mrlapp', [
    'ui.bootstrap',
    'mrlapp.service',
    'mrlapp.service.arduinogui',
    'mrlapp.service.clockgui'
])

        .service('ServiceControllerService', ['HelperService', function (HelperService) {

                /*function Message() {
                 this.msgID;
                 this.timestamp;
                 this.name;
                 this.sender;
                 this.sendingMethod;
                 this.historyList;
                 this.security;
                 this.status;
                 this.msgType;
                 this.method;
                 this.data;
                 }*/

                /*function Message(name, method, params) {
                 this.msgID = new Date().getTime();
                 this.timeStamp = this.msgID;
                 this.name = name;
                 this.sender = webguiName; // FIXME - named passed in
                 this.sendingMethod = method;
                 this.historyList = new Array(); // necessary?
                 this.method = method;
                 this.data = params;
                 }*/

                this.services = [];

                function Serv(name, servic) {
                    this.name = name;
                    this.servic = servic;
                    this.listener = [];
                }

                this.getServiceInst = function (name) {
                    if (HelperService.isUndefinedOrNull(this.services[name])) {
                        return null;
                    }
                    return this.services[name].servic;
                };

                this.addService = function (name, servic) {
                    this.services[name] = new Serv(name, servic);
                };

                this.removeService = function (name, servic) {
                    //TODO - fill in
                };

                this.addListener = function (name, listener, listener2) {
                    //TODO: right name?
                    //TODO - need to work on this
                    this.services[name].listener.push(listener);
                };

                this.removeListener = function () {
                    //TODO: right name?
                    //TODO - fill in
                };

                this.notify = function () {
                    //TODO: what did I want to do with this function?
                    //TODO - fill in
                };

                this.test = function (name) {
                    //TODO: remove
                    executeFunctionByName("pulse", this.services[name].servic.methods);
//                    this.services["clock"].servic["tester"].apply(this);
                };

//                TODO - delete
//                this.observers = [];
//
//                this.registerObserver = function (observer) {
//                    this.observers.push(observer);
//                };
//
//                this.notifyAll = function () {
//                    for (var index = 0; index < this.observers.length; ++index)
//                        this.observers[index].notify();
//                };
//
//                this.myData = ["some", "list", "of", "data"];
//
//                this.setData = function (newData) {
//                    myData = newData;
//                    notifyAll();
//                };
//
//                this.getData = function () {
//                    return myData;
//                };

                function executeFunctionByName(functionName, context /*, args */) {
                    var args = [].slice.call(arguments).splice(2);
                    var namespaces = functionName.split(".");
                    var func = namespaces.pop();
                    for (var i = 0; i < namespaces.length; i++) {
                        context = context[namespaces[i]];
                    }
                    return context[func].apply(this, args);
                }
            }])

        .service('HelperService', [function () {
                this.isUndefinedOrNull = function (val) {
                    return angular.isUndefined(val) || val === null;
                };
            }])

        .directive('serviceComponent', ['$document', function ($document) {
                return {
                    scope: {
                        //"=" -> binding to items in parent-scope specified by attribute
                        //"@" -> using passed attribute
                        index: '@index',
                        list: '=list',
                        reftomain: '=reftomain',
                        size: '=size'
                    },
                    templateUrl: 'views/service.html',
                    link: function (scope, element, attr) {
                        var startX = 0, startY = 0, x = 0, y = 0;
                        var offsetY = 200;
                        var headerY = 50;
                        var footerY = 50;

                        var outgenerallist = false;
                        var ingenerallist = false;

                        element.css({
                            position: 'relative'
                        });

                        element.on('mousedown', function (event) {
                            outgenerallist = event.pageY < 250;
                            startX = event.pageX - x;
                            startY = event.pageY - y;
                            var height = element.height();
                            if (startY < offsetY + headerY ||
                                    startY > offsetY + height - footerY) {
                                // Prevent default dragging of selected content
                                event.preventDefault();

                                //put panel in foreground
                                //TODO: worky, but sometimes buggy
                                var zindex = scope.list[scope.index].zindex;
                                console.log('zindex', zindex);
//                                var str1 = '';
//                                angular.forEach(scope.list, function (value, key) {
//                                    str1 = str1 + value.zindex + ", ";
//                                });
//                                console.log('zindex3', str1);
                                angular.forEach(scope.list, function (value, key) {
                                    //console.log("zindex2", key, value.zindex);
                                    if (value.zindex > zindex) {
                                        value.zindex--;
                                    }
                                });
                                scope.list[scope.index].zindex = scope.list.length;
//                                var str2 = '';
//                                angular.forEach(scope.list, function (value, key) {
//                                    str2 = str2 + value.zindex + ", ";
//                                });
//                                console.log('zindex3', str2);

                                element.css({
                                    cursor: 'move',
                                    'z-index': zindex
                                });
                                $document.on('mousemove', mousemove);
                                $document.on('mouseup', mouseup);
                            }
                        });

                        function mousemove(event) {
//                            console.log('mousemove', event.pageX, event.pageY);
                            ingenerallist = event.pageY < 250;
                            y = event.pageY - startY;
                            x = event.pageX - startX;
                            element.css({
                                top: y + 'px',
                                left: x + 'px'
                            });
                        }

                        function mouseup() {
                            $document.off('mousemove', mousemove);
                            $document.off('mouseup', mouseup);
                            element.css({
                                cursor: 'auto'
                            });
                            //move panel to different list (if it was moved there)
                            //TODO: worky, but sometimes buggy
                            if (ingenerallist && !outgenerallist) {
                                scope.reftomain.dragInGenerallist(scope.index, scope.list);
                            } else if (!ingenerallist && outgenerallist) {
                                scope.reftomain.dragOutGenerallist(scope.index);
                            }
                        }
                    }
                };
            }])

        .directive('tabComponent', [function () {
                return {
                    scope: {
                        //"=" -> binding to items in parent-scope specified by attribute
                        //"@" -> using passed attribute
                        index: '@index',
                        workspaces: '=workspaces',
                        reftomain: '=reftomain'
                    },
                    templateUrl: 'views/tab.html'
                };
            }])

        .directive('dropComponent', [function () {
                return {
                    scope: {
                        //"=" -> binding to items in parent-scope specified by attribute
                        //"@" -> using passed attribute
                        list: '=list',
                        size: '@size'
                    },
                    templateUrl: 'views/drop.html'
                };
            }])

        .filter('reverse', function () {
            return function (items) {
                return items.slice().reverse();
            };
        })

        .controller('MainCtrl', ['$scope', 'ServiceControllerService', function ($scope, ServiceControllerService) {

                //START_Status
                $scope.statuslist = [];

                $scope.addStatus = function (status) {
                    $scope.statuslist.push(status);
                };

                $scope.addStatus('And this is my status history!');
                $scope.addStatus('And this is my status history!');
                $scope.addStatus('And this is my status history!');
                $scope.addStatus('I am going to be the new WebUI for MyRobotLab!');
                //END_Status

                $scope.allServices = [];

                $scope.generallist = [];

                //START_Workspaces
                $scope.workspaces = [];
                $scope.workspacesref = [];
                var workspacecounter = 0;

                var setAllInactive = function () {
                    angular.forEach($scope.workspaces, function (workspace) {
                        workspace.active = false;
                    });
                };

                var addNewWorkspace = function () {
                    workspacecounter++;
                    $scope.workspaces.push({
                        name: "Workspace " + workspacecounter,
                        active: true,
                        dropdownisopen: false
                    });
                };

                addNewWorkspace();
                addNewWorkspace();
                setAllInactive();
                $scope.workspaces[0].active = true;

                $scope.addWorkspace = function () {
                    setAllInactive();
                    addNewWorkspace();
                };

                $scope.removeWorkspace = function (index) {
                    console.log('removeworkspace, ', index);
                    if ($scope.workspaces.length > 1) {
                        $scope.workspaces.splice(index, 1);
                        $scope.workspacesref.splice(index, 1);
                    } else {
                        console.log('cant remove, not enough workspaces left');
                    }
                };
                //END_Workspaces

                //TODO: refactor this
                $scope.reftomain = {};

                $scope.reftomain.addRefToWorkspace = function (index, workspace) {
                    $scope.workspacesref[index] = workspace;
                };

                $scope.reftomain.dragInGenerallist = function (index, list) {
                    console.log('tab -> general');
                    $scope.generallist.push(list[index]);
                    list.splice(index, 1);
                };

                $scope.reftomain.dragOutGenerallist = function (index) {
                    console.log('general -> tab');
                    var ind = -1;
                    angular.forEach($scope.workspaces, function (value, key) {
                        if (value.active) {
                            ind = key;
                        }
                    });
                    $scope.workspacesref[ind].addDragToList($scope.generallist[index]);
                    $scope.generallist.splice(index, 1);
                };

                //TODO: not final method & location
                $scope.createService = function (name, type) {
                    //spawn service in first workspace
                    var spawnin = 0;
                    $scope.workspacesref[spawnin].addDragToList({
                        'name': name,
                        'type': type
                    });
                    $scope.allServices.push({
                        'name': name,
                        'type': type,
                        'workspace': spawnin
                    });
                };

                $scope.about = function () {
                    console.log('about');
                };

                var servicecounter = 0;

                $scope.help = function () {
                    console.log('help');
                    var servicetype;
                    if (servicecounter % 2 == 0) {
                        servicetype = 'clock';
                    } else {
                        servicetype = 'arduino';
                    }
                    $scope.createService("ser" + servicecounter, servicetype);
                    servicecounter++;
                };

                $scope.searchOnSelect = function (item, model, label) {
                    console.log('searchOnSelect');
                    //select the workspace containing the selected service
                    setAllInactive();
                    $scope.workspaces[item.workspace].active = true;
                    //TODO: scroll to selected service
                };

                var Connection = {};
                Connection.transport = 'websocket';
                Connection.socket = null;

                Connection.receivedMessage = function (message) {
                    console.log('Received Message: ', message);
                    //TODO - process message (& probably forward it to ServiceControllerService (in most cases))
//                    var packet = message;
//                    switch (packet.type) {
//                            case 'update':
//                                for (var i = 0; i < packet.data.length; i++) {
//                                    Game.updateSnake(packet.data[i].id, packet.data[i].body);
//                                }
//                                break;
//                            case 'join':
//                                for (var j = 0; j < packet.data.length; j++) {
//                                    Game.addSnake(packet.data[j].id, packet.data[j].color);
//                                }
//                                break;
//                            case 'leave':
//                                Game.removeSnake(packet.id);
//                                break;
//                            case 'dead':
//                                Console.log('Info: Your snake is dead, bad luck!');
//                                Game.direction = 'none';
//                                break;
//                            case 'kill':
//                                Console.log('Info: Head shot!');
//                                break;
//                        }
                };

                Connection.sendMessage = function (message) {
                    Connection.socket.push(message);
                    console.log('Sent message: ' + message);
                };

                Connection.connect = function (host) {
                    var request = {url: host,
                        transport: 'websocket',
                        enableProtocol: true,
                        trackMessageLength: true,
                        logLevel: 'debug'};

                    request.onOpen = function (response) {
                        // Socket open ...
                        console.log('Info: ' + Connection.transport + ' connection opened.');
                    };

                    request.onClose = function (response) {
                        console.log('websocket, onclose');
                        if (response.state == "unsubscribe") {
                            console.log('Info: ' + Connection.transport + ' closed.');
                        }
                    };

                    request.onTransportFailure = function (errorMsg, request) {
                        jQuery.atmosphere.info(errorMsg);
                        if (window.EventSource) {
                            request.fallbackTransport = "sse";
                        } else {
                            request.fallbackTransport = 'long-polling';
                        }
                        Connection.transport = request.fallbackTransport;

                        console.log('Error: falling back to ' + Connection.transport + ' ' + errorMsg);
                    };

                    request.onMessage = function (response) {
                        var message = response.responseBody;
                        var packet;
                        try {
                            packet = eval('(' + message + ')'); //jQuery.parseJSON(message);
                        } catch (e) {
                            if (message == 'X') {
                                console.log('heartbeat:', message);
                            } else {
                                console.log('Error Message: ', message);
                            }
                            return;
                        }

                        Connection.receivedMessage(packet);
                    };
                    Connection.socket = $.atmosphere.subscribe(request);
                };

                Connection.connect(document.location.origin.toString() + '/api');
//                Connection.connect(document.location.origin.toString() + '/api');
//                console.log($);
//                Connection.connect('/api');
            }])

        .controller('TabsChildCtrl', ['$scope', 'ServiceControllerService', 'HelperService', function ($scope, ServiceControllerService, HelperService) {

                console.log("scope,workspaces", $scope.workspaces);
                console.log("scope,index", $scope.index);

                if (!HelperService.isUndefinedOrNull($scope.index)) {
                    $scope.workspace = $scope.workspaces[$scope.index];
                }

                //TODO: refactor this
                $scope.reftotab = {};
                $scope.reftotab.addDragToList = function (panel) {
                    angular.forEach($scope.servicelist, function (value, key) {
                        value.zindex++;
                    });
                    panel.zindex = 1;
                    $scope.servicelist.push(panel);
                };

                $scope.reftomain.addRefToWorkspace($scope.index, $scope.reftotab);

                $scope.servicelist = [
//                    {'name': 'sera', 'drag': true, 'zindex': 1, 'type': 'clock'},
//                    {'name': 'serb', 'drag': true, 'zindex': 2, 'type': 'arduino'},
//                    {'name': 'serc', 'drag': true, 'zindex': 3, 'type': 'clock'},
//                    {'name': 'serd', 'drag': true, 'zindex': 4, 'type': 'arduino'},
//                    {'name': 'sere', 'drag': true, 'zindex': 5, 'type': 'clock'},
//                    {'name': 'serf', 'drag': true, 'zindex': 6, 'type': 'arduino'},
//                    {'name': 'serg', 'drag': true, 'zindex': 7, 'type': 'clock'},
//                    {'name': 'serh', 'drag': true, 'zindex': 8, 'type': 'arduino'},
//                    {'name': 'seri', 'drag': true, 'zindex': 9, 'type': 'clock'},
//                    {'name': 'serj', 'drag': true, 'zindex': 10, 'type': 'arduino'},
//                    {'name': 'serk', 'drag': true, 'zindex': 11, 'type': 'clock'},
//                    {'name': 'serl', 'drag': true, 'zindex': 12, 'type': 'arduino'},
//                    {'name': 'serm', 'drag': true, 'zindex': 13, 'type': 'clock'},
//                    {'name': 'sern', 'drag': true, 'zindex': 14, 'type': 'arduino'},
//                    {'name': 'sero', 'drag': true, 'zindex': 15, 'type': 'clock'}
                ];
            }]);
<|endoftext|>


<commit_before>// Config
const port = process.env.PORT || 3000;
const minutes = parseFloat(process.env.TRIGGER_ON_MINUTES || 0.5);
const secretToken = process.env.SECRET_TOKEN || 'secret';
const secretPath = '/' + secretToken;

const Hapi = require('hapi');

const server = new Hapi.Server({ port, host: '0.0.0.0' });

let state = 0;
let timer;

const turnOn = () => {
    console.log('Light turned on');
    state = 1;
};
const turnOff = () => {
    console.log('Light turned off');
    state = 0;
};

function startTimerFor(func) {
    if (timer) {
        clearTimeout(timer);
    } else {
        timer = setTimeout(func, minutes * 60 * 1000)
    }
}

server.route({
    method: 'GET',
    path: secretPath,
    handler: function (request, h) {
        console.log(`[${request.info.referrer || request.info.remoteAddress}] State requested: ${state}`);
        return state;
    }
});

server.route({
    method: 'GET',
    path: secretPath + '/on',
    handler: function (request, h) {
        console.log(`[${request.info.referrer || request.info.remoteAddress}] Turn on requested`);
        turnOn();
        startTimerFor(turnOff);
        return state;
    }
});

async function start() {
    try {
        await server.start();
        console.log('Server started')
    } catch (err) {
        console.log(err);
    }
}

start();<commit_msg>Change to POST and x-forwarded-for<commit_after>// Config
const port = process.env.PORT || 3000;
const minutes = parseFloat(process.env.TRIGGER_ON_MINUTES || 0.5);
const secretToken = process.env.SECRET_TOKEN || 'secret';
const secretPath = '/' + secretToken;

const Hapi = require('hapi');

const server = new Hapi.Server({ port, host: '0.0.0.0' });

let state = 0;
let timer;

const turnOn = () => {
    console.log('Light turned on');
    state = 1;
};
const turnOff = () => {
    console.log('Light turned off');
    state = 0;
};

function startTimerFor(func) {
    if (timer) {
        clearTimeout(timer);
    } else {
        timer = setTimeout(func, minutes * 60 * 1000)
    }
}

server.route({
    method: 'GET',
    path: secretPath,
    handler: function (request, h) {
        console.log(`[${request.info.referrer || request.info.remoteAddress}] State requested: ${state}`);
        return state;
    }
});

server.route({
    method: 'POST',
    path: secretPath + '/on',
    handler: function (request, h) {
        console.log(`[${request.headers['x-forwarded-for'] || request.info.remoteAddress}] Turn on requested`);
        turnOn();
        startTimerFor(turnOff);
        return state;
    }
});

async function start() {
    try {
        await server.start();
        console.log('Server started')
    } catch (err) {
        console.log(err);
    }
}

start();<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var bodyParser = require("body-parser");

// ENV vars SLACK_API_KEY, SLACK_API_SECRET, SLASH_COMMAND_TOKEN, TEAM_SLASH_COMMAND_TOKEN

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.set('port', (process.env.PORT || 5000));

app.get('/', function(req, res) {

	// TODO: use handlebars here

	res.send('
Hello Slack!\n

');
});

app.listen(app.get('port'), function() {
	console.log('Node app is running on port', app.get('port'));
});

app.post('/slack/rickroll', function(req, res) {
	var urls,
		index,
		response;

	console.log('Received Rick Roll request');
	console.log(req.body);

	// Urls courtesy of http://brojsimpson.com/pranks/hidden-rick-roll-video-link-collection-rickrolled/
	urls = [
		{
			description: 'THE ORIGINAL RICKROLL’D VIDEO (Not Hidden)',
			url: 'http://www.youtube.com/watch?v=oHg5SJYRHA0'
		},
		{
			description: 'News Alert – Breaking News',
			url: 'https://www.youtube.com/watch?v=xfr64zoBTAQ'
		},
		{
			description: 'Coldplay – True Love [new album Ghost Stories song]',
			url: 'http://youtu.be/hVzINKRbekY'
		},
		{
			description: 'Lala Showers – Tiki Bar TV',
			url: 'http://www.youtube.com/watch?v=r8tXjJL3xcM'
		},
		// Rick Roll "worship" link
		{
			description: 'OMG check it out.',
			url: 'http://rick.amigocraft.net'
		}
	];

	index = Math.floor(Math.random() * urls.length);

	response = {
		"response_type": "in_channel",
		"text": urls[index].description + ' ' + urls[index].url
	};

	res.send(response);
});<commit_msg>posting as user<commit_after>var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var http = require('http');

// ENV vars SLACK_API_KEY, SLACK_API_SECRET, SLASH_COMMAND_TOKEN, TEAM_SLASH_COMMAND_TOKEN

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.set('port', (process.env.PORT || 5000));

app.get('/', function(req, res) {

	// TODO: use handlebars here

	res.send('
Hello Slack!\n

');
});

app.listen(app.get('port'), function() {
	console.log('Node app is running on port', app.get('port'));
});

app.post('/slack/rickroll', function(req, res) {
	var urls,
		index,
		responseStatus = {error: 'unknown'};

	console.log('Received Rick Roll request');
	console.log(req.body);

	// check the token
		// if not present and accurate return status

	// Urls courtesy of http://brojsimpson.com/pranks/hidden-rick-roll-video-link-collection-rickrolled/
	urls = [
		{
			description: 'THE ORIGINAL RICKROLL’D VIDEO (Not Hidden)',
			url: 'http://www.youtube.com/watch?v=oHg5SJYRHA0'
		},
		{
			description: 'News Alert – Breaking News',
			url: 'https://www.youtube.com/watch?v=xfr64zoBTAQ'
		},
		{
			description: 'Coldplay – True Love [new album Ghost Stories song]',
			url: 'http://youtu.be/hVzINKRbekY'
		},
		{
			description: 'Lala Showers – Tiki Bar TV',
			url: 'http://www.youtube.com/watch?v=r8tXjJL3xcM'
		},
		// Rick Roll "worship" link
		{
			description: 'OMG check it out.',
			url: 'http://rick.amigocraft.net'
		}
	];

	index = Math.floor(Math.random() * urls.length);

	//response = {
	//	response_type: 'in_channel',
	//	text: urls[index].description + ' ' + urls[index].url,
	//	as_user: req.body.user_name,
	//	channel: req.body.channel
	//};

	var httpGetOptions = {
		host: 'https://slack.com/',
		port: 80,
		path: 'api/chat.postMessage',
		token: req.body.token,
		channel: req.body.channel,
		text: urls[index].description + ' ' + urls[index].url,
		as_user: true
	};

	http.get(httpGetOptions, function (slackResponse) {
		slackResponse.on('data', function(chunk){
			console.log(chunk);
		});
	}).on('error', function(e){
		console.log('Got error: ' + e.message);
	});

	// todo: make this the real status
	responseStatus = {success: 'okay'};

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


<commit_before> /**
 * Represents the application api.  If the variable is already defined use it,
 * otherwise create an empty object.
 *
 * @type {EScreeningDashboardApp|*|EScreeningDashboardApp|*|{}|{}}
 */
var EScreeningDashboardApp = EScreeningDashboardApp || {};
/**
 * Represents the application static variable. Use existing static variable, if one already exists,
 * otherwise create a new one.
 *visible
 * @static
 * @type {*|EScreeningDashboardApp.models|*|EScreeningDashboardApp.models|Object|*|Object|*}
 */
EScreeningDashboardApp.models = EScreeningDashboardApp.models || EScreeningDashboardApp.namespace("gov.va.escreening.models");
/**
 * Constructor method for the Answer class.  The properties of this class can be initialized with
 * the jsonUserObject.
 * @class
 * @classdesc   This class is a domain model class; which means it has both behaviour and state
 *              information about the user.
 * @param {String}  jsonAnswerObject  Represents the JSON representation of a Answer object.
 * @constructor
 * @author Bryan Henderson
 */
EScreeningDashboardApp.models.Answer = function (jsonAnswerObject) {
    var that = this,
        id = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.id))? jsonAnswerObject.id : -1,
        exportName = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.exportName)) ? jsonAnswerObject.exportName : null,
        text = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.text))? jsonAnswerObject.text : null,
        type = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.type))? jsonAnswerObject.type : null;

    this.getId = function(){
        return id;
    };

    this.getExportName = function(){
    	return exportName;
    };

    this.getText = function() {
        return text;
    };

    this.getType = function() {
        return type;
    };

    this.toString = function() {
        return "Answer{id: " + id + ", exportName: " + exportName + ", text: " + text + ", type: " + type + "}";
    };

    this.toJSON = function () {
        return angular.toJson(this.toUIObject());
    };

    this.toUIObject = function(){
    	return {
    		answerId : (Object.isDefined(id) && id > 0)? id : null,
    		answerText : text,
    		answerType : type,
    		'exportName' : exportName,
    	};
    };
};<commit_msg>#714 fixed Answer domain object to use AnswerInfo.java fields<commit_after> /**
 * Represents the application api.  If the variable is already defined use it,
 * otherwise create an empty object.
 *
 * @type {EScreeningDashboardApp|*|EScreeningDashboardApp|*|{}|{}}
 */
var EScreeningDashboardApp = EScreeningDashboardApp || {};
/**
 * Represents the application static variable. Use existing static variable, if one already exists,
 * otherwise create a new one.
 *visible
 * @static
 * @type {*|EScreeningDashboardApp.models|*|EScreeningDashboardApp.models|Object|*|Object|*}
 */
EScreeningDashboardApp.models = EScreeningDashboardApp.models || EScreeningDashboardApp.namespace("gov.va.escreening.models");
/**
 * Constructor method for the Answer class.  The properties of this class can be initialized with
 * the jsonUserObject.
 * @class
 * @classdesc   This class is a domain model class; which means it has both behaviour and state
 *              information about the user.
 * @param {String}  jsonAnswerObject  Represents the JSON representation of a Answer object.
 * @constructor
 * @author Bryan Henderson
 */
EScreeningDashboardApp.models.Answer = function (jsonAnswerObject) {
    var that = this,
        id = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.id))? jsonAnswerObject.id : -1,
        exportName = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.exportName)) ? jsonAnswerObject.exportName : null,
        text = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.text))? jsonAnswerObject.text : null,
        type = (Object.isDefined(jsonAnswerObject) && Object.isDefined(jsonAnswerObject.type))? jsonAnswerObject.type : null;

    this.getId = function(){
        return id;
    };

    this.getExportName = function(){
    	return exportName;
    };

    this.getText = function() {
        return text;
    };

    this.getType = function() {
        return type;
    };

    this.toString = function() {
        return "Answer{id: " + id + ", exportName: " + exportName + ", text: " + text + ", type: " + type + "}";
    };

    this.toJSON = function () {
        return angular.toJson(this.toUIObject());
    };

    this.toUIObject = function(){
    	return {
    		'id' : (Object.isDefined(id) && id > 0)? id : null,
    		'text' : text,
    		'type' : type,
    		'exportName' : exportName
    	};
    };
};<|endoftext|>


<commit_before>import nock from 'nock';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { actionTypes } from './constants';
import * as actions from './actions';
import { API_HOST } from '../api';
import reducer from './reducer';
import * as selectors from './selectors';
// import * as state from './api';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

describe('affordability actions', () => {
  describe('affordability fetch actions', () => {
    it('should have a start action', () => {
      const expectedAction = {
        type: actionTypes.CALL_START,
      };

      expect(actions.affordabilityStart()).to.eql(expectedAction);
    });

    it('should have a success action', () => {
      const payload = {
        data: {
          neighborhoods: [1, 2, 3],
        },
      };
      const expectedAction = {
        type: actionTypes.CALL_SUCCESS,
        payload,
      };

      expect(actions.affordabilitySuccess(payload)).to.eql(expectedAction);
    });

    it('should have a fail action', () => {
      const payload = new Error('Hmm. This should not have happened');
      const expectedAction = {
        type: actionTypes.CALL_FAIL,
        payload,
      };

      expect(actions.affordabilityFail(payload)).to.eql(expectedAction);
    });
  });

  describe('affordability fetch thunk', () => {
    const commonAffordabilityRequest = '/affordable?format=json&demographic=Avg.%20Portland%20Household&housing_size=Homeownership';
    let store;

    beforeEach(() => {
      store = mockStore({});
    });

    afterEach(() => { nock.cleanAll(); });

    it('should dispatch fetch and success when the fetch is successful', () => {
      const mockAffordabilityResponse = [
        {
          affordable: true,
          demographic: 'Senior',
          housing_size: '1-BR',
          neighborhood: 'Centennial-Glenfair-Wilkes',
          NP_ID: 10,
        },
      ];

      nock(API_HOST)
        .get(commonAffordabilityRequest)
        .reply(200, mockAffordabilityResponse);

      const expectedActions = [
        { type: actionTypes.CALL_START },
        {
          type: actionTypes.CALL_SUCCESS,
          payload: [{
            affordable: true,
            id: 10,
          }],
        },
      ];

      return store.dispatch(actions.fetchAffordabilityData()).then(() => {
        expect(store.getActions()).to.eql(expectedActions);
      });
    });

    it('should dispatch fetch and fail when the fetch is unsuccessful', () => {
      nock(API_HOST)
        .get(commonAffordabilityRequest)
        .reply(500, { error: 'Request was just no good' });

      const expectedActions = [
        { type: actionTypes.CALL_START },
        {
          type: actionTypes.CALL_FAIL,
          payload: new Error({ error: 'Request was just no good' }),
        },
      ];

      return store.dispatch(actions.fetchAffordabilityData()).then(() => {
        expect(store.getActions()).to.eql(expectedActions);
      });
    });
  });
});

describe('affordability reducer', () => {
  const initialState = {
    pending: false,
    data: null,
    error: null,
  };

  it('should return the initial state', () => {
    expect(reducer(undefined, {})).to.eql(initialState);
  });

  it('should handle CALL_START', () => {
    expect(reducer(initialState, {
      type: actionTypes.CALL_START,
    })).to.eql({
      pending: true,
      data: null,
      error: null,
    });

    expect(reducer({
      pending: true,
      data: null,
      error: null,
    }, {
      type: actionTypes.CALL_START,
    })).to.eql({
      pending: true,
      data: null,
      error: null,
    });
  });

  it('should handle CALL_FAIL', () => {
    const error = new Error('oops');

    expect(reducer(initialState, {
      type: actionTypes.CALL_FAIL,
      payload: error,
    })).to.eql({
      pending: false,
      data: null,
      error,
    });

    expect(reducer({
      pending: true,
      data: ['stuff'],
      error: null,
    }, {
      type: actionTypes.CALL_FAIL,
      payload: error,
    })).to.eql({
      pending: false,
      data: null,
      error,
    });
  });

  it('should handle CALL_SUCCESS', () => {
    const data = [
      [':D', 'Senior', 37469, 'Centennial-Glenfair-Wilkes', 2016],
      [':(', 'Senior', 37469, 'Sellwood-Moreland-Brooklyn', 2016],
    ];

    expect(reducer(initialState, {
      type: actionTypes.CALL_SUCCESS,
      payload: data,
    })).to.eql({
      pending: false,
      error: null,
      data,
    });

    expect(reducer({
      pending: true,
      error: new Error('oops'),
      data: null,
    }, {
      type: actionTypes.CALL_SUCCESS,
      payload: data,
    })).to.eql({
      pending: false,
      error: null,
      data,
    });
  });
});

describe('affordability selectors', () => {
  let state;
  const affordability = {};

  beforeEach(() => {
    state = { affordability };
  });

  describe('getAffordabilityState', () => {
    it('handles no state without errors', () => {
      selectors.getAffordabilityState().should.eql({});
    });
  });

  describe('getAffordabilityRequest', () => {
    it('should return an empty object when unset', () => {
      state = {};
      expect(selectors.getAffordabilityRequest(state)).to.eql({});
    });

    it('should return the affordability request object when set', () => {
      state = { affordability: {
        pending: true,
        data: null,
        error: null,
      } };
      expect(selectors.getAffordabilityRequest(state)).to.eql(state.affordability);
    });
  });

  describe('getAffordabilityData', () => {
    it('should return undefined when unset', () => {
      state = {};
      expect(selectors.getAffordabilityData(state)).to.be.undefined;
    });

    it('should return affordability data when set', () => {
      const data = 'you found it!';
      state = { affordability: { data } };
      expect(selectors.getAffordabilityData(state)).to.eql(data);
    });
  });
});
<commit_msg>Remove comment<commit_after>import nock from 'nock';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { actionTypes } from './constants';
import * as actions from './actions';
import { API_HOST } from '../api';
import reducer from './reducer';
import * as selectors from './selectors';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

describe('affordability actions', () => {
  describe('affordability fetch actions', () => {
    it('should have a start action', () => {
      const expectedAction = {
        type: actionTypes.CALL_START,
      };

      expect(actions.affordabilityStart()).to.eql(expectedAction);
    });

    it('should have a success action', () => {
      const payload = {
        data: {
          neighborhoods: [1, 2, 3],
        },
      };
      const expectedAction = {
        type: actionTypes.CALL_SUCCESS,
        payload,
      };

      expect(actions.affordabilitySuccess(payload)).to.eql(expectedAction);
    });

    it('should have a fail action', () => {
      const payload = new Error('Hmm. This should not have happened');
      const expectedAction = {
        type: actionTypes.CALL_FAIL,
        payload,
      };

      expect(actions.affordabilityFail(payload)).to.eql(expectedAction);
    });
  });

  describe('affordability fetch thunk', () => {
    const commonAffordabilityRequest = '/affordable?format=json&demographic=Avg.%20Portland%20Household&housing_size=Homeownership';
    let store;

    beforeEach(() => {
      store = mockStore({});
    });

    afterEach(() => { nock.cleanAll(); });

    it('should dispatch fetch and success when the fetch is successful', () => {
      const mockAffordabilityResponse = [
        {
          affordable: true,
          demographic: 'Senior',
          housing_size: '1-BR',
          neighborhood: 'Centennial-Glenfair-Wilkes',
          NP_ID: 10,
        },
      ];

      nock(API_HOST)
        .get(commonAffordabilityRequest)
        .reply(200, mockAffordabilityResponse);

      const expectedActions = [
        { type: actionTypes.CALL_START },
        {
          type: actionTypes.CALL_SUCCESS,
          payload: [{
            affordable: true,
            id: 10,
          }],
        },
      ];

      return store.dispatch(actions.fetchAffordabilityData()).then(() => {
        expect(store.getActions()).to.eql(expectedActions);
      });
    });

    it('should dispatch fetch and fail when the fetch is unsuccessful', () => {
      nock(API_HOST)
        .get(commonAffordabilityRequest)
        .reply(500, { error: 'Request was just no good' });

      const expectedActions = [
        { type: actionTypes.CALL_START },
        {
          type: actionTypes.CALL_FAIL,
          payload: new Error({ error: 'Request was just no good' }),
        },
      ];

      return store.dispatch(actions.fetchAffordabilityData()).then(() => {
        expect(store.getActions()).to.eql(expectedActions);
      });
    });
  });
});

describe('affordability reducer', () => {
  const initialState = {
    pending: false,
    data: null,
    error: null,
  };

  it('should return the initial state', () => {
    expect(reducer(undefined, {})).to.eql(initialState);
  });

  it('should handle CALL_START', () => {
    expect(reducer(initialState, {
      type: actionTypes.CALL_START,
    })).to.eql({
      pending: true,
      data: null,
      error: null,
    });

    expect(reducer({
      pending: true,
      data: null,
      error: null,
    }, {
      type: actionTypes.CALL_START,
    })).to.eql({
      pending: true,
      data: null,
      error: null,
    });
  });

  it('should handle CALL_FAIL', () => {
    const error = new Error('oops');

    expect(reducer(initialState, {
      type: actionTypes.CALL_FAIL,
      payload: error,
    })).to.eql({
      pending: false,
      data: null,
      error,
    });

    expect(reducer({
      pending: true,
      data: ['stuff'],
      error: null,
    }, {
      type: actionTypes.CALL_FAIL,
      payload: error,
    })).to.eql({
      pending: false,
      data: null,
      error,
    });
  });

  it('should handle CALL_SUCCESS', () => {
    const data = [
      [':D', 'Senior', 37469, 'Centennial-Glenfair-Wilkes', 2016],
      [':(', 'Senior', 37469, 'Sellwood-Moreland-Brooklyn', 2016],
    ];

    expect(reducer(initialState, {
      type: actionTypes.CALL_SUCCESS,
      payload: data,
    })).to.eql({
      pending: false,
      error: null,
      data,
    });

    expect(reducer({
      pending: true,
      error: new Error('oops'),
      data: null,
    }, {
      type: actionTypes.CALL_SUCCESS,
      payload: data,
    })).to.eql({
      pending: false,
      error: null,
      data,
    });
  });
});

describe('affordability selectors', () => {
  let state;
  const affordability = {};

  beforeEach(() => {
    state = { affordability };
  });

  describe('getAffordabilityState', () => {
    it('handles no state without errors', () => {
      selectors.getAffordabilityState().should.eql({});
    });
  });

  describe('getAffordabilityRequest', () => {
    it('should return an empty object when unset', () => {
      state = {};
      expect(selectors.getAffordabilityRequest(state)).to.eql({});
    });

    it('should return the affordability request object when set', () => {
      state = { affordability: {
        pending: true,
        data: null,
        error: null,
      } };
      expect(selectors.getAffordabilityRequest(state)).to.eql(state.affordability);
    });
  });

  describe('getAffordabilityData', () => {
    it('should return undefined when unset', () => {
      state = {};
      expect(selectors.getAffordabilityData(state)).to.be.undefined;
    });

    it('should return affordability data when set', () => {
      const data = 'you found it!';
      state = { affordability: { data } };
      expect(selectors.getAffordabilityData(state)).to.eql(data);
    });
  });
});
<|endoftext|>


<commit_before>//Loads images and then initializes Datatables
$(window).load(function() {
	var tableTitle = $('.tableImage');
	var imageTitle = $('.tableTitle a');
	var i = 0;

	for (i; i < tableTitle.length; i++) {
		var imageLink = imageTitle[i].innerText.toLowerCase();
		$('.tableImage')[i].innerHTML = "";
	}
});<commit_msg>enter<commit_after>//Loads images and then initializes Datatables
$(window).load(function() {
	var tableTitle = $('.tableImage');
	var imageTitle = $('.tableTitle a');
	var i = 0;

	for (i; i < tableTitle.length; i++) {
		var imageLink = imageTitle[i].innerText.toLowerCase();

		$('.tableImage')[i].innerHTML = "";
	}
});<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const JSDOM = require('jsdom').JSDOM;
const showdown = require('showdown'); // This is our fork of showdown, which will auto-link to HTTPS as oppose to HTTP. Currently not in used, replaced with 'markdown-it'.
const domspace = require('domspace');
const path = require('path');
const hljs = require('highlight.js'); // https://highlightjs.org/
const iterator = require('markdown-it-for-inline');

// full options list (defaults)
var md = require('markdown-it')({
  html: true,        // Enable HTML tags in source
  xhtmlOut: false,        // Use '/' to close single tags (
).
  // This is only for full CommonMark compatibility.
  breaks: false,        // Convert '\n' in paragraphs into

  langPrefix: 'language-',  // CSS language prefix for fenced blocks. Can be
  // useful for external highlighters.
  linkify: true,        // Autoconvert URL-like text to links

  // Enable some language-neutral replacement + quotes beautification
  // For the full list of replacements, see https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js
  typographer: true,

  // Double + single quotes replacement pairs, when typographer enabled,
  // and smartquotes on. Could be either a String or an Array.
  //
  // For example, you can use '«»„“' for Russian, '„“‚‘' for German,
  // and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
  quotes: '“”‘’',

  // Highlighter function. Should return escaped HTML,
  // or '' if the source string is not changed and should be escaped externally.
  // If result starts with <pre... internal wrapper is skipped.
  // highlight: function (/*str, lang*/) { return ''; }
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return '
' +
          hljs.highlight(lang, str, true).value +
          '
';
      } catch (__) { }
    }

    return '
' + md.utils.escapeHtml(str) + '
';
  }
});

var r = new RegExp('^(?:[a-z]+:)?//', 'i');

md.use(iterator, 'url_new_win', 'link_open', function (tokens, idx) {

  let url = tokens[idx].attrs[0][1];

  // If the URL is relative, replace the ".md" ending with ".html".
  if (!r.test(url) && url.endsWith(".md")) {
    tokens[idx].attrs[0][1] = url.replace('.md', '.html');
  }

  //console.log(!r.test(url) + ": " + url);

  //console.log(tokens[idx].attrs);
  //console.log(tokens);
  //console.log(idx);
  //tokens[idx].attrPush([ 'target', '_blank' ]);
});

function isRelative(url) {
  return (/^(\.){1,2}(\/){1,2}$/.test(url.slice(0, 3)) ||
    /(\/){1,2}(\.){1,2}(\/){1,2}/.test(url));
}

function process(dir, template, converter, containerId) {
  const files = fs.readdirSync(dir);

  // Load the template into a DOM. We currently do this for each iteration, to start off with a "fresh" DOM.
  const htmlDoc = new JSDOM(template);

  files.forEach(function (file) {

    var currentPath = path.join(dir, file);

    if (fs.statSync(currentPath).isDirectory()) {

      // Modify the path
      const distPath = currentPath.replace('pages', 'dist');

      fs.mkdirSync(distPath);

      process(currentPath, template, converter, containerId);
    }
    else {
      const extension = path.extname(currentPath);

      if (extension == '.md') {
        const markdown = fs.readFileSync(currentPath, 'utf-8');
        // const content = converter.makeHtml(markdown);
        const content = md.render(markdown);

        htmlDoc.window.document.getElementById(containerId).innerHTML = content;

        // Render the document title if there is any H1 tags available.
        var h1s = htmlDoc.window.document.getElementsByTagName("H1");

        if (h1s.length > 0) {
          htmlDoc.window.document.title = h1s[0].innerHTML + ' - ' + htmlDoc.window.document.title;
        }

        domspace(htmlDoc.window.document);

        let distPath = currentPath.replace('pages', 'dist');
        distPath = distPath.replace('.md', '.html');

        // htmlDoc.window.document.innerHTML

        fs.writeFileSync(distPath, htmlDoc.window.document.documentElement.outerHTML, 'utf-8');
      }
      else {
        const distPath = currentPath.replace('pages', 'dist');
        fs.copyFileSync(currentPath, distPath);
      }
    }
  });
}

function run(containerId) {
  console.log('Basilar processing...');

  // Removing the "dist" folder.
  fs.rmdirSync('dist', { recursive: true });

  // Create the dist folder.
  fs.mkdirSync('dist');

  // Copy the assets. // TODO: Make this a configuration setting ("basilar.json").
  fs.copyFileSync('www/style.css', 'dist/style.css');
  fs.copyFileSync('www/web.js', 'dist/web.js');
  fs.copyFileSync('www/favicon.png', 'dist/favicon.png');

  // First get the HTML template
  const template = fs.readFileSync('www/index.html', 'utf-8');

  // Create the MD to HTML converter instance.
  // const converter = new showdown.Converter({ simplifiedAutoLink: true, tables: true, strikethrough: true });

  // Loop through all the content.
  process('pages', template, md, containerId);

  console.log('Processing completed. Output available in "dist" folder.');
}

run('content', true);
<commit_msg>Copy CNAME when building<commit_after>'use strict';

const fs = require('fs');
const JSDOM = require('jsdom').JSDOM;
const showdown = require('showdown'); // This is our fork of showdown, which will auto-link to HTTPS as oppose to HTTP. Currently not in used, replaced with 'markdown-it'.
const domspace = require('domspace');
const path = require('path');
const hljs = require('highlight.js'); // https://highlightjs.org/
const iterator = require('markdown-it-for-inline');

// full options list (defaults)
var md = require('markdown-it')({
  html: true,        // Enable HTML tags in source
  xhtmlOut: false,        // Use '/' to close single tags (
).
  // This is only for full CommonMark compatibility.
  breaks: false,        // Convert '\n' in paragraphs into

  langPrefix: 'language-',  // CSS language prefix for fenced blocks. Can be
  // useful for external highlighters.
  linkify: true,        // Autoconvert URL-like text to links

  // Enable some language-neutral replacement + quotes beautification
  // For the full list of replacements, see https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js
  typographer: true,

  // Double + single quotes replacement pairs, when typographer enabled,
  // and smartquotes on. Could be either a String or an Array.
  //
  // For example, you can use '«»„“' for Russian, '„“‚‘' for German,
  // and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
  quotes: '“”‘’',

  // Highlighter function. Should return escaped HTML,
  // or '' if the source string is not changed and should be escaped externally.
  // If result starts with <pre... internal wrapper is skipped.
  // highlight: function (/*str, lang*/) { return ''; }
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return '
' +
          hljs.highlight(lang, str, true).value +
          '
';
      } catch (__) { }
    }

    return '
' + md.utils.escapeHtml(str) + '
';
  }
});

var r = new RegExp('^(?:[a-z]+:)?//', 'i');

md.use(iterator, 'url_new_win', 'link_open', function (tokens, idx) {

  let url = tokens[idx].attrs[0][1];

  // If the URL is relative, replace the ".md" ending with ".html".
  if (!r.test(url) && url.endsWith(".md")) {
    tokens[idx].attrs[0][1] = url.replace('.md', '.html');
  }

  //console.log(!r.test(url) + ": " + url);

  //console.log(tokens[idx].attrs);
  //console.log(tokens);
  //console.log(idx);
  //tokens[idx].attrPush([ 'target', '_blank' ]);
});

function isRelative(url) {
  return (/^(\.){1,2}(\/){1,2}$/.test(url.slice(0, 3)) ||
    /(\/){1,2}(\.){1,2}(\/){1,2}/.test(url));
}

function process(dir, template, converter, containerId) {
  const files = fs.readdirSync(dir);

  // Load the template into a DOM. We currently do this for each iteration, to start off with a "fresh" DOM.
  const htmlDoc = new JSDOM(template);

  files.forEach(function (file) {

    var currentPath = path.join(dir, file);

    if (fs.statSync(currentPath).isDirectory()) {

      // Modify the path
      const distPath = currentPath.replace('pages', 'dist');

      fs.mkdirSync(distPath);

      process(currentPath, template, converter, containerId);
    }
    else {
      const extension = path.extname(currentPath);

      if (extension == '.md') {
        const markdown = fs.readFileSync(currentPath, 'utf-8');
        // const content = converter.makeHtml(markdown);
        const content = md.render(markdown);

        htmlDoc.window.document.getElementById(containerId).innerHTML = content;

        // Render the document title if there is any H1 tags available.
        var h1s = htmlDoc.window.document.getElementsByTagName("H1");

        if (h1s.length > 0) {
          htmlDoc.window.document.title = h1s[0].innerHTML + ' - ' + htmlDoc.window.document.title;
        }

        domspace(htmlDoc.window.document);

        let distPath = currentPath.replace('pages', 'dist');
        distPath = distPath.replace('.md', '.html');

        // htmlDoc.window.document.innerHTML

        fs.writeFileSync(distPath, htmlDoc.window.document.documentElement.outerHTML, 'utf-8');
      }
      else {
        const distPath = currentPath.replace('pages', 'dist');
        fs.copyFileSync(currentPath, distPath);
      }
    }
  });
}

function run(containerId) {
  console.log('Basilar processing...');

  // Removing the "dist" folder.
  fs.rmdirSync('dist', { recursive: true });

  // Create the dist folder.
  fs.mkdirSync('dist');

  // Copy the assets. // TODO: Make this a configuration setting ("basilar.json").
  fs.copyFileSync('www/style.css', 'dist/style.css');
  fs.copyFileSync('www/web.js', 'dist/web.js');
  fs.copyFileSync('www/favicon.png', 'dist/favicon.png');
  fs.copyFileSync('CNAME', 'dist/CNAME');

  // First get the HTML template
  const template = fs.readFileSync('www/index.html', 'utf-8');

  // Create the MD to HTML converter instance.
  // const converter = new showdown.Converter({ simplifiedAutoLink: true, tables: true, strikethrough: true });

  // Loop through all the content.
  process('pages', template, md, containerId);

  console.log('Processing completed. Output available in "dist" folder.');
}

run('content', true);
<|endoftext|>


<commit_before>import { isString, isFunction, isRegExp, isPlainObject } from 'lodash';

export default class RocExportPlugin {
    constructor(resolveRequest) {
        this.resolveRequest = resolveRequest;
    }

    apply(compiler) {
        const getAlias = createGetAlias(compiler.options.resolve.alias); // eslint-disable-line

        // We assume that loaders will be managed in Webpack-land, that is we will not manage them in exports
        compiler.plugin('normal-module-factory', (normalModuleFactory) => {
            normalModuleFactory.plugin('before-resolve', (result, callback) => {
                // We do not want to process:
                // 1. No result
                // 2. Webpack special paths
                // 3. Externals
                if (
                    !result ||
                    result.request.match(/(\?|!)/) ||
                    findExternal(result.request, compiler.options.externals, result.context)  // eslint-disable-line
                ) {
                    return callback(null, result);
                }

                // Use resolve.alias to use the alias if one exists and match
                result.request = getAlias(result.request); // eslint-disable-line

                // Try to resolve the dependency against the roc dependency context
                result.request = this.resolveRequest(result.request, result.context); // eslint-disable-line

                // Test to see if we can resolve the dependency
                return compiler.resolvers.normal.resolve(result.context, result.request, (err) => {
                    if (err) {
                        // We got an error and will try again with fallback enabled
                        result.request = this.resolveRequest(result.request, result.context, true); // eslint-disable-line
                    }

                    return callback(null, result);
                });
            });
        });
    }
}

function findExternal(request, externals, context) {
    if (!externals) {
        return false;
    }

    if (isString(externals)) {
        return request === externals;
    }

    if (Array.isArray(externals)) {
        return externals.some((external) => findExternal(request, external, context));
    }

    if (isRegExp(externals)) {
        return externals.test(request);
    }

    if (isFunction(externals)) {
        let functionExternalFound = false;
        externals(context, request, (error, result) => {
            if (error) {
                functionExternalFound = false;
            } else {
                functionExternalFound = findExternal(request, result, context);
            }
        });
        return functionExternalFound;
    }

    // Otherwise it is a Object
    return Object.keys(externals).some((key) => request === key);
}

// Based on code from enhanced-resolve
function createGetAlias(aliases) {
    if (isPlainObject(aliases) && !Array.isArray(aliases)) {
        aliases = Object.keys(aliases).map((key) => { // eslint-disable-line
            let onlyModule = false;
            let obj = aliases[key];
            if (/\$$/.test(key)) {
                onlyModule = true;
                key = key.substr(0, key.length - 1); // eslint-disable-line
            }
            if (isString(obj)) {
                obj = {
                    alias: obj,
                };
            }
            return {
                name: key,
                onlyModule,
                ...obj,
            };
        });
    }

    return (request) => {
        for (const alias of aliases) {
            if ((!alias.onlyModule && request.indexOf(`${alias.name}/`) === 0) || request === alias.name) {
                if (request.indexOf(`${alias.alias}/`) !== 0 && request !== alias.alias) {
                    return alias.alias + request.substr(alias.name.length);
                }
            }
        }
        return request;
    };
}
<commit_msg>Improved the resolving by managing loaders and queries better<commit_after>import { isString, isFunction, isRegExp, isPlainObject } from 'lodash';

export default class RocExportPlugin {
    constructor(resolveRequest) {
        this.resolveRequest = resolveRequest;
    }

    apply(compiler) {
        const getAlias = createGetAlias(compiler.options.resolve.alias); // eslint-disable-line
        const isExternal = createIsExternal(compiler.options.externals); // eslint-disable-line

        // We assume that loaders will be managed in Webpack-land, meaning that we will not manage
        // them using exports in Roc
        compiler.plugin('normal-module-factory', (normalModuleFactory) => {
            normalModuleFactory.plugin('before-resolve', (result, callback) => {
                // Do nothing if it is external or falsy
                if (!result || isExternal(result.request, result.context)) {
                    return callback(null, result);
                }

                let request = result.request;

                // Strip loaders
                let loaders = '';
                const finalBang = request.lastIndexOf('!');
                if (finalBang >= 0) {
                    loaders = request.substring(0, finalBang + 1);
                    request = request.substring(finalBang + 1);
                }

                // Strip resource query
                let query = '';
                const finalQuestionMark = request.lastIndexOf('?');
                if (finalQuestionMark >= 0) {
                    query = request.substring(finalQuestionMark);
                    request = request.substring(0, finalQuestionMark);
                }

                // Use resolve.alias to use the alias if one exists and match
                request = getAlias(request);

                // Try to resolve the dependency against the roc dependency context
                request = this.resolveRequest(request, result.context);

                // Test to see if we can resolve the dependency
                return compiler.resolvers.normal.resolve(result.context, request, (err) => {
                    if (err) {
                        // We got an error and will try again with fallback enabled
                        request = this.resolveRequest(request, result.context, true);
                    }

                    // Put the request back together with the possible loaders and the possible query
                    result.request = `${loaders}${request}${query}`; // eslint-disable-line
                    return callback(null, result);
                });
            });
        });
    }
}

function createIsExternal(externals) {
    return (request, context) => {
        if (!externals) {
            return false;
        }

        if (isString(externals)) {
            return request === externals;
        }

        if (Array.isArray(externals)) {
            return externals.some((external) => createIsExternal(external)(request, context));
        }

        if (isRegExp(externals)) {
            return externals.test(request);
        }

        if (isFunction(externals)) {
            let functionExternalFound = false;
            externals(context, request, (error, result) => {
                if (error) {
                    functionExternalFound = false;
                } else {
                    functionExternalFound = createIsExternal(result)(request, context);
                }
            });
            return functionExternalFound;
        }

        // Otherwise it is a Object
        return Object.keys(externals).some((key) => request === key);
    };
}

// Based on code from enhanced-resolve
function createGetAlias(aliases) {
    if (isPlainObject(aliases) && !Array.isArray(aliases)) {
        aliases = Object.keys(aliases).map((key) => { // eslint-disable-line
            let onlyModule = false;
            let obj = aliases[key];
            if (/\$$/.test(key)) {
                onlyModule = true;
                key = key.substr(0, key.length - 1); // eslint-disable-line
            }
            if (isString(obj)) {
                obj = {
                    alias: obj,
                };
            }
            return {
                name: key,
                onlyModule,
                ...obj,
            };
        });
    }

    return (request) => {
        for (const alias of aliases) {
            if ((!alias.onlyModule && request.indexOf(`${alias.name}/`) === 0) || request === alias.name) {
                if (request.indexOf(`${alias.alias}/`) !== 0 && request !== alias.alias) {
                    return alias.alias + request.substr(alias.name.length);
                }
            }
        }
        return request;
    };
}
<|endoftext|>