<commit_before>/**
 * Created by xubt on 6/17/16.
 */
kanbanApp.directive('card', function ($uibModal) {
    return {
        restrict: 'E',
        templateUrl: 'component/card/partials/card.html',
        replace: true,
        transclude: true,
        scope: {
            card: '=',
            procedure: '='
        },
        controller: ['$scope', 'localStorageService', 'assignmentServices', 'cardsServices', 'acceptanceCriteriaService', 'usersService', 'timerMessageService', function ($scope, localStorageService, assignmentServices, cardsServices, acceptanceCriteriaService, usersService, timerMessageService) {
            var acceptanceCriterias = $scope.card.acceptanceCriterias === undefined ? [] : $scope.card.acceptanceCriterias.acceptanceCriterias;
            var finishedAcceptanceCriteriasCount = 0;
            for (var index in acceptanceCriterias) {
                if (acceptanceCriterias[index].finished === true) {
                    finishedAcceptanceCriteriasCount++;
                }
            }
            $scope.card.finishedAcceptanceCriteriasCount = finishedAcceptanceCriteriasCount;
            $scope.card.totalAcceptanceCriteriasCount = acceptanceCriterias.length;

            $scope.assign = function (_card) {
                var thisScope = $scope;
                $uibModal.open({
                    animation: false,
                    templateUrl: 'component/card/partials/assignment-confirm.html',
                    controller: function ($scope, $uibModalInstance) {
                        $scope.title = '确认信息';
                        if (thisScope.isIamAssigned) {
                            $scope.message = "你确定不再做该卡片吗?";
                            $scope.ok = function () {
                                var userName = usersService.getCurrentUser().userName;
                                var myAssignmentLink;
                                angular.forEach(thisScope.assignments, function (_assignment) {
                                    if (userName === _assignment.assignee) {
                                        myAssignmentLink = _assignment._links.self.href;
                                    }
                                });
                                var assignmentPromise = assignmentServices.giveUp(myAssignmentLink);
                                assignmentPromise.then(function (_data) {
                                    thisScope.loadAssignments();
                                });
                                $uibModalInstance.close();
                            };
                        }
                        else {
                            $scope.message = "你确定要认领该卡片吗?";
                            $scope.ok = function () {
                                var assignment = {
                                    cardId: _card.id,
                                    assignee: usersService.getCurrentUser().userName,
                                    assigner: usersService.getCurrentUser().userName
                                };

                                var assignmentPromise = assignmentServices.assign(assignment, _card._links.assignments.href);
                                assignmentPromise.then(function (_data) {
                                    thisScope.loadAssignments();
                                });
                                $uibModalInstance.close();
                            };
                        }
                        $scope.cancel = function () {
                            $uibModalInstance.dismiss('cancel');
                        };
                    },
                    size: 'sm'
                });
            };

            var cardScope = $scope;
            $scope.openCardConfiguration = function () {
                $uibModal.open({
                    animation: true,
                    templateUrl: 'component/card/partials/card-configuration.html',
                    controller: ['$scope', 'teamsService', 'timerMessageService', '$uibModalInstance',
                        function ($scope, teamsService, timerMessageService, $uibModalInstance) {
                            $scope.card = cardScope.card;
                            $scope.cardSaveButton = "保存";
                            $scope.procedure = cardScope.procedure;
                            $scope.saveCard = function () {
                                $scope.cardSaveButton = "保存中..";
                                $scope.isDisableCardSaveButton = true;
                                var cardPromise = cardsServices.update($scope.card);
                                cardPromise.then(function (_card) {
                                    timerMessageService.message("配置已经更新");
                                    _card.tags = cardScope.card.tags;
                                    cardScope.card = _card;
                                    $scope.card = _card;

                                }).finally(function () {
                                    $scope.cardSaveButton = "保存";
                                    $scope.isDisableCardSaveButton = false;
                                });
                            };
                            $scope.cancel = function () {
                                $uibModalInstance.dismiss('cancel');
                            };
                        }],
                    size: 'mid',
                    backdrop: "static"
                });
            };
            $scope.updateCard = function (_summary, _card) {
                if (_summary === "") {
                    return "卡片描述不能为空";
                }
                var card = _card;
                card.summary = _summary;
                var cardPromise = cardsServices.update(card);
                cardPromise.then(function () {
                });
            };
            $scope.openDeleteModal = function (_message, _link) {
                var currentScope = $scope;
                $uibModal.open({
                    animation: false,
                    templateUrl: 'foundation/modal/partials/confirm-dialog.html',
                    controller: function ($scope, $uibModalInstance) {
                        $scope.title = '警告';
                        $scope.message = "确定要删除" + _message + "吗?";
                        $scope.ok = function () {
                            cardsServices.deleteByLink(_link).then(function () {
                                currentScope.$parent.removeCard(currentScope.card);
                                timerMessageService.message("卡片已经删除。");
                            });
                            $uibModalInstance.close();
                        };
                        $scope.cancel = function () {
                            $uibModalInstance.dismiss('cancel');
                        };
                    },
                    size: 'sm',
                    backdrop: "static"
                });
            };

            $scope.initAssignmentStatus = function () {
                var userName = usersService.getCurrentUser().userName;
                $scope.isIamAssigned = false;
                angular.forEach($scope.assignments, function (_assignment) {
                    if (userName === _assignment.assignee) {
                        $scope.isIamAssigned = true;
                    }
                });
                $scope.assignTip = $scope.isIamAssigned === true ? "我不做了" : "认领";
                $scope.assignIco = $scope.isIamAssigned === true ? "heart" : "heart-empty";

                $scope.menuOptions = [
                    ['' + $scope.assignTip, function ($itemScope) {
                        console.log("Assign");
                        $itemScope.assign($itemScope.card);
                    }],
                    null,
                    ['删除', function ($itemScope) {
                        console.log("Delete");
                        $itemScope.openDeleteModal($itemScope.card.summary, $itemScope.card._links.self.href);
                    }]
                ];
            };
            $scope.calculateWidth = function (_totalAcceptanceCriteriasCount) {
                if (_totalAcceptanceCriteriasCount === 0) {
                    return 0;
                }
                var width = (100 / _totalAcceptanceCriteriasCount) - 1;
                return (width.toFixed(2) + "%");
            };

            $scope.initAssignmentStatus();
        }]
    };
});

<commit_msg>Fix assignment status bug.<commit_after>/**
 * Created by xubt on 6/17/16.
 */
