<commit_before>/**********************************************************************************************************************
*   Controller for views/task.view.html
*
*   Manages the displacement of all Homeworks.
*
*   Page is orderd via:
*   Homeworks -> TaskFiles(in the selected HW) -> SubTasks(in the selected TF) -> Submits(of the selected ST)
*
*   Selected Items are stored in $scope, the recieved data from the server in vm
*
*   The Controller is handled in states to fit the current Selection
**********************************************************************************************************************/

(function () {

angular
    .module('app')
    .controller('TasksController', TasksController);

    TasksController.$inject = ['$scope', '$uibModal', 'TaskService', 'FlashService', '$rootScope', '$location', '$filter', '$timeout', '$q'];
    function TasksController($scope, $uibModal, TaskService, FlashService, $rootScope, $location, $filter, $timeout, $q) {
        var vm = this;

        $scope.orderReverse = false;
        $scope.orderTaskSetPredicate = 'taskSetName';
        $scope.orderTaskPredicate = 'taskName';
        $scope.orderTablePredicate = 'tableName';
        $scope.search = '';

        $scope.dataTypes = [];
        $scope.tabActive = {
            intensionTables : false,
            intensionForeignKeys : false,
            extension : false,
            tasks : false
        };

        $scope.animationsEnabled = true;

        vm.taskSets = [];
        vm.tasks = [];
        vm.tables = [];
        vm.foreignKeys = [];
        $scope.selectedTaskSet = {};
        $scope.selectedTask = {};
        $scope.selectedTable = {};

        function initController() {
            getAllTaskSets();
            getColumnDefinitionDataTypes();
        }

        //////////////////////////////777
        //  Fetch initial Data
        //////////////////////////////777

        function getAllTaskSets() {
            if ($rootScope.Tasks.taskSets) {
                vm.taskSets = $rootScope.Tasks.taskSets;
                $scope.getCurrentPath();
            } else {
                TaskService.getAllTaskSets().then(
                        function (result) {
                            vm.taskSets = result;
                            $scope.getCurrentPath();
                            console.log(result);
                        }, function (error) {
                            FlashService.Error(error);
                        }
                );
            }
        }

        function getColumnDefinitionDataTypes() {

            TaskService.getColumnDefinitionDataTypes().then(
                function (result) {
                    vm.dataTypes = result;
                },
                null
            );
        }

        function getTasksForTaskSet(taskSet) {
            TaskService.getAllTasksForTaskSet(taskSet.id).then(
                function(result) {
                    if (result) {
                        vm.tasks = result;
                    } else {
                        vm.tasks = [];
                    }
                },
                function(error) {
                    FlashService.Error(error);
                }
            );
        }
        //////////////////////////////777
        //  Saving data when leaving View
        //  Restoring saved Data and Displaying the correct screen
        //////////////////////////////777

        $scope.keepTabActive = function () {
            $rootScope.Tasks.tabActive = $scope.tabActive;
        };

        $scope.keepTaskSets = function () {
            $rootScope.Tasks.taskSets = vm.taskSets;
        };

        $scope.$on('$locationChangeStart', function(event) {
            $scope.keepTabActive();
            $scope.keepTaskSets();
        });

        $scope.getCurrentPath = function () {
            var path = $rootScope.Tasks;

            //Find out if a TaskSet is currently selected
            if (path.selectedTaskSet) {
                $scope.tabActive = path.tabActive;
                $scope.selectTaskSet(path.selectedTaskSet);
            } else {
                return;
            }

        };

        //////////////////////////////777
        //  TaskSet - Control
        //////////////////////////////777

        /* Data */
        $scope.taskSetSelectionStatus = {
            taskSetSelected : false
        };

        var DefaultTaskSet = function() {
            this.taskSetName = "";
            this.tableDefinitions = [];
            this.foreignKeyRelations = [];
            this.tasks=[];
            this.isHomeWork = false;
        };

        /* Methods */
        $scope.pushNewTaskSet = function () {
            vm.taskSets.push(new DefaultTaskSet());
        };

        $scope.selectTaskSet = function(taskSet, destination) {
            var index = findInArray(vm.taskSets, taskSet);
            selectTaskSet(index);
            $scope.tabActive.intensionTables = true;
            getTasksForTaskSet(taskSet);
        };

        function selectTaskSet (taskSetIndex) {
            $scope.selectedTable = undefined;
            $scope.selectedTask = undefined;
            $scope.selectedTaskSet = vm.taskSets[taskSetIndex];
            vm.tables = $scope.selectedTaskSet.tableDefinitions;
            vm.foreignKeyRelations = $scope.selectedTaskSet.foreignKeyRelations;
            $rootScope.Tasks.selectedTaskSet = $scope.selectedTaskSet;
            $scope.tableSelectionStatus.tableNotSelected = true;
            $scope.tableSelectionStatus.tableSelected = false;
        }

        $scope.viewTaskSetComments = function(taskSet) {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/comment.template.html',
                    controller: 'CommentController',
                    resolve: {
                        commentTaskObject: function() {
                            return {content: taskSet, type: 'taskSet'};
                        }
                    }
            });

            modalInstance.result.then(
                FlashService.Clear
            );
        };

        /* Server Side Methods */
        $scope.saveTaskSet = function(taskSet) {
            if (taskSet.id !== undefined) {

                return TaskService.editTaskSet(taskSet, taskSet.id).then(
                        function (result) {
                            FlashService.Success("Updated TaskSet");

                        }, function (error) {
                            FlashService.Error(error);
                        }
                );

            } else {
                return TaskService.createTaskSet(taskSet).then(
                        function (result) {
                            FlashService.Success("Created new TaskSet");
                            vm.taskSets[findInArray(vm.taskSets, taskSet)] = result;

                        }, function (error) {
                            FlashService.Error(error);

                        }
                );

            }
        };

        $scope.exportTaskSets = function() {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/exportTaskSet.template.html',
                    controller: 'exportTaskSetController'
            });

            modalInstance.result.then(
                function (taskSetIds) {
                    return TaskService.exportTaskSets({taskSetIds: taskSetIds});
                }, null
            );
        };

        $scope.importTaskSets = function() {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/importTaskSet.template.html',
                    controller: 'importTaskSetController'
            });
        };

        $scope.saveSelectedTaskSet = function () {
             $scope.saveTaskSet($scope.selectedTaskSet);
        };

        $scope.deleteTaskSet = function (taskSet) {
            if (taskSet.id === undefined) {
                vm.taskSets.splice(findInArray(vm.taskSets, taskSet), 1);
                return;
            }

            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/sure.template.html',
                    controller: 'sureTemplateController',
                    resolve: {
                        sureTemplateMessage: function () {
                                return " Are you sure you want to delete TaskSet: " + taskSet.taskSetName + "?
 It will be deleted forever!";
                            }
                    }
            });

            modalInstance.result
            .then(
                function () {
                    return TaskService.deleteTaskSet(taskSet.id);
                },
                function () {
                    return $q.reject({noerror: true});
                }
            ).then(
                function () {
                    vm.taskSets.splice(findInArray(vm.taskSets, taskSet), 1);
                },
                function (error) {
                    if (!error.noerror)
                        FlashService.Error(error);
                }
            );
        };

        $scope.rateTaskSet = function (taskSet, decision) {
            var ratingJson = {};
            switch (decision) {
                case 'positive': {
                    ratingJson = {'positive': 1, 'needReview': 0, 'negative': 0};
                    break;
                }
                case 'needReview': {
                    ratingJson = {'positive': 0, 'needReview': 1, 'negative': 0};
                    break;
                }
                case 'negative': {
                    ratingJson = {'positive': 0, 'needReview': 0, 'negative': 1};
                    break;
                }
            }

            TaskService.rateTaskSet(taskSet.id, ratingJson).then(
                function (result) {
                    vm.taskSets[findInArray(vm.taskSets, taskSet)] = result;

                }, function (error) {
                    FlashService.Error(error);

                });
        };

        //////////////////////////////777
        //  Intension: TableDefinition - Control
        //////////////////////////////777

        /* Data */
        $scope.tableSelectionStatus = {
            tableSelected : false,
            tableNotSelected : true
        };

        var DefaultTable = function () {
            this.tableName = "";
            this.columnDefinitions = [];
            this.extension = "";
        };

        /* Methods */
        $scope.pushNewTable = function () {
            vm.tables.push(new DefaultTable());
        };

        $scope.selectTable = function (table) {
            var index = findInArray(vm.tables, table);
            selectTable(index);
            $scope.tableSelectionStatus.tableNotSelected = false;
            $scope.tableSelectionStatus.tableSelected = true;
        };

        function selectTable(tableIndex) {
            $scope.selectedTable = vm.tables[tableIndex];
            $rootScope.Tasks.selectedTable = $scope.selectedTable;
            vm.columnDefinitions = $scope.selectedTable.columnDefinitions;
        }

        /* Changes are only changed on the Server via TaskSet Actions */
        $scope.deleteTable = function (table) {
            vm.tables.splice(findInArray(vm.tables, table), 1);
        };

        //////////////////////////////777
        //  Intension: TableDefinition: Column - Control
        //////////////////////////////777

        /* Data */
        var DefaultColumn = function () {
            this.columnName = "";
            this.dataType = "BIGINT";
            this.notNull = true;
            this.primaryKey = false;
        };

        /* Methods */
        $scope.pushNewColumn = function () {
            vm.columnDefinitions.push(new DefaultColumn());
        };

        /* Changes are only changed on the Server via TaskSet Actions */
        $scope.deleteColumn = function (column) {
            vm.columnDefinitions.splice(findInArray(vm.columnDefinitions, column), 1);
        };

        //////////////////////////////777
        //  Tasks: Control
        //////////////////////////////777

        /* Data */
        var DefaultForeignKey = function () {
            this.sourceTable = "";
            this.sourceColumn = "";
            this.destinationTable = "";
            this.destinationColumn = "";
        };

        /* Methods */
        $scope.pushNewForeignKey = function () {
            vm.foreignKeyRelations.push(new DefaultForeignKey());
        };

        /* Changes are only changed on the Server via TaskSet Actions */
        $scope.deleteForeignKey = function (foreignKey) {
            vm.foreignKeyRelations.splice(findInArray(vm.foreignKeyRelations, foreignKey), 1);
        };

        //////////////////////////////777
        //  Tasks: Control
        //////////////////////////////777

        /* Data */
        var DefaultTask = function () {
            this.taskSet = $scope.selectedTaskSet.id;
            this.taskName = "";
            this.refStatement = "";
            this.evaluationStrategy = 1;
            this.points = 1;
            this.requiredTerm = 0;
            this.isCollapsed = true;
            this.availableSyntaxChecks = 0;
            this.availableSemanticChecks = 0;
        };

        /* Methods */

        $scope.pushNewTask = function () {
            vm.tasks.push(new DefaultTask());
        };

        $scope.viewTaskComments = function(task) {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/comment.template.html',
                    controller: 'CommentController',
                    resolve: {
                        commentTaskObject: function() {
                            return {content: task, type: 'task'};
                        }
                    }
            });

            modalInstance.result.then(
                FlashService.Clear
            );
        };

        /* Server Side Methods */
        $scope.saveTask = function (task) {
            if (task.id !== undefined) {
                TaskService.editTask(task.id, task).then(
                        function (result) {
                            FlashService.Success("Updated Task");
                        }, function (error) {
                            FlashService.Error(error);
                        }
                );
            } else {
                TaskService.createTask(task.taskSet, task).then(
                        function (result) {
                            /* Let's put in the new values we just created in BackEnd */
                            vm.tasks[findInArray(vm.tasks, task)] = result;

                            FlashService.Success("Created new Task");

                        }, function (error) {
                            FlashService.Error(error);

                        }
                );
            }
        };

        $scope.deleteTask = function (task) {
            /* If not in Database, we don't need to do much */
            if (task.id === undefined) {
                vm.tasks.splice(findInArray(vm.tasks, task), 1);
                return;
            }

            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/sure.template.html',
                    controller: 'sureTemplateController',
                    resolve: {
                        sureTemplateMessage: function () {
                                return " Are you sure you want to delete Task: " + task.taskName + "?
 It will be deleted forever!";
                            }
                    }
            });

            modalInstance.result
            .then(
                function () {
                    return TaskService.deleteTask(task.id);
                }, function () {
                    return $q.reject({noerror: true});
                }
            ).then(
                function (result) {
                    FlashService.Success("Deleted Task.");
                    vm.tasks.splice(findInArray(vm.tasks, task), 1);
                },
                function (error) {
                    if (!error.noerror)
                        FlashService.Error(error);
                }
            );
        };

        $scope.rateTask = function (task, decision) {
            var ratingJson = {};
            switch (decision) {
                case 'positive': {
                    ratingJson = {'positive': 1, 'needReview': 0, 'negative': 0};
                    break;
                }
                case 'needReview': {
                    ratingJson = {'positive': 0, 'needReview': 1, 'negative': 0};
                    break;
                }
                case 'negative': {
                    ratingJson = {'positive': 0, 'needReview': 0, 'negative': 1};
                    break;
                }
            }
            TaskService.rateTask(task.id, ratingJson).then(
                function (result) {
                    vm.tasks[findInArray(vm.tasks, task)] = result;

                }, function (error) {
                    FlashService.Error(error);
                }
            );
        };

        //////////////////////////////777
        //  Array functions
        //////////////////////////////777

        function findInArray(array, item) {
            for (var i = 0; i < array.length; i++) {
                if (array[i].$$hashKey === item.$$hashKey) {
                    return i;
                }
            }
            return -1;
        }

        $scope.findColumnsForTableName = function (tableName) {
            var columns = [];
            for (var i = 0; i < vm.tables.length; i++) {
                if (vm.tables[i].tableName === tableName) {
                    for (var j = 0; j < vm.tables[i].columnDefinitions.length; j++) {
                        columns.push(vm.tables[i].columnDefinitions[j].columnName);
                    }
                }
            }
            return columns;
        };

        initController();
    }
})();
<commit_msg>removed sqlstatements parameter from saving tasksets<commit_after>/**********************************************************************************************************************
*   Controller for views/task.view.html
*
*   Manages the displacement of all Homeworks.
*
*   Page is orderd via:
*   Homeworks -> TaskFiles(in the selected HW) -> SubTasks(in the selected TF) -> Submits(of the selected ST)
*
*   Selected Items are stored in $scope, the recieved data from the server in vm
*
*   The Controller is handled in states to fit the current Selection
**********************************************************************************************************************/

