/* global Messages */
Template.snippetPage.helpers({
	snippet: function() {
		return Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
	},
	snippetContent: function() {
		let message = Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
		if (message === undefined) {
			return null;
		} else {
			message.html = message.msg;
			let markdownCode = new RocketChat.MarkdownCode(message);
			return markdownCode.tokens[0].text;
		}
	},
	date() {
		let snippet = Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
		if (snippet !== undefined) {
			return moment(snippet.ts).format(RocketChat.settings.get('Message_DateFormat'));
		}
	},
	time() {
		let snippet = Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
		if (snippet !== undefined) {
			return moment(snippet.ts).format(RocketChat.settings.get('Message_TimeFormat'));
		}
	}
});

Template.snippetPage.onCreated(function() {
	let snippetId = FlowRouter.getParam('snippetId');
	console.log(`${snippetId}: ${this.snippet}`);
	this.autorun(function() {
		Meteor.subscribe('snippetedMessage', snippetId);
	});
});

/* global Messages */
Template.snippetPage.helpers({
	snippet: function() {
		return Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
	},
	snippetContent: function() {
		let message = Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
		if (message === undefined) {
			return null;
		}
		message.html = message.msg;
		let markdownCode = new RocketChat.MarkdownCode(message);
		return markdownCode.tokens[0].text;
	},
	date() {
		let snippet = Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
		if (snippet !== undefined) {
			return moment(snippet.ts).format(RocketChat.settings.get('Message_DateFormat'));
		}
	},
	time() {
		let snippet = Messages.findOne({ _id: FlowRouter.getParam('snippetId') });
		if (snippet !== undefined) {
			return moment(snippet.ts).format(RocketChat.settings.get('Message_TimeFormat'));
		}
	}
});

Template.snippetPage.onCreated(function() {
	let snippetId = FlowRouter.getParam('snippetId');
	this.autorun(function() {
		Meteor.subscribe('snippetedMessage', snippetId);
	});
});

Remove log and useless else condition.


process.env.NODE_ENV = 'test';

var should = require('should'),
  request = require('supertest'),
  testSetup = require('../util/testSetup'),
  url = 'http://localhost:1337';

describe('Controllers/MoviesController', function() {
  before(function(done) {
    testSetup.before(done);
  });
  it('index - should return blank array', function(done) {
      request(url)
          .get('/movies')
          .expect(200)
          .end(function(err, res) {
              var movies = res.body;
              should.equal(movies.length,0);
              should.not.exist(err);
              if (err) { return done(err); }
              done();
          });
  });
  after(function(done) {
    testSetup.after(done);
  });
});

process.env.NODE_ENV = 'test';

var should = require('should'),
  request = require('supertest'),
  testSetup = require('../util/testSetup'),
  url = 'http://localhost:1337';

describe('Controllers/MoviesController', function() {
  before(function(done) {
    testSetup.before(done);
  });
  it('index - should return blank array', function(done) {
      request(url)
          .get('/movies')
          .expect(200)
          .end(function(err, res) {
              var movies = res.body.movies;
              should.equal(movies.length,0);
              should.not.exist(err);
              if (err) { return done(err); }
              done();
          });
  });
  after(function(done) {
    testSetup.after(done);
  });
});

Update test for named object response


angular
	.module('ngSharepoint')
	.provider('$spLog', function() {
		var prefix = '[ngSharepoint] ';
		var enabled = true;
		return {
			setPrefix: function(prefix) {
				this.prefix = '[' + prefix + '] ';
			},
			setEnabled: function(enabled) {
				this.enabled = enabled;
			},
			$get: function() {
				return ({
					error: function(msg) {
						if (enabled) {
							if (typeof msg === 'object') {
								console.error(prefix + 'Object: %O', msg);
							}else {
								console.error(prefix + msg);
							}
						}
					},
					warn: function(msg) {
						if (enabled) {
							if (typeof msg === 'object') {
								console.warn(prefix + 'Object: %O', msg);
							}else {
								console.warn(prefix + msg);
							}
						}
					},
					log: function(msg) {
						if (enabled) {
							if (typeof msg === 'object') {
								console.log(prefix + 'Object: %O', msg);
							}else {
								console.log(prefix + msg);
							}
						}
					}
				});
			}
		};
	});

angular
	.module('ngSharepoint')
	.provider('$spLog', function($log) {
		var prefix = '[ngSharepoint] ';
		var enabled = true;
		return {
			setPrefix: function(prefix) {
				this.prefix = '[' + prefix + '] ';
			},
			setEnabled: function(enabled) {
				this.enabled = enabled;
			},
			$get: function() {
				return ({
					error: function(msg) {
						if (enabled) {
							if (angular.isObject(msg)) {
								$log.error(prefix + 'Object: %O', msg);
							}else {
								$log.error(prefix + msg);
							}
						}
					},
					warn: function(msg) {
						if (enabled) {
							if (angular.isObject(msg)) {
								$log.warn(prefix + 'Object: %O', msg);
							}else {
								$log.warn(prefix + msg);
							}
						}
					},
					log: function(msg) {
						if (enabled) {
							if (angular.isObject(msg)) {
								$log.log(prefix + 'Object: %O', msg);
							}else {
								$log.log(prefix + msg);
							}
						}
					}
				});
			}
		};
	});

Use $log instead of console and use angulars isObject method for typechecking


define([
  'marked',
  'to-markdown'
], function (
  marked,
  tomarkdown
) {
  'use strict';
  return (function() {
    var toHTML = function(src) {
      marked.setOptions({
        breaks: true
      });
      return marked(src);
    };

    var toMarkdown = function(src) {
      return tomarkdown(src);
    };

    return {
      toHTML : toHTML,
      toMarkdown : toMarkdown
    };
  })();
});

define([
  'marked',
  'to-markdown'
], function (
  marked,
  tomarkdown
) {
  'use strict';
  return (function() {
    var toHTML = function(src) {
      marked.setOptions({
        breaks: true,
        table: false
      });
      return marked(src);
    };

    var toMarkdown = function(src) {
      return tomarkdown(src);
    };

    return {
      toHTML : toHTML,
      toMarkdown : toMarkdown
    };
  })();
});

Stop marked from converting Markdown tables into HTML


module.exports = {
	mode: "production",
	entry: "./index",
	output: {
		filename: "bundle.js"
	},
	profile: true,
	stats: {
		reasons: true,
		chunkModules: true,
		chunkOrigins: true,
		modules: true,
		cached: true,
		cachedAssets: true,
		source: true,
		errorDetails: true,
		publicPath: true
	}
};

module.exports = {
	mode: "production",
	entry: "./index",
	output: {
		filename: "bundle.js"
	},
	profile: true,
	stats: {
		reasons: true,
		chunkModules: true,
		chunkOrigins: true,
		modules: true,
		cached: true,
		cachedAssets: true,
		source: true,
		errorDetails: true,
		publicPath: true,
		outputPath: true,
	}
};

Add option in integration test


function refresh () {
  $(".refresh-link").on("click", function(event) {
    event.preventDefault();
    var $target = $(event.target);
    var url = $target.attr("href");
    var id = url.match(/(\d+)(?!.*\d)/)[0].toString();
    var dateTimeIn24Hours = new Date();
    var $dateSpan = $(".data" + id);
    $.ajax({
      url: url,
      type: "get"
    }).done(function(response) {
      $dateSpan.data("countdown", formatCurrentDateTime(dateTimeIn24Hours));
      countdown();
    });
  });
}

function refresh () {
  $(".refresh-link").on("click", function(event) {
    event.preventDefault();
    var $target = $(event.target);
    var url = $target.attr("href");
    var id = url.match(/(\d+)(?!.*\d)/)[0].toString();
    var dateTimeIn24Hours = new Date();
    var $dateSpan = $(".data" + id);
    var $timeRemainingSpan = $(".time-remaining" + id);
    var longest = parseInt($("#longest" + id).text(), 10);
    var current = parseInt($("#current" + id).text(), 10);

    $.ajax({
      url: url,
      type: "get"
    }).done(function(response) {
      countdown();
    });
  });
}

Add variables to grab the timeRemainingSpan, current streak integer, and longest streak integer


'use strict';

const { omitBy } = require('../../../../../../utilities');

const filterFields = function ({ fields, parentDef, opts }) {
  return omitBy(fields, (def, defName) =>
    filterField({ parentDef, def, defName, opts })
  );
};

const filterField = function ({
  parentDef,
  def,
  defName,
  opts: { inputObjectType },
}) {
  // Filter arguments for single actions only include `id`
  return (
    defName !== 'id' &&
    inputObjectType === 'filter' &&
    !parentDef.action.multiple
  // Nested data arguments do not include `id`
  ) || (
    defName === 'id' &&
    inputObjectType === 'data' &&
    parentDef.kind === 'attribute'
  // Readonly fields cannot be specified as data argument
  ) || (
    inputObjectType === 'data' &&
    def.readonly
  // `updateOne|updateMany` do not allow data.id
  ) || (
    defName === 'id' &&
    inputObjectType === 'data' &&
    parentDef.action.type === 'update'
  );
};

module.exports = {
  filterFields,
};

'use strict';

const { omitBy } = require('../../../../../../utilities');

const filterFields = function ({
  fields,
  parentDef: { kind, action },
  opts: { inputObjectType },
}) {
  return omitBy(fields, (def, defName) =>
    filterField({ kind, action, def, defName, inputObjectType })
  );
};

const filterField = function (opts) {
  return filters.some(filter => filter(opts));
};

// Filter arguments for single actions only include `id`
const singleIdFilter = function ({ defName, inputObjectType, action }) {
  return defName !== 'id' &&
    inputObjectType === 'filter' &&
    !action.multiple;
};

// Nested data arguments do not include `id`
const nestedIdData = function ({ defName, inputObjectType, kind }) {
  return defName === 'id' &&
    inputObjectType === 'data' &&
    kind === 'attribute';
};

// Computed fields cannot be specified as data argument
const computeData = function ({ def, inputObjectType }) {
  return inputObjectType === 'data' &&
    def.compute !== undefined;
};

// Readonly fields cannot be specified as data argument,
// except during model creation
const readonlyData = function ({ def, inputObjectType, action }) {
  return inputObjectType === 'data' &&
    def.readonly &&
    !['create', 'upsert'].includes(action.type);
};

// `updateOne|updateMany` do not allow data.id
const updateIdData = function ({ defName, inputObjectType, action }) {
  return defName === 'id' &&
    inputObjectType === 'data' &&
    action.type === 'update';
};

const filters = [
  singleIdFilter,
  nestedIdData,
  computeData,
  readonlyData,
  updateIdData,
];

module.exports = {
  filterFields,
};

Fix GraphQL schema for compute|readonly attributes in args.data


"use strict";

var fs = require('fs');
var path = require('path');
var extend = require('extend');
var template = require('lodash/template');

var _fileNumber = 1;
var _config = {
    onEachFile: function() {},
    onCompleted: function() {}
};

