<commit_before>
angular.module('os.administrative.user.dropdown', ['os.administrative.models'])
  .directive('osUsers', function($filter, AuthorizationService, User) {
    function loadUsers(scope, searchTerm, ctrl, attrs) {
      var opts = angular.extend({searchString : searchTerm}, scope.filterOpts || {});
      if (attrs.queryParams) {
        angular.extend(opts, JSON.parse(attrs.queryParams));
      }

      if (attrs.hasOwnProperty('excludeContacts')) {
        opts.excludeType = 'CONTACT';
      }

      if (attrs.hasOwnProperty('includeArchived')) {
        opts.activityStatus = opts.activityStatus || 'all';
      }

      ctrl.listLoaded = true;

      var promise = !attrs.listFn ? User.query(opts) : scope.listFn(opts);
      promise.then(
        function(result) {
          scope.users = result;
          loadSelectedUser(scope, result, ctrl);
        }
      );
    };

    function loadSelectedUser(scope, usersList, ctrl) {
      if (ctrl.onceLoaded) {
        return;
      }

      ctrl.onceLoaded = true;
      var selectProp = ctrl.attrs.selectProp;
      if (selectProp != 'id' || !scope.ngModel) {
        return;
      }

      var selectedUser = usersList.find(function(user) { return user[selectProp] == scope.ngModel; });
      if (selectedUser) {
        return;
      }

      User.getById(scope.ngModel).then(
        function(user) {
          usersList.push(user);
        }
      );
    }

    return {
      restrict: 'AE',

      scope: {
        ngModel: '=ngModel',
        placeholder: '@',
        filterOpts: '=',
        defaultList: '=',
        onSelect: '&',
        listFn: '&'
      },

      replace: true,

      controller: function($scope, $element, $attrs) {
        var ctrl = this;

        if ($attrs.options) {
          $scope.users = ctrl.localList = JSON.parse($attrs.options);
          ctrl.listLoaded = true;

          $scope.searchUsers = function(searchTerm) {
            if (searchTerm) {
              $scope.users = $filter('filter')(ctrl.localList, searchTerm);
            } else {
              $scope.users = ctrl.localList;
            }
          }

          return;
        }

        $scope.searchUsers = function(searchTerm) {
          if (!searchTerm && $scope.defaultList) {
            $scope.users = $scope.defaultList;
            loadSelectedUser($scope, $scope.users, ctrl);
            return;
          }

          loadUsers($scope, searchTerm, ctrl, $attrs);
        };

        $scope.$watch('filterOpts', function(newVal, oldVal) {
          if (newVal == oldVal) {
            return;
          }

          loadUsers($scope, undefined, ctrl, $attrs);
        });

        $attrs.$observe('queryParams',
          function() {
            if (!ctrl.listLoaded) {
              //
              // this is done to ensure we do not load users list twice
              // once by the attributes observer and another by the filterOpts watcher
              //
              return;
            }

            loadUsers($scope, undefined, ctrl, $attrs);
          }
        );
      },

      link: function(scope, element, attrs, ctrl) {
        ctrl.attrs = attrs;

        if (!scope.ngModel && attrs.hasOwnProperty('defaultCurrentUser')) {
          var user = angular.copy(AuthorizationService.currentUser() || {});
          if (attrs.selectProp) {
            user = user[attrs.selectProp];
          }

          if (attrs.hasOwnProperty('multiple')) {
            scope.ngModel = [user];
          } else {
            scope.ngModel = user;
          }
        } else if (!scope.ngModel && attrs.hasOwnProperty('multiple')) {
          scope.ngModel = [];
        }
      },

      template: function(tElem, tAttrs) {
        var bodyAppend = angular.isDefined(tAttrs.appendToBody) ? tAttrs.appendToBody : "true";
        var tabable = angular.isDefined(tAttrs.osTabable) ? tAttrs.osTabable : "false";

        var loopExpr = 'user in users';
        if (angular.isDefined(tAttrs.selectProp)) {
          loopExpr = 'user.' + tAttrs.selectProp + ' as ' + loopExpr;
        }

        return angular.isDefined(tAttrs.multiple) ?
              '
' +
                '<ui-select multiple os-fix-dd ng-model="$parent.ngModel" reset-search-input="true"' +
                  (!!tAttrs.onSelect ? 'on-select="$parent.onSelect({user: $item})"' : '') +
                  ' append-to-body="' + bodyAppend + '" os-tabable="' + tabable + '">' +
                  '<ui-select-match placeholder="{{$parent.placeholder}}">' +
                    '{{$item.firstName}} {{$item.lastName}}' +
                  '</ui-select-match>' +
                  '<ui-select-choices repeat="' + loopExpr +'" refresh="searchUsers($select.search)" refresh-delay="750">' +
                    '' +
                  '</ui-select-choices>' +
                '</ui-select>' +
              '
'

              :

              '
' +
                '<ui-select os-fix-dd ng-model="$parent.ngModel" reset-search-input="true"' +
                  (!!tAttrs.onSelect ? 'on-select="$parent.onSelect({user: $item})"' : '') +
                  ' append-to-body="' + bodyAppend + '" os-tabable="' + tabable + '">' +
                  '<ui-select-match placeholder="{{$parent.placeholder}}" allow-clear="'+ (tAttrs.required == undefined) +'">' +
                    '{{$select.selected.firstName}} {{$select.selected.lastName}}' +
                  '</ui-select-match>' +
                  '<ui-select-choices repeat="' + loopExpr +'" refresh="searchUsers($select.search)" refresh-delay="750">' +
                    '' +
                  '</ui-select-choices>' +
                '</ui-select>' +
              '
';
      }
    };
  });
<commit_msg>Added an input attribute to the users dropdown widget to allow inclusion of system user in the dropdown list.<commit_after>
angular.module('os.administrative.user.dropdown', ['os.administrative.models'])
  .directive('osUsers', function($filter, AuthorizationService, User) {
    function loadUsers(scope, searchTerm, ctrl, attrs) {
      var opts = angular.extend({searchString : searchTerm}, scope.filterOpts || {});
      if (attrs.queryParams) {
        angular.extend(opts, JSON.parse(attrs.queryParams));
      }

      if (attrs.hasOwnProperty('excludeContacts')) {
        opts.excludeType = 'CONTACT';
      }

      if (attrs.hasOwnProperty('includeArchived')) {
        opts.activityStatus = opts.activityStatus || 'all';
      }

      if (attrs.hasOwnProperty('includeSysUser')) {
        opts.includeSysUser = 'true';
      }

      ctrl.listLoaded = true;

      var promise = !attrs.listFn ? User.query(opts) : scope.listFn(opts);
      promise.then(
        function(result) {
          scope.users = result;
          loadSelectedUser(scope, result, ctrl);
        }
      );
    };

    function loadSelectedUser(scope, usersList, ctrl) {
      if (ctrl.onceLoaded) {
        return;
      }

      ctrl.onceLoaded = true;
      var selectProp = ctrl.attrs.selectProp;
      if (selectProp != 'id' || !scope.ngModel) {
        return;
      }

      var selectedUser = usersList.find(function(user) { return user[selectProp] == scope.ngModel; });
      if (selectedUser) {
        return;
      }

      User.getById(scope.ngModel).then(
        function(user) {
          usersList.push(user);
        }
      );
    }

    return {
      restrict: 'AE',

      scope: {
        ngModel: '=ngModel',
        placeholder: '@',
        filterOpts: '=',
        defaultList: '=',
        onSelect: '&',
        listFn: '&'
      },

      replace: true,

      controller: function($scope, $element, $attrs) {
        var ctrl = this;

        if ($attrs.options) {
          $scope.users = ctrl.localList = JSON.parse($attrs.options);
          ctrl.listLoaded = true;

          $scope.searchUsers = function(searchTerm) {
            if (searchTerm) {
              $scope.users = $filter('filter')(ctrl.localList, searchTerm);
            } else {
              $scope.users = ctrl.localList;
            }
          }

          return;
        }

        $scope.searchUsers = function(searchTerm) {
          if (!searchTerm && $scope.defaultList) {
            $scope.users = $scope.defaultList;
            loadSelectedUser($scope, $scope.users, ctrl);
            return;
          }

          loadUsers($scope, searchTerm, ctrl, $attrs);
        };

        $scope.$watch('filterOpts', function(newVal, oldVal) {
          if (newVal == oldVal) {
            return;
          }

          loadUsers($scope, undefined, ctrl, $attrs);
        });

        $attrs.$observe('queryParams',
          function() {
            if (!ctrl.listLoaded) {
              //
              // this is done to ensure we do not load users list twice
              // once by the attributes observer and another by the filterOpts watcher
              //
              return;
            }

            loadUsers($scope, undefined, ctrl, $attrs);
          }
        );
      },

      link: function(scope, element, attrs, ctrl) {
        ctrl.attrs = attrs;

        if (!scope.ngModel && attrs.hasOwnProperty('defaultCurrentUser')) {
          var user = angular.copy(AuthorizationService.currentUser() || {});
          if (attrs.selectProp) {
            user = user[attrs.selectProp];
          }

          if (attrs.hasOwnProperty('multiple')) {
            scope.ngModel = [user];
          } else {
            scope.ngModel = user;
          }
        } else if (!scope.ngModel && attrs.hasOwnProperty('multiple')) {
          scope.ngModel = [];
        }
      },

      template: function(tElem, tAttrs) {
        var bodyAppend = angular.isDefined(tAttrs.appendToBody) ? tAttrs.appendToBody : "true";
        var tabable = angular.isDefined(tAttrs.osTabable) ? tAttrs.osTabable : "false";

        var loopExpr = 'user in users';
        if (angular.isDefined(tAttrs.selectProp)) {
          loopExpr = 'user.' + tAttrs.selectProp + ' as ' + loopExpr;
        }

        return angular.isDefined(tAttrs.multiple) ?
              '
' +
                '<ui-select multiple os-fix-dd ng-model="$parent.ngModel" reset-search-input="true"' +
                  (!!tAttrs.onSelect ? 'on-select="$parent.onSelect({user: $item})"' : '') +
                  ' append-to-body="' + bodyAppend + '" os-tabable="' + tabable + '">' +
                  '<ui-select-match placeholder="{{$parent.placeholder}}">' +
                    '{{$item.firstName}} {{$item.lastName}}' +
                  '</ui-select-match>' +
                  '<ui-select-choices repeat="' + loopExpr +'" refresh="searchUsers($select.search)" refresh-delay="750">' +
                    '' +
                  '</ui-select-choices>' +
                '</ui-select>' +
              '
'

              :

              '
' +
                '<ui-select os-fix-dd ng-model="$parent.ngModel" reset-search-input="true"' +
                  (!!tAttrs.onSelect ? 'on-select="$parent.onSelect({user: $item})"' : '') +
                  ' append-to-body="' + bodyAppend + '" os-tabable="' + tabable + '">' +
                  '<ui-select-match placeholder="{{$parent.placeholder}}" allow-clear="'+ (tAttrs.required == undefined) +'">' +
                    '{{$select.selected.firstName}} {{$select.selected.lastName}}' +
                  '</ui-select-match>' +
                  '<ui-select-choices repeat="' + loopExpr +'" refresh="searchUsers($select.search)" refresh-delay="750">' +
                    '' +
                  '</ui-select-choices>' +
                '</ui-select>' +
              '
';
      }
    };
  });
<|endoftext|>


