<commit_before>var mamidApp = angular.module('mamidApp', ['ngRoute', 'ngResource']);

// http://www.codelord.net/2014/06/25/generic-error-handling-in-angularjs/
var specificallyHandleInProgress = false;
var HEADER_NAME = 'MyApp-Handle-Errors-Generically';
mamidApp.factory('RequestsErrorHandler', ['$q', function ($q) {
    return {
        // --- The user's API for claiming responsiblity for requests ---
        specificallyHandled: function (specificallyHandledBlock) {
            specificallyHandleInProgress = true;
            try {
                return specificallyHandledBlock();
            } finally {
                specificallyHandleInProgress = false;
            }
        },

        // --- Response interceptor for handling errors generically ---
        responseError: function (rejection) {
            var shouldHandle = (rejection && rejection.config && rejection.config.headers
            && rejection.config.headers[HEADER_NAME]);
            if (shouldHandle) {
                var root = $('#content')[0];
                var ediv = document.createElement('div');
                ediv.setAttribute('class', 'alert alert-danger alert-dismissible fade in');
                ediv.setAttribute('role', 'alert');
                var button = document.createElement('button');
                button.setAttribute('class', 'close');
                button.setAttribute('data-dismiss', 'alert');
                button.setAttribute('type', 'button');
                button.innerHTML = '×';
                ediv.appendChild(button);
                var h4 = document.createElement('h4');
                h4.innerHTML = 'Houps! An error occurred.';
                ediv.appendChild(h4);
                var p = document.createElement('p');
                p.innerHTML = rejection.data;
                ediv.appendChild(p);
                $(ediv).hide();
                root.insertBefore(ediv, root.firstChild);
                $(ediv).alert();
                $(ediv).fadeTo(5000, 500).slideUp(500, function () {
                    $(ediv).alert('close');
                });
                window.console.error(rejection);
            }

            return $q.reject(rejection);
        }
    };
}]);
mamidApp.config(['$provide', '$httpProvider', function ($provide, $httpProvider) {
    $httpProvider.interceptors.push('RequestsErrorHandler');

    // --- Decorate $http to add a special header by default ---

    function addHeaderToConfig(config) {
        config = config || {};
        config.headers = config.headers || {};

        // Add the header unless user asked to handle errors himself
        if (!specificallyHandleInProgress) {
            config.headers[HEADER_NAME] = true;
        }

        return config;
    }

    // The rest here is mostly boilerplate needed to decorate $http safely
    $provide.decorator('$http', ['$delegate', function ($delegate) {
        function decorateRegularCall(method) {
            return function (url, config) {
                return $delegate[method](url, addHeaderToConfig(config));
            };
        }

        function decorateDataCall(method) {
            return function (url, data, config) {
                return $delegate[method](url, data, addHeaderToConfig(config));
            };
        }

        function copyNotOverriddenAttributes(newHttp) {
            for (var attr in $delegate) {
                if (!newHttp.hasOwnProperty(attr)) {
                    if (typeof($delegate[attr]) === 'function') {
                        newHttp[attr] = function () {
                            return $delegate[attr].apply($delegate, arguments);
                        };
                    } else {
                        newHttp[attr] = $delegate[attr];
                    }
                }
            }
        }

        var newHttp = function (config) {
            return $delegate(addHeaderToConfig(config));
        };

        newHttp.get = decorateRegularCall('get');
        newHttp.delete = decorateRegularCall('delete');
        newHttp.head = decorateRegularCall('head');
        newHttp.jsonp = decorateRegularCall('jsonp');
        newHttp.post = decorateDataCall('post');
        newHttp.put = decorateDataCall('put');

        copyNotOverriddenAttributes(newHttp);

        return newHttp;
    }]);
}]);

mamidApp.config(function ($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'pages/home.html',
            controller: 'mainController'
        })
        .when('/slaves', {
            templateUrl: 'pages/slaves.html',
            controller: 'slaveIndexController'
        })
        .when('/slaves/:slaveId', {
            templateUrl: 'pages/slave.html',
            controller: 'slaveByIdController'
        })
        .when('/replicasets', {
            templateUrl: 'pages/replicasets.html',
            controller: 'replicasetIndexController'
        })
        .when('/replicasets/:replicasetId', {
            templateUrl: 'pages/replicaset.html',
            controller: 'replicasetByIdController'
        })
        .when('/problems', {
            templateUrl: 'pages/problems.html',
            controller: 'problemIndexController'
        })
        .when('/riskgroups', {
            templateUrl: 'pages/riskgroups.html',
            controller: 'riskGroupIndexController'
        })
});

mamidApp.factory('SlaveService', function ($resource) {
    return $resource('/api/slaves/:slave', {slave: "@id"}, {
        create: {method: 'put'},
        queryByReplicaSet: {method: 'get', url: '/api/replicasets/:replicaset/slaves/', isArray: true},
        getProblems: {method: 'get', url: '/api/slaves/:slave/problems', isArray: true}
    });
});

mamidApp.factory('ProblemService', function ($resource) {
    return $resource('/api/problems/:problem', {problem: "@id"}, {});
});

mamidApp.factory('ReplicaSetService', function ($resource) {
    return $resource('/api/replicasets/:replicaset', {replicaset: "@id"}, {
        create: {method: 'put'},
        getProblems: {method: 'get', url: '/api/replicasets/:replicaset/problems', isArray: true}
    });
});

mamidApp.factory('RiskGroupService', function ($resource) {
    return $resource('/api/riskgroups/:riskgroup', {riskgroup: "@id"}, {
        create: {method: 'put'},
        getUnassignedSlaves: {method: 'get', url: '/api/riskgroups/0/slaves/', isArray: true},
        assignToRiskGroup: {
            method: 'put',
            url: '/api/riskgroups/:riskgroup/slaves/:slave',
            params: {riskgroup: "@riskgroup", slave: "@slave"}
        },
        removeFromRiskGroup: {
            method: 'delete',
            url: '/api/riskgroups/:riskgroup/slaves/:slave',
            params: {riskgroup: "@riskgroup", slave: "@slave"}
        },
        getSlaves: {method: 'get', url: '/api/riskgroups/:riskgroup/slaves', isArray: true},
        remove: {method: 'delete'}
    });
});

mamidApp.controller('mainController', function ($scope, $location, filterFilter, SlaveService, ProblemService) {
    $scope.problems = ProblemService.query();
    $scope.$location = $location;
    SlaveService.query(function (slaves) {

        $scope.slaves = slaves;
        for (var i = 0; i < $scope.slaves.length; i++) {
            $scope.slaves[i].problems = SlaveService.getProblems({slave: $scope.slaves[i].id}, function(problems) {
                 $scope.genChart();
            });
        }
    });
    $scope.genChart = function() {
        c3.generate({
                bindto: '#slaves',
                data: {
                    columns: [
                        ['Active', $scope.getStateCount('active')],
                        ['Maintenance', $scope.getStateCount('maintenance')],
                        ['Disabled', $scope.getStateCount('disabled')],
                        ['Problematic', $scope.getProblemCount()]
                    ],
                    type: 'donut',
                },
                donut: {
                    title: "Slave states"
                }
                ,
                color: {
                    pattern: ['#22aa22', '#0af', '#c0c0c0', '#d43f3a']
                }
                ,
            })
            ;
    };
    $scope.getStateCount = function (state) {
        var s = []
        for(var i=0;i<$scope.slaves.length;i++){
            if($scope.slaves[i].problems.length == 0) {
                s.push($scope.slaves[i]);
            }
        }
        return filterFilter(s, {configured_state: state}).length;
    };

    $scope.getProblemCount = function() {
        var count = 0;
        for(var i=0;i<$scope.slaves.length;i++){
            window.console.log($scope.slaves[i].problems.length);
            if($scope.slaves[i].problems.length > 0) {
                count++;
            }
        }
        return count;
    }

});

mamidApp.controller('slaveIndexController', function ($scope, $http, SlaveService) {
    SlaveService.query(function (slaves) {
        $scope.slaves = slaves;
        for (var i = 0; i < $scope.slaves.length; i++) {
            $scope.slaves[i].problems = SlaveService.getProblems({slave: $scope.slaves[i].id});
        }
    });

});
var problemPolling = false;
mamidApp.controller('problemIndexController', function ($scope, $http, $timeout, ProblemService) {
    if (!problemPolling) {
        (function tick() {
            ProblemService.query(function (problems) {
                $scope.problems = problems;
                $timeout(tick, 1000 * 5);
                problemPolling = true;
            });
        })();
    }
    $scope.formatDate = function (date) {
        return String(new Date(Date.parse(date)));
    }
});

mamidApp.controller('riskGroupIndexController', function ($scope, $http, RiskGroupService) {
    $scope.riskgroups = RiskGroupService.query();
    $scope.unassigned_slaves = RiskGroupService.getUnassignedSlaves();
    $scope.new_riskgroup = new RiskGroupService();
    $scope.createRiskGroup = function () {
        $scope.new_riskgroup.$create();
        $scope.new_riskgroup = new RiskGroupService();
        $scope.refreshRiskGroups();
    };
    $scope.assignToRiskGroup = function (slave, oldriskgroup) {
        if (slave.riskgroup == 0) {
            RiskGroupService.removeFromRiskGroup({slave: slave.id, riskgroup: oldriskgroup.id});
            $scope.refreshRiskGroups();
            $scope.unassigned_slaves = RiskGroupService.getUnassignedSlaves();
            return;
        }
        RiskGroupService.assignToRiskGroup({slave: slave.id, riskgroup: slave.riskgroup});
        $scope.refreshRiskGroups();
        $scope.unassigned_slaves = RiskGroupService.getUnassignedSlaves();
    };
    $scope.getSlaves = function (riskgroup) {
        riskgroup.slaves = RiskGroupService.getSlaves({riskgroup: riskgroup.id});
    };
    $scope.removeRiskGroup = function (riskgroup) {
        riskgroup.slaves = RiskGroupService.remove({riskgroup: riskgroup.id});
        $scope.refreshRiskGroups();
        $('#confirm_remove' + riskgroup.id).modal('hide');
    };
    $scope.isDeletable = function (riskgroup) {
        if (riskgroup.slaves === undefined) {
            $scope.getSlaves(riskgroup);
        }
        return riskgroup.slaves.length == 0;
    };
    $(function () {
        $('[data-toggle="tooltip"]').tooltip();
    });

    $scope.refreshRiskGroups = function () {
        RiskGroupService.query(function (riskgroups) {
            $scope.riskgroups = riskgroups;
        });
    }
});

