<commit_before>/*******************************************************************************
 * (C) Copyright 2016 Jerome Comte and Dorian Cransac
 *
 * This file is part of STEP
 *
 * STEP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * STEP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with STEP.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
angular.module('screenConfigurationControllers',['tables','step'])

.run(function(ViewRegistry) {
  ViewRegistry.registerDashlet('admin/controller','Screens','partials/screenconfiguration/screenConfiguration.html','screens');
})

.factory('ScreenTemplates', function($http, $q) {

  var api = {};

  var screensCache = {};

  api.clearCache = function() {
    screensCache = {};
  }

  api.getScreens = function(screenId) {
    return $q(function(resolve, reject) {
      $http.get("rest/screens").then(function(response){
        resolve(response.data)
      })
    })
  }

  api.getScreenInputsByScreenId = function(screenId, params) {
    return $q(function(resolve, reject) {
      if(!params && screensCache[screenId]) {
        return resolve(screensCache[screenId]);
      } else {
        $http({url:"rest/screens/"+screenId, method:"GET", params:params}).then(function(response){
          var screenInputs = response.data;
          screensCache[screenId] = screenInputs;
          resolve(screenInputs);
        })
      }
    })
  }

  api.getScreenInputByScreenId = function(screenId, screenInputId) {
    return $q(function(resolve, reject) {
      $http.get("rest/screens/"+screenId+"/"+screenInputId).then(function(response){
        resolve(response.data)
      })
    })
  }

  api.getScreenInputModel = function(value, input) {
    var bean = new Bean(value)
    return function(value) {
      if(angular.isDefined(value)) {
        bean.setProperty(input.id,value);
      } else {
        return bean.getProperty(input.id);
      }
    }
  }

  return api;
})

.controller('ScreenConfigurationCtrl', function($rootScope, $scope, $http, stateStorage, ScreenTemplates, Dialogs, InputDialogs, AuthService) {
    stateStorage.push($scope, 'screenconfiguration', {});
    $scope.authService = AuthService;

    $scope.currentScreenId = 'executionParameters'

    ScreenTemplates.getScreens().then(function(res) {
      $scope.screens = res;
    })

    function reload() {
      $http.get("rest/screens/input/byscreen/"+$scope.currentScreenId).then(function(res) {
        $scope.screenInputs = res.data;
        ScreenTemplates.clearCache();
      });
    }

    $scope.reload = reload;

    reload();

    $scope.addInput = function() {
      InputDialogs.editScreenInput(null, $scope.currentScreenId, function() {reload()});
    }

    $scope.editInput = function(id) {
      InputDialogs.editScreenInput(id, null, function() {reload()});
    }

    $scope.moveInput = function(id, offset) {
      $http.post("rest/screens/input/"+id+"/move",offset).then(function() {
        reload();
      });
    }

    $scope.deleteInput = function(id) {
      Dialogs.showDeleteWarning().then(function() {
        $http.delete("rest/screens/input/"+id).then(function() {
          reload();
        });
      })
    }

    $scope.tableHandle = {};
  })

.factory('InputDialogs', function ($uibModal, $http, Dialogs) {

  function openModal(id, screenId) {
    var modalInstance = $uibModal.open({
      backdrop: 'static',
        templateUrl: 'partials/screenconfiguration/editScreenInputDialog.html',
        controller: 'editScreenInputCtrl',
        resolve: {id: function () {return id;}, screenId: function () {return screenId;}}
      });

      return modalInstance.result;
  }

  var dialogs = {};

  dialogs.editScreenInput = function(id, screenId, callback) {
    openModal(id, screenId).then(function() {
      if(callback){callback()};
    })
  }

  return dialogs;
})

.controller('editScreenInputCtrl', function ($scope, $uibModalInstance, $http, AuthService, id, screenId) {

  if(id==null) {
    $scope.input = {screenId:screenId, input: {}}
  } else {
    $http.get("rest/screens/input/"+id).then(function(response){
      $scope.input = response.data;
    })
  }

  $scope.addOption = function() {
    if(!$scope.input.input.options) {
      $scope.input.input.options = [];
    }
    $scope.input.input.options.push({value:"",activationExpression:{script:""}});
  }

  $scope.moveOption = function(value, offset) {
    var options = $scope.input.input.options;
    var position = _.findIndex(options, function(option) {return option && option.value == value});
    var newPosition = position + offset;
    if(newPosition >= 0 && newPosition < options.length) {
      var item = options[position];
      options.splice(position, 1);
      options.splice(newPosition, 0, item);
    }
  }

  $scope.removeOption = function(value) {
    $scope.input.input.options = _.reject($scope.input.input.options, function(option) {return option.value == value});
  }

  $scope.save = function () {
    $http.post("rest/screens/input",$scope.input).then(function(response) {
      $uibModalInstance.close();
    })
  }

  $scope.cancel = function () {
    $uibModalInstance.dismiss('cancel');
  };
})
.directive('stCustomForm', function(ScreenTemplates) {
  return {
    restrict: 'E',
    scope: {
      stScreen: '@',
      stModel: '=',
      stOnChange: '&?',
      stDisabled: '=?',
      stInline: '=?',
      stExcludeFields: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customForm.html',
    controller: function($scope) {

      function retrieveInputs() {
        var params =  _.clone($scope.stModel);
        ScreenTemplates.getScreenInputsByScreenId($scope.stScreen, params).then(function(attributes) {
          var newAttributes=_.reject(attributes, function(attribute) {
            return $scope.stExcludeFields!=null && $scope.stExcludeFields.indexOf(attribute.id) >= 0;
          });
          if($scope.attributes) {
            // If an input is deactivated due to its "activationExpression" returning false,
            // the corresponding bean property has to be deleted
            _.each($scope.attributes, function(input) {
              if(!_.find(newAttributes, function(i) {
                return i.id == input.id
              })) {
                eval('delete $scope.stModel.'+input.id)
              }
            })
          }
          $scope.attributes = newAttributes;
        })
      }

      $scope.$watch('stModel', function(value) {
        if(value) {
          retrieveInputs();
        }
      })

      $scope.saveAttributes = function() {
      	// Retrieve the inputs again to force the reevaluation of the activationExpressions of the inputs
        retrieveInputs();
        if($scope.stOnChange) {
          $scope.stOnChange();
        }
      }
    }
  }
})
.directive('stCustomFormInput', function(ScreenTemplates) {
  return {
    restrict: 'E',
    scope: {
      ngModel: '=?',
      stBean: '=?',
      stInput: '=?',
      stScreen: '=?',
      stInputId: '=?',
      ngOnChange: '&?',
      ngDisabled: '=?',
      stInline: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customFormInput.html',
    controller: function ctrl($scope) {
      if(!$scope.stInput) {
        ScreenTemplates.getScreenInputByScreenId($scope.stScreen, $scope.stInputId).then(function(input) {
          $scope.input=input
        })
      } else {
        $scope.input = $scope.stInput
      }

      $scope.model = function() {
        if($scope.stBean) {
          return ScreenTemplates.getScreenInputModel($scope.stBean, $scope.input);
        } else {
          return function(value) {
            if(angular.isDefined(value)) {
              $scope.ngModel=value;
            } else {
              return $scope.ngModel;
            }
          }
        }
      }

      $scope.saveAttributes = function() {
        if($scope.stOnChange) {
          $scope.stOnChange();
        }
      }
    }
  }
})
.directive('stCustomFormValue', function(ScreenTemplates, $compile) {
  return {
    restrict: 'E',
    scope: {
      stBean: '=?',
      stInput: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customFormValue.html',
    link: function($scope, $element, $attrs) {
      if($scope.input.valueHtmlTemplate) {
        var template = $compile($scope.input.valueHtmlTemplate)($scope)
        $element.replaceWith(template)
      }
    },
    controller: function ctrl($scope, $compile) {
      $scope.input = $scope.stInput
      $scope.model = ScreenTemplates.getScreenInputModel($scope.stBean, $scope.input);
    }
  }
})
.directive('stCustomColumns', function(ScreenTemplates) {
  return {
    restrict: 'E',
    scope: {
      stScreen: '@',
      stExcludeFields: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customColumns.html',
    controller: function($scope) {
      ScreenTemplates.getScreenInputsByScreenId($scope.stScreen).then(function(attributes) {
        $scope.attributes=_.reject(attributes, function(attribute) {
          return $scope.stExcludeFields!=null && $scope.stExcludeFields.indexOf(attribute.id) >= 0;
        });
      })
    }
  }
})<commit_msg>Avoiding focus loss on st-custom-forms<commit_after>/*******************************************************************************
 * (C) Copyright 2016 Jerome Comte and Dorian Cransac
 *
 * This file is part of STEP
 *
 * STEP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * STEP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with STEP.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
angular.module('screenConfigurationControllers',['tables','step'])

.run(function(ViewRegistry) {
  ViewRegistry.registerDashlet('admin/controller','Screens','partials/screenconfiguration/screenConfiguration.html','screens');
})

.factory('ScreenTemplates', function($http, $q) {

  var api = {};

  var screensCache = {};

  api.clearCache = function() {
    screensCache = {};
  }

  api.getScreens = function(screenId) {
    return $q(function(resolve, reject) {
      $http.get("rest/screens").then(function(response){
        resolve(response.data)
      })
    })
  }

  api.getScreenInputsByScreenId = function(screenId, params) {
    return $q(function(resolve, reject) {
      if(!params && screensCache[screenId]) {
        return resolve(screensCache[screenId]);
      } else {
        $http({url:"rest/screens/"+screenId, method:"GET", params:params}).then(function(response){
          var screenInputs = response.data;
          screensCache[screenId] = screenInputs;
          resolve(screenInputs);
        })
      }
    })
  }

  api.getScreenInputByScreenId = function(screenId, screenInputId) {
    return $q(function(resolve, reject) {
      $http.get("rest/screens/"+screenId+"/"+screenInputId).then(function(response){
        resolve(response.data)
      })
    })
  }

  api.getScreenInputModel = function(value, input) {
    var bean = new Bean(value)
    return function(value) {
      if(angular.isDefined(value)) {
        bean.setProperty(input.id,value);
      } else {
        return bean.getProperty(input.id);
      }
    }
  }

  return api;
})

.controller('ScreenConfigurationCtrl', function($rootScope, $scope, $http, stateStorage, ScreenTemplates, Dialogs, InputDialogs, AuthService) {
    stateStorage.push($scope, 'screenconfiguration', {});
    $scope.authService = AuthService;

    $scope.currentScreenId = 'executionParameters'

    ScreenTemplates.getScreens().then(function(res) {
      $scope.screens = res;
    })

    function reload() {
      $http.get("rest/screens/input/byscreen/"+$scope.currentScreenId).then(function(res) {
        $scope.screenInputs = res.data;
        ScreenTemplates.clearCache();
      });
    }

    $scope.reload = reload;

    reload();

    $scope.addInput = function() {
      InputDialogs.editScreenInput(null, $scope.currentScreenId, function() {reload()});
    }

    $scope.editInput = function(id) {
      InputDialogs.editScreenInput(id, null, function() {reload()});
    }

    $scope.moveInput = function(id, offset) {
      $http.post("rest/screens/input/"+id+"/move",offset).then(function() {
        reload();
      });
    }

    $scope.deleteInput = function(id) {
      Dialogs.showDeleteWarning().then(function() {
        $http.delete("rest/screens/input/"+id).then(function() {
          reload();
        });
      })
    }

    $scope.tableHandle = {};
  })

.factory('InputDialogs', function ($uibModal, $http, Dialogs) {

  function openModal(id, screenId) {
    var modalInstance = $uibModal.open({
      backdrop: 'static',
        templateUrl: 'partials/screenconfiguration/editScreenInputDialog.html',
        controller: 'editScreenInputCtrl',
        resolve: {id: function () {return id;}, screenId: function () {return screenId;}}
      });

      return modalInstance.result;
  }

  var dialogs = {};

  dialogs.editScreenInput = function(id, screenId, callback) {
    openModal(id, screenId).then(function() {
      if(callback){callback()};
    })
  }

  return dialogs;
})

.controller('editScreenInputCtrl', function ($scope, $uibModalInstance, $http, AuthService, id, screenId) {

  if(id==null) {
    $scope.input = {screenId:screenId, input: {}}
  } else {
    $http.get("rest/screens/input/"+id).then(function(response){
      $scope.input = response.data;
    })
  }

  $scope.addOption = function() {
    if(!$scope.input.input.options) {
      $scope.input.input.options = [];
    }
    $scope.input.input.options.push({value:"",activationExpression:{script:""}});
  }

  $scope.moveOption = function(value, offset) {
    var options = $scope.input.input.options;
    var position = _.findIndex(options, function(option) {return option && option.value == value});
    var newPosition = position + offset;
    if(newPosition >= 0 && newPosition < options.length) {
      var item = options[position];
      options.splice(position, 1);
      options.splice(newPosition, 0, item);
    }
  }

  $scope.removeOption = function(value) {
    $scope.input.input.options = _.reject($scope.input.input.options, function(option) {return option.value == value});
  }

  $scope.save = function () {
    $http.post("rest/screens/input",$scope.input).then(function(response) {
      $uibModalInstance.close();
    })
  }

  $scope.cancel = function () {
    $uibModalInstance.dismiss('cancel');
  };
})
.directive('stCustomForm', function(ScreenTemplates) {
  return {
    restrict: 'E',
    scope: {
      stScreen: '@',
      stModel: '=',
      stOnChange: '&?',
      stDisabled: '=?',
      stInline: '=?',
      stExcludeFields: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customForm.html',
    controller: function($scope) {

      function retrieveInputs() {
        var params =  _.clone($scope.stModel);
        ScreenTemplates.getScreenInputsByScreenId($scope.stScreen, params).then(function(attributes) {
          var newAttributes=_.reject(attributes, function(attribute) {
            return $scope.stExcludeFields!=null && $scope.stExcludeFields.indexOf(attribute.id) >= 0;
          });
          if($scope.attributes) {
            // If an input is deactivated due to its "activationExpression" returning false,
            // the corresponding bean property has to be deleted
            _.each($scope.attributes, function(input) {
              if(!_.find(newAttributes, function(i) {
                return i.id == input.id
              })) {
                eval('delete $scope.stModel.'+input.id)
              }
            })
          }
          // Reload attributes only if necessary to avoid focus lost on forms
          if(!angular.equals($scope.attributes, newAttributes)) {
            $scope.attributes = newAttributes;
          }
        })
      }

      $scope.$watch('stModel', function(value) {
        if(value) {
          retrieveInputs();
        }
      })

      $scope.saveAttributes = function() {
      	// Retrieve the inputs again to force the reevaluation of the activationExpressions of the inputs
        retrieveInputs();
        if($scope.stOnChange) {
          $scope.stOnChange();
        }
      }
    }
  }
})
.directive('stCustomFormInput', function(ScreenTemplates) {
  return {
    restrict: 'E',
    scope: {
      ngModel: '=?',
      stBean: '=?',
      stInput: '=?',
      stScreen: '=?',
      stInputId: '=?',
      ngOnChange: '&?',
      ngDisabled: '=?',
      stInline: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customFormInput.html',
    controller: function ctrl($scope) {
      if(!$scope.stInput) {
        ScreenTemplates.getScreenInputByScreenId($scope.stScreen, $scope.stInputId).then(function(input) {
          $scope.input=input
        })
      } else {
        $scope.input = $scope.stInput
      }

      $scope.model = function() {
        if($scope.stBean) {
          return ScreenTemplates.getScreenInputModel($scope.stBean, $scope.input);
        } else {
          return function(value) {
            if(angular.isDefined(value)) {
              $scope.ngModel=value;
            } else {
              return $scope.ngModel;
            }
          }
        }
      }

      $scope.saveAttributes = function() {
        if($scope.stOnChange) {
          $scope.stOnChange();
        }
      }
    }
  }
})
.directive('stCustomFormValue', function(ScreenTemplates, $compile) {
  return {
    restrict: 'E',
    scope: {
      stBean: '=?',
      stInput: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customFormValue.html',
    link: function($scope, $element, $attrs) {
      if($scope.input.valueHtmlTemplate) {
        var template = $compile($scope.input.valueHtmlTemplate)($scope)
        $element.replaceWith(template)
      }
    },
    controller: function ctrl($scope, $compile) {
      $scope.input = $scope.stInput
      $scope.model = ScreenTemplates.getScreenInputModel($scope.stBean, $scope.input);
    }
  }
})
.directive('stCustomColumns', function(ScreenTemplates) {
  return {
    restrict: 'E',
    scope: {
      stScreen: '@',
      stExcludeFields: '=?'
    },
    templateUrl: 'partials/screenconfiguration/customColumns.html',
    controller: function($scope) {
      ScreenTemplates.getScreenInputsByScreenId($scope.stScreen).then(function(attributes) {
        $scope.attributes=_.reject(attributes, function(attribute) {
          return $scope.stExcludeFields!=null && $scope.stExcludeFields.indexOf(attribute.id) >= 0;
        });
      })
    }
  }
})<|endoftext|>


<commit_before>'use strict';

class Pencil {

    // create Pencil.js instance
    // [[ CanvasRenderingContext2D ]]
    constructor(context2d) {
        this.ctx = context2d;
    }

    // clear whole frame
    // [[ ]]
    clear() {
        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
    }

    // draw image to the canvas
    // [[ image, sx, sy, sw, sh, dx, dy, dw, dh, rad ]]
    drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, rad) {
        if (rad === 0) {
            this.ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
        }
        else {
            this.ctx.save();
            this.ctx.translate(dx + dw/2, dy + dh/2);
            this.ctx.rotate(rad);
            this.ctx.drawImage(image, sx, sy, sw, sh, -(dw/2), -(dh/2), dw, dh);
            this.ctx.restore();
        }
    }

    // complete path started with beginPath with a fill
    // [[ color ]]
    fill(c) {
        if (c !== undefined)
            this.ctx.fillStyle = c;
        this.ctx.fill();
    }

    // complete path started with beginPath with a stroke
    // [[ color ]]
    stroke(c) {
        if (c !== undefined)
            this.ctx.strokeStyle = c;
        this.ctx.stroke();
    }

    draw(m,c) {
        this[m || 'stroke'](c);
    }

    // integration for geometry.js
    // [[ shape, color, mode ]]
    drawShape(s, c, m) {
        switch (s.__proto__.constructor) {
            case Point: {
                this.drawRect(s.x, s.y, 1, 1, c, m);
                break;
            }
            case Circle: {
                this.ctx.beginPath();
                this.ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
                this.draw(m,c);
                break;
            }
            case Line: {
                this.ctx.beginPath();
                this.ctx.moveTo(s.pt1.x, s.pt1.y);
                this.ctx.lineTo(s.pt2.x, s.pt2.y);
                this.draw(m,c);
                break;
            }
            case Rectangle:
            case Square: {
                this.drawPolygon(s.pts);
                break;
            }
        }
    }

    // draw an array of Points
    // [[ Array<Point>, color, mode ]]
    drawPolygon(pts, c, m) {
        this.ctx.beginPath();
        this.ctx.moveTo(pts[0].x, pts[1].y);
        let pa = pts.slice();
        pa.push(pa.shift());
        pa.forEach((v) => {
            this.ctx.lineTo(v.x, v.y);
        });
        this.draw(m,c);
    }

    // draw a rectangle
    // [[ x, y, width, height, color, mode ]]
    drawRect(x, y, w, h, c, m) {
        this.ctx.beginPath();
        this.ctx.rect(x,y,w,h);
        this.draw(m,c);
    }

    // draw Text
    // [[ x, y, mode, text, color, font ]]
    drawText(x, y, m, t, c, f) {
        if (c !== undefined)
            this.ctx[`${m}Style`] = c;
        if (f !== undefined)
            this.ctx.font = f;
        this.ctx[`${m}Text`](t, x, y);
    }
}
<commit_msg>Fix Pencil.drawPolygon again<commit_after>'use strict';

class Pencil {

    // create Pencil.js instance
    // [[ CanvasRenderingContext2D ]]
    constructor(context2d) {
        this.ctx = context2d;
    }

    // clear whole frame
    // [[ ]]
    clear() {
        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
    }

    // draw image to the canvas
    // [[ image, sx, sy, sw, sh, dx, dy, dw, dh, rad ]]
    drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, rad) {
        if (rad === 0) {
            this.ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
        }
        else {
            this.ctx.save();
            this.ctx.translate(dx + dw/2, dy + dh/2);
            this.ctx.rotate(rad);
            this.ctx.drawImage(image, sx, sy, sw, sh, -(dw/2), -(dh/2), dw, dh);
            this.ctx.restore();
        }
    }

    // complete path started with beginPath with a fill
    // [[ color ]]
    fill(c) {
        if (c !== undefined)
            this.ctx.fillStyle = c;
        this.ctx.fill();
    }

    // complete path started with beginPath with a stroke
    // [[ color ]]
    stroke(c) {
        if (c !== undefined)
            this.ctx.strokeStyle = c;
        this.ctx.stroke();
    }

    draw(m,c) {
        this[m || 'stroke'](c);
    }

    // integration for geometry.js
    // [[ shape, color, mode ]]
    drawShape(s, c, m) {
        switch (s.__proto__.constructor) {
            case Point: {
                this.drawRect(s.x, s.y, 1, 1, c, m);
                break;
            }
            case Circle: {
                this.ctx.beginPath();
                this.ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
                this.draw(m,c);
                break;
            }
            case Line: {
                this.ctx.beginPath();
                this.ctx.moveTo(s.pt1.x, s.pt1.y);
                this.ctx.lineTo(s.pt2.x, s.pt2.y);
                this.draw(m,c);
                break;
            }
            case Rectangle:
            case Square: {
                this.drawPolygon(s.pts);
                break;
            }
        }
    }

    // draw an array of Points
    // [[ Array<Point>, color, mode ]]
    drawPolygon(pts, c, m) {
        this.ctx.beginPath();
        this.ctx.moveTo(pts[0].x, pts[1].y);
        pts.forEach((v) => {
            this.ctx.lineTo(v.x, v.y);
        });
        this.draw(m,c);
    }

    // draw a rectangle
    // [[ x, y, width, height, color, mode ]]
    drawRect(x, y, w, h, c, m) {
        this.ctx.beginPath();
        this.ctx.rect(x,y,w,h);
        this.draw(m,c);
    }

    // draw Text
    // [[ x, y, mode, text, color, font ]]
    drawText(x, y, m, t, c, f) {
        if (c !== undefined)
            this.ctx[`${m}Style`] = c;
        if (f !== undefined)
            this.ctx.font = f;
        this.ctx[`${m}Text`](t, x, y);
    }
}
<|endoftext|>


<commit_before>/*
 * This is a hack to prevent inheritDoc and override tags from entirely removing
 * documentation of the method that inherits the documentation.
 *
 * TODO: Remove this hack when https://github.com/jsdoc3/jsdoc/issues/53
 * is addressed.
 */
