<commit_before>var gulp = require('gulp')
var gutil = require('gulp-util')
var sass = require('gulp-sass')
var concat = require('gulp-concat')
var minify = require('gulp-minify-css')
var rename = require('gulp-rename')
var babel = require('gulp-babel')
var promise = require('bluebird').Promise
var Spawner = require('promise-spawner')
var del = require('del')

var jsDirectories = ['bin', 'lib', 'middlewares', 'plugins', 'routes']
var jsGlob = function(prefix) {
  return jsDirectories.map(function(e) {
    return [
      [prefix, e, '**', '*.js'].join('/'),
      [prefix, e, '*.js'].join('/')
    ]
  })
  .reduce(function(a, b) { return a.concat(b) })
  .concat(['!'+prefix+'/gulpfile.js', prefix + '/*.js'])
}

gulp.task('styles', function() {
  return gulp.src('./client/scss/*.scss')
  .pipe(sass({
    includePaths: ['bower_components/foundation/scss']
  }))
  .pipe(concat('app.css'))
  .pipe(gulp.dest('./client/css'))
  .pipe(minify())
  .pipe(rename('app.min.css'))
  .pipe(gulp.dest('./client/css'))
})

gulp.task('babelize', function() {
  return gulp.src(jsGlob('.'), {base: './'})
  .pipe(babel())
  .pipe(gulp.dest('./dist/'))
})

gulp.task('publish:backup', ['babelize'], function() {
  return gulp.src(jsGlob('.'), {base: './'})
  .pipe(gulp.dest('./src'))
})

gulp.task('publish:babelize', ['publish:backup'], function() {
  return gulp.src(jsGlob('./dist'), {base: './dist'})
  .pipe(gulp.dest('./'))
})

gulp.task('publish:restore', function() {
  return gulp.src(jsGlob('./src'), {base: './src'})
  .pipe(gulp.dest('.'))
})

gulp.task('publish:clean', ['publish:restore'], function() {
  return del(['./dist', './src'])
})

gulp.task('publish:npm', ['publish:babelize'], function() {
  var spawn = new Spawner({
    out: function(d) { return gutil.log(gutil.colors.green(d)) },
    err: function(d) { return gutil.log(gutil.colors.red(d)) },
  })

  return spawn.sp('npm publish', {cwd: __dirname})
  .catch(function(){
    //resolving to go to next task
    return Promise.resolve()
  })
})

gulp.task('publish', ['publish:npm'], function() {
  return gulp.start('publish:clean')
})

gulp.task('watch', ['default'], function() {
  gulp.watch('./client/scss/*.scss', ['styles'])
})
<commit_msg>chore(gulp): Missing default task<commit_after>var gulp = require('gulp')
var gutil = require('gulp-util')
var sass = require('gulp-sass')
var concat = require('gulp-concat')
var minify = require('gulp-minify-css')
var rename = require('gulp-rename')
var babel = require('gulp-babel')
var promise = require('bluebird').Promise
var Spawner = require('promise-spawner')
var del = require('del')

var jsDirectories = ['bin', 'lib', 'middlewares', 'plugins', 'routes']
var jsGlob = function(prefix) {
  return jsDirectories.map(function(e) {
    return [
      [prefix, e, '**', '*.js'].join('/'),
      [prefix, e, '*.js'].join('/')
    ]
  })
  .reduce(function(a, b) { return a.concat(b) })
  .concat(['!'+prefix+'/gulpfile.js', prefix + '/*.js'])
}

gulp.task('styles', function() {
  return gulp.src('./client/scss/*.scss')
  .pipe(sass({
    includePaths: ['bower_components/foundation/scss']
  }))
  .pipe(concat('app.css'))
  .pipe(gulp.dest('./client/css'))
  .pipe(minify())
  .pipe(rename('app.min.css'))
  .pipe(gulp.dest('./client/css'))
})

gulp.task('babelize', function() {
  return gulp.src(jsGlob('.'), {base: './'})
  .pipe(babel())
  .pipe(gulp.dest('./dist/'))
})

gulp.task('publish:backup', ['babelize'], function() {
  return gulp.src(jsGlob('.'), {base: './'})
  .pipe(gulp.dest('./src'))
})

gulp.task('publish:babelize', ['publish:backup'], function() {
  return gulp.src(jsGlob('./dist'), {base: './dist'})
  .pipe(gulp.dest('./'))
})

gulp.task('publish:restore', function() {
  return gulp.src(jsGlob('./src'), {base: './src'})
  .pipe(gulp.dest('.'))
})

gulp.task('publish:clean', ['publish:restore'], function() {
  return del(['./dist', './src'])
})

gulp.task('publish:npm', ['publish:babelize'], function() {
  var spawn = new Spawner({
    out: function(d) { return gutil.log(gutil.colors.green(d)) },
    err: function(d) { return gutil.log(gutil.colors.red(d)) },
  })

  return spawn.sp('npm publish', {cwd: __dirname})
  .catch(function(){
    //resolving to go to next task
    return Promise.resolve()
  })
})

gulp.task('publish', ['publish:npm'], function() {
  return gulp.start('publish:clean')
})

gulp.task('default', ['styles'])

gulp.task('watch', ['default'], function() {
  gulp.watch('./client/scss/*.scss', ['styles'])
})
<|endoftext|>


<commit_before>/* eslint-env mocha */

var appdmg = require('../')
var imageFormat = require('./lib/image-format')
var visuallyVerifyImage = require('./lib/visually-verify-image')

var fs = require('fs')
var path = require('path')
var temp = require('fs-temp')
var assert = require('assert')

var STEPS = 20

function runAppdmg (opts, verify, cb) {
  var progressCalled = 0
  var ee = appdmg(opts)

  ee.on('progress', function () {
    progressCalled++
  })

  ee.on('finish', function () {
    try {
      assert.equal(progressCalled, STEPS * 2)
      assert.equal(imageFormat(opts.target), verify.format)
    } catch (err) {
      return cb(err)
    }

    var expected = path.join(__dirname, verify.visually)
    visuallyVerifyImage(opts.target, verify.title, expected, cb)
  })
}

describe('api', function () {
  var targetDir, targetPath

  beforeEach(function () {
    targetDir = temp.mkdirSync()
    targetPath = path.join(targetDir, 'Test.dmg')
  })

  afterEach(function () {
    fs.unlinkSync(targetPath)
    fs.rmdirSync(path.dirname(targetPath))
  })

  it('creates an image from a modern specification', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      source: path.join(__dirname, 'assets', 'appdmg.json')
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image from a legacy specification', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      source: path.join(__dirname, 'assets', 'appdmg-legacy.json')
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image from a passed options', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      basepath: path.join(__dirname, 'assets'),
      specification: {
        title: 'Test Title',
        icon: 'TestIcon.icns',
        background: 'TestBkg.png',
        contents: [
          { x: 448, y: 344, type: 'link', path: '/Applications' },
          { x: 192, y: 344, type: 'file', path: 'TestApp.app' },
          { x: 512, y: 128, type: 'file', path: 'TestDoc.txt' }
        ]
      }
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image without compression', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      basepath: path.join(__dirname, 'assets'),
      specification: {
        title: 'Test Title',
        icon: 'TestIcon.icns',
        background: 'TestBkg.png',
        format: 'UDRO',
        contents: [
          { x: 448, y: 344, type: 'link', path: '/Applications' },
          { x: 192, y: 344, type: 'file', path: 'TestApp.app' },
          { x: 512, y: 128, type: 'file', path: 'TestDoc.txt' }
        ]
      }
    }

    var verify = {
      format: 'UDRO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image with a background color', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      source: path.join(__dirname, 'assets', 'appdmg-bg-color.json')
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-2.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image with custom names', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      basepath: path.join(__dirname, 'assets'),
      specification: {
        title: 'Test Title',
        icon: 'TestIcon.icns',
        background: 'TestBkg.png',
        contents: [
          { x: 448, y: 344, type: 'link', path: '/Applications', name: 'System Apps' },
          { x: 192, y: 344, type: 'file', path: 'TestApp.app', name: 'My Nice App.app' },
          { x: 512, y: 128, type: 'file', path: 'TestDoc.txt', name: 'Documentation.txt' }
        ]
      }
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-3.png'
    }

    runAppdmg(opts, verify, done)
  })
})
<commit_msg>Fix number of steps in api test<commit_after>/* eslint-env mocha */

var appdmg = require('../')
var imageFormat = require('./lib/image-format')
var visuallyVerifyImage = require('./lib/visually-verify-image')

var fs = require('fs')
var path = require('path')
var temp = require('fs-temp')
var assert = require('assert')

var STEPS = 21

function runAppdmg (opts, verify, cb) {
  var progressCalled = 0
  var ee = appdmg(opts)

  ee.on('progress', function () {
    progressCalled++
  })

  ee.on('finish', function () {
    try {
      assert.equal(progressCalled, STEPS * 2)
      assert.equal(imageFormat(opts.target), verify.format)
    } catch (err) {
      return cb(err)
    }

    var expected = path.join(__dirname, verify.visually)
    visuallyVerifyImage(opts.target, verify.title, expected, cb)
  })
}

