<commit_before>import AWS from 'aws-sdk'

const BASE_PATH = `https://s3.${process.env.AWS_REGION}.amazonaws.com/${process.env.AWS_BUCKET_NAME}/`

function urlToKey(url) {
  return url.replace(BASE_PATH, '')
}

function request(method, Key, customParams, customMethod) {
  const defaultParams = {
    Bucket: process.env.AWS_BUCKET_NAME,
  }

  if (Key) {
    defaultParams.Key = Key
  }

  const params = Object.assign({}, defaultParams, customParams)
  const s3 = new AWS.S3({ signatureVersion: 'v4' })

  if (customParams && 'Delete' in customParams) {
    params.Delete = {
      Objects: customParams.Delete.Objects,
    }
  }

  return new Promise((resolve, reject) => {
    let promise

    if (customMethod) {
      // Wrap this around a Promise since S3 SDK is not doing this for us
      promise = new Promise((customResolve, customReject) => {
        s3[method](customMethod, params, (err, data) => {
          if (err) {
            customReject(err)
          } else {
            customResolve(data)
          }
        })
      })
    } else {
      promise = s3[method](params).promise()
    }

    promise
      .then(data => {
        resolve({
          data,
          url: `${BASE_PATH}${Key}`,
        })
      })
      .catch(reject)
  })
}

export function hasAWSConfiguration() {
  return [
    'AWS_REGION',
    'AWS_ACCESS_KEY_ID',
    'AWS_SECRET_ACCESS_KEY',
    'AWS_BUCKET_NAME',
  ].find(field => {
    return process.env[field] === ''
  }) === undefined
}

export function putObject(Body, Key) {
  const params = {
    Body,
    ACL: 'public-read',
  }

  return request('putObject', Key, params)
}

export function deleteObjects(urls) {
  const params = {
    Delete: {
      Objects: urls.map(url => { return { Key: urlToKey(url) } }),
    },
  }

  return request('deleteObjects', null, params)
}

export function deleteObject(url) {
  return deleteObjects([url])
}
<commit_msg>Wrap basePath in own function to make sure env-variables are set<commit_after>import AWS from 'aws-sdk'

function getBasePath() {
  return `https://s3.${process.env.AWS_REGION}.amazonaws.com/${process.env.AWS_BUCKET_NAME}/`
}

function urlToKey(url) {
  return url.replace(getBasePath(), '')
}

function request(method, Key, customParams, customMethod) {
  const defaultParams = {
    Bucket: process.env.AWS_BUCKET_NAME,
  }

  if (Key) {
    defaultParams.Key = Key
  }

  const params = Object.assign({}, defaultParams, customParams)
  const s3 = new AWS.S3({ signatureVersion: 'v4' })

  if (customParams && 'Delete' in customParams) {
    params.Delete = {
      Objects: customParams.Delete.Objects,
    }
  }

  return new Promise((resolve, reject) => {
    let promise

    if (customMethod) {
      // Wrap this around a Promise since S3 SDK is not doing this for us
      promise = new Promise((customResolve, customReject) => {
        s3[method](customMethod, params, (err, data) => {
          if (err) {
            customReject(err)
          } else {
            customResolve(data)
          }
        })
      })
    } else {
      promise = s3[method](params).promise()
    }

    promise
      .then(data => {
        resolve({
          data,
          url: `${getBasePath()}${Key}`,
        })
      })
      .catch(reject)
  })
}

export function hasAWSConfiguration() {
  return [
    'AWS_REGION',
    'AWS_ACCESS_KEY_ID',
    'AWS_SECRET_ACCESS_KEY',
    'AWS_BUCKET_NAME',
  ].find(field => {
    return process.env[field] === ''
  }) === undefined
}

export function putObject(Body, Key) {
  const params = {
    Body,
    ACL: 'public-read',
  }

  return request('putObject', Key, params)
}

export function deleteObjects(urls) {
  const params = {
    Delete: {
      Objects: urls.map(url => { return { Key: urlToKey(url) } }),
    },
  }

  return request('deleteObjects', null, params)
}

export function deleteObject(url) {
  return deleteObjects([url])
}
<|endoftext|>


<commit_before>'use strict';

/* https://github.com/angular/protractor/blob/master/docs/toc.md */

describe('Pear2Pear', function() {
  var random = require('./random');

  beforeAll(function() {
    browser.get('index.html');

    browser.driver.executeScript('window.localStorage.clear();');
  });

  describe('1% core user', function() {
    beforeAll(function() {
      browser.get('index.html');
    });

    it('should create a project and share it', function() {
      /*
       * If it is not loaded in 10 seconds, we have a problem in mobiles
       * Please do not increase this
       */
      var timeout = 10000;
      var login = random.emailUser();
      var loginButton = element(by.css('input:enabled[type=submit]'));

      element(by.css('input#login')).sendKeys(login);

      browser.wait(function() {
        return loginButton.click().then(
          function() { return true; },
          function() { return false; }
        );
      }, timeout);

      var communityList = by.css('.communities');
      var communitySearchInput = by.css('.community-search input');
      var toggleCommunitySearchBtn = by.css('.sidebar-toggle');

      browser.wait(function() {
        return browser.isElementPresent(toggleCommunitySearchBtn);
      }, timeout);

      element(toggleCommunitySearchBtn).click();

      browser.wait(function() {
        return element(communitySearchInput).isDisplayed() &&
          element(communityList).isDisplayed();
      }, timeout);

      element(communitySearchInput).sendKeys('Testing Community');

      var newCommunityButton = by.css('.new-community-item .btn');

      browser.wait(function() {
        return browser.isElementPresent(newCommunityButton);
      }, timeout);

      element(newCommunityButton).click();

      var projectList = by.css('.projects');

      browser.wait(function() {
        return browser.isElementPresent(projectList);
      }, timeout);

      // Wait until pear has loaded the projects
      browser.wait(element(projectList).evaluate('projects.create'), timeout);

      var newProjectButton = by.css('.cta-btn');

      browser.wait(function() {
        return browser.isElementPresent(newProjectButton);
      }, timeout);

      element(newProjectButton).click();

      var editTitle = by.css('.project-title input');

      browser.wait(function() {
        return browser.isElementPresent(editTitle);
      }, timeout);

      element(editTitle).sendKeys('Testing');

      element(by.css('.swellrt-editor')).click();
      element(by.css('.wave-editor-on')).sendKeys('Grow your community with Pear2Pear');

      element(by.css('a.nav-chat')).click();

      var chatText = 'This is a nice opportunity to discuss about testing';

      element(by.css('.chat-send textarea')).sendKeys(chatText);
      element(by.css('.chat-input-button')).click();

      expect(element.all(by.css('.chat-message-text')).last().getText())
        .toEqual(chatText);

      browser.get('/#/frontpage');

      var comId = browser.driver.executeScript('return window.localStorage.communityId;');

      comId.then(function(communityId){
        expect(browser.getLocationAbsUrl()).toBe('/communities/' + communityId + '/projects?section=mydoing');
      });
    });
  });
});
<commit_msg>fix tests for bigger screens<commit_after>'use strict';

/* https://github.com/angular/protractor/blob/master/docs/toc.md */

describe('Pear2Pear', function() {
  var random = require('./random');

  beforeAll(function() {
    browser.get('index.html');

    browser.driver.executeScript('window.localStorage.clear();');
  });

  describe('1% core user', function() {
    beforeAll(function() {
      browser.get('index.html');
    });

    it('should create a project and share it', function() {
      /*
       * If it is not loaded in 10 seconds, we have a problem in mobiles
       * Please do not increase this
       */
      var timeout = 10000;
      var login = random.emailUser();
      var loginButton = element(by.css('input:enabled[type=submit]'));

      element(by.css('input#login')).sendKeys(login);

      browser.wait(function() {
        return loginButton.click().then(
          function() { return true; },
          function() { return false; }
        );
      }, timeout);

      var communityList = by.css('.communities');
      var communitySearchInput = by.css('.community-search input');
      var toggleCommunitySearchBtn = by.css('.sidebar-toggle');

      element(communitySearchInput).isDisplayed().then(function(displayed){
        if (!displayed){
          element(toggleCommunitySearchBtn).click();
        }
      });

      browser.wait(function() {
        return element(communitySearchInput).isDisplayed() &&
          element(communityList).isDisplayed();
      }, timeout);

      element(communitySearchInput).sendKeys('Testing Community');

      var newCommunityButton = by.css('.new-community-item .btn');

      browser.wait(function() {
        return browser.isElementPresent(newCommunityButton);
      }, timeout);

      element(newCommunityButton).click();

      var projectList = by.css('.projects');

      browser.wait(function() {
        return browser.isElementPresent(projectList);
      }, timeout);

      // Wait until pear has loaded the projects
      browser.wait(element(projectList).evaluate('projects.create'), timeout);

      var newProjectButton = by.css('.cta-btn');

      browser.wait(function() {
        return browser.isElementPresent(newProjectButton);
      }, timeout);

      element(newProjectButton).click();

      var editTitle = by.css('.project-title input');

      browser.wait(function() {
        return browser.isElementPresent(editTitle);
      }, timeout);

      element(editTitle).sendKeys('Testing');

      element(by.css('.swellrt-editor')).click();
      element(by.css('.wave-editor-on')).sendKeys('Grow your community with Pear2Pear');

      element(by.css('a.nav-chat')).click();

      var chatText = 'This is a nice opportunity to discuss about testing';

      element(by.css('.chat-send textarea')).sendKeys(chatText);
      element(by.css('.chat-input-button')).click();

      expect(element.all(by.css('.chat-message-text')).last().getText())
        .toEqual(chatText);

      browser.get('/#/frontpage');

      var comId = browser.driver.executeScript('return window.localStorage.communityId;');

      comId.then(function(communityId){
        expect(browser.getLocationAbsUrl()).toBe('/communities/' + communityId + '/projects?section=mydoing');
      });
    });
  });
});
<|endoftext|>


