<commit_before>////////////////////////////////////////////////////////////////////////////////
// Prepare the app for dist
////////////////////////////////////////////////////////////////////////////////

'use strict';

require('shelljs/global');
require('colors');

var path = require('path'),
    fs = require('fs-extra');

// Auto-exit on errors
config.fatal = true;

echo('-----> Preparing for build...'.yellow);

// -- Determine the platform and arch running ----------------------------------

var args = require('minimist')(process.argv.slice(2));

var currentPlatform = process.platform;
var platform = args.platform;
var arch = args.arch;

if (!platform) {
  throw new Error('Platform not specified...'.bold.red);
}

if (!arch) {
  throw new Error('Architecture not specified...'.bold.red);
}

var onWindows = (currentPlatform === 'win32') ? true : false;

console.log('Target platform: '.bold.white, platform);
console.log('Target architecture: '.bold.white, arch);

// -- Set up some paths --------------------------------------------------------

var dir = __dirname;
var base = path.normalize(path.join(dir, '..'));

// -- Build the meteor app -----------------------------------------------------

echo('-----> Building bundle from Meteor app, this may take a few minutes...'.yellow);

cd(base + '/meteor');

var meteorCommand = (onWindows === true) ? 'meteor.bat' : 'meteor';
exec(meteorCommand + ' build --directory ../.');

cd(base + '/bundle');

// -- Install Meteor Npm package dependencies ----------------------------------

echo('-----> Installing bundle npm packages...'.yellow);
cd('./programs/server');
exec('npm install');
echo('-----> Bundle created :)\n'.green);

cd(base);

// -- Copy all necessary stuff into ./app directory ----------------------------

fs.removeSync('./app');

mkdir('./app');

function copyMeteorBundle(os) {
  switch (os) {

    case 'win32':
    case 'linux':
    case 'darwin':
      mv('bundle', './app/bundle');
      break;

    default:
      throw new Error('Unrecognized Operating System. Exiting...'.bold.red);
  }
}

function copyStartupFiles(os) {
  switch (os) {

    case 'win32':
    case 'linux':
    case 'darwin':
      cp('./index.js', './app/');
      cp('./about.html', './app/');
      cp('./package.json', './app/');
      cp('-R', './node_modules', './app/');
      break;

    default:
      throw new Error('Unrecognized Operating System. Exiting...'.bold.red);
  }
}

function copyBinaryFiles(os, architecture) {
  switch (os) {

    case 'win32':
    case 'linux':
    case 'darwin':
      mkdir('./app/resources');
      var nodePostfix = (platform === 'win32') ? 'node.exe' : 'bin/node';
      var mongodbPostfix = (platform === 'win32') ? 'mongod.exe' : 'mongod';
      cp('./cache/' + 'node-' + os + '-' + architecture + '/' + nodePostfix, './app/resources/');
      cp('./cache/' + 'mongodb-' + os + '-' + architecture + '/bin/' + mongodbPostfix, './app/resources/');
      break;

    default:
      throw new Error('Unrecognized Operating System. Exiting...'.bold.red);
  }
}

// Move necessary files

echo('-----> Copying Meteor bundle into ./app ...'.yellow);
copyMeteorBundle(platform, arch);

echo('-----> Copying startup files into ./app ...'.yellow);
copyStartupFiles(platform, arch);

echo('-----> Copying binary files into ./app ...'.yellow);
copyBinaryFiles(platform, arch);
<commit_msg>Copy over the licenses too.<commit_after>////////////////////////////////////////////////////////////////////////////////
// Prepare the app for dist
////////////////////////////////////////////////////////////////////////////////

'use strict';

require('shelljs/global');
require('colors');

var path = require('path'),
    fs = require('fs-extra');

// Auto-exit on errors
config.fatal = true;

echo('-----> Preparing for build...'.yellow);

// -- Determine the platform and arch running ----------------------------------

var args = require('minimist')(process.argv.slice(2));

var currentPlatform = process.platform;
var platform = args.platform;
var arch = args.arch;

if (!platform) {
  throw new Error('Platform not specified...'.bold.red);
}

if (!arch) {
  throw new Error('Architecture not specified...'.bold.red);
}

var onWindows = (currentPlatform === 'win32') ? true : false;

console.log('Target platform: '.bold.white, platform);
console.log('Target architecture: '.bold.white, arch);

// -- Set up some paths --------------------------------------------------------

var dir = __dirname;
var base = path.normalize(path.join(dir, '..'));

// -- Build the meteor app -----------------------------------------------------

echo('-----> Building bundle from Meteor app, this may take a few minutes...'.yellow);

cd(base + '/meteor');

var meteorCommand = (onWindows === true) ? 'meteor.bat' : 'meteor';
exec(meteorCommand + ' build --directory ../.');

cd(base + '/bundle');

// -- Install Meteor Npm package dependencies ----------------------------------

echo('-----> Installing bundle npm packages...'.yellow);
cd('./programs/server');
exec('npm install');
echo('-----> Bundle created :)\n'.green);

cd(base);

// -- Copy all necessary stuff into ./app directory ----------------------------

fs.removeSync('./app');

mkdir('./app');

function copyMeteorBundle(os) {
  switch (os) {

    case 'win32':
    case 'linux':
    case 'darwin':
      mv('bundle', './app/bundle');
      break;

    default:
      throw new Error('Unrecognized Operating System. Exiting...'.bold.red);
  }
}

function copyStartupFiles(os) {
  switch (os) {

    case 'win32':
    case 'linux':
    case 'darwin':
      cp('./index.js', './app/');
      cp('./about.html', './app/');
      cp('./package.json', './app/');
      cp('-R', './node_modules', './app/');
      break;

    default:
      throw new Error('Unrecognized Operating System. Exiting...'.bold.red);
  }
}

function copyBinaryFiles(os, architecture) {
  switch (os) {

    case 'win32':
    case 'linux':
    case 'darwin':
      mkdir('./app/resources');
      var nodePostfix = (platform === 'win32') ? 'node.exe' : 'bin/node';
      var mongodbPostfix = (platform === 'win32') ? 'mongod.exe' : 'mongod';
      var np = './cache/' + 'node-' + os + '-' + architecture + '/';
      var mp = './cache/' + 'mongodb-' + os + '-' + architecture + '/';
      cp(np + nodePostfix, './app/resources/');
      cp(np + 'LICENSE', './app/resources/');
      cp(mp + 'bin/' + mongodbPostfix, './app/resources/');
      cp(mp + 'GNU-AGPL-3.0', './app/resources/');
      break;

    default:
      throw new Error('Unrecognized Operating System. Exiting...'.bold.red);
  }
}

// Move necessary files

echo('-----> Copying Meteor bundle into ./app ...'.yellow);
copyMeteorBundle(platform, arch);

echo('-----> Copying startup files into ./app ...'.yellow);
copyStartupFiles(platform, arch);

echo('-----> Copying binary files into ./app ...'.yellow);
copyBinaryFiles(platform, arch);
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var Ftp = require('jsftp')

var params = {
  repo:   process.argv[2],
  branch: process.argv[3],
  owner:  process.argv[4],
  giturl: process.argv[5],
  source: process.argv[6],
  build:  process.argv[7]
};
var ftpConfig = {
  host: process.env.FTP_HOST,
  user: process.env.FTP_USER,
  pass: process.env.FTP_PASS
};
var ftpRoot = path.join("/", params.repo);

var remote = {
  _ftp: new Ftp(ftpConfig),

  _dirCallbacks: {},
  _createdDirs: {},
  mkDir: function(dirname, cb) {
    if(dirname == '/' || remote._createdDirs[dirname]) {
      cb(null);
    } else if(remote._dirCallbacks[dirname]) {
      remote._dirCallbacks[dirname].push(cb);
    } else {
      remote._dirCallbacks[dirname] = [cb];
      var cb2 = function(err) {
        var callbacks = remote._dirCallbacks[dirname];
        delete remote._dirCallbacks[dirname];
        callbacks.forEach(function(f) { f(err); });
      }
      remote.mkDir(path.dirname(dirname), function(err) {
        if(err) {
          cb2(err);
        } else {
          console.log('[ftp] mkdir ' + dirname);
          remote._ftp.raw.mkd(dirname, function(err, data) {
            remote._createdDirs[dirname] = 1;
            cb2(null);
          });
        }
      });
    }
  },

  put: function(localFile, remoteFile, cb) {
    remote.mkDir(path.dirname(remoteFile), function(err) {
      if(err) {
        cb(err);
      } else {
        fs.readFile(localFile, function(err, data) {
          if(err) {
            cb(err)
          } else {
            remote._ftp.put(remoteFile, data, cb);
          }
        });
      }
    });
  }
};

remote._ftp.on('connect', function() { console.log("CONNECTED"); }).on('disconnect', "DISCONNECTED");

var started = 0;
var finished = 0;

var uploadFile = function(localFile, remoteFile) {
  started += 1;
  console.log("[" + started + "] " + localFile + " --> " + remoteFile);
  remote.put(localFile, remoteFile, function(err) {
    finished += 1;
    if(err) {
      console.error("[" + finished + "/" + started + "] " + remoteFile + ": " + err);
    } else {
      console.log("[" + finished + "/" + started + "] " + remoteFile + ": success");
    }
  });
};

var uploadDirectory = function(localDir, remoteDir) {
  fs.readdir(localDir, function(err, list) {
    if(err) {
      console.error(localDir + ": " + err);
    } else {
      list.forEach(function(file) {
        var localPath = path.join(localDir, file);
        var remotePath = path.join(remoteDir, file);
        fs.stat(localPath, function(err, stat) {
          if(err) {
            console.error(localPath + ": " + err);
          } else {
            if(stat.isDirectory()) {
              uploadDirectory(localPath, remotePath);
            } else {
              uploadFile(localPath, remotePath);
            }
          }
        });
      });
    }
  });
};
uploadDirectory(params.build, ftpRoot);
<commit_msg>Use the emitter.<commit_after>var fs = require('fs');
var path = require('path');
var Ftp = require('jsftp')

var params = {
  repo:   process.argv[2],
  branch: process.argv[3],
  owner:  process.argv[4],
  giturl: process.argv[5],
  source: process.argv[6],
  build:  process.argv[7]
};
var ftpConfig = {
  host: process.env.FTP_HOST,
  user: process.env.FTP_USER,
  pass: process.env.FTP_PASS
};
var ftpRoot = path.join("/", params.repo);

var remote = {
  _ftp: new Ftp(ftpConfig),

  _dirCallbacks: {},
  _createdDirs: {},
  mkDir: function(dirname, cb) {
    if(dirname == '/' || remote._createdDirs[dirname]) {
      cb(null);
    } else if(remote._dirCallbacks[dirname]) {
      remote._dirCallbacks[dirname].push(cb);
    } else {
      remote._dirCallbacks[dirname] = [cb];
      var cb2 = function(err) {
        var callbacks = remote._dirCallbacks[dirname];
        delete remote._dirCallbacks[dirname];
        callbacks.forEach(function(f) { f(err); });
      }
      remote.mkDir(path.dirname(dirname), function(err) {
        if(err) {
          cb2(err);
        } else {
          console.log('[ftp] mkdir ' + dirname);
          remote._ftp.raw.mkd(dirname, function(err, data) {
            remote._createdDirs[dirname] = 1;
            cb2(null);
          });
        }
      });
    }
  },

  put: function(localFile, remoteFile, cb) {
    remote.mkDir(path.dirname(remoteFile), function(err) {
      if(err) {
        cb(err);
      } else {
        fs.readFile(localFile, function(err, data) {
          if(err) {
            cb(err)
          } else {
            remote._ftp.put(remoteFile, data, cb);
          }
        });
      }
    });
  }
};

remote._ftp.emitter.on('connect', function() { console.log("CONNECTED"); }).on('disconnect', "DISCONNECTED");