(function () {

angular
    .module('app')
    .controller('TasksController', TasksController);

    TasksController.$inject = ['$scope', '$uibModal', 'TaskService', 'FlashService', '$rootScope', '$location', '$filter', '$timeout', '$q'];
    function TasksController($scope, $uibModal, TaskService, FlashService, $rootScope, $location, $filter, $timeout, $q) {
        var vm = this;

        $scope.orderReverse = false;
        $scope.orderTaskSetPredicate = 'taskSetName';
        $scope.orderTaskPredicate = 'taskName';
        $scope.orderTablePredicate = 'tableName';
        $scope.search = '';

        $scope.dataTypes = [];
        $scope.tabActive = {
            intensionTables : false,
            intensionForeignKeys : false,
            extension : false,
            tasks : false
        };

        $scope.animationsEnabled = true;

        vm.taskSets = [];
        vm.tasks = [];
        vm.tables = [];
        vm.foreignKeys = [];
        $scope.selectedTaskSet = {};
        $scope.selectedTask = {};
        $scope.selectedTable = {};

        function initController() {
            getAllTaskSets();
            getColumnDefinitionDataTypes();
        }

        //////////////////////////////777
        //  Fetch initial Data
        //////////////////////////////777

        function getAllTaskSets() {
            if ($rootScope.Tasks.taskSets) {
                vm.taskSets = $rootScope.Tasks.taskSets;
                $scope.getCurrentPath();
            } else {
                TaskService.getAllTaskSets().then(
                        function (result) {
                            vm.taskSets = result;
                            $scope.getCurrentPath();
                            console.log(result);
                        }, function (error) {
                            FlashService.Error(error);
                        }
                );
            }
        }

        function getColumnDefinitionDataTypes() {

            TaskService.getColumnDefinitionDataTypes().then(
                function (result) {
                    vm.dataTypes = result;
                },
                null
            );
        }

        function getTasksForTaskSet(taskSet) {
            TaskService.getAllTasksForTaskSet(taskSet.id).then(
                function(result) {
                    if (result) {
                        vm.tasks = result;
                    } else {
                        vm.tasks = [];
                    }
                },
                function(error) {
                    FlashService.Error(error);
                }
            );
        }
        //////////////////////////////777
        //  Saving data when leaving View
        //  Restoring saved Data and Displaying the correct screen
        //////////////////////////////777

        $scope.keepTabActive = function () {
            $rootScope.Tasks.tabActive = $scope.tabActive;
        };

        $scope.keepTaskSets = function () {
            $rootScope.Tasks.taskSets = vm.taskSets;
        };

        $scope.$on('$locationChangeStart', function(event) {
            $scope.keepTabActive();
            $scope.keepTaskSets();
        });

        $scope.getCurrentPath = function () {
            var path = $rootScope.Tasks;

            //Find out if a TaskSet is currently selected
            if (path.selectedTaskSet) {
                $scope.tabActive = path.tabActive;
                $scope.selectTaskSet(path.selectedTaskSet);
            } else {
                return;
            }

        };

        //////////////////////////////777
        //  TaskSet - Control
        //////////////////////////////777

        /* Data */
        $scope.taskSetSelectionStatus = {
            taskSetSelected : false
        };

        var DefaultTaskSet = function() {
            this.taskSetName = "";
            this.tableDefinitions = [];
            this.foreignKeyRelations = [];
            this.tasks=[];
            this.isHomeWork = false;
        };

        /* Methods */
        $scope.pushNewTaskSet = function () {
            vm.taskSets.push(new DefaultTaskSet());
        };

        $scope.selectTaskSet = function(taskSet, destination) {
            var index = findInArray(vm.taskSets, taskSet);
            selectTaskSet(index);
            $scope.tabActive.intensionTables = true;
            getTasksForTaskSet(taskSet);
        };

        function selectTaskSet (taskSetIndex) {
            $scope.selectedTable = undefined;
            $scope.selectedTask = undefined;
            $scope.selectedTaskSet = vm.taskSets[taskSetIndex];
            vm.tables = $scope.selectedTaskSet.tableDefinitions;
            vm.foreignKeyRelations = $scope.selectedTaskSet.foreignKeyRelations;
            $rootScope.Tasks.selectedTaskSet = $scope.selectedTaskSet;
            $scope.tableSelectionStatus.tableNotSelected = true;
            $scope.tableSelectionStatus.tableSelected = false;
        }

        $scope.viewTaskSetComments = function(taskSet) {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/comment.template.html',
                    controller: 'CommentController',
                    resolve: {
                        commentTaskObject: function() {
                            return {content: taskSet, type: 'taskSet'};
                        }
                    }
            });

            modalInstance.result.then(
                FlashService.Clear
            );
        };

        /* Server Side Methods */
        $scope.saveTaskSet = function(taskSet) {
            taskSet.sqlstatements = undefined;
            if (taskSet.id !== undefined) {
                return TaskService.editTaskSet(taskSet, taskSet.id).then(
                        function (result) {
                            FlashService.Success("Updated TaskSet");

                        }, function (error) {
                            FlashService.Error(error);
                        }
                );

            } else {
                return TaskService.createTaskSet(taskSet).then(
                        function (result) {
                            FlashService.Success("Created new TaskSet");
                            vm.taskSets[findInArray(vm.taskSets, taskSet)] = result;

                        }, function (error) {
                            FlashService.Error(error);

                        }
                );

            }
        };

        $scope.exportTaskSets = function() {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/exportTaskSet.template.html',
                    controller: 'exportTaskSetController'
            });

            modalInstance.result.then(
                function (taskSetIds) {
                    return TaskService.exportTaskSets({taskSetIds: taskSetIds});
                }, null
            );
        };

        $scope.importTaskSets = function() {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/importTaskSet.template.html',
                    controller: 'importTaskSetController'
            });
        };

        $scope.saveSelectedTaskSet = function () {
             $scope.saveTaskSet($scope.selectedTaskSet);
        };

        $scope.deleteTaskSet = function (taskSet) {
            if (taskSet.id === undefined) {
                vm.taskSets.splice(findInArray(vm.taskSets, taskSet), 1);
                return;
            }

            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/sure.template.html',
                    controller: 'sureTemplateController',
                    resolve: {
                        sureTemplateMessage: function () {
                                return " Are you sure you want to delete TaskSet: " + taskSet.taskSetName + "?
 It will be deleted forever!";
                            }
                    }
            });

            modalInstance.result
            .then(
                function () {
                    return TaskService.deleteTaskSet(taskSet.id);
                },
                function () {
                    return $q.reject({noerror: true});
                }
            ).then(
                function () {
                    vm.taskSets.splice(findInArray(vm.taskSets, taskSet), 1);
                },
                function (error) {
                    if (!error.noerror)
                        FlashService.Error(error);
                }
            );
        };

        $scope.rateTaskSet = function (taskSet, decision) {
            var ratingJson = {};
            switch (decision) {
                case 'positive': {
                    ratingJson = {'positive': 1, 'needReview': 0, 'negative': 0};
                    break;
                }
                case 'needReview': {
                    ratingJson = {'positive': 0, 'needReview': 1, 'negative': 0};
                    break;
                }
                case 'negative': {
                    ratingJson = {'positive': 0, 'needReview': 0, 'negative': 1};
                    break;
                }
            }

            TaskService.rateTaskSet(taskSet.id, ratingJson).then(
                function (result) {
                    vm.taskSets[findInArray(vm.taskSets, taskSet)] = result;

                }, function (error) {
                    FlashService.Error(error);

                });
        };

        //////////////////////////////777
        //  Intension: TableDefinition - Control
        //////////////////////////////777

        /* Data */
        $scope.tableSelectionStatus = {
            tableSelected : false,
            tableNotSelected : true
        };

        var DefaultTable = function () {
            this.tableName = "";
            this.columnDefinitions = [];
            this.extension = "";
        };

        /* Methods */
        $scope.pushNewTable = function () {
            vm.tables.push(new DefaultTable());
        };

        $scope.selectTable = function (table) {
            var index = findInArray(vm.tables, table);
            selectTable(index);
            $scope.tableSelectionStatus.tableNotSelected = false;
            $scope.tableSelectionStatus.tableSelected = true;
        };

        function selectTable(tableIndex) {
            $scope.selectedTable = vm.tables[tableIndex];
            $rootScope.Tasks.selectedTable = $scope.selectedTable;
            vm.columnDefinitions = $scope.selectedTable.columnDefinitions;
        }

        /* Changes are only changed on the Server via TaskSet Actions */
        $scope.deleteTable = function (table) {
            vm.tables.splice(findInArray(vm.tables, table), 1);
        };

        //////////////////////////////777
        //  Intension: TableDefinition: Column - Control
        //////////////////////////////777

        /* Data */
        var DefaultColumn = function () {
            this.columnName = "";
            this.dataType = "BIGINT";
            this.notNull = true;
            this.primaryKey = false;
        };

        /* Methods */
        $scope.pushNewColumn = function () {
            vm.columnDefinitions.push(new DefaultColumn());
        };

        /* Changes are only changed on the Server via TaskSet Actions */
        $scope.deleteColumn = function (column) {
            vm.columnDefinitions.splice(findInArray(vm.columnDefinitions, column), 1);
        };

        //////////////////////////////777
        //  Tasks: Control
        //////////////////////////////777

        /* Data */
        var DefaultForeignKey = function () {
            this.sourceTable = "";
            this.sourceColumn = "";
            this.destinationTable = "";
            this.destinationColumn = "";
        };

        /* Methods */
        $scope.pushNewForeignKey = function () {
            vm.foreignKeyRelations.push(new DefaultForeignKey());
        };

        /* Changes are only changed on the Server via TaskSet Actions */
        $scope.deleteForeignKey = function (foreignKey) {
            vm.foreignKeyRelations.splice(findInArray(vm.foreignKeyRelations, foreignKey), 1);
        };

        //////////////////////////////777
        //  Tasks: Control
        //////////////////////////////777

        /* Data */
        var DefaultTask = function () {
            this.taskSet = $scope.selectedTaskSet.id;
            this.taskName = "";
            this.refStatement = "";
            this.evaluationStrategy = 1;
            this.points = 1;
            this.requiredTerm = 0;
            this.isCollapsed = true;
            this.availableSyntaxChecks = 0;
            this.availableSemanticChecks = 0;
        };

        /* Methods */

        $scope.pushNewTask = function () {
            vm.tasks.push(new DefaultTask());
        };

        $scope.viewTaskComments = function(task) {
            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/comment.template.html',
                    controller: 'CommentController',
                    resolve: {
                        commentTaskObject: function() {
                            return {content: task, type: 'task'};
                        }
                    }
            });

            modalInstance.result.then(
                FlashService.Clear
            );
        };

        /* Server Side Methods */
        $scope.saveTask = function (task) {
            if (task.id !== undefined) {
                TaskService.editTask(task.id, task).then(
                        function (result) {
                            FlashService.Success("Updated Task");
                        }, function (error) {
                            FlashService.Error(error);
                        }
                );
            } else {
                TaskService.createTask(task.taskSet, task).then(
                        function (result) {
                            /* Let's put in the new values we just created in BackEnd */
                            vm.tasks[findInArray(vm.tasks, task)] = result;

                            FlashService.Success("Created new Task");

                        }, function (error) {
                            FlashService.Error(error);

                        }
                );
            }
        };

        $scope.deleteTask = function (task) {
            /* If not in Database, we don't need to do much */
            if (task.id === undefined) {
                vm.tasks.splice(findInArray(vm.tasks, task), 1);
                return;
            }

            var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'assets/templates/sure.template.html',
                    controller: 'sureTemplateController',
                    resolve: {
                        sureTemplateMessage: function () {
                                return " Are you sure you want to delete Task: " + task.taskName + "?
 It will be deleted forever!";
                            }
                    }
            });

            modalInstance.result
            .then(
                function () {
                    return TaskService.deleteTask(task.id);
                }, function () {
                    return $q.reject({noerror: true});
                }
            ).then(
                function (result) {
                    FlashService.Success("Deleted Task.");
                    vm.tasks.splice(findInArray(vm.tasks, task), 1);
                },
                function (error) {
                    if (!error.noerror)
                        FlashService.Error(error);
                }
            );
        };

        $scope.rateTask = function (task, decision) {
            var ratingJson = {};
            switch (decision) {
                case 'positive': {
                    ratingJson = {'positive': 1, 'needReview': 0, 'negative': 0};
                    break;
                }
                case 'needReview': {
                    ratingJson = {'positive': 0, 'needReview': 1, 'negative': 0};
                    break;
                }
                case 'negative': {
                    ratingJson = {'positive': 0, 'needReview': 0, 'negative': 1};
                    break;
                }
            }
            TaskService.rateTask(task.id, ratingJson).then(
                function (result) {
                    vm.tasks[findInArray(vm.tasks, task)] = result;

                }, function (error) {
                    FlashService.Error(error);
                }
            );
        };

        //////////////////////////////777
        //  Array functions
        //////////////////////////////777

        function findInArray(array, item) {
            for (var i = 0; i < array.length; i++) {
                if (array[i].$$hashKey === item.$$hashKey) {
                    return i;
                }
            }
            return -1;
        }

        $scope.findColumnsForTableName = function (tableName) {
            var columns = [];
            for (var i = 0; i < vm.tables.length; i++) {
                if (vm.tables[i].tableName === tableName) {
                    for (var j = 0; j < vm.tables[i].columnDefinitions.length; j++) {
                        columns.push(vm.tables[i].columnDefinitions[j].columnName);
                    }
                }
            }
            return columns;
        };

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


