<commit_before>/* eslint strict: 0*/

const api = require('../../API_KEYS');
const httpRequest = require('http-request');
const parseString = require('xml2js').parseString;

module.exports = {
  dictionary: (req, res) => {
    'use strict';
    const reqWord = req.params.word;
    const webster = `http://www.dictionaryapi.com/api/v1/references/collegiate/xml/${reqWord}?key=${api.websterDictionaryAPI}`;
    httpRequest.get(webster, (err, data) => {
      if (err) {
        return;
      }
      parseString(data.buffer, (error, result) => {
        if (error) {
          res.send(error);
          return;
        }
        const dictionaryEntries = result.entry_list.entry[0].def[0].dt;
        for (let i = 0; i < dictionaryEntries.length; i ++) {
          if (typeof dictionaryEntries[i] === 'string') {
            const defWithColon = dictionaryEntries[i];
            const defWithoutColon = defWithColon.slice(1, defWithColon.length);
            res.send(defWithoutColon);
            return;
          }
        }
        for (let j = 0; j < dictionaryEntries.length; j ++) {
          if (dictionaryEntries[j]._.length > 2) {
            const defWithColon = dictionaryEntries[j]._;
            const defWithoutColon = defWithColon.slice(1, defWithColon.length);
            res.send(defWithoutColon);
            return;
          }
        }
      });
    });
  },

  thesaurus: (req, res) => {
    const reqWord = req.params.word;
    const webster = `http://www.dictionaryapi.com/api/v1/references/thesaurus/xml/${reqWord}?key=${api.websterThesaurusAPI}`;
    httpRequest.get(webster, (err, data) => {
      if (err) {
        res.send(err);
        return;
      }
      parseString(data.buffer, (error, result) => {
        if (error) {
          res.send(error);
          return;
        }
        const thesaurusEntries = result.entry_list.entry;
        const thesaurusObj = {};
        if (thesaurusEntries.length === 1) {
          if (typeof thesaurusEntries[0].sens[0].syn[0] === 'object') {
            thesaurusObj.syns = thesaurusEntries[0].sens[0].syn[0][0];
          } else {
            thesaurusObj.syns = thesaurusEntries[0].sens[0].syn[0];
          }
          thesaurusObj.pos = thesaurusEntries[0].fl[0];
        } else {
          if (typeof thesaurusEntries[1].sens[0].syn[0] === 'object') {
            thesaurusObj.syns = thesaurusEntries[1].sens[0].syn[0]._;
          } else {
            thesaurusObj.syns = thesaurusEntries[1].sens[0].syn[0];
          }
          thesaurusObj.pos = thesaurusEntries[1].fl[0];
        }
        res.send(thesaurusObj);
      });
    });
  },
};
<commit_msg>Clean up spacing<commit_after>/* eslint strict: 0*/

const api = require('../../API_KEYS');
const httpRequest = require('http-request');
const parseString = require('xml2js').parseString;

module.exports = {
  dictionary: (req, res) => {
    'use strict';
    const reqWord = req.params.word;
    const webster = `http://www.dictionaryapi.com/api/v1/references/collegiate/xml/${reqWord}?key=${api.websterDictionaryAPI}`;
    httpRequest.get(webster, (err, data) => {
      if (err) {
        return;
      }
      parseString(data.buffer, (error, result) => {
        if (error) {
          res.send(error);
          return;
        }
        const dictionaryEntries = result.entry_list.entry[0].def[0].dt;
        for (let i = 0; i < dictionaryEntries.length; i ++) {
          if (typeof dictionaryEntries[i] === 'string') {
            const defWithColon = dictionaryEntries[i];
            const defWithoutColon = defWithColon.slice(1, defWithColon.length);
            res.send(defWithoutColon);
            return;
          }
        }
        for (let j = 0; j < dictionaryEntries.length; j ++) {
          if (dictionaryEntries[j]._.length > 2) {
            const defWithColon = dictionaryEntries[j]._;
            const defWithoutColon = defWithColon.slice(1, defWithColon.length);
            res.send(defWithoutColon);
            return;
          }
        }
      });
    });
  },

  thesaurus: (req, res) => {
    const reqWord = req.params.word;
    const webster = `http://www.dictionaryapi.com/api/v1/references/thesaurus/xml/${reqWord}?key=${api.websterThesaurusAPI}`;
    httpRequest.get(webster, (err, data) => {
      if (err) {
        res.send(err);
        return;
      }
      parseString(data.buffer, (error, result) => {
        if (error) {
          res.send(error);
          return;
        }
        const thesaurusEntries = result.entry_list.entry;
        const thesaurusObj = {};
        if (thesaurusEntries !== undefined) {
          if (thesaurusEntries.length === 1) {
            if (typeof thesaurusEntries[0].sens[0].syn[0] === 'object') {
              thesaurusObj.syns = thesaurusEntries[0].sens[0].syn[0][0];
            } else {
              thesaurusObj.syns = thesaurusEntries[0].sens[0].syn[0];
            }
            thesaurusObj.pos = thesaurusEntries[0].fl[0];
          } else {
            if (typeof thesaurusEntries[1].sens[0].syn[0] === 'object') {
              thesaurusObj.syns = thesaurusEntries[1].sens[0].syn[0]._;
            } else {
              thesaurusObj.syns = thesaurusEntries[1].sens[0].syn[0];
            }
            thesaurusObj.pos = thesaurusEntries[1].fl[0];
          }
          res.send(thesaurusObj);
        } else {
          res.send('-');
        }
      });
    });
  },
};
<|endoftext|>


<commit_before>import { expect } from 'chai';
import testUtils from './utils';
import { AddCommands } from './commands';

(process.env.PROTONMAIL_TEST_USERNAME ? describe : describe.skip)('unread notifications', function () {
  const expectUnreadEmails = 2;
  this.timeout(200000);

  beforeEach(testUtils.beforeEach);
  afterEach(testUtils.afterEach);

  it('should display accurate unread emails in the sidebar', async function () {
    AddCommands.addAccount.call(this);
    /**
     * We need to create to accounts since the webview wont get focus (which we need)
     * after an account is created.
     */
    await this.app.client.addAccount(process.env.PROTONMAIL_TEST_USERNAME);
    await this.app.client.addAccount(process.env.PROTONMAIL_TEST_USERNAME);

    return this.app.client
      .click('.etabs-tabs .etabs-tab:first-child')
      .pause(5000)
      .keys(['Tab'])
      .pause(1000)
      .keys(process.env.PROTONMAIL_TEST_PASSWORD)
      .pause(1000)
      .keys(['Enter'])
      .pause(10000)
      /**
       * Protonmail wont show unread emails in the title immediately,
       * therefore we need to visit the draft folder first
       */
      .keys('gd')
      .pause(2000)
      .keys('gi')
      .then(() => this.app.client.waitForVisible('.etabs-tabs .etabs-tab-badge'))
      .then(() => this.app.client.getText('.etabs-tabs .etabs-tab-badge'))
      .then(text => {
        expect(Number(text[0])).equal(expectUnreadEmails);
        expect(text[1]).equal('');
      })
      .catch(testUtils.saveErrorShot.bind(this));
  });
});
<commit_msg>slow down e2e to test to pass in CI<commit_after>import { expect } from 'chai';
import testUtils from './utils';
import { AddCommands } from './commands';

(process.env.PROTONMAIL_TEST_USERNAME ? describe : describe.skip)('unread notifications', function () {
  const expectUnreadEmails = 2;
  this.timeout(200000);

  beforeEach(testUtils.beforeEach);
  afterEach(testUtils.afterEach);

  it('should display accurate unread emails in the sidebar', async function () {
    AddCommands.addAccount.call(this);
    /**
     * We need to create to accounts since the webview wont get focus (which we need)
     * after an account is created.
     */
    await this.app.client.addAccount(process.env.PROTONMAIL_TEST_USERNAME);
    await this.app.client.addAccount(process.env.PROTONMAIL_TEST_USERNAME);

    return this.app.client
      .click('.etabs-tabs .etabs-tab:first-child')
      .pause(5000)
      .keys(['Tab'])
      .pause(2000)
      .keys(process.env.PROTONMAIL_TEST_PASSWORD)
      .pause(2000)
      .keys(['Enter'])
      .pause(10000)
      /**
       * Protonmail wont show unread emails in the title immediately,
       * therefore we need to visit the draft folder first
       */
      .keys('gd')
      .pause(2000)
      .keys('gi')
      .then(() => this.app.client.waitForVisible('.etabs-tabs .etabs-tab-badge'))
      .then(() => this.app.client.getText('.etabs-tabs .etabs-tab-badge'))
      .then(text => {
        expect(Number(text[0])).equal(expectUnreadEmails);
        expect(text[1]).equal('');
      })
      .catch(testUtils.saveErrorShot.bind(this));
  });
});
<|endoftext|>


<commit_before>var particles = []
var arrows = []
var numberOfParticles = 0
var temp = 0
var wind = {
  angle: 0,
  speed: 0,
  vector: null
}