describe('api', function () {
  var targetDir, targetPath

  beforeEach(function () {
    targetDir = temp.mkdirSync()
    targetPath = path.join(targetDir, 'Test.dmg')
  })

  afterEach(function () {
    fs.unlinkSync(targetPath)
    fs.rmdirSync(path.dirname(targetPath))
  })

  it('creates an image from a modern specification', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      source: path.join(__dirname, 'assets', 'appdmg.json')
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image from a legacy specification', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      source: path.join(__dirname, 'assets', 'appdmg-legacy.json')
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image from a passed options', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      basepath: path.join(__dirname, 'assets'),
      specification: {
        title: 'Test Title',
        icon: 'TestIcon.icns',
        background: 'TestBkg.png',
        contents: [
          { x: 448, y: 344, type: 'link', path: '/Applications' },
          { x: 192, y: 344, type: 'file', path: 'TestApp.app' },
          { x: 512, y: 128, type: 'file', path: 'TestDoc.txt' }
        ]
      }
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image without compression', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      basepath: path.join(__dirname, 'assets'),
      specification: {
        title: 'Test Title',
        icon: 'TestIcon.icns',
        background: 'TestBkg.png',
        format: 'UDRO',
        contents: [
          { x: 448, y: 344, type: 'link', path: '/Applications' },
          { x: 192, y: 344, type: 'file', path: 'TestApp.app' },
          { x: 512, y: 128, type: 'file', path: 'TestDoc.txt' }
        ]
      }
    }

    var verify = {
      format: 'UDRO',
      title: 'Test Title',
      visually: 'accepted-1.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image with a background color', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      source: path.join(__dirname, 'assets', 'appdmg-bg-color.json')
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-2.png'
    }

    runAppdmg(opts, verify, done)
  })

  it('creates an image with custom names', function (done) {
    this.timeout(60000) // 1 minute

    var opts = {
      target: targetPath,
      basepath: path.join(__dirname, 'assets'),
      specification: {
        title: 'Test Title',
        icon: 'TestIcon.icns',
        background: 'TestBkg.png',
        contents: [
          { x: 448, y: 344, type: 'link', path: '/Applications', name: 'System Apps' },
          { x: 192, y: 344, type: 'file', path: 'TestApp.app', name: 'My Nice App.app' },
          { x: 512, y: 128, type: 'file', path: 'TestDoc.txt', name: 'Documentation.txt' }
        ]
      }
    }

    var verify = {
      format: 'UDZO',
      title: 'Test Title',
      visually: 'accepted-3.png'
    }

    runAppdmg(opts, verify, done)
  })
})
<|endoftext|>


<commit_before>/**
 *
 *
 * @copyright 2017 Government of Canada
 * @license MIT
 * @author igboyes
 *
 */

import React from "react";
import PropTypes from "prop-types";
import { Table, Label, Collapse } from "react-bootstrap";
import { Icon, Flex, FlexItem, ListGroupItem } from "../../../base";
import { followDownload } from "../../../utils";

class Sequence extends React.Component {

    constructor (props) {
        super(props);
        this.state = {
            in: false
        };
    }

    static propTypes = {
        id: PropTypes.string,
        accession: PropTypes.string,
        definition: PropTypes.string,
        host: PropTypes.string,
        sequence: PropTypes.string,
        showEditSequence: PropTypes.func,
        showRemoveSequence: PropTypes.func,
        canModify: PropTypes.bool
    };

    handleCloseClick = () => {
        this.setState({in: false});
    };

    handleDownload = () => {
        followDownload(`/download/sequences/${this.props.id}`);
    };

    handleShowEditSequence = () => {
        this.props.showEditSequence(this.props.id);
    };

    handleShowRemoveSequence = () => {
        this.props.showRemoveSequence(this.props.id);
    };

    render () {

        const accession = this.props.accession;
        const id = this.props.id;

        let buttons;

        if (this.state.in) {
            buttons = (
                <FlexItem>
                    <Flex alignItem="center">
                        {this.props.canModify ? (
                            <FlexItem grow={0} shrink={0}>
                                <Icon
                                    name="pencil-alt"
                                    bsStyle="warning"
                                    tip="Edit Sequence"
                                    onClick={this.handleShowEditSequence}
                                />
                            </FlexItem>
                        ) : null}
                        {this.props.canModify ? (
                            <FlexItem grow={0} shrink={0} pad={3}>
                                <Icon
                                    name="trash"
                                    bsStyle="danger"
                                    tip="Remove Sequence"
                                    onClick={this.handleShowRemoveSequence}
                                />
                            </FlexItem>
                        ) : null}
                        <FlexItem grow={0} shrink={0} pad={3}>
                            <Icon
                                name="download"
                                tip="Download FASTA"
                                onClick={this.handleDownload}
                            />
                        </FlexItem>
                        <FlexItem pad={5}>
                            <button type="button" className="close" onClick={this.handleCloseClick}>
                                ×
                            </button>
                        </FlexItem>
                    </Flex>
                </FlexItem>
            );
        }

        return (
            <ListGroupItem
                className="spaced"
                componentClass="div"
                key={id}
                onClick={this.state.in ? null : () => this.setState({in: true})}
            >

                    <Flex alignItems="center">
                        <FlexItem grow={0} shrink={0}>
                            {id}
                        </FlexItem>
                        <FlexItem className="sequence-header-definition" grow={1} shrink={1} pad={5}>
                            {this.props.definition}
                        </FlexItem>
                        {buttons}
                    </Flex>

                <Collapse in={this.state.in}>

                                    Accession
                                    {accession}

                                    Unique ID
                                    {id}

                                    Host
                                    {this.props.host}

                                    Definition
                                    {this.props.definition}

                                    Sequence

                                        <textarea
                                            rows="5"
                                            value={this.props.sequence}
                                            readOnly
                                        />

                </Collapse>
            </ListGroupItem>
        );
    }
}

export default Sequence;
<commit_msg>Remove id, fix label<commit_after>/**
 *
 *
 * @copyright 2017 Government of Canada
 * @license MIT
 * @author igboyes
 *
 */

import React from "react";
import PropTypes from "prop-types";
import { Table, Label, Collapse } from "react-bootstrap";
import { Icon, Flex, FlexItem, ListGroupItem } from "../../../base";
import { followDownload } from "../../../utils";

class Sequence extends React.Component {

    constructor (props) {
        super(props);
        this.state = {
            in: false
        };
    }

    static propTypes = {
        id: PropTypes.string,
        accession: PropTypes.string,
        definition: PropTypes.string,
        host: PropTypes.string,
        sequence: PropTypes.string,
        showEditSequence: PropTypes.func,
        showRemoveSequence: PropTypes.func,
        canModify: PropTypes.bool
    };

    handleCloseClick = () => {
        this.setState({in: false});
    };

    handleDownload = () => {
        followDownload(`/download/sequences/${this.props.id}`);
    };

    handleShowEditSequence = () => {
        this.props.showEditSequence(this.props.id);
    };

    handleShowRemoveSequence = () => {
        this.props.showRemoveSequence(this.props.id);
    };

    render () {

        const accession = this.props.accession;
        const id = this.props.id;

        let buttons;

        if (this.state.in) {
            buttons = (
                <FlexItem>
                    <Flex alignItem="center">
                        {this.props.canModify ? (
                            <FlexItem grow={0} shrink={0}>
                                <Icon
                                    name="pencil-alt"
                                    bsStyle="warning"
                                    tip="Edit Sequence"
                                    onClick={this.handleShowEditSequence}
                                />
                            </FlexItem>
                        ) : null}
                        {this.props.canModify ? (
                            <FlexItem grow={0} shrink={0} pad={3}>
                                <Icon
                                    name="trash"
                                    bsStyle="danger"
                                    tip="Remove Sequence"
                                    onClick={this.handleShowRemoveSequence}
                                />
                            </FlexItem>
                        ) : null}
                        <FlexItem grow={0} shrink={0} pad={3}>
                            <Icon
                                name="download"
                                tip="Download FASTA"
                                onClick={this.handleDownload}
                            />
                        </FlexItem>
                        <FlexItem pad={5}>
                            <button type="button" className="close" onClick={this.handleCloseClick}>
                                ×
                            </button>
                        </FlexItem>
                    </Flex>
                </FlexItem>
            );
        }

        return (
            <ListGroupItem
                className="spaced"
                componentClass="div"
                key={id}
                onClick={this.state.in ? null : () => this.setState({in: true})}
            >

                    <Flex alignItems="center">
                        <FlexItem grow={0} shrink={0}>
                            {accession}
                        </FlexItem>
                        <FlexItem className="sequence-header-definition" grow={1} shrink={1} pad={5}>
                            {this.props.definition}
                        </FlexItem>
                        {buttons}
                    </Flex>

                <Collapse in={this.state.in}>

                                    Accession
                                    {accession}

                                    Host
                                    {this.props.host}

                                    Definition
                                    {this.props.definition}

                                    Sequence

                                        <textarea
                                            rows="5"
                                            value={this.props.sequence}
                                            readOnly
                                        />

                </Collapse>
            </ListGroupItem>
        );
    }
}

export default Sequence;
<|endoftext|>


<commit_before>// These substrings get you hundreds or thousands of results so we
// avoid searching for them, opting instead to wait for the user to
// type another character
var COMMON = ["ille", "vill", "land", "owns", "svil", "ship", "nshi",
              "wnsh", "ield", "fiel", "burg", "ngto", "ingt", "gton",
              "ford", "ring", "town", "sbur", "ston", "wood", "ount",
              "ster", "orth", "prin", "nton", "ings", "lton", "nvil",
              "dale", "idge", "reen", "outh"];

$(document).bind('yourlabsWidgetReady',
                 function() {
                     $('body').on('initialize',
                                  '.autocomplete-light-widget[data-widget-bootstrap=side-by-side]',
                                  function() {
                                      $(this).yourlabsWidget(ourWidget);
                                  });
                 });

var ourWidget = { initializeAutocomplete: init,
                  selectChoice: select,
                  deselectChoice: deselect,
                  updateAutocompleteExclude: updateExclude,
                  hide: nothing
                };

function nothing() {
    // do nothing, on purpose
}

/**
 * Overrides for the Autocomplete class
 */
function refresh() {
    this.value = this.getQuery();
    if (this.value.length > 4 || COMMON.indexOf(this.value) === -1) {
        yourlabs.Autocomplete.prototype.refresh.call(this);
    }
}

/**
 * Overrides for the Widget class
 */
function init() {
    this.select = this.widget.find('select.value-select');
    var box = this.box = this.widget.find('select.box');
    var deck = this.deck = this.widget.find('select.sbsdeck');
    this.autocomplete = this.input.yourlabsAutocomplete({ box: this.box,
                                                          fixPosition: nothing,
                                                          hide: nothing,
                                                          move: nothing,
                                                          boxMouseenter: nothing,
                                                          boxMouseleave: nothing,
                                                          boxClick: nothing,
                                                          minimumCharacters: 4,
                                                          refresh: refresh
                                                        });
    var self = this;
    $("button.select").click(function () {
                                 box.find(':selected')
                                    .each(function () {
                                              self.selectChoice($(this));
                                          });
                             });
    $("button.deselect").click(function () {
                                   deck.find(':selected')
                                       .each(function () {
                                                 self.deselectChoice($(this));
                                             });
                               });
}