kanbanApp.directive('card', function ($uibModal) {
    return {
        restrict: 'E',
        templateUrl: 'component/card/partials/card.html',
        replace: true,
        transclude: true,
        scope: {
            card: '=',
            procedure: '='
        },
        controller: ['$scope', 'localStorageService', 'assignmentServices', 'cardsServices', 'acceptanceCriteriaService', 'usersService', 'timerMessageService', function ($scope, localStorageService, assignmentServices, cardsServices, acceptanceCriteriaService, usersService, timerMessageService) {
            var acceptanceCriterias = $scope.card.acceptanceCriterias === undefined ? [] : $scope.card.acceptanceCriterias.acceptanceCriterias;
            var finishedAcceptanceCriteriasCount = 0;
            for (var index in acceptanceCriterias) {
                if (acceptanceCriterias[index].finished === true) {
                    finishedAcceptanceCriteriasCount++;
                }
            }
            $scope.card.finishedAcceptanceCriteriasCount = finishedAcceptanceCriteriasCount;
            $scope.card.totalAcceptanceCriteriasCount = acceptanceCriterias.length;

            $scope.assign = function (_card) {
                var thisScope = $scope;
                $uibModal.open({
                    animation: false,
                    templateUrl: 'component/card/partials/assignment-confirm.html',
                    controller: function ($scope, $uibModalInstance) {
                        $scope.title = '确认信息';
                        if (thisScope.isIamAssigned) {
                            $scope.message = "你确定不再做该卡片吗?";
                            $scope.ok = function () {
                                var userName = usersService.getCurrentUser().userName;
                                var myAssignmentLink;
                                angular.forEach(thisScope.assignments, function (_assignment) {
                                    if (userName === _assignment.assignee) {
                                        myAssignmentLink = _assignment._links.self.href;
                                    }
                                });
                                var assignmentPromise = assignmentServices.giveUp(myAssignmentLink);
                                assignmentPromise.then(function (_data) {
                                    var index = thisScope.assignments.indexOf(_data);
                                    thisScope.assignments.splice(index, 1);
                                    thisScope.initAssignmentStatus();
                                });
                                $uibModalInstance.close();
                            };
                        }
                        else {
                            $scope.message = "你确定要认领该卡片吗?";
                            $scope.ok = function () {
                                var assignment = {
                                    cardId: _card.id,
                                    assignee: usersService.getCurrentUser().userName,
                                    assigner: usersService.getCurrentUser().userName
                                };

                                var assignmentPromise = assignmentServices.assign(assignment, _card._links.assignments.href);
                                assignmentPromise.then(function (_data) {
                                    thisScope.assignments.push(_data);
                                    thisScope.initAssignmentStatus();
                                });
                                $uibModalInstance.close();
                            };
                        }
                        $scope.cancel = function () {
                            $uibModalInstance.dismiss('cancel');
                        };
                    },
                    size: 'sm'
                });
            };

            var cardScope = $scope;
            $scope.openCardConfiguration = function () {
                $uibModal.open({
                    animation: true,
                    templateUrl: 'component/card/partials/card-configuration.html',
                    controller: ['$scope', 'teamsService', 'timerMessageService', '$uibModalInstance',
                        function ($scope, teamsService, timerMessageService, $uibModalInstance) {
                            $scope.card = cardScope.card;
                            $scope.cardSaveButton = "保存";
                            $scope.procedure = cardScope.procedure;
                            $scope.saveCard = function () {
                                $scope.cardSaveButton = "保存中..";
                                $scope.isDisableCardSaveButton = true;
                                var cardPromise = cardsServices.update($scope.card);
                                cardPromise.then(function (_card) {
                                    timerMessageService.message("配置已经更新");
                                    _card.tags = cardScope.card.tags;
                                    cardScope.card = _card;
                                    $scope.card = _card;

                                }).finally(function () {
                                    $scope.cardSaveButton = "保存";
                                    $scope.isDisableCardSaveButton = false;
                                });
                            };
                            $scope.cancel = function () {
                                $uibModalInstance.dismiss('cancel');
                            };
                        }],
                    size: 'mid',
                    backdrop: "static"
                });
            };
            $scope.updateCard = function (_summary, _card) {
                if (_summary === "") {
                    return "卡片描述不能为空";
                }
                var card = _card;
                card.summary = _summary;
                var cardPromise = cardsServices.update(card);
                cardPromise.then(function () {
                });
            };
            $scope.openDeleteModal = function (_message, _link) {
                var currentScope = $scope;
                $uibModal.open({
                    animation: false,
                    templateUrl: 'foundation/modal/partials/confirm-dialog.html',
                    controller: function ($scope, $uibModalInstance) {
                        $scope.title = '警告';
                        $scope.message = "确定要删除" + _message + "吗?";
                        $scope.ok = function () {
                            cardsServices.deleteByLink(_link).then(function () {
                                currentScope.$parent.removeCard(currentScope.card);
                                timerMessageService.message("卡片已经删除。");
                            });
                            $uibModalInstance.close();
                        };
                        $scope.cancel = function () {
                            $uibModalInstance.dismiss('cancel');
                        };
                    },
                    size: 'sm',
                    backdrop: "static"
                });
            };

            $scope.initAssignmentStatus = function () {
                var userName = usersService.getCurrentUser().userName;
                $scope.isIamAssigned = false;
                angular.forEach($scope.assignments, function (_assignment) {
                    if (userName === _assignment.assignee) {
                        $scope.isIamAssigned = true;
                    }
                });
                $scope.assignTip = $scope.isIamAssigned === true ? "我不做了" : "认领";
                $scope.assignIco = $scope.isIamAssigned === true ? "heart" : "heart-empty";

                $scope.menuOptions = [
                    ['' + $scope.assignTip, function ($itemScope) {
                        console.log("Assign");
                        $itemScope.assign($itemScope.card);
                    }],
                    null,
                    ['删除', function ($itemScope) {
                        console.log("Delete");
                        $itemScope.openDeleteModal($itemScope.card.summary, $itemScope.card._links.self.href);
                    }]
                ];
            };
            $scope.calculateWidth = function (_totalAcceptanceCriteriasCount) {
                if (_totalAcceptanceCriteriasCount === 0) {
                    return 0;
                }
                var width = (100 / _totalAcceptanceCriteriasCount) - 1;
                return (width.toFixed(2) + "%");
            };

            $scope.initAssignmentStatus();
        }]
    };
});

<|endoftext|>


<commit_before>/*global define,window*/
/*jslint white:true,browser:true*/
/**
 * Uses the user's login information to initialize the IPython environment.
 * This should be one of the very first functions to be run on the page, as it sets up
 * the login widget, and wires the environment together.
 * @author Bill Riehl wjriehl@lbl.gov
 */
