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

module.exports = function (req, res) {
	if (!keystone.security.csrf.validate(req)) {
		return res.apiError(403, 'invalid csrf');
	}
	var item = new req.list.model();
	item.getUpdateHandler(req).process(req.body, { flashErrors: false, logErrors: true }, function (err) {
		if (err) {
			if (err.name === 'ValidationErrors') {
				return res.apiError(400, 'validation errors', err.errors);
			} else {
				return res.apiError(500, 'error', err);
			}
		}
		res.json(req.list.getData(item));
	});
};

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

module.exports = function (req, res) {
	if (!keystone.security.csrf.validate(req)) {
		return res.apiError(403, 'invalid csrf');
	}
	var item = new req.list.model();
	item.getUpdateHandler(req).process(req.body, { flashErrors: false, logErrors: true, ignoreNoedit: true }, function (err) {
		if (err) {
			if (err.name === 'ValidationErrors') {
				return res.apiError(400, 'validation errors', err.errors);
			} else {
				return res.apiError(500, 'error', err);
			}
		}
		res.json(req.list.getData(item));
	});
};

Fix validation on noedit initial fields


//= require libs/jquery/jquery-ui-1.8.16.custom.min
//= require libs/jquery/plugins/jquery.base64
//= require libs/jquery/plugins/jquery.mustache.js
//= require libs/jquery/plugins/jquery.player.min
//= require libs/suchi/isOld.js
//= require cookie-functions
//= require govuk_toolkit
//= require core
//= require devolution
//= require popup
//= require geo-locator
//= require welcome
//= require browse
//= require jquery.history
//= require jquery.tabs
//= require mobile
//= require stop-related-scrolling
//= require browser-check
//= require analytics
//= require variant-testing

Replace reference to variant test for preview by nhs chaps


'use strict';

var DataCollection = require('data-collection');

/**
 * Given a array of relationship data and the HTTP query, filters it
 * @param  {Array} data      Array of data coming from a relationship
 * @param  {Object} httpQuery
 * @return {Array}
 */
module.exports = function filterRelationship(data, httpQuery) {
	if(httpQuery.limit || httpQuery.offset || httpQuery.orderby || httpQuery.order) {
		var collection = new DataCollection(data),
			query = collection.query();

		if(httpQuery.orderby) {
			httpQuery.order = httpQuery.order || 'asc';
			query = query.order(httpQuery.orderby, httpQuery.order === 'desc');
		}

		if(httpQuery.limit || httpQuery.offset) {
			httpQuery.offset = httpQuery.offset || 0;
			query = query.limit(httpQuery.offset, httpQuery.limit);
		}

		return query.values();
	}

	return data;
};

'use strict';

var DataCollection = require('data-collection'),
	_ = require('lodash');

/**
 * Given a array of relationship data and the HTTP query, filters it
 * @param  {Array} data      Array of data coming from a relationship
 * @param  {Object} httpQuery
 * @return {Array}
 */
module.exports = function filterRelationship(data, httpQuery) {
	if(!_.isArray(data)) {
		return data;
	}

	if(httpQuery.limit || httpQuery.offset || httpQuery.orderby || httpQuery.order) {
		var collection = new DataCollection(data),
			query = collection.query();

		if(httpQuery.orderby) {
			httpQuery.order = httpQuery.order || 'asc';
			query = query.order(httpQuery.orderby, httpQuery.order === 'desc');
		}

		if(httpQuery.limit || httpQuery.offset) {
			httpQuery.offset = httpQuery.offset || 0;
			query = query.limit(httpQuery.offset, httpQuery.limit);
		}

		return query.values();
	}

	return data;
};

Fix bug in relationships via REST API.


'use strict';

module.exports = {
  name: 'torii',
  init: function() {
    this.treePaths.app = '../lib/torii';
    this.treePaths.addon = '../lib/torii';
  },

  treeForApp: function treeForApp(tree) {
    var Funnel = require('broccoli-funnel');

    return new Funnel(tree, {
      srcDir: 'initializers',
      destDir: 'initializers'
    });
  },

  treeForAddon: function treeForAddon() {
    var tree = this._super.treeForAddon.apply(this, arguments);

    this.replace = this.replace || require('broccoli-string-replace');

    // Use a build-time check to output a warning if Torii is not
    // conigured.
    var config = this.project.config(process.env.EMBER_ENV);
    if (!config.torii) {
      console.warn("Torii is installed but not configured in config/environment.js!");
    } else {
      // Use run-time lookup of the ENV via require. This is better than
      // build-time configuration since this code will not be run again if
      // config/environment changes.
      tree = this.replace(tree, {
        files: ['modules/torii/configuration.js'],
        patterns: [{
          match: /get\(window, 'ENV\.torii'\)/,
          replacement: 'require("'+this.project.name()+'/config/environment")["default"].torii'
        }]
      });
    }

    return tree;
  }
};

'use strict';

module.exports = {
  name: 'torii',
  init: function() {
    this.treePaths.app = '../lib/torii';
    this.treePaths.addon = '../lib/torii';
  },

  treeForApp: function treeForApp(tree) {
    var Funnel = require('broccoli-funnel');

    return new Funnel(tree, {
      srcDir: 'initializers',
      destDir: 'initializers'
    });
  },

  treeForAddon: function treeForAddon() {
    var tree = this._super.treeForAddon.apply(this, arguments);

    this.replace = this.replace || require('broccoli-string-replace');

    // Use a build-time check to output a warning if Torii is not
    // conigured.
    var config = this.project.config(process.env.EMBER_ENV);
    if (!config.torii) {
      console.warn("Torii is installed but not configured in config/environment.js!");
    } else {
      var projectPrefix = this.project.name();
      if (this.project.isEmberCLIAddon()) {
        projectPrefix = config.modulePrefix;
      }
      // Use run-time lookup of the ENV via require. This is better than
      // build-time configuration since this code will not be run again if
      // config/environment changes.
      tree = this.replace(tree, {
        files: ['modules/torii/configuration.js'],
        patterns: [{
          match: /get\(window, 'ENV\.torii'\)/,
          replacement: 'require("'+projectPrefix+'/config/environment")["default"].torii'
        }]
      });
    }

    return tree;
  }
};

Fix behavior when nested in another addon


'use strict';

const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: {
        bundle: './assets/js/app.js',
        styles: './assets/css/app.scss'
    },
    output: {
        path: './public/assets',
        filename: '[name].js'
    },

    module: {
        loaders: [
            {
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract('style-loader', 'css-loader!postcss-loader!resolve-url!sass-loader?sourceMap')
            }
        ]
    },

    postcss: function () {
        return [autoprefixer];
    },

    plugins: [
        new ExtractTextPlugin('[name].css', {
            allChunks: true
        })
    ]
};

'use strict';

const NODE_ENV = process.env.NODE_ENV || 'development';

const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');

module.exports = {
    context: path.resolve(__dirname, './assets'),
    entry: {
        bundle: './js/app.js',
        styles: './css/app.scss'
    },
    output: {
        path: path.resolve(__dirname, './public/assets'),
        filename: '[name].js'
    },

    devtool: NODE_ENV == 'development' ? 'cheap-eval-source-map' : null,

    module: {
        loaders: [
            // Compile SASS
            {
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract('style-loader', 'css-loader!postcss-loader!resolve-url!sass-loader?sourceMap')
            }
        ]
    },

    plugins: [
        // Extract css to separate file
        new ExtractTextPlugin('[name].css', {
            allChunks: true
        })
    ],

    postcss: function () {
        return [autoprefixer];
    },

    watch: NODE_ENV == 'development'
};

// Minify JS in production mode
if (NODE_ENV == 'production') {
    module.exports.plugins.push(
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            output: {
                comments: false,
            },
            sourceMap: false
        })
    );
}

Watch assets and recompile them on change, minify JS for production mode


/* eslint-disable */
//noinspection Eslint
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
//noinspection Eslint
const ExtractTextPlugin = require("extract-text-webpack-plugin");

//noinspection Eslint
module.exports = {
    // eslint-disable-line
    entry:   __dirname + '/src/main/resources/static/js/main.js',
    devtool: 'eval-source-map',
    output:  {
        filename: 'main.js', // eslint-disable-line
        path:     __dirname + '/target/classes/static/dist/' // copy to target
    },
    module:  {
        rules: [
            {
                test:    /\.js$/,
                exclude: /node_modules/,
                use:     {
                    loader: 'babel-loader'
                }
            }, {
                test:    /\.css$/,
                exclude: /node_modules/,
                use:     ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use:      'css-loader'
                })
            }, {
                test:    /\.js$/,
                enforce: 'pre',
                exclude: /node_modules/,
                use:     {
                    loader: 'eslint-loader'
                }
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin('bundle.css', {allChunks: true}), //
        new BrowserSyncPlugin({
            proxy: 'http://localhost:8080/'
        })
    ]
};

/* eslint-disable */
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
    entry:   __dirname + '/src/main/resources/static/js/main.js',
    devtool: 'eval-source-map',
    output:  {
        filename: 'main.js',
        path:     __dirname + '/target/classes/static/dist/' // copy to target
    },
    module:  {
        rules: [
            {
                test:    /\.js$/,
                exclude: /node_modules/,
                use:     {
                    loader: 'babel-loader'
                }
            }, {
                test:    /\.css$/,
                exclude: /node_modules/,
                use:     ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use:      'css-loader'
                })
            }, {
                test:    /\.js$/,
                enforce: 'pre',
                exclude: /node_modules/,
                use:     {
                    loader: 'eslint-loader'
                }
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin('bundle.css', {allChunks: true}), //
        new BrowserSyncPlugin({
            proxy: 'http://localhost:8080/'
        })
    ]
};

Update dependencies, migrate webpack dev conf + babel + adapt to new react v16


/**
 * Created by SuhairZain on 12/5/16.
 */

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

var PROD = JSON.parse(process.env.PROD_ENV || '0');

var plugins = [
    new HtmlWebpackPlugin({
        title: "URL to GDrive",
        filename: '../index.html',
        template: 'index-file-template.ejs'
    })
];

if(PROD){
    plugins.push(
        new webpack.optimize.UglifyJsPlugin({
            compress: { warnings: false }
        })
    );
    plugins.push(
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production')
            }
        })
    );
}

module.exports = {
    entry: './src/main.jsx',
    output: {
        path: "./dist",
        publicPath: '/dist/',
        filename: `bundle_${Date.now()}.js`
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                loaders: ['style', 'css']
            }
        ]
    },
    plugins: plugins
};

/**
 * Created by SuhairZain on 12/5/16.
 */

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

var PROD = JSON.parse(process.env.PROD_ENV || '0');

var plugins = [
    new HtmlWebpackPlugin({
        title: "URL to GDrive",
        filename: '../index.html',
        template: 'index-file-template.ejs'
    })
];

if(PROD){
    plugins.push(
        new webpack.optimize.UglifyJsPlugin({
            compress: { warnings: false }
        })
    );
    plugins.push(
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production')
            }
        })
    );
}

module.exports = {
    entry: './src/main.jsx',
    output: {
        path: "./dist",
        publicPath: './dist/',
        filename: `bundle_${Date.now()}.js`
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                loaders: ['style', 'css']
            }
        ]
    },
    plugins: plugins
};

Fix for server root relative url


'use strict';