function select(choice) {
    var self = this;
    var values = choice.data('value-multiple');
    if (values) {
        this.freeDeck();
        this.addToDeck(choice, choice.data('value'));
        if (typeof values === "string") {
            values = values.split(",");
        } else if (typeof values === "number") {
            values = [values];
        }
        values.map(function (v) {
                       yourlabs.Widget
                               .prototype
                               .addToSelect
                               .call(self, choice, v);
                   });
        var index = $(':input:visible').index(this.input);
        this.resetDisplay();
        if (this.input.is(':visible')) {
            this.input.focus();
        } else {
            var next = $(':input:visible:eq('+ index +')');
            next.focus();
        }
        if (this.clearInputOnSelectChoice === "1")
            this.input.val('');
    } else {
        yourlabs.Widget.prototype.selectChoice.call(this, choice);
    }
}

function deselect(choice) {
    var self = this;
    var values = choice.data('value-multiple');
    if (values) {
        if (typeof values === "string") {
            values = values.split(",");
        } else if (typeof values === "number") {
            values = [values];
        }
        values.map(function (v) {
                       self.select
                           .find('option[value="'+v+'"]')
                           .remove();
                   });
        this.select.trigger('change');
        choice.remove();
        this.updateAutocompleteExclude();
        this.resetDisplay();
    } else {
        yourlabs.Widget.prototype.deselectChoice.call(this, choice);
    }
}

function updateExclude() {
    var widget = this;
    var choices = this.select.find("[value]");
    this.autocomplete.data['exclude'] = $.map(choices,
                                              function(choice) {
                                                  return $(choice).attr("value");
                                              });
}

<commit_msg>allow autocompletes of known short city names<commit_after>// These substrings get you hundreds or thousands of results so we
// avoid searching for them, opting instead to wait for the user to
// type another character
var COMMON = ["ille", "vill", "land", "owns", "svil", "ship", "nshi",
              "wnsh", "ield", "fiel", "burg", "ngto", "ingt", "gton",
              "ford", "ring", "town", "sbur", "ston", "wood", "ount",
              "ster", "orth", "prin", "nton", "ings", "lton", "nvil",
              "dale", "idge", "reen", "outh"];

// These, on the other hand, are all the cities which have
// three-character names. We'll autocomplete these even though some of
// them return more results than we'd like.
var THREE_LETTER = ["ace", "ada", "aho", "aid", "ajo", "ama", "amo",
                    "ari", "ark", "arm", "arp", "art", "ary", "ash",
                    "ava", "ayr", "bay", "bee", "bem", "bim", "bly",
                    "bow", "bud", "cid", "cly", "coe", "cox", "coy",
                    "cut", "day", "dee", "dix", "dow", "duo", "dye",
                    "eek", "ege", "ela", "eli", "elk", "elm", "ely",
                    "era", "eva", "fay", "fig", "flo", "fly", "fox",
                    "fry", "gap", "gas", "gay", "gem", "guy", "hay",
                    "hoy", "hye", "ida", "igo", "ila", "ina", "ink",
                    "ira", "iva", "ivy", "ixl", "jal", "jay", "jet",
                    "job", "joy", "jud", "kay", "keo", "kim", "lay",
                    "lea", "lee", "leo", "loa", "lon", "lum", "lux",
                    "mae", "man", "max", "may", "mio", "moe", "naf",
                    "ned", "ney", "nye", "oak", "odd", "ola", "oma",
                    "ona", "ong", "ono", "opp", "ops", "ora", "ord",
                    "orr", "oso", "oto", "pax", "pep", "poe", "ray",
                    "rea", "reo", "rew", "rex", "rig", "rio", "roe",
                    "roy", "rye", "sac", "sod", "sun", "tad", "tea",
                    "tok", "tom", "tow", "tye", "ulm", "una", "uno",
                    "usk", "ute", "uva", "van", "veo", "war", "wax",
                    "way", "wea", "why", "yoe", "zap", "zim", "zoe"];

$(document).bind('yourlabsWidgetReady',
                 function() {
                     $('body').on('initialize',
                                  '.autocomplete-light-widget[data-widget-bootstrap=side-by-side]',
                                  function() {
                                      $(this).yourlabsWidget(ourWidget);
                                  });
                 });

var ourWidget = { initializeAutocomplete: init,
                  selectChoice: select,
                  deselectChoice: deselect,
                  updateAutocompleteExclude: updateExclude,
                  hide: nothing
                };

function nothing() {
    // do nothing, on purpose
}

/**
 * Overrides for the Autocomplete class
 */
function refresh() {
    this.value = this.getQuery().toLowerCase();
    if (THREE_LETTER.indexOf(this.value) !== -1 ||
        this.value.length > 4 ||
        COMMON.indexOf(this.value) === -1) {
        yourlabs.Autocomplete.prototype.refresh.call(this);
    }
}

/**
 * Overrides for the Widget class
 */
function init() {
    this.select = this.widget.find('select.value-select');
    var box = this.box = this.widget.find('select.box');
    var deck = this.deck = this.widget.find('select.sbsdeck');
    this.autocomplete = this.input.yourlabsAutocomplete({ box: this.box,
                                                          fixPosition: nothing,
                                                          hide: nothing,
                                                          move: nothing,
                                                          boxMouseenter: nothing,
                                                          boxMouseleave: nothing,
                                                          boxClick: nothing,
                                                          minimumCharacters: 3,
                                                          refresh: refresh
                                                        });
    var self = this;
    $("button.select").click(function () {
                                 box.find(':selected')
                                    .each(function () {
                                              self.selectChoice($(this));
                                          });
                             });
    $("button.deselect").click(function () {
                                   deck.find(':selected')
                                       .each(function () {
                                                 self.deselectChoice($(this));
                                             });
                               });
}

function select(choice) {
    var self = this;
    var values = choice.data('value-multiple');
    if (values) {
        this.freeDeck();
        this.addToDeck(choice, choice.data('value'));
        if (typeof values === "string") {
            values = values.split(",");
        } else if (typeof values === "number") {
            values = [values];
        }
        values.map(function (v) {
                       yourlabs.Widget
                               .prototype
                               .addToSelect
                               .call(self, choice, v);
                   });
        var index = $(':input:visible').index(this.input);
        this.resetDisplay();
        if (this.input.is(':visible')) {
            this.input.focus();
        } else {
            var next = $(':input:visible:eq('+ index +')');
            next.focus();
        }
        if (this.clearInputOnSelectChoice === "1")
            this.input.val('');
    } else {
        yourlabs.Widget.prototype.selectChoice.call(this, choice);
    }
}

function deselect(choice) {
    var self = this;
    var values = choice.data('value-multiple');
    if (values) {
        if (typeof values === "string") {
            values = values.split(",");
        } else if (typeof values === "number") {
            values = [values];
        }
        values.map(function (v) {
                       self.select
                           .find('option[value="'+v+'"]')
                           .remove();
                   });
        this.select.trigger('change');
        choice.remove();
        this.updateAutocompleteExclude();
        this.resetDisplay();
    } else {
        yourlabs.Widget.prototype.deselectChoice.call(this, choice);
    }
}

function updateExclude() {
    var widget = this;
    var choices = this.select.find("[value]");
    this.autocomplete.data['exclude'] = $.map(choices,
                                              function(choice) {
                                                  return $(choice).attr("value");
                                              });
}

<|endoftext|>


<commit_before>/**
 * --------------------------------------------
 * AdminLTE Treeview.js
 * License MIT
 * --------------------------------------------
 */

const Treeview = (($) => {
  /**
   * Constants
   * ====================================================
   */

  const NAME               = 'Treeview'
  const DATA_KEY           = 'lte.treeview'
  const EVENT_KEY          = `.${DATA_KEY}`
  const JQUERY_NO_CONFLICT = $.fn[NAME]

  const Event = {
    SELECTED     : `selected${EVENT_KEY}`,
    EXPANDED     : `expanded${EVENT_KEY}`,
    COLLAPSED    : `collapsed${EVENT_KEY}`,
    LOAD_DATA_API: `load${EVENT_KEY}`
  }

  const Selector = {
    LI           : '.nav-item',
    LINK         : '.nav-link',
    TREEVIEW_MENU: '.nav-treeview',
    OPEN         : '.menu-open',
    DATA_WIDGET  : '[data-widget="treeview"]'
  }

  const ClassName = {
    LI               : 'nav-item',
    LINK             : 'nav-link',
    TREEVIEW_MENU    : 'nav-treeview',
    OPEN             : 'menu-open',
    SIDEBAR_COLLAPSED: 'sidebar-collapse'
  }

  const Default = {
    trigger              : `${Selector.DATA_WIDGET} ${Selector.LINK}`,
    animationSpeed       : 300,
    accordion            : true,
    expandSidebar        : true,
    sidebarButtonSelector: '[data-widget="pushmenu"]'
  }

  /**
   * Class Definition
   * ====================================================
   */
  class Treeview {
    constructor(element, config) {
      this._config  = config
      this._element = element
    }

    // Public

    init() {
      this._setupListeners()
    }

    expand(treeviewMenu, parentLi) {
      const expandedEvent = $.Event(Event.EXPANDED)

      if (this._config.accordion) {
        const openMenuLi   = parentLi.siblings(Selector.OPEN).first()
        const openTreeview = openMenuLi.find(Selector.TREEVIEW_MENU).first()
        this.collapse(openTreeview, openMenuLi)
      }

      treeviewMenu.stop().slideDown(this._config.animationSpeed, () => {
        parentLi.addClass(ClassName.OPEN)
        $(this._element).trigger(expandedEvent)
      })

      if (this._config.expandSidebar) {
        this._expandSidebar()
      }
    }

    collapse(treeviewMenu, parentLi) {
      const collapsedEvent = $.Event(Event.COLLAPSED)

      treeviewMenu.stop().slideUp(this._config.animationSpeed, () => {
        parentLi.removeClass(ClassName.OPEN)
        $(this._element).trigger(collapsedEvent)
        treeviewMenu.find(`${Selector.OPEN} > ${Selector.TREEVIEW_MENU}`).slideUp()
        treeviewMenu.find(Selector.OPEN).removeClass(ClassName.OPEN)
      })
    }

    toggle(event) {

      const $relativeTarget = $(event.currentTarget)
      const $parent = $relativeTarget.parent()

      let treeviewMenu = $parent.find('> ' + Selector.TREEVIEW_MENU)

      if (!treeviewMenu.is(Selector.TREEVIEW_MENU)) {

        if (!$parent.is(Selector.LI)) {
          treeviewMenu = $parent.parent().find('> ' + Selector.TREEVIEW_MENU)
        }

        if (!treeviewMenu.is(Selector.TREEVIEW_MENU)) {
          return
        }
      }

      event.preventDefault()

      const parentLi = $relativeTarget.parents(Selector.LI).first()
      const isOpen   = parentLi.hasClass(ClassName.OPEN)

      if (isOpen) {
        this.collapse($(treeviewMenu), parentLi)
      } else {
        this.expand($(treeviewMenu), parentLi)
      }
    }

    // Private

    _setupListeners() {
      $(document).on('click', this._config.trigger, (event) => {
        this.toggle(event)
      })
    }

    _expandSidebar() {
      if ($('body').hasClass(ClassName.SIDEBAR_COLLAPSED)) {
        $(this._config.sidebarButtonSelector).PushMenu('expand')
      }
    }

    // Static

    static _jQueryInterface(config) {
      return this.each(function () {
        let data = $(this).data(DATA_KEY)
        const _options = $.extend({}, Default, $(this).data())

        if (!data) {
          data = new Treeview($(this), _options)
          $(this).data(DATA_KEY, data)
        }

        if (config === 'init') {
          data[config]()
        }
      })
    }
  }

  /**
   * Data API
   * ====================================================
   */

  $(window).on(Event.LOAD_DATA_API, () => {
    $(Selector.DATA_WIDGET).each(function () {
      Treeview._jQueryInterface.call($(this), 'init')
    })
  })

  /**
   * jQuery API
   * ====================================================
   */

  $.fn[NAME] = Treeview._jQueryInterface
  $.fn[NAME].Constructor = Treeview
  $.fn[NAME].noConflict  = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT
    return Treeview._jQueryInterface
  }

  return Treeview
})(jQuery)