var started = 0;
var finished = 0;

var uploadFile = function(localFile, remoteFile) {
  started += 1;
  console.log("[" + started + "] " + localFile + " --> " + remoteFile);
  remote.put(localFile, remoteFile, function(err) {
    finished += 1;
    if(err) {
      console.error("[" + finished + "/" + started + "] " + remoteFile + ": " + err);
    } else {
      console.log("[" + finished + "/" + started + "] " + remoteFile + ": success");
    }
  });
};

var uploadDirectory = function(localDir, remoteDir) {
  fs.readdir(localDir, function(err, list) {
    if(err) {
      console.error(localDir + ": " + err);
    } else {
      list.forEach(function(file) {
        var localPath = path.join(localDir, file);
        var remotePath = path.join(remoteDir, file);
        fs.stat(localPath, function(err, stat) {
          if(err) {
            console.error(localPath + ": " + err);
          } else {
            if(stat.isDirectory()) {
              uploadDirectory(localPath, remotePath);
            } else {
              uploadFile(localPath, remotePath);
            }
          }
        });
      });
    }
  });
};
uploadDirectory(params.build, ftpRoot);
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var Ftp = require('jsftp')

var params = {
  repo:   process.argv[2],
  branch: process.argv[3],
  owner:  process.argv[4],
  giturl: process.argv[5],
  source: process.argv[6],
  build:  process.argv[7]
};
var ftpConfig = {
  host: process.env.FTP_HOST,
  user: process.env.FTP_USER,
  pass: process.env.FTP_PASS
};
var ftpRoot = path.join("/", params.repo);

var remote = {
  _ftp: new Ftp(ftpConfig),

  _dirCallbacks: {},
  _createdDirs: {},
  mkDir: function(dirname, cb) {
    if(dirname == '/' || remote._createdDirs[dirname]) {
      cb(null);
    } else if(remote._dirCallbacks[dirname]) {
      remote._dirCallbacks[dirname].push(cb);
    } else {
      remote._dirCallbacks[dirname] = [cb];
      var cb2 = function(err) {
        var callbacks = remote._dirCallbacks[dirname];
        delete remote._dirCallbacks[dirname];
        callbacks.forEach(function(f) { f(err); });
      }
      remote.mkDir(path.dirname(dirname), function(err) {
        if(err) {
          cb2(err);
        } else {
          console.log('[ftp] mkdir ' + dirname);
          remote._ftp.raw.mkd(dirname, function(err, data) {
            remote._createdDirs[dirname] = 1;
            cb2(null);
          });
        }
      });
    }
  },

  put: function(localFile, remoteFile, cb) {
    remote.mkDir(path.dirname(remoteFile), function(err) {
      if(err) {
        cb(err);
      } else {
        fs.readFile(localFile, function(err, data) {
          if(err) {
            cb(err)
          } else {
            remote._ftp.put(remoteFile, data, cb);
          }
        });
      }
    });
  }
};

remote._ftp.emitter.on('connect', function() { console.log("CONNECTED"); }).on('disconnect', "DISCONNECTED");

var started = 0;
var finished = 0;

var uploadFile = function(localFile, remoteFile) {
  started += 1;
  console.log("[" + started + "] " + localFile + " --> " + remoteFile);
  remote.put(localFile, remoteFile, function(err) {
    finished += 1;
    if(err) {
      console.error("[" + finished + "/" + started + "] " + remoteFile + ": " + err);
    } else {
      console.log("[" + finished + "/" + started + "] " + remoteFile + ": success");
    }
  });
};

var uploadDirectory = function(localDir, remoteDir) {
  fs.readdir(localDir, function(err, list) {
    if(err) {
      console.error(localDir + ": " + err);
    } else {
      list.forEach(function(file) {
        var localPath = path.join(localDir, file);
        var remotePath = path.join(remoteDir, file);
        fs.stat(localPath, function(err, stat) {
          if(err) {
            console.error(localPath + ": " + err);
          } else {
            if(stat.isDirectory()) {
              uploadDirectory(localPath, remotePath);
            } else {
              uploadFile(localPath, remotePath);
            }
          }
        });
      });
    }
  });
};
uploadDirectory(params.build, ftpRoot);
<commit_msg>More simple errors.<commit_after>var fs = require('fs');
var path = require('path');
var Ftp = require('jsftp')

var params = {
  repo:   process.argv[2],
  branch: process.argv[3],
  owner:  process.argv[4],
  giturl: process.argv[5],
  source: process.argv[6],
  build:  process.argv[7]
};
var ftpConfig = {
  host: process.env.FTP_HOST,
  user: process.env.FTP_USER,
  pass: process.env.FTP_PASS
};
var ftpRoot = path.join("/", params.repo);

var remote = {
  _ftp: new Ftp(ftpConfig),

  _dirCallbacks: {},
  _createdDirs: {},
  mkDir: function(dirname, cb) {
    if(dirname == '/' || remote._createdDirs[dirname]) {
      cb(null);
    } else if(remote._dirCallbacks[dirname]) {
      remote._dirCallbacks[dirname].push(cb);
    } else {
      remote._dirCallbacks[dirname] = [cb];
      var cb2 = function(err) {
        var callbacks = remote._dirCallbacks[dirname];
        delete remote._dirCallbacks[dirname];
        callbacks.forEach(function(f) { f(err); });
      }
      remote.mkDir(path.dirname(dirname), function(err) {
        if(err) {
          cb2(err);
        } else {
          console.log('[ftp] mkdir ' + dirname);
          remote._ftp.raw.mkd(dirname, function(err, data) {
            remote._createdDirs[dirname] = 1;
            cb2(null);
          });
        }
      });
    }
  },

  put: function(localFile, remoteFile, cb) {
    remote.mkDir(path.dirname(remoteFile), function(err) {
      if(err) {
        cb(err);
      } else {
        fs.readFile(localFile, function(err, data) {
          if(err) {
            cb(err)
          } else {
            remote._ftp.put(remoteFile, data, cb);
          }
        });
      }
    });
  }
};

remote._ftp.emitter.on('connect', function() { console.log("CONNECTED"); }).on('disconnect', function() { console.log("DISCONNECTED") });

var started = 0;
var finished = 0;

var uploadFile = function(localFile, remoteFile) {
  started += 1;
  console.log("[" + started + "] " + localFile + " --> " + remoteFile);
  remote.put(localFile, remoteFile, function(err) {
    finished += 1;
    if(err) {
      console.error("[" + finished + "/" + started + "] " + remoteFile + ": " + err);
    } else {
      console.log("[" + finished + "/" + started + "] " + remoteFile + ": success");
    }
  });
};

var uploadDirectory = function(localDir, remoteDir) {
  fs.readdir(localDir, function(err, list) {
    if(err) {
      console.error(localDir + ": " + err);
    } else {
      list.forEach(function(file) {
        var localPath = path.join(localDir, file);
        var remotePath = path.join(remoteDir, file);
        fs.stat(localPath, function(err, stat) {
          if(err) {
            console.error(localPath + ": " + err);
          } else {
            if(stat.isDirectory()) {
              uploadDirectory(localPath, remotePath);
            } else {
              uploadFile(localPath, remotePath);
            }
          }
        });
      });
    }
  });
};
uploadDirectory(params.build, ftpRoot);
<|endoftext|>


<commit_before>const path = require('path');
const q = require('q');
const inquirer = require('inquirer');
const replace = require('replace');
const semver = require('semver');
const root = require('app-root-path').path;
const git = require('simple-git')( root );
const conventionalChangelog = require('conventional-changelog');
const child_process = require('child_process');

const packageFile = `${root}/package.json`;
const changelogFile = `${root}/CHANGELOG.md`;

function requestReleaseType() {
  var deferred = q.defer();
  inquirer.prompt([
    {
      type: 'list',
      name: 'type',
      message: 'What type of release would you like?',
      choices: ['patch', 'minor', 'major'],
      default: 0
    }
  ], function( answers ) {
      deferred.resolve( answers.type );
  });
  return deferred.promise;
}

function bump( current, type) {
  const next = semver.inc( current, type );

  replace({
    regex: /"version": "[^"]+"/m,
    replacement: `"version": "${next}"`,
    paths: [ packageFile ],
    recursive: false,
  });

  return q.when( next );
}

function preVersion( version ) {
  var deferred = q.defer();
  inquirer.prompt([
    { type: 'confirm', name: 'continue', message: `Continue with release of ${version}? (Last chance to edit CHANGELOG!)`, default: true },
  ], function( answer ) {
    if (answer.continue) {
      deferred.resolve(version);
    } else {
      git.reset('hard', () => deferred.reject(new Error()));
    }
  });
  return deferred.promise;
}

function runVersion( version ) {
  var deferred = q.defer();

  console.log('Committing...');
  git.commit(`chore(release): ${version}`, [ packageFile, changelogFile ], () => {
    console.log('Tagging...');
    git.addAnnotatedTag(`v${version}`, 'Version release', () => deferred.resolve(version));
  });

  return deferred.promise;
}

function publish(version) {
  var deferred = q.defer();
  console.log('Publishing...');
  child_process.exec('gulp prepublish && npm publish ./dist', function (err, stdout, stderr){
    if (err) {
      console.log('child processes failed with error code: ', err);
      deferred.reject();
    } else {
      console.log(stdout);
      deferred.resolve(version);
    }
  });
  return deferred.promise;
}

function postVersion( version ) {
  var deferred = q.defer();
  bump( version, 'prerelease').then(() => {
    git.commit(`chore(release): starting new releace cycle`, [ packageFile ], deferred.resolve());
  });
  return deferred.promise;
}

function push() {
  var deferred = q.defer();
  inquirer.prompt({
    type: 'confirm',
    name: 'push',
    message: 'Push to origin?',
    default: true,
  }, function(response) {
    if (response.push) {
      git.push('origin', 'master', () => git.pushTags('origin', () => deferred.resolve(true)));
      return;
    }
    deferred.resolve(false);
  });
  return deferred.promise;
}

function changelog( version ) {
  const shell = require('shelljs');
  shell.exec(`${root}/node_modules/.bin/conventional-changelog -p angular -i ${changelogFile} -s`);
}

// Start
requestReleaseType()
.then(type => bump(require(packageFile).version, type))
.then(changelog)
.then(preVersion)
.then(runVersion, () => q.reject())
.then(publish, () => q.reject())
.then(postVersion)
.then(push);
<commit_msg>chore(scripts): remove unused package `conventional-changelog`<commit_after>const path = require('path');
const q = require('q');
const inquirer = require('inquirer');
const replace = require('replace');
const semver = require('semver');
const root = require('app-root-path').path;
const git = require('simple-git')( root );
const child_process = require('child_process');

const packageFile = `${root}/package.json`;
const changelogFile = `${root}/CHANGELOG.md`;

function requestReleaseType() {
  var deferred = q.defer();
  inquirer.prompt([
    {
      type: 'list',
      name: 'type',
      message: 'What type of release would you like?',
      choices: ['patch', 'minor', 'major'],
      default: 0
    }
  ], function( answers ) {
      deferred.resolve( answers.type );
  });
  return deferred.promise;
}

function bump( current, type) {
  const next = semver.inc( current, type );

  replace({
    regex: /"version": "[^"]+"/m,
    replacement: `"version": "${next}"`,
    paths: [ packageFile ],
    recursive: false,
  });

  return q.when( next );
}

function preVersion( version ) {
  var deferred = q.defer();
  inquirer.prompt([
    { type: 'confirm', name: 'continue', message: `Continue with release of ${version}? (Last chance to edit CHANGELOG!)`, default: true },
  ], function( answer ) {
    if (answer.continue) {
      deferred.resolve(version);
    } else {
      git.reset('hard', () => deferred.reject(new Error()));
    }
  });
  return deferred.promise;
}