<commit_before>import ActorClient from 'utils/ActorClient';
import Raven from 'utils/Raven';
import mixpanel from 'utils/Mixpanel';

import ActorAppDispatcher from 'dispatcher/ActorAppDispatcher';
import { ActionTypes, AuthSteps } from 'constants/ActorAppConstants';

import { EventEmitter } from 'events';
import assign from 'object-assign';

const CHANGE_EVENT = 'change';

let errors = {
  phone: null,
  code: null,
  signup: null
};

let step = AuthSteps.PHONE_WAIT;

let isSmsRequested = false,
    isSignupStarted = false,
    myUid = null;

var LoginStore = assign({}, EventEmitter.prototype, {
  isLoggedIn: function () {
    return (ActorClient.isLoggedIn());
  },

  getStep: () => step,

  getErrors: () => errors,

  isSmsRequested: function () {
    return (isSmsRequested);
  },

  isSignupStarted: function () {
    return (isSignupStarted);
  },

  emitChange: function () {
    this.emit(CHANGE_EVENT);
  },

  addChangeListener: function (callback) {
    this.on(CHANGE_EVENT, callback);
  },

  removeChangeListener: function (callback) {
    this.removeListener(CHANGE_EVENT, callback);
  },

  getMyId: function () {
    return (myUid);
  }
});

