(function($) {
  $.widget('pageflow.hiddenTextIndicator', {
    _create: function() {
      var parent = this.options.parent,
          that = this;

      parent.on('pageactivate', function(event) {
        that.element.toggleClass('invert', $(event.target).hasClass('invert'));
        that.element.toggleClass('hidden',
                                 $(event.target).hasClass('hide_content_with_text') ||
                                 $(event.target).hasClass('no_hidden_text_indicator'));
      });

      parent.on('hidetextactivate', function() {
        that.element.addClass('visible');
      });

      parent.on('hidetextdeactivate', function() {
        that.element.removeClass('visible');
      });
    }
  });
}(jQuery));

(function($) {
  $.widget('pageflow.hiddenTextIndicator', {
    _create: function() {
      var parent = this.options.parent,
          that = this;

      parent.on('pageactivate', function(event) {
        var pageOrPageWrapper = $(event.target).add('.content_and_background', event.target);

        that.element.toggleClass('invert', $(event.target).hasClass('invert'));
        that.element.toggleClass('hidden',
                                 pageOrPageWrapper.hasClass('hide_content_with_text') ||
                                 pageOrPageWrapper.hasClass('no_hidden_text_indicator'));
      });

      parent.on('hidetextactivate', function() {
        that.element.addClass('visible');
      });

      parent.on('hidetextdeactivate', function() {
        that.element.removeClass('visible');
      });
    }
  });
}(jQuery));

Allow setting hide text related css classes on wrapper


var MidiInput = function() {
  this.init = function(visualizer) {
    this.visualizer = visualizer;

    if (navigator.requestMIDIAccess) {
        navigator.requestMIDIAccess().then(onMidiSuccess, onMidiReject);
    } else {
      console.log('No MIDI support: navigator.requestMIDIAccess is not defined');
    }
  };

  function onMidiReject(err) {
    console.log('MIDI init error: ' + err);
  }

  function onMidiSuccess(midi) {
    console.log('MIDI init ok!');
  }
};

var MidiInput = function() {
  this.init = function(visualizer) {
    this.visualizer = visualizer;

    if (navigator.requestMIDIAccess) {
        navigator.requestMIDIAccess().then(onMidiSuccess.bind(this), onMidiReject);
    } else {
      console.log('No MIDI support: navigator.requestMIDIAccess is not defined');
    }
  };

  function onMidiReject(err) {
    console.log('MIDI init error: ' + err);
  }

  function onMidiSuccess(midi) {
    if (midi.inputs.size > 0) {
      // Get first MIDI device
      var input = midi.inputs.values().next().value;
      console.log('MIDI device found: ' + input.name);

      // Set MIDI message handler
      input.onmidimessage = messageHandler.bind(this);
    } else {
      console.log('No MIDI input devices available');
    }
  }

  function messageHandler(event) {
    var data = {
      status: event.data[0] & 0xf0,
      data: [
        event.data[1],
        event.data[2]
      ]
    };

    handleInput(data);
  }

  function handleInput(data) {
    // Note on event
    if (data.status === 144) {
      var note = data.data[0];
      var velocity = data.data[1];
      console.log('Note on: ' + note + ', ' + velocity);

    // Control change event
    } else if (data.status === 176) {
      var index = data.data[0];
      var value = data.data[1];
      console.log('Control change: ' + index + ', ' + value);
    }
  }
};

Read note on and control change events from MIDI input


import { uploadValidationActive } from 'preprint-service/helpers/upload-validation-active';
import { module, test } from 'qunit';

module('Unit | Helper | upload validation active');

// Replace this with your real tests.
test('it works', function(assert) {
    var editMode = true;
    var nodeLocked = true;
    var hasOpened = true;
    let result = uploadValidationActive([editMode, nodeLocked, hasOpened]);
    assert.ok(result);
});

import { uploadValidationActive } from 'preprint-service/helpers/upload-validation-active';
import { module, test } from 'qunit';

module('Unit | Helper | upload validation active');

test('edit mode upload validation active', function(assert) {
    var editMode = true;
    var nodeLocked = true;
    var hasOpened = true;
    let result = uploadValidationActive([editMode, nodeLocked, hasOpened]);
    assert.equal(result, true);
});

test('edit mode upload validation not active', function(assert) {
    var editMode = true;
    var nodeLocked = false;
    var hasOpened = true;
    let result = uploadValidationActive([editMode, nodeLocked, hasOpened]);
    assert.equal(result, false);
});

test('add mode upload validation active', function(assert) {
    var editMode = false;
    var nodeLocked = true;
    var hasOpened = true;
    let result = uploadValidationActive([editMode, nodeLocked, hasOpened]);
    assert.equal(result, true);
});

test('add mode upload validation not active', function(assert) {
    var editMode = false;
    var nodeLocked = false;
    var hasOpened = true;
    let result = uploadValidationActive([editMode, nodeLocked, hasOpened]);
    assert.equal(result, false);
});

Add tests for upload-validation-active helper.


$(function() {
  $('body').on('click', '[data-apos-search-filter]', function() {
    $(this).closest('form').submit();
  });
  $('body').on('keyup', '[data-apos-search-field]').keyup(function (e) {
    if (e.keyCode == 13) {
      $(this).closest('form').submit();
      return false;
    }
  });
});

$(function() {
  $('body').on('click', '[data-apos-search-filter]', function() {
    $(this).closest('form').submit();
  });
  $('body').on('keyup', '[data-apos-search-field]', function (e) {
    if (e.keyCode == 13) {
      $(this).closest('form').submit();
      return false;
    }
  });
});

Fix typo on a keyup handler that was causing chrome to throw errors on every key press


/**
 * Script for AutoTabber
 * Handles Tab Keypress
 * @author MarcosBL <soy@marcosbl.com>
*/

/* DOKUWIKI:include taboverride.js */
/* DOKUWIKI:include taboverride.escape.js */

jQuery(window).load(function(){
        var textareas = document.getElementsByTagName('textarea');
        tabOverride.set(textareas).tabSize(0).autoIndent(true).escape(true);
});

/**
 * Script for AutoTabber
 * Handles Tab Keypress
 * @author MarcosBL <soy@marcosbl.com>
*/

/* DOKUWIKI:include taboverride.js */
/* DOKUWIKI:include taboverride.escape.js */

jQuery(window).on('load', function(){
        var textareas = document.getElementsByTagName('textarea');
        tabOverride.set(textareas).tabSize(0).autoIndent(true).escape(true);
});

Fix exception for 'load' on jQuery 1.8 and above


(function() {
  // Resolves string keys with dots in a deeply nested object
  // http://stackoverflow.com/a/22129960/4405214
  var resolveObject = function(path, obj) {
    return path
      .split('.')
      .reduce(function(prev, curr) {
        return prev && prev[curr];
      }, obj || self);
  }

  Spree.t = function(key, options) {
    options = (options || {});
    if(options.scope) {
      key = options.scope + "." + key;
    }
    var translation = resolveObject(key, Spree.translations);
    if (translation) {
      return translation;
    } else {
      console.error("No translation found for " + key + ".");
      return key;
    }
  }

  Spree.human_attribute_name = function(model, attr) {
    return Spree.t("activerecord.attributes." + model + '.' + attr);
  }
})();

(function() {
  // Resolves string keys with dots in a deeply nested object
  // http://stackoverflow.com/a/22129960/4405214
  var resolveObject = function(path, obj) {
    return path
      .split('.')
      .reduce(function(prev, curr) {
        return prev && prev[curr];
      }, obj || self);
  }

  Spree.t = function(key, options) {
    options = (options || {});
    if(options.scope) {
      key = options.scope + "." + key;
    }
    var translation = resolveObject(key, Spree.translations);
    if (translation) {
      return translation;
    } else {
      console.warn("No translation found for " + key + ".");
      return key;
    }
  }

  Spree.human_attribute_name = function(model, attr) {
    return Spree.t("activerecord.attributes." + model + '.' + attr);
  }
})();

Use console.warn instead of console.error


export function changeLocation(location) {
  return {
    type: 'CHANGE_LOCATION',
    location
  };
}

export function changeUnitType(unitType) {
  return {
    type: 'CHANGE_UNIT_TYPE',
    unitType
  };
}

export function setAlert({type, message}) {
  return {
    type: 'SET_ALERT',
    alert: {
      type,
      message
    }
  };
}

export function setTooltip({x, y, contentElement, originTarget, title}) {
  return {
    type: 'SET_TOOLTIP',
    tooltip: {
      x,
      y,
      contentElement,
      originTarget,
      title
    }
  };
}

export function hideTooltip() {
  return {
    type: 'SET_TOOLTIP',
    tooltip: {}
  };
}

export function changeLocation(location) {
  return {
    type: 'CHANGE_LOCATION',
    location
  };
}

export function changeUnitType(unitType) {
  return {
    type: 'CHANGE_UNIT_TYPE',
    unitType
  };
}

export function setAlert({type, message}) {
  return {
    type: 'SET_ALERT',
    alert: {
      type,
      message
    }
  };
}

export function hideAlert() {
  return {
    type: 'SET_ALERT',
    alert: {}
  };
}

export function setTooltip({x, y, contentElement, originTarget, title}) {
  return {
    type: 'SET_TOOLTIP',
    tooltip: {
      x,
      y,
      contentElement,
      originTarget,
      title
    }
  };
}

export function hideTooltip() {
  return {
    type: 'SET_TOOLTIP',
    tooltip: {}
  };
}

Add hide alert action creator


/** @babel */

import etch from 'etch'

import {CompositeDisposable} from 'atom'

export default class AbstractComponent {
  constructor(properties, children, callback) {
    if (properties) this.properties = properties
    else this.properties = {}
    if (children) this.children = children
    else this.children = []

    this.disposables = new CompositeDisposable()
    if (callback) callback(this.properties, this.children)
    etch.initialize(this)
  }

  update(properties, children, callback) {
    if (properties && this.properties !== properties) this.properties = properties
    if (children && this.children !== children) this.children = children
    if (callback) callback(this.properties, this.children)
    return etch.update(this)
  }

  destroy(callback) {
    this.disposables.dispose()
    if (callback) callback()
    return etch.destroy(this)
  }
}

/** @babel */

import etch from 'etch'

import {Emitter, CompositeDisposable} from 'atom'

export default class AbstractComponent {
  constructor(properties, children, callback) {
    if (properties) this.properties = properties
    else this.properties = {}
    if (children) this.children = children
    else this.children = []

    this.disposables = new CompositeDisposable()
    this.emitter = new Emitter()
    if (callback) callback(this.properties, this.children)
    etch.initialize(this)
  }

  update(properties, children, callback) {
    if (properties && this.properties !== properties) this.properties = properties
    if (children && this.children !== children) this.children = children
    if (callback) callback(this.properties, this.children)
    return etch.update(this)
  }

  destroy(callback) {
    this.disposables.dispose()
    this.emitter.dispose()
    if (callback) callback()
    return etch.destroy(this)
  }
}

Add an emitter to AbstractComponent


#!/usr/bin/env node

/*!
 * BALLZ repl module
 *
 * @author pfleidi
 */

var Readline = require('readline');
var Util = require('util');

var Parser = require('../lib/parser');
var Environment = require('../lib/environment');
var interpreter = require('../lib/interpreter').createInterpreter(
  Environment.createEnvironment()
);