exports.handlers = {

  beforeParse: function(e) {
    e.source = e.source.replace(
        /\/\*\*\r?\n?\s*\* @(inheritDoc|override)\r?\n?\s*\*\/\r?\n?/g,
        "/***\n *\n */\n");
  }

};<commit_msg>Nicer way to fix @inheritDoc<commit_after>/*
 * This is a hack to prevent inheritDoc and override tags from entirely removing
 * documentation of the method that inherits the documentation.
 *
 * TODO: Remove this hack when https://github.com/jsdoc3/jsdoc/issues/53
 * is addressed.
 */
exports.nodeVisitor = {

  visitNode: function(node, e, parser, currentSourceName) {
    if (/@(inheritDoc|override)(\n|\r)/.test(e.comment)) {
      e.preventDefault = true;
    }
  }

};<|endoftext|>


<commit_before>'use strict';

var bcrypt = require('bcrypt-nodejs'),
    Server = require('socket.io'),
    express = require('express'),
    http = require('http'),
    path = require('path'),
    mongo = require('mongojs');

var util = require('util');
var session = require('./session');
var _ = require('lodash');
var cors = require('cors');

var _validTokens = {};

function throwErr (func) {
    return function(err, data) {
        if (err) {
            throw err;
        } else {
            func.call(null, data);
        }
    };
}

