<commit_before>import Ember from 'ember';

import config from '../config/environment';

export default Ember.Service.extend({
    host: config.HOST,
    namespace: 'solr',
    core: 'dina',

    parseResponse (data) {
        return {
            records: data.response.docs.mapBy('primary_id'),
            totalRows: data.response.numFound
        };
    },

    select (query, {entityType, fq, rows}) {
        const service = this;
        let url = `${this.host}/${this.namespace}/${this.core}/select?q=${query}&fl=primary_id&wt=json&indent=true`;

        let fqString = '';
        if (entityType) {
            fqString += `&fq=entity_type%3A${entityType}`;
        }

        for(let key in fq) {
            fqString += `&fq=${key}%3D${fq[key]}`;
        }

        url += fqString;

        if (rows) {
            url += `&rows=${rows}`;
        }

        return new Ember.RSVP.Promise(function (resolve, reject) {
            Ember.$.getJSON(url).success((data)=>{
                let {records, totalRows} = service.parseResponse(data);
                resolve({records, totalRows});
            }).fail((error)=>{
                reject(error);
            });
        });
    },
    updateIndex () {
        const url = `${this.host}/${this.namespace}/${this.core}/dataimport?command=delta-import&commit=1&wt=json`;
        Ember.$.getJSON(url);
    }
});
<commit_msg>Use colon as separator in solr query<commit_after>import Ember from 'ember';

import config from '../config/environment';

export default Ember.Service.extend({
    host: config.HOST,
    namespace: 'solr',
    core: 'dina',

    parseResponse (data) {
        return {
            records: data.response.docs.mapBy('primary_id'),
            totalRows: data.response.numFound
        };
    },

    select (query, {entityType, fq, rows}) {
        const service = this;
        let url = `${this.host}/${this.namespace}/${this.core}/select?q=${query}&fl=primary_id&wt=json&indent=true`;

        let fqString = '';
        if (entityType) {
            fq['entity_type'] = entityType;
        }

        for(let key in fq) {
            fqString += `&fq=${key}%3A${fq[key]}`;
        }

        url += fqString;

        if (rows) {
            url += `&rows=${rows}`;
        }

        return new Ember.RSVP.Promise(function (resolve, reject) {
            Ember.$.getJSON(url).success((data)=>{
                let {records, totalRows} = service.parseResponse(data);
                resolve({records, totalRows});
            }).fail((error)=>{
                reject(error);
            });
        });
    },
    updateIndex () {
        const url = `${this.host}/${this.namespace}/${this.core}/dataimport?command=delta-import&commit=1&wt=json`;
        Ember.$.getJSON(url);
    }
});
<|endoftext|>


<commit_before>$.ajaxSetup({async: false});