<commit_before>(function () {
  'use strict';

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

  OrientationDataTabController.$inject = ['$cordovaDeviceMotion', '$cordovaDeviceOrientation', '$ionicModal',
    '$ionicPopup', '$log', '$q', '$scope', '$state', 'DataModelsFactory', 'FormFactory', 'HelpersFactory',
    'ProjectFactory'];

  function OrientationDataTabController($cordovaDeviceMotion, $cordovaDeviceOrientation, $ionicModal, $ionicPopup, $log,
                                        $q, $scope, $state, DataModelsFactory, FormFactory, HelpersFactory,
                                        ProjectFactory) {
    var vm = this;
    var vmParent = $scope.vm;
    vmParent.loadTab($state);  // Need to load current state into parent

    vm.addAssociatedOrientation = addAssociatedOrientation;
    vm.addOrientation = addOrientation;
    vm.basicFormModal = {};
    vm.copyAssociatedOrientation = copyAssociatedOrientation;
    vm.copyOrientation = copyOrientation;
    vm.deleteAssociatedOrientation = deleteAssociatedOrientation;
    vm.deleteOrientation = deleteOrientation;
    vm.editAssociatedOrientation = editAssociatedOrientation;
    vm.editOrientation = editOrientation;
    vm.getCompassInfo = getCompassInfo;
    vm.modalTitle = '';
    vm.parentOrientation = {};
    vm.submit = submit;

    activate();

    /**
     * Private Functions
     */

    function activate() {
      $log.log('Orientation Data:', vmParent.spot.properties.orientation_data);
      checkProperties();
      createModal();
    }

    function assignProperties(item) {
      if (!item.label) item.label = item.name || createDefaultLabel(item);
      if (!item.id) item.id = HelpersFactory.newId();
      if (!item.type) item.type = item.orientation_type || 'planar_orientation';
    }

    function calculateOrientation(magneticHeading, x, y, z) {
      var g = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
      var s = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
      var B = Math.acos(Math.abs(y) / s);
      var R = 90 - B;
      var d = Math.acos(Math.abs(z) / g);
      var b = Math.atan(Math.tan(R) * Math.cos(d));
      var dipdir;
      var diry = magneticHeading;

      if (x === 0 && y === 0) {
        d = 0;
        dipdir = 180;
      }
      else if (x >= 0 && y >= 0) dipdir = diry - 90 - b;
      else if (y <= 0 && x >= 0) dipdir = diry - 90 + b;
      else if (y <= 0 && x <= 0) dipdir = diry + 90 - b;
      else if (x <= 0 && y >= 0) dipdir = diry + 90 + b;

      var strike = dipdir - 90;
      strike = strike % 360;
      dipdir = dipdir % 360;
      var dip = d;
      var trend = diry;
      var plunge = Math.acos(Math.abs(y) / g);
      var rake = R;

      if (vmParent.data.type === 'linear_orientation') {
        vmParent.data.trend = Math.round(trend * 1000) / 1000;
        vmParent.data.plunge = Math.round(plunge * 1000) / 1000;
        vmParent.data.rake = Math.round(rake * 1000) / 1000;
        vmParent.data.rake_calculated = 'yes';
      }
      else {
        vmParent.data.strike = Math.round(strike * 1000) / 1000;
        vmParent.data.dip_direction = Math.round(dipdir * 1000) / 1000;
        vmParent.data.dip = Math.round(dip * 1000) / 1000;
      }

      return {
        'strike': vmParent.data.strike, 'dipdir': vmParent.data.dip_direction, 'dip': vmParent.data.dip,
        'trend': vmParent.data.trend, 'plunge': vmParent.data.plunge, 'rake': vmParent.data.rake
      };
    }

    function checkProperties() {
      _.each(vmParent.spot.properties.orientation_data, function (orientation) {
        assignProperties(orientation);
        _.each(orientation.associated_orientation, function (associated_orientation) {
          assignProperties(associated_orientation);
        });
      });
    }

    function createDefaultLabel(orientationToLabel) {
      var label = DataModelsFactory.getFeatureTypeLabel(orientationToLabel.feature_type);
      if (!label && orientationToLabel.type) label = orientationToLabel.type.split('_')[0] + ' feature';
      if (orientationToLabel.strike) label += ' ' + orientationToLabel.strike.toString();
      else if (orientationToLabel.trend) label += ' ' + orientationToLabel.trend.toString();
      return label;
    }

    function createModal() {
      $ionicModal.fromTemplateUrl('app/spot/basic-form-modal.html', {
        'scope': $scope,
        'animation': 'slide-in-up',
        'focusFirstInput': true,
        'backdropClickToClose': false
      }).then(function (modal) {
        vm.basicFormModal = modal;
      });

      // Cleanup the modal when we're done with it!
      $scope.$on('$destroy', function () {
        vm.basicFormModal.remove();
      });
    }

    function getModalTitlePart() {
      if (vmParent.data.type === 'linear_orientation') return 'Line';
      if (vmParent.data.type === 'planar_orientation') return 'Plane';
      if (vmParent.data.type === 'tabular_orientation') return 'Tabular Zone';
    }

    /**
     * Public Functions
     */

    function addAssociatedOrientation(parentThisOrientation, type) {
      vm.parentOrientation = parentThisOrientation;
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[type].choices;
      vmParent.data = {};
      vmParent.data.type = type;
      vmParent.data.id = HelpersFactory.newId();
      vm.modalTitle = 'Add a ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function addOrientation(type) {
      vm.parentOrientation = undefined;
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[type].choices;
      vmParent.data = {};
      vmParent.data.type = type;
      vmParent.data.id = HelpersFactory.newId();
      vm.modalTitle = 'Add a ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function copyAssociatedOrientation(parentThisOrientation, orientation) {
      var copy = angular.copy(orientation);
      delete copy.id;
      assignProperties(copy);
      parentThisOrientation.associated_orientation.push(copy);
    }

    function copyOrientation(orientation) {
      var copy = angular.copy(orientation);
      delete copy.id;
      _.each(copy.associated_orientation, function (associatedOrientation) {
        delete associatedOrientation.id;
        assignProperties(associatedOrientation);
      });
      assignProperties(copy);
      vmParent.spot.properties.orientation_data.push(copy);
    }

    function deleteAssociatedOrientation(parentThisOrientation, orientationToDelete) {
      var confirmPopup = $ionicPopup.confirm({
        'title': 'Delete Associated Orientation',
        'template': 'Are you sure you want to delete this  associated orientation?'
      });
      confirmPopup.then(function (res) {
        if (res) {
          parentThisOrientation.associated_orientation = _.reject(parentThisOrientation.associated_orientation,
            function (associatedOrientation) {
              return associatedOrientation.id === orientationToDelete.id;
            });
          if (parentThisOrientation.associated_orientation === 0) delete parentThisOrientation.associated_orientation;
        }
      });
    }

    function deleteOrientation(orientationToDelete) {
      var confirmPopup = $ionicPopup.confirm({
        'title': 'Delete Orientation',
        'template': 'Are you sure you want to delete this orientation?'
      });
      confirmPopup.then(function (res) {
        if (res) {
          vmParent.spot.properties.orientation_data = _.reject(vmParent.spot.properties.orientation_data,
            function (orientation) {
              return orientation.id === orientationToDelete.id;
            });
          if (vmParent.spot.properties.orientation_data === 0) delete vmParent.spot.properties.orientation_data;
          ProjectFactory.removeFeatureFromTags(vmParent.spot.properties.id, orientationToDelete.id);
        }
      });
    }

    function editAssociatedOrientation(parentThisOrientation, orientationToEdit) {
      vm.parentOrientation = parentThisOrientation;
      vmParent.data = angular.fromJson(angular.toJson(orientationToEdit));  // Copy value, not reference
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].choices;
      vm.modalTitle = 'Edit ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function editOrientation(orientationToEdit) {
      vm.parentOrientation = undefined;
      vmParent.data = angular.fromJson(angular.toJson(orientationToEdit));  // Copy value, not reference
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].choices;
      vm.modalTitle = 'Edit ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function getCompassInfo() {
      var promises = [];
      var promise;
      var msgText = '';
      var magneticHeading, x, y, z;

      promise = $cordovaDeviceOrientation.getCurrentHeading().then(function (result) {
        magneticHeading = result.magneticHeading;
        msgText += 'Magnetic Heading = ' + magneticHeading + '
';
      }, function (err) {
        msgText += 'Compass Error: ' + err + '
';
        $log.log(err);
      });
      promises.push(promise);

      if (navigator.accelerometer) {
        promise = $cordovaDeviceMotion.getCurrentAcceleration().then(function (result) {
          x = result.x;
          y = result.y;
          z = result.z;
          msgText += 'X = ' + x + '
';
          msgText += 'Y = ' + y + '
';
          msgText += 'Z = ' + z + '
';
        }, function (err) {
          msgText = 'Acceleration Error: ' + err + '
';
        });
        promises.push(promise);
      }
      else msgText += 'Accelerometer Error: No accelerometer on Device
';

      $q.all(promises).then(function () {
        if (magneticHeading && x && y && z) {
          var orientation = calculateOrientation(magneticHeading, x, y, z);
          if (vmParent.data.type === 'linear_orientation') {
            msgText += 'Trend = ' + orientation.trend + '
';
            msgText += 'Plunge = ' + orientation.plunge + '
';
            msgText += 'Rake = ' + orientation.rake + '
';
          }
          else {
            msgText += 'Strike = ' + orientation.strike + '
';
            msgText += 'Dip Direction = ' + orientation.dipdir + '
';
            msgText += 'Dip = ' + orientation.dip + '
';
          }
        }
        $ionicPopup.alert({
          'title': 'Compass & Accelerometer Info',
          'template': msgText
        });
      });
    }

    function submit() {
      if (_.size(vmParent.data) <= 2) {
        // If not more than type and id fields no data has been entered so don't continue, just close modal
        vmParent.data = {};
        vm.parentOrientation = undefined;
        vm.basicFormModal.hide();
        return;
      }
      if (!vmParent.data.label) vmParent.data.label = createDefaultLabel(vmParent.data);
      if (FormFactory.validate(vmParent.survey, vmParent.data)) {
        if (!vm.parentOrientation) {
          if (!vmParent.spot.properties.orientation_data) vmParent.spot.properties.orientation_data = [];
          vmParent.spot.properties.orientation_data = _.reject(vmParent.spot.properties.orientation_data,
            function (orientation) {
              return orientation.id === vmParent.data.id;
            });
          vmParent.spot.properties.orientation_data.push(vmParent.data);
        }
        else {
          if (!vm.parentOrientation.associated_orientation) vm.parentOrientation.associated_orientation = [];
          vm.parentOrientation.associated_orientation = _.reject(vm.parentOrientation.associated_orientation,
            function (associatedOrientation) {
              return associatedOrientation.id === vmParent.data.id;
            });
          vm.parentOrientation.associated_orientation.push(vmParent.data);
          vmParent.spot.properties.orientation_data = _.reject(vmParent.spot.properties.orientation_data,
            function (orientation) {
              return orientation.id === vm.parentOrientation.id;
            });
          vmParent.spot.properties.orientation_data.push(vm.parentOrientation);
        }
        vmParent.data = {};
        vm.basicFormModal.hide();
      }
    }
  }
}());
<commit_msg>adjustment to orientation calculations<commit_after>(function () {
  'use strict';

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

  OrientationDataTabController.$inject = ['$cordovaDeviceMotion', '$cordovaDeviceOrientation', '$ionicModal',
    '$ionicPopup', '$log', '$q', '$scope', '$state', 'DataModelsFactory', 'FormFactory', 'HelpersFactory',
    'ProjectFactory'];

  function OrientationDataTabController($cordovaDeviceMotion, $cordovaDeviceOrientation, $ionicModal, $ionicPopup, $log,
                                        $q, $scope, $state, DataModelsFactory, FormFactory, HelpersFactory,
                                        ProjectFactory) {
    var vm = this;
    var vmParent = $scope.vm;
    vmParent.loadTab($state);  // Need to load current state into parent

    vm.addAssociatedOrientation = addAssociatedOrientation;
    vm.addOrientation = addOrientation;
    vm.basicFormModal = {};
    vm.copyAssociatedOrientation = copyAssociatedOrientation;
    vm.copyOrientation = copyOrientation;
    vm.deleteAssociatedOrientation = deleteAssociatedOrientation;
    vm.deleteOrientation = deleteOrientation;
    vm.editAssociatedOrientation = editAssociatedOrientation;
    vm.editOrientation = editOrientation;
    vm.getCompassInfo = getCompassInfo;
    vm.modalTitle = '';
    vm.parentOrientation = {};
    vm.submit = submit;

    activate();

    /**
     * Private Functions
     */

    function activate() {
      $log.log('Orientation Data:', vmParent.spot.properties.orientation_data);
      checkProperties();
      createModal();
    }

    function assignProperties(item) {
      if (!item.label) item.label = item.name || createDefaultLabel(item);
      if (!item.id) item.id = HelpersFactory.newId();
      if (!item.type) item.type = item.orientation_type || 'planar_orientation';
    }

    function calculateOrientation(magneticHeading, x, y, z) {
      var g = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
      var s = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
      var B = Math.acos(Math.abs(y) / s);
      var R = 90 - B;
      var d = Math.acos(Math.abs(z) / g);
      var b = Math.atan(Math.tan(R) * Math.cos(d));
      var dipdir;
      var diry = magneticHeading;

      if (x === 0 && y === 0) {
        d = 0;
        dipdir = 180;
      }
      else if (x >= 0 && y >= 0) dipdir = diry - 90 - b;
      else if (y <= 0 && x >= 0) dipdir = diry - 90 + b;
      else if (y <= 0 && x <= 0) dipdir = diry + 90 - b;
      else if (x <= 0 && y >= 0) dipdir = diry + 90 + b;

      if (dipdir < 0) dipdir = 360 + dipdir;
      var strike = dipdir - 90;
      if (strike < 0) strike = 360 + strike;
      strike = strike % 360;
      dipdir = dipdir % 360;
      var dip = d;
      var trend = diry;
      var plunge = Math.acos(Math.abs(y) / g);
      var rake = R;

      if (vmParent.data.type === 'linear_orientation') {
        vmParent.data.trend = Math.round(trend * 1000) / 1000;
        vmParent.data.plunge = Math.round(plunge * 1000) / 1000;
        vmParent.data.rake = Math.round(rake * 1000) / 1000;
        vmParent.data.rake_calculated = 'yes';
      }
      else {
        vmParent.data.strike = Math.round(strike * 1000) / 1000;
        vmParent.data.dip_direction = Math.round(dipdir * 1000) / 1000;
        vmParent.data.dip = Math.round(dip * 1000) / 1000;
      }

      return {
        'strike': vmParent.data.strike, 'dipdir': vmParent.data.dip_direction, 'dip': vmParent.data.dip,
        'trend': vmParent.data.trend, 'plunge': vmParent.data.plunge, 'rake': vmParent.data.rake
      };
    }

    function checkProperties() {
      _.each(vmParent.spot.properties.orientation_data, function (orientation) {
        assignProperties(orientation);
        _.each(orientation.associated_orientation, function (associated_orientation) {
          assignProperties(associated_orientation);
        });
      });
    }

    function createDefaultLabel(orientationToLabel) {
      var label = DataModelsFactory.getFeatureTypeLabel(orientationToLabel.feature_type);
      if (!label && orientationToLabel.type) label = orientationToLabel.type.split('_')[0] + ' feature';
      if (orientationToLabel.strike) label += ' ' + orientationToLabel.strike.toString();
      else if (orientationToLabel.trend) label += ' ' + orientationToLabel.trend.toString();
      return label;
    }

    function createModal() {
      $ionicModal.fromTemplateUrl('app/spot/basic-form-modal.html', {
        'scope': $scope,
        'animation': 'slide-in-up',
        'focusFirstInput': true,
        'backdropClickToClose': false
      }).then(function (modal) {
        vm.basicFormModal = modal;
      });

      // Cleanup the modal when we're done with it!
      $scope.$on('$destroy', function () {
        vm.basicFormModal.remove();
      });
    }

    function getModalTitlePart() {
      if (vmParent.data.type === 'linear_orientation') return 'Line';
      if (vmParent.data.type === 'planar_orientation') return 'Plane';
      if (vmParent.data.type === 'tabular_orientation') return 'Tabular Zone';
    }

    /**
     * Public Functions
     */

    function addAssociatedOrientation(parentThisOrientation, type) {
      vm.parentOrientation = parentThisOrientation;
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[type].choices;
      vmParent.data = {};
      vmParent.data.type = type;
      vmParent.data.id = HelpersFactory.newId();
      vm.modalTitle = 'Add a ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function addOrientation(type) {
      vm.parentOrientation = undefined;
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[type].choices;
      vmParent.data = {};
      vmParent.data.type = type;
      vmParent.data.id = HelpersFactory.newId();
      vm.modalTitle = 'Add a ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function copyAssociatedOrientation(parentThisOrientation, orientation) {
      var copy = angular.copy(orientation);
      delete copy.id;
      assignProperties(copy);
      parentThisOrientation.associated_orientation.push(copy);
    }

    function copyOrientation(orientation) {
      var copy = angular.copy(orientation);
      delete copy.id;
      _.each(copy.associated_orientation, function (associatedOrientation) {
        delete associatedOrientation.id;
        assignProperties(associatedOrientation);
      });
      assignProperties(copy);
      vmParent.spot.properties.orientation_data.push(copy);
    }

    function deleteAssociatedOrientation(parentThisOrientation, orientationToDelete) {
      var confirmPopup = $ionicPopup.confirm({
        'title': 'Delete Associated Orientation',
        'template': 'Are you sure you want to delete this  associated orientation?'
      });
      confirmPopup.then(function (res) {
        if (res) {
          parentThisOrientation.associated_orientation = _.reject(parentThisOrientation.associated_orientation,
            function (associatedOrientation) {
              return associatedOrientation.id === orientationToDelete.id;
            });
          if (parentThisOrientation.associated_orientation === 0) delete parentThisOrientation.associated_orientation;
        }
      });
    }

    function deleteOrientation(orientationToDelete) {
      var confirmPopup = $ionicPopup.confirm({
        'title': 'Delete Orientation',
        'template': 'Are you sure you want to delete this orientation?'
      });
      confirmPopup.then(function (res) {
        if (res) {
          vmParent.spot.properties.orientation_data = _.reject(vmParent.spot.properties.orientation_data,
            function (orientation) {
              return orientation.id === orientationToDelete.id;
            });
          if (vmParent.spot.properties.orientation_data === 0) delete vmParent.spot.properties.orientation_data;
          ProjectFactory.removeFeatureFromTags(vmParent.spot.properties.id, orientationToDelete.id);
        }
      });
    }

    function editAssociatedOrientation(parentThisOrientation, orientationToEdit) {
      vm.parentOrientation = parentThisOrientation;
      vmParent.data = angular.fromJson(angular.toJson(orientationToEdit));  // Copy value, not reference
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].choices;
      vm.modalTitle = 'Edit ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function editOrientation(orientationToEdit) {
      vm.parentOrientation = undefined;
      vmParent.data = angular.fromJson(angular.toJson(orientationToEdit));  // Copy value, not reference
      vmParent.survey = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].survey;
      vmParent.choices = DataModelsFactory.getDataModel('orientation_data')[vmParent.data.type].choices;
      vm.modalTitle = 'Edit ' + getModalTitlePart();
      vm.basicFormModal.show();
    }

    function getCompassInfo() {
      var promises = [];
      var promise;
      var msgText = '';
      var magneticHeading, x, y, z;

      promise = $cordovaDeviceOrientation.getCurrentHeading().then(function (result) {
        magneticHeading = result.magneticHeading;
        msgText += 'Magnetic Heading = ' + magneticHeading + '
';
      }, function (err) {
        msgText += 'Compass Error: ' + err + '
';
        $log.log(err);
      });
      promises.push(promise);

      if (navigator.accelerometer) {
        promise = $cordovaDeviceMotion.getCurrentAcceleration().then(function (result) {
          x = result.x;
          y = result.y;
          z = result.z;
          msgText += 'X = ' + x + '
';
          msgText += 'Y = ' + y + '
';
          msgText += 'Z = ' + z + '
';
        }, function (err) {
          msgText = 'Acceleration Error: ' + err + '
';
        });
        promises.push(promise);
      }
      else msgText += 'Accelerometer Error: No accelerometer on Device
';

      $q.all(promises).then(function () {
        if (magneticHeading && x && y && z) {
          var orientation = calculateOrientation(magneticHeading, x, y, z);
          if (vmParent.data.type === 'linear_orientation') {
            msgText += 'Trend = ' + orientation.trend + '
';
            msgText += 'Plunge = ' + orientation.plunge + '
';
            msgText += 'Rake = ' + orientation.rake + '
';
          }
          else {
            msgText += 'Strike = ' + orientation.strike + '
';
            msgText += 'Dip Direction = ' + orientation.dipdir + '
';
            msgText += 'Dip = ' + orientation.dip + '
';
          }
        }
        $ionicPopup.alert({
          'title': 'Compass & Accelerometer Info',
          'template': msgText
        });
      });
    }

    function submit() {
      if (_.size(vmParent.data) <= 2) {
        // If not more than type and id fields no data has been entered so don't continue, just close modal
        vmParent.data = {};
        vm.parentOrientation = undefined;
        vm.basicFormModal.hide();
        return;
      }
      if (!vmParent.data.label) vmParent.data.label = createDefaultLabel(vmParent.data);
      if (FormFactory.validate(vmParent.survey, vmParent.data)) {
        if (!vm.parentOrientation) {
          if (!vmParent.spot.properties.orientation_data) vmParent.spot.properties.orientation_data = [];
          vmParent.spot.properties.orientation_data = _.reject(vmParent.spot.properties.orientation_data,
            function (orientation) {
              return orientation.id === vmParent.data.id;
            });
          vmParent.spot.properties.orientation_data.push(vmParent.data);
        }
        else {
          if (!vm.parentOrientation.associated_orientation) vm.parentOrientation.associated_orientation = [];
          vm.parentOrientation.associated_orientation = _.reject(vm.parentOrientation.associated_orientation,
            function (associatedOrientation) {
              return associatedOrientation.id === vmParent.data.id;
            });
          vm.parentOrientation.associated_orientation.push(vmParent.data);
          vmParent.spot.properties.orientation_data = _.reject(vmParent.spot.properties.orientation_data,
            function (orientation) {
              return orientation.id === vm.parentOrientation.id;
            });
          vmParent.spot.properties.orientation_data.push(vm.parentOrientation);
        }
        vmParent.data = {};
        vm.basicFormModal.hide();
      }
    }
  }
}());
<|endoftext|>


