<commit_before>var express = require('express');
var async = require('async');
var fs = require('fs');
var UserClient = require('webmaker-user-client');
var BadgeClient = require('badgekit-api-client');
var path = require('path');
var i18n = require('webmaker-i18n');

module.exports = function (config, webmakerAuth, liveReloadRelativePath) {
  var router = express.Router();
  var userClient = new UserClient({
    endpoint: config.loginUrlWithAuth
  });
  var badgesClient = new BadgeClient(config.badgekitApiUrl, {
    key: config.badgekitApiKey,
    secret: config.badgekitApiSecret
  });
  var badgesContext = {
    system: 'webmaker'
  };

  // Localized Strings
  router.get("/localized/strings/:lang?", i18n.stringsRoute("en-US"));

  // Match any URL that doesn't fall under an underscore prefixed subdirectory and serve index.html
  // eg: /user/joe/*  NOT  /user/_less/app.less
  router.get(/^\/user(?!\/_)/, function (req, res) {
    if (liveReloadRelativePath) {
      res.sendfile(path.resolve(__dirname, '../', liveReloadRelativePath, 'index.html'));
    } else {
      res.sendfile(path.resolve(__dirname, '../../app/index.html'));
    }
  })

  router.get('/user/_service/env.json', function (req, res) {
    var env = config.public;
    env.csrf = req.csrfToken();
    env.l10n = {
      supported_languages: i18n.getSupportLanguages(),
      lang: req.localeInfo.lang,
      defaultLang: 'en-US',
      direction: req.localeInfo.direction
    };
    res.json(config.public);
  });

  // Returns a list of a user's badges given a username
  router.get('/user/_service/badges/username/:username', function (req, res, next) {
    async.waterfall([
      function (callback) {
        userClient.get.byUsername(req.params.username, callback);
      },
      function (result, callback) {
        if (!result.user) {
          var error = new Error('User not found');
          error.code = 400;
          return callback(error);
        }
        badgesClient.getBadgeInstances(badgesContext, result.user.email, callback);
      }
    ], function (err, badges) {
      if (err) {
        return next(err);
      }
      // Remove emails
      badges.forEach(function (badge) {
        badge.email = undefined;
      });
      res.send(badges);
    });

  });

  // Get a user's public data subset
  router.get('/user/_service/user-data/:username', function (req, res, next) {
    userClient.get.byUsername(req.params.username, function (err, data) {
      if (err) {
        return res.json(500, {
          error: err.toString()
        });
      }

      if (!data.user) {
        return res.send(404);
      }

      // Make the returned avatar be 400x400
      data.user.avatar = data.user.avatar + '&s=400';

      // Don't expose PII publicly
      delete data.user.email;

      res.json(data);
    })
  });

  router.put('/user/_service/user-data/:username', function (req, res, next) {
    if (req.params.username !== req.session.user.username) {
      return res.json(403, {
        "error": "You do not have permission to modify " + req.params.username
      })
    }

    var filteredData = {
      bio: req.body.bio,
      location: req.body.location,
      links: req.body.links
    }

    userClient.update.byUsername(req.params.username, filteredData, function (err, data) {
      if (err) {
        return res.json(500, {
          error: err
        });
      }

      res.json(data);
    });
  });

  router.post('/user/_service/login/verify', webmakerAuth.handlers.verify);
  router.post('/user/_service/login/authenticate', webmakerAuth.handlers.authenticate);
  router.post('/user/_service/login/create', webmakerAuth.handlers.create);
  router.post('/user/_service/login/logout', webmakerAuth.handlers.logout);
  router.post('/user/_service/login/check-username', webmakerAuth.handlers.exists);

  return router;
};
<commit_msg>Fixed Bug 1053066<commit_after>var express = require('express');
var async = require('async');
var fs = require('fs');
var UserClient = require('webmaker-user-client');
var BadgeClient = require('badgekit-api-client');
var path = require('path');
var i18n = require('webmaker-i18n');

module.exports = function (config, webmakerAuth, liveReloadRelativePath) {
  var router = express.Router();
  var userClient = new UserClient({
    endpoint: config.loginUrlWithAuth
  });
  var badgesClient = new BadgeClient(config.badgekitApiUrl, {
    key: config.badgekitApiKey,
    secret: config.badgekitApiSecret
  });
  var badgesContext = {
    system: 'webmaker'
  };

  // Localized Strings
  router.get("/user/localized/strings/:lang?", i18n.stringsRoute("en-US"));

  // Match any URL that doesn't fall under an underscore prefixed subdirectory and serve index.html
  // eg: /user/joe/*  NOT  /user/_less/app.less
  router.get(/^\/user(?!\/_)/, function (req, res) {
    if (liveReloadRelativePath) {
      res.sendfile(path.resolve(__dirname, '../', liveReloadRelativePath, 'index.html'));
    } else {
      res.sendfile(path.resolve(__dirname, '../../app/index.html'));
    }
  })

  router.get('/user/_service/env.json', function (req, res) {
    var env = config.public;
    env.csrf = req.csrfToken();
    env.l10n = {
      supported_languages: i18n.getSupportLanguages(),
      lang: req.localeInfo.lang,
      defaultLang: 'en-US',
      direction: req.localeInfo.direction
    };
    res.json(config.public);
  });

  // Returns a list of a user's badges given a username
  router.get('/user/_service/badges/username/:username', function (req, res, next) {
    async.waterfall([
      function (callback) {
        userClient.get.byUsername(req.params.username, callback);
      },
      function (result, callback) {
        if (!result.user) {
          var error = new Error('User not found');
          error.code = 400;
          return callback(error);
        }
        badgesClient.getBadgeInstances(badgesContext, result.user.email, callback);
      }
    ], function (err, badges) {
      if (err) {
        return next(err);
      }
      // Remove emails
      badges.forEach(function (badge) {
        badge.email = undefined;
      });
      res.send(badges);
    });

  });

  // Get a user's public data subset
  router.get('/user/_service/user-data/:username', function (req, res, next) {
    userClient.get.byUsername(req.params.username, function (err, data) {
      if (err) {
        return res.json(500, {
          error: err.toString()
        });
      }

      if (!data.user) {
        return res.send(404);
      }

      // Make the returned avatar be 400x400
      data.user.avatar = data.user.avatar + '&s=400';

      // Don't expose PII publicly
      delete data.user.email;

      res.json(data);
    })
  });

  router.put('/user/_service/user-data/:username', function (req, res, next) {
    if (req.params.username !== req.session.user.username) {
      return res.json(403, {
        "error": "You do not have permission to modify " + req.params.username
      })
    }

    var filteredData = {
      bio: req.body.bio,
      location: req.body.location,
      links: req.body.links
    }

    userClient.update.byUsername(req.params.username, filteredData, function (err, data) {
      if (err) {
        return res.json(500, {
          error: err
        });
      }

      res.json(data);
    });
  });

  router.post('/user/_service/login/verify', webmakerAuth.handlers.verify);
  router.post('/user/_service/login/authenticate', webmakerAuth.handlers.authenticate);
  router.post('/user/_service/login/create', webmakerAuth.handlers.create);
  router.post('/user/_service/login/logout', webmakerAuth.handlers.logout);
  router.post('/user/_service/login/check-username', webmakerAuth.handlers.exists);

  return router;
};
<|endoftext|>


<commit_before>require([
  'jquery',
  'backbone',
  'views/root'<% if (starterApp === 'Hello World') { %>,
  'routers/hello-world'<% } else if (starterApp === 'Todo List') { %>,
  'routers/todo-list'<% } %>
], function ($, Backbone, RootView<% if (starterApp === 'Hello World') { %>, HelloWorldRouter<% } else if (starterApp === 'Todo List') { %>, TodoListRouter <% } %>) {

  initialize(function(next) {
    // Load any data that your app requires to boot
    // and initialize all routers here, the callback
    // `next` is provided in case the operations
    // needed are aysynchronous
    <% if (starterApp === 'Hello World') { %>new HelloWorldRouter;<% } else if (starterApp === 'Todo List') { %>new TodoListRouter;<% } %>

    next();
  });

  function initialize() {
    $(function() {
      Backbone.history.start({
        pushState: false,
        root: '/',
        silent: true
      });

      // RootView may use link or url helpers which
      // depend on Backbone history being setup
      // so need to wait to loadUrl() (which will)
      // actually execute the route
      RootView.getInstance(document.body);

      complete(function() {
        Backbone.history.loadUrl();
      });
    });
  }

});
<commit_msg>Add missing callback<commit_after>require([
  'jquery',
  'backbone',
  'views/root'<% if (starterApp === 'Hello World') { %>,
  'routers/hello-world'<% } else if (starterApp === 'Todo List') { %>,
  'routers/todo-list'<% } %>
], function ($, Backbone, RootView<% if (starterApp === 'Hello World') { %>, HelloWorldRouter<% } else if (starterApp === 'Todo List') { %>, TodoListRouter <% } %>) {

  initialize(function(next) {
    // Load any data that your app requires to boot
    // and initialize all routers here, the callback
    // `next` is provided in case the operations
    // needed are aysynchronous
    <% if (starterApp === 'Hello World') { %>new HelloWorldRouter;<% } else if (starterApp === 'Todo List') { %>new TodoListRouter;<% } %>

    next();
  });

  function initialize(complete) {
    $(function() {
      Backbone.history.start({
        pushState: false,
        root: '/',
        silent: true
      });

      // RootView may use link or url helpers which
      // depend on Backbone history being setup
      // so need to wait to loadUrl() (which will)
      // actually execute the route
      RootView.getInstance(document.body);

      complete(function() {
        Backbone.history.loadUrl();
      });
    });
  }

});
<|endoftext|>