module.exports = function() {

    return {
        run: run,
        setConfig: setConfig
    }

    function setConfig(config) {
        _config = extend(_config, config);
    }

    function run(callback) {
        _config.files.forEach(function(element, index, array) {
            templateFile(element);
        });
    }

    function templateFile(filePaths) {
        var compiled;
        var output;

        fs.readFile(filePaths.src, 'utf8', function(err, fileContents) {
            if (err) return console.error(err)

            compiled = template(fileContents);
            output = compiled(_config.data);

            fs.writeFile(filePaths.dest, output, 'utf8', function(err) {
                if (err) return console.error(err)

                _config.onEachFile(filePaths.dest);

                if(_fileNumber === _config.files.length) {
                    _config.onCompleted();
                }

                _fileNumber++;

            });

        });
    }

}

"use strict";

var fs = require('fs');
var path = require('path');
var extend = require('extend');
var template = require('lodash/template');

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

var _fileNumber = 1;
var _config = {
    onEachFile: function() {},
    onCompleted: function() {}
};

module.exports = function() {

    return {
        run: run,
        setConfig: setConfig
    }

    function setConfig(config) {
        _config = extend(_config, config);
    }

    function run(callback) {
        _config.files.forEach(function(element, index, array) {
            templateFile(element);
        });
    }

    function templateFile(filePaths) {
        var compiled;
        var output;

        fs.readFile(filePaths.src, 'utf8', function(err, fileContents) {
            if (err) errorHandler(err);

            compiled = template(fileContents);
            output = compiled(_config.data);

            fs.writeFile(filePaths.dest, output, 'utf8', function(err) {
                if (err) errorHandler(err);

                _config.onEachFile(filePaths.dest);

                if(_fileNumber === _config.files.length) {
                    _config.onCompleted();
                }

                _fileNumber++;

            });

        });
    }

}

Add error handler to file templater


import React from 'react';

function Icon(props) {
    if (props.url) {
        return (
            <span className={className(props)} style={{
                backgroundImage: `url(${props.url})`
            }}>

        );
    } else {
        return (

                {props.children}

        );
    }
}

function className(props) {
    var className = 'icon';

    if (props.className) {
        className += ' ' + props.className;
    }

    return className;
}

Icon.propTypes = {
    url: React.PropTypes.string
};

export default Icon;

import React from 'react';

class Icon extends React.Component {
    render() {
        if (this.props.url) {
            return (
                <span className={this.className()} style={{
                    backgroundImage: `url(${this.props.url})`
                }}>

            );
        } else {
            return (

                    {this.props.children}

            );
        }
    }

    className() {
        var className = 'icon';

        if (this.props.className) {
            className += ' ' + this.props.className;
        }

        return className;
    }
}

Icon.propTypes = {
    url: React.PropTypes.string
};

export default Icon;

Revert "Icon is a stateless component"


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')
  }

}]

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: $scope.name || stage.name
        // options: {}
      })
      .then(res => {
        console.log(res)
      })
      .catch(err => {
        console.error(err)
      })

    $uibModalInstance.close()
  }

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

}]

Set stage name based on user input or stage default


import d3 from 'd3';

export default function openmetadesign_viz(data) {
    var svg = d3.select('#d3-container').append("svg");
    svg.append("rect")
        .attr("x", 10)
        .attr("y", 10)
        .attr("width", 50)
        .attr("height", 100)
        .attr("class", "svg-modal-button")
        .on("mouseover", function() {
            d3.select(this)
                .classed("glow", true);
        })
        .on("mouseout", function() {
            d3.select(this)
                .classed("glow", false);
        })
        .attr("data-toggle", "modal");

    svg.append("rect")
        .attr("x", 40)
        .attr("y", 50)
        .attr("width", 50)
        .attr("height", 100);

    // Filters
    var defs = svg.append("defs");
    var glow = defs.append("filter")
        .attr("id", "glow");
    glow.append("feGaussianBlur")
        .attr("stdDeviation", "3.5")
        .attr("result", "coloredBlur");
    var feMerge = glow.append("feMerge");
    feMerge.append("feMergeNode")
        .attr("in", "coloredBlur");
    feMerge.append("feMergeNode")
        .attr("in", "SourceGraphic");

}

import d3 from 'd3';

export default function openmetadesign_viz(data) {

    // The container for the viz
    var d3Container = document.getElementById("d3-container");

    // Get dimensions of the container on window resize
    window.addEventListener("resize", function(d) {
        width = d3Container.clientWidth;
        height = d3Container.clientHeight;
        console.log(width, height);
    });

    // Add the SVG to the container
    var svg = d3.select('#d3-container').append("svg");
    svg.append("rect")
        .attr("x", 10)
        .attr("y", 10)
        .attr("width", 50)
        .attr("height", 100)
        .attr("class", "svg-modal-button")
        .on("mouseover", function() {
            d3.select(this)
                .classed("glow", true);
        })
        .on("mouseout", function() {
            d3.select(this)
                .classed("glow", false);
        })
        .attr("data-toggle", "modal");

    svg.append("rect")
        .attr("x", 40)
        .attr("y", 50)
        .attr("width", 50)
        .attr("height", 100);

    // Filters
    var defs = svg.append("defs");
    var glow = defs.append("filter")
        .attr("id", "glow");
    glow.append("feGaussianBlur")
        .attr("stdDeviation", "3.5")
        .attr("result", "coloredBlur");
    var feMerge = glow.append("feMerge");
    feMerge.append("feMergeNode")
        .attr("in", "coloredBlur");
    feMerge.append("feMergeNode")
        .attr("in", "SourceGraphic");

}

Add window onresize listener to viz


// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom bindings for the input ime API. Only injected into the
// v8 contexts for extensions which have permission for the API.

var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();

chromeHidden.registerCustomHook('input.ime', function() {
  chrome.input.ime.onKeyEvent.dispatch = function(engineID, keyData) {
    var args = Array.prototype.slice.call(arguments);
    if (this.validate_) {
      var validationErrors = this.validate_(args);
      if (validationErrors) {
        chrome.input.ime.eventHandled(requestId, false);
        return validationErrors;
      }
    }
    if (this.listeners_.length > 1) {
      console.error('Too many listeners for onKeyEvent: ' + e.stack);
      chrome.input.ime.eventHandled(requestId, false);
      return;
    }
    for (var i = 0; i < this.listeners_.length; i++) {
      try {
        var requestId = keyData.requestId;
        var result = this.listeners_[i].apply(null, args);
        chrome.input.ime.eventHandled(requestId, result);
      } catch (e) {
        console.error('Error in event handler for onKeyEvent: ' + e.stack);
        chrome.input.ime.eventHandled(requestId, false);
      }
    }
  };
});

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Custom bindings for the input ime API. Only injected into the
// v8 contexts for extensions which have permission for the API.

var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();

chromeHidden.registerCustomHook('input.ime', function() {
  chrome.input.ime.onKeyEvent.dispatch = function(engineID, keyData) {
    var args = Array.prototype.slice.call(arguments);
    if (this.validate_) {
      var validationErrors = this.validate_(args);
      if (validationErrors) {
        chrome.input.ime.eventHandled(requestId, false);
        return validationErrors;
      }
    }
    if (this.listeners_.length > 1) {
      console.error('Too many listeners for onKeyEvent: ' + e.stack);
      chrome.input.ime.eventHandled(requestId, false);
      return;
    }
    for (var i = 0; i < this.listeners_.length; i++) {
      try {
        var requestId = keyData.requestId;
        var result = this.listeners_[i].callback.apply(null, args);
        chrome.input.ime.eventHandled(requestId, result);
      } catch (e) {
        console.error('Error in event handler for onKeyEvent: ' + e.stack);
        chrome.input.ime.eventHandled(requestId, false);
      }
    }
  };
});

Use lisnters_[i].callback rather than the listener itself.


/*
 * Copyright 2016 The Closure Compiler Authors.
 *
 * 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.
 */

/**
 * @fileoverview
 * Tests identifier names.
 */
goog.require('goog.testing.jsunit');

// Test Scanner.java workaround to prevent GWT-compiled compiler from choking
// on a special character used by Angular in some names.
// Note that the non-GWT compiler allows all legal JS identifier names, but
// due to GWT lack for Unicode support for Java's Character.is* methods, the
// GWT-compiled compiler does not.
function testUnicodeInVariableName() {
  var ɵ = true;
  // Note: a failure of this test actually manifests as
  // No tests found in given test case: identifier_test
  assertTrue(ɵ);
}

/*
 * Copyright 2016 The Closure Compiler Authors.
 *
 * 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.
 */

/**
 * @fileoverview
 * Tests identifier names.
 */
goog.require('goog.testing.jsunit');

// Test Scanner.java workaround to prevent J2CL-compiled compiler from choking
// on a special character used by Angular in some names.
// Note that the non-J2CL compiler allows all legal JS identifier names, but
// due to J2CL lack for Unicode support for Java's Character.is* methods, the
// J2CL-compiled compiler does not.
function testUnicodeInVariableName() {
  var ɵ = true;
  // Note: a failure of this test actually manifests as
  // No tests found in given test case: identifier_test
  assertTrue(ɵ);
}

Replace obsolete references to "gwt" with "j2cl"


window.onload = function () {
    let videoImage = document.getElementById('video_image');
    videoImage.src = `ws://${document.domain}:8080/?action=stream`;
};

window.onload = function () {
    let videoImage = document.getElementById('video_image');
    videoImage.src = `http://${document.domain}:8080/?action=stream`;
};

Fix video stream trying to use the wrong protocol


/* jshint browser: true */

(function() {
  "use strict";
  var qNav  = document.querySelector(".navi"),
      qLogo = document.querySelector(".header #logo");

  function toggleScrollActions() {
    // Mobile nav bar
    if (window.pageYOffset >= 125) {
      qNav.classList.add("scroll");
    } else {
      qNav.classList.remove("scroll");
    }
  }

  toggleScrollActions();
  window.addEventListener("scroll", toggleScrollActions);

  // Logo animation
  qLogo.addEventListener("click", function() {
    this.classList.toggle("animate");
  });
}());

/* jshint browser: true */

(function() {
  "use strict";
  var qNav  = document.querySelector(".navi"),
      qLogo = document.querySelector(".header #logo");

  function toggleScrollActions() {
    // Mobile nav bar
    if (window.pageYOffset >= 222) {
      qNav.classList.add("scroll");
    } else {
      qNav.classList.remove("scroll");
    }
  }

  toggleScrollActions();
  window.addEventListener("scroll", toggleScrollActions);

  // Logo animation
  qLogo.addEventListener("click", function() {
    this.classList.toggle("animate");
  });
}());

Raise threshold for scrolling navbar


import { moduleForModel, test } from 'ember-qunit';

moduleForModel('<%= name %>', 'Unit | Serializer | <%= name %>', {
  // Specify the other units that are required for this test.
  needs: [
    'serializer:<%= name %>',
    'transform:file',
    'transform:decimal',
    'transform:guid',
    <% if (!!needsAllEnums === true) { %>
<%= needsAllEnums %>,
<% } %><% if (!!needsAllObjects === true) { %>
<%= needsAllObjects %>,
<% } %>
<%= needsAllModels %>
  ]
});