<commit_before>// Data access/propagation rules for apps

'use strict';

var aFrom            = require('es5-ext/array/from')
  , compose          = require('es5-ext/function/#/compose')
  , ensureIterable   = require('es5-ext/iterable/validate-object')
  , findKey          = require('es5-ext/object/find-key')
  , forEach          = require('es5-ext/object/for-each')
  , ensureCallable   = require('es5-ext/object/valid-callable')
  , ensureObject     = require('es5-ext/object/valid-object')
  , ensureString     = require('es5-ext/object/validate-stringifiable-value')
  , endsWith         = require('es5-ext/string/#/ends-with')
  , uncapitalize     = require('es5-ext/string/#/uncapitalize')
  , memoize          = require('memoizee')
  , Set              = require('es6-set')
  , deferred         = require('deferred')
  , unserializeValue = require('dbjs/_setup/unserialize/value')
  , ObservableSet    = require('observable-set')
  , ObservableMulti  = require('observable-multi-set')
  , Fragment         = require('data-fragment')
  , ensureFragment   = require('data-fragment/ensure')
  , FragmentGroup    = require('data-fragment/group')
  , ensureDriver     = require('dbjs-persistence/ensure-driver')
  , unserializeView  = require('../utils/db-view/unserialize-ids')
  , getReducedFrag   = require('./data-fragments/get-reduced-object-fragments')
  , getRedRecFrag    = require('./data-fragments/get-reduced-records-fragment')
  , getObjFragment   = require('./data-fragments/get-direct-object-fragments')
  , getColFragments  = require('./data-fragments/get-collection-fragments')
  , getPartFragments = require('./data-fragments/get-part-object-fragments')
  , getDbRecordSet   = require('./utils/get-db-record-set')
  , userListProps    = require('../apps/users-admin/user-list-properties')

  , create = Object.create, keys = Object.keys, stringify = JSON.stringify
  , emptyFragment = new Fragment()
  , isOfficialRoleName = RegExp.prototype.test.bind(/^official[A-Z]/);