Number.prototype.map = function ( in_min , in_max , out_min , out_max ) {
    return ( this - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min;
}

function calculateHSL(hsb){
    // determine the lightness in the range [0,100]
    var l = (2 - hsb.s / 100) * hsb.b / 2;
    // store the HSL components
    var hsl =
      {
        'h' : hsb.h,
        's' : hsb.s * hsb.b / (l < 50 ? l * 2 : 200 - l * 2),
        'l' : l
      };
    // correct a division-by-zero error
    if (isNaN(hsl.s)) hsl.s = 0;
    return hsl
}

function getHsb(temp){
    var hsb = {
        'h' : 0,
        's' : 80,
        'b' : 85
      };

    temp = temp > 32 ? 32 : temp < -10 ? -10 : temp

    hsb.h = 200 - temp.map(0, 40, 0, 250)

    return hsb
}

function drawBackground(hsb) {
    var hsl = calculateHSL(hsb)
    background(hsb.h, hsb.s, hsb.b)
    $('body').css('background', 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%)') // css HSL
}

function boundCheck(position){
    if (position.x > width)  position.x = 0
    if (position.x < 0)      position.x = width
    if (position.y > height) position.y = 0
    if (position.y < 0)      position.y = height
}

function Particle () {
    this.position = createVector(random(width), random(height))
    this.size = random(8)
    this.opacity = random(1)

    this.draw = function(speed, i, mouseX, mouseY){

      mouse = createVector(mouseX, mouseY)
      normalizedPosition = this.position.copy()
      distance = mouse.dist(normalizedPosition)

      repulsion = createVector(normalizedPosition.x - mouse.x - sin(i), normalizedPosition.y - mouse.y - cos(i));
      repulsion.normalize()

      if (distance<30){
        this.position.add(repulsion)
      }
      else if (distance<60){
        repulsion.div(2)
        this.position.add(repulsion)
      }
      else if (distance<90){
        repulsion.div(3)
        this.position.add(repulsion)
      }
      else if (distance<120){
        repulsion.div(4)
        this.position.add(repulsion)
      }

      this.position.add(speed)

      // add some randomness
      this.position.x = this.position.x + cos(i)/10
      this.position.y = this.position.y + sin(i)/10
      this.size = this.size

      boundCheck(this.position)

      noStroke()
      fill(color(25, this.opacity))
      ellipse(this.position.x, this.position.y, this.size, this.size)
    }
}

function Arrow () {
    this.position = createVector(random(width), random(height))
    this.size = random(10)
    this.opacity = random(1)

    this.draw = function(speed, i, mouseX, mouseY){

      mouse = createVector(mouseX, mouseY)
      normalizedPosition = this.position.copy()
      distance = mouse.dist(normalizedPosition)

      repulsion = createVector(normalizedPosition.x - mouse.x - sin(i), normalizedPosition.y - mouse.y - cos(i))
      repulsion.normalize()

      if (distance<30){
        this.position.add(repulsion)
      }
      else if (distance<60){
        repulsion.div(2)
        this.position.add(repulsion)
      }
      else if (distance<90){
        repulsion.div(3)
        this.position.add(repulsion)
      }
      else if (distance<120){
        repulsion.div(4)
        this.position.add(repulsion)
      }

      this.position.add(speed)

      // add some randomness
      this.position.x = this.position.x + cos(i)/10
      this.position.y = this.position.y + sin(i)/10
      this.size = this.size

      boundCheck(this.position)

      stroke(color(255, this.opacity))
      strokeWeight(1)
      push()
      translate(this.position.x, this.position.y)
      rotate(wind.angle);
      line(0, 0, this.size*2 ,0)
      //arrow
      line(this.size*2, 0, this.size*1.4, -this.size/2)
      line(this.size*2, 0, this.size*1.4, this.size/2)
      pop();
    }
}

function setWeather(temperature, windSpeed, windDirection) {
  temp = floor(temperature)

  if (!windDirection){
    windDirection = -90
  }
  if (!windSpeed) {
    windSpeed = 0.5
  }

  // convert to radians and account for meteorological degrees
  wind.angle = radians(windDirection + 90)
  wind.speed = Number(windSpeed)

  wind.vector = p5.Vector.fromAngle(wind.angle)
  // add wind magnitude
  wind.vector.mult(wind.speed/4)
}

function getData(){
  jQuery.ajax( {
    url: 'http://ip-api.com/json',
    type: 'GET',
    dataType: 'jsonp',
    cache: false,
    headers: { "Content-type": "application/json" },
    success: function(location) {
      jQuery.ajax( {
        url: 'http://api.openweathermap.org/data/2.5/weather?lat=' + location.lat + '&lon=' + location.lon +  '&units=metric&APPID=4e6e342eef6a9a7f8ea3d5f3f95a7b84',
        type: 'GET',
        dataType: 'jsonp',
        cache: false,
        headers: { "Content-type": "application/json" },
        success: function(weather) {
          console.log(weather)
          setWeather(weather.main.temp, weather.wind.speed, weather.wind.deg)
          setTimeout(function(){
            $(".spinner-container").css("opacity", 0)
          }, 500);
        }
      });
  }
} );
}

function setup() {
    particles = []
    arrows = []
    temp = 0

    createCanvas($(window).width(), $(window).height());
    getData()

    numberOfParticles = floor(width/14)
    if(numberOfParticles>90){
      numberOfParticles = 90
    }

    for(i=0; i < numberOfParticles; i++){
      particle = new Particle()
      particles.push(particle)

      arrow = new Arrow()
      arrows.push(arrow)
    }
    colorMode(HSB, 360, 100, 100, 1)
}

function draw() {
  // if temperature was read
  if(temp && wind){
      hsb = getHsb(temp)
      drawBackground(hsb)

      // removed mobile for now
      for(i=0; i < numberOfParticles; i++){
          particles[i].draw(wind.vector, i, mouseX, mouseY)
          arrows[i].draw(wind.vector, i , mouseX, mouseY)
      }

      if(wind.speed < 2)
          $(".wind").html("Barely windy")
      else if(2 <= wind.speed && wind.speed < 6)
          $(".wind").html("A bit windy")
      else if(6 <= wind.speed && wind.speed < 9)
          $(".wind").html("Quite windy")
      else if(9 < wind.speed && wind.speed < 12)
          $(".wind").html("Really windy")
      else if(wind.speed >= 12)
          $(".wind").html("Outright windy")
    }

    $('html, body').on('touchstart touchmove', function(e){
     //prevent native touch activity like scrolling
     e.preventDefault()
  	});
}

function windowResized() {
    resizeCanvas(windowWidth, windowHeight)

    particles = []
    arrows = []

    numberOfParticles = floor(width/14)
    if(numberOfParticles>90){
      numberOfParticles = 90
    }

    for(i=0; i<numberOfParticles; i++){
      particle = new Particle()
      particles.push(particle)

      arrow = new Arrow()
      arrows.push(arrow)
    }
}<commit_msg>change wind dampening<commit_after>var particles = []
var arrows = []
var numberOfParticles = 0
var temp = 0
var wind = {
  angle: 0,
  speed: 0,
  vector: null
}

Number.prototype.map = function ( in_min , in_max , out_min , out_max ) {
    return ( this - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min;
}

function calculateHSL(hsb){
    // determine the lightness in the range [0,100]
    var l = (2 - hsb.s / 100) * hsb.b / 2;
    // store the HSL components
    var hsl =
      {
        'h' : hsb.h,
        's' : hsb.s * hsb.b / (l < 50 ? l * 2 : 200 - l * 2),
        'l' : l
      };
    // correct a division-by-zero error
    if (isNaN(hsl.s)) hsl.s = 0;
    return hsl
}

function getHsb(temp){
    var hsb = {
        'h' : 0,
        's' : 80,
        'b' : 85
      };

    temp = temp > 32 ? 32 : temp < -10 ? -10 : temp

    hsb.h = 200 - temp.map(0, 40, 0, 250)

    return hsb
}

function drawBackground(hsb) {
    var hsl = calculateHSL(hsb)
    background(hsb.h, hsb.s, hsb.b)
    $('body').css('background', 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%)') // css HSL
}

function boundCheck(position){
    if (position.x > width)  position.x = 0
    if (position.x < 0)      position.x = width
    if (position.y > height) position.y = 0
    if (position.y < 0)      position.y = height
}

function Particle () {
    this.position = createVector(random(width), random(height))
    this.size = random(8)
    this.opacity = random(1)

    this.draw = function(speed, i, mouseX, mouseY){

      mouse = createVector(mouseX, mouseY)
      normalizedPosition = this.position.copy()
      distance = mouse.dist(normalizedPosition)

      repulsion = createVector(normalizedPosition.x - mouse.x - sin(i), normalizedPosition.y - mouse.y - cos(i));
      repulsion.normalize()

      if (distance<30){
        this.position.add(repulsion)
      }
      else if (distance<60){
        repulsion.div(2)
        this.position.add(repulsion)
      }
      else if (distance<90){
        repulsion.div(3)
        this.position.add(repulsion)
      }
      else if (distance<120){
        repulsion.div(4)
        this.position.add(repulsion)
      }

      this.position.add(speed)

      // add some randomness
      this.position.x = this.position.x + cos(i)/10
      this.position.y = this.position.y + sin(i)/10
      this.size = this.size

      boundCheck(this.position)

      noStroke()
      fill(color(25, this.opacity))
      ellipse(this.position.x, this.position.y, this.size, this.size)
    }
}

function Arrow () {
    this.position = createVector(random(width), random(height))
    this.size = random(10)
    this.opacity = random(1)

    this.draw = function(speed, i, mouseX, mouseY){

      mouse = createVector(mouseX, mouseY)
      normalizedPosition = this.position.copy()
      distance = mouse.dist(normalizedPosition)

      repulsion = createVector(normalizedPosition.x - mouse.x - sin(i), normalizedPosition.y - mouse.y - cos(i))
      repulsion.normalize()

      if (distance<30){
        this.position.add(repulsion)
      }
      else if (distance<60){
        repulsion.div(2)
        this.position.add(repulsion)
      }
      else if (distance<90){
        repulsion.div(3)
        this.position.add(repulsion)
      }
      else if (distance<120){
        repulsion.div(4)
        this.position.add(repulsion)
      }

      this.position.add(speed)

      // add some randomness
      this.position.x = this.position.x + cos(i)/10
      this.position.y = this.position.y + sin(i)/10
      this.size = this.size

      boundCheck(this.position)

      stroke(color(255, this.opacity))
      strokeWeight(1)
      push()
      translate(this.position.x, this.position.y)
      rotate(wind.angle);
      line(0, 0, this.size*2 ,0)
      //arrow
      line(this.size*2, 0, this.size*1.4, -this.size/2)
      line(this.size*2, 0, this.size*1.4, this.size/2)
      pop();
    }
}

function setWeather(temperature, windSpeed, windDirection) {
  temp = floor(temperature)

  if (!windDirection){
    windDirection = -90
  }
  if (!windSpeed) {
    windSpeed = 0.5
  }

  // convert to radians and account for meteorological degrees
  wind.angle = radians(windDirection + 90)
  wind.speed = Number(windSpeed)

  wind.vector = p5.Vector.fromAngle(wind.angle)
  // add wind magnitude
  wind.vector.mult(wind.speed/3)
}

function getData(){
  jQuery.ajax( {
    url: 'http://ip-api.com/json',
    type: 'GET',
    dataType: 'jsonp',
    cache: false,
    headers: { "Content-type": "application/json" },
    success: function(location) {
      jQuery.ajax( {
        url: 'http://api.openweathermap.org/data/2.5/weather?lat=' + location.lat + '&lon=' + location.lon +  '&units=metric&APPID=4e6e342eef6a9a7f8ea3d5f3f95a7b84',
        type: 'GET',
        dataType: 'jsonp',
        cache: false,
        headers: { "Content-type": "application/json" },
        success: function(weather) {
          console.log(weather)
          setWeather(weather.main.temp, weather.wind.speed, weather.wind.deg)
          setTimeout(function(){
            $(".spinner-container").css("opacity", 0)
          }, 500);
        }
      });
  }
} );
}

function setup() {
    particles = []
    arrows = []
    temp = 0

    createCanvas($(window).width(), $(window).height());
    getData()

    numberOfParticles = floor(width/14)
    if(numberOfParticles>90){
      numberOfParticles = 90
    }

    for(i=0; i < numberOfParticles; i++){
      particle = new Particle()
      particles.push(particle)

      arrow = new Arrow()
      arrows.push(arrow)
    }
    colorMode(HSB, 360, 100, 100, 1)
}

function draw() {
  // if temperature was read
  if(temp && wind){
      hsb = getHsb(temp)
      drawBackground(hsb)

      // removed mobile for now
      for(i=0; i < numberOfParticles; i++){
          particles[i].draw(wind.vector, i, mouseX, mouseY)
          arrows[i].draw(wind.vector, i , mouseX, mouseY)
      }

      if(wind.speed < 2)
          $(".wind").html("Barely windy")
      else if(2 <= wind.speed && wind.speed < 6)
          $(".wind").html("A bit windy")
      else if(6 <= wind.speed && wind.speed < 9)
          $(".wind").html("Quite windy")
      else if(9 < wind.speed && wind.speed < 12)
          $(".wind").html("Really windy")
      else if(wind.speed >= 12)
          $(".wind").html("Outright windy")
    }

    $('html, body').on('touchstart touchmove', function(e){
     //prevent native touch activity like scrolling
     e.preventDefault()
  	});
}

function windowResized() {
    resizeCanvas(windowWidth, windowHeight)

    particles = []
    arrows = []

    numberOfParticles = floor(width/14)
    if(numberOfParticles>90){
      numberOfParticles = 90
    }

    for(i=0; i<numberOfParticles; i++){
      particle = new Particle()
      particles.push(particle)

      arrow = new Arrow()
      arrows.push(arrow)
    }
}<|endoftext|>


<commit_before>/**
 * Created by kweinberger on 06.12.2018.
 */

import { details, mergeInEmptyDraft } from "../detail-definitions.js";
import won from "../../app/won-es6.js";
import { getIn, is } from "../../app/utils.js";
import {
  textSearchSubQuery,
  vicinityScoreSubQuery,
  filterPriceRange,
  concatenateFilters,
  sparqlQuery,
} from "../../app/sparql-builder-utils.js";

export const goodsServiceSearch = {
  identifier: "goodsServiceSearch",
  label: "Look for something",
  icon: "#ico36_plus",
  draft: {
    ...mergeInEmptyDraft({
      content: {
        type: ["s:Demand"],
      },
      seeks: {
        type: ["s:Offer"],
        images: { ...details.images },
      },
    }),
  },
  reactionUseCases: ["serviceOffer", "goodsOffer"],
  seeksDetails: {
    title: { ...details.title },
    tags: {
      ...details.tags,
      label: "Keywords to search for",
      mandatory: true,
    },
    priceRange: { ...details.pricerange },
    description: { ...details.description },
    location: { ...details.location },
  },
  generateQuery: (draft, resultName) => {
    let subQueries = [];
    let subScores = [];

    const tags = getIn(draft, ["seeks", "tags"]);
    let keywords = [];

    // prep tags for searching
    if (tags && is("Array", tags) && tags.length > 0) {
      keywords = tags
        .map(s => s.split(/\s+/)) // remove all whitespace
        .reduce((arrArr, arr) => arrArr.concat(arr), []); // flatten array, Array.flat() does not work on edge

      // search for all keywords in title, description and tags
      // this is probably horribly inefficient
      for (const keyword of keywords) {
        let titleSQ = textSearchSubQuery({
          resultName: resultName,
          bindScoreAs: "?title_" + keyword + "_index",
          pathToText: "dc:title",
          prefixesInPath: {
            dc: won.defaultContext["dc"],
          },
          keyword: keyword,
        });

        if (titleSQ) {
          subQueries.push(titleSQ);
          subScores.push("?title_" + keyword + "_index"); // dirty hack.
        }

        let descriptionSQ = textSearchSubQuery({
          resultName: resultName,
          bindScoreAs: "?description_" + keyword + "_index",
          pathToText: "dc:description",
          prefixesInPath: {
            dc: won.defaultContext["dc"],
          },
          keyword: keyword,
        });

        if (descriptionSQ) {
          subQueries.push(descriptionSQ);
          subScores.push("?description_" + keyword + "_index");
        }

        let tagsSQ = textSearchSubQuery({
          resultName: resultName,
          bindScoreAs: "?tags_" + keyword + "_index",
          pathToText: "won:tags",
          prefixesInPath: {},
          keyword: keyword,
        });

        if (tagsSQ) {
          subQueries.push(tagsSQ);
          subScores.push("?tags_" + keyword + "_index");
        }
      }
    }

    // dirty hack, part 2
    // this is done to be able to use the indices generated above
    // in the sparql query below
    const iterator = subScores.values();
    let subScoreString = ``;

    for (const value of iterator) {
      subScoreString += `COALESCE(` + value + `, 0) + `;
    }

    // prioritise close results
    const vicinityScoreSQ = vicinityScoreSubQuery({
      resultName: resultName,
      bindScoreAs: "?location_geoScore",
      pathToGeoCoords: "s:location/s:geo",
      prefixesInPath: {
        s: won.defaultContext["s"],
      },
      geoCoordinates: getIn(draft, ["seeks", "location"]),
    });

    subQueries.push(vicinityScoreSQ);

    subQueries = subQueries
      .filter(sq => sq) // filters out "undefined" subqueries
      .map(sq => ({
        query: sq,
        optional: true,
      }));

    // filter for price range
    const priceRange = getIn(draft, ["seeks", "pricerange"]);

    const filters = [
      {
        prefixes: {
          won: won.defaultContext["won"],
        },
        operations: [
          `${resultName} rdf:type won:Atom.`,
          `${resultName} rdf:type s:Offer.`,
          `BIND( ( ` +
          subScoreString + // contains all COALESCE statements for text search results
            `COALESCE(?location_geoScore, 0)
            ) as ?score)`,
        ],
      },
      priceRange &&
        filterPriceRange(
          `${resultName}`,
          priceRange.min,
          priceRange.max,
          priceRange.currency
        ),
    ];

    const concatenatedFilters = concatenateFilters(filters);

    const query = sparqlQuery({
      prefixes: {
        won: won.defaultContext["won"],
        rdf: won.defaultContext["rdf"],
        dc: won.defaultContext["dc"],
        s: won.defaultContext["s"],
      },
      distinct: true,
      variables: [resultName],
      subQueries: subQueries,
      where: concatenatedFilters.operations,
      orderBy: [{ order: "DESC", variable: "?score" }],
    });

    return query;
  },
};
<commit_msg>Moved images from prefilled draft to details (was a bug)<commit_after>/**
 * Created by kweinberger on 06.12.2018.
 */

import { details, mergeInEmptyDraft } from "../detail-definitions.js";
import won from "../../app/won-es6.js";
import { getIn, is } from "../../app/utils.js";
import {
  textSearchSubQuery,
  vicinityScoreSubQuery,
  filterPriceRange,
  concatenateFilters,
  sparqlQuery,
} from "../../app/sparql-builder-utils.js";

export const goodsServiceSearch = {
  identifier: "goodsServiceSearch",
  label: "Look for something",
  icon: "#ico36_plus",
  draft: {
    ...mergeInEmptyDraft({
      content: {
        type: ["s:Demand"],
      },
      seeks: {
        type: ["s:Offer"],
      },
    }),
  },
  reactionUseCases: ["serviceOffer", "goodsOffer"],
  seeksDetails: {
    title: { ...details.title },
    tags: {
      ...details.tags,
      label: "Keywords to search for",
      mandatory: true,
    },
    priceRange: { ...details.pricerange },
    description: { ...details.description },
    location: { ...details.location },
    images: { ...details.images },
  },
  generateQuery: (draft, resultName) => {
    let subQueries = [];
    let subScores = [];

    const tags = getIn(draft, ["seeks", "tags"]);
    let keywords = [];

    // prep tags for searching
    if (tags && is("Array", tags) && tags.length > 0) {
      keywords = tags
        .map(s => s.split(/\s+/)) // remove all whitespace
        .reduce((arrArr, arr) => arrArr.concat(arr), []); // flatten array, Array.flat() does not work on edge

      // search for all keywords in title, description and tags
      // this is probably horribly inefficient
      for (const keyword of keywords) {
        let titleSQ = textSearchSubQuery({
          resultName: resultName,
          bindScoreAs: "?title_" + keyword + "_index",
          pathToText: "dc:title",
          prefixesInPath: {
            dc: won.defaultContext["dc"],
          },
          keyword: keyword,
        });

        if (titleSQ) {
          subQueries.push(titleSQ);
          subScores.push("?title_" + keyword + "_index"); // dirty hack.
        }

        let descriptionSQ = textSearchSubQuery({
          resultName: resultName,
          bindScoreAs: "?description_" + keyword + "_index",
          pathToText: "dc:description",
          prefixesInPath: {
            dc: won.defaultContext["dc"],
          },
          keyword: keyword,
        });

        if (descriptionSQ) {
          subQueries.push(descriptionSQ);
          subScores.push("?description_" + keyword + "_index");
        }

        let tagsSQ = textSearchSubQuery({
          resultName: resultName,
          bindScoreAs: "?tags_" + keyword + "_index",
          pathToText: "won:tags",
          prefixesInPath: {},
          keyword: keyword,
        });

        if (tagsSQ) {
          subQueries.push(tagsSQ);
          subScores.push("?tags_" + keyword + "_index");
        }
      }
    }

    // dirty hack, part 2
    // this is done to be able to use the indices generated above
    // in the sparql query below
    const iterator = subScores.values();
    let subScoreString = ``;

    for (const value of iterator) {
      subScoreString += `COALESCE(` + value + `, 0) + `;
    }

    // prioritise close results
    const vicinityScoreSQ = vicinityScoreSubQuery({
      resultName: resultName,
      bindScoreAs: "?location_geoScore",
      pathToGeoCoords: "s:location/s:geo",
      prefixesInPath: {
        s: won.defaultContext["s"],
      },
      geoCoordinates: getIn(draft, ["seeks", "location"]),
    });

    subQueries.push(vicinityScoreSQ);

    subQueries = subQueries
      .filter(sq => sq) // filters out "undefined" subqueries
      .map(sq => ({
        query: sq,
        optional: true,
      }));

    // filter for price range
    const priceRange = getIn(draft, ["seeks", "pricerange"]);

    const filters = [
      {
        prefixes: {
          won: won.defaultContext["won"],
        },
        operations: [
          `${resultName} rdf:type won:Atom.`,
          `${resultName} rdf:type s:Offer.`,
          `BIND( ( ` +
          subScoreString + // contains all COALESCE statements for text search results
            `COALESCE(?location_geoScore, 0)
            ) as ?score)`,
        ],
      },
      priceRange &&
        filterPriceRange(
          `${resultName}`,
          priceRange.min,
          priceRange.max,
          priceRange.currency
        ),
    ];

    const concatenatedFilters = concatenateFilters(filters);

    const query = sparqlQuery({
      prefixes: {
        won: won.defaultContext["won"],
        rdf: won.defaultContext["rdf"],
        dc: won.defaultContext["dc"],
        s: won.defaultContext["s"],
      },
      distinct: true,
      variables: [resultName],
      subQueries: subQueries,
      where: concatenatedFilters.operations,
      orderBy: [{ order: "DESC", variable: "?score" }],
    });

    return query;
  },
};
<|endoftext|>


<commit_before>function _bh(){
  var self = this
    , bh = {};

  bh['_viewSet'] = function(options, callback){
    var a = Belt.argulint(arguments)
      , self = this
      , gb = {};
    a.o = _.defaults(a.o, {
      //el
      //path
      //value
      //view
      //data
    });

    $(a.o.el).find('[data-set="' + a.o.path + '"]').each(function(i, el){
      var $el = $(el)
        , method = $el.attr('data-set-method')
        , transform = $el.attr('data-set-transformer')
        , value;

      if (transform && Belt.get(a.o.view, 'transformers.' + transform)){
        value = _.bind(a.o.view.transformers[transform], a.o.view)(a.o.value, $el, a.o);
      } else {
        value = a.o.value;
      }

      Belt.call($el, method, value);
    });
  };

  bh['_viewGet'] = function(options, callback){
    var a = Belt.argulint(arguments)
      , self = this
      , gb = {};
    a.o = _.defaults(a.o, {
      //el
      //path
      //data
    });

    var $el = $(a.o.el).find('[data-get="' + a.o.path + '"]')
      , method = $el.attr('data-get-method')
      , transform = $el.attr('data-get-transformer')
      , value;

    if (transform && Belt.get(a.o.view, 'transformers.' + transform)){
      value = _.bind(a.o.view.transformers[transform], a.o.view)(Belt.get($el, method), $el, a.o);
    } else {
      value = Belt.get($el, method);
    }

    return value;
  };

  bh['View'] = function(options, callback){
    var a = Belt.argulint(arguments)
      , self = this
      , gb = {};
    a.o = _.defaults(a.o, {
      //template
      //el
    });

    var view = new (Backbone.View.extend(_.pick(a.o, [
      'template'
    ])))();

    _.extend(view, _.omit(a.o, [
      'el'
    ]));

    view['setters'] = view.setters || {};
    view['getters'] = view.getters || {};
    view['subviews'] = view.subviews || {};
    view['data'] = view.data || {};
    view['events'] = view.events || {};
    view['transformers'] = view.transformers || {};
    view['triggers'] = view.triggers || {};

    view['loadSubviews'] = function(){
      var self = this;

      _.each(self.subviews, function(v, k){
        if (_.isString(v)){
          self.subviews[k] = self.$el.find(v);
        } else {
          self.subviews[k] = v;
        }
      });
    };
    view.loadSubviews();

    view['set'] = function(vals, opts){
      var self = this;

      opts = opts || {};

      if (!opts.no_persist) _.each(vals, function(v, k){
        self.data[k] = v;
      });

      vals['this'] = self.data;

      _.each(vals, function(v, k){
        if (self.setters[k]) self.setters[k](v, opts);

        bh._viewSet({
          'el': self.$el
        , 'value': v
        , 'path': k
        , 'view': view
        , 'data': vals
        });

        if (!opts.silent) self.emit('set:' + k, v);
      });
    };

    view['get'] = function(path, opts){
      var self = this;

      opts = opts || {};

      if (Belt.isNull(path)) return _.mapObject(self.getters, function(v, k){
        return view.get(k, opts);
      });

      if (_.isArray(path)) return _.object(path, _.map(path, function(k){
        return view.get(k, opts);
      }));

      var val;

      if (self.getters[path]){
        val =  self.getters[path](opts);
      } else {
        val = bh._viewGet({
          'el': self.$el
        , 'path': path
        , 'view': view
        });
      }

      if (!opts.no_persist) self.data[path] = val;
      if (!opts.silent) self.emit('get:' + path, val);

      return val;
    };

    _.extend(view, Backbone.Events);

    view.setEvents = function(events){
      _.each(events, function(v, k){
        view.on(k, _.bind(v, view));
      });
    };

    view.setEvents(view.events);

    view['setEl'] = function(el){
      view['$el'] = $(el);

      _.each(view.triggers, function(v, k){
        var cmps = k.split(' ')
          , event = cmps.shift()
          , sel = cmps.join(' ');

        view.$el.on(event, sel, _.bind(v, view));
      });
    };

    if (a.o.el) view.setEl(a.o.el);

    view.emit('load');

    return view;
  };
};

var Bh = _bh.call(this);
<commit_msg>adding default transformers<commit_after>function _bh(){
  var self = this
    , bh = {};

  bh['_viewSet'] = function(options, callback){
    var a = Belt.argulint(arguments)
      , self = this
      , gb = {};
    a.o = _.defaults(a.o, {
      //el
      //path
      //value
      //view
      //data
    });

    $(a.o.el).find('[data-set="' + a.o.path + '"]').each(function(i, el){
      var $el = $(el)
        , method = $el.attr('data-set-method')
        , transform = $el.attr('data-set-transformer') || ('set:' + a.o.path)
        , value;

      if (transform && (Belt.get(a.o.view, 'transformers') || {})[transform])){
        value = _.bind(a.o.view.transformers[transform], a.o.view)(a.o.value, $el, a.o);
      } else {
        value = a.o.value;
      }

      Belt.call($el, method, value);
    });
  };

  bh['_viewGet'] = function(options, callback){
    var a = Belt.argulint(arguments)
      , self = this
      , gb = {};
    a.o = _.defaults(a.o, {
      //el
      //path
      //data
    });

    var $el = $(a.o.el).find('[data-get="' + a.o.path + '"]')
      , method = $el.attr('data-get-method')
      , transform = $el.attr('data-set-transformer') || ('get:' + a.o.path)
      , value;

    if (transform && (Belt.get(a.o.view, 'transformers') || {})[transform])){
      value = _.bind(a.o.view.transformers[transform], a.o.view)(Belt.get($el, method), $el, a.o);
    } else {
      value = Belt.get($el, method);
    }

    return value;
  };

  bh['View'] = function(options, callback){
    var a = Belt.argulint(arguments)
      , self = this
      , gb = {};
    a.o = _.defaults(a.o, {
      //template
      //el
    });

    var view = new (Backbone.View.extend(_.pick(a.o, [
      'template'
    ])))();

    _.extend(view, _.omit(a.o, [
      'el'
    ]));

    view['setters'] = view.setters || {};
    view['getters'] = view.getters || {};
    view['subviews'] = view.subviews || {};
    view['data'] = view.data || {};
    view['events'] = view.events || {};
    view['transformers'] = view.transformers || {};
    view['triggers'] = view.triggers || {};

    view['loadSubviews'] = function(){
      var self = this;

      _.each(self.subviews, function(v, k){
        if (_.isString(v)){
          self.subviews[k] = self.$el.find(v);
        } else {
          self.subviews[k] = v;
        }
      });
    };
    view.loadSubviews();

    view['set'] = function(vals, opts){
      var self = this;

      opts = opts || {};

      if (!opts.no_persist) _.each(vals, function(v, k){
        self.data[k] = v;
      });

      vals['this'] = self.data;

      _.each(vals, function(v, k){
        if (self.setters[k]) self.setters[k](v, opts);

        bh._viewSet({
          'el': self.$el
        , 'value': v
        , 'path': k
        , 'view': view
        , 'data': vals
        });

        if (!opts.silent) self.emit('set:' + k, v);
      });
    };

    view['get'] = function(path, opts){
      var self = this;

      opts = opts || {};

      if (Belt.isNull(path)) return _.extend(view.$el.find('[data-get]').map(function(i, e){
        var $el = $(e)
          , path = $el.attr('data-get');
        return view.get(path, opts);
      }), _.mapObject(self.getters, function(v, k){
        return view.get(k, opts);
      }));

      if (_.isArray(path)) return _.object(path, _.map(path, function(k){
        return view.get(k, opts);
      }));

      var val;

      if (self.getters[path]){
        val =  self.getters[path](opts);
      } else {
        val = bh._viewGet({
          'el': self.$el
        , 'path': path
        , 'view': view
        });
      }

      if (!opts.no_persist) self.data[path] = val;
      if (!opts.silent) self.emit('get:' + path, val);

      return val;
    };

    _.extend(view, Backbone.Events);

    view.setEvents = function(events){
      _.each(events, function(v, k){
        view.on(k, _.bind(v, view));
      });
    };

    view.setEvents(view.events);

    view['setEl'] = function(el){
      view['$el'] = $(el);

      _.each(view.triggers, function(v, k){
        var cmps = k.split(' ')
          , event = cmps.shift()
          , sel = cmps.join(' ');

        view.$el.on(event, sel, _.bind(v, view));
      });
    };

    if (a.o.el) view.setEl(a.o.el);

    view.emit('load');

    return view;
  };
};