export default Treeview
<commit_msg>disabled expandSidebar by default in Treeview<commit_after>/**
 * --------------------------------------------
 * AdminLTE Treeview.js
 * License MIT
 * --------------------------------------------
 */

const Treeview = (($) => {
  /**
   * Constants
   * ====================================================
   */

  const NAME               = 'Treeview'
  const DATA_KEY           = 'lte.treeview'
  const EVENT_KEY          = `.${DATA_KEY}`
  const JQUERY_NO_CONFLICT = $.fn[NAME]

  const Event = {
    SELECTED     : `selected${EVENT_KEY}`,
    EXPANDED     : `expanded${EVENT_KEY}`,
    COLLAPSED    : `collapsed${EVENT_KEY}`,
    LOAD_DATA_API: `load${EVENT_KEY}`
  }

  const Selector = {
    LI           : '.nav-item',
    LINK         : '.nav-link',
    TREEVIEW_MENU: '.nav-treeview',
    OPEN         : '.menu-open',
    DATA_WIDGET  : '[data-widget="treeview"]'
  }

  const ClassName = {
    LI               : 'nav-item',
    LINK             : 'nav-link',
    TREEVIEW_MENU    : 'nav-treeview',
    OPEN             : 'menu-open',
    SIDEBAR_COLLAPSED: 'sidebar-collapse'
  }

  const Default = {
    trigger              : `${Selector.DATA_WIDGET} ${Selector.LINK}`,
    animationSpeed       : 300,
    accordion            : true,
    expandSidebar        : false,
    sidebarButtonSelector: '[data-widget="pushmenu"]'
  }

  /**
   * Class Definition
   * ====================================================
   */
  class Treeview {
    constructor(element, config) {
      this._config  = config
      this._element = element
    }

    // Public

    init() {
      this._setupListeners()
    }

    expand(treeviewMenu, parentLi) {
      const expandedEvent = $.Event(Event.EXPANDED)

      if (this._config.accordion) {
        const openMenuLi   = parentLi.siblings(Selector.OPEN).first()
        const openTreeview = openMenuLi.find(Selector.TREEVIEW_MENU).first()
        this.collapse(openTreeview, openMenuLi)
      }

      treeviewMenu.stop().slideDown(this._config.animationSpeed, () => {
        parentLi.addClass(ClassName.OPEN)
        $(this._element).trigger(expandedEvent)
      })

      if (this._config.expandSidebar) {
        this._expandSidebar()
      }
    }

    collapse(treeviewMenu, parentLi) {
      const collapsedEvent = $.Event(Event.COLLAPSED)

      treeviewMenu.stop().slideUp(this._config.animationSpeed, () => {
        parentLi.removeClass(ClassName.OPEN)
        $(this._element).trigger(collapsedEvent)
        treeviewMenu.find(`${Selector.OPEN} > ${Selector.TREEVIEW_MENU}`).slideUp()
        treeviewMenu.find(Selector.OPEN).removeClass(ClassName.OPEN)
      })
    }

    toggle(event) {

      const $relativeTarget = $(event.currentTarget)
      const $parent = $relativeTarget.parent()

      let treeviewMenu = $parent.find('> ' + Selector.TREEVIEW_MENU)

      if (!treeviewMenu.is(Selector.TREEVIEW_MENU)) {

        if (!$parent.is(Selector.LI)) {
          treeviewMenu = $parent.parent().find('> ' + Selector.TREEVIEW_MENU)
        }

        if (!treeviewMenu.is(Selector.TREEVIEW_MENU)) {
          return
        }
      }

      event.preventDefault()

      const parentLi = $relativeTarget.parents(Selector.LI).first()
      const isOpen   = parentLi.hasClass(ClassName.OPEN)

      if (isOpen) {
        this.collapse($(treeviewMenu), parentLi)
      } else {
        this.expand($(treeviewMenu), parentLi)
      }
    }

    // Private

    _setupListeners() {
      $(document).on('click', this._config.trigger, (event) => {
        this.toggle(event)
      })
    }

    _expandSidebar() {
      if ($('body').hasClass(ClassName.SIDEBAR_COLLAPSED)) {
        $(this._config.sidebarButtonSelector).PushMenu('expand')
      }
    }

    // Static

    static _jQueryInterface(config) {
      return this.each(function () {
        let data = $(this).data(DATA_KEY)
        const _options = $.extend({}, Default, $(this).data())

        if (!data) {
          data = new Treeview($(this), _options)
          $(this).data(DATA_KEY, data)
        }

        if (config === 'init') {
          data[config]()
        }
      })
    }
  }

  /**
   * Data API
   * ====================================================
   */

  $(window).on(Event.LOAD_DATA_API, () => {
    $(Selector.DATA_WIDGET).each(function () {
      Treeview._jQueryInterface.call($(this), 'init')
    })
  })

  /**
   * jQuery API
   * ====================================================
   */

  $.fn[NAME] = Treeview._jQueryInterface
  $.fn[NAME].Constructor = Treeview
  $.fn[NAME].noConflict  = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT
    return Treeview._jQueryInterface
  }

  return Treeview
})(jQuery)

export default Treeview
<|endoftext|>


<commit_before>	var React = require('react');
var ReactDom = require('react-dom');
var domSelect = require('dom-select');
var ReactF1 = require(process.env.PATH_F1);
var async = require('async');

var container;

var target;

var states = {
  out: {
    item: {
    	play: true
    }
  },

  idle: {
    item: {
    	play: false
    }

  }
};

var transitions = [
  { from: 'out', to: 'idle', bi: true }
];

module.exports = function(t) {

  var statesVisited = [];

  // each one of these objects will be applied to the `react-f1` component
  // a callback will be passed to the onComplete function if no onComplete
  // is passed then it is automatically
  async.eachSeries(
    [
      { go: 'out', states: states, transitions: transitions },
      {
        go: 'idle', states: states, transitions: transitions,
        onComplete: function(callback, state, stateName) {
          var el = domSelect('[data-f1]');
          t.equal(stateName, 'idle', 'stateName is idle');
          t.equal(typeof state, 'object', 'state is an object');
          t.equal(el.innerHTML, 'The value has been set to false', 'The div innerHTML has been set to the correct string');

          statesVisited.push(stateName);

          callback(null);
        }
      },
      {
        go: 'out', states: states, transitions: transitions,
        onComplete: function(callback, state, stateName) {
          var el = domSelect('[data-f1]');
          t.equal(stateName, 'out', 'stateName is out');
          t.equal(typeof state, 'object', 'state is an object');
        	t.equal(el.innerHTML, 'The value has been set to true', 'The div innerHTML has been set to the correct string');

          statesVisited.push(stateName);

          callback(null);
        }
      }
    ],
    render,
    function() {
      t.deepEqual(statesVisited, ['idle', 'out'], 'visited all states');

      container.parentNode.removeChild(container);

      t.end();
    }
  );
};

function render(settings, callback) {

  container = container || document.body.appendChild(document.createElement('div'));

  settings.onComplete = settings.onComplete && settings.onComplete.bind(null, callback);

  settings.parsers = {
    init: [],
    update: [
      function(item, state){
        item.innerHTML = (state.play)? 'The value has been set to true' : 'The value has been set to false';
      }
    ]
  }

  var component = <ReactF1
    {...settings}
    style={undefined}
  >

  </ReactF1>;

  ReactDom.render(component, container);

  if(!settings.onComplete) {
    callback(null);
  }
}<commit_msg>Fixing tabs<commit_after>var React = require('react');
var ReactDom = require('react-dom');
var domSelect = require('dom-select');
var ReactF1 = require(process.env.PATH_F1);
var async = require('async');

var container;

var target;

var states = {
  out: {
    item: {
    	play: true
    }
  },

  idle: {
    item: {
    	play: false
    }

  }
};

var transitions = [
  { from: 'out', to: 'idle', bi: true }
];

module.exports = function(t) {

  var statesVisited = [];

  // each one of these objects will be applied to the `react-f1` component
  // a callback will be passed to the onComplete function if no onComplete
  // is passed then it is automatically
  async.eachSeries(
    [
      { go: 'out', states: states, transitions: transitions },
      {
        go: 'idle', states: states, transitions: transitions,
        onComplete: function(callback, state, stateName) {
          var el = domSelect('[data-f1]');
          t.equal(stateName, 'idle', 'stateName is idle');
          t.equal(typeof state, 'object', 'state is an object');
          t.equal(el.innerHTML, 'The value has been set to false', 'The div innerHTML has been set to the correct string');

          statesVisited.push(stateName);

          callback(null);
        }
      },
      {
        go: 'out', states: states, transitions: transitions,
        onComplete: function(callback, state, stateName) {
          var el = domSelect('[data-f1]');
          t.equal(stateName, 'out', 'stateName is out');
          t.equal(typeof state, 'object', 'state is an object');
        	t.equal(el.innerHTML, 'The value has been set to true', 'The div innerHTML has been set to the correct string');

          statesVisited.push(stateName);

          callback(null);
        }
      }
    ],
    render,
    function() {
      t.deepEqual(statesVisited, ['idle', 'out'], 'visited all states');

      container.parentNode.removeChild(container);

      t.end();
    }
  );
};