<commit_before>// convert one or more files
// convert
'use strict';
module.exports = function (server) {

var UploadHandler = require('./handler');
var Collection = require('./collection');
var Path = require('path');
var formidable = require('formidable');
var FileInfo = require('./fileinfo');
var zipFile = require('./zipfile');
var uuid = require('node-uuid');
var fs = require('fs');
var rmdirSync =require('./rmdir');
var childProcess = require('child_process');
var walk = require('walk');

server.jobManager.addJob('convert', {
  concurrency: 100, //number of concurrent jobs ran at the same time, default 50 if not specified
  work: function (params) {          //The job
      this.params = params;
      this.dirname = uuid.v4(); //generate random/unique repository name
      this.stderr = "", this.stdout = "", this.result=[], this.timeout = 1000*60*5;
      this.writeLogs = function(){
         fs.writeFile(this.dirname+"/stderr_"+this.dirname, this.stderr+".log", function(err) { //create stderr log
          if(err) {
              console.log(err);
          } else {
              console.log("Log stderr conversion created");
          }
          });
          fs.writeFile(this.dirname+"/stdout_"+this.dirname+".log", this.stdout, function(err) {//create stdout log
          if(err) {
              console.log(err);
          } else {
              console.log("Log stdout conversion created");
          }
          });
      }
      fs.mkdirSync(this.dirname); //create temporary folder for stocking assets to be converted
      fs.chmodSync(this.dirname, '777'); //set access mode R&W
      var stock = this;
      zipFile.unzipUrl(params.handler,params.collectionpath,params.assetpath,params.url,undefined,this.dirname,function(err,files){
        if(err){
          stock.stderr += err + '\n';
        }
        else{
          files.forEach(function(fileInfo){
            if(fileInfo.type == "model/collada+xml"){
              var output_path = fileInfo.path.stringBefore(".dae")+'/';
              fs.mkdirSync(output_path);
              fs.chmodSync(output_path, '777');
              var cmd = "cd "+output_path +" && "+server.collada2gltf + " -p -f \"" + fileInfo.path + "\" -o \"" + output_path + "\"";
              console.log( "--> exec "+cmd);
              stock.stdout += "--> exec "+cmd+"\n";
              var ls = childProcess.exec(cmd, function (error, stdout, stderr) {
                if (error) {
                  console.log("error in convert: "+error.stack);
                  stock.stderr += error.stack + '\n';
                  stock.stderr += error.code + '\n';
                  stock.stderr += error.signal + '\n';
                }
              });
              ls.on('exit', function (code, output) {
                console.log('Child process exited with exit code ' + code );
                stock.stdout += 'Child process exited with exit code ' + code+'\n';
                if (code !== 0) {
                    stock.stderr += 'Child process exited with exit code '+code+'\n';
                }
                else{
                  var options = {
                    listeners: {
                      file: function (root, fileStats, next) {
                        var item = {
                          name: fileStats.name,
                          path: Path.join(root,fileStats.name)
                        };
                        var fileInfoBis = new FileInfo(item, stock.params.collectionpath, stock.params.assetpath);
                        fileInfoBis.upload(stock.params.handler, function(err,file){
                          if(err){
                            stock.stderr += "upload "+file.name+" "+err+'\n';
                            console.log("upload "+file.name+" "+err);
                          }
                          else{
                            stock.result.push(file);
                            stock.stdout += "uploaded "+file.name+'\n';
                            console.log("uploaded "+file.name);
                          }
                        });
                        next();
                        }
                      , errors: function (root, nodeStatsArray, next) {
                          next();
                        }
                    }
                  };
                  walk.walkSync(output_path, options);
                }

              })
            }
            console.log("copyall",stock.params.copyall);
            if(stock.params.copyall){

              fileInfo.upload(stock.params.hander,function(err,file){
                if(err){
                  stock.stderr += "upload "+file.name+" "+err+'\n';
                  console.log("upload "+file.name+" "+err);
                }
                else{
                  stock.result.push(file);
                  stock.stdout += "uploaded "+file.name+'\n';
                  console.log("uploaded "+file.name);
                }
              })
            }
          });
        }
        stock.params.handler.handleResult(stock.dirname);
        setTimeout(function(){stock.finished = true;},stock.timeout);
    })
      // var stock = this;
      // if(params.files[0][0].path.indexOf("tmp/")!==-1){ // if it is a file unziped in tmp, move files
      //   params.files[0].forEach(function(fileInfo){
      //     fs.createReadStream(fileInfo.path).pipe(fs.createWriteStream(stock.dirname+'/'+fileInfo.name));
      //   })
      // }
      // else{  //Must be cache, copy
      //}
    }
});
server.jobManager.on('finish', function (job, worker) {
    worker.params.handler.handleResult("Convert job finished");
    rmdirSync(worker.dirname); //remove temporary directory
  });

UploadHandler.prototype.convert = function (collectionpath, assetpath) {
    var handler = this;
    var form = new formidable.IncomingForm();
    var tmpFiles = [];
    var files = [];
    var map = {}
    var counter = 1;
    var copyall = false;

    // var finish = function (err, asset) {
    //   if (err) {
    //     console.log('ERROR IN CONVERT FINISH');
    //     counter = -1;
    //     handler.handleError(err);
    //     return;
    //   }
    //   counter -= 1;

    //   // // here start conversion, and then call fileInfo.upload on converted files
    //   // // check copyall

    //     var results = [];
    //     if (files.length==0){
    //       return handler.handleError({message:'post did not send any files', statusCode:400});
    //     }
    //     files.forEach(function (fileInfo) {
    //       //fileInfo.initUrls(handler.req);
    //       var timeout = function (db) {
    //         fileInfo.delete(db,function(){}); // no callback
    //         console.log('timeout !! ' + fileInfo.name + ' was deleted');
    //       }
    //       setTimeout(timeout, 60 * 60 * 1000, handler.db);
    //     });
    //     server.jobManager.enqueue('convert', {'files':files,'handler':handler}); //Call convert job

    // };

     //form.uploadDir = FileInfo.options.tmpDir;
    form.on('fileBegin', function (name, file) {

      tmpFiles.push(file.path);
      var fileInfo = new FileInfo(file, collectionpath, assetpath);
      //fileInfo.safeName();
      map[file.path] = fileInfo;
      //files.push(fileInfo); -> this will happen later

    }).on('field', function (name, value) {
       if (name === 'copyall') {
          copyall=true;
       }
       if (name === 'url') {
        counter++; // one more result to POST
        var params = {};
        params.handler = handler, params.collectionpath = collectionpath, params.assetpath = assetpath, params.url = value, params.copyall =copyall;
        server.jobManager.enqueue('convert', params);
      }
    }).on('file', function (name, file) {

      // if (file.size ===0) {
      //   // form did not send a valid file
      //   return;
      // }
      // var fileInfo = map[file.path];
      // fileInfo.size = file.size;
      // fileInfo.type = Mime.lookup(fileInfo.name);

      // counter++; // so that 'end' does not finish
      // //                                                              no jar
      // zipFile.getAssetInfoFile(handler, collectionpath, assetpath, fileInfo.name, fileInfo.path, null, function(error,result) {
      //   if (error)
      //     finish(error);
      //   else {
      //     // turn {asset} into fileInfos
      //     var getFileInfos = function (results) {

      //       if (results.fileInfo && results.fileInfo.asset)
      //         files.push(results.fileInfo);

      //       if (results.children) {
      //         for (var i = 0; i < results.children.length; i++) {
      //           getFileInfos(results.children[i]);
      //         }
      //       }
      //     };
      //     getFileInfos(result);
      //     // finish(undefined);
      //   }
      // });

    }).on('aborted', function () {
      tmpFiles.forEach(function (file) {
        fs.unlinkSync(file);
      });
    }).on('error', function (e) {
      finish({message:'NONO, Could not parse form', statusCode:400});
    }).on('progress', function (bytesReceived, bytesExpected) {
      if (bytesReceived > FileInfo.options.maxPostSize) {
        handler.req.connection.destroy();
      }
    }).on('end',function(){
      console.log("form ended")
    });
    form.parse(handler.req);
  };

}<commit_msg>Touch<commit_after>// convert one or more files
// convert
'use strict';
module.exports = function (server) {

var UploadHandler = require('./handler');
var Collection = require('./collection');
var Path = require('path');
var formidable = require('formidable');
var FileInfo = require('./fileinfo');
var zipFile = require('./zipfile');
var uuid = require('node-uuid');
var fs = require('fs');
var rmdirSync =require('./rmdir');
var childProcess = require('child_process');
var walk = require('walk');

server.jobManager.addJob('convert', {
  concurrency: 100, //number of concurrent jobs ran at the same time, default 50 if not specified
  work: function (params) {          //The job
      this.params = params;
      this.dirname = uuid.v4(); //generate random/unique repository name
      this.stderr = "", this.stdout = "", this.result=[], this.timeout = 1000*60*5;
      this.writeLogs = function(){
         fs.writeFile(this.dirname+"/stderr_"+this.dirname, this.stderr+".log", function(err) { //create stderr log
          if(err) {
              console.log(err);
          } else {
              console.log("Log stderr conversion created");
          }
          });
          fs.writeFile(this.dirname+"/stdout_"+this.dirname+".log", this.stdout, function(err) {//create stdout log
          if(err) {
              console.log(err);
          } else {
              console.log("Log stdout conversion created");
          }
          });
      }
      fs.mkdirSync(this.dirname); //create temporary folder for stocking assets to be converted
      fs.chmodSync(this.dirname, '777'); //set access mode R&W
      var stock = this;
      zipFile.unzipUrl(params.handler,params.collectionpath,params.assetpath,params.url,undefined,this.dirname,function(err,files){
        if(err){
          stock.stderr += err + '\n';
        }
        else{
          files.forEach(function(fileInfo){
            if(fileInfo.type == "model/collada+xml"){
              var output_path = fileInfo.path.stringBefore(".dae")+'/';
              fs.mkdirSync(output_path);
              fs.chmodSync(output_path, '777');
              var cmd = "cd "+output_path +" && "+server.collada2gltf + " -p -f \"" + fileInfo.path + "\" -o \"" + output_path + "\"";
              console.log( "--> exec "+cmd);
              stock.stdout += "--> exec "+cmd+"\n";
              childProcess.exec("cd "+output_path);
              var ls1 = childProcess.exec("ls ");
              ls1.on('exit', function (code, output) {
                console.log(code, output);
              });
              var ls = childProcess.exec(cmd, function (error, stdout, stderr) {
                if (error) {
                  console.log("error in convert: "+error.stack);
                  stock.stderr += error.stack + '\n';
                  stock.stderr += error.code + '\n';
                  stock.stderr += error.signal + '\n';
                }
              });
              ls.on('exit', function (code, output) {
                console.log('Child process exited with exit code ' + code );
                stock.stdout += 'Child process exited with exit code ' + code+'\n';
                if (code !== 0) {
                    stock.stderr += 'Child process exited with exit code '+code+'\n';
                }
                else{
                  var options = {
                    listeners: {
                      file: function (root, fileStats, next) {
                        var item = {
                          name: fileStats.name,
                          path: Path.join(root,fileStats.name)
                        };
                        var fileInfoBis = new FileInfo(item, stock.params.collectionpath, stock.params.assetpath);
                        fileInfoBis.upload(stock.params.handler, function(err,file){
                          if(err){
                            stock.stderr += "upload "+file.name+" "+err+'\n';
                            console.log("upload "+file.name+" "+err);
                          }
                          else{
                            stock.result.push(file);
                            stock.stdout += "uploaded "+file.name+'\n';
                            console.log("uploaded "+file.name);
                          }
                        });
                        next();
                        }
                      , errors: function (root, nodeStatsArray, next) {
                          next();
                        }
                    }
                  };
                  walk.walkSync(output_path, options);
                }

              })
            }
            console.log("copyall",stock.params.copyall);
            if(stock.params.copyall){

              fileInfo.upload(stock.params.hander,function(err,file){
                if(err){
                  stock.stderr += "upload "+file.name+" "+err+'\n';
                  console.log("upload "+file.name+" "+err);
                }
                else{
                  stock.result.push(file);
                  stock.stdout += "uploaded "+file.name+'\n';
                  console.log("uploaded "+file.name);
                }
              })
            }
          });
        }
        stock.params.handler.handleResult(stock.dirname);
        setTimeout(function(){stock.finished = true;},stock.timeout);
    })
      // var stock = this;
      // if(params.files[0][0].path.indexOf("tmp/")!==-1){ // if it is a file unziped in tmp, move files
      //   params.files[0].forEach(function(fileInfo){
      //     fs.createReadStream(fileInfo.path).pipe(fs.createWriteStream(stock.dirname+'/'+fileInfo.name));
      //   })
      // }
      // else{  //Must be cache, copy
      //}
    }
});
server.jobManager.on('finish', function (job, worker) {
    worker.params.handler.handleResult("Convert job finished");
    rmdirSync(worker.dirname); //remove temporary directory
  });

UploadHandler.prototype.convert = function (collectionpath, assetpath) {
    var handler = this;
    var form = new formidable.IncomingForm();
    var tmpFiles = [];
    var files = [];
    var map = {}
    var counter = 1;
    var copyall = false;

    // var finish = function (err, asset) {
    //   if (err) {
    //     console.log('ERROR IN CONVERT FINISH');
    //     counter = -1;
    //     handler.handleError(err);
    //     return;
    //   }
    //   counter -= 1;

    //   // // here start conversion, and then call fileInfo.upload on converted files
    //   // // check copyall

    //     var results = [];
    //     if (files.length==0){
    //       return handler.handleError({message:'post did not send any files', statusCode:400});
    //     }
    //     files.forEach(function (fileInfo) {
    //       //fileInfo.initUrls(handler.req);
    //       var timeout = function (db) {
    //         fileInfo.delete(db,function(){}); // no callback
    //         console.log('timeout !! ' + fileInfo.name + ' was deleted');
    //       }
    //       setTimeout(timeout, 60 * 60 * 1000, handler.db);
    //     });
    //     server.jobManager.enqueue('convert', {'files':files,'handler':handler}); //Call convert job

    // };

     //form.uploadDir = FileInfo.options.tmpDir;
    form.on('fileBegin', function (name, file) {

      tmpFiles.push(file.path);
      var fileInfo = new FileInfo(file, collectionpath, assetpath);
      //fileInfo.safeName();
      map[file.path] = fileInfo;
      //files.push(fileInfo); -> this will happen later

    }).on('field', function (name, value) {
       if (name === 'copyall') {
          copyall=true;
       }
       if (name === 'url') {
        counter++; // one more result to POST
        var params = {};
        params.handler = handler, params.collectionpath = collectionpath, params.assetpath = assetpath, params.url = value, params.copyall =copyall;
        server.jobManager.enqueue('convert', params);
      }
    }).on('file', function (name, file) {

      // if (file.size ===0) {
      //   // form did not send a valid file
      //   return;
      // }
      // var fileInfo = map[file.path];
      // fileInfo.size = file.size;
      // fileInfo.type = Mime.lookup(fileInfo.name);

      // counter++; // so that 'end' does not finish
      // //                                                              no jar
      // zipFile.getAssetInfoFile(handler, collectionpath, assetpath, fileInfo.name, fileInfo.path, null, function(error,result) {
      //   if (error)
      //     finish(error);
      //   else {
      //     // turn {asset} into fileInfos
      //     var getFileInfos = function (results) {

      //       if (results.fileInfo && results.fileInfo.asset)
      //         files.push(results.fileInfo);

      //       if (results.children) {
      //         for (var i = 0; i < results.children.length; i++) {
      //           getFileInfos(results.children[i]);
      //         }
      //       }
      //     };
      //     getFileInfos(result);
      //     // finish(undefined);
      //   }
      // });

    }).on('aborted', function () {
      tmpFiles.forEach(function (file) {
        fs.unlinkSync(file);
      });
    }).on('error', function (e) {
      finish({message:'NONO, Could not parse form', statusCode:400});
    }).on('progress', function (bytesReceived, bytesExpected) {
      if (bytesReceived > FileInfo.options.maxPostSize) {
        handler.req.connection.destroy();
      }
    }).on('end',function(){
      console.log("form ended")
    });
    form.parse(handler.req);
  };

}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
const {actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});

XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);

const PREFERENCES_LOADED_EVENT = "home-pane-loaded";

// These "section" objects are formatted in a way to be similar to the ones from
// SectionsManager to construct the preferences view.
const PREFS_BEFORE_SECTIONS = [
  {
    id: "search",
    pref: {
      feed: "showSearch",
      titleString: "prefs_search_header",
    },
    icon: "chrome://browser/skin/search-glass.svg",
  },
  {
    id: "topsites",
    pref: {
      feed: "feeds.topsites",
      titleString: "settings_pane_topsites_header",
      descString: "prefs_topsites_description",
    },
    icon: "topsites",
    maxRows: 4,
    rowsPref: "topSitesRows",
  },
];
const PREFS_AFTER_SECTIONS = [
  {
    id: "snippets",
    pref: {
      feed: "feeds.snippets",
      titleString: "settings_pane_snippets_header",
      descString: "prefs_snippets_description",
    },
    icon: "info",
  },
];

// This CSS is added to the whole about:preferences page
const CUSTOM_CSS = `
#homeContentsGroup checkbox[src] .checkbox-icon {
  margin-inline-end: 8px;
  margin-inline-start: 4px;
  width: 16px;
}
#homeContentsGroup [data-subcategory] {
  margin-top: 14px;
}
#homeContentsGroup [data-subcategory] .section-checkbox {
  font-weight: 600;
}
#homeContentsGroup [data-subcategory] > vbox menulist {
  margin-top: 0;
  margin-bottom: 0;
}
`;

this.AboutPreferences = class AboutPreferences {
  init() {
    Services.obs.addObserver(this, PREFERENCES_LOADED_EVENT);
  }

  uninit() {
    Services.obs.removeObserver(this, PREFERENCES_LOADED_EVENT);
  }

  onAction(action) {
    switch (action.type) {
      case at.INIT:
        this.init();
        break;
      case at.UNINIT:
        this.uninit();
        break;
      case at.SETTINGS_OPEN:
        action._target.browser.ownerGlobal.openPreferences("paneHome", {origin: "aboutHome"});
        break;
      // This is used to open the web extension settings page for an extension
      case at.OPEN_WEBEXT_SETTINGS:
        action._target.browser.ownerGlobal.BrowserOpenAddonsMgr(`addons://detail/${encodeURIComponent(action.data)}`);
        break;
    }
  }

  async observe(window) {
    this.renderPreferences(window, await this.strings, [...PREFS_BEFORE_SECTIONS,
      ...this.store.getState().Sections, ...PREFS_AFTER_SECTIONS]);
  }

  /**
   * Get strings from a js file that the content page would have loaded. The
   * file should be a single variable assignment of a JSON/JS object of strings.
   */
  get strings() {
    return this._strings || (this._strings = new Promise(async resolve => {
      let data = {};
      try {
        const locale = Cc["@mozilla.org/browser/aboutnewtab-service;1"]
          .getService(Ci.nsIAboutNewTabService).activityStreamLocale;
        const request = await fetch(`resource://activity-stream/prerendered/${locale}/activity-stream-strings.js`);
        const text = await request.text();
        const [json] = text.match(/{[^]*}/);
        data = JSON.parse(json);
      } catch (ex) {
        Cu.reportError("Failed to load strings for Activity Stream about:preferences");
      }
      resolve(data);
    }));
  }

  /**
   * Render preferences to an about:preferences content window with the provided
   * strings and preferences structure.
   */
  renderPreferences({document, Preferences, gHomePane}, strings, prefStructure) {
    // Helper to create a new element and append it
    const createAppend = (tag, parent) => parent.appendChild(
      document.createXULElement(tag));

    // Helper to get strings and format with values if necessary
    const formatString = id => {
      if (typeof id !== "object") {
        return strings[id] || id;
      }
      let string = strings[id.id] || JSON.stringify(id);
      if (id.values) {
        Object.entries(id.values).forEach(([key, val]) => {
          string = string.replace(new RegExp(`{${key}}`, "g"), val);
        });
      }
      return string;
    };

    // Helper to link a UI element to a preference for updating
    const linkPref = (element, name, type) => {
      const fullPref = `browser.newtabpage.activity-stream.${name}`;
      element.setAttribute("preference", fullPref);
      Preferences.add({id: fullPref, type});

      // Prevent changing the UI if the preference can't be changed
      element.disabled = Preferences.get(fullPref).locked;
    };

    // Add in custom styling
    document.insertBefore(document.createProcessingInstruction("xml-stylesheet",
      `href="data:text/css,${encodeURIComponent(CUSTOM_CSS)}" type="text/css"`),
      document.documentElement);

    // Insert a new group immediately after the homepage one
    const homeGroup = document.getElementById("homepageGroup");
    const contentsGroup = homeGroup.insertAdjacentElement("afterend", homeGroup.cloneNode());
    contentsGroup.id = "homeContentsGroup";
    contentsGroup.setAttribute("data-subcategory", "contents");
    const caption = createAppend("caption", contentsGroup);
    const captionLabel = createAppend("label", caption);
    captionLabel.setAttribute("value", formatString("prefs_home_header"));
    const description = createAppend("description", contentsGroup);
    description.textContent = formatString("prefs_home_description");

    // Add preferences for each section
    prefStructure.forEach(sectionData => {
      const {
        id,
        pref: prefData,
        icon = "webextension",
        maxRows,
        rowsPref,
        shouldHidePref,
      } = sectionData;
      const {
        feed: name,
        titleString,
        descString,
        nestedPrefs = [],
      } = prefData || {};

      // Don't show any sections that we don't want to expose in preferences UI
      if (shouldHidePref) {
        return;
      }

      // Use full icon spec for certain protocols or fall back to packaged icon
      const iconUrl = !icon.search(/^(chrome|moz-extension|resource):/) ? icon :
        `resource://activity-stream/data/content/assets/glyph-${icon}-16.svg`;

      // Add the main preference for turning on/off a section
      const sectionVbox = createAppend("vbox", contentsGroup);
      sectionVbox.setAttribute("data-subcategory", id);
      const checkbox = createAppend("checkbox", sectionVbox);
      checkbox.classList.add("section-checkbox");
      checkbox.setAttribute("label", formatString(titleString));
      checkbox.setAttribute("src", iconUrl);
      linkPref(checkbox, name, "bool");

      // Specially add a link for stories
      if (id === "topstories") {
        const sponsoredHbox = createAppend("hbox", sectionVbox);
        sponsoredHbox.setAttribute("align", "center");
        sponsoredHbox.appendChild(checkbox);
        checkbox.classList.add("tail-with-learn-more");

        const link = createAppend("label", sponsoredHbox);
        link.classList.add("learn-sponsored");
        link.classList.add("text-link");
        link.setAttribute("href", sectionData.learnMore.link.href);
        link.textContent = formatString(sectionData.learnMore.link.id);
      }

      // Add more details for the section (e.g., description, more prefs)
      const detailVbox = createAppend("vbox", sectionVbox);
      detailVbox.classList.add("indent");
      if (descString) {
        const label = createAppend("label", detailVbox);
        label.classList.add("indent");
        label.textContent = formatString(descString);

        // Add a rows dropdown if we have a pref to control and a maximum
        if (rowsPref && maxRows) {
          const detailHbox = createAppend("hbox", detailVbox);
          detailHbox.setAttribute("align", "center");
          label.setAttribute("flex", 1);
          detailHbox.appendChild(label);

          // Add appropriate number of localized entries to the dropdown
          const menulist = createAppend("menulist", detailHbox);
          menulist.setAttribute("crop", "none");
          const menupopup = createAppend("menupopup", menulist);
          for (let num = 1; num <= maxRows; num++) {
            const plurals = formatString({id: "prefs_section_rows_option", values: {num}});
            const item = createAppend("menuitem", menupopup);
            item.setAttribute("label", PluralForm.get(num, plurals));
            item.setAttribute("value", num);
          }
          linkPref(menulist, rowsPref, "int");
        }
      }

      // Add a checkbox pref for any nested preferences
      nestedPrefs.forEach(nested => {
        const subcheck = createAppend("checkbox", detailVbox);
        subcheck.classList.add("indent");
        subcheck.setAttribute("label", formatString(nested.titleString));
        linkPref(subcheck, nested.name, "bool");
      });
    });

    // Update the visibility of the Restore Defaults btn based on checked prefs
    gHomePane.toggleRestoreDefaultsBtn();
  }
};