var Bh = _bh.call(this);
<|endoftext|>


<commit_before>function offlineify ({
  log = console.log
} = {}) {
  function toDataURI (response) {
    return response.blob().then(blob => new Promise(resolve => {
      const reader = new FileReader()
      reader.addEventListener('load', e => {
        resolve(reader.result)
      }, { once: true })
      reader.readAsDataURL(blob)
    }))
  }
  function toText (response) {
    return response.ok ? response.text() : Promise.reject(new Error(response.status))
  }
  function removeScriptTag (js) {
    return js.replace(/<\/script>/g, '')
  }
  log('Getting all required files')
  return Promise.all([
    fetch('./index.html').then(toText),
    fetch('https://sheeptester.github.io/scratch-vm/16-9/vm.min.js')
      .then(toText)
      .then(async vmCode => {
        let extensionWorker
        const extensionWorkerMatch = vmCode.match(extensionWorkerGet)
        if (!extensionWorkerMatch) return Promise.reject(new Error('Cannot find extension-worker.js'))
        const workerCode = await fetch('https://sheeptester.github.io/scratch-vm/16-9/' + extensionWorkerMatch[1])
          .then(r => r.text())
        return [vmCode, workerCode].map(removeScriptTag)
      }),
    fetch('./hacky-file-getter.js').then(toText).then(removeScriptTag),
    fetch('./download.js').then(toText).then(removeScriptTag),
    fetch('./template.html').then(toDataURI)
  ]).then(([html, [vm, extensionWorker], hackyFileGetter, downloader, template]) => {
    html = html
      .replace('<body>', '<body class="offline">')
      // Using functions to avoid $ substitution
      .replace('<script src="./hacky-file-getter.js" charset="utf-8"></script>', () => `<script>${hackyFileGetter}</script>`)
      .replace('<script src="./download.js" charset="utf-8"></script>', () => `<script>${downloader}</script>`)
      // . wildcard in regex doesn't include newlines lol
      // https://stackoverflow.com/a/45981809
      .replace(/<!-- no-offline -->[^]*?<!-- \/no-offline -->/g, '')
      .replace(/\/\* no-offline \*\/[^]*?\/\* \/no-offline \*\//g, '')
      .replace('// [offline-vm-src]', `Promise.resolve(document.getElementById('vm-src').innerHTML)`)
      .replace('// [offline-extension-worker-src]', `const workerCode = document.getElementById('worker-src').innerHTML`)
      .replace('// [template]', () => JSON.stringify(template))
      // Do this last because it phat
      // javascript/worker: https://www.html5rocks.com/en/tutorials/workers/basics/
      .replace('<script src="https://sheeptester.github.io/scratch-vm/16-9/vm.min.js" charset="utf-8"></script>', () => `<script id="vm-src">${vm}</script><script id="worker-src" type="javascript/worker">${extensionWorker}</script>`)
    log('Attempting to download...')
    download(html, 'htmlifier-offline.html', 'text/html')
    log('All good!')
  })
}
<commit_msg>Allow CSS to work offline<commit_after>function offlineify ({
  log = console.log
} = {}) {
  function toDataURI (response) {
    return response.blob().then(blob => new Promise(resolve => {
      const reader = new FileReader()
      reader.addEventListener('load', e => {
        resolve(reader.result)
      }, { once: true })
      reader.readAsDataURL(blob)
    }))
  }
  function toText (response) {
    return response.ok ? response.text() : Promise.reject(new Error(response.status))
  }
  function removeScriptTag (js) {
    return js.replace(/<\/script>/g, '')
  }
  log('Getting all required files')
  return Promise.all([
    fetch('./index.html').then(toText),
    fetch('https://sheeptester.github.io/scratch-vm/16-9/vm.min.js')
      .then(toText)
      .then(async vmCode => {
        let extensionWorker
        const extensionWorkerMatch = vmCode.match(extensionWorkerGet)
        if (!extensionWorkerMatch) return Promise.reject(new Error('Cannot find extension-worker.js'))
        const workerCode = await fetch('https://sheeptester.github.io/scratch-vm/16-9/' + extensionWorkerMatch[1])
          .then(r => r.text())
        return [vmCode, workerCode].map(removeScriptTag)
      }),
    fetch('./hacky-file-getter.js').then(toText).then(removeScriptTag),
    fetch('./download.js').then(toText).then(removeScriptTag),
    fetch('./template.html').then(toDataURI),
    fetch('./main.css').then(toText)
  ]).then(([html, [vm, extensionWorker], hackyFileGetter, downloader, template, css]) => {
    html = html
      .replace('<body>', '<body class="offline">')
      // Using functions to avoid $ substitution
      .replace('<script src="./hacky-file-getter.js" charset="utf-8"></script>', () => `<script>${hackyFileGetter}</script>`)
      .replace('<script src="./download.js" charset="utf-8"></script>', () => `<script>${downloader}</script>`)
      // . wildcard in regex doesn't include newlines lol
      // https://stackoverflow.com/a/45981809
      .replace(/<!-- no-offline -->[^]*?<!-- \/no-offline -->/g, '')
      .replace(/\/\* no-offline \*\/[^]*?\/\* \/no-offline \*\//g, '')
      .replace('// [offline-vm-src]', `Promise.resolve(document.getElementById('vm-src').innerHTML)`)
      .replace('// [offline-extension-worker-src]', `const workerCode = document.getElementById('worker-src').innerHTML`)
      .replace('<link rel="stylesheet" href="./main.css">', () => `<style>${css}</style>`)
      .replace('// [template]', () => JSON.stringify(template))
      // Do this last because it phat
      // javascript/worker: https://www.html5rocks.com/en/tutorials/workers/basics/
      .replace('<script src="https://sheeptester.github.io/scratch-vm/16-9/vm.min.js" charset="utf-8"></script>', () => `<script id="vm-src">${vm}</script><script id="worker-src" type="javascript/worker">${extensionWorker}</script>`)
    log('Attempting to download...')
    download(html, 'htmlifier-offline.html', 'text/html')
    log('All good!')
  })
}
<|endoftext|>


<commit_before>'use strict'

const Http = require('./http')
const middleware = new WeakMap()

/**
 * The Ash route class extends the @see Http class and so has access
 * to request and response properties.
 *
 * Routes execute via a series of hooks in the following order
 *
 * 1. deserialize
 * 2. beforeModel
 * 3. model
 * 4. afterModel
 * 5. serialize
 *
 * If a hook returns a promise, the subsequent hook will not execute until the promise has resolved.
 *
 * All hooks are optional except for `model` and amything returned from the `model` hook will be returned
 * to the client.
 *
 * Routes support the following:
 * - mixins (@see Mixin)
 * - services (@see Service)
 * - middleware (@see Middleware)
 *
 * @class Route
 * @extends Http
 * @constructor
 */
module.exports = class Route extends Http {
  /**
   *
   * @method constructor
   */
  constructor (context) {
    super(context)

    const mw = []
    this.constructor.middleware(middleware => mw.push(middleware))
    middleware.set(this, mw)
  }

  /**
   * @method hasMiddleware
   * @private
   */
  get hasMiddleware () {
    return middleware.get(this).length > 0
  }

  /**
   * @method registeredMiddleware
   * @private
   */
  get registeredMiddleware () {
    return middleware.get(this)
  }

  /**
   * Route middleware
   *
   * You can use this to register route specific middleware. ie. middleware specified here
   * will only run for this route. You can register the same piece of middleware in multiple
   * routes but you must do so explicitly by registering it in that routes `middleware` method.
   *
   * Call `register` with the name of the middleware in the `app/middleware` directory that
   * you want to load. You can call register multiple times to register more than one middleware
   * and middleware will be executed in the order registered.
   *
   * Example
   *
   * Example: registering middleware on a route
   * ```
   *
   * // app/routes/my-route.js
   * const Ash = require('@ash-framework/ash')
   *
   * module.exports = class MyRoute extends Ash.Route {
   *   static middleware (register) {
   *     register('my-middleware')
   *   }
   * }
   * ```
   *
   * @method middleware
   * @static
   * @param {Function} register
   */
  static middleware (register) {

  }

  /**
   * The first hook to be executed during the lifecycle of a route.
   * This hook should generally be used to perform operations on an incoming
   * request body. As such it makes more sense to use this hook for POSTs, PUTs and PATCHs
   * rather than GETs and DELETEs.
   *
   * @method {Function} deserialize
   */
  deserialize () {

  }

  /**
   * @method beforeModel
   */
  beforeModel () {

  }

  /**
   * @method model
   */
  model () {
    console.log(`Route '${this.name}' must define a 'model' method`)
  }

  /**
   * @method afterModel
   * @param {Object} model
   */
  afterModel (model) {

  }

  /**
   * @method serialize
   * @param {Object} model
   */
  serialize (model) {

  }

  /**
   * @method error
   * @param {Object} error
   */
  error (error) {
    return error
  }

  /**
   * The model for the route as returned from the model hook.
   * Provided for access in later hooks such as `afterModel` or `serialize`
   *
   * Example:
   * ```
   *
   * afterModel () {
   *   this.currentModel.color = 'red'
   * }
   * ```
   *
   * @property {Mixed} currentModel
   */

  /**
   * The name of the route. This is the same as the name of the route js file (without the .js)
   * and not the name of the exported class. For the name of the class use `this.name`
   *
   * @property {String} routeName
   */
}
<commit_msg>Remove route.currentModel<commit_after>'use strict'

const Http = require('./http')
const middleware = new WeakMap()

/**
 * The Ash route class extends the @see Http class and so has access
 * to request and response properties.
 *
 * Routes execute via a series of hooks in the following order
 *
 * 1. deserialize
 * 2. beforeModel
 * 3. model
 * 4. afterModel
 * 5. serialize
 *
 * If a hook returns a promise, the subsequent hook will not execute until the promise has resolved.
 *
 * All hooks are optional except for `model` and amything returned from the `model` hook will be returned
 * to the client.
 *
 * Routes support the following:
 * - mixins (@see Mixin)
 * - services (@see Service)
 * - middleware (@see Middleware)
 *
 * @class Route
 * @extends Http
 * @constructor
 */
module.exports = class Route extends Http {
  /**
   *
   * @method constructor
   */
  constructor (context) {
    super(context)

    const mw = []
    this.constructor.middleware(middleware => mw.push(middleware))
    middleware.set(this, mw)
  }

  /**
   * @method hasMiddleware
   * @private
   */
  get hasMiddleware () {
    return middleware.get(this).length > 0
  }

  /**
   * @method registeredMiddleware
   * @private
   */
  get registeredMiddleware () {
    return middleware.get(this)
  }

  /**
   * Route middleware
   *
   * You can use this to register route specific middleware. ie. middleware specified here
   * will only run for this route. You can register the same piece of middleware in multiple
   * routes but you must do so explicitly by registering it in that routes `middleware` method.
   *
   * Call `register` with the name of the middleware in the `app/middleware` directory that
   * you want to load. You can call register multiple times to register more than one middleware
   * and middleware will be executed in the order registered.
   *
   * Example
   *
   * Example: registering middleware on a route
   * ```
   *
   * // app/routes/my-route.js
   * const Ash = require('@ash-framework/ash')
   *
   * module.exports = class MyRoute extends Ash.Route {
   *   static middleware (register) {
   *     register('my-middleware')
   *   }
   * }
   * ```
   *
   * @method middleware
   * @static
   * @param {Function} register
   */
  static middleware (register) {

  }

  /**
   * The first hook to be executed during the lifecycle of a route.
   * This hook should generally be used to perform operations on an incoming
   * request body. As such it makes more sense to use this hook for POSTs, PUTs and PATCHs
   * rather than GETs and DELETEs.
   *
   * @method {Function} deserialize
   */
  deserialize () {

  }

  /**
   * @method beforeModel
   */
  beforeModel () {

  }

  /**
   * @method model
   */
  model () {
    console.log(`Route '${this.name}' must define a 'model' method`)
  }

  /**
   * @method afterModel
   * @param {Object} model
   */
  afterModel (model) {

  }

  /**
   * @method serialize
   * @param {Object} model
   */
  serialize (model) {

  }

  /**
   * @method error
   * @param {Object} error
   */
  error (error) {
    return error
  }

  /**
   * The name of the route. This is the same as the name of the route js file (without the .js)
   * and not the name of the exported class. For the name of the class use `this.name`
   *
   * @property {String} routeName
   */
}
<|endoftext|>


<commit_before>module.exports = function enableAuthentication(server) {
  // enable authentication
  server.enableAuth();
};
<commit_msg>Enable API authentication in production mode<commit_after>module.exports = function enableAuthentication(server) {
  if (process.env.NODE_ENV === 'production') {
    server.enableAuth();
  }
};
<|endoftext|>


<commit_before>'use strict';

angular.module('hackshareApp')
    .factory('geoFactory', function ($rootScope, $http, $q) {
        // Service logic
        var geocoder;
        var map;
        var infowindow = new google.maps.InfoWindow();
        var marker;
        var initialized = false;
        function initialize() {
            geocoder = new google.maps.Geocoder();
            var latlng = new google.maps.LatLng(40.730885,-73.997383);
            var mapOptions = {
                zoom: 8,
                center: latlng
            };
            map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
        }

        // Public API here
        return {
            getPosition: function() {
                return $q(function(resolve, reject) {
                    if(!initialized) initialize();
                    if (Modernizr.geolocation) {
                        navigator.geolocation.getCurrentPosition(function (position) {
                            console.log("Latitude: " + position.coords.latitude +
                            "\nLongitude: " + position.coords.longitude);

                            $rootScope.location = position;
                            console.log(position);
                            resolve(position);
                        });
                    } else {
                        // no native support; maybe try a fallback?
                        console.warn('No location support, user must select location manually');
                        reject();
                    }
                })
            }, getLocation: function(position) {
                var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                geocoder.geocode({'latLng': latlng}, function(results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        if (results[1]) {
                            console.log(results);
                            map.setZoom(11);
                            marker = new google.maps.Marker({
                                position: latlng,
                                map: map
                            });
                            infowindow.setContent(results[1].formatted_address);
                            infowindow.open(map, marker);
                        }
                    } else {
                        alert("Geocoder failed due to: " + status);
                    }
                });
            }
        };
    });
<commit_msg>feat(geo): update geoFactory<commit_after>'use strict';

angular.module('hackshareApp')
    .factory('geoFactory', function ($rootScope, $http, $q) {
        // Service logic
        var geocoder;
        var map;
        var infowindow = new google.maps.InfoWindow();
        var marker;
        var initialized = false;
        function initialize() {
            geocoder = new google.maps.Geocoder();
            var latlng = new google.maps.LatLng(40.730885,-73.997383);
            var mapOptions = {
                zoom: 8,
                center: latlng
            };
            //map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
        }

        // Public API here
        return {
            getPosition: function() {
                return $q(function(resolve, reject) {
                    if(!initialized) initialize();
                    if (Modernizr.geolocation) {
                        navigator.geolocation.getCurrentPosition(function (position) {
                            console.log("Latitude: " + position.coords.latitude +
                            "\nLongitude: " + position.coords.longitude);

                            $rootScope.location = position;
                            console.log(position);
                            resolve(position);
                        });
                    } else {
                        // no native support; maybe try a fallback?
                        console.warn('No location support, user must select location manually');
                        reject();
                    }
                })
            }, getLocation: function(position) {
                return $q(function(resolve, reject) {
                    var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                    geocoder.geocode({'latLng': latlng}, function(results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            if (results[0]) {
                                //map.setZoom(11);
                                marker = new google.maps.Marker({
                                    position: latlng,
                                    map: map
                                });
                                infowindow.setContent(results[0].formatted_address);
                                //infowindow.open(map, marker);
                                resolve(results);
                            }
                        } else {
                            alert("Geocoder failed due to: " + status);
                            reject(status);
                        }
                    });
                })
            }
        };
    });
