angular.module('zeus.results', [])
.controller('ResultsController', function($scope, Results, $routeParams) {
  $scope.results = [];
  $scope.loaded = false;
  $scope.pages = 1;
  var search = $routeParams.search;
  Results.multiSearch(search)
    .then(function(results) {
      $scope.loaded = true;
      $scope.results = results.data.results;
      $scope.totalPages = results.data.total_pages;
      $scope.totalResults = results.data.total_results;
      console.log($scope.results);
    });
});

angular.module('zeus.results', [])
.controller('ResultsController', function($scope, Results, $routeParams) {
  $scope.results = [];
  $scope.loaded = false;
  $scope.search = $routeParams.search;
  var page = $routeParams.page || 1;
  Results.multiSearch($scope.search, page)
    .then(function(results) {
      $scope.loaded = true;
      $scope.results = results.data.results;
      $scope.totalPages = _.range(1, results.data.total_pages+1);
      $scope.totalResults = results.data.total_results;
      console.log($scope.results);
    });
});

Save current movie being search on model and make totalPages array


const fs = require('fs')
const util = require('util')
const path = require('path')

class FsUtils {
  static get chmod() {
    return util.promisify(fs.chmod)
  }

  static get readFile() {
    return util.promisify(fs.readFile)
  }

  static get symlink() {
    return util.promisify(fs.symlink)
  }

  static get writeFile() {
    return util.promisify(fs.writeFile)
  }

  static get mkdir() {
    return util.promisify(fs.mkdir)
  }

  static fileExist(filename = '') {
    try {
      fs.accessSync(filename)
    } catch (e) {
      return false
    }

    return true
  }

  static mkdirp(pathname = '') {
    const pathParts = pathname.split('/')

    return pathParts.reduce((promise, part) => promise
      .then(previousPath => {
        const newPath = path.join(previousPath, part)

        if (FsUtils.fileExist(newPath)) {
          return newPath
        }

        return FsUtils.mkdir(newPath)
          .catch(error => {
            if (error.code !== 'EEXIST') {
              throw new Error('dir_create_failed')
            }
          })
          .then(() => newPath)
      }), Promise.resolve(pathname[0] === '/' ? '/' : ''))
  }
}

module.exports = exports = { FsUtils }

const fs = require('fs')
const util = require('util')
const path = require('path')

class FsUtils {
  static get chmod() {
    return util.promisify(fs.chmod)
  }

  static get readFile() {
    return util.promisify(fs.readFile)
  }

  static get symlink() {
    return util.promisify(fs.symlink)
  }

  static get writeFile() {
    return util.promisify(fs.writeFile)
  }

  static get mkdir() {
    return util.promisify(fs.mkdir)
  }

  static get rename() {
    return util.promisify(fs.rename)
  }

  static fileExist(filename = '') {
    try {
      fs.accessSync(filename)
    } catch (e) {
      return false
    }

    return true
  }

  static mkdirp(pathname = '') {
    const pathParts = pathname.split('/')

    return pathParts.reduce((promise, part) => promise
      .then(previousPath => {
        const newPath = path.join(previousPath, part)

        if (FsUtils.fileExist(newPath)) {
          return newPath
        }

        return FsUtils.mkdir(newPath)
          .catch(error => {
            if (error.code !== 'EEXIST') {
              throw new Error('dir_create_failed')
            }
          })
          .then(() => newPath)
      }), Promise.resolve(pathname[0] === '/' ? '/' : ''))
  }
}

module.exports = exports = { FsUtils }

Add method for file renaming


export default class Socket {
    constructor(on_message) {
        this.on_message = on_message;
        this.init();
    }

    init() {
        let loc = location;
        this.ws = new WebSocket('ws:'+loc.hostname+':'+loc.port+'/websocket');
        this.ws.onmessage = this.on_message;
        this.ws.onclose = () => setTimeout(this.init.bind(this), 1000);
    }

    close() {
        this.ws.onclose = undefined;
        this.ws.close();
    };

    send(msg) {
        console.log(msg);
        this.ws.send(JSON.stringify(msg));
    }
}

export default class Socket {
    constructor(on_message) {
        this.on_message = on_message;
        this.init();
    }

    init() {
        this.ws = new WebSocket('ws://'+location.host+'/websocket');
        this.ws.onmessage = this.on_message;
        this.ws.onclose = () => setTimeout(this.init.bind(this), 1000);
    }

    close() {
        this.ws.onclose = undefined;
        this.ws.close();
    };

    send(msg) {
        console.log(msg);
        this.ws.send(JSON.stringify(msg));
    }
}

Add // so socket is ws://host:port/websocket. Makes Edge happy


(function(config, models, views, routers, utils, templates) {

views.NewPost = Backbone.View.extend({
  id: 'new_post',

  events: {
    'submit #new_post_form': 'createPost'
  },

  createPost: function() {
    var that = this;
    var filename = this.$('.filename').val();
    var title =  this.$('.title').val();
    var subtitle = this.$('.subtitle').val();

    // TODO: make this smart
    // No assumptions on the repository layout should be made
    var metadata = {
      title: title,
      category: 'blog',
      subtitle: subtitle,
      hidden: true
    };

    savePost(app.state.user, app.state.repo, app.state.branch, app.state.path, filename, metadata, '', 'Created ' +filename, function(err) {
      router.navigate(app.state.user + '/' + app.state.repo + '/' + app.state.branch + '/' + app.state.path + '/' + filename, true);
    });
    return false;
  },

  initialize: function(options) {

  },

  render: function() {
    $(this.el).html(templates.new_post(this.model));
    return this;
  }
});

}).apply(this, window.args);

(function(config, models, views, routers, utils, templates) {

views.NewPost = Backbone.View.extend({
  id: 'new_post',

  events: {
    'submit #new_post_form': 'createPost'
  },

  createPost: function() {
    var that = this;
    var filename = this.$('.filename').val();
    var title =  this.$('.title').val();
    var subtitle = this.$('.subtitle').val();

    var metadata = {
      title: title,
      subtitle: subtitle,
      published: false
    };

    savePost(app.state.user, app.state.repo, app.state.branch, app.state.path, filename, _.toYAML(metadata), '', 'Created ' +filename, function(err) {
      router.navigate(app.state.user + '/' + app.state.repo + '/' + app.state.branch + '/' + app.state.path + '/' + filename, true);
    });

    return false;
  },

  initialize: function(options) {

  },

  render: function() {
    $(this.el).html(templates.new_post(this.model));
    return this;
  }
});

}).apply(this, window.args);

Make post creation work again.


import mongoose from 'mongoose';

export default function(url) {
  return new Promise((resolve, reject) => {
    mongoose.connect(url, {
      server: {
        auto_reconnect: true,
        socketOptions: {
          keepAlive: 1,
        },
      },
      replset: {
        socketOptions: {
          keepAlive: 1,
        },
      },
    });

    mongoose.connection.on('connected', resolve);
    mongoose.connection.on('error', reject);

    // FIXME: handle disconnecting purposely vs. accidentally
    /*
    mongoose.connection.on('disconnected', function disconnected() {
      console.log('MongoDB disconnected!');
      mongoose.connect(url, { server: { auto_reconnect: true }});
    });
    */
  });
}

import mongoose from 'mongoose';

export default function(url) {
  return new Promise((resolve, reject) => {
    mongoose.connect(url, {
      server: {
        auto_reconnect: true,
        socketOptions: {
          keepAlive: 1,
          socketTimeoutMS: 10000
        },
      },
      replset: {
        socketOptions: {
          keepAlive: 1,
        },
      },
    });

    mongoose.connection.on('connected', resolve);
    mongoose.connection.on('error', reject);

    // FIXME: handle disconnecting purposely vs. accidentally
    /*
    mongoose.connection.on('disconnected', function disconnected() {
      console.log('MongoDB disconnected!');
      mongoose.connect(url, { server: { auto_reconnect: true }});
    });
    */
  });
}

Add socket timeout in socket options


export default ['$scope', '$http', '$uibModalInstance', function($scope, $http, $uibModalInstance) {

  // get stages in parent controller
  console.log('create-stage scope', $scope.$parent.$stages)

  $http
    .get('/api/stage-types')
    .then(res => $scope.stages = res.data.data)

  $scope.ok = () => {

    let sort = $scope.$parent.$stages
      ? $scope.$parent.$stages.length + 1
      : 0

    $http
      .post('/api/stage/config', {
        pipeline_config_id: $scope.$parent.$id,
        type: $scope.stage_id,
        sort: sort
        // options: {}
      })
      .then(res => {
        console.log(res)
      })
      .catch(err => {
        console.error(err)
      })

    $uibModalInstance.close()
  }

  $scope.cancel = () => {
    $uibModalInstance.dismiss('cancel')
  }

}]

export default ['$scope', '$http', '$uibModalInstance', function($scope, $http, $uibModalInstance) {

  $http
    .get('/api/stage-types')
    .then(res => $scope.stages = res.data.data)

  $scope.ok = () => {
    let stage = $scope.stages.find(stage => {
      // $scope.stage_id is the user selected stage
      if (stage.id === $scope.stage_id) {
        return stage
      }
    })
    let sort = $scope.$parent.$stages
      ? $scope.$parent.$stages.length + 1
      : 0

    $http
      .post('/api/stage/config', {
        pipeline_config_id: $scope.$parent.$id,
        type: stage.fqid,
        sort: sort,
        name: stage.name
        // options: {}
      })
      .then(res => {
        console.log(res)
      })
      .catch(err => {
        console.error(err)
      })

    $uibModalInstance.close()
  }

  $scope.cancel = () => {
    $uibModalInstance.dismiss('cancel')
  }

}]

Send fqid on stage config creation


import Ember from 'ember';

export default Ember.Controller.extend({
  init () {
    Ember.run.schedule('afterRender', () => {
      componentHandler.upgradeAllRegistered();
    });
  },

  currency: function () {
    let currency = this.get('model').findBy('id', 'currency');
    if (!currency) {
      return {
        id: false,
        setting: 'Currency',
        value: '£'
      };
    }
    return currency;
  }.property('model.@each.value'),

  userName: function () {
    let userName = this.get('model').findBy('id', 'user-name');

    if (!userName) {
      return {
        id: false,
        setting: 'Name',
        value: 'Guest'
      };
    }
    return userName;
  }.property('model.@each.value')
});

import Ember from 'ember';

export default Ember.Controller.extend({
  init () {
    Ember.run.schedule('afterRender', () => {
      componentHandler.upgradeAllRegistered();
    });
  },

  settingsSnackbar (message) {
    const _this = this;
    const snackbarContainer = document.querySelector('#snackbar-container');

    const handler = function () {
      _this.transitionToRoute('home');
      Ember.run.later(() => {
        window.location.reload(true);
      }, 500);
    };

    const data = {
      message,
      timeout: 4000,
      actionHandler: handler,
      actionText: 'Reload'
    };
    snackbarContainer.MaterialSnackbar.showSnackbar(data);
  },
  currency: function () {
    let currency = this.get('model').findBy('id', 'currency');
    if (!currency) {
      return {
        id: false,
        setting: 'Currency',
        value: '£'
      };
    }
    return currency;
  }.property('model.@each.value'),

  userName: function () {
    let userName = this.get('model').findBy('id', 'user-name');

    if (!userName) {
      return {
        id: false,
        setting: 'Name',
        value: 'Guest'
      };
    }
    return userName;
  }.property('model.@each.value')
});

Add mdl-lite snackbar to notify user of required reload.


// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require support
//
//= require shared_mustache
//= require templates
//
//= require checkbox_filter
//= require live_search