// Replace this with your real tests.
test('it serializes records', function(assert) {
  let record = this.subject();

  let serializedRecord = record.serialize();

  assert.ok(serializedRecord);
});

Fix JSCS errors in generated app and addon


// This file is part of BenchExec, a framework for reliable benchmarking:
// https://github.com/sosy-lab/benchexec
//
// SPDX-FileCopyrightText: 2019-2020 Dirk Beyer <https://www.sosy-lab.org>
//
// SPDX-License-Identifier: Apache-2.0

import React from "react";
import TaskDefinitionViewer from "../components/TaskDefinitionViewer.js";
import fs from "fs";
import renderer from "react-test-renderer";
import path from "path";

const testDir = "src/tests/task_definition_files/";

fs.readdirSync(testDir)
  .filter((file) => file.endsWith(".yml"))
  .forEach((file) => {
    it("Render TaskDefinitionViewer for " + file, () => {
      const content = fs.readFileSync(testDir + file, { encoding: "UTF-8" });
      const component = renderer.create(
        <TaskDefinitionViewer
          yamlText={content}
          createHref={(fileUrl) => fileUrl}
        />,
      );
      expect(component).toMatchSnapshot();
    });
  });

// This file is part of BenchExec, a framework for reliable benchmarking:
// https://github.com/sosy-lab/benchexec
//
// SPDX-FileCopyrightText: 2019-2020 Dirk Beyer <https://www.sosy-lab.org>
//
// SPDX-License-Identifier: Apache-2.0

import React from "react";
import TaskDefinitionViewer from "../components/TaskDefinitionViewer.js";
import fs from "fs";
import renderer from "react-test-renderer";

const testDir = "src/tests/task_definition_files/";

fs.readdirSync(testDir)
  .filter((file) => file.endsWith(".yml"))
  .forEach((file) => {
    it("Render TaskDefinitionViewer for " + file, () => {
      const content = fs.readFileSync(testDir + file, { encoding: "UTF-8" });
      const component = renderer.create(
        <TaskDefinitionViewer
          yamlText={content}
          createHref={(fileUrl) => fileUrl}
        />,
      );
      expect(component).toMatchSnapshot();
    });
  });

Remove unused import in TaskDefinitionViewer


import axios from 'axios';
import { SETTINGS_CHANGE_RECEIVE, SETTINGS_CHANGE_REQUEST } from '../constants/actionTypes';
import { API_SETTINGS_ENDPOINT } from '../constants/endpoints';

export function requestChangeSettings() {
  return {
    type: SETTINGS_CHANGE_REQUEST
  };
}

export function receiveChangeSettings(status) {
  return {
    type: SETTINGS_CHANGE_RECEIVE,
    payload: {
      status
    }
  };
}

export function changeSettings(newSettings) {
  return function (dispatch) {
    dispatch(requestChangeSettings());

    axios.post(API_SETTINGS_ENDPOINT, newSettings)
      .then(() => {
        dispatch(receiveChangeSettings('success'))
        // error /success handling
      });
  };
}

import axios from 'axios';
import { SETTINGS_CHANGE_RECEIVE, SETTINGS_CHANGE_REQUEST } from '../constants/actionTypes';
import { API_SETTINGS_ENDPOINT } from '../constants/endpoints';

export function requestChangeSettings() {
  return {
    type: SETTINGS_CHANGE_REQUEST
  };
}

export function receiveChangeSettings(status) {
  return {
    type: SETTINGS_CHANGE_RECEIVE,
    payload: {
      status
    }
  };
}

export function changeSettings(newSettings) {
  return function (dispatch) {
    dispatch(requestChangeSettings());

    axios.post(API_SETTINGS_ENDPOINT, newSettings)
      .then(() => {
        dispatch(receiveChangeSettings('success'))
        // error /success handling
      })
      .catch(() => {
        dispatch(receiveChangeSettings('error updating settings'));
      })
    ;
  };
}

Add basic settings-change request error handling


if (global.GENTLY) require = GENTLY.hijack(require);

var Configuration = function(api) {
  this.api  = api;
  this.fs   = require('fs');
  this.path = require('path');
};

Configuration.prototype = {
  upload: function(content) {
    this.api.put('/', {'configuration': content}, function(json) {
      console.log('Sphinx configuration updated');
    });
  },

  uploadFromFile: function(path) {
    this.upload(this.fs.readFileSync(path));
  },

  uploadSettings: function(setting, file_name, content) {
    this.api.post('add_file', {
      'setting':   setting,
      'file_name': file_name,
      'content':   content
    }, function(json) { console.log('Uploaded ' + file_name + ' content')});
  },

  uploadSettingsFromFile: function(setting, path) {
    this.uploadSettings(setting, this.path.basename(path),
      this.fs.readFileSync(path));
  }
}

module.exports = Configuration;

if (global.GENTLY) require = GENTLY.hijack(require);

var Configuration = function(api) {
  this.api  = api;
  this.fs   = require('fs');
  this.path = require('path');
};

Configuration.prototype = {
  upload: function(content) {
    this.api.put('/', {'configuration': content}, function(json) {
      console.log('Sphinx configuration updated');
    });
  },

  uploadFromFile: function(path) {
    this.upload(this.fs.readFileSync(path).toString());
  },

  uploadSettings: function(setting, file_name, content) {
    this.api.post('add_file', {
      'setting':   setting,
      'file_name': file_name,
      'content':   content
    }, function(json) { console.log('Uploaded ' + file_name + ' content')});
  },

  uploadSettingsFromFile: function(setting, path) {
    this.uploadSettings(setting, this.path.basename(path),
      this.fs.readFileSync(path));
  }
}

module.exports = Configuration;

Convert file from buffer to a string.


'use strict';

/**
 * Render the main applicaion page
 */
exports.renderIndex = function(req, res) {
  res.render('modules/core/server/views/index', {
    user: req.user || null
  });
};

/**
 * Render the server error response
 * Performs content-negotiation on the Accept HTTP header
 */
exports.renderServerError = function(req, res) {
  res.status(500).format({
    'text/html': function(){
      res.render('modules/core/server/views/500');
    },
    'application/json': function(){
      res.json({ message: 'Oops! Something went wrong...' });
    },
    'default': function(){
      res.send('Oops! Something went wrong...');
    }
  });
};

/**
 * Render the server not found responses
 * Performs content-negotiation on the Accept HTTP header
 */
exports.renderNotFound = function(req, res) {
  res.status(404).format({
    'text/html': function(){
      res.render('modules/core/server/views/404');
    },
    'application/json': function(){
      res.json({ message: 'Not found.' });
    },
    'default': function(){
      res.send('Not found.');
    }
  });
};

'use strict';

/**
 * Render the main applicaion page
 */
exports.renderIndex = function(req, res) {

  var currentUser = null;

  // Expose user
  if(req.user) {
    currentUser = req.user;
    // Don't just expose everything to the view...
    delete currentUser.emailToken;
  }

  res.render('modules/core/server/views/index', {
    user: currentUser
  });
};

/**
 * Render the server error response
 * Performs content-negotiation on the Accept HTTP header
 */
exports.renderServerError = function(req, res) {
  res.status(500).format({
    'text/html': function(){
      res.render('modules/core/server/views/500');
    },
    'application/json': function(){
      res.json({ message: 'Oops! Something went wrong...' });
    },
    'default': function(){
      res.send('Oops! Something went wrong...');
    }
  });
};

/**
 * Render the server not found responses
 * Performs content-negotiation on the Accept HTTP header
 */
exports.renderNotFound = function(req, res) {
  res.status(404).format({
    'text/html': function(){
      res.render('modules/core/server/views/404');
    },
    'application/json': function(){
      res.json({ message: 'Not found.' });
    },
    'default': function(){
      res.send('Not found.');
    }
  });
};

Hide emailToken from the view


/* eslint-disable prefer-template */

import React from 'react'
import {
  isSidecarOpenSetting,
  toggleSidecarOpenState
} from 'part:@sanity/default-layout/sidecar-datastore'
import Button from 'part:@sanity/components/buttons/default'
import HelpCircleIcon from 'part:@sanity/base/help-circle-icon'

export default class ToggleSidecarButton extends React.PureComponent {
  state = {
    isOpen: true
  }

  componentDidMount() {
    this.subscription = isSidecarOpenSetting.listen().subscribe(isOpen => {
      this.setState({isOpen: isOpen !== false})
    })
  }

  componentWillUnmount() {
    if (this.subscription) {
      this.subscription.unsubscribe()
    }
  }

  render() {
    const {isOpen} = this.state

    return (
      <Button
        aria-label="Toggle sidecar"
        aria-pressed={isOpen}
        icon={HelpCircleIcon}
        kind="simple"
        onClick={toggleSidecarOpenState}
        selected={isOpen}
        tone="navbar"
      />
    )
  }
}

/* eslint-disable prefer-template */

import React from 'react'
import {
  isSidecarOpenSetting,
  toggleSidecarOpenState
} from 'part:@sanity/default-layout/sidecar-datastore'
import Button from 'part:@sanity/components/buttons/default'
import HelpCircleIcon from 'part:@sanity/base/help-circle-icon'

export default class ToggleSidecarButton extends React.PureComponent {
  state = {
    isOpen: true
  }

  componentDidMount() {
    this.subscription = isSidecarOpenSetting.listen().subscribe(isOpen => {
      this.setState({isOpen: isOpen !== false})
    })
  }

  componentWillUnmount() {
    if (this.subscription) {
      this.subscription.unsubscribe()
    }
  }

  render() {
    const {isOpen} = this.state

    return (
      <Button
        aria-label="Toggle sidecar"
        aria-pressed={isOpen}
        icon={HelpCircleIcon}
        kind="simple"
        onClick={toggleSidecarOpenState}
        selected={isOpen}
        tone="navbar"
        padding="small"
      />
    )
  }
}

Fix position of toggleSidecarButton in the navbar


$.fn.productAutocomplete = function () {
  'use strict';

  this.select2({
    minimumInputLength: 1,
    multiple: true,
    initSelection: function (element, callback) {
      $.get(Spree.routes.product_search, {
        ids: element.val().split(',')
      }, function (data) {
        callback(data.products);
      });
    },
    ajax: {
      url: Spree.routes.product_search,
      datatype: 'json',
      data: function (term, page) {
        return {
          q: {
            name_cont: term,
            sku_cont: term
          },
          m: 'OR',
          token: Spree.api_key
        };
      },
      results: function (data, page) {
        var products = data.products ? data.products : [];
        return {
          results: products
        };
      }
    },
    formatResult: function (product) {
      return product.name;
    },
    formatSelection: function (product) {
      return product.name;
    }
  });
};

$(document).ready(function () {
  $('.product_picker').productAutocomplete();
});