mamidApp.controller('slaveByIdController', function ($scope, $http, $routeParams, $location, SlaveService) {
    var slaveId = $routeParams['slaveId'];
    $scope.is_create_view = slaveId === "new";
    if ($scope.is_create_view) {
        $scope.slave = new SlaveService();

        $scope.slave.configured_state = "disabled";

        //Copy slave for edit form so that changes are only applied to model when apply is clicked
        $scope.edit_slave = angular.copy($scope.slave);
    } else {
        $scope.slave = SlaveService.get({slave: slaveId});
        $scope.problems = SlaveService.getProblems({slave: slaveId});

        //Copy slave for edit form so that changes are only applied to model when apply is clicked
        $scope.slave.$promise.then(function () {
            $scope.edit_slave = angular.copy($scope.slave);
        });
    }

    $scope.updateSlave = function () {
        angular.copy($scope.edit_slave, $scope.slave);
        if ($scope.is_create_view) {
            $scope.slave.$create(function () {
                $location.path("/slaves");
            });
        } else {
            $scope.slave.$save();
        }

    };

    $scope.deleteSlave = function () {
        $scope.slave.$delete();
        $('#confirm_remove').modal('hide');
        $location.path("/slaves");
    };

    $scope.setSlaveState = function (state) {
        $scope.slave.configured_state = state;
        $scope.slave.$save();
    }
});

mamidApp.controller('replicasetIndexController', function ($scope, $http, ReplicaSetService) {
    ReplicaSetService.query(function (replicasets) {
        $scope.replicasets = replicasets;
        for (var i = 0; i < $scope.replicasets.length; i++) {
            $scope.replicasets[i].problems = ReplicaSetService.getProblems({replicaset: $scope.replicasets[i].id});
        }
    });
});

mamidApp.controller('replicasetByIdController',
    function ($scope, $http, $routeParams, $location, SlaveService, ReplicaSetService) {
        var replicasetId = $routeParams['replicasetId'];
        $scope.is_create_view = replicasetId === "new";
        if ($scope.is_create_view) {
            $scope.replicaset = new ReplicaSetService();

            //Copy replicaset for edit form so that changes are only applied to model when apply is clicked
            $scope.edit_replicaset = angular.copy($scope.replicaset);
        } else {
            $scope.replicaset = ReplicaSetService.get({replicaset: replicasetId});
            $scope.replicaset_slaves = SlaveService.queryByReplicaSet({replicaset: replicasetId});
            $scope.problems = ReplicaSetService.getProblems({replicaset: replicasetId});

            //Copy replicaset for edit form so that changes are only applied to model when apply is clicked
            $scope.replicaset.$promise.then(function () {
                $scope.edit_replicaset = angular.copy($scope.replicaset);
            });
        }

        $scope.updateReplicaSet = function () {
            angular.copy($scope.edit_replicaset, $scope.replicaset);
            if ($scope.is_create_view) {
                $scope.replicaset.$create();
            } else {
                $scope.replicaset.$save();
            }
            $location.path("/replicasets");
        };

        $scope.deleteReplicaSet = function () {
            $scope.replicaset.$delete();
            $('#confirm_remove').modal('hide');
            $location.path("/replicasets");
        };
    });<commit_msg>FIX: api change in getUnassignedSlaves<commit_after>var mamidApp = angular.module('mamidApp', ['ngRoute', 'ngResource']);

// http://www.codelord.net/2014/06/25/generic-error-handling-in-angularjs/
var specificallyHandleInProgress = false;
var HEADER_NAME = 'MyApp-Handle-Errors-Generically';
mamidApp.factory('RequestsErrorHandler', ['$q', function ($q) {
    return {
        // --- The user's API for claiming responsiblity for requests ---
        specificallyHandled: function (specificallyHandledBlock) {
            specificallyHandleInProgress = true;
            try {
                return specificallyHandledBlock();
            } finally {
                specificallyHandleInProgress = false;
            }
        },

        // --- Response interceptor for handling errors generically ---
        responseError: function (rejection) {
            var shouldHandle = (rejection && rejection.config && rejection.config.headers
            && rejection.config.headers[HEADER_NAME]);
            if (shouldHandle) {
                var root = $('#content')[0];
                var ediv = document.createElement('div');
                ediv.setAttribute('class', 'alert alert-danger alert-dismissible fade in');
                ediv.setAttribute('role', 'alert');
                var button = document.createElement('button');
                button.setAttribute('class', 'close');
                button.setAttribute('data-dismiss', 'alert');
                button.setAttribute('type', 'button');
                button.innerHTML = '×';
                ediv.appendChild(button);
                var h4 = document.createElement('h4');
                h4.innerHTML = 'Houps! An error occurred.';
                ediv.appendChild(h4);
                var p = document.createElement('p');
                p.innerHTML = rejection.data;
                ediv.appendChild(p);
                $(ediv).hide();
                root.insertBefore(ediv, root.firstChild);
                $(ediv).alert();
                $(ediv).fadeTo(5000, 500).slideUp(500, function () {
                    $(ediv).alert('close');
                });
                window.console.error(rejection);
            }

            return $q.reject(rejection);
        }
    };
}]);
mamidApp.config(['$provide', '$httpProvider', function ($provide, $httpProvider) {
    $httpProvider.interceptors.push('RequestsErrorHandler');

    // --- Decorate $http to add a special header by default ---

    function addHeaderToConfig(config) {
        config = config || {};
        config.headers = config.headers || {};

        // Add the header unless user asked to handle errors himself
        if (!specificallyHandleInProgress) {
            config.headers[HEADER_NAME] = true;
        }

        return config;
    }

    // The rest here is mostly boilerplate needed to decorate $http safely
    $provide.decorator('$http', ['$delegate', function ($delegate) {
        function decorateRegularCall(method) {
            return function (url, config) {
                return $delegate[method](url, addHeaderToConfig(config));
            };
        }

        function decorateDataCall(method) {
            return function (url, data, config) {
                return $delegate[method](url, data, addHeaderToConfig(config));
            };
        }

        function copyNotOverriddenAttributes(newHttp) {
            for (var attr in $delegate) {
                if (!newHttp.hasOwnProperty(attr)) {
                    if (typeof($delegate[attr]) === 'function') {
                        newHttp[attr] = function () {
                            return $delegate[attr].apply($delegate, arguments);
                        };
                    } else {
                        newHttp[attr] = $delegate[attr];
                    }
                }
            }
        }

        var newHttp = function (config) {
            return $delegate(addHeaderToConfig(config));
        };

        newHttp.get = decorateRegularCall('get');
        newHttp.delete = decorateRegularCall('delete');
        newHttp.head = decorateRegularCall('head');
        newHttp.jsonp = decorateRegularCall('jsonp');
        newHttp.post = decorateDataCall('post');
        newHttp.put = decorateDataCall('put');

        copyNotOverriddenAttributes(newHttp);

        return newHttp;
    }]);
}]);

mamidApp.config(function ($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'pages/home.html',
            controller: 'mainController'
        })
        .when('/slaves', {
            templateUrl: 'pages/slaves.html',
            controller: 'slaveIndexController'
        })
        .when('/slaves/:slaveId', {
            templateUrl: 'pages/slave.html',
            controller: 'slaveByIdController'
        })
        .when('/replicasets', {
            templateUrl: 'pages/replicasets.html',
            controller: 'replicasetIndexController'
        })
        .when('/replicasets/:replicasetId', {
            templateUrl: 'pages/replicaset.html',
            controller: 'replicasetByIdController'
        })
        .when('/problems', {
            templateUrl: 'pages/problems.html',
            controller: 'problemIndexController'
        })
        .when('/riskgroups', {
            templateUrl: 'pages/riskgroups.html',
            controller: 'riskGroupIndexController'
        })
});

mamidApp.factory('SlaveService', function ($resource) {
    return $resource('/api/slaves/:slave', {slave: "@id"}, {
        create: {method: 'put'},
        queryByReplicaSet: {method: 'get', url: '/api/replicasets/:replicaset/slaves/', isArray: true},
        getProblems: {method: 'get', url: '/api/slaves/:slave/problems', isArray: true}
    });
});

mamidApp.factory('ProblemService', function ($resource) {
    return $resource('/api/problems/:problem', {problem: "@id"}, {});
});

mamidApp.factory('ReplicaSetService', function ($resource) {
    return $resource('/api/replicasets/:replicaset', {replicaset: "@id"}, {
        create: {method: 'put'},
        getProblems: {method: 'get', url: '/api/replicasets/:replicaset/problems', isArray: true}
    });
});

mamidApp.factory('RiskGroupService', function ($resource) {
    return $resource('/api/riskgroups/:riskgroup', {riskgroup: "@id"}, {
        create: {method: 'put'},
        getUnassignedSlaves: {method: 'get', url: '/api/riskgroups/null/slaves/', isArray: true},
        assignToRiskGroup: {
            method: 'put',
            url: '/api/riskgroups/:riskgroup/slaves/:slave',
            params: {riskgroup: "@riskgroup", slave: "@slave"}
        },
        removeFromRiskGroup: {
            method: 'delete',
            url: '/api/riskgroups/:riskgroup/slaves/:slave',
            params: {riskgroup: "@riskgroup", slave: "@slave"}
        },
        getSlaves: {method: 'get', url: '/api/riskgroups/:riskgroup/slaves', isArray: true},
        remove: {method: 'delete'}
    });
});

mamidApp.controller('mainController', function ($scope, $location, filterFilter, SlaveService, ProblemService) {
    $scope.problems = ProblemService.query();
    $scope.$location = $location;
    SlaveService.query(function (slaves) {

        $scope.slaves = slaves;
        for (var i = 0; i < $scope.slaves.length; i++) {
            $scope.slaves[i].problems = SlaveService.getProblems({slave: $scope.slaves[i].id}, function(problems) {
                 $scope.genChart();
            });
        }
    });
    $scope.genChart = function() {
        c3.generate({
                bindto: '#slaves',
                data: {
                    columns: [
                        ['Active', $scope.getStateCount('active')],
                        ['Maintenance', $scope.getStateCount('maintenance')],
                        ['Disabled', $scope.getStateCount('disabled')],
                        ['Problematic', $scope.getProblemCount()]
                    ],
                    type: 'donut',
                },
                donut: {
                    title: "Slave states"
                }
                ,
                color: {
                    pattern: ['#22aa22', '#0af', '#c0c0c0', '#d43f3a']
                }
                ,
            })
            ;
    };
    $scope.getStateCount = function (state) {
        var s = []
        for(var i=0;i<$scope.slaves.length;i++){
            if($scope.slaves[i].problems.length == 0) {
                s.push($scope.slaves[i]);
            }
        }
        return filterFilter(s, {configured_state: state}).length;
    };

    $scope.getProblemCount = function() {
        var count = 0;
        for(var i=0;i<$scope.slaves.length;i++){
            window.console.log($scope.slaves[i].problems.length);
            if($scope.slaves[i].problems.length > 0) {
                count++;
            }
        }
        return count;
    }

});