function runVersion( version ) {
  var deferred = q.defer();

  console.log('Committing...');
  git.commit(`chore(release): ${version}`, [ packageFile, changelogFile ], () => {
    console.log('Tagging...');
    git.addAnnotatedTag(`v${version}`, 'Version release', () => deferred.resolve(version));
  });

  return deferred.promise;
}

function publish(version) {
  var deferred = q.defer();
  console.log('Publishing...');
  child_process.exec('gulp prepublish && npm publish ./dist', function (err, stdout, stderr){
    if (err) {
      console.log('child processes failed with error code: ', err);
      deferred.reject();
    } else {
      console.log(stdout);
      deferred.resolve(version);
    }
  });
  return deferred.promise;
}

function postVersion( version ) {
  var deferred = q.defer();
  bump( version, 'prerelease').then(() => {
    git.commit(`chore(release): starting new releace cycle`, [ packageFile ], deferred.resolve());
  });
  return deferred.promise;
}

function push() {
  var deferred = q.defer();
  inquirer.prompt({
    type: 'confirm',
    name: 'push',
    message: 'Push to origin?',
    default: true,
  }, function(response) {
    if (response.push) {
      git.push('origin', 'master', () => git.pushTags('origin', () => deferred.resolve(true)));
      return;
    }
    deferred.resolve(false);
  });
  return deferred.promise;
}

function changelog( version ) {
  const shell = require('shelljs');
  shell.exec(`${root}/node_modules/.bin/conventional-changelog -p angular -i ${changelogFile} -s`);
}

// Start
requestReleaseType()
.then(type => bump(require(packageFile).version, type))
.then(changelog)
.then(preVersion)
.then(runVersion, () => q.reject())
.then(publish, () => q.reject())
.then(postVersion)
.then(push);
<|endoftext|>


<commit_before>//==================================================
// 数据缓存模块
//==================================================
define("data", ["$lang"], function( $ ){
    function Data(user) {
        this.owners = [];
        this.user = user;
        this.cache = [];
    }
    Data.prototype = {
        add: function( owner ) {
            var index = this.owners.push( owner );
            return (this.cache[ index - 1 ] = {});
        },
        access: function( owner, key, value ) {
            var index = this.owners.indexOf( owner );
            var cache = index === -1 ?  this.add( owner ) : this.cache[ index ];
            if(typeof key == "string"){
                if(value == undefined){//读方法
                    //对于用HTML5 data-*属性保存的数据， 如<input id="test" data-full-name="Planet Earth"/>
                    //我们可以通过$("#test").data("full-name")或$("#test").data("fullName")访问到
                    if(this.user && !(key in cache) && owner && owner.nodeType == 1 ){
                        $.parseData( owner, key, cache );
                    }
                    return cache[key];
                }else{
                    return cache[key] = value;//写方法
                }
            }
            return key && typeof key == "object" ?  $.mix(cache, value) : cache;
        },
        remove: function( owner, key ) {
            var name,
            camel = $.String.camelize,
            index = this.owners.indexOf( owner ),
            cache = this.cache[ index ];
            if ( key === undefined ) {
                cache = {};
            } else {
                if ( cache ) {//如果已经存在
                    if ( !Array.isArray( key ) ) { //如果不是数组
                        if ( key in cache ) {
                            name = [ key ];
                        } else {//尝试驼峰化再求,再不行数组化
                            name = camel( key );
                            name = name in cache ? [ name ] : name.match($.rword);
                        }
                    } else {//如果是数组
                        name = key.concat( key.map( camel ) );
                    }
                    for (var i =0, l = name.length ; i < l; i++ ) {
                        delete cache[ name[i] ];
                    }
                }
            }
            this.cache[ index ] = cache;
        },
        hasData: function( owner ) {
            var index = this.owners.indexOf( owner );
            if ( index > -1 ) {
                return !$.isEmptyObject( this.cache[ index ] );
            }
            return false;
        }
    };
    var user = new Data(true), priv = new Data;
    $.mix( {
        data: function( elem, name, data ) {
            return user.access( elem, name, data );
        },
        removeData: function( elem, name ) {
            return user.remove( elem, name );
        },
        _data: function( elem, name, data ) {
            return priv.access( elem, name, data );
        },
        _removeData: function( elem, name ) {
            return priv.remove( elem, name );
        },
        hasData: function( elem ) {
            return user.hasData( elem ) || priv.hasData( elem );
        },
        parseData: function(target, name, cache, value){
            var data, key = $.String.camelize(name),_eval
            if(cache && (key in cache))
                return cache[key];
            if(arguments.length != 4){
                var attr = "data-" + name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
                value = target.getAttribute( attr );
            }
            if ( typeof value === "string") {//转换 /^(?:\{.*\}|null|false|true|NaN)$/
                if(/^(?:\{.*\}|\[.*\]|null|false|true|NaN)$/.test(value) || +value + "" === value){
                    _eval = true
                }
                try {
                    data = _eval ?  eval("0,"+ value ) : value
                } catch( e ) {
                    data = value
                }
                if(cache){
                    cache[ key ] = data
                }
            }
            return data;

        },
        //合并数据
        mergeData: function( cur, src){
            if( priv.hasData(src) ){
                var oldData  = priv.access(src), curData = priv.access(cur), events = oldData .events;
                $.Object.merge( curData , oldData  );
                if(events){
                    curData.events = [];
                    for (var i = 0, item ; item =  events[i++]; ) {
                        $.event.bind( cur, item );
                    }
                }
            }
            if( user.hasData(src) ){
                oldData = user.access(src)
                curData = user.access(cur)
                $.Object.merge( curData , oldData  );
            }
        }
    });
    return $
});

/**
2011.9.27 uniqueID改为uniqueNumber 简化data与removeData
2011.9.28 添加$._data处理内部数据
2011.10.21 强化mergeData，可以拷贝事件
2012.1.31 简化$.Object.merge的调用
2012.4.5 修正mergeData BUG, 让$.data能获取HTML5 data-*
2012.5.2 $._db -> $["@data]
2012.5.21 抽象出validate私有方法
2012.9.29 对parseData的数据进行严格的验证后才转换  v2
2012.12.30 使用jquery2.0的新思路,通过存放目标的数组的索引值来关联目标与缓存体 v3
*/
<commit_msg>升级到v4<commit_after>//==================================================
// 数据缓存模块
//==================================================
define("data", ["$lang"], function( $ ){
    var owners = [], caches =[]
    function  add ( owner ) {
        var index = owners.push( owner );
        return caches[ index - 1 ] = {
            data: {}
        };
    }
    function innerData( owner, name, data, pvt ) {//IE678不能为文本节点注释节点添加数据
        var index = owners.indexOf( owner );
        var table = index === -1 ?  add( owner ) : caches[ index ];
        var getOne = typeof name === "string"//取得单个属性
        var cache = table;
        //私有数据都是直接放到table中，普通数据放到table.data中
        if ( !pvt ) {
            table = table.data;
        }
        if ( name && typeof name == "object" ) {
            $.mix( table, name );//写入一组属性
        }else if(getOne && data !== void 0){
            table[ name ] = data;//写入单个属性
        }
        if(getOne){
            if(name in table){
                return table[name]
            }else if(owner && owner.nodeType == 1 && !pvt){
                //对于用HTML5 data-*属性保存的数据， 如<input id="test" data-full-name="Planet Earth"/>
                //我们可以通过$("#test").data("full-name")或$("#test").data("fullName")访问到
                return $.parseData( owner, name, cache );
            }
        }else{
            return table
        }
    }
    function innerRemoveData (owner, name, pvt){
        var index = owners.indexOf( owner );
        if(index > -1 ){
            var clear = 1, delOne = typeof name == "string",
            table = caches[ index ], cache = table;
            if ( delOne ) {
                if(!pvt){
                    table = table.data
                }
                if(table){
                    delOne = table[ name ];
                    delete table[ name ];
                }
                    loop:
                    for(var key in cache){
                        if(key == "data"){
                            for(var i in cache.data){
                                clear = 0;
                                break loop;
                            }
                        }else{
                            clear = 0;
                            break loop;
                        }
                    }
            }
            if(clear){
                owners.splice( index, 1 );
                caches.splice( index, 1 );
            }
            return delOne;//返回被移除的数据
        }
    }

    $.mix( {
        data: function( target, name, data ) {  // 读写数据
            return innerData(target, name, data)
        },
        _data: function(target,name,data){//仅内部调用
            return innerData(target, name, data, true)
        },
        removeData: function(target, name){  //移除数据
            return innerRemoveData(target, name);
        },
        _removeData: function(target, name){//仅内部调用
            return innerRemoveData(target, name, true);
        },
        parseData: function(target, name, cache, value){
            var data, key = $.String.camelize(name),_eval
            if(cache && (key in cache))
                return cache[key];
            if(arguments.length != 4){
                var attr = "data-" + name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
                value = target.getAttribute( attr );
            }
            if ( typeof value === "string") {//转换 /^(?:\{.*\}|null|false|true|NaN)$/
                if(/^(?:\{.*\}|\[.*\]|null|false|true|NaN)$/.test(value) || +value + "" === value){
                    _eval = true
                }
                try {
                    data = _eval ?  eval("0,"+ value ) : value
                } catch( e ) {
                    data = value
                }
                if(cache){
                    cache[ key ] = data
                }
            }
            return data;

        },
        //合并数据
        mergeData: function( cur, src){
            var oldData  = $._data(src), curData  = $._data(cur), events = oldData .events;
            if(oldData  && curData ){
                $.Object.merge( curData , oldData  );
                if(events){
                    curData .events = [];
                    for (var i = 0, item ; item =  events[i++]; ) {
                        $.event.bind( cur, item );
                    }
                }
            }
        }
    });
    return $
});

/**
2011.9.27 uniqueID改为uniqueNumber 简化data与removeData
2011.9.28 添加$._data处理内部数据
2011.10.21 强化mergeData，可以拷贝事件
2012.1.31 简化$.Object.merge的调用
2012.4.5 修正mergeData BUG, 让$.data能获取HTML5 data-*
2012.5.2 $._db -> $["@data]
2012.5.21 抽象出validate私有方法
2012.9.29 对parseData的数据进行严格的验证后才转换  v2
2012.12.30 使用jquery2.0的新思路,通过存放目标的数组的索引值来关联目标与缓存体 v3
2013.1.2 升级到v4
*/
<|endoftext|>


<commit_before>import Webiny from 'Webiny';

class SimpleSelect extends Webiny.Ui.Component {

    constructor(props) {
        super(props);

        this.select2 = null;
        this.options = null;
        this.bindMethods('getConfig,getValue,triggerChange,getSelect2InputElement,itemRenderer,getCurrentData,getPreviousData');
    }

    componentDidMount() {
        super.componentDidMount();
        if (!this.isRendered()) {
            return;
        }
        this.instantiate();
    }

    componentWillReceiveProps(props) {
        super.componentWillReceiveProps(props);
        if (props.value !== this.props.value) {
            this.previousData = _.clone(this.getCurrentData());
        }
    }

    componentDidUpdate() {
        super.componentDidUpdate();
        if (!this.isRendered()) {
            this.select2 = null;
            return;
        }

        this.instantiate();
        const possibleValues = _.map(this.options, obj => obj.id.toString());
        const value = this.getValue();
        const inPossibleValues = possibleValues.indexOf(value) > -1;

        if (!this.options || !_.isEqual(this.props.options, this.options)) {
            this.select2.empty();
            this.getSelect2InputElement().select2(this.getConfig(this.props));
            setTimeout(() => {
                this.select2.val(this.getValue()).trigger('change');
            }, 100);
        }

        $(ReactDOM.findDOMNode(this)).find('select').prop('disabled', !!this.props.disabled);

        if (value !== null && !inPossibleValues && possibleValues.length > 0) {
            this.triggerChange(null);
            return;
        }

        if (value !== null && inPossibleValues) {
            this.select2.val(value).trigger('change');
            return;
        }

        this.select2.val('').trigger('change');
    }