this.PREFERENCES_LOADED_EVENT = PREFERENCES_LOADED_EVENT;
const EXPORTED_SYMBOLS = ["AboutPreferences", "PREFERENCES_LOADED_EVENT"];
<commit_msg>Backport Bug 1429940 - Use HTML headings inside the label element for labeling groupbox elements in Preferences<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
const {actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});

XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);

const HTML_NS = "http://www.w3.org/1999/xhtml";

const PREFERENCES_LOADED_EVENT = "home-pane-loaded";

// These "section" objects are formatted in a way to be similar to the ones from
// SectionsManager to construct the preferences view.
const PREFS_BEFORE_SECTIONS = [
  {
    id: "search",
    pref: {
      feed: "showSearch",
      titleString: "prefs_search_header",
    },
    icon: "chrome://browser/skin/search-glass.svg",
  },
  {
    id: "topsites",
    pref: {
      feed: "feeds.topsites",
      titleString: "settings_pane_topsites_header",
      descString: "prefs_topsites_description",
    },
    icon: "topsites",
    maxRows: 4,
    rowsPref: "topSitesRows",
  },
];
const PREFS_AFTER_SECTIONS = [
  {
    id: "snippets",
    pref: {
      feed: "feeds.snippets",
      titleString: "settings_pane_snippets_header",
      descString: "prefs_snippets_description",
    },
    icon: "info",
  },
];

// This CSS is added to the whole about:preferences page
const CUSTOM_CSS = `
#homeContentsGroup checkbox[src] .checkbox-icon {
  margin-inline-end: 8px;
  margin-inline-start: 4px;
  width: 16px;
}
#homeContentsGroup [data-subcategory] {
  margin-top: 14px;
}
#homeContentsGroup [data-subcategory] .section-checkbox {
  font-weight: 600;
}
#homeContentsGroup [data-subcategory] > vbox menulist {
  margin-top: 0;
  margin-bottom: 0;
}
`;

this.AboutPreferences = class AboutPreferences {
  init() {
    Services.obs.addObserver(this, PREFERENCES_LOADED_EVENT);
  }

  uninit() {
    Services.obs.removeObserver(this, PREFERENCES_LOADED_EVENT);
  }

  onAction(action) {
    switch (action.type) {
      case at.INIT:
        this.init();
        break;
      case at.UNINIT:
        this.uninit();
        break;
      case at.SETTINGS_OPEN:
        action._target.browser.ownerGlobal.openPreferences("paneHome", {origin: "aboutHome"});
        break;
      // This is used to open the web extension settings page for an extension
      case at.OPEN_WEBEXT_SETTINGS:
        action._target.browser.ownerGlobal.BrowserOpenAddonsMgr(`addons://detail/${encodeURIComponent(action.data)}`);
        break;
    }
  }

  async observe(window) {
    this.renderPreferences(window, await this.strings, [...PREFS_BEFORE_SECTIONS,
      ...this.store.getState().Sections, ...PREFS_AFTER_SECTIONS]);
  }

  /**
   * Get strings from a js file that the content page would have loaded. The
   * file should be a single variable assignment of a JSON/JS object of strings.
   */
  get strings() {
    return this._strings || (this._strings = new Promise(async resolve => {
      let data = {};
      try {
        const locale = Cc["@mozilla.org/browser/aboutnewtab-service;1"]
          .getService(Ci.nsIAboutNewTabService).activityStreamLocale;
        const request = await fetch(`resource://activity-stream/prerendered/${locale}/activity-stream-strings.js`);
        const text = await request.text();
        const [json] = text.match(/{[^]*}/);
        data = JSON.parse(json);
      } catch (ex) {
        Cu.reportError("Failed to load strings for Activity Stream about:preferences");
      }
      resolve(data);
    }));
  }

  /**
   * Render preferences to an about:preferences content window with the provided
   * strings and preferences structure.
   */
  renderPreferences({document, Preferences, gHomePane}, strings, prefStructure) {
    // Helper to create a new element and append it
    const createAppend = (tag, parent) => parent.appendChild(
      document.createXULElement(tag));

    // Helper to get strings and format with values if necessary
    const formatString = id => {
      if (typeof id !== "object") {
        return strings[id] || id;
      }
      let string = strings[id.id] || JSON.stringify(id);
      if (id.values) {
        Object.entries(id.values).forEach(([key, val]) => {
          string = string.replace(new RegExp(`{${key}}`, "g"), val);
        });
      }
      return string;
    };

    // Helper to link a UI element to a preference for updating
    const linkPref = (element, name, type) => {
      const fullPref = `browser.newtabpage.activity-stream.${name}`;
      element.setAttribute("preference", fullPref);
      Preferences.add({id: fullPref, type});

      // Prevent changing the UI if the preference can't be changed
      element.disabled = Preferences.get(fullPref).locked;
    };

    // Add in custom styling
    document.insertBefore(document.createProcessingInstruction("xml-stylesheet",
      `href="data:text/css,${encodeURIComponent(CUSTOM_CSS)}" type="text/css"`),
      document.documentElement);

    // Insert a new group immediately after the homepage one
    const homeGroup = document.getElementById("homepageGroup");
    const contentsGroup = homeGroup.insertAdjacentElement("afterend", homeGroup.cloneNode());
    contentsGroup.id = "homeContentsGroup";
    contentsGroup.setAttribute("data-subcategory", "contents");
    createAppend("label", contentsGroup)
      .appendChild(document.createElementNS(HTML_NS, "h2"))
      .textContent = formatString("prefs_home_header");
    createAppend("description", contentsGroup)
      .textContent = formatString("prefs_home_description");

    // Add preferences for each section
    prefStructure.forEach(sectionData => {
      const {
        id,
        pref: prefData,
        icon = "webextension",
        maxRows,
        rowsPref,
        shouldHidePref,
      } = sectionData;
      const {
        feed: name,
        titleString,
        descString,
        nestedPrefs = [],
      } = prefData || {};

      // Don't show any sections that we don't want to expose in preferences UI
      if (shouldHidePref) {
        return;
      }

      // Use full icon spec for certain protocols or fall back to packaged icon
      const iconUrl = !icon.search(/^(chrome|moz-extension|resource):/) ? icon :
        `resource://activity-stream/data/content/assets/glyph-${icon}-16.svg`;

      // Add the main preference for turning on/off a section
      const sectionVbox = createAppend("vbox", contentsGroup);
      sectionVbox.setAttribute("data-subcategory", id);
      const checkbox = createAppend("checkbox", sectionVbox);
      checkbox.classList.add("section-checkbox");
      checkbox.setAttribute("label", formatString(titleString));
      checkbox.setAttribute("src", iconUrl);
      linkPref(checkbox, name, "bool");

      // Specially add a link for stories
      if (id === "topstories") {
        const sponsoredHbox = createAppend("hbox", sectionVbox);
        sponsoredHbox.setAttribute("align", "center");
        sponsoredHbox.appendChild(checkbox);
        checkbox.classList.add("tail-with-learn-more");

        const link = createAppend("label", sponsoredHbox);
        link.classList.add("learn-sponsored");
        link.classList.add("text-link");
        link.setAttribute("href", sectionData.learnMore.link.href);
        link.textContent = formatString(sectionData.learnMore.link.id);
      }

      // Add more details for the section (e.g., description, more prefs)
      const detailVbox = createAppend("vbox", sectionVbox);
      detailVbox.classList.add("indent");
      if (descString) {
        const label = createAppend("label", detailVbox);
        label.classList.add("indent");
        label.textContent = formatString(descString);

        // Add a rows dropdown if we have a pref to control and a maximum
        if (rowsPref && maxRows) {
          const detailHbox = createAppend("hbox", detailVbox);
          detailHbox.setAttribute("align", "center");
          label.setAttribute("flex", 1);
          detailHbox.appendChild(label);

          // Add appropriate number of localized entries to the dropdown
          const menulist = createAppend("menulist", detailHbox);
          menulist.setAttribute("crop", "none");
          const menupopup = createAppend("menupopup", menulist);
          for (let num = 1; num <= maxRows; num++) {
            const plurals = formatString({id: "prefs_section_rows_option", values: {num}});
            const item = createAppend("menuitem", menupopup);
            item.setAttribute("label", PluralForm.get(num, plurals));
            item.setAttribute("value", num);
          }
          linkPref(menulist, rowsPref, "int");
        }
      }

      // Add a checkbox pref for any nested preferences
      nestedPrefs.forEach(nested => {
        const subcheck = createAppend("checkbox", detailVbox);
        subcheck.classList.add("indent");
        subcheck.setAttribute("label", formatString(nested.titleString));
        linkPref(subcheck, nested.name, "bool");
      });
    });

    // Update the visibility of the Restore Defaults btn based on checked prefs
    gHomePane.toggleRestoreDefaultsBtn();
  }
};