<|endoftext|>


<commit_before>//
//   Copyright 2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const UserGId = require('../models/userGId');
const log = require('./log');
const conf = require('./conf');
const User = require('../models/user');
const nicksService = require('../services/nicks');
const redis = require('./redis').createClient();
const notification = require('../lib/notification');

const networks = [ 'MAS', ...Object.keys(conf.get('irc:networks')) ];

exports.introduce = async function introduce(user, userGId, session) {
    await introduceUsers(user, [ userGId ], session, null);
};

exports.scanAndIntroduce = async function scanAndIntroduce(user, msg, session, socket) {
    await introduceUsers(user, scanUserGIds(msg), session, socket);
};

async function introduceUsers(user, userGIds, session, socket) {
    if (session) {
        // If no session is given, force broadcast userGids without remembering them
        session.knownUserGIds = session.knownUserGIds || {};
    }

    const newUsers = {};

    for (const userGId of userGIds) {
        if (!session || !session.knownUserGIds[userGId.toString()]) {
            if (session) {
                session.knownUserGIds[userGId.toString()] = true;
            }

            const entry = { nick: {} };

            if (userGId.isMASUser) {
                const foundUser = await User.fetch(userGId.id);

                entry.name = foundUser.get('name');
                entry.gravatar = foundUser.get('emailMD5');

                for (const network of networks) {
                    const currentNick = await nicksService.getCurrentNick(foundUser, network);

                    // Fallback to default nick. This solves the situation where the user joins
                    // a new IRC network during the session. In that case his own userGId is in
                    // knownUserGIds table but with null nick for that IRC network. Fallback works
                    // because if the user's nick changes for any reason from the default, that is
                    // communicated separately to the client.
                    entry.nick[network] = currentNick || foundUser.get('nick');
                }
            } else {
                entry.name = 'IRC User';
                entry.gravatar = '';

                let nick = await redis.hget(`ircuser:${userGId}`, 'nick');

                if (userGId.id === 0) {
                    nick = 'server';
                }

                for (const network of networks) {
                    entry.nick[network] = nick; // shortcut, ircUserId is scoped by network
                }
            }

            newUsers[userGId] = entry;
        }
    }

    if (Object.keys(newUsers).length > 0) {
        const ntf = {
            id: 'USERS',
            mapping: newUsers
        };

        log.info(user, `Emitted USERS ${JSON.stringify(ntf)}`);

        if (socket) {
            socket.emit('ntf', ntf);
        } else if (session) {
            await notification.send(user, session.id, ntf);
        } else {
            await notification.broadcast(user, ntf);
        }
    }
}