var joinSets = function (sets) {
	var set = new ObservableMulti(sets);
	set.promise = deferred.map(sets, function (set) { return set.promise; });
	return set;
};
module.exports = function (dbDriver, data) {
	var userStorage = ensureDriver(dbDriver).getStorage('user')
	  , reducedStorage = dbDriver.getReducedStorage()
	  , getUserData = getObjFragment(userStorage)
	  , getBusinessProcessData = getObjFragment()
	  , getUserReducedData = getReducedFrag(userStorage)
	  , getReducedData = getReducedFrag(reducedStorage)
	  , resolveOfficialSteps, processingStepsMeta, processingStepsDefaultMap = create(null)
	  , businessProcessListProperties, globalFragment, getMetaAdminFragment
	  , assignableProcessingSteps;

	ensureObject(data);
	processingStepsMeta = ensureObject(data.processingStepsMeta);

	// Eventual fragment that should be passed to all clients
	if (data.globalFragment != null) globalFragment = ensureFragment(data.globalFragment);
	if (data.getMetaAdminFragment != null) {
		getMetaAdminFragment = memoize(ensureCallable(data.getMetaAdminFragment), { length: 0 });
	}
	if (data.assignableProcessingSteps != null) {
		assignableProcessingSteps = new Set(aFrom(ensureIterable(data.assignableProcessingSteps),
			function (stepShortPath) {
				stepShortPath = ensureString(stepShortPath);
				if (!processingStepsMeta[stepShortPath]) {
					throw new Error("Unrecognized step short path " + stringify(stepShortPath));
				}
				return stepShortPath;
			}));
	}
	businessProcessListProperties =
		new Set(aFrom(ensureIterable(data.businessProcessListProperties)));

	// Configure official steps (per user) resolver
	var defaultOfficialStepsResolver = function (userId) {
		var rolesSet = getDbRecordSet(userStorage, userId + '/roles');
		var resultSet = rolesSet.map(unserializeValue).filter(isOfficialRoleName)
			.map(function (roleName) { return uncapitalize.call(roleName.slice('official'.length)); })
			.filter(function (stepShortPath) { return processingStepsMeta[stepShortPath]; });
		resultSet.promise = rolesSet.promise;
		return resultSet;
	};
	if (data.normalizeOfficialStepsPaths != null) {
		resolveOfficialSteps = compose.bind(ensureCallable(data.resolveOfficialSteps),
			defaultOfficialStepsResolver);
	} else {
		resolveOfficialSteps = defaultOfficialStepsResolver;
	}
	resolveOfficialSteps = memoize(resolveOfficialSteps, { length: 1, primitive: true });

	// Resolve default step statuses (in most cases 'pending')
	forEach(processingStepsMeta, function (meta, stepShortPath) {
		var defaultKey = findKey(meta, function (conf) {
			return conf.default;
		});
		if (!defaultKey) throw new Error("Not found default key for " + stringify(stepShortPath));
		processingStepsDefaultMap[stepShortPath] = defaultKey;
	});
	var resolveDefaultStatus = function (stepShortPath) {
		var defaultKey = processingStepsDefaultMap[stepShortPath];
		if (!defaultKey) throw new Error("Unrecognized step short path " + stringify(stepShortPath));
		return defaultKey;
	};

	// Configure fragment resolvers
	// Non role specific
	var getUserFragment = function (id) {
		return getUserData(id,
			{ filter: function (data) { return !endsWith.call(data.id, '/password'); } });
	};
	var getFirstPageItems = memoize(function (storage, viewName) {
		var objects = new ObservableSet(), id = 'views/' + viewName + '/21';
		objects.promise = storage.getReduced(id)(function (data) {
			if (data) objects.reload(unserializeView(unserializeValue(data.value)));
		});
		storage.on('keyid:' + id, function (event) {
			objects.reload(unserializeView(unserializeValue(event.data.value)));
		});
		return objects;
	}, { primitive: true });
	var addOfficialStepsPendingSizes = (function () {
		var resolveFragment = function (stepsShortPaths) {
			var ids;
			if (!stepsShortPaths.size) return emptyFragment;
			ids = [];
			stepsShortPaths.forEach(function (stepShortPath) {
				var defaultKey = resolveDefaultStatus(stepShortPath);
				ids.push('views/pendingBusinessProcesses/' + stepShortPath + '/' + defaultKey +
					'/totalSize');
			});
			return getRedRecFrag(reducedStorage, ids);
		};
		return function (userId, fragment) {
			var stepsShortPaths = resolveOfficialSteps(userId)
			  , current;
			current = resolveFragment(stepsShortPaths);
			fragment.addFragment(current);
			stepsShortPaths.on('change', function () {
				var nu = resolveFragment(stepsShortPaths);
				if (nu === current) return;
				fragment.addFragment(nu);
				fragment.deleteFragment(current);
				current = nu;
			});
		};
	}());

	// Users Admin resolvers
	var getUserListFragment = getPartFragments(userStorage, userListProps);
	var getRecentlyVisitedUsersFragment = function (userId) {
		var list = getDbRecordSet(userStorage, userId + '/recentlyVisited/users')
			.map(function (value) { return value.slice(1); });

		return getColFragments(list, getUserListFragment);
	};
	var getUsersAdminFragment = memoize(function () {
		var fragment = new FragmentGroup();
		// First page snapshot
		fragment.addFragment(getUserReducedData('views/usersAdmin'));
		// First page list data
		fragment.addFragment(getColFragments(getFirstPageItems(userStorage, 'usersAdmin'),
			getUserListFragment));
		return fragment;
	});

	// Official roles resolvers
	var getRecentlyVisitedBusinessProcessesFragment = function (userId, roleName) {
		var list = getDbRecordSet(userStorage,
			userId + '/recentlyVisited/businessProcesses/' + roleName)
			.map(function (value) { return value.slice(1); });

		return getColFragments(list, getBusinessProcessData);
	};
	var getBusinessProcessOfficialListFragment =
		getPartFragments(null, businessProcessListProperties);

	var getOfficialFragment = memoize(function (stepShortPath) {
		var fragment = new FragmentGroup()
		  , defaultStatusName = resolveDefaultStatus(stepShortPath);

		// To be visited (recently pending) business processes (full data)
		fragment.addFragment(getColFragments(getFirstPageItems(reducedStorage,
			'pendingBusinessProcesses/' + stepShortPath + '/' + defaultStatusName).toArray().slice(0, 10),
			getBusinessProcessData));
		// First page snapshot for each status
		fragment.addFragment(getReducedData('views/pendingBusinessProcesses/' + stepShortPath));
		// First page list data for each status
		fragment.addFragment(getColFragments(joinSets(
			keys(processingStepsMeta[stepShortPath]).map(function (status) {
				return getFirstPageItems(reducedStorage,
					'pendingBusinessProcesses/' + stepShortPath + '/' + status);
			})
		), getBusinessProcessOfficialListFragment));
		return fragment;
	}, { primitive: true });

	var getBusinessProcessDispatcherListFragment = getPartFragments(null, (function (props) {
		var set = new Set(props);
		assignableProcessingSteps.forEach(function (stepShortPath) {
			// TODO: Fix for deep paths
			set.add('processingSteps/map/' + stepShortPath + '/assignee');
		});
		return set;
	}(businessProcessListProperties)));

	var getDispatcherFragment = memoize(function () {
		var fragment = new FragmentGroup();

		assignableProcessingSteps.forEach(function (stepShortPath) {
			var defaultStatusName = resolveDefaultStatus(stepShortPath);
			// First page snapshot
			fragment.addFragment(getReducedData('views/pendingBusinessProcesses/' + stepShortPath + '/' +
				defaultStatusName));
			// First page list data
			fragment.addFragment(getColFragments(getFirstPageItems(reducedStorage,
				'pendingBusinessProcesses/' + stepShortPath + '/' + defaultStatusName),
				getBusinessProcessDispatcherListFragment));
		});
		return fragment;
	});

	return memoize(function (appId) {
		var userId, roleName, stepShortPath, custom, fragment, initialBusinessProcesses, promise;

		appId = appId.split('.');
		userId = appId[0];
		roleName = appId[1];
		custom = appId[2];

		if (!roleName) return emptyFragment; // Temporary inconsistent state (client migration)

		fragment = new FragmentGroup();

		// User profile data
		fragment.addFragment(getUserFragment(userId));
		// Sizes of pending files in official roles of user
		addOfficialStepsPendingSizes(userId, fragment);
		// Eventual global fragment
		if (globalFragment) fragment.addFragment(globalFragment);

		if (roleName === 'user') {
			if (custom) {
				// Business process application
				// Business process data
				fragment.addFragment(getBusinessProcessData(custom));
			} else {
				// My account
				// All businesss processes (full data)
				initialBusinessProcesses = getDbRecordSet(userStorage,
					userId + '/initialBusinessProcesses');
				promise = initialBusinessProcesses.promise;
				initialBusinessProcesses = initialBusinessProcesses
					.map(function (value) { return value.slice(1); });
				initialBusinessProcesses.promise = promise;
				// - All initial business processes
				fragment.addFragment(getColFragments(initialBusinessProcesses, getBusinessProcessData));
			}
			return fragment;
		}
		if (roleName === 'usersAdmin') {
			// Recently visited users (full data)
			fragment.addFragment(getRecentlyVisitedUsersFragment(userId));
			// Users Admin specific data
			fragment.addFragment(getUsersAdminFragment());
			return fragment;
		}
		if (roleName === 'metaAdmin') {
			if (getMetaAdminFragment) fragment.addFragment(getMetaAdminFragment());
			return fragment;
		}

		if (isOfficialRoleName(roleName)) {
			stepShortPath = uncapitalize.call(roleName.slice('official'.length));
			// Recently visited business processes (full data)
			fragment.addFragment(getRecentlyVisitedBusinessProcessesFragment(userId, stepShortPath));
			// Official role specific data
			if (assignableProcessingSteps && assignableProcessingSteps.has(stepShortPath)) {
				fragment.addFragment(getOfficialFragment('assigned/7' + userId + '/' + stepShortPath));
			} else {
				fragment.addFragment(getOfficialFragment(stepShortPath));
			}
			return fragment;
		}

		if (roleName === 'dispatcher') {
			// Recently visited business processes (full data)
			fragment.addFragment(getRecentlyVisitedBusinessProcessesFragment(userId, 'dispatcher'));
			if (!assignableProcessingSteps) {
				console.error("\n\nError: Missing assignableProcessingSteps setting for dispatcher");
				return fragment;
			}
			// Assignable roles data
			fragment.addFragment(getDispatcherFragment());
			return fragment;
		}

		console.error("\n\nError: Unrecognized role " + roleName + "\n\n");
		return fragment;
	}, { primitive: true });
};
<commit_msg>Access rules for supervisor role<commit_after>// Data access/propagation rules for apps

'use strict';