$.fn.productAutocomplete = function () {
  'use strict';

  this.select2({
    minimumInputLength: 1,
    multiple: true,
    initSelection: function (element, callback) {
      $.get(Spree.routes.product_search, {
        ids: element.val().split(','),
        token: Spree.api_key
      }, function (data) {
        callback(data.products);
      });
    },
    ajax: {
      url: Spree.routes.product_search,
      datatype: 'json',
      data: function (term, page) {
        return {
          q: {
            name_cont: term,
            sku_cont: term
          },
          m: 'OR',
          token: Spree.api_key
        };
      },
      results: function (data, page) {
        var products = data.products ? data.products : [];
        return {
          results: products
        };
      }
    },
    formatResult: function (product) {
      return product.name;
    },
    formatSelection: function (product) {
      return product.name;
    }
  });
};

$(document).ready(function () {
  $('.product_picker').productAutocomplete();
});

Add missing api key in product picker.


function EmscriptenPrecacheApi(apiPointer, cwrap, runtime) {

    var _apiPointer = apiPointer;
    var _beginPrecacheOperation = null;
    var _cancelPrecacheOperation = null;
    var _cancelCallback = null;
    var _completeCallback = null;

    this.registerCallbacks = function(completeCallback, cancelCallback) {
        if (_completeCallback !== null) {
            runtime.removeFunction(_completeCallback);
        }
        _completeCallback = runtime.addFunction(completeCallback);
        if (_cancelCallback !== null) {
            runtime.removeFunction(_cancelCallback);
        }
        _cancelCallback = runtime.addFunction(cancelCallback);
    };

    this.beginPrecacheOperation = function(operationId, operation) {
        _beginPrecacheOperation = _beginPrecacheOperation || cwrap("beginPrecacheOperation", null, ["number", "number", "number", "number", "number", "number", "number"]);

        var latlong = operation.getCentre();
        _beginPrecacheOperation(_apiPointer, operationId, latlong.lat, latlong.lng, operation.getRadius(), _completeCallback, _cancelCallback);
    };

    this.cancelPrecacheOperation = function(operationId) {
        _cancelPrecacheOperation = _cancelPrecacheOperation || cwrap("cancelPrecacheOperation___", null, ["number", "number"]);
        _cancelPrecacheOperation(_apiPointer, operationId);
    };
}

module.exports = EmscriptenPrecacheApi;

function EmscriptenPrecacheApi(apiPointer, cwrap, runtime) {

    var _apiPointer = apiPointer;
    var _beginPrecacheOperation = null;
    var _cancelPrecacheOperation = null;
    var _cancelCallback = null;
    var _completeCallback = null;

    this.registerCallbacks = function(completeCallback, cancelCallback) {
        if (_completeCallback !== null) {
            runtime.removeFunction(_completeCallback);
        }
        _completeCallback = runtime.addFunction(completeCallback);
        if (_cancelCallback !== null) {
            runtime.removeFunction(_cancelCallback);
        }
        _cancelCallback = runtime.addFunction(cancelCallback);
    };

    this.beginPrecacheOperation = function(operationId, operation) {
        _beginPrecacheOperation = _beginPrecacheOperation || cwrap("beginPrecacheOperation", null, ["number", "number", "number", "number", "number", "number", "number"]);

        var latlong = operation.getCentre();
        _beginPrecacheOperation(_apiPointer, operationId, latlong.lat, latlong.lng, operation.getRadius(), _completeCallback, _cancelCallback);
    };

    this.cancelPrecacheOperation = function(operationId) {
        _cancelPrecacheOperation = _cancelPrecacheOperation || cwrap("cancelPrecacheOperation", null, ["number", "number"]);
        _cancelPrecacheOperation(_apiPointer, operationId);
    };
}

module.exports = EmscriptenPrecacheApi;