function render(settings, callback) {

  container = container || document.body.appendChild(document.createElement('div'));

  settings.onComplete = settings.onComplete && settings.onComplete.bind(null, callback);

  settings.parsers = {
    init: [],
    update: [
      function(item, state){
        item.innerHTML = (state.play)? 'The value has been set to true' : 'The value has been set to false';
      }
    ]
  }

  var component = <ReactF1
    {...settings}
    style={undefined}
  >

  </ReactF1>;

  ReactDom.render(component, container);

  if(!settings.onComplete) {
    callback(null);
  }
}<|endoftext|>


<commit_before>'use strict';

var Q = require('q');
var gulpUtil = require('gulp-util');
var childProcess = require('child_process');
var jetpack = require('fs-jetpack');
var utils = require('./utils');

var projectDir;
var tmpDir;
var releasesDir;
var readyAppDir;
var codeDir;
var manifest;

var init = function () {
    projectDir = jetpack;
    tmpDir = projectDir.dir('./tmp', { empty: true });
    releasesDir = projectDir.dir('./releases');
    manifest = projectDir.read('app/package.json', 'json');
    readyAppDir = tmpDir.cwd(manifest.name);
    codeDir = readyAppDir.cwd('resources/app');

    return Q();
};

var copyRuntime = function () {
    return projectDir.copyAsync('node_modules/electron-prebuilt/dist', readyAppDir.path(), { overwrite: true });
};

var copyBuiltApp = function () {
    return projectDir.copyAsync('build', codeDir.path(), { overwrite: true });
};

var finalize = function () {
    var deferred = Q.defer();

    return projectDir.copy('resources/windows/icon.ico', readyAppDir.path('icon.ico'));

    // Replace Electron icon for your own.
    var rcedit = require('rcedit');
    rcedit(readyAppDir.path('electron.exe'), {
        icon: projectDir.path('resources/windows/icon.ico')
    }, function (err) {
        if (!err) {
            deferred.resolve();
        }
    });

    return deferred.promise;
};

var createInstaller = function () {
    var deferred = Q.defer();

    var finalPackageName = manifest.name + '_' + manifest.version + '.exe';
    var installScript = projectDir.read('resources/windows/installer.nsi');
    installScript = utils.replace(installScript, {
        name: manifest.name,
        productName: manifest.productName,
        version: manifest.version,
        src: readyAppDir.path(),
        dest: releasesDir.path(finalPackageName),
        icon: readyAppDir.path('icon.ico'),
        setupIcon: projectDir.path('resources/windows/setup-icon.ico'),
        banner: projectDir.path('resources/windows/setup-banner.bmp'),
    });
    tmpDir.write('installer.nsi', installScript);

    gulpUtil.log('Building installer with NSIS...');

    // Remove destination file if already exists.
    releasesDir.remove(finalPackageName);

    // Note: NSIS have to be added to PATH (environment variables).
    var nsis = childProcess.spawn('makensis', [tmpDir.path('installer.nsi')]);
    nsis.stdout.pipe(process.stdout);
    nsis.stderr.pipe(process.stderr);
    nsis.on('close', function () {
        gulpUtil.log('Installer ready!', releasesDir.path(finalPackageName));
        deferred.resolve();
    });

    return deferred.promise;
};

var cleanClutter = function () {
    return tmpDir.removeAsync('.');
};

module.exports = function () {
    return init()
    .then(copyRuntime)
    .then(copyBuiltApp)
    .then(finalize)
    .then(createInstaller)
    .then(cleanClutter);
};
<commit_msg>Bugfix<commit_after>'use strict';

var Q = require('q');
var gulpUtil = require('gulp-util');
var childProcess = require('child_process');
var jetpack = require('fs-jetpack');
var utils = require('./utils');

var projectDir;
var tmpDir;
var releasesDir;
var readyAppDir;
var codeDir;
var manifest;

var init = function () {
    projectDir = jetpack;
    tmpDir = projectDir.dir('./tmp', { empty: true });
    releasesDir = projectDir.dir('./releases');
    manifest = projectDir.read('app/package.json', 'json');
    readyAppDir = tmpDir.cwd(manifest.name);
    codeDir = readyAppDir.cwd('resources/app');

    return Q();
};

var copyRuntime = function () {
    return projectDir.copyAsync('node_modules/electron-prebuilt/dist', readyAppDir.path(), { overwrite: true });
};

var copyBuiltApp = function () {
    return projectDir.copyAsync('build', codeDir.path(), { overwrite: true });
};

var finalize = function () {
    var deferred = Q.defer();

    projectDir.copy('resources/windows/icon.ico', readyAppDir.path('icon.ico'));

    // Replace Electron icon for your own.
    var rcedit = require('rcedit');
    rcedit(readyAppDir.path('electron.exe'), {
        icon: projectDir.path('resources/windows/icon.ico')
    }, function (err) {
        if (!err) {
            deferred.resolve();
        }
    });

    return deferred.promise;
};

var createInstaller = function () {
    var deferred = Q.defer();

    var finalPackageName = manifest.name + '_' + manifest.version + '.exe';
    var installScript = projectDir.read('resources/windows/installer.nsi');
    installScript = utils.replace(installScript, {
        name: manifest.name,
        productName: manifest.productName,
        version: manifest.version,
        src: readyAppDir.path(),
        dest: releasesDir.path(finalPackageName),
        icon: readyAppDir.path('icon.ico'),
        setupIcon: projectDir.path('resources/windows/setup-icon.ico'),
        banner: projectDir.path('resources/windows/setup-banner.bmp'),
    });
    tmpDir.write('installer.nsi', installScript);

    gulpUtil.log('Building installer with NSIS...');

    // Remove destination file if already exists.
    releasesDir.remove(finalPackageName);

    // Note: NSIS have to be added to PATH (environment variables).
    var nsis = childProcess.spawn('makensis', [tmpDir.path('installer.nsi')]);
    nsis.stdout.pipe(process.stdout);
    nsis.stderr.pipe(process.stderr);
    nsis.on('close', function () {
        gulpUtil.log('Installer ready!', releasesDir.path(finalPackageName));
        deferred.resolve();
    });

    return deferred.promise;
};

var cleanClutter = function () {
    return tmpDir.removeAsync('.');
};

module.exports = function () {
    return init()
    .then(copyRuntime)
    .then(copyBuiltApp)
    .then(finalize)
    .then(createInstaller)
    .then(cleanClutter);
};
<|endoftext|>


<commit_before>/* eslint-disable no-magic-numbers */
import React, {Component, PropTypes} from 'react'
import shallowCompare from 'react-addons-shallow-compare'

import _ from 'lodash'
import moment from 'moment'

import Dygraphs from 'src/external/dygraph'
import getRange from 'shared/parsing/getRangeForDygraph'
import DygraphLegend from 'src/shared/components/DygraphLegend'
import {DISPLAY_OPTIONS} from 'src/dashboards/constants'
import {buildDefaultYLabel} from 'shared/presenters'
import {numberValueFormatter} from 'src/utils/formatting'
import {
  OPTIONS,
  LINE_COLORS,
  LABEL_WIDTH,
  CHAR_PIXELS,
  barPlotter,
  hasherino,
  highlightSeriesOpts,
} from 'src/shared/graphs/helpers'
const {LINEAR, LOG, BASE_10, BASE_2} = DISPLAY_OPTIONS

export default class Dygraph extends Component {
  constructor(props) {
    super(props)
    this.state = {
      legend: {
        x: null,
        series: [],
      },
      sortType: '',
      filterText: '',
      isSynced: false,
      isHidden: true,
      isAscending: true,
      isSnipped: false,
      isFilterVisible: false,
    }
  }

  componentDidMount() {
    const {
      axes: {y, y2},
      ruleValues,
      isGraphFilled: fillGraph,
      isBarGraph,
      options,
    } = this.props

    const timeSeries = this.getTimeSeries()
    const graphRef = this.graphRef

    let defaultOptions = {
      fillGraph,
      logscale: y.scale === LOG,
      colors: this.getLineColors,
      series: this.hashColorDygraphSeries(),
      legendFormatter: legend => this.legendFormatter(legend),
      highlightCallback: e => this.highlightCallback(e),
      unhighlightCallback: e => this.unhighlightCallback(e),
      plugins: [new Dygraphs.Plugins.Crosshair({direction: 'vertical'})],
      axes: {
        y: {
          valueRange: getRange(timeSeries, y.bounds, ruleValues),
          axisLabelFormatter: (yval, __, opts) =>
            numberValueFormatter(yval, opts, y.prefix, y.suffix),
          axisLabelWidth: this.getLabelWidth(),
          labelsKMB: y.base === BASE_10,
          labelsKMG2: y.base === BASE_2,
        },
        y2: {
          valueRange: getRange(timeSeries, y2.bounds),
        },
      },
      highlightSeriesOpts,
      zoomCallback: (lower, upper) => this.handleZoom(lower, upper),
    }

    if (isBarGraph) {
      defaultOptions = {
        ...defaultOptions,
        plotter: barPlotter,
        plugins: [],
        highlightSeriesOpts: {
          ...highlightSeriesOpts,
          highlightCircleSize: 0,
        },
      }
    }

    this.dygraph = new Dygraphs(graphRef, timeSeries, {
      ...defaultOptions,
      ...options,
      ...OPTIONS,
    })

    const {w} = this.dygraph.getArea()
    this.props.setResolution(w)

    // Simple opt-out for now, if a graph should not be synced
    if (this.props.synchronizer) {
      this.sync()
    }
  }

  componentWillUnmount() {
    this.dygraph.destroy()
    delete this.dygraph
  }

  shouldComponentUpdate(nextProps, nextState) {
    const timeRangeChanged = !_.isEqual(
      nextProps.timeRange,
      this.props.timeRange
    )

    if (this.dygraph.isZoomed() && timeRangeChanged) {
      this.dygraph.resetZoom()
    }

    // Will cause componentDidUpdate to fire twice, currently. This could
    // be reduced by returning false from within the reset conditional above,
    // though that would be based on the assumption that props for timeRange
    // will always change before those for data.
    return shallowCompare(this, nextProps, nextState)
  }