const webpack = require('webpack');
const path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {

    entry: [
        'webpack-dev-server/client?https://0.0.0.0:8080',
        './src/index.js'
    ],

    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'project.bundle.js'
    },

    devtool: "source-map",
    devServer: {
        contentBase: './build',
        hot: true,
        host: process.env.IP,
        port: process.env.PORT,
        // "public": "bestburger2-feine.c9users.io",
         "public": "bestburger-phaser2-feyrkh.c9users.io",
        historyApiFallback: true
    },

    plugins: [
        // new CopyWebpackPlugin([
        //   {from: 'assets', to: 'build/assets/'}
        // ])
    ]

};

'use strict';

const webpack = require('webpack');
const path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {

    entry: [
        'webpack-dev-server/client?https://0.0.0.0:8080',
        './src/index.js'
    ],

    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'project.bundle.js'
    },

    devtool: "source-map",
    devServer: {
        contentBase: './build',
        hot: true,
        host: process.env.IP,
        port: process.env.PORT,
         "public": "bestburger2-feine.c9users.io",
        // "public": "bestburger-phaser2-feyrkh.c9users.io",
        historyApiFallback: true
    },

    plugins: [
        // new CopyWebpackPlugin([
        //   {from: 'assets', to: 'build/assets/'}
        // ])
    ]

};

Switch default URL back to Jesse


define([
  'Backbone',

  //Views
  'app/views/projectsView',

  //Templates
  'text!templates/home/boxesTemplate.html'
], function(

  Backbone,

  projectsView,

  //Template
  boxesTemplate
){

  var HomeView = Backbone.View.extend({

    template: _.template(boxesTemplate),

    initialize: function(){
      this.render();

      this.projects = new projectsView({
        el: '.js-projects',
        account: this.options.account
      });

    },

    render: function(){
      this.$el.html(this.template());
    }
  });

  return HomeView;

});

define([
  'Backbone',

  //Views
  'app/views/projectsView',

  //Templates
  'text!templates/home/boxesTemplate.html'
], function(

  Backbone,

  projectsView,

  //Template
  boxesTemplate
){

  var HomeView = Backbone.View.extend({

    template: _.template(boxesTemplate),

    initialize: function(){
      this.render();

      this.projects = new projectsView({
        el: '.js-projects',
        account: this.options.account,
        router: this.options.router
      });

    },

    render: function(){
      this.$el.html(this.template());
    }
  });

  return HomeView;

});

Send router to home view


// Meta data is stored on the html element
var html = document.getElementsByTagName('html')[0];

// A helper to grab our meta data
function getData(name) {
  name = `data-${name}`;
  return html.hasAttribute(name) ? html.getAttribute(name) : undefined;
}

// Access, then export, our data
export const ENV = getData('env');
export const VERSION = getData('version');
export const SHA = getData('sha');

export default {ENV, VERSION, SHA};

// Meta data is stored on the html element
var html = document.getElementsByTagName('html')[0];

// A helper to grab our meta data
function getData(name) {
  name = `data-${name}`;
  return html.hasAttribute(name) ? html.getAttribute(name) : undefined;
}

export default {ENV, VERSION, SHA};

Remove named exports for CJS interop.


var rtddata = require('./rtd-data');