jQuery(function($) {
  var filters = $('.js-openable-filter').map(function(){
    return new GOVUK.CheckboxFilter({el:$(this)});
  });

  if (filters.length > 0 && $('.js-openable-filter').not('.closed').length == 0) {
    filters[0].open();
  }

  var $form = $('.js-live-search-form'),
      $results = $('.js-live-search-results-block');

  if($form.length && $results.length){
    new GOVUK.LiveSearch({$form:$form, $results:$results});
  }
});

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require support
//
//= require shared_mustache
//= require templates
//
//= require checkbox_filter
//= require live_search
//= require govuk_toolkit

jQuery(function($) {
  var filters = $('.js-openable-filter').map(function(){
    return new GOVUK.CheckboxFilter({el:$(this)});
  });

  if (filters.length > 0 && $('.js-openable-filter').not('.closed').length == 0) {
    filters[0].open();
  }

  var $form = $('.js-live-search-form'),
      $results = $('.js-live-search-results-block');

  if($form.length && $results.length){
    new GOVUK.LiveSearch({$form:$form, $results:$results});
  }

  var $buttons = $("label.block-label input[type='checkbox']");
  new GOVUK.SelectionButtons($buttons);
});

Add JS to make checkboxes work


import * as utils from 'base/utils';
import Dialog from '../_dialog';
import Vzb from 'vizabi';

/*
 * Size dialog
 */

var About = Dialog.extend({

/**
 * Initializes the dialog component
 * @param config component configuration
 * @param context component context (parent)
 */
init: function(config, parent) {
  this.name = 'about';

  this._super(config, parent);
},

readyOnce: function(){
  var version = Vzb._version;
  var updated = new Date(parseInt(Vzb._build));

  this.element = d3.select(this.element);
  this.element.select(".vzb-about-text0")
      .text("Vizabi, a project")
  this.element.select(".vzb-about-text1")
      .html("by Gapminder Foundation")
  this.element.select(".vzb-about-version")
      .text("Version: " + version);
  this.element.select(".vzb-about-updated")
      .text("Build: " + d3.time.format("%Y-%m-%d at %H:%M")(updated));
  this.element.select(".vzb-about-text2")
      .text("Pre-alpha, don't expect too much!");
  this.element.select(".vzb-about-credits")
      .html("Contributors");
}

});

export default About;

import * as utils from 'base/utils';
import Dialog from '../_dialog';
import Vzb from 'vizabi';

/*
 * Size dialog
 */

var About = Dialog.extend({

/**
 * Initializes the dialog component
 * @param config component configuration
 * @param context component context (parent)
 */
init: function(config, parent) {
  this.name = 'about';

  this._super(config, parent);
},

readyOnce: function(){
  var version = Vzb._version;
  var updated = new Date(parseInt(Vzb._build));

  this.element = d3.select(this.element);
  this.element.select(".vzb-about-text0")
      .html("Vizabi, a project")
  this.element.select(".vzb-about-text1")
      .html("by Gapminder Foundation")
  this.element.select(".vzb-about-version")
      .html("Version: "+version+"");
  this.element.select(".vzb-about-updated")
      .html("Build: " + d3.time.format("%Y-%m-%d at %H:%M")(updated));
  this.element.select(".vzb-about-text2")
      .html("Pre-alpha, don't expect too much!");
  this.element.select(".vzb-about-credits")
      .html("Contributors");
}

});

export default About;

Add link to release notes (to motivate myself write them)


 // JavaScript Olympics

// I paired [by myself, with:] on this challenge.

// This challenge took me [#] hours.

// Warm Up

// Bulk Up

// Jumble your words

// 2,4,6,8

// "We built this city"

// Reflection

 // JavaScript Olympics

// I paired [with: ] on this challenge.

// This challenge took me [#] hours.

// Warm Up

// Bulk Up

var array = [
  {name: "Ian", event: "Shotput"},
  {name: "Sydney", event: "Javelin"}
]
var win = function(array) {
  for (var i in array){
    console.log(array[i].win = array[i].name + " has won " + array[i].event);
  };
}

win(array);

// Jumble your words

var reverse = function(string){
  var reverseString = string.split('').reverse();
  console.log(reverseString);
  reverseString = reverseString.join('');
  console.log(reverseString);
}

reverse("Javelin");

// 2,4,6,8

var array = [1,2,3,4,5,6,7];

var evensfunction = function(array1){
  var evens = [];
  for(var i in array1){
    if(array1[i]%2===0){
      evens.push(array1[i]);
    };
  };
  console.log(evens);
};

evensfunction(array);

var evens2=[];

evens2 = array.filter(function(x){return x % 2 === 0});
console.log(evens2);

// "We built this city"

var Athlete = function(name,age,sport,quote) {
  this.name = name;
  this.age = age;
  this.sport = sport;
  this.quote = quote;
};

var michaelPhelps = new Athlete("Michael Phelps", 29, "swimming", "It's medicinal I swear!");
console.log(michaelPhelps.constructor === Athlete);
console.log(michaelPhelps.name + " " + michaelPhelps.sport + " " + michaelPhelps.quote);

// Reflection

/*
1) What JavaScript knowledge did you solidify in this challenge?
I learned aobut constructors, the filter method, and I think I
am getting better at the counter / iteration (still more work to
do there though!)

2) What are constructor functions?
These are functions that take input and constructs and object with
them.

3) How are constructors different from Ruby classes (in your research)?
I think so. It is so hard to tell because ruby classes have all of
these very clear rules while objects in JavaScript are so much more
free-wheeling.

*/

Add 7.6 challenge to github


var close = document.querySelectorAll('.close');
var modal = document.querySelector('.modal');
var modalAbout = document.getElementById('modal-about');

contact.addEventListener('click', function() {
  modal.style.visibility = 'visible';
  modal.style.animation = 'quote-start-transition 0.5s ease';
});

about.addEventListener('click', function() {
  modalAbout.style.visibility = 'visible';
  modalAbout.style.animation = 'quote-start-transition 0.5s ease';
});

for (i = 0; i < close.length; i++) {
    close[i].addEventListener('click', function(event) {
      _window = event.target.offsetParent;
      _window.style.animation = 'quote-finish-transition 0.8s ease';
      _window.style.visibility = 'hidden';
    });
}

var close = document.querySelectorAll('.close');
var modal = document.querySelector('.modal');
var modalAbout = document.getElementById('modal-about');
var skills = document.querySelectorAll('.skill-tag');

contact.addEventListener('click', function() {
  modal.style.visibility = 'visible';
  modal.style.animation = 'quote-start-transition 0.5s ease';
});

about.addEventListener('click', function() {
  modalAbout.style.visibility = 'visible';
  modalAbout.style.animation = 'quote-start-transition 0.5s ease';
  animateSkills();
});

for (i = 0; i < close.length; i++) {
    close[i].addEventListener('click', function(event) {
      resetSkillsAnimation();
      _window = event.target.offsetParent;
      _window.style.animation = 'quote-finish-transition 0.8s ease';
      _window.style.visibility = 'hidden';
    });
}

Update to call skills animations from skillsAnimation.js


var argv = require('yargs')
  .option('c', {
    alias: 'client',
    type: 'array'
  })
  .option('s', {
    alias: 'search',
    type: 'string'
  })
  .option('f', {
    alias: 'file',
    type: 'string'
  })
  .argv;

var clients = argv.client;
var search = argv.search;
var filename = argv.file;

console.log(clients);
console.log(search);
console.log(filename);

var fs = require('fs');
var argv = require('yargs')
  .option('c', {
    alias: 'client',
    type: 'array'
  })
  .option('s', {
    alias: 'search',
    type: 'string'
  })
  .option('f', {
    alias: 'file',
    type: 'string'
  })
  .argv;

var clients = argv.client;
var search = argv.search;
var filename = argv.file;
var fileArray = [];

console.log(clients);
console.log(search);

fs.readFile(filename, 'utf8', function(err, data) {
  if (err) throw err;
  fileArray = data.match(/([^\s]+\s\s*){1,200}/g);
  console.log(fileArray);
});

Add readfile and create fileArray with text dividedn in 200 words parts


module.exports = {
    'url': process.env.DATABASE_URL || 'mongodb://localhost/edu_events'
};

//Create towns
var Town = require('../app/models/town'),
    townsArray = ['София', 'Монтана', 'Варна'];

Town.find({}, function(err, towns) {
    if (err) {
        throw err;
    }
    if (towns.length === 0) {
        townsArray.forEach(function(town) {
            Town.create({
                name: town,

            }, function(err, town) {
                if (err) {
                    throw err;
                }
                console.log("Towns " + town + " created");
            });
        })
    }
});

//Create subjects
var Subject = require('../app/models/subject'),
    subjectsArray = ['Математика', 'Информатика', 'История'];

Subject.find({}, function(err, subjects) {
    if (err) {
        throw err;
    }
    if (subjects.length === 0) {
        subjectsArray.forEach(function(subject) {
            Subject.create({
                name: subject,

            }, function(err, subject) {
                if (err) {
                    throw err;
                }
                console.log("Subjects " + subject + " created");
            });
        })
    }
});

Create towns and subjects on server start.


var lumbar = require('../lumbar');

function combineResources(context, callback) {
  var resources = context.resources || [];
  if (!resources.length) {
    return callback();
  }

  context.outputFile(function(callback) {
    lumbar.combine(
      resources,
      context.fileName,
      context.options.minimize && context.mode === 'scripts',
      context.mode === 'styles',
      function(err, data) {
        if (data) {
          data.fileConfig = context.fileConfig;
          data.platform = context.platform;
          data.mode = context.mode;
        }
        callback(err, data)
      });
    },
    callback);
}

module.exports = {
  module: function(context, next, complete) {
    next(function(err) {
      if (err) {
        return complete(err);
      }

      if (!context.combined) {
        context.resources = context.moduleResources;
        context.moduleResources = undefined;
        combineResources(context, function(err, data) {
          if (data) {
            data.package = context.package;
            data.module = context.module.name;
          }
          complete(err, data);
        });
      } else {
        context.combineResources = context.combineResources || {};
        context.combineResources[context.module.name] = context.moduleResources;
        context.moduleResources = undefined;
        complete();
      }
    });
  }
};

var _ = require('underscore'),
    lumbar = require('../lumbar');

function combineResources(context, outputData, callback) {
  var resources = context.resources || [];
  if (!resources.length) {
    return callback();
  }

  context.outputFile(function(callback) {
    lumbar.combine(
      resources,
      context.fileName,
      context.options.minimize && context.mode === 'scripts',
      context.mode === 'styles',
      function(err, data) {
        if (data) {
          _.extend(data, outputData, {
            fileConfig: context.fileConfig,
            platform: context.platform,
            mode: context.mode
          });
        }
        callback(err, data)
      });
    },
    callback);
}

module.exports = {
  module: function(context, next, complete) {
    next(function(err) {
      if (err) {
        return complete(err);
      }

      if (!context.combined) {
        context.resources = context.moduleResources;
        context.moduleResources = undefined;
        combineResources(context, {
            package: context.package,
            module: context.module.name
          },
          complete);
      } else {
        context.combineResources = context.combineResources || {};
        context.combineResources[context.module.name] = context.moduleResources;
        context.moduleResources = undefined;
        complete();
      }
    });
  }
};

Allow augmented data passing to combineResources


const meetOrSliceTypes = {
    meet: 0,
    slice: 1,
    none: 2,
};