const processPhoneExpired = () => {
  errors.name = null;
  errors.phone = 'Phone code is expired';
  step = AuthSteps.PHONE_WAIT;
  LoginStore.emitChange();
};

LoginStore.dispatchToken = ActorAppDispatcher.register(function (action) {
  switch (action.type) {
    case ActionTypes.AUTH_SMS_REQUEST_SUCCESS:
      errors.phone = null;
      step = AuthSteps.CODE_WAIT;
      mixpanel.track('Request SMS');
      LoginStore.emitChange();
      break;
    case ActionTypes.AUTH_SMS_REQUEST_FAILURE:
      switch (action.error) {
        case 'PHONE_NUMBER_INVALID':
          errors.phone = 'Invalid number';
          break;
        default:
          errors.phone = action.error;
      }

      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_CODE_SUCCESS:
      errors.code = null;

      if (action.needSignup) {
        step = AuthSteps.SIGNUP_NAME_WAIT;
      }

      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_CODE_FAILURE:
      switch (action.error) {
        case 'PHONE_CODE_INVALID':
          errors.code = 'Invalid code';
          mixpanel.track('Invalid code');
          break;
        case 'PHONE_CODE_EXPIRED':
          processPhoneExpired();
          break;
        default:
          errors.code = action.error;
      }

      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_SIGNUP_SUCCESS:
      errors.name = null;
      step = AuthSteps.COMPLETED;
      mixpanel.track('Sign up');
      mixpanel.alias(ActorClient.getUid());
      mixpanel.people.set_once({$created: new Date()});
      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_SIGNUP_FAILURE:
      switch (action.error) {
        case 'NAME_INVALID':
          errors.signup = 'Invalid name';
          break;
        case 'PHONE_CODE_EXPIRED':
          errors.signup = null;
          processPhoneExpired();
          break;
        default:
          errors.name = action.error;
      }
      LoginStore.emitChange();
      break;
    case ActionTypes.AUTH_WRONG_NUMBER_CLICK:
      errors.phone = null;
      step = AuthSteps.PHONE_WAIT;
      LoginStore.emitChange();
      break;
    case ActionTypes.SET_LOGGED_IN:
      myUid = ActorClient.getUid();
      const user = ActorClient.getUser(myUid);
      Raven.setUserContext({id: myUid});
      mixpanel.identify(myUid);
      mixpanel.people.set({
        $phone: user.phones[0],
        $name: user.name
      });
      mixpanel.track('Successful login');
      LoginStore.emitChange();
      break;
    case ActionTypes.SET_LOGGED_OUT:
      Raven.setUserContext();
      mixpanel.track('Log out');
      mixpanel.cookie.clear();
      localStorage.clear();
      location.reload();
      break;
    default:
  }
});

export default LoginStore;
<commit_msg>fix(web): disable 'Successful login' mixpanel tracking event on app reload.<commit_after>import ActorClient from 'utils/ActorClient';
import Raven from 'utils/Raven';
import mixpanel from 'utils/Mixpanel';

import ActorAppDispatcher from 'dispatcher/ActorAppDispatcher';
import { ActionTypes, AuthSteps } from 'constants/ActorAppConstants';

import { EventEmitter } from 'events';
import assign from 'object-assign';

const CHANGE_EVENT = 'change';

let errors = {
  phone: null,
  code: null,
  signup: null
};

let step = AuthSteps.PHONE_WAIT;

let isSmsRequested = false,
    isSignupStarted = false,
    myUid = null;

var LoginStore = assign({}, EventEmitter.prototype, {
  isLoggedIn: function () {
    return (ActorClient.isLoggedIn());
  },

  getStep: () => step,

  getErrors: () => errors,

  isSmsRequested: function () {
    return (isSmsRequested);
  },

  isSignupStarted: function () {
    return (isSignupStarted);
  },

  emitChange: function () {
    this.emit(CHANGE_EVENT);
  },

  addChangeListener: function (callback) {
    this.on(CHANGE_EVENT, callback);
  },

  removeChangeListener: function (callback) {
    this.removeListener(CHANGE_EVENT, callback);
  },

  getMyId: function () {
    return (myUid);
  }
});

const processPhoneExpired = () => {
  errors.name = null;
  errors.phone = 'Phone code is expired';
  step = AuthSteps.PHONE_WAIT;
  LoginStore.emitChange();
};

LoginStore.dispatchToken = ActorAppDispatcher.register(function (action) {
  switch (action.type) {
    case ActionTypes.AUTH_SMS_REQUEST_SUCCESS:
      errors.phone = null;
      step = AuthSteps.CODE_WAIT;
      mixpanel.track('Request SMS');
      LoginStore.emitChange();
      break;
    case ActionTypes.AUTH_SMS_REQUEST_FAILURE:
      switch (action.error) {
        case 'PHONE_NUMBER_INVALID':
          errors.phone = 'Invalid number';
          break;
        default:
          errors.phone = action.error;
      }

      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_CODE_SUCCESS:
      errors.code = null;

      if (action.needSignup) {
        step = AuthSteps.SIGNUP_NAME_WAIT;
      } else {
        mixpanel.track('Successful login');
      }

      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_CODE_FAILURE:
      switch (action.error) {
        case 'PHONE_CODE_INVALID':
          errors.code = 'Invalid code';
          mixpanel.track('Invalid code');
          break;
        case 'PHONE_CODE_EXPIRED':
          processPhoneExpired();
          break;
        default:
          errors.code = action.error;
      }

      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_SIGNUP_SUCCESS:
      errors.name = null;
      step = AuthSteps.COMPLETED;
      mixpanel.track('Sign up');
      mixpanel.alias(ActorClient.getUid());
      mixpanel.people.set_once({$created: new Date()});
      LoginStore.emitChange();
      break;
    case ActionTypes.SEND_SIGNUP_FAILURE:
      switch (action.error) {
        case 'NAME_INVALID':
          errors.signup = 'Invalid name';
          break;
        case 'PHONE_CODE_EXPIRED':
          errors.signup = null;
          processPhoneExpired();
          break;
        default:
          errors.name = action.error;
      }
      LoginStore.emitChange();
      break;
    case ActionTypes.AUTH_WRONG_NUMBER_CLICK:
      errors.phone = null;
      step = AuthSteps.PHONE_WAIT;
      LoginStore.emitChange();
      break;
    case ActionTypes.SET_LOGGED_IN:
      myUid = ActorClient.getUid();
      const user = ActorClient.getUser(myUid);
      Raven.setUserContext({id: myUid});
      mixpanel.identify(myUid);
      mixpanel.people.set({
        $phone: user.phones[0],
        $name: user.name
      });
      LoginStore.emitChange();
      break;
    case ActionTypes.SET_LOGGED_OUT:
      Raven.setUserContext();
      mixpanel.track('Log out');
      mixpanel.cookie.clear();
      localStorage.clear();
      location.reload();
      break;
    default:
  }
});

export default LoginStore;
<|endoftext|>


<commit_before>odoo.define('sms.fields', function (require) {
"use strict";

var basic_fields = require('web.basic_fields');
var core = require('web.core');
var session = require('web.session');

var _t = core._t;

/**
 * Override of FieldPhone to add a button calling SMS composer if option activated (default)
 */

var Phone = basic_fields.FieldPhone;
Phone.include({
    /**
     * By default, enable_sms is activated
     *
     * @override
     */
    init() {
        this._super.apply(this, arguments);
        this.enableSMS = 'enable_sms' in this.attrs.options ? this.attrs.options.enable_sms : true;
        // reinject in nodeOptions (and thus in this.attrs) to signal the property
        this.attrs.options.enable_sms = this.enableSMS;
    },
    /**
     * When the send SMS button is displayed, $el becomes a div wrapping
     * the original links.
     * This method makes sure we always focus the phone number
     *
     * @override
     */
    getFocusableElement() {
        if (this.enableSMS && this.mode === 'readonly') {
            return this.$('.' + this.className);
        }
        return this._super.apply(this, arguments);
    },
    //--------------------------------------------------------------------------
    // Private
    //--------------------------------------------------------------------------

    /**
     * Open SMS composer wizard
     *
     * @private
     */
    _onClickSMS: function (ev) {
        ev.preventDefault();
        ev.stopPropagation();

        var context = session.user_context;
        context = _.extend({}, context, {
            default_res_model: this.model,
            default_res_id: parseInt(this.res_id),
            default_number_field_name: this.name,
            default_composition_mode: 'comment',
        });
        var self = this;
        return this.do_action({
            title: _t('Send SMS Text Message'),
            type: 'ir.actions.act_window',
            res_model: 'sms.composer',
            target: 'new',
            views: [[false, 'form']],
            context: context,
        }, {
        on_close: function () {
            self.trigger_up('reload');
        }});
    },

    /**
     * Add a button to call the composer wizard
     *
     * @override
     * @private
     */
    _renderReadonly: function () {
        var def = this._super.apply(this, arguments);
        if (this.enableSMS && this.value) {
            var $composerButton = $('<a>', {
                title: _t('Send SMS Text Message'),
                href: '',
                class: 'ml-3 d-inline-flex align-items-center o_field_phone_sms',
                html: $('<small>', {class: 'font-weight-bold ml-1', html: 'SMS'}),
            });
            $composerButton.prepend($('<i>', {class: 'fa fa-mobile'}));
            $composerButton.on('click', this._onClickSMS.bind(this));
            this.$el = $('<div/>').append(this.$el).append($composerButton);
        }

        return def;
    },
});

return Phone;

});
<commit_msg>[IMP] sms: do not wrap phone widget element in div<commit_after>odoo.define('sms.fields', function (require) {
"use strict";

var basic_fields = require('web.basic_fields');
var core = require('web.core');
var session = require('web.session');

var _t = core._t;

/**
 * Override of FieldPhone to add a button calling SMS composer if option activated (default)
 */

var Phone = basic_fields.FieldPhone;
Phone.include({
    /**
     * By default, enable_sms is activated
     *
     * @override
     */
    init() {
        this._super.apply(this, arguments);
        this.enableSMS = 'enable_sms' in this.attrs.options ? this.attrs.options.enable_sms : true;
        // reinject in nodeOptions (and thus in this.attrs) to signal the property
        this.attrs.options.enable_sms = this.enableSMS;
    },
    /**
     * When the send SMS button is displayed, $el becomes a div wrapping
     * the original links.
     * This method makes sure we always focus the phone number
     *
     * @override
     */
    getFocusableElement() {
        if (this.enableSMS && this.mode === 'readonly') {
            return this.$el.filter('.' + this.className);
        }
        return this._super.apply(this, arguments);
    },
    //--------------------------------------------------------------------------
    // Private
    //--------------------------------------------------------------------------

    /**
     * Open SMS composer wizard
     *
     * @private
     */
    _onClickSMS: function (ev) {
        ev.preventDefault();
        ev.stopPropagation();

        var context = session.user_context;
        context = _.extend({}, context, {
            default_res_model: this.model,
            default_res_id: parseInt(this.res_id),
            default_number_field_name: this.name,
            default_composition_mode: 'comment',
        });
        var self = this;
        return this.do_action({
            title: _t('Send SMS Text Message'),
            type: 'ir.actions.act_window',
            res_model: 'sms.composer',
            target: 'new',
            views: [[false, 'form']],
            context: context,
        }, {
        on_close: function () {
            self.trigger_up('reload');
        }});
    },

    /**
     * Add a button to call the composer wizard
     *
     * @override
     * @private
     */
    _renderReadonly: function () {
        var def = this._super.apply(this, arguments);
        if (this.enableSMS && this.value) {
            var $composerButton = $('<a>', {
                title: _t('Send SMS Text Message'),
                href: '',
                class: 'ml-3 d-inline-flex align-items-center o_field_phone_sms',
                html: $('<small>', {class: 'font-weight-bold ml-1', html: 'SMS'}),
            });
            $composerButton.prepend($('<i>', {class: 'fa fa-mobile'}));
            $composerButton.on('click', this._onClickSMS.bind(this));
            this.$el = this.$el.add($composerButton);
        }

        return def;
    },
});

return Phone;

});
<|endoftext|>