$.getJSON('Dengue.json', function (data) {
    DengueTW = data
});
function initialize() {
    var map,
        currentPlayIndex = false,
        cunli;

    /*map setting*/
    $('#map-canvas').height(window.outerHeight / 2.2);

    map = new google.maps.Map(document.getElementById('map-canvas'), {
        zoom: 12,
        center: {lat: 23.00, lng: 120.30}
    });

    $.getJSON('../geojson/cunli.json', function (data) {
        cunli = map.data.addGeoJson(data);
    });

    cunli.forEach(function (value) {
        var key = value.getProperty('VILLAGE_ID'),
            count = 0;
        if (DengueTW[key]) {
            DengueTW[key].forEach(function (val) {
                count += val[1];
            });
        }
        value.setProperty('num', count);
    });

    map.data.setStyle(function (feature) {
        color = ColorBar(feature.getProperty('num'));
        return {
            fillColor: color,
            fillOpacity: 0.6,
            strokeColor: 'gray',
            strokeWeight: 1
        }
    });

    map.data.addListener('mouseover', function (event) {
        var Cunli = event.feature.getProperty('C_Name') + event.feature.getProperty('T_Name') + event.feature.getProperty('V_Name');
        map.data.revertStyle();
        map.data.overrideStyle(event.feature, {fillColor: 'white'});
        $('#content').html('
' + Cunli + ' ：' + event.feature.getProperty('num') + ' 例
').removeClass('text-muted');
    });

    map.data.addListener('mouseout', function (event) {
        map.data.revertStyle();
        $('#content').html('在地圖上滑動或點選以顯示數據').addClass('text-muted');
    });

    map.data.addListener('click', function (event) {
        var Cunli = value.getProperty('VILLAGE_ID');
        var CunliTitle = event.feature.getProperty('C_Name') + event.feature.getProperty('T_Name') + event.feature.getProperty('V_Name');
        if ($('#myTab a[name|="' + Cunli + '"]').tab('show').length === 0) {
            $('#myTab').append('
' + CunliTitle +
                    '<button class="close" onclick="closeTab(this.parentNode)">×</button>
');
            $('#myTabContent').append('

');
            $('#myTab a:last').tab('show');
            createStockChart(Cunli, cunli);
            $('#myTab li a:last').click(function (e) {
                $(window).trigger('resize');
            });
        }
    });
    createStockChart('total', cunli);

    $('#playButton1').on('click', function () {
        var maxIndex = DengueTW['total'].length;
        if (false === currentPlayIndex) {
            currentPlayIndex = 0;
        } else {
            currentPlayIndex += 1;
            $(this).addClass('active disabled').find('.glyphicon').show();
        }

        if (currentPlayIndex < maxIndex) {
            showDateMap(new Date(DengueTW['total'][currentPlayIndex][0]), cunli);
            setTimeout(function () {
                $('#playButton1').trigger('click');
            }, 300);
        } else {
            $(this).removeClass('active disabled').find('.glyphicon').hide();
            currentPlayIndex = false;
            $('#title').html('');
        }
        return false;
    });

    $('#playButton2').on('click', function () {
        var maxIndex = DengueTW['total'].length;
        if (false === currentPlayIndex) {
            currentPlayIndex = 0;
        } else {
            currentPlayIndex += 1;
            $(this).addClass('active disabled').find('.glyphicon').show();
        }

        if (currentPlayIndex < maxIndex) {
            showDayMap(new Date(DengueTW['total'][currentPlayIndex][0]), cunli);
            setTimeout(function () {
                $('#playButton2').trigger('click');
            }, 300);
        } else {
            $(this).removeClass('active disabled').find('.glyphicon').hide();
            currentPlayIndex = false;
            $('#title').html('');
        }
        return false;
    });
}

function createStockChart(Cunli, cunli) {
    var series = [];

    for (var i = 0; i < DengueTW[Cunli].length; i++) {
        series.push([new Date(DengueTW[Cunli][i][0]).getTime(), DengueTW[Cunli][i][1]]);
    }

    Highcharts.setOptions({
        lang: {
            months: ['一月', '二月', '三月', '四月', '五月', '六月',  '七月', '八月', '九月', '十月', '十一月', '十二月'],
            shortMonths: ['一月', '二月', '三月', '四月', '五月', '六月',  '七月', '八月', '九月', '十月', '十一月', '十二月'],
            weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
            loading: '載入中'
        }
    });

    $('#' + Cunli).highcharts('StockChart', {
        chart: {
            alignTicks: false,
            width: $('#myTabContent').width(),
            height: $('#myTabContent').height()
        },
        rangeSelector: {
            enabled: false
        },
        tooltip: {
            enabled: true,
            positioner: function () {
                return {x: 10, y: 30}
            }
        },
        plotOptions: {
            series: {
                cursor: 'pointer',
                point: {
                    events: {
                        click: function () {
                            showDayMap(new Date(this.x), cunli);
                        }
                    }
                },
            }
        },
        series: [{
                type: 'column',
                name: Cunli,
                data: series,
            }]
    });
}

function showDateMap(clickedDate, cunli) {
    var yyyy = clickedDate.getFullYear().toString(),
        mm = (clickedDate.getMonth() + 1).toString(),
        dd = clickedDate.getDate().toString(),
        clickedDateKey = yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]);

    $('#title').html(clickedDateKey + ' 累積病例');
    cunli.forEach(function (value) {
        var key = value.getProperty('T_Name') + value.getProperty('V_Name'),
            count = 0;

        if (DengueTW[key]) {
            DengueTW[key].forEach(function (val) {
                var recordDate = new Date(val[0]);
                if (recordDate <= clickedDate) {
                    count += val[1];
                }
            });
        }
        value.setProperty('num', count);
    });
}

function showDayMap(clickedDate, cunli) {
    var yyyy = clickedDate.getFullYear().toString(),
        mm = (clickedDate.getMonth() + 1).toString(),
        dd = clickedDate.getDate().toString(),
        clickedDateKey = yyyy + '-' + (mm[1] ? mm : "0" + mm[0]) + '-' + (dd[1] ? dd : "0" + dd[0]);

    $('#title').html(clickedDateKey + ' 當日病例');
    cunli.forEach(function (value) {
        var key = value.getProperty('T_Name') + value.getProperty('V_Name'),
            count = 0;

        if (DengueTW[key]) {
            DengueTW[key].forEach(function (val) {
                if (clickedDateKey == val[0]) {
                    count += val[1];
                }
            });
        }
        value.setProperty('num', count);
    });
}

$(window).resize(function () {
    var len = $('#myTabContent > .tab-pane').length;
    for (var i = 0; i < len; i++) {
        $('#myTabContent > .tab-pane').eq(i).highcharts().setSize($('#myTabContent').width(), $('#myTabContent').height());
    }
});

function closeTab(node) {
    var nodename = node.name;
    node.parentNode.remove();
    $('#' + nodename).remove();
    $('#myTab a:first').tab('show');
}

google.maps.event.addDomListener(window, 'load', initialize);<commit_msg>fix method to get property<commit_after>$.ajaxSetup({async: false});

$.getJSON('Dengue.json', function (data) {
    DengueTW = data
});
function initialize() {
    var map,
        currentPlayIndex = false,
        cunli;

    /*map setting*/
    $('#map-canvas').height(window.outerHeight / 2.2);

    map = new google.maps.Map(document.getElementById('map-canvas'), {
        zoom: 12,
        center: {lat: 23.00, lng: 120.30}
    });

    $.getJSON('../geojson/cunli.json', function (data) {
        cunli = map.data.addGeoJson(data);
    });

    cunli.forEach(function (value) {
        var key = value.getProperty('VILLAGE_ID'),
            count = 0;
        if (DengueTW[key]) {
            DengueTW[key].forEach(function (val) {
                count += val[1];
            });
        }
        value.setProperty('num', count);
    });

    map.data.setStyle(function (feature) {
        color = ColorBar(feature.getProperty('num'));
        return {
            fillColor: color,
            fillOpacity: 0.6,
            strokeColor: 'gray',
            strokeWeight: 1
        }
    });

    map.data.addListener('mouseover', function (event) {
        var Cunli = event.feature.getProperty('C_Name') + event.feature.getProperty('T_Name') + event.feature.getProperty('V_Name');
        map.data.revertStyle();
        map.data.overrideStyle(event.feature, {fillColor: 'white'});
        $('#content').html('
' + Cunli + ' ：' + event.feature.getProperty('num') + ' 例
').removeClass('text-muted');
    });

    map.data.addListener('mouseout', function (event) {
        map.data.revertStyle();
        $('#content').html('在地圖上滑動或點選以顯示數據').addClass('text-muted');
    });

    map.data.addListener('click', function (event) {
        var Cunli = event.feature.getProperty('VILLAGE_ID');
        var CunliTitle = event.feature.getProperty('C_Name') + event.feature.getProperty('T_Name') + event.feature.getProperty('V_Name');
        if ($('#myTab a[name|="' + Cunli + '"]').tab('show').length === 0) {
            $('#myTab').append('
' + CunliTitle +
                    '<button class="close" onclick="closeTab(this.parentNode)">×</button>
');
            $('#myTabContent').append('

');
            $('#myTab a:last').tab('show');
            createStockChart(Cunli, cunli);
            $('#myTab li a:last').click(function (e) {
                $(window).trigger('resize');
            });
        }
    });
    createStockChart('total', cunli);

    $('#playButton1').on('click', function () {
        var maxIndex = DengueTW['total'].length;
        if (false === currentPlayIndex) {
            currentPlayIndex = 0;
        } else {
            currentPlayIndex += 1;
            $(this).addClass('active disabled').find('.glyphicon').show();
        }

        if (currentPlayIndex < maxIndex) {
            showDateMap(new Date(DengueTW['total'][currentPlayIndex][0]), cunli);
            setTimeout(function () {
                $('#playButton1').trigger('click');
            }, 300);
        } else {
            $(this).removeClass('active disabled').find('.glyphicon').hide();
            currentPlayIndex = false;
            $('#title').html('');
        }
        return false;
    });

    $('#playButton2').on('click', function () {
        var maxIndex = DengueTW['total'].length;
        if (false === currentPlayIndex) {
            currentPlayIndex = 0;
        } else {
            currentPlayIndex += 1;
            $(this).addClass('active disabled').find('.glyphicon').show();
        }

        if (currentPlayIndex < maxIndex) {
            showDayMap(new Date(DengueTW['total'][currentPlayIndex][0]), cunli);
            setTimeout(function () {
                $('#playButton2').trigger('click');
            }, 300);
        } else {
            $(this).removeClass('active disabled').find('.glyphicon').hide();
            currentPlayIndex = false;
            $('#title').html('');
        }
        return false;
    });
}

function createStockChart(Cunli, cunli) {
    var series = [];

    for (var i = 0; i < DengueTW[Cunli].length; i++) {
        series.push([new Date(DengueTW[Cunli][i][0]).getTime(), DengueTW[Cunli][i][1]]);
    }

    Highcharts.setOptions({
        lang: {
            months: ['一月', '二月', '三月', '四月', '五月', '六月',  '七月', '八月', '九月', '十月', '十一月', '十二月'],
            shortMonths: ['一月', '二月', '三月', '四月', '五月', '六月',  '七月', '八月', '九月', '十月', '十一月', '十二月'],
            weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
            loading: '載入中'
        }
    });

    $('#' + Cunli).highcharts('StockChart', {
        chart: {
            alignTicks: false,
            width: $('#myTabContent').width(),
            height: $('#myTabContent').height()
        },
        rangeSelector: {
            enabled: false
        },
        tooltip: {
            enabled: true,
            positioner: function () {
                return {x: 10, y: 30}
            }
        },
        plotOptions: {
            series: {
                cursor: 'pointer',
                point: {
                    events: {
                        click: function () {
                            showDayMap(new Date(this.x), cunli);
                        }
                    }
                },
            }
        },
        series: [{
                type: 'column',
                name: Cunli,
                data: series,
            }]
    });
}

function showDateMap(clickedDate, cunli) {
    var yyyy = clickedDate.getFullYear().toString(),
        mm = (clickedDate.getMonth() + 1).toString(),
        dd = clickedDate.getDate().toString(),
        clickedDateKey = yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]);

    $('#title').html(clickedDateKey + ' 累積病例');
    cunli.forEach(function (value) {
        var key = value.getProperty('T_Name') + value.getProperty('V_Name'),
            count = 0;

        if (DengueTW[key]) {
            DengueTW[key].forEach(function (val) {
                var recordDate = new Date(val[0]);
                if (recordDate <= clickedDate) {
                    count += val[1];
                }
            });
        }
        value.setProperty('num', count);
    });
}

function showDayMap(clickedDate, cunli) {
    var yyyy = clickedDate.getFullYear().toString(),
        mm = (clickedDate.getMonth() + 1).toString(),
        dd = clickedDate.getDate().toString(),
        clickedDateKey = yyyy + '-' + (mm[1] ? mm : "0" + mm[0]) + '-' + (dd[1] ? dd : "0" + dd[0]);

    $('#title').html(clickedDateKey + ' 當日病例');
    cunli.forEach(function (value) {
        var key = value.getProperty('T_Name') + value.getProperty('V_Name'),
            count = 0;

        if (DengueTW[key]) {
            DengueTW[key].forEach(function (val) {
                if (clickedDateKey == val[0]) {
                    count += val[1];
                }
            });
        }
        value.setProperty('num', count);
    });
}

$(window).resize(function () {
    var len = $('#myTabContent > .tab-pane').length;
    for (var i = 0; i < len; i++) {
        $('#myTabContent > .tab-pane').eq(i).highcharts().setSize($('#myTabContent').width(), $('#myTabContent').height());
    }
});

function closeTab(node) {
    var nodename = node.name;
    node.parentNode.remove();
    $('#' + nodename).remove();
    $('#myTab a:first').tab('show');
}

google.maps.event.addDomListener(window, 'load', initialize);<|endoftext|>


<commit_before>// Load mist textures

let numTexturesLoaded = 0;
let texturesLoaded = false;

// Paths to all the mist particle textures
const texturePaths = [
  require('./textures/mist-particle-1.png'),
  require('./textures/mist-particle-2.png'),
  require('./textures/mist-particle-3.png'),
  require('./textures/mist-particle-4.png'),
  require('./textures/mist-particle-5.png'),
];

// Array of Image objects, one for each mist particle texture
const textures = texturePaths.map(() => new Image());

// Called when a mist particle texture finishes loading to be able to tell when all mist particles
// have loaded.
function textureLoadCallback() {
  numTexturesLoaded += 1;
  if (numTexturesLoaded === texturePaths.length) {
    texturesLoaded = true;
  }
}

// Assign a mist particle texture to each Image object
for (let i = 0; i < textures.length; i += 1) {
  textures[i].addEventListener('load', textureLoadCallback);
  textures[i].src = texturePaths[i];
}

// Helper functions

// My [].fill polyfill
if (!Array.prototype.fill) {
  /* eslint-disable no-extend-native */
  Array.prototype.fill = (value) => {
    for (let i = 0; i < this.length; i += 1) {
      this[i] = value;
    }
    return this;
  };
  /* eslint-enable no-extend-native */
}

/** Return a random number between `low` and `high` */
function random(low, high) {
  return (Math.random() * (high - low)) + low;
}

/** Return a random integer between `low` and `high-1` */
function randint(low, high) {
  return Math.floor(random(low, high));
}

/** Return a random item from an array */
function randchoice(array) {
  return array[randint(0, array.length)];
}

/** Implements basic particle physics (moving and bouncing) */
class Particle {
  /**
   * Create a new particle in a simulation.
   * Particles have positions and velocities, and remember which renderer they're bound to.
   * @param {ParticleRenderer} renderer - the ParticleRender that the particle belongs to.
   * @param {number} x - the initial X position of the particle
   * @param {number} y - the initial Y position of the particle
   * @param {number} vx - the initial X velocity of the particle
   * @param {number} vy - the initial Y velocity of the particle
   * @param {number} vrot - the initial rotational velocity of the particle (degrees)
   */
  constructor(renderer, x, y, vx, vy, vrot, image) {
    this.renderer = renderer;
    // Image object for mist particle texture. Not used by Particle, used by ParticleRenderer
    this.image = image;

    this.rot = 0;      // Rotation (in degrees)
    this.x = x;        // X position on canvas
    this.y = y;        // Y position on canvas
    this.vx = vx;      // X velocity
    this.vy = vy;      // Y velocity
    this.vrot = vrot;  // Rotational velocity
  }

  /** Advance the simulation by one step */
  step() {
    // Bounce particles when they hit the edges of the canvas
    const marginX = this.image.width / 2;
    const marginY = this.image.height / 2;
    if (this.x < -marginX || this.x >= this.renderer.width() + marginX) {
      this.bounceX();
    }
    if (this.y < -1 * marginY || this.y >= this.renderer.height() + marginX) {
      this.bounceY();
    }

    this.x += this.vx;
    this.y += this.vy;

    this.rot += this.vrot;
    this.rot %= 360;
  }

  /** Cause the current particle to bounce in the X direction */
  bounceX() {
    this.vx = -1 * this.vx;
  }

  /** Cause the current particle to bounce in the Y direction */
  bounceY() {
    this.vy = -1 * this.vy;
  }
}

/** Orchestrates and renders particles */
class ParticleRenderer {
  /**
   * Create a new particle renderer.
   * @param {CanvasRenderingContext2D} ctx - the rendering context of the canvas to draw on
   * @param {number} particleCount - the number of particles to maintain in the simulation
   * @param {number} fps - the number of frames per second at which the simulation should run
   */
  constructor(ctx, particleCount, fps) {
    this.ctx = ctx;
    this.particleCount = particleCount;
    this.fps = fps;

    this.particles = new Array(this.particleCount).fill(0).map(() => new Particle(
      this,
      randint(0, this.width()),   // X position
      randint(0, this.height()),  // Y position
      randint(-4, 4),             // X velocity
      randint(-4, 4),             // Y velocity
      random(-0.5, 0.5),          // Rotational velocity
      randchoice(textures),       // Random choice of the mist particle textures
    ));

    // Make sure no particles have 0 velocity in either direction
    this.particles = this.particles.map((p) => {
      const particle = p;
      while (particle.vx === 0) particle.vx = randint(-4, 4);
      while (particle.vy === 0) particle.vy = randint(-4, 4);
      return particle;
    });
  }

  /**
   * Draw the particles on the canvas
   */
  draw() {
    this.ctx.globalCompositeOperation = 'source-over';

    if (texturesLoaded) {
      this.ctx.clearRect(0, 0, this.width(), this.height());
      this.particles.forEach((p) => {
        const width = window.innerWidth / 3;
        const height = width;
        const rotation = p.rot * (Math.PI / 180);

        this.ctx.translate(p.x, p.y);
        this.ctx.rotate(rotation);

        this.ctx.drawImage(
          p.image,
          -(width / 2), -(height / 2),
          width, height,
        );

        this.ctx.rotate(-rotation);
        this.ctx.translate(-p.x, -p.y);
      });
    }

    // Create fade by using blend modes to create gradient opacity masks

    this.ctx.globalCompositeOperation = 'destination-out';
    const gradient = this.ctx.createLinearGradient(0, 0, 0, this.height() / 2);
    gradient.addColorStop(0.0, 'rgba(255, 255, 255, 1)');
    gradient.addColorStop(1.0, 'rgba(255, 255, 255, 0)');
    this.ctx.fillStyle = gradient;
    this.ctx.fillRect(0, 0, this.width(), this.height() / 2);
  }

  /**
   * Advance the simulation by one step
   */
  step() {
    this.particles.forEach(particle => particle.step());
  }

  /**
   * Begin a render loop
   */
  start() {
    // TODO
    this.interval = setInterval(() => {
      this.step();
      requestAnimationFrame(() => { this.draw(); });
    }, 1000 / this.fps);
  }

  /**
   * Get the width of the canvas coordinate system.
   * @return {number} the width of the canvas
   */
  width() {
    return this.ctx.canvas.width;
  }

  /**
   * Get the height of the canvas coordinate system
   * @return {number} the height of the canvas
   */
  height() {
    return this.ctx.canvas.height;
  }
}

window.addEventListener('resize', () => {
  const canvas = document.getElementById('mist');

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight * 0.8;
});

window.addEventListener('load', () => window.dispatchEvent(new Event('resize')));

window.addEventListener('load', () => {
  const canvas = document.getElementById('mist');
  const ctx = canvas.getContext('2d');
  window.mistSim = new ParticleRenderer(ctx, 85, 25);
  window.mistSim.start();
});
<commit_msg>Add radial gradient cutout<commit_after>// Load mist textures

let numTexturesLoaded = 0;
let texturesLoaded = false;

// Paths to all the mist particle textures
const texturePaths = [
  require('./textures/mist-particle-1.png'),
  require('./textures/mist-particle-2.png'),
  require('./textures/mist-particle-3.png'),
  require('./textures/mist-particle-4.png'),
  require('./textures/mist-particle-5.png'),
];

// Array of Image objects, one for each mist particle texture
const textures = texturePaths.map(() => new Image());

// Called when a mist particle texture finishes loading to be able to tell when all mist particles
// have loaded.
function textureLoadCallback() {
  numTexturesLoaded += 1;
  if (numTexturesLoaded === texturePaths.length) {
    texturesLoaded = true;
  }
}

// Assign a mist particle texture to each Image object
for (let i = 0; i < textures.length; i += 1) {
  textures[i].addEventListener('load', textureLoadCallback);
  textures[i].src = texturePaths[i];
}

// Helper functions

// My [].fill polyfill
if (!Array.prototype.fill) {
  /* eslint-disable no-extend-native */
  Array.prototype.fill = (value) => {
    for (let i = 0; i < this.length; i += 1) {
      this[i] = value;
    }
    return this;
  };
  /* eslint-enable no-extend-native */
}

/** Return a random number between `low` and `high` */
function random(low, high) {
  return (Math.random() * (high - low)) + low;
}

/** Return a random integer between `low` and `high-1` */
function randint(low, high) {
  return Math.floor(random(low, high));
}

/** Return a random item from an array */
function randchoice(array) {
  return array[randint(0, array.length)];
}

/** Implements basic particle physics (moving and bouncing) */
class Particle {
  /**
   * Create a new particle in a simulation.
   * Particles have positions and velocities, and remember which renderer they're bound to.
   * @param {ParticleRenderer} renderer - the ParticleRender that the particle belongs to.
   * @param {number} x - the initial X position of the particle
   * @param {number} y - the initial Y position of the particle
   * @param {number} vx - the initial X velocity of the particle
   * @param {number} vy - the initial Y velocity of the particle
   * @param {number} vrot - the initial rotational velocity of the particle (degrees)
   */
  constructor(renderer, x, y, vx, vy, vrot, image) {
    this.renderer = renderer;
    // Image object for mist particle texture. Not used by Particle, used by ParticleRenderer
    this.image = image;

    this.rot = 0;      // Rotation (in degrees)
    this.x = x;        // X position on canvas
    this.y = y;        // Y position on canvas
    this.vx = vx;      // X velocity
    this.vy = vy;      // Y velocity
    this.vrot = vrot;  // Rotational velocity
  }

  /** Advance the simulation by one step */
  step() {
    // Bounce particles when they hit the edges of the canvas
    const marginX = this.image.width / 2;
    const marginY = this.image.height / 2;
    if (this.x < -marginX || this.x >= this.renderer.width() + marginX) {
      this.bounceX();
    }
    if (this.y < -1 * marginY || this.y >= this.renderer.height() + marginX) {
      this.bounceY();
    }

    this.x += this.vx;
    this.y += this.vy;

    this.rot += this.vrot;
    this.rot %= 360;
  }

  /** Cause the current particle to bounce in the X direction */
  bounceX() {
    this.vx = -1 * this.vx;
  }

  /** Cause the current particle to bounce in the Y direction */
  bounceY() {
    this.vy = -1 * this.vy;
  }
}

/** Orchestrates and renders particles */
class ParticleRenderer {
  /**
   * Create a new particle renderer.
   * @param {CanvasRenderingContext2D} ctx - the rendering context of the canvas to draw on
   * @param {number} particleCount - the number of particles to maintain in the simulation
   * @param {number} fps - the number of frames per second at which the simulation should run
   */
  constructor(ctx, particleCount, fps) {
    this.ctx = ctx;
    this.particleCount = particleCount;
    this.fps = fps;

    this.particles = new Array(this.particleCount).fill(0).map(() => new Particle(
      this,
      randint(0, this.width()),   // X position
      randint(0, this.height()),  // Y position
      randint(-4, 4),             // X velocity
      randint(-4, 4),             // Y velocity
      random(-0.5, 0.5),          // Rotational velocity
      randchoice(textures),       // Random choice of the mist particle textures
    ));

    // Make sure no particles have 0 velocity in either direction
    this.particles = this.particles.map((p) => {
      const particle = p;
      while (particle.vx === 0) particle.vx = randint(-4, 4);
      while (particle.vy === 0) particle.vy = randint(-4, 4);
      return particle;
    });
  }

  /**
   * Draw the particles on the canvas
   */
  draw() {
    this.ctx.globalCompositeOperation = 'source-over';

    if (texturesLoaded) {
      this.ctx.clearRect(0, 0, this.width(), this.height());
      this.particles.forEach((p) => {
        const width = window.innerWidth / 3;
        const height = width;
        const rotation = p.rot * (Math.PI / 180);

        this.ctx.translate(p.x, p.y);
        this.ctx.rotate(rotation);

        this.ctx.drawImage(
          p.image,
          -(width / 2), -(height / 2),
          width, height,
        );

        this.ctx.rotate(-rotation);
        this.ctx.translate(-p.x, -p.y);
      });
    }

    // Create fade by using blend modes to create gradient opacity masks

    this.ctx.globalCompositeOperation = 'destination-out';
    // Short linear fade at the top
    const gradient1 = this.ctx.createLinearGradient(0, 0, 0, this.height() / 2);
    gradient1.addColorStop(0, 'rgba(255, 255, 255, 1)');
    gradient1.addColorStop(1, 'rgba(255, 255, 255, 0)');
    this.ctx.fillStyle = gradient1;
    this.ctx.fillRect(0, 0, this.width(), this.height() / 2);

    // Large radial gradient to cut out the top center in an arc
    const gradient2 = this.ctx.createRadialGradient(
      (this.width() / 2), 0, 0,
      (this.width() / 2), 0, (this.height() * 2),
    );
    gradient2.addColorStop(0, 'rgba(255, 255, 255, 1)');
    gradient2.addColorStop(1, 'rgba(255, 255, 255, 0)');
    this.ctx.fillStyle = gradient2;
    this.ctx.fillRect(0, 0, this.width(), this.height() * 2);
  }

  /**
   * Advance the simulation by one step
   */
  step() {
    this.particles.forEach(particle => particle.step());
  }

  /**
   * Begin a render loop
   */
  start() {
    // TODO
    this.interval = setInterval(() => {
      this.step();
      requestAnimationFrame(() => { this.draw(); });
    }, 1000 / this.fps);
  }

  /**
   * Get the width of the canvas coordinate system.
   * @return {number} the width of the canvas
   */
  width() {
    return this.ctx.canvas.width;
  }

  /**
   * Get the height of the canvas coordinate system
   * @return {number} the height of the canvas
   */
  height() {
    return this.ctx.canvas.height;
  }
}

window.addEventListener('resize', () => {
  const canvas = document.getElementById('mist');

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight * 0.8;
});

window.addEventListener('load', () => window.dispatchEvent(new Event('resize')));

window.addEventListener('load', () => {
  const canvas = document.getElementById('mist');
  const ctx = canvas.getContext('2d');
  window.mistSim = new ParticleRenderer(ctx, 85, 25);
  window.mistSim.start();
});
<|endoftext|>


<commit_before>import {homedir} from 'os';
import path from 'path';
import {rename as fsRename} from 'fs';

import {app, dialog, BrowserWindow, ipcMain, Menu} from 'electron';
import isDev from 'electron-is-dev';
import mkdirp from 'mkdirp';

import autoUpdater from './auto-updater';
import analytics from './analytics';
import {applicationMenu, cogMenu} from './menus';

const menubar = require('menubar')({
  index: `file://${__dirname}/index.html`,
  icon: path.join(__dirname, '..', 'static', 'menubarDefaultTemplate.png'),
  width: 320,
  height: 500,
  preloadWindow: true,
  transparent: true,
  resizable: false
});

require('./reporter');

let appState = 'initial';
let cropperWindow;
let mainWindowIsDetached = false;
let mainWindow;
let mainWindowIsNew = true;
let positioner;
let shouldStopWhenTrayIsClicked = false;
let tray;

let recording = false;

if (isDev) {
  const electronExecutable = `${__dirname}/../../node_modules/electron/dist/Electron.app/Contents/MacOS/Electron`; // TODO send a PR
  require('electron-reload')(__dirname, {electron: electronExecutable}); // eslint-disable-line import/newline-after-import
  // menubar.setOption('alwaysOnTop', true);
}

ipcMain.on('set-main-window-size', (event, args) => {
  if (args.width && args.height && mainWindow) {
    [args.width, args.height] = [parseInt(args.width, 10), parseInt(args.height, 10)];
    mainWindow.setSize(args.width, args.height, true); // true == animate
  }
});

ipcMain.on('set-cropper-window-size', (event, args) => {
  if (args.width && args.height && cropperWindow) {
    [args.width, args.height] = [parseInt(args.width, 10), parseInt(args.height, 10)];
    cropperWindow.setSize(args.width, args.height, true); // true == animate
  }
});

ipcMain.on('show-options-menu', (event, coordinates) => {
  if (coordinates && coordinates.x && coordinates.y) {
    coordinates.x = parseInt(coordinates.x.toFixed(), 10);
    coordinates.y = parseInt(coordinates.y.toFixed(), 10);

    cogMenu.popup(coordinates.x + 4, coordinates.y); // 4 is the magic number ✨
  }
});

function setCropperWindowOnBlur() {
  cropperWindow.on('blur', () => {
    if (!mainWindow.isFocused() &&
        !cropperWindow.webContents.isDevToolsFocused() &&
        !mainWindow.webContents.isDevToolsFocused() &&
        !recording) {
      cropperWindow.close();
    }
  });
}

ipcMain.on('open-cropper-window', (event, size) => {
  mainWindow.setAlwaysOnTop(true); // TODO send a PR to `menubar`
  menubar.setOption('alwaysOnTop', true);
  if (cropperWindow) {
    cropperWindow.focus();
  } else {
    cropperWindow = new BrowserWindow({
      width: size.width,
      height: size.height,
      frame: false,
      transparent: true,
      resizable: true,
      shadow: false
    });
    cropperWindow.loadURL(`file://${__dirname}/cropper.html`);
    cropperWindow.setIgnoreMouseEvents(false); // TODO this should be false by default

    if (isDev) {
      cropperWindow.openDevTools({mode: 'detach'});
      cropperWindow.webContents.on('devtools-opened', () => {
        setCropperWindowOnBlur();
      });
    } else {
      setCropperWindowOnBlur();
    }

    cropperWindow.on('closed', () => {
      cropperWindow = undefined;
      mainWindow.webContents.send('cropper-window-closed');
    });

    cropperWindow.on('resize', () => {
      const size = {};
      [size.width, size.height] = cropperWindow.getSize();
      mainWindow.webContents.send('cropper-window-new-size', size);
    });
  }
});

ipcMain.on('close-cropper-window', () => {
  if (cropperWindow && !recording) {
    mainWindow.setAlwaysOnTop(false); // TODO send a PR to `menubar`
    menubar.setOption('alwaysOnTop', false);
    cropperWindow.close(); // TODO: cropperWindow.hide()
  }
});

function resetMainWindowShadow() {
  const size = mainWindow.getSize();
  setTimeout(() => {
    size[1]++;
    mainWindow.setSize(...size, true);
  }, 100);
  setTimeout(() => {
    size[1]--;
    mainWindow.setSize(...size, true);
  }, 110);
}

function resetTrayIcon() {
  appState = 'initial'; // if the icon is being reseted, we are not recording anymore
  shouldStopWhenTrayIsClicked = false;
  tray.setImage(path.join(__dirname, '..', 'static', 'menubarDefaultTemplate.png'));
}

menubar.on('after-create-window', () => {
  let expectedWindowPosition;
  const currentWindowPosition = {};
  mainWindow = menubar.window;
  if (isDev) {
    mainWindow.openDevTools({mode: 'detach'});
  }

  function recomputeExpectedWindowPosition() {
    expectedWindowPosition = positioner.calculate('trayCenter', tray.getBounds());
  }

  function recomputeCurrentWindowPosition() {
    [currentWindowPosition.x, currentWindowPosition.y] = mainWindow.getPosition();
  }

  mainWindow.on('blur', () => {
    if (cropperWindow && !cropperWindow.isFocused() && !recording) {
      // close the cropper window if the main window loses focus and the cropper window
      // is not focused
      cropperWindow.close();
    }

    recomputeExpectedWindowPosition();
    recomputeCurrentWindowPosition();
    if (expectedWindowPosition.x !== currentWindowPosition.x || expectedWindowPosition.y !== currentWindowPosition.y) { // this line is too long
      menubar.setOption('x', currentWindowPosition.x);
      menubar.setOption('y', currentWindowPosition.y);
    } else { // reset the position if the window is back at it's original position
      menubar.setOption('x', undefined);
      menubar.setOption('y', undefined);
    }
  });

  let wasStuck = true;
  mainWindow.on('move', () => { // unfortunately this is just an alias for 'moved'
    recomputeExpectedWindowPosition();
    recomputeCurrentWindowPosition();
    const diff = {
      x: Math.abs(expectedWindowPosition.x - currentWindowPosition.x),
      y: Math.abs(expectedWindowPosition.y - currentWindowPosition.y)
    };

    if (diff.y < 50 && diff.x < 50) {
      if (!wasStuck) {
        mainWindow.webContents.send('stick-to-menubar');
        app.dock.hide();
        resetMainWindowShadow();
        wasStuck = true;
        mainWindowIsDetached = false;
      }
      // the `move` event is called when the user reselases the mouse button
      // because of that, we need to move the window to it's expected position, since the
      // user will never release the mouse in the *right* position (diff.[x, y] === 0)
      tray.setHighlightMode('always');
      positioner.move('trayCenter', tray.getBounds());
    } else if (wasStuck) {
      mainWindow.webContents.send('unstick-from-menubar');
      app.dock.show();
      setTimeout(() => mainWindow.show(), 250);
      setTimeout(() => resetMainWindowShadow(), 100);
      tray.setHighlightMode('never');
      wasStuck = false;
      mainWindowIsDetached = true;
    }
  });

  tray = menubar.tray;
  positioner = menubar.positioner;

  tray.on('click', () => {
    if (mainWindowIsNew) {
      mainWindowIsNew = false;
      positioner.move('trayCenter', tray.getBounds()); // not sure why the fuck this is needed (ﾉಠдಠ)ﾉ︵┻━┻
    }
    if (appState === 'recording' && shouldStopWhenTrayIsClicked) {
      mainWindow.webContents.send('stop-recording');
    } else if (app.dock.isVisible()) {
      mainWindow.show();
    }
  });

  mainWindow.on('hide', () => {
    if (appState === 'recording') {
      tray.setImage(path.join(__dirname, '..', 'static', 'menubarStopTemplate.png'));
      shouldStopWhenTrayIsClicked = true;
    }
  });

  menubar.on('show', () => {
    if (mainWindowIsDetached) {
      tray.setHighlightMode('never');
    }
  });

  app.on('activate', () => { // == dockIcon.onclick
    if (!mainWindow.isVisible()) {
      mainWindow.show();
    }
  });

  mainWindow.once('ready-to-show', () => {
    positioner.move('trayCenter', tray.getBounds()); // not sure why the fuck this is needed (ﾉಠдಠ)ﾉ︵┻━┻
    mainWindow.show();
  });

  mainWindowIsNew = true;
  autoUpdater.init(mainWindow);
  analytics.init();
  Menu.setApplicationMenu(applicationMenu);
});

ipcMain.on('get-cropper-bounds', event => {
  if (cropperWindow) {
    event.returnValue = cropperWindow.getContentBounds();
  }
});

ipcMain.on('is-cropper-active', event => {
  event.returnValue = Boolean(cropperWindow);
});

ipcMain.on('will-start-recording', () => {
  recording = true;
  if (cropperWindow) {
    cropperWindow.setResizable(false);
    cropperWindow.setIgnoreMouseEvents(true);
    cropperWindow.setAlwaysOnTop(true);
  }
});

ipcMain.on('started-recording', () => {
  appState = 'recording';
  if (!mainWindowIsDetached) {
    mainWindow.hide();
    tray.setHighlightMode('never');
  }
});

ipcMain.on('stopped-recording', () => {
  resetTrayIcon();
  analytics.track('recording/finished');
});

ipcMain.on('will-stop-recording', () => {
  recording = false;
  if (cropperWindow) {
    cropperWindow.close();
  }
});

ipcMain.on('hide-main-window', () => {
  mainWindow.hide();
});

ipcMain.on('minimize-main-window', () => {
  mainWindow.minimize();
});

ipcMain.on('move-cropper-window', (event, data) => {
  if (!data.direction || !data.amount) {
    return;
  }

  const position = cropperWindow.getPosition();
  if (data.direction === 'left') {
    position[0] -= data.amount;
  } else if (data.direction === 'up') {
    position[1] -= data.amount;
  } else if (data.direction === 'right') {
    position[0] += data.amount;
  } else if (data.direction === 'down') {
    position[1] += data.amount;
  }

  cropperWindow.setPosition(...position);
});

ipcMain.on('ask-user-to-save-file', (event, data) => {
  const kapturesDir = `${homedir()}/Movies/Kaptures`;
  mkdirp(kapturesDir, err => {
    if (err) {
      // can be ignored
    }
    dialog.showSaveDialog({
      title: data.fileName,
      defaultPath: `${kapturesDir}/${data.fileName}`,
      filters: [{name: 'Movies', extensions: ['mp4']}]
    }, fileName => {
      if (fileName) {
        fsRename(data.filePath, fileName);
      }
    });
  });
});
<commit_msg>Change to switch/case syntax (#16)<commit_after>import {homedir} from 'os';
import path from 'path';
import {rename as fsRename} from 'fs';

import {app, dialog, BrowserWindow, ipcMain, Menu} from 'electron';
import isDev from 'electron-is-dev';
import mkdirp from 'mkdirp';

import autoUpdater from './auto-updater';
import analytics from './analytics';
import {applicationMenu, cogMenu} from './menus';

const menubar = require('menubar')({
  index: `file://${__dirname}/index.html`,
  icon: path.join(__dirname, '..', 'static', 'menubarDefaultTemplate.png'),
  width: 320,
  height: 500,
  preloadWindow: true,
  transparent: true,
  resizable: false
});

require('./reporter');

let appState = 'initial';
let cropperWindow;
let mainWindowIsDetached = false;
let mainWindow;
let mainWindowIsNew = true;
let positioner;
let shouldStopWhenTrayIsClicked = false;
let tray;

let recording = false;

if (isDev) {
  const electronExecutable = `${__dirname}/../../node_modules/electron/dist/Electron.app/Contents/MacOS/Electron`; // TODO send a PR
  require('electron-reload')(__dirname, {electron: electronExecutable}); // eslint-disable-line import/newline-after-import
  // menubar.setOption('alwaysOnTop', true);
}

ipcMain.on('set-main-window-size', (event, args) => {
  if (args.width && args.height && mainWindow) {
    [args.width, args.height] = [parseInt(args.width, 10), parseInt(args.height, 10)];
    mainWindow.setSize(args.width, args.height, true); // true == animate
  }
});

ipcMain.on('set-cropper-window-size', (event, args) => {
  if (args.width && args.height && cropperWindow) {
    [args.width, args.height] = [parseInt(args.width, 10), parseInt(args.height, 10)];
    cropperWindow.setSize(args.width, args.height, true); // true == animate
  }
});

ipcMain.on('show-options-menu', (event, coordinates) => {
  if (coordinates && coordinates.x && coordinates.y) {
    coordinates.x = parseInt(coordinates.x.toFixed(), 10);
    coordinates.y = parseInt(coordinates.y.toFixed(), 10);

    cogMenu.popup(coordinates.x + 4, coordinates.y); // 4 is the magic number ✨
  }
});

function setCropperWindowOnBlur() {
  cropperWindow.on('blur', () => {
    if (!mainWindow.isFocused() &&
        !cropperWindow.webContents.isDevToolsFocused() &&
        !mainWindow.webContents.isDevToolsFocused() &&
        !recording) {
      cropperWindow.close();
    }
  });
}

ipcMain.on('open-cropper-window', (event, size) => {
  mainWindow.setAlwaysOnTop(true); // TODO send a PR to `menubar`
  menubar.setOption('alwaysOnTop', true);
  if (cropperWindow) {
    cropperWindow.focus();
  } else {
    cropperWindow = new BrowserWindow({
      width: size.width,
      height: size.height,
      frame: false,
      transparent: true,
      resizable: true,
      shadow: false
    });
    cropperWindow.loadURL(`file://${__dirname}/cropper.html`);
    cropperWindow.setIgnoreMouseEvents(false); // TODO this should be false by default

    if (isDev) {
      cropperWindow.openDevTools({mode: 'detach'});
      cropperWindow.webContents.on('devtools-opened', () => {
        setCropperWindowOnBlur();
      });
    } else {
      setCropperWindowOnBlur();
    }

    cropperWindow.on('closed', () => {
      cropperWindow = undefined;
      mainWindow.webContents.send('cropper-window-closed');
    });

    cropperWindow.on('resize', () => {
      const size = {};
      [size.width, size.height] = cropperWindow.getSize();
      mainWindow.webContents.send('cropper-window-new-size', size);
    });
  }
});

ipcMain.on('close-cropper-window', () => {
  if (cropperWindow && !recording) {
    mainWindow.setAlwaysOnTop(false); // TODO send a PR to `menubar`
    menubar.setOption('alwaysOnTop', false);
    cropperWindow.close(); // TODO: cropperWindow.hide()
  }
});

function resetMainWindowShadow() {
  const size = mainWindow.getSize();
  setTimeout(() => {
    size[1]++;
    mainWindow.setSize(...size, true);
  }, 100);
  setTimeout(() => {
    size[1]--;
    mainWindow.setSize(...size, true);
  }, 110);
}

function resetTrayIcon() {
  appState = 'initial'; // if the icon is being reseted, we are not recording anymore
  shouldStopWhenTrayIsClicked = false;
  tray.setImage(path.join(__dirname, '..', 'static', 'menubarDefaultTemplate.png'));
}

menubar.on('after-create-window', () => {
  let expectedWindowPosition;
  const currentWindowPosition = {};
  mainWindow = menubar.window;
  if (isDev) {
    mainWindow.openDevTools({mode: 'detach'});
  }

  function recomputeExpectedWindowPosition() {
    expectedWindowPosition = positioner.calculate('trayCenter', tray.getBounds());
  }

  function recomputeCurrentWindowPosition() {
    [currentWindowPosition.x, currentWindowPosition.y] = mainWindow.getPosition();
  }

  mainWindow.on('blur', () => {
    if (cropperWindow && !cropperWindow.isFocused() && !recording) {
      // close the cropper window if the main window loses focus and the cropper window
      // is not focused
      cropperWindow.close();
    }

    recomputeExpectedWindowPosition();
    recomputeCurrentWindowPosition();
    if (expectedWindowPosition.x !== currentWindowPosition.x || expectedWindowPosition.y !== currentWindowPosition.y) { // this line is too long
      menubar.setOption('x', currentWindowPosition.x);
      menubar.setOption('y', currentWindowPosition.y);
    } else { // reset the position if the window is back at it's original position
      menubar.setOption('x', undefined);
      menubar.setOption('y', undefined);
    }
  });

  let wasStuck = true;
  mainWindow.on('move', () => { // unfortunately this is just an alias for 'moved'
    recomputeExpectedWindowPosition();
    recomputeCurrentWindowPosition();
    const diff = {
      x: Math.abs(expectedWindowPosition.x - currentWindowPosition.x),
      y: Math.abs(expectedWindowPosition.y - currentWindowPosition.y)
    };

    if (diff.y < 50 && diff.x < 50) {
      if (!wasStuck) {
        mainWindow.webContents.send('stick-to-menubar');
        app.dock.hide();
        resetMainWindowShadow();
        wasStuck = true;
        mainWindowIsDetached = false;
      }
      // the `move` event is called when the user reselases the mouse button
      // because of that, we need to move the window to it's expected position, since the
      // user will never release the mouse in the *right* position (diff.[x, y] === 0)
      tray.setHighlightMode('always');
      positioner.move('trayCenter', tray.getBounds());
    } else if (wasStuck) {
      mainWindow.webContents.send('unstick-from-menubar');
      app.dock.show();
      setTimeout(() => mainWindow.show(), 250);
      setTimeout(() => resetMainWindowShadow(), 100);
      tray.setHighlightMode('never');
      wasStuck = false;
      mainWindowIsDetached = true;
    }
  });

  tray = menubar.tray;
  positioner = menubar.positioner;

  tray.on('click', () => {
    if (mainWindowIsNew) {
      mainWindowIsNew = false;
      positioner.move('trayCenter', tray.getBounds()); // not sure why the fuck this is needed (ﾉಠдಠ)ﾉ︵┻━┻
    }
    if (appState === 'recording' && shouldStopWhenTrayIsClicked) {
      mainWindow.webContents.send('stop-recording');
    } else if (app.dock.isVisible()) {
      mainWindow.show();
    }
  });

  mainWindow.on('hide', () => {
    if (appState === 'recording') {
      tray.setImage(path.join(__dirname, '..', 'static', 'menubarStopTemplate.png'));
      shouldStopWhenTrayIsClicked = true;
    }
  });

  menubar.on('show', () => {
    if (mainWindowIsDetached) {
      tray.setHighlightMode('never');
    }
  });

  app.on('activate', () => { // == dockIcon.onclick
    if (!mainWindow.isVisible()) {
      mainWindow.show();
    }
  });

  mainWindow.once('ready-to-show', () => {
    positioner.move('trayCenter', tray.getBounds()); // not sure why the fuck this is needed (ﾉಠдಠ)ﾉ︵┻━┻
    mainWindow.show();
  });

  mainWindowIsNew = true;
  autoUpdater.init(mainWindow);
  analytics.init();
  Menu.setApplicationMenu(applicationMenu);
});

ipcMain.on('get-cropper-bounds', event => {
  if (cropperWindow) {
    event.returnValue = cropperWindow.getContentBounds();
  }
});

ipcMain.on('is-cropper-active', event => {
  event.returnValue = Boolean(cropperWindow);
});

ipcMain.on('will-start-recording', () => {
  recording = true;
  if (cropperWindow) {
    cropperWindow.setResizable(false);
    cropperWindow.setIgnoreMouseEvents(true);
    cropperWindow.setAlwaysOnTop(true);
  }
});

ipcMain.on('started-recording', () => {
  appState = 'recording';
  if (!mainWindowIsDetached) {
    mainWindow.hide();
    tray.setHighlightMode('never');
  }
});

ipcMain.on('stopped-recording', () => {
  resetTrayIcon();
  analytics.track('recording/finished');
});

ipcMain.on('will-stop-recording', () => {
  recording = false;
  if (cropperWindow) {
    cropperWindow.close();
  }
});

ipcMain.on('hide-main-window', () => {
  mainWindow.hide();
});

ipcMain.on('minimize-main-window', () => {
  mainWindow.minimize();
});

ipcMain.on('move-cropper-window', (event, data) => {
  if (!data.direction || !data.amount) {
    return;
  }

  const position = cropperWindow.getPosition();
  const amount = data.amount;

  switch (data.direction) {
    case 'left':
      position[0] -= amount;
      break;
    case 'up':
      position[1] -= amount;
      break;
    case 'right':
      position[0] += amount;
      break;
    case 'down':
      position[1] += amount;
      break;
    default:
      // Catch occasions where direction is not defined for whatever reason (should never happen).
      break;
  }

  cropperWindow.setPosition(...position);
});

ipcMain.on('ask-user-to-save-file', (event, data) => {
  const kapturesDir = `${homedir()}/Movies/Kaptures`;
  mkdirp(kapturesDir, err => {
    if (err) {
      // can be ignored
    }
    dialog.showSaveDialog({
      title: data.fileName,
      defaultPath: `${kapturesDir}/${data.fileName}`,
      filters: [{name: 'Movies', extensions: ['mp4']}]
    }, fileName => {
      if (fileName) {
        fsRename(data.filePath, fileName);
      }
    });
  });
});
<|endoftext|>


<commit_before>import React from 'react';
import injectTapEventPlugin from 'react-tap-event-plugin';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AppBar from 'material-ui/AppBar';
import './css/app.css';

// Needed for onTouchTap
injectTapEventPlugin();

class App extends React.Component {
    render() {
        return (
            <MuiThemeProvider>

                    <AppBar
                        title="0xFF"
                        onLeftIconButtonTouchTap={()=>alert("touched!")}
                    />
                    {this.props.children}

            </MuiThemeProvider>
        );
    }
}

App.propTypes = {
    children: React.PropTypes.element
};

export default App;
<commit_msg>Change title<commit_after>import React from 'react';
import injectTapEventPlugin from 'react-tap-event-plugin';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AppBar from 'material-ui/AppBar';
import './css/app.css';

// Needed for onTouchTap
injectTapEventPlugin();

class App extends React.Component {
    render() {
        return (
            <MuiThemeProvider>

                    <AppBar
                        title="Title"
                        onLeftIconButtonTouchTap={()=>alert("touched")}
                    />
                    {this.props.children}

            </MuiThemeProvider>
        );
    }
}

App.propTypes = {
    children: React.PropTypes.element
};

export default App;
<|endoftext|>


<commit_before>/* global msGMLOutputFuel */
goog.require('ngeo.WfsPermalink');
goog.require('ol.format.filter');
goog.require('ngeo.test.data.msGMLOutputFuel');

describe('ngeo.WfsPermalink', () => {

  let ngeoWfsPermalink;
  let ngeoQueryResult;

  beforeEach(() => {
    module('ngeo', ($provide) => {
      $provide.value('ngeoWfsPermalinkOptions', {
        url: 'https://geomapfish-demo.camptocamp.net/2.1/wsgi/mapserv_proxy',
        wfsTypes: [{featureType: 'fuel'}, {featureType: 'highway'}],
        defaultFeatureNS: 'http://mapserver.gis.umn.edu/mapserver',
        defaultFeaturePrefix: 'ms'
      });
    });

    inject(($injector) => {
      ngeoWfsPermalink = $injector.get('ngeoWfsPermalink');
      ngeoQueryResult = $injector.get('ngeoQueryResult');
    });
  });

  it('creates a service', () => {
    expect(ngeoWfsPermalink instanceof ngeo.WfsPermalink).toBe(true);
  });

  describe('#issue', () => {

    let $httpBackend;
    let map;

    beforeEach(() => {
      const url = 'https://geomapfish-demo.camptocamp.net/2.1/wsgi/mapserv_proxy';
      inject(($injector) => {
        $httpBackend = $injector.get('$httpBackend');
        $httpBackend.when('POST', url).respond(msGMLOutputFuel);
        $httpBackend = $injector.get('$httpBackend');
      });

      const projection = ol.proj.get('EPSG:21781');
      projection.setExtent([485869.5728, 76443.1884, 837076.5648, 299941.7864]);

      map = new ol.Map({
        layers: [],
        view: new ol.View({
          projection,
          resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5],
          center: [537635, 152640],
          zoom: 0
        })
      });
    });

    afterEach(() => {
      $httpBackend.verifyNoOutstandingExpectation();
      $httpBackend.verifyNoOutstandingRequest();
    });

    it('makes a query and adds the result', () => {
      const queryData = {
        'wfsType': 'fuel',
        'showFeatures': true,
        'filterGroups': [
          {
            'filters': [
              {'property': 'osm_id', 'condition': '1420918679'}
            ]
          }
        ]
      };

      ngeoWfsPermalink.issue(queryData, map);
      $httpBackend.flush();
      expect(ngeoQueryResult.sources[ngeoQueryResult.sources.length - 1].features.length).toBe(1);
      ngeoWfsPermalink.clear();
      expect(ngeoQueryResult.total).toBe(0);
    });
  });

  describe('#createFilters_', () => {
    const expectFiltersToEqual = function(filter1, filter2) {
      expect(filter1.constructor).toBe(filter2.constructor, 'same filter type');
      if (filter1 instanceof ol.format.filter.LogicalBinary) {
        expectFiltersToEqual(filter1.conditionA, filter2.conditionA);
        expectFiltersToEqual(filter1.conditionB, filter2.conditionB);
      } else {
        expect(filter1 instanceof ol.format.filter.EqualTo);
        expect(filter1.propertyName).toBe(filter2.propertyName);
        expect(filter1.expression).toBe(filter2.expression);
      }
    };

    it('creates filters', () => {
      const queryData = {
        'wfsType': 'fuel',
        'filterGroups': [
          {
            'filters': [
              {'property': 'osm_id', 'condition': '12345'},
              {'property': 'type', 'condition': ['diesel', 'gas']}
            ]
          },
          {
            'filters': [
              {'property': 'payment', 'condition': ['card', 'cash']}
            ]
          },
          {
            'filters': [
              {'property': 'open_7_24', 'condition': '1'}
            ]
          }
        ]
      };
      const f = ol.format.filter;
      const expectedFilters = f.or(
          f.or(
            f.and(
                f.equalTo('osm_id', '12345'),
                f.or(
                  f.equalTo('type', 'diesel'),
                  f.equalTo('type', 'gas')
                )
            ),
            f.or(
              f.equalTo('payment', 'card'),
              f.equalTo('payment', 'cash')
            )
          ),
          f.equalTo('open_7_24', '1')
      );
      expectFiltersToEqual(
          ngeoWfsPermalink.createFilters_(queryData['filterGroups']),
          expectedFilters
      );
    });

    it('handles 0 filter groups', () => {
      expect(ngeoWfsPermalink.createFilters_([])).toBe(null);
    });
  });

});
<commit_msg>Fix binary logical filter<commit_after>/* global msGMLOutputFuel */
goog.require('ngeo.WfsPermalink');
goog.require('ol.format.filter');
goog.require('ol.format.filter.LogicalNary');
goog.require('ngeo.test.data.msGMLOutputFuel');

describe('ngeo.WfsPermalink', () => {

  let ngeoWfsPermalink;
  let ngeoQueryResult;

  beforeEach(() => {
    module('ngeo', ($provide) => {
      $provide.value('ngeoWfsPermalinkOptions', {
        url: 'https://geomapfish-demo.camptocamp.net/2.1/wsgi/mapserv_proxy',
        wfsTypes: [{featureType: 'fuel'}, {featureType: 'highway'}],
        defaultFeatureNS: 'http://mapserver.gis.umn.edu/mapserver',
        defaultFeaturePrefix: 'ms'
      });
    });

    inject(($injector) => {
      ngeoWfsPermalink = $injector.get('ngeoWfsPermalink');
      ngeoQueryResult = $injector.get('ngeoQueryResult');
    });
  });

  it('creates a service', () => {
    expect(ngeoWfsPermalink instanceof ngeo.WfsPermalink).toBe(true);
  });

  describe('#issue', () => {

    let $httpBackend;
    let map;

    beforeEach(() => {
      const url = 'https://geomapfish-demo.camptocamp.net/2.1/wsgi/mapserv_proxy';
      inject(($injector) => {
        $httpBackend = $injector.get('$httpBackend');
        $httpBackend.when('POST', url).respond(msGMLOutputFuel);
        $httpBackend = $injector.get('$httpBackend');
      });

      const projection = ol.proj.get('EPSG:21781');
      projection.setExtent([485869.5728, 76443.1884, 837076.5648, 299941.7864]);

      map = new ol.Map({
        layers: [],
        view: new ol.View({
          projection,
          resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5],
          center: [537635, 152640],
          zoom: 0
        })
      });
    });

    afterEach(() => {
      $httpBackend.verifyNoOutstandingExpectation();
      $httpBackend.verifyNoOutstandingRequest();
    });

    it('makes a query and adds the result', () => {
      const queryData = {
        'wfsType': 'fuel',
        'showFeatures': true,
        'filterGroups': [
          {
            'filters': [
              {'property': 'osm_id', 'condition': '1420918679'}
            ]
          }
        ]
      };

      ngeoWfsPermalink.issue(queryData, map);
      $httpBackend.flush();
      expect(ngeoQueryResult.sources[ngeoQueryResult.sources.length - 1].features.length).toBe(1);
      ngeoWfsPermalink.clear();
      expect(ngeoQueryResult.total).toBe(0);
    });
  });

  describe('#createFilters_', () => {
    const expectFiltersToEqual = function(filter1, filter2) {
      expect(filter1.constructor).toBe(filter2.constructor, 'same filter type');
      if (filter1 instanceof ol.format.filter.LogicalNary) {
        expectFiltersToEqual(filter1.conditions.length, filter2.conditions.length);
        for (let i = 0; i < filter1.conditions.length; ++i) {
          expectFiltersToEqual(filter1.conditions[i], filter2.conditions[i]);
        }
      } else {
        expect(filter1 instanceof ol.format.filter.EqualTo);
        expect(filter1.propertyName).toBe(filter2.propertyName);
        expect(filter1.expression).toBe(filter2.expression);
      }
    };

    it('creates filters', () => {
      const queryData = {
        'wfsType': 'fuel',
        'filterGroups': [
          {
            'filters': [
              {'property': 'osm_id', 'condition': '12345'},
              {'property': 'type', 'condition': ['diesel', 'gas']}
            ]
          },
          {
            'filters': [
              {'property': 'payment', 'condition': ['card', 'cash']}
            ]
          },
          {
            'filters': [
              {'property': 'open_7_24', 'condition': '1'}
            ]
          }
        ]
      };
      const f = ol.format.filter;
      const expectedFilters = f.or(
          f.or(
            f.and(
                f.equalTo('osm_id', '12345'),
                f.or(
                  f.equalTo('type', 'diesel'),
                  f.equalTo('type', 'gas')
                )
            ),
            f.or(
              f.equalTo('payment', 'card'),
              f.equalTo('payment', 'cash')
            )
          ),
          f.equalTo('open_7_24', '1')
      );
      expectFiltersToEqual(
          ngeoWfsPermalink.createFilters_(queryData['filterGroups']),
          expectedFilters
      );
    });

    it('handles 0 filter groups', () => {
      expect(ngeoWfsPermalink.createFilters_([])).toBe(null);
    });
  });

});
<|endoftext|>


<commit_before>import { actions } from './actions'

let onChangeInput = (state, action) => ({
    input: {
        value: action.value,
        length: action.value.length
    },
    info: state.info
});

let onChangeInputLength = (state, action) => ({
    input: state.input,
    info: {
        inputLength: action.length
    }
});

let reducer = (state, action) => {
	switch (action.type) {
	case actions.CHANGE_INPUT:
		return onChangeInput(state, action);
	case actions.CHANGE_INPUT_LENGTH:
		return onChangeInputLength(state, action);
	default:
		return state;
	}
};

export default reducer;
<commit_msg>Used combineReducers<commit_after>import { combineReducers } from "redux";
import { actions } from './actions'

let input = (state = { value: '', length: 0 }, action) => {
    if (action.type === actions.CHANGE_INPUT) {
        return {
            value: action.value,
            length: action.value.length
        };
    } else {
        return state;
    }
};

let info = (state = { inputLength: 0 }, action) => {
    if (action.type === actions.CHANGE_INPUT_LENGTH) {
        return {
            inputLength: action.length
        };
    } else {
        return state;
    }
};

export default combineReducers({ input, info });
<|endoftext|>


<commit_before>// import third party library
var mongoose = require('mongoose');
var async = require('async');
var jwt = require('jsonwebtoken');
// import model
var Tasks = require('../../db_modules/models/tasks');
var Users = require('../../db_modules/models/users');
// import helper
var ResponseHelper = require('../helper/ResponseHelper');
var MongoHelper = require('../helper/MongoHelper');
var ServerError = require('../ServerError');
var RUserCreateTasks = require('../../db_modules/models/rUserCreateTasks');
var task = {
    rootPath: 'task',
    actions: {}
};

task.actions.createTask = {
    path: 'createTask',
    method: 'post',
	permissionValidators: ['validateLogin'],
    execute: function(req, res) {
		var name = req.body.name || '';
        async.waterfall([function(callback) {
            var task = new Tasks({name: name});
			task.save(function(error, task) {
                if (error) {
                    callback(error);
                } else {
                    callback(null, task);
                }
            });
        }, function(task, callback) {
            var rUserCreateTasks = new RUserCreateTasks({
                targetRef: task._id,
                initiatorRef: MongoHelper.parseObjectId(req.body.userId)
            });
            rUserCreateTasks.save(function(error, rUserCreateTasks) {
                if (error) {
                    callback(error);
                } else {
                    callback(null, task);
                }
            });
        }], function(error, task) {
            ResponseHelper.buildResponse(res, error, task);
        });
    }
};

task.actions.updateTask = {
	path: 'updateTask',
    method: 'post',
	execute: function(req, res) {
        var _id = req.body._id;
        var name = req.body.name || '';
        var create = req.body.create || '';
        var deadline = req.body.deadline || '';
        if (name.length === 0 || create.length === 0 || deadline.length === 0) {
            ResponseHelper.buildResponse(res, ServerError.NotEnoughParam);
            return;
        }
        Tasks.findOne({
            _id: _id
        }, function(error, task) {
            if (error) {
                ResponseHelper.buildResponse(res, error);
            } else if (!task) {
                ResponseHelper.buildResponse(res, ServerError.ERR_NOT_LOGGED_IN);
            } else {
                task.name = name;
                task.deadline = deadline;
                task.save(function(error, task) {
                    if (error) {
                        ResponseHelper.buildResponse(res, error);
                    } else {
                        ResponseHelper.buildResponse(res, null, task);
                    }
                })
            }
        });
    }
};

task.actions.remove = {
    path: 'remove',
    method: 'post',
    execute: function (req, res) {
        var taskId = req.body._id;
        var task = 'success';
        Tasks.remove({_id: taskId}).exec(function(error, task){
            ResponseHelper.buildResponse(res, error, task);
        });
    }
};

task.actions.show = {
    path: 'show',
    method: 'post',
    execute: function(req, res) {
        var _id = req.body._id;
        var pageNumber = req.body.num||1;
        var resultsPerPage = 5;
        var skipFrom = (pageNumber * resultsPerPage) - resultsPerPage;
        var limit = skipFrom + resultsPerPage;
        RUserCreateTasks.find({'initiatorRef': _id}).populate('targetRef').exec(function(error, task){
            var tasks = {};
            var j = 0;
            for(var i = 0; i < task.length; i++){
                if (task[i].targetRef != null) {
                    tasks[j] = task[i].targetRef;
                    j++;
                }
            }
            var y = 0;
            var taskShow = [];
            var taskSh = {};
            for (var x = skipFrom; x < limit ; x++) {
                taskSh[skipFrom] = tasks[x];
                skipFrom++;
            }
            var count = j;
            taskShow[0] = taskSh;
            taskShow[1] = count;
            ResponseHelper.buildResponse(res, error, taskShow);
            console.log(taskShow);
        });
    }
};

task.actions.request = {
    path: 'request',
    method: 'post',
    execute: function(req, res) {
        var _id = req.body._id;
        Tasks.findOne({
            _id: _id
        }, function(error, task) {
            if (error) {
                ResponseHelper.buildResponse(res, error);
            } else if (!task) {
                ResponseHelper.buildResponse(res, ServerError.ERR_NOT_LOGGED_IN);
            } else {
                ResponseHelper.buildResponse(res, null, task);
            }
        });
    }
};

task.actions.getMe = {
    path: '',
    method: 'get',
    execute: function(req, res) {
        var _id = req.body.taskId;
        Tasks.findOne({
            _id: _id
        }, function(error, task) {
            if (error) {
                ResponseHelper.buildResponse(res, error);
            } else if (!task) {
                ResponseHelper.buildResponse(res, ServerError.ERR_NOT_LOGGED_IN);
            } else {
                ResponseHelper.buildResponse(res, null, task);
            }
        });
    }
};
// export module
module.exports = task;
<commit_msg>fix bug<commit_after>// import third party library
var mongoose = require('mongoose');
var async = require('async');
var jwt = require('jsonwebtoken');
// import model
var Tasks = require('../../db_modules/models/tasks');
var Users = require('../../db_modules/models/users');
// import helper
var ResponseHelper = require('../helper/ResponseHelper');
var MongoHelper = require('../helper/MongoHelper');
var ServerError = require('../ServerError');
var RUserCreateTasks = require('../../db_modules/models/rUserCreateTasks');
var task = {
    rootPath: 'task',
    actions: {}
};

task.actions.create = {
    path: '',
    method: 'post',
    permissionValidators: ['validateLogin'],
    execute: function(req, res) {
        var name = req.body.name || '';
        async.waterfall([function(callback) {
            var task = new Tasks({name: name});
            task.save(function(error, task) {
                if (error) {
                    callback(error);
                } else {
                    callback(null, task);
                }
            });
        }, function(task, callback) {
            var rUserCreateTasks = new RUserCreateTasks({
                targetRef: task._id,
                initiatorRef: req.body.userId
            });
            rUserCreateTasks.save(function(error, rUserCreateTasks) {
                if (error) {
                    callback(error);
                } else {
                    callback(null, task);
                }
            });
        }], function(error, task) {
            ResponseHelper.buildResponse(res, error, task);
        });
    }
};

task.actions.update = {
    path: ':id',
    method: 'put',
    permissionValidators: ['validateLogin'],
    execute: function(req, res) {
        var _id = req.params.id;
        var name = req.body.name || '';
        var deadline = req.body.deadline || '';
        if (name.length === 0) {
            ResponseHelper.buildResponse(res, ServerError.NotEnoughParam);
            return;
        }
        Tasks.findOne({
            _id: MongoHelper.parseObjectId(_id)
        }, function(error, task) {
            if (error) {
                ResponseHelper.buildResponse(res, error);
            } else if (!task) {
                ResponseHelper.buildResponse(res, ServerError.ERR_NOT_LOGGED_IN);
            } else {
                task.name = name;
                task.deadline = deadline;
                task.save(function(error, task) {
                    if (error) {
                        ResponseHelper.buildResponse(res, error);
                    } else {
                        ResponseHelper.buildResponse(res, null, task);
                    }
                });
            }
        });
    }
};

task.actions.delete = {
    path: ':id',
    method: 'delete',
    permissionValidators: ['validateLogin'],
    execute: function(req, res) {
        var taskId = MongoHelper.parseObjectId(req.params.id);
        async.waterfall([function(callback) {
            Tasks.remove({_id: taskId}).exec(function(error) {
                callback(error);
            });
        }, function(callback) {
            RUserCreateTasks.remove({targetRef: taskId}).exec(function(error) {
                callback(error);
            });
        }], function(error) {
            ResponseHelper.buildResponse(res, error, {});
        });
    }
};

task.actions.show = {
    path: 'show',
    method: 'post',
    execute: function(req, res) {
        var _id = req.body._id;
        var pageNumber = req.body.num || 1;
        var resultsPerPage = 5;
        var skipFrom = (pageNumber * resultsPerPage) - resultsPerPage;
        var limit = skipFrom + resultsPerPage;
        RUserCreateTasks.find({'initiatorRef': _id}).populate('targetRef').exec(function(error, task) {
            var tasks = {};
            var j = 0;
            for (var i = 0; i < task.length; i++) {
                if (task[i].targetRef != null) {
                    tasks[j] = task[i].targetRef;
                    j++;
                }
            }
            var y = 0;
            var taskShow = [];
            var taskSh = {};
            for (var x = skipFrom; x < limit ; x++) {
                taskSh[skipFrom] = tasks[x];
                skipFrom++;
            }
            var count = j;
            taskShow[0] = taskSh;
            taskShow[1] = count;
            ResponseHelper.buildResponse(res, error, taskShow);
            console.log(taskShow);
        });
    }
};

task.actions.request = {
    path: 'request',
    method: 'post',
    execute: function(req, res) {
        var _id = req.body._id;
        Tasks.findOne({
            _id: _id
        }, function(error, task) {
            if (error) {
                ResponseHelper.buildResponse(res, error);
            } else if (!task) {
                ResponseHelper.buildResponse(res, ServerError.ERR_NOT_LOGGED_IN);
            } else {
                ResponseHelper.buildResponse(res, null, task);
            }
        });
    }
};

task.actions.getMe = {
    path: '',
    method: 'get',
    execute: function(req, res) {
        var _id = req.body.taskId;
        Tasks.findOne({
            _id: _id
        }, function(error, task) {
            if (error) {
                ResponseHelper.buildResponse(res, error);
            } else if (!task) {
                ResponseHelper.buildResponse(res, ServerError.ERR_NOT_LOGGED_IN);
            } else {
                ResponseHelper.buildResponse(res, null, task);
            }
        });
    }
};
// export module
module.exports = task;
<|endoftext|>


<commit_before>var _ = require('underscore');
var async = require('async');
var keystone = require('../../');
var jade = require('jade');

exports = module.exports = function(req, res) {

	var sendResponse = function(status) {
		res.json(status);
	};

	var sendError = function(key, err, msg) {
		msg = msg || 'API Error';
		key = key || 'unknown error';
		msg += ' (' + key + ')';
		console.log(msg + (err ? ':' : ''));
		if (err) {
			console.log(err);
		}
		res.status(500);
		sendResponse({ error: key || 'error', detail: err ? err.message : '' });
	};

	switch (req.params.action) {

		case 'autocomplete':
			var limit = req.query.limit || 50;
			var page = req.query.page || 1;
			var skip = limit * (page - 1);

			var filters = req.list.getSearchFilters(req.query.q);

			var count = req.list.model.count(filters);
			var query = req.list.model.find(filters)
				.limit(limit)
				.skip(skip)
				.sort(req.list.defaultSort);

			if (req.query.context === 'relationship') {
				var srcList = keystone.list(req.query.list);
				if (!srcList) return sendError('invalid list provided');

				var field = srcList.fields[req.query.field];
				if (!field) return sendError('invalid field provided');

				_.each(req.query.filters, function(value, key) {
					query.where(key).equals(value ? value : null);
					count.where(key).equals(value ? value : null);
				});
			}

			count.exec(function(err, total) {

				if (err) return sendError('database error', err);

				query.exec(function(err, items) {

					if (err) return sendError('database error', err);

					sendResponse({
						total: total,
						items: items.map(function(i) {
							return {
								name: req.list.getDocumentName(i, false) || '(' + i.id + ')',
								id: i.id
							};
						})
					});

				});

			});

		break;

		case 'get':

			req.list.model.findById(req.query.id).exec(function(err, item) {

				if (err) return sendError('database error', err);
				if (!item) return sendResponse({ name: req.query.id, id: req.query.id });

				switch (req.query.dataset) {
					case 'simple':
						return sendResponse({
							name: req.list.getDocumentName(item, false),
							id: item.id
						});
					default:
						return sendResponse(item);
				}
			});

		break;

		case 'order':

			if (!keystone.security.csrf.validate(req)) {
				return sendError('invalid csrf');
			}

			var order = req.query.order || req.body.order;
			var queue = [];

			if ('string' === typeof order) {
				order = order.split(',');
			}

			_.each(order, function(id, i) {
				queue.push(function(done) {
					req.list.model.update({ _id: id }, { $set: { sortOrder: i } }, done);
				});
			});

			async.parallel(queue, function(err) {

				if (err) return sendError('database error', err);

				return sendResponse({
					success: true
				});

			});

		break;

		case 'create':

			if (!keystone.security.csrf.validate(req)) {
				return sendError('invalid csrf');
			}

			var item = new req.list.model();
			var updateHandler = item.getUpdateHandler(req);
			var data = (req.method === 'POST') ? req.body : req.query;

			if (req.list.nameIsInitial) {
				if (req.list.nameField.validateInput(data)) {
					req.list.nameField.updateItem(item, data);
				} else {
					updateHandler.addValidationError(req.list.nameField.path, 'Name is required.');
				}
			}

			updateHandler.process(data, {
				flashErrors: true,
				logErrors: true,
				fields: req.list.initialFields
			}, function(err) {
				if (err) {
					return sendResponse({
						success: false,
						err: err
					});
				} else {
					return sendResponse({
						success: true,
						name: req.list.getDocumentName(item, false),
						id: item.id
					});
				}
			});

		break;

		case 'delete':

			if (!keystone.security.csrf.validate(req)) {
				return sendError('invalid csrf');
			}

			if (req.list.get('nodelete')) {
				return sendError('nodelete');
			}

			var id = req.body.id || req.query.id;

			if (req.user && id === req.user.id) {
				return sendError('You can not delete yourself');
			}

			req.list.model.findById(id).exec(function (err, item) {

				if (err) return sendError('database error', err);
				if (!item) return sendError('not found');

				item.remove(function (err) {
					if (err) return sendError('database error', err);

					return sendResponse({
						success: true,
						count: 1
					});
				});

			});

		break;

		case 'fetch':

			if (!keystone.security.csrf.validate(req)) {
				return sendError('invalid csrf');
			}

			(function() {

				var queryFilters = req.list.getSearchFilters(req.query.search, req.query.filters);
				var skip = parseInt(req.query.items.last) - 1;
				var querystring = require('querystring');
				var link_to = function(params) {
						var p = params.page || '';
						delete params.page;
						var queryParams = _.clone(req.query.q);
						for (var i in params) {
							if (params[i] === undefined) {
								delete params[i];
								delete queryParams[i];
							}
						}
						params = querystring.stringify(_.defaults(params, queryParams));
						return '/keystone/' + req.list.path + (p ? '/' + p : '') + (params ? '?' + params : '');
					};

				var query = req.list.model.find(queryFilters).sort(req.query.sort).skip(skip).limit(1);
				var columns = req.list.expandColumns(req.query.cols);

				req.list.selectColumns(query, columns);

				query.exec(function(err, items) {
					if (err) return sendError('database error', err);
					if (!items) return sendError('not found');

					var locals, row, pagination;

					req.list.getPages(req.query.items, req.list.pagination.maxPages);

					locals = { list: req.list, columns: columns, item: items[0], csrf_query: req.query.csrf_query, _:_ };
					row = jade.renderFile(__dirname + '/../../templates/partials/row.jade', locals);
					pagination = jade.renderFile(__dirname + '/../../templates/partials/pagination.jade', { items: req.query.items, link_to: link_to });

					return sendResponse({
						item: items[0],
						row: row,
						pagination: pagination,
						success: true,
						count: 1
					});
				});

			})();

		break;

	}

};
<commit_msg>Removing old List Delete API<commit_after>var _ = require('underscore');
var async = require('async');
var keystone = require('../../');
var jade = require('jade');

exports = module.exports = function(req, res) {

	var sendResponse = function(status) {
		res.json(status);
	};

	var sendError = function(key, err, msg) {
		msg = msg || 'API Error';
		key = key || 'unknown error';
		msg += ' (' + key + ')';
		console.log(msg + (err ? ':' : ''));
		if (err) {
			console.log(err);
		}
		res.status(500);
		sendResponse({ error: key || 'error', detail: err ? err.message : '' });
	};

	switch (req.params.action) {

		case 'autocomplete':
			var limit = req.query.limit || 50;
			var page = req.query.page || 1;
			var skip = limit * (page - 1);

			var filters = req.list.getSearchFilters(req.query.q);

			var count = req.list.model.count(filters);
			var query = req.list.model.find(filters)
				.limit(limit)
				.skip(skip)
				.sort(req.list.defaultSort);

			if (req.query.context === 'relationship') {
				var srcList = keystone.list(req.query.list);
				if (!srcList) return sendError('invalid list provided');

				var field = srcList.fields[req.query.field];
				if (!field) return sendError('invalid field provided');

				_.each(req.query.filters, function(value, key) {
					query.where(key).equals(value ? value : null);
					count.where(key).equals(value ? value : null);
				});
			}

			count.exec(function(err, total) {

				if (err) return sendError('database error', err);

				query.exec(function(err, items) {

					if (err) return sendError('database error', err);

					sendResponse({
						total: total,
						items: items.map(function(i) {
							return {
								name: req.list.getDocumentName(i, false) || '(' + i.id + ')',
								id: i.id
							};
						})
					});

				});

			});

		break;

		case 'get':

			req.list.model.findById(req.query.id).exec(function(err, item) {

				if (err) return sendError('database error', err);
				if (!item) return sendResponse({ name: req.query.id, id: req.query.id });

				switch (req.query.dataset) {
					case 'simple':
						return sendResponse({
							name: req.list.getDocumentName(item, false),
							id: item.id
						});
					default:
						return sendResponse(item);
				}
			});

		break;

		case 'order':

			if (!keystone.security.csrf.validate(req)) {
				return sendError('invalid csrf');
			}

			var order = req.query.order || req.body.order;
			var queue = [];

			if ('string' === typeof order) {
				order = order.split(',');
			}

			_.each(order, function(id, i) {
				queue.push(function(done) {
					req.list.model.update({ _id: id }, { $set: { sortOrder: i } }, done);
				});
			});

			async.parallel(queue, function(err) {

				if (err) return sendError('database error', err);

				return sendResponse({
					success: true
				});

			});

		break;

		case 'create':

			if (!keystone.security.csrf.validate(req)) {
				return sendError('invalid csrf');
			}

			var item = new req.list.model();
			var updateHandler = item.getUpdateHandler(req);
			var data = (req.method === 'POST') ? req.body : req.query;

			if (req.list.nameIsInitial) {
				if (req.list.nameField.validateInput(data)) {
					req.list.nameField.updateItem(item, data);
				} else {
					updateHandler.addValidationError(req.list.nameField.path, 'Name is required.');
				}
			}

			updateHandler.process(data, {
				flashErrors: true,
				logErrors: true,
				fields: req.list.initialFields
			}, function(err) {
				if (err) {
					return sendResponse({
						success: false,
						err: err
					});
				} else {
					return sendResponse({
						success: true,
						name: req.list.getDocumentName(item, false),
						id: item.id
					});
				}
			});

		break;

		case 'fetch':

			if (!keystone.security.csrf.validate(req)) {
				return sendError('invalid csrf');
			}

			(function() {

				var queryFilters = req.list.getSearchFilters(req.query.search, req.query.filters);
				var skip = parseInt(req.query.items.last) - 1;
				var querystring = require('querystring');
				var link_to = function(params) {
						var p = params.page || '';
						delete params.page;
						var queryParams = _.clone(req.query.q);
						for (var i in params) {
							if (params[i] === undefined) {
								delete params[i];
								delete queryParams[i];
							}
						}
						params = querystring.stringify(_.defaults(params, queryParams));
						return '/keystone/' + req.list.path + (p ? '/' + p : '') + (params ? '?' + params : '');
					};

				var query = req.list.model.find(queryFilters).sort(req.query.sort).skip(skip).limit(1);
				var columns = req.list.expandColumns(req.query.cols);

				req.list.selectColumns(query, columns);

				query.exec(function(err, items) {
					if (err) return sendError('database error', err);
					if (!items) return sendError('not found');

					var locals, row, pagination;

					req.list.getPages(req.query.items, req.list.pagination.maxPages);

					locals = { list: req.list, columns: columns, item: items[0], csrf_query: req.query.csrf_query, _:_ };
					row = jade.renderFile(__dirname + '/../../templates/partials/row.jade', locals);
					pagination = jade.renderFile(__dirname + '/../../templates/partials/pagination.jade', { items: req.query.items, link_to: link_to });

					return sendResponse({
						item: items[0],
						row: row,
						pagination: pagination,
						success: true,
						count: 1
					});
				});

			})();

		break;

	}

};
<|endoftext|>


<commit_before><commit_msg>Refactor comments & add exported comment.<commit_after><|endoftext|>


<commit_before>'use strict';

const utils = require('util');

module.exports = {

    command: 'start',

    config: {
        description: 'Start a development server',
        options: [
            ['-p, --port <number>', 'The port to run the server on.'],
            ['-t, --theme <package-name>', 'The name of custom UI theme to use, if required'],
            ['-s, --sync', 'Use BrowserSync to sync and reload pages when changes occur'],
            ['-w, --watch', 'Watch the filesystem for changes.'],
        ],
    },

    action(args, done) {
        const server = this.fractal.web.server(args.options);

        server.on('ready', () => {
            const header = 'Fractal web UI server is running!';
            const footer = this.fractal.cli.isInteractive() ? 'Use the \'stop\' command to stop the server.' : 'Use ^C to stop the server.';
            const serverUrl = server.urls.server;
            const format = str => this.console.theme.format(str, 'success', true);
            let body = '';

            if (!server.isSynced) {
                body += `Local URL: ${format(serverUrl)}`;
            } else {
                const syncUrls = server.urls.sync;
                body += `Local URL:      ${format(syncUrls.local)}`;
                body += `\nNetwork URL:    ${format(syncUrls.external)}`;
                body += `\nBrowserSync UI: ${format(syncUrls.ui)}`;
            }

            return this.console.box(header, body, footer).persist();
        });

        server.on('error', (err, req) => {
            if (err.status === '404') {
                this.console.warn(`404: ${err.message}`);
            } else {
                this.console.error(err.message, err);
            }
            done();
        });

        server.on('destroy', () => done());
        server.on('stopped', () => done());

        server.start(args.options.sync).catch(e => {
            this.console.error(e);
            done();
        });
    },

};
<commit_msg>prevent 404 errors from stoppping fractal server (#515)<commit_after>'use strict';

const utils = require('util');

module.exports = {

    command: 'start',

    config: {
        description: 'Start a development server',
        options: [
            ['-p, --port <number>', 'The port to run the server on.'],
            ['-t, --theme <package-name>', 'The name of custom UI theme to use, if required'],
            ['-s, --sync', 'Use BrowserSync to sync and reload pages when changes occur'],
            ['-w, --watch', 'Watch the filesystem for changes.'],
        ],
    },

    action(args, done) {
        const server = this.fractal.web.server(args.options);

        server.on('ready', () => {
            const header = 'Fractal web UI server is running!';
            const footer = this.fractal.cli.isInteractive() ? 'Use the \'stop\' command to stop the server.' : 'Use ^C to stop the server.';
            const serverUrl = server.urls.server;
            const format = str => this.console.theme.format(str, 'success', true);
            let body = '';

            if (!server.isSynced) {
                body += `Local URL: ${format(serverUrl)}`;
            } else {
                const syncUrls = server.urls.sync;
                body += `Local URL:      ${format(syncUrls.local)}`;
                body += `\nNetwork URL:    ${format(syncUrls.external)}`;
                body += `\nBrowserSync UI: ${format(syncUrls.ui)}`;
            }

            return this.console.box(header, body, footer).persist();
        });

        server.on('error', (err, req) => {
            if (err.status === '404') {
                this.console.warn(`404: ${err.message}`);
            } else {
                this.console.error(err.message, err);
            }
        });

        server.on('destroy', () => done());
        server.on('stopped', () => done());

        server.start(args.options.sync).catch(e => {
            this.console.error(e);
            done();
        });
    },

};
<|endoftext|>


<commit_before>// Copyright (c) 2012-2017, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

var Compile = require('../base-compiler');
var asm = require('../asm-cl');

function compileCl(info, env) {
    var compile = new Compile(info, env);
    compile.asm = new asm.AsmParser(env.compilerProps);
    info.supportsFiltersInBinary = true;
    if (process.platform == "linux") {
        var wine = env.gccProps("wine");
        var origExec = compile.exec;
        compile.exec = function (command, args, options) {
            if (command.toLowerCase().endsWith(".exe")) {
                args.unshift(command);
                command = wine;
            }
            return origExec(command, args, options);
        };
        compile.filename = function (fn) {
            return 'Z:' + fn;
        };
    }
    compile.supportsObjdump = function () {
        return false;
    };
    compile.optionsForFilter = function (filters, outputFilename, userOptions) {
        return [
            '/FAsc',
            '/c',
            '/Fa' + this.filename(outputFilename),
            '/Fo' + this.filename(outputFilename + '.obj')
        ];
    };
    return compile.initialise();
}

module.exports = compileCl;<commit_msg>once undname works properly under Wine, this code should support that<commit_after>// Copyright (c) 2012-2017, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

var Compile = require('../base-compiler');
var asm = require('../asm-cl');
var utils = require('../utils');
var fs = require('fs-extra'),
    path = require('path'),
    _ = require('underscore-node');

function compileCl(info, env) {
    var compile = new Compile(info, env);
    compile.asm = new asm.AsmParser(env.compilerProps);
    info.supportsFiltersInBinary = true;
    if (process.platform == "linux") {
        var wine = env.gccProps("wine");
        var origExec = compile.exec;
        compile.exec = function (command, args, options) {
            if (command.toLowerCase().endsWith(".exe")) {
                args.unshift(command);
                command = wine;
            }
            return origExec(command, args, options);
        };
        compile.filename = function (fn) {
            return 'Z:' + fn;
        };
    }
    compile.supportsObjdump = function () {
        return false;
    };

    compile.postProcessAsm = function (result) {
        if (!result.okToCache) return result;
        var demangler = this.compiler.demangler;
        if (!demangler) return result;

        if (demangler.toLowerCase().endsWith("undname.exe")) {
            return this.newTempDir().then(function (tmpDir) {
                var tmpfile = path.join(tmpDir, "output.s");
                fs.writeFileSync(tmpfile, _.pluck(result.asm, 'text').join("\r\n"));

                return this.exec(demangler, [tmpfile], {})
                    .then(_.bind(function (demangleResult) {
                    fs.unlink(tmpfile, function() {
                        fs.remove(tmpDir, function() {});
                    });

                    var lines = utils.splitLines(demangleResult.stdout);
                    for (var i = 0; i < result.asm.length; ++i)
                        result.asm[i].text = lines[i];
                    return result;
                }, this));
            }.bind(this));
        } else {
            return this.exec(demangler, [], {input: _.pluck(result.asm, 'text').join("\n")})
                .then(_.bind(function (demangleResult) {
                    var lines = utils.splitLines(demangleResult.stdout);
                    for (var i = 0; i < result.asm.length; ++i)
                        result.asm[i].text = lines[i];
                    return result;
                }, this));
        }
    };

    compile.optionsForFilter = function (filters, outputFilename, userOptions) {
        return [
            '/FAsc',
            '/c',
            '/Fa' + this.filename(outputFilename),
            '/Fo' + this.filename(outputFilename + '.obj')
        ];
    };
    return compile.initialise();
}

module.exports = compileCl;<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 Vanderbilt University, All rights reserved.
 *
 * Author: Miklos Maroti
 */

define(function () {
	"use strict";

	var assert = function (cond) {
		if( !cond ) {
			var error = new Error("ASSERT failed");
			var message = "ASSERT failed at " + error.stack;

			if( console && !process ) {
				console.log(message);
			}

			throw error;
		}
	};

	return assert;
});
<commit_msg>assert have been modified to not throw exception if the process is not defined...<commit_after>/*
 * Copyright (C) 2012 Vanderbilt University, All rights reserved.
 *
 * Author: Miklos Maroti
 */

define(function () {
	"use strict";

	var assert = function (cond) {
		if( !cond ) {
			var error = new Error("ASSERT failed");
			var message = "ASSERT failed at " + error.stack;

            if(typeof(process) === "undefined" && typeof(console) !== "undefined"){
                console.log(message);
            }

            throw error;
		}
	};

	return assert;
});
<|endoftext|>


<commit_before>var config = {};
config.annotator = {};
config.profile = {};
config.apache2 = {};
config.protocal = 'http' // options: http or https

// postgres db
config.postgres = process.env.DATABASE_URL || 'postgres://postgres:<password>@<domain name>:5432/dbmiannotator';

// apache2
config.apache2.host = '<domain name>';
config.apache2.port = '80'  // 443 for https

// dbmi annotator
config.annotator.host = '<domain name>';
config.annotator.port = '3000';

// user default profile
config.profile.def = 'MP';
config.profile.pluginSetL = [];
config.profile.userProfile = {};

//article list
//vlan
config.article = ['dailymed','pmc','wiley','elsevier','springer','sage','taylor','wolters','future'];
//public
//config.article = ['dailymed','pmc';

module.exports = config;
<commit_msg>add experiment option to config sample<commit_after>var config = {};
config.annotator = {};
config.profile = {};
config.apache2 = {};
config.protocal = 'http' // options: http or https

// postgres db
config.postgres = process.env.DATABASE_URL || 'postgres://postgres:<password>@<domain name>:5432/dbmiannotator';

// apache2
config.apache2.host = '<domain name>';
config.apache2.port = '80'  // 443 for https

// dbmi annotator
config.annotator.host = '<domain name>';
config.annotator.port = '3000';

// user default profile
config.profile.def = 'MP';
config.profile.pluginSetL = [];
config.profile.userProfile = {};

//article list
//vlan
config.article = ['dailymed','pmc','wiley','elsevier','springer','sage','taylor','wolters','future', 'test-experiment'];
//public
//config.article = ['dailymed','pmc';

module.exports = config;
<|endoftext|>