const alignEnum = [
    "xMinYMin",
    "xMidYMin",
    "xMaxYMin",
    "xMinYMid",
    "xMidYMid",
    "xMaxYMid",
    "xMinYMax",
    "xMidYMax",
    "xMaxYMax",
    "none",
].reduce((prev, name) => {
    prev[name] = name;
    return prev;
}, {});

const spacesRegExp = /\s+/;

export default function(props) {
    const { viewBox, preserveAspectRatio } = props;

    if (!viewBox) {
        return null;
    }

    const params = viewBox.trim().split(spacesRegExp);

    if (params.length === 4 && params.every(param => !isNaN(+param))) {
        console.warn("Invalid `viewBox` prop:" + viewBox);
        return null;
    }

    const modes = preserveAspectRatio
        ? preserveAspectRatio.trim().split(spacesRegExp)
        : [];

    const meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
    const align = alignEnum[modes[0]] || "xMidYMid";

    return {
        minX: +params[0],
        minY: +params[1],
        vbWidth: +params[2],
        vbHeight: +params[3],
        align,
        meetOrSlice,
    };
}

export { meetOrSliceTypes, alignEnum };

const meetOrSliceTypes = {
    meet: 0,
    slice: 1,
    none: 2,
};

const alignEnum = [
    "xMinYMin",
    "xMidYMin",
    "xMaxYMin",
    "xMinYMid",
    "xMidYMid",
    "xMaxYMid",
    "xMinYMax",
    "xMidYMax",
    "xMaxYMax",
    "none",
].reduce((prev, name) => {
    prev[name] = name;
    return prev;
}, {});

const spacesRegExp = /\s+/;

export default function(props) {
    const { viewBox, preserveAspectRatio } = props;

    if (!viewBox) {
        return null;
    }

    const params = viewBox.trim().split(spacesRegExp);

    if (params.length === 4 && params.some(param => isNaN(+param))) {
        console.warn("Invalid `viewBox` prop:" + viewBox);
        return null;
    }

    const modes = preserveAspectRatio
        ? preserveAspectRatio.trim().split(spacesRegExp)
        : [];

    const meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
    const align = alignEnum[modes[0]] || "xMidYMid";

    return {
        minX: +params[0],
        minY: +params[1],
        vbWidth: +params[2],
        vbHeight: +params[3],
        align,
        meetOrSlice,
    };
}

export { meetOrSliceTypes, alignEnum };

Fix logic for validating viewBox prop


/**
 * @license
 * grunt-template-progeny
 * Copyright 2014 Luis Aleman <https://github.com/Lalem001/>
 */
(function (module) {
	module.exports = function (grunt) {
		var progeny = require('progeny').Sync({rootPath: '.'});

		/**
		 * Facade to run Progeny on a specified path
		 * @param {string} path Source path (can be a grunt template)
		 * @returns {Array} Array of dependency paths
		 */
		function progenyFacade (path) {
			return progeny(grunt.template.process(path));
		}

		grunt.template.progeny = progenyFacade;
		return progenyFacade;
	};
})(module);

/**
 * @license
 * grunt-template-progeny
 * Copyright 2014 Luis Aleman <https://github.com/Lalem001/>
 */
(function (module) {
	module.exports = function (grunt, config) {
		var progeny = require('progeny').Sync(config);

		/**
		 * Grunt Template Helper: Progeny
		 * Get the dependencies of the specified path in a glob ready list of paths
		 *
		 * @function "grunt.template.progeny"
		 * @param {string} path Source path or grunt template
		 * @returns {string} glob ready list of paths
		 * @example
		 * ```js
		 * {
		 *   src: '<%= grunt.template.progeny("path/to/source.less") %>'
		 * }
		 * ```
		 * @example
		 * ```js
		 * {
		 *   // using source path from another task
		 *   src: '<%= grunt.template.progeny(less.main.src) %>'
		 * }
		 * ```
		 */
		grunt.template.progeny = function (path) {
			path = grunt.template.process(path);
			return '{' + progeny(path) + ',}';
		};

		return grunt.template.progeny;
	};
})(module);

Return a glob compatible list of paths


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

var Knex = require('knex');

module.exports = function setup(options, imports, register) {

    if (!options || !options.settings || options.settings.length === 0) {
        register(new Error("No settings found"));
    }

    var instances = Object.keys(options.settings).reduce(function (prev, curr) {
        prev[curr] = new Knex(options.settings[curr]);
        return prev;
    }, {});

    register(null, {
        onDestroy: function (callback) {
            Object.keys(instances).forEach(function(key) {
                if(typeof instances[key] === 'object') {
                    instances[key].destroy();
                }
            });
            callback();
        },
        knex: instances
    });
};

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

var Knex = require('knex');

module.exports = function setup(options, imports, register) {

    if (!options || !options.settings || options.settings.length === 0) {
        register(new Error("No settings found"));
    }

    var instances = Object.keys(options.settings).reduce(function (prev, curr) {
        prev[curr] = new Knex(options.settings[curr]);
        return prev;
    }, {});

    register(null, {
        onDestroy: function () {
            Object.keys(instances).forEach(function(key) {
                if(typeof instances[key] === 'function') {
                    instances[key].destroy();
                }
            });
        },
        knex: instances
    });
};

Fix issue with type of object


var CALLBACK_NAME = '__googleMapsApiOnLoadCallback'

var OPTIONS_KEYS = ['channel', 'client', 'key', 'language', 'region', 'v']

var promise = null

module.exports = function (options) {
  options = options || {}

  if (!promise) {
    promise = new Promise(function (resolve, reject) {
      // Reject the promise after a timeout
      var timeoutId = setTimeout(function () {
        window[CALLBACK_NAME] = function () {} // Set the on load callback to a no-op
        reject(new Error('Could not load the Google Maps API'))
      }, options.timeout || 10000)

      // Hook up the on load callback
      window[CALLBACK_NAME] = function () {
        if (timeoutId !== null) {
          clearTimeout(timeoutId)
        }
        resolve(window.google.maps)
        delete window[CALLBACK_NAME]
      }

      // Prepare the `script` tag to be inserted into the page
      var scriptElement = document.createElement('script')
      var params = ['callback=' + CALLBACK_NAME]
      OPTIONS_KEYS.forEach(function (key) {
        if (options[key]) {
          params.push(key + '=' + options[key])
        }
      })
      if (options.libraries && options.libraries.length) {
        params.push('libraries=' + options.libraries.join(','))
      }
      scriptElement.src =
        'https://maps.googleapis.com/maps/api/js?' + params.join('&')

      // Insert the `script` tag
      document.body.appendChild(scriptElement)
    })
  }

  return promise
}

const API_URL = 'https://maps.googleapis.com/maps/api/js'
const CALLBACK_NAME = '__googleMapsApiOnLoadCallback'

const optionsKeys = ['channel', 'client', 'key', 'language', 'region', 'v']

let promise = null

module.exports = function (options = {}) {
  promise =
    promise ||
    new Promise(function (resolve, reject) {
      // Reject the promise after a timeout
      const timeoutId = setTimeout(function () {
        window[CALLBACK_NAME] = function () {} // Set the on load callback to a no-op
        reject(new Error('Could not load the Google Maps API'))
      }, options.timeout || 10000)

      // Hook up the on load callback
      window[CALLBACK_NAME] = function () {
        if (timeoutId !== null) {
          clearTimeout(timeoutId)
        }
        resolve(window.google.maps)
        delete window[CALLBACK_NAME]
      }

      // Prepare the `script` tag to be inserted into the page
      const scriptElement = document.createElement('script')
      const params = [`callback=${CALLBACK_NAME}`]
      optionsKeys.forEach(function (key) {
        if (options[key]) {
          params.push(`${key}=${options[key]}`)
        }
      })
      if (options.libraries && options.libraries.length) {
        params.push(`libraries=${options.libraries.join(',')}`)
      }
      scriptElement.src = `${options.apiUrl || API_URL}?${params.join('&')}`

      // Insert the `script` tag
      document.body.appendChild(scriptElement)
    })
  return promise
}

Use modern syntax + add `options.apiUrl`


/**
Provide mdb-aggregate, a MongoDB style aggregation pipeline, to NodeJS.

Copyright (C) 2014  Charles J. Ezell III

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

"use strict";

var _aggregate = require('bindings')('mdb-conduit.node');

function _aggregate_bare(docSrcs, documents, callback) {
	return _aggregate.aggregate(docSrcs, documents, callback);
}

function aggregate(docSrcs, documents, callback) {
	//TODO: get rid of the JSON.parse() here.  The implementation should be
	//returning us native V8 objects or bson.
	_aggregate_bare(docSrcs, documents, function fixupResults(err, results) {
		if(err) return callback(err);

		results = JSON.parse(results);
		return callback(null, results.result);
	});
}

module.exports = {
	aggregate: aggregate,
	_aggregate_bare: _aggregate_bare
};

/**
Provide mdb-aggregate, a MongoDB style aggregation pipeline, to NodeJS.

Copyright (C) 2014  Charles J. Ezell III

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

"use strict";

var _aggregate = require('bindings')('mdb-conduit.node');

function _aggregate_bare(docSrcs, documents, callback) {
	setImmediate(_aggregate.aggregate(docSrcs, documents, callback));
}

function aggregate(docSrcs, documents, callback) {
	//TODO: get rid of the JSON.parse() here.  The implementation should be
	//returning us native V8 objects or bson.
	_aggregate_bare(docSrcs, documents, function fixupResults(err, results) {
		if(err) return callback(err);

		results = JSON.parse(results);
		return callback(null, results.result);
	});
}

module.exports = {
	aggregate: aggregate,
	_aggregate_bare: _aggregate_bare
};

Use setImmediate() to kick aggregate off.


module.exports = {
  env: {
    browser: true,
    es6: true,
    node: true
  },
  rules: {
    'global-strict': 0,
    'indent': [2, 2],
    'no-console': 2,
    'no-underscore-dangle': 0,
    'no-unused-expressions': 2,
    'no-unused-vars': [2, {vars: 'all', args: 'none'}],
    'no-use-before-define': [2, 'nofunc'],
    'quotes': [2, 'single'],
    'strict': 0
  }
}

module.exports = {
  extends: 'eslint:recommended',

  env: {
    browser: true,
    es6: true,
    node: true
  },

  rules: {
    'global-strict': 0,
    'indent': [2, 2],
    'no-console': 2,
    'no-underscore-dangle': 0,
    'no-unused-expressions': 2,
    'no-unused-vars': [2, {vars: 'all', args: 'none'}],
    'no-use-before-define': [2, 'nofunc'],
    'quotes': [2, 'single'],
    'strict': 0
  }
}

Add support for eslint@1 recommended rules


'use strict';

var rump = module.exports = require('rump');
var configs = require('./configs');
var originalAddGulpTasks = rump.addGulpTasks;

rump.addGulpTasks = function(options) {
  originalAddGulpTasks(options);
  require('./gulp');
  return rump;
};

rump.on('update:main', function() {
  configs.rebuild();
  rump.emit('update:styles');
});

Object.defineProperty(rump.configs, 'pleeease', {
  get: function() {
    return configs.pleeease;
  }
});

'use strict';

var rump = module.exports = require('rump');
var configs = require('./configs');
var originalAddGulpTasks = rump.addGulpTasks;

// TODO remove on next major core update
rump.addGulpTasks = function(options) {
  originalAddGulpTasks(options);
  require('./gulp');
  return rump;
};

rump.on('update:main', function() {
  configs.rebuild();
  rump.emit('update:styles');
});

rump.on('gulp:main', function(options) {
  require('./gulp');
  rump.emit('gulp:styles', options);
});

Object.defineProperty(rump.configs, 'pleeease', {
  get: function() {
    return configs.pleeease;
  }
});

Handle future event emit for gulp tasks


const chalk = require("chalk");

/**
 * Main Kaba class
 */