var aFrom            = require('es5-ext/array/from')
  , compose          = require('es5-ext/function/#/compose')
  , ensureIterable   = require('es5-ext/iterable/validate-object')
  , findKey          = require('es5-ext/object/find-key')
  , forEach          = require('es5-ext/object/for-each')
  , ensureCallable   = require('es5-ext/object/valid-callable')
  , ensureObject     = require('es5-ext/object/valid-object')
  , ensureString     = require('es5-ext/object/validate-stringifiable-value')
  , endsWith         = require('es5-ext/string/#/ends-with')
  , uncapitalize     = require('es5-ext/string/#/uncapitalize')
  , memoize          = require('memoizee')
  , Set              = require('es6-set')
  , deferred         = require('deferred')
  , unserializeValue = require('dbjs/_setup/unserialize/value')
  , ObservableSet    = require('observable-set')
  , ObservableMulti  = require('observable-multi-set')
  , Fragment         = require('data-fragment')
  , ensureFragment   = require('data-fragment/ensure')
  , FragmentGroup    = require('data-fragment/group')
  , ensureDriver     = require('dbjs-persistence/ensure-driver')
  , unserializeView  = require('../utils/db-view/unserialize-ids')
  , getReducedFrag   = require('./data-fragments/get-reduced-object-fragments')
  , getRedRecFrag    = require('./data-fragments/get-reduced-records-fragment')
  , getObjFragment   = require('./data-fragments/get-direct-object-fragments')
  , getColFragments  = require('./data-fragments/get-collection-fragments')
  , getPartFragments = require('./data-fragments/get-part-object-fragments')
  , getDbRecordSet   = require('./utils/get-db-record-set')
  , userListProps    = require('../apps/users-admin/user-list-properties')

  , create = Object.create, keys = Object.keys, stringify = JSON.stringify
  , emptyFragment = new Fragment()
  , isOfficialRoleName = RegExp.prototype.test.bind(/^official[A-Z]/);

var joinSets = function (sets) {
	var set = new ObservableMulti(sets);
	set.promise = deferred.map(sets, function (set) { return set.promise; });
	return set;
};
module.exports = function (dbDriver, data) {
	var userStorage = ensureDriver(dbDriver).getStorage('user')
	  , reducedStorage = dbDriver.getReducedStorage()
	  , getUserData = getObjFragment(userStorage)
	  , getBusinessProcessData = getObjFragment()
	  , getUserReducedData = getReducedFrag(userStorage)
	  , getReducedData = getReducedFrag(reducedStorage)
	  , resolveOfficialSteps, processingStepsMeta, processingStepsDefaultMap = create(null)
	  , businessProcessListProperties, globalFragment, getMetaAdminFragment
	  , assignableProcessingSteps;

	ensureObject(data);
	processingStepsMeta = ensureObject(data.processingStepsMeta);

	// Eventual fragment that should be passed to all clients
	if (data.globalFragment != null) globalFragment = ensureFragment(data.globalFragment);
	if (data.getMetaAdminFragment != null) {
		getMetaAdminFragment = memoize(ensureCallable(data.getMetaAdminFragment), { length: 0 });
	}
	if (data.assignableProcessingSteps != null) {
		assignableProcessingSteps = new Set(aFrom(ensureIterable(data.assignableProcessingSteps),
			function (stepShortPath) {
				stepShortPath = ensureString(stepShortPath);
				if (!processingStepsMeta[stepShortPath]) {
					throw new Error("Unrecognized step short path " + stringify(stepShortPath));
				}
				return stepShortPath;
			}));
	}
	businessProcessListProperties =
		new Set(aFrom(ensureIterable(data.businessProcessListProperties)));

	// Configure official steps (per user) resolver
	var defaultOfficialStepsResolver = function (userId) {
		var rolesSet = getDbRecordSet(userStorage, userId + '/roles');
		var resultSet = rolesSet.map(unserializeValue).filter(isOfficialRoleName)
			.map(function (roleName) { return uncapitalize.call(roleName.slice('official'.length)); })
			.filter(function (stepShortPath) { return processingStepsMeta[stepShortPath]; });
		resultSet.promise = rolesSet.promise;
		return resultSet;
	};
	if (data.normalizeOfficialStepsPaths != null) {
		resolveOfficialSteps = compose.bind(ensureCallable(data.resolveOfficialSteps),
			defaultOfficialStepsResolver);
	} else {
		resolveOfficialSteps = defaultOfficialStepsResolver;
	}
	resolveOfficialSteps = memoize(resolveOfficialSteps, { length: 1, primitive: true });

	// Resolve default step statuses (in most cases 'pending')
	forEach(processingStepsMeta, function (meta, stepShortPath) {
		var defaultKey = findKey(meta, function (conf) {
			return conf.default;
		});
		if (!defaultKey) throw new Error("Not found default key for " + stringify(stepShortPath));
		processingStepsDefaultMap[stepShortPath] = defaultKey;
	});
	var resolveDefaultStatus = function (stepShortPath) {
		var defaultKey = processingStepsDefaultMap[stepShortPath];
		if (!defaultKey) throw new Error("Unrecognized step short path " + stringify(stepShortPath));
		return defaultKey;
	};

	// Configure fragment resolvers
	// Non role specific
	var getUserFragment = function (id) {
		return getUserData(id,
			{ filter: function (data) { return !endsWith.call(data.id, '/password'); } });
	};
	var resolveViewData = function (data) {
		return unserializeView(unserializeValue(data.value)).map(function (id) {
			return id.split('/', 1)[0];
		});
	};
	var getFirstPageItems = memoize(function (storage, viewName) {
		var objects = new ObservableSet(), id = 'views/' + viewName + '/21';
		objects.promise = storage.getReduced(id)(function (data) {
			if (data) objects.reload(resolveViewData(data));
		});
		storage.on('keyid:' + id, function (event) { objects.reload(resolveViewData(event.data)); });
		return objects;
	}, { primitive: true });
	var addOfficialStepsPendingSizes = (function () {
		var resolveFragment = function (stepsShortPaths) {
			var ids;
			if (!stepsShortPaths.size) return emptyFragment;
			ids = [];
			stepsShortPaths.forEach(function (stepShortPath) {
				var defaultKey = resolveDefaultStatus(stepShortPath);
				ids.push('views/pendingBusinessProcesses/' + stepShortPath + '/' + defaultKey +
					'/totalSize');
			});
			return getRedRecFrag(reducedStorage, ids);
		};
		return function (userId, fragment) {
			var stepsShortPaths = resolveOfficialSteps(userId)
			  , current;
			current = resolveFragment(stepsShortPaths);
			fragment.addFragment(current);
			stepsShortPaths.on('change', function () {
				var nu = resolveFragment(stepsShortPaths);
				if (nu === current) return;
				fragment.addFragment(nu);
				fragment.deleteFragment(current);
				current = nu;
			});
		};
	}());

	// Users Admin resolvers
	var getUserListFragment = getPartFragments(userStorage, userListProps);
	var getRecentlyVisitedUsersFragment = function (userId) {
		var list = getDbRecordSet(userStorage, userId + '/recentlyVisited/users')
			.map(function (value) { return value.slice(1); });

		return getColFragments(list, getUserListFragment);
	};
	var getUsersAdminFragment = memoize(function () {
		var fragment = new FragmentGroup();
		// First page snapshot
		fragment.addFragment(getUserReducedData('views/usersAdmin'));
		// First page list data
		fragment.addFragment(getColFragments(getFirstPageItems(userStorage, 'usersAdmin'),
			getUserListFragment));
		return fragment;
	});

	// Official roles resolvers
	var getRecentlyVisitedBusinessProcessesFragment = function (userId, roleName) {
		var list = getDbRecordSet(userStorage,
			userId + '/recentlyVisited/businessProcesses/' + roleName)
			.map(function (value) { return value.slice(1); });

		return getColFragments(list, getBusinessProcessData);
	};
	var getBusinessProcessOfficialListFragment =
		getPartFragments(null, businessProcessListProperties);

	var getOfficialFragment = memoize(function (stepShortPath) {
		var fragment = new FragmentGroup()
		  , defaultStatusName = resolveDefaultStatus(stepShortPath);

		// To be visited (recently pending) business processes (full data)
		fragment.addFragment(getColFragments(getFirstPageItems(reducedStorage,
			'pendingBusinessProcesses/' + stepShortPath + '/' + defaultStatusName).toArray().slice(0, 10),
			getBusinessProcessData));
		// First page snapshot for each status
		fragment.addFragment(getReducedData('views/pendingBusinessProcesses/' + stepShortPath));
		// First page list data for each status
		fragment.addFragment(getColFragments(joinSets(
			keys(processingStepsMeta[stepShortPath]).map(function (status) {
				return getFirstPageItems(reducedStorage,
					'pendingBusinessProcesses/' + stepShortPath + '/' + status);
			})
		), getBusinessProcessOfficialListFragment));
		return fragment;
	}, { primitive: true });

	// Dispatcher resolvers
	var getBusinessProcessDispatcherListFragment = getPartFragments(null, (function (props) {
		var set = new Set(props);
		assignableProcessingSteps.forEach(function (stepShortPath) {
			// TODO: Fix for deep paths
			set.add('processingSteps/map/' + stepShortPath + '/assignee');
		});
		return set;
	}(businessProcessListProperties)));
	var getDispatcherFragment = memoize(function () {
		var fragment = new FragmentGroup();

		assignableProcessingSteps.forEach(function (stepShortPath) {
			var defaultStatusName = resolveDefaultStatus(stepShortPath);
			// First page snapshot
			fragment.addFragment(getReducedData('views/pendingBusinessProcesses/' + stepShortPath + '/' +
				defaultStatusName));
			// First page list data
			fragment.addFragment(getColFragments(getFirstPageItems(reducedStorage,
				'pendingBusinessProcesses/' + stepShortPath + '/' + defaultStatusName),
				getBusinessProcessDispatcherListFragment));
		});
		return fragment;
	});

	// Supervisor resolvers
	var getBusinessProcessSupervisorListFragment = getPartFragments(null, (function () {
		var set = new Set(['businessName']);
		forEach(processingStepsMeta, function (data, stepShortPath) {
			// TODO: Fix for deep paths
			set.add('processingSteps/map/' + stepShortPath + '/resolvedStatus');
		});
		return set;
	}()));
	var getSupervisorFragment = memoize(function () {
		var fragment = new FragmentGroup();
		// "All roles" first page snapshot
		fragment.addFragment(getReducedData('views/supervisor'));
		fragment.addFragment(getColFragments(getFirstPageItems(reducedStorage, 'supervisor'),
			getBusinessProcessSupervisorListFragment));

		// Per role first page snapshots
		forEach(processingStepsMeta, function (data, stepShortPath) {
			var defaultStatusName = resolveDefaultStatus(stepShortPath);
			// First page snapshot
			fragment.addFragment(getReducedData('views/pendingBusinessProcesses/' + stepShortPath + '/' +
				defaultStatusName));
			// First page list data
			fragment.addFragment(getColFragments(getFirstPageItems(reducedStorage,
				'pendingBusinessProcesses/' + stepShortPath + '/' + defaultStatusName),
				getBusinessProcessSupervisorListFragment));
		});
		return fragment;
	});

	return memoize(function (appId) {
		var userId, roleName, stepShortPath, custom, fragment, initialBusinessProcesses, promise;

		appId = appId.split('.');
		userId = appId[0];
		roleName = appId[1];
		custom = appId[2];

		if (!roleName) return emptyFragment; // Temporary inconsistent state (client migration)

		fragment = new FragmentGroup();

		// User profile data
		fragment.addFragment(getUserFragment(userId));
		// Sizes of pending files in official roles of user
		addOfficialStepsPendingSizes(userId, fragment);
		// Eventual global fragment
		if (globalFragment) fragment.addFragment(globalFragment);

		if (roleName === 'user') {
			if (custom) {
				// Business process application
				// Business process data
				fragment.addFragment(getBusinessProcessData(custom));
			} else {
				// My account
				// All businesss processes (full data)
				initialBusinessProcesses = getDbRecordSet(userStorage,
					userId + '/initialBusinessProcesses');
				promise = initialBusinessProcesses.promise;
				initialBusinessProcesses = initialBusinessProcesses
					.map(function (value) { return value.slice(1); });
				initialBusinessProcesses.promise = promise;
				// - All initial business processes
				fragment.addFragment(getColFragments(initialBusinessProcesses, getBusinessProcessData));
			}
			return fragment;
		}
		if (roleName === 'usersAdmin') {
			// Recently visited users (full data)
			fragment.addFragment(getRecentlyVisitedUsersFragment(userId));
			// Users Admin specific data
			fragment.addFragment(getUsersAdminFragment());
			return fragment;
		}
		if (roleName === 'metaAdmin') {
			if (getMetaAdminFragment) fragment.addFragment(getMetaAdminFragment());
			return fragment;
		}

		if (isOfficialRoleName(roleName)) {
			stepShortPath = uncapitalize.call(roleName.slice('official'.length));
			// Recently visited business processes (full data)
			fragment.addFragment(getRecentlyVisitedBusinessProcessesFragment(userId, stepShortPath));
			// Official role specific data
			if (assignableProcessingSteps && assignableProcessingSteps.has(stepShortPath)) {
				fragment.addFragment(getOfficialFragment('assigned/7' + userId + '/' + stepShortPath));
			} else {
				fragment.addFragment(getOfficialFragment(stepShortPath));
			}
			return fragment;
		}

		if (roleName === 'dispatcher') {
			// Recently visited business processes (full data)
			fragment.addFragment(getRecentlyVisitedBusinessProcessesFragment(userId, 'dispatcher'));
			if (!assignableProcessingSteps) {
				console.error("\n\nError: Missing assignableProcessingSteps setting for dispatcher");
				return fragment;
			}
			// Assignable roles data
			fragment.addFragment(getDispatcherFragment());
			return fragment;
		}

		if (roleName === 'supervisor') {
			// Recently visited business processes (full data)
			fragment.addFragment(getRecentlyVisitedBusinessProcessesFragment(userId, 'supervisor'));
			// Supervisor specific data
			fragment.addFragment(getSupervisorFragment());
			return fragment;
		}
		console.error("\n\nError: Unrecognized role " + roleName + "\n\n");
		return fragment;
	}, { primitive: true });
};
<|endoftext|>


