<commit_before>'use strict';
/* global require */

var Interviewee = require('mongoose').model('Interviewee');

exports.getInterviewees = function (req, res, next) {
    var query = Interviewee.find(req.query);

    query.exec(function (err, interviewees) {
        if (err) { return next(err); }
        if (!interviewees) { return next(new Error('No interviewees found')); }
        res.send(interviewees);
    });
};

exports.getIntervieweeByID = function (req, res, next) {
    var query = Interviewee.findOne({_id: req.params.id});

    query.exec(function (err, interviewee) {
        if (err) { return next(err); }
        if (!interviewee) { return next(new Error('No interviewee found')); }
        res.send(interviewee);
    });
};
//noinspection JSUnusedLocalSymbols
exports.createInterviewee = function (req, res, next) {
    var interviewee_data = req.body;

    interviewee_data.createdBy = req.user._id;

    //noinspection JSUnusedLocalSymbols
    Interviewee.create(interviewee_data, function (err, interviewee) {
        // console.log(err);
        if (err) {
            if (err.toString().indexOf('E11000') > -1) {
                err = new Error('Duplicate email and phone number combination');
            }
            res.status(400);
            return res.send({reason: err.toString()});
        } else {
            res.send(interviewee);
        }
    });
};
exports.updateInterviewee = function (req, res) {
    var interviewee_updates = req.body,
        query = Interviewee.findOne({_id: req.body._id});

    query.exec(function (err, interviewee) {
        if (err) {
            res.status(400);
            return res.send({reason: err.toString()});
        }
        interviewee.firstName = interviewee_updates.firstName;
        interviewee.lastName = interviewee_updates.lastName;
        interviewee.email = interviewee_updates.email;
        interviewee.phone = interviewee_updates.phone;
        interviewee.role = interviewee_updates.role;
        interviewee.title = interviewee_updates.title;
        interviewee.salutation = interviewee_updates.salutation;
        interviewee.organization = interviewee_updates.organization;
        interviewee.assessments = interviewee_updates.assessments;
        interviewee.answers = interviewee_updates.answers;
        interviewee.users = interviewee_updates.users;
        interviewee.questions = interviewee_updates.questions;
        interviewee.modified.push({modifiedBy: req.user._id});

        interviewee.save(function (err) {
            if (err) {
                return res.send({reason: err.toString()});
            }
        });
    });
    res.send();
};

exports.deleteInterviewee = function (req, res) {
    Interviewee.remove({_id: req.params.id}, function (err) {
        res.send(err ? {reason: err.toString()} : {});
    });
};

exports.parseCriterion = function(req, res, next) {
    req.query.answer_ID = {$in: req.params.answers.split(',')};
    next();
};
<commit_msg>clean up the `interviewee` module<commit_after>'use strict';
/* global require */

var Interviewee = require('mongoose').model('Interviewee');
var generalResponse = require('./general-response');

var getIntervieweeSet = function(method, criteria, errorMessage, res, next) {
    Interviewee[method](criteria).exec(function (err, interviewees) {
        if (err) {
            return next(err);
        }

        if (!interviewees) {
            return next(new Error(errorMessage));
        }

        res.send(interviewees);
    });
};

exports.getInterviewees = function (req, res, next) {
    getIntervieweeSet('find', req.query, 'No interviewees found', res, next);
};

exports.getIntervieweeByID = function (req, res, next) {
    getIntervieweeSet('findOne', {_id: req.params.id}, 'No interviewee found', res, next);
};
//noinspection JSUnusedLocalSymbols
exports.createInterviewee = function (req, res, next) {
    var interviewee_data = req.body;

    interviewee_data.createdBy = req.user._id;

    //noinspection JSUnusedLocalSymbols
    Interviewee.create(interviewee_data, function (err, interviewee) {
        if (err) {
            if (err.toString().indexOf('E11000') > -1) {
                err = new Error('Duplicate email and phone number combination');
            }

            return generalResponse.respondError(err, res);
        } else {
            res.send(interviewee);
        }
    });
};
exports.updateInterviewee = function (req, res) {
    var interviewee_updates = req.body,
        query = Interviewee.findOne({_id: req.body._id});

    query.exec(function (err, interviewee) {
        if (err) {
            return generalResponse.respondError(err, res);
        }
        interviewee.firstName = interviewee_updates.firstName;
        interviewee.lastName = interviewee_updates.lastName;
        interviewee.email = interviewee_updates.email;
        interviewee.phone = interviewee_updates.phone;
        interviewee.role = interviewee_updates.role;
        interviewee.title = interviewee_updates.title;
        interviewee.salutation = interviewee_updates.salutation;
        interviewee.organization = interviewee_updates.organization;
        interviewee.assessments = interviewee_updates.assessments;
        interviewee.answers = interviewee_updates.answers;
        interviewee.users = interviewee_updates.users;
        interviewee.questions = interviewee_updates.questions;
        interviewee.modified.push({modifiedBy: req.user._id});

        interviewee.save(function (err) {
            if (err) {
                return res.send({reason: err.toString()});
            }
        });
    });
    res.send();
};

exports.deleteInterviewee = function (req, res) {
    Interviewee.remove({_id: req.params.id}, function (err) {
        res.send(err ? {reason: err.toString()} : {});
    });
};

exports.parseCriterion = function(req, res, next) {
    req.query.answer_ID = {$in: req.params.answers.split(',')};
    next();
};
<|endoftext|>


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

  angular
    .module('improvements')
    .controller('ImprovementsListController', ImprovementsListController);

  ImprovementsListController.$inject = ['$state', 'ImprovementsService'];

  function ImprovementsListController($state, ImprovementsService) {
    var vm = this;

    vm.improvements = ImprovementsService.query();

    vm.sortTerm = 'date'; // Sort by date by default
    vm.sortBtnText = 'Sort by Date'; // The value to display in the sort button
    vm.sortReverse = false; // Sort in ascending order by default
    vm.sortMenuOpen = false; // The sort menu starts off closed by default
    vm.incrementLikes = incrementLikes;
    vm.decrementLikes = decrementLikes;

    // The code for managing the sorting functionality
    vm.sortBy = function(inSortTerm) {

      // Change the value of the search term to the imported value
      switch (inSortTerm) {
        case 'user':
          vm.sortTerm = 'user.displayName';
          vm.sortBtnText = 'Sort by User';
          break;
        default:
          vm.sortTerm = 'date';
          vm.sortBtnText = 'Sort by Date';
          break;
      }

      // Change the sorting order on every click
      vm.sortReverse = !vm.sortReverse;
    };

    vm.toggleSortMenu = function() {
      vm.sortMenuOpen = !vm.sortMenuOpen;
    };

    // Load improvements list
    vm.load = function(){
      $state.reload();
    };

    // Incrementing logic
    function incrementLikes(improvement){
      if(improvement.likes===null){
        improvement.likes=0;
      }
      improvement.likes+=1;
      improvement.$update(successCallback, errorCallback);
    }

    // Decrementing logic
    function decrementLikes(improvement){
      if(improvement.likes!==0){
        improvement.likes-=1;
      }
      else if(improvement.likes===null){
        improvement.likes=0;
      }
      improvement.$update(successCallback, errorCallback);
    }

    function successCallback(res) {
    }

    function errorCallback(res) {
      vm.error = res.data.message;
    }
  }
})();
<commit_msg>Cosmetic adjustments & logic fixes - list-improvements view   - Sort by most popular<commit_after>(function () {
  'use strict';

  angular
    .module('improvements')
    .controller('ImprovementsListController', ImprovementsListController);

  ImprovementsListController.$inject = ['$state', 'ImprovementsService'];

  function ImprovementsListController($state, ImprovementsService) {
    var vm = this;

    vm.improvements = ImprovementsService.query();

    vm.sortTerm = 'like'; // Sort by date by default
    vm.sortBtnText = 'Sort by Popularity'; // The value to display in the sort button
    vm.sortReverse = false; // Sort in ascending order by default
    vm.sortMenuOpen = false; // The sort menu starts off closed by default
    vm.incrementLikes = incrementLikes;
    vm.decrementLikes = decrementLikes;

    // The code for managing the sorting functionality
    vm.sortBy = function(inSortTerm) {

      // Change the value of the search term to the imported value
      switch (inSortTerm) {
        case 'likes':
          vm.sortTerm = 'likes';
          vm.sortBtnText = 'Sort by Popularity';
          break;
        case 'date':
          vm.sortTerm = 'date';
          vm.sortBtnText = 'Sort by Date';
        case 'user':
          vm.sortTerm = 'user.displayName';
          vm.sortBtnText = 'Sort by User';
          break;
        default:
          vm.sortTerm = 'likes';
          vm.sortBtnText = 'Sort by Popularity';
          break;
      }

      // Change the sorting order on every click
      vm.sortReverse = !vm.sortReverse;
    };

    vm.toggleSortMenu = function() {
      vm.sortMenuOpen = !vm.sortMenuOpen;
    };

    // Load improvements list
    vm.load = function(){
      $state.reload();
    };

    // Incrementing logic
    function incrementLikes(improvement){
      if(improvement.likes===null){
        improvement.likes=0;
      }
      improvement.likes+=1;
      improvement.$update(successCallback, errorCallback);
    }

    // Decrementing logic
    function decrementLikes(improvement){
      if(improvement.likes!==0){
        improvement.likes-=1;
      }
      else if(improvement.likes===null){
        improvement.likes=0;
      }
      improvement.$update(successCallback, errorCallback);
    }

    function successCallback(res) {
    }

    function errorCallback(res) {
      vm.error = res.data.message;
    }
  }
})();
<|endoftext|>


<commit_before>'use strict'
const
  fs = require('fs'),
  path = require('path'),
  async = require('async'),
  GitStatistics = require('../classes/gitStatistics.js');

function Updater(pathToReposDir) {
  this.pathToReposDir = pathToReposDir;
  this.repos = this.getAllRepos();
  this.gitStatisticsArray = new Array();
  let self = this;

  this.repos.forEach(function(repoName) {
    self.gitStatisticsArray.push(new GitStatistics(path.join(self.pathToReposDir, repoName)));
  });
};