this.PREFERENCES_LOADED_EVENT = PREFERENCES_LOADED_EVENT;
const EXPORTED_SYMBOLS = ["AboutPreferences", "PREFERENCES_LOADED_EVENT"];
<|endoftext|>


<commit_before>const neo4j = require('neo4j-driver').v1;

const driver = neo4j.driver(
  process.env.NEO4J_URL,
  neo4j.auth.basic(process.env.NEO4J_USER, process.env.NEO4J_PASSWORD)
);

let getUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (u:USER {email: $email}) WITH u \
      MATCH (u)-[:LIKES]->(t:TAG) WITH u,t \
      RETURN u, collect(t.name) as tags',
        { email: user.email }
      )
      .then(result => {
        session.close();
        if (result.records.length > 0) {
          resolve({ user: result });
        }
        resolve({ user: null });
      })
      .catch(err => {
        reject(err);
      });
  });
};

let createUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (user:USER {id: $userid, name: $name, email: $email}) RETURN user', {
        userid: user.id.toString(),
        name: user.name,
        email: user.email
      })
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let createArticle = article => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'CREATE (a:ARTICLE {id: $id, title: $title, url: $url, keywords: $keywords}) \
        MERGE (author:AUTHOR {name: $author}) \
        MERGE (a)-[r:AUTHORED_BY]->(author) \
        MERGE (provider:PROVIDER {name: $provider}) \
        MERGE (a)-[ap:PUBLISHED_BY]->(provider) \
        ON CREATE SET ap.published_on=$pubDate \
        RETURN a',
        {
          id: article._id.toString(),
          title: article.title.trim(),
          provider: article.provider.trim(),
          author: article.author.trim(),
          pubDate: article.pubDate.toString(),
          url: article.url,
          keywords: article.keywords.toString()
        }
      )
      .then(result => {
        session.close();
        resolve({ msg: result.records[0] });
      })
      .catch(err => reject(err));
  });
};

let articleCategoryRelationship = article => {
  const session = driver.session();
  session
    .run('MATCH (a:ARTICLE {id: $id}), (c:CATEGORY {id: $subCatId}) CREATE (a)-[r:HAS_CATEGORY]->(c) RETURN a', {
      id: article._id.toString(),
      subCatId: article.subcategory._id.toString()
    })
    .then(result => {
      session.close();
      console.log('Article node and Relationship created.');
      console.log(result.records[0]);
    })
    .catch(err => console.log(err));
};

let createCategory = category => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (c:CATEGORY {name: $name, id: $id}) RETURN c', {
        name: category.name,
        id: category._id.toString()
      })
      .then(result => {
        session.close();
        resolve({ msg: result.records });
      })
      .catch(err => reject(err));
  });
};

let createParentChildRelationship = item => {
  console.log(item);
  const session = driver.session();
  return new Promise((resolve, reject) => {
    if (item.parent) {
      session
        .run(
          'MATCH (a:CATEGORY {id: $parentId}), (b:CATEGORY {id: $childId}) \
          CREATE (b)-[:HAS_PARENT]->(a)',
          {
            parentId: item.parent._id.toString(),
            childId: item._id.toString()
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result.records });
        })
        .catch(err => reject(err));
    }
  });
};

let userAction = (user, action, item) => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    switch (action) {
    case 'like':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unlike':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:LIKES]->(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'dislike':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:DISLIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'undislike':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:DISLIKES]->(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'save':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LATER]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unsave':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:LATER]->(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'like-tag':
      session
        .run(
          'MERGE (t:TAG {name: $tag}) WITH t \
        MATCH (u:USER {email: $useremail}) \
        CREATE (u)-[r:LIKES]->(t) RETURN r',
          {
            useremail: user.email,
            tag: item
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unlike-tag':
      session
        .run(
          'MATCH (t:TAG {name: $tag}) \
        MATCH (u:USER {email: $useremail}) \
        MATCH (u)-[r:LIKES]->(t) DELETE r',
          {
            useremail: user.email,
            tag: item
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    default:
      break;
    }
  });
};

let userInterestIn = (userId, interestId, action) => {
  let query = null;
  if (action === 'add') {
    query = 'MATCH (u:USER {id: $userId}), (c:CATEGORY {id: $categoryId}) CREATE (u)-[r:INTERESTED_IN]->(c) RETURN r';
  } else {
    query = 'MATCH (u:USER {id: $userId})-[r:INTERESTED_IN]->(c:CATEGORY {id: $categoryId}) DELETE r';
  }
  // let query = 'MERGE (u:USER {id: $userId})-[r:INTERESTED_IN]->(c:CATEGORY {id: $categoryId}) return type(r)';
  const session = driver.session();
  session
    .run(query, {
      userId: userId.toString(),
      categoryId: interestId.toString()
    })
    .then(result => {
      session.close();
      console.log(result);
    })
    .catch(err => console.log(err));
};

let userRecommendation = (userid, interests) => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (u:USER {id: $userId})-[:LIKES]->(t:TAG) \
        WITH t, \
        collect(t.name) as tags \
        UNWIND tags as tag with tag \
        MATCH (a:ARTICLE),(a)-[pub:PUBLISHED_BY]->(p:PROVIDER) where a.keywords contains tag \
        RETURN DISTINCT a.id AS id, a.title AS title, pub.pubDate ORDER BY pub.pubDate DESC LIMIT 100 \
        UNION \
        MATCH (u:USER {id: $userId}), (a:ARTICLE)-[*]->(c:CATEGORY), (a)-[pub:PUBLISHED_BY]->(p:PROVIDER) \
        WHERE c.id in $interestList AND NOT (u)-[:DISLIKES]->(a) \
        RETURN DISTINCT a.id AS id, a.title AS title, pub.pubDate ORDER BY pub.pubDate DESC LIMIT 100',
        {
          userId: userid.toString(),
          interestList: interests
        }
      )
      .then(result => {
        resolve(result);
        session.close();
      })
      .catch(err => reject(err));
  });
};

let standardRecommendation = () => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE), (a)-[pub:PUBLISHED_BY]->(p:PROVIDER) \
      RETURN DISTINCT a.id AS id, a.title AS title, pub ORDER BY pub.pubDate DESC LIMIT 100'
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let userSavedList = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE)<-[:LATER]-(user:USER) WHERE user.email = $UserEmail \
        RETURN a.id AS id, a.title AS title, a.url AS url',
        {
          UserEmail: user[0].email
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let otherCategoryRecommendation = userId => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'match (u:USER)-[:INTERESTED_IN]-(c:CATEGORY)-[:INTERESTED_IN]-(ou:USER) with u,ou,c \
        match (ou)-[:INTERESTED_IN]-(oc:CATEGORY) \
        where u.id=$userid AND NOT c=oc \
        Return DISTINCT oc.name as name',
        {
          userid: userId.toString()
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

module.exports = {
  getUser,
  createUser,
  createParentChildRelationship,
  createCategory,
  createArticle,
  articleCategoryRelationship,
  userAction,
  userInterestIn,
  userRecommendation,
  standardRecommendation,
  userSavedList,
  otherCategoryRecommendation
};
<commit_msg>refactored article recommendation query<commit_after>const neo4j = require('neo4j-driver').v1;

const driver = neo4j.driver(
  process.env.NEO4J_URL,
  neo4j.auth.basic(process.env.NEO4J_USER, process.env.NEO4J_PASSWORD)
);

let getUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (u:USER {email: $email}) WITH u \
      MATCH (u)-[:LIKES]->(t:TAG) WITH u,t \
      RETURN u, collect(t.name) as tags',
        { email: user.email }
      )
      .then(result => {
        session.close();
        if (result.records.length > 0) {
          resolve({ user: result });
        }
        resolve({ user: null });
      })
      .catch(err => {
        reject(err);
      });
  });
};

let createUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (user:USER {id: $userid, name: $name, email: $email}) RETURN user', {
        userid: user.id.toString(),
        name: user.name,
        email: user.email
      })
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let createArticle = article => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'CREATE (a:ARTICLE {id: $id, title: $title, url: $url, keywords: $keywords}) \
        MERGE (author:AUTHOR {name: $author}) \
        MERGE (a)-[r:AUTHORED_BY]->(author) \
        MERGE (provider:PROVIDER {name: $provider}) \
        MERGE (a)-[ap:PUBLISHED_BY]->(provider) \
        ON CREATE SET ap.published_on=$pubDate \
        RETURN a',
        {
          id: article._id.toString(),
          title: article.title.trim(),
          provider: article.provider.trim(),
          author: article.author.trim(),
          pubDate: article.pubDate.toString(),
          url: article.url,
          keywords: article.keywords.toString()
        }
      )
      .then(result => {
        session.close();
        resolve({ msg: result.records[0] });
      })
      .catch(err => reject(err));
  });
};

let articleCategoryRelationship = article => {
  const session = driver.session();
  session
    .run('MATCH (a:ARTICLE {id: $id}), (c:CATEGORY {id: $subCatId}) CREATE (a)-[r:HAS_CATEGORY]->(c) RETURN a', {
      id: article._id.toString(),
      subCatId: article.subcategory._id.toString()
    })
    .then(result => {
      session.close();
      console.log('Article node and Relationship created.');
      console.log(result.records[0]);
    })
    .catch(err => console.log(err));
};

let createCategory = category => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (c:CATEGORY {name: $name, id: $id}) RETURN c', {
        name: category.name,
        id: category._id.toString()
      })
      .then(result => {
        session.close();
        resolve({ msg: result.records });
      })
      .catch(err => reject(err));
  });
};