<commit_before>var Plurb = require('../db/dbconfig').Plurb;
var User = require('../db/dbconfig').User;

module.exports = {
  //currently not being used
  getAllPlurbs: function (req, res) {
    Plurb.findAll({})
    .then(function (plurbs) {
      res.status(200).json(plurbs);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  createPlurb: function (req, res) {
    var googId = req.session.user;
    var topicId = req.body.topicId;
    //make a db call using the googid and returns user data
    User.find({where:
      {googid: googId}
    })
    .then(function (user) {
      //set the values for first and last names, picture
      //put all data into an objected used to create plurb
      var plurbData = {
        text: req.body.text,
        lat: req.body.lat,
        long: req.body.long,
        firstName: user.dataValues.firstName,
        lastName: user.dataValues.lastName,
        picture: user.dataValues.picture
      };
      Plurb.create(plurbData)
      .then(function (plurb) {
        //sets the foreign key of googId and topicId
        plurb.setUser(googId);
        plurb.setTopic(topicId);
        res.status(201).json(plurb);
      })
      .catch(function (err) {
        console.error(err);
      });
    });
  },

  getPlurb: function (req, res) {
    var plurbId = req.params.plurbId;
    Plurb.findById(plurbId)
    .then(function (plurb) {
      res.status(200).json(plurb);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  deletePlurb: function (req, res) {
    var plurbId = req.params.plurbId;
    Plurb.destroy({where: {id: plurbId}})
    .then(function () {
      res.status(201);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  getPlurbsByGoogId: function (req, res) {
    var googId = req.params.googId;
    Plurb.findAll({where: {UserGoogid: googId}})
    .then(function (plurbs) {
      res.status(200).json(plurbs);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  getPlurbsByLocation: function (req, res) {
    var googId = req.body.googId;
    var topicId = req.body.topicId;
    var minLat = req.body.mapBounds.minLat;
    var maxLat = req.body.mapBounds.maxLat;
    var minLng = req.body.mapBounds.minLng;
    var maxLng = req.body.mapBounds.maxLng;
    var query = {};
  //builds query object based off the presences of googId and/or topicId
    if(!topicId && !googId) {
  //if topic id is 0 and there is no googId, send back all plurbs in that location regardless of topic
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]}
        }
      };
    } else if (!topicId) {
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]},
          UserGoogid: googId
        }
      };
    } else if (!googId) {
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]},
          TopicId: topicId,
        }
      };
    } else {
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]},
          TopicId: topicId,
          UserGoogid: googId
        }
      };
    }

    Plurb.findAll(query)
    .then(function (plurbs) {
      res.status(200).json(plurbs);
    })
    .catch(function (err) {
      console.error (err);
    });
  },

  getAllFriendsAllPlurbs: function (req, res) {
    var googId = req.session.user;
    var friendsGoogIds = [];

    //Create array of all friends googIds
    User.find({where: {googid: googId}})
    .then(function(user) {
      //this built in Sequelize method will pull all friends
      user.getFriends()
       .then(function(friends){
        friends.forEach(function(friend) {
          //push each friend googid to the array
          friendsGoogIds.push(Number(friend.dataValues.googid));
        });
       })
       .then(function(){
        //find all plurbs that have the friend googIds as UserGoogId (meaning they authored the plurb)
          Plurb.findAll({
            where: {
              $or: [
                {UserGoogid: friendsGoogIds}
              ]
            }
          })
            .then(function (plurbs) {
              res.status(200).json(plurbs);
            })
            .catch(function (err) {
              console.error(err);
            });
       });
    })
    .catch(function (err) {
      console.error(err);
    });
  }
};
<commit_msg>(feat) Will eager load Topic on getAllPlurbs method<commit_after>var Plurb = require('../db/dbconfig').Plurb;
var User = require('../db/dbconfig').User;
var Topic = require('../db/dbconfig').Topic;

module.exports = {
  getAllPlurbs: function (req, res) {
    Plurb.findAll({
       include: [Topic]
    })
    .then(function (plurbs) {
      res.status(200).json(plurbs);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  createPlurb: function (req, res) {
    var googId = req.session.user;
    var topicId = req.body.topicId;
    //make a db call using the googid and returns user data
    User.find({where:
      {googid: googId}
    })
    .then(function (user) {
      //set the values for first and last names, picture
      //put all data into an objected used to create plurb
      var plurbData = {
        text: req.body.text,
        lat: req.body.lat,
        long: req.body.long,
        firstName: user.dataValues.firstName,
        lastName: user.dataValues.lastName,
        picture: user.dataValues.picture
      };
      Plurb.create(plurbData)
      .then(function (plurb) {
        //sets the foreign key of googId and topicId
        plurb.setUser(googId);
        plurb.setTopic(topicId);
        res.status(201).json(plurb);
      })
      .catch(function (err) {
        console.error(err);
      });
    });
  },

  getPlurb: function (req, res) {
    var plurbId = req.params.plurbId;
    Plurb.findById(plurbId)
    .then(function (plurb) {
      res.status(200).json(plurb);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  deletePlurb: function (req, res) {
    var plurbId = req.params.plurbId;
    Plurb.destroy({where: {id: plurbId}})
    .then(function () {
      res.status(201);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  getPlurbsByGoogId: function (req, res) {
    var googId = req.params.googId;
    Plurb.findAll({where: {UserGoogid: googId}})
    .then(function (plurbs) {
      res.status(200).json(plurbs);
    })
    .catch(function (err) {
      console.error(err);
    });
  },

  getPlurbsByLocation: function (req, res) {
    var googId = req.body.googId;
    var topicId = req.body.topicId;
    var minLat = req.body.mapBounds.minLat;
    var maxLat = req.body.mapBounds.maxLat;
    var minLng = req.body.mapBounds.minLng;
    var maxLng = req.body.mapBounds.maxLng;
    var query = {};
  //builds query object based off the presences of googId and/or topicId
    if(!topicId && !googId) {
  //if topic id is 0 and there is no googId, send back all plurbs in that location regardless of topic
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]}
        }
      };
    } else if (!topicId) {
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]},
          UserGoogid: googId
        }
      };
    } else if (!googId) {
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]},
          TopicId: topicId,
        }
      };
    } else {
      query = {
        where: {
          lat: {$between: [minLat, maxLat]},
          long: {$between: [minLng, maxLng]},
          TopicId: topicId,
          UserGoogid: googId
        }
      };
    }

    Plurb.findAll(query)
    .then(function (plurbs) {
      res.status(200).json(plurbs);
    })
    .catch(function (err) {
      console.error (err);
    });
  },

  getAllFriendsAllPlurbs: function (req, res) {
    var googId = req.session.user;
    var friendsGoogIds = [];

    //Create array of all friends googIds
    User.find({where: {googid: googId}})
    .then(function(user) {
      //this built in Sequelize method will pull all friends
      user.getFriends()
       .then(function(friends){
        friends.forEach(function(friend) {
          //push each friend googid to the array
          friendsGoogIds.push(Number(friend.dataValues.googid));
        });
       })
       .then(function(){
        //find all plurbs that have the friend googIds as UserGoogId (meaning they authored the plurb)
          Plurb.findAll({
            where: {
              $or: [
                {UserGoogid: friendsGoogIds}
              ]
            }
          })
            .then(function (plurbs) {
              res.status(200).json(plurbs);
            })
            .catch(function (err) {
              console.error(err);
            });
       });
    })
    .catch(function (err) {
      console.error(err);
    });
  }
};
<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';

let tempFolder = '/tmp/userData';
if (RocketChat.settings.get('UserData_FileSystemPath') != null) {
	if (RocketChat.settings.get('UserData_FileSystemPath').trim() !== '') {
		tempFolder = RocketChat.settings.get('UserData_FileSystemPath');
	}
}

Meteor.methods({
	requestDataDownload({fullExport = false}) {
		const currentUserData = Meteor.user();
		const userId = currentUserData._id;

		const lastOperation = RocketChat.models.ExportOperations.findLastOperationByUser(userId, fullExport);

		if (lastOperation) {
			const yesterday = new Date();
			yesterday.setUTCDate(yesterday.getUTCDate() - 1);

			if (lastOperation.createdAt > yesterday) {
				return {
					requested: false,
					exportOperation: lastOperation
				};
			}
		}

		const subFolderName = fullExport ? 'full' : 'partial';
		const baseFolder = path.join(tempFolder, userId);
		if (!fs.existsSync(baseFolder)) {
			fs.mkdirSync(baseFolder);
		}

		const folderName = path.join(baseFolder, subFolderName);
		if (!fs.existsSync(folderName)) {
			fs.mkdirSync(folderName);
		}
		const assetsFolder = path.join(folderName, 'assets');
		if (!fs.existsSync(assetsFolder)) {
			fs.mkdirSync(assetsFolder);
		}

		const exportOperation = {
			userId : currentUserData._id,
			roomList: null,
			status: 'pending',
			exportPath: folderName,
			assetsPath: assetsFolder,
			fileList: [],
			generatedFile: null,
			fullExport
		};

		RocketChat.models.ExportOperations.create(exportOperation);

		return {
			requested: true,
			exportOperation
		};
	}
});
<commit_msg>Create temp folder if it doesn't exist (#10837)<commit_after>import fs from 'fs';
import path from 'path';

let tempFolder = '/tmp/userData';
if (RocketChat.settings.get('UserData_FileSystemPath') != null) {
	if (RocketChat.settings.get('UserData_FileSystemPath').trim() !== '') {
		tempFolder = RocketChat.settings.get('UserData_FileSystemPath');
	}
}