mamidApp.controller('slaveIndexController', function ($scope, $http, SlaveService) {
    SlaveService.query(function (slaves) {
        $scope.slaves = slaves;
        for (var i = 0; i < $scope.slaves.length; i++) {
            $scope.slaves[i].problems = SlaveService.getProblems({slave: $scope.slaves[i].id});
        }
    });

});
var problemPolling = false;
mamidApp.controller('problemIndexController', function ($scope, $http, $timeout, ProblemService) {
    if (!problemPolling) {
        (function tick() {
            ProblemService.query(function (problems) {
                $scope.problems = problems;
                $timeout(tick, 1000 * 5);
                problemPolling = true;
            });
        })();
    }
    $scope.formatDate = function (date) {
        return String(new Date(Date.parse(date)));
    }
});

mamidApp.controller('riskGroupIndexController', function ($scope, $http, RiskGroupService) {
    $scope.riskgroups = RiskGroupService.query();
    $scope.unassigned_slaves = RiskGroupService.getUnassignedSlaves();
    $scope.new_riskgroup = new RiskGroupService();
    $scope.createRiskGroup = function () {
        $scope.new_riskgroup.$create();
        $scope.new_riskgroup = new RiskGroupService();
        $scope.refreshRiskGroups();
    };
    $scope.assignToRiskGroup = function (slave, oldriskgroup) {
        if (slave.riskgroup == 0) {
            RiskGroupService.removeFromRiskGroup({slave: slave.id, riskgroup: oldriskgroup.id});
            $scope.refreshRiskGroups();
            $scope.unassigned_slaves = RiskGroupService.getUnassignedSlaves();
            return;
        }
        RiskGroupService.assignToRiskGroup({slave: slave.id, riskgroup: slave.riskgroup});
        $scope.refreshRiskGroups();
        $scope.unassigned_slaves = RiskGroupService.getUnassignedSlaves();
    };
    $scope.getSlaves = function (riskgroup) {
        riskgroup.slaves = RiskGroupService.getSlaves({riskgroup: riskgroup.id});
    };
    $scope.removeRiskGroup = function (riskgroup) {
        riskgroup.slaves = RiskGroupService.remove({riskgroup: riskgroup.id});
        $scope.refreshRiskGroups();
        $('#confirm_remove' + riskgroup.id).modal('hide');
    };
    $scope.isDeletable = function (riskgroup) {
        if (riskgroup.slaves === undefined) {
            $scope.getSlaves(riskgroup);
        }
        return riskgroup.slaves.length == 0;
    };
    $(function () {
        $('[data-toggle="tooltip"]').tooltip();
    });

    $scope.refreshRiskGroups = function () {
        RiskGroupService.query(function (riskgroups) {
            $scope.riskgroups = riskgroups;
        });
    }
});

mamidApp.controller('slaveByIdController', function ($scope, $http, $routeParams, $location, SlaveService) {
    var slaveId = $routeParams['slaveId'];
    $scope.is_create_view = slaveId === "new";
    if ($scope.is_create_view) {
        $scope.slave = new SlaveService();

        $scope.slave.configured_state = "disabled";

        //Copy slave for edit form so that changes are only applied to model when apply is clicked
        $scope.edit_slave = angular.copy($scope.slave);
    } else {
        $scope.slave = SlaveService.get({slave: slaveId});
        $scope.problems = SlaveService.getProblems({slave: slaveId});

        //Copy slave for edit form so that changes are only applied to model when apply is clicked
        $scope.slave.$promise.then(function () {
            $scope.edit_slave = angular.copy($scope.slave);
        });
    }

    $scope.updateSlave = function () {
        angular.copy($scope.edit_slave, $scope.slave);
        if ($scope.is_create_view) {
            $scope.slave.$create(function () {
                $location.path("/slaves");
            });
        } else {
            $scope.slave.$save();
        }

    };

    $scope.deleteSlave = function () {
        $scope.slave.$delete();
        $('#confirm_remove').modal('hide');
        $location.path("/slaves");
    };

    $scope.setSlaveState = function (state) {
        $scope.slave.configured_state = state;
        $scope.slave.$save();
    }
});

mamidApp.controller('replicasetIndexController', function ($scope, $http, ReplicaSetService) {
    ReplicaSetService.query(function (replicasets) {
        $scope.replicasets = replicasets;
        for (var i = 0; i < $scope.replicasets.length; i++) {
            $scope.replicasets[i].problems = ReplicaSetService.getProblems({replicaset: $scope.replicasets[i].id});
        }
    });
});

mamidApp.controller('replicasetByIdController',
    function ($scope, $http, $routeParams, $location, SlaveService, ReplicaSetService) {
        var replicasetId = $routeParams['replicasetId'];
        $scope.is_create_view = replicasetId === "new";
        if ($scope.is_create_view) {
            $scope.replicaset = new ReplicaSetService();

            //Copy replicaset for edit form so that changes are only applied to model when apply is clicked
            $scope.edit_replicaset = angular.copy($scope.replicaset);
        } else {
            $scope.replicaset = ReplicaSetService.get({replicaset: replicasetId});
            $scope.replicaset_slaves = SlaveService.queryByReplicaSet({replicaset: replicasetId});
            $scope.problems = ReplicaSetService.getProblems({replicaset: replicasetId});

            //Copy replicaset for edit form so that changes are only applied to model when apply is clicked
            $scope.replicaset.$promise.then(function () {
                $scope.edit_replicaset = angular.copy($scope.replicaset);
            });
        }

        $scope.updateReplicaSet = function () {
            angular.copy($scope.edit_replicaset, $scope.replicaset);
            if ($scope.is_create_view) {
                $scope.replicaset.$create();
            } else {
                $scope.replicaset.$save();
            }
            $location.path("/replicasets");
        };

        $scope.deleteReplicaSet = function () {
            $scope.replicaset.$delete();
            $('#confirm_remove').modal('hide');
            $location.path("/replicasets");
        };
    });<|endoftext|>


<commit_before>import h from 'react-hyperscript'
import { compose } from 'recompose'
import { connect as connectFela } from 'react-fela'
import { map, partial } from 'ramda'

import { FormattedMessage } from '../../lib/Intl'
import styles from '../styles/ProductListEditor'
import ProductEditor from '../../supply/components/ProductEditor'

import RaisedButton from 'material-ui/RaisedButton'

const ProductListEditor = compose(
  connectFela(styles)
)(props => {
  const { styles, createProduct, products, updateResourceType, savePriceSpecs } = props

  console.log('products', products)

  const renderProducts = map(product => {
    return h(ProductEditor, {
      product,
      key: product.id,
      updateResourceType,
      savePriceSpecs: partial(savePriceSpecs, [product.id])
    })
  })

  return h('div', {
    className: styles.container
  }, [
    h(RaisedButton, {
      className: styles.addProductButton,
      onClick: () => createProduct()
    }, [
      h(FormattedMessage, {
        id: 'supply.createProduct',
        className: styles.labelText
      })
    ]),
    renderProducts(products)
  ])
})

export default ProductListEditor
<commit_msg>use floating action button to create product<commit_after>import h from 'react-hyperscript'
import { compose } from 'recompose'
import { connect as connectFela } from 'react-fela'
import { map, partial } from 'ramda'
import FloatingActionButton from 'material-ui/FloatingActionButton'
import ContentAdd from 'material-ui/svg-icons/content/add'

import { FormattedMessage } from '../../lib/Intl'
import styles from '../styles/ProductListEditor'
import ProductEditor from '../../supply/components/ProductEditor'

const ProductListEditor = compose(
  connectFela(styles)
)(props => {
  const { styles, createProduct, products, updateResourceType, savePriceSpecs } = props

  console.log('products', products)

  const renderProducts = map(product => {
    return h(ProductEditor, {
      product,
      key: product.id,
      updateResourceType,
      savePriceSpecs: partial(savePriceSpecs, [product.id])
    })
  })

  return h('div', {
    className: styles.container
  }, [
    renderProducts(products),
    h(FloatingActionButton, {
      className: styles.addProductButton,
      onClick: () => createProduct()
    }, [
      h(ContentAdd)
    ])
  ])
})

export default ProductListEditor
<|endoftext|>


<commit_before>import React from 'react';
import * as utils from '../../lib/utils';
import PostItem from '../post-item';
import {postFetchAllRequest} from '../../action/post-actions.js';
import {connect} from 'react-redux';

class PostList extends React.Component {
  constructor(props){
    super(props);
    this.state = {

    };
  }

  render () {
    console.log('(**********this is state post*****',this.props.post);
    return (

hihihihhihihihih

        {utils.renderIf(this.props.post,
          this.props.post.map(post =>

{
              <PostItem key={post._id} post={post}
              />
            }

          ))}

    );
  }
}

let mapStateToProps = state => ({
  auth: state.auth,
  user: state.user,
  post: state.post,
});

let mapDispatchToProps = dispatch => ({
  postFetch: () => dispatch(postFetchAllRequest()),

});

export default connect(mapStateToProps, mapDispatchToProps)(PostList);
<commit_msg>got posts rendering<commit_after>import React from 'react';
import * as utils from '../../lib/utils';
import PostItem from '../post-item';
import {postFetchAllRequest} from '../../action/post-actions.js';
import {connect} from 'react-redux';

class PostList extends React.Component {
  constructor(props){
    super(props);
    this.state = {

    };
  }

  render () {
    console.log('(**********this is state post*****',this.props.post);
    return (

This is the list of posts

        {utils.renderIf(this.props.post,
          this.props.post.map(post =>

{
              <PostItem key={post._id} post={post}
              />
            }

          ))}

    );
  }
}

let mapStateToProps = state => ({
  auth: state.auth,
  user: state.user,
  post: state.post,
});

let mapDispatchToProps = dispatch => ({
  postFetch: () => dispatch(postFetchAllRequest()),

});

export default connect(mapStateToProps, mapDispatchToProps)(PostList);
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-dom/test-utils';
import { shallow, mount } from 'enzyme';
// import renderer from 'react-test-renderer';