function scanUserGIds(msg) {
    return Object.keys(scan(msg))
      .map(userGIdString => UserGId.create(userGIdString))
      .filter(userGId => userGId && userGId.valid);
}

function scan(msg) {
    const res = {};

    Object.keys(msg).forEach(key => {
        const value = msg[key];

        if (typeof value === 'object') {
            Object.assign(res, scan(value));
        } else if (key === 'userId' && value) {
            res[value] = true;
        }
    });

    return res;
}
<commit_msg>Fix classic JavaScript bug<commit_after>//
//   Copyright 2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const UserGId = require('../models/userGId');
const log = require('./log');
const conf = require('./conf');
const User = require('../models/user');
const nicksService = require('../services/nicks');
const redis = require('./redis').createClient();
const notification = require('../lib/notification');

const networks = [ 'MAS', ...Object.keys(conf.get('irc:networks')) ];

exports.introduce = async function introduce(user, userGId, session) {
    await introduceUsers(user, [ userGId ], session, null);
};

exports.scanAndIntroduce = async function scanAndIntroduce(user, msg, session, socket) {
    await introduceUsers(user, scanUserGIds(msg), session, socket);
};

async function introduceUsers(user, userGIds, session, socket) {
    if (session) {
        // If no session is given, force broadcast userGids without remembering them
        session.knownUserGIds = session.knownUserGIds || {};
    }

    const newUsers = {};

    for (const userGId of userGIds) {
        if (!session || !session.knownUserGIds[userGId.toString()]) {
            if (session) {
                session.knownUserGIds[userGId.toString()] = true;
            }

            const entry = { nick: {} };

            if (userGId.isMASUser) {
                const foundUser = await User.fetch(userGId.id);

                entry.name = foundUser.get('name');
                entry.gravatar = foundUser.get('emailMD5');

                for (const network of networks) {
                    const currentNick = await nicksService.getCurrentNick(foundUser, network);

                    // Fallback to default nick. This solves the situation where the user joins
                    // a new IRC network during the session. In that case his own userGId is in
                    // knownUserGIds table but with null nick for that IRC network. Fallback works
                    // because if the user's nick changes for any reason from the default, that is
                    // communicated separately to the client.
                    entry.nick[network] = currentNick || foundUser.get('nick');
                }
            } else {
                entry.name = 'IRC User';
                entry.gravatar = '';

                let nick = await redis.hget(`ircuser:${userGId}`, 'nick');

                if (userGId.id === 0) {
                    nick = 'server';
                }

                for (const network of networks) {
                    entry.nick[network] = nick; // shortcut, ircUserId is scoped by network
                }
            }

            newUsers[userGId] = entry;
        }
    }

    if (Object.keys(newUsers).length > 0) {
        const ntf = {
            id: 'USERS',
            mapping: newUsers
        };

        log.info(user, `Emitted USERS ${JSON.stringify(ntf)}`);

        if (socket) {
            socket.emit('ntf', ntf);
        } else if (session) {
            await notification.send(user, session.id, ntf);
        } else {
            await notification.broadcast(user, ntf);
        }
    }
}