<commit_before>/* global assetPath */

const _loaded = {};

function loadWithTag(path, cb) {
  const head = document.getElementsByTagName('head')[0];

  let s = document.createElement('script');
  s.src = path;
  head.appendChild(s);

  s.onload = s.onreadystatechange = function(_, abort) {
    if (abort || !s.readyState || s.readyState === "loaded" || s.readyState === "complete") {
      s = s.onload = s.onreadystatechange = null;
      if (!abort) { cb(); }
    }
  };
}

export default function loadScript(url, opts) {
  opts = opts || {};

  return new Ember.RSVP.Promise(function(resolve) {
    url = Discourse.getURL((assetPath && assetPath(url)) || url);

    // If we already loaded this url
    if (_loaded[url]) { return resolve(); }

    const cb = function() {
      _loaded[url] = true;
      resolve();
    };

    var cdnUrl = url;

    if (Discourse.CDN && url[0] === "/") {
      // ensure stuff is rooted correctly
      cdnUrl = Discourse.CDN.replace(/\/$/,"");

      // protocol agnostic so append protocol
      if ( cdnUrl[0] === "/" && cdnUrl[1] === "/") {
        cdnUrl = window.location.protocol + cdnUrl;
      }

      cdnUrl += url;
    }

    // Some javascript depends on the path of where it is loaded (ace editor)
    // to dynamically load more JS. In that case, add the `scriptTag: true`
    // option.
    if (opts.scriptTag) {
      loadWithTag(cdnUrl, cb);
    } else {
      Discourse.ajax({url: cdnUrl, dataType: "script", cache: true}).then(cb);
    }
  });
}
<commit_msg>another try at a fix<commit_after>/* global assetPath */

const _loaded = {};

function loadWithTag(path, cb) {
  const head = document.getElementsByTagName('head')[0];

  let s = document.createElement('script');
  s.src = path;
  head.appendChild(s);

  s.onload = s.onreadystatechange = function(_, abort) {
    if (abort || !s.readyState || s.readyState === "loaded" || s.readyState === "complete") {
      s = s.onload = s.onreadystatechange = null;
      if (!abort) { cb(); }
    }
  };
}

export default function loadScript(url, opts) {
  opts = opts || {};

  return new Ember.RSVP.Promise(function(resolve) {
    url = Discourse.getURL((assetPath && assetPath(url)) || url);

    // If we already loaded this url
    if (_loaded[url]) { return resolve(); }

    const cb = function() {
      _loaded[url] = true;
      resolve();
    };

    var cdnUrl = url;

    if (Discourse.CDN && url[0] === "/" && url[1] !== "/") {
      // ensure stuff is rooted correctly
      cdnUrl = Discourse.CDN.replace(/\/$/,"");

      // protocol agnostic so append protocol
      if ( cdnUrl[0] === "/" && cdnUrl[1] === "/") {
        cdnUrl = window.location.protocol + cdnUrl;
      }

      cdnUrl += url;
    }

    // Some javascript depends on the path of where it is loaded (ace editor)
    // to dynamically load more JS. In that case, add the `scriptTag: true`
    // option.
    if (opts.scriptTag) {
      loadWithTag(cdnUrl, cb);
    } else {
      Discourse.ajax({url: cdnUrl, dataType: "script", cache: true}).then(cb);
    }
  });
}
<|endoftext|>


<commit_before>import CleansUp from 'discourse/mixins/cleans-up';

var clickOutsideEventName = "mousedown.outside-user-card",
    clickDataExpand = "click.discourse-user-card",
    clickMention = "click.discourse-user-mention";

export default Discourse.View.extend(CleansUp, {
  elementId: 'user-card',
  classNameBindings: ['controller.visible::hidden', 'controller.showBadges', 'controller.hasCardBadgeImage'],
  allowBackgrounds: Discourse.computed.setting('allow_profile_backgrounds'),

  addBackground: function() {
    var url = this.get('controller.user.card_background');
    if (!this.get('allowBackgrounds')) { return; }

    var $this = this.$();
    if (!$this) { return; }

    if (Ember.empty(url)) {
      $this.css('background-image', '').addClass('no-bg');
    } else {
      $this.css('background-image', "url(" + url + ")").removeClass('no-bg');
    }
  }.observes('controller.user.card_background'),

  _setup: function() {
    var self = this;
    this.appEvents.on('poster:expand', this, '_posterExpand');

    $('html').off(clickOutsideEventName).on(clickOutsideEventName, function(e) {
      if (self.get('controller.visible')) {
        var $target = $(e.target);
        if ($target.closest('[data-user-card]').data('userCard') ||
            $target.closest('a.mention').length > 0) {
          return;
        }

        self.get('controller').close();
      }

      return true;
    });

    var expand = function(username, $target){
      self._posterExpand($target);
      self.get('controller').show(username, $target[0]);
      return false;
    };

    $('#main-outlet').on(clickDataExpand, '[data-user-card]', function(e) {
      var $target = $(e.currentTarget);
      var username = $target.data('user-card');
      return expand(username, $target);
    });

    $('#main-outlet').on(clickMention, 'a.mention', function(e) {
      var $target = $(e.target);
      var username = $target.text().replace(/^@/, '');
      return expand(username, $target);
    });
  }.on('didInsertElement'),

  _posterExpand: function(target) {
    if (!target) { return; }
    var self = this,
        width = this.$().width();
    Em.run.schedule('afterRender', function() {
      if (target) {
        var position = target.offset();
        if (position) {
          position.left += target.width() + 10;

          var overage = ($(window).width() - 50) - (position.left + width);
          if (overage < 0) {
            position.left += overage;
            position.top += target.height() + 5;
          }
          self.$().css(position);
        }
      }
    });
  },

  cleanUp: function() {
    this.get('controller').close();
  },

  _removeEvents: function() {
    $('html').off(clickOutsideEventName);
    $('#main').off(clickDataExpand);
    $('#main').off(clickMention);

    this.appEvents.off('poster:expand', this, '_posterExpand');
  }.on('willDestroyElement')

});
<commit_msg>correct positioning of user card on sites with custom headers fix regression (can not click on links in card)<commit_after>import CleansUp from 'discourse/mixins/cleans-up';

var clickOutsideEventName = "mousedown.outside-user-card",
    clickDataExpand = "click.discourse-user-card",
    clickMention = "click.discourse-user-mention";

export default Discourse.View.extend(CleansUp, {
  elementId: 'user-card',
  classNameBindings: ['controller.visible::hidden', 'controller.showBadges', 'controller.hasCardBadgeImage'],
  allowBackgrounds: Discourse.computed.setting('allow_profile_backgrounds'),

  addBackground: function() {
    var url = this.get('controller.user.card_background');
    if (!this.get('allowBackgrounds')) { return; }

    var $this = this.$();
    if (!$this) { return; }

    if (Ember.empty(url)) {
      $this.css('background-image', '').addClass('no-bg');
    } else {
      $this.css('background-image', "url(" + url + ")").removeClass('no-bg');
    }
  }.observes('controller.user.card_background'),

  _setup: function() {
    var self = this;
    this.appEvents.on('poster:expand', this, '_posterExpand');

    $('html').off(clickOutsideEventName).on(clickOutsideEventName, function(e) {
      if (self.get('controller.visible')) {
        var $target = $(e.target);
        if ($target.closest('[data-user-card]').data('userCard') ||
            $target.closest('a.mention').length > 0 ||
            $target.closest('#user-card').length > 0) {
          return;
        }

        self.get('controller').close();
      }

      return true;
    });

    var expand = function(username, $target){
      self._posterExpand($target);
      self.get('controller').show(username, $target[0]);
      return false;
    };

    $('#main-outlet').on(clickDataExpand, '[data-user-card]', function(e) {
      var $target = $(e.currentTarget);
      var username = $target.data('user-card');
      return expand(username, $target);
    });

    $('#main-outlet').on(clickMention, 'a.mention', function(e) {
      var $target = $(e.target);
      var username = $target.text().replace(/^@/, '');
      return expand(username, $target);
    });
  }.on('didInsertElement'),

  _posterExpand: function(target) {
    if (!target) { return; }
    var self = this,
        width = this.$().width();
    Em.run.schedule('afterRender', function() {
      if (target) {
        var position = target.offset();
        if (position) {
          position.left += target.width() + 10;

          var overage = ($(window).width() - 50) - (position.left + width);
          if (overage < 0) {
            position.left += overage;
            position.top += target.height() + 5;
          }

          position.top -= $('#main-outlet').offset().top;
          self.$().css(position);
        }
      }
    });
  },

  cleanUp: function() {
    this.get('controller').close();
  },

  _removeEvents: function() {
    $('html').off(clickOutsideEventName);
    $('#main').off(clickDataExpand);
    $('#main').off(clickMention);

    this.appEvents.off('poster:expand', this, '_posterExpand');
  }.on('willDestroyElement')

});
<|endoftext|>