Updater.prototype.statisticsSections = function(gitStatistics) {
  let self = this;

  return [
    function(callback) {
      gitStatistics.updateRepo(function() {
        callback(null, null);
      });
    },
    function(callback) {
      gitStatistics.get10LatestCommits(function(latestCommits) {
        callback(null, { latestCommits: latestCommits });
      });
    },
    function(callback) {
      gitStatistics.getTop10Committers(function(top10Committers) {
        callback(null, { top10Committers: top10Committers });
      });
    },
    function(callback) {
      gitStatistics.getMostRecentTags(function(mostRecentTags) {
        callback(null, { mostRecentTags: mostRecentTags });
      });
    },
    function(callback) {
      gitStatistics.getMostRecentBranches(function(mostRecentBranches) {
        callback(null, { mostRecentBranches: mostRecentBranches });
      });
    },
    function(callback) {
      self.getStatistics(gitStatistics, function(statistics) {
        callback(null, { statistics: statistics });
      });
    }
  ]
};

Updater.prototype.updateData = function(done) {
  let self = this;

  async.map(self.gitStatisticsArray, function(gitStatistics, repoCallback) {
    async.series(
      self.statisticsSections(gitStatistics),
      function(err, results) {
        let repoData = {};
        repoData[path.basename(gitStatistics.repoPath)] = {};
        self.formatResults(repoData[path.basename(gitStatistics.repoPath)], results);

        repoCallback(null, repoData);
      }
    );
  }, function(err, results) {
    let data = {};
    data.repos = self.repos;
    self.formatResults(data, results);

    self.calculateCombinedStatistics(data, function(combinedStatistics) {
      self.formatResults(data, [combinedStatistics]);
      data.repos.push('all');
      done(data);
    });
  });
};

Updater.prototype.getStatistics = function(gitStatistics, callback) {
  let self = this;

  async.series([
    function(callback) {
      gitStatistics.getTotalNumberOfCommits(function(numberOfCommits) {
        callback(null, { numberOfCommits: numberOfCommits });
      })
    },
    function(callback) {
      gitStatistics.getTotalNumberOfBranches(function(numberOfBranches) {
        callback(null, { numberOfBranches: numberOfBranches });
      })
    },
    function(callback) {
      gitStatistics.getTotalNumberOfTags(function(numberOfTags) {
        callback(null, { numberOfTags: numberOfTags });
      })
    },
    function(callback) {
      gitStatistics.getNumberOfLinesAddedAndRemoved(function(result) {
        callback(null, result);
      })
    }
  ],
  function(err, results) {
    let data = {}
    self.formatResults(data, results);
    callback(data);
  });
};

Updater.prototype.getAllRepos = function() {
  let
    self = this,
    repos = new Array(),
    files = fs.readdirSync(this.pathToReposDir);

  files.forEach(function(file) {
    let repoPath = path.join(self.pathToReposDir, file);
    if(fs.lstatSync(repoPath).isDirectory()) {
      repos.push(file);
    }
  });

  return repos;
};

Updater.prototype.formatResults = function(data, results) {
  for(let i in results) {
    for(let c in results[i]) {
      data[c] = results[i][c];
    }
  }
};

Updater.prototype.calculateCombinedStatistics = function(data, callback) {
  let combinedStatistics = {};

  // latestCommits
  let allCommits = this.getCombinedStatisticsSection(data, 'latestCommits');
  allCommits.sort(function(a,b) { return new Date(a.date) - new Date(b.data) } );
  combinedStatistics.latestCommits = allCommits.slice(0, 10);

  // top10Committers
  let allCommitters = this.getCombinedStatisticsSection(data, 'top10Committers');
  allCommitters.sort(function(a,b) { return parseInt(b.numberOfCommits) - parseInt(a.numberOfCommits) } );
  combinedStatistics.top10Committers = allCommitters.slice(0, 10);

  // mostRecentTags
  let allTags = this.getCombinedStatisticsSection(data, 'mostRecentTags');
  allTags.sort(function(a,b) { return new Date(a.date) - new Date(b.data) } );
  combinedStatistics.mostRecentTags = allTags.slice(0, 5);

  // mostRecentBranches
  let allBranches = this.getCombinedStatisticsSection(data, 'mostRecentBranches');
  allBranches.sort(function(a,b) { return new Date(a.date) - new Date(b.data) } );
  combinedStatistics.mostRecentBranches = allBranches.slice(0, 5);

  // statistics
  let statistics = this.getCombinedQuickStats(data, 'statistics');
  combinedStatistics.statistics = statistics;

  callback({all: combinedStatistics});
};

Updater.prototype.getCombinedStatisticsSection = function(data, section) {
  let items = [];

  for(let i in data) {
    if(data[i] == 'repos') {
      continue;
    }

    for(let c in data[i][section]) {
      let item = JSON.parse(JSON.stringify(data[i][section][c]));
      item.repo = i;
      items.push(item);
    }
  }
  return items;
};

Updater.prototype.getCombinedQuickStats = function(data) {
  let combinesQuickStats = {
    numberOfCommits: 0,
    numberOfBranches: 0,
    numberOfTags: 0,
    linesAdded: 0,
    linesRemoved: 0
  };

  for(let i in data) {
    if(i == 'repos') {
      continue;
    }

    for(let info in combinesQuickStats) {
      combinesQuickStats[info] +=  data[i].statistics[info];
    }
  }

  return combinesQuickStats;

};

module.exports = Updater;<commit_msg>Bugfix<commit_after>'use strict'
const
  fs = require('fs'),
  path = require('path'),
  async = require('async'),
  GitStatistics = require('../classes/gitStatistics.js');

function Updater(pathToReposDir) {
  this.pathToReposDir = pathToReposDir;
  this.repos = this.getAllRepos();
  this.gitStatisticsArray = new Array();
  let self = this;

  this.repos.forEach(function(repoName) {
    self.gitStatisticsArray.push(new GitStatistics(path.join(self.pathToReposDir, repoName)));
  });
};

Updater.prototype.statisticsSections = function(gitStatistics) {
  let self = this;

  return [
    function(callback) {
      gitStatistics.updateRepo(function() {
        callback(null, null);
      });
    },
    function(callback) {
      gitStatistics.get10LatestCommits(function(latestCommits) {
        callback(null, { latestCommits: latestCommits });
      });
    },
    function(callback) {
      gitStatistics.getTop10Committers(function(top10Committers) {
        callback(null, { top10Committers: top10Committers });
      });
    },
    function(callback) {
      gitStatistics.getMostRecentTags(function(mostRecentTags) {
        callback(null, { mostRecentTags: mostRecentTags });
      });
    },
    function(callback) {
      gitStatistics.getMostRecentBranches(function(mostRecentBranches) {
        callback(null, { mostRecentBranches: mostRecentBranches });
      });
    },
    function(callback) {
      self.getStatistics(gitStatistics, function(statistics) {
        callback(null, { statistics: statistics });
      });
    }
  ]
};

Updater.prototype.updateData = function(done) {
  let self = this;

  async.map(self.gitStatisticsArray, function(gitStatistics, repoCallback) {
    async.series(
      self.statisticsSections(gitStatistics),
      function(err, results) {
        let repoData = {};
        repoData[path.basename(gitStatistics.repoPath)] = {};
        self.formatResults(repoData[path.basename(gitStatistics.repoPath)], results);

        repoCallback(null, repoData);
      }
    );
  }, function(err, results) {
    let data = {};
    data.repos = self.repos;
    self.formatResults(data, results);

    self.calculateCombinedStatistics(data, function(combinedStatistics) {
      self.formatResults(data, [combinedStatistics]);
      data.repos.push('all');
      done(data);
    });
  });
};

Updater.prototype.getStatistics = function(gitStatistics, callback) {
  let self = this;

  async.series([
    function(callback) {
      gitStatistics.getTotalNumberOfCommits(function(numberOfCommits) {
        callback(null, { numberOfCommits: numberOfCommits });
      })
    },
    function(callback) {
      gitStatistics.getTotalNumberOfBranches(function(numberOfBranches) {
        callback(null, { numberOfBranches: numberOfBranches });
      })
    },
    function(callback) {
      gitStatistics.getTotalNumberOfTags(function(numberOfTags) {
        callback(null, { numberOfTags: numberOfTags });
      })
    },
    function(callback) {
      gitStatistics.getNumberOfLinesAddedAndRemoved(function(result) {
        callback(null, result);
      })
    }
  ],
  function(err, results) {
    let data = {}
    self.formatResults(data, results);
    callback(data);
  });
};

Updater.prototype.getAllRepos = function() {
  let
    self = this,
    repos = new Array(),
    files = fs.readdirSync(this.pathToReposDir);

  files.forEach(function(file) {
    let repoPath = path.join(self.pathToReposDir, file);
    if(fs.lstatSync(repoPath).isDirectory()) {
      repos.push(file);
    }
  });

  return repos;
};

Updater.prototype.formatResults = function(data, results) {
  for(let i in results) {
    for(let c in results[i]) {
      data[c] = results[i][c];
    }
  }
};

Updater.prototype.calculateCombinedStatistics = function(data, callback) {
  let combinedStatistics = {};

  // latestCommits
  let allCommits = this.getCombinedStatisticsSection(data, 'latestCommits');
  allCommits.sort(function(a,b) { return new Date(a.date) - new Date(b.data) } );
  combinedStatistics.latestCommits = allCommits.slice(0, 10);

  // top10Committers
  let allCommitters = this.getCombinedStatisticsSection(data, 'top10Committers');
  allCommitters.sort(function(a,b) { return parseInt(b.numberOfCommits) - parseInt(a.numberOfCommits) } );
  combinedStatistics.top10Committers = allCommitters.slice(0, 10);

  // mostRecentTags
  let allTags = this.getCombinedStatisticsSection(data, 'mostRecentTags');
  allTags.sort(function(a,b) { return new Date(a.date) - new Date(b.data) } );
  combinedStatistics.mostRecentTags = allTags.slice(0, 5);

  // mostRecentBranches
  let allBranches = this.getCombinedStatisticsSection(data, 'mostRecentBranches');
  allBranches.sort(function(a,b) { return new Date(a.date) - new Date(b.data) } );
  combinedStatistics.mostRecentBranches = allBranches.slice(0, 5);

  // statistics
  let statistics = this.getCombinedQuickStats(data, 'statistics');
  combinedStatistics.statistics = statistics;

  callback({all: combinedStatistics});
};