var repl = Readline.createInterface(process.stdin, process.stdout);

function exec(cmd) {
  var ast = Parser.parse(cmd);
  return Util.inspect(interpreter.eval(ast));
}

repl.setPrompt('ballz >');

repl.on('line', function (cmd) {
    try {
      console.log('==> ' + exec(cmd));
    } catch (e) {
      console.log(e.message);
      console.log(e.stack);
    }
    repl.prompt();
  });

repl.on('SIGINT', function () {
    repl.close();
  });

repl.on('close', function () {
    console.log('goodbye!');
    process.exit(0);
  });

repl.prompt();

#!/usr/bin/env node

/*!
 * BALLZ repl module
 *
 * @author pfleidi
 */

var Readline = require('readline');
var Eyes = require('eyes');

var Parser = require('../lib/parser');
var Environment = require('../lib/environment');
var interpreter = require('../lib/interpreter').createInterpreter(
  Environment.createEnvironment()
);

var repl = Readline.createInterface(process.stdin, process.stdout);

function exec(cmd) {
  var ast = Parser.parse(cmd);
  return Eyes.inspect(interpreter.eval(ast));
}

repl.setPrompt('ballz >');

repl.on('line', function (cmd) {
    try {
      console.log('==> ' + exec(cmd));
    } catch (e) {
      console.log(e.message);
      console.log(e.stack);
    }
    repl.prompt();
  });

repl.on('SIGINT', function () {
    repl.close();
  });

repl.on('close', function () {
    console.log('goodbye!');
    process.exit(0);
  });

repl.prompt();

Add colored output to repl


var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);

var expect = chai.expect;

module.exports = function() {

    disclaimer = element(by.css('div.disclaimer'));

    this.Given(/^that I am at the HMDA homepage$/, function(next) {
        browser.get('http://dev.hmda-pilot.ec2.devis.com/#/');
        //Prevents 'are you sure you want to leave?' window from popping up
        browser.executeScript('window.onbeforeunload = function(){};').then(function(){
            next();
        });
    });

    this.Then(/^I will see a disclaimer at the top$/, function (next) {
        expect(disclaimer.isPresent()).to.eventually.be.true.notify(next);
    });
};

var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);

var expect = chai.expect;

module.exports = function() {

    disclaimer = element(by.css('div.disclaimer'));

    this.Given(/^that I am at the HMDA homepage$/, function(next) {
        passwordBox = element.all(by.id('txt-pwd'));
        loginButton = element.all(by.css('.login-button'))

        browser.get('http://dev.hmda-pilot.ec2.devis.com/#/');

        //Prevents 'are you sure you want to leave?' window from popping up
        browser.executeScript('window.onbeforeunload = function(){};').then(function(){
            if(passwordBox.count() !== 0){
                //Log in if we have not already done so
                passwordBox.sendKeys('p1l0t');
                loginButton.click();
            }
        });
            next();
    });

    this.Then(/^I will see a disclaimer at the top$/, function (next) {
        expect(disclaimer.isPresent()).to.eventually.be.true.notify(next);
    });
};

Set up tests to log in on first getting to the site


Space.Object.extend('Todos.LayoutController', {

  mixin: [
    Space.messaging.EventSubscribing
  ],

  dependencies: {
    layout: 'Layout',
    _: 'underscore'
  },

  Constructor() {
    this._currentLayout = null;
    this._currentSections = {};
  },

  eventSubscriptions() {
    return [{
      'Todos.RouteTriggered': function(event) {
        switch (event.routeName) {
        //case 'routeName': this._routeHanlder(); break;
        default: this._renderIndexPage();
        }
      }
    }];
  },

  _renderIndexPage() {
    this._render('index', {
      input: 'input',
      todo_list: 'todo_list',
      footer: 'footer'
    });
  },

  _render(layout, sections) {
    this._currentLayout = layout;
    this._.extend(this._currentSections, sections);
    this.layout.render(this._currentLayout, this._currentSections);
  },

  _updateSections(sections) {
    this._render(this._currentLayout, sections);
  }

});

Space.Object.extend('Todos.LayoutController', {

  mixin: [
    Space.messaging.EventSubscribing
  ],

  dependencies: {
    layout: 'Layout',
    _: 'underscore'
  },

  _currentLayout: null,

  _currentSections: {},

  eventSubscriptions() {
    return [{
      'Todos.RouteTriggered': function(event) {
        switch (event.routeName) {
        //case 'routeName': this._routeHanlder(); break;
        default: this._renderIndexPage();
        }
      }
    }];
  },

  _renderIndexPage() {
    this._render('index', {
      input: 'input',
      todo_list: 'todo_list',
      footer: 'footer'
    });
  },

  _render(layout, sections) {
    this._currentLayout = layout;
    this._.extend(this._currentSections, sections);
    this.layout.render(this._currentLayout, this._currentSections);
  },

  _updateSections(sections) {
    this._render(this._currentLayout, sections);
  }

});

Refactor layout controllers layout attributes to static members


(function () {

    // Set to true to show console.log for debugging
    var DEBUG_MODE = true;

    'use strict';

    var Slide = function (title) {

        // Constructor
        this.title = title;
        this.eleRef = null;

    };

    Slide.prototype.SetReference = function (dom) {
        this.eleRef = dom;
    };

    Slide.prototype.MoveLeft = function () {};
    Slide.prototype.MoveRight = function () {};
    Slide.prototype.TransitionLeft = function () {};
    Slide.prototype.TransitionRight = function () {};

    /////////////////
    /// APP START ///
    /////////////////

    var slides = [];
    var currentSlideIdx = 0;

    /**
     * Initialize App
     */
    function Initialize() {

        GetSlides();

    }

    /**
     * Get slide DOM reference
     */
    function GetSlides() {

        var slidesDOM = document.getElementsByClassName('slide');

        setTimeout(function () {

            for (var i = 0, limit = slidesDOM.length; i < limit; ++i) {

                var newSlide = new Slide(slidesDOM[i].dataset.title);
                    newSlide.SetReference(slidesDOM[i]);

                slides.push(newSlide);

            }

        }, 0);

    }

    Initialize();

}());

(function () {

    // Set to true to show console.log for debugging
    var DEBUG_MODE = true;

    'use strict';

    var Slide = function (title) {

        // Constructor
        this.title = title;
        this.eleRef = null;

    };

    Slide.prototype.SetReference = function (dom) {
        this.eleRef = dom;
    };

    Slide.prototype.MoveLeft = function () {};
    Slide.prototype.MoveRight = function () {};
    Slide.prototype.TransitionLeft = function () {};
    Slide.prototype.TransitionRight = function () {};

    /////////////////
    /// APP START ///
    /////////////////

    var slides = [];
    var currentSlideIdx = 0;

    /**
     * Initialize App
     */
    function Initialize() {

        GetSlides();

    }

    /**
     * Get slide DOM reference
     */
    function GetSlides() {

        var slidesDOM = document.getElementsByClassName('slide');

        setTimeout(function () {

            for (var i = 0, limit = slidesDOM.length; i < limit; ++i) {

                // Set z-index for each slide
                slidesDOM[i].style.zIndex = 10 + i;

                var newSlide = new Slide(slidesDOM[i].dataset.title);
                    newSlide.SetReference(slidesDOM[i]);

                slides.push(newSlide);

            }

        }, 0);

    }

    Initialize();

}());

Set each slide to have it's own z-index.


import { withName } from './shared';
import { FEATURES } from 'data/columns';

export default function isEnterprise(modules) {
  const serverModule = modules.find(withName('SERVER'));

  const hasFeatures = /[CDEFSW]/.test(serverModule[FEATURES]);
  const hasModules = ['WSINPUT', 'WSOUTPUT', 'ECOPY'].some(name => (
    modules.some(withName(name))
  ));

  return hasFeatures || hasModules;
}

import { withName } from './shared';

export default function isEnterprise(modules) {
  const hasModules = ['WSINPUT', 'WSOUTPUT', 'ECOPY'].some(name => (
    modules.some(withName(name))
  ));

  return hasModules;
}

Stop checking server features to determine enterprise vs. standard


export default class Vector2 {

    constructor(x = 0, y = 0) {
        this.x = x;
        this.y = y;
    }

    set(x, y) {
        this.x = x;
        this.y = y;
        return this;
    }

    add(vec2) {
        this.x = vec2.x;
        this.y = vec2.y;
        return this;
    }

    subtract(vec2) {
        this.x -= vec2.x;
        this.y -= vec2.y;
        return this;
    }

    multiply(vec2) {
        this.x *= vec2.x;
        this.y *= vec2.y;
        return this;
    }

    divide(vec2) {
        this.x /= vec2.x;
        this.y /= vec2.y;
        return this;
    }

    angle(vec2) {
        return Math.atan2(vec2.y - this.y, vec2.x - this.x);
    }

    distance(vec2) {
        return Math.sqrt(Math.pow(vec2.x - this.x, 2) + Math.pow(vec2.y - this.y, 2));
    }

    distanceSq(vec2) {
        return Math.pow(vec2.x - this.x, 2) + Math.pow(vec2.y - this.y, 2);
    }

    clone() {
        return new Vector2(this.x, this.y);
    }

}

export default class Vector2 {

    constructor(x = 0, y = 0) {
        this.x = x;
        this.y = y;
    }

    set(x, y) {
        this.x = x;
        this.y = y;
        return this;
    }

    add(vec2) {
        this.x = vec2.x;
        this.y = vec2.y;
        return this;
    }

    subtract(vec2) {
        this.x -= vec2.x;
        this.y -= vec2.y;
        return this;
    }

    multiplyVector(vec2) {
        this.x *= vec2.x;
        this.y *= vec2.y;
        return this;
    }

    multiplyScalar(scalar) {
        this.x *= scalar;
        this.y *= scalar;
        return this;
    }

    divideVector(vec2) {
        this.x /= vec2.x;
        this.y /= vec2.y;
        return this;
    }

    divideScalar(scalar) {
        this.x /= scalar;
        this.y /= scalar;
        return this;
    }

    angle(vec2) {
        return Math.atan2(vec2.y - this.y, vec2.x - this.x);
    }

    distance(vec2) {
        return Math.sqrt(Math.pow(vec2.x - this.x, 2) + Math.pow(vec2.y - this.y, 2));
    }

    distanceSq(vec2) {
        return Math.pow(vec2.x - this.x, 2) + Math.pow(vec2.y - this.y, 2);
    }

    clone() {
        return new Vector2(this.x, this.y);
    }

}

Implement scalar/vector multiply and divide


import React from 'react';
import classnames from 'classnames';
import { GridContainer, GridRow, GridCol } from '../Grid';

const Nav = props => (
  <div
    className={classnames('ui-nav', {
      'ui-nav-fixed': props.fixed,
      'ui-nav-inverse': props.inverse,
    })}
  >
    <GridContainer fluid>
      <GridRow>
        <GridCol>
          <div className={classnames('ui-nav-navitems')}>
            {props.children}
          </div>
        </GridCol>
      </GridRow>
    </GridContainer>
  </div>
);

Nav.propTypes = {
  fixed: React.PropTypes.bool.isRequired,
  inverse: React.PropTypes.bool.isRequired,
  children: React.PropTypes.node,
};

Nav.defaultProps = {
  fixed: false,
  inverse: false,
};