function init(data) {
    var rtd = rtddata.get();

    /// Out of date message

    if (data.is_highest) {
        return;
    }

    var currentURL = window.location.pathname.replace(rtd['version'], data.slug);
    var warning = $(
        '
 ' +
        '
Note
 ' +
        '
 ' +
        'You are not using the most up to date version of the library. ' +
        ' is the newest version.' +
        '
' +
        '
');

    warning
      .find('a')
      .attr('href', currentURL)
      .text(data.slug);

    var body = $("div.body");
    if (!body.length) {
        body = $("div.document");
    }
    body.prepend(warning);
}

module.exports = {
    init: init
};

var rtddata = require('./rtd-data');

function init(data) {
    var rtd = rtddata.get();

    /// Out of date message

    if (data.is_highest) {
        return;
    }

    var currentURL = window.location.pathname.replace(rtd['version'], data.slug);
    var warning = $(
        '
 ' +
        '
Note
 ' +
        '
 ' +
        'You are not reading the most recent version of this documentation. ' +
        ' is the latest version available.' +
        '
' +
        '
');

    warning
      .find('a')
      .attr('href', currentURL)
      .text(data.slug);

    var body = $("div.body");
    if (!body.length) {
        body = $("div.document");
    }
    body.prepend(warning);
}

module.exports = {
    init: init
};

Tweak version compare warning to be more general


'use strict';

/* DEPENDENCIES */
var usherBot = require('./usherbot');

// Load local dev environment variables from .env
if( process.env.NODE_ENV == "DEV" ) {
	var dotenv = require('dotenv');
	dotenv.load();
}

/* ENV VARS */
var token = process.env.BOT_API_KEY;
var localClient = process.env.PG_URL;
//var herokuClient = redis.createClient(process.env.DATABASE_URL);

// Starting component
var usher = new usherBot( token, localClient );
usher.start();

'use strict';

/* DEPENDENCIES */
var usherBot = require('./usherbot');

// Load local dev environment variables from .env
if( process.env.NODE_ENV == "DEV" ) {
	var dotenv = require('dotenv');
	dotenv.load();
}

/* ENV VARS */
var token = process.env.BOT_API_KEY;
var localClient = process.env.PG_URL + "?ssl=true";
//var herokuClient = redis.createClient(process.env.DATABASE_URL);

// Starting component
var usher = new usherBot( token, localClient );
usher.start();

Add ssl mode for connecting to postgrep db


var path = require('path');
var _ = require('lodash');
var packageJSON = require('../json/package.json.js');
var sailsrc = require('../json/sailsrc');

/**
 * sails-generate-new
 *
 * Usage:
 * `sails-generate-new`
 *
 * @type {Object}
 */
module.exports = {

	moduleDir: require('path').resolve(__dirname, '..'),

	templatesDirectory: require('path').resolve(__dirname,'../templates'),

	before: require('./before'),

	targets: {

		'.': ['backend','frontend'],
		'./.gitignore': { copy: 'gitignore' },
		'./README.md': { template: './README.md' },
		'./package.json': { jsonfile: packageJSON },
		'./.sailsrc': { jsonfile: sailsrc },
		'./app.js': { copy: 'app.js' },
		'./Gruntfile.js': 'gruntfile'
	}
};

var path = require('path');
var _ = require('lodash');
var packageJSON = require('../json/package.json.js');
var sailsrc = require('../json/sailsrc');

/**
 * sails-generate-new
 *
 * Usage:
 * `sails-generate-new`
 *
 * @type {Object}
 */
module.exports = {

	moduleDir: require('path').resolve(__dirname, '..'),

	templatesDirectory: require('path').resolve(__dirname,'../templates'),

	before: require('./before'),

	targets: {

		'.': ['backend','frontend'],
		'./Gruntfile.js': 'gruntfile',
		'./.gitignore': { copy: 'gitignore' },
		'./README.md': { template: './README.md' },
		'./package.json': { jsonfile: packageJSON },
		'./.sailsrc': { jsonfile: sailsrc },
		'./app.js': { copy: 'app.js' }
	}
};

Put generators at top of targets (experimenting w/ convention)


$(function () {
    // Replace the <textarea class="ckeditor"> with a CKEditor
    // instance, using default configuration.
    CKEDITOR.replaceClass = 'ckeditor';

    //bootstrap WYSIHTML5 - text editor
    $(".bootstrap-wysihtml5").wysihtml5();
    $('select').selectize();
    $("input[type=date]").pikaday({  format: 'YYYY-MM-DD'});
});

$(function () {
    // Replace the <textarea class="ckeditor"> with a CKEditor
    // instance, using default configuration.
    CKEDITOR.replaceClass = 'ckeditor';

    //bootstrap WYSIHTML5 - text editor
    $(".bootstrap-wysihtml5").wysihtml5();
    $('select[multiple]').selectize();
    $("input[type=date]").pikaday({  format: 'YYYY-MM-DD'});
});

Apply selectizejs only in single selects


/**
 * Load configuration objects
 */
import path from 'path'
import * as databaseConfig from './database'
import * as redisConfig from './redis'
import * as awsConfig from './aws'

// Environment
export const env = process.env.NODE_ENV || 'development'

// Server
export const keys = ['keys']

// Database, Redis, AWS
export const database = databaseConfig[env]
export const redis = redisConfig[env]
export const aws = awsConfig[env]

// Assets path
export const assetsPath = path.resolve(__dirname, '../build/assets')

// Image root url
// export const imageRoot = `//localhost:10001/${aws.bucket}`

// Queue names
export const PROCESS_IMAGE_WORKER_QUEUE = 'PROCESS_IMAGE_WORKER_QUEUE'
export const IMAGE_UPDATES_WORKER_QUEUE = 'IMAGE_UPDATES_WORKER_QUEUE'
export const VOTE_UPDATES_WORKER_QUEUE = 'VOTE_UPDATES_WORKER_QUEUE'

/**
 * Load configuration objects
 */
import path from 'path'
import * as databaseConfig from './database'
import * as redisConfig from './redis'
import * as awsConfig from './aws'

// Environment
export const env = process.env.NODE_ENV || 'development'

// Server
export const keys = ['keys']

// Database, Redis, AWS
export const database = databaseConfig[env]
export const redis = redisConfig[env]
export const aws = awsConfig[env]

// Assets path
export const ASSETS_PATH = path.resolve(__dirname, '../build/assets')

// Queue names
export const PROCESS_IMAGE_WORKER_QUEUE = 'PROCESS_IMAGE_WORKER_QUEUE'
export const IMAGE_UPDATES_WORKER_QUEUE = 'IMAGE_UPDATES_WORKER_QUEUE'
export const VOTE_UPDATES_WORKER_QUEUE = 'VOTE_UPDATES_WORKER_QUEUE'

Rename asset part and remove image root


Package.describe({
  name: 'quark:electron',
  summary: "Electron",
  version: "0.1.3",
  git: "https://github.com/rissem/meteor-electron"
});

Npm.depends({
  connect: '2.11.0',
  "electron-packager": "5.0.2",
  "is-running": "1.0.5",
  "mkdirp": "0.5.1",
  "tar":"2.2.1",
  "fstream":"1.0.8",
  "serve-static": "1.1.0"
});

Package.on_use(function (api, where) {
  api.use(["mongo-livedata", "webapp", "ejson", "underscore"], "server");
  api.use(["iron:router"], {weak: true});
  api.add_files(['server.js'], 'server')
  api.add_files([
    "app/package.json",
    "app/main.js"
  ], "server", {isAsset: true});
  api.add_files(['client.js'], "client");
  api.export("Electron", ["client", "server"]);
});

Package.describe({
  name: 'quark:electron',
  summary: "Electron",
  version: "0.1.3",
  git: "https://github.com/rissem/meteor-electron"
});

Npm.depends({
  connect: '2.11.0',
  "electron-packager": "5.0.2",
  "is-running": "1.0.5",
  "mkdirp": "0.5.1",
  "tar":"2.2.1",
  "fstream":"1.0.8",
  "serve-static": "1.1.0"
});

Package.on_use(function (api, where) {
  api.use(["mongo-livedata", "webapp", "ejson", "underscore"], "server");
  api.use(["iron:router"], {weak: true});
  api.addFiles(['server.js'], 'server');
  api.addAssets([
    "app/package.json",
    "app/main.js"
  ], "server");
  api.addFiles(['client.js'], "client");
  api.export("Electron", ["client", "server"]);
});

Use the modern files/assets APIs


Package.describe({
  summary: 'A standard library for node.js that abstracts differences among cloud providers'
});

Package.on_use(function(api) {
  api.add_files(['lib/pkgcloud.js'], 'server');
  if (typeof api.export !== 'undefined') { api.export('PkgCloud', 'server'); }
});

Npm.depends({ 'pkgcloud': '0.9.0' });

Package.describe({
  summary: 'A standard library for node.js that abstracts differences among cloud providers',
  documentation: README.md',
  git: 'https://github.com/patrickocoffeyo/meteor-pkgcloud.git'
});

Package.on_use(function(api) {
  api.add_files(['lib/pkgcloud.js'], 'server');
  if (typeof api.export !== 'undefined') { api.export('PkgCloud', 'server'); }
});

Npm.depends({ 'pkgcloud': '0.9.0' });

Add documentation link and git url


Package.describe({
	name:"lepozepo:cloudinary",
	summary: "Upload files to Cloudinary",
	version:"4.2.1",
	git:"https://github.com/Lepozepo/cloudinary"
});

Npm.depends({
	cloudinary: "1.3.1",
	"cloudinary-jquery": "2.0.9"
});

Package.on_use(function (api){
	api.versionsFrom('METEOR@1.0');

	// Core Packages
	api.use(["meteor-base@1.0.1","coffeescript","mongo","underscore"], ["client", "server"]);
	api.use(["templating"], "client");
	api.imply(["check","random","reactive-var"], ["client","server"]);

	// External Packages
	api.use(["matb33:collection-hooks@0.7.3"], ["client", "server"],{weak:true});

	// Cloudinary Client Side
	api.add_files(".npm/package/node_modules/cloudinary-jquery/cloudinary-jquery.min.js","client");

	// Core Files
	api.add_files("server/configuration.coffee", "server");
	api.add_files("server/signature.coffee", "server");

	api.add_files("client/functions.coffee", "client");

	api.export && api.export("Cloudinary",["server","client"]);
});

Package.describe({
	name:"lepozepo:cloudinary",
	summary: "Upload files to Cloudinary",
	version:"4.2.1",
	git:"https://github.com/Lepozepo/cloudinary"
});

Npm.depends({
	cloudinary: "1.3.1",
	"cloudinary-jquery": "2.0.9"
});

Package.on_use(function (api){
	api.versionsFrom('METEOR@1.0');

	// Core Packages
	api.use(["meteor-base@1.0.1","coffeescript","mongo","underscore"], ["client", "server"]);
	api.use(["templating"], "client");
	api.use(["check","random","reactive-var"], ["client","server"]);

	// External Packages
	api.use(["matb33:collection-hooks@0.7.3"], ["client", "server"],{weak:true});

	// Cloudinary Client Side
	api.add_files(".npm/package/node_modules/cloudinary-jquery/cloudinary-jquery.min.js","client");

	// Core Files
	api.add_files("server/configuration.coffee", "server");
	api.add_files("server/signature.coffee", "server");

	api.add_files("client/functions.coffee", "client");

	api.export && api.export("Cloudinary",["server","client"]);
});

Use check, random, and reactive-var


module.exports = function(grunt) {
	require("time-grunt")(grunt);
	grunt.initConfig({
		pkg: grunt.file.readJSON("package.json"),
		eslint: {
			options: {
				configFile: ".eslintrc.json"
			},
			target: ["js/*.js", "modules/default/*.js", "serveronly/*.js", "*.js"]
		},
		stylelint: {
			simple: {
				options: {
					configFile: ".stylelintrc"
				},
				src: ["css/custom.css", "css/main.css", "modules/default/calendar/calendar.css", "modules/default/clock/clock_styles.css", "modules/default/currentweather/currentweather.css", "modules/default/weatherforcast/weatherforcast.css"]
			}
		}
	});
	grunt.loadNpmTasks("grunt-eslint");
	grunt.loadNpmTasks("grunt-stylelint");
	grunt.registerTask("default", ["eslint", "stylelint"]);
};

module.exports = function(grunt) {
	require("time-grunt")(grunt);
	grunt.initConfig({
		pkg: grunt.file.readJSON("package.json"),
		eslint: {
			options: {
				configFile: ".eslintrc.json"
			},
			target: ["js/*.js", "modules/default/*.js", "serveronly/*.js", "*.js"]
		},
		stylelint: {
			simple: {
				options: {
					configFile: ".stylelintrc"
				},
				src: ["css/main.css", "modules/default/calendar/calendar.css", "modules/default/clock/clock_styles.css", "modules/default/currentweather/currentweather.css", "modules/default/weatherforcast/weatherforcast.css"]
			}
		}
	});
	grunt.loadNpmTasks("grunt-eslint");
	grunt.loadNpmTasks("grunt-stylelint");
	grunt.registerTask("default", ["eslint", "stylelint"]);
};

Clean Up the Contributing Documentation and Process: Part VII.XXXIII


module.exports = function(grunt) {

  require('load-grunt-tasks')(grunt);

  grunt.initConfig({

    sass: {
      dist: {
        files: {
          'css/main.css': 'sass/main.sass'
        }
      }
    },

    cssmin: {
      target: {
        files: [{
          expand: true,
          src: ['css/*.css'],
          dest: 'dist',
        }]
      }
    },

    uglify: {
      build: {
        src: ['js/*.js'],
        dest: 'dist/js/main.js'
      }
    },

    watch: {
      sass: {
        files: ['sass/**/*.sass', 'sass/**/*.scss'],
        tasks: ['sass']
      }
    }

  });

  grunt.registerTask('build', ['sass']);

  grunt.registerTask('default', ['sass', 'cssmin', 'uglify', 'watch']);

};

module.exports = function(grunt) {

  require('load-grunt-tasks')(grunt);

  grunt.initConfig({

    sass: {
      dist: {
        files: {
          'css/main.css': 'sass/main.sass'
        }
      }
    },

    cssmin: {
      target: {
        files: [{
          expand: true,
          src: ['css/*.css'],
          dest: 'dist',
        }]
      }
    },

    uglify: {
      build: {
        src: ['js/*.js'],
        dest: 'dist/js/main.js'
      }
    },

    watch: {
      sass: {
        files: ['sass/**/*.sass', 'sass/**/*.scss'],
        tasks: ['sass']
      }
    }

  });

  grunt.registerTask('build', ['sass']);

  grunt.registerTask('iter', ['sass', 'watch']);

  grunt.registerTask('default', ['sass', 'cssmin', 'uglify', 'watch']);

};

Add iter task to Grunt


module.exports = function(grunt) {
    var pkg = grunt.file.readJSON('package.json');

    (function () {
        var taskName;
        for(taskName in pkg.devDependencies) {
            if(taskName.substring(0, 6) === 'grunt-') {
                grunt.loadNpmTasks(taskName);
            }
        }
    })();

    grunt.initConfig({
        pkg: pkg,
        jshint: {
            files: [
                'lib/**/*.js'
            ],
            options: {
                jshintrc: '.jshintrc'
            }
        },
        mochaTest: {
            unit: {
                options: {
                    reporter: 'spec'
                },
                src: ['test/**/*.js']
            }
        }
    });

    grunt.registerTask('test', ['mochaTest:unit']);
};

module.exports = function(grunt) {
    var pkg = grunt.file.readJSON('package.json');

    (function () {
        var taskName;
        for(taskName in pkg.devDependencies) {
            if(taskName.substring(0, 6) === 'grunt-') {
                grunt.loadNpmTasks(taskName);
            }
        }
    })();

    grunt.initConfig({
        pkg: pkg,
        jshint: {
            files: [
                'lib/**/*.js'
            ],
            options: {
                jshintrc: '.jshintrc'
            }
        },
        mochaTest: {
            unit: {
                options: {
                    reporter: 'spec'
                },
                src: ['test/**/*.js']
            }
        }
    });

    grunt.registerTask('test', ['jshint', 'mochaTest:unit']);
};

Integrate jshint in CI process.


module.exports = function(grunt) {
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-sass');
	grunt.initConfig({
		watch: {
			sass: {
				files: ['xmd/style/**/*.scss', 'actions/**/css/*.scss', 'inc/widgets/**/css/*.scss', 'modules/**/css/*.scss'],
				tasks: ['sass']
			}
		},
		sass: {
			dist: {
				files: [{
					expand: true,
					src: ['xmd/style/**/*.scss', 'actions/**/css/*.scss', 'inc/widgets/**/css/*.scss', 'modules/**/css/*.scss'],
					ext: '.css'
				}]
			}
		}
  //     	autoprefixer: {
		// 	options: {
		// 		browsers: ['last 1 version']
		// 	},
		// 	dist: {
		// 		files: [{
		// 			expand: true,
		// 			cwd: '.tmp/styles/',
		// 			src: '{,*/}*.css',
		// 			dest: '.tmp/styles/'
		// 		}]
		// 	}
		// }
	});
	grunt.registerTask('default', [
    	// 'autoprefixer',
    	'watch'
  	]);
};

module.exports = function(grunt) {
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-sass');
	grunt.initConfig({
		watch: {
			sass: {
				files: ['xmd/style/**/*.scss', 'actions/**/css/*.scss', 'inc/widgets/**/css/*.scss', 'modules/**/css/*.scss', '!**/_*.scss'],
				tasks: ['sass:dev'],
				options: {
      				spawn: false
    			}
			}
		},
		sass: {
			dist: {
				files: [{
					expand: true,
					files: ['xmd/style/**/*.scss', 'actions/**/css/*.scss', 'inc/widgets/**/css/*.scss', 'modules/**/css/*.scss'],
					ext: '.css'
				}]
			},
			dev: {
				files: {}
			}
		}
	});
	grunt.registerTask('default', [
    	'watch'
  	]);
  	grunt.event.on('watch', function(action, filepath, target) {
		var filedest = filepath.slice(0, filepath.lastIndexOf("."));
		filedest += '.css'
		var files = {};
		files[filedest] = filepath;
		grunt.config.set('sass.dev.files', files);
	});
};

Update grunt to watch for sass changes


module.exports = function(grunt) {

  grunt.initConfig({
    qunit: {
      options: {
        "--web-security": "no",
        coverage: {
          src: ["js/grande.js"],
          instrumentedFiles: "temp/",
          htmlReport: "report/coverage",
          coberturaReport: "report/",
          linesThresholdPct: 85
        }
      },
      all: ["test/**.html"]
    }
  });

  grunt.loadNpmTasks("grunt-qunit-istanbul");
  // @TODO: add lint hook here as well for eslint
  grunt.registerTask("travis", "qunit");
};

module.exports = function(grunt) {

  grunt.initConfig({
    qunit: {
      options: {
        "--web-security": "no",
        coverage: {
          src: ["js/grande.js"],
          instrumentedFiles: "temp/",
          htmlReport: "report/coverage",
          coberturaReport: "report/"
        }
      },
      all: ["test/**.html"]
    }
  });

  grunt.loadNpmTasks("grunt-qunit-istanbul");
  // @TODO: add lint hook here as well for eslint
  grunt.registerTask("travis", "qunit");
};

Remove false threshold for now


'use strict';

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        jshint: {
            allFiles: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js', 'index.js'],
            options: {
                jshintrc: '.jshintrc',
            }
        },
        mochacli: {
            all: ['test/**/*.js'],
            options: {
                reporter: 'spec',
                ui: 'tdd'
            }
        }
    })

    // Load the plugins
    grunt.loadNpmTasks('grunt-contrib-jshint')
    grunt.loadNpmTasks('grunt-mocha-cli')

    // Configure tasks
    grunt.registerTask('default', ['test'])
    grunt.registerTask('test', ['mochacli', 'jshint'])
}