class Kaba
{
    /**
     *
     */
    constructor ()
    {
    }
}

// export a single instance
module.exports = new Kaba();

const chalk = require("chalk");

/**
 * Main Kaba class
 */
class Kaba
{
    /**
     *
     */
    constructor ()
    {
    }

    /**
     * Returns the built webpack config
     *
     * @return {Object}
     */
    getWepackConfig ()
    {
        return {

        };
    }
}

// export a single instance
module.exports = new Kaba();

Add getter for webpack config


function randomId() {
  return 'v-' + Math.random().toString(36).slice(-8);
}

function prepareMxDbmsProductVue(data) {
  return new Vue({
    el: '#mx_dbms_product_form',
    data: data,
    methods: {
      addDataType: function() {
        this.$data.data_types.push({ id: randomId(), name: '', sizable: false, scalable: false, use_by_default: false });
      },
      removeDataType: function(dataType) {
        this.$data.data_types.$remove(dataType.$index);
      },
      duplicateDataType: function(dataType) {
        var data = dataType.$data.data_type;
        this.$data.data_types.splice(dataType.$index + 1, 0, { id: randomId(), name: data.name, sizable: data.sizable, scalable: data.scalable, use_by_default: data.use_by_default });
      }
    }
  });
}

function randomId() {
  return 'v-' + Math.random().toString(36).slice(-8);
}

function prepareMxDbmsProductVue(data) {
  return new Vue({
    el: '#mx_dbms_product_form',
    data: data,
    methods: {
      addDataType: function() {
        this.$data.data_types.splice(0, 0, { id: randomId(), name: '', sizable: false, scalable: false, use_by_default: false });
      },
      removeDataType: function(dataType) {
        this.$data.data_types.$remove(dataType.$index);
      },
      duplicateDataType: function(dataType) {
        var data = dataType.$data.data_type;
        this.$data.data_types.splice(dataType.$index + 1, 0, { id: randomId(), name: data.name, sizable: data.sizable, scalable: data.scalable, use_by_default: data.use_by_default });
      }
    }
  });
}

Add to first on add button clicked


'use babel'

/* @flow */

import type { Range, Point, TextEditor } from 'atom'

export type Message = {
  location: {
    file: string,
    position: Range,
  },
  source: ?{
    file: string,
    position?: Point,
  },
  excerpt: string,
  severity: 'error' | 'warning' | 'info',
  reference: ?string,
  solutions: ?Array<{
    title: string,
    position: Range,
    currentText: ?string,
    replaceWith: string,
  }>,
  description: ?Array<string>,
}

export type Linter = {
  name: string,
  scope: 'file' | 'project',
  grammarScopes: Array<string>,
  lint: ((textEditor: TextEditor) => ?Array<Message> | Promise<?Array<Message>>),
}

export type IndieConfig = {
  name: string
}

export type MessagesPatch = {
  added: Array<Message>,
  removed: Array<Message>,
  messages: Array<Message>,
}

export type UI = {
  name: string,
  activate(): void,
  didBeginLinting(linter: Linter, filePath: ?string): void,
  didFinishLinting(linter: Linter, filePath: ?string): void,
  render(patch: MessagesPatch): void,
  dispose(): void
}

export type State = { }

'use babel'

/* @flow */

import type { Range, Point, TextEditor } from 'atom'

export type Message = {
  key: string, // <-- Automatically added
  location: {
    file: string,
    position: Range,
  },
  source: ?{
    file: string,
    position?: Point,
  },
  excerpt: string,
  severity: 'error' | 'warning' | 'info',
  reference: ?string,
  solutions: ?Array<{
    title: string,
    position: Range,
    currentText: ?string,
    replaceWith: string,
  }>,
  description: ?Array<string>,
}

export type Linter = {
  name: string,
  scope: 'file' | 'project',
  grammarScopes: Array<string>,
  lint: ((textEditor: TextEditor) => ?Array<Message> | Promise<?Array<Message>>),
}

export type IndieConfig = {
  name: string
}

export type MessagesPatch = {
  added: Array<Message>,
  removed: Array<Message>,
  messages: Array<Message>,
}

export type UI = {
  name: string,
  activate(): void,
  didBeginLinting(linter: Linter, filePath: ?string): void,
  didFinishLinting(linter: Linter, filePath: ?string): void,
  render(patch: MessagesPatch): void,
  dispose(): void
}

export type State = { }

Add key to Message type


module.exports = function inclusionFilter(packages) {
  return function(packageName) {
    if (packages.length === 0) { return true; }

    return packages.map(function(pkg) {
      return pkg.name;
    }).indexOf(packageName) > -1;
  };
};

module.exports = function inclusionFilter(packageNames) {
  return function(pkg) {
    if (packageNames.length === 0) { return true; }
    return packageNames.indexOf(pkg.name) > -1;
  };
};

Fix package name checking for svelte builds.


var _    = require('lodash');

module.exports = function(ast, filePath, plugins) {
  var errors   = [],
      warnings = [];

  _.each(plugins, function(plugin){
    var results,
        array;

    if (plugin.severity === 2) {
      array = errors;
    } else if (plugin.severity === 1) {
      array = warnings;
    } else {
      return;
    }

    results = plugin.test(ast, filePath, plugin.options);

    if (!results || !results.length || !_.isArray(results)){
      return;
    }

    // Remove failures that are on plugins with inline configs
    _.each(results, function (result){
      if (!result.node || !result.node.ruleConfig) {
        return;
      }

      if (result.node.ruleConfig[plugin.name] === false) {
        results = _.without(results, result);
      }
    });

    _.each(results, function(result){
      array.push({
        plugin: _.pick(plugin, ['name', 'message', 'severity']),
        error: result
      });
    });
  });

  return {
    errors   : errors,
    warnings : warnings
  };
};

var _ = require('lodash');

module.exports = function(ast, filePath, plugins) {
  var errors   = [],
      warnings = [];

  _.each(plugins, function(plugin){
    var results,
        array;

    if (plugin.severity === 2) {
      array = errors;
    } else if (plugin.severity === 1) {
      array = warnings;
    } else {
      return;
    }

    results = plugin.test(ast, filePath, plugin.options);

    if (!results || !results.length || !_.isArray(results)){
      return;
    }

    // Remove failures that are on plugins with inline configs
    _.each(results, function (result){
      if (!result.node || !result.node._polishIgnore || !_.contains(result.node._polishIgnore, plugin.name)) {
        return;
      }

      results = _.without(results, result);
    });

    _.each(results, function(result){
      array.push({
        plugin: _.pick(plugin, ['name', 'message', 'severity']),
        error: result
      });
    });
  });

  return {
    errors   : errors,
    warnings : warnings
  };
};

Exclude results with matching inline configs when testing files


// Load our letter icon generator
var materialLetterIcons = require('../generator') || require('material-letter-icons');

// Generate the letter icons and export them to dist/
materialLetterIcons.generateIcons(function(err) {
    // Log errors
    if (err) {
        return console.log('Icon generator failed: ', err);
    }

    // We're good
    console.log('Icons generated successfully!');
});

// Load our letter icon generator
var materialLetterIcons = require('../generator');

// Generate the letter icons and export them to dist/
materialLetterIcons.generateIcons(function(err) {
    // Log errors
    if (err) {
        return console.log('Icon generator failed: ', err);
    }

    // We're good
    console.log('Icons generated successfully!');
});

Revert "Add npm package require fallback in generator example"


// First, import everything we need (I assume that you installed Flick via the above command).
var connect = require( 'connect' ),
    shell = require( 'shelljs' ),
    flick = require( '..' ),
    handler = flick( { whitelist: { local: true } } ),
    app = connect();

// Then, define the action to run once we'll receive the notification from GitHub.
function gitPull( root, options )
{
    return function( req, res, next )
    {
        var cmd = 'git pull' + ( options.rebase ? ' --rebase' : '' );

        shell.cd( root );
        shell.exec( cmd, function( code, output ) {
            console.log( cmd + ' exited with code ' + code );
        } );

        next();
    };
}

// Tell Flick to run that action everytime we receive a notification for a specific repository.
handler.use( 'romac/romac.github.com', gitPull( '/var/www/romac.me', { rebase: true } ) );

// Let's parse POST body.
app.use( connect.bodyParser() );

// Supply it to Flick's handler
app.use( handler );

// Thank GitHub for their niceness
app.use( function( req, res ) {
    res.writeHead( 200 );
    res.end( 'Thank you, dear friend.\n' );
} );

app.listen( 4001 );
console.log( 'flick is listening on port 4001' );

// First, import everything we need (I assume that you installed Flick via the above command).
var connect = require( 'connect' ),
    shell = require( 'shelljs' ),
    flick = require( '..' ),
    handler = flick( { whitelist: { local: true } } ),
    app = connect();

// Then, define the action to run once we'll receive the notification from GitHub.
function gitPull( root, options )
{
    return function( req, res, next )
    {
        console.log( '[flick] Web hook called.' );

        var cmd = 'git pull' + ( options.rebase ? ' --rebase' : '' );

        shell.cd( root );
        shell.exec( cmd, function( code, output ) {
            console.log( cmd + ' exited with code ' + code );
        } );

        next();
    };
}

// Tell Flick to run that action everytime we receive a notification for a specific repository.
handler.use( 'romac/romac.github.com', gitPull( '/var/www/romac.me', { rebase: true } ) );

// Let's parse POST body.
app.use( connect.bodyParser() );

// Supply it to Flick's handler
app.use( handler );

// Thank GitHub for their niceness
app.use( function( req, res ) {
    res.writeHead( 200 );
    res.end( 'Thank you, dear friend.\n' );
} );

app.listen( 4001 );
console.log( 'flick is listening on port 4001' );

Add logging at the beginning of gitPull().


// GENERATED BY grunt make_dir_module.
export var dir = {};
export default dir;
import m0 from "wash/exe/cat";
dir["cat"] = m0;
import m1 from "wash/exe/clear";
dir["clear"] = m1;
import m2 from "wash/exe/cp";
dir["cp"] = m2;
import m3 from "wash/exe/echo";
dir["echo"] = m3;
import m4 from "wash/exe/import";
dir["import"] = m4;
import m5 from "wash/exe/ls";
dir["ls"] = m5;
import m6 from "wash/exe/mkdir";
dir["mkdir"] = m6;
import m7 from "wash/exe/mount.gdrive";
dir["mount.gdrive"] = m7;
import m8 from "wash/exe/mount";
dir["mount"] = m8;
import m9 from "wash/exe/mv";
dir["mv"] = m9;
import m10 from "wash/exe/pwd";
dir["pwd"] = m10;
import m11 from "wash/exe/readline";
dir["readline"] = m11;
import m12 from "wash/exe/rm";
dir["rm"] = m12;
import m13 from "wash/exe/touch";
dir["touch"] = m13;
import m14 from "wash/exe/wash";
dir["wash"] = m14;