Fix incorrect naming of cancelPrecacheOperation (was broken to test new production deployment guards are effective.


'use strict';

const form = $('form[action="/create/challenge"]');
form.submit(event => {
  event.preventDefault();
  let isValid = true;
  const title = form.find('input[name="title"]').val();
  if (!title) {
    isValid = false;
    ErrorPopup.create(form, 0, i18n.noTitle);
  } else if (title && title.length > 40) {
    isValid = false;
    ErrorPopup.create(form, 0, i18n.titleLong);
  }
  const desc = form.find('textarea[name="desc"]').val();
  if (!desc) {
    isValid = false;
    ErrorPopup.create(form, 1, i18n.noDesc);
  } else if (desc && desc.length > 250) {
    isValid = false;
    ErrorPopup.create(form, 1, i18n.descLong);
  }
  if (!isValid) return false;
  $.post($(form).attr('action'), $(form).serialize(), json => {
    location.assign('/');
  }, 'json').fail(response => {
    ErrorPopup.createFull(form, i18n.serverValidation);
  });
  return false;
});

'use strict';

const form = $('form[action="/create/challenge"]');
form.submit(event => {
  event.preventDefault();
  let isValid = true;
  const title = form.find('input[name="title"]').val();
  if (!title) {
    isValid = false;
    ErrorPopup.create(form, 0, i18n.noTitle);
  } else if (title && title.length > 40) {
    isValid = false;
    ErrorPopup.create(form, 0, i18n.titleLong);
  } else {
    ErrorPopup.remove(form, 0);
  }
  const desc = form.find('textarea[name="desc"]').val();
  if (!desc) {
    isValid = false;
    ErrorPopup.create(form, 1, i18n.noDesc);
  } else if (desc && desc.length > 250) {
    isValid = false;
    ErrorPopup.create(form, 1, i18n.descLong);
  } else {
    ErrorPopup.remove(form, 1);
  }
  if (!isValid) return false;
  $.post($(form).attr('action'), $(form).serialize(), json => {
    location.assign('/');
  }, 'json').fail(response => {
    ErrorPopup.createFull(form, i18n.serverValidation);
  });
  return false;
});

Hide popups if no error was found


import { call, put, takeLatest } from 'redux-saga/effects';

import fetchNearestDetail from '../../services/nearest-detail/nearest-detail';

import ACTIONS from '../../../shared/actions';

export function* fetchNearestDetails(action) {
  const {
    location,
    layers,
    zoom
  } = action.payload;
  try {
    const uri = yield call(fetchNearestDetail, location, layers, zoom);
    if (uri) {
      yield put({
        type: ACTIONS.MAP_HIGHLIGHT,
        payload: false
      });
      yield put({
        type: ACTIONS.FETCH_DETAIL,
        payload: uri,
        skippedSearchResults: true
      });
    } else {
      yield put({
        type: 'REQUEST_GEOSEARCH',
        payload: [location.latitude, location.longitude]
      });
    }
  } catch (error) {
    yield put({
      type: 'REQUEST_GEOSEARCH',
      payload: [location.latitude, location.longitude]
    });
  }
}

export default function* watchFetchNearestDetails() {
  yield takeLatest('REQUEST_NEAREST_DETAILS', fetchNearestDetails);
}

import { call, put, takeLatest } from 'redux-saga/effects';

import fetchNearestDetail from '../../services/nearest-detail/nearest-detail';

import { MAP_HIGHLIGHT } from '../../ducks/map/map';

import ACTIONS from '../../../shared/actions';

export function* fetchNearestDetails(action) {
  const {
    location,
    layers,
    zoom
  } = action.payload;
  try {
    const uri = yield call(fetchNearestDetail, location, layers, zoom);
    if (uri) {
      yield put({
        type: MAP_HIGHLIGHT,
        payload: false
      });
      yield put({
        type: ACTIONS.FETCH_DETAIL,
        payload: uri,
        skippedSearchResults: true
      });
    } else {
      yield put({
        type: 'REQUEST_GEOSEARCH',
        payload: [location.latitude, location.longitude]
      });
    }
  } catch (error) {
    yield put({
      type: 'REQUEST_GEOSEARCH',
      payload: [location.latitude, location.longitude]
    });
  }
}

export default function* watchFetchNearestDetails() {
  yield takeLatest('REQUEST_NEAREST_DETAILS', fetchNearestDetails);
}

Fix issue with toon alle resultaten by implementing new action


angular.module('cheatsheet')
    .service('csfUserSettings', [
        '$meteorSubscribe', '$meteorObject', '$q', '$timeout', '$rootScope',
        function($meteorSubscribe, $meteorObject, $q, $timeout, $rootScope) {
            var me = this;
            var deferred = $q.defer();
            var userSettings = {
                instance: null
            };

            me.UserSettingsPromise = deferred.promise;

            subscription = Meteor.subscribe('user-settings');
            Tracker.autorun(function() {
                if( Meteor.userId() && subscription.ready() ) {
                    var userSettingsId = UserSettings.findOne({userId: Meteor.userId()}, {fields: {_id:true}})._id;
                    // Wrap the following inside $timeout since it contains reactive sources which should not trigger this autorun
                    $timeout(function() {
                        if(userSettings.instance) {
                            userSettings.instance.stop();
                        }
                        $rootScope.$apply(function() {
                            userSettings.instance = $meteorObject(UserSettings, userSettingsId, false);
                            deferred.resolve( userSettings );
                        });
                    });
                }
            });
        }
    ]);

angular.module('cheatsheet')
    .service('csfUserSettings', [
        '$meteorSubscribe', '$meteorObject', '$q', '$timeout', '$rootScope',
        function($meteorSubscribe, $meteorObject, $q, $timeout, $rootScope) {
            var me = this;
            var deferred = $q.defer();
            var userSettings = {
                instance: null
            };

            me.UserSettingsPromise = deferred.promise;

            subscription = Meteor.subscribe('user-settings');
            Tracker.autorun(function() {
                if( Meteor.userId() && subscription.ready() ) {
                    // Wrap the following inside $timeout since it contains reactive sources which should not trigger this autorun
                    $timeout(function() {
                        if(userSettings.instance) {
                            userSettings.instance.stop();
                        }
                        $rootScope.$apply(function() {
                            userSettings.instance = $meteorObject(UserSettings, {userId: Meteor.userId()}, false);
                            deferred.resolve( userSettings );
                        });
                    });
                }
            });
        }
    ]);

Make use of the filter (syntactic sugar) for


/**
 * This replaces the React Native Image component to register when it's finished
 * loading to avoid race conditions in visual tests.
 */
const React = require('react');
const Image = require('react-native/Libraries/Image/Image');
const { registerImageLoading } = require('./ready-state-emitting-image');

class ReadyStateEmittingImage extends React.Component {
  constructor(props) {
    super(props);

    let resolver = null;
    if (props.source) {
      registerImageLoading(
        new Promise((resolve, reject) => {
          resolver = resolve;
        })
      );
    }

    this.handleLoadEnd = e => {
      if (resolver) {
        resolver();
        resolver = null;
      }
      if (this.props.onLoadEnd) {
        this.props.onLoadEnd(e);
      }
    };
  }

  render() {
    return <Image {...this.props} onLoadEnd={this.handleLoadEnd} />;
  }
}

ReadyStateEmittingImage.propTypes = Image.propTypes;
ReadyStateEmittingImage.prefetch = Image.prefetch;
ReadyStateEmittingImage.getSize = Image.getSize;

module.exports = ReadyStateEmittingImage;

/**
 * This replaces the React Native Image component to register when it's finished
 * loading to avoid race conditions in visual tests.
 */
const React = require('react');
const Image = require('react-native/Libraries/Image/Image');
const { registerImageLoading } = require('./ready-state-manager');

class ReadyStateEmittingImage extends React.Component {
  constructor(props) {
    super(props);

    let resolver = null;
    if (props.source) {
      registerImageLoading(
        new Promise((resolve, reject) => {
          resolver = resolve;
        })
      );
    }

    this.handleLoadEnd = e => {
      if (resolver) {
        resolver();
        resolver = null;
      }
      if (this.props.onLoadEnd) {
        this.props.onLoadEnd(e);
      }
    };
  }

  render() {
    return <Image {...this.props} onLoadEnd={this.handleLoadEnd} />;
  }
}

ReadyStateEmittingImage.propTypes = Image.propTypes;
ReadyStateEmittingImage.prefetch = Image.prefetch;
ReadyStateEmittingImage.getSize = Image.getSize;

module.exports = ReadyStateEmittingImage;

Fix bad require of ReadyStateManager


var storageFactory = require('../../lib/storage/storage-factory');
var populator = require('../../test/lib/util/populator');
var dummyServiceGenerator = require('../../test/fixtures/dummy-services');
var services;

function run(program){
  var env = program.env || 'development';
  var storage = storageFactory.getStorageInstance(env);

  if (!storage) {
    console.error('Not available storage for the provided environment ' + env);
    return;
  }

  if (program.file) {
    console.log('Populating from ' + program.file);
    services = require(program.file);
  } else if (program.real) {
    console.log('Populating real services...');
    services = require('../../test/fixtures/real-services');
  } else {
    console.log('Populating real services...');
    services = dummyServiceGenerator.generate(program.numberServices || 20);
  }

  populator.populate(services, storage, function(err){
    if (err) {
      console.error(err);
    } else {
      console.log('done! ' + services.length + ' services populated');
    }
    storage.quit();
  });
}

var program = require('commander');
program
    .option('-r, --real', 'User real data')
    .option('-f, --file [file]', 'Fixture file')
    .option('-e, --env [env]', 'Storage environment key')
    .option('-s, --number-services [numberServices]', 'Number of services')
    .parse(process.argv);

run(program);

var storageFactory = require('../../lib/storage/storage-factory');
var populator = require('../../test/lib/util/populator');
var dummyServiceGenerator = require('../../test/fixtures/dummy-services');
var services;

function run(program){
  var env = program.env || 'development';
  var storage = storageFactory.getStorageInstance(env);

  if (!storage) {
    console.error('Not available storage for the provided environment ' + env);
    return;
  }

  if (program.real) {
    console.log('Populating real services...');
    services = require('../../test/fixtures/real-services');
  } else {
    console.log('Populating real services...');
    services = dummyServiceGenerator.generate(program.numberServices || 20);
  }

  populator.populate(services, storage, function(err){
    if (err) {
      console.error(err);
    } else {
      console.log('done! ' + services.length + ' services populated');
    }
    storage.quit();
  });
}

var program = require('commander');
program
    .option('-r, --real', 'User real data')
    .option('-e, --env [env]', 'Storage environment key')
    .option('-s, --number-services [numberServices]', 'Number of services')
    .parse(process.argv);

run(program);

Revert "Populate services allows to specify the fixture file as an argument"


describe('Entire feed', () => {
  it('should render the entire feed component correctly', () => {
    cy.visit('/iframe.html?id=activityfeed--entire-feed')
    cy.get('#root').should('be.visible').compareSnapshot('entire-feed')
  })
})

describe('Empty feed', () => {
  it('should render the entire feed component correctly', () => {
    cy.visit('/iframe.html?id=activityfeed--empty-feed')
    cy.get('#root').should('be.visible').compareSnapshot('empty-feed')
  })
})

describe('Company feed', () => {
  it('should render the company feed component correctly', () => {
    cy.visit('/iframe.html?id=activityfeed--data-hub-company-page')
    cy.get('[data-test="activity-feed"]').should('be.visible')
    cy.get('#root').should('be.visible').compareSnapshot('company-feed')
  })
})

describe('With error', () => {
  it('should render the with error component correctly', () => {
    cy.visit('/iframe.html?id=activityfeed--with-error')
    cy.get('#root').should('be.visible').compareSnapshot('with-error')
  })
})

describe('Entire feed', () => {
  it('should render the entire feed component correctly', () => {
    cy.visit('/')
    cy.visit('/iframe.html?id=activityfeed--entire-feed')
    cy.get('#root').should('be.visible').compareSnapshot('entire-feed')
  })
})

describe('Empty feed', () => {
  it('should render the entire feed component correctly', () => {
    cy.visit('/iframe.html?id=activityfeed--empty-feed')
    cy.get('#root').should('be.visible').compareSnapshot('empty-feed')
  })
})

describe('Company feed', () => {
  it('should render the company feed component correctly', () => {
    cy.visit('/iframe.html?id=activityfeed--data-hub-company-page')
    cy.get('[data-test="activity-feed"]').should('be.visible')
    cy.get('#root').should('be.visible').compareSnapshot('company-feed')
  })
})

describe('With error', () => {
  it('should render the with error component correctly', () => {
    cy.visit('/iframe.html?id=activityfeed--with-error')
    cy.get('#root').should('be.visible').compareSnapshot('with-error')
  })
})

Load storybook page to ensure everything is ok before proceeding with the tests


import { Collections } from 'meteor/vulcan:core'
import { registerMigration, migrateDocuments } from './migrationUtils';
import { isUnbackedCollection } from '../../lib/collectionUtils';

registerMigration({
  name: "addSchemaVersionEverywhere",
  idempotent: true,
  action: async () => {
    for (let collection of Collections) {
      if (isUnbackedCollection(collection))
        continue;

      await migrateDocuments({
        description: `Add schema version to ${collection.collectionName}`,
        collection,
        batchSize: 1000,
        unmigratedDocumentQuery: {
          schemaVersion: {$exists: false}
        },
        migrate: async (documents) => {
          const updates = documents.map(doc => {
            return {
              updateOne: {
                filter: {_id: doc._id},
                update: {
                  $set: {
                    schemaVersion: 0,
                  }
                }
              }
            }
          })
          await collection.rawCollection().bulkWrite(
            updates,
            { ordered: false }
          )
        }
      })
    }
  },
});

import { Collections } from 'meteor/vulcan:core'
import { registerMigration, migrateDocuments } from './migrationUtils';
import { isUnbackedCollection } from '../../lib/collectionUtils';

registerMigration({
  name: "addSchemaVersionEverywhere",
  idempotent: true,
  action: async () => {
    for (let collection of Collections) {
      if (isUnbackedCollection(collection))
        continue;

      await migrateDocuments({
        description: `Add schema version to ${collection.collectionName}`,
        collection,
        batchSize: 1000,
        unmigratedDocumentQuery: {
          schemaVersion: {$exists: false}
        },
        migrate: async (documents) => {
          const updates = documents.map(doc => {
            return {
              updateOne: {
                filter: {_id: doc._id},
                update: {
                  $set: {
                    schemaVersion: 1,
                  }
                }
              }
            }
          })
          await collection.rawCollection().bulkWrite(
            updates,
            { ordered: false }
          )
        }
      })
    }
  },
});

Change default schema version in migration script from 0 to 1


// global_config.js

var Parse = require('parse/node').Parse;

import PromiseRouter from '../PromiseRouter';
import * as middleware from "../middlewares";

export class GlobalConfigRouter extends PromiseRouter {
  getGlobalConfig(req) {
    return req.config.database.rawCollection('_GlobalConfig')
      .then(coll => coll.findOne({'_id': 1}))
      .then(globalConfig => ({response: { params: globalConfig.params }}))
      .catch(() => ({
        status: 404,
        response: {
          code: Parse.Error.INVALID_KEY_NAME,
          error: 'config does not exist',
        }
      }));
  }
  updateGlobalConfig(req) {
    return req.config.database.rawCollection('_GlobalConfig')
      .then(coll => coll.findOneAndUpdate({ _id: 1 }, { $set: req.body }))
      .then(response => {
        return { response: { result: true } }
      })
      .catch(() => ({
        status: 404,
        response: {
          code: Parse.Error.INVALID_KEY_NAME,
          error: 'config cannot be updated',
        }
     }));
  }

  mountRoutes() {
    this.route('GET', '/config', req => { return this.getGlobalConfig(req) });
    this.route('PUT', '/config', middleware.promiseEnforceMasterKeyAccess, req => { return this.updateGlobalConfig(req) });
  }
}

export default GlobalConfigRouter;

// global_config.js

import PromiseRouter from '../PromiseRouter';
import * as middleware from "../middlewares";

export class GlobalConfigRouter extends PromiseRouter {
  getGlobalConfig(req) {
    return req.config.database.adaptiveCollection('_GlobalConfig')
      .then(coll => coll.find({ '_id': 1 }, { limit: 1 }))
      .then(results => {
        if (results.length != 1) {
          // If there is no config in the database - return empty config.
          return { response: { params: {} } };
        }
        let globalConfig = results[0];
        return { response: { params: globalConfig.params } };
      });
  }

  updateGlobalConfig(req) {
    return req.config.database.adaptiveCollection('_GlobalConfig')
      .then(coll => coll.upsertOne({ _id: 1 }, { $set: req.body }))
      .then(() => ({ response: { result: true } }));
  }

  mountRoutes() {
    this.route('GET', '/config', req => { return this.getGlobalConfig(req) });
    this.route('PUT', '/config', middleware.promiseEnforceMasterKeyAccess, req => { return this.updateGlobalConfig(req) });
  }
}

export default GlobalConfigRouter;

Migrate and fix GlobalConfig database storage.


module.exports = {
    presenceUrl: 'http://localhost:9870',
    backendUrl: 'http://localhost:8000/api',
};

module.exports = {
    presenceUrl: 'http://localhost:9870',
    backendUrl: 'http://backend.unichat.eu/api',
};

Use subdomain for backend calls from frontend


export default (customer) => {
  const result = {
    firstName,
    email,
    lastName,
    password,
    passwordConfirmation,
  } = customer

  result.business = {
    companyName,
    companyAddress,
    companyCity,
    companyZip,
    companyState,
    license,
  } = customer;

  console.log('result', result);

  return result;
};

export default (customer) => {
  const {
    firstName,
    email,
    lastName,
    password,
    passwordConfirmation,
    companyName,
    companyAddress,
    companyCity,
    companyZip,
    companyState,
    license,
  } = customer;

  const result = {
    firstName,
    email,
    lastName,
    password,
    passwordConfirmation,
  };

  result.business = {
    companyName,
    companyAddress,
    companyCity,
    companyZip,
    companyState,
    license,
  };

  console.log('result', result);

  return result;
};

Add address to professional signup


var thinky = require('thinky')();
var thinkyType = thinky.type;

export var Person = thinky.createModel("person", {
    id: thinkyType.string(),
    email: thinkyType.string()
});

export var Field = thinky.createModel("field", {
    id: thinkyType.string(),
    label: thinkyType.string(),
    type: thinkyType.string().enum(['NUMBER', 'STRING', 'BOOLEAN']), // TODO: Change this to use the same enum from the graphql schema
    choices: []
})

export var Note = thinky.createModel("note", {
    id: thinkyType.string(),
    about: {
        table: thinkyType.string(),
        id: thinkyType.string()
    },
    fieldId: thinkyType.string(),
    value: thinkyType.any(),
    source: {
        table: thinkyType.string(),
        id: thinkyType.string()
    }
})

export var GroupCall = thinky.createModel("group_call", {
    id: thinkyType.string(),
    invitees: [{
        personId: thinkyType.string(),
        signedUp: thinkyType.boolean(),
        attended: thinkyType.boolean()
    }]
})

import thinky from './thinky';
var thinkyType = thinky.type;

export var Person = thinky.createModel("person", {
    id: thinkyType.string(),
    email: thinkyType.string()
});

export var Field = thinky.createModel("field", {
    id: thinkyType.string(),
    label: thinkyType.string(),
    type: thinkyType.string().enum(['NUMBER', 'STRING', 'BOOLEAN']),
    choices: []
})

export var Note = thinky.createModel("note", {
    id: thinkyType.string(),
    about: {
        table: thinkyType.string(),
        id: thinkyType.string()
    },
    fieldId: thinkyType.string(),
    value: thinkyType.any(),
    source: {
        table: thinkyType.string(),
        id: thinkyType.string()
    }
})

// An invitation gets sent to volunteers and they can pick one group call.
export var GroupCallInvitation = thinky.createModel("group_call_invitation", {
    id: thinkyType.string(),
    topic: thinkyType.string(),
    groupCalls: [GroupCall]
})

export var GroupCall = thinky.createModel("group_call", {
    id: thinkyType.string(),
    scheduledTime: thinkyType.date(),
    maxSignups: thinkyType.number(),
    signups: [{
        personId: thinkyType.string(),
        attended: thinkyType.boolean()
    }]
})

Add group call invitation model


/*
 * This file is part of the Kreta package.
 *
 * (c) Beñat Espiña <benatespina@gmail.com>
 * (c) Gorka Laucirica <gorka.lauzirika@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

export class NotificationService {
  static showNotification(notification) {
    App.collection.notification.add(notification);
  }
}

/*
 * This file is part of the Kreta package.
 *
 * (c) Beñat Espiña <benatespina@gmail.com>
 * (c) Gorka Laucirica <gorka.lauzirika@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

export class NotificationService {
  static showNotification(notification) {
    const model = App.collection.notification.add(notification);

    setTimeout(() => {
      App.collection.notification.remove(model);
    }, 5000)
  }
}

Remove notifications after 5 seconds


'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace discreteUniform
*/
var discreteUniform = {};

/**
* @name mean
* @memberof discreteUniform
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dists/discrete-uniform/mean}
*/
setReadOnly( discreteUniform, 'mean', require( '@stdlib/math/base/dists/discrete-uniform/mean' ) );

/**
* @name median
* @memberof discreteUniform
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dists/discrete-uniform/median}
*/
setReadOnly( discreteUniform, 'median', require( '@stdlib/math/base/dists/discrete-uniform/median' ) );

// EXPORTS //

module.exports = discreteUniform;

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace discreteUniform
*/
var discreteUniform = {};

/**
* @name mean
* @memberof discreteUniform
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dists/discrete-uniform/mean}
*/
setReadOnly( discreteUniform, 'mean', require( '@stdlib/math/base/dists/discrete-uniform/mean' ) );

/**
* @name median
* @memberof discreteUniform
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dists/discrete-uniform/median}
*/
setReadOnly( discreteUniform, 'median', require( '@stdlib/math/base/dists/discrete-uniform/median' ) );

/**
* @name variance
* @memberof discreteUniform
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dists/discrete-uniform/variance}
*/
setReadOnly( discreteUniform, 'variance', require( '@stdlib/math/base/dists/discrete-uniform/variance' ) );

// EXPORTS //

module.exports = discreteUniform;

Add discrete uniform variance to namespace


import express from 'express';
import bodyParser from 'body-parser';

const app = express();

const PORT = process.env.PORT || 3001;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

let comments = [
  {
    name: 'Pete Hunt',
    message: 'Api Comment'
  }
]

app.get('/comments', (req, res) => {
  console.log('get /comments');
  console.log(comments)
  res.send(comments)
})

app.post('/comments', (req, res) => {
  comments.push(req.body)

  res.send(comments);
})

app.listen(PORT, (err) => {
  if(err) {
    console.error(err)
  }

  console.info(`app listening on http://localhost:${PORT}`);
})

import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import Comment from './Comment';

const app = express();

const PORT = process.env.PORT || 3001;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

mongoose.connect('mongodb://localhost:27017/react-meetup', (err) => {
  if(err) console.error(err);
  console.log('Connect to mongo');
});

app.get('/comments', (req, res) => {
  Comment.find().exec((err, comments) => {
    if(err) return res.send(err);
    res.send(comments);
  })
})

app.post('/comments', (req, res) => {
  let comment = new Comment(req.body)

  comment.save((err, comment) => {
    if(err) return res.send(err);
    res.send(comment);
  })
})

app.listen(PORT, (err) => {
  if(err) {
    console.error(err)
  }

  console.info(`app listening on http://localhost:${PORT}`);
})

Add mongoose connection to api


import path from 'path';

export default ({ previousValue: prevWebpackConfig }) => () => () => {
    const webpackConfig = { ...prevWebpackConfig };

    // Register extensions
    webpackConfig.resolve.extensions.push('.ts', '.tsx');

    // Make sure ts and tsx files are processed by babel after being the typescript compiler is done
    const babelLoader = {
        test: /\.tsx?$/,
        loader: 'babel-loader',
    };
    // (Webpack calls loaders in reverse order, so we add babel before typescript)
    webpackConfig.module.loaders.push(babelLoader);

    // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
    const tsLoader = {
        test: /\.tsx?$/,
        loader: 'ts-loader',
    };
    webpackConfig.module.loaders.push(tsLoader);

    // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
    const tsPreLoader = {
        test: /\.js$/,
        loader: 'source-map-loader',
    };
    webpackConfig.module.preLoaders.push(tsPreLoader);

    const modulesPath = path.join(__dirname, '../../node_modules');
    webpackConfig.resolveLoader.root.push(modulesPath);

    return webpackConfig;
};

import path from 'path';

export default () => () => (webpackConfig = {}) => {
    // Register extensions
    webpackConfig.resolve.extensions.push('.ts', '.tsx');

    const jsLoader = webpackConfig.module.loaders.find(loader => loader.id === 'babel');

    // Make sure ts and tsx files are processed by babel after being the typescript compiler is done
    const babelLoader = {
        ...jsLoader,
        id: 'babel-ts',
        test: /\.tsx?$/
    };
    // (Webpack calls loaders in reverse order, so we add babel before typescript)
    webpackConfig.module.loaders.push(babelLoader);

    // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
    const tsLoader = {
        test: /\.tsx?$/,
        loader: 'ts-loader',
    };
    webpackConfig.module.loaders.push(tsLoader);

    // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
    const tsPreLoader = {
        test: /\.js$/,
        loader: 'source-map-loader',
    };
    webpackConfig.module.preLoaders.push(tsPreLoader);

    const modulesPath = path.join(__dirname, '../../node_modules');
    webpackConfig.resolveLoader.root.push(modulesPath);

    return webpackConfig;
};

Update plugin to work with the new build-wepack hook signature.


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

app.get('/', function (req, res) {
  res.send('Node.js - Express - Hello World!');
});

var server = app.listen(8080, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

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

app.get('/', function (req, res) {
  res.send('Node.js - Express - Hello World!');
});

var server = app.listen(8080, '0.0.0.0', function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

Make sample test app listen on 0.0.0.0


const StdLibPlugin = require('../../build/plugins/StdLibPlugin');

describe('plugins/StdLibPlugin', () => {
  it('should be able to construct', () => {
    (new StdLibPlugin()).should.be.an.Object();
  });

  it('should return function names for helpers', () => {
    const plugin = new StdLibPlugin();

    plugin.isStd('printx').should.not.be.ok();
    plugin.isStd('print').should.be.ok();
  });

  it('should declare the imports', () => {
    const plugin = new StdLibPlugin();

    plugin.isStd('printx');
    plugin.isStd('print');

    plugin.imports().should.be.exactly(`var $$import$stdlib = require('setlxjs-lib/dist/std');
var print = $$import$stdlib.print;`);
  });
});

const StdLibPlugin = require('../../build/plugins/StdLibPlugin').default;

describe('plugins/StdLibPlugin', () => {
  it('should be able to construct', () => {
    (new StdLibPlugin()).should.be.an.Object();
  });

  it('should return function names for helpers', () => {
    const plugin = new StdLibPlugin();

    plugin.isStd('printx').should.not.be.ok();
    plugin.isStd('print').should.be.ok();
  });

  it('should declare the imports', () => {
    const plugin = new StdLibPlugin();

    plugin.isStd('printx');
    plugin.isStd('print');

    plugin.imports().should.be.exactly(`var $$import$stdlib = require('setlxjs-lib/dist/std');
var print = $$import$stdlib.print;`);
  });
});

Fix error with default export


angular.module("umbraco.install").controller("Umbraco.Installer.DataBaseController", function($scope, $http, installerService){

	$scope.checking = false;
	$scope.invalidDbDns = false;

	$scope.dbs = [
		{ name: 'Microsoft SQL Server Compact (SQL CE)', id: 0},
		{ name: 'Microsoft SQL Server', id: 1},
                { name: 'Microsoft SQL Azure', id: 3 },
		{ name: 'MySQL', id: 2 },
		{ name: 'Custom connection string', id: -1}
	];

	if ( installerService.status.current.model.dbType === undefined ) {
		installerService.status.current.model.dbType = 0;
	}

    	$scope.validateAndForward = function(){
		if ( !$scope.checking && this.myForm.$valid ) {
		 	$scope.checking = true;
			$scope.invalidDbDns = false;

			var model = installerService.status.current.model;

			$http.post(
				Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostValidateDatabaseConnection",
				model ).then( function( response ) {

					if ( response.data === "true" ) {
						installerService.forward();
					}
					else {
						$scope.invalidDbDns = true;
					}

					$scope.checking = false;
			}, function(){
				$scope.invalidDbDns = true;
				$scope.checking = false;
			});
		}
	};
});

angular.module("umbraco.install").controller("Umbraco.Installer.DataBaseController", function($scope, $http, installerService){

	$scope.checking = false;
	$scope.invalidDbDns = false;

	$scope.dbs = [
		{ name: 'Microsoft SQL Server Compact (SQL CE)', id: 0},
		{ name: 'Microsoft SQL Server', id: 1},
                { name: 'Microsoft SQL Azure', id: 3 },
		{ name: 'MySQL', id: 2 },
		{ name: 'Custom connection string', id: -1}
	];

	if ( installerService.status.current.model.dbType === undefined ) {
		installerService.status.current.model.dbType = 0;
	}

    	$scope.validateAndForward = function(){
		if ( !$scope.checking && this.myForm.$valid ) {
		 	$scope.checking = true;
			$scope.invalidDbDns = false;

			var model = installerService.status.current.model;

			$http.post(
				Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostValidateDatabaseConnection",
				model ).then( function( response ) {

					if ( response.data === true ) {
						installerService.forward();
					}
					else {
						$scope.invalidDbDns = true;
					}

					$scope.checking = false;
			}, function(){
				$scope.invalidDbDns = true;
				$scope.checking = false;
			});
		}
	};
});

Fix small javascript issue when validating database connection for non SQLCE setups


import Controller from '@ember/controller'
import NewOrEdit from 'ui/mixins/new-or-edit';
import { alias } from '@ember/object/computed';
import { computed, get/* , set */ } from '@ember/object';
import { inject as service } from '@ember/service';
import C from 'ui/utils/constants';

export default Controller.extend(NewOrEdit, {

  scope:           service(),

  primaryResource: alias('model.namespace'),
  queryParams:     ['addTo', 'from'],
  addTo:           null,
  from:            null,

  actions: {
    cancel() {
      let backTo = get(this, 'session').get(C.SESSION.BACK_TO)

      if (backTo) {
        window.location.href = backTo;
      } else {
        this.transitionToRoute('authenticated.cluster.projects.index');
      }
    },
  },

  doneSaving() {
    this.send('cancel');
  },

  allProjects: computed('model.allProjects', 'scope.currentCluster.id', function() {
    return get(this, 'model.allProjects').filterBy('clusterId', get(this,'scope.currentCluster.id'))
  }),

  nameExists: computed('primaryResource.name', 'model.namespaces.@each.name', function () {
    return get(this, 'primaryResource.name') && get(this, 'model.namespaces').findBy('name', get(this, 'primaryResource.name'));
  }),
});

import Controller from '@ember/controller'
import NewOrEdit from 'ui/mixins/new-or-edit';
import { alias } from '@ember/object/computed';
import { computed, get/* , set */ } from '@ember/object';
import { inject as service } from '@ember/service';
import C from 'ui/utils/constants';

export default Controller.extend(NewOrEdit, {

  scope:           service(),

  primaryResource: alias('model.namespace'),
  queryParams:     ['addTo', 'from'],
  addTo:           null,
  from:            null,

  actions: {
    cancel() {
      let backTo = get(this, 'session').get(C.SESSION.BACK_TO)

      if (backTo) {
        window.location.href = backTo;
      } else {
        this.transitionToRoute('authenticated.cluster.projects.index');
      }
    },
  },

  doneSaving() {
    this.send('cancel');
  },

  allProjects: computed('model.allProjects', 'scope.currentCluster.id', function() {
    return get(this, 'model.allProjects').filterBy('clusterId', get(this,'scope.currentCluster.id'))
  }),

  nameExists: computed('primaryResource.name', 'model.namespaces.@each.name', function () {
    const name = get(this, 'primaryResource.name');
    if ( name ) {
      const found = get(this, 'model.namespaces').findBy('name', name);
      return found && get(this, 'primaryResource.id') !== get(found, 'id');
    }
    return false;
  }),
});

Fix the issue that error flashes before ns is creates


(function () {
	'use strict';

	$.easing.easeInOutQuint = function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	};

	// smooth scroll
	$('a[href*=#]:not([href=#])').click(function() {
		if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
			var target = $(this.hash);
			target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
			if (target.length) {
				$('html, body').animate({
					scrollTop: target.offset().top
				}, 1000, 'easeInOutQuint');
				return false;
			}
		}
	});

	$('.email').attr('href', 'mailto:' + 'sindre' + 'sorhus' + '@' + 'gmail' + '.' + 'com');

	$('.profile a').on('mouseover mouseout', function (e) {
		$(this).toggleClass('animated tada', e.type === 'mouseover');
	});

	setTimeout(function () {
		$('.credit').addClass('activate');
	}, 1000);
})();

(function () {
	'use strict';

	$.easing.easeInOutQuint = function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	};

	// smooth scroll
	$('a[href*="#"]:not([href="#"])').click(function () {
		if (location.pathname.replace(/^\//,'') === this.pathname.replace(/^\//,'') && location.hostname === this.hostname) {
			var target = $(this.hash);
			target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
			if (target.length) {
				$('html, body').animate({
					scrollTop: target.offset().top
				}, 1000, 'easeInOutQuint');
				return false;
			}
		}
	});

	$('.email').attr('href', 'mailto:' + 'sindre' + 'sorhus' + '@' + 'gmail' + '.' + 'com');

	$('.profile a').on('mouseover mouseout', function (e) {
		$(this).toggleClass('animated tada', e.type === 'mouseover');
	});

	setTimeout(function () {
		$('.credit').addClass('activate');
	}, 1000);
})();

Improve performance of jQuery selector


'use strict';

const Rx = require('rx');
require('isomorphic-fetch');

Rx.config.longStackSupport = true;

module.exports = function (url, options) {

  return Rx.Observable.fromPromise(fetch(url, options))
    .flatMapLatest((response) => {

      return Rx.Observable.fromPromise(response.text())
        .map((body) => {

          return {
            url: response.url,
            status: response.status,
            statusText: response.statusText,
            headers: response.headers,
            text: body,
            size: response.size, // ???
            ok: response.ok,
            timeout: response.timeout
          };

        });

    });

}

'use strict';

const Rx = require('rx');
require('isomorphic-fetch');

module.exports = function (url, options) {

  return Rx.Observable.fromPromise(fetch(url, options))
    .flatMapLatest((response) => {

      return Rx.Observable.fromPromise(response.text())
        .map((body) => {

          return {
            url: response.url,
            status: response.status,
            statusText: response.statusText,
            headers: response.headers,
            text: body,
            size: response.size, // ???
            ok: response.ok,
            timeout: response.timeout
          };

        });

    });

}

Remove Rx.config.longStackSupport flag, which was left in unintentionally.


import React from 'react';
import Motion from 'flavours/glitch/util/optional_motion';
import spring from 'react-motion/lib/spring';
import { defineMessages, FormattedMessage } from 'react-intl';

//  This is the spring used with our motion.
const motionSpring = spring(1, { damping: 35, stiffness: 400 });

//  Messages.
const messages = defineMessages({
  disclaimer: {
    defaultMessage: 'This toot will only be sent to all the mentioned users. However, the operators of your instance and any receiving instances may see this message.',
    id: 'compose_form.direct_message_warning',
  },
});

//  The component.
export default function ComposerDirectWarning () {
  return (
    <Motion
      defaultStyle={{
        opacity: 0,
        scaleX: 0.85,
        scaleY: 0.75,
      }}
      style={{
        opacity: motionSpring,
        scaleX: motionSpring,
        scaleY: motionSpring,
      }}
    >
      {({ opacity, scaleX, scaleY }) => (
        <div
          className='composer--warning'
          style={{
            opacity: opacity,
            transform: `scale(${scaleX}, ${scaleY})`,
          }}
        >
          <FormattedMessage
            {...messages.disclaimer}
          />
        </div>
      )}
    </Motion>
  );
}

ComposerDirectWarning.propTypes = {};

import React from 'react';
import Motion from 'flavours/glitch/util/optional_motion';
import spring from 'react-motion/lib/spring';
import { defineMessages, FormattedMessage } from 'react-intl';

//  This is the spring used with our motion.
const motionSpring = spring(1, { damping: 35, stiffness: 400 });

//  Messages.
const messages = defineMessages({
  disclaimer: {
    defaultMessage: 'This toot will only be sent to all the mentioned users.',
    id: 'compose_form.direct_message_warning',
  },
  learn_more: {
    defaultMessage: 'Learn more',
    id: 'compose_form.direct_message_warning_learn_more'
  }
});

//  The component.
export default function ComposerDirectWarning () {
  return (
    <Motion
      defaultStyle={{
        opacity: 0,
        scaleX: 0.85,
        scaleY: 0.75,
      }}
      style={{
        opacity: motionSpring,
        scaleX: motionSpring,
        scaleY: motionSpring,
      }}
    >
      {({ opacity, scaleX, scaleY }) => (
        <div
          className='composer--warning'
          style={{
            opacity: opacity,
            transform: `scale(${scaleX}, ${scaleY})`,
          }}
        >

            <FormattedMessage {...messages.disclaimer} /> <FormattedMessage {...messages.learn_more} />

      )}
    </Motion>
  );
}

ComposerDirectWarning.propTypes = {};

Change direct message warning to match upstream


var fs = require('fs')
var path = require('path');
var log = require('../../../log').logger('opensbp');

// Load all the files in the 'routes' directory and process them as route-producing modules
exports.load = function() {
	var commandDir = __dirname;
	var files = fs.readdirSync(commandDir);
	var retval = {}
    files.forEach(function (file) {
        filePath = path.resolve('./', commandDir, file)
        if((path.extname(filePath) == '.js') && (path.basename(filePath) != 'index.js')) {
            try {
               commands = require(filePath);
	       for(var attr in commands) { retval[attr] = commands[attr]; }
               log.debug('Loaded OpenSBP commands from "' + filePath + '"');
            } catch(e) {
               log.warn('Could not load OpenSBP Commands from "' + filePath + '": ' + e);
            }
	}
    });
    return retval;
}

var fs = require('fs')
var path = require('path');
var log = require('../../../log').logger('opensbp');

// Load all the files in the 'routes' directory and process them as route-producing modules
exports.load = function() {
	var commandDir = __dirname;
	var files = fs.readdirSync(commandDir);
	var retval = {}
    files.forEach(function (file) {
        filePath = path.resolve('./', commandDir, file)
        if((path.extname(filePath) == '.js') && (path.basename(filePath) != 'index.js')) {
            try {
               commands = require(filePath);
	       for(var attr in commands) { retval[attr] = commands[attr]; }
               log.debug('Loaded OpenSBP commands from "' + filePath + '"');
            } catch(e) {
               log.warn('Could not load OpenSBP Commands from "' + filePath + '": ' + e);
		log.error(e);
}
	}
    });
    return retval;
}

Improve error report on failed sbp command load


'use strict';

/**
 * Module dependencies
 */

// Node.js core.
const path = require('path');

// Local dependencies.
const packageJSON = require('../json/package.json.js');

/**
 * Copy required files for the generated application
 */

module.exports = {
  moduleDir: path.resolve(__dirname, '..'),
  templatesDirectory: path.resolve(__dirname, '..', 'templates'),
  before: require('./before'),
  after: require('./after'),
  targets: {

    // Main package.
    'package.json': {
      jsonfile: packageJSON
    },

    // Copy dot files.
    '.editorconfig': {
      copy: 'editorconfig'
    },
    '.gitignore': {
      copy: 'gitignore'
    },
    '.npmignore': {
      copy: 'npmignore'
    },

    // Copy Markdown files with some information.
    'README.md': {
      template: 'README.md'
    },

    // Empty data directory.
    'data': {
      folder: {}
    },

    // Empty API directory.
    'api': {
      folder: {}
    }
  }
};

'use strict';

/**
 * Module dependencies
 */

// Node.js core.
const path = require('path');

// Local dependencies.
const packageJSON = require('../json/package.json.js');

/**
 * Copy required files for the generated application
 */

module.exports = {
  moduleDir: path.resolve(__dirname, '..'),
  templatesDirectory: path.resolve(__dirname, '..', 'templates'),
  before: require('./before'),
  after: require('./after'),
  targets: {

    // Main package.
    'package.json': {
      jsonfile: packageJSON
    },

    // Copy dot files.
    '.editorconfig': {
      copy: 'editorconfig'
    },
    '.gitignore': {
      copy: 'gitignore'
    },
    '.npmignore': {
      copy: 'npmignore'
    },

    // Copy Markdown files with some information.
    'README.md': {
      template: 'README.md'
    },

    // Empty data directory.
    'data': {
      folder: {}
    },

    // Empty API directory.
    'api': {
      folder: {}
    },

    // Empty plugins directory.
    'plugins': {
      folder: {}
    }
  }
};

Create plugins directory on new app


// Check if enough memory is available on the system
// args[0] : expected memory size in Kb

// WARNING : works only with Sun JVMs > 1.5

var selected = false;

var osb = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
var mem = osb.getFreePhysicalMemorySize()/1024;
print(mem+" Kb available");
//var swap = osb.getFreeSwapSpaceSize()/1024;
//print(swap+" Kb");
selected=java.lang.Integer.parseInt(mem)>java.lang.Integer.parseInt(args[0]);
print("FreeMem check : "+selected);

// Check if enough memory is available on the system
// args[0] : expected memory size in Kb

// WARNING : works only with Sun JVMs > 1.5

var selected = false;

var osb = java.lang.management.ManagementFactory.getOperatingSystemMXBean();
var mem = java.lang.Math.round(osb.getFreePhysicalMemorySize()/1024);
print(mem+" Kb available");
//var swap = osb.getFreeSwapSpaceSize()/1024;
//print(swap+" Kb");
selected=java.lang.Integer.parseInt(mem)>java.lang.Integer.parseInt(args[0]);
print("FreeMem check : "+selected);

Fix memory selection script in case of weird RAM amount


'use strict';
$(document).ready(()=> {
  new Vue({
    el: "#fluent-log",
    paramAttributes: ["logUrl", "initialAutoReload"],
    data: {
      "autoFetch": false,
      "logs": [],
      "limit": 30,
      "processing": false
    },

    compiled: function(){
      this.fetchLogs();

      var self = this;
      var timer;
      this.$watch("autoFetch", function(newValue){
        if(newValue === true) {
          timer = setInterval(function(){
            self.fetchLogs();
            var $log = $(".log", self.$el);
            $log.scrollTop($log.innerHeight());
          }, 1000);
        } else {
          clearInterval(timer);
        }
      });
      if(this.initialAutoReload) {
        this.autoFetch = true;
      }
    },

    computed: {
      isPresentedLogs: function(){
        return this.logs.length > 0;
      }
    },

    methods: {
      fetchLogs: function() {
        if(this.processing) return;
        this.processing = true;
        var self = this;
        new Promise(function(resolve, reject) {
          $.getJSON(self.logUrl + "?limit=" + self.limit, resolve).fail(reject);
        }).then(function(logs){
          self.logs = logs;
          setTimeout(function(){
            self.processing = false;
          }, 256); // delay to reduce flicking loading icon
        })["catch"](function(error){
          self.processing = false;
        });
      }
    }
  });
});

'use strict';
$(document).ready(()=> {
  new Vue({
    el: "#fluent-log",
    paramAttributes: ["logUrl", "initialAutoReload"],
    data: {
      "autoFetch": false,
      "logs": [],
      "limit": 30,
      "processing": false
    },

    mounted: function(){
      this.fetchLogs();

      var self = this;
      var timer;
      this.$watch("autoFetch", function(newValue){
        if(newValue === true) {
          timer = setInterval(function(){
            self.fetchLogs();
            var $log = $(".log", self.$el);
            $log.scrollTop($log.innerHeight());
          }, 1000);
        } else {
          clearInterval(timer);
        }
      });
      if(this.initialAutoReload) {
        this.autoFetch = true;
      }
    },

    computed: {
      isPresentedLogs: function(){
        return this.logs.length > 0;
      }
    },

    methods: {
      fetchLogs: function() {
        if(this.processing) return;
        this.processing = true;
        var self = this;
        new Promise(function(resolve, reject) {
          $.getJSON(self.logUrl + "?limit=" + self.limit, resolve).fail(reject);
        }).then(function(logs){
          self.logs = logs;
          setTimeout(function(){
            self.processing = false;
          }, 256); // delay to reduce flicking loading icon
        })["catch"](function(error){
          self.processing = false;
        });
      }
    }
  });
});

Use mounted instead of compiled


import React from 'react';

import '../../scss/_hero.scss';

class Home extends React.Component {
	render() {
		return (

					The Amazing GRace

					7th December, 2017

					Registration opens

					Monday 18th September, 2017

		);
	}
}

export default Home;

Fix registration text in the wrong position


$().ready(function(){
  function init(){
    renderMap();

    requestYears(function(years, formattedYears){
      renderSlider(years, formattedYears, {
        onChange: function(currentYear){
          requestInfluences(currentYear, function(influences){
            renderInfluencesInMap(influences);
          });
        },
        onInit: function(){
          requestInfluences(years[0], function(influences){
            renderInfluencesInMap(influences);
          });
        }
      });
    });

    listenSearch({
      onSearch: function(term){
        requestYearByInfluenceName(term, function(year){
          changeSliderTo(year);

          requestInfluences(year, function(influences){
            renderInfluencesInMap(influences);
          });
        })
      }
    });

    listenRequestYear({
      onSearch: function(year){
        changeSliderTo(year);

        requestInfluences(year, function(influences){
          renderInfluencesInMap(influences);
        });
      }
    });
  }
  init();
});

$().ready(function(){
  function init(){
    var initialYear = new Date().getFullYear() - 100;
    renderMap();

    requestYears(function(years, formattedYears){
      renderSlider(years, formattedYears, {
        onChange: function(currentYear){
          requestInfluences(currentYear, function(influences){
            renderInfluencesInMap(influences);
          });
        },
        onInit: function(){
          requestInfluences(initialYear, function(influences){
            renderInfluencesInMap(influences);
          });
        }
      });
    });

    listenSearch({
      onSearch: function(term){
        requestYearByInfluenceName(term, function(year){
          changeSliderTo(year);

          requestInfluences(year, function(influences){
            renderInfluencesInMap(influences);
          });
        })
      }
    });

    listenRequestYear({
      onSearch: function(year){
        changeSliderTo(year);

        requestInfluences(year, function(influences){
          renderInfluencesInMap(influences);
        });
      }
    });
  }
  init();
});

Change initial year in map for 100 years ago from now


'use strict';

var App =      require('../../../src/chrome/background'),
    Sessions = require('../../../src/chrome/session-handler');

describe('Background initialization', function() {

  beforeAll(function() {
    App.initialize();
  });

  it('should have no existing tab status', function() {
    expect(Sessions.tabStatus).toEqual([]);
  });

  it('should have no existing active sessions', function() {
    expect(Sessions.activeSessions).toEqual([]);
  });

});

'use strict';

var App =      require('../../../src/chrome/background'),
    Sessions = require('../../../src/chrome/session-handler');

describe('Background initialization', function() {

  beforeAll(function() {
    App.initialize();
  });

  it('should have no existing tab status', function() {
    expect(Sessions.tabStatus).toEqual([]);
  });

  it('should have no existing active sessions', function() {
    expect(Sessions.activeSessions).toEqual([]);
  });

  it('should be able to clear a session', function() {
    Sessions.activeSessions = [{ id: 123 }, { id: 543} , { id: 998} ];

    Sessions.clearSession(543);
    expect(Sessions.activeSessions).toEqual([{ id: 123}, { id: 998} ]);

    Sessions.clearSession(123);
    expect(Sessions.activeSessions).toEqual([{ id: 998 }]);

    Sessions.clearSession(998);
    expect(Sessions.activeSessions).toEqual([]);
  });

  it('should be able to clear all sessions', function() {
    Sessions.activeSessions = [{ id: 123 }, { id: 543} , { id: 998} ];

    Sessions.clearAllSessions();
    expect(Sessions.activeSessions = []);
  });

  it('should be able to create a session', function() {
    var newSession;
    var commitData = {
      tabId: 567
    };

    Sessions.createNewSession(commitData);
    newSession = Sessions.activeSessions[0];

    expect(typeof newSession.id).toBe('number');
    expect(newSession.tabs).toContain(567);
    expect(newSession.nodeIndex).toEqual(1);
  });

});

Add some tests for session-handler


/* eslint new-cap: [2, {capIsNewExceptions: ["Given", "When", "Then"]}]*/

/**
 * Holds steps related to the events feature.
 * @module website/events
 */

import {Given, When, Then} from 'cypress-cucumber-preprocessor/steps';

/**
 * A step to navigate to the events page.
 * @example
 * Given I navigate to the events page
 */
const navigateToEventsPage = () => {
  cy.visit({url: 'website/event/2016', method: 'GET'});
};
Given(`I navigate to the events page`, navigateToEventsPage);

/**
 * A step to view a given event.
 * @param {string} event - the name of event to view
 * @example
 * When viewing the event "Mystery Bus"
 */
const viewGivenEvent = (event) => {
  cy.get('a').contains(event).click();
};
When(`viewing the event {string}`, viewGivenEvent);

/**
 * A step to assert the event contains the given details.
 * @param {string} expectedDetails - the expected details of the event
 * @example
 * Then I see details relating to "school buses"
 */
const assertEventDetails = (expectedDetails) => {
  cy.get('p').contains(expectedDetails).should('be.visible');
};
Then(`I see details relating to {string}`, assertEventDetails);

/* eslint new-cap: [2, {capIsNewExceptions: ["Given", "When", "Then"]}]*/

/**
 * Holds steps related to the events feature.
 * @module website/events
 */

import {Given, When, Then} from 'cypress-cucumber-preprocessor/steps';

/**
 * The URL for the events page.
 * @private
 */
const EVENTS_PAGE = 'website/event/';

/**
 * A step to navigate to the events page.
 * @example
 * Given I navigate to the events page
 */
const navigateToEventsPage = () => {
  // using 2016 since guaranteed about its events
  cy.visit({url: EVENTS_PAGE + 2016, method: 'GET'});
};
Given(`I navigate to the events page`, navigateToEventsPage);

/**
 * A step to view a given event.
 * @param {string} event - the name of event to view
 * @example
 * When viewing the event "Mystery Bus"
 */
const viewGivenEvent = (event) => {
  cy.get('a').contains(event).click();
};
When(`viewing the event {string}`, viewGivenEvent);

/**
 * A step to assert the event contains the given details.
 * @param {string} expectedDetails - the expected details of the event
 * @example
 * Then I see details relating to "school buses"
 */
const assertEventDetails = (expectedDetails) => {
  cy.get('p').contains(expectedDetails).should('be.visible');
};
Then(`I see details relating to {string}`, assertEventDetails);

Use a constant for URL