<commit_before>(function() {
  window.shared || (window.shared = {});
  var dom = window.shared.ReactHelpers.dom;
  var createEl = window.shared.ReactHelpers.createEl;
  var merge = window.shared.ReactHelpers.merge;
  var QuadConverter = window.shared.QuadConverter;

  var ProfileChartSettings = window.ProfileChartSettings;
  var HighchartsWrapper = window.shared.HighchartsWrapper;

  // Component for all charts in the profile page.
  window.shared.ProfileChart = React.createClass({
    displayName: 'ProfileChart',

    propTypes: {
      quadSeries: React.PropTypes.arrayOf( // you can plot multiple series on the same graph
        React.PropTypes.shape({
          name: React.PropTypes.string.isRequired, // e.g. 'Scaled score'
          data: React.PropTypes.array.isRequired // [year, month, date, value] quads
        })
      ),
      titleText: React.PropTypes.string.isRequired, // e.g. 'MCAS scores, last 4 years'
      yAxis: React.PropTypes.object.isRequired, // options for rendering the y-axis
      student: React.PropTypes.object.isRequired
    },

    getDefaultProps: function() {
      var now = moment.utc().toDate();
      // The intent of fixing this date range is that when staff are looking at profile of different students,
      // the scales are consistent (and not changing between 3 mos and 6 years depending on the student's record,
      // since that's easy to miss and misinterpret.
      var intervalBack = [4, 'years'];

      return {
        now: now,
        intervalBack: intervalBack,
        timestampRange: {
          min: moment(now).subtract(4, 'years').toDate().getTime(),
          max: now.getTime(),
        }
      };
    },

    render: function() {
      return createEl(HighchartsWrapper, merge(this.baseOptions(), {
        series: this.props.quadSeries.map(function(obj){
          return {
            name: obj.name,
            data: obj.data ? _.map(obj.data, QuadConverter.toPair): []
          }
        }),
        yAxis: this.props.yAxis
      }));
    },

    getSchoolYearStartPositions: function(n, now, current_grade){
      // Takes in an integer (number of months back), the current date as a Moment object (UTC), and the student's current grade.
      // Returns an object mapping integer (tick position) --> string (school year starting at that position).

      var range = [now.clone().subtract(n, 'months'), now];
      var startDates = QuadConverter.schoolYearStartDates(range);
      var create_label = function(current, current_grade){
        return _.template("<%=year%> - <%=year + 1%>
Grade <%=grade%>")({
          year: current.year(),
          grade: current_grade
        });
      };

      return _.object(
        startDates.map(function(date){ return date.valueOf(); }),
        startDates.map(function(date){ return create_label(date, 5); })
      );
    },

    baseOptions: function() {
      var positionsForYearStarts = this.getSchoolYearStartPositions(
        48, moment.utc(), parseInt(this.props.student.grade)
      );

      return merge(ProfileChartSettings.base_options, {
        xAxis: [
          merge(ProfileChartSettings.x_axis_datetime, {
            plotLines: this.x_axis_bands,
            min: this.props.timestampRange.min,
            max: this.props.timestampRange.max
          }),
          {
            type: "datetime",
            offset: 35,
            linkedTo: 0,
            tickPositions: _.keys(positionsForYearStarts).map(Number),
            categories: positionsForYearStarts,
          }
        ]
      });
    },
  });
})();
<commit_msg>Now assuming student grade goes down by 1 each year.<commit_after>(function() {
  window.shared || (window.shared = {});
  var dom = window.shared.ReactHelpers.dom;
  var createEl = window.shared.ReactHelpers.createEl;
  var merge = window.shared.ReactHelpers.merge;
  var QuadConverter = window.shared.QuadConverter;

  var ProfileChartSettings = window.ProfileChartSettings;
  var HighchartsWrapper = window.shared.HighchartsWrapper;

  // Component for all charts in the profile page.
  window.shared.ProfileChart = React.createClass({
    displayName: 'ProfileChart',

    propTypes: {
      quadSeries: React.PropTypes.arrayOf( // you can plot multiple series on the same graph
        React.PropTypes.shape({
          name: React.PropTypes.string.isRequired, // e.g. 'Scaled score'
          data: React.PropTypes.array.isRequired // [year, month, date, value] quads
        })
      ),
      titleText: React.PropTypes.string.isRequired, // e.g. 'MCAS scores, last 4 years'
      yAxis: React.PropTypes.object.isRequired, // options for rendering the y-axis
      student: React.PropTypes.object.isRequired
    },

    getDefaultProps: function() {
      var now = moment.utc().toDate();
      // The intent of fixing this date range is that when staff are looking at profile of different students,
      // the scales are consistent (and not changing between 3 mos and 6 years depending on the student's record,
      // since that's easy to miss and misinterpret.
      var intervalBack = [4, 'years'];

      return {
        now: now,
        intervalBack: intervalBack,
        timestampRange: {
          min: moment(now).subtract(4, 'years').toDate().getTime(),
          max: now.getTime(),
        }
      };
    },

    render: function() {
      return createEl(HighchartsWrapper, merge(this.baseOptions(), {
        series: this.props.quadSeries.map(function(obj){
          return {
            name: obj.name,
            data: obj.data ? _.map(obj.data, QuadConverter.toPair): []
          }
        }),
        yAxis: this.props.yAxis
      }));
    },

    getSchoolYearStartPositions: function(n, now, current_grade){
      // Takes in an integer (number of months back), the current date as a Moment object (UTC), and the student's current grade.
      // Returns an object mapping integer (timestamp) --> string (school year starting at that position).

      var range = [now.clone().subtract(n, 'months'), now];
      var startDates = QuadConverter.schoolYearStartDates(range);
      var create_label = function(current, grade){
        // Assumes that the student progressed grades in the usual fashion; wasn't held back or skipped forward.
        // John Breslin says these events are very rare.
        return _.template("Grade <%=grade%>
started")({
          year: current.year(),
          grade: grade
        });
      };

      return _.object(
        startDates.map(function(date){ return date.valueOf(); }),
        startDates.map(function(date, i){
          return create_label(
            date,
            (current_grade - startDates.length) + (i + 1) // (current_grade - n/12) to current_grade inclusive
          );
        })
      );
    },

    baseOptions: function() {
      var positionsForYearStarts = this.getSchoolYearStartPositions(
        48, moment.utc(), parseInt(this.props.student.grade)
      );

      return merge(ProfileChartSettings.base_options, {
        xAxis: [
          merge(ProfileChartSettings.x_axis_datetime, {
            plotLines: this.x_axis_bands,
            min: this.props.timestampRange.min,
            max: this.props.timestampRange.max
          }),
          {
            type: "datetime",
            offset: 35,
            linkedTo: 0,
            tickPositions: _.keys(positionsForYearStarts).map(Number),
            categories: positionsForYearStarts,
          }
        ]
      });
    },
  });
})();
<|endoftext|>