    instantiate() {
        if (!this.select2) {
            this.select2 = this.getSelect2InputElement().select2(this.getConfig(this.props));
            this.select2.on('select2:select', e => {
                this.triggerChange(e.target.value);
            });
            this.select2.on('select2:unselect', () => {
                this.triggerChange('');
            });
            this.select2.val(this.getValue()).trigger('change');

            if (this.props.dropdownClassName) {
                setTimeout(() => this.select2.data('select2').$dropdown.addClass(this.props.dropdownClassName));
            }
        }
    }

    getSelect2InputElement() {
        return $(ReactDOM.findDOMNode(this)).find('select');
    }

    getValue() {
        const value = this.props.value;
        if (value === null || value === undefined) {
            return value;
        }

        return _.isObject(value) ? value.id : '' + value;
    }

    getCurrentData() {
        if (this.props.useDataAsValue) {
            return this.props.value;
        }

        let data = null;
        const option = _.find(this.options, {id: this.props.value});
        if (option) {
            data = option.data;
        }

        return this.props.value ? data : null;
    }

    getPreviousData() {
        return this.previousData;
    }

    triggerChange(value) {
        if (this.props.useDataAsValue && value) {
            const selectedOption = _.find(this.options, {id: value});
            if (!selectedOption.data) {
                console.warn('Warning: attempting to use item data but data is not present in option items!');
            } else {
                value = selectedOption.data;
            }
        }

        // Save previous selection data so it can be accessed from onChange handlers
        const prevValue = this.getValue();
        if (this.props.useDataAsValue) {
            this.previousData = prevValue ? _.clone(prevValue) : null;
        } else {
            let data = null;
            const option = _.find(this.options, {id: prevValue});
            if (option) {
                data = option.data;
            }
            this.previousData = data ? _.clone(data) : null;
        }
        this.props.onChange(value);
    }

    getOptionText(text) {
        if (!text) {
            return '';
        }

        if (text.startsWith('<')) {
            return $(text);
        }

        return text || '';
    }

    /**
     * This will be triggered twice due to a bug in Select2 (https://github.com/select2/select2/pull/4306)
     * @param item
     * @param type optionRenderer || selectedRenderer
     * @returns {*}
     */
    itemRenderer(item, type) {
        let text = item.text;
        if (_.isFunction(this.props[type]) && item.id) {
            text = this.props[type].call(this, item || {});
        }

        if (text && !_.isString(text)) {
            text = ReactDOMServer.renderToStaticMarkup(text);
        }

        return this.getOptionText(text);
    }

    getConfig(props) {
        const config = {
            disabled: props.disabled,
            minimumResultsForSearch: props.minimumResultsForSearch,
            minimumInputLength: props.minimumInputLength,
            placeholder: _.get(props.placeholder, 'props.children', props.placeholder),
            allowClear: props.allowClear,
            templateResult: item => this.itemRenderer(item, 'optionRenderer'),
            templateSelection: item => this.itemRenderer(item, 'selectedRenderer')
        };

        if (this.props.dropdownParent) {
            config['dropdownParent'] = $(ReactDOM.findDOMNode(this)).find(props.dropdownParent);
        }

        if (!this.options || !_.isEqual(props.options, this.options) || !this.select2) {
            // Prepare options
            const options = [];
            _.each(props.options, option => {
                if (React.isValidElement(option.text)) {
                    option.text = ReactDOMServer.renderToStaticMarkup(option.text);
                }
                options.push(option);
            });
            config['data'] = this.options = options;
        }

        return config;
    }
}

SimpleSelect.defaultProps = {
    value: null,
    allowClear: false,
    placeholder: null,
    onChange: _.noop,
    minimumInputLength: 0,
    minimumResultsForSearch: 15,
    useDataAsValue: false,
    dropdownParent: '.dropdown-wrapper',
    dropdownClassName: '',
    optionRenderer: null,
    selectedRenderer: null,
    renderer() {
        return (
            <webiny-select>
                <select style={{'width': '100%'}}/>

            </webiny-select>
        );
    }
};

export default SimpleSelect;<commit_msg>Added "autoSelectFirstOption" prop.<commit_after>import Webiny from 'Webiny';

class SimpleSelect extends Webiny.Ui.Component {

    constructor(props) {
        super(props);

        this.select2 = null;
        this.options = null;
        this.bindMethods('getConfig,getValue,triggerChange,getSelect2InputElement,itemRenderer,getCurrentData,getPreviousData');
    }

    componentDidMount() {
        super.componentDidMount();
        if (!this.isRendered()) {
            return;
        }
        this.instantiate();
    }

    componentWillReceiveProps(props) {
        super.componentWillReceiveProps(props);
        if (props.value !== this.props.value) {
            this.previousData = _.clone(this.getCurrentData());
        }
    }

    componentDidUpdate() {
        super.componentDidUpdate();
        if (!this.isRendered()) {
            this.select2 = null;
            return;
        }

        this.instantiate();
        const possibleValues = _.map(this.options, obj => obj.id.toString());
        const value = this.getValue();
        const inPossibleValues = possibleValues.indexOf(value) > -1;

        if (!this.options || !_.isEqual(this.props.options, this.options)) {
            this.select2.empty();
            this.getSelect2InputElement().select2(this.getConfig(this.props));
            setTimeout(() => {
                this.select2.val(this.getValue()).trigger('change');
            }, 100);
        }

        $(ReactDOM.findDOMNode(this)).find('select').prop('disabled', !!this.props.disabled);

        if (value !== null && !inPossibleValues && possibleValues.length > 0) {
            this.triggerChange(null);
            return;
        }

        if (value !== null && inPossibleValues) {
            this.select2.val(value).trigger('change');
            return;
        }

        // Select first value if model is empty and "autoSelectFirstOptionOption" is enabled
        if (value === null && this.props.autoSelectFirstOption) {
            const firstValue = _.get(this.props.options, '0.id');
            if (firstValue) {
                this.triggerChange(firstValue);
            }
            return;
        }

        this.select2.val('').trigger('change');
    }

    instantiate() {
        if (!this.select2) {
            this.select2 = this.getSelect2InputElement().select2(this.getConfig(this.props));
            this.select2.on('select2:select', e => {
                this.triggerChange(e.target.value);
            });
            this.select2.on('select2:unselect', () => {
                this.triggerChange('');
            });
            this.select2.val(this.getValue()).trigger('change');

            if (this.props.dropdownClassName) {
                setTimeout(() => this.select2.data('select2').$dropdown.addClass(this.props.dropdownClassName));
            }
        }
    }

    getSelect2InputElement() {
        return $(ReactDOM.findDOMNode(this)).find('select');
    }

    getValue() {
        const value = this.props.value;
        if (value === null || value === undefined) {
            return value;
        }

        return _.isObject(value) ? value.id : '' + value;
    }

    getCurrentData() {
        if (this.props.useDataAsValue) {
            return this.props.value;
        }

        let data = null;
        const option = _.find(this.options, {id: this.props.value});
        if (option) {
            data = option.data;
        }

        return this.props.value ? data : null;
    }

    getPreviousData() {
        return this.previousData;
    }

    triggerChange(value) {
        if (this.props.useDataAsValue && value) {
            const selectedOption = _.find(this.options, {id: value});
            if (!selectedOption.data) {
                console.warn('Warning: attempting to use item data but data is not present in option items!');
            } else {
                value = selectedOption.data;
            }
        }

        // Save previous selection data so it can be accessed from onChange handlers
        const prevValue = this.getValue();
        if (this.props.useDataAsValue) {
            this.previousData = prevValue ? _.clone(prevValue) : null;
        } else {
            let data = null;
            const option = _.find(this.options, {id: prevValue});
            if (option) {
                data = option.data;
            }
            this.previousData = data ? _.clone(data) : null;
        }
        this.props.onChange(value);
    }

    getOptionText(text) {
        if (!text) {
            return '';
        }

        if (text.startsWith('<')) {
            return $(text);
        }

        return text || '';
    }

    /**
     * This will be triggered twice due to a bug in Select2 (https://github.com/select2/select2/pull/4306)
     * @param item
     * @param type optionRenderer || selectedRenderer
     * @returns {*}
     */
    itemRenderer(item, type) {
        let text = item.text;
        if (_.isFunction(this.props[type]) && item.id) {
            text = this.props[type].call(this, item || {});
        }

        if (text && !_.isString(text)) {
            text = ReactDOMServer.renderToStaticMarkup(text);
        }

        return this.getOptionText(text);
    }

    getConfig(props) {
        const config = {
            disabled: props.disabled,
            minimumResultsForSearch: props.minimumResultsForSearch,
            minimumInputLength: props.minimumInputLength,
            placeholder: _.get(props.placeholder, 'props.children', props.placeholder),
            allowClear: props.allowClear,
            templateResult: item => this.itemRenderer(item, 'optionRenderer'),
            templateSelection: item => this.itemRenderer(item, 'selectedRenderer')
        };

        if (this.props.dropdownParent) {
            config['dropdownParent'] = $(ReactDOM.findDOMNode(this)).find(props.dropdownParent);
        }

        if (!this.options || !_.isEqual(props.options, this.options) || !this.select2) {
            // Prepare options
            const options = [];
            _.each(props.options, option => {
                if (React.isValidElement(option.text)) {
                    option.text = ReactDOMServer.renderToStaticMarkup(option.text);
                }
                options.push(option);
            });
            config['data'] = this.options = options;
        }

        return config;
    }
}

SimpleSelect.defaultProps = {
    value: null,
    allowClear: false,
    autoSelectFirstOption: false,
    placeholder: null,
    onChange: _.noop,
    minimumInputLength: 0,
    minimumResultsForSearch: 15,
    useDataAsValue: false,
    dropdownParent: '.dropdown-wrapper',
    dropdownClassName: '',
    optionRenderer: null,
    selectedRenderer: null,
    renderer() {
        return (
            <webiny-select>
                <select style={{'width': '100%'}}/>

            </webiny-select>
        );
    }
};

export default SimpleSelect;<|endoftext|>


<commit_before>// Apparently locations are not needed.
var locations = {
  outsideVJC: { lat: 1.3065322, lng: 103.9207787 },
};

// ---------------------------------------
// EDIT THIS TO START FROM A CHOSEN IMAGE.
// ---------------------------------------
var startingLink = {
  pano: 'P041',
  heading: -110,
  description: 'VJC'
};