'use strict';

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        jshint: {
            allFiles: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js', 'index.js'],
            options: {
                jshintrc: '.jshintrc',
            }
        },
        mochacli: {
            all: ['test/**/*.js'],
            options: {
                reporter: 'spec',
                ui: 'tdd'
            }
        },
        'mocha_istanbul': {
            coveralls: {
                src: [ 'test/lib', 'test/lib/utils' ],
                options: {
                    coverage: true,
                    legend: true,
                    check: {
                        lines: 97,
                        statements: 98
                    },
                    root: './lib',
                    reportFormats: ['lcov']
                }
            }
        }
    })

    grunt.event.on('coverage', function(lcov, done){
        require('coveralls').handleInput(lcov, function(error) {
            if (error) {
                console.log(error)
                return done(error)
            }
            done()
        })
    })

    // Load the plugins
    grunt.loadNpmTasks('grunt-contrib-jshint')
    grunt.loadNpmTasks('grunt-mocha-cli')
    grunt.loadNpmTasks('grunt-mocha-istanbul')

    // Configure tasks
    grunt.registerTask('coveralls', ['mocha_istanbul:coveralls'])
    grunt.registerTask('default', ['test'])

    grunt.registerTask('test', ['mochacli', 'jshint', 'coveralls'])
}

Update grunt file to generate coverage reports


module.exports = function(grunt) {
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.initConfig({
    concat: {
      'build/pointerevents.css': 'src/*.css',
    },
    uglify: {
      pointerevents: {
        dest: 'build/pointerevents.js',
        src: [
          'src/PointerEvent.js',
          'src/pointermap.js',
          'src/sidetable.js',
          'src/dispatcher.js',
          'src/installer.js',
          'src/findTarget.js',
          'src/platform-events.js',
          'src/capture.js',
        ]
      }
    },
  });

  grunt.registerTask('default', ['concat', 'uglify']);
};

module.exports = function(grunt) {
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.initConfig({
    concat: {
      'build/pointerevents.css': 'src/*.css',
    },
    uglify: {
      pointerevents: {
        options: {
          sourceMap: 'build/pointerevents.js.map',
          sourceMappingURL: 'pointerevents.js.map',
          sourceMapRoot: '..'
        },
        dest: 'build/pointerevents.js',
        src: [
          'src/PointerEvent.js',
          'src/pointermap.js',
          'src/sidetable.js',
          'src/dispatcher.js',
          'src/installer.js',
          'src/findTarget.js',
          'src/platform-events.js',
          'src/capture.js',
        ]
      }
    },
  });

  grunt.registerTask('default', ['concat', 'uglify']);
};

Make sourcemaps from grunt build


'use strict';

module.exports = function (grunt) {
  // Show elapsed time at the end
  require('time-grunt')(grunt);
  // Load all grunt tasks
  require('load-grunt-tasks')(grunt);

  // Project configuration.
  grunt.initConfig({
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      lib: {
        src: ['lib/**/*.js']
      },
      test: {
        src: ['test/**/*.js']
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: ['test/**/*.js']
      }
    },
    watch: {
      gruntfile: {
        files: '<%= jshint.gruntfile.src %>',
        tasks: ['jshint:gruntfile']
      },
      lib: {
        files: '<%= jshint.lib.src %>',
        tasks: ['jshint:lib', 'nodeunit']
      },
      test: {
        files: '<%= jshint.test.src %>',
        tasks: ['jshint:test', 'mochaTest']
      }
    }
  });

  // Default task.
  grunt.registerTask('default', ['jshint', 'mochaTest']);
  grunt.registerTask('test', ['jshint:test','mochaTest']);

};

'use strict';

module.exports = function (grunt) {
  // Show elapsed time at the end
  require('time-grunt')(grunt);
  // Load all grunt tasks
  require('load-grunt-tasks')(grunt);

  // Project configuration.
  grunt.initConfig({
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      lib: {
        src: ['lib/**/*.js']
      },
      test: {
        src: ['test/**/*.js']
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          timeout: 5000
        },
        src: ['test/**/*.js']
      }
    },
    watch: {
      gruntfile: {
        files: '<%= jshint.gruntfile.src %>',
        tasks: ['jshint:gruntfile']
      },
      lib: {
        files: '<%= jshint.lib.src %>',
        tasks: ['jshint:lib', 'nodeunit']
      },
      test: {
        files: '<%= jshint.test.src %>',
        tasks: ['jshint:test', 'mochaTest']
      }
    }
  });

  // Default task.
  grunt.registerTask('default', ['jshint', 'mochaTest']);
  grunt.registerTask('test', ['jshint:test','mochaTest']);

};

Set mocha tests timeout to 5s.


'use strict';

module.exports = function(grunt) {
    // Configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        jscs: {
            options: {
                config: '.jscsrc'
            },
            bin: 'bin/**/*.js',
            grunt: 'Gruntfile.js',
            lib: 'lib/**/*.js',
            test: '<%= nodeunit.all %>'
        },
        jshint: {
            options: {
                jshintrc: true
            },
            bin: 'bin/**/*.js',
            grunt: 'Gruntfile.js',
            lib: 'lib/**/*.js',
            test: '<%= nodeunit.all %>'
        },
        jsonlint: {
            jshint: ['.jshintrc'],
            npm: ['package.json']
        },
        nodeunit: {
            all: ['test/**/*.js']
        }
    });

    // Load tasks.
    grunt.loadTasks('./tasks');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-nodeunit');
    grunt.loadNpmTasks('grunt-jscs-checker');
    grunt.loadNpmTasks('grunt-jsonlint');
    grunt.loadNpmTasks('grunt-release');

    // Register tasks.
    grunt.registerTask('lint', ['jsonlint', 'jshint', 'jscs', 'npm-validate']);
    grunt.registerTask('test', ['nodeunit']);
    grunt.registerTask('travis', ['lint', 'test']);
    grunt.registerTask('default', ['lint', 'test']);
};

'use strict';

module.exports = function(grunt) {
    // Configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        jscs: {
            options: {
                config: '.jscsrc'
            },
            bin: 'bin/**/*.js',
            grunt: 'Gruntfile.js',
            lib: 'lib/**/*.js',
            test: '<%= nodeunit.all %>'
        },
        jshint: {
            options: {
                jshintrc: true
            },
            bin: 'bin/**/*.js',
            grunt: 'Gruntfile.js',
            lib: 'lib/**/*.js',
            test: '<%= nodeunit.all %>'
        },
        jsonlint: {
            jshint: ['.jshintrc'],
            npm: ['package.json']
        },
        nodeunit: {
            all: ['test/**/*.js']
        }
    });

    // Load tasks.
    grunt.loadTasks('./tasks');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-nodeunit');
    grunt.loadNpmTasks('grunt-jscs-checker');
    grunt.loadNpmTasks('grunt-jsonlint');
    grunt.loadNpmTasks('grunt-release');

    // Register tasks.
    grunt.renameTask('release', 'bump');
    grunt.registerTask('lint', ['jsonlint', 'jshint', 'jscs', 'npm-validate']);
    grunt.registerTask('test', ['nodeunit']);
    grunt.registerTask('travis', ['lint', 'test']);
    grunt.registerTask('default', ['lint', 'test']);
};

Rename `release` task to `bump`.


module.exports = function(grunt) {

	/* Load Plugins */

	grunt.loadNpmTasks('grunt-contrib-less');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-compress');
	grunt.loadNpmTasks('grunt-bump');

	grunt.initConfig({
		pkg: '<json:package.json>',
		compress: {
			main: {
				options: {
					archive: 'theme-extension.zip',
					mode: 'zip'
				},
				files: [
					{
						cwd: 'theme-extension/',
						src: '**/*',
						expand: true
					}
				]
			}
		},
		less: {
			generate: {
				files: {
					'theme-extension/stable.css': 'less/build-stable.less',
					'theme-extension/canary.css': 'less/build-canary.less',
				}
			}
		},
		watch: {
			canary: {
				files: ['less/*.less','themes/*.less'],
				tasks: ['less:generate']
			},

		}

	});

	grunt.registerTask('default', ['less']);
};

module.exports = function(grunt) {

	/* Load Plugins */

	grunt.loadNpmTasks('grunt-contrib-less');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-compress');
	grunt.loadNpmTasks('grunt-bump');

	grunt.initConfig({
		pkg: '<json:package.json>',
		compress: {
			main: {
				options: {
					archive: 'theme-extension.zip',
					mode: 'zip'
				},
				files: [
					{
						cwd: 'theme-extension/',
						src: '**/*',
						expand: true
					}
				]
			}
		},
		less: {
			generate: {
				files: {
					'theme-extension/stable.css': 'less/build-stable.less',
					'theme-extension/canary.css': 'less/build-canary.less',
				}
			},
			build: {
				options: {
					compress: true
				},
				files: {
					'theme-extension/stable.css': 'less/build-stable.less',
					'theme-extension/canary.css': 'less/build-canary.less',
				}
			}
		},
		watch: {
			canary: {
				files: ['less/*.less','themes/*.less'],
				tasks: ['less:generate']
			},

		}

	});

	grunt.registerTask('default', ['less:generate']);
	grunt.registerTask('package', ['less:build', 'compress']);
};

Add grunt task to minify css