export default Nav;

import React from 'react';
import classnames from 'classnames';

function Nav({ inverse, children, fixed, prefix }) {
  const className = classnames('ui-nav', {
    'ui-nav-fixed': fixed,
    'ui-nav-inverse': inverse,
  });

  return (

      {prefix &&
{prefix}
}

        {children}

  );
}

Nav.propTypes = {
  fixed: React.PropTypes.bool.isRequired,
  inverse: React.PropTypes.bool.isRequired,
  children: React.PropTypes.node,
  prefix: React.PropTypes.node,
};

Nav.defaultProps = {
  fixed: false,
  inverse: false,
  prefix: null,
  children: null,
};

export default Nav;

Enhance nav component and introduce prefix prop


var express = require('express');
var app = express();

var config = require('./config');
var bodyParser = require('body-parser');
var morgan = require('morgan')
var mongoose   = require('mongoose');

var Recording = require('./models/measurement');
var Station = require('./models/station');

var measurements = require('./routes/measurements');
var stations = require('./routes/stations');

mongoose.connect(config.mongodb.url);

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('combined'))

var router = express.Router();

router.get('/wrm.aspx', measurements.saveMeasurement);
router.get('/measurements', measurements.allMeasurements)

router.get('/stations', stations.findAllStations);
router.get('/stations/:stationId', stations.findOneStation);
router.post('/stations', stations.saveStation);

app.use('', router);

app.listen(3000);
console.log('Listening on port 3000...');

var express = require('express');
var app = express();

var config = require('./config');
var bodyParser = require('body-parser');
var morgan = require('morgan')
var mongoose   = require('mongoose');

var Recording = require('./models/measurement');
var Station = require('./models/station');

var measurements = require('./routes/measurements');
var stations = require('./routes/stations');

mongoose.connect(config.mongodb.url);

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('combined'))

var router = express.Router();

router.get('/wrm.aspx', measurements.saveMeasurement);
router.post('/v2/measurements', measurements.saveMeasurement);
router.get('/v2/measurements', measurements.allMeasurements)

router.get('/v2/stations', stations.findAllStations);
router.get('/v2/stations/:stationId', stations.findOneStation);
router.post('/v2/stations', stations.saveStation);

app.use('', router);

app.listen(8000);
console.log('Listening on port 8000...');

Change URLs so they can live aside eachother.


import React from 'react';
import PropTypes from 'prop-types';
import Example from './Example';
import Props from './Props';

const ComponentPage = ({component}) => {
  const {name, description, props, examples} = component;

  return (

{name}

{description}

Example{examples.length > 1 && "s"}

      {
        examples.length > 0 ?
        examples.map( example => <Example key={example.name} example={example} componentName={name} /> ) :
        "No examples exist."
      }

Props

      {
        props ?
        <Props props={props} /> :
        "This component accepts no props."
      }

  )
};

ComponentPage.propTypes = {
  component: PropTypes.object.isRequired
};

export default ComponentPage;

import React from 'react';
import PropTypes from 'prop-types';
import Example from './Example';
import Props from './Props';

const ComponentPage = ({component}) => {
  const {name, description, props, examples} = component;

  return (

{name}

{description}

Example{examples.length > 1 && "s"}

      {
        examples.length > 0 ?
        examples.map( example => <Example key={example.code} example={example} componentName={name} /> ) :
        "No examples exist."
      }

Props

      {
        props ?
        <Props props={props} /> :
        "This component accepts no props."
      }

  )
};

ComponentPage.propTypes = {
  component: PropTypes.object.isRequired
};

export default ComponentPage;

Switch to a truly unique key


import fetch from 'node-fetch';

import { userModel } from '../models/index';

export const authenticatedWithToken = (req, res, next) => {
  let csrf;
  let jwt;

  if (req && req.cookies && req.headers){
    csrf = req.headers.csrf;
    jwt = req.cookies.jwt;

    const opts = {
      headers: {
        csrf,
        jwt
      }
    };

    fetch('http://localhost:3002/signcheck', opts)
      .then(res => {
        if (res.status === 401) {
          return null;
        }

        return res.json();
      })
      .then(user => {
        if (!user) {
          return next();
        } else {
          return userModel.findOne({name: user.name})
            .then(user => {
              req.user = user;

              return next();
          });
        }
      })
  }
};

import fetch from 'node-fetch';

import { userModel } from '../models/index';

export const authenticatedWithToken = async (req, res, next) => {
  if (req && req.cookies && req.cookies.jwt && req.headers && req.headers.csrf) {
    let csrf = req.headers.csrf;
    let jwt = req.cookies.jwt;

    const opts = {
      headers: {
        csrf,
        jwt
      }
    };

    let res = await fetch('http://localhost:3002/signcheck', opts);

    if (res.status === 401) {
      return null;
    }

    let resJson = await res.json();

    if (!resJson) {
      next();
    } else {
      try {
        let user = await userModel.findOne({name: resJson.name}).exec();

        if (user) {
          req.user = user;
          next();
        }
      } catch (error) {
        console.log(error)
      }
    }
  } else {
    req.err = 'Either the cookie or the token is missing';

    next();
  }
};

Replace promise with async await and handle error cases


var path = require('path'),
    fs = require('fs'),
    crypto = require('crypto');

describe("readFile functionality", function() {
    var _this = this;
    require('./harness.js')(_this);
    it("creates a directory", function(done) {
        var fname = "testDir";
        var resolved = path.resolve(_this.tempdir, fname);
        crypto.pseudoRandomBytes(128 * 1024, function(err, data) {
            if (err) throw err;
            fs.writeFile(resolved, data, function(err) {
                if (err) throw err;
                _this.wd.readFile(fname, function(err, rdata) {
                    expect(err).toBe(null);
                    expect(rdata.toString()).toBe(data.toString());
                    done();
                });
            });
        });
    });
});

var path = require('path'),
    fs = require('fs'),
    crypto = require('crypto');

describe("readFile functionality", function() {
    var _this = this;
    require('./harness.js')(_this);
    it("reads a file", function(done) {
        var fname = "testDir";
        var resolved = path.resolve(_this.tempdir, fname);
        crypto.pseudoRandomBytes(128 * 1024, function(err, data) {
            if (err) throw err;
            fs.writeFile(resolved, data, function(err) {
                if (err) throw err;
                _this.wd.readFile(fname, function(err, rdata) {
                    expect(err).toBe(null);
                    expect(rdata.toString()).toBe(data.toString());
                    done();
                });
            });
        });
    });
});

Fix name of readFile test


// look for groups of matching characters
// pass each group to say() and concatenate returns
var look = function(lookString) {
  var i = 0;
  var j = 1;
  var sayString = '';

  while (i < lookString.length) {
    while (lookString[i] === lookString[j]) {
      j++;
    }
    sayString += say(lookString.slice(i,j));
    i += (j - i);
  }

  return sayString;
}

// convert a group of matching characters to
// the replacement sequence
var say = function(group) {
  var output = 0;
  return '' + group.length + group[0];
}

// run look-and-say on a given input n times and
// print the result's length to the console.
var lookAndSay = function(input, n) {
  var lastString = input;
  for (var i = 0; i < n; i++) {
    lastString = look(lastString);
  }

  console.log(lastString.length);
}

lookAndSay('1321131112', 50);

// Look for groups of matching characters.
// Map the conversion function to each.
// Join & return the new string.
var convert = function(input) {
  var groups = input.match(/(\d)\1*/g);
  return groups.map(s => s.length + s[0]).join('');
}

// run look-and-say on a given input n times and
// print the result's length to the console.
var lookAndSay = function(input, n) {
  var lastString = input;

  while (n) {
    lastString = convert(lastString);
    n--;
  }

  console.log(lastString.length);
}

lookAndSay('1321131112', 50);

Refactor solution to use regex and map


import React, { Component } from 'react';
import { connect } from 'react-redux';
import Snackbar from 'material-ui/Snackbar';
import { red900, grey50 } from 'material-ui/styles/colors';

class ErrorReporting extends Component {

    static defaultProps = {
        open: false,
        action: '',
        error: null,
        autoHideDuration: 10000,
        getMessage: (props) => props.error ? props.action + ': ' + props.error.toString() : '',
        style: {
            backgroundColor: red900,
            color: grey50
        }
    }

    render() {
        return (
            <Snackbar
              open={this.props.open}
              message={this.props.getMessage(this.props)}
              autoHideDuration={this.props.autoHideDuration}
              style={this.props.style}
              contentStyle={this.props.style}
              bodyStyle={this.props.style}
              />
        );
    }
}

function mapStoreToProps(state) {
    const { action, error } = state.errors;
    return {
        open: error !== null,
        action: action,
        error: error
    };
}

export default connect(mapStoreToProps)(ErrorReporting);

import React, { Component } from 'react';
import { connect } from 'react-redux';
import Snackbar from 'material-ui/Snackbar';
import { red900, grey50 } from 'material-ui/styles/colors';

class ErrorReporting extends Component {

    static defaultProps = {
        open: false,
        action: '',
        error: null,
        autoHideDuration: 10000,
        getMessage: (props) => props.error ? props.action + ': ' + props.error.toString() : '',
        style: {
            backgroundColor: red900,
            color: grey50
        },
        contentStyle: {
            display: 'block',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
            overflow: 'hidden'
        }
    }

    exclusiveProps = [
        'getMessage',
        'error',
        'action'
    ]

    getSnackbarProps() {
        return Object
            .keys(this.props)
            .filter(
                (name) => this.exclusiveProps.indexOf(name) === -1
            )
            .reduce(
                (acc, name) => {
                    acc[name] = this.props[name];
                    return acc;
                },
                {}
            );
    }

    render() {
        return (
            <Snackbar
              open={this.props.open}
              message={this.props.getMessage(this.props)}
              autoHideDuration={this.props.autoHideDuration}
              style={this.props.style}
              contentStyle={this.props.style}
              bodyStyle={this.props.style}
              {...this.getSnackbarProps()}
              />
        );
    }
}

function mapStoreToProps(state) {
    const { action, error } = state.errors;
    return {
        open: error !== null,
        action: action,
        error: error
    };
}

export default connect(mapStoreToProps)(ErrorReporting);

Set default contentStyle prop to make message more readable


/**
 * setupSiteKit utility.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { activatePlugin } from '@wordpress/e2e-test-utils';

/**
 * Internal depedencies
 */
import {
	setSiteVerification,
	setSearchConsoleProperty,
} from '.';

export const setupSiteKit = async ( { verified, property } = {} ) => {
	await activatePlugin( 'e2e-tests-auth-plugin' );
	await setSiteVerification( verified );
	await setSearchConsoleProperty( property );
};

/**
 * setupSiteKit utility.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { activatePlugin } from '@wordpress/e2e-test-utils';

/**
 * Internal depedencies
 */
import {
	setSiteVerification,
	setSearchConsoleProperty,
} from '.';

export const setupSiteKit = async ( { verified, property, auth = 'proxy' } = {} ) => {
	if ( auth !== 'proxy' && auth !== 'gcp' ) {
		throw new Error( 'Auth type must be either proxy or gcp' );
	}
	await activatePlugin( `e2e-tests-${ auth }-auth-plugin` );
	await setSiteVerification( verified );
	await setSearchConsoleProperty( property );
};

Update helper to set auth type.