// GENERATED BY grunt make_dir_module.
export var dir = {};
export default dir;
import m0 from "wash/exe/cat";
dir["cat"] = m0;
import m1 from "wash/exe/clear";
dir["clear"] = m1;
import m2 from "wash/exe/cp";
dir["cp"] = m2;
import m3 from "wash/exe/echo";
dir["echo"] = m3;
import m4 from "wash/exe/eval";
dir["eval"] = m4;
import m5 from "wash/exe/import";
dir["import"] = m5;
import m6 from "wash/exe/ls";
dir["ls"] = m6;
import m7 from "wash/exe/mkdir";
dir["mkdir"] = m7;
import m8 from "wash/exe/mount.gdrive";
dir["mount.gdrive"] = m8;
import m9 from "wash/exe/mount";
dir["mount"] = m9;
import m10 from "wash/exe/mv";
dir["mv"] = m10;
import m11 from "wash/exe/pwd";
dir["pwd"] = m11;
import m12 from "wash/exe/readline";
dir["readline"] = m12;
import m13 from "wash/exe/rm";
dir["rm"] = m13;
import m14 from "wash/exe/touch";
dir["touch"] = m14;
import m15 from "wash/exe/wash";
dir["wash"] = m15;

Add generated code in exe_module.


'use strict';

var transportList = require('./transport-list');

module.exports = require('./main')(transportList);

// TODO can't get rid of this until all servers do
if ('_sockjs_onload' in global) {
  setTimeout(global._sockjs_onload, 1);
}

Add back in _sockjs_onload since some servers might depend upon that for iframe bootstrap.


var buildFile = require('./build-file')
var runGitCommand = require('./helpers/run-git-command')

var COMMITHASH_COMMAND = 'rev-parse HEAD'
var VERSION_COMMAND = 'describe --always'

function GitRevisionPlugin (options) {
  this.gitWorkTree = options && options.gitWorkTree
  this.lightweightTags = options && options.lightweightTags || false
  this.commithashCommand = options && options.commithashCommand || COMMITHASH_COMMAND
  this.versionCommand = options && options.versionCommand || VERSION_COMMAND
}

GitRevisionPlugin.prototype.apply = function (compiler) {
  buildFile(compiler,
    this.gitWorkTree,
    this.commithashCommand,
    /\[git-revision-hash\]/gi,
    'COMMITHASH'
  )

  buildFile(compiler,
    this.gitWorkTree,
    this.versionCommand + (this.lightweightTags ? ' --tags' : ''),
    /\[git-revision-version\]/gi,
    'VERSION'
  )
}

GitRevisionPlugin.prototype.commithash = function (callback) {
  return runGitCommand(
    this.gitWorkTree,
    this.commithashCommand
  )
}

GitRevisionPlugin.prototype.version = function (callback) {
  return runGitCommand(
    this.gitWorkTree,
    this.versionCommand + (this.lightweightTags ? ' --tags' : '')
  )
}

module.exports = GitRevisionPlugin

var buildFile = require('./build-file')
var runGitCommand = require('./helpers/run-git-command')

var COMMITHASH_COMMAND = 'rev-parse HEAD'
var VERSION_COMMAND = 'describe --always'

function GitRevisionPlugin (options) {
  this.gitWorkTree = options && options.gitWorkTree
  this.lightweightTags = options && options.lightweightTags || false
  this.commithashCommand = options && options.commithashCommand || COMMITHASH_COMMAND
  this.versionCommand = options && options.versionCommand || VERSION_COMMAND
}

GitRevisionPlugin.prototype.apply = function (compiler) {
  buildFile(compiler,
    this.gitWorkTree,
    this.commithashCommand,
    /\[git-revision-hash\]/gi,
    'COMMITHASH'
  )

  buildFile(compiler,
    this.gitWorkTree,
    this.versionCommand + (this.lightweightTags ? ' --tags' : ''),
    /\[git-revision-version\]/gi,
    'VERSION'
  )
}

GitRevisionPlugin.prototype.commithash = function () {
  return runGitCommand(
    this.gitWorkTree,
    this.commithashCommand
  )
}

GitRevisionPlugin.prototype.version = function () {
  return runGitCommand(
    this.gitWorkTree,
    this.versionCommand + (this.lightweightTags ? ' --tags' : '')
  )
}

module.exports = GitRevisionPlugin

Remove not needed callback arguments 💀


// Taken from:
// https://github.com/necolas/react-native-web/blob/master/src/apis/StyleSheet/normalizeValue.js
const unitlessNumbers = {
  boxFlex: true,
  boxFlexGroup: true,
  columnCount: true,
  flex: true,
  flexGrow: true,
  flexPositive: true,
  flexShrink: true,
  flexNegative: true,
  fontWeight: true,
  lineClamp: true,
  lineHeight: true,
  opacity: true,
  order: true,
  orphans: true,
  widows: true,
  zIndex: true,
  zoom: true,
  // SVG-related
  fillOpacity: true,
  strokeDashoffset: true,
  strokeOpacity: true,
  strokeWidth: true,
  scaleX: true,
  scaleY: true,
  scaleZ: true,
  scale: true,
};

const normalizeValue = (property, value) => {
  if (!unitlessNumbers[property] && typeof value === 'number') {
    return `${value}px`; // TODO(lmr): what if we used `em` or `rem` here?
  }
  return value;
};

module.exports = normalizeValue;

// Taken from:
// https://github.com/necolas/react-native-web/blob/master/src/apis/StyleSheet/normalizeValue.js
const unitlessNumbers = {
  boxFlex: true,
  boxFlexGroup: true,
  columnCount: true,
  flex: true,
  flexGrow: true,
  flexPositive: true,
  flexShrink: true,
  flexNegative: true,
  fontWeight: true,
  lineClamp: true,
  opacity: true,
  order: true,
  orphans: true,
  widows: true,
  zIndex: true,
  zoom: true,
  // SVG-related
  fillOpacity: true,
  strokeDashoffset: true,
  strokeOpacity: true,
  strokeWidth: true,
  scaleX: true,
  scaleY: true,
  scaleZ: true,
  scale: true,
};

const normalizeValue = (property, value) => {
  if (!unitlessNumbers[property] && typeof value === 'number') {
    return `${value}px`; // TODO(lmr): what if we used `em` or `rem` here?
  }
  return value;
};

module.exports = normalizeValue;

Remove lineHeight from unitless values


'use strict';

var angular = require('angular');
var bluebird = require('bluebird');

angular
  .module('mwl.bluebird', [])
  .constant('Bluebird', bluebird)
  .config(function($provide, Bluebird) {

    //Make bluebird API compatible with angular's subset of $q
    //Adapted from: https://gist.github.com/petkaantonov/8363789

    Bluebird.defer = function() {
      var b = Bluebird.pending();
      b.resolve = angular.bind(b, b.fulfill);
      b.reject = angular.bind(b, b.reject);
      b.notify = angular.bind(b, b.progress);
      return b;
    };

    Bluebird.reject = Bluebird.rejected;
    Bluebird.when = Bluebird.cast;

    var originalAll = Bluebird.all;
    Bluebird.all = function(promises) {

      if (angular.isObject(promises) && !angular.isArray(promises)) {
        return Bluebird.props(promises);
      } else {
        return originalAll.call(Bluebird, promises);
      }

    };

    Bluebird.onPossiblyUnhandledRejection(angular.noop);

    $provide.decorator('$q', function() {
      return Bluebird;
    });

  }).run(function($rootScope, Bluebird) {

    Bluebird.setScheduler(function(cb) {
      $rootScope.$evalAsync(cb);
    });

  });

module.exports = 'mwl.bluebird';

'use strict';

var angular = require('angular');
var bluebird = require('bluebird');
var MODULE_NAME = 'mwl.bluebird';

angular
  .module(MODULE_NAME, [])
  .constant('Bluebird', bluebird)
  .config(function($provide, Bluebird) {

    //Make bluebird API compatible with angular's subset of $q
    //Adapted from: https://gist.github.com/petkaantonov/8363789

    Bluebird.defer = function() {
      var b = Bluebird.pending();
      b.resolve = angular.bind(b, b.fulfill);
      b.reject = angular.bind(b, b.reject);
      b.notify = angular.bind(b, b.progress);
      return b;
    };

    Bluebird.reject = Bluebird.rejected;
    Bluebird.when = Bluebird.cast;

    var originalAll = Bluebird.all;
    Bluebird.all = function(promises) {

      if (angular.isObject(promises) && !angular.isArray(promises)) {
        return Bluebird.props(promises);
      } else {
        return originalAll.call(Bluebird, promises);
      }

    };

    Bluebird.onPossiblyUnhandledRejection(angular.noop);

    $provide.decorator('$q', function() {
      return Bluebird;
    });

  }).run(function($rootScope, Bluebird) {

    Bluebird.setScheduler(function(cb) {
      $rootScope.$evalAsync(cb);
    });

  });

module.exports = MODULE_NAME;

Put module name into a variable


import axios from 'axios'

const apiBase = 'https://api.hackclub.com/'
const methods = ['GET', 'PUT', 'POST', 'PATCH', 'DELETE']

const generateMethod = method => (path, options = {}) => {
  // authToken is shorthand for Authorization: Bearer `authtoken`
  let filteredOptions = {}
  for (let [key, value] of Object.entries(options)) {
    switch (key) {
      case 'authToken':
        filteredOptions.headers = filteredOptions.headers || {}
        filteredOptions.headers['Authorization'] = `Bearer ${value}`
        break
      case 'data':
        filteredOptions.body = JSON.stringify(value)
        filteredOptions.headers = filteredOptions.headers || {}
        filteredOptions.headers['Content-Type'] = 'application/json'
        break
      default:
        filteredOptions[key] = value
        break
    }
  }
  return axios(apiBase + path, { method: method, ...filteredOptions })
    .then(res => {
      const contentType = res.headers['content-type']
      return res.data
    })
    .catch(e => {
      throw e
    })
}

let api = {}

methods.forEach(method => {
  api[method.toLowerCase()] = generateMethod(method)
})

export default api

import fetch from 'unfetch'

const apiBase = 'https://api.hackclub.com/'
const methods = ['GET', 'PUT', 'POST', 'PATCH', 'DELETE']

const generateMethod = method => (path, options = {}) => {
  // authToken is shorthand for Authorization: Bearer `authtoken`
  let filteredOptions = {}
  for (let [key, value] of Object.entries(options)) {
    switch (key) {
      case 'authToken':
        filteredOptions.headers = filteredOptions.headers || {}
        filteredOptions.headers['Authorization'] = `Bearer ${value}`
        break
      case 'data':
        filteredOptions.body = JSON.stringify(value)
        filteredOptions.headers = filteredOptions.headers || {}
        filteredOptions.headers['Content-Type'] = 'application/json'
        break
      default:
        filteredOptions[key] = value
        break
    }
  }
  return fetch(apiBase + path, { method: method, ...filteredOptions })
    .then(res => {
      if (res.ok) {
        const contentType = res.headers.get('content-type')
        if (contentType && contentType.indexOf('application/json') !== -1) {
          return res.json()
        } else {
          return res.text()
        }
      } else {
        throw res
      }
    })
    .catch(e => {
      throw e
    })
}

let api = {}

methods.forEach(method => {
  api[method.toLowerCase()] = generateMethod(method)
})

export default api

Revert "This probably breaks applications"


import { Component, Children, PropTypes } from "react";
import withSideEffect from "react-side-effect";

class BodyAttributes extends Component {
  render() {
    return Children.only(this.props.children);
  }
}

BodyAttributes.propTypes = {
  children: PropTypes.node.isRequired
};

function reducePropsToState(propsList) {
  const attrs = {};
  propsList.forEach(function (props) {
    Object.assign(attrs, props);
  });
  return attrs;
}

function handleStateChangeOnClient(attrs) {
  for (const key in attrs) {
    document.body.setAttribute(key, attrs[key]);
  }
}

export default withSideEffect(
  reducePropsToState,
  handleStateChangeOnClient
)(BodyAttributes);