module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    clean: {
      dist: ["dist"]
    },
    exec: {
        tsc_package: "node node_modules/typescript/bin/tsc -p ./source/",
        npm_pack: {
        cmd: "npm pack ./package",
        cwd: "dist/"
      }
    },
    copy: {
      package: {
        files: [
          { expand: true, cwd: 'source', src: ['**/*.js', 'package.json', 'README.md', 'platforms/**'], dest: 'dist/package' }
        ]
      }
    },
    mkdir: {
      dist: {
        options: {
          create: ["dist/package"]
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-exec');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-mkdir');

  // Default task(s).
  grunt.registerTask('default', [
    'clean:dist',
    'exec:tsc_package',
    'mkdir:dist',
    'copy:package',
    'exec:npm_pack'
  ]);
};

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    clean: {
      dist: ["dist"]
    },
    exec: {
        tsc_package: "node node_modules/typescript/bin/tsc -p ./source/",
        npm_pack: {
        cmd: "npm pack ./package",
        cwd: "dist/"
      }
    },
    copy: {
      package: {
        files: [
          {
              expand: true,
              cwd: 'source',
              src: [
                  '**/*.js',
                  '**/*.d.ts',
                  'package.json',
                  'README.md',
                  'platforms/**'
              ],
              dest: 'dist/package'
          }
        ]
      }
    },
    mkdir: {
      dist: {
        options: {
          create: ["dist/package"]
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-exec');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-mkdir');

  // Default task(s).
  grunt.registerTask('default', [
    'clean:dist',
    'exec:tsc_package',
    'mkdir:dist',
    'copy:package',
    'exec:npm_pack'
  ]);
};

Package the type definitions in the npm module.


module.exports = function (grunt) {
    grunt.initConfig({
        clean: ['tmp/'],
        'module-graph': {
            simple: {
                src: ['tests/assets/*.js'],
                dest: 'tmp/graph-simple.json'
            },
            full: {
                options: {
                    includeBindings: true
                },
                src: ['tests/assets/*.js'],
                dest: 'tmp/graph-full.json'
            }
        },
        mochaTest: {
            test: {
                options: {
                    reporter: 'spec'
                },
                src: ['tests/*.js']
            },
            sd: {
                options: {
                    reporter: 'xunit'
                },
                src: ['tests/*.js']
            }
        }
    });

    // load this module's tasks
    grunt.loadTasks('tasks');

    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-mocha-test');

    grunt.registerTask('test', [
        'clean',
        'module-graph',
        'mochaTest:test'
    ]);

    grunt.registerTask('testsd', [
        'clean',
        'module-graph',
        'mochaTest:sd'
    ]);
};

module.exports = function (grunt) {
    grunt.initConfig({
        clean: ['tmp/'],
        'module-graph': {
            simple: {
                src: ['tests/assets/*.js'],
                dest: 'tmp/graph-simple.json'
            },
            full: {
                options: {
                    includeBindings: true
                },
                src: ['tests/assets/*.js'],
                dest: 'tmp/graph-full.json'
            }
        },
        mochaTest: {
            test: {
                options: {
                    reporter: 'spec'
                },
                src: ['tests/*.js']
            },
            sd: {
                options: {
                    reporter: 'xunit'
                },
                src: ['tests/*.js']
            }
        }
    });

    // load this module's tasks
    grunt.loadTasks('tasks');

    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-mocha-test');

    grunt.registerTask('test', [
        'clean',
        'module-graph',
        'mochaTest'
    ]);
};

Use only one test task


import fetch from '../server/fetch';

export const REQUEST_ITEMS = 'REQUEST_ITEMS';
function requestItems () {
  return {
    type: REQUEST_ITEMS,
  };
}

export const RECEIVE_ITEMS_SUCCESS = 'RECEIVE_ITEMS_SUCCESS';
function receiveItemsSuccess (json) {
  return {
    type: RECEIVE_ITEMS_SUCCESS,
    items: json,
  };
}

export const RECEIVE_ITEMS_ERROR = 'RECEIVE_ITEMS_ERROR';
function receiveItemsError (error) {
  return {
    type: RECEIVE_ITEMS_ERROR,
    error,
  };
}

function fetchItems () {
  return dispatch => {
    dispatch(requestItems());

    return fetch('/api/items')
      .then(
        response => response.json(),
        err => dispatch(receiveItemsError(err))
      ).then(
        json => dispatch(receiveItemsSuccess(json))
      );
  };
}

function shouldFetchItems (state) {
  const {items} = state;
  return !items || (items.items.length === 0 && !items.isFetching);
}

export function fetchItemsIfNeeded () {
  return (dispatch, getState) => {
    if (shouldFetchItems(getState())) {
      return dispatch(fetchItems());
    }
  };
}

import fetch from '../server/fetch';

export const REQUEST_ITEMS = 'REQUEST_ITEMS';
function requestItems () {
  return {
    type: REQUEST_ITEMS,
  };
}

export const RECEIVE_ITEMS_SUCCESS = 'RECEIVE_ITEMS_SUCCESS';
function receiveItemsSuccess (json) {
  return {
    type: RECEIVE_ITEMS_SUCCESS,
    items: json,
  };
}

export const RECEIVE_ITEMS_ERROR = 'RECEIVE_ITEMS_ERROR';
function receiveItemsError (error) {
  return {
    type: RECEIVE_ITEMS_ERROR,
    error,
  };
}

function fetchItems () {
  return dispatch => {
    dispatch(requestItems());

    return fetch('/api/items')
      .then(response => response.json())
      .then(json => {
        if (!Array.isArray(json)) {
          dispatch(receiveItemsError(json));
        } else {
          dispatch(receiveItemsSuccess(json));
        }
      });
  };
}

function shouldFetchItems (state) {
  const {items} = state;
  return !items || (items.items.length === 0 && !items.isFetching);
}

export function fetchItemsIfNeeded () {
  return (dispatch, getState) => {
    if (shouldFetchItems(getState())) {
      return dispatch(fetchItems());
    }
  };
}

Handle server GET /api/items error


import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';
import license from 'rollup-plugin-license';
import uglify from 'rollup-plugin-uglify';
import pkg from './package.json';

const banner = {
  banner: `
        ${pkg.name} - v${pkg.version}
        ${pkg.description}
        ${pkg.homepage}

        Made by ${pkg.author}
        Under ${pkg.license} License
      `
};
const globals = {
  'prop-types': 'PropTypes',
  'react-dom': 'ReactDOM',
  'react': 'React'
};
const external = Object.keys(globals);

export default [
  {
    input: 'index.js',
    output: {
      name: 'SimpleBar',
      file: pkg.main,
      format: 'umd',
      globals: globals
    },
    external: external,
    plugins: [
      babel(),
      resolve(), // so Rollup can find dependencies
      commonjs(), // so Rollup can convert dependencies to an ES module
      uglify(),
      license(banner)
    ]
  },
  {
    input: 'index.js',
    external: external,
    output: {
      file: pkg.module,
      format: 'es'
    },
    plugins: [
      babel(),
      license(banner)
    ]
  }
];

import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';
import license from 'rollup-plugin-license';
import uglify from 'rollup-plugin-uglify';
import pkg from './package.json';

const banner = {
  banner: `
        ${pkg.name} - v${pkg.version}
        ${pkg.description}
        ${pkg.homepage}

        Made by ${pkg.author}
        Under ${pkg.license} License
      `
};
const globals = {
  'prop-types': 'PropTypes',
  'react': 'React'
};
const external = [...Object.keys(pkg.dependencies), 'react'];

export default [
  {
    input: 'index.js',
    output: {
      name: 'SimpleBar',
      file: pkg.main,
      format: 'umd',
      globals: globals
    },
    external: external,
    plugins: [
      babel(),
      resolve(), // so Rollup can find dependencies
      commonjs(), // so Rollup can convert dependencies to an ES module
      uglify(),
      license(banner)
    ]
  },
  {
    input: 'index.js',
    external: external,
    output: {
      file: pkg.module,
      format: 'es'
    },
    plugins: [
      babel(),
      license(banner)
    ]
  }
];

Fix missing dependencies in simplebar-react bundle


Kwf.Form.ShowField = Ext.extend(Ext.form.Field,
{
    defaultAutoCreate : {tag: 'div', cls: 'kwf-form-show-field'},
    /**
     * {value} wenn kein objekt übergeben, sonst index aus objekt
     */
    tpl: '{value}',

    initValue : function(){
        if(this.value !== undefined){
            this.setValue(this.value);
        }
    },
    afterRender : function(){
        Kwf.Form.ShowField.superclass.afterRender.call(this);
        if (typeof this.tpl == 'string') this.tpl = new Ext.XTemplate(this.tpl);
        this.tpl.compile();
        this.setRawValue(" "); //bugfix für IE 7 -> /kwf/test/kwf_form_show-field_value-overlaps-error
    },
    getName: function(){
        return this.name;
    },
    setRawValue : function(v){
        return this.el.update(v);
    },
    getRawValue : function(){
        return this.el.dom.innerHTML;
    },
    getValue : function()
    {
        return null;
    },
    setValue : function(value)
    {
        this.value = value;
        if(this.rendered){
            if (!value) {
                this.setRawValue(value);
            } else {
                if (typeof value != 'object') value = { value : value };
                this.tpl.overwrite(this.el, value);
            }
        }
        if (this.getRawValue() == '') {
            this.setRawValue(" ");
        }
    }
});
Ext.reg('showfield', Kwf.Form.ShowField);

Kwf.Form.ShowField = Ext.extend(Ext.form.Field,
{
    defaultAutoCreate : {tag: 'div', cls: 'kwf-form-show-field'},
    /**
     * {value} wenn kein objekt übergeben, sonst index aus objekt
     */
    tpl: '{value}',

    initValue : function(){
        if(this.value !== undefined){
            this.setValue(this.value);
        }
    },
    afterRender : function(){
        Kwf.Form.ShowField.superclass.afterRender.call(this);
        if (typeof this.tpl == 'string') this.tpl = new Ext.XTemplate(this.tpl);
        this.tpl.compile();
        this.setRawValue(" "); //bugfix für IE 7 -> /kwf/test/kwf_form_show-field_value-overlaps-error
    },
    getName: function(){
        return this.name;
    },
    setRawValue : function(v){
        return this.el.update(v);
    },
    getRawValue : function(){
        return this.el.dom.innerHTML;
    },
    getValue : function()
    {
        return this.value;
    },
    setValue : function(value)
    {
        this.value = value;
        if(this.rendered){
            if (!value) {
                this.setRawValue(value);
            } else {
                if (typeof value != 'object') value = { value : value };
                this.tpl.overwrite(this.el, value);
            }
        }
        if (this.getRawValue() == '') {
            this.setRawValue(" ");
        }
    }
});
Ext.reg('showfield', Kwf.Form.ShowField);

Return value instead of null


import Configuration from '../helpers/Configuration'
import Scene from '../components/Scene'
import Camera from '../components/Camera'
import Renderer from '../components/Renderer'
import PostProcessing from '../components/PostProcessing/PostProcessing'
import EffectComposer from '../components/PostProcessing/EffectComposer'
import Clock from '../components/Utils/Clock'
import GUI from '../components/Utils/GUI'
import TextureLoader from '../helpers/TextureLoader'

export default [
  // --- Services
  {
    type: 'service',
    name: 'Configuration',
    constructor: Configuration
  },
  {
    type: 'service',
    name: 'Scene',
    constructor: Scene
  },
  {
    type: 'service',
    name: 'Camera',
    constructor: Camera,
    dependencies: [ 'Configuration' ]
  },
  {
    type: 'service',
    name: 'Renderer',
    constructor: Renderer
  },
  {
    type: 'service',
    name: 'EffectComposer',
    constructor: EffectComposer,
    dependencies: [ 'Renderer', 'Configuration' ]
  },
  {
    type: 'service',
    name: 'PostProcessing',
    constructor: PostProcessing,
    dependencies: [ 'EffectComposer', 'Scene', 'Camera', 'Renderer', 'GUI', 'Configuration' ]
  },
  {
    type: 'service',
    name: 'Clock',
    constructor: Clock
  },
  {
    type: 'service',
    name: 'GUI',
    constructor: GUI
  },
  {
    type: 'service',
    name: 'TextureLoader',
    constructor: TextureLoader,
    dependencies: [ 'Configuration' ]
  }
]

import Configuration from '../helpers/Configuration'
import Scene from '../components/Core/Scene'
import Camera from '../components/Core/Camera'
import Renderer from '../components/Core/Renderer'
import PostProcessing from '../components/PostProcessing/PostProcessing'
import EffectComposer from '../components/PostProcessing/EffectComposer'
import Clock from '../components/Utils/Clock'
import GUI from '../components/Utils/GUI'
import TextureLoader from '../helpers/TextureLoader'

export default [
  // --- Services
  {
    type: 'service',
    name: 'Configuration',
    constructor: Configuration
  },
  {
    type: 'service',
    name: 'Scene',
    constructor: Scene
  },
  {
    type: 'service',
    name: 'Camera',
    constructor: Camera,
    dependencies: [ 'Configuration' ]
  },
  {
    type: 'service',
    name: 'Renderer',
    constructor: Renderer
  },
  {
    type: 'service',
    name: 'EffectComposer',
    constructor: EffectComposer,
    dependencies: [ 'Renderer', 'Configuration' ]
  },
  {
    type: 'service',
    name: 'PostProcessing',
    constructor: PostProcessing,
    dependencies: [ 'EffectComposer', 'Scene', 'Camera', 'Renderer', 'GUI', 'Configuration' ]
  },
  {
    type: 'service',
    name: 'Clock',
    constructor: Clock
  },
  {
    type: 'service',
    name: 'GUI',
    constructor: GUI
  },
  {
    type: 'service',
    name: 'TextureLoader',
    constructor: TextureLoader,
    dependencies: [ 'Configuration' ]
  }
]

Structure - Edit depedencies path


'use strict';

(function ($) {
  var showBanner = function (content) {
    if (content) {
      $('header').after(content)
    }
  }

  var getBannerHost = function () {
    var local = window.location.host.startsWith('ckan-gateway')
    if (local) {
      return 'http://localhost:8000'
    }

    var production = window.location.host.startsWith('catalogue')
    return production ? '//data.govt.nz' : '//diadata-uat.cwp.govt.nz'
  }

  var getBanner = function () {
    $.ajax({
      url: getBannerHost() + '/api/banner',
      success: function (banner) {
        if (banner.enabled) {
          showBanner(banner.content)
        }
      }
    })
  }

  getBanner();
})($)

'use strict';

(function ($) {
  var showBanner = function (content) {
    if (content) {
      $('header.site-header').after(content)
    }
  }

  var getBannerHost = function () {
    var local = window.location.host.startsWith('ckan-gateway')
    if (local) {
      return 'http://localhost:8000'
    }

    var production = window.location.host.startsWith('catalogue')
    return production ? '//data.govt.nz' : '//diadata-uat.cwp.govt.nz'
  }

  var getBanner = function () {
    $.ajax({
      url: getBannerHost() + '/api/banner',
      success: function (banner) {
        if (banner.enabled) {
          showBanner(banner.content)
        }
      }
    })
  }

  getBanner();
})($)

Fix issue with nested headers on page in admin area


/**
 * This class provides the modal Ext.Window support for all Authentication forms. It's
 * layout is structured to center any Authentication dialog within it's center
 */
Ext.define('Starter.view.base.LockingWindow', {
	extend: 'Ext.window.Window',
	cls: 'auth-locked-window',

	closable: false,
	resizable: false,
	autoShow: true,
	titleAlign: 'center',
	maximized: true,
	modal: true,

	layout: {
		type: 'vbox',
		align: 'center',
		pack: 'center'
	}
});

/**
 * This class provides the modal Ext.Window support for all Authentication forms. It's
 * layout is structured to center any Authentication dialog within it's center
 */
Ext.define('Starter.view.base.LockingWindow', {
	extend: 'Ext.window.Window',
	cls: 'auth-locked-window',

	closable: false,
	resizable: false,
	autoShow: true,
	titleAlign: 'center',
	maximized: true,
	modal: false,

	layout: {
		type: 'vbox',
		align: 'center',
		pack: 'center'
	}
});

Fix a strange mask problem


module.exports = function (grunt) {

    /*
        Create template pages and their associated assets
        Run from the command line as follows: grunt create --name=$var
    */

    var name = grunt.option('name') || null;

    grunt.registerTask('create', function() {

        var assetsDirectory = 'app/assets/',
            pagesDirectory = 'app/templates/pages/',
            cssDirectory = 'app/assets/styles/',
            imagesDirectory = 'app/assets/img/',
            javascriptDirectory = 'app/assets/scripts/',
            modulePattern = 'var '+name+' = (function () {\n\tfunction init () {\n\t}\n\treturn {\n\t\tinit: init\n\t}\n}());\n\n$(function () {\n\t'+name+'.init();\n});',
            templateContent = '---\ntitle: '+name+'\ncssname: ' + name + '\njsname: ' + name + '\n---';

        // Cursory check that the file doesn't exist
        if(grunt.file.exists(pagesDirectory+name+'.hbs')) {
            grunt.fail.warn('Sorry, that page already exists' ,1);
        }

        // Make img directory
        grunt.file.mkdir(imagesDirectory+name);

        // create css
        grunt.file.write(cssDirectory+name+'.scss', '#'+name+' {\n\n}');

        // create js module
        grunt.file.write(javascriptDirectory+name+'.js', modulePattern)

        // create page template
        grunt.file.write(pagesDirectory+name+'.hbs', templateContent);

    });
};

module.exports = function (grunt) {

    /*
        Create template pages and their associated assets
        Run from the command line as follows: grunt create --name=$var
    */

    var name = grunt.option('name') || null;

    grunt.registerTask('create', function () {

        var title = name,
            filename = name.toUpperCase().split(' ').join('_'),
            pagesDirectory = 'app/templates/pages/',
            cssDirectory = 'app/assets/styles/pages/',
            imagesDirectory = 'app/assets/img/',
            javascriptDirectory = 'app/assets/scripts/',
            modulePattern = 'var ' + name + ' = (function () {\n\tfunction init () {\n\t}\n\treturn {\n\t\tinit: init\n\t}\n}());\n\n$(function () {\n\t' + name + '.init();\n});',
            templateContent = '---\ntitle: ' + title + '\ncssname: ' + filename + '\njsname: ' + filename + '\n---';

        // Cursory check that the file doesn't exist
        if (grunt.file.exists(pagesDirectory + filename + '.hbs')) {
            grunt.fail.warn('Sorry, that page already exists', 1);
        }

        // Make img directory
        grunt.file.mkdir(imagesDirectory + filename);

        // create css
        grunt.file.write(cssDirectory + filename + '.scss', '#' + filename + ' {\n\n}');

        // create js module
        grunt.file.write(javascriptDirectory + filename + '.js', modulePattern);

        // create page template
        grunt.file.write(pagesDirectory + filename + '.hbs', templateContent);

    });
};

Add sanitation of provided name, formatting.


/*
 * grunt-deploy
 * https://github.com/kevinschaul/strib-deploy
 *
 * Copyright (c) 2013 Kevin Schaul
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks

  grunt.registerMultiTask('deploy', 'Deploy to apps.startribune.com', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      punctuation: '.',
      separator: ', '
    });

    // Iterate over all specified file groups.
    this.files.forEach(function(f) {
      // Concat specified files.
      var src = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).map(function(filepath) {
        // Read file source.
        return grunt.file.read(filepath);
      }).join(grunt.util.normalizelf(options.separator));

      // Handle options.
      src += options.punctuation;

      // Write the destination file.
      grunt.file.write(f.dest, src);

      // Print a success message.
      grunt.log.writeln('File "' + f.dest + '" created.');
    });
  });

};

/*
 * grunt-deploy
 * https://github.com/kevinschaul/strib-deploy
 *
 * Copyright (c) 2013 Kevin Schaul
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks

  grunt.registerTask('deploy', 'Deploy to apps.startribune.com', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      appsSvnPath: '../apps',
      branch: 'master'
    });

    if (!options.dateSlug) {
      grunt.log.error('dateSlug option is required.');
      return false;
    }

    /*
    // Iterate over all specified file groups.
    this.files.forEach(function(f) {
      // Concat specified files.
      var src = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).map(function(filepath) {
        // Read file source.
        return grunt.file.read(filepath);
      }).join(grunt.util.normalizelf(options.separator));

      // Handle options.
      src += options.punctuation;

      // Write the destination file.
      grunt.file.write(f.dest, src);

      // Print a success message.
      grunt.log.writeln('File "' + f.dest + '" created.');
    });
   */
  });

};