function scanUserGIds(msg) {
    return Object.keys(scan(msg))
      .map(userGIdString => UserGId.create(userGIdString))
      .filter(userGId => userGId && userGId.valid);
}

function scan(msg) {
    const res = {};

    Object.keys(msg).forEach(key => {
        const value = msg[key];

        if (typeof value === 'object' && value !== null) {
            Object.assign(res, scan(value));
        } else if (key === 'userId' && value) {
            res[value] = true;
        }
    });

    return res;
}
<|endoftext|>


<commit_before>
(function() {

    /**
     * table view shown in admin
     */
    cdb.admin.TableView = cdb.ui.common.Table.extend({
      classLabel: 'cdb.admin.TableView',
      events: cdb.core.View.extendEvents({
          'click .clearview': '_clearView',
          'click .sqlview .export_query': '_tableFromQuery',
          'click .noRows': 'addEmptyRow'
      }),

      rowView: cdb.admin.RowView,

      initialize: function() {
        var self = this;
        this.elder('initialize');
        this.options.row_header = true;
        this.model.data().bind('newPage', this.newPage, this);
        _.bindAll(this, "render", "addEmptyRow", "_checkEmptyTable", "_forceScroll", "rowChanged", "rowSynched", "rowFailed", "rowDestroyed", "emptyTable");
        var topReached = false;
        this._editorsOpened = null;

         // pagination
        setInterval(function() {
          if(!self.$el.is(":visible") || self.model.data().isFetchingPage()) {
            return;
          }
          var pos = $(this).scrollTop();
          var d = self.model.data();
          // do not let to fetch previous pages
          // until the user dont scroll back a little bit
          if(pos > 2) {
            topReached = false;
          }
          var pageSize = $(window).height() - self.$el.offset().top;
          var tableHeight = this.$('tbody').height();
          var realPos = pos + pageSize;
          if(tableHeight < pageSize) {
            return;
          }
          if(realPos > tableHeight) {
             d.setPage(d.getPage() + 1);
          } else if (pos <= 0) {
            if(!topReached) {
              d.setPage(d.getPage() - 1);
            }
            topReached = true;
          }

        }, 2000);

        // Moving header and loaders when scrolls
        $(window).scroll(function(ev){
          // move header
          self.$el.find("thead > tr > th > div").css({marginLeft: -$(window).scrollLeft() + "px"});
        });

        this.model.data().bind('loadingRows', function(updown) {
          var fn = updown === 'up'? 'prepend': 'append';
          self.$el[fn]("

Loading more rows

Now viewing 120 of 264

");
        });

        this.model.data().bind('endLoadingRows', function() {
          //self.$el.find('.page_loader').remove();
        });

        this.bind('cellDblClick', this._editCell, this);
        this.model.bind('change:dataSource', this._onSQLView, this);
        // when model changes the header is re rendered so the notice should be added
        this.model.bind('change', this._onSQLView, this);
        this.model.bind('dataLoaded', this._checkEmptyTable);
        this.model.bind('dataLoaded', this._forceScroll);
        // this._models[0].bind('add', this._checkEmptyTable);

        this.bind('createRow', function() {
          self._checkEmptyTable();
        });

        // this.model.bind('loadModelStarted', function() {
        //   self.$el.fadeOut()
        // })

        // this.model.bind('loadModelCompleted', function() {
        //   self.$el.fadeIn()
        // })

        // this.model.bind('loadModelFailed', function() {
        //   self.$el.fadeIn()
        // })

      },

      render: function(args) {
        this.elder('render', args);
        this.trigger('render');
      },

      _onSQLView: function() {
        // if we are in a SQL view add a header
        this.$('.sqlview').remove();
        if(this.model.isInSQLView()) {
          if(!this.isEmptyTable()) {
            this.$('thead').append(
              this.getTemplate('table/views/sql_view_notice')()
            );
          }
          this.$('thead > tr').css('height', 64 + 42);
          if(this.isEmptyTable()) {
            this.addEmptySQLIfo();
          }
        }
      },

      _clearView: function(e) {
        e.preventDefault();
        this.trigger('clearSQLView');
        //this.model.useSQLView(null);
        return false;
      },

      _tableFromQuery: function(e) {
        var self = this;
        e.preventDefault();
        //this.model.useSQLView(null);
        var dlg = new cdb.admin.TableNameDialog({
          ok: function(name) {
            var sql = self.model.data().getSQL();
            alert('to be done in backend');
            /*
            var table = cdb.admin.CartoDBTableMetadata.createFromQuery(name, sql);

            table.save(null, {
              success: function() {
              },
              error: function() {
                cdb.log.error("problem creating table from query");
              }
            });
            */
          }
        });
        dlg.appendToBody().show();
        return false;
        /*
        from_query:SELECT * FROM cb_municipios_5000_e limit 1
        name:asdasdasd
        */
      },

      _getEditor: function(columnType, opts) {
        var editors = {
          'string': cdb.admin.EditStringDialog,
          'number': cdb.admin.EditNumberDialog,
          'date': cdb.admin.EditDateDialog,
          'geometry': cdb.admin.EditGeometryDialog,
          'boolean': cdb.admin.EditBooleanDialog
        };

        // clean previous if exits
        var view = this._editorsOpened;
        if(view) {
          view.clean();
        }

        var Editor = editors[columnType];
        this._editorsOpened = new Editor(opts);
        return this._editorsOpened;

      },

      _editCell: function(e, cell, x, y) {
        var self = this;
        if(this.model.data().isReadOnly()) {
          return;
        }
        var column = self.model.columnName(x-1);
        var columnType = this.model.getColumnType(column);

        if(this.model.isReservedColumn(column)) {
          return;
        }

        var row = self.model.data().getRowAt(y);

        var initial_value = '';
        if(self.model.data().getCell(y, column) === 0 || self.model.data().getCell(y, column) === '0') {
          initial_value = '0';
        } else if (self.model.data().getCell(y, column)) {
          initial_value = self.model.data().getCell(y, column);
        }
        var dlg = this._getEditor(columnType, {
          initial_value: initial_value,
          row: row,
          res: function(val) {
            var update = {};
            update[column] = val;
            row.set(update).save();
          }
        });

        if(!dlg) {
          cdb.log.error("editor not defined for column type " + columnType);
          return;
        }

        // auto add to table view
        // Check first if the row is the first or the cell is the last :)
        var $td = $(e.target).closest("td")
          , offset = $td.position()
          , width = $td.outerWidth();

        if ($td.parent().index() == 0) {
          offset.top += 5;
        } else {
          offset.top -= 11;
        }

        if ($td.index() == ($td.size() - 1)) {
          offset.left -= 22;
        } else {
          offset.left -= 11;
        }

        dlg.showAt(offset.left, offset.top, width, true);
      },

      /**
       * called when a new page is loaded
       */
      newPage: function(currentPage, direction) {
         var d = this.model.data();
         var rowspp = d.options.get('rows_per_page');
         var max_items = rowspp*4;
         if(d.size() > max_items) {
           var idx = currentPage*rowspp;
           cdb.log.debug("removing rows: " + d.size() + " " + idx);
           if(direction == 'up') {
             d.remove(d.models.slice(max_items, d.size()));
           } else {
             d.remove(d.models.slice(0, idx));
           }
         }
      },

      headerView: function(column) {
        if(column[1] !== 'header') {
          var v = new cdb.admin.HeaderView({
            column: column,
            table: this.model,
            sqlView: this.options.sqlView
          }).bind('georeference', function() { self.$('header .georeference').click();})
          this.addView(v);
          return v.render().el;
        } else {
          return '

';
        }
      },

      /**
      * Checks if the table has any rows, and if not, launch the method for showing the appropiate view elements
      * @method _checkEmptyTable
      */
      _checkEmptyTable: function() {
        if(this.isEmptyTable()) {
          this.addEmptyTableInfo();
        } else {
          this.cleanEmptyTableInfo();
        }
      },

      /**
      * Force the table to be at the beginning
      * @method _forceScroll
      */
      _forceScroll: function(ev){
        $(window).scrollLeft(0);
      },

      /**
      * Adds the view elements associated with no content in the table
      * @method addemptyTableInfo
      */
      addEmptyTableInfo: function() {
        if(this.$('.noRows').length == 0 && !this.model.isInSQLView()) {
          this.elder('addEmptyTableInfo');

          this.$el.hide();
          var columnsNumber = this.model.get('schema').length;
          var columns = '
+	';
          for(var i = 0; i < columnsNumber; i++) {
            columns += '	';
          }
          columns += '
';
          var columnsFooter = '
	';
          for(var i = 0; i < columnsNumber; i++) {
            columnsFooter += '	';
          }
          columnsFooter += '
';

          var $columns = $(columns+columnsFooter)
          this.$el.append($columns);

          this.template_base = cdb.templates.getTemplate('table/views/empty_table');
          var content = this.template_base(this.import_);
          var $footer = $('

' + content + '

');
          this.$el.append($footer);

          this.$el.fadeIn();
        }
      },

      /**
      * Adds the view elements associated with no content in the table when a SQL is applied
      * @method addEmptySQLIfo
      */
      addEmptySQLIfo: function() {
        if(this.model.isInSQLView()) {
          this.elder('addEmptySQLInfo');

          this.$el.hide();

          this.template_base = cdb.templates.getTemplate('table/views/empty_sql');
          var content = this.template_base(this.import_);
          var $footer = $('

' + content + '

');
          this.$el.append($footer);

          this.$el.fadeIn();
        }
      },

      /**
      * Removes from the view the no-content elements
      * @method cleanEmptyTableInfo
      */
      cleanEmptyTableInfo: function() {
        this.$('tfoot').fadeOut('fast', function() {
          $(this).remove();
        })
        this.$('.noRows').slideUp('fast', function() {
            $(this).remove();
        })
      },

      /**
      * Add a new row and removes the empty table view elemetns
      * @method addEmptyRow
      * @todo: (xabel) refactor this to include a "addRow" method in _models[0]
      */
      addEmptyRow: function() {
        this.dataModel.addRow({ at: 0});
        this.cleanEmptyTableInfo();
      },

      /**
      * Captures the change event from the row and produces a notification
      * @method rowChanged
      * @todo (xabel) i'm pretty sure there has to be a less convulted way of doing this, without capturing a event
      * to throw another event in the model to be captured by some view
      */
      rowChanged: function() {
        this.model.notice('Saving your edit.');
      },

      /**
      * Captures the change event from the row and produces a notification
      * @method rowSynched
      * @todo (xabel) i'm pretty sure there has to be a less convulted way of doing this, without capturing a event
      * to throw another event in the model to be captured by some view
      */
      rowSynched: function() {
        this.model.notice('Sucessfully saved');
      },

      /**
      * Captures the change event from the row and produces a notification
      * @method rowSynched
      * @todo (xabel) i'm pretty sure there has to be a less convulted way of doing this, without capturing a event
      * to throw another event in the model to be captured by some view
      */
      rowFailed: function() {
        this.model.notice('Oops, there has been an error saving your changes.');
      },

      /**
      * Captures the destroy event from the row and produces a notification
      * @method rowDestroyed
      */

      rowDestroyed: function() {
        this.model.notice('Sucessfully deleted')
        this._checkEmptyTable();
      }

    });

    cdb.admin.TableTab = cdb.core.View.extend({

      className: 'table',

      initialize: function() {
        this.tableView = new cdb.admin.TableView({
          dataModel: this.model.data(),
          model: this.model,
          sqlView: this.options.sqlView
        });

      },

      render: function() {
        this.$el.append(this.tableView.el);
        return this;
      }

    });

})();
<commit_msg>dataLoaded bind refactored<commit_after>
(function() {

    /**
     * table view shown in admin
     */
    cdb.admin.TableView = cdb.ui.common.Table.extend({
      classLabel: 'cdb.admin.TableView',
      events: cdb.core.View.extendEvents({
          'click .clearview': '_clearView',
          'click .sqlview .export_query': '_tableFromQuery',
          'click .noRows': 'addEmptyRow'
      }),

      rowView: cdb.admin.RowView,

      initialize: function() {
        var self = this;
        this.elder('initialize');
        this.options.row_header = true;
        this.model.data().bind('newPage', this.newPage, this);
        _.bindAll(this, "render", "addEmptyRow", "_checkEmptyTable", "_forceScroll", "rowChanged", "rowSynched", "rowFailed", "rowDestroyed", "emptyTable");
        var topReached = false;
        this._editorsOpened = null;

         // pagination
        setInterval(function() {
          if(!self.$el.is(":visible") || self.model.data().isFetchingPage()) {
            return;
          }
          var pos = $(this).scrollTop();
          var d = self.model.data();
          // do not let to fetch previous pages
          // until the user dont scroll back a little bit
          if(pos > 2) {
            topReached = false;
          }
          var pageSize = $(window).height() - self.$el.offset().top;
          var tableHeight = this.$('tbody').height();
          var realPos = pos + pageSize;
          if(tableHeight < pageSize) {
            return;
          }
          if(realPos > tableHeight) {
             d.setPage(d.getPage() + 1);
          } else if (pos <= 0) {
            if(!topReached) {
              d.setPage(d.getPage() - 1);
            }
            topReached = true;
          }

        }, 2000);

        // Moving header and loaders when scrolls
        $(window).scroll(function(ev){
          // move header
          self.$el.find("thead > tr > th > div").css({marginLeft: -$(window).scrollLeft() + "px"});
        });

        this.model.data().bind('loadingRows', function(updown) {
          var fn = updown === 'up'? 'prepend': 'append';
          self.$el[fn]("

Loading more rows

Now viewing 120 of 264

");
        });

        this.model.data().bind('endLoadingRows', function() {
          //self.$el.find('.page_loader').remove();
        });

        this.bind('cellDblClick', this._editCell, this);
        this.model.bind('change:dataSource', this._onSQLView, this);
        // when model changes the header is re rendered so the notice should be added
        this.model.bind('change', this._onSQLView, this);
        this.model.bind('dataLoaded', function() {
          self._checkEmptyTable();
          self._forceScroll();
        });

        this.bind('createRow', function() {
          self._checkEmptyTable();
        });

        // this.model.bind('loadModelStarted', function() {
        //   self.$el.fadeOut()
        // })

        // this.model.bind('loadModelCompleted', function() {
        //   self.$el.fadeIn()
        // })

        // this.model.bind('loadModelFailed', function() {
        //   self.$el.fadeIn()
        // })

      },

      render: function(args) {
        this.elder('render', args);
        this.trigger('render');
      },

      _onSQLView: function() {
        // if we are in a SQL view add a header
        this.$('.sqlview').remove();
        if(this.model.isInSQLView()) {
          if(!this.isEmptyTable()) {
            this.$('thead').append(
              this.getTemplate('table/views/sql_view_notice')()
            );
          }
          this.$('thead > tr').css('height', 64 + 42);
          if(this.isEmptyTable()) {
            this.addEmptySQLIfo();
          }
        }
      },

      _clearView: function(e) {
        e.preventDefault();
        this.trigger('clearSQLView');
        //this.model.useSQLView(null);
        return false;
      },

      _tableFromQuery: function(e) {
        var self = this;
        e.preventDefault();
        //this.model.useSQLView(null);
        var dlg = new cdb.admin.TableNameDialog({
          ok: function(name) {
            var sql = self.model.data().getSQL();
            alert('to be done in backend');
            /*
            var table = cdb.admin.CartoDBTableMetadata.createFromQuery(name, sql);

            table.save(null, {
              success: function() {
              },
              error: function() {
                cdb.log.error("problem creating table from query");
              }
            });
            */
          }
        });
        dlg.appendToBody().show();
        return false;
        /*
        from_query:SELECT * FROM cb_municipios_5000_e limit 1
        name:asdasdasd
        */
      },

      _getEditor: function(columnType, opts) {
        var editors = {
          'string': cdb.admin.EditStringDialog,
          'number': cdb.admin.EditNumberDialog,
          'date': cdb.admin.EditDateDialog,
          'geometry': cdb.admin.EditGeometryDialog,
          'boolean': cdb.admin.EditBooleanDialog
        };

        // clean previous if exits
        var view = this._editorsOpened;
        if(view) {
          view.clean();
        }

        var Editor = editors[columnType];
        this._editorsOpened = new Editor(opts);
        return this._editorsOpened;

      },

      _editCell: function(e, cell, x, y) {
        var self = this;
        if(this.model.data().isReadOnly()) {
          return;
        }
        var column = self.model.columnName(x-1);
        var columnType = this.model.getColumnType(column);

        if(this.model.isReservedColumn(column)) {
          return;
        }

        var row = self.model.data().getRowAt(y);

        var initial_value = '';
        if(self.model.data().getCell(y, column) === 0 || self.model.data().getCell(y, column) === '0') {
          initial_value = '0';
        } else if (self.model.data().getCell(y, column)) {
          initial_value = self.model.data().getCell(y, column);
        }
        var dlg = this._getEditor(columnType, {
          initial_value: initial_value,
          row: row,
          res: function(val) {
            var update = {};
            update[column] = val;
            row.set(update).save();
          }
        });

        if(!dlg) {
          cdb.log.error("editor not defined for column type " + columnType);
          return;
        }

        // auto add to table view
        // Check first if the row is the first or the cell is the last :)
        var $td = $(e.target).closest("td")
          , offset = $td.position()
          , width = $td.outerWidth();

        if ($td.parent().index() == 0) {
          offset.top += 5;
        } else {
          offset.top -= 11;
        }

        if ($td.index() == ($td.size() - 1)) {
          offset.left -= 22;
        } else {
          offset.left -= 11;
        }

        dlg.showAt(offset.left, offset.top, width, true);
      },

      /**
       * called when a new page is loaded
       */
      newPage: function(currentPage, direction) {
         var d = this.model.data();
         var rowspp = d.options.get('rows_per_page');
         var max_items = rowspp*4;
         if(d.size() > max_items) {
           var idx = currentPage*rowspp;
           cdb.log.debug("removing rows: " + d.size() + " " + idx);
           if(direction == 'up') {
             d.remove(d.models.slice(max_items, d.size()));
           } else {
             d.remove(d.models.slice(0, idx));
           }
         }
      },

      headerView: function(column) {
        if(column[1] !== 'header') {
          var v = new cdb.admin.HeaderView({
            column: column,
            table: this.model,
            sqlView: this.options.sqlView
          }).bind('georeference', function() { self.$('header .georeference').click();})
          this.addView(v);
          return v.render().el;
        } else {
          return '

';
        }
      },

      /**
      * Checks if the table has any rows, and if not, launch the method for showing the appropiate view elements
      * @method _checkEmptyTable
      */
      _checkEmptyTable: function() {
        if(this.isEmptyTable()) {
          this.addEmptyTableInfo();
        } else {
          this.cleanEmptyTableInfo();
        }
      },

      /**
      * Force the table to be at the beginning
      * @method _forceScroll
      */
      _forceScroll: function(ev){
        $(window).scrollLeft(0);
      },

      /**
      * Adds the view elements associated with no content in the table
      * @method addemptyTableInfo
      */
      addEmptyTableInfo: function() {
        if(this.$('.noRows').length == 0 && !this.model.isInSQLView()) {
          this.elder('addEmptyTableInfo');

          this.$el.hide();
          var columnsNumber = this.model.get('schema').length;
          var columns = '
+	';
          for(var i = 0; i < columnsNumber; i++) {
            columns += '	';
          }
          columns += '
';
          var columnsFooter = '
	';
          for(var i = 0; i < columnsNumber; i++) {
            columnsFooter += '	';
          }
          columnsFooter += '
';

          var $columns = $(columns+columnsFooter)
          this.$el.append($columns);

          this.template_base = cdb.templates.getTemplate('table/views/empty_table');
          var content = this.template_base(this.import_);
          var $footer = $('

' + content + '

');
          this.$el.append($footer);

          this.$el.fadeIn();
        }
      },

      /**
      * Adds the view elements associated with no content in the table when a SQL is applied
      * @method addEmptySQLIfo
      */
      addEmptySQLIfo: function() {
        if(this.model.isInSQLView()) {
          this.elder('addEmptySQLInfo');

          this.$el.hide();

          this.template_base = cdb.templates.getTemplate('table/views/empty_sql');
          var content = this.template_base(this.import_);
          var $footer = $('

' + content + '

');
          this.$el.append($footer);

          this.$el.fadeIn();
        }
      },

      /**
      * Removes from the view the no-content elements
      * @method cleanEmptyTableInfo
      */
      cleanEmptyTableInfo: function() {
        this.$('tfoot').fadeOut('fast', function() {
          $(this).remove();
        })
        this.$('.noRows').slideUp('fast', function() {
            $(this).remove();
        })
      },

      /**
      * Add a new row and removes the empty table view elemetns
      * @method addEmptyRow
      * @todo: (xabel) refactor this to include a "addRow" method in _models[0]
      */
      addEmptyRow: function() {
        this.dataModel.addRow({ at: 0});
        this.cleanEmptyTableInfo();
      },

      /**
      * Captures the change event from the row and produces a notification
      * @method rowChanged
      * @todo (xabel) i'm pretty sure there has to be a less convulted way of doing this, without capturing a event
      * to throw another event in the model to be captured by some view
      */
      rowChanged: function() {
        this.model.notice('Saving your edit.');
      },

      /**
      * Captures the change event from the row and produces a notification
      * @method rowSynched
      * @todo (xabel) i'm pretty sure there has to be a less convulted way of doing this, without capturing a event
      * to throw another event in the model to be captured by some view
      */
      rowSynched: function() {
        this.model.notice('Sucessfully saved');
      },

      /**
      * Captures the change event from the row and produces a notification
      * @method rowSynched
      * @todo (xabel) i'm pretty sure there has to be a less convulted way of doing this, without capturing a event
      * to throw another event in the model to be captured by some view
      */
      rowFailed: function() {
        this.model.notice('Oops, there has been an error saving your changes.');
      },

      /**
      * Captures the destroy event from the row and produces a notification
      * @method rowDestroyed
      */

      rowDestroyed: function() {
        this.model.notice('Sucessfully deleted')
        this._checkEmptyTable();
      }

    });

    cdb.admin.TableTab = cdb.core.View.extend({

      className: 'table',

      initialize: function() {
        this.tableView = new cdb.admin.TableView({
          dataModel: this.model.data(),
          model: this.model,
          sqlView: this.options.sqlView
        });

      },

      render: function() {
        this.$el.append(this.tableView.el);
        return this;
      }

    });

})();
<|endoftext|>


<commit_before>// 'use strict'
var http = require('http');
var cheerio = require('cheerio');

var blastoff = (function () {

  function getLaunchData(count, callback) {

    if (typeof count === 'function') {
      callback = count;
      count = 1;
    }

    http.get('http://spaceflightnow.com/launch-schedule/', function (response) {

      var body = '';
      response.on('data', function (chunk) {
        body += chunk;
      });
      response.on('error', function (err) {
        return callback(err);
      });
      response.on('end', function () {
        return callback(null, parseLaunchData(body, count));
      });

    });
  }

  function parseLaunchData(data, count) {
    var $ = cheerio.load(data);
    var launchData = [];

    var launchCount = $('.datename .mission').length;

    for (var i = 0; i < count && i < 60; i++) {
      mission = $('.datename .mission').eq(i).text();
      date = $('.datename .launchdate').eq(i).text();

      if(missiondata.length < 2){
        break;
      }

      missiondata = $('.missiondata').eq(i).text().split('\n');
      launchtime = missiondata[0].slice(13);
      launchsite = missiondata[1].slice(13);
      description = $('.missdescrip').eq(i).text().slice(0, -9);

      launchData.push({
        mission: mission,
        date: date,
        launchtime: launchtime,
        launchsite: launchsite,
        description: description
      });
    }

    return launchData;
  }

  return getLaunchData;

})();

module.exports = blastoff;
<commit_msg>Minor goof fixup<commit_after>// 'use strict'
var http = require('http');
var cheerio = require('cheerio');

var blastoff = (function () {

  function getLaunchData(count, callback) {

    if (typeof count === 'function') {
      callback = count;
      count = 1;
    }

    http.get('http://spaceflightnow.com/launch-schedule/', function (response) {

      var body = '';
      response.on('data', function (chunk) {
        body += chunk;
      });
      response.on('error', function (err) {
        return callback(err);
      });
      response.on('end', function () {
        return callback(null, parseLaunchData(body, count));
      });

    });
  }

  function parseLaunchData(data, count) {
    var $ = cheerio.load(data);
    var launchData = [];

    var launchCount = $('.datename .mission').length;

    for (var i = 0; i < count && i < 60; i++) {
      mission = $('.datename .mission').eq(i).text();
      date = $('.datename .launchdate').eq(i).text();
      missiondata = $('.missiondata').eq(i).text().split('\n');

      if(missiondata.length < 2){
        break;
      }

      launchtime = missiondata[0].slice(13);
      launchsite = missiondata[1].slice(13);
      description = $('.missdescrip').eq(i).text().slice(0, -9);

      launchData.push({
        mission: mission,
        date: date,
        launchtime: launchtime,
        launchsite: launchsite,
        description: description
      });
    }

    return launchData;
  }

  return getLaunchData;

})();

module.exports = blastoff;
<|endoftext|>