  componentDidUpdate() {
    const {labels, axes: {y, y2}, options, ruleValues, isBarGraph} = this.props

    const dygraph = this.dygraph
    if (!dygraph) {
      throw new Error(
        'Dygraph not configured in time; this should not be possible!'
      )
    }

    const timeSeries = this.getTimeSeries()

    const updateOptions = {
      ...options,
      labels,
      ylabel: this.getLabel('y'),
      file: timeSeries,
      logscale: y.scale === LOG,
      axes: {
        y: {
          valueRange: getRange(timeSeries, y.bounds, ruleValues),
          axisLabelFormatter: (yval, __, opts) =>
            numberValueFormatter(yval, opts, y.prefix, y.suffix),
          axisLabelWidth: this.getLabelWidth(),
          labelsKMB: y.base === BASE_10,
          labelsKMG2: y.base === BASE_2,
        },
        y2: {
          valueRange: getRange(timeSeries, y2.bounds),
        },
      },
      colors: this.getLineColors,
      series: this.hashColorDygraphSeries(),
      plotter: isBarGraph ? barPlotter : null,
      visibility: this.visibility(),
    }

    dygraph.updateOptions(updateOptions)

    const {w} = this.dygraph.getArea()
    this.resize()
    this.dygraph.resize()
    this.props.setResolution(w)
  }

  handleZoom = (lower, upper) => {
    const {onZoom} = this.props

    if (this.dygraph.isZoomed() === false) {
      return onZoom(null, null)
    }

    onZoom(this.formatTimeRange(lower), this.formatTimeRange(upper))
  }

  hashColorDygraphSeries = () => {
    const {dygraphSeries} = this.props
    const colors = this.getLineColors()
    const hashColorDygraphSeries = {}

    for (const seriesName in dygraphSeries) {
      const series = dygraphSeries[seriesName]
      const hashIndex = hasherino(seriesName, colors.length)
      const color = colors[hashIndex]
      hashColorDygraphSeries[seriesName] = {...series, color}
    }

    return hashColorDygraphSeries
  }

  sync = () => {
    if (!this.state.isSynced) {
      this.props.synchronizer(this.dygraph)
      this.setState({isSynced: true})
    }
  }

  handleSortLegend = sortType => () => {
    this.setState({sortType, isAscending: !this.state.isAscending})
  }

  handleLegendInputChange = e => {
    this.setState({filterText: e.target.value})
  }

  handleSnipLabel = () => {
    this.setState({isSnipped: !this.state.isSnipped})
  }

  handleToggleFilter = () => {
    this.setState({
      isFilterVisible: !this.state.isFilterVisible,
      filterText: '',
    })
  }

  handleHideLegend = e => {
    const {top, bottom, left, right} = this.graphRef.getBoundingClientRect()

    const mouseY = e.clientY
    const mouseX = e.clientX

    const mouseInGraphY = mouseY <= bottom && mouseY >= top
    const mouseInGraphX = mouseX <= right && mouseX >= left
    const isMouseHoveringGraph = mouseInGraphY && mouseInGraphX

    if (!isMouseHoveringGraph) {
      this.setState({isHidden: true})
      if (!this.visibility().find(bool => bool === true)) {
        this.setState({filterText: ''})
      }
    }
  }

  getLineColors = () => {
    return [...(this.props.overrideLineColors || LINE_COLORS)]
  }

  getLabelWidth = () => {
    const {axes: {y}} = this.props
    return (
      LABEL_WIDTH +
      y.prefix.length * CHAR_PIXELS +
      y.suffix.length * CHAR_PIXELS
    )
  }

  visibility = () => {
    const timeSeries = this.getTimeSeries()
    const {filterText, legend} = this.state
    const series = _.get(timeSeries, '0', [])
    const numSeries = series.length
    return Array(numSeries ? numSeries - 1 : numSeries)
      .fill(true)
      .map((s, i) => {
        if (!legend.series[i]) {
          return true
        }

        return !!legend.series[i].label.match(filterText)
      })
  }

  getTimeSeries = () => {
    const {timeSeries} = this.props
    // Avoid 'Can't plot empty data set' errors by falling back to a
    // default dataset that's valid for Dygraph.
    return timeSeries.length ? timeSeries : [[0]]
  }

  getLabel = axis => {
    const {axes, queries} = this.props
    const label = _.get(axes, [axis, 'label'], '')
    const queryConfig = _.get(queries, ['0', 'queryConfig'], false)

    if (label || !queryConfig) {
      return label
    }

    return buildDefaultYLabel(queryConfig)
  }

  handleLegendRef = el => (this.legendRef = el)

  resize = () => {
    this.dygraph.resizeElements_()
    this.dygraph.predraw_()
  }

  formatTimeRange = timeRange => {
    if (!timeRange) {
      return ''
    }

    return moment(timeRange).utc().format()
  }

  deselectCrosshair = () => {
    const plugins = this.dygraph.plugins_
    const crosshair = plugins.find(
      ({plugin}) => plugin.toString() === 'Crosshair Plugin'
    )

    if (!crosshair || this.props.isBarGraph) {
      return
    }

    crosshair.plugin.deselect()
  }

  unhighlightCallback = e => {
    const {top, bottom, left, right} = this.legendRef.getBoundingClientRect()

    const mouseY = e.clientY
    const mouseX = e.clientX

    const mouseBuffer = 5
    const mouseInLegendY = mouseY <= bottom && mouseY >= top - mouseBuffer
    const mouseInLegendX = mouseX <= right && mouseX >= left
    const isMouseHoveringLegend = mouseInLegendY && mouseInLegendX

    if (!isMouseHoveringLegend) {
      this.setState({isHidden: true})

      if (!this.visibility().find(bool => bool === true)) {
        this.setState({filterText: ''})
      }
    }
  }

  highlightCallback = e => {
    // Move the Legend on hover
    const graphRect = this.graphRef.getBoundingClientRect()
    const legendRect = this.legendRef.getBoundingClientRect()

    const graphWidth = graphRect.width + 32 // Factoring in padding from parent
    const graphHeight = graphRect.height
    const graphBottom = graphRect.bottom
    const legendWidth = legendRect.width
    const legendHeight = legendRect.height
    const screenHeight = window.innerHeight
    const legendMaxLeft = graphWidth - legendWidth / 2
    const trueGraphX = e.pageX - graphRect.left

    let legendLeft = trueGraphX

    // Enforcing max & min legend offsets
    if (trueGraphX < legendWidth / 2) {
      legendLeft = legendWidth / 2
    } else if (trueGraphX > legendMaxLeft) {
      legendLeft = legendMaxLeft
    }

    // Disallow screen overflow of legend
    const isLegendBottomClipped = graphBottom + legendHeight > screenHeight

    const legendTop = isLegendBottomClipped
      ? graphHeight + 8 - legendHeight
      : graphHeight + 8

    this.legendRef.style.left = `${legendLeft}px`
    this.legendRef.style.top = `${legendTop}px`

    this.setState({isHidden: false})
  }

  legendFormatter = legend => {
    if (!legend.x) {
      return ''
    }

    const {state: {legend: prevLegend}} = this
    const highlighted = legend.series.find(s => s.isHighlighted)
    const prevHighlighted = prevLegend.series.find(s => s.isHighlighted)

    const yVal = highlighted && highlighted.y
    const prevY = prevHighlighted && prevHighlighted.y

    if (legend.x === prevLegend.x && yVal === prevY) {
      return ''
    }

    this.setState({legend})
    return ''
  }

  render() {
    const {
      legend,
      filterText,
      isAscending,
      sortType,
      isHidden,
      isSnipped,
      isFilterVisible,
    } = this.state

    return (
      <div className="dygraph-child" onMouseLeave={this.deselectCrosshair}>
        <DygraphLegend
          {...legend}
          sortType={sortType}
          onHide={this.handleHideLegend}
          isHidden={isHidden}
          isFilterVisible={isFilterVisible}
          isSnipped={isSnipped}
          filterText={filterText}
          isAscending={isAscending}
          onSnip={this.handleSnipLabel}
          onSort={this.handleSortLegend}
          legendRef={this.handleLegendRef}
          onToggleFilter={this.handleToggleFilter}
          onInputChange={this.handleLegendInputChange}
        />
        <div
          ref={r => {
            this.graphRef = r
            this.props.dygraphRef(r)
          }}
          className="dygraph-child-container"
          style={this.props.containerStyle}
        />
      </div>
    )
  }
}

const {array, arrayOf, bool, func, shape, string} = PropTypes

Dygraph.defaultProps = {
  axes: {
    y: {
      bounds: [null, null],
      prefix: '',
      suffix: '',
      base: BASE_10,
      scale: LINEAR,
    },
    y2: {
      bounds: undefined,
      prefix: '',
      suffix: '',
    },
  },
  containerStyle: {},
  isGraphFilled: true,
  overrideLineColors: null,
  dygraphRef: () => {},
  onZoom: () => {},
}

Dygraph.propTypes = {
  axes: shape({
    y: shape({
      bounds: array,
    }),
    y2: shape({
      bounds: array,
    }),
  }),
  queries: arrayOf(shape),
  timeSeries: array.isRequired,
  labels: array.isRequired,
  options: shape({}),
  containerStyle: shape({}),
  isGraphFilled: bool,
  isBarGraph: bool,
  overrideLineColors: array,
  dygraphSeries: shape({}).isRequired,
  ruleValues: shape({
    operator: string,
    value: string,
    rangeValue: string,
  }),
  timeRange: shape({
    lower: string.isRequired,
  }),
  synchronizer: func,
  setResolution: func,
  dygraphRef: func,
  onZoom: func,
}
<commit_msg>Invoke line colors and stop wrapping<commit_after>/* eslint-disable no-magic-numbers */
import React, {Component, PropTypes} from 'react'
import shallowCompare from 'react-addons-shallow-compare'

import _ from 'lodash'
import moment from 'moment'