Updater.prototype.getCombinedStatisticsSection = function(data, section) {
  let items = [];

  for(let i in data) {
    if(i == 'repos') {
      continue;
    }

    for(let c in data[i][section]) {
      let item = JSON.parse(JSON.stringify(data[i][section][c]));
      item.repo = i;
      items.push(item);
    }
  }
  return items;
};

Updater.prototype.getCombinedQuickStats = function(data) {
  let combinesQuickStats = {
    numberOfCommits: 0,
    numberOfBranches: 0,
    numberOfTags: 0,
    linesAdded: 0,
    linesRemoved: 0
  };

  for(let i in data) {
    if(i == 'repos') {
      continue;
    }

    for(let info in combinesQuickStats) {
      combinesQuickStats[info] +=  data[i].statistics[info];
    }
  }

  return combinesQuickStats;

};

module.exports = Updater;<|endoftext|>


<commit_before>'use strict';

angular.module('users').controller('ProfileFollowsController', [
  '$scope',
  'UserApi',
  'Action',
  'ngDialog',
  'toastr',
  function ($scope, UserApi, Action, dialog, toast) {
    $scope.screen = 'profile-follow';
    $scope.polls = [];
    $scope.page = 0;
    $scope.busy = false;
    $scope.stopped = false;

    $scope.get_polls = get_polls;
    function get_polls() {
      if ($scope.busy || $scope.stopped) return;
      $scope.busy = true;
      UserApi.get_follows($scope.profile._id, $scope.page)
        .then(res => {
          if (!res.data.length || res.data.length === 0) {
            $scope.busy = false;
            $scope.stopped = true;
            return;
          }
          var promises = [];
          res.data.forEach(poll => {
            promises.push(process_before_show(poll));
          });
          return Promise.all(promises);
        })
        .then(results => {
          // Gán data vào list hiện tại
          $scope.polls = _.union($scope.polls, results);
          $scope.page += 1;
          $scope.busy = false;
        })
        .catch(err => {
          $scope.busy = false;
          $scope.stopped = true;
          toast.error(err.message, 'Error!');
        });
    }
    function process_before_show(poll) {
      return new Promise((resolve, reject) => {
        poll = Action.process_before_show(poll);
        return resolve(poll);
      });
    }
    $scope.poll_filter = poll => {
      if (poll.isPublic) {
        return true;
      } else {
        return $scope.isCurrentOwner;
      }
    };

    $scope.follow_poll = (poll) => {
      console.log('kajdkajsdkajsdkajsdkajsd');
    };
  }
]);
<commit_msg>Commited from lenh at Mon, Aug 14, 2017 11:11:05 AM<commit_after>'use strict';

