<commit_before>var Comment = require('../models/comments');
var Idea = require('../models/ideas');
var User = require('../models/users');
var Vote = require('../models/votes');
var IFuncs = require('./idea-functions');
var VoteFuncs = require('./vote-functions');
//var slackPost = require('./slackPost');
//var request = require('request');

// helper functions for querying data by userId and parentId with async callbacks
function findUser (un, callback){
  User.findOne({ sUserName: un }, function (err, user) {
    if (err) {
      callback(err, null);
    } else {
      callback(null, user);
    }
  });
}
function getIdeaId (pi, callback) {
  Idea.find({ shortId: pi }, function(err, idea){
    if(err) {
      callback(err, null);
    } else {
      callback(null, idea);
    }
  });
}
function getCommId (pi, callback) {
  Comment.find({ commShortId: pi }, function(err, comment){
    if(err) {
      callback(err, null);
    } else {
      callback(null, comment);
    }
  });
}// end helper db functions

function slackInt (req, res){

  // Parsing incoming request data
  // For ideas    : req.body.text = [ title | text | tags ];
  // For comments : req.body.text = [ shortId | text ];
  // For votes    : req.body.text = [ shortId ];

  var parsed = req.body.text.split("|").map(function(y){ return y.trim(); });

  // Set slackId to the user_id
  req.body.slackId = req.body.user_id;

  // Parsing data and directing idea / comment / vote to db insert functions
  switch(req.body.command){
    case '/idea':
      // TODO: create hyperlink for unique id
      req.body.shortId = String(parsed[0].split(" ").slice(0,3).join("_")+"_"+req.body.user_name).toLowerCase();
      req.body.title = parsed[0];
      req.body.body = parsed[1];
      if (parsed.length === 3) {
        req.body.tags = parsed[2].split(' ');
      }
      findUser(req.body.user_name, function(err, uId) {
        if (err) console.log(err);
        req.body.userId = uId._id;
        getIdeaId(req.body.shortId, function(err, pId) {
          // if shortId already exists, send user req information back and have them choose a different title
          console.log('pId: ', pId);
          if (pId.length === 0) {
            IFuncs.createIdea(req, res);
          } else {
            var reply = 'Please select a different title for your idea request. This one has already been used: ' + '\n\n shortId: '+ req.body.shortId + '\n title: ' + req.body.title + '\n body: ' + req.body.body + '\n tags: ' + req.body.tags;
            res.end(reply);
          }
        });
      });
      break;
    case '/comment':
      // TODO: create hyperlink for comment id
      // TODO: *shortId* for comments will be different than shortIds for ideas
      // TODO: need logic for commenting on a comment

      req.body.shortId    = parsed[0].toLowerCase();
      req.body.body       = parsed[1];
      req.body.sUserName  = req.body.user_name;

      var ideaOrComm      = req.body.shortId.split("_");
      ideaOrComm          = ideaOrComm[ideaOrComm.length-1].slice(0,4);

      findUser(req.body.sUserName, function(err, uId){
        req.body.img      = uId.image['24'];
        req.body.slackReq = true;

        if (ideaOrComm === "comm") {
          req.body.parentType = "comment";

          // search in the db for the shortId, if it does not exist, send error msg back to user
          getCommId (req.body.shortId, function(err, pId) {
            if (pId[0] === undefined) {
              console.log('ShortId is not found.');
              reply = 'Comment not found.';
              res.end(reply);
            } else {
              // creating a unique comment id based on the length of the comments array
              var count = pId[0].comments.length+1;
              req.body.commShortId = req.body.shortId + count;
              req.body.parentId = pId[0]._id;
              IFuncs.createComment(req, res);
            }
          });
        } else {
          req.body.parentType = 'idea';

          // search in the db for the shortId, if it does not exist, send error msg back to user
          getIdeaId (req.body.shortId, function(err, pId) {
            if (pId[0] === undefined) {
              console.log('ShortId is not found.');
              reply = 'Idea not found. See a list of active ideas with /allideas';
              res.end(reply);
            } else {
              // creating a unique comment id based on the ideaId and the length of the comments array
              var count = pId[0].comments.length+1;
              req.body.commShortId = String(parsed[0].split("_").slice(0,-1).join("_") + '_comm' + count).toLowerCase();

              //debugging
              console.log('req.body.commShortId: ', req.body.commShortId);

              req.body.parentId = pId[0]._id;
              IFuncs.createComment(req, res);
            }
          });
        }
      });
      break;
    case '/upvote':

      req.body.shortId = parsed[0].toLowerCase();

      // determine whether the vote is for a comment or an idea via the shortId
      var ideaOrCom   = req.body.shortId.split("_");
      if (ideaOrCom[ideaOrCom.length-1].slice(0,4) === "comm") {
        req.body.voteType = "comment";
      } else {
        req.body.voteType = "idea";
      }

      // if comment is on an idea, search for the correct parentId, etc. in the Idea collection
      // otherwise search in the Comment collection for the correct parentId, etc.
      if (req.body.voteType === "idea") {
        getIdeaId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId    : uId._id,
                parentId   : req.body.parentId,
                parentTitle: req.body.parentTitle,
                shortId    : req.body.shortId,
                user_name  : req.body.user_name,
                voteType   : req.body.voteType,
                voteRating : 1,
                userImage  : uId.image['24'],
                slackReq   : true,
                slackCommand  : '/upvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      } else if (req.body.voteType === "comment") {
        getCommId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId       : uId._id,
                parentId      : req.body.parentId,
                parentTitle   : req.body.parentTitle,
                shortId       : req.body.shortId,
                user_name     : req.body.user_name,
                voteType      : req.body.voteType,
                voteRating    : 1,
                userImage     : uId.image['24'],
                slackReq      : true,
                slackCommand  : '/upvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      }
      res.end();
      break;
    case '/downvote':

      req.body.shortId = parsed[0].toLowerCase();

      // determine whether the vote is for a comment or an idea via the shortId
      var ideaOrCo   = req.body.shortId.split("_");
      if (ideaOrCo[ideaOrCo.length-1].slice(0,4) === "comm") {
        req.body.voteType = "comment";
      } else {
        req.body.voteType = "idea";
      }

      // if comment is on an idea, search for the correct parentId, etc. in the Idea collection
      // otherwise search in the Comment collection for the correct parentId, etc.
      if (req.body.voteType === "idea") {
        getIdeaId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId       : uId._id,
                parentId      : req.body.parentId,
                parentTitle   : req.body.parentTitle,
                shortId       : req.body.shortId,
                user_name     : req.body.user_name,
                voteType      : req.body.voteType,
                voteRating    : -1,
                userImage     : uId.image['24'],
                slackReq      : true,
                slackCommand  : '/downvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      } else if (req.body.voteType === "comment") {
        getCommId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId       : uId._id,
                parentId      : req.body.parentId,
                parentTitle   : req.body.parentTitle,
                shortId       : req.body.shortId,
                user_name     : req.body.user_name,
                voteType      : req.body.voteType,
                voteRating    : -1,
                userImage     : uId.image['24'],
                slackReq      : true,
                slackCommand  : '/downvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      }
      break;
    case '/allideas':
      var selectFields = 'createdAt updatedAt shortId userId slackId sUserName title body tags active voters upvotes downvotes rating';

      var rawIdeas = Idea.find()
                      .select(selectFields)
                      .where({ active: true })
                      .sort('-updatedAt')
                      .limit(10);
      rawIdeas.exec().then(function(value){
        console.log('value: ', value);
        var ideas = [];
        for (var i = 0; i < value.length; i++){
          var con = String(new Date(value[i].createdAt));
          var date = con.split(" ").slice(1,-3).join(" ");
          ideas.push('ID: ' + value[i].shortId + ' | TITLE: ' + value[i].title + ' | CREATED: ' + date + '\n');
        }
        res.send(ideas.join("\n"));
        res.end();
      });
      break;
    default:
      res.end();
  }
} // end slackInt

// expose functions
module.exports = { slackInt: slackInt };
<commit_msg>change in status for slash command for allideas<commit_after>var Comment = require('../models/comments');
var Idea = require('../models/ideas');
var User = require('../models/users');
var Vote = require('../models/votes');
var IFuncs = require('./idea-functions');
var VoteFuncs = require('./vote-functions');
var Status = require('./statusConstants');
//var slackPost = require('./slackPost');
//var request = require('request');

// helper functions for querying data by userId and parentId with async callbacks
function findUser (un, callback){
  User.findOne({ sUserName: un }, function (err, user) {
    if (err) {
      callback(err, null);
    } else {
      callback(null, user);
    }
  });
}
function getIdeaId (pi, callback) {
  Idea.find({ shortId: pi }, function(err, idea){
    if(err) {
      callback(err, null);
    } else {
      callback(null, idea);
    }
  });
}
function getCommId (pi, callback) {
  Comment.find({ commShortId: pi }, function(err, comment){
    if(err) {
      callback(err, null);
    } else {
      callback(null, comment);
    }
  });
}// end helper db functions

function slackInt (req, res){

  // Parsing incoming request data
  // For ideas    : req.body.text = [ title | text | tags ];
  // For comments : req.body.text = [ shortId | text ];
  // For votes    : req.body.text = [ shortId ];

  var parsed = req.body.text.split("|").map(function(y){ return y.trim(); });

  // Set slackId to the user_id
  req.body.slackId = req.body.user_id;

  // Parsing data and directing idea / comment / vote to db insert functions
  switch(req.body.command){
    case '/idea':
      // TODO: create hyperlink for unique id
      req.body.shortId = String(parsed[0].split(" ").slice(0,3).join("_")+"_"+req.body.user_name).toLowerCase();
      req.body.title = parsed[0];
      req.body.body = parsed[1];
      if (parsed.length === 3) {
        req.body.tags = parsed[2].split(' ');
      }
      findUser(req.body.user_name, function(err, uId) {
        if (err) console.log(err);
        req.body.userId = uId._id;
        getIdeaId(req.body.shortId, function(err, pId) {
          // if shortId already exists, send user req information back and have them choose a different title
          console.log('pId: ', pId);
          if (pId.length === 0) {
            IFuncs.createIdea(req, res);
          } else {
            var reply = 'Please select a different title for your idea request. This one has already been used: ' + '\n\n shortId: '+ req.body.shortId + '\n title: ' + req.body.title + '\n body: ' + req.body.body + '\n tags: ' + req.body.tags;
            res.end(reply);
          }
        });
      });
      break;
    case '/comment':
      // TODO: create hyperlink for comment id
      // TODO: *shortId* for comments will be different than shortIds for ideas
      // TODO: need logic for commenting on a comment

      req.body.shortId    = parsed[0].toLowerCase();
      req.body.body       = parsed[1];
      req.body.sUserName  = req.body.user_name;

      var ideaOrComm      = req.body.shortId.split("_");
      ideaOrComm          = ideaOrComm[ideaOrComm.length-1].slice(0,4);

      findUser(req.body.sUserName, function(err, uId){
        req.body.img      = uId.image['24'];
        req.body.slackReq = true;

        if (ideaOrComm === "comm") {
          req.body.parentType = "comment";

          // search in the db for the shortId, if it does not exist, send error msg back to user
          getCommId (req.body.shortId, function(err, pId) {
            if (pId[0] === undefined) {
              console.log('ShortId is not found.');
              reply = 'Comment not found.';
              res.end(reply);
            } else {
              // creating a unique comment id based on the length of the comments array
              var count = pId[0].comments.length+1;
              req.body.commShortId = req.body.shortId + count;
              req.body.parentId = pId[0]._id;
              IFuncs.createComment(req, res);
            }
          });
        } else {
          req.body.parentType = 'idea';

          // search in the db for the shortId, if it does not exist, send error msg back to user
          getIdeaId (req.body.shortId, function(err, pId) {
            if (pId[0] === undefined) {
              console.log('ShortId is not found.');
              reply = 'Idea not found. See a list of active ideas with /allideas';
              res.end(reply);
            } else {
              // creating a unique comment id based on the ideaId and the length of the comments array
              var count = pId[0].comments.length+1;
              req.body.commShortId = String(parsed[0].split("_").slice(0,-1).join("_") + '_comm' + count).toLowerCase();

              //debugging
              console.log('req.body.commShortId: ', req.body.commShortId);

              req.body.parentId = pId[0]._id;
              IFuncs.createComment(req, res);
            }
          });
        }
      });
      break;
    case '/upvote':

      req.body.shortId = parsed[0].toLowerCase();

      // determine whether the vote is for a comment or an idea via the shortId
      var ideaOrCom   = req.body.shortId.split("_");
      if (ideaOrCom[ideaOrCom.length-1].slice(0,4) === "comm") {
        req.body.voteType = "comment";
      } else {
        req.body.voteType = "idea";
      }

      // if comment is on an idea, search for the correct parentId, etc. in the Idea collection
      // otherwise search in the Comment collection for the correct parentId, etc.
      if (req.body.voteType === "idea") {
        getIdeaId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId    : uId._id,
                parentId   : req.body.parentId,
                parentTitle: req.body.parentTitle,
                shortId    : req.body.shortId,
                user_name  : req.body.user_name,
                voteType   : req.body.voteType,
                voteRating : 1,
                userImage  : uId.image['24'],
                slackReq   : true,
                slackCommand  : '/upvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      } else if (req.body.voteType === "comment") {
        getCommId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId       : uId._id,
                parentId      : req.body.parentId,
                parentTitle   : req.body.parentTitle,
                shortId       : req.body.shortId,
                user_name     : req.body.user_name,
                voteType      : req.body.voteType,
                voteRating    : 1,
                userImage     : uId.image['24'],
                slackReq      : true,
                slackCommand  : '/upvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      }
      res.end();
      break;
    case '/downvote':

      req.body.shortId = parsed[0].toLowerCase();

      // determine whether the vote is for a comment or an idea via the shortId
      var ideaOrCo   = req.body.shortId.split("_");
      if (ideaOrCo[ideaOrCo.length-1].slice(0,4) === "comm") {
        req.body.voteType = "comment";
      } else {
        req.body.voteType = "idea";
      }

      // if comment is on an idea, search for the correct parentId, etc. in the Idea collection
      // otherwise search in the Comment collection for the correct parentId, etc.
      if (req.body.voteType === "idea") {
        getIdeaId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId       : uId._id,
                parentId      : req.body.parentId,
                parentTitle   : req.body.parentTitle,
                shortId       : req.body.shortId,
                user_name     : req.body.user_name,
                voteType      : req.body.voteType,
                voteRating    : -1,
                userImage     : uId.image['24'],
                slackReq      : true,
                slackCommand  : '/downvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      } else if (req.body.voteType === "comment") {
        getCommId (req.body.shortId, function(err, pId) {
          if (pId[0] === undefined) {
            console.log('ShortId is not found.');
            reply = 'ID not found. See a list of active ideas with /allideas';
            res.end(reply);
          } else {
            req.body.parentId = pId[0]._id;
            req.body.parentTitle = pId[0].title;
            findUser(req.body.user_name, function(err, uId) {

              var voteInfo = {
                voterId       : uId._id,
                parentId      : req.body.parentId,
                parentTitle   : req.body.parentTitle,
                shortId       : req.body.shortId,
                user_name     : req.body.user_name,
                voteType      : req.body.voteType,
                voteRating    : -1,
                userImage     : uId.image['24'],
                slackReq      : true,
                slackCommand  : '/downvote'
              };

              console.log('voteInfo:', voteInfo);
              VoteFuncs.voteOptions(voteInfo);
            });
          }
        });
      }
      break;
    case '/allideas':
      var selectFields = 'createdAt updatedAt shortId userId slackId sUserName title body tags active voters upvotes downvotes rating';

      var rawIdeas = Idea.find()
                      .select(selectFields)
                      .where({ status: Status.OPEN })
                      .sort('-updatedAt')
                      .limit(10);
      rawIdeas.exec().then(function(value){
        console.log('value: ', value);
        var ideas = [];
        for (var i = 0; i < value.length; i++){
          var con = String(new Date(value[i].createdAt));
          var date = con.split(" ").slice(1,-3).join(" ");
          ideas.push('ID: ' + value[i].shortId + ' | TITLE: ' + value[i].title + ' | CREATED: ' + date + '\n');
        }
        res.send(ideas.join("\n"));
        res.end();
      });
      break;
    default:
      res.end();
  }
} // end slackInt

// expose functions
module.exports = { slackInt: slackInt };
<|endoftext|>


<commit_before>/**
 * Middleware
 * @flow
 */

/**
 * Ensure session.userId is set on every request
 * Create the user if they're don't have an id yet
 */
export function setUser () {
  return function * setUserMiddleware (next) {
    const { User } = this.models
    if (!this.session.userId) {
      try {
        const user = yield User.create()
        this.session.userId = user.id
      } catch (err) {
        console.error('setUserMiddleware', err)
        throw err
      }
    }
    yield next
  }
}

/**
 * Middleware to set XSRF-TOKEN cookie on every response
 */
export function setCsrfToken () {
  return function * setCsrfCookieMidleware (next) {
    yield next
    this.cookies.set('XSRF-TOKEN', this.csrf, {
      httpOnly: false
    })
  }
}

/**
 * Middleware to expose errors when not in production mode
 */
export function exposeError (env) {
  const isProduction = env === 'production'
  return function * exposeErrorMiddleware (next) {
    try {
      yield next
    } catch (err) {
      if (!isProduction) {
        err.expose = true
      }
      throw err
    }
  }
}
<commit_msg>Make exposeError middleware do less work<commit_after>/**
 * Middleware
 * @flow
 */

/**
 * Ensure session.userId is set on every request
 * Create the user if they're don't have an id yet
 */
export function setUser () {
  return function * setUserMiddleware (next) {
    const { User } = this.models
    if (!this.session.userId) {
      try {
        const user = yield User.create()
        this.session.userId = user.id
      } catch (err) {
        console.error('setUserMiddleware', err)
        throw err
      }
    }
    yield next
  }
}

/**
 * Middleware to set XSRF-TOKEN cookie on every response
 */
export function setCsrfToken () {
  return function * setCsrfCookieMidleware (next) {
    yield next
    this.cookies.set('XSRF-TOKEN', this.csrf, {
      httpOnly: false
    })
  }
}

/**
 * Middleware to expose errors when not in production mode
 * @TODO: log errors somewhere when in production
 */
export function exposeError (env) {
  return env === 'production'
    ? noopMiddleware
    : exposeErrorMiddleware

  function * exposeErrorMiddleware (next) {
    try {
      yield next
    } catch (err) {
      err.expose = true
      throw err
    }
  }

  function * noopMiddleware (next) {
    return yield next
  }
}
<|endoftext|>


<commit_before>(() => {
  let count = 1;

  if (!window.$docsify) {
    throw new Error('Docsify must be loaded before installing this plugin.');
  }

  function runScript(script) {
    const newScript = document.createElement('script');

    if (script.type === 'module') {
      newScript.type = 'module';
      newScript.textContent = script.innerHTML;
    } else {
      newScript.appendChild(document.createTextNode(`(() => { ${script.innerHTML} })();`));
    }

    script.parentNode.replaceChild(newScript, script);
  }

  function wrap(el, wrapper) {
    el.parentNode.insertBefore(wrapper, el);
    wrapper.appendChild(el);
  }

  window.$docsify.plugins.push((hook, vm) => {
    // Convert code blocks to previews
    hook.afterEach(function (html, next) {
      const domParser = new DOMParser();
      const doc = domParser.parseFromString(html, 'text/html');

      [...doc.querySelectorAll('code[class^="lang-"]')].map(code => {
        if (code.classList.contains('preview')) {
          const pre = code.closest('pre');
          const preId = `code-block-preview-${count}`;
          const toggleId = `code-block-toggle-${count}`;

          pre.id = preId;
          pre.classList.add('code-block__source');
          pre.setAttribute('data-lang', pre.getAttribute('data-lang').replace(/ preview$/, ''));
          pre.setAttribute('aria-labelledby', toggleId);

          const codeBlock = `

                ${code.textContent}

                  <sl-icon name="grip-vertical"></sl-icon>

              ${pre.outerHTML}

                Source
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <polyline points="6 9 12 15 18 9"></polyline>
                </svg>

          `;

          pre.replaceWith(domParser.parseFromString(codeBlock, 'text/html').body);

          count++;
        }
      });

      next(doc.body.innerHTML);
    });

    // After the page is done loading, force scripts in previews to execute
    hook.doneEach(() => {
      [...document.querySelectorAll('.code-block__preview script')].map(script => runScript(script));
    });

    // Horizontal resizing
    hook.doneEach(() => {
      [...document.querySelectorAll('.code-block__preview')].map(preview => {
        const resizer = preview.querySelector('.code-block__resizer');
        let startX;
        let startWidth;

        const dragStart = event => {
          startX = event.changedTouches ? event.changedTouches[0].pageX : event.clientX;
          startWidth = parseInt(document.defaultView.getComputedStyle(preview).width, 10);
          preview.classList.add('code-block__preview--dragging');
          event.preventDefault();
          resizer.focus();
          document.documentElement.addEventListener('mousemove', dragMove, false);
          document.documentElement.addEventListener('touchmove', dragMove, false);
          document.documentElement.addEventListener('mouseup', dragStop, false);
          document.documentElement.addEventListener('touchend', dragStop, false);
        };

        const dragMove = event => {
          setWidth(startWidth + (event.changedTouches ? event.changedTouches[0].pageX : event.pageX) - startX);
        };

        const dragStop = event => {
          preview.classList.remove('code-block__preview--dragging');
          document.documentElement.removeEventListener('mousemove', dragMove, false);
          document.documentElement.removeEventListener('touchmove', dragMove, false);
          document.documentElement.removeEventListener('mouseup', dragStop, false);
          document.documentElement.removeEventListener('touchend', dragStop, false);
        };

        const handleKeyDown = event => {
          if (['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
            const currentWidth = preview.clientWidth;
            const maxWidth = preview.parentElement.clientWidth;
            const incr = event.shiftKey ? 100 : 10;

            event.preventDefault();

            if (event.key === 'ArrowLeft') setWidth(currentWidth - incr);
            if (event.key === 'ArrowRight') setWidth(currentWidth + incr);
            if (event.key === 'Home') setWidth(0);
            if (event.key === 'End') setWidth(maxWidth);
          }
        };

        const setWidth = width => (preview.style.width = width + 'px');

        resizer.addEventListener('mousedown', dragStart);
        resizer.addEventListener('touchstart', dragStart);
        resizer.addEventListener('keydown', handleKeyDown);
      }, false);
    });
  });

  // Expand and collapse code blocks
  document.addEventListener('click', event => {
    const toggle = event.target.closest('.code-block__toggle');
    if (toggle) {
      const codeBlock = event.target.closest('.code-block');
      codeBlock.classList.toggle('code-block--expanded');
      event.target.setAttribute('aria-expanded', codeBlock.classList.contains('code-block--expanded'));
    }
  });
})();
<commit_msg>use a button<commit_after>(() => {
  let count = 1;

  if (!window.$docsify) {
    throw new Error('Docsify must be loaded before installing this plugin.');
  }

  function runScript(script) {
    const newScript = document.createElement('script');

    if (script.type === 'module') {
      newScript.type = 'module';
      newScript.textContent = script.innerHTML;
    } else {
      newScript.appendChild(document.createTextNode(`(() => { ${script.innerHTML} })();`));
    }

    script.parentNode.replaceChild(newScript, script);
  }

  function wrap(el, wrapper) {
    el.parentNode.insertBefore(wrapper, el);
    wrapper.appendChild(el);
  }

  window.$docsify.plugins.push((hook, vm) => {
    // Convert code blocks to previews
    hook.afterEach(function (html, next) {
      const domParser = new DOMParser();
      const doc = domParser.parseFromString(html, 'text/html');

      [...doc.querySelectorAll('code[class^="lang-"]')].map(code => {
        if (code.classList.contains('preview')) {
          const pre = code.closest('pre');
          const preId = `code-block-preview-${count}`;
          const toggleId = `code-block-toggle-${count}`;

          pre.id = preId;
          pre.classList.add('code-block__source');
          pre.setAttribute('data-lang', pre.getAttribute('data-lang').replace(/ preview$/, ''));
          pre.setAttribute('aria-labelledby', toggleId);

          const codeBlock = `

                ${code.textContent}

                  <sl-icon name="grip-vertical"></sl-icon>

              ${pre.outerHTML}

              <button type="button" class="code-block__toggle" aria-expanded="false" aria-controls="${preId}">
                Source
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <polyline points="6 9 12 15 18 9"></polyline>
                </svg>
              </button>

          `;

          pre.replaceWith(domParser.parseFromString(codeBlock, 'text/html').body);

          count++;
        }
      });

      next(doc.body.innerHTML);
    });

    // After the page is done loading, force scripts in previews to execute
    hook.doneEach(() => {
      [...document.querySelectorAll('.code-block__preview script')].map(script => runScript(script));
    });

    // Horizontal resizing
    hook.doneEach(() => {
      [...document.querySelectorAll('.code-block__preview')].map(preview => {
        const resizer = preview.querySelector('.code-block__resizer');
        let startX;
        let startWidth;

        const dragStart = event => {
          startX = event.changedTouches ? event.changedTouches[0].pageX : event.clientX;
          startWidth = parseInt(document.defaultView.getComputedStyle(preview).width, 10);
          preview.classList.add('code-block__preview--dragging');
          event.preventDefault();
          resizer.focus();
          document.documentElement.addEventListener('mousemove', dragMove, false);
          document.documentElement.addEventListener('touchmove', dragMove, false);
          document.documentElement.addEventListener('mouseup', dragStop, false);
          document.documentElement.addEventListener('touchend', dragStop, false);
        };

        const dragMove = event => {
          setWidth(startWidth + (event.changedTouches ? event.changedTouches[0].pageX : event.pageX) - startX);
        };

        const dragStop = event => {
          preview.classList.remove('code-block__preview--dragging');
          document.documentElement.removeEventListener('mousemove', dragMove, false);
          document.documentElement.removeEventListener('touchmove', dragMove, false);
          document.documentElement.removeEventListener('mouseup', dragStop, false);
          document.documentElement.removeEventListener('touchend', dragStop, false);
        };

        const handleKeyDown = event => {
          if (['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
            const currentWidth = preview.clientWidth;
            const maxWidth = preview.parentElement.clientWidth;
            const incr = event.shiftKey ? 100 : 10;

            event.preventDefault();

            if (event.key === 'ArrowLeft') setWidth(currentWidth - incr);
            if (event.key === 'ArrowRight') setWidth(currentWidth + incr);
            if (event.key === 'Home') setWidth(0);
            if (event.key === 'End') setWidth(maxWidth);
          }
        };

        const setWidth = width => (preview.style.width = width + 'px');

        resizer.addEventListener('mousedown', dragStart);
        resizer.addEventListener('touchstart', dragStart);
        resizer.addEventListener('keydown', handleKeyDown);
      }, false);
    });
  });

  // Expand and collapse code blocks
  document.addEventListener('click', event => {
    const toggle = event.target.closest('.code-block__toggle');
    if (toggle) {
      const codeBlock = event.target.closest('.code-block');
      codeBlock.classList.toggle('code-block--expanded');
      event.target.setAttribute('aria-expanded', codeBlock.classList.contains('code-block--expanded'));
    }
  });
})();
<|endoftext|>


<commit_before>/* globals Games,gameCache */
/* updateLag:true */

updateLag = 0;

Meteor.methods({
    getLag: function(){
	return updateLag;
    },

    gameMove: function(gameId, dim, choiceIndex){
	"use strict";
	var ts = +new Date();
	var game = gameCache[gameId];
	if (choiceIndex < 0) return;
	if (!game || (ts>game.timeEnds)) return;
	if ((dim!=='row') && (dim!=='col'))
	    throw new Meteor.Error("Invalid","dimname must be 'row' or 'col'");
	if (dim==='row'){
	    if (game.rowUserId !== this.userId) return;
	    if (game.rownames.length <= choiceIndex) return;
	    Meteor.setTimeout(function(){
		Games.update(gameId,
			     {$set: {
				 timeRow: ts,
				 row: choiceIndex,
			     },
			      $push: {
				  moves: [ts,0,choiceIndex]
			      }
			     });
		updateLag = 0.8*updateLag+0.2*(+new Date()-ts);
	    }, 20);
	}
	if (dim==='col'){
	    if (game.colUserId !== this.userId) return;
	    if (game.colnames.length <= choiceIndex) return;
	    Meteor.setTimeout(function(){
		Games.update(gameId,
			     {$set: {
				 timeCol: ts,
				 col: choiceIndex,
			     },
			      $push: {
				  moves: [ts, 1, choiceIndex]
			      }
			     });
		updateLag = 0.8*updateLag+0.2*(+new Date()-ts);
	    }, 20);
	}
    }
});
<commit_msg>add updateLag to jshint globals<commit_after>/* globals Games,gameCache */
/* globals updateLag:true */

updateLag = 0;

Meteor.methods({
    getLag: function(){
	return updateLag;
    },

    gameMove: function(gameId, dim, choiceIndex){
	"use strict";
	var ts = +new Date();
	var game = gameCache[gameId];
	if (choiceIndex < 0) return;
	if (!game || (ts>game.timeEnds)) return;
	if ((dim!=='row') && (dim!=='col'))
	    throw new Meteor.Error("Invalid","dimname must be 'row' or 'col'");
	if (dim==='row'){
	    if (game.rowUserId !== this.userId) return;
	    if (game.rownames.length <= choiceIndex) return;
	    Meteor.setTimeout(function(){
		Games.update(gameId,
			     {$set: {
				 timeRow: ts,
				 row: choiceIndex,
			     },
			      $push: {
				  moves: [ts,0,choiceIndex]
			      }
			     });
		updateLag = 0.8*updateLag+0.2*(+new Date()-ts);
	    }, 20);
	}
	if (dim==='col'){
	    if (game.colUserId !== this.userId) return;
	    if (game.colnames.length <= choiceIndex) return;
	    Meteor.setTimeout(function(){
		Games.update(gameId,
			     {$set: {
				 timeCol: ts,
				 col: choiceIndex,
			     },
			      $push: {
				  moves: [ts, 1, choiceIndex]
			      }
			     });
		updateLag = 0.8*updateLag+0.2*(+new Date()-ts);
	    }, 20);
	}
    }
});
<|endoftext|>


<commit_before>import {Meteor} from 'meteor/meteor';
import {HTTP} from 'meteor/http';

import _ from "lodash";
import __ from 'deepdash/standalone';
import fs from 'fs';
import path from 'path';
import moment from 'moment';

export default function () {

  Meteor.methods({
    async getDeploymentDateTimeUTC() {
      this.unblock();
      try {
        const timeMs = fs.statSync(path.join(process.cwd(), "package.json")).ctimeMs;
        const dtUTC = moment(timeMs).utc().toISOString();
        return dtUTC;
      } catch(error) {
        console.error("getDeploymentDateTimeUTC", error);
      }
    },

    async updateUserWithORCID({code}) {
      let id, orcid, token, existingUser;
      if (id) try {
        let user = await Meteor.call('esGetUserByID', {id});
        orcid = user && user.orcid && user.orcid.id;
        token = user && user.orcid && user.orcid.token;
        existingUser = user;
      } catch (error) {
        console.error('updateUserWithORCID esGetUserByID', id, error);
      }
      if (code && (!orcid || !token)) try {
        let auth = HTTP.call("POST", `https://${Meteor.isDevelopment ? 'sandbox.' : ''}orcid.org/oauth/token`, {
          headers: {
            Accept: 'application/json'
          },
          params: {
            client_id: Meteor.isDevelopment ? 'APP-F8JQS3NCYGINEF7B' : 'APP-7V8YQW9CI7R01H1T',
            client_secret: Meteor.isDevelopment ? Meteor.settings.orcid.sandbox_client_secret : Meteor.settings.orcid.client_secret,
            grant_type: 'authorization_code',
            code: code
          }
        });
        orcid = auth.data.orcid;
        token = auth.data.access_token;
      } catch (error) {
        console.error('updateUserWithORCID Authorize', error);
        throw new Meteor.Error(
          'Failed to authenticate your ORCID account.',
          'Please retry logging in with ORCID. If you are still having trouble, please email us.'
        );
      }
      if (orcid) try {
        existingUser = await Meteor.call('esGetUserByORCID', {orcid});
      } catch (error) {
        console.error('updateUserWithORCID esGetUserByORCID', orcid, error);
      }
      try {
        let record = HTTP.call("GET", `https://api.${Meteor.isDevelopment ? 'sandbox.' : ''}orcid.org/v3.0/${orcid}/record`, {
          headers: {
            Accept: 'application/vnd.orcid+json',
            Authorization: `Bearer ${token}`
          }
        });
        let content = JSON.parse(record.content);
        let emailsSortedByMostReliable =
            content.person.emails &&
            content.person.emails.email &&
            content.person.emails.email.sort((e1, e2) => {
          if (e1.primary && !e2.primary) return -1;
          if (!e1.primary && e2.primary) return 1;
          if (e1.verified && !e2.verified) return -1;
          if (!e1.verified && e2.verified) return 1;
        }).map(x => { return { email: x.email, verified: x.verified, primary: x.primary }});
        for (x of emailsSortedByMostReliable) {
          try {
            if (!existingUser) {
              let users = await Meteor.call('esGetUsersByEmail', {email: x.email});
              let orcidUsers = users && users.filter(x => x && x.orcid && x.orcid.id === orcid) || undefined;
              existingUser = orcidUsers && orcidUsers.length && orcidUsers[0] || users[0];
            }
          } catch (e) {
            console.error("updateUserWithORCID esGetUsersByEmail", `Failed to get user for email ${x.email}`, e);
          }
        }
        let user = {
          orcid: {
            id: orcid,
            token: token
          },
          name: {
            source: 'EarthRef'
          },
          email: {
            source: 'EarthRef'
          }
        };
        if (content.person.name) {
          if (content.person.name['given-names'] && content.person.name['given-names'].value) {
            user.name.given = content.person.name['given-names'].value;
            user.name.source = 'ORCID';
          }
          if (content.person.name['family-name'] && content.person.name['family-name'].value) {
            user.name.family = content.person.name['family-name'].value;
            user.name.source = 'ORCID';
          }
          if (content.person.name['credit-name'] && content.person.name['credit-name'].value) {
            user.name.published = content.person.name['credit-name'].value;
            user.name.source = 'ORCID';
          }
        }
        if (emailsSortedByMostReliable && emailsSortedByMostReliable[0] && emailsSortedByMostReliable[0].email) {
          user.email.address = emailsSortedByMostReliable[0].email;
          user.email.source = 'ORCID';
        }
        if (existingUser) {
          user = _.merge(existingUser, user);
          await Meteor.call('esUpdateUserORCID', user);
        } else {
          user = await Meteor.call('esCreateUserFromORCID', user);
        }
        return __.omitDeep(user, /(^|\.)_/);
      } catch (error) {
        console.error('orcidLogin Record Request', error);
        throw new Meteor.Error(
          'Failed to retrieve your ORCID record.',
          'Please retry logging in with ORCID. If you are still having trouble, please email us.'
        );
      }
    },

    async getReferenceMetadata(doi, attempt = 0) {
      this.unblock();
      // console.log("getReferenceMetadata", attempt, `http://api.crossref.org/works/${doi}`);
      let resp = HTTP.call("GET", `http://api.crossref.org/works/${doi}`);
      if (!resp.statusCode || !resp.data || !resp.data.message) {
        if (attempt < 3) {
          return Meteor.call("getReferenceMetadata", doi, attempt + 1);
        } else {
          console.error("getReferenceMetadata", `Failed to retrieve reference metadata for doi ${doi}`);
          throw new Meteor.Error("getReferenceMetadata", `Failed to retrieve reference metadata for doi ${doi}`);
        }
      } else {
        let d = resp.data.message;
        let _reference = {
          source: 'crossref',
          doi: _.toUpper(d.DOI)
        };

        if (d.title && d.title.length > 0)
          _reference.title = d.title[0];

        if (d['container-title'] && d['container-title'].length > 0)
          _reference.journal = d['container-title'][0];

        if (d['published-print'] && d['published-print']['date-parts'] &&
          d['published-print']['date-parts'][0] && d['published-print']['date-parts'][0][0])
          _reference.year = d['published-print']['date-parts'][0][0];
        else if (d['published-online'] && d['published-online']['date-parts'] &&
          d['published-online']['date-parts'][0] && d['published-online']['date-parts'][0][0])
          _reference.year = d['published-online']['date-parts'][0][0];

        if (d.subject)
          _reference.keywords = d.subject;

        if (d.author && d.author.length === 1)
          _reference.citation = d.author[0].family;
        else if (d.author && d.author.length === 2)
          _reference.citation = d.author[0].family + ' & ' + d.author[1].family;
        else if (d.author && d.author.length > 2)
          _reference.citation = d.author[0].family + ' et al.';
        if (_reference.year)
          _reference.citation += ' (' + _reference.year + ')';

        if (d.author)
          _reference.authors = d.author.map((a) => {
            let author = {};
            author.family = a.family;
            author._name = (_.trim(a.given) === '' ? '' : a.given.toUpperCase().substr(0, 1) + '. ') + a.family;
            if (a.given) author.given = a.given;
            if (a.affiliation && a.affiliation.length > 0)
              author.affiliation = a.affiliation.map((affiliation) => affiliation.name);
            if (a.ORCID) {
              let match = a.ORCID.match(/\/([^\/]+)$/);
              if (match.length >= 2) author._orcid = match[1];
            }
            return author;
          });

        if (d.author)
          _reference.long_authors = d.author.map((a) => (a.given ? a.given + ' ' : '') + a.family).join(', ');

        if (d['is-referenced-by-count'])
          _reference.n_citations = d['is-referenced-by-count'];

        _reference.html = '' +
          (_reference.long_authors ? _reference.long_authors : 'Unknown Authors') +
          ' (' + (_reference.year ? _reference.year : 'Unknown Year') + '). ' +
          (_reference.title ? _reference.title : 'Unknown Title') + '. ' +
          (_reference.journal ? _reference.journal : 'Unknown Journal') +
          (d.volume ? ' ' + d.volume : '') +
          (d.issue ? ' (' + d.issue + ')' : '') +
          (d.page ? ':' + d.page : '') + '.' +
          (d.DOI ? ' doi:' + _.toUpper(d.DOI) + '.' : '') +
          '';
        _reference.html = _reference.html.replace(/"/g, "'");
        //console.log("getReferenceMetadata", attempt, `http://api.crossref.org/works/${doi}`, _reference);
        return _reference;

      }
    }
  });

};<commit_msg>Capitalize authors from Crossref<commit_after>import {Meteor} from 'meteor/meteor';
import {HTTP} from 'meteor/http';

import _ from "lodash";
import __ from 'deepdash/standalone';
import fs from 'fs';
import path from 'path';
import moment from 'moment';

export default function () {

  Meteor.methods({
    async getDeploymentDateTimeUTC() {
      this.unblock();
      try {
        const timeMs = fs.statSync(path.join(process.cwd(), "package.json")).ctimeMs;
        const dtUTC = moment(timeMs).utc().toISOString();
        return dtUTC;
      } catch(error) {
        console.error("getDeploymentDateTimeUTC", error);
      }
    },

    async updateUserWithORCID({code}) {
      let id, orcid, token, existingUser;
      if (id) try {
        let user = await Meteor.call('esGetUserByID', {id});
        orcid = user && user.orcid && user.orcid.id;
        token = user && user.orcid && user.orcid.token;
        existingUser = user;
      } catch (error) {
        console.error('updateUserWithORCID esGetUserByID', id, error);
      }
      if (code && (!orcid || !token)) try {
        let auth = HTTP.call("POST", `https://${Meteor.isDevelopment ? 'sandbox.' : ''}orcid.org/oauth/token`, {
          headers: {
            Accept: 'application/json'
          },
          params: {
            client_id: Meteor.isDevelopment ? 'APP-F8JQS3NCYGINEF7B' : 'APP-7V8YQW9CI7R01H1T',
            client_secret: Meteor.isDevelopment ? Meteor.settings.orcid.sandbox_client_secret : Meteor.settings.orcid.client_secret,
            grant_type: 'authorization_code',
            code: code
          }
        });
        orcid = auth.data.orcid;
        token = auth.data.access_token;
      } catch (error) {
        console.error('updateUserWithORCID Authorize', error);
        throw new Meteor.Error(
          'Failed to authenticate your ORCID account.',
          'Please retry logging in with ORCID. If you are still having trouble, please email us.'
        );
      }
      if (orcid) try {
        existingUser = await Meteor.call('esGetUserByORCID', {orcid});
      } catch (error) {
        console.error('updateUserWithORCID esGetUserByORCID', orcid, error);
      }
      try {
        let record = HTTP.call("GET", `https://api.${Meteor.isDevelopment ? 'sandbox.' : ''}orcid.org/v3.0/${orcid}/record`, {
          headers: {
            Accept: 'application/vnd.orcid+json',
            Authorization: `Bearer ${token}`
          }
        });
        let content = JSON.parse(record.content);
        let emailsSortedByMostReliable =
            content.person.emails &&
            content.person.emails.email &&
            content.person.emails.email.sort((e1, e2) => {
          if (e1.primary && !e2.primary) return -1;
          if (!e1.primary && e2.primary) return 1;
          if (e1.verified && !e2.verified) return -1;
          if (!e1.verified && e2.verified) return 1;
        }).map(x => { return { email: x.email, verified: x.verified, primary: x.primary }});
        for (x of emailsSortedByMostReliable) {
          try {
            if (!existingUser) {
              let users = await Meteor.call('esGetUsersByEmail', {email: x.email});
              let orcidUsers = users && users.filter(x => x && x.orcid && x.orcid.id === orcid) || undefined;
              existingUser = orcidUsers && orcidUsers.length && orcidUsers[0] || users[0];
            }
          } catch (e) {
            console.error("updateUserWithORCID esGetUsersByEmail", `Failed to get user for email ${x.email}`, e);
          }
        }
        let user = {
          orcid: {
            id: orcid,
            token: token
          },
          name: {
            source: 'EarthRef'
          },
          email: {
            source: 'EarthRef'
          }
        };
        if (content.person.name) {
          if (content.person.name['given-names'] && content.person.name['given-names'].value) {
            user.name.given = content.person.name['given-names'].value;
            user.name.source = 'ORCID';
          }
          if (content.person.name['family-name'] && content.person.name['family-name'].value) {
            user.name.family = content.person.name['family-name'].value;
            user.name.source = 'ORCID';
          }
          if (content.person.name['credit-name'] && content.person.name['credit-name'].value) {
            user.name.published = content.person.name['credit-name'].value;
            user.name.source = 'ORCID';
          }
        }
        if (emailsSortedByMostReliable && emailsSortedByMostReliable[0] && emailsSortedByMostReliable[0].email) {
          user.email.address = emailsSortedByMostReliable[0].email;
          user.email.source = 'ORCID';
        }
        if (existingUser) {
          user = _.merge(existingUser, user);
          await Meteor.call('esUpdateUserORCID', user);
        } else {
          user = await Meteor.call('esCreateUserFromORCID', user);
        }
        return __.omitDeep(user, /(^|\.)_/);
      } catch (error) {
        console.error('orcidLogin Record Request', error);
        throw new Meteor.Error(
          'Failed to retrieve your ORCID record.',
          'Please retry logging in with ORCID. If you are still having trouble, please email us.'
        );
      }
    },

    async getReferenceMetadata(doi, attempt = 0) {
      this.unblock();
      // console.log("getReferenceMetadata", attempt, `http://api.crossref.org/works/${doi}`);
      let resp = HTTP.call("GET", `http://api.crossref.org/works/${doi}`);
      if (!resp.statusCode || !resp.data || !resp.data.message) {
        if (attempt < 3) {
          return Meteor.call("getReferenceMetadata", doi, attempt + 1);
        } else {
          console.error("getReferenceMetadata", `Failed to retrieve reference metadata for doi ${doi}`);
          throw new Meteor.Error("getReferenceMetadata", `Failed to retrieve reference metadata for doi ${doi}`);
        }
      } else {
        let d = resp.data.message;
        let _reference = {
          source: 'crossref',
          doi: _.toUpper(d.DOI)
        };

        if (d.title && d.title.length > 0)
          _reference.title = d.title[0];

        if (d['container-title'] && d['container-title'].length > 0)
          _reference.journal = d['container-title'][0];

        if (d['published-print'] && d['published-print']['date-parts'] &&
          d['published-print']['date-parts'][0] && d['published-print']['date-parts'][0][0])
          _reference.year = d['published-print']['date-parts'][0][0];
        else if (d['published-online'] && d['published-online']['date-parts'] &&
          d['published-online']['date-parts'][0] && d['published-online']['date-parts'][0][0])
          _reference.year = d['published-online']['date-parts'][0][0];

        if (d.subject)
          _reference.keywords = d.subject;

        if (d.author && d.author.length === 1)
          _reference.citation = d.author[0].family;
        else if (d.author && d.author.length === 2)
          _reference.citation = d.author[0].family + ' & ' + d.author[1].family;
        else if (d.author && d.author.length > 2)
          _reference.citation = d.author[0].family + ' et al.';
        if (_reference.year)
          _reference.citation += ' (' + _reference.year + ')';

        if (d.author)
          _reference.authors = d.author.map((a) => {
            let author = {};
            author.family = (a.family == a.family.toUpperCase() ? _.startCase(_.lowerCase(a.family)) : a.family);
            author._name = (_.trim(a.given) === '' ? '' : a.given.toUpperCase().substr(0, 1) + '. ') + a.family;
            if (a.given) author.given = a.given;
            if (a.affiliation && a.affiliation.length > 0)
              author.affiliation = a.affiliation.map((affiliation) => affiliation.name);
            if (a.ORCID) {
              let match = a.ORCID.match(/\/([^\/]+)$/);
              if (match.length >= 2) author._orcid = match[1];
            }
            return author;
          });

        if (d.author)
          _reference.long_authors = d.author.map((a) => (a.given ? a.given + ' ' : '') + a.family).join(', ');

        if (d['is-referenced-by-count'])
          _reference.n_citations = d['is-referenced-by-count'];

        _reference.html = '' +
          (_reference.long_authors ? _reference.long_authors : 'Unknown Authors') +
          ' (' + (_reference.year ? _reference.year : 'Unknown Year') + '). ' +
          (_reference.title ? _reference.title : 'Unknown Title') + '. ' +
          (_reference.journal ? _reference.journal : 'Unknown Journal') +
          (d.volume ? ' ' + d.volume : '') +
          (d.issue ? ' (' + d.issue + ')' : '') +
          (d.page ? ':' + d.page : '') + '.' +
          (d.DOI ? ' doi:' + _.toUpper(d.DOI) + '.' : '') +
          '';
        _reference.html = _reference.html.replace(/"/g, "'");
        //console.log("getReferenceMetadata", attempt, `http://api.crossref.org/works/${doi}`, _reference);
        return _reference;

      }
    }
  });

};<|endoftext|>


<commit_before>'use strict'

// external deps
var ObjectId = require("mongodb").ObjectId;
var UomManager = require('./uom-manager');
var BaseManager = require('module-toolkit').BaseManager;
var i18n = require('dl-i18n');
var assert = require('assert');

// internal deps
require('mongodb-toolkit');
var DLModels = require('dl-models');
var map = DLModels.map;
var Product = DLModels.master.Product;
var UomManager = require('./uom-manager');
var CurrencyManager = require('./currency-manager');

module.exports = class GarmentProductManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(map.master.collection.GarmentProduct);
        this.uomManager = new UomManager(db, user);
        this.currencyManager = new CurrencyManager(db, user);
    }

    _getQuery(paging) {
        var _default = {
            _deleted: false,

        },
            pagingFilter = paging.filter || {},
            keywordFilter = {},

            query = {};

        if (paging.keyword) {
            var keyRegex = new RegExp(paging.keyword, "i");
            var codeFilter = {
                'code': {
                    '$regex': keyRegex
                }
            };
            var nameFilter = {
                'name': {
                    '$regex': keyRegex
                }
            };

            keywordFilter['$or'] = [codeFilter, nameFilter];
        }

        query["$and"] = [_default, keywordFilter, pagingFilter];
        return query;
    }

    _validate(product) {
        var errors = {};
        var valid = product;

        // 1. begin: Declare promises.
        var getProductPromise = this.collection.singleOrDefault({
            _id: {
                '$ne': new ObjectId(valid._id)
            },
            code: valid.code
        });

        var getUom = valid.uom && ObjectId.isValid(valid.uom._id) ? this.uomManager.getSingleByIdOrDefault(valid.uom._id) : Promise.resolve(null);
        var getCurrency = valid.currency && ObjectId.isValid(valid.currency._id) ? this.currencyManager.getSingleByIdOrDefault(valid.currency._id) : Promise.resolve(null);

        // 2. begin: Validation.
        return Promise.all([getProductPromise, getUom, getCurrency])
            .then((results) => {
                var _module = results[0];
                var _uom = results[1];
                var _currency = results[2];

                if (!valid.code || valid.code == '') {
                    errors["code"] = i18n.__("Product.code.isRequired:%s is required", i18n.__("Product.code._:Code")); // "Kode tidak boleh kosong.";
                } else if (_module) {
                    errors["code"] = i18n.__("Product.code.isExists:%s is already exists", i18n.__("Product.code._:Code")); // "Kode sudah terdaftar.";
                }

                if (!valid.name || valid.name == '') {
                    errors["name"] = i18n.__("Product.name.isRequired:%s is required", i18n.__("Product.name._:Name")); // "Nama tidak boleh kosong.";
                }
                if (!valid.uom) {
                    errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                if (valid.uom) {
                    if (!valid.uom.unit || valid.uom.unit == '')
                        errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                else if (_uom) {
                    errors["uom"] = i18n.__("Product.uom.noExists:%s is not exists", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }

                // 2c. begin: check if data has any error, reject if it has.
                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require('module-toolkit').ValidationError;
                    return Promise.reject(new ValidationError('Product Manager : data does not pass validation' + JSON.stringify(errors), errors));
                }
                if (!valid.stamp) {
                    valid = new Product(valid);
                }
                valid.stamp(this.user.username, 'manager');

                valid.uom = _uom;
                valid.uomId = new ObjectId(valid.uom._id);
                if (_currency) {
                    valid.currency = _currency;
                }
                valid.currency.rate = Number(valid.currency.rate);
                valid.price = Number(valid.price);
                return Promise.resolve(valid);
            });
    }

    getProduct() {
        return new Promise((resolve, reject) => {
            var query = {
                _deleted: false
            };
            this.collection
                .where(query)
                .execute()
                .then(products => {
                    resolve(products);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    insert(dataFile) {
        return new Promise((resolve, reject) => {
            var product, uoms, currencies;
            this.getProduct()
                .then(results => {
                    this.uomManager.getUOM()
                        .then(_uoms => {
                            this.currencyManager.getCurrency()
                                .then(_currencies => {
                                    product = results.data;
                                    uoms = _uoms.data;
                                    currencies = _currencies.data;
                                    var data = [];
                                    if (dataFile != "") {
                                        for (var i = 1; i < dataFile.length; i++) {
                                            var properties = [];
                                            if (dataFile[i].length >= 8) {
                                                properties.push(dataFile[i][7].trim())
                                                if (dataFile[i].length >= 9) {
                                                    properties.push(dataFile[i][8].trim())
                                                    if (dataFile[i].length >= 10) {
                                                        properties.push(dataFile[i][9].trim())
                                                    }
                                                }
                                            }
                                            data.push({
                                                "code": dataFile[i][0].trim(),
                                                "name": dataFile[i][1].trim(),
                                                "uom": dataFile[i][2].trim(),
                                                "currency": dataFile[i][3].trim(),
                                                "price": dataFile[i][4],
                                                "tags": dataFile[i][5].trim(),
                                                "description": dataFile[i][6].trim(),
                                                "properties": properties
                                            });
                                        }
                                    }

                                    var dataError = [], errorMessage;
                                    for (var i = 0; i < data.length; i++) {
                                        errorMessage = "";
                                        if (data[i]["code"] === "" || data[i]["code"] === undefined) {
                                            errorMessage = errorMessage + "Kode tidak boleh kosong, ";
                                        }
                                        if (data[i]["name"] === "" || data[i]["name"] === undefined) {
                                            errorMessage = errorMessage + "Nama tidak boleh kosong, ";
                                        }
                                        if (data[i]["uom"] === "" || data[i]["uom"] === undefined) {
                                            errorMessage = errorMessage + "Satuan tidak boleh kosong, ";
                                        }
                                        // if (data[i]["currency"] === "" || data[i]["currency"] === undefined) {
                                        //     errorMessage = errorMessage + "Mata Uang tidak boleh kosong, ";
                                        // }
                                        // if (data[i]["price"] === "" || data[i]["price"] === undefined) {
                                        //     errorMessage = errorMessage + "Harga tidak boleh kosong, ";
                                        // } else if (isNaN(data[i]["price"])) {
                                        //     errorMessage = errorMessage + "Harga harus numerik, ";
                                        // }
                                        // else {
                                        //     var rateTemp = (data[i]["price"]).toString().split(".");
                                        //     if (rateTemp[1] === undefined) {
                                        //     } else if (rateTemp[1].length > 2) {
                                        //         errorMessage = errorMessage + "Harga maksimal memiliki 2 digit dibelakang koma, ";
                                        //     }
                                        // }
                                        for (var j = 0; j < product.length; j++) {
                                            if (product[j]["code"] === data[i]["code"]) {
                                                errorMessage = errorMessage + "Kode tidak boleh duplikat, ";
                                            }
                                            if (product[j]["name"] === data[i]["name"]) {
                                                errorMessage = errorMessage + "Nama tidak boleh duplikat, ";
                                            }
                                        }
                                        // var flagUom = false;
                                        var _uom = uoms.find(uom => uom.unit === data[i]["uom"])
                                        if (!_uom) {
                                            errorMessage = errorMessage + "Satuan tidak terdaftar di Master Satuan, ";
                                        }

                                        var _currency = currencies.find(currency => currency.code === data[i]["currency"])
                                        if (!_currency) {
                                            errorMessage = errorMessage + "Mata Uang tidak terdaftar di Master Mata Uang";
                                        }

                                        if (errorMessage !== "") {
                                            dataError.push({ "code": data[i]["code"], "name": data[i]["name"], "uom": data[i]["uom"], "currency": data[i]["currency"], "price": data[i]["price"], "tags": data[i]["tags"], "description": data[i]["description"], "properties": data[i]["properties"], "Error": errorMessage });
                                        } else {
                                            data[i]["currency"] = _currency;
                                            data[i]["uom"] = _uom;
                                        }
                                    }
                                    if (dataError.length === 0) {
                                        var newProduct = [];
                                        for (var i = 0; i < data.length; i++) {
                                            var valid = new Product(data[i]);
                                            valid.currency.rate = Number(valid.currency.rate);
                                            valid.price = Number(valid.price);
                                            valid.uomId = new ObjectId(valid.uom._id);
                                            valid.stamp(this.user.username, 'manager');
                                            this.collection.insert(valid)
                                                .then(id => {
                                                    this.getSingleById(id)
                                                        .then(resultItem => {
                                                            newProduct.push(resultItem)
                                                            resolve(newProduct);
                                                        })
                                                        .catch(e => {
                                                            reject(e);
                                                        });
                                                })
                                                .catch(e => {
                                                    reject(e);
                                                });

                                        }
                                    } else {
                                        resolve(dataError);
                                    }
                                })
                        })
                })
        })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.master.collection.Product}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var codeIndex = {
            name: `ix_${map.master.collection.Product}_code`,
            key: {
                code: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, codeIndex]);
    }

    getProductByTags(key, tag) {
        return new Promise((resolve, reject) => {
            var regex = new RegExp(key, "i");
            var regex2 = new RegExp(tag, "i");
            this.collection.aggregate(
                [{
                    $match: {
                        $and: [{
                            $and: [{
                                "tags": regex2
                            }, {
                                    "_deleted": false
                                }]
                        }, {
                                "name": {
                                    "$regex": regex
                                }
                            }]
                    }
                }]
            )
                .toArray(function (err, result) {
                    assert.equal(err, null);
                    resolve(result);
                });
        });
    }

    readById(paging) {
        var _paging = Object.assign({
            order: {},
            filter: {},
            select: []
        }, paging);

        return this._createIndexes()
            .then((createIndexResults) => {
                return this.collection
                    .where(_paging.filter)
                    .select(_paging.select)
                    .order(_paging.order)
                    .execute();
            });
    }
};
<commit_msg>fix validation<commit_after>'use strict'

// external deps
var ObjectId = require("mongodb").ObjectId;
var UomManager = require('./uom-manager');
var BaseManager = require('module-toolkit').BaseManager;
var i18n = require('dl-i18n');
var assert = require('assert');

// internal deps
require('mongodb-toolkit');
var DLModels = require('dl-models');
var map = DLModels.map;
var Product = DLModels.master.Product;
var UomManager = require('./uom-manager');
var CurrencyManager = require('./currency-manager');

module.exports = class GarmentProductManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(map.master.collection.GarmentProduct);
        this.uomManager = new UomManager(db, user);
        this.currencyManager = new CurrencyManager(db, user);
    }

    _getQuery(paging) {
        var _default = {
            _deleted: false,

        },
            pagingFilter = paging.filter || {},
            keywordFilter = {},

            query = {};

        if (paging.keyword) {
            var keyRegex = new RegExp(paging.keyword, "i");
            var codeFilter = {
                'code': {
                    '$regex': keyRegex
                }
            };
            var nameFilter = {
                'name': {
                    '$regex': keyRegex
                }
            };

            keywordFilter['$or'] = [codeFilter, nameFilter];
        }

        query["$and"] = [_default, keywordFilter, pagingFilter];
        return query;
    }

    _validate(product) {
        var errors = {};
        var valid = product;

        // 1. begin: Declare promises.
        var getProductPromise = this.collection.singleOrDefault({
            _id: {
                '$ne': new ObjectId(valid._id)
            },
            code: valid.code
        });

        var getUom = valid.uom && ObjectId.isValid(valid.uom._id) ? this.uomManager.getSingleByIdOrDefault(valid.uom._id) : Promise.resolve(null);
        var getCurrency = valid.currency && ObjectId.isValid(valid.currency._id) ? this.currencyManager.getSingleByIdOrDefault(valid.currency._id) : Promise.resolve(null);

        // 2. begin: Validation.
        return Promise.all([getProductPromise, getUom, getCurrency])
            .then((results) => {
                var _module = results[0];
                var _uom = results[1];
                var _currency = results[2];

                if (!valid.code || valid.code == '') {
                    errors["code"] = i18n.__("Product.code.isRequired:%s is required", i18n.__("Product.code._:Code")); // "Kode tidak boleh kosong.";
                } else if (_module) {
                    errors["code"] = i18n.__("Product.code.isExists:%s is already exists", i18n.__("Product.code._:Code")); // "Kode sudah terdaftar.";
                }

                if (!valid.name || valid.name == '') {
                    errors["name"] = i18n.__("Product.name.isRequired:%s is required", i18n.__("Product.name._:Name")); // "Nama tidak boleh kosong.";
                }
                if (!valid.uom) {
                    errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                if (valid.uom) {
                    if (!valid.uom.unit || valid.uom.unit == '')
                        errors["uom"] = i18n.__("Product.uom.isRequired:%s is required", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }
                else if (_uom) {
                    errors["uom"] = i18n.__("Product.uom.noExists:%s is not exists", i18n.__("Product.uom._:Uom")); //"Satuan tidak boleh kosong";
                }

                // 2c. begin: check if data has any error, reject if it has.
                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require('module-toolkit').ValidationError;
                    return Promise.reject(new ValidationError('Product Manager : data does not pass validation' + JSON.stringify(errors), errors));
                }
                if (!valid.stamp) {
                    valid = new Product(valid);
                }
                valid.stamp(this.user.username, 'manager');

                valid.uom = _uom;
                valid.uomId = new ObjectId(valid.uom._id);
                if (_currency) {
                    valid.currency = _currency;
                }
                valid.currency.rate = Number(valid.currency.rate);
                valid.price = Number(valid.price);
                return Promise.resolve(valid);
            });
    }

    getProduct() {
        return new Promise((resolve, reject) => {
            var query = {
                _deleted: false
            };
            this.collection
                .where(query)
                .execute()
                .then(products => {
                    resolve(products);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    insert(dataFile) {
        return new Promise((resolve, reject) => {
            var product, uoms, currencies;
            this.getProduct()
                .then(results => {
                    this.uomManager.getUOM()
                        .then(_uoms => {
                            this.currencyManager.getCurrency()
                                .then(_currencies => {
                                    product = results.data;
                                    uoms = _uoms.data;
                                    currencies = _currencies.data;
                                    var data = [];
                                    if (dataFile != "") {
                                        for (var i = 1; i < dataFile.length; i++) {
                                            var properties = [];
                                            if (dataFile[i].length >= 8) {
                                                properties.push(dataFile[i][7].trim())
                                                if (dataFile[i].length >= 9) {
                                                    properties.push(dataFile[i][8].trim())
                                                    if (dataFile[i].length >= 10) {
                                                        properties.push(dataFile[i][9].trim())
                                                    }
                                                }
                                            }
                                            data.push({
                                                "code": dataFile[i][0].trim(),
                                                "name": dataFile[i][1].trim(),
                                                "uom": dataFile[i][2].trim(),
                                                "currency": dataFile[i][3].trim(),
                                                "price": dataFile[i][4],
                                                "tags": dataFile[i][5].trim(),
                                                "description": dataFile[i][6].trim(),
                                                "properties": properties
                                            });
                                        }
                                    }

                                    var dataError = [], errorMessage;
                                    for (var i = 0; i < data.length; i++) {
                                        errorMessage = "";
                                        if (data[i]["code"] === "" || data[i]["code"] === undefined) {
                                            errorMessage = errorMessage + "Kode tidak boleh kosong, ";
                                        }
                                        if (data[i]["name"] === "" || data[i]["name"] === undefined) {
                                            errorMessage = errorMessage + "Nama tidak boleh kosong, ";
                                        }
                                        if (data[i]["uom"] === "" || data[i]["uom"] === undefined) {
                                            errorMessage = errorMessage + "Satuan tidak boleh kosong, ";
                                        }
                                        // if (data[i]["currency"] === "" || data[i]["currency"] === undefined) {
                                        //     errorMessage = errorMessage + "Mata Uang tidak boleh kosong, ";
                                        // }
                                        // if (data[i]["price"] === "" || data[i]["price"] === undefined) {
                                        //     errorMessage = errorMessage + "Harga tidak boleh kosong, ";
                                        // } else if (isNaN(data[i]["price"])) {
                                        //     errorMessage = errorMessage + "Harga harus numerik, ";
                                        // }
                                        if (isNaN(data[i]["price"])) {
                                            errorMessage = errorMessage + "Harga harus numerik, ";
                                        }
                                        // else {
                                        //     var rateTemp = (data[i]["price"]).toString().split(".");
                                        //     if (rateTemp[1] === undefined) {
                                        //     } else if (rateTemp[1].length > 2) {
                                        //         errorMessage = errorMessage + "Harga maksimal memiliki 2 digit dibelakang koma, ";
                                        //     }
                                        // }
                                        for (var j = 0; j < product.length; j++) {
                                            if (product[j]["code"] === data[i]["code"]) {
                                                errorMessage = errorMessage + "Kode tidak boleh duplikat, ";
                                            }
                                            if (product[j]["name"] === data[i]["name"]) {
                                                errorMessage = errorMessage + "Nama tidak boleh duplikat, ";
                                            }
                                        }
                                        // var flagUom = false;
                                        var _uom = uoms.find(uom => uom.unit === data[i]["uom"])
                                        if (!_uom) {
                                            errorMessage = errorMessage + "Satuan tidak terdaftar di Master Satuan, ";
                                        }

                                        var _currency = currencies.find(currency => currency.code === data[i]["currency"])
                                        if (!_currency) {
                                            errorMessage = errorMessage + "Mata Uang tidak terdaftar di Master Mata Uang";
                                        }

                                        if (errorMessage !== "") {
                                            dataError.push({ "code": data[i]["code"], "name": data[i]["name"], "uom": data[i]["uom"], "currency": data[i]["currency"], "price": data[i]["price"], "tags": data[i]["tags"], "description": data[i]["description"], "properties": data[i]["properties"], "Error": errorMessage });
                                        } else {
                                            data[i]["currency"] = _currency;
                                            data[i]["uom"] = _uom;
                                        }
                                    }
                                    if (dataError.length === 0) {
                                        var newProduct = [];
                                        for (var i = 0; i < data.length; i++) {
                                            var valid = new Product(data[i]);
                                            valid.currency.rate = Number(valid.currency.rate);
                                            valid.price = Number(valid.price);
                                            valid.uomId = new ObjectId(valid.uom._id);
                                            valid.stamp(this.user.username, 'manager');
                                            this.collection.insert(valid)
                                                .then(id => {
                                                    this.getSingleById(id)
                                                        .then(resultItem => {
                                                            newProduct.push(resultItem)
                                                            resolve(newProduct);
                                                        })
                                                        .catch(e => {
                                                            reject(e);
                                                        });
                                                })
                                                .catch(e => {
                                                    reject(e);
                                                });

                                        }
                                    } else {
                                        resolve(dataError);
                                    }
                                })
                        })
                })
        })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.master.collection.Product}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var codeIndex = {
            name: `ix_${map.master.collection.Product}_code`,
            key: {
                code: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, codeIndex]);
    }

    getProductByTags(key, tag) {
        return new Promise((resolve, reject) => {
            var regex = new RegExp(key, "i");
            var regex2 = new RegExp(tag, "i");
            this.collection.aggregate(
                [{
                    $match: {
                        $and: [{
                            $and: [{
                                "tags": regex2
                            }, {
                                    "_deleted": false
                                }]
                        }, {
                                "name": {
                                    "$regex": regex
                                }
                            }]
                    }
                }]
            )
                .toArray(function (err, result) {
                    assert.equal(err, null);
                    resolve(result);
                });
        });
    }

    readById(paging) {
        var _paging = Object.assign({
            order: {},
            filter: {},
            select: []
        }, paging);

        return this._createIndexes()
            .then((createIndexResults) => {
                return this.collection
                    .where(_paging.filter)
                    .select(_paging.select)
                    .order(_paging.order)
                    .execute();
            });
    }
};
<|endoftext|>