Meteor.methods({
	requestDataDownload({fullExport = false}) {
		const currentUserData = Meteor.user();
		const userId = currentUserData._id;

		const lastOperation = RocketChat.models.ExportOperations.findLastOperationByUser(userId, fullExport);

		if (lastOperation) {
			const yesterday = new Date();
			yesterday.setUTCDate(yesterday.getUTCDate() - 1);

			if (lastOperation.createdAt > yesterday) {
				return {
					requested: false,
					exportOperation: lastOperation
				};
			}
		}

		if (!fs.existsSync(tempFolder)) {
			fs.mkdirSync(tempFolder);
		}

		const subFolderName = fullExport ? 'full' : 'partial';
		const baseFolder = path.join(tempFolder, userId);
		if (!fs.existsSync(baseFolder)) {
			fs.mkdirSync(baseFolder);
		}

		const folderName = path.join(baseFolder, subFolderName);
		if (!fs.existsSync(folderName)) {
			fs.mkdirSync(folderName);
		}
		const assetsFolder = path.join(folderName, 'assets');
		if (!fs.existsSync(assetsFolder)) {
			fs.mkdirSync(assetsFolder);
		}

		const exportOperation = {
			userId : currentUserData._id,
			roomList: null,
			status: 'pending',
			exportPath: folderName,
			assetsPath: assetsFolder,
			fileList: [],
			generatedFile: null,
			fullExport
		};

		RocketChat.models.ExportOperations.create(exportOperation);

		return {
			requested: true,
			exportOperation
		};
	}
});
<|endoftext|>


<commit_before>import fs from 'fs';
import { execFile } from 'child_process';
import { promisify } from 'util';
import R from 'ramda';
import lunr from 'lunr';
import getManifestsFromFiles from './getManifestsFromFiles';

const readFile = promisify(fs.readFile);

let manifestPromise;
let indexPromise;
let dependentsPromise;
let index;

async function refreshIndex(repoDir) {
  const indexFile = './searchIndex.json';

  await new Promise((resolve, reject) => {
    execFile('node', ['./build-index/cli.js', repoDir, indexFile], (error, stdout, stderr) => {
      console.log(stdout);
      if (error) reject(error);
      else resolve();
    });
  });

  const stringIndex = await readFile(indexFile);
  const obj = JSON.parse(stringIndex);

  index = lunr.Index.load(obj.index);

  return index;
}

const indexDependencies = R.pipe(
  R.filter(manifest => !!manifest.dependencies),
  R.chain(R.pipe(
    R.props(['key_path', 'dependencies']),
    ([keyPath, dependencies]) => dependencies.map(dependency => ({ dependency, keyPath })),
  )),
  R.groupBy(R.prop('dependency')),
  R.map(R.map(R.prop('keyPath'))),
);

export default {
  get indexPromise() {
    return indexPromise;
  },
  get manifests() {
    return manifestPromise;
  },
  get index() {
    return index;
  },
  dependents(key) {
    return dependentsPromise.then(x => x[key] || []);
  },
  refreshIndex: (repoDir) => {
    indexPromise = refreshIndex(repoDir);
    manifestPromise = getManifestsFromFiles(repoDir);
    dependentsPromise = manifestPromise.then(indexDependencies);

    return indexPromise;
  },
};
<commit_msg>Update searchIndex.js<commit_after>import fs from 'fs';
import { execFile } from 'child_process';
import { promisify } from 'util';
import R from 'ramda';
import lunr from 'lunr';
import getManifestsFromFiles from './getManifestsFromFiles';

const readFile = promisify(fs.readFile);

let manifestPromise;
let indexPromise;
let dependentsPromise;
let index;

async function refreshIndex(repoDir) {
  const indexFile = './searchIndex.json';

  await new Promise((resolve, reject) => {
    execFile('node', ['./build-index/cli.js', repoDir, indexFile], (error, stdout, stderr) => {
      console.log(stdout);
      if (error) reject(error);
      else resolve();
    });
  });

  const stringIndex = await readFile(indexFile);
  const obj = JSON.parse(stringIndex);

  index = lunr.Index.load(obj.index);

  return index;
}

const indexDependencies = R.pipe(
  R.filter(manifest => manifest.dependencies),
  R.chain(({ key_path, dependencies }) => dependencies.map(dependency => ([dependency, key_path]))),
  R.groupBy(([dependency]) => dependency),
  R.map(R.map(([, key_path]) => key_path)),
);

export default {
  get indexPromise() {
    return indexPromise;
  },
  get manifests() {
    return manifestPromise;
  },
  get index() {
    return index;
  },
  dependents(key) {
    return dependentsPromise.then(x => x[key] || []);
  },
  refreshIndex: (repoDir) => {
    indexPromise = refreshIndex(repoDir);
    manifestPromise = getManifestsFromFiles(repoDir);
    dependentsPromise = manifestPromise.then(indexDependencies);

    return indexPromise;
  },
};
<|endoftext|>


<commit_before><commit_msg>[docs] More tweaks for better defaults on mobile/desktop<commit_after><|endoftext|>


<commit_before>const { promises: fs, readdirSync } = require('fs');
const path = require('path');
const { prepareMarkdown } = require('./parseMarkdown');

const notEnglishMarkdownRegExp = /-([a-z]{2})\.md$/;
// TODO: pass as argument
const LANGUAGES_IN_PROGRESS = ['en', 'zh', 'ru', 'pt', 'es', 'fr', 'de', 'ja'];

/**
 * @param {string} string
 */
function upperCaseFirst(string) {
  return `${string[0].toUpperCase()}${string.slice(1)}`;
}

/**
 * @param {string} moduleID
 * @example moduleIDToJSIdentifier('./Box.js') === '$$IndexJs'
 * @example moduleIDToJSIdentifier('./Box-new.js') === '$$BoxNewJs'
 * @example moduleIDToJSIdentifier('../Box-new.js') === '$$$BoxNewJs'
 */
function moduleIDToJSIdentifier(moduleID) {
  const delimiter = /(\.|-|\/)/;
  return moduleID
    .split(delimiter)
    .filter((part) => !delimiter.test(part))
    .map((part) => (part.length === 0 ? '$' : part))
    .map(upperCaseFirst)
    .join('');
}

const componentPackageMapping = {
  'material-ui': {},
  base: {},
};

const packages = [
  {
    product: 'material-ui',
    paths: [
      path.join(__dirname, '../../../packages/mui-lab/src'),
      path.join(__dirname, '../../../packages/mui-material/src'),
      path.join(__dirname, '../../../packages/mui-base/src'),
    ],
  },
  {
    product: 'base',
    paths: [path.join(__dirname, '../../../packages/mui-base/src')],
  },
];

packages.forEach((pkg) => {
  pkg.paths.forEach((pkgPath) => {
    const match = pkgPath.match(/packages(?:\\|\/)([^/\\]+)(?:\\|\/)src/);
    const packageName = match ? match[1] : null;
    if (!packageName) {
      throw new Error(`cannot find package name from path: ${pkgPath}`);
    }
    const filePaths = readdirSync(pkgPath);
    filePaths.forEach((folder) => {
      if (folder.match(/^[A-Z]/)) {
        if (!componentPackageMapping[pkg.product]) {
          throw new Error(`componentPackageMapping must have "${pkg.product}" as a key`);
        }
        // filename starts with Uppercase = component
        componentPackageMapping[pkg.product][folder] = packageName;
      }
    });
  });
});

/**
 * @type {import('webpack').loader.Loader}
 */