var panoramas = {
  outsideVJC: undefined,

  P001: {
    description: 'Victoria Junior College - P001',
    links: [
      ['outsideVJC', 75],
      ['P002', 255]
    ],
    centerHeading: 240,
    tileUrl: './images/001.jpg'
  },

  P002: {
    description: 'Victoria Junior College - P002',
    links: [
      ['P003', 260],
      ['P001', 80]
    ],
    centerHeading: 255,
    tileUrl: './images/002.jpg'
  },

  P003: {
    description: 'Victoria Junior College - P003',
    links: [
      ['P004', 260],
      ['P002', 80]
    ],
    centerHeading: 190,
    tileUrl: './images/003.jpg'
  },

 P004: {
    description: 'Victoria Junior College - P004',
    links: [
      ['P005', -90],
      ['P003', 45]
    ],
    centerHeading: -20,
    tileUrl: './images/004.jpg'
  },

  P005: {
    description: 'Victoria Junior College - P005',
    links: [
      ['P004', 180],
      ['P006', -90],
      ['P037', 90],
      ['P036', 0]
    ],
    centerHeading: 80,
    tileUrl: './images/005.jpg'
  },

  P006: {
    description: 'Victoria Junior College - P006',
    links: [
      ['P005', 50,],
      ['P007', 250]
    ],
    centerHeading: 80,
    tileUrl: './images/006.jpg'
  },

  P007: {
    description: 'Victoria Junior College - P007',
    links: [
      ['P006', 120],
      ['P008', 210]
    ],
    centerHeading: 30,
    tileUrl: './images/007.jpg'
  },

  P008: {
    description: 'Victoria Junior College - P008',
    links: [
      ['P007', 75],
      ['P009', -125]
    ],
    centerHeading: -30,
    tileUrl: './images/008.jpg'
  },

  P009: {
    description: 'Victoria Junior College - P009',
    links: [
      ['P008', 185],
      ['P010', -85],
      ['P020', 5]
    ],
    centerHeading: 40,
    tileUrl: './images/009.jpg'
  },

  P010: {
    description: 'Victoria Junior College - P010',
    links: [
      ['P009', 100],
      ['P011', -90]
    ],
    centerHeading: 230,
    tileUrl: './images/010.jpg'
  },

  P011: {
    description: 'Victoria Junior College - P011',
    links: [
      ['P010', -20],
      ['P005', 70],
      ['P016', -110],
      ['P012', 160]
    ],
    centerHeading: 30,
    tileUrl: './images/011.jpg'
  },

  P012: {
    description: 'Victoria Junior College - P012',
    links: [
      ['P011', 80],
      ['P013', -55]
    ],
    centerHeading: 280,
    tileUrl: './images/012.jpg'
  },

  P013: {
    description: 'Victoria Junior College - P013',
    links: [
      ['P012', 35],
      ['P014', 260]
    ],
    centerHeading: 180,
    tileUrl: './images/013.jpg'
  },

  P014: {
    description: 'Victoria Junior College - P014',
    links: [
      ['P013', 75],
      ['P015', -105]
    ],
    centerHeading: 165,
    tileUrl: './images/014.jpg'
  },

  P015: {
    description: 'Victoria Junior College - P015',
    links: [
      ['P014', 80]
    ],
    centerHeading: 285,
    tileUrl: './images/015.jpg'
  },

  P016: {
    description: 'Victoria Junior College - P016',
    links: [
      ['P011', 70],
      ['P017', -200],
      ['P018', -20],
      ['P035', -110]
    ],
    centerHeading: 70,
    tileUrl: './images/016.jpg'
  },

  P017: {
    description: 'Victoria Junior College - P017',
    links: [
      ['P016', 80]

    ],
    centerHeading: 80,
    tileUrl: './images/017.jpg'
  },

  P018: {
    description: 'Victoria Junior College - P018',
    links: [
      ['P016', 70],
      ['P019', -110]

    ],
    centerHeading: 160,
    tileUrl: './images/018.jpg'
  },

  P019: {
    description: 'Victoria Junior College - P019',
    links: [
      ['P020', -130],
      ['P018', 60]
    ],
    centerHeading: 250,
    tileUrl: './images/019.jpg'
  },

  P020: {
    description: 'Victoria Junior College - P020',
    links: [
      ['P019', 150],
      ['P026', -110]
    ],
    centerHeading: 80,
    tileUrl: './images/020.jpg'
  },

  P022: {
    description: 'Victoria Junior College - P022',
    links: [
      ['P024', -104],
      ['P026', -14]
    ],
    centerHeading: 50,
    tileUrl: './images/022.jpg'
  },

  P024: {
    description: 'Victoria Junior College - P024',
    links: [
      ['P022', 80],
      ['P025', -100]
    ],
    centerHeading: 130,
    tileUrl: './images/024.jpg'
  },

  P025: {
    description: 'Victoria Junior College - P025',
    links: [
      ['P024', 75],
      ['P041', 255]
    ],
    centerHeading: -75,
    tileUrl: './images/025.jpg'
  },

  P026: {
    description: 'Victoria Junior College - P026',
    links: [
      ['P020', 70],
      ['P027', -110],
      ['P022', -20]
    ],
    centerHeading: 220,
    tileUrl: './images/026.jpg'
  },

  P027: {
    description: 'Victoria Junior College - P027',
    links: [
      ['P026', 65],
      ['P029', -115]
    ],
    centerHeading: 0,
    tileUrl: './images/027.jpg'
  },

  P029: {
    description: 'Victoria Junior College - P029',
    links: [
      ['P027', -100],
      ['P030', -30]
    ],
    centerHeading: 80,
    tileUrl: './images/029.jpg'
  },

  P030: {
    description: 'Victoria Junior College - P030',
    links: [
      ['P029', 90]

    ],
    centerHeading: 170,
    tileUrl: './images/030.jpg'
  },

  P033: {
    description: 'Victoria Junior College - P033',
    links: [
      ['P034', 80]
    ],
    centerHeading: -20,
    tileUrl: './images/033.jpg'
  },

  P034: {
    description: 'Victoria Junior College - P034',
    links: [
      ['P035', 70],
      ['P033', -110]
    ],
    centerHeading: 210,
    tileUrl: './images/034.jpg'
  },

  P035: {
    description: 'Victoria Junior College - P035',
    links: [
      ['P016', 70],
      ['P034', -110]
    ],
    centerHeading: 150,
    tileUrl: './images/035.jpg'
  },

  P036: {
    description: 'Victoria Junior College - P036',
    links: [

      ['P005', 50],
      ['P039', -12],
      ['P041', -75]
    ],
    centerHeading: 150,
    tileUrl: './images/036.jpg'
  },

  P037: {
    description: 'Victoria Junior College - P037',
    links: [
      ['P005', -90],
      ['P039', 0]
    ],
    centerHeading: -20,
    tileUrl: './images/037.jpg'
  },

  P039: {
    description: 'Victoria Junior College - P039',
    links: [
      ['P036', 70],
      ['P037', -20],
      ['P040', 160]
    ],
    centerHeading: 250,
    tileUrl: './images/039.jpg'
  },

  P040: {
    description: 'Victoria Junior College - P040',
    links: [
      ['P039', -10],
      ['P041', 170],
      ['P043', -100]
    ],
    centerHeading: 160,
    tileUrl: './images/040.jpg'
  },

  P041: {
    description: 'Victoria Junior College - P041',
    links: [
      ['P025', 0],
      ['P036', -60],
      ['P040', -120],
      ['P042', 110]
    ],
    centerHeading: 60,
    tileUrl: './images/041.jpg'
  },

  P042: {
    description: 'Victoria Junior College - P042',
    links: [
      ['P041', 55]
    ],
    centerHeading: 90,
    tileUrl: './images/042.jpg'
  },

  P043: {
    description: 'Victoria Junior College - P043',
    links: [
      ['P040', 0]
    ],
    centerHeading: -70,
    tileUrl: './images/043.jpg'
  },

  // TODO
  // P044 - P062

  P063: {
    description: 'Concourse',
    // TODO
    links: [
      ['P062', 0],
      ['P064', -86]
    ],
    centerHeading: 140,
    // TODO
    tileUrl: './images/063.jpg'
  },

  P064: {
    description: 'Concourse / Near General Office',
    links: [
      ['P063', 86],
      ['P065', 200]
    ],
    centerHeading: 75,
    tileUrl: './images/064.jpg'
  },

  P065: {
    description: 'General Office',
    links: [
      ['P064', -200],
      ['P066', 0]
    ],
    centerHeading: 90,
    tileUrl: './images/065.jpg'
  },

  // TODO

  P066: {
    description: 'General Office',
    links: [
      ['P065', 0],
      ['P067', 0]
    ],
    centerHeading: 0,
    tileUrl: './images/066.jpg'
  },

  P067: {
    description: 'General Office',
    links: [
      ['P066', 0],
      ['P068', 0]
    ],
    centerHeading: 0,
    tileUrl: './images/067.jpg'
  },

  P068: {
    description: 'Beside LT1',
    links: [
      ['P067', 0],
      ['P069', 0]
    ],
    centerHeading: 0,
    tileUrl: './images/068.jpg'
  },

};
<commit_msg>more images<commit_after>// Apparently locations are not needed.
var locations = {
  outsideVJC: { lat: 1.3065322, lng: 103.9207787 },
};

// ---------------------------------------
// EDIT THIS TO START FROM A CHOSEN IMAGE.
// ---------------------------------------
var startingLink = {
  pano: 'P045',
  heading: -110,
  description: 'VJC'
};