var bridge = function (presenterPath) {
    window.rhubarb.viewBridgeClasses.HtmlViewBridge.apply(this, arguments);
};

bridge.prototype = new window.rhubarb.viewBridgeClasses.HtmlViewBridge();
bridge.prototype.constructor = bridge;

bridge.spawn = function (spawnData, index, parentPresenterPath) {
    var textBox = document.createElement("INPUT");
    textBox.setAttribute("type", spawnData.type);
    textBox.setAttribute("size", spawnData.size);
    if (spawnData.maxLength) {
        textBox.setAttribute("maxlength", spawnData.maxLength);
    }

    window.rhubarb.viewBridgeClasses.HtmlViewBridge.applyStandardAttributesToSpawnedElement(textBox, spawnData, index, parentPresenterPath);

    return textBox;
};

bridge.prototype.onKeyPress = function(event){
    if (this.onKeyPress){
        this.onKeyPress(event);
    }
};

bridge.prototype.attachDomChangeEventHandler = function (triggerChangeEvent) {
    window.rhubarb.viewBridgeClasses.HtmlViewBridge.prototype.attachDomChangeEventHandler.apply(this,arguments);

    var self = this;

    if (!this.viewNode.addEventListener) {
        this.viewNode.attachEvent("onkeypress", self.onKeyPress.bind(self));
    }
    else {
        // Be interested in a changed event if there is one.
        this.viewNode.addEventListener('keypress', self.onKeyPress.bind(self), false);
    }
};

window.rhubarb.viewBridgeClasses.TextBoxViewBridge = bridge;

var bridge = function (presenterPath) {
    window.rhubarb.viewBridgeClasses.HtmlViewBridge.apply(this, arguments);
};

bridge.prototype = new window.rhubarb.viewBridgeClasses.HtmlViewBridge();
bridge.prototype.constructor = bridge;

bridge.spawn = function (spawnData, index, parentPresenterPath) {
    var textBox = document.createElement("INPUT");
    textBox.setAttribute("type", spawnData.type);
    textBox.setAttribute("size", spawnData.size);
    if (spawnData.maxLength) {
        textBox.setAttribute("maxlength", spawnData.maxLength);
    }

    window.rhubarb.viewBridgeClasses.HtmlViewBridge.applyStandardAttributesToSpawnedElement(textBox, spawnData, index, parentPresenterPath);

    return textBox;
};

bridge.prototype.keyPressed = function(event){
    if (this.onKeyPress){
        this.onKeyPress(event);
    }
};

bridge.prototype.attachDomChangeEventHandler = function (triggerChangeEvent) {
    window.rhubarb.viewBridgeClasses.HtmlViewBridge.prototype.attachDomChangeEventHandler.apply(this,arguments);

    var self = this;

    if (!this.viewNode.addEventListener) {
        this.viewNode.attachEvent("onkeypress", self.keyPressed.bind(self));
    }
    else {
        // Be interested in a changed event if there is one.
        this.viewNode.addEventListener('keypress', self.keyPressed.bind(self), false);
    }
};

window.rhubarb.viewBridgeClasses.TextBoxViewBridge = bridge;

Fix for textbox view bridge causing recursion


"use strict";

var config = require("12factor-config");

var appConfig = config({
  apiUrl: {
    env: "AGFAPHD_WEBAPP_API_URL",
    type: "string",
    default: "http://localhost:8089"
  },
  emailApiKey: {
    env: "AGFAPHD_WEBAPP_EMAIL_API_KEY",
    type: "string",
    required: true
  },
  emailApiUrl: {
    env: "AGFAPHD_WEBAPP_EMAIL_API_URL",
    type: "string",
    default: "sandboxa92275a42f30470c860fda4a09140bf6.mailgun.org"
  },
  emailFrom: {
    env: "AGFAPHD_WEBAPP_EMAIL_FROM",
    type: "string",
    default: "Debt Sentry <sentry@agoodfriendalwayspayshisdebts.com>"
  },
  revisionMapPath: {
    env: "AGFAPHD_WEBAPP_REVISION_MAP_PATH",
    type: "string",
    default: "../public/default_map.json"
  },
  serverPort: {
    env: "PORT",
    type: "integer",
    default: 5000
  }
});

module.exports = appConfig;

"use strict";

var config = require("12factor-config");

var appConfig = config({
  apiUrl: {
    env: "AGFAPHD_WEBAPP_API_URL",
    type: "string",
    default: "http://localhost:8089"
  },
  emailApiKey: {
    env: "AGFAPHD_WEBAPP_EMAIL_API_KEY",
    type: "string",
    required: true
  },
  emailApiUrl: {
    env: "AGFAPHD_WEBAPP_EMAIL_API_URL",
    type: "string",
    required: true
  },
  emailFrom: {
    env: "AGFAPHD_WEBAPP_EMAIL_FROM",
    type: "string",
    default: "Debt Sentry <sentry@agoodfriendalwayspayshisdebts.com>"
  },
  revisionMapPath: {
    env: "AGFAPHD_WEBAPP_REVISION_MAP_PATH",
    type: "string",
    default: "../public/default_map.json"
  },
  serverPort: {
    env: "PORT",
    type: "integer",
    default: 5000
  }
});

module.exports = appConfig;

Add email api url requirement


/**!
 *
 * Copyright (c) 2015-2016 Cisco Systems, Inc. See LICENSE file.
 */
import {assert} from '@ciscospark/test-helper-chai';
import Avatar, {config} from '../../';
// import '@ciscospark/test-helper-sinon';
import {MockSpark} from '@ciscospark/test-helper-mock-spark';

describe(`Services`, () => {
  describe(`Avatar`, () => {
    describe(`AvatarUrlBatcher`, () => {
      let batcher;
      let spark;

      beforeEach(() => {
        spark = new MockSpark({
          children: {
            avatar: Avatar
          }
        });

        spark.config.avatar = config.avatar;
        batcher = spark.avatar.batcher;
        console.warn(JSON.stringify(spark, null, `\t`));
      });

      describe(`#fingerprintRequest(item)`, () => {
        it(`returns 'uuid - size'`, () => {
          assert.equal(batcher.fingerprintRequest({uuid: `uuid1`, size: 80}), `uuid1 - 80`);
        });
      });
    });
  });
});

/**!
 *
 * Copyright (c) 2015-2016 Cisco Systems, Inc. See LICENSE file.
 */
import {assert} from '@ciscospark/test-helper-chai';
import Avatar from '../../';
import MockSpark from '@ciscospark/test-helper-mock-spark';

describe(`Services`, () => {
  describe(`Avatar`, () => {
    describe(`AvatarUrlBatcher`, () => {
      let batcher;
      let spark;

      beforeEach(() => {
        spark = new MockSpark({
          children: {
            avatar: Avatar
          }
        });
        console.warn('spark: <' + JSON.stringify(spark) + '>');
        batcher = spark.avatar.batcher;
      });

      describe(`#fingerprintRequest(item)`, () => {
        it(`returns 'uuid - size'`, () => {
          assert.equal(batcher.fingerprintRequest({uuid: `uuid1`, size: 80}), `uuid1 - 80`);
        });
      });
    });
  });
});

Refactor ciscospark Migrate Avatar to packages


Template.HostCreate.events({
  'submit form' : function (event, template) {
    event.preventDefault();

    // Define form field variables.
    var hostname = event.target.hostname.value,
      type = event.target.type.value,
      version = event.target.version.value;

    // Need more validation here.
    if (hostname.length) {

      // Create sort field sequence value.
      var total = Hosts.find().count();
      if (total == 0) {
        var seq = total;
      } else {
        var seq = total++;
      }

      // Insert data into document.
      Hosts.insert({
        hostname: hostname,
        type: type,
        version: version,
        hostCreated: new Date,
        sort: seq
      });
      // Reset form.
      template.find('form').reset();
      Router.go('/');
    }
  }
});

Template.HostCreate.events({
  'submit form' : function (event, template) {
    event.preventDefault();

    // Define form field variables.
    var hostname = event.target.hostname.value,
      type = event.target.type.value,
      version = event.target.version.value;

    // Need more validation here.
    if (hostname.length) {

      // Create sort field sequence value.
      var total = Hosts.find().count();
      if (total == 0) {
        var seq = total;
      } else {
        var seq = total++;
      }

      // Insert data into document.
      Hosts.insert({
        hostname: hostname,
        type: type,
        version: version,
        hostCreated: new Date,
        sort: seq
      });
      // Reset form.
      template.find('form').reset();
      Router.go('home');
    }
  }
});

Use route names instead of paths.


const assert = require('assert');
'use strict';

/**
 * Once middleware will block an event if there is already a scheduled event
 * @param {Event} event the event to check
 * @param {DBWrkr} wrkr wrkr instance to work with
 * @param {function} done callback
 */
function once(event, wrkr, done) {
  assert(typeof event.name === 'string', 'event must be a valid event');

  const findSpec = {
    name: event.name
  };
  if (event.tid) findSpec.tid = event.tid;

  wrkr.find(findSpec, (err, events) => {
    if (err) return done(err);

    // Mark event as Blocked, DBWrkr.publish will not store it
    if (events.length) {
      event.__blocked = true;
    }

    event.when = event.once;
    if (typeof event.when === 'number') {   // ms
      event.when = new Date(Date.now()+event.when);
    }

    delete event.once;
    return done();
  });
}

// Exports
module.exports = {
  once: once
};

'use strict';

/**
 * Once middleware will block an event if there is already a scheduled event
 * @param {Event} event the event to check
 * @param {DBWrkr} wrkr wrkr instance to work with
 * @param {function} done callback
 */
function once(event, wrkr, done) {

  const findSpec = {
    name: event.name
  };
  if (event.tid) findSpec.tid = event.tid;

  wrkr.find(findSpec, (err, events) => {
    if (err) return done(err);

    // Mark event as Blocked, DBWrkr.publish will not store it
    if (events.length) {
      event.__blocked = true;
    }

    event.when = event.once;
    if (typeof event.when === 'number') {   // ms
      event.when = new Date(Date.now()+event.when);
    }

    delete event.once;
    return done();
  });
}

// Exports
module.exports = {
  once: once
};

Remove assert on event.name (handled somewhere else)


(function () {
    function initTwinklingStars() {
        particlesJS('stars', {
            particles: {
                number: {
                    value: 180,
                    density: {
                        enable: true,
                        value_area: 600
                    }
                },
                color: {
                    value: '#ffffff'
                },
                shape: {
                    type: 'circle'
                },
                opacity: {
                    value: 1,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 3,
                        opacity_min: 0
                    }
                },
                size: {
                    value: 1.5,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 1,
                        size_min: 0.5,
                        sync: false
                    }
                },
                line_linked: {
                    enable: false
                },
                move: {
                    enable: true,
                    speed: 50,
                    direction: 'none',
                    random: true,
                    straight: true,
                    out_mode: 'bounce'
                }
            },
            retina_detect: true
        });
    }

    window.onload = function () {
        document.body.className = '';
        initTwinklingStars();
    }

    window.onresize = function () {
        clearTimeout(window.onResizeEnd);
        window.onResizeEnd = setTimeout(initTwinklingStars, 250);
    }

    window.ontouchmove = function () {
        return false;
    }

    window.onorientationchange = function () {
        document.body.scrollTop = 0;
    }
}());