Set up options structure, require dateSlug


import resolve from "resolve";

const cache = {};

export default function (basedir, filename, extensions) {
	const cached = cache[basedir];

	if(cached) {
		const withFilename = cached[filename];
		if(withFilename) {
			let resolved = withFilename.get(extensions);
			if(resolved !== undefined) return resolved;

			resolved = getResolved();
			withFilename.set(extensions, resolved);
			return resolved;
		}

		const resolved = getResolved();
		cached[filename] = new Map().set(extensions, resolved);
		return resolved;
	}

	const resolved = getResolved();
	cache[basedir] = {
		[filename]: new Map().set(extensions, resolved)
	};

	return resolved;

	function getResolved(){
		return resolve.sync(filename, {
			basedir,
			extensions
		});
	}
}

import resolve from "resolve";
import path from "path";

const cache = {};

export default function (basedir, filename, extensions) {
	const cached = cache[basedir];

	if(cached) {
		const withFilename = cached[filename];
		if(withFilename) {
			let resolved = withFilename.get(extensions);
			if(resolved !== undefined) return resolved;

			resolved = getResolved();
			withFilename.set(extensions, resolved);
			return resolved;
		}

		const resolved = getResolved();
		cached[filename] = new Map().set(extensions, resolved);
		return resolved;
	}

	const resolved = getResolved();
	cache[basedir] = {
		[filename]: new Map().set(extensions, resolved)
	};

	return resolved;

	function getResolved(){
		try {
			return resolve.sync(filename, {
				basedir,
				extensions
			});
		} catch (err) {
			let errMessage = err.message + "\nMake sure it is available later", resolved;
			if(filename.startsWith("/") || filename.startsWith(".")) {
				resolved = path.resolve(basedir, filename);
			} else {
				errMessage += " in node_modules";
				resolved = "/node_modules/" + filename;
			}

			console.error(errMessage);
			return resolved;
		}
	}
}

Fix resolving to assumed but presently not available node module relatively


import React from 'react';

const METHODS_TO_BIND = ['onImageError'];

class Image extends React.Component {
  constructor() {
    super(...arguments);

    METHODS_TO_BIND.forEach((method) => {
      this[method] = this[method].bind(this);
    });
  }

  onImageError(event) {
    let {fallbackSrc} = this.props;
    if (!fallbackSrc || event.target.src === fallbackSrc) {
      return;
    }

    event.target.src = fallbackSrc;
  }

  render() {
    let {props} = this;

    return (
      <img src={props.src} onError={this.onImageError} {...props} />
    );
  }
}

Image.propTypes = {
  src: React.PropTypes.string,
  fallbackSrc: React.PropTypes.string
};

module.exports = Image;

import classNames from 'classnames/dedupe';
import React from 'react';
import ReactDOM from 'react-dom';

import Util from '../utils/Util';

const METHODS_TO_BIND = ['onImageError'];

class Image extends React.Component {
  constructor() {
    super(...arguments);

    this.state = {
      imageErrorCount: 0
    };

    METHODS_TO_BIND.forEach((method) => {
      this[method] = this[method].bind(this);
    });
  }

  componentWillReceiveProps(nextProps) {
    // Try again if new urls were provided
    let image = ReactDOM.findDOMNode(this);
    image.src = nextProps.src;

    this.setState({imageErrorCount: 0});
  }

  onImageError(event) {
    let {props: {fallbackSrc}, state: {imageErrorCount}} = this;

    if (imageErrorCount === 0) {
      event.target.src = fallbackSrc;
    }

    // Both src and fallback failed
    this.setState({imageErrorCount: imageErrorCount + 1});
  }

  render() {
    let {props, state: {imageErrorCount}} = this;
    let classes = classNames(
      {'hidden': imageErrorCount > 1},
      props.className
    );

    return (
      <img
        className={classes}
        onError={this.onImageError}
        {...Util.omit(props, ['className'])} />
    );
  }
}

Image.propTypes = {
  src: React.PropTypes.string,
  fallbackSrc: React.PropTypes.string,

  // Classes
  className: React.PropTypes.oneOfType([
    React.PropTypes.array,
    React.PropTypes.object,
    React.PropTypes.string
  ])
};

module.exports = Image;

Make component more solid when receiving new props


import { getLogger } from "./logger";
const logger = getLogger();

const helpTextHandlers = {
  [MISSING_404_TEXT]: showMissing404Text
};