var panoramas = {
  outsideVJC: undefined,

  P001: {
    description: 'Victoria Junior College - P001',
    links: [
      ['outsideVJC', 75],
      ['P002', 255]
    ],
    centerHeading: 240,
    tileUrl: './images/001.jpg'
  },

  P002: {
    description: 'Victoria Junior College - P002',
    links: [
      ['P003', 260],
      ['P001', 80]
    ],
    centerHeading: 255,
    tileUrl: './images/002.jpg'
  },

  P003: {
    description: 'Victoria Junior College - P003',
    links: [
      ['P004', 260],
      ['P002', 80]
    ],
    centerHeading: 190,
    tileUrl: './images/003.jpg'
  },

 P004: {
    description: 'Victoria Junior College - P004',
    links: [
      ['P005', -90],
      ['P003', 45]
    ],
    centerHeading: -20,
    tileUrl: './images/004.jpg'
  },

  P005: {
    description: 'Victoria Junior College - P005',
    links: [
      ['P004', 180],
      ['P006', -90],
      ['P037', 90],
      ['P036', 0]
    ],
    centerHeading: 80,
    tileUrl: './images/005.jpg'
  },

  P006: {
    description: 'Victoria Junior College - P006',
    links: [
      ['P005', 50,],
      ['P007', 250]
    ],
    centerHeading: 80,
    tileUrl: './images/006.jpg'
  },

  P007: {
    description: 'Victoria Junior College - P007',
    links: [
      ['P006', 120],
      ['P008', 210]
    ],
    centerHeading: 30,
    tileUrl: './images/007.jpg'
  },

  P008: {
    description: 'Victoria Junior College - P008',
    links: [
      ['P007', 75],
      ['P009', -125]
    ],
    centerHeading: -30,
    tileUrl: './images/008.jpg'
  },

  P009: {
    description: 'Victoria Junior College - P009',
    links: [
      ['P008', 185],
      ['P010', -85],
      ['P020', 5]
    ],
    centerHeading: 40,
    tileUrl: './images/009.jpg'
  },

  P010: {
    description: 'Victoria Junior College - P010',
    links: [
      ['P009', 100],
      ['P011', -90]
    ],
    centerHeading: 230,
    tileUrl: './images/010.jpg'
  },

  P011: {
    description: 'Victoria Junior College - P011',
    links: [
      ['P010', -20],
      ['P005', 70],
      ['P016', -110],
      ['P012', 160]
    ],
    centerHeading: 30,
    tileUrl: './images/011.jpg'
  },

  P012: {
    description: 'Victoria Junior College - P012',
    links: [
      ['P011', 80],
      ['P013', -55]
    ],
    centerHeading: 280,
    tileUrl: './images/012.jpg'
  },

  P013: {
    description: 'Victoria Junior College - P013',
    links: [
      ['P012', 35],
      ['P014', 260]
    ],
    centerHeading: 180,
    tileUrl: './images/013.jpg'
  },

  P014: {
    description: 'Victoria Junior College - P014',
    links: [
      ['P013', 75],
      ['P015', -105]
    ],
    centerHeading: 165,
    tileUrl: './images/014.jpg'
  },

  P015: {
    description: 'Victoria Junior College - P015',
    links: [
      ['P014', 80]
    ],
    centerHeading: 285,
    tileUrl: './images/015.jpg'
  },

  P016: {
    description: 'Victoria Junior College - P016',
    links: [
      ['P011', 70],
      ['P017', -200],
      ['P018', -20],
      ['P035', -110]
    ],
    centerHeading: 70,
    tileUrl: './images/016.jpg'
  },

  P017: {
    description: 'Victoria Junior College - P017',
    links: [
      ['P016', 80]

    ],
    centerHeading: 80,
    tileUrl: './images/017.jpg'
  },

  P018: {
    description: 'Victoria Junior College - P018',
    links: [
      ['P016', 70],
      ['P019', -110]

    ],
    centerHeading: 160,
    tileUrl: './images/018.jpg'
  },

  P019: {
    description: 'Victoria Junior College - P019',
    links: [
      ['P020', -130],
      ['P018', 60]
    ],
    centerHeading: 250,
    tileUrl: './images/019.jpg'
  },

  P020: {
    description: 'Victoria Junior College - P020',
    links: [
      ['P019', 150],
      ['P026', -110]
    ],
    centerHeading: 80,
    tileUrl: './images/020.jpg'
  },

  P022: {
    description: 'Victoria Junior College - P022',
    links: [
      ['P024', -104],
      ['P026', -14]
    ],
    centerHeading: 50,
    tileUrl: './images/022.jpg'
  },

  P024: {
    description: 'Victoria Junior College - P024',
    links: [
      ['P022', 80],
      ['P025', -100]
    ],
    centerHeading: 130,
    tileUrl: './images/024.jpg'
  },

  P025: {
    description: 'Victoria Junior College - P025',
    links: [
      ['P024', 75],
      ['P041', 255]
    ],
    centerHeading: -75,
    tileUrl: './images/025.jpg'
  },

  P026: {
    description: 'Victoria Junior College - P026',
    links: [
      ['P020', 70],
      ['P027', -110],
      ['P022', -20]
    ],
    centerHeading: 220,
    tileUrl: './images/026.jpg'
  },

  P027: {
    description: 'Victoria Junior College - P027',
    links: [
      ['P026', 70],
      ['P028', -110]
    ],
    centerHeading: 0,
    tileUrl: './images/027.jpg'
  },

   P028: {
    description: 'Victoria Junior College - P028',
    links: [
      ['P027', 75],
      ['P029', 255]
    ],
    centerHeading: -90,
    tileUrl: './images/028.jpg'
  },

  P029: {
    description: 'Victoria Junior College - P029',
    links: [
      ['P027', -100],
      ['P030', -30]
    ],
    centerHeading: 80,
    tileUrl: './images/029.jpg'
  },

  P030: {
    description: 'Victoria Junior College - P030',
    links: [
      ['P029', 90],
      ['P031', -90]
    ],
    centerHeading: 170,
    tileUrl: './images/030.jpg'
  },

  P031: {
    description: 'Victoria Junior College - P031',
    links: [
      ['P030', 80],
      ['P033', -100]

    ],
    centerHeading: -30,
    tileUrl: './images/031.jpg'
  },

  P033: {
    description: 'Victoria Junior College - P033',
    links: [
      ['P031', 80],
      ['P034', -80]
    ],
    centerHeading: -70,
    tileUrl: './images/033.jpg'
  },

  P034: {
    description: 'Victoria Junior College - P034',
    links: [
      ['P035', -110],
      ['P033', 70]
    ],
    centerHeading: 110,
    tileUrl: './images/034.jpg'
  },

  P035: {
    description: 'Victoria Junior College - P035',
    links: [
      ['P016', -110],
      ['P034', 70]
    ],
    centerHeading: 50,
    tileUrl: './images/035.jpg'
  },

  P036: {
    description: 'Victoria Junior College - P036',
    links: [

      ['P005', 50],
      ['P039', -12],
      ['P041', -75]
    ],
    centerHeading: 150,
    tileUrl: './images/036.jpg'
  },

  P037: {
    description: 'Victoria Junior College - P037',
    links: [
      ['P005', -90],
      ['P039', 0],
      ['P048', 90]
    ],
    centerHeading: -20,
    tileUrl: './images/037.jpg'
  },

  P039: {
    description: 'Victoria Junior College - P039',
    links: [
      ['P036', 70],
      ['P037', -20],
      ['P040', 160]
    ],
    centerHeading: 250,
    tileUrl: './images/039.jpg'
  },

  P040: {
    description: 'Victoria Junior College - P040',
    links: [
      ['P039', -10],
      ['P041', 170],
      ['P043', -100]
    ],
    centerHeading: 160,
    tileUrl: './images/040.jpg'
  },

  P041: {
    description: 'Victoria Junior College - P041',
    links: [
      ['P025', 0],
      ['P036', -60],
      ['P040', -120],
      ['P042', 110]
    ],
    centerHeading: 60,
    tileUrl: './images/041.jpg'
  },

  P042: {
    description: 'Victoria Junior College - P042',
    links: [
      ['P041', 55]
    ],
    centerHeading: 90,
    tileUrl: './images/042.jpg'
  },

  P043: {
    description: 'Victoria Junior College - P043',
    links: [
      ['P040', 0],
      ['P049', 180]
    ],
    centerHeading: -70,
    tileUrl: './images/043.jpg'
  },

  P045: {
    description: 'Victoria Junior College - P045',
    links: [
      ['P049', 80],
      ['P047', -100]
    ],
    centerHeading: -25,
    tileUrl: './images/045.jpg'
  },

  P047: {
    description: 'Victoria Junior College - P047',
    links: [
      ['P045', 135],
      ['P048', 45]
    ],
    centerHeading: 13,
    tileUrl: './images/047.jpg'
  },

  P048: {
    description: 'Victoria Junior College - P048',
    links: [
      ['P047', 75],
      ['P037', -105]
    ],
    centerHeading: 150,
    tileUrl: './images/048.jpg'
  },

   P049: {
    description: 'Victoria Junior College - P049',
    links: [
      ['P043', 0],
      ['P045', -90]
    ],
    centerHeading: -115,
    tileUrl: './images/049.jpg'
  },

  // TODO
  // P044 - P062

  P063: {
    description: 'Concourse',
    // TODO
    links: [
      ['P062', 0],
      ['P064', -86]
    ],
    centerHeading: 140,
    // TODO
    tileUrl: './images/063.jpg'
  },

  P064: {
    description: 'Concourse / Near General Office',
    links: [
      ['P063', 86],
      ['P065', 200]
    ],
    centerHeading: 75,
    tileUrl: './images/064.jpg'
  },

  P065: {
    description: 'General Office',
    links: [
      ['P064', -200],
      ['P066', 0]
    ],
    centerHeading: 90,
    tileUrl: './images/065.jpg'
  },

  // TODO

  P066: {
    description: 'General Office',
    links: [
      ['P065', 0],
      ['P067', 0]
    ],
    centerHeading: 0,
    tileUrl: './images/066.jpg'
  },

  P067: {
    description: 'General Office',
    links: [
      ['P066', 0],
      ['P068', 0]
    ],
    centerHeading: 0,
    tileUrl: './images/067.jpg'
  },

  P068: {
    description: 'Beside LT1',
    links: [
      ['P067', 0],
      ['P069', 0]
    ],
    centerHeading: 0,
    tileUrl: './images/068.jpg'
  },

};
<|endoftext|>


<commit_before>data = {
  "bigbusiness": {
    "title": "Big business",
    "desc": "Labor’s carbon and mining taxes will pay for most of its other policies (and reduce pollution). Liberal policy will replace that revenue with spending on direct action and on a tax cut for all companies.",
    "alp": [
      {
        // revenue of 13519, minus compensation measures
        "label": "Carbon tax",
        "revenue": 6048
      },
      {
        "label": "Mining tax",
        "revenue": 3700
      }
    ],
    "lib": [
      {
        "label": "Paid parental leave levy",
        "revenue": 4400
      },
      {
        "label": "Direct-action emissions reduction fund",
        "spending": 1550
      },
      {
        "label": "Company tax rate cut",
        "spending": 4900
      }
    ]
  },
  "families": {
    "title": "Families",
    "desc": "The Liberal paid parental leave scheme will cost more than twice as much as Labor’s scheme, funded by cutting the existing Schoolkids Bonus and introducing a levy on large employers.",
    "alp": [
      {
        "label": "Schoolkids Bonus",
        "spending": 4641
      },
      {
        "label": "Paid parental leave",
        "spending": 3665
      }
    ],
    "lib": [
      {
        "label": "Paid parental leave",
        "spending": 9802
      }
    ]
  },
  "smallbusiness": {
    "title": "Small business",
    "desc": "The Liberals propose to cancel various small business tax cuts introduced by Labor.",
    "lib": [
      {
        "label": "Instant asset write-off",
        "revenue": 2905
      },
      {
        "label": "Interest withholding tax",
        "revenue": 405
      },
      {
        "label": "Tax loss carry back",
        "revenue": 950
      },
      {
        "label": "Accelerated depreciation for cars",
        "revenue": 425
      },
    ]
  },
  "superannuation": {
    "title": "Superannuation",
    "desc": "A key part of Labor’s mining tax package was an increase in everyone’s level of super, along with an additional boost for low-income earners.",
    "alp": [
      {
        "label": "12% super guarantee",
        "spending": 1640
      },
      {
        "label": "Low Income Super Contribution",
        "spending": 3722
      }
    ]
  },
  "infrastructure": {
    "title": "Infrastructure",
    "desc": "Tony Abbott wants to be the “infrastructure prime minister”, by cutting spending on rail and funding WestConnex, East-West Link, and the Brisbane Gateway instead.",
    "alp": [
      {
        "label": "Rail projects in Brisbane, Melbourne, Perth",
        "spending": 628
      }
    ],
    "lib": [
      {
        "label": "Road projects in Sydney, Melbourne, Brisbane",
        "spending": 4000
      }
    ]
  },
  "aid": {
    "title": "Foreign Aid",
    "desc": "To fund its road commitments, a Liberal government would significantly cut Australia’s xxxbn foreign aid budget in half.",
    "lib": [
      {
        "label": "Cuts to foreign aid",
        "revenue": 4500
      }
    ]
  },
  "publicservice": {
    "title": "The public service",
    "desc": "Most of the other proposed Liberal savings come from reduced public sector spending.",
    "lib": [
      {
        "label": "Not replacing public servants as they retire",
        "saving": 5212
      },
      {
        "label": "Cuts to existing public servant parental leave",
        "saving": 1229
      },
      {
        "label": "Reduced political advertising",
        "saving": 428
      }
    ]
  },
  "regions": {
    "title": "Rural and regional areas",
    "desc": "Labor has allocated funding for regional areas through an infrastructure fund and a deal with the states in the Murray basin, which the Liberal Party intends to cancel.",
    "alp": [
      {
        "label": "Regional Infrastructure Fund",
        "spending": 2485
      }
    ],
    "lib": [
      {
        "label": "Cuts to Murray-Darling Water Buybacks",
        "saving": 650
      },
    ]
  }
}
<commit_msg>shorten labels that are now too long<commit_after>data = {
  "bigbusiness": {
    "title": "Big business",
    "desc": "Labor’s carbon and mining taxes will pay for most of its other policies (and reduce pollution). Liberal policy will replace that revenue with spending on direct action and on a tax cut for all companies.",
    "alp": [
      {
        // revenue of 13519, minus compensation measures
        "label": "Carbon tax",
        "revenue": 6048
      },
      {
        "label": "Mining tax",
        "revenue": 3700
      }
    ],
    "lib": [
      {
        "label": "Paid parental leave levy",
        "revenue": 4400
      },
      {
        "label": "Direct-action emissions reduction",
        "spending": 1550
      },
      {
        "label": "Company tax rate cut",
        "spending": 4900
      }
    ]
  },
  "families": {
    "title": "Families",
    "desc": "The Liberal paid parental leave scheme will cost more than twice as much as Labor’s scheme, funded by cutting the existing Schoolkids Bonus and introducing a levy on large employers.",
    "alp": [
      {
        "label": "Schoolkids Bonus",
        "spending": 4641
      },
      {
        "label": "Paid parental leave",
        "spending": 3665
      }
    ],
    "lib": [
      {
        "label": "Paid parental leave",
        "spending": 9802
      }
    ]
  },
  "smallbusiness": {
    "title": "Small business",
    "desc": "The Liberals propose to cancel various small business tax cuts introduced by Labor.",
    "lib": [
      {
        "label": "Instant asset write-off",
        "revenue": 2905
      },
      {
        "label": "Interest withholding tax",
        "revenue": 405
      },
      {
        "label": "Tax loss carry back",
        "revenue": 950
      },
      {
        "label": "Accelerated depreciation for cars",
        "revenue": 425
      },
    ]
  },
  "superannuation": {
    "title": "Superannuation",
    "desc": "A key part of Labor’s mining tax package was an increase in everyone’s level of super, along with an additional boost for low-income earners.",
    "alp": [
      {
        "label": "12% super guarantee",
        "spending": 1640
      },
      {
        "label": "Low Income Super Contribution",
        "spending": 3722
      }
    ]
  },
  "infrastructure": {
    "title": "Infrastructure",
    "desc": "Tony Abbott wants to be the “infrastructure prime minister”, by cutting spending on rail and funding WestConnex, East-West Link, and the Brisbane Gateway instead.",
    "alp": [
      {
        "label": "Rail (Brisbane, Melbourne, Perth)",
        "spending": 628
      }
    ],
    "lib": [
      {
        "label": "Roads (Sydney, Melbourne, Brisbane)",
        "spending": 4000
      }
    ]
  },
  "aid": {
    "title": "Foreign Aid",
    "desc": "To fund its road commitments, a Liberal government would significantly cut Australia’s xxxbn foreign aid budget in half.",
    "lib": [
      {
        "label": "Cuts to foreign aid",
        "revenue": 4500
      }
    ]
  },
  "publicservice": {
    "title": "The public service",
    "desc": "Most of the other proposed Liberal savings come from reduced public sector spending.",
    "lib": [
      {
        "label": "Not replacing retiring public servants",
        "saving": 5212
      },
      {
        "label": "Cuts to public servant parental leave",
        "saving": 1229
      },
      {
        "label": "Reduced political advertising",
        "saving": 428
      }
    ]
  },
  "regions": {
    "title": "Rural and regional areas",
    "desc": "Labor has allocated funding for regional areas through an infrastructure fund and a deal with the states in the Murray basin, which the Liberal Party intends to cancel.",
    "alp": [
      {
        "label": "Regional Infrastructure Fund",
        "spending": 2485
      }
    ],
    "lib": [
      {
        "label": "Cuts to Murray-Darling Water Buybacks",
        "saving": 650
      },
    ]
  }
}
<|endoftext|>