<commit_before>define([
    "dojo/_base/declare",
    "dojo/text!./dbscripts/feedback.sql",
    "dojo/text!./dbscripts/settings.sql",
    "dojo/text!./dbscripts/users.sql"
], function (declare, feedbackSQL, settingsSQL, usersSQL)
{
    var onSQLError = window.onSQLError = function (err)
    {
        console.error(JSON.stringify(err));
    };

    var dbUtil = {
        annoDB: null,
        firstInstall:false,
        dbIsReady:false,
        userChecked:false,
        hasUserInLocalDB:false,
        localUserInfo:null,
        createCommentTableIndexScript: "CREATE INDEX feedback_comment_created ON feedback_comment(created)",
        initDB: function(callback)
        {
            this.callback = callback;
            this.annoDB = window.sqlitePlugin.openDatabase({name: "anno", bgType2: 1});
            this.checkTables();

            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fs){
                localFileSystem = fs;
            });
        },
        reconnectToDB:function()
        {
            this.annoDB = window.sqlitePlugin.openDatabase({name: "anno", bgType2: 1});
            console.log("db reconnected.");
        },
        checkTables: function()
        {
            var self = this;
            this.annoDB.executeSql("SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='feedback_comment'", [], function(res) {
                if (!res) return;

                if (res.rows.item(0).cnt == 1)
                {
                    self.doUpgrade();
                    self.dbIsReady = true;
                }
                else
                {
                    self.firstInstall = true;
                    self.initTables();
                }

                console.log("dbIsReady! ");
            });
        },
        initTables: function()
        {
            var self = this;
            this.annoDB.transaction(function(tx) {
                tx.executeSql(feedbackSQL);
                tx.executeSql(self.createCommentTableIndexScript);
                tx.executeSql(settingsSQL);
                tx.executeSql(usersSQL);
                //tx.executeSql("insert into app_settings(item, value) values('ServerURL','1')");
                self.dbIsReady = true;
                self.userChecked = true;

                if (self.callback)
                {
                    window.setTimeout(function(){
                        self.callback();
                    }, 5);
                }
            });
        },
        doUpgrade: function()
        {
            var self = this;
            this.annoDB.executeSql("SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='app_users'", [], function(res) {
                if (!res) return;

                // console.log("app_users " + res.rows.item(0).cnt);

                if (res.rows.item(0).cnt == 0)
                {
                    self.annoDB.executeSql(usersSQL);
                    self.userChecked = true;
                }
                else
                {
                    // check if the db schema need be upgraded.
                    self.annoDB.executeSql("pragma table_info (app_users);", [], function(pres) {
                        if (!pres) return;

                        var rows = pres.rows;
                        var tempObj = {};
                        for (var i=0;i<rows.length;i++)
                        {
                            var item = rows.item(i);
                            tempObj[item.name] = item;
                        }

                        // console.error("doUpgrade "+JSON.stringify(tempObj));

                        if (!tempObj["teamkey"] && !tempObj["teamsecret"]) {
                            self.annoDB.executeSql("alter table app_users add column teamkey text");
                            self.annoDB.executeSql("alter table app_users add column teamsecret text");
                        }

                        if (!tempObj["signedup"])
                        {
                            self.annoDB.executeSql("alter table app_users add column signedup integer default 0", [], function(pures){
                                console.log("signedup column added.");

                                self.annoDB.executeSql("update app_users set signedup=?", [1], function(pures){
                                    if (pures)
                                    {
                                        self.annoDB.executeSql("select * from app_users", [], function(psres){
                                            if (psres)
                                            {
                                                console.log("app_users2: " + psres.rows.length);
                                                self.hasUserInLocalDB = psres.rows.length>0;
                                                if (psres.rows.length>0)
                                                    self.localUserInfo = psres.rows.item(0);
                                                self.userChecked = true;
                                                console.log("app_users: " + JSON.stringify(self.localUserInfo));
                                            }
                                        });
                                    }
                                });
                            });
                        }
                        else
                        {
                            self.annoDB.executeSql("select * from app_users", [], function(ures){
                                if (ures)
                                {
                                    // console.log("app_users2: " + ures.rows.length);
                                    self.hasUserInLocalDB = ures.rows.length>0;
                                    if (ures.rows.length>0)
                                        self.localUserInfo = ures.rows.item(0);
                                    self.userChecked = true;
                                    // console.error("app_users: "+JSON.stringify(self.localUserInfo));
                                }
                            });
                        }

                    });
                }
            });

            // check if the db schema need be upgraded.
            this.annoDB.executeSql("pragma table_info (feedback_comment);", [], function(res) {
                if (!res) return;

                // console.error("doUpgrade "+JSON.stringify(tempObj));
                var columns = [
                    {name:'_id', type:'integer', extra:'primary key autoincrement'},
                    {name:'comment', type:'text', constraint:'not null'},
                    {name:'screenshot_key', type:'text', constraint:'not null'},
                    {name:'app_version', type:'text'},
                    {name:'os_version', type:'text'},
                    {name:'last_update', type:'integer', constraint:'not null'},
                    {name:'object_key', type:'text'},
                    {name:'level', type:'integer', constraint: 'not null'},
                    {name:'app_name', type:'text'},
                    {name:'model', type:'text'},
                    {name:'source', type:'text'},
                    {name:'os_name', type:'text', 'default':"'Android'"},
                    {name:'anno_type', type:'text', 'default':"'simple comment'"},
                    {name:'synched', type:'integer', 'default':0},
                    {name:'created', type:'VARCHAR(30)', 'default':"'0'"},
                    {name:'draw_elements', type:'text'},
                    {name:'draw_is_anonymized', type:'integer', 'default':0},
                    {name:'team_key', type:'text'},
                    {name:'screen_info', type:'text'}
                    // {name:'column_is_anonymized', type:'integer', 'default':0}
                ];

                var rows = res.rows;
                var tempObj = {};
                var name_list = [];
                for (var i=0;i<rows.length;i++)
                {
                    var item = rows.item(i);
                    tempObj[item.name] = item;
                    name_list.push(item.name);
                }

                for(var i = 0; i < columns.length; i ++) {
                    if (tempObj[columns[i].name]) {
                        name_list.splice(name_list.indexOf(columns[i].name), 1);
                        continue;
                    }

                    var alter_stmnt = 'alter table feedback_comment add column ' + columns[i].name + ' ' + columns[i].type;
                    if (columns[i].constraint !== undefined)
                        alter_stmnt += (' ' + columns[i].constraint);
                    if (columns[i].default !== undefined)
                        alter_stmnt += (' default ' + columns[i].default);
                    if (columns[i].extra !== undefined)
                        alter_stmnt += (' ' + columns[i].extra);

                    console.log("Do Upgrade Schema: " + alter_stmnt);
                    self.annoDB.executeSql(alter_stmnt, [], function(res) {
                        console.log("Add Column: " + JSON.stringify(res));
                    });
                }

                // No Drop column support in SQLite
                // for (var i = 0; i < name_list.length; i ++) {
                //     alter_stmnt = "alter table feedback_comment drop " + name_list[i];
                //     console.error(alter_stmnt);
                //     self.annoDB.executeSql(alter_stmnt, [], function(res) {
                //         console.error("Drop Column: " + JSON.stringify(res));
                //     });
                // }

            });

            this.annoDB.executeSql("SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='app_settings'", [], function(res) {
                if (!res) return;

                // console.log("app_settings " + res.rows.item(0).cnt);
                if (res.rows.item(0).cnt == 0)
                {
                    self.annoDB.executeSql(settingsSQL);
                    //self.annoDB.executeSql("insert into app_settings(item, value) values('ServerURL','1')");

                    if (self.callback)
                    {
                        window.setTimeout(function(){
                            self.callback();
                        }, 5);
                    }
                }
                else
                {
                    if (self.callback)
                    {
                        window.setTimeout(function(){
                            self.callback();
                        }, 5);
                    }
                }
            });
        },
        loadLocalUserInfo: function()
        {
            var self = this;
            this.annoDB.executeSql("select * from app_users", [], function(psres){
                if (psres)
                {
                    self.hasUserInLocalDB = psres.rows.length>0;
                    if (psres.rows.length>0)
                        self.localUserInfo = psres.rows.item(0);
                    self.userChecked = true;
                    console.log("app_users: " + JSON.stringify(self.localUserInfo));
                }
            });
        },
        executeSelectSql: function(sql, params, onSuccess, onFail)
        {
            this.annoDB.executeSql(sql, params, onSuccess, onFail);
        },
        executeUpdateSql: function (sql, params, onSuccess, onFail)
        {
            this.annoDB.executeSql(sql, params, onSuccess, onFail);
        }
    };

    return dbUtil;
});<commit_msg>[Android] Add workaround for Android db locking issue<commit_after>define([
    "dojo/_base/declare",
    "dojo/text!./dbscripts/feedback.sql",
    "dojo/text!./dbscripts/settings.sql",
    "dojo/text!./dbscripts/users.sql"
], function (declare, feedbackSQL, settingsSQL, usersSQL)
{
    var onSQLError = window.onSQLError = function (err)
    {
        console.error(JSON.stringify(err));
    };

    var dbUtil = {
        annoDB: null,
        firstInstall:false,
        dbIsReady:false,
        userChecked:false,
        hasUserInLocalDB:false,
        localUserInfo:null,
        createCommentTableIndexScript: "CREATE INDEX feedback_comment_created ON feedback_comment(created)",
        initDB: function(callback)
        {
            this.callback = callback;
            this.annoDB = window.sqlitePlugin.openDatabase({name: "anno", androidLockWorkaround: 1});
            this.checkTables();

            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fs){
                localFileSystem = fs;
            });
        },
        reconnectToDB:function()
        {
            this.annoDB = window.sqlitePlugin.openDatabase({name: "anno", androidLockWorkaround: 1});
            console.log("db reconnected.");
        },
        checkTables: function()
        {
            var self = this;
            this.annoDB.executeSql("SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='feedback_comment'", [], function(res) {
                if (!res) return;

                if (res.rows.item(0).cnt == 1)
                {
                    self.doUpgrade();
                    self.dbIsReady = true;
                }
                else
                {
                    self.firstInstall = true;
                    self.initTables();
                }

                console.log("dbIsReady! ");
            });
        },
        initTables: function()
        {
            var self = this;
            this.annoDB.transaction(function(tx) {
                tx.executeSql(feedbackSQL);
                tx.executeSql(self.createCommentTableIndexScript);
                tx.executeSql(settingsSQL);
                tx.executeSql(usersSQL);
                //tx.executeSql("insert into app_settings(item, value) values('ServerURL','1')");
                self.dbIsReady = true;
                self.userChecked = true;

                if (self.callback)
                {
                    window.setTimeout(function(){
                        self.callback();
                    }, 5);
                }
            });
        },
        doUpgrade: function()
        {
            var self = this;
            this.annoDB.executeSql("SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='app_users'", [], function(res) {
                if (!res) return;

                // console.log("app_users " + res.rows.item(0).cnt);

                if (res.rows.item(0).cnt == 0)
                {
                    self.annoDB.executeSql(usersSQL);
                    self.userChecked = true;
                }
                else
                {
                    // check if the db schema need be upgraded.
                    self.annoDB.executeSql("pragma table_info (app_users);", [], function(pres) {
                        if (!pres) return;

                        var rows = pres.rows;
                        var tempObj = {};
                        for (var i=0;i<rows.length;i++)
                        {
                            var item = rows.item(i);
                            tempObj[item.name] = item;
                        }

                        // console.error("doUpgrade "+JSON.stringify(tempObj));

                        if (!tempObj["teamkey"] && !tempObj["teamsecret"]) {
                            self.annoDB.executeSql("alter table app_users add column teamkey text");
                            self.annoDB.executeSql("alter table app_users add column teamsecret text");
                        }

                        if (!tempObj["signedup"])
                        {
                            self.annoDB.executeSql("alter table app_users add column signedup integer default 0", [], function(pures){
                                console.log("signedup column added.");

                                self.annoDB.executeSql("update app_users set signedup=?", [1], function(pures){
                                    if (pures)
                                    {
                                        self.annoDB.executeSql("select * from app_users", [], function(psres){
                                            if (psres)
                                            {
                                                console.log("app_users2: " + psres.rows.length);
                                                self.hasUserInLocalDB = psres.rows.length>0;
                                                if (psres.rows.length>0)
                                                    self.localUserInfo = psres.rows.item(0);
                                                self.userChecked = true;
                                                console.log("app_users: " + JSON.stringify(self.localUserInfo));
                                            }
                                        });
                                    }
                                });
                            });
                        }
                        else
                        {
                            self.annoDB.executeSql("select * from app_users", [], function(ures){
                                if (ures)
                                {
                                    // console.log("app_users2: " + ures.rows.length);
                                    self.hasUserInLocalDB = ures.rows.length>0;
                                    if (ures.rows.length>0)
                                        self.localUserInfo = ures.rows.item(0);
                                    self.userChecked = true;
                                    // console.error("app_users: "+JSON.stringify(self.localUserInfo));
                                }
                            });
                        }

                    });
                }
            });

            // check if the db schema need be upgraded.
            this.annoDB.executeSql("pragma table_info (feedback_comment);", [], function(res) {
                if (!res) return;

                // console.error("doUpgrade "+JSON.stringify(tempObj));
                var columns = [
                    {name:'_id', type:'integer', extra:'primary key autoincrement'},
                    {name:'comment', type:'text', constraint:'not null'},
                    {name:'screenshot_key', type:'text', constraint:'not null'},
                    {name:'app_version', type:'text'},
                    {name:'os_version', type:'text'},
                    {name:'last_update', type:'integer', constraint:'not null'},
                    {name:'object_key', type:'text'},
                    {name:'level', type:'integer', constraint: 'not null'},
                    {name:'app_name', type:'text'},
                    {name:'model', type:'text'},
                    {name:'source', type:'text'},
                    {name:'os_name', type:'text', 'default':"'Android'"},
                    {name:'anno_type', type:'text', 'default':"'simple comment'"},
                    {name:'synched', type:'integer', 'default':0},
                    {name:'created', type:'VARCHAR(30)', 'default':"'0'"},
                    {name:'draw_elements', type:'text'},
                    {name:'draw_is_anonymized', type:'integer', 'default':0},
                    {name:'team_key', type:'text'},
                    {name:'screen_info', type:'text'}
                    // {name:'column_is_anonymized', type:'integer', 'default':0}
                ];

                var rows = res.rows;
                var tempObj = {};
                var name_list = [];
                for (var i=0;i<rows.length;i++)
                {
                    var item = rows.item(i);
                    tempObj[item.name] = item;
                    name_list.push(item.name);
                }

                for(var i = 0; i < columns.length; i ++) {
                    if (tempObj[columns[i].name]) {
                        name_list.splice(name_list.indexOf(columns[i].name), 1);
                        continue;
                    }

                    var alter_stmnt = 'alter table feedback_comment add column ' + columns[i].name + ' ' + columns[i].type;
                    if (columns[i].constraint !== undefined)
                        alter_stmnt += (' ' + columns[i].constraint);
                    if (columns[i].default !== undefined)
                        alter_stmnt += (' default ' + columns[i].default);
                    if (columns[i].extra !== undefined)
                        alter_stmnt += (' ' + columns[i].extra);

                    console.log("Do Upgrade Schema: " + alter_stmnt);
                    self.annoDB.executeSql(alter_stmnt, [], function(res) {
                        console.log("Add Column: " + JSON.stringify(res));
                    });
                }

                // No Drop column support in SQLite
                // for (var i = 0; i < name_list.length; i ++) {
                //     alter_stmnt = "alter table feedback_comment drop " + name_list[i];
                //     console.error(alter_stmnt);
                //     self.annoDB.executeSql(alter_stmnt, [], function(res) {
                //         console.error("Drop Column: " + JSON.stringify(res));
                //     });
                // }

            });

            this.annoDB.executeSql("SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='app_settings'", [], function(res) {
                if (!res) return;

                // console.log("app_settings " + res.rows.item(0).cnt);
                if (res.rows.item(0).cnt == 0)
                {
                    self.annoDB.executeSql(settingsSQL);
                    //self.annoDB.executeSql("insert into app_settings(item, value) values('ServerURL','1')");

                    if (self.callback)
                    {
                        window.setTimeout(function(){
                            self.callback();
                        }, 5);
                    }
                }
                else
                {
                    if (self.callback)
                    {
                        window.setTimeout(function(){
                            self.callback();
                        }, 5);
                    }
                }
            });
        },
        loadLocalUserInfo: function()
        {
            var self = this;
            this.annoDB.executeSql("select * from app_users", [], function(psres){
                if (psres)
                {
                    self.hasUserInLocalDB = psres.rows.length>0;
                    if (psres.rows.length>0)
                        self.localUserInfo = psres.rows.item(0);
                    self.userChecked = true;
                    console.log("app_users: " + JSON.stringify(self.localUserInfo));
                }
            });
        },
        executeSelectSql: function(sql, params, onSuccess, onFail)
        {
            this.annoDB.executeSql(sql, params, onSuccess, onFail);
        },
        executeUpdateSql: function (sql, params, onSuccess, onFail)
        {
            this.annoDB.executeSql(sql, params, onSuccess, onFail);
        }
    };

    return dbUtil;
});<|endoftext|>