define ([
    'jquery',
    'bluebird',
    'kbapi',
    'base/js/utils',
    'narrativeConfig',
    'api/auth',
    'userMenu',
    'util/bootstrapDialog'
], function(
    $,
    Promise,
    kbapi,
    JupyterUtils,
    Config,
    Auth,
    UserMenu,
    BootstrapDialog
) {
    'use strict';
    var baseUrl = JupyterUtils.get_body_data('baseUrl'),
        cookieName = Config.get('auth_cookie'),
        authClient = Auth.make({url: Config.url('auth')}),
        sessionInfo = null;

    /* set the auth token by calling the kernel execute method on a function in
     * the magics module
     */
    function ipythonLogin(token) {
        window.kb = new KBCacheClient(token);
        $.ajax({
            url: JupyterUtils.url_join_encode(baseUrl, 'login')
        }).then(
            function(ret) {
                // console.log(ret);
            }
        ).fail(
            function(err) {
                // console.err(err);
            }
        );
    }

    function ipythonLogout() {
        $.ajax({
            url: JupyterUtils.url_join_encode(baseUrl, 'logout')
        }).then(
            function(ret) {
                // console.log(ret);
            }
        ).fail(
            function(err) {
                // console.err(err);
            }
        );
        window.location.href = '/';
    }

    function showNotLoggedInDialog() {
        var dialog = new BootstrapDialog({
            'title': 'Not Logged In',
            'body': $('
').append('You are not logged in (or your session has expired), and you will be redirected to the sign in page shortly.'),
            'buttons': [$('')
                        .append('OK')
                        .click(function () {
                            dialog.hide();
                        })]
        });
        dialog.show();
    }

    function initEvents() {
        $(document).on('loggedInQuery.kbase', function(e, callback) {
            if (callback) {
                callback(sessionInfo);
            }
        });

        $(document).on('logout.kbase', function() {
            alert('Thanks for using KBase!');
            ipythonLogout();
        });
    }

    function init($elem) {
        /* Flow.
         * 1. Get cookie. If present and valid, yay. If not, dialog / redirect to login page.
         * 2. Setup event triggers. need loggedInQuery.kbase, promptForLogin.kbase, logout.kbase,
         * 3. events to trigger: loggedIn, loggedInFailure, loggedOut
         * 4. Set up user widget thing on #signin-button
         */
        var sessionToken = $.cookie(cookieName);
        return Promise.all([authClient.getTokenInfo(sessionToken), authClient.getUserProfile(sessionToken)])
            .then(function(results) {
                var tokenInfo = results[0];
                sessionInfo = tokenInfo;
                this.sessionInfo = tokenInfo;
                this.sessionInfo.token = sessionToken;
                this.sessionInfo.kbase_sessionid = this.sessionInfo.id;
                initEvents();
                UserMenu.make({
                    target: $elem,
                    token: sessionToken,
                    userName: sessionInfo.user,
                    email: results[1].email,
                    displayName: results[1].display
                });
                ipythonLogin(sessionToken);
                $(document).trigger('loggedIn', this.sessionInfo);
                $(document).trigger('loggedIn.kbase', this.sessionInfo);
            }.bind(this))
            .catch(function(error) {
                showNotLoggedInDialog();
            });
    }

    return {
        init: init,
        sessionInfo: sessionInfo
    };
});
<commit_msg>added about-to-expire dialog<commit_after>/*global define,window*/
/*jslint white:true,browser:true*/
/**
 * Uses the user's login information to initialize the IPython environment.
 * This should be one of the very first functions to be run on the page, as it sets up
 * the login widget, and wires the environment together.
 * @author Bill Riehl wjriehl@lbl.gov
 */
define ([
    'jquery',
    'bluebird',
    'kbapi',
    'base/js/utils',
    'narrativeConfig',
    'api/auth',
    'userMenu',
    'util/bootstrapDialog'
], function(
    $,
    Promise,
    kbapi,
    JupyterUtils,
    Config,
    Auth,
    UserMenu,
    BootstrapDialog
) {
    'use strict';
    var baseUrl = JupyterUtils.get_body_data('baseUrl'),
        cookieName = Config.get('auth_cookie'),
        authClient = Auth.make({url: Config.url('auth')}),
        sessionInfo = null;

    /* set the auth token by calling the kernel execute method on a function in
     * the magics module
     */
    function ipythonLogin(token) {
        window.kb = new KBCacheClient(token);
        $.ajax({
            url: JupyterUtils.url_join_encode(baseUrl, 'login')
        }).then(
            function(ret) {
                // console.log(ret);
            }
        ).fail(
            function(err) {
                // console.err(err);
            }
        );
    }

    function ipythonLogout() {
        $.ajax({
            url: JupyterUtils.url_join_encode(baseUrl, 'logout')
        }).then(
            function(ret) {
                // console.log(ret);
            }
        ).fail(
            function(err) {
                // console.err(err);
            }
        );
        window.location.href = '/';
    }

    function showNotLoggedInDialog() {
        var dialog = new BootstrapDialog({
            'title': 'Not Logged In',
            'body': $('
').append('You are not logged in (or your session has expired), and you will be redirected to the sign in page shortly.'),
            'buttons': [$('')
                        .append('OK')
                        .click(function () {
                            dialog.hide();
                        })]
        });
        dialog.show();
    }

    function showAboutToLogoutDialog() {
        var dialog = new BootstrapDialog({
            'title': 'Expiring session',
            'body': $('
').append('Your authenticated KBase session will expire in approximately 5 minutes. To continue using KBase, we suggest you log out and back in.'),
            'buttons': [$('')
                        .append('OK')
                        .click(function () {
                            dialog.hide();
                        })]
        });
        dialog.show();
    }

    function initEvents() {
        $(document).on('loggedInQuery.kbase', function(e, callback) {
            if (callback) {
                callback(sessionInfo);
            }
        });

        $(document).on('logout.kbase', function() {
            alert('Thanks for using KBase!');
            ipythonLogout();
        });
    }

    function init($elem) {
        /* Flow.
         * 1. Get cookie. If present and valid, yay. If not, dialog / redirect to login page.
         * 2. Setup event triggers. need loggedInQuery.kbase, promptForLogin.kbase, logout.kbase,
         * 3. events to trigger: loggedIn, loggedInFailure, loggedOut
         * 4. Set up user widget thing on #signin-button
         */
        showAboutToLogoutDialog();
        var sessionToken = $.cookie(cookieName);
        return Promise.all([authClient.getTokenInfo(sessionToken), authClient.getUserProfile(sessionToken)])
            .then(function(results) {
                var tokenInfo = results[0];
                sessionInfo = tokenInfo;
                this.sessionInfo = tokenInfo;
                this.sessionInfo.token = sessionToken;
                this.sessionInfo.kbase_sessionid = this.sessionInfo.id;
                initEvents();
                UserMenu.make({
                    target: $elem,
                    token: sessionToken,
                    userName: sessionInfo.user,
                    email: results[1].email,
                    displayName: results[1].display
                });
                ipythonLogin(sessionToken);
                $(document).trigger('loggedIn', this.sessionInfo);
                $(document).trigger('loggedIn.kbase', this.sessionInfo);
            }.bind(this))
            .catch(function(error) {
                showNotLoggedInDialog();
            });
    }

    return {
        init: init,
        sessionInfo: sessionInfo
    };
});
<|endoftext|>


<commit_before>/**
 * https://github.com/timonreinhard/wemo-client
 */
var Wemo = require('wemo-client');
var wemo = new Wemo();

var LIGHT_DIMMABLE = "dimmableLight";
var devices = [];

exports.init = function(listener) {
    console.log("Starts initiating wemo plugin");
    wemo.discover(function(deviceInfo) {
        var client = wemo.client(deviceInfo);
        var modelName = deviceInfo.modelName;
        if(modelName === "Bridge") {
            client.getEndDevices(function(err, data){
                devices = devices.concat(loadDevices(data, client));
                console.log("Wemo plugin initiated with " + devices.length + " devices");
            });
        } else if(modelName === "Socket") {
            devices.push(registerSocket(deviceInfo, client, listener));
            console.log("Wemo plugin initiated with " + devices.length + " devices");
        } else if(modelName === "Sensor") {
            devices.push(registerSensor(deviceInfo, client, listener));
            console.log("Wemo plugin initiated with " + devices.length + " devices");
        } else {
            console.log("Unable to handle device with name: " + modelName);
        }
    });
};

function loadDevices(devices, client) {
    return devices.map(function(device) {
        if(device.deviceType === LIGHT_DIMMABLE) {
            return registerLight(device, client);
        }
    });
}

function registerLight(device, client) {
    return {
        id: device.deviceId,
        name: device.friendlyName,
        type: 'light',
        enabled: device.capabilities['10006'] === "1",
        brightness: device.capabilities['10008'],
        setEnabled: function(enabled, cb) {
            var enabledValue = enabled ? 1 : 0;
            var device = this;
            client.setDeviceStatus(this.id, 10006, enabledValue, function(err, resp) {
                device.enabled = enabled;
                cb();
            });
        },
        setBrightness: function(value, cb) {
            var device = this;
            if(value < 0 || value > 255) {
                console.log(value + " is not between 0 or 255");
                return;
            }
            client.setDeviceStatus(this.id, 10008, value, function(err, resp) {
                device.brightness = value;
                device.enabled = value !== "0";
                cb();
            });
        }
    }
}

function registerSocket(deviceInfo, client, listener) {
    var device = {
        id: deviceInfo.serialNumber,
        name: deviceInfo.friendlyName,
        type: 'socket',
        enabled: deviceInfo.binaryState === '1',
        setEnabled: function(enabled, cb) {
            var enabledValue = enabled ? 1 : 0;
            var device = this;
            client.setBinaryState(enabledValue, function(err, response) {
                if(!err) {
                    device.enabled = enabled;
                    cb();
                } else {
                    console.log(err);
                }
            });
        }
    };
    client.on('binaryState', function(value) {
        device.enabled = value === '1';
        listener(device);
    });
    return device;
}

function registerSensor(deviceInfo, client, listener) {
    var device = {
        id: deviceInfo.serialNumber,
        name: deviceInfo.friendlyName,
        type: 'sensor',
        enabled: deviceInfo.binaryState === '1'
    };
    client.on('binaryState', function(value) {
        var enabled = value === '1';
        if(device.enabled != enabled) {
            listener(device);
        }
        device.enabled = enabled;
    });
    return device;
}

exports.getDevices = function () {
    return devices;
};
<commit_msg>Change state before notifying<commit_after>/**
 * https://github.com/timonreinhard/wemo-client
 */
var Wemo = require('wemo-client');
var wemo = new Wemo();

var LIGHT_DIMMABLE = "dimmableLight";
var devices = [];

exports.init = function(listener) {
    console.log("Starts initiating wemo plugin");
    wemo.discover(function(deviceInfo) {
        var client = wemo.client(deviceInfo);
        var modelName = deviceInfo.modelName;
        if(modelName === "Bridge") {
            client.getEndDevices(function(err, data){
                devices = devices.concat(loadDevices(data, client));
                console.log("Wemo plugin initiated with " + devices.length + " devices");
            });
        } else if(modelName === "Socket") {
            devices.push(registerSocket(deviceInfo, client, listener));
            console.log("Wemo plugin initiated with " + devices.length + " devices");
        } else if(modelName === "Sensor") {
            devices.push(registerSensor(deviceInfo, client, listener));
            console.log("Wemo plugin initiated with " + devices.length + " devices");
        } else {
            console.log("Unable to handle device with name: " + modelName);
        }
    });
};

function loadDevices(devices, client) {
    return devices.map(function(device) {
        if(device.deviceType === LIGHT_DIMMABLE) {
            return registerLight(device, client);
        }
    });
}

function registerLight(device, client) {
    return {
        id: device.deviceId,
        name: device.friendlyName,
        type: 'light',
        enabled: device.capabilities['10006'] === "1",
        brightness: device.capabilities['10008'],
        setEnabled: function(enabled, cb) {
            var enabledValue = enabled ? 1 : 0;
            var device = this;
            client.setDeviceStatus(this.id, 10006, enabledValue, function(err, resp) {
                device.enabled = enabled;
                cb();
            });
        },
        setBrightness: function(value, cb) {
            var device = this;
            if(value < 0 || value > 255) {
                console.log(value + " is not between 0 or 255");
                return;
            }
            client.setDeviceStatus(this.id, 10008, value, function(err, resp) {
                device.brightness = value;
                device.enabled = value !== "0";
                cb();
            });
        }
    }
}

function registerSocket(deviceInfo, client, listener) {
    var device = {
        id: deviceInfo.serialNumber,
        name: deviceInfo.friendlyName,
        type: 'socket',
        enabled: deviceInfo.binaryState === '1',
        setEnabled: function(enabled, cb) {
            var enabledValue = enabled ? 1 : 0;
            var device = this;
            client.setBinaryState(enabledValue, function(err, response) {
                if(!err) {
                    device.enabled = enabled;
                    cb();
                } else {
                    console.log(err);
                }
            });
        }
    };
    client.on('binaryState', function(value) {
        device.enabled = value === '1';
        listener(device);
    });
    return device;
}

function registerSensor(deviceInfo, client, listener) {
    var device = {
        id: deviceInfo.serialNumber,
        name: deviceInfo.friendlyName,
        type: 'sensor',
        enabled: deviceInfo.binaryState === '1'
    };
    client.on('binaryState', function(value) {
        var enabled = value === '1';
        var changed = device.enabled != enabled;

        device.enabled = enabled;
        if(changed) {
            listener(device);
        }
    });
    return device;
}

exports.getDevices = function () {
    return devices;
};
<|endoftext|>


<commit_before>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

/**
 * Base class for managing window menus whose HTML code is in templates/index.html.
 */

function WindowMenu(title, extra_class) {
    // Allow hierarchy
    if (arguments.length == 0)
        return;

    this.childWindow = null;
    this.htmlElement = document.createElement('div');  // create the root HTML element
    Element.extend(this.htmlElement);
    this.htmlElement.className = "window_menu";
    if (extra_class != null) {
        this.htmlElement.addClassName(extra_class);
    }

    // Window Top
    this.windowTop = document.createElement('div');
    this.windowTop.className = "window_top";
    this.htmlElement.appendChild(this.windowTop);

    this._closeListener = this._closeListener.bind(this);
    this.closeButton = new StyledElements.StyledButton({
        'class': "closebutton",
        'plain': true
    });
    this.closeButton.insertInto(this.windowTop);
    this.closeButton.addEventListener("click", this._closeListener);

    this.titleElement = document.createElement('div');
    Element.extend(this.titleElement);
    this.titleElement.className = "window_title";
    this.windowTop.appendChild(this.titleElement);

    var clearer = document.createElement('div');
    Element.extend(clearer);
    clearer.addClassName("floatclearer");
    this.windowTop.appendChild(clearer);

    // Window Content
    this.windowContent = document.createElement('div');
    Element.extend(this.windowContent);
    this.windowContent.className = "window_content";
    this.htmlElement.appendChild(this.windowContent);

    this.msgElement = document.createElement('div');
    Element.extend(this.msgElement);
    this.msgElement.className = "msg";
    this.windowContent.appendChild(this.msgElement);

    // Window Bottom
    this.windowBottom = document.createElement('div');
    Element.extend(this.windowBottom);
    this.windowBottom.className = "window_bottom";
    this.htmlElement.appendChild(this.windowBottom);

    // Initial title
    this.setTitle(title);

    // Make draggable
    this.makeDraggable();
}

/**
 * Make Draggable.
 */
WindowMenu.prototype.makeDraggable = function makeDraggable() {
    this.draggable = new Draggable(this.windowTop, {window_menu: this},
        function onStart(draggable, context) {
            var position;
            context.y = context.window_menu.htmlElement.style.top === "" ? 0 : parseInt(context.window_menu.htmlElement.style.top, 10);
            context.x = context.window_menu.htmlElement.style.left === "" ? 0 : parseInt(context.window_menu.htmlElement.style.left, 10);
        },
        function onDrag(e, draggable, context, xDelta, yDelta) {
            context.window_menu.setPosition({posX: context.x + xDelta, posY: context.y + yDelta});
        },
        function onFinish(draggable, context) {
            var position = context.window_menu.getStylePosition();
            if (position.posX < 0) {
                position.posX = 8;
            }
            if (position.posY < 0) {
                position.posY = 8;
            }
            context.window_menu.setPosition(position);
        },
        function () { return true; }
    );
};

/**
 * set position.
 */
WindowMenu.prototype.setPosition = function setPosition(coordinates) {
    this.htmlElement.style.left = coordinates.posX + 'px';
    this.htmlElement.style.top = coordinates.posY + 'px';
};

/**
 * get style position.
 */
WindowMenu.prototype.getStylePosition = function getStylePosition() {
    return {
        posX: parseInt(this.htmlElement.style.left, 10),
        posY: parseInt(this.htmlElement.style.top, 10)
    };
};

WindowMenu.prototype.setTitle = function setTitle(title) {
    this.titleElement.setTextContent(title);
};

/**
 * @private
 *
 * Click Listener for the close button.
 */
WindowMenu.prototype._closeListener = function(e) {
    this.hide();
}

/**
 * Updates the message displayed by this WindowMenu
 */
WindowMenu.prototype.setMsg = function (msg) {
    this.msgElement.setTextContent(msg);

    if (isElement(this.htmlElement.parentNode)) {
        this.calculatePosition();
    }
}

/**
 * @private
 *
 * Calculates a usable absolute position for the window
 */
WindowMenu.prototype.calculatePosition = function() {
    var coordenates = [];

    var windowHeight = BrowserUtilsFactory.getInstance().getHeight();
    var windowWidth = BrowserUtilsFactory.getInstance().getWidth();

    this.htmlElement.setStyle({'max-height' : 'none'});
    var menuHeight = this.htmlElement.getHeight();
    var menuWidth = this.htmlElement.getWidth();

    if (menuWidth > windowWidth/2) {
        menuWidth = windowWidth/2; //IE6 hack
        this.htmlElement.setStyle({'width': menuWidth+'px'});
    }

    coordenates[1] = windowHeight/2 - menuHeight/2;
    coordenates[0] = windowWidth/2 - menuWidth/2;

    if (windowHeight < menuHeight) {
        var windowStyle = document.defaultView.getComputedStyle(this.htmlElement, null);

        var padding;
        padding = windowStyle.getPropertyCSSValue("padding-top").
                  getFloatValue(CSSPrimitiveValue.CSS_PX);
        padding+= windowStyle.getPropertyCSSValue("padding-bottom").
                  getFloatValue(CSSPrimitiveValue.CSS_PX);

        this.htmlElement.setStyle({'max-height': windowHeight - padding + 'px',
                                   'top': '0px'});
    } else {
        this.htmlElement.style.top = coordenates[1]+"px";
    }
    this.htmlElement.style.left = coordenates[0]+"px";

    if (this.childWindow != null) {
        this.childWindow.calculatePosition();
    }
}

/**
 *
 */
WindowMenu.prototype.setHandler = function (handler) {
    this.operationHandler = handler;
}

/**
 * Makes this WindowMenu visible.
 *
 * @param parentWindow
 */
WindowMenu.prototype.show = function (parentWindow) {
    this._parentWindowMenu = parentWindow;

    if (this._parentWindowMenu != null) {
        this._parentWindowMenu._addChildWindow(this);
    } else {
        LayoutManagerFactory.getInstance()._showWindowMenu(this);
    }

    document.body.appendChild(this.htmlElement);
    this.calculatePosition();
    this.htmlElement.style.display = "block";
    this.setFocus();
}

/**
 * Makes this WindowMenu hidden.
 */
WindowMenu.prototype.hide = function () {
    if (!isElement(this.htmlElement.parentNode)) {
        // This windowmenu is currently hidden => Nothing to do
        return;
    }

    this.htmlElement.parentNode.removeChild(this.htmlElement);
    if (this.msgElement != null) {
        this.msgElement.update();
    }
    if (this.childWindow != null) {
        this.childWindow.hide();
    }

    if (this._parentWindowMenu != null) {
        this._parentWindowMenu._removeChildWindow(this);
        this._parentWindowMenu = null;
    } else {
        LayoutManagerFactory.getInstance().hideCover();
    }
}

WindowMenu.prototype._addChildWindow = function (windowMenu) {
    if (windowMenu !== this) {
        this.childWindow = windowMenu;
    } else {
        throw TypeError('Window menus cannot be its own child');
    }
};

WindowMenu.prototype._removeChildWindow = function (windowMenu) {
    if (this.childWindow === windowMenu) {
        this.childWindow = null;
    }
};

WindowMenu.prototype.setFocus = function () {
}

/**
 * Specific class for platform preferences windows.
 *
 * @param manager
 *
 * @author jmostazo-upm
 */
function PreferencesWindowMenu(scope, manager) {
    WindowMenu.call(this, '');

    this.manager = manager;
    var table = manager.getPreferencesDef().getInterface();
    this.windowContent.insertBefore(table, this.msgElement);

    // Accept button
    this.acceptButton = new StyledElements.StyledButton({
        text: gettext('Save'),
        'class': 'btn-primary'
    });
    this._executeOperation = this._executeOperation.bind(this);
    this.acceptButton.addEventListener("click", this._executeOperation);
    this.acceptButton.insertInto(this.windowBottom);

    // Cancel button
    this.cancelButton = new StyledElements.StyledButton({
        text: gettext('Cancel')
    });

    Element.extend(this.cancelButton);
    this.cancelButton.addEventListener("click", this._closeListener);
    this.cancelButton.insertInto(this.windowBottom);
}
PreferencesWindowMenu.prototype = new WindowMenu();

PreferencesWindowMenu.prototype.setCancelable = function(cancelable) {
    this.closeButton.setDisabled(!cancelable);
    if (cancelable === true) {
        this.cancelButton.enable();
    } else {
        this.cancelButton.disable();
    }
};

PreferencesWindowMenu.prototype._executeOperation = function() {
    // Validate input fields
    var validationManager = new ValidationErrorManager();
    for (var fieldId in this.fields)
        validationManager.validate(this.fields[fieldId].inputInterface);

    // Build Error Message
    var errorMsg = validationManager.toHTML();

    // Show error message if needed
    if (errorMsg != "") {
        this.setMsg(errorMsg);
    } else {
        this.manager.save();
        this.hide();
    }
}

PreferencesWindowMenu.prototype.show = function (parentWindow) {
    this.setTitle(this.manager.buildTitle());
    this.manager.resetInterface('platform');
    WindowMenu.prototype.show.call(this, parentWindow);
}
<commit_msg>Remove close button of window menues<commit_after>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

/**
 * Base class for managing window menus whose HTML code is in templates/index.html.
 */

function WindowMenu(title, extra_class) {
    // Allow hierarchy
    if (arguments.length == 0)
        return;

    this.childWindow = null;
    this.htmlElement = document.createElement('div');  // create the root HTML element
    Element.extend(this.htmlElement);
    this.htmlElement.className = "window_menu";
    if (extra_class != null) {
        this.htmlElement.addClassName(extra_class);
    }

    // Window Top
    this.windowTop = document.createElement('div');
    this.windowTop.className = "window_top";
    this.htmlElement.appendChild(this.windowTop);

    this._closeListener = this._closeListener.bind(this);

    this.titleElement = document.createElement('div');
    Element.extend(this.titleElement);
    this.titleElement.className = "window_title";
    this.windowTop.appendChild(this.titleElement);

    var clearer = document.createElement('div');
    Element.extend(clearer);
    clearer.addClassName("floatclearer");
    this.windowTop.appendChild(clearer);

    // Window Content
    this.windowContent = document.createElement('div');
    Element.extend(this.windowContent);
    this.windowContent.className = "window_content";
    this.htmlElement.appendChild(this.windowContent);

    this.msgElement = document.createElement('div');
    Element.extend(this.msgElement);
    this.msgElement.className = "msg";
    this.windowContent.appendChild(this.msgElement);

    // Window Bottom
    this.windowBottom = document.createElement('div');
    Element.extend(this.windowBottom);
    this.windowBottom.className = "window_bottom";
    this.htmlElement.appendChild(this.windowBottom);

    // Initial title
    this.setTitle(title);

    // Make draggable
    this.makeDraggable();
}

/**
 * Make Draggable.
 */
WindowMenu.prototype.makeDraggable = function makeDraggable() {
    this.draggable = new Draggable(this.windowTop, {window_menu: this},
        function onStart(draggable, context) {
            var position;
            context.y = context.window_menu.htmlElement.style.top === "" ? 0 : parseInt(context.window_menu.htmlElement.style.top, 10);
            context.x = context.window_menu.htmlElement.style.left === "" ? 0 : parseInt(context.window_menu.htmlElement.style.left, 10);
        },
        function onDrag(e, draggable, context, xDelta, yDelta) {
            context.window_menu.setPosition({posX: context.x + xDelta, posY: context.y + yDelta});
        },
        function onFinish(draggable, context) {
            var position = context.window_menu.getStylePosition();
            if (position.posX < 0) {
                position.posX = 8;
            }
            if (position.posY < 0) {
                position.posY = 8;
            }
            context.window_menu.setPosition(position);
        },
        function () { return true; }
    );
};

/**
 * set position.
 */
WindowMenu.prototype.setPosition = function setPosition(coordinates) {
    this.htmlElement.style.left = coordinates.posX + 'px';
    this.htmlElement.style.top = coordinates.posY + 'px';
};

/**
 * get style position.
 */
WindowMenu.prototype.getStylePosition = function getStylePosition() {
    return {
        posX: parseInt(this.htmlElement.style.left, 10),
        posY: parseInt(this.htmlElement.style.top, 10)
    };
};

WindowMenu.prototype.setTitle = function setTitle(title) {
    this.titleElement.setTextContent(title);
};

/**
 * @private
 *
 * Click Listener for the close button.
 */
WindowMenu.prototype._closeListener = function(e) {
    this.hide();
}

/**
 * Updates the message displayed by this WindowMenu
 */
WindowMenu.prototype.setMsg = function (msg) {
    this.msgElement.setTextContent(msg);

    if (isElement(this.htmlElement.parentNode)) {
        this.calculatePosition();
    }
}

/**
 * @private
 *
 * Calculates a usable absolute position for the window
 */
WindowMenu.prototype.calculatePosition = function() {
    var coordenates = [];

    var windowHeight = BrowserUtilsFactory.getInstance().getHeight();
    var windowWidth = BrowserUtilsFactory.getInstance().getWidth();

    this.htmlElement.setStyle({'max-height' : 'none'});
    var menuHeight = this.htmlElement.getHeight();
    var menuWidth = this.htmlElement.getWidth();

    if (menuWidth > windowWidth/2) {
        menuWidth = windowWidth/2; //IE6 hack
        this.htmlElement.setStyle({'width': menuWidth+'px'});
    }

    coordenates[1] = windowHeight/2 - menuHeight/2;
    coordenates[0] = windowWidth/2 - menuWidth/2;

    if (windowHeight < menuHeight) {
        var windowStyle = document.defaultView.getComputedStyle(this.htmlElement, null);

        var padding;
        padding = windowStyle.getPropertyCSSValue("padding-top").
                  getFloatValue(CSSPrimitiveValue.CSS_PX);
        padding+= windowStyle.getPropertyCSSValue("padding-bottom").
                  getFloatValue(CSSPrimitiveValue.CSS_PX);

        this.htmlElement.setStyle({'max-height': windowHeight - padding + 'px',
                                   'top': '0px'});
    } else {
        this.htmlElement.style.top = coordenates[1]+"px";
    }
    this.htmlElement.style.left = coordenates[0]+"px";

    if (this.childWindow != null) {
        this.childWindow.calculatePosition();
    }
}

/**
 *
 */
WindowMenu.prototype.setHandler = function (handler) {
    this.operationHandler = handler;
}

/**
 * Makes this WindowMenu visible.
 *
 * @param parentWindow
 */
WindowMenu.prototype.show = function (parentWindow) {
    this._parentWindowMenu = parentWindow;

    if (this._parentWindowMenu != null) {
        this._parentWindowMenu._addChildWindow(this);
    } else {
        LayoutManagerFactory.getInstance()._showWindowMenu(this);
    }

    document.body.appendChild(this.htmlElement);
    this.calculatePosition();
    this.htmlElement.style.display = "block";
    this.setFocus();
}

/**
 * Makes this WindowMenu hidden.
 */
WindowMenu.prototype.hide = function () {
    if (!isElement(this.htmlElement.parentNode)) {
        // This windowmenu is currently hidden => Nothing to do
        return;
    }

    this.htmlElement.parentNode.removeChild(this.htmlElement);
    if (this.msgElement != null) {
        this.msgElement.update();
    }
    if (this.childWindow != null) {
        this.childWindow.hide();
    }

    if (this._parentWindowMenu != null) {
        this._parentWindowMenu._removeChildWindow(this);
        this._parentWindowMenu = null;
    } else {
        LayoutManagerFactory.getInstance().hideCover();
    }
}

WindowMenu.prototype._addChildWindow = function (windowMenu) {
    if (windowMenu !== this) {
        this.childWindow = windowMenu;
    } else {
        throw TypeError('Window menus cannot be its own child');
    }
};

WindowMenu.prototype._removeChildWindow = function (windowMenu) {
    if (this.childWindow === windowMenu) {
        this.childWindow = null;
    }
};

WindowMenu.prototype.setFocus = function () {
}

/**
 * Specific class for platform preferences windows.
 *
 * @param manager
 *
 * @author jmostazo-upm
 */
function PreferencesWindowMenu(scope, manager) {
    WindowMenu.call(this, '');

    this.manager = manager;
    var table = manager.getPreferencesDef().getInterface();
    this.windowContent.insertBefore(table, this.msgElement);

    // Accept button
    this.acceptButton = new StyledElements.StyledButton({
        text: gettext('Save'),
        'class': 'btn-primary'
    });
    this._executeOperation = this._executeOperation.bind(this);
    this.acceptButton.addEventListener("click", this._executeOperation);
    this.acceptButton.insertInto(this.windowBottom);

    // Cancel button
    this.cancelButton = new StyledElements.StyledButton({
        text: gettext('Cancel')
    });

    Element.extend(this.cancelButton);
    this.cancelButton.addEventListener("click", this._closeListener);
    this.cancelButton.insertInto(this.windowBottom);
}
PreferencesWindowMenu.prototype = new WindowMenu();

PreferencesWindowMenu.prototype.setCancelable = function(cancelable) {
    this.ccancelButton.setDisabled(!cancelable);
};

PreferencesWindowMenu.prototype._executeOperation = function() {
    // Validate input fields
    var validationManager = new ValidationErrorManager();
    for (var fieldId in this.fields)
        validationManager.validate(this.fields[fieldId].inputInterface);

    // Build Error Message
    var errorMsg = validationManager.toHTML();

    // Show error message if needed
    if (errorMsg != "") {
        this.setMsg(errorMsg);
    } else {
        this.manager.save();
        this.hide();
    }
}

PreferencesWindowMenu.prototype.show = function (parentWindow) {
    this.setTitle(this.manager.buildTitle());
    this.manager.resetInterface('platform');
    WindowMenu.prototype.show.call(this, parentWindow);
}
<|endoftext|>


<commit_before>import Video from 'twilio-video';

Template.videoChat.onDestroyed(function (event, template) {
  event.preventDefault();
  if (template.room) {
    template.room.disconnect();
  }
});

Template.videoChat.onCreated(function (){
   this.mutedVariable = new ReactiveVar(null);
   this.cameraDisabledVariable = new ReactiveVar(null);
   this.previewVariable = new ReactiveVar(null);
   this.callStartedVariable = new ReactiveVar(null);
   this.mediaAttachedVarirable =  new ReactiveVar(null);
});

Template.videoChat.onRendered(function (){
   this.mutedVariable.set(false);
   this.cameraDisabledVariable.set(false);
   this.previewVariable.set(false);
   this.callStartedVariable.set(false);
   this.mediaAttachedVarirable.set(false);
});

Template.videoChat.helpers({
  twilioVideoNotSupportedByBrowser: function(){
    return (!navigator.webkitGetUserMedia && !navigator.mozGetUserMedia)
  },
  theClientIsMuted: function(){
    return (Template.instance().mutedVariable.get())
  },
  theCameraIsDisabled: function(){
    return (Template.instance().cameraDisabledVariable.get())
  },
  inPreviewMode: function () {
    return (Template.instance().previewVariable.get())
  },
  theCallStarted: function(){
    return (Template.instance().callStartedVariable.get())
  },
  theMediaIsAttached: function(){
    return (Template.instance().mediaAttachedVarirable.get())
  }
});

Template.videoChat.events({
  'submit #js-request-video-chat': function (event, template) {
    event.preventDefault();
    const target = event.target;
    const roomName = target.text.value;
    let initAccessToken;
    let accessToken;

    initAccessToken = Meteor.call(
      "requestVideoChatAccess", roomName,
      function requestVideoChatAccessCallback(error, result) {
        let localMediaPreview = null;
        if (error) {
          console.log(error, error.reson);
        }
        if (result) {
          accessToken = result;
          template.client = new Video.Client(accessToken.token);
          if (template.localMedia) {
            localMediaPreview = template.localMedia;
          }else {
            template.localMedia = new Video.LocalMedia();
            Video.getUserMedia().then(
              function (mediaStream) {
                template.localMedia.addStream(mediaStream);
                template.mediaAttachedVarirable.set(true);
              },
            function (error){
              console.log('LocalMedia error', error);
            })
          }
          room = template.client.connect({
            to: roomName,
            localMedia: localMediaPreview,
            audio: ( ! template.mutedVariable.get()),
            video: ( ! template.cameraDisabledVariable.get())
          })
          .then(
            room => {
              template.localMedia.attach('#local-media');

              room.participants.forEach(function(participant) {
                participant.media.attach('#remote-media');
              });

              room.on('participantConnected', function (participant) {
                participant.media.attach('#remote-media');
              });

              room.on('participantDisconnected', function(participant) {
                participant.media.detach();
              });

              room.on('disconnected', function () {
                room.localParticipant.media.detach();
                room.participants.forEach(function(participant) {
                  participant.media.detach();
                });
              });
              template.room = room;
              template.callStartedVariable.set(true);
            }
          )
        }
    })
  },
  "click #js-end-video-chat" : function (event, template){
    event.preventDefault();
    if (template.room) {
      template.room.disconnect();
      template.localMedia.detach('#local-media');
      template.callStartedVariable.set(false);
      template.mediaAttachedVarirable.set(false);
      template.previewVariable.set(false);
    }
  },
  "click #js-mute-video-chat" : function (event, template) {
    event.preventDefault();
    template.localMedia.mute();
    if (template.localMedia) {
      template.localMedia.removeMicrophone()
      console.log(template.localMedia);
      // template.localMedia.mute();
      // if (template.localMedia.isMuted) {
      template.mutedVariable.set(true);
      // }
    }
  },
  "click #js-unmute-video-chat" : function (event, template){
    event.preventDefault();
    template.localMedia.unmute();
    if (template.localMedia) {
      template.localMedia.addMicrophone()
      console.log(template.localMedia);
      // template.localMedia.unmute();
      // if ( ! template.localMedia.isMuted) {
      template.mutedVariable.set(false);
      // }
    }
  },
  "click #js-disable-camera-video-chat": function (event, template) {
    event.preventDefault();
    if (template.localMedia) {
      const localVideoTrack = template.localMedia.removeCamera();
      template.cameraDisabledVariable.set(true);
    }
  },
  "click #js-enable-camera-video-chat": function (event, template) {
    event.preventDefault();
    if (template.localMedia) {
      template.localMedia.addCamera().then(
        function(localVideoTrack){
          if (localVideoTrack.mediaStream.active) {
            template.cameraDisabledVariable.set(false);
          }
        },
        function (error){
          console.log('LocalMedia error', error);
        }
      )
    }
  },
  "click #js-preview-camera": function (event, template) {
    event.preventDefault();
    if( ! template.localMedia){
      template.localMedia = new Video.LocalMedia();
      Video.getUserMedia().then(
        function (mediaStream) {
          template.localMedia.addStream(mediaStream);
          template.localMedia.attach('#local-media');
          template.previewVariable.set(true);
          template.mediaAttachedVarirable.set(true);
        },
      function (error){
        console.log('LocalMedia error', error);
      })
    }
  }
});
<commit_msg>cruft<commit_after>import Video from 'twilio-video';

Template.videoChat.onDestroyed(function (event, template) {
  event.preventDefault();
  if (template.room) {
    template.room.disconnect();
  }
});

Template.videoChat.onCreated(function (){
   this.mutedVariable = new ReactiveVar(null);
   this.cameraDisabledVariable = new ReactiveVar(null);
   this.previewVariable = new ReactiveVar(null);
   this.callStartedVariable = new ReactiveVar(null);
   this.mediaAttachedVarirable =  new ReactiveVar(null);
});

Template.videoChat.onRendered(function (){
   this.mutedVariable.set(false);
   this.cameraDisabledVariable.set(false);
   this.previewVariable.set(false);
   this.callStartedVariable.set(false);
   this.mediaAttachedVarirable.set(false);
});

Template.videoChat.helpers({
  twilioVideoNotSupportedByBrowser: function(){
    return (!navigator.webkitGetUserMedia && !navigator.mozGetUserMedia)
  },
  theClientIsMuted: function(){
    return (Template.instance().mutedVariable.get())
  },
  theCameraIsDisabled: function(){
    return (Template.instance().cameraDisabledVariable.get())
  },
  inPreviewMode: function () {
    return (Template.instance().previewVariable.get())
  },
  theCallStarted: function(){
    return (Template.instance().callStartedVariable.get())
  },
  theMediaIsAttached: function(){
    return (Template.instance().mediaAttachedVarirable.get())
  }
});

Template.videoChat.events({
  'submit #js-request-video-chat': function (event, template) {
    event.preventDefault();
    const target = event.target;
    const roomName = target.text.value;
    let initAccessToken;
    let accessToken;

    initAccessToken = Meteor.call(
      "requestVideoChatAccess", roomName,
      function requestVideoChatAccessCallback(error, result) {
        let localMediaPreview = null;
        if (error) {
          console.log(error, error.reson);
        }
        if (result) {
          accessToken = result;
          template.client = new Video.Client(accessToken.token);
          if (template.localMedia) {
            localMediaPreview = template.localMedia;
          }else {
            template.localMedia = new Video.LocalMedia();
            Video.getUserMedia().then(
              function (mediaStream) {
                template.localMedia.addStream(mediaStream);
                template.mediaAttachedVarirable.set(true);
              },
            function (error){
              console.log('LocalMedia error', error);
            })
          }
          room = template.client.connect({
            to: roomName,
            localMedia: localMediaPreview,
            audio: ( ! template.mutedVariable.get()),
            video: ( ! template.cameraDisabledVariable.get())
          })
          .then(
            room => {
              template.localMedia.attach('#local-media');

              room.participants.forEach(function(participant) {
                participant.media.attach('#remote-media');
              });

              room.on('participantConnected', function (participant) {
                participant.media.attach('#remote-media');
              });

              room.on('participantDisconnected', function(participant) {
                participant.media.detach();
              });

              room.on('disconnected', function () {
                room.localParticipant.media.detach();
                room.participants.forEach(function(participant) {
                  participant.media.detach();
                });
              });
              template.room = room;
              template.callStartedVariable.set(true);
            }
          )
        }
    })
  },
  "click #js-end-video-chat" : function (event, template){
    event.preventDefault();
    if (template.room) {
      template.room.disconnect();
      template.localMedia.detach('#local-media');
      template.callStartedVariable.set(false);
      template.mediaAttachedVarirable.set(false);
      template.previewVariable.set(false);
    }
  },
  "click #js-mute-video-chat" : function (event, template) {
    event.preventDefault();
    template.localMedia.mute();
    if (template.localMedia) {
      template.localMedia.removeMicrophone()
      template.mutedVariable.set(true);
    }
  },
  "click #js-unmute-video-chat" : function (event, template){
    event.preventDefault();
    template.localMedia.unmute();
    if (template.localMedia) {
      template.localMedia.addMicrophone()
      template.mutedVariable.set(false);
    }
  },
  "click #js-disable-camera-video-chat": function (event, template) {
    event.preventDefault();
    if (template.localMedia) {
      template.localMedia.removeCamera();
      template.cameraDisabledVariable.set(true);
    }
  },
  "click #js-enable-camera-video-chat": function (event, template) {
    event.preventDefault();
    if (template.localMedia) {
      template.localMedia.addCamera().then(
        function(localVideoTrack){
          if (localVideoTrack.mediaStream.active) {
            template.cameraDisabledVariable.set(false);
          }
        },
        function (error){
          console.log('LocalMedia error', error);
        }
      )
    }
  },
  "click #js-preview-camera": function (event, template) {
    event.preventDefault();
    if( ! template.localMedia){
      template.localMedia = new Video.LocalMedia();
      Video.getUserMedia().then(
        function (mediaStream) {
          template.localMedia.addStream(mediaStream);
          template.localMedia.attach('#local-media');
          template.previewVariable.set(true);
          template.mediaAttachedVarirable.set(true);
        },
      function (error){
        console.log('LocalMedia error', error);
      })
    }
  }
});
<|endoftext|>


<commit_before>Template.lecture.helpers({
  myLecture: function() {
    return this.course.owner == Meteor.userId();
  }
});  <commit_msg>data context in each was the lecture itself<commit_after>Template.lecture.helpers({
  myLecture: function() {
    console.log('myLecture', this);
    return this.owner == Meteor.userId();
  }
});  <|endoftext|>


<commit_before>const coreApp = require('kolibri');
const coreActions = require('kolibri.coreVue.vuex.actions');
const ConditionalPromise = require('kolibri.lib.conditionalPromise');
const Constants = require('./state/constants');

const LearnerGroupResource = coreApp.resources.LearnerGroupResource;
const MembershipResource = coreApp.resources.MembershipResource;
const FacilityUserResource = coreApp.resources.FacilityUserResource;
const ClassroomResource = coreApp.resources.ClassroomResource;

function displayModal(store, modalName) {
  store.dispatch('SET_MODAL', modalName);
}

function showGroupsPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', Constants.PageNames.COACH_GROUPS_PAGE);

  const facilityPromise = FacilityUserResource.getCurrentFacility();
  const classPromise = ClassroomResource.getModel(classId).fetch();
  const classUsersPromise =
    FacilityUserResource.getCollection({ member_of: classId }).fetch({}, true);
  const groupPromise = LearnerGroupResource.getCollection({ parent: classId }).fetch();

  ConditionalPromise.all([facilityPromise, classPromise, classUsersPromise, groupPromise]).only(
    coreActions.samePageCheckGenerator(store),
    ([facility, classModel, classUsers, groups]) => {
      const groupUsersPromises = groups.map(group =>
        FacilityUserResource.getCollection({ member_of: group.id }).fetch({}, true));
      ConditionalPromise.all(groupUsersPromises).only(
        coreActions.samePageCheckGenerator(store),
        groupsUsers => {
          groups.forEach((group, index) => {
            groups[index].users = groupsUsers[index];
          });
          const pageState = {
            facilityId: facility[0],
            class: classModel,
            classUsers,
            groups,
            modalShown: false,
          };
          store.dispatch('SET_PAGE_STATE', pageState);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('CORE_SET_TITLE', 'Groups');
        },
        error => coreActions.handleError(store, error)
      );
    },
    error => coreActions.handleError(store, error)
  );
}

function createGroup(store, classId, groupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    parent: classId,
    name: groupName,
  };
  LearnerGroupResource.createModel(groupPayload).save().then(
    group => {
      group.users = []; // pass in an empty array
      store.dispatch('ADD_GROUP', group);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      displayModal(store, false);
    },
    error => coreActions.handleError(store, error)
  );
}

function renameGroup(store, classId, groupId, newGroupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    name: newGroupName,
  };
  LearnerGroupResource.getModel(groupId).save(groupPayload).then(
    () => {
      store.dispatch('RENAME_GROUP', groupId, newGroupName);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function deleteGroup(store, classId, groupId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  LearnerGroupResource.getModel(groupId).delete().then(
    () => {
      store.dispatch('DELETE_GROUP', groupId);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function _addUserToGroup(store, groupId, userId) {
  const membershipPayload = {
    collection: groupId,
    user: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.createModel(membershipPayload).save().then(
      () => {
        store.dispatch('ADD_USER_TO_GROUP', groupId, userId);
        resolve();
      },
      error => reject(error)
    );
  });
}

function _addMultipleUsersToGroup(store, groupId, userIds) {
  const addPromises = userIds.map(userId => _addUserToGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(addPromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function _removeUserfromGroup(store, groupId, userId) {
  const membershipPayload = {
    collection_id: groupId,
    user_id: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.getCollection(membershipPayload).fetch().then(
      membership => {
        const membershipId = membership[0].id; // will always only have one item in the array.
        MembershipResource.getModel(membershipId).delete().then(
          () => {
            store.dispatch('REMOVE_USER_FROM_GROUP', groupId, userId);
            resolve();
          },
          error => reject(error)
        );
      }
    );
  });
}

function _removeMultipleUsersFromGroup(store, groupId, userIds) {
  const removePromises = userIds.map(userId => _removeUserfromGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(removePromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function addUsersToGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _addMultipleUsersToGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function removeUsersFromGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _removeMultipleUsersFromGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function moveUsersBetweenGroups(store, currentGroupId, newGroupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const removeUsersPromise = _removeMultipleUsersFromGroup(store, currentGroupId, userIds);
  const addUsersPromise = _addMultipleUsersToGroup(store, newGroupId, userIds);
  Promise.all([removeUsersPromise, addUsersPromise]).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

module.exports = {
  displayModal,
  showGroupsPage,
  createGroup,
  renameGroup,
  deleteGroup,
  addUsersToGroup,
  removeUsersFromGroup,
  moveUsersBetweenGroups,
};
<commit_msg>Add consistency to users and groups within vuex.<commit_after>const coreApp = require('kolibri');
const coreActions = require('kolibri.coreVue.vuex.actions');
const ConditionalPromise = require('kolibri.lib.conditionalPromise');
const Constants = require('./state/constants');

const LearnerGroupResource = coreApp.resources.LearnerGroupResource;
const MembershipResource = coreApp.resources.MembershipResource;
const FacilityUserResource = coreApp.resources.FacilityUserResource;
const ClassroomResource = coreApp.resources.ClassroomResource;

function _classState(classModel) {
  return {
    id: classModel.id,
    name: classModel.name,
  };
}

function _userState(user) {
  return {
    id: user.id,
    username: user.username,
    full_name: user.full_name,
  };
}

function _usersState(users) {
  return users.map(user => _userState(user));
}

function _groupState(group) {
  return {
    id: group.id,
    name: group.name,
    users: [],
  };
}

function _groupsState(groups) {
  return groups.map(group => _groupState(group));
}

function displayModal(store, modalName) {
  store.dispatch('SET_MODAL', modalName);
}

function showGroupsPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', Constants.PageNames.COACH_GROUPS_PAGE);

  const facilityPromise = FacilityUserResource.getCurrentFacility();
  const classPromise = ClassroomResource.getModel(classId).fetch();
  const classUsersPromise =
    FacilityUserResource.getCollection({ member_of: classId }).fetch({}, true);
  const groupPromise = LearnerGroupResource.getCollection({ parent: classId }).fetch();

  ConditionalPromise.all([facilityPromise, classPromise, classUsersPromise, groupPromise]).only(
    coreActions.samePageCheckGenerator(store),
    ([facility, classModel, classUsers, groupsCollection]) => {
      const groups = _groupsState(groupsCollection);
      const groupUsersPromises = groups.map(group =>
        FacilityUserResource.getCollection({ member_of: group.id }).fetch({}, true));

      ConditionalPromise.all(groupUsersPromises).only(
        coreActions.samePageCheckGenerator(store),
        groupsUsersCollection => {
          groupsUsersCollection.forEach((groupUsers, index) => {
            groups[index].users = _usersState(groupUsers);
          });

          const pageState = {
            facilityId: facility[0],
            class: _classState(classModel),
            classUsers: _usersState(classUsers),
            groups,
            modalShown: false,
          };

          store.dispatch('SET_PAGE_STATE', pageState);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('CORE_SET_TITLE', 'Groups');
        },
        error => coreActions.handleError(store, error)
      );
    },
    error => coreActions.handleError(store, error)
  );
}

function createGroup(store, classId, groupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    parent: classId,
    name: groupName,
  };
  LearnerGroupResource.createModel(groupPayload).save().then(
    group => {
      store.dispatch('ADD_GROUP', _groupState(group));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      displayModal(store, false);
    },
    error => coreActions.handleError(store, error)
  );
}

function renameGroup(store, classId, groupId, newGroupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    name: newGroupName,
  };
  LearnerGroupResource.getModel(groupId).save(groupPayload).then(
    () => {
      store.dispatch('RENAME_GROUP', groupId, newGroupName);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function deleteGroup(store, classId, groupId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  LearnerGroupResource.getModel(groupId).delete().then(
    () => {
      store.dispatch('DELETE_GROUP', groupId);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function _addUserToGroup(store, groupId, userId) {
  const membershipPayload = {
    collection: groupId,
    user: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.createModel(membershipPayload).save().then(
      () => {
        store.dispatch('ADD_USER_TO_GROUP', groupId, userId);
        resolve();
      },
      error => reject(error)
    );
  });
}

function _addMultipleUsersToGroup(store, groupId, userIds) {
  const addPromises = userIds.map(userId => _addUserToGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(addPromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function _removeUserfromGroup(store, groupId, userId) {
  const membershipPayload = {
    collection_id: groupId,
    user_id: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.getCollection(membershipPayload).fetch().then(
      membership => {
        const membershipId = membership[0].id; // will always only have one item in the array.
        MembershipResource.getModel(membershipId).delete().then(
          () => {
            store.dispatch('REMOVE_USER_FROM_GROUP', groupId, userId);
            resolve();
          },
          error => reject(error)
        );
      }
    );
  });
}

function _removeMultipleUsersFromGroup(store, groupId, userIds) {
  const removePromises = userIds.map(userId => _removeUserfromGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(removePromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function addUsersToGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _addMultipleUsersToGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function removeUsersFromGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _removeMultipleUsersFromGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function moveUsersBetweenGroups(store, currentGroupId, newGroupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const removeUsersPromise = _removeMultipleUsersFromGroup(store, currentGroupId, userIds);
  const addUsersPromise = _addMultipleUsersToGroup(store, newGroupId, userIds);
  Promise.all([removeUsersPromise, addUsersPromise]).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

module.exports = {
  displayModal,
  showGroupsPage,
  createGroup,
  renameGroup,
  deleteGroup,
  addUsersToGroup,
  removeUsersFromGroup,
  moveUsersBetweenGroups,
};
<|endoftext|>


<commit_before>const coreApp = require('kolibri');
const coreActions = require('kolibri.coreVue.vuex.actions');
const ConditionalPromise = require('kolibri.lib.conditionalPromise');
const Constants = require('./state/constants');

const LearnerGroupResource = coreApp.resources.LearnerGroupResource;
const MembershipResource = coreApp.resources.MembershipResource;
const FacilityUserResource = coreApp.resources.FacilityUserResource;
const ClassroomResource = coreApp.resources.ClassroomResource;

function displayModal(store, modalName) {
  store.dispatch('SET_MODAL', modalName);
}

function showGroupsPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', Constants.PageNames.COACH_GROUPS_PAGE);

  const facilityPromise = FacilityUserResource.getCurrentFacility();
  const classPromise = ClassroomResource.getModel(classId).fetch();
  const classUsersPromise =
    FacilityUserResource.getCollection({ member_of: classId }).fetch({}, true);
  const groupPromise = LearnerGroupResource.getCollection({ parent: classId }).fetch();

  ConditionalPromise.all(
    [facilityPromise, classPromise, classUsersPromise, groupPromise]).only(
    coreActions.samePageCheckGenerator(store),
    ([facility, classModel, classUsers, groups]) => {
      const groupUsersPromises = groups.map(group =>
        FacilityUserResource.getCollection({ member_of: group.id }).fetch({}, true));
      ConditionalPromise.all(groupUsersPromises).only(
        coreActions.samePageCheckGenerator(store),
        groupsUsers => {
          groups.forEach((group, index) => {
            groups[index].users = groupsUsers[index];
          });
          const pageState = {
            facilityId: facility[0],
            class: classModel,
            classUsers,
            groups,
            modalShown: false,
          };
          store.dispatch('SET_PAGE_STATE', pageState);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('CORE_SET_TITLE', 'Groups');
        },
        error => {
          coreActions.handleError(store, error);
        }
      );
    },
    error => {
      coreActions.handleError(store, error);
    }
    );
}

function createGroup(store, classId, groupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    parent: classId,
    name: groupName,
  };
  LearnerGroupResource.createModel(groupPayload).save().then(
    group => {
      group.users = []; // pass in an empty array
      store.dispatch('ADD_GROUP', group);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      displayModal(store, false);
    },
    error => coreActions.handleError(store, error)
  );
}

function renameGroup(store, classId, groupId, newGroupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    name: newGroupName,
  };
  LearnerGroupResource.getModel(groupId).save(groupPayload).then(
    () => {
      store.dispatch('RENAME_GROUP', groupId, newGroupName);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function deleteGroup(store, classId, groupId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  LearnerGroupResource.getModel(groupId).delete().then(
    () => {
      store.dispatch('DELETE_GROUP', groupId);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function _addUserToGroup(store, groupId, userId) {
  const membershipPayload = {
    collection: groupId,
    user: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.createModel(membershipPayload).save().then(
      () => {
        store.dispatch('ADD_USER_TO_GROUP', groupId, userId);
        resolve();
      },
      error => reject(error)
    );
  });
}

function _addMultipleUsersToGroup(store, groupId, userIds) {
  const addPromises = userIds.map(userId => _addUserToGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(addPromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function _removeUserfromGroup(store, groupId, userId) {
  const membershipPayload = {
    collection_id: groupId,
    user_id: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.getCollection(membershipPayload).fetch().then(
      membership => {
        const membershipId = membership[0].id; // will always only have one item in the array.
        MembershipResource.getModel(membershipId).delete().then(
          () => {
            store.dispatch('REMOVE_USER_FROM_GROUP', groupId, userId);
            resolve();
          },
          error => reject(error)
        );
      }
    );
  });
}

function _removeMultipleUsersFromGroup(store, groupId, userIds) {
  const removePromises = userIds.map(userId => _removeUserfromGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(removePromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function addUsersToGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _addMultipleUsersToGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function removeUsersFromGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _removeMultipleUsersFromGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function moveUsersBetweenGroups(store, currentGroupId, newGroupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const removeUsersPromise = _removeMultipleUsersFromGroup(store, currentGroupId, userIds);
  const addUsersPromise = _addMultipleUsersToGroup(store, newGroupId, userIds);
  Promise.all([removeUsersPromise, addUsersPromise]).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

module.exports = {
  displayModal,
  showGroupsPage,
  createGroup,
  renameGroup,
  deleteGroup,
  addUsersToGroup,
  removeUsersFromGroup,
  moveUsersBetweenGroups,
};
<commit_msg>That alignment tho.<commit_after>const coreApp = require('kolibri');
const coreActions = require('kolibri.coreVue.vuex.actions');
const ConditionalPromise = require('kolibri.lib.conditionalPromise');
const Constants = require('./state/constants');

const LearnerGroupResource = coreApp.resources.LearnerGroupResource;
const MembershipResource = coreApp.resources.MembershipResource;
const FacilityUserResource = coreApp.resources.FacilityUserResource;
const ClassroomResource = coreApp.resources.ClassroomResource;

function displayModal(store, modalName) {
  store.dispatch('SET_MODAL', modalName);
}

function showGroupsPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', Constants.PageNames.COACH_GROUPS_PAGE);

  const facilityPromise = FacilityUserResource.getCurrentFacility();
  const classPromise = ClassroomResource.getModel(classId).fetch();
  const classUsersPromise =
    FacilityUserResource.getCollection({ member_of: classId }).fetch({}, true);
  const groupPromise = LearnerGroupResource.getCollection({ parent: classId }).fetch();

  ConditionalPromise.all([facilityPromise, classPromise, classUsersPromise, groupPromise]).only(
    coreActions.samePageCheckGenerator(store),
    ([facility, classModel, classUsers, groups]) => {
      const groupUsersPromises = groups.map(group =>
        FacilityUserResource.getCollection({ member_of: group.id }).fetch({}, true));
      ConditionalPromise.all(groupUsersPromises).only(
        coreActions.samePageCheckGenerator(store),
        groupsUsers => {
          groups.forEach((group, index) => {
            groups[index].users = groupsUsers[index];
          });
          const pageState = {
            facilityId: facility[0],
            class: classModel,
            classUsers,
            groups,
            modalShown: false,
          };
          store.dispatch('SET_PAGE_STATE', pageState);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('CORE_SET_TITLE', 'Groups');
        },
        error => coreActions.handleError(store, error)
      );
    },
    error => coreActions.handleError(store, error)
  );
}

function createGroup(store, classId, groupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    parent: classId,
    name: groupName,
  };
  LearnerGroupResource.createModel(groupPayload).save().then(
    group => {
      group.users = []; // pass in an empty array
      store.dispatch('ADD_GROUP', group);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      displayModal(store, false);
    },
    error => coreActions.handleError(store, error)
  );
}

function renameGroup(store, classId, groupId, newGroupName) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const groupPayload = {
    name: newGroupName,
  };
  LearnerGroupResource.getModel(groupId).save(groupPayload).then(
    () => {
      store.dispatch('RENAME_GROUP', groupId, newGroupName);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function deleteGroup(store, classId, groupId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  LearnerGroupResource.getModel(groupId).delete().then(
    () => {
      store.dispatch('DELETE_GROUP', groupId);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => coreActions.handleError(store, error)
  );
}

function _addUserToGroup(store, groupId, userId) {
  const membershipPayload = {
    collection: groupId,
    user: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.createModel(membershipPayload).save().then(
      () => {
        store.dispatch('ADD_USER_TO_GROUP', groupId, userId);
        resolve();
      },
      error => reject(error)
    );
  });
}

function _addMultipleUsersToGroup(store, groupId, userIds) {
  const addPromises = userIds.map(userId => _addUserToGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(addPromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function _removeUserfromGroup(store, groupId, userId) {
  const membershipPayload = {
    collection_id: groupId,
    user_id: userId,
  };
  return new Promise((resolve, reject) => {
    MembershipResource.getCollection(membershipPayload).fetch().then(
      membership => {
        const membershipId = membership[0].id; // will always only have one item in the array.
        MembershipResource.getModel(membershipId).delete().then(
          () => {
            store.dispatch('REMOVE_USER_FROM_GROUP', groupId, userId);
            resolve();
          },
          error => reject(error)
        );
      }
    );
  });
}

function _removeMultipleUsersFromGroup(store, groupId, userIds) {
  const removePromises = userIds.map(userId => _removeUserfromGroup(store, groupId, userId));

  return new Promise((resolve, reject) => {
    Promise.all(removePromises).then(
      () => resolve(),
      error => reject(error)
    );
  });
}

function addUsersToGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _addMultipleUsersToGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function removeUsersFromGroup(store, groupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _removeMultipleUsersFromGroup(store, groupId, userIds).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

function moveUsersBetweenGroups(store, currentGroupId, newGroupId, userIds) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  const removeUsersPromise = _removeMultipleUsersFromGroup(store, currentGroupId, userIds);
  const addUsersPromise = _addMultipleUsersToGroup(store, newGroupId, userIds);
  Promise.all([removeUsersPromise, addUsersPromise]).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      this.displayModal(false);
    },
    error => error(error)
  );
}

module.exports = {
  displayModal,
  showGroupsPage,
  createGroup,
  renameGroup,
  deleteGroup,
  addUsersToGroup,
  removeUsersFromGroup,
  moveUsersBetweenGroups,
};
<|endoftext|>