<commit_before>module.exports = function (app) {
    var express = require('express');
    var jwt = require('jsonwebtoken');
    var router = express.Router();
    var mailer = require('../helpers/mailer');

    var List = require('../models/lists');

    app.use('/api/lists', router);

    router.post('/', function (req, res) {
        var listData = JSON.parse(req.body.list);
        var listOwnerData = JSON.parse(req.body.owner);
        var list = new List({
            name: listData.name,
            picturePath: listData.picturePath,
            subscribers: listData.subscribers,
            owner: {
                id: listOwnerData.id,
                username: listOwnerData.username,
                email: listOwnerData.email
            }
        });
        list.save(function (err, data) {
            if (err) return console.error(err);
            res.json(data);
        });
    });

    router.get('/byuser', function (req, res) {
        var userId = req.param("userId");

        List.find({ "owner.id": userId }, function (err, data) {
            if (err) return console.error(err);

            if (data) {
                List.find({ "subscribers": { $elemMatch: { id: userId } } }, function (err2, data2) {
                    if (err2) return console.error(err2);

                    if (data2) {
                        data = data.concat(data2);
                        res.json(data)
                    } else {
                        res.json(null);
                    }
                });
            } else {
                res.json(null);
            }
        });
    });

    router.put('/', function (req, res) {
        var listData = JSON.parse(req.body.list);

        listData.invitations.forEach(function (user) {
            mailer.sendEmail('template', { email: user.email }, "Invitation to join "+listData.name+" list on Dailymumm", user.email, function () {
                console.log('invitation sent to ' + user.email);
            });
        });
        List.update({ "_id": listData.id }, {
            name: listData.name,
            picturePath: listData.picturePath,
            $push: {
                subscribers: {
                    $each: listData.invitations
                }
            }
        }, function (err, data) {
            if (err) return console.error(err);

            if (data) {
                res.json(data)
            } else {
                res.json(null);
            }
        });
    });

    router.put('/invite', function (req, res) {
        var listId = req.body.listId;
        var listOfSubscribers = JSON.parse(req.body.listOfSubscribers);

        List.update({ "_id": listId }, {
            $push: {
                subscribers: {
                    $each: listOfSubscribers
                }
            }
        }, function (err, data) {
            if (err) return console.error(err);

            if (data) {
                res.json(data)
            } else {
                res.json(null);
            }
        });
    });

    router.delete('/', function (req, res) {

    });

};<commit_msg>Fix inseting invited emails in node application<commit_after>module.exports = function (app) {
    var express = require('express');
    var jwt = require('jsonwebtoken');
    var router = express.Router();
    var mailer = require('../helpers/mailer');

    var List = require('../models/lists');

    app.use('/api/lists', router);

    router.post('/', function (req, res) {
        var listData = JSON.parse(req.body.list);
        var listOwnerData = JSON.parse(req.body.owner);
        var list = new List({
            name: listData.name,
            picturePath: listData.picturePath,
            subscribers: listData.invitations,
            owner: {
                id: listOwnerData.id,
                username: listOwnerData.username,
                email: listOwnerData.email
            }
        });
        list.save(function (err, data) {
            if (err) return console.error(err);
            res.json(data);
        });
    });

    router.get('/byuser', function (req, res) {
        var userId = req.param("userId");

        List.find({ "owner.id": userId }, function (err, data) {
            if (err) return console.error(err);

            if (data) {
                List.find({ "subscribers": { $elemMatch: { id: userId } } }, function (err2, data2) {
                    if (err2) return console.error(err2);

                    if (data2) {
                        data = data.concat(data2);
                        res.json(data)
                    } else {
                        res.json(null);
                    }
                });
            } else {
                res.json(null);
            }
        });
    });

    router.put('/', function (req, res) {
        var listData = JSON.parse(req.body.list);

        listData.invitations.forEach(function (user) {
            mailer.sendEmail('invite-user-to-list', { listname: listData.name }, "Invitation to join "+listData.name+" list on Dailymumm", user.email, function () {
                console.log('invitation sent to ' + user.email);
            });
        });
        List.update({ "_id": listData.id }, {
            name: listData.name,
            picturePath: listData.picturePath,
            $push: {
                subscribers: {
                    $each: listData.invitations
                }
            }
        }, function (err, data) {
            if (err) return console.error(err);

            if (data) {
                res.json(data)
            } else {
                res.json(null);
            }
        });
    });

    router.put('/invite', function (req, res) {
        var listId = req.body.listId;
        var listOfSubscribers = JSON.parse(req.body.listOfSubscribers);

        List.update({ "_id": listId }, {
            $push: {
                subscribers: {
                    $each: listOfSubscribers
                }
            }
        }, function (err, data) {
            if (err) return console.error(err);

            if (data) {
                res.json(data)
            } else {
                res.json(null);
            }
        });
    });

    router.delete('/', function (req, res) {

    });

};<|endoftext|>


<commit_before>

const express = require('express'),
      Post = require('../models/post')

module.exports = (() => {

'use strict';

const router = express.Router();

const postProjection = {
__v: false,
_id: false
}

router.get('/', (req, res) => {
Post.find({}, (err, posts) => {
  if (err) throw err
  if (!posts) {
    const init = new Post({
      id: 0,
      username: 'ragingbull',
      displayName: 'Raging Bull',
      date: Date.now(),
      title: 'Greetings from California State University, ' +
        'Dominguez Hills in Carson, CA!',
      body: 'This post serves as a placeholder.'
    })
    init.save(err => {
      if (err) throw err
      console.log('Sample post initialized.')
      res.json({ posts: init })
    })
  }
  else {
    console.log('Posts retrieved: ', posts)
    res.json({ posts })
  }
})
})

    /* Endpoint to provide partial list of posts based on keyword search */
    router.get('/list/:keyword', (req,res) => {
      console.log("Endpoint: Listing Posts Based on Keyword Match ")
     Post.find({body: {$regex: req.params.keyword}}, function(err, posts) {
        if (err) throw err;
        if (!posts || (posts.length<1) ) {
          console.log('Total Posts Found:  ', posts.length)
          console.log('No Post Found matching the keyword.')
          res.json({ posts })
        }
        else {
          console.log('Total Posts Found:  ', posts.length)
          console.log('')
          console.log('POSTS: ')
          console.log(' ',posts)
          res.json({ posts })
        }
      })
    });//End Endpoint

    /* Endpoint: Delete Single Post Based on  */
    /* new attempt */
    router.get('/delete/:id', (req, res) => {
          Post.remove( Post.findById(req.params.id) ,  (err, result) => {
              console.log('Endpoint: Delete Post')
                  if(err){
                    console.log('Error in delete post');
                    res.status(204).send();//No record
                  }
                  else{
                    console.log('Success in Delete Post');//, result);
                    res.status(200).send();
                    //res.json({result})
                  }
        })
    })//End of Endpoint

    /* Endpoint: Delete Many Posts Based on  */
    /* not working yet */
    /* ~TEMP~ Delete Many Posts */
    router.post('/deleteMany', (req, res) => {
      /* json data */
      var errorsInDeleting=false;
      console.log('Endpoint: Delete Many Posts')
      for(var key in req.body.deleteIds){
        var idToDelete = req.body.deleteIds[key]
        console.log('ID :  ', idToDelete )

        /* Delete One ID */
        Post.remove( Post.findById( idToDelete ) , (err, result) => {
          if(err){
            console.log('Failure (Error): Delete Post ', err);
            //res.status(204).send();//No record
          }
          if(!result){//.length<1){//} || result.length<1){
            console.log('FAIL: No Results')
            console.log('FAIL: Did Not Delete ID: ', idToDelete)
            errorsInDeleting=true;
            //res.status(204).send();//No record
          }
          else{
            console.log('Success in Delete Post');//, result);
            console.log('Deleted Post ID:', idToDelete )
            //res.status(200).send();
          }
        })

        /* try find [2] */
        // Post.find( Post.findById( idToDelete ) , function(err, posts) {
        //   if (err) throw err;
        //   if (!posts || (posts.length<1) ) {
        //     console.log('Total Posts Found:  ', posts.length)
        //     console.log('No Post Found matching the keyword.')
        //     //res.json({ posts })
        //   }
        //   else {
        //     console.log('Total Posts Found:  ', posts.length)
        //     console.log('')
        //     console.log('POSTS: ')
        //     console.log(' ',posts)
        //     Post.remove( Post.findById( idToDelete ) ,(err, result) => {} )
        //     //res.json({ posts })
        //   }
        // })
        /*  */

       } //End for
       res.json({})

    })//End Endpoint

router.post('/create', (req, res) => {

const newPost = new Post({
  user: req.body.user,
  title: req.body.title,
  body: req.body.body,
  createdOn: new Date
})

console.log("post created");
Post.create(newPost, (err) => {
  console.log(newPost)
  if (err) {
      throw err
  }
  res.status(200).send();
})
})

       // Update POST
     router.put('/update/:id', (req, res, next) => {

    console.log("EndPoint : update Post");

    Post.update(Post.findById(req.params.id),req.body, (err, result) => {

      if (err) {
        console.log("Post record doesn't exist!");
        res.status(204).send();
               }
      else{

        console.log("success");
        res.status(200).send();

          }
    })
    })

    router.get('/:id', (req, res) => {

          Post.find( Post.findById(req.params.id) ,  (err, result) => {
            console.log('Endpoint: Read Post')
                if(err){
                  console.log("Post record doesn't exist!");
                  res.status(204).send();
                }
                else{
                  console.log('Post found');
                  res.send(JSON.stringify(result));
                }
          })
        })

    return router;
})
();
<commit_msg>remove _id form endpoint List Posts<commit_after>