import NavButton from '.';

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

    let props;
    let mountedNavButton;
    const onClick=() => {};
    const navButton = () => {
        if (!mountedNavButton) {
            mountedNavButton = mount(
                <NavButton
                    onClick={onClick}
                />
            );
        }
        return mountedNavButton;
    }
    it('renders without crashing', () => {
        const div = document.createElement('div');
        ReactDOM.render(
            <NavButton
                onClick={() => {}}
            />, div);
    });

    /** Just an example, normally props should not be tested, as they
        are already covered by PropTypes. */
    it('allows us to set props', () => {
        const onClick = () => console.log('onClick() fired');
        const wrapper = mount(
            <NavButton
                onClick={onClick}
                propOne="foo"
            />);
        expect(wrapper.props().propOne).toEqual('foo');
        wrapper.setProps({ propOne: 'bonka' });
        expect(wrapper.props().propOne).toEqual('bonka');
    });

    it('handles click events', () => {
        NavButton.prototype.onClick = jest.fn();
        const mockClick = NavButton.prototype.onClick;
        const wrapper = mount((
            <NavButton
                onClick={mockClick}
                icon="fa fa-arrow-up"
            />
        ));
        wrapper.find('button').simulate('click');
        expect(mockClick).toHaveBeenCalled();
    });
});<commit_msg>more test setups<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
// import ReactTestUtils from 'react-dom/test-utils';
import { mount } from 'enzyme';
// import renderer from 'react-test-renderer';

import NavButton from '.';

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

    let props;
    let mountedNavButton;
    const onClick=() => {};
    const navButtonJSX = <NavButton {...props} />;
    const navButton = () => {
        if (!mountedNavButton) {
            mountedNavButton = mount(
                navButtonJSX
            );
        }
        return mountedNavButton;
    };

    beforeEach(() => {
        props = {
            onClick: onClick,
            icon: 'fa fa-arrow-up'
        };
        mountedNavButton = undefined;
    });

    it('renders without crashing', () => {
        const div = document.createElement('div');
        ReactDOM.render(
            navButtonJSX, div);
    });

    /** Just an example, normally props should not be tested, as they
        are already covered by PropTypes. */
/*     it('allows us to set props', () => {
        const onClick = () => console.log('onClick() fired');
        const wrapper = mount(
            <NavButton
                onClick={onClick}
                propOne="foo"
            />);
        expect(wrapper.props().propOne).toEqual('foo');
        wrapper.setProps({ propOne: 'bonka' });
        expect(wrapper.props().propOne).toEqual('bonka');
    }); */

    it('mounts NavButton on FullDOM rendering', () => {
        const renderedTag = navButton().find('NavButton');
        expect(renderedTag.length).toBe(1);
    });

    it('handles click events', () => {
        NavButton.prototype.onClick = jest.fn();
        const mockClick = NavButton.prototype.onClick;
        const wrapper = mount((
            navButtonJSX
        ));
        wrapper.find('button').simulate('click');
        expect(mockClick).toHaveBeenCalled();
    });
});<|endoftext|>


<commit_before>var path = require('path');
var pkg = require('../../package.json');

/**
 * Configuration class containing all properties to be used throughout the build
 */
var Config = function() {
  this.debugMode = false;
  this.lessExtension = "less";
  this.sassExtension = "scss";
  this.buildSass = false;
  this.copyRightMessage = "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.";
	var distPath = 'dist';
	var srcPath = 'src';
	this.paths = {
		distComponents: distPath + '/components',
		distLess: distPath + '/less',
    distSass: distPath + '/sass',
		distCSS: distPath + '/css',
		distSamples: distPath + '/samples',
		distSampleComponents: distPath + '/samples/' +  '/Components',
		distJS: distPath + '/js',
		distPackages: distPath + '/packages',
		srcPath: srcPath,
		srcSamples: srcPath + '/samples',
    srcSass: srcPath + '/sass',
		componentsPath : 'src/components',
		srcLess: srcPath + '/less',
		templatePath : srcPath + '/templates'
	};
	this.port =  process.env.PORT || 2020;
	this.projectURL =  "http://localhost";
	this.projectDirectory =  path.resolve(__dirname, '../../' + this.paths.distSamples);
	this.servePaths = [
        {
            'urlPath': '/css',
            'folderPath': '../css'
        }
    ];
	this.nugetConfig = {
		id: "OfficeUIFabric",
		title: "Office UI Fabric",
		version: pkg.version,
		authors: "Microsoft Corporation",
		owners: "Microsoft Corporation",
		description: "Fabric is a responsive, mobile-first, front-end framework, designed to make it quick and simple for you to create web experiences using the Office Design Language. It’s easy to get up and running with Fabric—whether you’re creating a new Office experience from scratch or adding new features to an existing one.",
		summary: "The front-end framework for building experiences for Office and Office 365.",
		language: "en-us",
		projectUrl: "https://github.com/OfficeDev/Office-UI-Fabric",
		licenseUrl: "https://github.com/OfficeDev/Office-UI-Fabric/blob/master/LICENSE",
		copyright: "Copyright (c) Microsoft Corporation",
		requireLicenseAcceptance: true,
		tags: "Microsoft UI Fabric CSS",
		outputDir: this.paths.distPackages
	};
	this.nugetPaths = [
		{src: this.paths.componentsPath, dest: "/content/components/"},
		{src: this.paths.distCSS, dest: "/content/css/"},
		{src: this.paths.distJS, dest: "/content/scripts/"},
		{src: this.paths.distLess, dest: "/content/less/"},
        {src: this.paths.distSass, dest: "/content/sass/"}
	];
  this.componentSamplesUpdate = "Components Samples updated successfully! Yay!";
  this.componentSamplesFinished = ' Component Samples build was successful! Yay!';
  //JS Files to be ignored in the JS Linter for Components
  //NOTE: Only use this for third party files, do not add any Fabric JS files to this.
  this.ignoreComponentJSLinting = [{
        src: this.paths.componentsPath + '/DatePicker/PickaDate.js',
        dist: this.paths.distSampleComponents + '/DatePicker/'
  }];
  //Errors
  this.genericBuildError = "Hmm, something went wrong in the build... Here is the error dump";
};

module.exports = new Config();<commit_msg>Change NuGet package's "components" source folder from "src/components" to "dist/components"<commit_after>var path = require('path');
var pkg = require('../../package.json');

/**
 * Configuration class containing all properties to be used throughout the build
 */
var Config = function() {
  this.debugMode = false;
  this.lessExtension = "less";
  this.sassExtension = "scss";
  this.buildSass = false;
  this.copyRightMessage = "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.";
	var distPath = 'dist';
	var srcPath = 'src';
	this.paths = {
		distComponents: distPath + '/components',
		distLess: distPath + '/less',
    distSass: distPath + '/sass',
		distCSS: distPath + '/css',
		distSamples: distPath + '/samples',
		distSampleComponents: distPath + '/samples/' +  '/Components',
		distJS: distPath + '/js',
		distPackages: distPath + '/packages',
		srcPath: srcPath,
		srcSamples: srcPath + '/samples',
    srcSass: srcPath + '/sass',
		componentsPath : 'src/components',
		srcLess: srcPath + '/less',
		templatePath : srcPath + '/templates'
	};
	this.port =  process.env.PORT || 2020;
	this.projectURL =  "http://localhost";
	this.projectDirectory =  path.resolve(__dirname, '../../' + this.paths.distSamples);
	this.servePaths = [
        {
            'urlPath': '/css',
            'folderPath': '../css'
        }
    ];
	this.nugetConfig = {
		id: "OfficeUIFabric",
		title: "Office UI Fabric",
		version: pkg.version,
		authors: "Microsoft Corporation",
		owners: "Microsoft Corporation",
		description: "Fabric is a responsive, mobile-first, front-end framework, designed to make it quick and simple for you to create web experiences using the Office Design Language. It’s easy to get up and running with Fabric—whether you’re creating a new Office experience from scratch or adding new features to an existing one.",
		summary: "The front-end framework for building experiences for Office and Office 365.",
		language: "en-us",
		projectUrl: "https://github.com/OfficeDev/Office-UI-Fabric",
		licenseUrl: "https://github.com/OfficeDev/Office-UI-Fabric/blob/master/LICENSE",
		copyright: "Copyright (c) Microsoft Corporation",
		requireLicenseAcceptance: true,
		tags: "Microsoft UI Fabric CSS",
		outputDir: this.paths.distPackages
	};
	this.nugetPaths = [
		{src: this.paths.distComponents, dest: "/content/components/"},
		{src: this.paths.distCSS, dest: "/content/css/"},
		{src: this.paths.distJS, dest: "/content/scripts/"},
		{src: this.paths.distLess, dest: "/content/less/"},
        {src: this.paths.distSass, dest: "/content/sass/"}
	];
  this.componentSamplesUpdate = "Components Samples updated successfully! Yay!";
  this.componentSamplesFinished = ' Component Samples build was successful! Yay!';
  //JS Files to be ignored in the JS Linter for Components
  //NOTE: Only use this for third party files, do not add any Fabric JS files to this.
  this.ignoreComponentJSLinting = [{
        src: this.paths.componentsPath + '/DatePicker/PickaDate.js',
        dist: this.paths.distSampleComponents + '/DatePicker/'
  }];
  //Errors
  this.genericBuildError = "Hmm, something went wrong in the build... Here is the error dump";
};

module.exports = new Config();<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router';
import { getNewPath } from 'utils/helpers';

import IsAllowed from 'components/IsAllowed/IsAllowed';
import ActionButton from './ActionButton';

import {
  EDIT,
  REVIEW,
  APPROVE,
  DRAFT,
  SENT_FOR_REVIEW,
  WAITING_FOR_APPROVAL,
  APPROVED
} from '../../../../config/constants';