angular.module('users').controller('ProfileFollowsController', [
  '$scope',
  'UserApi',
  'Action',
  'ngDialog',
  'toastr',
  function ($scope, UserApi, Action, dialog, toast) {
    $scope.screen = 'profile-follow';
    $scope.polls = [];
    $scope.page = 0;
    $scope.busy = false;
    $scope.stopped = false;

    $scope.get_polls = get_polls;
    function get_polls() {
      if ($scope.busy || $scope.stopped) return;
      $scope.busy = true;
      UserApi.get_follows($scope.profile._id, $scope.page)
        .then(res => {
          if (!res.data.length || res.data.length === 0) {
            $scope.busy = false;
            $scope.stopped = true;
            return;
          }
          var promises = [];
          res.data.forEach(poll => {
            promises.push(process_before_show(poll));
          });
          return Promise.all(promises);
        })
        .then(results => {
          // Gán data vào list hiện tại
          $scope.polls = _.union($scope.polls, results);
          $scope.page += 1;
          $scope.busy = false;
        })
        .catch(err => {
          $scope.busy = false;
          $scope.stopped = true;
          toast.error(err.message, 'Error!');
        });
    }
    function process_before_show(poll) {
      return new Promise((resolve, reject) => {
        poll = Action.process_before_show(poll);
        return resolve(poll);
      });
    }
    $scope.poll_filter = poll => {
      if (poll.isPublic) {
        return true;
      } else {
        return $scope.isCurrentOwner;
      }
    };

    $scope.follow_poll = (poll) => {
      if (!$scope.isLogged) {
        toast.error('You must login to follow poll.', 'Error!');
        return;
      }
      if ($scope.isCurrentOwner) {
        $scope.polls = _.without($scope.polls, poll);
      }
      Action.save_follow(poll.follow)
        .then(res => {
          if (res) {
            poll.follow = res;
            toast.success('You followed ' + poll.title, 'Success!');
          } else {
            poll.follow = { poll: poll._id };
          }
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
  }
]);
<|endoftext|>


<commit_before>// Convert topics and posts
//

'use strict';

var _        = require('lodash');
var async    = require('async');
var mongoose = require('mongoose');
var progress = require('./progressbar');
var POST     = 1; // content type for posts

var html_entities = {
  '&':  '&',
  '"': '"',
  '>':   '>',
  '<':   '<'
};

// Replace html entities like """ with the corresponding characters
//
function html_unescape(text) {
  return text.replace(/&(?:quot|amp|lt|gt|#(\d{1,6}));/g, function (entity, code) {
    return html_entities[entity] || String.fromCharCode(+code);
  });
}

module.exports = function (N, callback) {
  /* eslint-disable max-nested-callbacks */
  var users, sections, conn;

  // Get a { hid: { _id, hb } } mapping for all registered users
  //
  function get_users(callback) {
    N.models.users.User.find()
        .select('hid _id hb')
        .lean(true)
        .exec(function (err, userlist) {

      if (err) {
        callback(err);
        return;
      }

      users = {};

      userlist.forEach(function (user) {
        users[user.hid] = user;
      });

      callback();
    });
  }

  // Get a { hid: { _id } } mapping for all sections
  //
  function get_sections(callback) {
    N.models.forum.Section.find()
        .select('hid _id')
        .lean(true)
        .exec(function (err, sectionlist) {

      if (err) {
        callback(err);
        return;
      }

      sections = {};

      sectionlist.forEach(function (section) {
        sections[section.hid] = section;
      });

      callback(null, sections);
    });
  }

  // Allocate SQL connection from the pool
  //
  function get_connection(callback) {
    N.vbconvert.getConnection(function (err, connection) {
      if (err) {
        callback(err);
        return;
      }

      conn = connection;
      callback();
    });
  }

  // Import a single topic by its id
  //
  function import_topic(threadid, callback) {
    var thread, posts, topic;

    // Fetch this thread from SQL
    //
    function fetch_thread(callback) {
      conn.query('SELECT threadid,forumid,title,views,dateline,visible,open,sticky ' +
          'FROM thread WHERE threadid = ? ORDER BY threadid ASC',
          [ threadid ],
          function (err, thread_data) {

        if (err) {
          callback(err);
          return;
        }

        thread = thread_data[0];

        callback();
      });
    }

    // Create a dummy { _id, hid } object in the mongodb, check if topic
    // can be imported.
    //
    // If topic is already imported or can't be imported, return error
    // with NOOP code that's ignored later on.
    //
    function create_topic_stub(callback) {
      if (!sections[thread.forumid]) {
        var err = new Error('this section is ignored');
        err.code = 'NOOP';
        callback(err);
        return;
      }

      topic = {
        _id:         new mongoose.Types.ObjectId(thread.dateline),
        hid:         thread.threadid,
        section:     sections[thread.forumid]._id,
        title:       html_unescape(thread.title),
        views_count: thread.views,
        version:     0
      };

      N.models.forum.Topic.findOneAndUpdate(
        { hid: thread.threadid },
        { $setOnInsert: topic },
        { 'new': false, upsert: true }
      ).lean(true).exec(function (err, old_topic) {
          if (err) {
            callback(err);
            return;
          }

          if (!old_topic) {
            // successfully created a dummy topic entry
            callback();
            return;
          }

          if (old_topic.cache) {
            // topic had been imported fully last time
            err = new Error('topic already imported');
            err.code = 'NOOP';
            callback(err);
            return;
          }

          // reuse old topic if it exists, but haven't been fully imported
          topic._id = old_topic._id;

          // topic hadn't been imported last time, remove all posts and try again
          N.models.forum.Post.find({ topic: old_topic._id })
                             .remove()
                             .exec(function (err) {
            if (err) {
              callback(err);
              return;
            }

            N.models.vbconvert.PostMapping.find({ topic_id: old_topic._id })
                                          .remove()
                                          .exec(callback);
          });
        }
      );
    }

    // Fetch posts from this thread from SQL
    //
    function fetch_posts(callback) {
      conn.query('SELECT threadid,postid,parentid,pagetext,dateline,ipaddress,userid,visible,' +
          'GROUP_CONCAT(vote) AS votes,GROUP_CONCAT(fromuserid) AS casters ' +
          'FROM post LEFT JOIN votes ON post.postid = votes.targetid AND votes.contenttypeid = ? ' +
          'WHERE threadid = ? GROUP BY postid ORDER BY postid ASC',
          [ POST, thread.threadid ],
          function (err, rows) {

        if (err) {
          callback(err);
          return;
        }

        if (rows.length === 0) {
          // empty topic, e.g. http://forum.rcdesign.ru/f90/thread121809.html
          err = new Error('no posts in this topic');
          err.code = 'NOOP';
          callback(err);
          return;
        }

        posts = rows;

        callback();
      });
    }

    // Bulk-store posts into mongodb
    //
    function import_posts(callback) {
      var posts_by_id = {};
      var post_bulk = N.models.forum.Post.collection.initializeOrderedBulkOp();
      var map_bulk  = N.models.vbconvert.PostMapping.collection.initializeOrderedBulkOp();
      var cache = topic.cache = {
        post_count: 0
      };
      var cache_hb = topic.cache_hb = {
        post_count: 0
      };

      posts.forEach(function (post, i) {
        var id   = new mongoose.Types.ObjectId(post.dateline);
        var ts   = new Date(post.dateline * 1000);
        var user = users[post.userid] || {};
        var hid  = i + 1;

        if (hid === 1) {
          cache_hb.first_post = id;
          cache_hb.first_ts   = ts;
          cache_hb.first_user = user._id;

          cache.first_post = id;
          cache.first_ts   = ts;
          cache.first_user = user._id;
        }

        if (post.visible === 1) {
          cache_hb.post_count++;
        }

        cache_hb.last_post = id;
        cache_hb.last_ts   = ts;
        cache_hb.last_user = user._id;

        if (!user.hb || hid === 1) {
          if (post.visible === 1) {
            cache.post_count++;
          }

          cache.last_post = id;
          cache.last_ts   = ts;
          cache.last_user = user._id;
        }

        var new_post = {
          _id:    id,
          topic:  topic._id,
          hid:    hid,
          ts:     ts,
          html:   post.pagetext,
          ip:     post.ipaddress,
          user:   user._id,
          attach: []
        };

        new_post.votes = 0;
        new_post.votes_hb = 0;

        _.zip((post.casters || '').split(','), (post.votes || '').split(',')).forEach(function (arr) {
          if (arr[0] && arr[1]) {
            if (users[arr[0]]) {
              new_post.votes_hb += Number(arr[1]);

              if (!users[arr[0]].hb) {
                new_post.votes += Number(arr[1]);
              }
            }
          }
        });

        if (user.hb) {
          new_post.st  = N.models.forum.Post.statuses.HB;
          new_post.ste = N.models.forum.Post.statuses.VISIBLE;
        } else {
          new_post.st = N.models.forum.Post.statuses.VISIBLE;
        }

        if (post.visible !== 1) {
          new_post.prev_st = _.omit({
            st:  new_post.st,
            ste: new_post.ste
          }, _.isUndefined);

          new_post.st = N.models.forum.Post.statuses.DELETED;
          delete new_post.ste;
        }

        // process replies if they are in the same topic
        if (post.parentid && posts_by_id[post.parentid]) {
          // ignore replies to the first post because most of them are
          // (that's the default for "reply in thread" button)
          if (posts_by_id[post.parentid].hid !== 1) {
            new_post.to      = posts_by_id[post.parentid]._id;
            new_post.to_user = posts_by_id[post.parentid].user;
            new_post.to_phid = posts_by_id[post.parentid].hid;
          }
        }

        posts_by_id[post.postid] = new_post;

        post_bulk.insert(new_post);
        map_bulk.insert({
          mysql_id: post.postid,
          topic_id: topic._id,
          post_id:  new_post._id,
          post_hid: hid,
          text:     post.pagetext
        });
      });

      post_bulk.execute(function (err) {
        if (err) {
          callback(err);
          return;
        }

        map_bulk.execute(callback);
      });
    }

    // Update created topic
    //
    function update_topic(callback) {
      // each fetched post is assigned a consecutive hid starting with 1,
      // so the last hid will be equal to the number of posts
      topic.last_post_hid = posts.length;

      topic.st = thread.open ?
                 N.models.forum.Topic.statuses.OPEN :
                 N.models.forum.Topic.statuses.CLOSED;

      if (users[posts[0].userid] && users[posts[0].userid].hb) {
        topic.ste = topic.st;
        topic.st  = N.models.forum.Topic.statuses.HB;
      } else if (thread.sticky) {
        topic.ste = topic.st;
        topic.st  = N.models.forum.Topic.statuses.PINNED;
      }

      if (thread.visible !== 1) {
        topic.prev_st = _.omit({
          st:  topic.st,
          ste: topic.ste
        }, _.isUndefined);

        topic.st = N.models.forum.Topic.statuses.DELETED;
        delete topic.ste;
      }

      N.models.forum.Topic.update(
        { hid: thread.threadid },
        topic,
        callback
      );
    }

    async.series([
      fetch_thread,
      create_topic_stub,
      fetch_posts,
      import_posts,
      update_topic
    ], function (err) {
      callback(err && err.code !== 'NOOP' ? err : null);
    });
  }

  // Import topics and posts
  //
  function import_all_topics(callback) {
    conn.query('SELECT threadid FROM thread ORDER BY threadid ASC', function (err, rows) {
      if (err) {
        callback(err);
        return;
      }

      var bar = progress(' topics :current/:total [:bar] :percent', rows.length);

      async.eachLimit(rows, 100, function (row, callback) {
        import_topic(row.threadid, function () {
          bar.tick();
          callback.apply(null, arguments);
        });
      }, function (err) {
        if (err) {
          callback(err);
          return;
        }

        bar.terminate();

        N.models.core.Increment.update(
          { key: 'topic' },
          { $set: { value: rows[rows.length - 1].threadid } },
          { upsert: true },
          callback
        );
      });
    });
  }

  // Link posts that reply to a different topic
  //
  function link_foreign_replies(callback) {
    conn.query('SELECT post.postid,post.parentid ' +
        'FROM post JOIN post AS parent ' +
        'ON (post.parentid = parent.postid AND post.threadid != parent.threadid)',
        function (err, rows) {

      if (err) {
        callback(err);
        return;
      }

      async.eachLimit(rows, 100, function (row, callback) {
        N.models.vbconvert.PostMapping.findOne({ mysql_id: row.postid })
            .lean(true)
            .exec(function (err, post_mapping) {

          if (err) {
            callback(err);
            return;
          }

          N.models.vbconvert.PostMapping.findOne({ mysql_id: row.parentid })
              .lean(true)
              .exec(function (err, parent_post_mapping) {

            if (err) {
              callback(err);
              return;
            }

            N.models.forum.Post.findOne({
              topic: parent_post_mapping.topic_id,
              hid: parent_post_mapping.post_hid
            }).lean(true).exec(function (err, post) {
              if (err) {
                callback(err);
                return;
              }

              N.models.forum.Topic.findById(post.topic)
                  .lean(true)
                  .exec(function (err, topic) {

                if (err) {
                  callback(err);
                  return;
                }

                N.models.forum.Section.findById(topic.section)
                    .lean(true)
                    .exec(function (err, section) {

                  if (err) {
                    callback(err);
                    return;
                  }

                  N.models.forum.Post.update({
                    topic: post_mapping.topic_id,
                    hid: post_mapping.post_hid
                  }, {
                    $set: {
                      to: post._id,
                      to_user: post.user,
                      to_phid: post.hid,
                      to_thid: topic.hid,
                      to_fhid: section.hid
                    }
                  }, callback);
                });
              });
            });
          });
        });
      }, callback);
    });
  }

  async.series([
    get_users,
    get_sections,
    get_connection,
    import_all_topics,
    link_foreign_replies
  ], function (err) {
    if (err) {
      callback(err);
      return;
    }

    if (conn) {
      conn.release();
    }

    N.logger.info('Topic import finished');
    callback();
  });
};
<commit_msg>Always set post.md on import<commit_after>// Convert topics and posts
//

'use strict';

var _        = require('lodash');
var async    = require('async');
var mongoose = require('mongoose');
var progress = require('./progressbar');
var POST     = 1; // content type for posts

var html_entities = {
  '&':  '&',
  '"': '"',
  '>':   '>',
  '<':   '<'
};

// Replace html entities like """ with the corresponding characters
//
function html_unescape(text) {
  return text.replace(/&(?:quot|amp|lt|gt|#(\d{1,6}));/g, function (entity, code) {
    return html_entities[entity] || String.fromCharCode(+code);
  });
}

module.exports = function (N, callback) {
  /* eslint-disable max-nested-callbacks */
  var users, sections, conn;

  // Get a { hid: { _id, hb } } mapping for all registered users
  //
  function get_users(callback) {
    N.models.users.User.find()
        .select('hid _id hb')
        .lean(true)
        .exec(function (err, userlist) {

      if (err) {
        callback(err);
        return;
      }

      users = {};

      userlist.forEach(function (user) {
        users[user.hid] = user;
      });

      callback();
    });
  }

  // Get a { hid: { _id } } mapping for all sections
  //
  function get_sections(callback) {
    N.models.forum.Section.find()
        .select('hid _id')
        .lean(true)
        .exec(function (err, sectionlist) {

      if (err) {
        callback(err);
        return;
      }

      sections = {};

      sectionlist.forEach(function (section) {
        sections[section.hid] = section;
      });

      callback(null, sections);
    });
  }

  // Allocate SQL connection from the pool
  //
  function get_connection(callback) {
    N.vbconvert.getConnection(function (err, connection) {
      if (err) {
        callback(err);
        return;
      }

      conn = connection;
      callback();
    });
  }

  // Import a single topic by its id
  //
  function import_topic(threadid, callback) {
    var thread, posts, topic;

    // Fetch this thread from SQL
    //
    function fetch_thread(callback) {
      conn.query('SELECT threadid,forumid,title,views,dateline,visible,open,sticky ' +
          'FROM thread WHERE threadid = ? ORDER BY threadid ASC',
          [ threadid ],
          function (err, thread_data) {

        if (err) {
          callback(err);
          return;
        }

        thread = thread_data[0];

        callback();
      });
    }

    // Create a dummy { _id, hid } object in the mongodb, check if topic
    // can be imported.
    //
    // If topic is already imported or can't be imported, return error
    // with NOOP code that's ignored later on.
    //
    function create_topic_stub(callback) {
      if (!sections[thread.forumid]) {
        var err = new Error('this section is ignored');
        err.code = 'NOOP';
        callback(err);
        return;
      }

      topic = {
        _id:         new mongoose.Types.ObjectId(thread.dateline),
        hid:         thread.threadid,
        section:     sections[thread.forumid]._id,
        title:       html_unescape(thread.title),
        views_count: thread.views,
        version:     0
      };

      N.models.forum.Topic.findOneAndUpdate(
        { hid: thread.threadid },
        { $setOnInsert: topic },
        { 'new': false, upsert: true }
      ).lean(true).exec(function (err, old_topic) {
          if (err) {
            callback(err);
            return;
          }

          if (!old_topic) {
            // successfully created a dummy topic entry
            callback();
            return;
          }

          if (old_topic.cache) {
            // topic had been imported fully last time
            err = new Error('topic already imported');
            err.code = 'NOOP';
            callback(err);
            return;
          }

          // reuse old topic if it exists, but haven't been fully imported
          topic._id = old_topic._id;

          // topic hadn't been imported last time, remove all posts and try again
          N.models.forum.Post.find({ topic: old_topic._id })
                             .remove()
                             .exec(function (err) {
            if (err) {
              callback(err);
              return;
            }

            N.models.vbconvert.PostMapping.find({ topic_id: old_topic._id })
                                          .remove()
                                          .exec(callback);
          });
        }
      );
    }

    // Fetch posts from this thread from SQL
    //
    function fetch_posts(callback) {
      conn.query('SELECT threadid,postid,parentid,pagetext,dateline,ipaddress,userid,visible,' +
          'GROUP_CONCAT(vote) AS votes,GROUP_CONCAT(fromuserid) AS casters ' +
          'FROM post LEFT JOIN votes ON post.postid = votes.targetid AND votes.contenttypeid = ? ' +
          'WHERE threadid = ? GROUP BY postid ORDER BY postid ASC',
          [ POST, thread.threadid ],
          function (err, rows) {

        if (err) {
          callback(err);
          return;
        }

        if (rows.length === 0) {
          // empty topic, e.g. http://forum.rcdesign.ru/f90/thread121809.html
          err = new Error('no posts in this topic');
          err.code = 'NOOP';
          callback(err);
          return;
        }

        posts = rows;

        callback();
      });
    }

    // Bulk-store posts into mongodb
    //
    function import_posts(callback) {
      var posts_by_id = {};
      var post_bulk = N.models.forum.Post.collection.initializeOrderedBulkOp();
      var map_bulk  = N.models.vbconvert.PostMapping.collection.initializeOrderedBulkOp();
      var cache = topic.cache = {
        post_count: 0
      };
      var cache_hb = topic.cache_hb = {
        post_count: 0
      };

      posts.forEach(function (post, i) {
        var id   = new mongoose.Types.ObjectId(post.dateline);
        var ts   = new Date(post.dateline * 1000);
        var user = users[post.userid] || {};
        var hid  = i + 1;

        if (hid === 1) {
          cache_hb.first_post = id;
          cache_hb.first_ts   = ts;
          cache_hb.first_user = user._id;

          cache.first_post = id;
          cache.first_ts   = ts;
          cache.first_user = user._id;
        }

        if (post.visible === 1) {
          cache_hb.post_count++;
        }

        cache_hb.last_post = id;
        cache_hb.last_ts   = ts;
        cache_hb.last_user = user._id;

        if (!user.hb || hid === 1) {
          if (post.visible === 1) {
            cache.post_count++;
          }

          cache.last_post = id;
          cache.last_ts   = ts;
          cache.last_user = user._id;
        }

        var new_post = {
          _id:    id,
          topic:  topic._id,
          hid:    hid,
          ts:     ts,
          md:     post.pagetext,
          html:   post.pagetext,
          ip:     post.ipaddress,
          user:   user._id,
          attach: []
        };

        new_post.votes = 0;
        new_post.votes_hb = 0;

        _.zip((post.casters || '').split(','), (post.votes || '').split(',')).forEach(function (arr) {
          if (arr[0] && arr[1]) {
            if (users[arr[0]]) {
              new_post.votes_hb += Number(arr[1]);

              if (!users[arr[0]].hb) {
                new_post.votes += Number(arr[1]);
              }
            }
          }
        });

        if (user.hb) {
          new_post.st  = N.models.forum.Post.statuses.HB;
          new_post.ste = N.models.forum.Post.statuses.VISIBLE;
        } else {
          new_post.st = N.models.forum.Post.statuses.VISIBLE;
        }

        if (post.visible !== 1) {
          new_post.prev_st = _.omit({
            st:  new_post.st,
            ste: new_post.ste
          }, _.isUndefined);

          new_post.st = N.models.forum.Post.statuses.DELETED;
          delete new_post.ste;
        }

        // process replies if they are in the same topic
        if (post.parentid && posts_by_id[post.parentid]) {
          // ignore replies to the first post because most of them are
          // (that's the default for "reply in thread" button)
          if (posts_by_id[post.parentid].hid !== 1) {
            new_post.to      = posts_by_id[post.parentid]._id;
            new_post.to_user = posts_by_id[post.parentid].user;
            new_post.to_phid = posts_by_id[post.parentid].hid;
          }
        }

        posts_by_id[post.postid] = new_post;

        post_bulk.insert(new_post);
        map_bulk.insert({
          mysql_id: post.postid,
          topic_id: topic._id,
          post_id:  new_post._id,
          post_hid: hid,
          text:     post.pagetext
        });
      });

      post_bulk.execute(function (err) {
        if (err) {
          callback(err);
          return;
        }

        map_bulk.execute(callback);
      });
    }

    // Update created topic
    //
    function update_topic(callback) {
      // each fetched post is assigned a consecutive hid starting with 1,
      // so the last hid will be equal to the number of posts
      topic.last_post_hid = posts.length;

      topic.st = thread.open ?
                 N.models.forum.Topic.statuses.OPEN :
                 N.models.forum.Topic.statuses.CLOSED;

      if (users[posts[0].userid] && users[posts[0].userid].hb) {
        topic.ste = topic.st;
        topic.st  = N.models.forum.Topic.statuses.HB;
      } else if (thread.sticky) {
        topic.ste = topic.st;
        topic.st  = N.models.forum.Topic.statuses.PINNED;
      }

      if (thread.visible !== 1) {
        topic.prev_st = _.omit({
          st:  topic.st,
          ste: topic.ste
        }, _.isUndefined);

        topic.st = N.models.forum.Topic.statuses.DELETED;
        delete topic.ste;
      }

      N.models.forum.Topic.update(
        { hid: thread.threadid },
        topic,
        callback
      );
    }

    async.series([
      fetch_thread,
      create_topic_stub,
      fetch_posts,
      import_posts,
      update_topic
    ], function (err) {
      callback(err && err.code !== 'NOOP' ? err : null);
    });
  }

  // Import topics and posts
  //
  function import_all_topics(callback) {
    conn.query('SELECT threadid FROM thread ORDER BY threadid ASC', function (err, rows) {
      if (err) {
        callback(err);
        return;
      }

      var bar = progress(' topics :current/:total [:bar] :percent', rows.length);

      async.eachLimit(rows, 100, function (row, callback) {
        import_topic(row.threadid, function () {
          bar.tick();
          callback.apply(null, arguments);
        });
      }, function (err) {
        if (err) {
          callback(err);
          return;
        }

        bar.terminate();

        N.models.core.Increment.update(
          { key: 'topic' },
          { $set: { value: rows[rows.length - 1].threadid } },
          { upsert: true },
          callback
        );
      });
    });
  }

  // Link posts that reply to a different topic
  //
  function link_foreign_replies(callback) {
    conn.query('SELECT post.postid,post.parentid ' +
        'FROM post JOIN post AS parent ' +
        'ON (post.parentid = parent.postid AND post.threadid != parent.threadid)',
        function (err, rows) {

      if (err) {
        callback(err);
        return;
      }

      async.eachLimit(rows, 100, function (row, callback) {
        N.models.vbconvert.PostMapping.findOne({ mysql_id: row.postid })
            .lean(true)
            .exec(function (err, post_mapping) {

          if (err) {
            callback(err);
            return;
          }

          N.models.vbconvert.PostMapping.findOne({ mysql_id: row.parentid })
              .lean(true)
              .exec(function (err, parent_post_mapping) {

            if (err) {
              callback(err);
              return;
            }

            N.models.forum.Post.findOne({
              topic: parent_post_mapping.topic_id,
              hid: parent_post_mapping.post_hid
            }).lean(true).exec(function (err, post) {
              if (err) {
                callback(err);
                return;
              }

              N.models.forum.Topic.findById(post.topic)
                  .lean(true)
                  .exec(function (err, topic) {

                if (err) {
                  callback(err);
                  return;
                }

                N.models.forum.Section.findById(topic.section)
                    .lean(true)
                    .exec(function (err, section) {

                  if (err) {
                    callback(err);
                    return;
                  }

                  N.models.forum.Post.update({
                    topic: post_mapping.topic_id,
                    hid: post_mapping.post_hid
                  }, {
                    $set: {
                      to: post._id,
                      to_user: post.user,
                      to_phid: post.hid,
                      to_thid: topic.hid,
                      to_fhid: section.hid
                    }
                  }, callback);
                });
              });
            });
          });
        });
      }, callback);
    });
  }

  async.series([
    get_users,
    get_sections,
    get_connection,
    import_all_topics,
    link_foreign_replies
  ], function (err) {
    if (err) {
      callback(err);
      return;
    }

    if (conn) {
      conn.release();
    }

    N.logger.info('Topic import finished');
    callback();
  });
};
<|endoftext|>


<commit_before>$(window).bind( 'hashchange', _updateFocusFromIri);

function _updateFocusFromIri(event) {
    var iri = event.getState( 'iri' );
    $( '#focusPanel' ).empty();
    sparql_predefined(
        "/sparql-queries/focus.sparql.txt",
        {'focus' : iri},
        _docReady_updateFocusFromJson);
}

function _rdfs_label(parsed) {
  return parsed['http://www.w3.org/2000/01/rdf-schema#label'][0]
}

function _first_or_undefined(parsed, iri) {
  var sent = parsed[iri];
  if (sent) {
    return sent[0];
  } else {
    return undefined;
  }
}

function _sepake_htmlDescription(parsed) {
  return _first_or_undefined(
    parsed,
    'http://dot.rural/sepake/htmlDescription');
}

function _prov_startedAtTime(parsed) {
  return _first_or_undefined(
    parsed,
    'http://www.w3.org/ns/prov#startedAtTime');
}

function _prov_endedAtTime(parsed) {
  return _first_or_undefined(
    parsed,
    'http://www.w3.org/ns/prov#endedAtTime');
}

function _foaf_homepage(parsed) {
  return parsed['http://xmlns.com/foaf/0.1/homepage'] || [];
}

function _updateFocusFromJson(response) {
    try {
        var parsed = sparqlListToObject(response, "p", "y");
        $( '#focusPanel' ).append('

');
        $( '#focusPanel .focusLabel' ).html(_rdfs_label(parsed));
        $( '#focusPanel' ).append('

');
        $( '#focusPanel .focusDescription' ).html(_sepake_htmlDescription(parsed) || "(No summary)");
        if (!_sepake_htmlDescription(parsed) && _focus_is_org()) {
          _set_html_from_dbpedia_description( '#focusPanel .focusDescription', _rdfs_label(parsed) );
        }
        var startedAtTime = _prov_startedAtTime(parsed);
        if (startedAtTime) {
          $( '#focusPanel' ).append('

');
          $( '#focusPanel .focusStart' ).append('Started      ');
          $( '#focusPanel .focusStart' ).append(startedAtTime);
        };
        var endedAtTime = _prov_endedAtTime(parsed);
        if (endedAtTime) {
          $( '#focusPanel' ).append('

');
          $( '#focusPanel .focusEnd' ).append('Ended      ');
          $( '#focusPanel .focusEnd' ).append(endedAtTime);
        };
        $.each(_foaf_homepage(parsed), function(index, homepage){
          $( '#focusPanel' ).append('

');
          $( '#focusPanel .focusHomepage:last' ).append('Homepage      ');
          $( '#focusPanel .focusHomepage:last' ).append('');
          $( '#focusPanel .focusHomepage:last a' ).text(homepage);
          $( '#focusPanel .focusHomepage:last a' ).attr("href", homepage);
        });
    } catch (err) {
      console.log( err );
    }
}

function _docReady_updateFocusFromJson(response) {
  $( document ).ready( function() {
    _updateFocusFromJson(response)
  });
}

function _focus_is_org() {
  var iri = jQuery.bbq.getState('iri');
  if (iri) {
    var iriType = iri.match(/\/([^/]+)#/)[1];
    return (iriType == 'UKEOFOrganisation');
  } else {
    return false;
  };
}

function _set_html_from_dbpedia_description(selector, search_for) {
  $.ajax({
    url: "http://lookup.dbpedia.org/api/search/KeywordSearch",
    data: {
      "QueryString" : search_for,
      "MaxHits" : 1,},
    dataType: 'json',
    success: function( response ) {
      if ( response.results[0] ) {
        $( selector ).html(response.results[0].description + " [Source: Wikipedia]");
      };
    },
    timeout: 2500,
  });
}

<commit_msg>Display DC.issued For #27-nerc<commit_after>$(window).bind( 'hashchange', _updateFocusFromIri);

function _updateFocusFromIri(event) {
    var iri = event.getState( 'iri' );
    $( '#focusPanel' ).empty();
    sparql_predefined(
        "/sparql-queries/focus.sparql.txt",
        {'focus' : iri},
        _docReady_updateFocusFromJson);
}

function _rdfs_label(parsed) {
  return parsed['http://www.w3.org/2000/01/rdf-schema#label'][0]
}

function _first_or_undefined(parsed, iri) {
  var sent = parsed[iri];
  if (sent) {
    return sent[0];
  } else {
    return undefined;
  }
}

function _sepake_htmlDescription(parsed) {
  return _first_or_undefined(
    parsed,
    'http://dot.rural/sepake/htmlDescription');
}

function _prov_startedAtTime(parsed) {
  return _first_or_undefined(
    parsed,
    'http://www.w3.org/ns/prov#startedAtTime');
}

function _prov_endedAtTime(parsed) {
  return _first_or_undefined(
    parsed,
    'http://www.w3.org/ns/prov#endedAtTime');
}

function _foaf_homepage(parsed) {
  return parsed['http://xmlns.com/foaf/0.1/homepage'] || [];
}

function _dc_issued(parsed) {
  return _first_or_undefined(
    parsed,
    'http://purl.org/dc/elements/1.1/issued');
}

function _updateFocusFromJson(response) {
    try {
        var parsed = sparqlListToObject(response, "p", "y");
        $( '#focusPanel' ).append('

');
        $( '#focusPanel .focusLabel' ).html(_rdfs_label(parsed));
        $( '#focusPanel' ).append('

');
        $( '#focusPanel .focusDescription' ).html(_sepake_htmlDescription(parsed) || "(No summary)");
        if (!_sepake_htmlDescription(parsed) && _focus_is_org()) {
          _set_html_from_dbpedia_description( '#focusPanel .focusDescription', _rdfs_label(parsed) );
        }
        if (_prov_startedAtTime(parsed)) {
          $( '#focusPanel' ).append('

');
          $( '#focusPanel .focusStart' ).append('Started      ');
          $( '#focusPanel .focusStart' ).append(_prov_startedAtTime(parsed));
        };
        if (_prov_endedAtTime(parsed)) {
          $( '#focusPanel' ).append('

');
          $( '#focusPanel .focusEnd' ).append('Ended      ');
          $( '#focusPanel .focusEnd' ).append(_prov_endedAtTime(parsed));
        };
        if (_dc_issued(parsed)) {
          $( '#focusPanel' ).append('

');
          $( '#focusPanel .focusIssued' ).append('Published      ');
          $( '#focusPanel .focusIssued' ).append(new Date(Date.parse(_dc_issued(parsed))).toDateString());
        };
        $.each(_foaf_homepage(parsed), function(index, homepage){
          $( '#focusPanel' ).append('

');
          $( '#focusPanel .focusHomepage:last' ).append('Homepage      ');
          $( '#focusPanel .focusHomepage:last' ).append('');
          $( '#focusPanel .focusHomepage:last a' ).text(homepage);
          $( '#focusPanel .focusHomepage:last a' ).attr("href", homepage);
        });
    } catch (err) {
      console.log( err );
    }
}

function _docReady_updateFocusFromJson(response) {
  $( document ).ready( function() {
    _updateFocusFromJson(response)
  });
}

function _focus_is_org() {
  var iri = jQuery.bbq.getState('iri');
  if (iri) {
    var iriType = iri.match(/\/([^/]+)#/)[1];
    return (iriType == 'UKEOFOrganisation');
  } else {
    return false;
  };
}

function _set_html_from_dbpedia_description(selector, search_for) {
  $.ajax({
    url: "http://lookup.dbpedia.org/api/search/KeywordSearch",
    data: {
      "QueryString" : search_for,
      "MaxHits" : 1,},
    dataType: 'json',
    success: function( response ) {
      if ( response.results[0] ) {
        $( selector ).html(response.results[0].description + " [Source: Wikipedia]");
      };
    },
    timeout: 2500,
  });
}

<|endoftext|>


<commit_before>/**
 * @overview
 * The base class for platform specific build commands. This ensures some
 * commonality between build commands so that hooks can consistently
 * access build properties.
 *
 * @copyright
 * Copyright (c) 2014 by Appcelerator, Inc. All Rights Reserved.
 *
 * @license
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */

var appc = require('node-appc'),
	async = require('async'),
	ejs = require('ejs'),
	fs = require('fs'),
	path = require('path'),
	ti = require('titanium-sdk'),
	wrench = require('wrench'),
	__ = appc.i18n(__dirname).__;

/**
 * The base class for project creators (i.e. apps, modules).
 *
 * General usage is to extend the Creator class and override the run(), methods.
 *
 * @module lib/creator
 */

module.exports = Creator;

/**
 * Constructs the creator state. This needs to be explicitly called from the
 * derived creator's constructor.
 * @class
 * @classdesc Base class for all project creators.
 * @constructor
 * @param {Object} logger - The logger instance
 * @param {Object} config - The CLI config
 * @param {Object} cli - The CLI instance
 */
function Creator(logger, config, cli) {
	this.logger = logger;
	this.config = config;
	this.cli = cli;

	this.platforms = ti.scrubPlatforms(cli.argv.platforms);
	this.projectType = cli.argv.type;
	this.projectName = cli.argv.name;
	this.id = cli.argv.id;
	this.url = cli.argv.url || '';
	this.sdk = cli.env.getSDK(cli.argv.sdk);
	this.projectDir = appc.fs.resolvePath(cli.argv['workspace-dir'], this.projectName);
	this.projectConfig = null;

	this.template = cli.argv.template;
	// the templateDir is populated by the create command after determining where it actual is
	this.templateDir = null;
}

Creator.availablePlatforms = [];
Creator.validPlatforms = {};

/**
 * Run stub function. Meant to be overwritten.
 * @param {Function} callback - A function to call after the function finishes
 */
Creator.prototype.run = function run(callback) {
	// stub
	callback();
};

/**
 * Recursively copies files and directories to the destintion. When an .ejs file
 * is encountered, the contents is substituted and the .ejs extension is removed.
 * @param {String} srcDir - The directory to copy
 * @param {String} destDir - The directory to copy the files to
 * @param {Function} callback - A function to call after all of the files have been copied
 * @param {Object} variables - An object to resolve filename substitutions and .ejs templates
 */
Creator.prototype.copyDir = function copyDir(srcDir, destDir, callback, variables) {
	if (!fs.existsSync(srcDir)) return callback();

	variables || (variables = {});

	fs.existsSync(destDir) || wrench.mkdirSyncRecursive(destDir);

	var _t = this,
		ejsRegExp = /\.ejs$/,
		nameRegExp = /\{\{(\w+?)\}\}/g,
		ignoreDirs = new RegExp(this.config.get('cli.ignoreDirs')),
		ignoreFiles = new RegExp(this.config.get('cli.ignoreFiles'));

	async.each(fs.readdirSync(srcDir), function (filename, next) {
		var src = path.join(srcDir, filename);
		if (!fs.existsSync(src)) return next();

		var destName = filename.replace(nameRegExp, function (match, name) {
				return variables[name] || variables[name.substring(0, 1).toLowerCase() + name.substring(1)] || match;
			}),
			dest = path.join(destDir, destName);

		if (fs.statSync(src).isDirectory() && !ignoreDirs.test(filename)) {
			_t.copyDir(src, dest, next, variables);

		} else if (!ignoreFiles.test(filename)) {
			if (ejsRegExp.test(filename)) {
				dest = dest.replace(ejsRegExp, '');
				this.logger.debug(__('Copying %s => %s', src.cyan, dest.cyan));
				// strip the .ejs extension and render the template
				fs.writeFile(dest, ejs.render(fs.readFileSync(src).toString(), variables), next);
			} else {
				this.logger.debug(__('Copying %s => %s', src.cyan, dest.cyan));
				fs.writeFile(dest, fs.readFileSync(src), next);
			}

		} else {
			// ignore
			next();
		}

	}.bind(this), callback);
};<commit_msg>[TIMOB-16977] Fixed how we copy module template files to allow many files.<commit_after>/**
 * @overview
 * The base class for platform specific build commands. This ensures some
 * commonality between build commands so that hooks can consistently
 * access build properties.
 *
 * @copyright
 * Copyright (c) 2014 by Appcelerator, Inc. All Rights Reserved.
 *
 * @license
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */

var appc = require('node-appc'),
	async = require('async'),
	ejs = require('ejs'),
	fs = require('fs'),
	path = require('path'),
	ti = require('titanium-sdk'),
	wrench = require('wrench'),
	__ = appc.i18n(__dirname).__;

/**
 * The base class for project creators (i.e. apps, modules).
 *
 * General usage is to extend the Creator class and override the run(), methods.
 *
 * @module lib/creator
 */

module.exports = Creator;

/**
 * Constructs the creator state. This needs to be explicitly called from the
 * derived creator's constructor.
 * @class
 * @classdesc Base class for all project creators.
 * @constructor
 * @param {Object} logger - The logger instance
 * @param {Object} config - The CLI config
 * @param {Object} cli - The CLI instance
 */
function Creator(logger, config, cli) {
	this.logger = logger;
	this.config = config;
	this.cli = cli;

	this.platforms = ti.scrubPlatforms(cli.argv.platforms);
	this.projectType = cli.argv.type;
	this.projectName = cli.argv.name;
	this.id = cli.argv.id;
	this.url = cli.argv.url || '';
	this.sdk = cli.env.getSDK(cli.argv.sdk);
	this.projectDir = appc.fs.resolvePath(cli.argv['workspace-dir'], this.projectName);
	this.projectConfig = null;

	this.template = cli.argv.template;
	// the templateDir is populated by the create command after determining where it actual is
	this.templateDir = null;
}

Creator.availablePlatforms = [];
Creator.validPlatforms = {};

/**
 * Run stub function. Meant to be overwritten.
 * @param {Function} callback - A function to call after the function finishes
 */
Creator.prototype.run = function run(callback) {
	// stub
	callback();
};

/**
 * Recursively copies files and directories to the destintion. When an .ejs file
 * is encountered, the contents is substituted and the .ejs extension is removed.
 * @param {String} srcDir - The directory to copy
 * @param {String} destDir - The directory to copy the files to
 * @param {Function} callback - A function to call after all of the files have been copied
 * @param {Object} variables - An object to resolve filename substitutions and .ejs templates
 */
Creator.prototype.copyDir = function copyDir(srcDir, destDir, callback, variables) {
	if (!fs.existsSync(srcDir)) return callback();

	variables || (variables = {});

	fs.existsSync(destDir) || wrench.mkdirSyncRecursive(destDir);

	var _t = this,
		ejsRegExp = /\.ejs$/,
		nameRegExp = /\{\{(\w+?)\}\}/g,
		ignoreDirs = new RegExp(this.config.get('cli.ignoreDirs')),
		ignoreFiles = new RegExp(this.config.get('cli.ignoreFiles')),
		files = fs.readdirSync(srcDir);

	async.whilst(
		function () {
			return files.length;
		},
		function (next) {
			var filename = files.shift(),
				src = path.join(srcDir, filename);

			if (!fs.existsSync(src)) return next();

			var destName = filename.replace(nameRegExp, function (match, name) {
					return variables[name] || variables[name.substring(0, 1).toLowerCase() + name.substring(1)] || match;
				}),
				dest = path.join(destDir, destName);

			if (fs.statSync(src).isDirectory() && !ignoreDirs.test(filename)) {
				_t.copyDir(src, dest, next, variables);

			} else if (!ignoreFiles.test(filename)) {
				if (ejsRegExp.test(filename)) {
					dest = dest.replace(ejsRegExp, '');
					_t.logger.debug(__('Copying %s => %s', src.cyan, dest.cyan));
					// strip the .ejs extension and render the template
					fs.writeFile(dest, ejs.render(fs.readFileSync(src).toString(), variables), next);
				} else {
					_t.logger.debug(__('Copying %s => %s', src.cyan, dest.cyan));
					fs.writeFile(dest, fs.readFileSync(src), next);
				}

			} else {
				// ignore
				next();
			}
		},
		callback
	);
};<|endoftext|>


<commit_before>var CronJob = require('cron').CronJob;
var cfg = require('./config');
var fs = require('fs');
var dbmanager = require('./dbmanager');

function doEverything() {
    // Crea hijo Java que crawlea info
    dbmanager.erase(cfg.bd.HOT_SPOTS, function(err){
        if (err) {
           console.log("error borrado");
        } else {
           makeJavaChild(function(data) {
              var tmp;
              for (var i=0; i<data.length; i++) {
                 tmp = parseJSON(data[i]);
                 if (tmp.confidence > 30) {
                    dbmanager.insert(cfg.bd.HOT_SPOTS, parseJSON(data[i]));
                 }
              }
              console.log("Introducidos " + data.length + " docs");
           });
        }
    });
}
exports.doEverything = doEverything;

function makeJavaChild(callback) {
    console.log("crawler.makeJavaChild()");
    var spawn = require('child_process').spawn;
    try {
       var java = spawn('java', ['-jar', '../serviceUtils/serviceUtils.jar', cfg.path.crawler], {detached: false, stdio: ['ignore', 'ignore','ignore']});
        java.on('close', function (code) {
           var data = JSON.parse(fs.readFileSync(cfg.path.crawler, "utf8"));
           console.log("makeJavaChild.makeJavaCrawler() the crawler dies");
           callback(data);

        });
    } catch (e) {
        console.log(e);
    }
}

function parseJSON(json) {
    var date = json.acq_date.trim().split("-");
    var newjson = {
          coordinates: {type: "Point", coordinates: [json.longitude, json.latitude]},
          windSpeed: json.windSpeed,
          date: new Date(date[0],date[1],date[2],json.acq_time.trim().substring(0,2),json.acq_time.trim().substring(2,4)),
          confidence: json.confidence,
          temperature: json.temperature,
          humidity: json.humidity,
          vegetation: json.vegetation,
          frp: json.frp,
          noise: 0.0
      };
    return newjson;
}
<commit_msg>fixed bug crawler insert (juan)<commit_after>var CronJob = require('cron').CronJob;
var cfg = require('./config');
var fs = require('fs');
var dbmanager = require('./dbmanager');

function doEverything() {
    // Crea hijo Java que crawlea info
    dbmanager.erase(cfg.bd.HOT_SPOTS, function(err){
        if (err) {
           console.log("error borrado");
        } else {
           makeJavaChild(function(data) {
              var tmp;
              for (var i=0; i<data.length; i++) {
                 tmp = parseJSON(data[i]);
                 if (tmp.confidence > 30) {
                    dbmanager.insert(cfg.bd.HOT_SPOTS, parseJSON(data[i]), function(){});
                 }
              }
              console.log("Introducidos " + data.length + " docs");
           });
        }
    });
}
exports.doEverything = doEverything;

function makeJavaChild(callback) {
    console.log("crawler.makeJavaChild()");
    var spawn = require('child_process').spawn;
    try {
       var java = spawn('java', ['-jar', '../serviceUtils/serviceUtils.jar', cfg.path.crawler], {detached: false, stdio: ['ignore', 'ignore','ignore']});
        java.on('close', function (code) {
           var data = JSON.parse(fs.readFileSync(cfg.path.crawler, "utf8"));
           console.log("makeJavaChild.makeJavaCrawler() the crawler dies");
           callback(data);

        });
    } catch (e) {
        console.log(e);
    }
}

function parseJSON(json) {
    var date = json.acq_date.trim().split("-");
    var newjson = {
          coordinates: {type: "Point", coordinates: [json.longitude, json.latitude]},
          windSpeed: json.windSpeed,
          date: new Date(date[0],date[1],date[2],json.acq_time.trim().substring(0,2),json.acq_time.trim().substring(2,4)),
          confidence: json.confidence,
          temperature: json.temperature,
          humidity: json.humidity,
          vegetation: json.vegetation,
          frp: json.frp,
          noise: 0.0
      };
    return newjson;
}
<|endoftext|>


<commit_before>var Random = require('random-js'),
     config = require('../config.json');

var RollModule = function () {
    this.random = new Random;
};

RollModule.prototype.Message = function(message)
{
    var keyword = 'roll';
    var rollIndex = message.content.indexOf(keyword);
    var sideCount = parseInt(message.content.substring(rollIndex + keyword.length).trim().replace(/\s/g, '+'));

    if(sideCount>0)
    {
        var engine = Random.engines.mt19937().autoSeed();
        try {
            var res = Random.die(sideCount)(engine);
            message.reply(`you rolled a ${res}`);
        } catch(error) {
            message.reply('error: Something went wrong. You probably picked a too high number.');
        };
    }else{
        message.reply(`error. Please provide a number >0, like \`${config.commandPrefix}roll 6\``);
    }

}

module.exports = RollModule;
<commit_msg>added some custom behaviour for various roll results<commit_after>var Random = require('random-js'),
     config = require('../config.json');

var RollModule = function () {
    this.random = new Random;
};

RollModule.prototype.Message = function(message)
{
    var keyword = 'roll';
    var rollIndex = message.content.indexOf(keyword);
    var sideCount = parseInt(message.content.substring(rollIndex + keyword.length).trim().replace(/\s/g, '+'));

    if(sideCount>0)
    {
        var engine = Random.engines.mt19937().autoSeed();
        try {
            var n = Random.die(sideCount)(engine);
            if(message.guild && message.guild.id == '340324466221514763')
            {
                if(n%10 == parseInt(n/10)%10){
                    message.reply(`you rolled a <:checkem:342834590865686530> ${n}. Checkem!`);
                }else{
                        switch(n){
                            case 420:
                                message.reply(`you rolled a <:weed:341315349058289664> <:420:341290982534283264> <:weed:341315349058289664>`);
                                break;
                            case 69:
                                message.reply(`you rolled a <:yaranaika:341315361666367488> 69.`);
                                break;
                            default:
                                message.reply(`you rolled a ${n}.`);
                        }
                }
            }else{
                message.reply(`you rolled a ${n}.`);
            }
        } catch(error) {
            message.reply('error: Something went wrong. You probably picked a too high number.');
        };
    }else{
        message.reply(`error. Please provide a number >0, like \`${config.commandPrefix}roll 6\`.`);
    }

}

module.exports = RollModule;
<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';
import { noop, initial, get, map } from 'lodash';
import {
  string,
  arrayOf,
  shape,
  func,
  element,
  bool,
  objectOf,
  any
} from 'prop-types';
import Button from '@material-ui/core/Button';
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';

import { intersperse } from 'helpers/fp';
import styles from './styles/sectiontree.scss';

const nodeShape = {
  label: string,
  icon: element,
  iconClassName: string
};
nodeShape.children = objectOf(shape(nodeShape));

export const sectionsShape = shape(nodeShape);

class SectionTree extends React.Component {
  static propTypes = {
    sections: sectionsShape.isRequired,
    activePath: arrayOf(string).isRequired,
    onNavigate: func.isRequired,
    selectedItemClasses: shape({
      leftIcon: string
    }),
    classes: shape({
      leftIcon: string
    })
  };

  handleNavigateForward = path => {
    this.props.onNavigate([...this.getNavigationRelativePath(), path]);
  };

  handleNavigateBack = () => {
    this.props.onNavigate(initial(this.getNavigationRelativePath()));
  };

  handleNavigateSibling = path => {
    this.props.onNavigate([...initial(this.getNavigationRelativePath()), path]);
  };

  getNavigationRelativePath = () => {
    const deepestMatchingPath = this.getDeepestMatchedPath();
    const showingPartialPath = deepestMatchingPath !== this.props.activePath;
    return showingPartialPath ? deepestMatchingPath : this.props.activePath;
  };

  getDeepestMatchedPath = () => {
    // find the deepest section we can match in the tree by dropping pieces
    // from the activePath until we find one that works.
    // this can probably be done more cleanly.
    return this.props.activePath.reduce(
      result => {
        const tryPath = intersperse(result, 'children');
        const maybeSection = get(this.props.sections.children, tryPath);

        return maybeSection ? result : initial(result);
      },
      [...this.props.activePath]
    );
  };

  render() {
    const deepestMatchedPath = this.getDeepestMatchedPath();
    const deepestMatchedPathParent = initial(deepestMatchedPath);

    const currentVisibleSection =
      this.props.activePath.length === 0
        ? this.props.sections // root visible by default
        : get(
            this.props.sections.children, // skip root when navigating
            intersperse(deepestMatchedPath, 'children')
          );

    const currentVisibleSectionParent = get(
      this.props.sections.children,
      intersperse(deepestMatchedPathParent, 'children'),
      this.props.sections
    );

    const parentIsRoot = currentVisibleSectionParent === this.props.sections;
    const selectedItemHasChildren = !!currentVisibleSection.children;
    const rootItemSelected = parentIsRoot && !selectedItemHasChildren;

    return (

        {!rootItemSelected &&
          this.props.activePath.length > 0 && (
            <SectionTreeTab
              selectedClasses={this.props.selectedItemClasses}
              classes={this.props.classes}
              selected
              label={currentVisibleSection.label}
              leftIcon={<ArrowBackIcon />}
              onClick={this.handleNavigateBack}
              data-testtarget="back-button"
            />
          )}

        {map(
          // render the parent (w/ current section highlighted + its siblings)
          // when we're at a leaf path
          currentVisibleSection.children
            ? currentVisibleSection.children
            : currentVisibleSectionParent.children,
          ({ label, formComponentId, children, icon, iconClassName }, path) => (
            <SectionTreeTab
              selectedClasses={this.props.selectedItemClasses}
              classes={this.props.classes}
              selected={label === currentVisibleSection.label}
              label={label}
              leftIcon={
                iconClassName ?  : icon
              }
              rightIcon={
                children && Object.keys(children).length && <ChevronRightIcon />
              }
              key={`${label}-${path}`}
              id={path}
              onClick={
                currentVisibleSection.children
                  ? this.handleNavigateForward
                  : this.handleNavigateSibling
              }
            />
          )
        )}

    );
  }
}

export default SectionTree;

export const SectionTreeTab = ({
  label,
  id,
  leftIcon,
  rightIcon,
  selected,
  selectedClasses = {},
  classes = {},
  onClick = noop
}) => (
  /* eslint-disable react/jsx-no-bind */
  <Button
    classes={{
      root: cx(styles.sectionTreeTab, { [styles.selected]: selected }),
      label: styles.muiButtonLabelOverride
    }}
    onClick={() => onClick(id)}
  >

      {leftIcon}

    {label}
    {rightIcon}
  </Button>
);

SectionTreeTab.propTypes = {
  label: string,
  id: string,
  leftIcon: element,
  rightIcon: element,
  selected: bool,
  onClick: func,
  classes: objectOf(any),
  selectedClasses: objectOf(any)
};
<commit_msg>VTN-28853: add data-veritone-element for sidebar<commit_after>import React from 'react';
import cx from 'classnames';
import { noop, initial, get, map, kebabCase } from 'lodash';
import {
  string,
  arrayOf,
  shape,
  func,
  element,
  bool,
  objectOf,
  any
} from 'prop-types';
import Button from '@material-ui/core/Button';
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';

import { intersperse } from 'helpers/fp';
import styles from './styles/sectiontree.scss';

const nodeShape = {
  label: string,
  icon: element,
  iconClassName: string
};
nodeShape.children = objectOf(shape(nodeShape));

export const sectionsShape = shape(nodeShape);

class SectionTree extends React.Component {
  static propTypes = {
    sections: sectionsShape.isRequired,
    activePath: arrayOf(string).isRequired,
    onNavigate: func.isRequired,
    selectedItemClasses: shape({
      leftIcon: string
    }),
    classes: shape({
      leftIcon: string
    })
  };

  handleNavigateForward = path => {
    this.props.onNavigate([...this.getNavigationRelativePath(), path]);
  };

  handleNavigateBack = () => {
    this.props.onNavigate(initial(this.getNavigationRelativePath()));
  };

  handleNavigateSibling = path => {
    this.props.onNavigate([...initial(this.getNavigationRelativePath()), path]);
  };

  getNavigationRelativePath = () => {
    const deepestMatchingPath = this.getDeepestMatchedPath();
    const showingPartialPath = deepestMatchingPath !== this.props.activePath;
    return showingPartialPath ? deepestMatchingPath : this.props.activePath;
  };

  getDeepestMatchedPath = () => {
    // find the deepest section we can match in the tree by dropping pieces
    // from the activePath until we find one that works.
    // this can probably be done more cleanly.
    return this.props.activePath.reduce(
      result => {
        const tryPath = intersperse(result, 'children');
        const maybeSection = get(this.props.sections.children, tryPath);

        return maybeSection ? result : initial(result);
      },
      [...this.props.activePath]
    );
  };

  render() {
    const deepestMatchedPath = this.getDeepestMatchedPath();
    const deepestMatchedPathParent = initial(deepestMatchedPath);

    const currentVisibleSection =
      this.props.activePath.length === 0
        ? this.props.sections // root visible by default
        : get(
            this.props.sections.children, // skip root when navigating
            intersperse(deepestMatchedPath, 'children')
          );

    const currentVisibleSectionParent = get(
      this.props.sections.children,
      intersperse(deepestMatchedPathParent, 'children'),
      this.props.sections
    );

    const parentIsRoot = currentVisibleSectionParent === this.props.sections;
    const selectedItemHasChildren = !!currentVisibleSection.children;
    const rootItemSelected = parentIsRoot && !selectedItemHasChildren;

    return (

        {!rootItemSelected &&
          this.props.activePath.length > 0 && (
            <SectionTreeTab
              selectedClasses={this.props.selectedItemClasses}
              classes={this.props.classes}
              selected
              label={currentVisibleSection.label}
              leftIcon={<ArrowBackIcon />}
              onClick={this.handleNavigateBack}
              data-testtarget="back-button"
              btnActionTrackName={currentVisibleSection.btnActionTrackName}
            />
          )}

        {map(
          // render the parent (w/ current section highlighted + its siblings)
          // when we're at a leaf path
          currentVisibleSection.children
            ? currentVisibleSection.children
            : currentVisibleSectionParent.children,
          ({ label, formComponentId, children, icon, iconClassName, btnActionTrackName }, path) => (
            <SectionTreeTab
              selectedClasses={this.props.selectedItemClasses}
              classes={this.props.classes}
              selected={label === currentVisibleSection.label}
              label={label}
              leftIcon={
                iconClassName ?  : icon
              }
              rightIcon={
                children && Object.keys(children).length && <ChevronRightIcon />
              }
              key={`${label}-${path}`}
              id={path}
              onClick={
                currentVisibleSection.children
                  ? this.handleNavigateForward
                  : this.handleNavigateSibling
              }
              btnActionTrackName={btnActionTrackName}
            />
          )
        )}

    );
  }
}

export default SectionTree;

export const SectionTreeTab = ({
  label = '',
  id,
  leftIcon,
  rightIcon,
  selected,
  selectedClasses = {},
  classes = {},
  onClick = noop,
  btnActionTrackName
}) => (
  /* eslint-disable react/jsx-no-bind */
  <Button
    classes={{
      root: cx(styles.sectionTreeTab, { [styles.selected]: selected }),
      label: styles.muiButtonLabelOverride
    }}
    onClick={() => onClick(id)}
    data-veritone-element={btnActionTrackName || `sidebar-${kebabCase(label.toLowerCase())}-button`}
  >

      {leftIcon}

    {label}
    {rightIcon}
  </Button>
);

SectionTreeTab.propTypes = {
  label: string,
  id: string,
  leftIcon: element,
  rightIcon: element,
  selected: bool,
  onClick: func,
  classes: objectOf(any),
  selectedClasses: objectOf(any),
  btnActionTrackName: string
};
<|endoftext|>