(function () {
    function initTwinklingStars(devicePixelRatio) {

        particlesJS('stars', {
            particles: {
                number: {
                    value: 180,
                    density: {
                        enable: true,
                        value_area: 600
                    }
                },
                color: {
                    value: '#ffffff'
                },
                shape: {
                    type: 'circle'
                },
                opacity: {
                    value: 1,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 3,
                        opacity_min: 0
                    }
                },
                size: {
                    value: 1.5 / devicePixelRatio,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 1,
                        size_min: 0.5 / devicePixelRatio,
                        sync: false
                    }
                },
                line_linked: {
                    enable: false
                },
                move: {
                    enable: true,
                    speed: 50,
                    direction: 'none',
                    random: true,
                    straight: true,
                    out_mode: 'bounce'
                }
            },
            retina_detect: true
        });
    }

    window.onload = function () {
        initTwinklingStars(window.devicePixelRatio / 1.5 || 1);
        document.body.className = '';
    }

    window.onresize = function () {
        clearTimeout(window.onResizeEnd);
        window.onResizeEnd = setTimeout(initTwinklingStars, 250);
    }

    window.ontouchmove = function () {
        return false;
    }

    window.onorientationchange = function () {
        document.body.scrollTop = 0;
    }
}());

Tweak stars size on retina devices


var moment = require('moment');

var System = {

    create: function(activityInstance, user, language, nation) {

        var now = moment();

        return {
            "User": {
                "HealthCareRole": user.startsWith("Patient") ? "Citizen" : "Physician",
                "HealthCareOrganization": {
                    "CodeValue": {},
                    "CodeSystem": {},
                    "CodeSystemVersion": {}
                },
                "HealthCareSpecialty": {
                    "CodeValue": {},
                    "CodeSystem": {},
                    "CodeSystemVersion": {}
                },
                "Language": {
                    "CodeValue": language,
                    "CodeSystem": "2.16.840.1.113883.6.99",
                    "CodeSystemVersion": {}
                },
                "Nation": {
                    "CodeValue": nation,
                    "CodeSystem": "ISO 3166-1",
                    "CodeSystemVersion": {}
                }
            },
            "Application": {
                "QueryID": activityInstance,
                "FeedbackType": "S",
                "CheckMoment": {
                    "CheckDate": now.format('YYYY-MM-DD'),
                    "CheckTime": now.format('HH:mm:ss')
                }
            }
        };
    }
};

module.exports = System;

var moment = require('moment');

var System = {

    create: function(activityInstance, user, language, nation) {

        var now = moment();

        return {
            "User": {
                "HealthCareRole": user.startsWith("Patient") ? "Citizen" : "Physician",
                "HealthCareOrganization": {
                    "CodeValue": "fhirdemo",
                    "CodeSystem": {},
                    "CodeSystemVersion": {}
                },
                "HealthCareSpecialty": {
                    "CodeValue": {},
                    "CodeSystem": {},
                    "CodeSystemVersion": {}
                },
                "Language": {
                    "CodeValue": language,
                    "CodeSystem": "2.16.840.1.113883.6.99",
                    "CodeSystemVersion": {}
                },
                "Nation": {
                    "CodeValue": nation,
                    "CodeSystem": "ISO 3166-1",
                    "CodeSystemVersion": {}
                }
            },
            "Application": {
                "QueryID": activityInstance,
                "FeedbackType": "S",
                "CheckMoment": {
                    "CheckDate": now.format('YYYY-MM-DD'),
                    "CheckTime": now.format('HH:mm:ss')
                }
            }
        };
    }
};

module.exports = System;

Set organization code to fhirdemo


require(['gitbook'], function(gitbook) {

    gitbook.events.bind('start', function(e, config) {
        var opts = config.toolbar;

        if (!opts || !opts.buttons) return;

        var buttons = opts.buttons.slice(0);
        buttons.reverse();

        buttons.forEach(function(button) {
            gitbook.toolbar.createButton({
                icon: button.icon || "fa fa-external-link",
                label: button.label || "Link",
                position: 'right',
                onClick: function(e) {
                    e.preventDefault();
                    var mapping = {
                        "{{title}}": encodeURIComponent(document.title),
                        "{{url}}": encodeURIComponent(location.href)
                    };
                    var re = RegExp(Object.keys(mapping).join("|"), "g");
                    window.open(button.url.replace(re, function(matched) {
                        return mapping[matched];
                    }));
                }
            });
        });
    });
});

require(['gitbook'], function(gitbook) {

    gitbook.events.bind('start', function(e, config) {
        var opts = config.toolbar;

        if (!opts || !opts.buttons) return;

        var buttons = opts.buttons.slice(0);
        buttons.reverse();

        buttons.forEach(function(button) {
            gitbook.toolbar.createButton({
                icon: button.icon || "fa fa-external-link",
                label: button.label || "Link",
                position: 'right',
                onClick: function(e) {
                    e.preventDefault();
                    var mapping = {
                        "{{title}}": encodeURIComponent(document.title),
                        "{{url}}": encodeURIComponent(location.href)
                    };
                    var re = RegExp(Object.keys(mapping).join("|"), "g");
                    var url = button.url.replace(re, function(matched) {
                        return mapping[matched];
                    });
                    if (button.target == "_self") {
                        window.location = url;
                    } else {
                        window.open(url, button.target || "_blank");
                    }
                }
            });
        });
    });
});