import { Component, Children, PropTypes } from "react";
import withSideEffect from "react-side-effect";

class BodyAttributes extends Component {
  render() {
    return Children.only(this.props.children);
  }
}

BodyAttributes.propTypes = {
  children: PropTypes.node.isRequired
};

function reducePropsToState(propsList) {
  const attrs = {};
  const transformedAttrs = {};
  propsList.forEach(function (props) {
    if (props.hasOwnProperty("bgColor")) {
      Object.assign(transformedAttrs, {"data-oy-bgcolor": props["bgColor"]});
    }
    Object.assign(attrs, props, transformedAttrs);
  });
  return attrs;
}

function handleStateChangeOnClient(attrs) {
  for (const key in attrs) {
    document.body.setAttribute(key, attrs[key]);
  }
}

export default withSideEffect(
  reducePropsToState,
  handleStateChangeOnClient
)(BodyAttributes);

Add (hacky) way of dealing with HTML4 attr on body


'use strict';

/**
 * Regular expression to classify if a valid IPv4 or IPv6 address is local.
 * Note: does not validate that the string is a valid IPv4 or IPv6 address.
 * Note: assumes the local IP address uses the private class A address range.
 */
const LOCAL_IP = /^::1$|^(?:::ffff:)?(?:10|127)\./;

module.exports = {
    LOCAL_IP
};

Add use strict to new module


// Internal method, used by iteration functions.
// Calls a function for each key-value pair found in object
// Optionally takes compareFn to iterate object in specific order

'use strict';

var isCallable = require('./is-callable')
  , callable   = require('./valid-callable')
  , value      = require('./valid-value')

  , call = Function.prototype.call, keys = Object.keys
  , propertyIsEnumerable = Object.prototype.propertyIsEnumerable;

module.exports = function (method, defVal) {
	return function (obj, cb/*, thisArg, compareFn*/) {
		var list, thisArg = arguments[2], compareFn = arguments[3];
		obj = Object(value(obj));
		callable(cb);

		list = keys(obj);
		if (compareFn) {
			list.sort(isCallable(compareFn) ? compareFn.bind(obj) : undefined);
		}
		return list[method](function (key, index) {
			if (!propertyIsEnumerable.call(obj, key)) return defVal;
			return call.call(cb, thisArg, obj[key], key, obj, index);
		});
	};
};

// Internal method, used by iteration functions.
// Calls a function for each key-value pair found in object
// Optionally takes compareFn to iterate object in specific order

'use strict';

var callable = require('./valid-callable')
  , value    = require('./valid-value')

  , bind = Function.prototype.bind, call = Function.prototype.call, keys = Object.keys
  , propertyIsEnumerable = Object.prototype.propertyIsEnumerable;

module.exports = function (method, defVal) {
	return function (obj, cb/*, thisArg, compareFn*/) {
		var list, thisArg = arguments[2], compareFn = arguments[3];
		obj = Object(value(obj));
		callable(cb);

		list = keys(obj);
		if (compareFn) {
			list.sort((typeof compareFn === 'function') ? bind.call(compareFn, obj) : undefined);
		}
		return list[method](function (key, index) {
			if (!propertyIsEnumerable.call(obj, key)) return defVal;
			return call.call(cb, thisArg, obj[key], key, obj, index);
		});
	};
};

Use typeof instead of isCallable


ngGridDirectives.directive('ngHeaderCell', ['$compile', function($compile) {
    var ngHeaderCell = {
        scope: false,
        compile: function() {
            return {
                pre: function($scope, iElement) {
                    iElement.append($compile($scope.col.headerCellTemplate)($scope));
                }
            };
        }
    };
    return ngHeaderCell;
}]);

ngGridDirectives.directive('ngHeaderCell', ['$compile', function($compile) {
    var ngHeaderCell = {
        scope: false,
        compile: function() {
            return {
                pre: function($scope, iElement) {
                    iElement.append($compile($scope.col.headerCellTemplate)($scope));
                    // put $scope back on the element so element.scope() works even when
                    // $compileProvider.debugInfoEnabled(false);
                    iElement.data('$scope', $scope);
                }
            };
        }
    };
    return ngHeaderCell;
}]);

Make columns reorderable when debug false


import {isFunction, isUndefined} from 'lodash/lang';
import {setHeader} from 'focus-core/application';
import {component as Empty} from '../../common/empty';

module.exports = {

    /**
     * Updates the cartridge using the cartridgeConfiguration.
     */
    _registerCartridge() {
        this.cartridgeConfiguration = this.cartridgeConfiguration || this.props.cartridgeConfiguration;

        if (!isFunction(this.cartridgeConfiguration)) {
            this.cartridgeConfiguration = () => ({});
            console.warn(`
                Your detail page does not have any cartrige configuration, this is not mandarory but recommended.
                It should be a component attribute return by a function.
                function cartridgeConfiguration(){
                    var cartridgeConfiguration = {
                    summary: {component: "A React Component", props: {id: this.props.id}},
                    cartridge: {component: "A React Component"},
                    actions: {components: "react actions"}
                    };
                    return cartridgeConfiguration;
                }
            `);
        }

        setHeader(this.cartridgeConfiguration());
    },

    /**
     * Registers the cartridge upon mounting.
     */
    componentWillMount() {
        this._registerCartridge();
    }
};

import { isFunction } from 'lodash';
import { setHeader } from 'focus-core/application';

module.exports = {

    /**
     * Updates the cartridge using the cartridgeConfiguration.
     */
    _registerCartridge(props = this.props) {
        const cartridgeConfiguration = this.cartridgeConfiguration || props.cartridgeConfiguration;

        if (!isFunction(cartridgeConfiguration)) {
            this.cartridgeConfiguration = () => ({});
            console.warn(`
                Your detail page does not have any cartrige configuration, this is not mandarory but recommended.
                It should be a component attribute return by a function.
                function cartridgeConfiguration(){
                    var cartridgeConfiguration = {
                    summary: {component: "A React Component", props: {id: this.props.id}},
                    cartridge: {component: "A React Component"},
                    actions: {components: "react actions"}
                    };
                    return cartridgeConfiguration;
                }
            `);
        }

        setHeader(cartridgeConfiguration());
    },

    /**
     * Registers the cartridge upon mounting.
     */
    componentWillMount() {
        this._registerCartridge();
    },

    componentWillReceiveProps(nextProps) {
        this._registerCartridge(nextProps);
    }
};

Change cartridge conf of advaced search dynamically


import ExecutorAbstract from '../ExecutorAbstract';

class PromiseExecutor extends ExecutorAbstract {
  //-----------------------------------
  // Constructor
  //-----------------------------------
  /**
   * Constructor for a new PromiseExecutor
   *
   * @param thread The parent thread that owns this executor.
   * @param promise The promise to execute
   */
  constructor(thread, promise) {
    super(thread);

    this.promise = promise;
  }

  //-----------------------------------
  // Methods
  //-----------------------------------
  /**
   * Internal execution method called by Thread only.
   *
   * @param doneHandler The handler to call when done() is called.
   * @param failHandler The handler to call when fail() is called;
   * @private
   */
  _execute(doneHandler, failHandler) {
    super._execute(doneHandler, failHandler);

    this.promise.then(this.done).catch(this.fail);
  }
}

export default PromiseExecutor;

import ExecutorAbstract from '../ExecutorAbstract';

class PromiseExecutor extends ExecutorAbstract {
  //-----------------------------------
  // Constructor
  //-----------------------------------
  /**
   * Constructor for a new PromiseExecutor
   *
   * @param thread The parent thread that owns this executor.
   * @param promise The promise to execute
   */
  constructor(thread, promise) {
    super(thread);

    this.promise = promise;
  }

  //-----------------------------------
  // Methods
  //-----------------------------------
  /**
   * Internal execution method called by Thread only.
   *
   * @param doneHandler The handler to call when done() is called.
   * @param failHandler The handler to call when fail() is called;
   * @private
   */
  _execute(doneHandler, failHandler) {
    super._execute(doneHandler, failHandler);

    this.waitForPromise(this.promise);
  }
}

export default PromiseExecutor;

Update promise executor to use existing method


'use strict'

/* @flow */

import type {Exec$Options} from './types'

export function validate(filePath: string, parameters: Array<string>, options: Exec$Options) {

}

'use strict'

/* @flow */

import invariant from 'assert'
import type {Exec$Options} from './types'

export function validate(filePath: string, parameters: Array<string>, options: Exec$Options) {
  invariant(typeof filePath === 'string', 'filePath must be a string')
  invariant(Array.isArray(parameters), 'parameters must be an array')
  invariant(typeof options === 'object' && options, 'options must be an object')
  if (options.stream) {
    const stream = options.stream
    invariant(stream === 'both' || stream === 'stdout' || stream === 'stderr', 'options.stream should be stdout|stderr|both')
  } else options.stream = 'stdout'
  if (options.timeout) {
    invariant(typeof options.timeout === 'number', 'options.timeout must be a number')
  } else options.timeout = Infinity
}

Implement a rock solid validator


function updateMasonry() {
    var $container = $('.row').masonry();
    $container.imagesLoaded(function () {
        $container.masonry();
    });
}
$(window).load(function () {
    updateMasonry();
});

$(".input-group input").change(function () {
    console.log("change");
    $(this).removeClass("is-not-empty");
    if ($(this).val() == "") {
    } else {
        $(this).addClass("is-not-empty");
    }
});
$(".sidenav-toggle").click(function () {
    if ($("body").hasClass("sidebar-active")) {
        $("body").removeClass("sidebar-active");
    } else {
        $("body").addClass("sidebar-active");
    }
    window.setTimeout(updateMasonry, 300);
});

function updateMasonry() {
    var container = $('.masonry-row').masonry({
        itemSelector : '.masonry-item',
        columnWidth: '.grid-sizer',
        percentPosition: true
    });
    container.imagesLoaded(function () {
        container.masonry();
    });
    container.masonry('reloadItems');
    container.masonry('layout');
}
$(window).load(function () {
    updateMasonry();
});

$(".input-group input").change(function () {
    console.log("change");
    $(this).removeClass("is-not-empty");
    if ($(this).val() == "") {
    } else {
        $(this).addClass("is-not-empty");
    }
});
$(".sidenav-toggle").click(function () {
    if ($("body").hasClass("sidebar-active")) {
        $("body").removeClass("sidebar-active");
    } else {
        $("body").addClass("sidebar-active");
    }
    window.setTimeout(updateMasonry, 300);
});

Add reloadItems to masonry update function


var events = require('events')
var util = require('util')
var web3 = require('web3')
var request = require('request')
var async = require('async')

function RPC (options) {
  this.url = ['http://', options.host || 'localhost', ':', options.port || 6767].join('')
  this.connected = false
}
util.inherits(RPC, events.EventEmitter)
module.exports = RPC

RPC.prototype.connect = function () {
  web3.setProvider(new web3.providers.HttpProvider(this.url))
}

RPC.prototype.isConnectedAsync = function (done) {
  request({
    uri: this.url,
    form: {
      id: 9999999999,
      jsonrpc: '2.0',
      method: 'net_listening',
      params: []
    }
  }, function (err, res, body) {
    if (err) {
      done(false)
    }
    else {
      done(true)
    }
  })
}

RPC.prototype.watch = function () {
  var self = this

  async.forever(function (done) {
    setTimeout(function () {
      self.isConnectedAsync(function (connected) {
        if (connected !== self.connected) {
          self.connected = connected
          self.emit('connection', self.connected)
        }
        done()
      })
    }, 1000)
  })
}