function showMissing404Text () {
  logger.info(`
#########################################################################################
Rendered a 404 Error but no custom 404 route detected.
You can create a custom 404 handler with the following steps:
  1. Create a new container that you would like to use when rendering 404 errors.
     > gluestick generate container RouteNotFound
  2. Import this new container in the routes file along with the 'ROUTE_NAME_404_NOT_FOUND' constant.
     import RouteNotFound from "../containers/RouteNotFound";
     import { ROUTE_NAME_404_NOT_FOUND } from "gluestick-shared";
  3. Add a new route that uses this constant and container as your very last route.
      <Route name={"ROUTE_NAME_404_NOT_FOUND"} path="*" component={RouteNotFound} />
#########################################################################################
`);
}

export default function showHelpText (key) {
  helpTextHandlers[key]();
}

export const MISSING_404_TEXT = "MISSING_404_TEXT";

import { getLogger } from "./logger";
const logger = getLogger();

const helpTextHandlers = {
  MISSING_404_TEXT: showMissing404Text
};

function showMissing404Text () {
  logger.info(`
#########################################################################################
Rendered a 404 Error but no custom 404 route detected.
You can create a custom 404 handler with the following steps:
  1. Create a new container that you would like to use when rendering 404 errors.
     > gluestick generate container RouteNotFound
  2. Import this new container in the routes file along with the 'ROUTE_NAME_404_NOT_FOUND' constant.
     import RouteNotFound from "../containers/RouteNotFound";
     import { ROUTE_NAME_404_NOT_FOUND } from "gluestick-shared";
  3. Add a new route that uses this constant and container as your very last route.
      <Route name={"ROUTE_NAME_404_NOT_FOUND"} path="*" component={RouteNotFound} />
#########################################################################################
`);
}

export default function showHelpText (key) {
  helpTextHandlers[key]();
}

export const MISSING_404_TEXT = "MISSING_404_TEXT";

Fix help handler for 404 message


'use strict';

/**@ngInject*/
function FormInput() {
    return {
        restrict: 'E',
        templateUrl: '/partials/common/form_input.html',
        scope: {
            fieldModel: "=fieldModel",
            fieldType: "=fieldType",
            fieldRequired: "=fieldRequired",
            fieldDisabled: "=fieldDisabled",
            fieldId: "=fieldId",
            fieldName: "=fieldName",
            label: "=label",
            helpText: "=helpText"
        },
        controller: [ '$scope', function ($scope) {
            $scope.dateOpened = [];

            $scope.openDate = function($event, index) {
                $event.preventDefault();
                $event.stopPropagation();
                $scope.answerDateOpened[index] = [];
                $scope.answerDateOpened[index] = true;
            };

            $scope.dateOptions = {
                formatYear: 'yy',
                startingDay: 1
            };

            $scope.format = 'yyyy-MM-dd';
        }]
    };
}

module.exports = FormInput;

'use strict';

/**@ngInject*/
function FormInput() {
    return {
        restrict: 'E',
        templateUrl: '/partials/common/form_input.html',
        scope: {
          field: '='
        },
        controller: [ '$scope', function ($scope) {
            $scope.dateOpened = [];

            $scope.openDate = function($event, index) {
                $event.preventDefault();
                $event.stopPropagation();
                $scope.answerDateOpened[index] = [];
                $scope.answerDateOpened[index] = true;
            };

            $scope.dateOptions = {
                formatYear: 'yy',
                startingDay: 1
            };

            $scope.format = 'yyyy-MM-dd';
        }]
    };
}

module.exports = FormInput;

Reduce the number of values required and put into scope.


/**
 * @fileOverview PocketCreateCtrl angular controller
 */

define(['./module', 'darkwallet'], function (controllers, DarkWallet) {
  'use strict';
  controllers.controller('PocketCreateCtrl', ['$scope', function($scope) {

    /**
     * Scope variables
     */
    $scope.newPocket = {};
    $scope.creatingPocket = false;

    /**
     * Create a pocket
     */
    $scope.createPocket = function() {
        if ($scope.creatingPocket && $scope.newPocket.name) {
            var identity = DarkWallet.getIdentity();

            // create pocket
            identity.wallet.pockets.createPocket($scope.newPocket.name);
            var pocketIndex = identity.wallet.pockets.hdPockets.length-1;

            // initialize pocket on angular
            $scope.initPocket(pocketIndex);

            // generate an address
            $scope.generateAddress(pocketIndex, 0);

            // select the pocket
            $scope.selectPocket($scope.newPocket.name, pocketIndex);

            // reset pocket form
            $scope.newPocket = {name:''};
        }
        $scope.creatingPocket = !$scope.creatingPocket;
    };

}]);
});

/**
 * @fileOverview PocketCreateCtrl angular controller
 */

define(['./module', 'darkwallet'], function (controllers, DarkWallet) {
  'use strict';
  controllers.controller('PocketCreateCtrl', ['$scope', function($scope) {

    /**
     * Scope variables
     */
    $scope.newPocket = {};
    $scope.creatingPocket = false;

    /**
     * Create a pocket
     */
    $scope.createPocket = function() {
        if ($scope.creatingPocket && $scope.newPocket.name) {
            var identity = DarkWallet.getIdentity();

            // create pocket
            identity.wallet.pockets.createPocket($scope.newPocket.name);
            var pocketIndex = identity.wallet.pockets.hdPockets.length-1;

            // initialize pocket on angular
            $scope.initPocket(pocketIndex);

            // generate an address
            $scope.generateAddress(pocketIndex*2, 0);

            // select the pocket
            $scope.selectPocket($scope.newPocket.name, pocketIndex);

            // reset pocket form
            $scope.newPocket = {name:''};
        }
        $scope.creatingPocket = !$scope.creatingPocket;
    };

}]);
});

Fix generating the first address for a pocket.


import ls from '../ls'

const dir = process.cwd()

describe('ls', () => {
  it('lists all files', async () => {
    const files = await ls(dir)
    expect(files).not.toEqual([])
  })
  it('ignores given patterns', async () => {
    const files = await ls(dir, ['package.json'])
    expect(files.indexOf('node_modules/jest')).toEqual(-1)
    expect(files.indexOf('package.json')).toEqual(-1)
  })
})

import ls from '../ls'
import { join } from 'path'

const dir = join(__dirname, '..', '..')

describe('ls', () => {
  it('lists all files', async () => {
    const files = await ls(dir)
    expect(files).not.toEqual([])
  })
  it('ignores given patterns', async () => {
    const files = await ls(dir, ['package.json'])
    expect(files.indexOf('node_modules/jest')).toEqual(-1)
    expect(files.indexOf('package.json')).toEqual(-1)
  })
})

Use __dirname instead of process.cwd()


import Arrow from './arrow'
import Atm from './atm'
import Attributes from './attributes'
import Bag from './bag'
import Bubbles from './bubbles'
import Cart from './cart'
import Checkmark from './checkmark'
import Error from './error'
import Headset from './headset'
import Magnifier from './magnifier'
import MagnifierAlt from './magnifier-alt'
import Notebook from './notebook'
import Payout from './payout'
import ProductBox from './product-box'
import Pencil from './pencil'
import Regret from './regret'
import TableSetting from './table-setting'
import Shop from './shop'
import ShopAlt from './shop-alt'
import Star from './star'
import Stock from './stock'
import Tags from './tags'
import Truck from './truck'
import Warning from './warning'
import X from './x'

export {
  Arrow,
  Atm,
  Attributes,
  Bag,
  Bubbles,
  Cart,
  Checkmark,
  Error,
  Headset,
  Magnifier,
  MagnifierAlt,
  Notebook,
  Payout,
  ProductBox,
  Pencil,
  Regret,
  TableSetting,
  Shop,
  ShopAlt,
  Star,
  Stock,
  Tags,
  Truck,
  Warning,
  X,
}

import Arrow from './arrow'
import Atm from './atm'
import Attributes from './attributes'
import Bag from './bag'
import Bubbles from './bubbles'
import Cart from './cart'
import Checkmark from './checkmark'
import Error from './error'
import Headset from './headset'
import Magnifier from './magnifier'
import MagnifierAlt from './magnifier-alt'
import Notebook from './notebook'
import Payout from './payout'
import ProductBox from './product-box'
import Pencil from './pencil'
import Regret from './regret'
import Shop from './shop'
import ShopAlt from './shop-alt'
import Star from './star'
import Stock from './stock'
import Tags from './tags'
import Truck from './truck'
import TableSetting from './table-setting'
import Warning from './warning'
import X from './x'

export {
  Arrow,
  Atm,
  Attributes,
  Bag,
  Bubbles,
  Cart,
  Checkmark,
  Error,
  Headset,
  Magnifier,
  MagnifierAlt,
  Notebook,
  Payout,
  ProductBox,
  Pencil,
  Regret,
  Shop,
  ShopAlt,
  Star,
  Stock,
  Tags,
  Truck,
  TableSetting,
  Warning,
  X,
}

Fix export in right place


// Download the Node helper library from twilio.com/docs/node/install
// These consts are your accountSid and authToken from https://www.twilio.com/console
const VoiceResponse = require('twilio').twiml.VoiceResponse;
const express = require('express');
const app = express();

app.post('/enqueue_call', (request, response) => {
  const resp = new VoiceResponse();

  const json = { account_number: '12345abcdef' };

  resp
    .enqueueTask({
      workflowSid: 'WW0123456789abcdef0123456789abcdef',
    })
    .task({}, JSON.stringify(json));

  response.setHeader('Content-Type', 'application/xml');
  response.write(resp.toString());
  response.end();
});

app.listen(8080);

// Download the Node helper library from twilio.com/docs/node/install
// These consts are your accountSid and authToken from https://www.twilio.com/console
const VoiceResponse = require('twilio').twiml.VoiceResponse;
const express = require('express');
const app = express();

app.post('/enqueue_call', (request, response) => {
  const resp = new VoiceResponse();

  const json = { account_number: '12345abcdef' };

  resp
    .enqueue({
      workflowSid: 'WW0123456789abcdef0123456789abcdef',
    })
    .task({}, JSON.stringify(json));

  response.setHeader('Content-Type', 'application/xml');
  response.write(resp.toString());
  response.end();
});

app.listen(8080);

Update to move enqueueTask -> enqueue


function ddg_spice_github_jobs(api_result) {
    if (api_result.length == 0) return;

    var jobs = api_result;
    var query = DDG.get_query();
    var re = /(?:\s*(?:i\s+|we\s+)?(?:need|want|deserve|seek|get)\s+(?:an?\s+)?)?(?:(.+)\s+)(?:jobs?|work|employment)(?:\s+(?:in\s+)?(.+))?/;
	jobs['description'] = query.replace(re, "$1");
	jobs['location'] = query.replace(re, "$2");

    Spice.render({
        data             : api_result,
        header1          : query + " (GitHub Jobs)",
        source_url       : 'https://jobs.github.com/positions?description='
                            + encodeURIComponent(jobs['description'])
                            + "&location=" +  encodeURIComponent(jobs['location']),
        source_name      : 'GitHub',
        spice_name      : 'github',

        template_frame   : 'list',
        template_options: {
            items: api_result,
            template_item: "github_jobs",
            show: 3,
            type: 'ul',
        },
        force_big_header : true,
        force_no_fold    : true
    });
}