Allow to set link target (_self to change current window's location)


import React, { PropTypes } from 'react';

import { Modal } from 'react-bootstrap';

const ReadModeModal = props => (

    <Modal.Header>
      <Modal.Title>{props.recipe.name}</Modal.Title>
    </Modal.Header>
    <Modal.Body>

        {props.recipe.description}

        {
          props.recipe.ingredients.split(',').map((ingredient,index) => (

{ingredient}
)
          )
        }

    </Modal.Body>
    <Modal.Footer>
      <button onClick={() => props.switchModal(props.recipeId,'update')}>
        Edit
      </button>
      <button onClick={() => props.switchModal(props.recipeId,'delete')}>
        Delete
      </button>
      <button onClick={props.onHide}>Close</button>
    </Modal.Footer>

);

ReadModeModal.PropTypes = {
  recipeId: PropTypes.number.isRequired,
  recipe: PropTypes.object.isRequired,
  onHide: PropTypes.func.isRequired,
  switchModal: PropTypes.func.isRequired
}

export default ReadModeModal;

import React, { PropTypes } from 'react';

import { Modal } from 'react-bootstrap';

const ReadModeModal = props => (

    <Modal.Header>
      <Modal.Title>{props.recipe.name}</Modal.Title>
    </Modal.Header>
    <Modal.Body>

        {props.recipe.description}

        {
          props.recipe.ingredients.split(',').map((ingredient,index) => (

{ingredient}
)
          )
        }

    </Modal.Body>
    <Modal.Footer>
      <button onClick={() => props.switchModal(props.recipeId,'update')}>
        Edit
      </button>
      <button onClick={() => props.switchModal(props.recipeId,'delete')}>
        Delete
      </button>
      <button onClick={props.onHide}>Close</button>
    </Modal.Footer>

);

ReadModeModal.PropTypes = {
  recipeId: PropTypes.number.isRequired,
  recipe: PropTypes.shape({
    name: PropTypes.string.isRequired,
    description: PropTypes.string.isRequired,
    ingredients: PropTypes.string.isRequired
  }),
  onHide: PropTypes.func.isRequired,
  switchModal: PropTypes.func.isRequired
}

export default ReadModeModal;

Update PropTypes of ReadModeModal component


'use strict'

const mongoose = require('mongoose')
const uuid = require('uuid').v4

const schema = new mongoose.Schema({
	id: {
		type: String,
		required: true,
		unique: true,
		default: uuid
	},
	created: {
		type: Date,
		required: true,
		default: Date.now
	},
	updated: {
		type: Date,
		required: true,
		default: Date.now
	}
})

module.exports = mongoose.model('Token', schema)

'use strict'

const mongoose = require('mongoose')
const uuid = require('uuid').v4

const schema = new mongoose.Schema({
	id: {
		type: String,
		required: true,
		unique: true,
		default: uuid
	},
	title: {
		type: String
	},
	permanent: {
		type: Boolean,
		default: false
	},
	created: {
		type: Date,
		required: true,
		default: Date.now
	},
	updated: {
		type: Date,
		required: true,
		default: Date.now
	}
})

module.exports = mongoose.model('Token', schema)

Add title and permanent flag to token model


/*
 * Ensures something has been found during the request.  Returns 404 if
 * res.template is unset, res.locals is empty and statusCode has not been set
 * to 204.
 *
 * Should be placed at the very end of the middleware pipeline,
 * after all project specific routes but before the error handler & responder.
 *
 * @module midwest/middleware/ensure-found
 */

'use strict';

const _ = require('lodash');

module.exports = function ensureFound(req, res, next) {
  // it seems most reasonable to check if res.locals is empty before res.statusCode
  // because the former is much more common
  if (res.template || res.master || !_.isEmpty(res.locals) || res.statusCode === 204) {
    next();
  } else {
    // generates Not Found error if there is no page to render and no truthy
    // values in data
    const err = new Error(`Not found: ${req.method.toUpperCase()} ${req.path}`);
    err.status = 404;

    next(err);
  }
};

/*
 * Ensures something has been found during the request.  Returns 404 if
 * res.template is unset, res.locals is empty and statusCode has not been set
 * to 204.
 *
 * Should be placed at the very end of the middleware pipeline,
 * after all project specific routes but before the error handler & responder.
 *
 * @module midwest/middleware/ensure-found
 */

'use strict';

function isEmpty(obj) {
  for (const prop in obj) {
    if (prop !== 'scripts' && obj.hasOwnProperty(prop)) {
      return false;
    }
  }

  return true;
}
module.exports = function ensureFound(req, res, next) {
  // it seems most reasonable to check if res.locals is empty before res.statusCode
  // because the former is much more common
  if (res.template || res.master || !isEmpty(res.locals) || res.statusCode === 204) {
    next();
  } else {
    // generates Not Found error if there is no page to render and no truthy
    // values in data
    const err = new Error(`Not found: ${req.method.toUpperCase()} ${req.path}`);
    err.status = 404;

    next(err);
  }
};

Optimize and classify only res.locals.scripts as not found


var BufferedStream = require('bufferedstream');
var createMockCouchAdapter = require('./createMockCouchAdapter');
var http = require('http');
var mockCouch = require('mock-couch-alexjeffburke');
var url = require('url');

function generateCouchdbResponse(databases, req, res) {
    var responseObject = null;

    var couchdbHandler = createMockCouchAdapter();
    var couchdb = new mockCouch.MockCouch(couchdbHandler, {});

    Object.keys(databases).forEach(function (databaseName) {
        couchdb.addDB(databaseName, databases[databaseName].docs || []);
    });

    // run the handler
    couchdbHandler(req, res, function () {});
}

module.exports = {
    name: 'unexpected-couchdb',
    installInto: function (expect) {
        expect.installPlugin(require('unexpected-mitm'));

        expect.addAssertion('<any> with couchdb mocked out <object> <assertion>', function (expect, subject, couchdb) {
            expect.errorMode = 'nested';

            var nextAssertionArgs = this.args.slice(1);
            var args = [subject, 'with http mocked out', {
                response: generateCouchdbResponse.bind(null, couchdb)
            }].concat(nextAssertionArgs);

            return expect.apply(expect, args);
        });

    }
};

var BufferedStream = require('bufferedstream');
var createMockCouchAdapter = require('./createMockCouchAdapter');
var http = require('http');
var mockCouch = require('mock-couch-alexjeffburke');
var url = require('url');

function generateCouchdbResponse(databases, req, res) {
    var responseObject = null;

    var couchdbHandler = createMockCouchAdapter();
    var couchdb = new mockCouch.MockCouch(couchdbHandler, {});

    Object.keys(databases).forEach(function (databaseName) {
        couchdb.addDB(databaseName, databases[databaseName].docs || []);
    });

    // run the handler
    couchdbHandler(req, res, function () {});
}

module.exports = {
    name: 'unexpected-couchdb',
    installInto: function (expect) {
        expect.installPlugin(require('unexpected-mitm'));

        expect.addAssertion('<any> with couchdb mocked out <object> <assertion>', function (expect, subject, couchdb) {
            expect.errorMode = 'nested';

            return expect(function () {
                return expect.shift();
            }, 'with http mocked out', {
                response: generateCouchdbResponse.bind(null, couchdb)
            }, 'not to error');
        });
    }
};

Use expect.shift instead of building an array of arguments for expect when delegating to the next assertion.


// default settings. fis3 release

// Global start
fis.match('src/ui-p2p-lending.less', {
  parser: fis.plugin('less'),
  rExt: '.css'
})

fis.match('src/*.less', {
  packTo: 'dist/ui-p2p-lending.css'
})

// Global end

// default media is `dev`

// extends GLOBAL config

fis.match('src/ui-p2p-lending.less', {
  parser: fis.plugin('less'),
  rExt: '.css',
  release: 'dist/ui-p2p-lending.css'
})

Modify the configuration of fis to remove the useless configurations


import React, { Component } from 'react'

import { propTypes, defaultProps } from './props'
import Player from './Player'
import { isEqual, getConfig } from './utils'

export default function createSinglePlayer (activePlayer) {
  return class SinglePlayer extends Component {
    static displayName = `${activePlayer.displayName}Player`
    static propTypes = propTypes
    static defaultProps = defaultProps
    static canPlay = activePlayer.canPlay

    shouldComponentUpdate (nextProps) {
      return !isEqual(this.props, nextProps)
    }
    componentWillUpdate (nextProps) {
      this.config = getConfig(nextProps, defaultProps)
    }
    render () {
      if (!activePlayer.canPlay(this.props.url)) {
        return null
      }
      return (
        <Player
          {...this.props}
          activePlayer={activePlayer}
          config={getConfig(this.props, defaultProps)}
        />
      )
    }
  }
}

import React, { Component } from 'react'

import { propTypes, defaultProps, DEPRECATED_CONFIG_PROPS } from './props'
import { getConfig, omit, isEqual } from './utils'
import Player from './Player'

const SUPPORTED_PROPS = Object.keys(propTypes)

export default function createSinglePlayer (activePlayer) {
  return class SinglePlayer extends Component {
    static displayName = `${activePlayer.displayName}Player`
    static propTypes = propTypes
    static defaultProps = defaultProps
    static canPlay = activePlayer.canPlay

    shouldComponentUpdate (nextProps) {
      return !isEqual(this.props, nextProps)
    }
    componentWillUpdate (nextProps) {
      this.config = getConfig(nextProps, defaultProps)
    }
    ref = player => {
      this.player = player
    }
    render () {
      if (!activePlayer.canPlay(this.props.url)) {
        return null
      }
      const { style, width, height, wrapper: Wrapper } = this.props
      const otherProps = omit(this.props, SUPPORTED_PROPS, DEPRECATED_CONFIG_PROPS)
      return (
        <Wrapper style={{ ...style, width, height }} {...otherProps}>
          <Player
            {...this.props}
            ref={this.ref}
            activePlayer={activePlayer}
            config={getConfig(this.props, defaultProps)}
          />
        </Wrapper>
      )
    }
  }
}

Add single player wrapper div


module.exports = process.platform === "linux" ?
    require("./watch-tree-unix") :
    require("./watch-tree-generic");

module.exports = process.platform === "linux" || process.platform === "darwin" ?
    require("./watch-tree-unix") :
    require("./watch-tree-generic");

Use unix fs-watch for OSX because of problems with OSX Lion


import { expect } from 'chai';
import jsf from '../../../src';

/* global describe, it */

describe('Random Generation', () => {
  it('should generate all the fields with alwaysFakeOptionals option and additionalProperties: true', async () => {
    jsf.option({
      alwaysFakeOptionals: true,
    });

    const schema = {
      type: 'object',
      properties: {
        foo: { type: 'string' },
        bar: { type: 'string' },
      },
      required: [],
      additionalProperties: true,
    };

    const resolved = await jsf.resolve(schema);

    expect(Object.keys(resolved).length).to.be.at.least(2);
  });
  it('should generate all the fields with alwaysFakeOptionals option and additionalProperties: false', async () => {
    jsf.option({
      alwaysFakeOptionals: true,
    });

    const schema = {
      type: 'object',
      properties: {
        foo: { type: 'string' },
        bar: { type: 'string' },
      },
      required: [],
      additionalProperties: false,
    };

    const resolved = await jsf.resolve(schema);

    expect(Object.keys(resolved).length).is.eql(2);
  });
});

import { expect } from 'chai';
import jsf from '../../../src';

/* global describe, it */

describe('Random Generation', () => {
  it('should generate all the fields with alwaysFakeOptionals option and additionalProperties: true', () => {
    jsf.option({
      alwaysFakeOptionals: true,
    });

    const schema = {
      type: 'object',
      properties: {
        foo: { type: 'string' },
        bar: { type: 'string' },
      },
      required: [],
      additionalProperties: true,
    };

    return jsf.resolve(schema).then(resolved => {
      expect(Object.keys(resolved).length).to.be.at.least(2);
    });
  });
  it('should generate all the fields with alwaysFakeOptionals option and additionalProperties: false', () => {
    jsf.option({
      alwaysFakeOptionals: true,
    });

    const schema = {
      type: 'object',
      properties: {
        foo: { type: 'string' },
        bar: { type: 'string' },
      },
      required: [],
      additionalProperties: false,
    };

    return jsf.resolve(schema).then(resolved => {
      expect(Object.keys(resolved).length).is.eql(2);
    });
  });
});

Disable async/await to run on v6


// @flow
import type {Snapshot, SnapshotItem} from 'redux-ship';

export type State = {
  logs: {action: mixed, snapshot: Snapshot<mixed, mixed>}[],
  selectedLog: ?number,
  selectedSnapshotItem: ?SnapshotItem<mixed, mixed>,
};

export const initialState: State = {
  logs: [],
  selectedLog: null,
  selectedSnapshotItem: null,
};

export type Commit = {
  type: 'AddLog',
  action: mixed,
  snapshot: Snapshot<mixed, mixed>,
} | {
  type: 'SelectLog',
  logIndex: number,
} | {
  type: 'SelectSnapshotItem',
  snapshotItem: SnapshotItem<mixed, mixed>,
};

export function reduce(state: State, commit: Commit): State {
  switch (commit.type) {
    case 'AddLog':
      return {
        ...state,
        logs: [
          ...state.logs,
          {
            action: commit.action,
            snapshot: commit.snapshot,
          }
        ],
      };
    case 'SelectLog':
      return {
        ...state,
        selectedLog: commit.logIndex,
      };
    case 'SelectSnapshotItem':
      return {
        ...state,
        selectedSnapshotItem: commit.snapshotItem,
      };
    default:
      return state;
  }
}

// @flow
import type {Snapshot, SnapshotItem} from 'redux-ship';

export type State = {
  logs: {action: mixed, snapshot: Snapshot<mixed, mixed>}[],
  selectedLog: ?number,
  selectedSnapshotItem: ?SnapshotItem<mixed, mixed>,
};

export const initialState: State = {
  logs: [],
  selectedLog: null,
  selectedSnapshotItem: null,
};

export type Commit = {
  type: 'AddLog',
  action: mixed,
  snapshot: Snapshot<mixed, mixed>,
} | {
  type: 'SelectLog',
  logIndex: number,
} | {
  type: 'SelectSnapshotItem',
  snapshotItem: SnapshotItem<mixed, mixed>,
};

export function reduce(state: State, commit: Commit): State {
  switch (commit.type) {
    case 'AddLog':
      return {
        ...state,
        logs: [
          ...state.logs,
          {
            action: commit.action,
            snapshot: commit.snapshot,
          }
        ],
      };
    case 'SelectLog':
      return commit.logIndex === state.selectedLog ? state : {
        ...state,
        selectedLog: commit.logIndex,
        selectedSnapshotItem: null,
      };
    case 'SelectSnapshotItem':
      return {
        ...state,
        selectedSnapshotItem: commit.snapshotItem,
      };
    default:
      return state;
  }
}

Hide the selected state when already on it


//= require ./core
//= require ./mixins
//= require ./forms
//= require_tree ./forms
//= require_tree ./views

//= require ./core
//= require ./mixins
//= require ./forms
//= require ./forms/field
//= require_tree ./forms
//= require_tree ./views

Fix dependency loading order for checkbox


var express = require('express');
var DataStore = require('./regard-data-store.js');
var Chart = require('../schemas/chart.js');

var router = express.Router();
var dataStore = new DataStore('Adobe', 'Brackets');

router.get('/chartdata', function (req, res, next) {
  var id = req.query.ids[0];

  dataStore.runQuery(id).then(function (result) {
    res.json({
      chartdata: [{
        _id: id,
        values: JSON.parse(result).Results
      }]
    });
  }, next);
});

router.post('/charts', function (req, res, next) {
  if (!req.body.chart.queryDefinition) {
    res.send(400, 'missing query definition');
  }

  var queryName = req.body.chart.id;
  var queryDefinition = req.body.chart.queryDefinition;

  dataStore.registerQuery(queryName, queryDefinition).done(function () {
    next();
  }, next);
});

module.exports = router;

var express = require('express');
var DataStore = require('./regard-data-store.js');
var Chart = require('../schemas/chart.js');

var router = express.Router();
var dataStore = new DataStore('Adobe', 'Brackets');

router.get('/chartdata', function (req, res, next) {
  var id = req.query.ids[0];

  dataStore.runQuery(id).then(function (result) {
  res.json({
      chartdata: [{
        _id: id,
        values: JSON.parse(result).Results
      }]
    });
  });
});

router.put('/charts/:id', function (req, res, next) {
  if (!req.body.chart.queryDefinition) {
    res.send(400, 'missing query definition');
  }

  var queryName = req.params.id;
  var queryDefinition = req.body.chart.queryDefinition;

  dataStore.registerQuery(queryName, queryDefinition).done(function () {
    next();
  }, next);
});

module.exports = router;

Revert "Register query on create."


function hook_menu(){
    $.contextMenu({
        selector: '.feeder_entry',
        callback: function(key, options) {
            if(key == 'gallery'){
                var id = $(this).attr('specie_id');
                var folder = '';
                $.each(collection_data.species,function(){
                    if(this.id == id){
                        folder = this.name.replace(/ /g,'_').replace(/\./g,'').toLowerCase();
                        console.log(this);
                        window.open("http://soundspawn.com/browser.php?p="+folder);
                    }
                });
                console.log(this);
            }
        },
        items: {
            "gallery": {name: "Gallery", icon: "quit"},
        }
    });
}

function hook_menu(){
    $.contextMenu('destroy','.feeder_entry');
    $.contextMenu({
        selector: '.feeder_entry',
        callback: function(key, options) {
            if(key == 'gallery'){
                var id = $(this).attr('specie_id');
                var folder = '';
                $.each(collection_data.species,function(){
                    if(this.id == id){
                        folder = this.name.replace(/ /g,'_').replace(/\./g,'').toLowerCase();
                        console.log(this);
                        window.open("http://soundspawn.com/browser.php?p="+folder);
                    }
                });
                console.log(this);
            }
        },
        items: {
            "gallery": {name: "Gallery", icon: "quit"},
        }
    });
}

Destroy any old bind, makes this function repeat-callable


import Ember from 'ember';

const { Controller, computed } = Ember;

export default Controller.extend({
  error: null,

  errorStr: computed('error', function() {
    return this.get('error').toString();
  }),

  errorCodes: computed('error', function() {
    const error = this.get('error');
    const codes = [error.code];

    if (error.errors) {
      error.errors.forEach(err => {
        codes.push(err.status);
      });
    }

    return codes
      .compact()
      .uniq()
      .map(code => '' + code);
  }),

  is404: computed('errorCodes.[]', function() {
    return this.get('errorCodes').includes('404');
  }),

  is500: computed('errorCodes.[]', function() {
    return this.get('errorCodes').includes('500');
  }),
});

import Ember from 'ember';

const { Controller, computed, inject, run, observer } = Ember;

export default Controller.extend({
  config: inject.service(),

  error: null,

  errorStr: computed('error', function() {
    return this.get('error').toString();
  }),

  errorCodes: computed('error', function() {
    const error = this.get('error');
    const codes = [error.code];

    if (error.errors) {
      error.errors.forEach(err => {
        codes.push(err.status);
      });
    }

    return codes
      .compact()
      .uniq()
      .map(code => '' + code);
  }),

  is404: computed('errorCodes.[]', function() {
    return this.get('errorCodes').includes('404');
  }),

  is500: computed('errorCodes.[]', function() {
    return this.get('errorCodes').includes('500');
  }),

  throwError: observer('error', function() {
    if (this.get('config.isDev')) {
      run.next(() => {
        throw this.get('error');
      });
    }
  }),
});

Throw errors that cause a redirect to make debugging easier


Make sure there actually is an object


import { EventEmitter } from 'events'
import PouchDB from 'pouchdb'
import Serial from '../serial'
import Classifier from './classifier'
import { parser, dataHandler } from './data-handler'

/**
 * Handles everything a Station should.
 * Brings Serial, data parsing and database saving together.
 */
export default class Station extends EventEmitter {
  /**
   * Sets up all relevant class instances (Serial, parsers...) and events listeners.
   */
  constructor () {
    /**
     * Database instance, internal to the station.
     */
    this.db = new PouchDB('station-db')

    /**
     * {@link Serial} instance with the {@link parser} attached
     */
    this.serial = new Serial(parser())

    /**
     * {@link Classifier} instance.
     */
    this.classifier = new Classifier()

    // Handle incoming packets
    this.serial.on('data', this::dataHandler)
  }
}

import { EventEmitter } from 'events'
import PouchDB from 'pouchdb'
import Serial from '../serial'
import Classifier from './classifier'
import { parser, dataHandler } from './data-handler'

/**
 * Handles everything a Station should.
 * Brings Serial, data parsing and database saving together.
 */
export default class Station extends EventEmitter {
  /**
   * Sets up all relevant class instances (Serial, parsers...) and events listeners.
   */
  constructor () {
    super()

    /**
     * Database instance, internal to the station.
     */
    this.db = new PouchDB('station-db')

    /**
     * {@link Serial} instance with the {@link parser} attached
     */
    this.serial = new Serial(parser())

    /**
     * {@link Classifier} instance.
     */
    this.classifier = new Classifier()

    // Handle incoming packets
    this.serial.on('data', this::dataHandler)
  }
}

Add missing Station super() call


var videoStyle = {
  width: '100%',
  height: '100%',
  backgroundColor: '#000'
};

var WatchPage = React.createClass({
  propTypes: {
    name: React.PropTypes.string,
  },

  render: function() {
    return (
      <main>
        <video style={videoStyle} src={"/view?name=" + this.props.name} controls />
      </main>
    );
  }
});

var videoStyle = {
  width: '100%',
  height: '100%',
  backgroundColor: '#000'
};

var WatchPage = React.createClass({
  propTypes: {
    name: React.PropTypes.string,
  },
  getInitialState: function() {
    return {
      readyToPlay: false,
      loadStatusMessage: "Requesting stream",
    };
  },
  componentDidMount: function() {
    lbry.getStream(this.props.name);
    this.updateLoadStatus();
  },
  updateLoadStatus: function() {
    lbry.getFileStatus(this.props.name, (status) => {
      if (status.code != 'running') {
        this.loadStatusMessage = status.message;
        setTimeout(() => { this.updateLoadStatus() }, 250);
      } else {
        this.setState({
          readyToPlay: true
        });
      }
    });
  },
  render: function() {
    if (!this.state.readyToPlay) {
      return (

Loading lbry://{this.props.name}

        {this.state.loadStatusMessage}

      );
    } else {
      return (

        <video style={videoStyle} src={"/view?name=" + this.props.name} controls />;

      );
    }
  }
});

Hide video until it's playable and show loading message


var Clock = module.exports;

Clock.weekday = function(weekday, hour, minute, seconds) {
  return moment({ hour: hour, minute: minute, seconds: seconds }).day(weekday).unix();
};

var Clock = module.exports;

Clock.weekday = function(weekday, hour, minute, seconds) {
  var now = moment();
  var target = moment({ hour: hour, minute: minute, seconds: seconds }).day(weekday);
  if (moment.max(now, target) === now) {
    target.add(1, 'week');
  }
  return target.unix();
};

Fix Clock weekday to always return a time in the future


var plugins = require('gulp-load-plugins')({
  lazy: true
});

////////// TASKS ////////////

/**
 * Prints out the list  of available tasks.
 */
gulp.task('default', plugins.taskListing);

/////// ACCESSORY FUNCTIONS ////////

var plugins = require('gulp-load-plugins')({
  lazy: true
});

////////// TASKS ////////////

/**
 * Prints out the list  of available tasks.
 */
gulp.task('default', plugins.taskListing);

////// igonzalez tasks /////////////
gulp.task('analyze');

////// fjfernandez tasks /////////////

/////// ACCESSORY FUNCTIONS ////////

Add personal areas to prevent merge conflicts.


module.exports = {
	BLACK: 1,
	RED: 1,
	GREEN: 2,
	BLUE: 3

}

module.exports = {
	BLACK: 0,
	RED: 1,
	GREEN: 2,
	BLUE: 3

}

Correct color value for Black


require.config({
    paths: {
        "jquery": "js/jquery-2.1.4.min",
        "underscore": "js/underscore-min",
        "knockout": "js/knockout-min-3.3.0"
    }
});

require(['jquery', 'js/modules/dukecondb', 'js/modules/dukeconsettings', 'domReady!'], function($, db, settings) {
    console.log("Clearing DB");
    db.purge();
    console.log("Clearing DB done; resetting localstore");
    settings.purge();
    console.log("Resetting localstore done; clearing the cache");
    window.parent.caches.delete("call");
    console.log("Clearing the cache done");
    $('#loading').hide();
    $('#layout').show();
});

require.config({
    paths: {
        "jquery": "js/jquery-2.1.4.min",
        "underscore": "js/underscore-min",
        "domReady": "js/domReady",
        "knockout": "js/knockout-min-3.3.0"
    }
});

require(['jquery', 'js/modules/dukecondb', 'js/modules/dukeconsettings', 'domReady!'], function($, db, settings) {
    console.log("Clearing DB");
    db.purge();
    console.log("Clearing DB done; resetting localstore");
    settings.purge();
    console.log("Resetting localstore done; clearing the cache");
    window.parent.caches.delete("call");
    console.log("Clearing the cache done");
    $('#loading').hide();
    $('#layout').show();
});

Add missing "domReady" module declaration


/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

define({
    // Relative to the samples folder
    "GETTING_STARTED"           : "root/Getting Started",
    "ADOBE_THIRD_PARTY"         : "http://www.adobe.com/go/thirdparty/",
    "WEB_PLATFORM_DOCS_LICENSE" : "http://creativecommons.org/licenses/by/3.0/"
});

/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

define({
    // Relative to the samples folder
    "GETTING_STARTED"           : "root/Getting Started",
    "ADOBE_THIRD_PARTY"         : "http://www.adobe.com/go/thirdparty/",
    "WEB_PLATFORM_DOCS_LICENSE" : "http://creativecommons.org/licenses/by/3.0/deed.zh_TW"
});

Update CC BY 3.0 link to zh-TW localized version.


/*
 * Copyright 2017-present, Hippothesis, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

'use strict';

export const Images = {
 	logo: null
};

export default Images;

/*
 * Copyright 2017-present, Hippothesis, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

'use strict';

export const Images = {
 	icons: {
    home: require('../images/home-icon.png'),
    search: require('../images/search-icon.png'),
    profile: require('../images/profile-icon.png')
  }
};

export default Images;

Add file paths to icons


var gulp = require('gulp');
var tsc = require('gulp-tsc');
var tape = require('gulp-tape');
var tapSpec = require('tap-spec');
var del = require('del');

gulp.task("test:clean", function(done) {
  del(['build-test/**']).then(function(paths) {
    console.log("=====\nDeleted the following files:\n" + paths.join('\n')+ "\n=====");
    done();
  });
});

gulp.task("test:build", function (done) {
  gulp.src(['test/**/*.ts'])
    .pipe(tsc())
    .pipe(gulp.dest('build-test/'))
    .on('end', done);
});