<commit_before>var MongoClient = require('mongodb').MongoClient
    , settings = require('./config.js')
    , uuid = require('node-uuid')
    , request = require('request');

var fullMongoUrl = settings.mongoConfig.serverUrl + settings.mongoConfig.database;
var exports = module.exports = {};

MongoClient.connect(fullMongoUrl)
.then(function(db) {
    var movieCollection = db.collection('movies');

    exports.getAllMovies = function() {
        return movieCollection.find().toArray();
    };

    exports.getMovie = function(id) {
        if (!id) {
            return Promise.reject('You must provide an ID');
        }

        return movieCollection
            .find({ _id: id })
            .limit(1)
            .toArray()
            .then(function(listOfMovies) {
                if (listOfMovies.length === 0) {
                    throw new ReferenceError('Could not find movie with id of ' + id);
                }

                return listOfMovies[0];
            });
    };

    exports.updateMovie = function(id, newTitle, newRating) {
        if (!id) {
            return Promise.reject('You must provide an ID');
        }
        if (!newTitle) {
            return Promise.reject('You must provide a title');
        }
        if (
            newRating == null ||
            newRating === undefined ||
            newRating < 0 ||
            newRating > 5
        ) {
            return Promise.reject('You have provided an invalid rating');
        }

        return movieCollection
            .updateOne({ _id: id }, { title: newTitle, rating: newRating })
            .then(function() {
                return exports.getMovie(id);
            });
    };

    exports.deleteMovie = function (id) {
        if (!id) {
            return Promise.Reject('You must provide an ID');
        }

        return movieCollection
            .deleteOne({ _id: id })
            .then(function(deletionInfo) {
                if (deletionInfo.deletedCount === 0) {
                    throw new ReferenceError('Could not find the document with this id to delete');
                }

                return true;
            });
    };

    exports.movieExists = function (id) {
        return movieCollection.findOne({ _id: id }).then(function (movie) {
            return movie !== undefined;
        });
    };

    exports.addMovie = function (title, year) {
        movieCollection.findOne({ title: title }).then(function (res) {
            if (!res) {
                // Let's get some API in here
                request(encodeURI("http://omdbapi.com?t=" + title + "&y=" + year), function (error, response, body) {
                    var movie = JSON.parse(body);
                    if (!movie.error) {
                        var doc = {
                            _id: uuid.v4(),
                            title: movie.Title,
                            description: movie.Plot,
                            genre: movie.Genre.split(", "),
                            image: movie.Poster,
                            actors: movie.Actors,
                            director: movie.Director,
                            userRating: 0,
                            criticRating: movie.imdbRating
                        };

                        movieCollection.insertOne(doc);
                    }
                });
            }
        });
    };

    exports.getMoviesByIDs = function (ids) {
        return movieCollection.find({ _id: { $in: ids }}).toArray();
    };
});

<commit_msg>Search: grouped all movie get functions<commit_after>var MongoClient = require('mongodb').MongoClient
    , settings = require('./config.js')
    , uuid = require('node-uuid')
    , request = require('request');

var fullMongoUrl = settings.mongoConfig.serverUrl + settings.mongoConfig.database;
var exports = module.exports = {};

MongoClient.connect(fullMongoUrl)
.then(function(db) {
    var movieCollection = db.collection('movies');

    //= functions to get movie(s) ==============================================

    //get a list of all movies
    exports.getAllMovies = function() {
        return movieCollection.find().toArray();
    };

    //get a single movie by id
    exports.getMovie = function(id) {
        if (!id) {
            return Promise.reject('You must provide an ID');
        }

        return movieCollection
            .find({ _id: id })
            .limit(1)
            .toArray()
            .then(function(listOfMovies) {
                if (listOfMovies.length === 0) {
                    throw new ReferenceError('Could not find movie with id of ' + id);
                }

                return listOfMovies[0];
            });
    };

    //get a list of movies by a list of ids
    exports.getMoviesByIDs = function (ids) {
        return movieCollection.find({ _id: { $in: ids }}).toArray();
    };

    //get a list of movies by a title
    exports.getMoviesByTitle = function (title) {
        if (!title) {
            return Promise.reject('You must provide a title');
        }
        // TODO:
    };

    //get a list of movies by a genre
    exports.getMoviesByGenre = function (genre) {
        if (!genre) {
            return Promise.reject('You must provide a genre');
        }
        // TODO:
    };

    //get a list of movies by an actor
    exports.getMoviesByActor = function (actor) {
        if (!actor) {
            return Promise.reject('You must provide a actor');
        }
        // TODO:
    };

    //get a list of movies by director
    exports.getMoviesByDirector = function (director) {
        if (!director) {
            return Promise.reject('You must provide a director');
        }
        // TODO:
    };

    //= all other operations ===================================================

    exports.updateMovie = function(id, newTitle, newRating) {
        if (!id) {
            return Promise.reject('You must provide an ID');
        }
        if (!newTitle) {
            return Promise.reject('You must provide a title');
        }
        if (
            newRating == null ||
            newRating === undefined ||
            newRating < 0 ||
            newRating > 5
        ) {
            return Promise.reject('You have provided an invalid rating');
        }

        return movieCollection
            .updateOne({ _id: id }, { title: newTitle, rating: newRating })
            .then(function() {
                return exports.getMovie(id);
            });
    };

    exports.deleteMovie = function (id) {
        if (!id) {
            return Promise.Reject('You must provide an ID');
        }

        return movieCollection
            .deleteOne({ _id: id })
            .then(function(deletionInfo) {
                if (deletionInfo.deletedCount === 0) {
                    throw new ReferenceError('Could not find the document with this id to delete');
                }

                return true;
            });
    };

    exports.movieExists = function (id) {
        return movieCollection.findOne({ _id: id }).then(function (movie) {
            return movie !== undefined;
        });
    };

    exports.addMovie = function (title, year) {
        movieCollection.findOne({ title: title }).then(function (res) {
            if (!res) {
                // Let's get some API in here
                request(encodeURI("http://omdbapi.com?t=" + title + "&y=" + year), function (error, response, body) {
                    var movie = JSON.parse(body);
                    if (!movie.error) {
                        var doc = {
                            _id: uuid.v4(),
                            title: movie.Title,
                            description: movie.Plot,
                            genre: movie.Genre.split(", "),
                            image: movie.Poster,
                            actors: movie.Actors,
                            director: movie.Director,
                            userRating: 0,
                            criticRating: movie.imdbRating
                        };

                        movieCollection.insertOne(doc);
                    }
                });
            }
        });
    };
});

<|endoftext|>


<commit_before>(function() {
  var colors = ['4a833e','689952','87b168','a6c781','c7de9d','c7adbf','b694b4','a67ba8','95649b','834d8e'];
  var mainTable = document.querySelector('.main-table');
  var mainTableRows = mainTable.querySelectorAll('tr');

  function colorizeColumn(columnNumber) {
    var values = [];
    var scale;
    var minimum;
    var maximum;

    columnNumber = columnNumber - 1;

    for (var i = 2, length = mainTableRows.length; i < length; i++) {
      var value =  mainTableRows[i].cells[columnNumber].innerHTML;
      if (value !== '') {
        values.push(parseInt(value));
      }
    }

    minimum = Math.min.apply(null, values);
    maximum = Math.max.apply(null, values);

    scale = chroma.scale(colors).domain([minimum, maximum]);

    for (var i = 2, length = mainTableRows.length; i < length; i++) {
      var content = mainTableRows[i].cells[columnNumber].innerHTML;
      if (content !== '') {
        mainTableRows[i].cells[columnNumber].style.backgroundColor = scale(parseInt(content));
      }
    }
  }

  // transform the last time checked dates to relative time (e.g. "3 days ago")
  function timeAgo() {
    for (var i = 2, len = mainTableRows.length; i < len; i++) {
      var cell =  mainTableRows[i].cells[2];

      if (cell.innerHTML !== '') {
        cell.innerHTML = moment(cell.innerHTML, 'MMMM Do YYYY').fromNow();
      }
    }
  }

  colorizeColumn(4);
  colorizeColumn(5);

  timeAgo();
})();
<commit_msg>Change order of JS calls.<commit_after>(function() {
  var colors = ['4a833e','689952','87b168','a6c781','c7de9d','c7adbf','b694b4','a67ba8','95649b','834d8e'];
  var mainTable = document.querySelector('.main-table');
  var mainTableRows = mainTable.querySelectorAll('tr');

  function colorizeColumn(columnNumber) {
    var values = [];
    var scale;
    var minimum;
    var maximum;

    columnNumber = columnNumber - 1;

    for (var i = 2, length = mainTableRows.length; i < length; i++) {
      var value =  mainTableRows[i].cells[columnNumber].innerHTML;
      if (value !== '') {
        values.push(parseInt(value));
      }
    }

    minimum = Math.min.apply(null, values);
    maximum = Math.max.apply(null, values);

    scale = chroma.scale(colors).domain([minimum, maximum]);

    for (var i = 2, length = mainTableRows.length; i < length; i++) {
      var content = mainTableRows[i].cells[columnNumber].innerHTML;
      if (content !== '') {
        mainTableRows[i].cells[columnNumber].style.backgroundColor = scale(parseInt(content));
      }
    }
  }

  colorizeColumn(4);
  colorizeColumn(5);

  // transform the last time checked dates to relative time (e.g. "3 days ago")
  function timeAgo() {
    for (var i = 2, len = mainTableRows.length; i < len; i++) {
      var cell =  mainTableRows[i].cells[2];

      if (cell.innerHTML !== '') {
        cell.innerHTML = moment(cell.innerHTML, 'MMMM Do YYYY').fromNow();
      }
    }
  }

  timeAgo();
})();
<|endoftext|>