<commit_before>var Logger = require('../services/Logger');

module.exports = (function() {

  var DeviceHistoryController = {},
      log = Logger('DeviceHistoryController');

  DeviceHistoryController.find = function(req, res, next) {
    var device_id = parseInt(req.params.id, 10),
        user_id = parseInt(req.session.userid, 10);

    function foundHistory(err, history) {
      if(err) {
        log('failed getting history: ' + err);
        return res.serverError(err);
      }

      return res.status(200).json(history);
    }

    function hasPermission(has_permission) {
      if(!has_permission) {
        log('failed getting permisions: ' + err);
        return res.status(404).send('');
      }
      DeviceHistory.find({device: device_id}).populate('track').exec(foundHistory);
    }

    if(device_id >= 0 && user_id >= 0) {
      log('looking up device permisions for user['+user_id+'] device['+device_id+']');
      return DevicePermissionManager.validate(device_id, user_id, hasPermission);
    }

    return res.badRequest('invalid params');
  };

  return DeviceHistoryController;

})();
<commit_msg>[LFTAPI-75] updating device history endpoint - filtering out histories with tracks that not longer exist<commit_after>var Logger = require('../services/Logger');

module.exports = (function() {

  var DeviceHistoryController = {},
      log = Logger('DeviceHistoryController');

  DeviceHistoryController.find = function(req, res, next) {
    var device_id = parseInt(req.params.id, 10),
        user_id = parseInt(req.session.userid, 10);

    function foundHistory(err, history) {
      var tracks = [];

      if(err) {
        log('failed getting history: ' + err);
        return res.serverError(err);
      }

      var c = history.length;
      for(var i = 0; i < c; i++) {
        var h = history[i].toJSON(),
            t = h.track;

        if(!t) continue;

        h.track = t.id;
        tracks.push(h);
      }

      return res.status(200).json(tracks);
    }

    function hasPermission(has_permission) {
      if(!has_permission) {
        log('failed getting permisions: ' + err);
        return res.status(404).send('');
      }

      DeviceHistory.find({
        where: {
          device: device_id
        },
        sort: 'createdAt DESC',
        limit: 20
      }).populate('track').exec(foundHistory);
    }

    if(device_id >= 0 && user_id >= 0) {
      log('looking up device permisions for user['+user_id+'] device['+device_id+']');
      return DevicePermissionManager.validate(device_id, user_id, hasPermission);
    }

    return res.badRequest('invalid params');
  };

  return DeviceHistoryController;

})();
<|endoftext|>


<commit_before>$(function(){
    var totalChars = 0;
	var max = 250;
	var visible, invisible;

	$('.character-limit').each(function(i){
		totalChars = $(this).text().length;

        if (totalChars > max){
            visible = $(this).text().substr(0, max);
            invisible = $(this).text().substr(max, totalChars - max);

            var content = visible + '...'
                + invisible + '';

            $(this).html(content);

            $('.read-more-content').addClass('hide')
            $('.read-more-show, .read-more-hide').removeClass('hide')
        }
	});

    $('.read-more-show').on('click', function(e){
        $(this).fadeOut(400, function(){
            $(this).next('.read-more-content').removeClass('hide').slideDown(1000);
            $(this).addClass('hide');
        });
        e.preventDefault();
    });
});
<commit_msg>Fixed page (initial) loading error<commit_after>var readmore = (function(){
    var totalChars = 0;
	var max = 250;
	var visible, invisible;

	$('.character-limit').each(function(i){
		totalChars = $(this).text().length;

        if (totalChars > max){
            visible = $(this).text().substr(0, max);
            invisible = $(this).text().substr(max, totalChars - max);

            var content = visible + '...'
                + invisible + '';

            $(this).html(content);

            $('.read-more-content').addClass('hide')
            $('.read-more-show, .read-more-hide').removeClass('hide')
        }
	});

    $('.read-more-show').on('click', function(e){
        $(this).fadeOut(400, function(){
            $(this).next('.read-more-content').removeClass('hide').slideDown(1000);
            $(this).addClass('hide');
        });
        e.preventDefault();
    });
});

$(document).on("page:load ready", readmore);<|endoftext|>