function validateScene (sceneData) {
    // convert _id so mongo recognizes it
    if (sceneData.hasOwnProperty('_id')) {
        sceneData._id = mongo.ObjectId(sceneData._id);
    }

    // add _ids to all mediaObjects
    if (sceneData.hasOwnProperty('scene')) {
        if (! Array.isArray(sceneData.scene) ) {
            throw new Error('"scene" property must be an array of objects');
        } else {
            sceneData.scene.forEach(function(mediaObject) {
                if (! mediaObject.hasOwnProperty('_id')) {
                    mediaObject._id = mongo.ObjectId();
                }
            });
        }
    }

    return sceneData;
}

function validateSceneGraph (sceneGraphData) {
    //convert _id so mongo recognizes it
    if (sceneGraphData.hasOwnProperty('_id')) {
        sceneGraphData._id = mongo.ObjectId(sceneGraphData._id);
    }

    //TODO most likely more detailed validation can occur

    return sceneGraphData;
}

function addApiCalls (hub, io, socket) {
    function idSearch (id) {
        return {_id: mongo.ObjectId(id)};
    }

    function _findScene (sceneId, cb) {
        return hub.db.mediaScenes.findOne(idSearch(sceneId), cb);
    }

    function _findSceneGraph(sceneGraphId, cb) {
        return hub.db.mediaSceneGraphs.findOne(idSearch(sceneGraphId), cb);
    }

    socket.on('listScenes', function(callback) {

        console.log("listScenes groupID: " + socket.groupID);

        //console.log("listScenes");
        //console.log("groupID: " + socket.groupID);

        //AJF: if the groupID is 0 (admin) then list all scenes
        if(socket.groupID == 0)
            hub.db.mediaScenes.find({'$query': {}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        else
        {
            hub.db.mediaScenes.find({'$query': {_groupID: socket.groupID}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        }

    });

    socket.on('listSceneGraphs', function(callback) {
        hub.db.mediaSceneGraphs.find({'$query': {}}, callback);

    });

    socket.on('saveScene', function(sceneData, callback) {
        try {

            console.log("saveScene");

            var data = validateScene(sceneData);

            //AJF: save the groupID acquired from the socket if the groupID isn't already set
            console.log("data._groupID: " + data._groupID);

            if(!data._groupID)
            {
                console.log("data._groupID not set so setting to: " + socket.groupID);
                data._groupID = socket.groupID;
            }

            hub.db.mediaScenes.save(data, function(err, scene) {
                io.to(scene._id.toString()).emit('sceneUpdate', scene);

                if (callback) {
                    callback(err, scene);
                }
            });
        } catch(err) {
            if (callback) {
                callback(err.message);
            }
        }
    });

    socket.on('saveSceneGraph', function(sceneGraphData, callback) {
        try {
            var data = validateSceneGraph(sceneGraphData);

            hub.db.mediaSceneGraphs.save(data, function(err, sceneGraph) {
                io.to(sceneGraph._id.toString()).emit('sceneGraphUpdate', sceneGraph);

                if (callback) {
                    callback(err, sceneGraph);
                }
            });

        } catch(err) {
            if(callback) {
                callback(err.message);
            }
        }
    });

    socket.on('loadScene', _findScene);

    socket.on('loadSceneGraph', _findSceneGraph);

    //TODO loadSceneGraphByName

    socket.on('loadSceneByName', function(name, callback) {
        hub.db.mediaScenes.findOne({name: name}, callback);
    });

    socket.on('deleteScene', function(sceneId, callback) {
        // hub.db.mediaScenes.remove(idSearch(sceneId), function(err) {
        //     if (callback) {
        //         callback(err);
        //     }
        // });
    });

    socket.on('subScene', function(sceneId, callback) {
        _findScene(sceneId, function(err, scene) {
            socket.join(sceneId);

            if (callback) {
                callback(err, scene);
            }
        });
    });

    socket.on('unsubScene', function(sceneId, callback) {
        _findScene(sceneId, function(err, scene) {
            socket.leave(sceneId);
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('sendCommand', function(roomId, commandName, commandValue) {

        console.log("sendCommand: ", {
            roomId: roomId,
            commandName: commandName,
            commandValue: commandValue
        });

        io.to(roomId).emit('command', {name: commandName, value: commandValue});
    });

    socket.on('register', function(roomId) {

        console.log("REGISTER TO ROOM: ", roomId);

        socket.join(roomId);
    });
}

var Hub = function(config) {
    this.config = config;
    this.db = mongo.connect(config.mongo, ['mediaScenes', 'sessions', 'mediaSceneGraphs']);
    session.setClient(this.db);
};

Hub.prototype.listen = function(callback) {
    var self = this,
        app = express(),
        server = http.Server(app),
        io = new Server(server);

    this.server = server;

    app.use(cors());

    // require a valid session token for all api calls
    var validateSession =  function(req, res, next) {
        session.find(req.query.token, function(err, data) {
            if (err || ! data) {
                res.sendStatus(401);
            } else {
                next();
            }
        });
    };

    // allow cross origin requests
    io.set('origins', '*:*');
    io.sockets.on('connection', function (socket) {
        var disconnectTimer = setTimeout(function() {
            socket.disconnect();
        }, 10000);

        socket.on('auth', function (creds, callback) {

            function succeed (record) {

                //AJF: set the groupID on the socket to be used in further local calls

                //AJF: set the groupID on the socket to be used in further calls

                socket.groupID = record._groupID;
                addApiCalls(self, io, socket);
                clearTimeout(disconnectTimer);
                callback(null, record._id.toString(), socket.id, record._groupID.toString());//AJF: try to return the groupID...
            }

            function fail (msg) {
                callback(msg);
                socket.disconnect();
            }

            if (creds.hasOwnProperty('password') && creds.password && creds.password !== '') {
                //AJF: Compares the passwords and determines what group the user logging into belongs to
                if ( bcrypt.compareSync(creds.password, self.config.secret) ) {
                    session.create(0, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_1)) {
                    session.create(1, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_2)) {
                    session.create(2, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_101)) {
                    session.create(101, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_102)) {
                    session.create(102, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_103)) {
                    session.create(103, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_104)) {
                    session.create(104, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_105)) {
                    session.create(105, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_106)) {
                    session.create(106, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_107)) {
                    session.create(107, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_108)) {
                    session.create(108, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_109)) {
                    session.create(109, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_110)) {
                    session.create(110, throwErr(succeed));
                } else {
                    fail('Invalid Password');
                }

            } else if (creds.hasOwnProperty('token') && creds.token && creds.token !== '') {
                console.log("Finding session via token");
                session.find(creds.token, function(err, data) {
                        if (data) {
                            succeed(data);
                        } else {
                            fail('Invalid Token');
                        }
                    });
            } else {
                fail('Password must be provided');
            }
        });

    });

    server.listen(self.config.port, callback);
};

Hub.prototype.close = function(cb) {
    this.server.close(cb);
};

module.exports = {
    createHub: function(mongoUrl) {
        return new Hub(mongoUrl);
    }
};
<commit_msg>Added some save logging in place<commit_after>'use strict';

var bcrypt = require('bcrypt-nodejs'),
    Server = require('socket.io'),
    express = require('express'),
    http = require('http'),
    path = require('path'),
    mongo = require('mongojs');

var util = require('util');
var session = require('./session');
var _ = require('lodash');
var cors = require('cors');

var _validTokens = {};

function throwErr (func) {
    return function(err, data) {
        if (err) {
            throw err;
        } else {
            func.call(null, data);
        }
    };
}

function validateScene (sceneData) {
    // convert _id so mongo recognizes it
    if (sceneData.hasOwnProperty('_id')) {
        sceneData._id = mongo.ObjectId(sceneData._id);
    }

    // add _ids to all mediaObjects
    if (sceneData.hasOwnProperty('scene')) {
        if (! Array.isArray(sceneData.scene) ) {
            throw new Error('"scene" property must be an array of objects');
        } else {
            sceneData.scene.forEach(function(mediaObject) {
                if (! mediaObject.hasOwnProperty('_id')) {
                    mediaObject._id = mongo.ObjectId();
                }
            });
        }
    }

    return sceneData;
}

function validateSceneGraph (sceneGraphData) {
    //convert _id so mongo recognizes it
    if (sceneGraphData.hasOwnProperty('_id')) {
        sceneGraphData._id = mongo.ObjectId(sceneGraphData._id);
    }

    //TODO most likely more detailed validation can occur

    return sceneGraphData;
}

function addApiCalls (hub, io, socket) {
    function idSearch (id) {
        return {_id: mongo.ObjectId(id)};
    }

    function _findScene (sceneId, cb) {
        return hub.db.mediaScenes.findOne(idSearch(sceneId), cb);
    }

    function _findSceneGraph(sceneGraphId, cb) {
        return hub.db.mediaSceneGraphs.findOne(idSearch(sceneGraphId), cb);
    }

    socket.on('listScenes', function(callback) {

        console.log("listScenes groupID: " + socket.groupID);

        //console.log("listScenes");
        //console.log("groupID: " + socket.groupID);

        //AJF: if the groupID is 0 (admin) then list all scenes
        if(socket.groupID == 0)
            hub.db.mediaScenes.find({'$query': {}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        else
        {
            hub.db.mediaScenes.find({'$query': {_groupID: socket.groupID}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        }

    });

    socket.on('listSceneGraphs', function(callback) {
        hub.db.mediaSceneGraphs.find({'$query': {}}, callback);

    });

    socket.on('saveScene', function(sceneData, callback) {
        try {
            console.log("saveScene: ", sceneData);

            var data = validateScene(sceneData);

            console.log("saveScene after validation: ", sceneData);

            //AJF: save the groupID acquired from the socket if the groupID isn't already set
            console.log("data._groupID: " + data._groupID);

            if(!data._groupID) {
                console.log("data._groupID not set so setting to: " + socket.groupID);
                data._groupID = socket.groupID;
            }

            hub.db.mediaScenes.save(data, function(err, scene) {
                io.to(scene._id.toString()).emit('sceneUpdate', scene);

                if (callback) {
                    callback(err, scene);
                }
            });
        } catch(err) {
            if (callback) {
                callback(err.message);
            }
        }
    });

    socket.on('saveSceneGraph', function(sceneGraphData, callback) {
        try {
            var data = validateSceneGraph(sceneGraphData);

            hub.db.mediaSceneGraphs.save(data, function(err, sceneGraph) {
                io.to(sceneGraph._id.toString()).emit('sceneGraphUpdate', sceneGraph);

                if (callback) {
                    callback(err, sceneGraph);
                }
            });

        } catch(err) {
            if(callback) {
                callback(err.message);
            }
        }
    });

    socket.on('loadScene', _findScene);

    socket.on('loadSceneGraph', _findSceneGraph);

    socket.on('loadSceneByName', function(name, callback) {
        hub.db.mediaScenes.findOne({name: name}, callback);
    });

    socket.on('deleteScene', function(sceneId, callback) {
        // hub.db.mediaScenes.remove(idSearch(sceneId), function(err) {
        //     if (callback) {
        //         callback(err);
        //     }
        // });
    });

    socket.on('subScene', function(sceneId, callback) {
        _findScene(sceneId, function(err, scene) {
            socket.join(sceneId);

            if (callback) {
                callback(err, scene);
            }
        });
    });

    socket.on('unsubScene', function(sceneId, callback) {
        _findScene(sceneId, function(err, scene) {
            socket.leave(sceneId);
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('sendCommand', function(roomId, commandName, commandValue) {

        console.log("sendCommand: ", {
            roomId: roomId,
            commandName: commandName,
            commandValue: commandValue
        });

        io.to(roomId).emit('command', {name: commandName, value: commandValue});
    });

    socket.on('register', function(roomId) {

        console.log("REGISTER TO ROOM: ", roomId);

        socket.join(roomId);
    });
}

var Hub = function(config) {
    this.config = config;
    this.db = mongo.connect(config.mongo, ['mediaScenes', 'sessions', 'mediaSceneGraphs']);
    session.setClient(this.db);
};

Hub.prototype.listen = function(callback) {
    var self = this,
        app = express(),
        server = http.Server(app),
        io = new Server(server);

    this.server = server;

    app.use(cors());

    // require a valid session token for all api calls
    var validateSession =  function(req, res, next) {
        session.find(req.query.token, function(err, data) {
            if (err || ! data) {
                res.sendStatus(401);
            } else {
                next();
            }
        });
    };

    // allow cross origin requests
    io.set('origins', '*:*');
    io.sockets.on('connection', function (socket) {
        var disconnectTimer = setTimeout(function() {
            socket.disconnect();
        }, 10000);

        socket.on('auth', function (creds, callback) {

            function succeed (record) {

                //AJF: set the groupID on the socket to be used in further local calls

                //AJF: set the groupID on the socket to be used in further calls

                socket.groupID = record._groupID;
                addApiCalls(self, io, socket);
                clearTimeout(disconnectTimer);
                callback(null, record._id.toString(), socket.id, record._groupID.toString());//AJF: try to return the groupID...
            }

            function fail (msg) {
                callback(msg);
                socket.disconnect();
            }

            if (creds.hasOwnProperty('password') && creds.password && creds.password !== '') {
                //AJF: Compares the passwords and determines what group the user logging into belongs to
                if ( bcrypt.compareSync(creds.password, self.config.secret) ) {
                    session.create(0, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_1)) {
                    session.create(1, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_2)) {
                    session.create(2, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_101)) {
                    session.create(101, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_102)) {
                    session.create(102, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_103)) {
                    session.create(103, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_104)) {
                    session.create(104, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_105)) {
                    session.create(105, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_106)) {
                    session.create(106, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_107)) {
                    session.create(107, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_108)) {
                    session.create(108, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_109)) {
                    session.create(109, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_110)) {
                    session.create(110, throwErr(succeed));
                } else {
                    fail('Invalid Password');
                }

            } else if (creds.hasOwnProperty('token') && creds.token && creds.token !== '') {
                console.log("Finding session via token");
                session.find(creds.token, function(err, data) {
                        if (data) {
                            succeed(data);
                        } else {
                            fail('Invalid Token');
                        }
                    });
            } else {
                fail('Password must be provided');
            }
        });

    });

    server.listen(self.config.port, callback);
};

Hub.prototype.close = function(cb) {
    this.server.close(cb);
};

module.exports = {
    createHub: function(mongoUrl) {
        return new Hub(mongoUrl);
    }
};
<|endoftext|>


<commit_before>'use strict';

var bcrypt = require('bcrypt-nodejs'),
    Server = require('socket.io'),
    express = require('express'),
    http = require('http'),
    path = require('path'),
    mongo = require('mongojs');

var util = require('util');
var session = require('./session');
var _ = require('lodash');
var cors = require('cors');

var _validTokens = {};

function getDateForLog() {
    return new Date();
}

function throwErr (func) {
    return function(err, data) {
        if (err) {
            throw err;
        } else {
            func.call(null, data);
        }
    };
}

function validateScene (sceneData) {
    // convert _id so mongo recognizes it
    if (sceneData.hasOwnProperty('_id')) {
        sceneData._id = mongo.ObjectId(sceneData._id);
    }

    // add _ids to all mediaObjects
    if (sceneData.hasOwnProperty('scene')) {
        if (! Array.isArray(sceneData.scene) ) {
            throw new Error('"scene" property must be an array of objects');
        } else {
            sceneData.scene.forEach(function(mediaObject) {
                if (! mediaObject.hasOwnProperty('_id')) {
                    mediaObject._id = mongo.ObjectId();
                }
            });
        }
    }

    return sceneData;
}

function validateSceneGraph (sceneGraphData) {
    //convert _id so mongo recognizes it
    if (sceneGraphData.hasOwnProperty('_id')) {
        sceneGraphData._id = mongo.ObjectId(sceneGraphData._id);
    }

    //TODO most likely more detailed validation can occur

    return sceneGraphData;
}

function addApiCalls (hub, io, socket) {
    function idSearch (id) {
        return {_id: mongo.ObjectId(id)};
    }

    function _findScene (sceneId, cb) {

        console.log(getDateForLog() + " - hub.js - _findScene");

        return hub.db.mediaScenes.findOne(idSearch(sceneId), cb);
    }

    function _findSceneGraph(sceneGraphId, cb) {

        console.log(getDateForLog() + " - hub.js - _findSceneGraph");

        return hub.db.mediaSceneGraphs.findOne(idSearch(sceneGraphId), cb);
    }

    socket.on('listScenes', function(callback) {

        console.log(getDateForLog() + " - hub.js - listScenes groupID: " + socket.groupID);

        //AJF: if the groupID is 0 (admin) then list all scenes
        if(socket.groupID == 0)
            hub.db.mediaScenes.find({'$query': {}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        else
        {
            hub.db.mediaScenes.find({'$query': {_groupID: socket.groupID}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        }

    });

    socket.on('listSceneGraphs', function(callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");
        hub.db.mediaSceneGraphs.find({'$query': {}}, callback);

    });

    socket.on('saveScene', function(sceneData, callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");

        try {
            var data = validateScene(sceneData);

            console.log(getDateForLog() + " - hub.js - saveScene after validation: ", data);

			//AJF: sanity check to stop client side CTRL+Z bug blank scene reaching the db
			if(data.hasOwnProperty('themes') || data.hasOwnProperty('style') || data.hasOwnProperty('scene'))
			{
				console.log("Valid");

            //AJF: save the groupID acquired from the socket if the groupID isn't already set
            console.log(getDateForLog() + " - hub.js - saveScene data._groupID: " + data._groupID);

            if(!data._groupID) {
                console.log(getDateForLog() + " - hub.js - saveScene data._groupID not set so setting to: " + socket.groupID);
                data._groupID = socket.groupID;
            }

            hub.db.mediaScenes.save(data, function(err, scene) {
                io.to(scene._id.toString()).emit('sceneUpdate', scene);

                if (callback) {
                    callback(err, scene);
                }
            });
			}
        } catch(err) {
            if (callback) {
                callback(err.message);
            }
        }
    });

    socket.on('saveSceneGraph', function(sceneGraphData, callback) {
        try {
            console.log(getDateForLog() + " - hub.js - saveSceneGraph");

            var data = validateSceneGraph(sceneGraphData);

            hub.db.mediaSceneGraphs.save(data, function(err, sceneGraph) {
                io.to(sceneGraph._id.toString()).emit('sceneGraphUpdate', sceneGraph);

                if (callback) {
                    callback(err, sceneGraph);
                }
            });

        } catch(err) {
            if(callback) {
                callback(err.message);
            }
        }
    });

    socket.on('loadScene', _findScene);

    socket.on('loadSceneGraph', _findSceneGraph);

    socket.on('loadSceneByName', function(name, callback) {

        console.log(getDateForLog() + " - hub.js - loadSceneByName");

        hub.db.mediaScenes.findOne({name: name}, callback);
    });

    socket.on('deleteScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - deleteScene");

        hub.db.mediaScenes.remove(idSearch(sceneId), function(err) {
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('deleteSceneGraph', function(sceneGraphId, callback){

        console.log(getDateForLog() + " - hub.js - deleteSceneGraph");

        hub.db.mediaSceneGraphs.remove(idSearch(sceneGraphId), function(err){
            if(callback) {
                callback(err);
            }
        });
    });

    socket.on('subScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - subScene");

        _findScene(sceneId, function(err, scene) {
            socket.join(sceneId);

            if (callback) {
                callback(err, scene);
            }
        });
    });

    socket.on('unsubScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - unsubScene");

        _findScene(sceneId, function(err, scene) {
            socket.leave(sceneId);
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('sendCommand', function(roomId, commandName, commandValue) {

        console.log(getDateForLog() + " - hub.js - sendCommand: ", {
            roomId: roomId,
            commandName: commandName,
            commandValue: commandValue
        });

        io.to(roomId).emit('command', {name: commandName, value: commandValue});
    });

    socket.on('register', function(roomId) {

        roomId = roomId.replace("/#", "");

        console.log(getDateForLog() + " - hub.js - REGISTER TO ROOM: ", roomId);

        socket.join(roomId);
    });
}

var Hub = function(config) {
    this.config = config;
    this.db = mongo.connect(config.mongo, ['mediaScenes', 'sessions', 'mediaSceneGraphs']);
    session.setClient(this.db);
};

Hub.prototype.listen = function(callback) {
    var self = this,
        app = express(),
        server = http.Server(app),
        io = new Server(server);

    this.server = server;

    app.use(cors());

    // require a valid session token for all api calls
    var validateSession =  function(req, res, next) {
        session.find(req.query.token, function(err, data) {
            if (err || ! data) {
                res.sendStatus(401);
            } else {
                next();
            }
        });
    };

    // allow cross origin requests
    io.set('origins', '*:*');
    io.sockets.on('connection', function (socket) {
        var disconnectTimer = setTimeout(function() {
            socket.disconnect();
        }, 10000);

        socket.on('auth', function (creds, callback) {

            function succeed (record) {

                //AJF: set the groupID on the socket to be used in further local calls

                //AJF: set the groupID on the socket to be used in further calls

                socket.groupID = record._groupID;
                addApiCalls(self, io, socket);
                clearTimeout(disconnectTimer);
                callback(null, record._id.toString(), socket.id, record._groupID.toString());//AJF: try to return the groupID...
            }

            function fail (msg) {
                callback(msg);
                socket.disconnect();
            }

            if (creds.hasOwnProperty('password') && creds.password && creds.password !== '') {
                //AJF: Compares the passwords and determines what group the user logging into belongs to
                if ( bcrypt.compareSync(creds.password, self.config.secret) ) {
                    session.create(0, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_1)) {
                    session.create(1, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_2)) {
                    session.create(2, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_101)) {
                    session.create(101, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_102)) {
                    session.create(102, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_103)) {
                    session.create(103, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_104)) {
                    session.create(104, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_105)) {
                    session.create(105, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_106)) {
                    session.create(106, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_107)) {
                    session.create(107, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_108)) {
                    session.create(108, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_109)) {
                    session.create(109, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_110)) {
                    session.create(110, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_111)) {
                    session.create(111, throwErr(succeed));
                } else {
                    fail('Invalid Password');
                }

            } else if (creds.hasOwnProperty('token') && creds.token && creds.token !== '') {
                console.log("Finding session via token");
                session.find(creds.token, function(err, data) {
                        if (data) {
                            succeed(data);
                        } else {
                            fail('Invalid Token');
                        }
                    });
            } else {
                fail('Password must be provided');
            }
        });

    });

    server.listen(self.config.port, callback);
};

Hub.prototype.close = function(cb) {
    this.server.close(cb);
};

module.exports = {
    createHub: function(mongoUrl) {
        return new Hub(mongoUrl);
    }
};
<commit_msg>Hub room id testing<commit_after>'use strict';

var bcrypt = require('bcrypt-nodejs'),
    Server = require('socket.io'),
    express = require('express'),
    http = require('http'),
    path = require('path'),
    mongo = require('mongojs');

var util = require('util');
var session = require('./session');
var _ = require('lodash');
var cors = require('cors');

var _validTokens = {};

function getDateForLog() {
    return new Date();
}

function throwErr (func) {
    return function(err, data) {
        if (err) {
            throw err;
        } else {
            func.call(null, data);
        }
    };
}

function validateScene (sceneData) {
    // convert _id so mongo recognizes it
    if (sceneData.hasOwnProperty('_id')) {
        sceneData._id = mongo.ObjectId(sceneData._id);
    }

    // add _ids to all mediaObjects
    if (sceneData.hasOwnProperty('scene')) {
        if (! Array.isArray(sceneData.scene) ) {
            throw new Error('"scene" property must be an array of objects');
        } else {
            sceneData.scene.forEach(function(mediaObject) {
                if (! mediaObject.hasOwnProperty('_id')) {
                    mediaObject._id = mongo.ObjectId();
                }
            });
        }
    }

    return sceneData;
}

function validateSceneGraph (sceneGraphData) {
    //convert _id so mongo recognizes it
    if (sceneGraphData.hasOwnProperty('_id')) {
        sceneGraphData._id = mongo.ObjectId(sceneGraphData._id);
    }

    //TODO most likely more detailed validation can occur

    return sceneGraphData;
}

function addApiCalls (hub, io, socket) {
    function idSearch (id) {
        return {_id: mongo.ObjectId(id)};
    }

    function _findScene (sceneId, cb) {

        console.log(getDateForLog() + " - hub.js - _findScene");

        return hub.db.mediaScenes.findOne(idSearch(sceneId), cb);
    }

    function _findSceneGraph(sceneGraphId, cb) {

        console.log(getDateForLog() + " - hub.js - _findSceneGraph");

        return hub.db.mediaSceneGraphs.findOne(idSearch(sceneGraphId), cb);
    }

    socket.on('listScenes', function(callback) {

        console.log(getDateForLog() + " - hub.js - listScenes groupID: " + socket.groupID);

        //AJF: if the groupID is 0 (admin) then list all scenes
        if(socket.groupID == 0)
            hub.db.mediaScenes.find({'$query': {}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        else
        {
            hub.db.mediaScenes.find({'$query': {_groupID: socket.groupID}, '$orderby': {name: 1}}, {name: 1, _groupID: 2}, callback);
        }

    });

    socket.on('listSceneGraphs', function(callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");
        hub.db.mediaSceneGraphs.find({'$query': {}}, callback);

    });

    socket.on('saveScene', function(sceneData, callback) {
        console.log(getDateForLog() + " - hub.js - listSceneGraphs");

        try {
            var data = validateScene(sceneData);

            console.log(getDateForLog() + " - hub.js - saveScene after validation: ", data);

			//AJF: sanity check to stop client side CTRL+Z bug blank scene reaching the db
			if(data.hasOwnProperty('themes') || data.hasOwnProperty('style') || data.hasOwnProperty('scene'))
			{
				console.log("Valid");

            //AJF: save the groupID acquired from the socket if the groupID isn't already set
            console.log(getDateForLog() + " - hub.js - saveScene data._groupID: " + data._groupID);

            if(!data._groupID) {
                console.log(getDateForLog() + " - hub.js - saveScene data._groupID not set so setting to: " + socket.groupID);
                data._groupID = socket.groupID;
            }

            hub.db.mediaScenes.save(data, function(err, scene) {
                io.to(scene._id.toString()).emit('sceneUpdate', scene);

                if (callback) {
                    callback(err, scene);
                }
            });
			}
        } catch(err) {
            if (callback) {
                callback(err.message);
            }
        }
    });

    socket.on('saveSceneGraph', function(sceneGraphData, callback) {
        try {
            console.log(getDateForLog() + " - hub.js - saveSceneGraph");

            var data = validateSceneGraph(sceneGraphData);

            hub.db.mediaSceneGraphs.save(data, function(err, sceneGraph) {
                io.to(sceneGraph._id.toString()).emit('sceneGraphUpdate', sceneGraph);

                if (callback) {
                    callback(err, sceneGraph);
                }
            });

        } catch(err) {
            if(callback) {
                callback(err.message);
            }
        }
    });

    socket.on('loadScene', _findScene);

    socket.on('loadSceneGraph', _findSceneGraph);

    socket.on('loadSceneByName', function(name, callback) {

        console.log(getDateForLog() + " - hub.js - loadSceneByName");

        hub.db.mediaScenes.findOne({name: name}, callback);
    });

    socket.on('deleteScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - deleteScene");

        hub.db.mediaScenes.remove(idSearch(sceneId), function(err) {
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('deleteSceneGraph', function(sceneGraphId, callback){

        console.log(getDateForLog() + " - hub.js - deleteSceneGraph");

        hub.db.mediaSceneGraphs.remove(idSearch(sceneGraphId), function(err){
            if(callback) {
                callback(err);
            }
        });
    });

    socket.on('subScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - subScene");

        _findScene(sceneId, function(err, scene) {
            socket.join(sceneId);

            if (callback) {
                callback(err, scene);
            }
        });
    });

    socket.on('unsubScene', function(sceneId, callback) {

        console.log(getDateForLog() + " - hub.js - unsubScene");

        _findScene(sceneId, function(err, scene) {
            socket.leave(sceneId);
            if (callback) {
                callback(err);
            }
        });
    });

    socket.on('sendCommand', function(roomId, commandName, commandValue) {

        console.log(getDateForLog() + " - hub.js - sendCommand: ", {
            roomId: roomId,
            commandName: commandName,
            commandValue: commandValue
        });

        io.to(roomId).emit('command', {name: commandName, value: commandValue});
    });

    socket.on('register', function(roomId) {

        roomId = roomId.replace("/#", "");

        console.log(getDateForLog() + " - hub.js - REGISTER TO ROOM: ", roomId);

        socket.join(roomId);
    });
}

var Hub = function(config) {
    this.config = config;
    this.db = mongo.connect(config.mongo, ['mediaScenes', 'sessions', 'mediaSceneGraphs']);
    session.setClient(this.db);
};

Hub.prototype.listen = function(callback) {
    var self = this,
        app = express(),
        server = http.Server(app),
        io = new Server(server);

    this.server = server;

    app.use(cors());

    // require a valid session token for all api calls
    var validateSession =  function(req, res, next) {
        session.find(req.query.token, function(err, data) {
            if (err || ! data) {
                res.sendStatus(401);
            } else {
                next();
            }
        });
    };

    // allow cross origin requests
    io.set('origins', '*:*');
    io.sockets.on('connection', function (socket) {
        var disconnectTimer = setTimeout(function() {
            socket.disconnect();
        }, 10000);

        socket.on('auth', function (creds, callback) {

            function succeed (record) {

                //AJF: set the groupID on the socket to be used in further local calls

                //AJF: set the groupID on the socket to be used in further calls

                socket.groupID = record._groupID;
                addApiCalls(self, io, socket);
                clearTimeout(disconnectTimer);
                var roomId = "TEST123";
                callback(null, record._id.toString(), roomId, record._groupID.toString());//AJF: try to return the groupID...
            }

            function fail (msg) {
                callback(msg);
                socket.disconnect();
            }

            if (creds.hasOwnProperty('password') && creds.password && creds.password !== '') {
                //AJF: Compares the passwords and determines what group the user logging into belongs to
                if ( bcrypt.compareSync(creds.password, self.config.secret) ) {
                    session.create(0, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_1)) {
                    session.create(1, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_2)) {
                    session.create(2, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_101)) {
                    session.create(101, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_102)) {
                    session.create(102, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_103)) {
                    session.create(103, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_104)) {
                    session.create(104, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_105)) {
                    session.create(105, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_106)) {
                    session.create(106, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_107)) {
                    session.create(107, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_108)) {
                    session.create(108, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_109)) {
                    session.create(109, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_110)) {
                    session.create(110, throwErr(succeed));
                } else if (bcrypt.compareSync(creds.password, self.config.secret_111)) {
                    session.create(111, throwErr(succeed));
                } else {
                    fail('Invalid Password');
                }

            } else if (creds.hasOwnProperty('token') && creds.token && creds.token !== '') {
                console.log("Finding session via token");
                session.find(creds.token, function(err, data) {
                        if (data) {
                            succeed(data);
                        } else {
                            fail('Invalid Token');
                        }
                    });
            } else {
                fail('Password must be provided');
            }
        });

    });

    server.listen(self.config.port, callback);
};

Hub.prototype.close = function(cb) {
    this.server.close(cb);
};

module.exports = {
    createHub: function(mongoUrl) {
        return new Hub(mongoUrl);
    }
};
<|endoftext|>


<commit_before>'use strict';

define(['req', 'knockout', 'onefold-js', './template', './core', './extensions', 'text!ko-grid/grid.html.template', 'ko-indexed-repeat'], function (req, ko, js) {
    var document = window.document;

    var koGrid = ko.bindingHandlers['grid'] = ko.bindingHandlers['grid'] || {};
    var core = require('./core');
    var extensions = require('./extensions');
    var GridTemplate = require('./template');

    var tableTemplate = require('text!ko-grid/grid.html.template');

    var coreComponentNames = ['columns', 'headers', 'data', 'layout'];
    var coreComponents = coreComponentNames.map(n => core[n]);

    var templateEngine = new ko.nativeTemplateEngine();
    templateEngine.addTemplate = function (templateName, templateMarkup) {
        var template = document.createElement('script');
        template.id = templateName;
        template.type = 'text/html';
        template.text = templateMarkup;

        document.querySelector('head').appendChild(template);
    };

    /** @constructor */
    function Grid(rootElement, bindingValue) {
        this.primaryKey = bindingValue['primaryKey'];
        this['primaryKey'] = this.primaryKey;
        this.rootElement = rootElement;
        this['rootElement'] = rootElement;
        this.element = null;
        this['element'] = null;
        this._classes = ko.observableArray([]);
        this._dispose = js.functions.nop;

        this.__postApplyBindings = js.functions.nop;

        this.postApplyBindings = callback => {
            if (!this.__postApplyBindings)
                throw new Error('Illegal state: postApplyBindings-callbacks have been called already.');

            var innerCallback = this.__postApplyBindings;
            this.__postApplyBindings = () => {
                innerCallback();
                callback();
            };
        };
    }

    ko.bindingHandlers['grid']['init'] = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var bindingValue = valueAccessor();
        var configName = bindingValue['config'];

        loadConfig(configName, function (config, templateName, extensionLoadOrder) {
            var disposeCallbacks = [];
            var grid = new Grid(element, bindingValue);
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                grid._dispose();
                disposeCallbacks.forEach(function (callback) {
                    callback();
                });
            });

            js.objects.forEachProperty(core, function (componentName, component) {
                var instance = new component.Constructor(bindingValue, config, grid);
                grid[componentName] = instance;
                grid.columns = grid['columns'];
                grid.headers = grid['headers'];
                grid.data = grid['data'];
                grid.layout = grid['layout'];
                if (typeof instance._dispose === 'function')
                    disposeCallbacks.push(instance._dispose.bind(instance));
            });

            var extensionConfigs = config['extensions'];
            var extensionBindingValues = bindingValue['extensions'] || {};
            var gridExtensions = grid['extensions'] = grid.extensions = {};

            extensionLoadOrder.forEach(function (extensionName) {
                var extension = koGrid.lookUpExtension(extensionName);
                var extensionConfig = extension.extractConfiguration(extensionConfigs, configName);
                var extensionBindingValue = extension.tryExtractBindingValue(extensionBindingValues) || {};

                if (extensionConfig['enabled'] === false && extensionBindingValue['enabled'] !== true || extensionBindingValue['enabled'] === false)
                    return;
                extension.dependencies.forEach(function (dependency) {
                    if (!gridExtensions[dependency])
                        throw new Error('Dependency \'' + dependency + '\' was disabled.');
                });

                var instance = new extension.Constructor(extensionBindingValue, extensionConfig, grid, bindingValue, config);
                extension.knownAliases.forEach(alias => {
                    gridExtensions[alias] = instance;
                });
                if (typeof instance.dispose === 'function')
                    disposeCallbacks.push(instance.dispose.bind(instance));
            });

            while (element.firstChild)
                ko.removeNode(element.firstChild);

            coreComponentNames.forEach(function (n) {
                if (grid[n]._preApplyBindings)
                    grid[n]._preApplyBindings();
            });

            var gridContext = bindingContext.createChildContext(grid, 'grid');
            ko.renderTemplate(templateName, gridContext, {'templateEngine': templateEngine}, element);

            var gridElement = element.querySelector('.ko-grid');
            grid.element = gridElement;
            grid['element'] = gridElement;

            js.objects.forEachProperty(extensionConfigs, function (extensionName) {
                gridElement.className += ' with-' + js.strings.convertCamelToHyphenCase(extensionName);
            });

            coreComponentNames.forEach(function (n) {
                if (grid[n]._postApplyBindings)
                    grid[n]._postApplyBindings();
            });

            grid.__postApplyBindings();
            grid.__postApplyBindings = null;
        });

        return {'controlsDescendantBindings': true};
    };
    ko.bindingHandlers['grid']['update'] = js.functions.nop;

    var loadedConfigs = {};
    var loadConfig = function (configName, handler) {
        function callHandler() {
            var loadedConfig = loadedConfigs[configName];
            handler(loadedConfig.config, loadedConfig.templateName, loadedConfig.extensionLoadOrder);
        }

        if (loadedConfigs[configName])
            return callHandler();

        req([configName], function (config) {
            var template = new GridTemplate(tableTemplate);
            coreComponents.forEach(function (component) { component.init(template, config); });

            var extensionConfigs = config['extensions'];
            var loadedExtensions = [];
            var loadingExtensions = [];
            var loadExtension = function (extensionName) {
                var extension = koGrid.lookUpExtension(extensionName);
                var primaryExtensionName = extension.primaryName;
                var extensionConfig = extension.extractConfiguration(extensionConfigs, configName);

                if (js.arrays.contains(loadedExtensions, primaryExtensionName))
                    return;
                if (js.arrays.contains(loadingExtensions, primaryExtensionName))
                    throw new Error('Dependency-Cycle: .. -> ' + loadingExtensions.join(' -> ') + ' -> ' + primaryExtensionName + ' -> ..');

                loadingExtensions.push(primaryExtensionName);
                extension.dependencies.forEach(loadExtension);
                extension.initializer(template, extensionConfig, config);

                if (loadingExtensions.pop() !== primaryExtensionName)
                    throw new Error('Assertion error.');
                loadedExtensions.push(primaryExtensionName);
            };
            Object.keys(extensionConfigs).forEach(loadExtension);

            var templateName = 'ko-grid-template-' + configName;
            templateEngine.addTemplate(templateName, template.build());
            loadedConfigs[configName] = {
                config: config,
                templateName: templateName,
                extensionLoadOrder: loadedExtensions
            };

            callHandler();
        });
    };

    ko.bindingHandlers['_gridWidth'] = {
        'init': js.functions.nop,
        'update': function (element, valueAccessor) {
            var w = valueAccessor();
            element.style.width = w;
            element.style.maxWidth = w;
        }
    };

    return koGrid;
});
<commit_msg>Minor bugfix: Require modules using local `require`.<commit_after>'use strict';

define(['req', 'knockout', 'onefold-js', './template', './core', './extensions', 'text!ko-grid/grid.html.template', 'ko-indexed-repeat'], function (req, ko, js) {
    var require = req;
    var document = window.document;

    var koGrid = ko.bindingHandlers['grid'] = ko.bindingHandlers['grid'] || {};
    var core = require('./core');
    var extensions = require('./extensions');
    var GridTemplate = require('./template');

    var tableTemplate = require('text!ko-grid/grid.html.template');

    var coreComponentNames = ['columns', 'headers', 'data', 'layout'];
    var coreComponents = coreComponentNames.map(n => core[n]);

    var templateEngine = new ko.nativeTemplateEngine();
    templateEngine.addTemplate = function (templateName, templateMarkup) {
        var template = document.createElement('script');
        template.id = templateName;
        template.type = 'text/html';
        template.text = templateMarkup;

        document.querySelector('head').appendChild(template);
    };

    /** @constructor */
    function Grid(rootElement, bindingValue) {
        this.primaryKey = bindingValue['primaryKey'];
        this['primaryKey'] = this.primaryKey;
        this.rootElement = rootElement;
        this['rootElement'] = rootElement;
        this.element = null;
        this['element'] = null;
        this._classes = ko.observableArray([]);
        this._dispose = js.functions.nop;

        this.__postApplyBindings = js.functions.nop;

        this.postApplyBindings = callback => {
            if (!this.__postApplyBindings)
                throw new Error('Illegal state: postApplyBindings-callbacks have been called already.');

            var innerCallback = this.__postApplyBindings;
            this.__postApplyBindings = () => {
                innerCallback();
                callback();
            };
        };
    }

    ko.bindingHandlers['grid']['init'] = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var bindingValue = valueAccessor();
        var configName = bindingValue['config'];

        loadConfig(configName, function (config, templateName, extensionLoadOrder) {
            var disposeCallbacks = [];
            var grid = new Grid(element, bindingValue);
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                grid._dispose();
                disposeCallbacks.forEach(function (callback) {
                    callback();
                });
            });

            js.objects.forEachProperty(core, function (componentName, component) {
                var instance = new component.Constructor(bindingValue, config, grid);
                grid[componentName] = instance;
                grid.columns = grid['columns'];
                grid.headers = grid['headers'];
                grid.data = grid['data'];
                grid.layout = grid['layout'];
                if (typeof instance._dispose === 'function')
                    disposeCallbacks.push(instance._dispose.bind(instance));
            });

            var extensionConfigs = config['extensions'];
            var extensionBindingValues = bindingValue['extensions'] || {};
            var gridExtensions = grid['extensions'] = grid.extensions = {};

            extensionLoadOrder.forEach(function (extensionName) {
                var extension = koGrid.lookUpExtension(extensionName);
                var extensionConfig = extension.extractConfiguration(extensionConfigs, configName);
                var extensionBindingValue = extension.tryExtractBindingValue(extensionBindingValues) || {};

                if (extensionConfig['enabled'] === false && extensionBindingValue['enabled'] !== true || extensionBindingValue['enabled'] === false)
                    return;
                extension.dependencies.forEach(function (dependency) {
                    if (!gridExtensions[dependency])
                        throw new Error('Dependency \'' + dependency + '\' was disabled.');
                });

                var instance = new extension.Constructor(extensionBindingValue, extensionConfig, grid, bindingValue, config);
                extension.knownAliases.forEach(alias => {
                    gridExtensions[alias] = instance;
                });
                if (typeof instance.dispose === 'function')
                    disposeCallbacks.push(instance.dispose.bind(instance));
            });

            while (element.firstChild)
                ko.removeNode(element.firstChild);

            coreComponentNames.forEach(function (n) {
                if (grid[n]._preApplyBindings)
                    grid[n]._preApplyBindings();
            });

            var gridContext = bindingContext.createChildContext(grid, 'grid');
            ko.renderTemplate(templateName, gridContext, {'templateEngine': templateEngine}, element);

            var gridElement = element.querySelector('.ko-grid');
            grid.element = gridElement;
            grid['element'] = gridElement;

            js.objects.forEachProperty(extensionConfigs, function (extensionName) {
                gridElement.className += ' with-' + js.strings.convertCamelToHyphenCase(extensionName);
            });

            coreComponentNames.forEach(function (n) {
                if (grid[n]._postApplyBindings)
                    grid[n]._postApplyBindings();
            });

            grid.__postApplyBindings();
            grid.__postApplyBindings = null;
        });

        return {'controlsDescendantBindings': true};
    };
    ko.bindingHandlers['grid']['update'] = js.functions.nop;

    var loadedConfigs = {};
    var loadConfig = function (configName, handler) {
        function callHandler() {
            var loadedConfig = loadedConfigs[configName];
            handler(loadedConfig.config, loadedConfig.templateName, loadedConfig.extensionLoadOrder);
        }

        if (loadedConfigs[configName])
            return callHandler();

        req([configName], function (config) {
            var template = new GridTemplate(tableTemplate);
            coreComponents.forEach(function (component) { component.init(template, config); });

            var extensionConfigs = config['extensions'];
            var loadedExtensions = [];
            var loadingExtensions = [];
            var loadExtension = function (extensionName) {
                var extension = koGrid.lookUpExtension(extensionName);
                var primaryExtensionName = extension.primaryName;
                var extensionConfig = extension.extractConfiguration(extensionConfigs, configName);

                if (js.arrays.contains(loadedExtensions, primaryExtensionName))
                    return;
                if (js.arrays.contains(loadingExtensions, primaryExtensionName))
                    throw new Error('Dependency-Cycle: .. -> ' + loadingExtensions.join(' -> ') + ' -> ' + primaryExtensionName + ' -> ..');

                loadingExtensions.push(primaryExtensionName);
                extension.dependencies.forEach(loadExtension);
                extension.initializer(template, extensionConfig, config);

                if (loadingExtensions.pop() !== primaryExtensionName)
                    throw new Error('Assertion error.');
                loadedExtensions.push(primaryExtensionName);
            };
            Object.keys(extensionConfigs).forEach(loadExtension);

            var templateName = 'ko-grid-template-' + configName;
            templateEngine.addTemplate(templateName, template.build());
            loadedConfigs[configName] = {
                config: config,
                templateName: templateName,
                extensionLoadOrder: loadedExtensions
            };

            callHandler();
        });
    };

    ko.bindingHandlers['_gridWidth'] = {
        'init': js.functions.nop,
        'update': function (element, valueAccessor) {
            var w = valueAccessor();
            element.style.width = w;
            element.style.maxWidth = w;
        }
    };

    return koGrid;
});
<|endoftext|>


<commit_before>/* jshint expr:true */
import { expect } from 'chai'
import {
  describeComponent,
  it
} from 'ember-mocha'
import hbs from 'htmlbars-inline-precompile'

describeComponent(
  'frost-navigation',
  'Integration: FrostNavigationComponent',
  {
    integration: true
  },
  function () {}
)
<commit_msg>fix for eslint<commit_after><|endoftext|>


<commit_before>import { isString, isArray, isFunction } from './util';

const resolved = {};

/**
 * Load javascript url asynchronously.
 *
 * @param {*} url               The javascript url to load.
 * @param {*} callback          Callback function to invoke on success.
 * @param {*} errorCallback     Callback function to invoke on error.
 * @returns {void}
 */
function loadScript(url, callback, errorCallback) {
  const invokeCallback = () => {
    resolved[url] = true;

    if (isFunction(callback)) {
      callback();
    }
  };

  if (resolved[url]) {
    invokeCallback();

    return;
  }

  const script = document.createElement('script');

  script.type = 'text/javascript';

  if (script.readyState) {
    // IE
    script.onreadystatechange = function() {
      if (script.readyState == 'loaded' || script.readyState == 'complete') {
        script.onreadystatechange = null;
        invokeCallback();
      }
    };
  } else {
    // Others
    script.onload = function() {
      invokeCallback();
    };
  }

  script.onerror = function(e) {
    resolved[url] = false;
    console.error(e);

    if (isFunction(errorCallback)) {
      errorCallback();
    }
  };

  script.src = url;
  const parent = document.body || document.head || document;

  parent.appendChild(script);
}

/**
 * Load javascript url (or a list of urls) asynchronously
 * and return a Promise instance.
 *
 * @param {*} src
 * @returns {Promise}
 */
function get(src) {
  if (isString(src)) {
    return new Promise((resolve, reject) => {
      loadScript(src, () => resolve(true), () => reject());
    });
  } else if (isArray(src)) {
    let p = Promise.resolve(true);

    src.forEach(url => {
      p = p.then(() => get(url));
    });

    return p;
  }

  throw new Error('Invalid argument for get()');
}

export default get;
<commit_msg>Return early<commit_after>import { isString, isArray, isFunction } from './util';

const resolved = {};

/**
 * Load javascript url asynchronously.
 *
 * @param {*} url               The javascript url to load.
 * @param {*} callback          Callback function to invoke on success.
 * @param {*} errorCallback     Callback function to invoke on error.
 * @returns {void}
 */
function loadScript(url, callback, errorCallback) {
  const invokeCallback = () => {
    resolved[url] = true;

    if (isFunction(callback)) {
      callback();
    }
  };

  if (resolved[url]) {
    invokeCallback();

    return;
  }

  const script = document.createElement('script');

  script.type = 'text/javascript';

  if (script.readyState) {
    // IE
    script.onreadystatechange = function() {
      if (script.readyState == 'loaded' || script.readyState == 'complete') {
        script.onreadystatechange = null;
        invokeCallback();
      }
    };
  } else {
    // Others
    script.onload = function() {
      invokeCallback();
    };
  }

  script.onerror = function(e) {
    resolved[url] = false;
    console.error(e);

    if (isFunction(errorCallback)) {
      errorCallback();
    }
  };

  script.src = url;
  const parent = document.body || document.head || document;

  parent.appendChild(script);
}

/**
 * Load javascript url (or a list of urls) asynchronously
 * and return a Promise instance.
 *
 * @param {*} src
 * @returns {Promise}
 */
function get(src) {
  if (isString(src)) {
    return new Promise((resolve, reject) => {
      loadScript(src, () => resolve(true), () => reject());
    });
  }

  if (isArray(src)) {
    let p = Promise.resolve(true);

    src.forEach(url => {
      p = p.then(() => get(url));
    });

    return p;
  }

  throw new Error('Invalid argument for get()');
}

export default get;
<|endoftext|>


<commit_before>
import _ from 'lodash';

import Model from './model';
import Client from './client';
import withLogger from './client-logger';
import Registry from './registry';

const DEFAULT_CONFIG = {
  host: 'localhost',
  logging: false,
};

export default class Grm {
  constructor(config) {
    this.config = _.defaults(config, DEFAULT_CONFIG);
    this.registry = new Registry();
    this.client = this._createClient();
  }

  define(name, config) {
    if (this.registry.contains(name)) {
      throw new Error(`Model [${name}] already defined`);
    }
    const model = new Model(this, name, config);
    this.registry.register(name, model);
    return model;
  }

  importFile(filePath) {
    return require(filePath)(this);
  }

  _createClient() {
    const client = new Client(this.config);
    return this.config.logging ? withLogger(client) : client;
  }
}
<commit_msg>fix: fix importFile function<commit_after>
import _ from 'lodash';

import Model from './model';
import Client from './client';
import withLogger from './client-logger';
import Registry from './registry';

const DEFAULT_CONFIG = {
  host: 'localhost',
  logging: false,
};

export default class Grm {
  constructor(config) {
    this.config = _.defaults(config, DEFAULT_CONFIG);
    this.registry = new Registry();
    this.client = this._createClient();
  }

  define(name, config) {
    if (this.registry.contains(name)) {
      throw new Error(`Model [${name}] already defined`);
    }
    const model = new Model(this, name, config);
    this.registry.register(name, model);
    return model;
  }

  importFile(filePath) {
    const module = require(filePath);
    if (_.isFunction(module)) {
      return module(this);
    } else if (_.isFunction(module.default)) {
      return module.default(this);
    } else {
      throw new Error(`Invalid model file [${filePath}]. Function expected as default export.`);
    }
  }

  _createClient() {
    const client = new Client(this.config);
    return this.config.logging ? withLogger(client) : client;
  }
}
<|endoftext|>