<commit_before>// steps = 0 => coming from whereis2.html i.e. not show steps
// steps = 1 => coming from whereis-text.html i.e. show steps
function loader(method, steps) {
    var state = document.readyState;

    if (typeof(localStorage) == 'undefined' ) {
	alert('Upgrade your browser as it does not support HTML5 localStorage.');
    }

    if (state == 'loaded' || state == 'complete') {
	method(steps);
    } else {
        if (navigator.userAgent.indexOf('Browzr') > -1) {
	    setTimeout(method(steps), 250);
        } else {
	    document.addEventListener('deviceready',method(steps),false);
	}
    }
}

$.extend({
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  },
  getParentUrlVars: function(){
    var vars = [], hash;
    var hashes = parent.window.location.href.slice(parent.window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getParentUrlVar: function(name){
    return $.getParentUrlVars()[name];
  }
});

function getLocationFromStore() {
    var gpsstore = new Lawnchair({table: 'mygps', adaptor: 'dom'});
    var destination;
    var to_lat;
    var to_long;
    var result = 0;

    // Getting URL var by its name
    var currentId = $.getUrlVar('id');

    if(currentId === undefined) {
	console.log("id is undefined, getting default store");
	// retrieve my data from my stores
	gpsstore.get('default', function(r) {
	    if(r !== null) {
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    } else {
	if(currentId == 0) currentId = "default";
	console.log("have an id value, GETTING store " + currentId);
	// retrieve my data from my stores
	gpsstore.get(currentId, function(r) {
	    if(r !== null) {
		console.log("DENTRO");
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    }

    if(result) {
	$('#main').append(destination + " (lat: " + to_lat + ", long: " + to_long + ")");
	// $('.content').append('
watch on map');
	$('#sidebar').show();
	if(currentId === undefined) {
	    $('#directions').attr('href', 'whereis-text.html');
	    $('#full-screen').attr('href', 'whereis2.html');
	    $('#delete').attr('href', 'delete.html');
	} else {
	    $('#directions').attr('href', 'whereis-text.html?id='+currentId);
	    $('#full-screen').attr('href', 'whereis2.html?id='+currentId);
	    $('#delete').attr('href', 'delete.html?id='+currentId);
	}
    } else {
	$('.content').append("No saved positions, park your car first!");
    }

}

var getLocation = function(steps, id) {
    console.log("getLocation()");
    var suc = function(p) {
	initializeMap(p, steps);
    };
    var fail = function() {
	alert("NOT ABLE TO GET THE CURRENT POSITION");
    };
    navigator.geolocation.getCurrentPosition(suc,fail);
}

function initializeMap(p, steps) {
    var gpsstore = new Lawnchair({table: 'mygps', adaptor: 'dom'});
    var destination;
    var to_lat;
    var to_long;
    var fromLatLng;
    var toLatLng;
    var directionsDisplay = new google.maps.DirectionsRenderer();
    var directionsService = new google.maps.DirectionsService();
    var map;
    var result = 0;

    console.log("actual latitude " + p.coords.latitude);
    console.log("actual longitude " + p.coords.longitude);

// Get object of URL parameters
// var allVars = $.getUrlVars();
// console.log("allVars");
// console.log(allVars);

    // Getting URL var by its nam
    var currentId = $.getUrlVar('id');

    if(currentId === undefined) {
	console.log("id is undefined, getting default store");
	// retrieve my data from my stores
	gpsstore.get('default', function(r) {
	    if(r !== null) {
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    } else {
	if(currentId == 0) currentId = "default";
	console.log("have an id value, getting store " + currentId);
	// retrieve my data from my stores
	gpsstore.get(currentId, function(r) {
	    if(r !== null) {
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    }

    if(!result) {
	console.log("no positions saved, exit...");
	$('.content').append("
No saved positions, park your car first!
");
	return;
    }

    // gpsstore.get('destination', function(r) {
    //     destination = r.value;
    // 	console.log("destination " + destination);
    // });

    //ATTENTION!! fake pos!!
    //toLatLng = new google.maps.LatLng(to_lat, to_long);
    toLatLng = new google.maps.LatLng(to_lat+1, to_long-2);

    fromLatLng = new google.maps.LatLng(p.coords.latitude, p.coords.longitude);
//    fromLatLng = new google.maps.LatLng(p.latitude, p.longitude);

    var request = {
	origin:fromLatLng,
	destination:toLatLng,
	travelMode: google.maps.DirectionsTravelMode.DRIVING
	// WALKING, BICYCLING
    };

    directionsService.route(request, function(result, status) {
	console.log("waiting for google service");
	console.log("status " + status);
	if (status == google.maps.DirectionsStatus.OK) {
	    console.log("google returned OK");
	    directionsDisplay.setDirections(result);
	    if(steps) {
		showSteps(result);
		return;
	    }
	}
    });

    var myOptions = {
	zoom:7,
	mapTypeId: google.maps.MapTypeId.ROADMAP,
    }

    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    directionsDisplay.setMap(map);
}

function showSteps(directionResult) {
    var myRoute = directionResult.routes[0].legs[0];
    var newText;
    newText = "
Total time
";
    newText += "
" + myRoute.duration.text + "
";
    newText += "
FROM
"
    newText += "
" + myRoute.start_address + "
";

    newText += "
Directions
"
    //TODO: paginate
    for (var i = 0; i < myRoute.steps.length; i++) {
	newText += "
" + i + " " + myRoute.steps[i].instructions;
	newText += " " + myRoute.steps[i].distance.text  + "
" ;
    }

    newText += "
DESTINATION
"
    newText += "
" + myRoute.end_address + "
";
    $('.ui-listview').html(newText).listview("refresh");
}

<commit_msg>whereis.js: more get id from iframe<commit_after>// steps = 0 => coming from whereis2.html i.e. not show steps
// steps = 1 => coming from whereis-text.html i.e. show steps
function loader(method, steps) {
    var state = document.readyState;

    if (typeof(localStorage) == 'undefined' ) {
	alert('Upgrade your browser as it does not support HTML5 localStorage.');
    }

    if (state == 'loaded' || state == 'complete') {
	method(steps);
    } else {
        if (navigator.userAgent.indexOf('Browzr') > -1) {
	    setTimeout(method(steps), 250);
        } else {
	    document.addEventListener('deviceready',method(steps),false);
	}
    }
}

$.extend({
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  },
  getParentUrlVars: function(){
    var vars = [], hash;
    var hashes = parent.window.location.href.slice(parent.window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getParentUrlVar: function(name){
    return $.getParentUrlVars()[name];
  }
});

function getLocationFromStore() {
    var gpsstore = new Lawnchair({table: 'mygps', adaptor: 'dom'});
    var destination;
    var to_lat;
    var to_long;
    var result = 0;

    // Getting URL var by its name
    var currentId = $.getUrlVar('id');

    if(currentId === undefined) {
	console.log("id is undefined, getting default store");
	// retrieve my data from my stores
	gpsstore.get('default', function(r) {
	    if(r !== null) {
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    } else {
	if(currentId == 0) currentId = "default";
	console.log("have an id value, GETTING store " + currentId);
	// retrieve my data from my stores
	gpsstore.get(currentId, function(r) {
	    if(r !== null) {
		console.log("DENTRO");
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    }

    if(result) {
	$('#main').append(destination + " (lat: " + to_lat + ", long: " + to_long + ")");
	// $('.content').append('
watch on map');
	$('#sidebar').show();
	if(currentId === undefined) {
	    $('#directions').attr('href', 'whereis-text.html');
	    $('#full-screen').attr('href', 'whereis2.html');
	    $('#delete').attr('href', 'delete.html');
	} else {
	    $('#directions').attr('href', 'whereis-text.html?id='+currentId);
	    $('#full-screen').attr('href', 'whereis2.html?id='+currentId);
	    $('#delete').attr('href', 'delete.html?id='+currentId);
	}
    } else {
	$('.content').append("No saved positions, park your car first!");
    }

}

var getLocation = function(steps, id) {
    console.log("getLocation()");
    var suc = function(p) {
	initializeMap(p, steps);
    };
    var fail = function() {
	alert("NOT ABLE TO GET THE CURRENT POSITION");
    };
    navigator.geolocation.getCurrentPosition(suc,fail);
}

function initializeMap(p, steps) {
    console.log("initializeMap");

    var gpsstore = new Lawnchair({table: 'mygps', adaptor: 'dom'});
    var destination;
    var to_lat;
    var to_long;
    var fromLatLng;
    var toLatLng;
    var directionsDisplay = new google.maps.DirectionsRenderer();
    var directionsService = new google.maps.DirectionsService();
    var map;
    var result = 0;

    console.log("actual latitude " + p.coords.latitude);
    console.log("actual longitude " + p.coords.longitude);

// Get object of URL parameters
// var allVars = $.getUrlVars();
// console.log("allVars");
// console.log(allVars);

    // Getting URL var by its name
    var currentId = $.getParentUrlVar('id');

    if(currentId === undefined) {
	console.log("id is undefined, getting default store");
	// retrieve my data from my stores
	gpsstore.get('default', function(r) {
	    if(r !== null) {
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    } else {
	if(currentId == 0) currentId = "default";
	console.log("have an id value, getting store " + currentId);
	// retrieve my data from my stores
	gpsstore.get(currentId, function(r) {
	    if(r !== null) {
		result = 1;
    		console.log(r);
		destination = r.value.name;
		to_lat = r.value.latitude;
		to_long = r.value.longitude;
	    }
	});
    }

    if(!result) {
	console.log("no positions saved, exit...");
	$('.content').append("
No saved positions, park your car first!
");
	return;
    }

    // gpsstore.get('destination', function(r) {
    //     destination = r.value;
    // 	console.log("destination " + destination);
    // });

    //ATTENTION!! fake pos!!
    //toLatLng = new google.maps.LatLng(to_lat, to_long);
    toLatLng = new google.maps.LatLng(to_lat+1, to_long-2);

    fromLatLng = new google.maps.LatLng(p.coords.latitude, p.coords.longitude);
//    fromLatLng = new google.maps.LatLng(p.latitude, p.longitude);

    var request = {
	origin:fromLatLng,
	destination:toLatLng,
	travelMode: google.maps.DirectionsTravelMode.DRIVING
	// WALKING, BICYCLING
    };

    directionsService.route(request, function(result, status) {
	console.log("waiting for google service");
	console.log("status " + status);
	if (status == google.maps.DirectionsStatus.OK) {
	    console.log("google returned OK");
	    directionsDisplay.setDirections(result);
	    if(steps) {
		showSteps(result);
		return;
	    }
	}
    });

    var myOptions = {
	zoom:7,
	mapTypeId: google.maps.MapTypeId.ROADMAP,
    }

    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    directionsDisplay.setMap(map);
}

function showSteps(directionResult) {
    var myRoute = directionResult.routes[0].legs[0];
    var newText;
    newText = "
Total time
";
    newText += "
" + myRoute.duration.text + "
";
    newText += "
FROM
"
    newText += "
" + myRoute.start_address + "
";

    newText += "
Directions
"
    //TODO: paginate
    for (var i = 0; i < myRoute.steps.length; i++) {
	newText += "
" + i + " " + myRoute.steps[i].instructions;
	newText += " " + myRoute.steps[i].distance.text  + "
" ;
    }

    newText += "
DESTINATION
"
    newText += "
" + myRoute.end_address + "
";
    $('.ui-listview').html(newText).listview("refresh");
}

<|endoftext|>