gulp.task("test:run", function (done) {
  gulp.src('build-test/test/**/*.test.js')
    .pipe(tape({
      reporter: tapSpec()
    }));
});

gulp.task("test", ["test:build"], function (done) {
  gulp.src('build-test/test/**/*.test.js')
    .pipe(tape({
      reporter: tapSpec()
    }));
});

var gulp = require('gulp');
var tsc = require('gulp-tsc');
var tape = require('gulp-tape');
var tapSpec = require('tap-spec');
var del = require('del');

gulp.task("test:clean", function(done) {
  del(['build-test/**']).then(function(paths) {
    console.log("=====\nDeleted the following files:\n" + paths.join('\n')+ "\n=====");
    done();
  });
});

gulp.task("test:build", function (done) {
  gulp.src(['test/**/*.ts'])
    .pipe(tsc())
    .pipe(gulp.dest('build-test/'))
    .on('end', done);
});

gulp.task("test:run", function (done) {
  gulp.src('build-test/test/**/*.test.js')
    .pipe(tape({
      reporter: tapSpec()
    }))
    .on('end', done);;
});

gulp.task("test", ["test:build"], function (done) {
  gulp.src('build-test/test/**/*.test.js')
    .pipe(tape({
      reporter: tapSpec()
    }));
});

Call completion callback in test:run