let createParentChildRelationship = item => {
  console.log(item);
  const session = driver.session();
  return new Promise((resolve, reject) => {
    if (item.parent) {
      session
        .run(
          'MATCH (a:CATEGORY {id: $parentId}), (b:CATEGORY {id: $childId}) \
          CREATE (b)-[:HAS_PARENT]->(a)',
          {
            parentId: item.parent._id.toString(),
            childId: item._id.toString()
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result.records });
        })
        .catch(err => reject(err));
    }
  });
};

let userAction = (user, action, item) => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    switch (action) {
    case 'like':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unlike':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:LIKES]->(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'dislike':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:DISLIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'undislike':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:DISLIKES]->(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'save':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LATER]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unsave':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:LATER]->(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'like-tag':
      session
        .run(
          'MERGE (t:TAG {name: $tag}) WITH t \
        MATCH (u:USER {email: $useremail}) \
        CREATE (u)-[r:LIKES]->(t) RETURN r',
          {
            useremail: user.email,
            tag: item
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unlike-tag':
      session
        .run(
          'MATCH (t:TAG {name: $tag}) \
        MATCH (u:USER {email: $useremail}) \
        MATCH (u)-[r:LIKES]->(t) DELETE r',
          {
            useremail: user.email,
            tag: item
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    default:
      break;
    }
  });
};

let userInterestIn = (userId, interestId, action) => {
  let query = null;
  if (action === 'add') {
    query = 'MATCH (u:USER {id: $userId}), (c:CATEGORY {id: $categoryId}) CREATE (u)-[r:INTERESTED_IN]->(c) RETURN r';
  } else {
    query = 'MATCH (u:USER {id: $userId})-[r:INTERESTED_IN]->(c:CATEGORY {id: $categoryId}) DELETE r';
  }
  // let query = 'MERGE (u:USER {id: $userId})-[r:INTERESTED_IN]->(c:CATEGORY {id: $categoryId}) return type(r)';
  const session = driver.session();
  session
    .run(query, {
      userId: userId.toString(),
      categoryId: interestId.toString()
    })
    .then(result => {
      session.close();
      console.log(result);
    })
    .catch(err => console.log(err));
};

let userRecommendation = (userid, interests) => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (u:USER {id: $userId})-[:LIKES]->(t:TAG) WITH t, \
        collect(t.name) as tags UNWIND tags as tag with tag \
        MATCH (a:ARTICLE),(a)-[pub:PUBLISHED_BY]->(p:PROVIDER) \
        where a.keywords contains tag \
        RETURN DISTINCT a.id AS id, a.title AS title, pub.pubDate ORDER BY pub.pubDate DESC LIMIT 100 \
        UNION \
        MATCH (a:ARTICLE)-[*]->(c:CATEGORY) WHERE c.id in $interestList with a \
        MATCH (u:USER {id: $userId}) \
        MATCH (a)-[pub:PUBLISHED_BY]->(p:PROVIDER) WHERE NOT (u)-[:DISLIKES]->(a) \
        RETURN DISTINCT a.id AS id, a.title AS title, pub.pubDate ORDER BY pub.pubDate DESC LIMIT 200',
        {
          userId: userid.toString(),
          interestList: interests
        }
      )
      .then(result => {
        resolve(result);
        session.close();
      })
      .catch(err => reject(err));
  });
};