const express = require('express'),
      Post = require('../models/post')

module.exports = (() => {

'use strict';

const router = express.Router();

const postProjection = {
__v: false,
_id: false
}

router.get('/', (req, res) => {
Post.find({}, (err, posts) => {
  if (err) throw err
  if (!posts) {
    const init = new Post({
      id: 0,
      username: 'ragingbull',
      displayName: 'Raging Bull',
      date: Date.now(),
      title: 'Greetings from California State University, ' +
        'Dominguez Hills in Carson, CA!',
      body: 'This post serves as a placeholder.'
    })
    init.save(err => {
      if (err) throw err
      console.log('Sample post initialized.')
      res.json({ posts: init })
    })
  }
  else {
    console.log('Posts retrieved: ', posts)
    res.json({ posts })
  }
})
})

    /* Endpoint to provide partial list of posts based on keyword search */
    router.get('/list/:keyword', (req,res) => {
      console.log("Endpoint: Listing Posts Based on Keyword Match ")
      const regex = { $regex: req.params.keyword }
     Post.find( {$or: [{title: regex}, {body: regex}] },{_id: 0, user: 0}, function(err, posts) {
        if (err) throw err;
        if (!posts || (posts.length<1) ) {
          console.log('Total Posts Found:  ', posts.length)
          console.log('No Post Found matching the keyword.')
          res.json({ posts })
        }
        else {
          console.log('Total Posts Found:  ', posts.length)
          console.log('')
          console.log('POSTS: ')
          console.log(' ',posts)
          res.json({ posts })
        }
      })
    });//End Endpoint

    /* Endpoint: Delete Single Post Based on  */
    /* new attempt */
    router.get('/delete/:id', (req, res) => {
          Post.remove( Post.findById(req.params.id) ,  (err, result) => {
              console.log('Endpoint: Delete Post')
                  if(err){
                    console.log('Error in delete post');
                    res.status(204).send();//No record
                  }
                  else{
                    console.log('Success in Delete Post');//, result);
                    res.status(200).send();
                    //res.json({result})
                  }
        })
    })//End of Endpoint

    /* Endpoint: Delete Many Posts Based on  */
    router.post('/deleteMany', (req, res) => {
      /* json data */
      var errorsInDeleting=false;
      console.log('Endpoint: Delete Many Posts')
      for(var key in req.body.deleteIds){
        var idToDelete = req.body.deleteIds[key]
        console.log('ID :  ', idToDelete )

        /* Delete One ID */
        Post.remove( Post.findById( idToDelete ) , (err, result) => {
          if(err){
            console.log('Failure (Error): Delete Post ', err);
            //res.status(204).send();//No record
          }
          if(!result){//.length<1){//} || result.length<1){
            console.log('FAIL: No Results')
            console.log('FAIL: Did Not Delete ID: ', idToDelete)
            errorsInDeleting=true;
            //res.status(204).send();//No record
          }
          else{
            console.log('Success in Delete Post');//, result);
            console.log('Deleted Post ID:', idToDelete )
            //res.status(200).send();
          }
        })

        /* try find [2] */
        // Post.find( Post.findById( idToDelete ) , function(err, posts) {
        //   if (err) throw err;
        //   if (!posts || (posts.length<1) ) {
        //     console.log('Total Posts Found:  ', posts.length)
        //     console.log('No Post Found matching the keyword.')
        //     //res.json({ posts })
        //   }
        //   else {
        //     console.log('Total Posts Found:  ', posts.length)
        //     console.log('')
        //     console.log('POSTS: ')
        //     console.log(' ',posts)
        //     Post.remove( Post.findById( idToDelete ) ,(err, result) => {} )
        //     //res.json({ posts })
        //   }
        // })
        /*  */

       } //End for
       res.json({})

    })//End Endpoint

router.post('/create', (req, res) => {

const newPost = new Post({
  user: req.body.user,
  title: req.body.title,
  body: req.body.body,
  createdOn: new Date
})

console.log("post created");
Post.create(newPost, (err) => {
  console.log(newPost)
  if (err) {
      throw err
  }
  res.status(200).send();
})
})

       // Update POST
     router.put('/update/:id', (req, res, next) => {

    console.log("EndPoint : update Post");

    Post.update(Post.findById(req.params.id),req.body, (err, result) => {

      if (err) {
        console.log("Post record doesn't exist!");
        res.status(204).send();
               }
      else{

        console.log("success");
        res.status(200).send();

          }
    })
    })

    router.get('/:id', (req, res) => {

          Post.find( Post.findById(req.params.id) ,  (err, result) => {
            console.log('Endpoint: Read Post')
                if(err){
                  console.log("Post record doesn't exist!");
                  res.status(204).send();
                }
                else{
                  console.log('Post found');
                  res.send(JSON.stringify(result));
                }
          })
        })

    return router;
})
();
<|endoftext|>


<commit_before>var shell = require("shelljs/global"),
    exec = require("child_process").exec;

if (!test('-f', 'bower.json')) {
  if (!which('bower')) {
    echo('bower module not installed');
    echo('run npm install -g bower && npm install');
    echo('aborting');
    exit(1);
  } else {
    echo('installing bower components');
    exec('bower install').stdout.pipe(process.stdout);
  }
} else {
  echo('bower.json is initialised');
}

if (test('-f', 'secrets-sample.coffee') && !test('-f', 'secrets.coffee')) {
  echo('creating your very own secrets');
  cp('secrets-sample.coffee', 'secrets.coffee');
  echo('secrets.coffee created');
} else {
  echo('secrets.coffee is ready');
}

if (!test('-d', 'jspm_packages')) {
  if (!which('jspm')) {
    echo('jspm not installed');
    echo('run npm install -g jspm && npm install');
    echo('aborting');
    exit(1);
  } else {
    echo('installing jspm packages');
    exec('jspm install').stdout.pipe(process.stdout);
  }
} else {
  echo('jspm packages installed');
}

if (!test('-L', 'styleguide/src/assets/toolkit/assets')) {
  echo('symlinking styleguide assets to site assets');
  cd('styleguide/src/assets/toolkit');
  ln('-s', '../../../../src/site/templates/assets', 'assets');
  echo('assets symlinked');
} else {
  echo('styleguide correctly symlinked to site assets');
}

<commit_msg>remove installation of jspm from setup.js<commit_after>var shell = require("shelljs/global"),
    exec = require("child_process").exec;

if (!test('-f', 'bower.json')) {
  if (!which('bower')) {
    echo('bower module not installed');
    echo('run npm install -g bower && npm install');
    echo('aborting');
    exit(1);
  } else {
    echo('installing bower components');
    exec('bower install').stdout.pipe(process.stdout);
  }
} else {
  echo('bower.json is initialised');
}

if (test('-f', 'secrets-sample.coffee') && !test('-f', 'secrets.coffee')) {
  echo('creating your very own secrets');
  cp('secrets-sample.coffee', 'secrets.coffee');
  echo('secrets.coffee created');
} else {
  echo('secrets.coffee is ready');
}

if (!test('-L', 'styleguide/src/assets/toolkit/assets')) {
  echo('symlinking styleguide assets to site assets');
  cd('styleguide/src/assets/toolkit');
  ln('-s', '../../../../src/site/templates/assets', 'assets');
  echo('assets symlinked');
} else {
  echo('styleguide correctly symlinked to site assets');
}

<|endoftext|>


<commit_before>var translations = {};
var general = {
  'save': 'Save',
  'done': 'Done',
  'edit': 'Edit',
  'published': 'Published',
  'notPublished': 'Not Published',
  'competencies': 'Competencies',
  'objectives': 'Objectives',
  'directors': 'Directors',
  'status': 'Status',
  'title': 'Title',
  'competency': 'Competency',
  'actions': 'Actions',
  'topics': 'Topics',
  'meshTerms': 'MeSH Terms'
};
translations.general = general;

var programs = {
  'allPrograms': 'All Programs',
  'programs': 'Programs',
  'program': {
    'title': 'Program Title',
    'shortTitle': 'Short Title',
    'duration': 'Duration',
    'durationYears.one': '1 year',
    'durationYears.other': '{{count}} years',
    'editingProgram': 'Editing {{title}}',
    'createNew': 'Create a New Program'
  },
  'programYear': {
    'academicYear': 'Academic Year',
    'createNew': 'Create a New Program Year',
    'addDirector': 'Add Director',
    'removeDirector': 'Remove Director',
    'addCompetency': 'Add Competency',
    'removeCompetency': 'Remove Competency',
    'addTopic': 'Add Topic',
    'removeTopic': 'Remove Topic',
    'stewardingSchools': 'Stewarding Schools',
    'objectives': {
      'showFullTitle': 'Show Full Title Text',
      'new': 'Crete a new objective'
    },
    'competencies': {
      'available': 'Available Competencies',
      'selected': 'Selected Competencies'
    },
    'topics': {
      'available': 'Available Topics',
      'selected': 'Selected Topics'
    },
    'stewardingSchool': {
      'available': 'Available Schools',
      'selected': 'Selected Schools'
    },
    'directors': {
      'available': 'Available Directors',
      'selected': 'Selected Directors',
      'noResults': 'Your seach returned no results.',
      'search': 'Search for directors'
    }
  }
};
translations.programs = programs;

var navigation = {
  'dashboard': 'Dashboard',
  'programs': 'Programs',
  'instructors': 'Instructors',
  'learnerGroups': 'Learner Group',
  'coursesSessions': 'Courses and Sessions',
  'logout': 'Logout',
  'logo': 'Ilios Logo'
};
translations.navigation = navigation;