'use strict';

var gulp = require('gulp');
var watch = require('gulp-watch');
var harp = require('harp');
var browserSync = require('browser-sync');
var ghPages = require('gulp-gh-pages');

var harpServerOptions = {
  port: 9000
};

var paths = {
  projectDir: './',
  outputDir: './dist',
  outputFiles: './dist/**/*.*',
  srcFiles: './public/**/*.*'
};

gulp.task('default', ['watch']);

gulp.task('deploy', ['build'], function () {
  return gulp.src(paths.outputFiles)
    .pipe(ghPages());
});

gulp.task('build', function (done) {
  harp.compile(paths.projectDir, paths.outputDir, done);
});

gulp.task('watch', ['dev-server'], function () {
  browserSync({
    open: false,
    proxy: 'localhost:' + harpServerOptions.port,
    notify: false
  });

  gulp.src(paths.srcFiles)
    .pipe(watch(paths.srcFiles, {
      verbose: true
    }))
    .pipe(browserSync.reload({
      stream: true
    }));
});

gulp.task('dev-server', function (done) {
  harp.server(__dirname, harpServerOptions, done);
});

'use strict';

var gulp = require('gulp');
var watch = require('gulp-watch');
var harp = require('harp');
var browserSync = require('browser-sync');
var ghPages = require('gulp-gh-pages');

var harpServerOptions = {
  port: 9000
};

var paths = {
  projectDir: './',
  outputDir: './dist',
  outputFiles: './dist/**/*',
  srcFiles: './public/**/*'
};

gulp.task('default', ['watch']);

gulp.task('deploy', ['build'], function () {
  return gulp.src(paths.outputFiles)
    .pipe(ghPages());
});

gulp.task('build', function (done) {
  harp.compile(paths.projectDir, paths.outputDir, done);
});

gulp.task('watch', ['dev-server'], function () {
  browserSync({
    open: false,
    proxy: 'localhost:' + harpServerOptions.port,
    notify: false
  });

  gulp.src(paths.srcFiles)
    .pipe(watch(paths.srcFiles, {
      verbose: true
    }))
    .pipe(browserSync.reload({
      stream: true
    }));
});

gulp.task('dev-server', function (done) {
  harp.server(__dirname, harpServerOptions, done);
});

Modify files globs to include all files


const gulp = require('gulp');
const browserify = require('gulp-browserify');
const pkg = require('./package.json')

gulp.task('build', () =>
  gulp.src(pkg.main)
    .pipe(browserify({
      insertGlobals : true,
      debug : !gulp.env.production
    }))
    .pipe(gulp.dest('dist'))
);

gulp.task('default', ['build']);

const gulp = require('gulp');
const browserify = require('gulp-browserify');
const rename = require("gulp-rename");
const pkg = require('./package.json');

gulp.task('build', () =>
  gulp.src(pkg.main)
    .pipe(browserify({
    insertGlobals: true,
    debug: !gulp.env.production
  }))
  .pipe(rename(function(path) {
    path.basename = pkg.name;
  }))
  .pipe(gulp.dest('dist'))
);

gulp.task('default', ['build']);

Add renaming of index.js to memefy.js


var gulp = require('gulp'),
    rimraf = require('rimraf'),
    jshint = require('gulp-jshint'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    insert = require('gulp-insert'),
    p = require('./package.json')
    ;

//Folders and annotation
var src = 'src/',
    dest = 'dist/',
    annotation = '/* ' + p.name + ' v' + p.version + ' | Copyright (c) ' + new Date().getFullYear() + ' ' + p.homepage + ' | ' + p.license + ' license */\n';

gulp.task('clean', function(cb) {
    rimraf(dest, cb);
});

gulp.task('scripts', ['clean'], function() {
    return gulp.src(src + '*.js')
        .pipe(jshint())
        .pipe(jshint.reporter())
        .pipe(uglify())
        .pipe(rename('jquery.seslider-' + p.version + '.min.js'))
        .pipe(insert.prepend(annotation))
        .pipe(gulp.dest(dest));
        ;
});

gulp.task('default', ['scripts'], function() {

});

var gulp = require('gulp'),
    rimraf = require('rimraf'),
    jshint = require('gulp-jshint'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    insert = require('gulp-insert'),
    p = require('./package.json')
    ;

//Folders and annotation
var src = 'src/',
    dest = 'dist/',
    annotation = '/* ' + p.name + ' v' + p.version + ' | Copyright (c) ' + new Date().getFullYear() + ' ' + p.homepage + ' | ' + p.license + ' license */\n';

gulp.task('clean', function(cb) {
    rimraf(dest, cb);
});

gulp.task('scripts', ['clean'], function() {
    return gulp.src(src + '*.js')
        .pipe(jshint())
        .pipe(jshint.reporter())
        .pipe(uglify())
        .pipe(rename('jquery.seslider.min.js'))
        .pipe(insert.prepend(annotation))
        .pipe(gulp.dest(dest));
        ;
});

gulp.task('default', ['scripts'], function() {

});

Update gulp to change name of generated file


'use strict';

var gulp = require('gulp');
var del = require('del');
var babel = require('gulp-babel');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');

var mocha = require('gulp-mocha');
var mochaBabelRegister = require('babel/register');

var buildDestination = 'build'

gulp.task('build', function() {
  del([buildDestination], function() {
    var bundleStream = browserify({
      entries: './index.js',
      debug: true,
    }).bundle();

    return bundleStream
      .pipe(source('min-flux.js'))
      .pipe(buffer())
      .pipe(babel())
      .pipe(gulp.dest(buildDestination));
  });
});

gulp.task('test', function() {
  var MinFlux = require('./index');
  var expect = require('chai').expect;

  return gulp.src(['test/**/*.js'], { read: false })
    .pipe(mocha({
      reporter: 'dot',
      require: [
        './index',
        'chai',
      ],
    }));
});

gulp.task('default', ['test']);

'use strict';

var gulp = require('gulp');
var del = require('del');
var babel = require('gulp-babel');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');

var mocha = require('gulp-mocha');
var mochaBabelRegister = require('babel/register');

var buildDestination = 'build'

gulp.task('build', function() {
  del([buildDestination], function() {
    var bundleStream = browserify({
      entries: './index.js',
      debug: true,
    }).bundle();

    return bundleStream
      .pipe(source('min-flux.js'))
      .pipe(buffer())
      .pipe(babel())
      .pipe(gulp.dest(buildDestination));
  });
});

gulp.task('test', function() {
  return gulp.src(['test/**/*.js'], { read: false })
    .pipe(mocha({
      reporter: 'dot',
    }));
});

gulp.task('live-test', function() {
  return gulp.watch(['index.js', 'lib/**/*.js', 'test/**/*.js'], ['test']);
});

gulp.task('default', ['test']);

Add gulp task to run tests on file change.


var gulp = require('gulp');
var iife = require('gulp-iife');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var rename = require('gulp-rename');

gulp.task('default', ['scripts']);

gulp.task('scripts', function () {
  gulp.src('src/**/*.js')
      .pipe(concat('vk-api-angular.js'))
      .pipe(iife())
      .pipe(gulp.dest('dist/'))
      .pipe(uglify())
      .pipe(rename({suffix: '.min'}))
      .pipe(gulp.dest('dist/'));
});

gulp.task('watch', ['default'], function () {
  gulp.watch('src/**/*.js', ['scripts']);
});

var gulp = require('gulp');
var iife = require('gulp-iife');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var rename = require('gulp-rename');

gulp.task('default', ['scripts']);

gulp.task('scripts', function () {
  return gulp.src('src/**/*.js')
      .pipe(concat('vk-api-angular.js'))
      .pipe(iife())
      .pipe(gulp.dest('dist/'))
      .pipe(uglify())
      .pipe(rename({suffix: '.min'}))
      .pipe(gulp.dest('dist/'));
});

gulp.task('watch', ['default'], function () {
  gulp.watch('src/**/*.js', ['scripts']);
});

Add return statement to gulp task


var del = require('del');
var gulp = require('gulp');
var webpack = require('webpack');

var WebpackDevServer = require('webpack-dev-server');

var $ = require('gulp-load-plugins')();

var config = require('./webpack.config.js');

gulp.task('js', function (cb) {
  webpack(config, function (err, stats) {
    if(err) throw new gutil.PluginError("webpack", err);
    $.util.log("[webpack]", stats.toString({
      colors: true
    }));
    cb();
  });
});

gulp.task('html', function () {
  gulp.src('./src/*.html')
    .pipe(gulp.dest('./build'));
});

gulp.task('css', function () {
  gulp.src('./src/css/*.css')
    .pipe(gulp.dest('./build/css'));
});

gulp.task('clean', function (cb) {
  del(['build']).then(cb);
});

gulp.task('build', ['html', 'css', 'js']);

gulp.task('dev', ['html', 'css'], function () {
  // Start a webpack-dev-server
  var compiler = webpack(config);

  new WebpackDevServer(compiler, {
    // server and middleware options
  }).listen(8080, "localhost", function(err) {
    if(err) throw new gutil.PluginError("webpack-dev-server", err);
    // Server listening
    $.util.log("[webpack-dev-server]", "http://localhost:8080/webpack-dev-server/index.html");
  });
});

var del = require('del');
var gulp = require('gulp');
var webpack = require('webpack');

var WebpackDevServer = require('webpack-dev-server');

var $ = require('gulp-load-plugins')();

var config = require('./webpack.config.js');

gulp.task('js', function (cb) {
  webpack(config, function (err, stats) {
    if(err) throw new gutil.PluginError("webpack", err);
    $.util.log("[webpack]", stats.toString({
      colors: true
    }));
    cb();
  });
});

gulp.task('html', function () {
  gulp.src('./src/*.html')
    .pipe(gulp.dest('./build'));
});

gulp.task('css', function () {
  gulp.src('./src/css/*.css')
    .pipe(gulp.dest('./build/css'));
});

gulp.task('clean', function (cb) {
  del(['build']).then(function () {
    cb()
  });
});

gulp.task('build', ['html', 'css', 'js']);

gulp.task('dev', ['html', 'css'], function () {
  // Start a webpack-dev-server
  var compiler = webpack(config);

  new WebpackDevServer(compiler, {
    // server and middleware options
  }).listen(8080, "localhost", function(err) {
    if(err) throw new gutil.PluginError("webpack-dev-server", err);
    // Server listening
    $.util.log("[webpack-dev-server]", "http://localhost:8080/webpack-dev-server/index.html");
  });
});

Fix an error in the clean task


'use strict';

module.exports = {
  camelCase: require('./camel-case'),
  colorString: require('./color-string'),
  nestOptions: require('./nest-options'),
  uid: require('./uid'),
  request: require('./request'),
  metadata: require('./metadata'),
  framerate: require('./framerate'),
  normalizeLanguage: require('./normalize-language'),
  pad: require('./pad'),
  output: require('./output')
};

'use strict';

module.exports = {
  camelCase: require('./camel-case'),
  colorString: require('./color-string'),
  nestOptions: require('./nest-options'),
  uid: require('./uid'),
  request: require('./request'),
  metadata: require('./metadata'),
  framerate: require('./framerate'),
  normalizeLanguage: require('./normalize-language'),
  pad: require('./pad'),
  output: require('./output'),
  commandExists: require('./command-exists')
};

Add command exists to utils