import EventEmitter from 'events'
import util from 'util'
import web3 from 'web3'
import request from 'request'
import async from 'async'

class RPC extends EventEmitter {
  constructor (options) {
    super()
    this.url = ['http://', options.host || 'localhost', ':', options.port || 6767].join('')
    this.connected = false
  }

  connect () {
    web3.setProvider(new web3.providers.HttpProvider(this.url))
  }

  isConnectedAsync (done) {
    request({
      uri: this.url,
      form: {
        id: 9999999999,
        jsonrpc: '2.0',
        method: 'net_listening',
        params: []
      }
    }, function (err, res, body) {
      if (err) {
        done(false)
      }
      else {
        done(true)
      }
    })
  }

  watch () {
    var self = this

    async.forever(function (done) {
      setTimeout(function () {
        self.isConnectedAsync(function (connected) {
          if (connected !== self.connected) {
            self.connected = connected
            self.emit('connection', self.connected)
          }
          done()
        })
      }, 1000)
    })
  }
}

export default RPC

Use class, module and async


/*
 * Copyright 2015 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

define([
    'find/app/find-pages',
    'find/idol/app/page/idol-find-search',
    'find/idol/app/page/find-about-page',
    'i18n!find/nls/bundle'
], function(FindPages, FindSearch, AboutPage, i18n) {

    'use strict';

    return FindPages.extend({
        initializePages: function() {
            this.pages = [
                {
                    constructor: FindSearch,
                    icon: 'hp-icon hp-fw hp-search',
                    pageName: 'search',
                    title: i18n['app.search']
                }, {
                    constructor: AboutPage,
                    icon: 'hp-icon hp-fw hp-info',
                    pageName: 'about',
                    title: i18n['app.about']
                }
            ];
        }
    });

});

/*
 * Copyright 2015 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

define([
    'find/app/find-pages',
    'find/idol/app/page/idol-find-search',
    'find/idol/app/page/find-about-page',
    'find/app/page/find-settings-page',
    'i18n!find/nls/bundle'
], function(FindPages, FindSearch, AboutPage, SettingsPage, i18n) {

    'use strict';

    return FindPages.extend({
        initializePages: function() {
            this.pages = [
                {
                    constructor: FindSearch,
                    icon: 'hp-icon hp-fw hp-search',
                    pageName: 'search',
                    title: i18n['app.search']
                }, {
                    constructor: AboutPage,
                    icon: 'hp-icon hp-fw hp-info',
                    pageName: 'about',
                    title: i18n['app.about']
                }, {
                    // TODO this shouldn't appear for users who can't use it
                    constructor: SettingsPage,
                    icon: 'hp-icon hp-fw hp-settings',
                    pageName: 'settings',
                    title: i18n['app.settings']
                }
            ];
        }
    });

});

Add settings page to app.


$(document).ready(function () {
    var locale = 'en' !== LOCALE ? LOCALE : '';

    var init;
    (init = function () {
        $('input[type="text"].datetime').each(function () {
            var $input = $(this);
            $input.datetimepicker($.extend({}, $.datepicker.regional[locale], $.timepicker.regional[locale]));
        });
    })();

    $(document).bind('ajaxSuccess', init);
});

$(document).ready(function () {
    var locale = 'en' !== LOCALE ? LOCALE : '';

    var init;
    (init = function () {
        $('input[type="text"].datetime').each(function () {
            var $input = $(this);
            $input.datetimepicker($.extend({}, $.datepicker.regional[locale], $.timepicker.regional[locale], {
                dateFormat: 'dd.mm.yy'
            }));
        });
    })();

    $(document).bind('ajaxSuccess', init);
});

Configure date picker date format.


var paths = require( './paths' );

module.exports = {

	options: {
		livereload: true,
	},
	styles: {
		// Which files to watch (all .less files recursively in the less directory)
		files: paths.styles,
		tasks: [ 'less' ],
		options: {
			nospawn: true
		}
	}

};

var paths = require( './paths' );

module.exports = {

	styles: {
		// Which files to watch (all .less files recursively in the less directory)
		files: paths.styles,
		tasks: [ 'less' ],
		options: {
			nospawn: true
		}
	}

};

Disable livereload because of port conflicts


const fs = require('fs');
const sysout = console.log;
function toFile(log) {
    fs.appendFile("./latest.log", log, () => {});
}
const out = log => {
    sysout(log);
    toFile(log);
};
console.log = log => {
    let d = new Date();
    log = `[${d.toString()} LOG] ${log}`;
    out(log);
};
console.info = console.log;
console.error = log => {
    let d = new Date();
    log = `[${d.toString()} ERROR] ${log}`;
    out(log);
};

const fs = require('fs');
const sysout = console.log;
function toFile(log) {
    fs.appendFile("./latest.log", log + '\n', () => {});
}
const out = log => {
    sysout(log);
    toFile(log);
};
console.log = log => {
    let d = new Date();
    log = `[${d.toString()} LOG] ${log}`;
    out(log);
};
console.info = console.log;
console.error = log => {
    let d = new Date();
    log = `[${d.toString()} ERROR] ${log}`;
    out(log);
};

Add newlines when writing to files


import Enzyme, { shallow, render, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import React from 'react'
import 'isomorphic-fetch'
import 'fetch-mock'

global.React = React

// React 16 Enzyme adapter
Enzyme.configure({ adapter: new Adapter() })

// Configure global env variables
process.env.HTTP_API_URL = 'http://test'

// Make Enzyme functions available in all test files without importing
global.shallow = shallow
global.render = render
global.mount = mount

// Add a helper to register snapshot
global.snapshot = element => expect(element).toMatchSnapshot()

// Shallow then snapshot component
global.snapshotComponent = component => snapshot(shallow(component))

/**
 * Apply all actions to given reducer and make a snapshot at each step.
 */
global.snapshotReducer = ((reducer, initialState, ...actions) => {
  snapshot(initialState)
  return actions.reduce((state, action) => {
    const newState = reducer(state, action)
    snapshot(newState)
    return newState
  }, initialState)
})