const ActionButtons = ({
  cancelEdit,
  documentState,
  fetchTos,
  saveDraft,
  changeStatus,
  setDocumentState,
  setPhasesVisibility,
  setTosVisibility,
  setValidationVisibility,
  review,
  status,
  tosId
}) => {
  const editMode = documentState === 'edit';

  const editable = (
    <IsAllowed to={EDIT}>

        <ActionButton
          className='btn-sm pull-right'
          type={editMode ? 'primary' : 'default'}
          action={editMode ? saveDraft : () => review(SENT_FOR_REVIEW)}
          label={editMode ? 'Tallenna luonnos' : 'Lähetä tarkastettavaksi'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type={editMode ? 'danger' : 'primary'}
          action={editMode ? cancelEdit : () => setDocumentState('edit')}
          label={editMode ? 'Peruuta muokkaus' : 'Muokkaustila'}
        />
        {/* {editMode &&
         = Pakollinen tieto
        } */}

    </IsAllowed>
  );

  const reviewable = (
    <IsAllowed to={REVIEW}>

        <ActionButton
          className='btn-sm pull-right'
          type='primary'
          action={() => changeStatus(WAITING_FOR_APPROVAL)}
          label={'Lähetä hyväksyttäväksi'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='danger'
          action={() => changeStatus(DRAFT)}
          label={'Palauta luonnokseksi'}
        />

    </IsAllowed>
  );

  const approvable = (
    <IsAllowed to={APPROVE}>

        <ActionButton
          className='btn-sm pull-right'
          type='primary'
          action={() => changeStatus(APPROVED)}
          label={'Hyväksy'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='danger'
          action={() => changeStatus(DRAFT)}
          label={'Palauta luonnokseksi'}
        />

    </IsAllowed>
  );

  const draftable = (
    <IsAllowed to={EDIT}>

        <ActionButton
          className='btn-sm pull-right'
          type='primary'
          icon='fa-file-o'
          action={saveDraft}
          label={'Luo luonnos'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='secondary'
          icon='fa-refresh'
          action={() => fetchTos(tosId, { state: 'approved' })}
          label={'Hae viimeisin hyväksytty versio'}
        />

    </IsAllowed>
  );

  return (

        {status === DRAFT && editable}
        {status === SENT_FOR_REVIEW && reviewable}
        {status === WAITING_FOR_APPROVAL && approvable}
        {status === APPROVED && draftable}
        {status !== APPROVED && (
          <ActionButton
            className='btn-sm pull-right'
            type='success'
            action={() => setValidationVisibility(true)}
            label={'Esitarkasta'}
            icon={'fa-check-circle-o'}
          />
        )}
        <Link
          className='btn btn-sm btn-primary pull-right'
          to={getNewPath(window.location.pathname, 'print')}
        >
          Raportti
        </Link>

        <ActionButton
          className='btn-sm pull-right'
          type='default'
          action={() => setTosVisibility(true)}
          label={'Avaa kaikki tiedot'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='default'
          action={setPhasesVisibility}
          label={'Avaa perustiedot'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='default'
          action={() => setTosVisibility(false)}
          label={'Pienennä kaikki'}
        />

  );
};

ActionButtons.propTypes = {
  cancelEdit: PropTypes.func,
  changeStatus: PropTypes.func,
  documentState: PropTypes.string,
  fetchTos: PropTypes.func,
  review: PropTypes.func.isRequired,
  saveDraft: PropTypes.func,
  setDocumentState: PropTypes.func,
  setPhasesVisibility: PropTypes.func.isRequired,
  setTosVisibility: PropTypes.func.isRequired,
  setValidationVisibility: PropTypes.func.isRequired,
  status: PropTypes.string.isRequired,
  tosId: PropTypes.string.isRequired
};

export default ActionButtons;
<commit_msg>Raportti button disabled on edit mode<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router';
import { getNewPath } from 'utils/helpers';

import IsAllowed from 'components/IsAllowed/IsAllowed';
import ActionButton from './ActionButton';

import {
  EDIT,
  REVIEW,
  APPROVE,
  DRAFT,
  SENT_FOR_REVIEW,
  WAITING_FOR_APPROVAL,
  APPROVED
} from '../../../../config/constants';

const ActionButtons = ({
  cancelEdit,
  documentState,
  fetchTos,
  saveDraft,
  changeStatus,
  setDocumentState,
  setPhasesVisibility,
  setTosVisibility,
  setValidationVisibility,
  review,
  status,
  tosId
}) => {
  const editMode = documentState === 'edit';

  const editable = (
    <IsAllowed to={EDIT}>

        <ActionButton
          className='btn-sm pull-right'
          type={editMode ? 'primary' : 'default'}
          action={editMode ? saveDraft : () => review(SENT_FOR_REVIEW)}
          label={editMode ? 'Tallenna luonnos' : 'Lähetä tarkastettavaksi'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type={editMode ? 'danger' : 'primary'}
          action={editMode ? cancelEdit : () => setDocumentState('edit')}
          label={editMode ? 'Peruuta muokkaus' : 'Muokkaustila'}
        />
        {/* {editMode &&
         = Pakollinen tieto
        } */}

    </IsAllowed>
  );

  const reviewable = (
    <IsAllowed to={REVIEW}>

        <ActionButton
          className='btn-sm pull-right'
          type='primary'
          action={() => changeStatus(WAITING_FOR_APPROVAL)}
          label={'Lähetä hyväksyttäväksi'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='danger'
          action={() => changeStatus(DRAFT)}
          label={'Palauta luonnokseksi'}
        />

    </IsAllowed>
  );

  const approvable = (
    <IsAllowed to={APPROVE}>

        <ActionButton
          className='btn-sm pull-right'
          type='primary'
          action={() => changeStatus(APPROVED)}
          label={'Hyväksy'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='danger'
          action={() => changeStatus(DRAFT)}
          label={'Palauta luonnokseksi'}
        />

    </IsAllowed>
  );

  const draftable = (
    <IsAllowed to={EDIT}>

        <ActionButton
          className='btn-sm pull-right'
          type='primary'
          icon='fa-file-o'
          action={saveDraft}
          label={'Luo luonnos'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='secondary'
          icon='fa-refresh'
          action={() => fetchTos(tosId, { state: 'approved' })}
          label={'Hae viimeisin hyväksytty versio'}
        />

    </IsAllowed>
  );

  return (

        {status === DRAFT && editable}
        {status === SENT_FOR_REVIEW && reviewable}
        {status === WAITING_FOR_APPROVAL && approvable}
        {status === APPROVED && draftable}
        {status !== APPROVED && (
          <ActionButton
            className='btn-sm pull-right'
            type='success'
            action={() => setValidationVisibility(true)}
            label={'Esitarkasta'}
            icon={'fa-check-circle-o'}
          />
        )}
        <Link
          className={`btn btn-sm btn-primary pull-right${editMode ? ' disabled' : ''}`}
          to={getNewPath(window.location.pathname, 'print')}
        >
          Raportti
        </Link>

        <ActionButton
          className='btn-sm pull-right'
          type='default'
          action={() => setTosVisibility(true)}
          label={'Avaa kaikki tiedot'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='default'
          action={setPhasesVisibility}
          label={'Avaa perustiedot'}
        />
        <ActionButton
          className='btn-sm pull-right'
          type='default'
          action={() => setTosVisibility(false)}
          label={'Pienennä kaikki'}
        />

  );
};

ActionButtons.propTypes = {
  cancelEdit: PropTypes.func,
  changeStatus: PropTypes.func,
  documentState: PropTypes.string,
  fetchTos: PropTypes.func,
  review: PropTypes.func.isRequired,
  saveDraft: PropTypes.func,
  setDocumentState: PropTypes.func,
  setPhasesVisibility: PropTypes.func.isRequired,
  setTosVisibility: PropTypes.func.isRequired,
  setValidationVisibility: PropTypes.func.isRequired,
  status: PropTypes.string.isRequired,
  tosId: PropTypes.string.isRequired
};

export default ActionButtons;
<|endoftext|>


<commit_before>/**
 * This file is part of power-ui, originally developed by Futurice Oy.
 *
 * power-ui is 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.
 */
/** @jsx hJSX */
import {hJSX} from '@cycle/dom';
import {Rx} from '@cycle/core';
import _ from 'lodash';
import {formatAsFinancialsNumber, EURO_SYMBOL} from 'power-ui/utils';
import styles from './styles.scss';
import {combineReports, augmentReportsWithMetadata} from './reportUtils';

function renderPeopleStatsItem(label, value, unit, className, special = false) {
  const peopleStatsItemClassName = special
    ? styles.peopleStatsItemSpecial
    : styles.peopleStatsItem;

  return (
    <li className={peopleStatsItemClassName + ` ${className}`}>
      {label}
      {value}
      {unit}

  );
}

function renderPeopleStatsList(report, monthIndex) {
  const benchVal = Math.ceil(report.bench[monthIndex]);
  const totalIntsVal = Math.ceil(report.fte[monthIndex]);
  const bookedVal = totalIntsVal - benchVal;
  const extFteVal = Math.ceil(report.ext_fte[monthIndex]);
  return (

      {renderPeopleStatsItem('Total exts.', extFteVal, 'FTE', 'exts', true)}
      {renderPeopleStatsItem('Total ints.', totalIntsVal, 'FTE', 'ints')}
      {renderPeopleStatsItem('Booked', bookedVal, 'FTE', 'booked')}
      {renderPeopleStatsItem('Bench', benchVal, 'FTE', 'bench')}

  );
}

function renderFinancialsStatsItem(
  label, value, legendBarStyle, className, special = false) {
  const financialsStatsItemClassName = special
    ? styles.financialsStatsItemSpecial
    : styles.financialsStatsItem;
  return (
    <li className={financialsStatsItemClassName + ` ${className}`}>

      {label}
      {value}
      {EURO_SYMBOL}

  );
}

function renderFinancialsStatsList(report, monthIndex) {
  const revenue = formatAsFinancialsNumber(report.value_creation[monthIndex]);
  const overruns = formatAsFinancialsNumber(report.overrun[monthIndex]);
  const overrunsBarStyle = styles.financialsStatsLegendBarOverruns;
  const revenueBarStyle = styles.financialsStatsLegendBarRevenue;
  return (

      {renderFinancialsStatsItem(
        'Overruns', overruns, overrunsBarStyle, 'overruns', true
      )}
      {renderFinancialsStatsItem(
        'Confirmed revenue', revenue, revenueBarStyle, 'confirmed_revenue'
      )}

  );
}

function renderMonthGraphPeople(report, monthIndex) {
  const useSmallBoxesThreshold = 52;

  const totalIntsVal = Math.ceil(report.fte[monthIndex]);
  const benchVal = Math.ceil(report.bench[monthIndex]);
  const extFteVal = Math.ceil(report.ext_fte[monthIndex]);
  const bookedVal = totalIntsVal - benchVal;
  const totalPeople = totalIntsVal + extFteVal;

  const extBoxStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxExternalSmall
          : styles.monthGraphPeopleBoxExternal;
  const bookedBoxStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxBookedSmall
          : styles.monthGraphPeopleBoxBooked;
  const benchBoxStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxBenchSmall
          : styles.monthGraphPeopleBoxBench;
  const boxListStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxListSmall
          : styles.monthGraphPeopleBoxList;
  const peopleChunkStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleChunkSmall
          : styles.monthGraphPeopleChunk;

  const boxes = _.range(totalPeople).map(i => {
    if (i < extFteVal) {
      return

;
    } else if (i < extFteVal + bookedVal) {
      return

;
    } else {
      return

;
    }
  });

  const chunks = _.chunk(boxes, (totalPeople > useSmallBoxesThreshold) ? 40 : 20);
  return (

      {chunks.map(chunk =>

          {chunk}

      )}

  );
}

const financialsGraphMaxHeight = 250; // px
const financialsGraphMinWidth = 8; // px
const financialsGraphMaxWidth = 40; // px

function calculateFinancialsGraphWidth(report) {
  const x = report.maxFinancialsVal;
  const T = report.companyWideMaxFinancialsVal;
  const max = financialsGraphMaxWidth;
  const min = financialsGraphMinWidth;
  return ((x / T) * (max - min)) + min;
}

function renderMonthGraphFinancials(report, monthIndex) {
  const pxPerEur = financialsGraphMaxHeight / report.maxFinancialsVal;
  const confirmedRevenueThisMonth = report.value_creation[monthIndex];
  const overrunThisMonth = report.overrun[monthIndex];
  const breakEven = report.costs[monthIndex];
  const graphStyle = {
    width: `${calculateFinancialsGraphWidth(report)}px`,
    height: `${financialsGraphMaxHeight}px`,
  };
  const overrunStyle = {
    height: `${Math.ceil(overrunThisMonth * pxPerEur)}px`,
    display: overrunThisMonth === 0 ? 'none' : 'inherit',
  };
  const confirmedStyle = {
    height: `${Math.ceil(confirmedRevenueThisMonth * pxPerEur)}px`,
    display: confirmedRevenueThisMonth === 0 ? 'none' : 'inherit',
  };
  const breakEvenStyle = {
    bottom: `${Math.ceil(breakEven * pxPerEur)}px`,
    display: confirmedRevenueThisMonth === 0 ? 'none' : 'inherit',
  };
  return (

        break even

  );
}

function renderMonthGraph(report, monthIndex) {
  const monthTitle = _.keys(report.months[monthIndex])[0];
  const businessDays = `(${report.business_days[monthIndex]} days)`;
  return (

        {renderMonthGraphPeople(report, monthIndex)}
        {renderMonthGraphFinancials(report, monthIndex)}

        {monthTitle}
        {businessDays}

  );
}

function renderMonthReport(report, monthIndex) {
  return (

      {renderPeopleStatsList(report, monthIndex)}
      {renderMonthGraph(report, monthIndex)}
      {renderFinancialsStatsList(report, monthIndex)}

  );
}

function renderMonthReportsRow(report) {
  const monthReports = report.months.map((irrelevant, i) =>
    renderMonthReport(report, i)
  );
  return (

      {monthReports}

  );
}

function sortReportsByLargestTribe(reports) {
  return _.sortBy(reports, report => -report.fte[0]);
}

function renderReports(reports) {
  return (

      {reports.map(report => {
        const tribeReportClass = [styles.tribeReport, 'tribe_report'].join(' ');
        return

{report.name}

Staffing & value creation

          {renderMonthReportsRow(report)}

;
      })}

  );
}

function renderLoadingIndicator() {
  return (

Loading...

  );
}

function view(state$, monthSelectorVTree$, locationFilterVTree$) {
  return Rx.Observable.combineLatest(
    state$, monthSelectorVTree$, locationFilterVTree$,
    (state, monthSelectorVTree, locationFilterVTree) => {
      let reports;
      if (state && state.filters && state.filters.location === 'all') {
        reports = combineReports(state.reports);
      } else {
        const sortedReports = sortReportsByLargestTribe(state.reports);
        const completeReports = augmentReportsWithMetadata(sortedReports);
        reports = completeReports;
      }

      return

Powerhead

          {monthSelectorVTree}

            {locationFilterVTree}

        {reports.length === 0
          ? renderLoadingIndicator()
          : renderReports(reports)
        }

;
    });
}

export default view;
<commit_msg>fix style issue in view.<commit_after>/**
 * This file is part of power-ui, originally developed by Futurice Oy.
 *
 * power-ui is 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.
 */
/** @jsx hJSX */
import {hJSX} from '@cycle/dom';
import {Rx} from '@cycle/core';
import _ from 'lodash';
import {formatAsFinancialsNumber, EURO_SYMBOL} from 'power-ui/utils';
import styles from './styles.scss';
import {combineReports, augmentReportsWithMetadata} from './reportUtils';

function renderPeopleStatsItem(label, value, unit, className, special = false) {
  const peopleStatsItemClassName = special
    ? styles.peopleStatsItemSpecial
    : styles.peopleStatsItem;

  return (
    <li className={peopleStatsItemClassName + ` ${className}`}>
      {label}
      {value}
      {unit}

  );
}

function renderPeopleStatsList(report, monthIndex) {
  const benchVal = Math.ceil(report.bench[monthIndex]);
  const totalIntsVal = Math.ceil(report.fte[monthIndex]);
  const bookedVal = totalIntsVal - benchVal;
  const extFteVal = Math.ceil(report.ext_fte[monthIndex]);
  return (

      {renderPeopleStatsItem('Total exts.', extFteVal, 'FTE', 'exts', true)}
      {renderPeopleStatsItem('Total ints.', totalIntsVal, 'FTE', 'ints')}
      {renderPeopleStatsItem('Booked', bookedVal, 'FTE', 'booked')}
      {renderPeopleStatsItem('Bench', benchVal, 'FTE', 'bench')}

  );
}

function renderFinancialsStatsItem(
  label, value, legendBarStyle, className, special = false) {
  const financialsStatsItemClassName = special
    ? styles.financialsStatsItemSpecial
    : styles.financialsStatsItem;
  return (
    <li className={financialsStatsItemClassName + ` ${className}`}>

      {label}
      {value}
      {EURO_SYMBOL}

  );
}

function renderFinancialsStatsList(report, monthIndex) {
  const revenue = formatAsFinancialsNumber(report.value_creation[monthIndex]);
  const overruns = formatAsFinancialsNumber(report.overrun[monthIndex]);
  const overrunsBarStyle = styles.financialsStatsLegendBarOverruns;
  const revenueBarStyle = styles.financialsStatsLegendBarRevenue;
  return (

      {renderFinancialsStatsItem(
        'Overruns', overruns, overrunsBarStyle, 'overruns', true
      )}
      {renderFinancialsStatsItem(
        'Confirmed revenue', revenue, revenueBarStyle, 'confirmed_revenue'
      )}

  );
}

function renderMonthGraphPeople(report, monthIndex) {
  const useSmallBoxesThreshold = 52;

  const totalIntsVal = Math.ceil(report.fte[monthIndex]);
  const benchVal = Math.ceil(report.bench[monthIndex]);
  const extFteVal = Math.ceil(report.ext_fte[monthIndex]);
  const bookedVal = totalIntsVal - benchVal;
  const totalPeople = totalIntsVal + extFteVal;

  const extBoxStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxExternalSmall
          : styles.monthGraphPeopleBoxExternal;
  const bookedBoxStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxBookedSmall
          : styles.monthGraphPeopleBoxBooked;
  const benchBoxStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxBenchSmall
          : styles.monthGraphPeopleBoxBench;
  const boxListStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleBoxListSmall
          : styles.monthGraphPeopleBoxList;
  const peopleChunkStyle = (totalPeople > useSmallBoxesThreshold)
          ? styles.monthGraphPeopleChunkSmall
          : styles.monthGraphPeopleChunk;

  const boxes = _.range(totalPeople).map(i => {
    if (i < extFteVal) {
      return

;
    } else if (i < extFteVal + bookedVal) {
      return

;
    } else {
      return

;
    }
  });

  const chunks = _.chunk(boxes, (totalPeople > useSmallBoxesThreshold) ? 40 : 20);
  return (

      {chunks.map(chunk =>

          {chunk}

      )}

  );
}

const financialsGraphMaxHeight = 250; // px
const financialsGraphMinWidth = 8; // px
const financialsGraphMaxWidth = 40; // px

function calculateFinancialsGraphWidth(report) {
  const x = report.maxFinancialsVal;
  const T = report.companyWideMaxFinancialsVal;
  const max = financialsGraphMaxWidth;
  const min = financialsGraphMinWidth;
  return ((x / T) * (max - min)) + min;
}

function renderMonthGraphFinancials(report, monthIndex) {
  const pxPerEur = financialsGraphMaxHeight / report.maxFinancialsVal;
  const confirmedRevenueThisMonth = report.value_creation[monthIndex];
  const overrunThisMonth = report.overrun[monthIndex];
  const breakEven = report.costs[monthIndex];
  const graphStyle = {
    width: `${calculateFinancialsGraphWidth(report)}px`,
    height: `${financialsGraphMaxHeight}px`,
  };
  const overrunStyle = {
    height: `${Math.ceil(overrunThisMonth * pxPerEur)}px`,
    display: overrunThisMonth === 0 ? 'none' : 'inherit',
  };
  const confirmedStyle = {
    height: `${Math.ceil(confirmedRevenueThisMonth * pxPerEur)}px`,
    display: confirmedRevenueThisMonth === 0 ? 'none' : 'inherit',
  };
  const breakEvenStyle = {
    bottom: `${Math.ceil(breakEven * pxPerEur)}px`,
    display: confirmedRevenueThisMonth === 0 ? 'none' : 'inherit',
  };
  return (

        break even

  );
}

function renderMonthGraph(report, monthIndex) {
  const monthTitle = _.keys(report.months[monthIndex])[0];
  const businessDays = `(${report.business_days[monthIndex]} days)`;
  return (

        {renderMonthGraphPeople(report, monthIndex)}
        {renderMonthGraphFinancials(report, monthIndex)}

        {monthTitle}
        {businessDays}

  );
}

function renderMonthReport(report, monthIndex) {
  return (

      {renderPeopleStatsList(report, monthIndex)}
      {renderMonthGraph(report, monthIndex)}
      {renderFinancialsStatsList(report, monthIndex)}

  );
}

function renderMonthReportsRow(report) {
  const monthReports = report.months.map((irrelevant, i) =>
    renderMonthReport(report, i)
  );
  return (

      {monthReports}

  );
}

function sortReportsByLargestTribe(reports) {
  return _.sortBy(reports, report => -report.fte[0]);
}

function renderReports(reports) {
  return (

      {reports.map(report => {
        const tribeReportClass = [styles.tribeReport, 'tribe_report'].join(' ');
        return

{report.name}

Staffing & value creation

          {renderMonthReportsRow(report)}

;
      })}

  );
}

function renderLoadingIndicator() {
  return (

Loading...

  );
}

function view(state$, monthSelectorVTree$, locationFilterVTree$) {
  return Rx.Observable.combineLatest(
    state$, monthSelectorVTree$, locationFilterVTree$,
    (state, monthSelectorVTree, locationFilterVTree) => {
      let reports;
      if (state && state.filters && state.filters.location === 'all') {
        reports = combineReports(state.reports);
      } else {
        const sortedReports = sortReportsByLargestTribe(state.reports);
        const completeReports = augmentReportsWithMetadata(sortedReports);
        reports = completeReports;
      }

      return (

Powerhead

            {monthSelectorVTree}

              {locationFilterVTree}

          {reports.length === 0
            ? renderLoadingIndicator()
            : renderReports(reports)
          }

      );
    });
}

export default view;
<|endoftext|>


<commit_before>var registerComponent = require('../../core/component').registerComponent;
var shouldCaptureKeyEvent = require('../../utils/').shouldCaptureKeyEvent;

module.exports.Component = registerComponent('keyboard-shortcuts', {
  schema: {
    enterVR: {default: true},
    exitVR: {default: true}
  },

  init: function () {
    var self = this;
    var scene = this.el;

    this.listener = window.addEventListener('keyup', function (event) {
      if (!shouldCaptureKeyEvent(event)) { return; }
      if (self.enterVREnabled && event.keyCode === 70) {  // f.
        scene.enterVR();
      }
      if (self.enterVREnabled && event.keyCode === 27) {  // escape.
        scene.exitVR();
      }
    }, false);
  },

  update: function (oldData) {
    var data = this.data;
    this.enterVREnabled = data.enterVR;
  },

  remove: function () {
    window.removeEventListener('keyup', this.listener);
  }
});
<commit_msg>keyboard-shortcuts removes event listener in pause<commit_after>var registerComponent = require('../../core/component').registerComponent;
var shouldCaptureKeyEvent = require('../../utils/').shouldCaptureKeyEvent;

module.exports.Component = registerComponent('keyboard-shortcuts', {
  schema: {
    enterVR: {default: true},
    exitVR: {default: true}
  },

  init: function () {
    var self = this;
    var scene = this.el;

    this.listener = function (event) {
      if (!shouldCaptureKeyEvent(event)) { return; }
      if (self.enterVREnabled && event.keyCode === 70) {  // f.
        scene.enterVR();
      }
      if (self.enterVREnabled && event.keyCode === 27) {  // escape.
        scene.exitVR();
      }
    };
  },

  update: function (oldData) {
    var data = this.data;
    this.enterVREnabled = data.enterVR;
  },

  play: function () {
    window.addEventListener('keyup', this.listener, false);
  },

  pause: function () {
    window.removeEventListener('keyup', this.listener);
  }
});
<|endoftext|>


<commit_before>/*
 * @flow
 */

import type {ExtendedModule} from '../../types/Stats';

import Button from '../Bootstrap/Button';
import ExternalModuleLink from './ExternalModuleLink';
import OffsetPageAnchor from '../OffsetPageAnchor';
import React, { Component } from 'react';
import Unit from '../Unit';

type Props = {
  removedModules: Array<ExtendedModule>,
};

type State = {
  isOpen: boolean
};

export default class BlacklistTableBody extends Component<Props, State> {
  state: State = {
    isOpen: false,
  };

  render() {
    if (this.state.isOpen) {
      return (

          {this.renderHideRow()}
          {this.props.removedModules.map((eModule, i) =>
            <tr key={`blacklist-${i}`} {...OffsetPageAnchor(String(eModule.id))}>

                <ExternalModuleLink
                  prefix={process.env.REACT_APP_EXTERNAL_URL_PREFIX}
                  module={eModule}
                />

                {eModule.name}

              <Unit
                elem='td'
                className="vert-align numeric"
                bytes={eModule.size} />

          )}
          {this.renderHideRow()}

      );
    } else if (this.props.removedModules.length > 0) {
      return (

              <Button
                size="xs"
                onClick={() => this.setState({ isOpen: true })}>

                Show {this.props.removedModules.length} more removed modules
              </Button>

      );
    } else {
      return null;
    }
  }

  renderHideRow() {
    return (

          <Button
            size="xs"
            onClick={() => this.setState({ isOpen: false })}>

            Hide extra modules
          </Button>

    );
  }
}
<commit_msg>Don't use glyphicon classes directly.<commit_after>/*
 * @flow
 */

import type {ExtendedModule} from '../../types/Stats';

import Button from '../Bootstrap/Button';
import ExternalModuleLink from './ExternalModuleLink';
import OffsetPageAnchor from '../OffsetPageAnchor';
import React, { Component } from 'react';
import Unit from '../Unit';
import { getClassName } from '../Bootstrap/GlyphiconNames';

type Props = {
  removedModules: Array<ExtendedModule>,
};

type State = {
  isOpen: boolean
};

export default class BlacklistTableBody extends Component<Props, State> {
  state: State = {
    isOpen: false,
  };

  render() {
    if (this.state.isOpen) {
      return (

          {this.renderHideRow()}
          {this.props.removedModules.map((eModule, i) =>
            <tr key={`blacklist-${i}`} {...OffsetPageAnchor(String(eModule.id))}>

                <ExternalModuleLink
                  prefix={process.env.REACT_APP_EXTERNAL_URL_PREFIX}
                  module={eModule}
                />

                {eModule.name}

              <Unit
                elem='td'
                className="vert-align numeric"
                bytes={eModule.size} />

          )}
          {this.renderHideRow()}

      );
    } else if (this.props.removedModules.length > 0) {
      return (

              <Button
                size="xs"
                onClick={() => this.setState({ isOpen: true })}>

                 Show {this.props.removedModules.length} more removed modules
              </Button>

      );
    } else {
      return null;
    }
  }

  renderHideRow() {
    return (

          <Button
            size="xs"
            onClick={() => this.setState({ isOpen: false })}>

             Hide extra modules
          </Button>

    );
  }
}
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

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.
*/

'use strict';

var React = require('react');

var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var GeminiScrollbar = require('react-gemini-scrollbar');

var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
var linkifyMatrix = require('matrix-react-sdk/lib/linkify-matrix');
var sanitizeHtml = require('sanitize-html');

linkifyMatrix(linkify);

module.exports = React.createClass({
    displayName: 'RoomDirectory',

    getInitialState: function() {
        return {
            publicRooms: [],
            roomAlias: '',
            loading: true,
        }
    },

    componentDidMount: function() {
        var self = this;
        MatrixClientPeg.get().publicRooms(function (err, data) {
            if (err) {
                self.setState({ loading: false });
                console.error("Failed to get publicRooms: %s", JSON.stringify(err));
                var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                Modal.createDialog(ErrorDialog, {
                    title: "Failed to get public room list",
                    description: err.message
                });
            }
            else {
                self.setState({
                    publicRooms: data.chunk,
                    loading: false,
                });
                self.forceUpdate();
            }
        });
    },

    showRoom: function(roomId) {
        // extract the metadata from the publicRooms structure to pass
        // as out-of-band data to view_room, because we get information
        // here that we can't get other than by joining the room in some
        // cases.
        var room;
        for (var i = 0; i < this.state.publicRooms.length; ++i) {
            if (this.state.publicRooms[i].room_id == roomId) {
                room = this.state.publicRooms[i];
                break;
            }
        }
        var oob_data = {};
        if (room) {
            oob_data = {
                avatarUrl: room.avatar_url,
                // XXX: This logic is duplicated from the JS SDK which
                // would normally decide what the name is.
                name: room.name || room.canonical_alias || (room.aliases ? room.aliases[0] : "Unnamed room"),
            };
        }

        dis.dispatch({
            action: 'view_room',
            room_id: roomId,
            oob_data: oob_data,
        });
    },

    getRows: function(filter) {
        var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');

        if (!this.state.publicRooms) return [];

        var rooms = this.state.publicRooms.filter(function(a) {
            // FIXME: if incrementally typing, keep narrowing down the search set
            // incrementally rather than starting over each time.
            return (((a.name && a.name.toLowerCase().search(filter.toLowerCase()) >= 0) ||
                     (a.aliases && a.aliases[0].toLowerCase().search(filter.toLowerCase()) >= 0)) &&
                      a.num_joined_members > 0);
        }).sort(function(a,b) {
            return a.num_joined_members - b.num_joined_members;
        });
        var rows = [];
        var self = this;
        var guestRead, guestJoin, perms;
        for (var i = 0; i < rooms.length; i++) {
            var alias = rooms[i].canonical_alias || (rooms[i].aliases ? rooms[i].aliases[0] : "");
            var name = rooms[i].name || alias || "Unnamed room";
            guestRead = null;
            guestJoin = null;

            if (rooms[i].world_readable) {
                guestRead = (

World readable

                );
            }
            if (rooms[i].guest_can_join) {
                guestJoin = (

Guests can join

                );
            }

            perms = null;
            if (guestRead || guestJoin) {
                perms =
{guestRead} {guestJoin}
;
            }

            var topic = rooms[i].topic || '';
            topic = linkifyString(sanitizeHtml(topic));

            rows.unshift(

                        <BaseAvatar width={24} height={24} resizeMethod='crop'
                            name={ name } idName={ name }
                            url={ ContentRepo.getHttpUriForMxc(
                                    MatrixClientPeg.get().getHomeserverUrl(),
                                    rooms[i].avatar_url, 24, 24, "crop") } />

{ name }

                        { perms }

{ alias }

                        { rooms[i].num_joined_members }

            );
        }
        return rows;
    },

    onKeyUp: function(ev) {
        this.forceUpdate();
        this.setState({ roomAlias : this.refs.roomAlias.value })
        if (ev.key == "Enter") {
            this.showRoom(this.refs.roomAlias.value);
        }
    },

    render: function() {
        if (this.state.loading) {
            var Loader = sdk.getComponent("elements.Spinner");
            return (

                    <Loader />

            );
        }

        var SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
        return (

                <SimpleRoomHeader>
                    Directory
                </SimpleRoomHeader>

                    <input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
                    <GeminiScrollbar className="mx_RoomDirectory_tableWrapper">

                                { this.getRows(this.state.roomAlias) }

                    </GeminiScrollbar>

        );
    }
});

<commit_msg>Pass SimpleRoomHeader topic in as a named prop<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

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.
*/

'use strict';

var React = require('react');

var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var GeminiScrollbar = require('react-gemini-scrollbar');

var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
var linkifyMatrix = require('matrix-react-sdk/lib/linkify-matrix');
var sanitizeHtml = require('sanitize-html');

linkifyMatrix(linkify);

module.exports = React.createClass({
    displayName: 'RoomDirectory',

    getInitialState: function() {
        return {
            publicRooms: [],
            roomAlias: '',
            loading: true,
        }
    },

    componentDidMount: function() {
        var self = this;
        MatrixClientPeg.get().publicRooms(function (err, data) {
            if (err) {
                self.setState({ loading: false });
                console.error("Failed to get publicRooms: %s", JSON.stringify(err));
                var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                Modal.createDialog(ErrorDialog, {
                    title: "Failed to get public room list",
                    description: err.message
                });
            }
            else {
                self.setState({
                    publicRooms: data.chunk,
                    loading: false,
                });
                self.forceUpdate();
            }
        });
    },

    showRoom: function(roomId) {
        // extract the metadata from the publicRooms structure to pass
        // as out-of-band data to view_room, because we get information
        // here that we can't get other than by joining the room in some
        // cases.
        var room;
        for (var i = 0; i < this.state.publicRooms.length; ++i) {
            if (this.state.publicRooms[i].room_id == roomId) {
                room = this.state.publicRooms[i];
                break;
            }
        }
        var oob_data = {};
        if (room) {
            oob_data = {
                avatarUrl: room.avatar_url,
                // XXX: This logic is duplicated from the JS SDK which
                // would normally decide what the name is.
                name: room.name || room.canonical_alias || (room.aliases ? room.aliases[0] : "Unnamed room"),
            };
        }

        dis.dispatch({
            action: 'view_room',
            room_id: roomId,
            oob_data: oob_data,
        });
    },

    getRows: function(filter) {
        var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');

        if (!this.state.publicRooms) return [];

        var rooms = this.state.publicRooms.filter(function(a) {
            // FIXME: if incrementally typing, keep narrowing down the search set
            // incrementally rather than starting over each time.
            return (((a.name && a.name.toLowerCase().search(filter.toLowerCase()) >= 0) ||
                     (a.aliases && a.aliases[0].toLowerCase().search(filter.toLowerCase()) >= 0)) &&
                      a.num_joined_members > 0);
        }).sort(function(a,b) {
            return a.num_joined_members - b.num_joined_members;
        });
        var rows = [];
        var self = this;
        var guestRead, guestJoin, perms;
        for (var i = 0; i < rooms.length; i++) {
            var alias = rooms[i].canonical_alias || (rooms[i].aliases ? rooms[i].aliases[0] : "");
            var name = rooms[i].name || alias || "Unnamed room";
            guestRead = null;
            guestJoin = null;

            if (rooms[i].world_readable) {
                guestRead = (

World readable

                );
            }
            if (rooms[i].guest_can_join) {
                guestJoin = (

Guests can join

                );
            }

            perms = null;
            if (guestRead || guestJoin) {
                perms =
{guestRead} {guestJoin}
;
            }

            var topic = rooms[i].topic || '';
            topic = linkifyString(sanitizeHtml(topic));

            rows.unshift(

                        <BaseAvatar width={24} height={24} resizeMethod='crop'
                            name={ name } idName={ name }
                            url={ ContentRepo.getHttpUriForMxc(
                                    MatrixClientPeg.get().getHomeserverUrl(),
                                    rooms[i].avatar_url, 24, 24, "crop") } />

{ name }

                        { perms }

{ alias }

                        { rooms[i].num_joined_members }

            );
        }
        return rows;
    },

    onKeyUp: function(ev) {
        this.forceUpdate();
        this.setState({ roomAlias : this.refs.roomAlias.value })
        if (ev.key == "Enter") {
            this.showRoom(this.refs.roomAlias.value);
        }
    },

    render: function() {
        if (this.state.loading) {
            var Loader = sdk.getComponent("elements.Spinner");
            return (

                    <Loader />

            );
        }

        var SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
        return (

                <SimpleRoomHeader title="Directory" />

                    <input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
                    <GeminiScrollbar className="mx_RoomDirectory_tableWrapper">

                                { this.getRows(this.state.roomAlias) }

                    </GeminiScrollbar>

        );
    }
});

<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

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.
*/

'use strict';

var React = require('react');

var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var GeminiScrollbar = require('react-gemini-scrollbar');

var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
var linkifyMatrix = require('matrix-react-sdk/lib/linkify-matrix');
var sanitizeHtml = require('sanitize-html');

linkifyMatrix(linkify);

module.exports = React.createClass({
    displayName: 'RoomDirectory',

    getInitialState: function() {
        return {
            publicRooms: [],
            roomAlias: '',
            loading: true,
        }
    },

    componentDidMount: function() {
        var self = this;
        MatrixClientPeg.get().publicRooms(function (err, data) {
            if (err) {
                self.setState({ loading: false });
                console.error("Failed to get publicRooms: %s", JSON.stringify(err));
                var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                Modal.createDialog(ErrorDialog, {
                    title: "Failed to get public room list",
                    description: err.message
                });
            }
            else {
                self.setState({
                    publicRooms: data.chunk,
                    loading: false,
                });
                self.forceUpdate();
            }
        });
    },

    showRoom: function(roomId) {
        var room;
        for (var i = 0; i < this.state.publicRooms.length; ++i) {
            if (this.state.publicRooms[i].room_id == roomId) {
                room = this.state.publicRooms[i];
                break;
            }
        }
        var oob_data = {};
        if (room) {
            oob_data = {
                avatarUrl: room.avatar_url,
                // XXX: This logic is duplicated from the JS SDK which
                // would normally decide what the name is.
                name: room.name || room.aliases[0],
            };
        }

        dis.dispatch({
            action: 'view_room',
            room_id: roomId,
            oob_data: oob_data,
        });
    },

    getRows: function(filter) {
        var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');

        if (!this.state.publicRooms) return [];

        var rooms = this.state.publicRooms.filter(function(a) {
            // FIXME: if incrementally typing, keep narrowing down the search set
            // incrementally rather than starting over each time.
            return (a.aliases[0].toLowerCase().search(filter.toLowerCase()) >= 0 && a.num_joined_members > 0);
        }).sort(function(a,b) {
            return a.num_joined_members - b.num_joined_members;
        });
        var rows = [];
        var self = this;
        var guestRead, guestJoin, perms;
        for (var i = 0; i < rooms.length; i++) {
            var name = rooms[i].name || rooms[i].aliases[0];
            guestRead = null;
            guestJoin = null;

            if (rooms[i].world_readable) {
                guestRead = (

World readable

                );
            }
            if (rooms[i].guest_can_join) {
                guestJoin = (

Guests can join

                );
            }

            perms = null;
            if (guestRead || guestJoin) {
                perms =
{guestRead} {guestJoin}
;
            }

            var topic = rooms[i].topic || '';
            topic = linkifyString(sanitizeHtml(topic));

            rows.unshift(

                        <BaseAvatar width={24} height={24} resizeMethod='crop'
                            name={ name } idName={ name }
                            url={ ContentRepo.getHttpUriForMxc(
                                    MatrixClientPeg.get().getHomeserverUrl(),
                                    rooms[i].avatar_url, 24, 24, "crop") } />

{ name }

                        { perms }

{ rooms[i].aliases[0] }

                        { rooms[i].num_joined_members }

            );
        }
        return rows;
    },

    onKeyUp: function(ev) {
        this.forceUpdate();
        this.setState({ roomAlias : this.refs.roomAlias.value })
        if (ev.key == "Enter") {
            this.showRoom(this.refs.roomAlias.value);
        }
    },

    render: function() {
        if (this.state.loading) {
            var Loader = sdk.getComponent("elements.Spinner");
            return (

                    <Loader />

            );
        }

        var RoomHeader = sdk.getComponent('rooms.RoomHeader');
        return (

                <RoomHeader simpleHeader="Directory" />

                    <input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
                    <GeminiScrollbar className="mx_RoomDirectory_tableWrapper">

                                { this.getRows(this.state.roomAlias) }

                    </GeminiScrollbar>

        );
    }
});

<commit_msg>Uncommit 71cb04c50ad1b76ac02d537cd096889ecdcc9f0a (I failed to branch)<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

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.
*/

'use strict';

var React = require('react');

var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var GeminiScrollbar = require('react-gemini-scrollbar');

var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
var linkifyMatrix = require('matrix-react-sdk/lib/linkify-matrix');
var sanitizeHtml = require('sanitize-html');

linkifyMatrix(linkify);

module.exports = React.createClass({
    displayName: 'RoomDirectory',

    getInitialState: function() {
        return {
            publicRooms: [],
            roomAlias: '',
            loading: true,
        }
    },

    componentDidMount: function() {
        var self = this;
        MatrixClientPeg.get().publicRooms(function (err, data) {
            if (err) {
                self.setState({ loading: false });
                console.error("Failed to get publicRooms: %s", JSON.stringify(err));
                var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                Modal.createDialog(ErrorDialog, {
                    title: "Failed to get public room list",
                    description: err.message
                });
            }
            else {
                self.setState({
                    publicRooms: data.chunk,
                    loading: false,
                });
                self.forceUpdate();
            }
        });
    },

    showRoom: function(roomId) {
        dis.dispatch({
            action: 'view_room',
            room_id: roomId
        });
    },

    getRows: function(filter) {
        var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');

        if (!this.state.publicRooms) return [];

        var rooms = this.state.publicRooms.filter(function(a) {
            // FIXME: if incrementally typing, keep narrowing down the search set
            // incrementally rather than starting over each time.
            return (a.aliases[0].toLowerCase().search(filter.toLowerCase()) >= 0 && a.num_joined_members > 0);
        }).sort(function(a,b) {
            return a.num_joined_members - b.num_joined_members;
        });
        var rows = [];
        var self = this;
        var guestRead, guestJoin, perms;
        for (var i = 0; i < rooms.length; i++) {
            var name = rooms[i].name || rooms[i].aliases[0];
            guestRead = null;
            guestJoin = null;

            if (rooms[i].world_readable) {
                guestRead = (

World readable

                );
            }
            if (rooms[i].guest_can_join) {
                guestJoin = (

Guests can join

                );
            }

            perms = null;
            if (guestRead || guestJoin) {
                perms =
{guestRead} {guestJoin}
;
            }

            var topic = rooms[i].topic || '';
            topic = linkifyString(sanitizeHtml(topic));

            rows.unshift(

                        <BaseAvatar width={24} height={24} resizeMethod='crop'
                            name={ name } idName={ name }
                            url={ ContentRepo.getHttpUriForMxc(
                                    MatrixClientPeg.get().getHomeserverUrl(),
                                    rooms[i].avatar_url, 24, 24, "crop") } />

{ name }

                        { perms }

{ rooms[i].aliases[0] }

                        { rooms[i].num_joined_members }

            );
        }
        return rows;
    },

    onKeyUp: function(ev) {
        this.forceUpdate();
        this.setState({ roomAlias : this.refs.roomAlias.value })
        if (ev.key == "Enter") {
            this.showRoom(this.refs.roomAlias.value);
        }
    },

    render: function() {
        if (this.state.loading) {
            var Loader = sdk.getComponent("elements.Spinner");
            return (

                    <Loader />

            );
        }

        var RoomHeader = sdk.getComponent('rooms.RoomHeader');
        return (

                <RoomHeader simpleHeader="Directory" />

                    <input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
                    <GeminiScrollbar className="mx_RoomDirectory_tableWrapper">

                                { this.getRows(this.state.roomAlias) }

                    </GeminiScrollbar>

        );
    }
});

<|endoftext|>