var mesh = {
  'buttonTitle': 'Add MeSH ({{count}})',
  'pickerTitle': 'Choose MeSH Terms',
  'selected': 'Selected MeSH Terms',
  'available': 'Available MeSH Terms',
  'search': 'Search MeSH Terms',
  'noResults': 'Your seach returned no results.',
};
translations.mesh = mesh;

export default translations;
<commit_msg>Change mesh button title<commit_after>var translations = {};
var general = {
  'save': 'Save',
  'done': 'Done',
  'edit': 'Edit',
  'published': 'Published',
  'notPublished': 'Not Published',
  'competencies': 'Competencies',
  'objectives': 'Objectives',
  'directors': 'Directors',
  'status': 'Status',
  'title': 'Title',
  'competency': 'Competency',
  'actions': 'Actions',
  'topics': 'Topics',
  'meshTerms': 'MeSH Terms'
};
translations.general = general;

var programs = {
  'allPrograms': 'All Programs',
  'programs': 'Programs',
  'program': {
    'title': 'Program Title',
    'shortTitle': 'Short Title',
    'duration': 'Duration',
    'durationYears.one': '1 year',
    'durationYears.other': '{{count}} years',
    'editingProgram': 'Editing {{title}}',
    'createNew': 'Create a New Program'
  },
  'programYear': {
    'academicYear': 'Academic Year',
    'createNew': 'Create a New Program Year',
    'addDirector': 'Add Director',
    'removeDirector': 'Remove Director',
    'addCompetency': 'Add Competency',
    'removeCompetency': 'Remove Competency',
    'addTopic': 'Add Topic',
    'removeTopic': 'Remove Topic',
    'stewardingSchools': 'Stewarding Schools',
    'objectives': {
      'showFullTitle': 'Show Full Title Text',
      'new': 'Crete a new objective'
    },
    'competencies': {
      'available': 'Available Competencies',
      'selected': 'Selected Competencies'
    },
    'topics': {
      'available': 'Available Topics',
      'selected': 'Selected Topics'
    },
    'stewardingSchool': {
      'available': 'Available Schools',
      'selected': 'Selected Schools'
    },
    'directors': {
      'available': 'Available Directors',
      'selected': 'Selected Directors',
      'noResults': 'Your seach returned no results.',
      'search': 'Search for directors'
    }
  }
};
translations.programs = programs;

var navigation = {
  'dashboard': 'Dashboard',
  'programs': 'Programs',
  'instructors': 'Instructors',
  'learnerGroups': 'Learner Group',
  'coursesSessions': 'Courses and Sessions',
  'logout': 'Logout',
  'logo': 'Ilios Logo'
};
translations.navigation = navigation;

var mesh = {
  'buttonTitle': 'Select MeSH ({{count}})',
  'pickerTitle': 'Choose MeSH Terms',
  'selected': 'Selected MeSH Terms',
  'available': 'Available MeSH Terms',
  'search': 'Search MeSH Terms',
  'noResults': 'Your seach returned no results.',
};
translations.mesh = mesh;

export default translations;
<|endoftext|>


<commit_before>// @flow

import 'isomorphic-fetch';

export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';

export class HttpError extends Error {
  response: Response;
}

export type HttpResponse<T> = {
  jsonData?: ?T,
  textString?: ?string
} & Response;

export type HttpRequestOptions = {
  method?: HttpMethod,
  headers: { [key: string]: string },
  body?: Object | string,
  json?: boolean,
  files?: Array<string>,
  timeout?: number,
  retryDelays?: Array<number>
};

function parseResponseBody<T>(
  response: HttpResponse<T>
): Promise<HttpResponse<T>> {
  return response.text().then(textString => {
    const contentType =
      response.headers.get('content-type') || 'application/json';

    if (contentType.includes('application/json') && textString) {
      response.jsonData = (JSON.parse(textString): T);
    }

    response.textString = textString;
    return response;
  });
}

function rejectOnHttpErrors(response: HttpResponse<*>) {
  if (response.ok) {
    return response;
  }

  const error = new HttpError(`HTTP ${response.status}`);
  error.response = response;
  throw error;
}

export function stringifyBody(requestOptions: HttpRequestOptions) {
  const { body, json } = requestOptions;

  if (typeof body === 'string') {
    return body;
  }

  if (typeof body === 'object' && json !== false) {
    return JSON.stringify(body);
  }

  return null;
}

function makeFormData(files, rawBody) {
  const body = new FormData();

  if (rawBody && typeof rawBody === 'object') {
    const object: { [key: string]: string } = rawBody;
    Object.keys(object).forEach(prop => {
      body.append(prop, object[prop]);
    });
  }

  body.append('file', files[0]);
  return body;
}

function timeoutPromise(ms = 0) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  }).then(() => {
    throw new Error('HTTP request timed out.');
  });
}

const defaultOptions = {
  files: [],
  retryDelays: [1000, 3000],
  timeout: 15000,
  headers: {}
};

export default function fetchJSON<T>(
  path: string,
  requestOptions: HttpRequestOptions = defaultOptions
): Promise<HttpResponse<T>> {
  const { files } = requestOptions;
  let body;
  if (files && files.length > 0) {
    body = makeFormData(files, requestOptions.body);
  } else {
    body = stringifyBody(requestOptions);
    requestOptions.headers['Content-Type'] = 'application/json';
  }

  const createRequest = () =>
    new Request(path, {
      ...requestOptions,
      body,
      headers: new Headers({
        Accept: 'application/json',
        ...requestOptions.headers
      })
    });

  return new Promise((resolve, reject) => {
    let requestsAttempted = 0;

    const wrappedFetch = () => {
      const request = createRequest();
      requestsAttempted++;
      return Promise.race([
        timeoutPromise(requestOptions.timeout),
        fetch(request)
          .then(parseResponseBody)
          .then(rejectOnHttpErrors)
          .then(resolve)
      ]).catch((error: HttpError) => {
        if (
          (error.response && error.response.status < 500) ||
          !requestOptions.retryDelays ||
          requestsAttempted > requestOptions.retryDelays.length ||
          !__CLIENT__
        ) {
          return reject(error);
        }

        setTimeout(
          wrappedFetch,
          requestOptions.retryDelays[requestsAttempted - 1]
        );
      });
    };

    return wrappedFetch();
  });
}
<commit_msg>Fix requests thinking they time out<commit_after>// @flow

import 'isomorphic-fetch';

export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';

export class HttpError extends Error {
  response: Response;
}

export type HttpResponse<T> = {
  jsonData?: ?T,
  textString?: ?string
} & Response;

export type HttpRequestOptions = {
  method?: HttpMethod,
  headers: { [key: string]: string },
  body?: Object | string,
  json?: boolean,
  files?: Array<string>,
  timeout?: number,
  retryDelays?: Array<number>
};

function parseResponseBody<T>(
  response: HttpResponse<T>
): Promise<HttpResponse<T>> {
  return response.text().then(textString => {
    const contentType =
      response.headers.get('content-type') || 'application/json';

    if (contentType.includes('application/json') && textString) {
      response.jsonData = (JSON.parse(textString): T);
    }

    response.textString = textString;
    return response;
  });
}

function rejectOnHttpErrors(response: HttpResponse<*>) {
  if (response.ok) {
    return response;
  }

  const error = new HttpError(`HTTP ${response.status}`);
  error.response = response;
  throw error;
}

export function stringifyBody(requestOptions: HttpRequestOptions) {
  const { body, json } = requestOptions;

  if (typeof body === 'string') {
    return body;
  }

  if (typeof body === 'object' && json !== false) {
    return JSON.stringify(body);
  }

  return null;
}

function makeFormData(files, rawBody) {
  const body = new FormData();

  if (rawBody && typeof rawBody === 'object') {
    const object: { [key: string]: string } = rawBody;
    Object.keys(object).forEach(prop => {
      body.append(prop, object[prop]);
    });
  }

  body.append('file', files[0]);
  return body;
}

function timeoutPromise(ms = 0) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  }).then(() => {
    throw new Error('HTTP request timed out.');
  });
}

const defaultOptions = {
  files: [],
  headers: {}
};

export default function fetchJSON<T>(
  path: string,
  requestOptions: HttpRequestOptions = defaultOptions
): Promise<HttpResponse<T>> {
  const { files, retryDelays = [1000, 3000], timeout = 15000 } = requestOptions;
  let body;
  if (files && files.length > 0) {
    body = makeFormData(files, requestOptions.body);
  } else {
    body = stringifyBody(requestOptions);
    requestOptions.headers['Content-Type'] = 'application/json';
  }

  const createRequest = () =>
    new Request(path, {
      ...requestOptions,
      body,
      headers: new Headers({
        Accept: 'application/json',
        ...requestOptions.headers
      })
    });

  return new Promise((resolve, reject) => {
    let requestsAttempted = 0;

    const wrappedFetch = () => {
      const request = createRequest();
      requestsAttempted++;
      return Promise.race([
        timeoutPromise(timeout),
        fetch(request)
          .then(parseResponseBody)
          .then(rejectOnHttpErrors)
          .then(resolve)
      ]).catch((error: HttpError) => {
        if (
          (error.response && error.response.status < 500) ||
          !retryDelays ||
          requestsAttempted > retryDelays.length ||
          !__CLIENT__
        ) {
          return reject(error);
        }

        setTimeout(
          wrappedFetch,
          retryDelays[requestsAttempted - 1]
        );
      });
    };

    return wrappedFetch();
  });
}
<|endoftext|>