import Enzyme, { shallow, render, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import React from 'react'
import 'isomorphic-fetch'
import 'fetch-mock'

global.React = React

// React 16 Enzyme adapter
Enzyme.configure({ adapter: new Adapter() })

// Configure global env variables
process.env.HTTP_API_URL = 'http://test'
process.env.INVITATION_SYSTEM = 'off'

// Make Enzyme functions available in all test files without importing
global.shallow = shallow
global.render = render
global.mount = mount

// Add a helper to register snapshot
global.snapshot = element => expect(element).toMatchSnapshot()

// Shallow then snapshot component
global.snapshotComponent = component => snapshot(shallow(component))

/**
 * Apply all actions to given reducer and make a snapshot at each step.
 */
global.snapshotReducer = ((reducer, initialState, ...actions) => {
  snapshot(initialState)
  return actions.reduce((state, action) => {
    const newState = reducer(state, action)
    snapshot(newState)
    return newState
  }, initialState)
})

Fix tests config for invitation system


/**
 * @module ember-flexberry
 */

import OlvInputCellComponent from 'ember-flexberry/components/object-list-view-input-cell';

export default OlvInputCellComponent.extend({
  actions: {
    fileChange: function(options) {
      this.get('record').set(this.get('column.propName'), options.value);
    }
  }
});

/**
 * @module ember-flexberry
 */

import OlvCellComponent from 'ember-flexberry/components/object-list-view-cell';

export default OlvCellComponent.extend({
  actions: {
    fileChange: function(options) {
      this.get('record').set(this.get('column.propName'), options.value);
    }
  }
});

Fix group edit file-related record clean


import Ember from 'ember'
import _ from 'lodash/lodash'

export default Ember.Component.extend({
  classNames: ['frost-pods'],
  classNameBindings: ['orientation'],

  orientation: 'vertical',

  podNames: Ember.computed('podStack.[]', function () {
    return _.dropRight(this.get('podStack').map(function (entry) {
      return entry.alias
    }), 1)
  }),

  podLayerAlias: Ember.computed('podStack.[]', function () {
    return this.get('podStack.lastObject.alias')
  }),

  podStack: null,
  podLayer: Ember.computed('podStack.[]', function () {
    let podLayer = {}
    podLayer[this.get('podStack.lastObject.id')] = true
    return podLayer
  }),

  init() {
    this._super();
    this.set('podStack', Ember.A())
    this.get('podStack').addObject({
      id: 'root',
      alias: 'NodeD'
    })
  },

  actions: {
    openPod (id, alias) {
      this.get('podStack').addObject({
        id: id,
        alias: alias
      })
    },

    closePod () {
      this.get('podStack').popObject()
    },

    changePod (pod) {
      _.dropRightWhile(this.get('podStack'), (n) => {
        if (n.alias !== pod) {
          this.get('podStack').popObject()
          return true
        }
        return false
      })
    }
  }
})

import Ember from 'ember'
import _ from 'lodash/lodash'

export default Ember.Component.extend({
  classNames: ['frost-pods'],
  classNameBindings: ['orientation'],

  orientation: 'vertical',

  podNames: Ember.computed('podStack.[]', function () {
    return _.dropRight(this.get('podStack').map(function (entry) {
      return entry.alias
    }), 1)
  }),

  podLayerAlias: Ember.computed('podStack.[]', function () {
    return this.get('podStack.lastObject.alias')
  }),

  podStack: null,
  podLayer: Ember.computed('podStack.[]', function () {
    let podLayer = {}
    podLayer[this.get('podStack.lastObject.id')] = true
    return podLayer
  }),

  init() {
    this._super(...arguments);
    this.set('podStack', Ember.A())
    this.get('podStack').addObject({
      id: 'root',
      alias: 'NodeD'
    })
  },

  actions: {
    openPod (id, alias) {
      this.get('podStack').addObject({
        id: id,
        alias: alias
      })
    },

    closePod () {
      this.get('podStack').popObject()
    },

    changePod (pod) {
      _.dropRightWhile(this.get('podStack'), (n) => {
        if (n.alias !== pod) {
          this.get('podStack').popObject()
          return true
        }
        return false
      })
    }
  }
})

Fix for CI comment - this._super(); + this._super(...arguments);


'use strict';

var chai = require('chai');
var chaihttp = require('chai-http');
var expect = require('chai').expect;

chai.use(chaihttp);

require('../../../server');

describe('Yelp search route', function() {

  it('should be able to get', function(done) {
    chai.request('http://localhost:3000')
      .get('/api/0_0_1/location' )
      .res(function(res) {
        expect(res).to.have.status(200);
      });
      done();
  });

});

'use strict';

var chai = require('chai');
var chaihttp = require('chai-http');
var expect = require('chai').expect;

chai.use(chaihttp);

var server = require('../../../server');

describe('Yelp search route', function() {
  console.log('Should look on port ' + server.port);
  it('should be able to get', function(done) {
    chai.request('http://localhost:' + server.port)
    .get('/api/0_0_1/[{"lat":47.6613676,"lon":-122.32989020000002}]/{}')
    .res(function(res) {
	      expect(res).to.have.status(200);
      done();
    });
  });

  it('should return an array', function(done) {
  	chai.request('http://localhost:' + server.port)
    .get('/api/0_0_1/[{"lat":47.6613676,"lon":-122.32989020000002}]/{}')
    .res(function(res) {
	      expect(Array.isArray(res.body)).to.be.true;
      done();
    });
  });

  it('should return Yelp objects within the array', function(done) {
  	chai.request('http://localhost:' + server.port)
    .get('/api/0_0_1/[{"lat":47.6613676,"lon":-122.32989020000002}]/{}')
    .res(function(res) {
	      expect(JSON.parse(res.body[0])).to.have.property('businesses');
      done();
    });
  });
});

Add a few more tests for our Yelp endpoint


import { reads, and } from '@ember/object/computed';
import LinkComponent from '@ember/routing/link-component';
import layout from '../templates/components/paper-link'

import FocusableMixin from 'ember-paper/mixins/focusable-mixin';
import ColorMixin from 'ember-paper/mixins/color-mixin';
import ProxiableMixin from 'ember-paper/mixins/proxiable-mixin';

export default LinkComponent.extend(FocusableMixin, ColorMixin, ProxiableMixin, {
  layout,

  // Add needed paper-button properties
  classNames: ['md-default-theme', 'md-button', 'paper-link'],
  raised: false,
  iconButton: false,
  fab: reads('mini'),  // circular button
  mini: false,

  // For raised buttons: toggle disabled when button is active
  disabled: and('raised', 'active'),

  classNameBindings: [
    'raised:md-raised',
    'iconButton:md-icon-button',
    'fab:md-fab',
    'mini:md-mini'
  ],

  // FocusableMixin overrides active so set back to link-to's active
  active: LinkComponent.active,

  // FocusableMixin overrides to prevent changing 'active' property
  down() {
    this.set('pressed', true);
  },
  up() {
    this.set('pressed', false);
  }
});

import { reads, and } from '@ember/object/computed';
import LinkComponent from '@ember/routing/link-component';
import layout from '../templates/components/paper-link'
import { computed } from '@ember/object';

import FocusableMixin from 'ember-paper/mixins/focusable-mixin';
import ColorMixin from 'ember-paper/mixins/color-mixin';
import ProxiableMixin from 'ember-paper/mixins/proxiable-mixin';

export default LinkComponent.extend(FocusableMixin, ColorMixin, ProxiableMixin, {
  layout,

  // Add needed paper-button properties
  classNames: ['md-default-theme', 'md-button', 'paper-link'],
  raised: false,
  iconButton: false,
  fab: reads('mini'),  // circular button
  mini: false,

  // For raised buttons: toggle disabled when button is active
  disabled: and('raised', 'active'),

  classNameBindings: [
    'raised:md-raised',
    'iconButton:md-icon-button',
    'fab:md-fab',
    'mini:md-mini'
  ],

  // FocusableMixin overrides active so set back to link-to's active
  active: computed('activeClass', '_active', function() {
    return this._active ? this.activeClass : false;
  }),

  // FocusableMixin overrides to prevent changing 'active' property
  down() {
    this.set('pressed', true);
  },
  up() {
    this.set('pressed', false);
  }
});

Fix active class not displaying on recent ember versions


var promisify = require("promisify-node");
var fs = promisify("fs");
var exec = promisify("child_process").exec;

before(function(done) {
  var url = "https://github.com/nodegit/nodegit";

  fs.exists("test/repos").then(null, function() {
    return fs.mkdir("test/repos").then(function() {
      return exec("git init test/repos/empty");
    }).then(function() {
      return exec("git clone " + url + " test/repos/workdir");
    }).then(function() {
      var nonrepo = "test/repos/nonrepo";

      return fs.mkdir(nonrepo).then(function() {
        return fs.writeFile(nonrepo + "/file.txt", "This is a bogus file");
      });
    })
  }).then(done.bind(null, undefined), done.bind(null, undefined));
});

var promisify = require("promisify-node");
var fs = promisify("fs");

// Have to wrap exec, since it has a weird callback signature.
var exec = promisify(function(command, callback) {
  return require("child_process").exec(command, callback);
});

before(function(done) {
  this.timeout(5000);

  var url = "https://github.com/nodegit/nodegit";
  var done = done.bind(null, null);

  fs.exists("test/repos").then(function() {
    return fs.mkdir("test/repos").then(function() {
      return exec("git init test/repos/empty");
    }).then(function() {
      return exec("git clone " + url + " test/repos/workdir");
    }).then(function() {
      var nonrepo = "test/repos/nonrepo";

      return fs.mkdir(nonrepo).then(function() {
        return fs.writeFile(nonrepo + "/file.txt", "This is a bogus file");
      });
    })
  }).then(done, done);
});

Fix issues with fetching the fixture data


(function(window) {
  'use strict';

  window.modular = {
    Module: window.parent.app.ModularModule,
  };

  window.addEventListener('load', function() {
    setTimeout(function() {
      window.postMessage(window.name, location.protocol + '//' + location.host);
    }, 0);
  });
})(this);

(function(window) {
  'use strict';

  window.modular = {
    Module: window.parent.app.ModularModule,
    exports: null,
  };

  window.addEventListener('load', function() {
    setTimeout(function() {
      window.postMessage(window.name, location.protocol + '//' + location.host);
    }, 0);
  });
})(this);

Make 'exports' property explicit for modular object


import React from 'react';
import PropTypes from 'prop-types';

//Custom all purpose dashboard button
class DashButton extends React.Component {

  render() {
    return (
      <div className="DashButton">
        <a
          style={{
            backgroundColor: this.props.isSelected? 'rgba(49, 119, 201, 0.75)' : '',
            width: '100%',
            display: 'flex',
            justifyContent: 'center'
          }}
          onClick={this.props.onClick}>
          {this.props.buttonText}
        </a>
      </div>
    );
  }
}
DashButton.propTypes = {
  buttonText: PropTypes.string.isRequired,
  onClick: PropTypes.func.isRequired,
  isSelected: PropTypes.bool.isRequired
};

export default DashButton;

import React from 'react';
import PropTypes from 'prop-types';

//Custom all purpose dashboard button
class DashButton extends React.Component {

  render() {
    const {isSelected} = this.props;
    return (
      <div className="DashButton">
        <a
          style={{
            backgroundColor: isSelected ? 'rgba(49, 119, 201, 0.75)' : '',
            color: isSelected ? 'white' : 'black',
            width: '100%',
            display: 'flex',
            justifyContent: 'center'
          }}
          onClick={this.props.onClick}>
          {this.props.buttonText}
        </a>
      </div>
    );
  }
}

DashButton.propTypes = {
  buttonText: PropTypes.string.isRequired,
  onClick: PropTypes.func.isRequired,
  isSelected: PropTypes.bool.isRequired
};

export default DashButton;

Use white when selected to contrast with blue


app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
    var rp = $routeProvider;

    rp.when('/', {
        templateUrl: '/html/home.html',
        controller: 'HomeCtrl',
    });

    rp.otherwise({
        redirectTo: '/'
    });

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
}]);

app.run(['$rootScope', '$log', 'User', function ($rootScope, $log, User) {
    $rootScope.user_not_checked = true;

    $rootScope.$on('$routeChangeStart', function(event, next, current) {

        // Check to see if the user is logged in ...
        if (!User.getIsLoggedIn()) {
            $log.debug('User is not logged in... changing html.');
            next.templateUrl = '/html/login.html';
            next.controller = 'LoginCtrl';
        } else {
            $log.debug('User is logged in. Continuing on.');
        }
    });
}]);

app.run(['$rootScope', '$log', '$route', 'User', function ($rootScope, $log, $route, User) {
    $rootScope.$on('user', function(event) {
        if ($rootScope.user_not_checked === true) {
            $rootScope.user_not_checked = false;

            if (!User.getIsLoggedIn()) return;
        }

        $route.reload();
    });
}]);

app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
    var rp = $routeProvider;

    rp.when('/', {
        templateUrl: '/html/home.html',
        controller: 'HomeCtrl',
    });

    rp.otherwise({
        redirectTo: '/'
    });

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
}]);

app.run(['$rootScope', '$log', '$route', 'User', function ($rootScope, $log, $route, User) {
    $rootScope.user_not_checked = true;

    $rootScope.$on('$routeChangeStart', function(event, next, current) {

        // Check to see if the user is logged in ...
        if (!User.getIsLoggedIn()) {
            $log.debug('User is not logged in... changing html.');
            next.templateUrl = '/html/login.html';
            next.controller = 'LoginCtrl';
        } else {
            $log.debug('User is logged in. Continuing on.');
        }
    });

    $rootScope.$on('user', function(event) {
        if ($rootScope.user_not_checked === true) {
            $rootScope.user_not_checked = false;

            if (!User.getIsLoggedIn()) return;
        }

        $route.reload();
    });
}]);

Refactor everything into a single .run() call


Package.describe({
  name: 'dispatch:phoneformat.js',
  summary: 'phoneformat.js packaged for meteor',
  version: '1.5.4',
  git: 'https://github.com/DispatchMe/phoneformat.js.git'
});

Package.onUse(function (api) {
  api.versionsFrom('1.0');

  api.use([
    // core
    'underscore',
    'reactive-var@1.0.5',
    'templating@1.1.1',

    // atmosphere
    'raix:eventemitter@0.1.2'
  ], 'web');

  api.addFiles([
    'google.phoneformat.js',
    'phoneformat.js',
    'country_code_map.js',
    'components/single-input/single_input.html',
    'components/single-input/single_input.js',
    'components/multi-input/multi_input.html',
    'components/multi-input/multi_input.js',
    'components/phone_input.js'
  ], 'web');

  api.use([
    'http@1.1.0'
  ], 'server');

  api.addFiles('server.js', 'server');

  api.export(['Phoneformat', 'PhoneInput']);
});

Cordova.depends({
  'org.apache.cordova.globalization': '0.3.4'
});

Package.describe({
  name: 'dispatch:phoneformat.js',
  summary: 'phoneformat.js packaged for meteor',
  version: '1.5.4',
  git: 'https://github.com/DispatchMe/phoneformat.js.git'
});

Package.onUse(function (api) {
  api.versionsFrom('1.0');

  api.use([
    // core
    'underscore',
    'reactive-var@1.0.5',
    'templating@1.1.1',

    // atmosphere
    'raix:eventemitter@0.1.2'
  ], 'web');

  api.addFiles([
    'google.phoneformat.js',
    'phoneformat.js',
    'country_code_map.js',
    'components/single-input/single_input.html',
    'components/single-input/single_input.js',
    'components/multi-input/multi_input.html',
    'components/multi-input/multi_input.js',
    'components/phone_input.js'
  ], 'web');

  api.use([
    'http@1.1.0'
  ], 'server');

  api.addFiles('server.js', 'server');

  api.export(['Phoneformat', 'PhoneInput']);
});

Cordova.depends({
  'cordova-plugin-globalization': '1.0.1'
});

Update cordova globalization plugin to v1.0.1


Package.describe({
    name: "froatsnook:sleep",
    summary: "Fiber-friendly sleep statements (server only)",
    version: "1.0.1",
    git: "https://github.com/froatsnook/sleep"
});

Package.onUse(function(api) {
    api.versionsFrom("0.9.2");
    api.addFiles("server/lib/sleep.js", ["server"]);
});

Package.onTest(function(api) {
    api.use("tinytest");
    api.use("froatsnook:sleep");

    api.addFiles("test/sleep-tests.js");
});

Package.describe({
    name: "froatsnook:sleep",
    summary: "Fiber-friendly sleep statements (server only)",
    version: "1.0.1",
    git: "https://github.com/froatsnook/meteor-sleep"
});

Package.onUse(function(api) {
    api.versionsFrom("0.9.2");
    api.addFiles("server/lib/sleep.js", ["server"]);
});

Package.onTest(function(api) {
    api.use("tinytest");
    api.use("froatsnook:sleep");

    api.addFiles("test/sleep-tests.js");
});

Update to new git repo.