module.exports = async function demoLoader() {
  const englishFilepath = this.resourcePath;

  const englishFilename = path.basename(englishFilepath, '.md');

  const files = await fs.readdir(path.dirname(englishFilepath));
  const translations = await Promise.all(
    files
      .map((filename) => {
        if (filename === `${englishFilename}.md`) {
          return {
            filename,
            userLanguage: 'en',
          };
        }

        const matchNotEnglishMarkdown = filename.match(notEnglishMarkdownRegExp);

        if (
          filename.startsWith(englishFilename) &&
          matchNotEnglishMarkdown !== null &&
          LANGUAGES_IN_PROGRESS.indexOf(matchNotEnglishMarkdown[1]) !== -1
        ) {
          return {
            filename,
            userLanguage: matchNotEnglishMarkdown[1],
          };
        }

        return null;
      })
      .filter((translation) => translation)
      .map(async (translation) => {
        const filepath = path.join(path.dirname(englishFilepath), translation.filename);
        this.addDependency(filepath);
        const markdown = await fs.readFile(filepath, { encoding: 'utf8' });

        return {
          ...translation,
          markdown,
        };
      }),
  );

  const pageFilename = this.context
    .replace(this.rootContext, '')
    // win32 to posix
    .replace(/\\/g, '/');
  const { docs } = prepareMarkdown({ pageFilename, translations, componentPackageMapping });

  const demos = {};
  const components = {};
  const demoModuleIDs = new Set();
  const componentModuleIDs = new Set();
  const demoNames = Array.from(
    new Set(
      docs.en.rendered
        .filter((markdownOrComponentConfig) => {
          return typeof markdownOrComponentConfig !== 'string' && markdownOrComponentConfig.demo;
        })
        .map((demoConfig) => {
          return demoConfig.demo;
        }),
    ),
  );

  await Promise.all(
    demoNames.map(async (demoName) => {
      // TODO: const moduleID = demoName;
      // The import paths currently use a completely different format.
      // They should just use relative imports.
      const moduleID = `./${demoName.replace(
        `pages/${pageFilename.replace(/^\/src\/pages\//, '')}/`,
        '',
      )}`;

      const moduleFilepath = path.join(
        path.dirname(this.resourcePath),
        moduleID.replace(/\//g, path.sep),
      );
      this.addDependency(moduleFilepath);
      demos[demoName] = {
        module: moduleID,
        raw: await fs.readFile(moduleFilepath, { encoding: 'utf-8' }),
      };
      demoModuleIDs.add(moduleID);

      try {
        const previewFilepath = moduleFilepath.replace(/\.js$/, '.tsx.preview');

        const jsxPreview = await fs.readFile(previewFilepath, { encoding: 'utf-8' });
        this.addDependency(previewFilepath);

        demos[demoName].jsxPreview = jsxPreview;
      } catch (error) {
        // No preview exists. This is fine.
      }

      try {
        const moduleTS = moduleID.replace(/\.js$/, '.tsx');
        const moduleTSFilepath = path.join(
          path.dirname(this.resourcePath),
          moduleTS.replace(/\//g, path.sep),
        );
        this.addDependency(moduleTSFilepath);
        const rawTS = await fs.readFile(moduleTSFilepath, { encoding: 'utf-8' });

        // In development devs can choose whether they want to work on the TS or JS version.
        // But this leads to building both demo version i.e. more build time.
        demos[demoName].moduleTS = this.mode === 'production' ? moduleID : moduleTS;
        demos[demoName].rawTS = rawTS;
        demoModuleIDs.add(demos[demoName].moduleTS);
      } catch (error) {
        // TS version of the demo doesn't exist. This is fine.
      }
    }),
  );

  const componentNames = Array.from(
    new Set(
      docs.en.rendered
        .filter((markdownOrComponentConfig) => {
          return (
            typeof markdownOrComponentConfig !== 'string' && markdownOrComponentConfig.component
          );
        })
        .map((componentConfig) => {
          return componentConfig.component;
        }),
    ),
  );

  componentNames.forEach((componentName) => {
    const moduleID = path.join(this.rootContext, 'src', componentName);

    components[moduleID] = componentName;
    componentModuleIDs.add(moduleID);
  });

  const transformed = `
    ${Array.from(demoModuleIDs)
      .map((moduleID) => {
        return `import ${moduleIDToJSIdentifier(moduleID)} from '${moduleID}';`;
      })
      .join('\n')}
    ${Array.from(componentModuleIDs)
      .map((moduleID) => {
        return `import ${moduleIDToJSIdentifier(moduleID)} from '${moduleID}';`;
      })
      .join('\n')}

    export const docs = ${JSON.stringify(docs, null, 2)};
    export const demos = ${JSON.stringify(demos, null, 2)};
    export const demoComponents = {${Array.from(demoModuleIDs)
      .map((moduleID) => {
        return `${JSON.stringify(moduleID)}: ${moduleIDToJSIdentifier(moduleID)},`;
      })
      .join('\n')}};
        export const srcComponents = {${Array.from(componentModuleIDs)
          .map((moduleID) => {
            return `${JSON.stringify(components[moduleID])}: ${moduleIDToJSIdentifier(moduleID)},`;
          })
          .join('\n')}};
  `;

  return transformed;
};
<commit_msg>[core] Fix markdown loader on Windows (#34623)<commit_after>const { promises: fs, readdirSync } = require('fs');
const path = require('path');
const { prepareMarkdown } = require('./parseMarkdown');

const notEnglishMarkdownRegExp = /-([a-z]{2})\.md$/;
// TODO: pass as argument
const LANGUAGES_IN_PROGRESS = ['en', 'zh', 'ru', 'pt', 'es', 'fr', 'de', 'ja'];

/**
 * @param {string} string
 */
function upperCaseFirst(string) {
  return `${string[0].toUpperCase()}${string.slice(1)}`;
}

/**
 * @param {string} moduleID
 * @example moduleIDToJSIdentifier('./Box.js') === '$$IndexJs'
 * @example moduleIDToJSIdentifier('./Box-new.js') === '$$BoxNewJs'
 * @example moduleIDToJSIdentifier('../Box-new.js') === '$$$BoxNewJs'
 */
function moduleIDToJSIdentifier(moduleID) {
  const delimiter = /(\.|-|\/|:)/;
  return moduleID
    .split(delimiter)
    .filter((part) => !delimiter.test(part))
    .map((part) => (part.length === 0 ? '$' : part))
    .map(upperCaseFirst)
    .join('');
}

const componentPackageMapping = {
  'material-ui': {},
  base: {},
};

const packages = [
  {
    product: 'material-ui',
    paths: [
      path.join(__dirname, '../../../packages/mui-lab/src'),
      path.join(__dirname, '../../../packages/mui-material/src'),
      path.join(__dirname, '../../../packages/mui-base/src'),
    ],
  },
  {
    product: 'base',
    paths: [path.join(__dirname, '../../../packages/mui-base/src')],
  },
];

packages.forEach((pkg) => {
  pkg.paths.forEach((pkgPath) => {
    const match = pkgPath.match(/packages(?:\\|\/)([^/\\]+)(?:\\|\/)src/);
    const packageName = match ? match[1] : null;
    if (!packageName) {
      throw new Error(`cannot find package name from path: ${pkgPath}`);
    }
    const filePaths = readdirSync(pkgPath);
    filePaths.forEach((folder) => {
      if (folder.match(/^[A-Z]/)) {
        if (!componentPackageMapping[pkg.product]) {
          throw new Error(`componentPackageMapping must have "${pkg.product}" as a key`);
        }
        // filename starts with Uppercase = component
        componentPackageMapping[pkg.product][folder] = packageName;
      }
    });
  });
});

/**
 * @type {import('webpack').loader.Loader}
 */
module.exports = async function demoLoader() {
  const englishFilepath = this.resourcePath;

  const englishFilename = path.basename(englishFilepath, '.md');

  const files = await fs.readdir(path.dirname(englishFilepath));
  const translations = await Promise.all(
    files
      .map((filename) => {
        if (filename === `${englishFilename}.md`) {
          return {
            filename,
            userLanguage: 'en',
          };
        }

        const matchNotEnglishMarkdown = filename.match(notEnglishMarkdownRegExp);

        if (
          filename.startsWith(englishFilename) &&
          matchNotEnglishMarkdown !== null &&
          LANGUAGES_IN_PROGRESS.indexOf(matchNotEnglishMarkdown[1]) !== -1
        ) {
          return {
            filename,
            userLanguage: matchNotEnglishMarkdown[1],
          };
        }

        return null;
      })
      .filter((translation) => translation)
      .map(async (translation) => {
        const filepath = path.join(path.dirname(englishFilepath), translation.filename);
        this.addDependency(filepath);
        const markdown = await fs.readFile(filepath, { encoding: 'utf8' });

        return {
          ...translation,
          markdown,
        };
      }),
  );

  const pageFilename = this.context
    .replace(this.rootContext, '')
    // win32 to posix
    .replace(/\\/g, '/');
  const { docs } = prepareMarkdown({ pageFilename, translations, componentPackageMapping });

  const demos = {};
  const components = {};
  const demoModuleIDs = new Set();
  const componentModuleIDs = new Set();
  const demoNames = Array.from(
    new Set(
      docs.en.rendered
        .filter((markdownOrComponentConfig) => {
          return typeof markdownOrComponentConfig !== 'string' && markdownOrComponentConfig.demo;
        })
        .map((demoConfig) => {
          return demoConfig.demo;
        }),
    ),
  );

  await Promise.all(
    demoNames.map(async (demoName) => {
      // TODO: const moduleID = demoName;
      // The import paths currently use a completely different format.
      // They should just use relative imports.
      const moduleID = `./${demoName.replace(
        `pages/${pageFilename.replace(/^\/src\/pages\//, '')}/`,
        '',
      )}`;

      const moduleFilepath = path.join(
        path.dirname(this.resourcePath),
        moduleID.replace(/\//g, path.sep),
      );
      this.addDependency(moduleFilepath);
      demos[demoName] = {
        module: moduleID,
        raw: await fs.readFile(moduleFilepath, { encoding: 'utf-8' }),
      };
      demoModuleIDs.add(moduleID);

      try {
        const previewFilepath = moduleFilepath.replace(/\.js$/, '.tsx.preview');

        const jsxPreview = await fs.readFile(previewFilepath, { encoding: 'utf-8' });
        this.addDependency(previewFilepath);

        demos[demoName].jsxPreview = jsxPreview;
      } catch (error) {
        // No preview exists. This is fine.
      }

      try {
        const moduleTS = moduleID.replace(/\.js$/, '.tsx');
        const moduleTSFilepath = path.join(
          path.dirname(this.resourcePath),
          moduleTS.replace(/\//g, path.sep),
        );
        this.addDependency(moduleTSFilepath);
        const rawTS = await fs.readFile(moduleTSFilepath, { encoding: 'utf-8' });

        // In development devs can choose whether they want to work on the TS or JS version.
        // But this leads to building both demo version i.e. more build time.
        demos[demoName].moduleTS = this.mode === 'production' ? moduleID : moduleTS;
        demos[demoName].rawTS = rawTS;
        demoModuleIDs.add(demos[demoName].moduleTS);
      } catch (error) {
        // TS version of the demo doesn't exist. This is fine.
      }
    }),
  );

  const componentNames = Array.from(
    new Set(
      docs.en.rendered
        .filter((markdownOrComponentConfig) => {
          return (
            typeof markdownOrComponentConfig !== 'string' && markdownOrComponentConfig.component
          );
        })
        .map((componentConfig) => {
          return componentConfig.component;
        }),
    ),
  );

  componentNames.forEach((componentName) => {
    const moduleID = path.join(this.rootContext, 'src', componentName).replace(/\\/g, '/');

    components[moduleID] = componentName;
    componentModuleIDs.add(moduleID);
  });

  const transformed = `
    ${Array.from(demoModuleIDs)
      .map((moduleID) => {
        return `import ${moduleIDToJSIdentifier(moduleID)} from '${moduleID}';`;
      })
      .join('\n')}
    ${Array.from(componentModuleIDs)
      .map((moduleID) => {
        return `import ${moduleIDToJSIdentifier(moduleID)} from '${moduleID}';`;
      })
      .join('\n')}

    export const docs = ${JSON.stringify(docs, null, 2)};
    export const demos = ${JSON.stringify(demos, null, 2)};
    export const demoComponents = {${Array.from(demoModuleIDs)
      .map((moduleID) => {
        return `${JSON.stringify(moduleID)}: ${moduleIDToJSIdentifier(moduleID)},`;
      })
      .join('\n')}};
        export const srcComponents = {${Array.from(componentModuleIDs)
          .map((moduleID) => {
            return `${JSON.stringify(components[moduleID])}: ${moduleIDToJSIdentifier(moduleID)},`;
          })
          .join('\n')}};
  `;

  return transformed;
};
<|endoftext|>


<commit_before>/* global document, window */
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter, HashRouter, Switch, Route } from 'react-router-dom';

import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';

import rootReducer from './reducers';
import App from './components/App';
import Login from './components/Login';
import LoginCallback from './components/Login/LoginCallback';
import StartScreen from './components/StartScreen';
import SignUp from './components/SignUp';
import SignUpAfterOnBoarding from './components/SignUpAfterOnBoarding';
import OnBoard from './components/OnBoard';
import RequestResetPassword from './components/RequestResetPassword';
import ResetPassword from './components/ResetPassword';
import authenticated from './utils/isAuthenticated';
import LandingPage from './components/Temp/LandingPage';
import DeveloperPage from './components/Temp/DeveloperPage';

import './index.css';

const configureStore = () => {
  if (process.env.NODE_ENV === 'production') {
    return createStore(rootReducer, applyMiddleware(thunk));
  }

  return createStore(
    rootReducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), // eslint-disable-line
    applyMiddleware(thunk),
  );
};

const isAuthenticated = () => {
  if (authenticated()) {
    return <App />;
  }
  return undefined;
};

const Router = process.env.REACT_APP_ROUTER === 'HASH'
  ? HashRouter
  : BrowserRouter;

const Root = () => (
  <Provider store={configureStore()}>
    <Router>
      <Switch>
        {isAuthenticated()}
        <Route exact path="/" component={LandingPage} />
        <Route exact path="/developer" component={DeveloperPage} />
        <Route exact path="/app" component={StartScreen} />
        <Route exact path="/login" component={Login} />
        <Route exact path="/login/callback/facebook/:token" component={LoginCallback} />
        <Route exact path="/reset-password" component={RequestResetPassword} />
        <Route exact path="/reset-password/:token" component={ResetPassword} />
        <Route exact path="/sign-up" component={SignUp} />
        <Route exact path="/you-made-it" component={SignUpAfterOnBoarding} />
        <Route exact path="/start" component={OnBoard} />
      </Switch>
    </Router>
  </Provider>
);

render(<Root />, document.getElementById('root'));
<commit_msg>404 will be shown even if user is not authenticated<commit_after>/* global document, window */
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter, HashRouter, Switch, Route } from 'react-router-dom';

import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';

import rootReducer from './reducers';
import App from './components/App';
import Login from './components/Login';
import LoginCallback from './components/Login/LoginCallback';
import StartScreen from './components/StartScreen';
import SignUp from './components/SignUp';
import SignUpAfterOnBoarding from './components/SignUpAfterOnBoarding';
import OnBoard from './components/OnBoard';
import RequestResetPassword from './components/RequestResetPassword';
import ResetPassword from './components/ResetPassword';
import authenticated from './utils/isAuthenticated';
import LandingPage from './components/Temp/LandingPage';
import DeveloperPage from './components/Temp/DeveloperPage';
import NotFound from './components/NotFound';

import './index.css';

const configureStore = () => {
  if (process.env.NODE_ENV === 'production') {
    return createStore(rootReducer, applyMiddleware(thunk));
  }

  return createStore(
    rootReducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), // eslint-disable-line
    applyMiddleware(thunk),
  );
};

const isAuthenticated = () => {
  if (authenticated()) {
    return <App />;
  }
  return undefined;
};

const Router = process.env.REACT_APP_ROUTER === 'HASH'
  ? HashRouter
  : BrowserRouter;

const Root = () => (
  <Provider store={configureStore()}>
    <Router>
      <Switch>
        {isAuthenticated()}
        <Route exact path="/" component={LandingPage} />
        <Route exact path="/developer" component={DeveloperPage} />
        <Route exact path="/app" component={StartScreen} />
        <Route exact path="/login" component={Login} />
        <Route exact path="/login/callback/facebook/:token" component={LoginCallback} />
        <Route exact path="/reset-password" component={RequestResetPassword} />
        <Route exact path="/reset-password/:token" component={ResetPassword} />
        <Route exact path="/sign-up" component={SignUp} />
        <Route exact path="/you-made-it" component={SignUpAfterOnBoarding} />
        <Route exact path="/start" component={OnBoard} />
        <Route component={NotFound} />
      </Switch>
    </Router>
  </Provider>
);

render(<Root />, document.getElementById('root'));
<|endoftext|>