<commit_before>import BaseValidator from './base';
import moment from 'moment';
import validator from 'npm:validator';
import {isBlank, isEmpty, isPresent} from '@ember/utils';

export default BaseValidator.create({
    properties: [
        'title',
        'customExcerpt',
        'codeinjectionHead',
        'codeinjectionFoot',
        'metaTitle',
        'metaDescription',
        'ogtitle',
        'ogDescription',
        'twitterTitle',
        'twitterDescription',
        'publishedAtBlogTime',
        'publishedAtBlogDate'
    ],

    title(model) {
        let title = model.get('title');

        if (isBlank(title)) {
            model.get('errors').add('title', 'You must specify a title for the post.');
            this.invalidate();
        }

        if (!validator.isLength(title || '', 0, 255)) {
            model.get('errors').add('title', 'Title cannot be longer than 255 characters.');
            this.invalidate();
        }
    },

    customExcerpt(model) {
        let customExcerpt = model.get('customExcerpt');

        if (!validator.isLength(customExcerpt || '', 0, 300)) {
            model.get('errors').add('customExcerpt', 'Excerpt cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    codeinjectionFoot(model) {
        let codeinjectionFoot = model.get('codeinjectionFoot');

        if (!validator.isLength(codeinjectionFoot, 0, 65535)) {
            model.get('errors').add('codeinjectionFoot', 'Footer code cannot be longer than 65535 characters.');
            this.invalidate();
        }
    },

    codeinjectionHead(model) {
        let codeinjectionHead = model.get('codeinjectionHead');

        if (!validator.isLength(codeinjectionHead || '', 0, 65535)) {
            model.get('errors').add('codeinjectionHead', 'Header code cannot be longer than 65535 characters.');
            this.invalidate();
        }
    },

    metaTitle(model) {
        let metaTitle = model.get('metaTitle');

        if (!validator.isLength(metaTitle || '', 0, 300)) {
            model.get('errors').add('metaTitle', 'Meta Title cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    metaDescription(model) {
        let metaDescription = model.get('metaDescription');

        if (!validator.isLength(metaDescription || '', 0, 500)) {
            model.get('errors').add('metaDescription', 'Meta Description cannot be longer than 500 characters.');
            this.invalidate();
        }
    },

    ogTitle(model) {
        let ogTitle = model.get('ogTitle');

        if (!validator.isLength(ogTitle || '', 0, 300)) {
            model.get('errors').add('ogTitle', 'Facebook Title cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    ogDescription(model) {
        let ogDescription = model.get('ogDescription');

        if (!validator.isLength(ogDescription || '', 0, 500)) {
            model.get('errors').add('ogDescription', 'Facebook Description cannot be longer than 500 characters.');
            this.invalidate();
        }
    },

    twitterTitle(model) {
        let twitterTitle = model.get('twitterTitle');

        if (!validator.isLength(twitterTitle || '', 0, 300)) {
            model.get('errors').add('twitterTitle', 'Twitter Title cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    twitterDescription(model) {
        let twitterDescription = model.get('twitterDescription');

        if (!validator.isLength(twitterDescription || '', 0, 500)) {
            model.get('errors').add('twitterDescription', 'Twitter Description cannot be longer than 500 characters.');
            this.invalidate();
        }
    },
    // for posts which haven't been published before and where the blog date/time
    // is blank we should ignore the validation
    _shouldValidatePublishedAtBlog(model) {
        let publishedAtUTC = model.get('publishedAtUTC');
        let publishedAtBlogDate = model.get('publishedAtBlogDate');
        let publishedAtBlogTime = model.get('publishedAtBlogTime');

        return isPresent(publishedAtUTC)
            || isPresent(publishedAtBlogDate)
            || isPresent(publishedAtBlogTime);
    },

    // convenience method as .validate({property: 'x'}) doesn't accept multiple properties
    publishedAtBlog(model) {
        this.publishedAtBlogTime(model);
        this.publishedAtBlogDate(model);
    },

    publishedAtBlogTime(model) {
        let publishedAtBlogTime = model.get('publishedAtBlogTime');
        let timeRegex = /^(([0-1]?[0-9])|([2][0-3])):([0-5][0-9])$/;

        if (!timeRegex.test(publishedAtBlogTime) && this._shouldValidatePublishedAtBlog(model)) {
            model.get('errors').add('publishedAtBlogTime', 'Must be in format: "15:00"');
            this.invalidate();
        }
    },

    publishedAtBlogDate(model) {
        let publishedAtBlogDate = model.get('publishedAtBlogDate');
        let publishedAtBlogTime = model.get('publishedAtBlogTime');

        if (!this._shouldValidatePublishedAtBlog(model)) {
            return;
        }

        // we have a time string but no date string
        if (isBlank(publishedAtBlogDate) && !isBlank(publishedAtBlogTime)) {
            model.get('errors').add('publishedAtBlogDate', 'Can\'t be blank');
            return this.invalidate();
        }

        // don't validate the date if the time format is incorrect
        if (isEmpty(model.get('errors').errorsFor('publishedAtBlogTime'))) {
            let status = model.get('statusScratch') || model.get('status');
            let now = moment();
            let publishedAtUTC = model.get('publishedAtUTC');
            let publishedAtBlogTZ = model.get('publishedAtBlogTZ');
            let matchesExisting = publishedAtUTC && publishedAtBlogTZ.isSame(publishedAtUTC);
            let isInFuture = publishedAtBlogTZ.isSameOrAfter(now.add(2, 'minutes'));

            // draft/published must be in past
            if ((status === 'draft' || status === 'published') && publishedAtBlogTZ.isSameOrAfter(now)) {
                model.get('errors').add('publishedAtBlogDate', 'Must be in the past');
                this.invalidate();

            // scheduled must be at least 2 mins in the future
            // ignore if it matches publishedAtUTC as that is likely an update of a scheduled post
            } else if (status === 'scheduled' && !matchesExisting && !isInFuture) {
                model.get('errors').add('publishedAtBlogDate', 'Must be at least 2 mins in the future');
                this.invalidate();
            }
        }
    }
});
<commit_msg>Fixed validator error when saving posts with no code injection footer<commit_after>import BaseValidator from './base';
import moment from 'moment';
import validator from 'npm:validator';
import {isBlank, isEmpty, isPresent} from '@ember/utils';

export default BaseValidator.create({
    properties: [
        'title',
        'customExcerpt',
        'codeinjectionHead',
        'codeinjectionFoot',
        'metaTitle',
        'metaDescription',
        'ogtitle',
        'ogDescription',
        'twitterTitle',
        'twitterDescription',
        'publishedAtBlogTime',
        'publishedAtBlogDate'
    ],

    title(model) {
        let title = model.get('title');

        if (isBlank(title)) {
            model.get('errors').add('title', 'You must specify a title for the post.');
            this.invalidate();
        }

        if (!validator.isLength(title || '', 0, 255)) {
            model.get('errors').add('title', 'Title cannot be longer than 255 characters.');
            this.invalidate();
        }
    },

    customExcerpt(model) {
        let customExcerpt = model.get('customExcerpt');

        if (!validator.isLength(customExcerpt || '', 0, 300)) {
            model.get('errors').add('customExcerpt', 'Excerpt cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    codeinjectionFoot(model) {
        let codeinjectionFoot = model.get('codeinjectionFoot');

        if (!validator.isLength(codeinjectionFoot || '', 0, 65535)) {
            model.get('errors').add('codeinjectionFoot', 'Footer code cannot be longer than 65535 characters.');
            this.invalidate();
        }
    },

    codeinjectionHead(model) {
        let codeinjectionHead = model.get('codeinjectionHead');

        if (!validator.isLength(codeinjectionHead || '', 0, 65535)) {
            model.get('errors').add('codeinjectionHead', 'Header code cannot be longer than 65535 characters.');
            this.invalidate();
        }
    },

    metaTitle(model) {
        let metaTitle = model.get('metaTitle');

        if (!validator.isLength(metaTitle || '', 0, 300)) {
            model.get('errors').add('metaTitle', 'Meta Title cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    metaDescription(model) {
        let metaDescription = model.get('metaDescription');

        if (!validator.isLength(metaDescription || '', 0, 500)) {
            model.get('errors').add('metaDescription', 'Meta Description cannot be longer than 500 characters.');
            this.invalidate();
        }
    },

    ogTitle(model) {
        let ogTitle = model.get('ogTitle');

        if (!validator.isLength(ogTitle || '', 0, 300)) {
            model.get('errors').add('ogTitle', 'Facebook Title cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    ogDescription(model) {
        let ogDescription = model.get('ogDescription');

        if (!validator.isLength(ogDescription || '', 0, 500)) {
            model.get('errors').add('ogDescription', 'Facebook Description cannot be longer than 500 characters.');
            this.invalidate();
        }
    },

    twitterTitle(model) {
        let twitterTitle = model.get('twitterTitle');

        if (!validator.isLength(twitterTitle || '', 0, 300)) {
            model.get('errors').add('twitterTitle', 'Twitter Title cannot be longer than 300 characters.');
            this.invalidate();
        }
    },

    twitterDescription(model) {
        let twitterDescription = model.get('twitterDescription');

        if (!validator.isLength(twitterDescription || '', 0, 500)) {
            model.get('errors').add('twitterDescription', 'Twitter Description cannot be longer than 500 characters.');
            this.invalidate();
        }
    },
    // for posts which haven't been published before and where the blog date/time
    // is blank we should ignore the validation
    _shouldValidatePublishedAtBlog(model) {
        let publishedAtUTC = model.get('publishedAtUTC');
        let publishedAtBlogDate = model.get('publishedAtBlogDate');
        let publishedAtBlogTime = model.get('publishedAtBlogTime');

        return isPresent(publishedAtUTC)
            || isPresent(publishedAtBlogDate)
            || isPresent(publishedAtBlogTime);
    },

    // convenience method as .validate({property: 'x'}) doesn't accept multiple properties
    publishedAtBlog(model) {
        this.publishedAtBlogTime(model);
        this.publishedAtBlogDate(model);
    },

    publishedAtBlogTime(model) {
        let publishedAtBlogTime = model.get('publishedAtBlogTime');
        let timeRegex = /^(([0-1]?[0-9])|([2][0-3])):([0-5][0-9])$/;

        if (!timeRegex.test(publishedAtBlogTime) && this._shouldValidatePublishedAtBlog(model)) {
            model.get('errors').add('publishedAtBlogTime', 'Must be in format: "15:00"');
            this.invalidate();
        }
    },

    publishedAtBlogDate(model) {
        let publishedAtBlogDate = model.get('publishedAtBlogDate');
        let publishedAtBlogTime = model.get('publishedAtBlogTime');

        if (!this._shouldValidatePublishedAtBlog(model)) {
            return;
        }

        // we have a time string but no date string
        if (isBlank(publishedAtBlogDate) && !isBlank(publishedAtBlogTime)) {
            model.get('errors').add('publishedAtBlogDate', 'Can\'t be blank');
            return this.invalidate();
        }

        // don't validate the date if the time format is incorrect
        if (isEmpty(model.get('errors').errorsFor('publishedAtBlogTime'))) {
            let status = model.get('statusScratch') || model.get('status');
            let now = moment();
            let publishedAtUTC = model.get('publishedAtUTC');
            let publishedAtBlogTZ = model.get('publishedAtBlogTZ');
            let matchesExisting = publishedAtUTC && publishedAtBlogTZ.isSame(publishedAtUTC);
            let isInFuture = publishedAtBlogTZ.isSameOrAfter(now.add(2, 'minutes'));

            // draft/published must be in past
            if ((status === 'draft' || status === 'published') && publishedAtBlogTZ.isSameOrAfter(now)) {
                model.get('errors').add('publishedAtBlogDate', 'Must be in the past');
                this.invalidate();

            // scheduled must be at least 2 mins in the future
            // ignore if it matches publishedAtUTC as that is likely an update of a scheduled post
            } else if (status === 'scheduled' && !matchesExisting && !isInFuture) {
                model.get('errors').add('publishedAtBlogDate', 'Must be at least 2 mins in the future');
                this.invalidate();
            }
        }
    }
});
<|endoftext|>


<commit_before>import $ from "jquery";

const gutter = 16;

class Tooltip {
  constructor(el) {
    this.$el = $(el);
    this.$target = this.$el.find(".tooltip-content");
    this.initBindings();
  }

  initBindings() {
    this.$el.on("click", (e) => {
      e.preventDefault();
      this.$target.toggleClass("open");
      this.checkOverflow();
    });
  }

  checkOverflow() {
    this.reset();

    let windowWidth = $(window).width();
    let windowHeight = $(window).height();

    let left = this.$target.offset().left;
    let right = left + this.$target.outerWidth();
    let top = this.$target.offset().top;
    let bottom = top + this.$target.outerWidth();

    if (left < gutter) {
      this.fixOverflow(left - gutter);
    }
    if (right > (windowWidth - gutter)) {
      this.fixOverflow(right - windowWidth + gutter);
    }
    if (bottom > (windowHeight - gutter)) {
      this.$target.addClass("tooltip-up");
    }
  }

  fixOverflow(offset) {
    this.$target.css("left", `calc(50% - ${offset}px)`);
  }

  reset() {
    this.$target.attr("style", "");
  }
}

export default Tooltip;
<commit_msg>Probably shouldn't hide tooltips outside window<commit_after>import $ from "jquery";

const gutter = 16;

class Tooltip {
  constructor(el) {
    this.$el = $(el);
    this.$target = this.$el.find(".tooltip-content");
    this.initBindings();
  }

  initBindings() {
    this.$el.on("click", (e) => {
      e.preventDefault();
      this.$target.toggleClass("open");
      this.checkOverflow();
    });
  }

  checkOverflow() {
    this.reset();

    let windowWidth = $(window).width();
    let windowHeight = $(window).height();

    let left = this.$target.offset().left;
    let right = left + this.$target.outerWidth();
    let top = this.$target.offset().top;
    let bottom = top + this.$target.outerWidth();

    if (left < gutter) {
      this.fixOverflow(left - gutter);
    }
    if (right > (windowWidth - gutter)) {
      this.fixOverflow(right - windowWidth + gutter);
    }
    if (bottom > (windowHeight + gutter)) {
      this.$target.addClass("tooltip-up");
    }
  }

  fixOverflow(offset) {
    this.$target.css("left", `calc(50% - ${offset}px)`);
  }

  reset() {
    this.$target.attr("style", "");
  }
}

export default Tooltip;
<|endoftext|>


<commit_before>var chalk = require('chalk');
var Promise = require('bluebird');
var Twitter = require('twitter');
var path = require('path');

var tweetFilter = require('./filter');
var streamError = require('./error');

var env = require(path.join(__dirname, '../env'));

var client = new Twitter({
  consumer_key: env.STREAM.consumer_key,
  consumer_secret: env.STREAM.consumer_secret,
  access_token_key: env.STREAM.access_token_key,
  access_token_secret: env.STREAM.access_token_secret
});

var streamParameters = {
  follow: env.STREAM_IDS.AP
};

client.stream('statuses/filter', streamParameters, function(stream) {
  stream.on('data', tweetFilter);
  stream.on('error', streamError);
});
<commit_msg>Created seperate streams for news and seed stories. Added parameters for news sources to stream<commit_after>var chalk = require('chalk');
var Promise = require('bluebird');
var Twitter = require('twitter');
var path = require('path');

var seedFilter = require('./filters/seed');
var newsFilter = require('./filters/news');
var streamError = require('./error');

var env = require(path.join(__dirname, '../env'));

var client = new Twitter({
  consumer_key: env.STREAM.consumer_key,
  consumer_secret: env.STREAM.consumer_secret,
  access_token_key: env.STREAM.access_token_key,
  access_token_secret: env.STREAM.access_token_secret
});

var seedStreamParameters = {
  follow: env.STREAM_IDS.AP
};

var newsStreamParameters = {
  follow: env.STREAM_IDS.NYT
};

client.stream('statuses/filter', seedStreamParameters, function(stream) {
  stream.on('data', seedFilter);
  stream.on('error', streamError);
});

client.stream('statuses/filter', newsStreamParameters, function(stream) {
  stream.on('data', newsFilter);
  stream.on('error', streamError);
});
<|endoftext|>


<commit_before>exports.post = function(request, response) {
    var tables = request.service.tables;
    var push = request.service.push;
    var todoItems = tables.getTable('TodoItem');
    response.send(statusCodes.OK, { message : 'Hello World!' });
};
<commit_msg>Committing update from request /api/scmvfs/service/api/overdue.js<commit_after>exports.post = function(request, response) {
    var tables = request.service.tables;
    var push = request.service.push;
    var todoItems = tables.getTable('TodoItem');
    todoItems.read( {
        success: markOverdue
        });

    function markOverdue(results) {
        results.forEach(function(item) {
            if(item.)
        });
    }
    response.send(statusCodes.OK, { message : 'Hello World!' });
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  'use strict';

  var path = require('path');
  var MessageFormat = require('messageformat');
  var EOL = require('os').EOL;

  grunt.registerMultiTask('messages', 'Compile messages!', function() {
    this.files.forEach(function(filePair) {
      filePair.src.forEach(function(src) {
        var locale = path.basename(src, '.json');
        var namespace = src.indexOf('common') > -1 ? 'locale' : 'appLocale';
        var formatted = process(locale, namespace, grunt.file.readJSON(src));
        grunt.file.write(filePair.dest, formatted);
      });
    });
  });

  function process(locale, namespace, json) {
    var mf;
    try {
      mf = new MessageFormat(locale, false, namespace);
    } catch (e) {
      // Fallback to en if locale is not found
      if(locale != 'en') {
        return process('en', namespace, json);
      } else {
        throw e;
      }
    }

    return [
      'var ' + namespace + ' = ' + mf.functions() + ';',
      '(window.blockly = window.blockly || {}).' + namespace + ' = ' + mf.precompileObject(json) + ';'
    ].join(EOL);
  }

};
<commit_msg>Log errors from 'grunt messages' processing. Use `grunt messages --force` to process all messages<commit_after>module.exports = function(grunt) {
  'use strict';

  var path = require('path');
  var MessageFormat = require('messageformat');
  var EOL = require('os').EOL;

  grunt.registerMultiTask('messages', 'Compile messages!', function() {
    this.files.forEach(function(filePair) {
      filePair.src.forEach(function(src) {
        var locale = path.basename(src, '.json');
        var namespace = src.indexOf('common') > -1 ? 'locale' : 'appLocale';
        try {
          var formatted = process(locale, namespace, grunt.file.readJSON(src));
          grunt.file.write(filePair.dest, formatted);
        } catch (e) {
          var errorMsg = "Error processing localization file " + src + ": " + e;
          if(grunt.option('force')) {
            grunt.log.warn(errorMsg)
          } else {
            throw new Error(errorMsg);
          }
        }
      });
    });
  });

  function process(locale, namespace, json) {
    var mf;
    try {
      mf = new MessageFormat(locale, false, namespace);
    } catch (e) {
      // Fallback to en if locale is not found
      if(locale != 'en') {
        return process('en', namespace, json);
      } else {
        throw e;
      }
    }

    return [
      'var ' + namespace + ' = ' + mf.functions() + ';',
      '(window.blockly = window.blockly || {}).' + namespace + ' = ' + mf.precompileObject(json) + ';'
    ].join(EOL);
  }

};
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const diff = require('diff')
const { bibertool } = require('./bibertool')
const pegjs = require('pegjs')
const shell = require('shelljs')
const { filePathFilter } = require('file-path-filter')
const esbuild = require('esbuild')
const putout = require('putout')

function load_patches(dir) {
  const patches = {}
  for (let patchfile of fs.readdirSync(dir)) {
    for (const patch of diff.parsePatch(fs.readFileSync(path.join(dir, patchfile), 'utf-8'))) {
      if (patch.oldFileName != patch.newFileName) throw new Error(`${patchfile} renames ${JSON.stringify(patch.oldFileName)} to ${JSON.stringify(patch.newFileName)}`)
      if (patches[patch.oldFileName]) throw new Error(`${patchfile} re-patches ${JSON.stringify(patch.oldFileName)}`)
      if (!patch.oldFileName.startsWith('node_modules/')) throw new Error(`${patchfile} patches ${JSON.stringify(patch.oldFileName)} outside node_modules`)
      patches[patch.oldFileName] = patch
    }
  }
  return patches
}

module.exports.patcher = function(dir) {
  const patches = load_patches(dir)
  const filter = '.*\\/(' + Object.keys(patches).map(source => source.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') + ')$'

  return {
    name: 'patcher',
    setup(build) {
      build.onLoad({ filter: new RegExp(filter) }, async (args) => {
        const target = args.path.replace(/.*[/]node_modules[/]/, 'node_modules/')
        console.log('  patching', target)
        const source = await fs.promises.readFile(args.path, 'utf-8')
        const patch = patches[target]

        return {
          contents: diff.applyPatch(source, patch),
          loader: 'js',
        }
      })
    }
  }
}

module.exports.bibertool = {
  name: 'bibertool',
  setup(build) {
    build.onLoad({ filter: /\/biber-tool\.conf$/ }, async (args) => {
      return {
        contents: bibertool(await fs.promises.readFile(args.path, 'utf-8')),
        loader: 'js'
      }
    })
  }
}

module.exports.pegjs = {
  name: 'pegjs',
  setup(build) {
    build.onLoad({ filter: /\.pegjs$/ }, async (args) => {
      return {
        contents: pegjs.generate(await fs.promises.readFile(args.path, 'utf-8'), {
          output: 'source',
          cache: false,
          optimize: 'speed',
          trace: false,
          format: 'commonjs',
        }),
        loader: 'js'
      }
    })
  }
}

module.exports.__dirname = {
  name: '__dirname',
  setup(build) {
    build.onLoad({ filter: /\/node_modules\/.+\.js$/ }, async (args) => {
      let contents = await fs.promises.readFile(args.path, 'utf-8')
      const filename = 'resource://zotero-better-bibtex/' + args.path.replace(/.*\/node_modules\/(\.pnpm)?/, '')
      const dirname = path.dirname(filename)

      contents = [
        `var __dirname=${JSON.stringify(dirname)};`,
        `var __filename=${JSON.stringify(filename)};`,
        contents,
      ].join('\n')

      return {
        contents,
        loader: 'js'
      }
    })
  }
}

function modulename(source) {
  source = source.replace(/.*(^|\/)node_modules\//, '')
  if (source[0] === '.') return null
  const dirs = source.split('/')

  if (dirs[0][0] === '@') {
    return dirs.unshift(2).join('/')
  }
  else {
    return dirs[0]
  }
}
module.exports.modulename = modulename
module.exports.node_modules = function(dir) {
  const patched = [...new Set(Object.keys(load_patches(dir)).map(modulename))]
  const external = []

  return {
    patched,
    external,
    // plugin: nodeExternalsPlugin({ allowList: patched }),
    plugin: {
      name: 'node-externals',
      setup(build) {
        build.onResolve({ namespace: 'file', filter: /.*/ }, args => {
          const name = modulename(args.path)
          if (!name || patched.includes(name)) return null
          if (!external.includes(name)) external.push(name)
          return { path: args.path, external: true }
        })
      }
    }
  }
}

let selected_for_trace = false
if (fs.existsSync(path.join(__dirname, '../../.trace.json'))) {
  const branch = (process.env.GITHUB_REF && process.env.GITHUB_REF.startsWith('refs/heads/')) ? process.env.GITHUB_REF.replace('refs/heads/', '') : shell.exec('git rev-parse --abbrev-ref HEAD', { silent: true }).stdout.trim()
  console.log('building on', branch)
  if (branch !== 'master' && branch !== 'main') {
    let trace = require('../../.trace.json')
    trace = trace[branch]
    console.log(`instrumenting ${branch}: ${!!trace}`)
    if (trace) selected_for_trace = filePathFilter(trace)
  }
}

const prefix = fs.readFileSync(path.join(__dirname, 'trace.js'), 'utf-8')

module.exports.trace = {
  name: 'trace',
  setup(build) {
    build.onLoad({ filter: /\.ts$/ }, async (args) => {
      if (!selected_for_trace) return null

      const source = await esbuild.transform(await fs.promises.readFile(args.path, 'utf-8'), { loader: 'ts' })
      for (const warning of source.warnings) {
        console.log('!!', warning)
      }

      const localpath = path.relative(process.cwd(), args.path)

      // inject __estrace so sources can tell an instrumented build is active even if not on the current source
      if (!selected_for_trace(localpath)) {
        const contents = `const __estrace = true;\n${source.code}`
        return {
          contents,
          loader: 'js',
        }
      }

      console.log(`!!!!!!!!!!!!!! Instrumenting ${localpath} for trace logging !!!!!!!!!!!!!`)

      try {
        const tracer = await import('estrace/plugin');
        const {code} = putout(source.code, {
          fixCount: 1,
          rules: {
            tracer: ['on', { url: localpath.replace(/\.ts$/, '') }],
          },
          plugins: [
            ['tracer', tracer],
          ],
        })
        const contents = prefix + code

        return {
          contents,
          loader: 'js',
        }
      }
      catch (err) {
        await fs.promises.writeFile('/tmp/tt', `/* ${localpath.replace(/\.ts$/, '')}\n${err.stack}\n*/\n/${source.code}`)
        throw err
      }

    })
  }
}

<commit_msg>completely disable tracing when not a tracing branch<commit_after>const fs = require('fs')
const path = require('path')
const diff = require('diff')
const { bibertool } = require('./bibertool')
const pegjs = require('pegjs')
const shell = require('shelljs')
const { filePathFilter } = require('file-path-filter')
const esbuild = require('esbuild')
const putout = require('putout')

function load_patches(dir) {
  const patches = {}
  for (let patchfile of fs.readdirSync(dir)) {
    for (const patch of diff.parsePatch(fs.readFileSync(path.join(dir, patchfile), 'utf-8'))) {
      if (patch.oldFileName != patch.newFileName) throw new Error(`${patchfile} renames ${JSON.stringify(patch.oldFileName)} to ${JSON.stringify(patch.newFileName)}`)
      if (patches[patch.oldFileName]) throw new Error(`${patchfile} re-patches ${JSON.stringify(patch.oldFileName)}`)
      if (!patch.oldFileName.startsWith('node_modules/')) throw new Error(`${patchfile} patches ${JSON.stringify(patch.oldFileName)} outside node_modules`)
      patches[patch.oldFileName] = patch
    }
  }
  return patches
}

module.exports.patcher = function(dir) {
  const patches = load_patches(dir)
  const filter = '.*\\/(' + Object.keys(patches).map(source => source.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') + ')$'

  return {
    name: 'patcher',
    setup(build) {
      build.onLoad({ filter: new RegExp(filter) }, async (args) => {
        const target = args.path.replace(/.*[/]node_modules[/]/, 'node_modules/')
        console.log('  patching', target)
        const source = await fs.promises.readFile(args.path, 'utf-8')
        const patch = patches[target]

        return {
          contents: diff.applyPatch(source, patch),
          loader: 'js',
        }
      })
    }
  }
}

module.exports.bibertool = {
  name: 'bibertool',
  setup(build) {
    build.onLoad({ filter: /\/biber-tool\.conf$/ }, async (args) => {
      return {
        contents: bibertool(await fs.promises.readFile(args.path, 'utf-8')),
        loader: 'js'
      }
    })
  }
}

module.exports.pegjs = {
  name: 'pegjs',
  setup(build) {
    build.onLoad({ filter: /\.pegjs$/ }, async (args) => {
      return {
        contents: pegjs.generate(await fs.promises.readFile(args.path, 'utf-8'), {
          output: 'source',
          cache: false,
          optimize: 'speed',
          trace: false,
          format: 'commonjs',
        }),
        loader: 'js'
      }
    })
  }
}

module.exports.__dirname = {
  name: '__dirname',
  setup(build) {
    build.onLoad({ filter: /\/node_modules\/.+\.js$/ }, async (args) => {
      let contents = await fs.promises.readFile(args.path, 'utf-8')
      const filename = 'resource://zotero-better-bibtex/' + args.path.replace(/.*\/node_modules\/(\.pnpm)?/, '')
      const dirname = path.dirname(filename)

      contents = [
        `var __dirname=${JSON.stringify(dirname)};`,
        `var __filename=${JSON.stringify(filename)};`,
        contents,
      ].join('\n')

      return {
        contents,
        loader: 'js'
      }
    })
  }
}

function modulename(source) {
  source = source.replace(/.*(^|\/)node_modules\//, '')
  if (source[0] === '.') return null
  const dirs = source.split('/')

  if (dirs[0][0] === '@') {
    return dirs.unshift(2).join('/')
  }
  else {
    return dirs[0]
  }
}
module.exports.modulename = modulename
module.exports.node_modules = function(dir) {
  const patched = [...new Set(Object.keys(load_patches(dir)).map(modulename))]
  const external = []

  return {
    patched,
    external,
    // plugin: nodeExternalsPlugin({ allowList: patched }),
    plugin: {
      name: 'node-externals',
      setup(build) {
        build.onResolve({ namespace: 'file', filter: /.*/ }, args => {
          const name = modulename(args.path)
          if (!name || patched.includes(name)) return null
          if (!external.includes(name)) external.push(name)
          return { path: args.path, external: true }
        })
      }
    }
  }
}

let selected_for_trace = false
if (fs.existsSync(path.join(__dirname, '../../.trace.json'))) {
  const branch = (process.env.GITHUB_REF && process.env.GITHUB_REF.startsWith('refs/heads/')) ? process.env.GITHUB_REF.replace('refs/heads/', '') : shell.exec('git rev-parse --abbrev-ref HEAD', { silent: true }).stdout.trim()
  console.log('building on', branch)
  if (branch !== 'master' && branch !== 'main') {
    let trace = require('../../.trace.json')
    trace = trace[branch]
    console.log(`instrumenting ${branch}: ${!!trace}`)
    if (trace) selected_for_trace = filePathFilter(trace)
  }
}

const prefix = fs.readFileSync(path.join(__dirname, 'trace.js'), 'utf-8')

module.exports.trace = {
  name: 'trace',
  setup(build) {
    build.onLoad({ filter: selected_for_trace ? /\.ts$/ : /^$/ }, async (args) => {
      if (!selected_for_trace) return null

      const source = await esbuild.transform(await fs.promises.readFile(args.path, 'utf-8'), { loader: 'ts' })
      for (const warning of source.warnings) {
        console.log('!!', warning)
      }

      const localpath = path.relative(process.cwd(), args.path)

      // inject __estrace so sources can tell an instrumented build is active even if not on the current source
      if (!selected_for_trace(localpath)) {
        const contents = `const __estrace = true;\n${source.code}`
        return {
          contents,
          loader: 'js',
        }
      }

      console.log(`!!!!!!!!!!!!!! Instrumenting ${localpath} for trace logging !!!!!!!!!!!!!`)

      try {
        const tracer = await import('estrace/plugin');
        const {code} = putout(source.code, {
          fixCount: 1,
          rules: {
            tracer: ['on', { url: localpath.replace(/\.ts$/, '') }],
          },
          plugins: [
            ['tracer', tracer],
          ],
        })
        const contents = prefix + code

        return {
          contents,
          loader: 'js',
        }
      }
      catch (err) {
        await fs.promises.writeFile('/tmp/tt', `/* ${localpath.replace(/\.ts$/, '')}\n${err.stack}\n*/\n/${source.code}`)
        throw err
      }

    })
  }
}

<|endoftext|>


<commit_before>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;

  var iconPath = '../img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'missing.png'
  };

  var createMarker = function(marker) {
    var latlng = new google.maps.LatLng(marker.latitude,marker.longitude);

    var icon;

    if(markerImg[marker.category]){
      icon = iconPath + markerImg[marker.category];
    } else {
      icon = iconPath + markerImg['DEFAULT'];
    }

    new google.maps.Marker({
      position: latlng,
      animation: google.maps.Animation.DROP,
      title: marker.title,
      icon: icon,
      map: map
    });
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },
    createMarkers: function(crimes) {
      console.log(crimes);
      for(var i = 0; i < crimes.length; i++){
        createMarker(crimes[i]);
      }
    },
    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },
    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });

    },
    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    }
  }
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<commit_msg>Fixes icon pathing issue for mobile emulators<commit_after>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;

  var iconPath = '../www/img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'missing.png'
  };

  var createMarker = function(marker) {
    var latlng = new google.maps.LatLng(marker.latitude,marker.longitude);

    var icon;

    if(markerImg[marker.category]){
      icon = iconPath + markerImg[marker.category];
    } else {
      icon = iconPath + markerImg['DEFAULT'];
    }

    new google.maps.Marker({
      position: latlng,
      animation: google.maps.Animation.DROP,
      title: marker.title,
      icon: icon,
      map: map
    });
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },
    createMarkers: function(crimes) {
      console.log(crimes);
      for(var i = 0; i < crimes.length; i++){
        createMarker(crimes[i]);
      }
    },
    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },
    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });

    },
    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    }
  }
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<|endoftext|>


<commit_before>/**
 * Test dependencies.
 */
const Coral = require('../../lib/coral')
const db = require('../helper/db')
const express = require('express')
const request = require('supertest')
const bodyParser = require('body-parser')
const app = express()

describe('Coral subDoc post tests', () => {
  // require to get req body parameters
  app.use(bodyParser.json())

  before((done) => {
    db.connect()
    db.initialise(done)
  })

  after((done) => {
    db.disconnect(done)
  })

  it('subDoc post - must create proper post route and return matching record', (done) => {
    // config to pass router find method
    const config = {
      path: '/localhost/articles/:name/comments',
      model: db.getModel('Article'),
      methods: ['POST'],
      conditions: {
        name: 'article-one'
      },
      subDoc: {
        path: 'comments'
      }
    }

    // data to be pass into post request
    const data = {
      'name': 'comment-three',
      'body': 'Article One Third Comment',
      'replies': [{
        'name': 'reply-one',
        'body': 'Article One Third Comment First Reply'
      }]
    }

    // call router get with the config
    app.use(new Coral(config))

    // invoke path with supertest
    request(app)
      .post('/localhost/articles/article-one/comments')
      .set('accept', 'application/json')
      .send(data)
      .expect(200)
      .end((err, res) => {
        res.body.name.should.equal('comment-three')
        console.log(err)
        done(err) // pass err so that fail expect errors will get caught
      })
  })

  it('sub subDoc post - must create proper post route and return matching record', (done) => {
    // config to pass router find method
    const config = {
      path: '/localhost/articles/:articleName/comments/:commentName/replies',
      model: db.getModel('Article'),
      methods: ['POST'],
      conditions: {
        name: 'article-one'
      },
      subDoc: {
        path: 'comments',
        idAttribute: 'name',
        idParam: 'commentName',
        subDoc: {
          path: 'replies'
        }
      }
    }

    // data to be pass into post request
    const data = {
      'name': 'reply-three',
      'body': 'Article One Second Comment Third Reply'
    }

    // call router get with the config
    app.use(new Coral(config))

    // invoke path with supertest
    request(app)
      .post('/localhost/articles/article-one/comments/comment-one/replies')
      .set('accept', 'application/json')
      .send(data)
      .expect(200)
      .end((err, res) => {
        res.body.name.should.equal('reply-three')
        done(err) // pass err so that fail expect errors will get caught
      })
  })
})
<commit_msg>fix unit test<commit_after>/**
 * Test dependencies.
 */
const Coral = require('../../lib/coral')
const db = require('../helper/db')
const express = require('express')
const request = require('supertest')
const bodyParser = require('body-parser')
const app = express()

describe('Coral subDoc post tests', () => {
  // require to get req body parameters
  app.use(bodyParser.json())

  beforeEach((done) => {
    db.connect()
    db.initialise(done)
  })

  afterEach((done) => {
    db.disconnect(done)
  })

  it('subDoc post - must create proper post route and return matching record', (done) => {
    // config to pass router find method
    const config = {
      path: '/localhost/articles/:name/comments',
      model: db.getModel('Article'),
      methods: ['POST'],
      conditions: {
        name: 'article-one'
      },
      subDoc: {
        path: 'comments'
      }
    }

    // data to be pass into post request
    const data = {
      'name': 'comment-three',
      'body': 'Article One Third Comment',
      'replies': [{
        'name': 'reply-one',
        'body': 'Article One Third Comment First Reply'
      }]
    }

    // call router get with the config
    app.use(new Coral(config))

    // invoke path with supertest
    request(app)
      .post('/localhost/articles/article-one/comments')
      .set('accept', 'application/json')
      .send(data)
      .expect(200)
      .end((err, res) => {
        res.body.name.should.equal('comment-three')
        console.log(err)
        done(err) // pass err so that fail expect errors will get caught
      })
  })

  it('sub subDoc post - must create proper post route and return matching record', (done) => {
    // config to pass router find method
    const config = {
      path: '/localhost/articles/:articleName/comments/:commentName/replies',
      model: db.getModel('Article'),
      methods: ['POST'],
      conditions: {
        name: 'article-one'
      },
      subDoc: {
        path: 'comments',
        idAttribute: 'name',
        idParam: 'commentName',
        subDoc: {
          path: 'replies'
        }
      }
    }

    // data to be pass into post request
    const data = {
      'name': 'reply-three',
      'body': 'Article One Second Comment Third Reply'
    }

    // call router get with the config
    app.use(new Coral(config))

    // invoke path with supertest
    request(app)
      .post('/localhost/articles/article-one/comments/comment-one/replies')
      .set('accept', 'application/json')
      .send(data)
      .expect(200)
      .end((err, res) => {
        res.body.name.should.equal('reply-three')
        done(err) // pass err so that fail expect errors will get caught
      })
  })
})
<|endoftext|>