import Dygraphs from 'src/external/dygraph'
import getRange from 'shared/parsing/getRangeForDygraph'
import DygraphLegend from 'src/shared/components/DygraphLegend'
import {DISPLAY_OPTIONS} from 'src/dashboards/constants'
import {buildDefaultYLabel} from 'shared/presenters'
import {numberValueFormatter} from 'src/utils/formatting'
import {
  OPTIONS,
  LINE_COLORS,
  LABEL_WIDTH,
  CHAR_PIXELS,
  barPlotter,
  hasherino,
  highlightSeriesOpts,
} from 'src/shared/graphs/helpers'
const {LINEAR, LOG, BASE_10, BASE_2} = DISPLAY_OPTIONS

export default class Dygraph extends Component {
  constructor(props) {
    super(props)
    this.state = {
      legend: {
        x: null,
        series: [],
      },
      sortType: '',
      filterText: '',
      isSynced: false,
      isHidden: true,
      isAscending: true,
      isSnipped: false,
      isFilterVisible: false,
    }
  }

  componentDidMount() {
    const {
      axes: {y, y2},
      ruleValues,
      isGraphFilled: fillGraph,
      isBarGraph,
      options,
    } = this.props

    const timeSeries = this.getTimeSeries()
    const graphRef = this.graphRef

    let defaultOptions = {
      fillGraph,
      logscale: y.scale === LOG,
      colors: this.getLineColors(),
      series: this.hashColorDygraphSeries(),
      legendFormatter: this.legendFormatter,
      highlightCallback: this.highlightCallback,
      unhighlightCallback: this.unhighlightCallback,
      plugins: [new Dygraphs.Plugins.Crosshair({direction: 'vertical'})],
      axes: {
        y: {
          valueRange: getRange(timeSeries, y.bounds, ruleValues),
          axisLabelFormatter: (yval, __, opts) =>
            numberValueFormatter(yval, opts, y.prefix, y.suffix),
          axisLabelWidth: this.getLabelWidth(),
          labelsKMB: y.base === BASE_10,
          labelsKMG2: y.base === BASE_2,
        },
        y2: {
          valueRange: getRange(timeSeries, y2.bounds),
        },
      },
      highlightSeriesOpts,
      zoomCallback: (lower, upper) => this.handleZoom(lower, upper),
    }

    if (isBarGraph) {
      defaultOptions = {
        ...defaultOptions,
        plotter: barPlotter,
        plugins: [],
        highlightSeriesOpts: {
          ...highlightSeriesOpts,
          highlightCircleSize: 0,
        },
      }
    }

    this.dygraph = new Dygraphs(graphRef, timeSeries, {
      ...defaultOptions,
      ...options,
      ...OPTIONS,
    })

    const {w} = this.dygraph.getArea()
    this.props.setResolution(w)

    // Simple opt-out for now, if a graph should not be synced
    if (this.props.synchronizer) {
      this.sync()
    }
  }

  componentWillUnmount() {
    this.dygraph.destroy()
    delete this.dygraph
  }

  shouldComponentUpdate(nextProps, nextState) {
    const timeRangeChanged = !_.isEqual(
      nextProps.timeRange,
      this.props.timeRange
    )

    if (this.dygraph.isZoomed() && timeRangeChanged) {
      this.dygraph.resetZoom()
    }

    // Will cause componentDidUpdate to fire twice, currently. This could
    // be reduced by returning false from within the reset conditional above,
    // though that would be based on the assumption that props for timeRange
    // will always change before those for data.
    return shallowCompare(this, nextProps, nextState)
  }

  componentDidUpdate() {
    const {labels, axes: {y, y2}, options, ruleValues, isBarGraph} = this.props

    const dygraph = this.dygraph
    if (!dygraph) {
      throw new Error(
        'Dygraph not configured in time; this should not be possible!'
      )
    }

    const timeSeries = this.getTimeSeries()

    const updateOptions = {
      ...options,
      labels,
      ylabel: this.getLabel('y'),
      file: timeSeries,
      logscale: y.scale === LOG,
      axes: {
        y: {
          valueRange: getRange(timeSeries, y.bounds, ruleValues),
          axisLabelFormatter: (yval, __, opts) =>
            numberValueFormatter(yval, opts, y.prefix, y.suffix),
          axisLabelWidth: this.getLabelWidth(),
          labelsKMB: y.base === BASE_10,
          labelsKMG2: y.base === BASE_2,
        },
        y2: {
          valueRange: getRange(timeSeries, y2.bounds),
        },
      },
      colors: this.getLineColors(),
      series: this.hashColorDygraphSeries(),
      plotter: isBarGraph ? barPlotter : null,
      visibility: this.visibility(),
    }

    dygraph.updateOptions(updateOptions)

    const {w} = this.dygraph.getArea()
    this.resize()
    this.dygraph.resize()
    this.props.setResolution(w)
  }

  handleZoom = (lower, upper) => {
    const {onZoom} = this.props

    if (this.dygraph.isZoomed() === false) {
      return onZoom(null, null)
    }

    onZoom(this.formatTimeRange(lower), this.formatTimeRange(upper))
  }

  hashColorDygraphSeries = () => {
    const {dygraphSeries} = this.props
    const colors = this.getLineColors()
    const hashColorDygraphSeries = {}

    for (const seriesName in dygraphSeries) {
      const series = dygraphSeries[seriesName]
      const hashIndex = hasherino(seriesName, colors.length)
      const color = colors[hashIndex]
      hashColorDygraphSeries[seriesName] = {...series, color}
    }

    return hashColorDygraphSeries
  }

  sync = () => {
    if (!this.state.isSynced) {
      this.props.synchronizer(this.dygraph)
      this.setState({isSynced: true})
    }
  }

  handleSortLegend = sortType => () => {
    this.setState({sortType, isAscending: !this.state.isAscending})
  }

  handleLegendInputChange = e => {
    this.setState({filterText: e.target.value})
  }

  handleSnipLabel = () => {
    this.setState({isSnipped: !this.state.isSnipped})
  }

  handleToggleFilter = () => {
    this.setState({
      isFilterVisible: !this.state.isFilterVisible,
      filterText: '',
    })
  }

  handleHideLegend = e => {
    const {top, bottom, left, right} = this.graphRef.getBoundingClientRect()

    const mouseY = e.clientY
    const mouseX = e.clientX

    const mouseInGraphY = mouseY <= bottom && mouseY >= top
    const mouseInGraphX = mouseX <= right && mouseX >= left
    const isMouseHoveringGraph = mouseInGraphY && mouseInGraphX

    if (!isMouseHoveringGraph) {
      this.setState({isHidden: true})
      if (!this.visibility().find(bool => bool === true)) {
        this.setState({filterText: ''})
      }
    }
  }

  getLineColors = () => {
    return [...(this.props.overrideLineColors || LINE_COLORS)]
  }

  getLabelWidth = () => {
    const {axes: {y}} = this.props
    return (
      LABEL_WIDTH +
      y.prefix.length * CHAR_PIXELS +
      y.suffix.length * CHAR_PIXELS
    )
  }

  visibility = () => {
    const timeSeries = this.getTimeSeries()
    const {filterText, legend} = this.state
    const series = _.get(timeSeries, '0', [])
    const numSeries = series.length
    return Array(numSeries ? numSeries - 1 : numSeries)
      .fill(true)
      .map((s, i) => {
        if (!legend.series[i]) {
          return true
        }

        return !!legend.series[i].label.match(filterText)
      })
  }

  getTimeSeries = () => {
    const {timeSeries} = this.props
    // Avoid 'Can't plot empty data set' errors by falling back to a
    // default dataset that's valid for Dygraph.
    return timeSeries.length ? timeSeries : [[0]]
  }

  getLabel = axis => {
    const {axes, queries} = this.props
    const label = _.get(axes, [axis, 'label'], '')
    const queryConfig = _.get(queries, ['0', 'queryConfig'], false)

    if (label || !queryConfig) {
      return label
    }

    return buildDefaultYLabel(queryConfig)
  }

  handleLegendRef = el => (this.legendRef = el)

  resize = () => {
    this.dygraph.resizeElements_()
    this.dygraph.predraw_()
  }

  formatTimeRange = timeRange => {
    if (!timeRange) {
      return ''
    }

    return moment(timeRange).utc().format()
  }

  deselectCrosshair = () => {
    const plugins = this.dygraph.plugins_
    const crosshair = plugins.find(
      ({plugin}) => plugin.toString() === 'Crosshair Plugin'
    )

    if (!crosshair || this.props.isBarGraph) {
      return
    }

    crosshair.plugin.deselect()
  }

  unhighlightCallback = e => {
    const {top, bottom, left, right} = this.legendRef.getBoundingClientRect()

    const mouseY = e.clientY
    const mouseX = e.clientX

    const mouseBuffer = 5
    const mouseInLegendY = mouseY <= bottom && mouseY >= top - mouseBuffer
    const mouseInLegendX = mouseX <= right && mouseX >= left
    const isMouseHoveringLegend = mouseInLegendY && mouseInLegendX

    if (!isMouseHoveringLegend) {
      this.setState({isHidden: true})

      if (!this.visibility().find(bool => bool === true)) {
        this.setState({filterText: ''})
      }
    }
  }

  highlightCallback = e => {
    // Move the Legend on hover
    const graphRect = this.graphRef.getBoundingClientRect()
    const legendRect = this.legendRef.getBoundingClientRect()

    const graphWidth = graphRect.width + 32 // Factoring in padding from parent
    const graphHeight = graphRect.height
    const graphBottom = graphRect.bottom
    const legendWidth = legendRect.width
    const legendHeight = legendRect.height
    const screenHeight = window.innerHeight
    const legendMaxLeft = graphWidth - legendWidth / 2
    const trueGraphX = e.pageX - graphRect.left

    let legendLeft = trueGraphX

    // Enforcing max & min legend offsets
    if (trueGraphX < legendWidth / 2) {
      legendLeft = legendWidth / 2
    } else if (trueGraphX > legendMaxLeft) {
      legendLeft = legendMaxLeft
    }

    // Disallow screen overflow of legend
    const isLegendBottomClipped = graphBottom + legendHeight > screenHeight

    const legendTop = isLegendBottomClipped
      ? graphHeight + 8 - legendHeight
      : graphHeight + 8

    this.legendRef.style.left = `${legendLeft}px`
    this.legendRef.style.top = `${legendTop}px`

    this.setState({isHidden: false})
  }

  legendFormatter = legend => {
    if (!legend.x) {
      return ''
    }

    const {state: {legend: prevLegend}} = this
    const highlighted = legend.series.find(s => s.isHighlighted)
    const prevHighlighted = prevLegend.series.find(s => s.isHighlighted)

    const yVal = highlighted && highlighted.y
    const prevY = prevHighlighted && prevHighlighted.y

    if (legend.x === prevLegend.x && yVal === prevY) {
      return ''
    }

    this.setState({legend})
    return ''
  }