let standardRecommendation = () => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE), (a)-[pub:PUBLISHED_BY]->(p:PROVIDER) \
      RETURN DISTINCT a.id AS id, a.title AS title, pub ORDER BY pub.pubDate DESC LIMIT 100'
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let userSavedList = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE)<-[:LATER]-(user:USER) WHERE user.email = $UserEmail \
        RETURN a.id AS id, a.title AS title, a.url AS url',
        {
          UserEmail: user[0].email
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let otherCategoryRecommendation = userId => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'match (u:USER)-[:INTERESTED_IN]-(c:CATEGORY)-[:INTERESTED_IN]-(ou:USER) with u,ou,c \
        match (ou)-[:INTERESTED_IN]-(oc:CATEGORY) \
        where u.id=$userid AND NOT c=oc \
        Return DISTINCT oc.name as name',
        {
          userid: userId.toString()
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

module.exports = {
  getUser,
  createUser,
  createParentChildRelationship,
  createCategory,
  createArticle,
  articleCategoryRelationship,
  userAction,
  userInterestIn,
  userRecommendation,
  standardRecommendation,
  userSavedList,
  otherCategoryRecommendation
};
<|endoftext|>


<commit_before>'use strict';

const WorldstateObject = require('./WorldstateObject.js');

/**
 * Represents a Conclave challenge
 * @extends {WorldstateObject}
 */
class ConclaveChallenge extends WorldstateObject {
  /**
   * @param   {Object}             data            The challenge data
   * @param   {Object}             deps            The dependencies object
   * @param   {MarkdownSettings}   deps.mdConfig   The markdown settings
   * @param   {Translator}         deps.translator The string translator
   * @param   {TimeDateFunctions}  deps.timeDate   The time and date functions
   * @param   {string}             deps.locale     Locale to use for translations
   */
  constructor(data, {
    mdConfig, translator, timeDate, locale,
  }) {
    super(data, { timeDate });

    /**
     * The markdown settings
     * @type {MarkdownSettings}
     * @private
     */
    this.mdConfig = mdConfig;
    Object.defineProperty(this, 'mdConfig', { enumerable: false, configurable: false });

    /**
     * Time and date functions
     * @type {TimeDateFunctions}
     * @private
     */
    this.timeDate = timeDate;
    Object.defineProperty(this, 'timeDate', { enumerable: false, configurable: false });

    /**
     * The challenge's description text
     * @type {string}
     */
    this.description = translator.languageString(data.challengeTypeRefID, locale);

    /**
     * The time and date at which the challenge expires
     * @type {Date}
     */
    this.expiry = timeDate.parseDate(data.endDate);

    /**
     * The number of times that the challenge's objective needs to be completed
     * @type {number}
     */
    this.amount = data.params[0].v;

    /**
     * The PVP mode that the challenge must be completed in
     * @type {string}
     */
    this.mode = translator.conclaveMode(data.PVPMode, locale);

    /**
     * The challenge's category (daily, weekly...)
     * @type {string}
     */
    this.category = translator.conclaveCategory(data.Category, locale);

    /**
     * ETA string (at time of object creation)
     * @type {String}
     */
    this.eta = this.getEndString();

    /**
     * Whether or not this is expired (at time of object creation)
     * @type {boolean}
     */
    this.expired = this.isExpired();

    /**
     * Whether or not this is a daily conclave challenge.
     * @type {boolean}
     */
    this.daily = this.isDaily();

    /**
     * Whether or not this is the root challenge
     * @type {boolean}
     */
    this.rootChallenge = this.isRootChallenge();

    /**
     * the end string
     * @type {string}
     */
    this.endString = this.getEndString();

    /**
     * This challenge as a string
     * @type {string}
     */
    this.asString = this.toString();
  }

  /**
   * Get whether or not the challenge is daily
   * @returns {boolean}
   */
  isDaily() {
    return this.category.toLowerCase() === 'day';
  }

  /**
   * Get whether or not this is the weekly root challenge
   * @returns {boolean}
   */
  isRootChallenge() {
    return this.category.toLowerCase() === 'week_root';
  }

  /**
   * Get whether or not the challenge has expired
   * @returns {boolean}
   */
  isExpired() {
    return this.timeDate.fromNow(this.expiry) < 0;
  }

  /**
   * Get a string indicating how much time is left before the challenge expires
   * @returns {string}
   */
  getEndString() {
    const timeDelta = this.timeDate.fromNow(this.expiry);
    return this.timeDate.timeDeltaToString(timeDelta);
  }

  /**
   * The conclave challenge's string representation
   * @returns {string}
   */
  toString() {
    return `${this.description} on ${this.mode} ${this.amount} times in a ${this.category}`;
  }
}

module.exports = ConclaveChallenge;
<commit_msg>fix: activation for conclave<commit_after>'use strict';

const WorldstateObject = require('./WorldstateObject.js');

/**
 * Represents a Conclave challenge
 * @extends {WorldstateObject}
 */
class ConclaveChallenge extends WorldstateObject {
  /**
   * @param   {Object}             data            The challenge data
   * @param   {Object}             deps            The dependencies object
   * @param   {MarkdownSettings}   deps.mdConfig   The markdown settings
   * @param   {Translator}         deps.translator The string translator
   * @param   {TimeDateFunctions}  deps.timeDate   The time and date functions
   * @param   {string}             deps.locale     Locale to use for translations
   */
  constructor(data, {
    mdConfig, translator, timeDate, locale,
  }) {
    super(data, { timeDate });

    /**
     * The markdown settings
     * @type {MarkdownSettings}
     * @private
     */
    this.mdConfig = mdConfig;
    Object.defineProperty(this, 'mdConfig', { enumerable: false, configurable: false });

    /**
     * Time and date functions
     * @type {TimeDateFunctions}
     * @private
     */
    this.timeDate = timeDate;
    Object.defineProperty(this, 'timeDate', { enumerable: false, configurable: false });

    /**
     * The challenge's description text
     * @type {string}
     */
    this.description = translator.languageString(data.challengeTypeRefID, locale);

    /**
     * The time and date at which the challenge expires
     * @type {Date}
     */
    this.expiry = timeDate.parseDate(data.endDate);

    /**
     * The time and date at which the challenge starts
     * @type {Date}
     */
    this.activation = timeDate.parseDate(data.startDate);

    /**
     * The number of times that the challenge's objective needs to be completed
     * @type {number}
     */
    this.amount = data.params[0].v;

    /**
     * The PVP mode that the challenge must be completed in
     * @type {string}
     */
    this.mode = translator.conclaveMode(data.PVPMode, locale);

    /**
     * The challenge's category (daily, weekly...)
     * @type {string}
     */
    this.category = translator.conclaveCategory(data.Category, locale);

    /**
     * ETA string (at time of object creation)
     * @type {String}
     */
    this.eta = this.getEndString();

    /**
     * Whether or not this is expired (at time of object creation)
     * @type {boolean}
     */
    this.expired = this.isExpired();

    /**
     * Whether or not this is a daily conclave challenge.
     * @type {boolean}
     */
    this.daily = this.isDaily();

    /**
     * Whether or not this is the root challenge
     * @type {boolean}
     */
    this.rootChallenge = this.isRootChallenge();

    /**
     * the end string
     * @type {string}
     */
    this.endString = this.getEndString();

    /**
     * This challenge as a string
     * @type {string}
     */
    this.asString = this.toString();
  }

  /**
   * Get whether or not the challenge is daily
   * @returns {boolean}
   */
  isDaily() {
    return this.category.toLowerCase() === 'day';
  }

  /**
   * Get whether or not this is the weekly root challenge
   * @returns {boolean}
   */
  isRootChallenge() {
    return this.category.toLowerCase() === 'week_root';
  }

  /**
   * Get whether or not the challenge has expired
   * @returns {boolean}
   */
  isExpired() {
    return this.timeDate.fromNow(this.expiry) < 0;
  }

  /**
   * Get a string indicating how much time is left before the challenge expires
   * @returns {string}
   */
  getEndString() {
    const timeDelta = this.timeDate.fromNow(this.expiry);
    return this.timeDate.timeDeltaToString(timeDelta);
  }

  /**
   * The conclave challenge's string representation
   * @returns {string}
   */
  toString() {
    return `${this.description} on ${this.mode} ${this.amount} times in a ${this.category}`;
  }
}

module.exports = ConclaveChallenge;
<|endoftext|>


<commit_before>/**
 * We now use require.js: these are the mappings of our application
 *
 * (c) 2014 Edouard Lafargue, ed@lafargue.name
 * All rights reserved.
 */

require.config({

    baseUrl: 'js',

    // On the Beaglebone, some calls take forever
    waitSeconds: 0,

    paths: {
        app: 'app',
        tpl: 'tpl',

        // Below we manage our versions explicitely, so that
        // we can upgrade easily
        jquery: 'lib/jquery-1.11.0',
        backbone: 'lib/backbone-1.1.2',
        localstorage: 'lib/backbone.localStorage-1.1.7',
        underscore: 'lib/underscore-1.6.0',
        snap: 'lib/snap.svg-0.2.0',
	    text: 'lib/text',

        // Signal processing libs
        dsp: 'lib/dsp',
        chroma: 'lib/chroma',
        resampler: 'lib/resampler',

        bootstrap: 'lib/bootstrap',
        bootstrapslider: 'lib/bootstrap-slider-2.0.0',
        bootstrapeditable: 'lib/bootstrap-editable',
        bootbox: 'lib/bootbox',
        flot: 'lib/flot-0.8.3/jquery.flot',
        flot_time: 'lib/flot-0.8.3/jquery.flot.time',
        flot_resize: 'lib/flot-0.8.3/jquery.flot.resize',
        flot_selection: 'lib/flot-0.8.3/jquery.flot.selection',
        flot_fillbetween: 'lib/flot-0.8.3/jquery.flot.fillbetween',
        flot_windrose: 'lib/jquery.flot.windrose',
        flot_jumlib: 'lib/jquery.flot.JUMlib',
    },

    /*
     * Mappings to be able to switch our models (in-mem, browser, backend, etc)
     */
    map: {
        '*': {
            'socketio': '/socket.io/socket.io.js'
        }
    },

    shim: {
        'backbone': {
            deps: ['underscore', 'jquery' ],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        // Define Bootstrap's main JS, then all plugins which depend on it:
        'bootstrap': {
            deps: ['jquery']
        },
        'bootstrapslider': {
            deps: ['bootstrap']
        },
        'bootstrapeditable': {
            deps: ['bootstrap']
        },
        'utils': {
            exports: 'utils'
        },

        // The Flot library, along with our dependencies:
        'flot': {
            deps: ['jquery' ],
            exports: '$.plot'
        },
        'flot_time': {
            deps: ['flot']
        },
        'flot_resize': {
            deps: ['flot']
        },
        'flot_selection': {
            deps: ['flot']
        },
        'flot_fillbetween': {
            deps: ['flot']
        },
        'flot_jumlib': {
            deps: ['jquery', 'flot'],
            exports: '$.plot.JUMlib'
        },
        'flot_windrose': {
            deps: ['flot', 'flot_jumlib']
        }

    }
});

// We are going to manage a single global variable for VizApp that contains the few things that have to
// be defined application-wise:
var vizapp = {

    // type is a helper to avoid code duplication depending on the
    // run mode of the application. Can be:
    //   - server : use a remote server for device connection & database
    //   - cordova: run as an embedded Cordova application on Android
    //   - others to be defined
    type: "server"
};

var router;

require(['jquery', 'backbone', 'app/router', 'app/models/settings','app/instruments/instrumentmanager', 'app/linkmanager',
         'app/outputs/outputmanager', 'app/models/instrument'], function($, Backbone, Router, Settings, InstrumentManager, LinkManager,
                                                                  OutputManager, Instrument) {
        // Get our settings here, and
        // share them afterwards, rather than requesting them
        // everytime...
        settings = new Settings({id: 1 });

        // Create our instrument manager: in charge of creating/deleting
        // instruments as necessary, as well as providing a list of
        // instruments to other parts who need those
        instrumentManager = new InstrumentManager();

        // Create our output manager: in charge of connecting instrument outputs
        // to third party data consumers.
        outputManager = new OutputManager();

        settings.fetch({success: function() {

            // Create our link manager: it is in charge of talking
            // to the server-side controller interface through a socket.io
            // web socket. It is passed to all views that need it.
            linkManager =  new LinkManager();

            var insId = settings.get('currentInstrument');
            if (insId != null) {
                    router = new Router();
                    router.switchinstrument(insId, false); // second argument prevents router from closing instrument
                    Backbone.history.start();
            } else {
           router = new Router();
           Backbone.history.start();
	       }
        },
		error: function() {
		// Probably first run: settings don't exist on the backend
		router = new Router();
		Backbone.history.start();
	}
                       });
});

<commit_msg>Add definition for indexeedb<commit_after>/**
 * We now use require.js: these are the mappings of our application
 *
 * (c) 2014 Edouard Lafargue, ed@lafargue.name
 * All rights reserved.
 */

require.config({

    baseUrl: 'js',

    // On the Beaglebone, some calls take forever
    waitSeconds: 0,

    paths: {
        app: 'app',
        tpl: 'tpl',

        // Below we manage our versions explicitely, so that
        // we can upgrade easily
        jquery: 'lib/jquery-1.11.0',
        backbone: 'lib/backbone-1.1.2',
        localstorage: 'lib/backbone.localStorage-1.1.7',
        bbindexeddb: 'lib/backbone-indexeddb',
        underscore: 'lib/underscore-1.6.0',
        snap: 'lib/snap.svg-0.2.0',
	    text: 'lib/text',

        // Signal processing libs
        dsp: 'lib/dsp',
        chroma: 'lib/chroma',
        resampler: 'lib/resampler',

        bootstrap: 'lib/bootstrap',
        bootstrapslider: 'lib/bootstrap-slider-2.0.0',
        bootstrapeditable: 'lib/bootstrap-editable',
        bootbox: 'lib/bootbox',
        flot: 'lib/flot-0.8.3/jquery.flot',
        flot_time: 'lib/flot-0.8.3/jquery.flot.time',
        flot_resize: 'lib/flot-0.8.3/jquery.flot.resize',
        flot_selection: 'lib/flot-0.8.3/jquery.flot.selection',
        flot_fillbetween: 'lib/flot-0.8.3/jquery.flot.fillbetween',
        flot_windrose: 'lib/jquery.flot.windrose',
        flot_jumlib: 'lib/jquery.flot.JUMlib',
    },

    /*
     * Mappings to be able to switch our models (in-mem, browser, backend, etc)
     */
    map: {
        '*': {
            'socketio': '/socket.io/socket.io.js'
        }
    },

    shim: {
        'backbone': {
            deps: ['underscore', 'jquery' ],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        // Define Bootstrap's main JS, then all plugins which depend on it:
        'bootstrap': {
            deps: ['jquery']
        },
        'bootstrapslider': {
            deps: ['bootstrap']
        },
        'bootstrapeditable': {
            deps: ['bootstrap']
        },
        'utils': {
            exports: 'utils'
        },

        // The Flot library, along with our dependencies:
        'flot': {
            deps: ['jquery' ],
            exports: '$.plot'
        },
        'flot_time': {
            deps: ['flot']
        },
        'flot_resize': {
            deps: ['flot']
        },
        'flot_selection': {
            deps: ['flot']
        },
        'flot_fillbetween': {
            deps: ['flot']
        },
        'flot_jumlib': {
            deps: ['jquery', 'flot'],
            exports: '$.plot.JUMlib'
        },
        'flot_windrose': {
            deps: ['flot', 'flot_jumlib']
        }

    }
});

// We are going to manage a single global variable for VizApp that contains the few things that have to
// be defined application-wise:
var vizapp = {

    // type is a helper to avoid code duplication depending on the
    // run mode of the application. Can be:
    //   - server : use a remote server for device connection & database
    //   - cordova: run as an embedded Cordova application on Android
    //   - others to be defined
    type: "server"
};

var router;

require(['jquery', 'backbone', 'app/router', 'app/models/settings','app/instruments/instrumentmanager', 'app/linkmanager',
         'app/outputs/outputmanager', 'app/models/instrument'], function($, Backbone, Router, Settings, InstrumentManager, LinkManager,
                                                                  OutputManager, Instrument) {
        // Get our settings here, and
        // share them afterwards, rather than requesting them
        // everytime...
        settings = new Settings({id: 1 });

        // Create our instrument manager: in charge of creating/deleting
        // instruments as necessary, as well as providing a list of
        // instruments to other parts who need those
        instrumentManager = new InstrumentManager();

        // Create our output manager: in charge of connecting instrument outputs
        // to third party data consumers.
        outputManager = new OutputManager();

        settings.fetch({success: function() {

            // Create our link manager: it is in charge of talking
            // to the server-side controller interface through a socket.io
            // web socket. It is passed to all views that need it.
            linkManager =  new LinkManager();

            var insId = settings.get('currentInstrument');
            if (insId != null) {
                    router = new Router();
                    router.switchinstrument(insId, false); // second argument prevents router from closing instrument
                    Backbone.history.start();
            } else {
           router = new Router();
           Backbone.history.start();
	       }
        },
		error: function() {
		// Probably first run: settings don't exist on the backend
		router = new Router();
		Backbone.history.start();
	}
                       });
});

<|endoftext|>


<commit_before>var url = require("url");
var http = require("http");
var ideal = require("ideal");
var oden = module.parent.exports;

oden.HttpClientRequest = ideal.Observable.clone().newSlots({
	type: "oden.HttpClientRequest",

	url: null,
	method: "GET",
	headers: null,

	nodeRequest: null,

	error: null,
	response: null
}).setSlots({
	init: function()
	{
		ideal.Observable.init.call(this);
		this.setUrl(oden.Url.clone());
		this.setHeaders(map({
			Accept: "*/*"
		}));
	},

	setUrlString: function(urlString)
	{
		this.url().setString(urlString);
		return this;
	},

	start: function()
	{
		var self = this;
		var url = this.url();
		var nodeRequest = http.request({
			host: url.host(),
			port: url.port(),
			method: this.method(),
			path: url.resource(),
			agent: false,
			headers: this.headers().jsMap()
		}, function(response){
			self.receivedResponse(response);
		});

		nodeRequest.on('error', function(e){
			self.failed(e);
		});

		nodeRequest.end();

		this.setNodeRequest(nodeRequest);

		return this;
	},

	setHeader: function(name, value)
	{
		this.headers().atPut(name, value);
		return this;
	},

	receivedResponse: function(nodeResponse)
	{
		var response = oden.HttpClientResponse.clone().setNodeResponse(nodeResponse);
		response.addObserver(this);
		response.start();
		this.setResponse(response);
		this.sendNotification("receivedResponse");
	},

	httpClientResponseEnded: function()
	{
		this.sendNotification("completed");
	},

	failed: function(error)
	{
		this.setError(error);
		this.sendNotification("failed");
	},

	cancel: function()
	{
		if (this.nodeRequest())
		{
			this.nodeRequest().abort();
		}

		this.removeAllObservers();
		return this;
	}
});

String.prototype.httpGet = function()
{
	return oden.HttpClientRequest.clone().setUrl(this.asUrl()).start();
}<commit_msg>post body<commit_after>var url = require("url");
var http = require("http");
var ideal = require("ideal");
var oden = module.parent.exports;

oden.HttpClientRequest = ideal.Observable.clone().newSlots({
	type: "oden.HttpClientRequest",

	url: null,
	method: "GET",
	headers: null,
	body: "",

	nodeRequest: null,

	error: null,
	response: null
}).setSlots({
	init: function()
	{
		ideal.Observable.init.call(this);
		this.setUrl(oden.Url.clone());
		this.setHeaders(map({
			Accept: "*/*"
		}));
	},

	setUrlString: function(urlString)
	{
		this.url().setString(urlString);
		return this;
	},

	start: function()
	{
		var self = this;
		var url = this.url();
		var nodeRequest = http.request({
			host: url.host(),
			port: url.port(),
			method: this.method(),
			path: url.resource(),
			agent: false,
			headers: this.headers().jsMap()
		});

		nodeRequest.end(this.body());

		nodeRequest.on('response', function(response){
			self.receivedResponse(response);
		});

		nodeRequest.on('error', function(e){
			self.failed(e);
		});

		nodeRequest.end();

		this.setNodeRequest(nodeRequest);

		return this;
	},

	setHeader: function(name, value)
	{
		this.headers().atPut(name, value);
		return this;
	},

	receivedResponse: function(nodeResponse)
	{
		var response = oden.HttpClientResponse.clone().setNodeResponse(nodeResponse);
		response.addObserver(this);
		response.start();
		this.setResponse(response);
		this.sendNotification("receivedResponse");
	},

	httpClientResponseEnded: function()
	{
		this.sendNotification("completed");
	},

	failed: function(error)
	{
		this.setError(error);
		this.sendNotification("failed");
	},

	cancel: function()
	{
		if (this.nodeRequest())
		{
			this.nodeRequest().abort();
		}

		this.removeAllObservers();
		return this;
	}
});

String.prototype.httpGet = function()
{
	return oden.HttpClientRequest.clone().setUrl(this.asUrl()).start();
}<|endoftext|>


<commit_before>/*global describe, it, before, beforeEach, after, afterEach */

var assert = require('assert'),
  should = require('should'),
  geo = require('../lib/geo');

describe('geo', function () {
  this.timeout(0);

  describe('#isRooftop()', function () {
    it('should return true when the input is rooftop', function () {
      geo.isRooftop({
        "results": [{
          "address_components": [{
            "long_name": "1600",
            "short_name": "1600",
            "types": ["street_number"]
          }, {
            "long_name": "Amphitheatre Pkwy",
            "short_name": "Amphitheatre Pkwy",
            "types": ["route"]
          }, {
            "long_name": "Mountain View",
            "short_name": "Mountain View",
            "types": ["locality", "political"]
          }, {
            "long_name": "Santa Clara",
            "short_name": "Santa Clara",
            "types": ["administrative_area_level_2", "political"]
          }, {
            "long_name": "California",
            "short_name": "CA",
            "types": ["administrative_area_level_1", "political"]
          }, {
            "long_name": "United States",
            "short_name": "US",
            "types": ["country", "political"]
          }, {
            "long_name": "94043",
            "short_name": "94043",
            "types": ["postal_code"]
          }],
          "formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
          "geometry": {
            "location": {
              "lat": 37.42291810,
              "lng": -122.08542120
            },
            "location_type": "ROOFTOP",
            "viewport": {
              "northeast": {
                "lat": 37.42426708029149,
                "lng": -122.0840722197085
              },
              "southwest": {
                "lat": 37.42156911970850,
                "lng": -122.0867701802915
              }
            }
          },
          "types": ["street_address"]
        }],
        "status": "OK"
      }).should.be.true;
    });

    it('should return false when the input is not rooftop', function () {
      geo.isRooftop({
        "status": "OK",
        "results": [{
          "types": ["sublocality", "political"],
          "formatted_address": "Winnetka, California, USA",
          "address_components": [{
            "long_name": "Winnetka",
            "short_name": "Winnetka",
            "types": ["sublocality", "political"]
          }, {
            "long_name": "Los Angeles",
            "short_name": "Los Angeles",
            "types": ["administrative_area_level_3", "political"]
          }, {
            "long_name": "Los Angeles",
            "short_name": "Los Angeles",
            "types": ["administrative_area_level_2", "political"]
          }, {
            "long_name": "California",
            "short_name": "CA",
            "types": ["administrative_area_level_1", "political"]
          }, {
            "long_name": "United States",
            "short_name": "US",
            "types": ["country", "political"]
          }],
          "geometry": {
            "location": {
              "lat": 34.2131710,
              "lng": -118.5710220
            },
            "location_type": "APPROXIMATE",
            "viewport": {
              "southwest": {
                "lat": 34.1947148,
                "lng": -118.6030368
              },
              "northeast": {
                "lat": 34.2316232,
                "lng": -118.5390072
              }
            },
            "bounds": {
              "southwest": {
                "lat": 34.1791050,
                "lng": -118.5883200
              },
              "northeast": {
                "lat": 34.2353090,
                "lng": -118.5534191
              }
            }
          }
        }]
      }).should.be.false;
    });
  });

  describe('#rooftopCode()', function () {
    it('should return a rooftop geocode', function (done) {
      geo.rooftopCode('3895 Church Street, Clarkston, GA 30021, USA', function (err, data) {
        (err === null).should.be.true;
        data.location.should.not.be.String;
        console.log(data);
        done();
      });
    });

    it('should return a non-rooftop geocode', function (done) {
      geo.rooftopCode('7665 Honey Abbey, Koggiung, MA', function (err, data) {
        (err === null).should.be.true;
        data.location.should.be.exactly('no rooftop code');
        console.log(data);
        done();
      });
    });
  });

});<commit_msg>update test case<commit_after>/*global describe, it, before, beforeEach, after, afterEach */

var assert = require('assert'),
  should = require('should'),
  geo = require('../lib/geo');

describe('geo', function () {
  this.timeout(0);

  describe('#isRooftop()', function () {
    it('should return true when the input is rooftop', function () {
      geo.isRooftop({
        "results": [{
          "address_components": [{
            "long_name": "1600",
            "short_name": "1600",
            "types": ["street_number"]
          }, {
            "long_name": "Amphitheatre Pkwy",
            "short_name": "Amphitheatre Pkwy",
            "types": ["route"]
          }, {
            "long_name": "Mountain View",
            "short_name": "Mountain View",
            "types": ["locality", "political"]
          }, {
            "long_name": "Santa Clara",
            "short_name": "Santa Clara",
            "types": ["administrative_area_level_2", "political"]
          }, {
            "long_name": "California",
            "short_name": "CA",
            "types": ["administrative_area_level_1", "political"]
          }, {
            "long_name": "United States",
            "short_name": "US",
            "types": ["country", "political"]
          }, {
            "long_name": "94043",
            "short_name": "94043",
            "types": ["postal_code"]
          }],
          "formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
          "geometry": {
            "location": {
              "lat": 37.42291810,
              "lng": -122.08542120
            },
            "location_type": "ROOFTOP",
            "viewport": {
              "northeast": {
                "lat": 37.42426708029149,
                "lng": -122.0840722197085
              },
              "southwest": {
                "lat": 37.42156911970850,
                "lng": -122.0867701802915
              }
            }
          },
          "types": ["street_address"]
        }],
        "status": "OK"
      }).should.be.true;
    });

    it('should return false when the input is not rooftop', function () {
      geo.isRooftop({
        "status": "OK",
        "results": [{
          "types": ["sublocality", "political"],
          "formatted_address": "Winnetka, California, USA",
          "address_components": [{
            "long_name": "Winnetka",
            "short_name": "Winnetka",
            "types": ["sublocality", "political"]
          }, {
            "long_name": "Los Angeles",
            "short_name": "Los Angeles",
            "types": ["administrative_area_level_3", "political"]
          }, {
            "long_name": "Los Angeles",
            "short_name": "Los Angeles",
            "types": ["administrative_area_level_2", "political"]
          }, {
            "long_name": "California",
            "short_name": "CA",
            "types": ["administrative_area_level_1", "political"]
          }, {
            "long_name": "United States",
            "short_name": "US",
            "types": ["country", "political"]
          }],
          "geometry": {
            "location": {
              "lat": 34.2131710,
              "lng": -118.5710220
            },
            "location_type": "APPROXIMATE",
            "viewport": {
              "southwest": {
                "lat": 34.1947148,
                "lng": -118.6030368
              },
              "northeast": {
                "lat": 34.2316232,
                "lng": -118.5390072
              }
            },
            "bounds": {
              "southwest": {
                "lat": 34.1791050,
                "lng": -118.5883200
              },
              "northeast": {
                "lat": 34.2353090,
                "lng": -118.5534191
              }
            }
          }
        }]
      }).should.be.false;
    });
  });

  describe('#rooftopCode()', function () {
    it('should return a rooftop geocode', function (done) {
      geo.rooftopCode('3895 Church Street, Clarkston, GA 30021, USA', function (err, data) {
        (err === null).should.be.true;
        data.location.should.not.be.String;
        console.log(data);
        done();
      });
    });

    it('should return a non-rooftop geocode', function (done) {
      geo.rooftopCode('7665 Honey Abbey, Koggiung, MA', function (err, data) {
        (err === null).should.be.true;
        (data === null).should.be.true;
        console.log(data);
        done();
      });
    });
  });

});<|endoftext|>