function ddg_spice_github_jobs(api_result) {
    if (api_result.length == 0) return;

    var jobs = api_result;
    var query = DDG.get_query();
    var re = /(?:\s*(?:i\s+|we\s+)?(?:need|want|deserve|seek|get)\s+(?:an?\s+)?)?(?:(.+)\s+)(?:jobs?|work|employment)(?:\s+(?:in\s+)?(.+))?/;
	jobs['description'] = query.replace(re, "$1");
	jobs['location'] = query.replace(re, "$2");

    Spice.render({
        data             : api_result,
        header1          : query + " (GitHub Jobs)",
        source_url       : 'https://jobs.github.com/positions?description='
                            + encodeURIComponent(jobs['description'])
                            + "&location=" +  encodeURIComponent(jobs['location']),
        source_name      : 'GitHub',
        spice_name      : 'github',

        template_frame   : 'list',
        template_options: {
            items: api_result,
            template_item: "github_jobs",
            show: 3,
	    max: 10,
            type: 'ul'
        },
        force_big_header : true,
        force_no_fold    : true
    });
}

Add a max option in Github Jobs.


import React from 'react';
import addons from '@storybook/addons';
import ActionLogger from './containers/ActionLogger';
import { ADDON_ID, PANEL_ID } from '.';

export function register() {
  addons.register(ADDON_ID, api => {
    const channel = addons.getChannel();
    addons.addPanel(PANEL_ID, {
      title: 'Action Logger',
      // eslint-disable-next-line react/prop-types
      render: ({ active, key }) => (
        <ActionLogger key={key} channel={channel} api={api} active={active} />
      ),
    });
  });
}

import React from 'react';
import addons from '@storybook/addons';
import ActionLogger from './containers/ActionLogger';
import { ADDON_ID, PANEL_ID } from '.';

export function register() {
  addons.register(ADDON_ID, api => {
    const channel = addons.getChannel();
    addons.addPanel(PANEL_ID, {
      title: 'Actions',
      // eslint-disable-next-line react/prop-types
      render: ({ active, key }) => (
        <ActionLogger key={key} channel={channel} api={api} active={active} />
      ),
    });
  });
}

Change title of panel to "Actions" from "Action logger"


var step = ''
           + '
Test Purpose:
'
           + '
Verifies the Typed Array can be created, set and got
'
           + '
Test Steps:
'
             + '
'
               + '
Click the "Set Value" button.
'
               + '
Click the "Get Value" button.
'
             + '
'
           + '
Expected Result:
'
           + '
Test passes if the array is initialized with 0 and can be filled to 1.
'
         + ''

var step = ''
           + '
Test Purpose:
'
           + '
Verifies the Typed Array can be created, set and got
'
           + '
Test Steps:
'
             + '
'
               + '
Click the "Set & Get Value" button.
'
             + '
'
           + '
Expected Result:
'
           + '
Test passes if the array is initialized with 0 and can be filled to 1.
'
         + ''

Update the desc of Test Steps in TypedArray


define('app/models/rule', ['ember'],
    //
    //  Rule Model
    //
    //  @returns Class
    ///
    function () {

        'use strict';

        return Ember.Object.extend({

            //
            //
            //  Properties
            //
            //

            id: null,
            unit: null,
            value: null,
            metric: null,
            cycles: null,
            command: null,
            machine: null,
            operator: null,
            maxValue: null,
            aggregate: null,
            timeWindow: null,
            machineKey: null,
            machineName: null,
            machineSize: null,
            actionToTake: null,
            machineImage: null,
            machineScript: null,
            pendingAction: false,
            machineBackend: null,
            machineLocation: null,

            init: function () {
                this._super();
                // TODO: delete. This is temp for debugging only
                this.set('aggregate', 'any');
                this.set('timeWindow', 1);
            },

        });
    }
);

define('app/models/rule', ['ember'],
    //
    //  Rule Model
    //
    //  @returns Class
    ///
    function () {

        'use strict';

        return Ember.Object.extend({

            //
            //
            //  Properties
            //
            //

            id: null,
            unit: null,
            value: null,
            metric: null,
            cycles: null,
            command: null,
            machine: null,
            operator: null,
            maxValue: null,
            aggregate: null,
            timeWindow: null,
            machineKey: null,
            machineName: null,
            machineSize: null,
            actionToTake: null,
            machineImage: null,
            machineScript: null,
            pendingAction: false,
            machineBackend: null,
            machineLocation: null,

            init: function () {
                this._super();
                // TODO: delete. This is temp for debugging only
                this.set('aggregate', 'every');
                this.set('timeWindow', 1);
            },

        });
    }
);

Make "every" the default aggregate option


import React, { Component } from 'react';

import {
  StyleSheet,
  Text,
  View,
  TouchableHighlight,
} from 'react-native';

class Story extends Component{

  onProfilePressed() {
    this.props.navigator.push({
      title: 'Story',
      component: Story
    })
  }

  render() {
    return (
      <View style={styles.container}>
        <Text>Day 7</Text>
          <Text style={styles.title}> My neighbor Amira </Text>
          <Text style={styles.content}> Today I met another girl my age named Amira, her family is like mine...</Text>

      <TouchableHighlight onPress={this.onProfilePressed.bind(this)} style={styles.button}>
        <Text style={styles.buttonText}>
        Ahmeds Profile
        </Text>
      </TouchableHighlight>

      </View>

    )
  }
};

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
   fontSize: 20,
   alignSelf: 'center',
   margin: 40
  },
  content: {
    alignSelf: 'center',
    fontSize: 21,
    marginTop: 10,
    marginBottom: 5,
  }
});

module.exports = Story;

import React, { Component } from 'react';

import {
  StyleSheet,
  Text,
  View,
  TouchableHighlight,
} from 'react-native';

class Story extends Component{

  onProfilePressed() {
    this.props.navigator.push({
      title: 'Story',
      component: Profile
    })
  }

  render() {
    return (
      <View style={styles.container}>
        <Text>Day 7</Text>
          <Text style={styles.title}> My neighbor Amira </Text>
          <Text style={styles.content}> Today I met another girl my age named Amira, her family is like mine...</Text>

      <TouchableHighlight onPress={this.onProfilePressed.bind(this)} style={styles.button}>
        <Text style={styles.buttonText}>
        Ahmeds Profile
        </Text>
      </TouchableHighlight>

      </View>

    )
  }
};

var styles = StyleSheet.create({
  button: {
    height: 50,
    backgroundColor: '#48BBEC',
    alignSelf: 'stretch',
    marginTop: 10,
    justifyContent: 'center'
  },
  buttonText: {
    textAlign: 'center',
  },
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
   fontSize: 20,
   alignSelf: 'center',
   margin: 40
  },
  content: {
    alignSelf: 'center',
    fontSize: 21,
    marginTop: 10,
    marginBottom: 5,
  },

});

module.exports = Story;

Add styles to button and button text, will move to top right


import Settings from 'utils/Settings';

import cs from './lang/cs';
import en from './lang/en';
import nl from './lang/nl';
import sk from './lang/sk';

const ALL = [
  cs,
  en,
  nl,
  sk
];

function getAvailable() {
  return ALL.slice();
}

function getSelected() {
  return Settings.get().then(({ language }) => language);
}

function find(languageCode) {
  const majorLanguageCode = languageCode.split(/-_/).shift().toLowerCase();

  return ALL.find(({ code }) => code === majorLanguageCode);
}

function detect(document) {
  const siteLanguageCode = document.documentElement.getAttribute('lang');
  const navigatorLanguageCode = navigator.language;
  const detectedlanguage = find(siteLanguageCode) || find(navigatorLanguageCode);

  return detectedlanguage || null;
}

export default {
  detect,
  find,
  getAvailable,
  getSelected
};

import Settings from 'utils/Settings';

import cs from './lang/cs';
import en from './lang/en';
import es from './lang/es';
import nl from './lang/nl';
import sk from './lang/sk';

const ALL = [
  cs,
  en,
  es,
  nl,
  sk
];

function getAvailable() {
  return ALL.slice();
}

function getSelected() {
  return Settings.get().then(({ language }) => language);
}

function find(languageCode) {
  const majorLanguageCode = languageCode.split(/-_/).shift().toLowerCase();

  return ALL.find(({ code }) => code === majorLanguageCode);
}

function detect(document) {
  const siteLanguageCode = document.documentElement.getAttribute('lang');
  const navigatorLanguageCode = navigator.language;
  const detectedlanguage = find(siteLanguageCode) || find(navigatorLanguageCode);

  return detectedlanguage || null;
}

export default {
  detect,
  find,
  getAvailable,
  getSelected
};

Add Spanish to list of available languages


import React from 'react'

function bannerClassName(level) {
    var output = 'general-banner alert'
    switch (level) {
        case 'notice':  return output += ' alert-info'
        case 'success': return output += ' alert-success'
        case 'error':   return output += ' alert-danger'
        case 'alert':   return output += ' alert-warning'
        default:        return output
    }
}

const GeneralBanner = (props) => {
    const banner = props.banner
    const showBanner = props.showBanner
    if (showBanner && banner.message){
        return (

{banner.title}: {banner.message}

        )
    } else { return null }
}
export default GeneralBanner

import React from 'react'

function bannerClassName(level) {
    var output = 'general-banner alert'
    switch (level) {
        case 'notice':  return output += ' alert-info'
        case 'success': return output += ' alert-success'
        case 'error':   return output += ' alert-danger'
        case 'alert':   return output += ' alert-warning'
        default:        return output
    }
}

const GeneralBanner = (props) => {
    const banner = props.options
    if (banner.visible && banner.message){
        return (

{banner.title}: {banner.message}

        )
    } else { return null }
}
export default GeneralBanner

Refactor banner options to include visibility variable


window.onload = function(){

    var searchForm = document.getElementById("search");

    if(searchForm){
        searchForm.action="https://www.google.com/search"; //override default search action
        searchForm.addEventListener("submit", addSiteToSearch); //add a listener for the search button
    }
}

function addSiteToSearch(e) {

    	e.preventDefault();

        var s = document.getElementById("search");
        var sv = s.firstChild.value;
    	sv = "site:"+document.URL+" "+sv;

        var t=document.getElementsByName("t")[0];
        var tv=t.options[t.selectedIndex].value;

        if(tv!="all"){
            t.name=t.name+"bs";
        var tb=document.getElementsByName("tbs")[0];
        var tbv=tb.options[tb.selectedIndex].value;
        var tbv="qdr:"+tv.charAt(0);
            console.log(tbv);
        }

    	//s.submit();
    return false;
}

window.onload = function(){

    var searchForm = document.getElementById("search");

    if(searchForm){
        searchForm.action="https://www.google.com/search"; //override default search action
        searchForm.addEventListener("submit", addSiteToSearch); //add a listener for the search button
    }
}

function addSiteToSearch(e) {

    	e.preventDefault();

        var s = document.getElementById("search");
        var sv = s.firstChild.value;

        var ignore = ["author:", "site:", "url:", "selftext:","self:","nsfw:"];

        var overrideSearch=true;

        for (var i in ignore) {

            if (sv.includes(ignore[i])) {
                doOverrideSearch=false;
            }
        }

        if (overrideSearch) {

            // Handle restrict search to subreddit

            var r=document.getElementsByName("restrict_sr")[0];
            var site=document.URL
            if (r) {
                if (r.checked) {

                } else {site="www.reddit.com/"}
            }

            sv = "site:"+site+" "+sv;

            console.log(sv);

            var t=document.getElementsByName("t")[0];
            var tv=t.options[t.selectedIndex].value;

            if(tv!="all"){
                t.name=t.name+"bs";
            var tb=document.getElementsByName("tbs")[0];
            var tbv=tb.options[tb.selectedIndex].value;
            var tbv="qdr:"+tv.charAt(0);
            }

        }
    	//s.submit();
    return false;
}

Use reddit search when searching by author etc.