  render() {
    const {
      legend,
      filterText,
      isAscending,
      sortType,
      isHidden,
      isSnipped,
      isFilterVisible,
    } = this.state

    return (
      <div className="dygraph-child" onMouseLeave={this.deselectCrosshair}>
        <DygraphLegend
          {...legend}
          sortType={sortType}
          onHide={this.handleHideLegend}
          isHidden={isHidden}
          isFilterVisible={isFilterVisible}
          isSnipped={isSnipped}
          filterText={filterText}
          isAscending={isAscending}
          onSnip={this.handleSnipLabel}
          onSort={this.handleSortLegend}
          legendRef={this.handleLegendRef}
          onToggleFilter={this.handleToggleFilter}
          onInputChange={this.handleLegendInputChange}
        />
        <div
          ref={r => {
            this.graphRef = r
            this.props.dygraphRef(r)
          }}
          className="dygraph-child-container"
          style={this.props.containerStyle}
        />
      </div>
    )
  }
}

const {array, arrayOf, bool, func, shape, string} = PropTypes

Dygraph.defaultProps = {
  axes: {
    y: {
      bounds: [null, null],
      prefix: '',
      suffix: '',
      base: BASE_10,
      scale: LINEAR,
    },
    y2: {
      bounds: undefined,
      prefix: '',
      suffix: '',
    },
  },
  containerStyle: {},
  isGraphFilled: true,
  overrideLineColors: null,
  dygraphRef: () => {},
  onZoom: () => {},
}

Dygraph.propTypes = {
  axes: shape({
    y: shape({
      bounds: array,
    }),
    y2: shape({
      bounds: array,
    }),
  }),
  queries: arrayOf(shape),
  timeSeries: array.isRequired,
  labels: array.isRequired,
  options: shape({}),
  containerStyle: shape({}),
  isGraphFilled: bool,
  isBarGraph: bool,
  overrideLineColors: array,
  dygraphSeries: shape({}).isRequired,
  ruleValues: shape({
    operator: string,
    value: string,
    rangeValue: string,
  }),
  timeRange: shape({
    lower: string.isRequired,
  }),
  synchronizer: func,
  setResolution: func,
  dygraphRef: func,
  onZoom: func,
}
<|endoftext|>


<commit_before>var gulp = require('gulp');
var gutil = require('gulp-util');
var bower = require('bower');
var concat = require('gulp-concat');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var sh = require('shelljs');
var pug = require('gulp-pug');
var path = require('path');
var cache = require('gulp-cached');

var paths = {
  sass: ['./scss/**/*.scss'],
  pug: ['./pug/**/*.pug']
};

//sends compiled pug file to correct directory
function pugDestination(file) {
  var dest = path.basename(file.path).replace('.html', '/');

  if (file.path.match(/templates\//) !== null) {
    file.path = file.path.replace('templates/', '');
    return './www/components/' + dest;
  } else {
    return './www/'
  }
}

gulp.task('default', ['sass', 'pug']);

gulp.task('sass', function(done) {
  gulp.src('./scss/ionic.app.scss')
    .pipe(cache('sass-cache'))
    .pipe(sass())
    .on('error', sass.logError)
    .pipe(gulp.dest('./www/assets/css/'))
    .pipe(minifyCss({
      keepSpecialComments: 0
    }))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(gulp.dest('./www/assets/css/'))
    .on('end', done);
});

gulp.task('pug', function(done) {
  gulp.src('./pug/**/*.pug')
    .pipe(cache('pug-cache'))
    .pipe(pug({ pretty: true }))
    .pipe(gulp.dest(pugDestination))
    .on('end', done);
});

gulp.task('watch', function() {
  gulp.watch(paths.sass, ['sass']);
  gulp.watch(paths.pug, ['pug']);
});

gulp.task('install', ['git-check'], function() {
  return bower.commands.install()
    .on('log', function(data) {
      gutil.log('bower', gutil.colors.cyan(data.id), data.message);
    });
});

gulp.task('git-check', function(done) {
  if (!sh.which('git')) {
    console.log(
      '  ' + gutil.colors.red('Git is not installed.'),
      '\n  Git, the version control system, is required to download Ionic.',
      '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
      '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
    );
    process.exit(1);
  }
  done();
});
<commit_msg>modily gulpfile to place compiled modal templates in correct component folder<commit_after>var gulp = require('gulp');
var gutil = require('gulp-util');
var bower = require('bower');
var concat = require('gulp-concat');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var sh = require('shelljs');
var pug = require('gulp-pug');
var path = require('path');
var cache = require('gulp-cached');

var paths = {
  sass: ['./scss/**/*.scss'],
  pug: ['./pug/**/*.pug']
};

//sends compiled pug file to correct directory
function pugDestination(file) {
  var dest = path.basename(file.path).replace(/\..*html/, '/');

  if (file.path.search('templates') !== -1) {
    file.path = file.path.replace('templates/', '');
    return './www/components/' + dest;
  }
  return './www/';
}

gulp.task('default', ['sass', 'pug']);

gulp.task('sass', function(done) {
  gulp.src('./scss/ionic.app.scss')
    .pipe(cache('sass-cache'))
    .pipe(sass())
    .on('error', sass.logError)
    .pipe(gulp.dest('./www/assets/css/'))
    .pipe(minifyCss({
      keepSpecialComments: 0
    }))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(gulp.dest('./www/assets/css/'))
    .on('end', done);
});

gulp.task('pug', function(done) {
  gulp.src('./pug/**/*.pug')
    .pipe(cache('pug-cache'))
    .pipe(pug({ pretty: true }))
    .pipe(gulp.dest(pugDestination))
    .on('end', done);
});

gulp.task('watch', function() {
  gulp.watch(paths.sass, ['sass']);
  gulp.watch(paths.pug, ['pug']);
});

gulp.task('install', ['git-check'], function() {
  return bower.commands.install()
    .on('log', function(data) {
      gutil.log('bower', gutil.colors.cyan(data.id), data.message);
    });
});

gulp.task('git-check', function(done) {
  if (!sh.which('git')) {
    console.log(
      '  ' + gutil.colors.red('Git is not installed.'),
      '\n  Git, the version control system, is required to download Ionic.',
      '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
      '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
    );
    process.exit(1);
  }
  done();
});
<|endoftext|>


<commit_before>/**
 * Show the request user has made in the last times (month or 21 days)
 *
 * It just prints the requests data as a simple chart.
 * It needs the data as an Array to work.
 *
 * Usage example:
 *
 *    // D3 API Requests
 *    this.stats = this.stats = new cdb.admin.D3Stats({
 *      el: this.$el.find("li:eq(2)"),
 *      api_calls: this.model.attributes.api_calls
 *    });
 */

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

  tagName: 'div',
  className: 'stats',

  initialize: function() {
    // Get data
    this.requests = this.options.api_calls || [1, 4, 10, 20, 5, 2, 4, 5];

    // Render graphic!
    this.render();
  },

  render: function() {

    // SVG
    var width = 291
      , height = 33
      , svg = d3.select(this.$el.find("div.stats")[0])
                .append("svg")
                .attr("width",width)
                .attr("height",height + 3)
      , max = _.max(_(this.requests).map(function(m){ return parseInt(m, 10) }));

    // Get scales and create the line
    var x = d3.scale.linear().domain([0, this.requests.length]).range([0, width])
      , y = d3.scale.linear().domain([0,max]).range([height,2])
      , line = d3.svg.line()
                .x(function(d,i) { return x(i); })
                .y(function(d) { return y(d); })
      , area = d3.svg.area()
                .x(function(d,i) { return x(i); })
                .y0(function(d) { return height + 3; })
                .y1(function(d) { return y(d); });

      // display the line by appending an svg:path element with the data line we created above
      svg.append("svg:path")
        .attr("d", area(this.requests))
        .style("fill", "#ECF5FA")

      svg.append("svg:path")
        .attr("d", line(this.requests))
        .style("fill", "none")
        .style("stroke-width", "2")
        .style("stroke", "#409FCE")

    // Put total api calls
    this.$el.find("p").html(
      "" + _.reduce(this.requests, function(memo, num){ return memo + num; }, 0) + " map views the last " + _.size(this.requests) + " days"
    )

    return this;
  }

});
<commit_msg>Sets stats to zero<commit_after>/**
 * Show the request user has made in the last times (month or 21 days)
 *
 * It just prints the requests data as a simple chart.
 * It needs the data as an Array to work.
 *
 * Usage example:
 *
 *    // D3 API Requests
 *    this.stats = this.stats = new cdb.admin.D3Stats({
 *      el: this.$el.find("li:eq(2)"),
 *      api_calls: this.model.attributes.api_calls
 *    });
 */

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

  tagName: 'div',
  className: 'stats',

  initialize: function() {
    // Get data
    this.requests = this.options.api_calls || [];

    // Render graphic!
    this.render();
  },

  render: function() {

    // SVG
    var width = 291
      , height = 33
      , svg = d3.select(this.$el.find("div.stats")[0])
                .append("svg")
                .attr("width",width)
                .attr("height",height + 3)
      , max = _.max(_(this.requests).map(function(m){ return parseInt(m, 10) }));

    // Get scales and create the line
    var x = d3.scale.linear().domain([0, this.requests.length]).range([0, width])
      , y = d3.scale.linear().domain([0,max]).range([height,2])
      , line = d3.svg.line()
                .x(function(d,i) { return x(i); })
                .y(function(d) { return y(d); })
      , area = d3.svg.area()
                .x(function(d,i) { return x(i); })
                .y0(function(d) { return height + 3; })
                .y1(function(d) { return y(d); });

      // display the line by appending an svg:path element with the data line we created above
      svg.append("svg:path")
        .attr("d", area(this.requests))
        .style("fill", "#ECF5FA")

      svg.append("svg:path")
        .attr("d", line(this.requests))
        .style("fill", "none")
        .style("stroke-width", "2")
        .style("stroke", "#409FCE")

    // Put total api calls
    this.$el.find("p").html(
      "" + _.reduce(this.requests, function(memo, num){ return memo + num; }, 0) + " map views the last " + _.size(this.requests) + " days"
    )

    return this;
  }

});
<|endoftext|>