var request = require('./request');
var config = require('./config');
var notifierVersion = require('./version').notifierVersion;

function merge(target, obj) {
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      target[key] = obj[key];
    }
  }
  return target;
}

function notify(err, options) {
  if (!options) options = {};
  request(config.endpoint, {
    payloadVersion: '3',
    notifierVersion: notifierVersion,

    apiKey: config.apiKey,
    projectRoot: config.projectRoot || window.location.protocol + '//' + window.location.host,
    context: config.context || window.location.pathname,
    user: config.user,
    metaData: merge({}, merge(options.metaData || {}, config.metaData)),
    releaseStage: config.releaseStage,

    appVersion: config.appVersion,
    url: window.location.href,
    userAgent: navigator.userAgent,

    language: navigator.language || navigator.userLanguage,

    severity: options.severity || config.severity,
    name: err.name,
    message: err.message,
    stacktrace: err.stack || err.backtrace || err.stacktrace,
    file: err.fileName || err.sourceURL,
    lineNumber: -1,
    columnNumber: -1,
    breadcrumbs: []
  });
}

module.exports = notify;

var request = require('./request');
var config = require('./config');
var notifierVersion = require('./version').notifierVersion;

function merge(target, obj) {
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      target[key] = obj[key];
    }
  }
  return target;
}

function notify(err, options) {
  if (!options) options = {};
  request(config.endpoint, {
    payloadVersion: '3',
    notifierVersion: notifierVersion,

    apiKey: config.apiKey,
    projectRoot: config.projectRoot || window.location.protocol + '//' + window.location.host,
    context: config.context || window.location.pathname,
    user: config.user,
    metaData: merge(merge({}, config.metaData), config.metaData || {}),
    releaseStage: config.releaseStage,

    appVersion: config.appVersion,
    url: window.location.href,
    userAgent: navigator.userAgent,

    language: navigator.language || navigator.userLanguage,

    severity: options.severity || config.severity,
    name: err.name,
    message: err.message,
    stacktrace: err.stack || err.backtrace || err.stacktrace,
    file: err.fileName || err.sourceURL,
    lineNumber: -1,
    columnNumber: -1,
    breadcrumbs: []
  });
}

module.exports = notify;

Add support for overriding global metaData


var message = "";

$("#sendMessage").on("click", function() {
    message = $("#contactform").serialize();
    $.ajax({
        url: "//formspree.io/robin.soubry@gmail.com",
        method: "POST",
        data: {message: message},
        dataType: "json"
    });

    $("#contact").innerHTML = "

Thanks for your message, we\'ll be in touch promptly.

";

    // alert('Thanks for the email, we\'ll be in touch promptly.');
    return false;
});

var message = "";

$("#sendMessage").on("click", function() {
    message = $("#contactform").serialize();
    $.ajax({
        url: "//formspree.io/info@hackagainstviolence.com",
        method: "POST",
        data: {message: message},
        dataType: "json"
    });

    $("#contact").innerHTML = "

Thanks for your message, we\'ll be in touch promptly.

";

    // alert('Thanks for the email, we\'ll be in touch promptly.');
    return false;
});

Update e-mail address to info@


/**
 * sails-generate-sails.io.js
 *
 * Usage:
 * `sails generate sails.io.js`
 *
 * @description Generates a sails-generate-sails.io.js
 * @help See http://links.sailsjs.org/docs/generators
 */

module.exports = {

  /**
   * The files/folders to generate.
   * @type {Object}
   */

  targets: {
    './assets/js/dependencies/sails.io.js': { template: 'sails.io.js' }
  },

  /**
   * The absolute path to the `templates` for this generator
   * (for use with the `template` helper)
   *
   * @type {String}
   */
  templatesDirectory: require('path').resolve(__dirname, './node_modules/sails.io.js-dist')
};

/**
 * sails-generate-sails.io.js
 *
 * Usage:
 * `sails generate sails.io.js`
 *
 * @description Generates a sails-generate-sails.io.js
 * @help See http://links.sailsjs.org/docs/generators
 */

module.exports = {

  /**
   * The files/folders to generate.
   * @type {Object}
   */

  targets: {
    './assets/js/dependencies/sails.io.js': { template: 'sails.io.js' }
  },

  /**
   * The absolute path to the `templates` for this generator
   * (for use with the `template` helper)
   *
   * @type {String}
   */
  templatesDirectory: require('path').dirname(require.resolve('sails.io.js-dist'))
};

Use require.resolve to get path to sails.io.js file


module.exports = function(grunt) {
  grunt.initConfig({
    concat: {
      options: {
        separator: ';',
      },
      dist: {
        src: ['lib/osteo.js', 'lib/*.js'],
        dest: 'osteo.js'
      }
    },

    jshint: {
      options: {
        jshintrc: true
      },
      beforeconcat: ['lib/*.js'],
      afterconcat:  ['osteo.js']
    },

    uglify: {
      options: {
        report: 'min'
      },
      dist: {
        src: 'osteo.js',
        dest: 'osteo.min.js'
      }
    },

    mocha: {
      src: ['test/test.html'],
      options: {
        bail: true,
        log: true,
        run: true,
        mocha: {
          ignoreLeaks: true
        }
      }
    },

    watch: {
      files: ['lib/*.js', 'test/*.js'],
      tasks: ['concat', 'jshint']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-mocha');

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

module.exports = function(grunt) {
  grunt.initConfig({
    concat: {
      dist: {
        src: ['lib/osteo.js', 'lib/*.js'],
        dest: 'osteo.js'
      }
    },

    jshint: {
      options: {
        jshintrc: true
      },
      beforeconcat: ['lib/*.js'],
      afterconcat:  ['osteo.js']
    },

    uglify: {
      options: {
        report: 'min'
      },
      dist: {
        src: 'osteo.js',
        dest: 'osteo.min.js'
      }
    },

    mocha: {
      src: ['test/test.html'],
      options: {
        bail: true,
        log: true,
        run: true,
        mocha: {
          ignoreLeaks: true
        }
      }
    },

    watch: {
      files: ['lib/*.js', 'test/*.js'],
      tasks: ['concat', 'jshint']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-mocha');

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

Stop inserting semicolons during concat


module.exports = function(grunt) {
    //"use strict";
    //This is disabled because it's picking up octal literal notation that is quoted in a string.

    //usage: grunt [server | watch | (--minify &| --syncload)]
    //server: Start a testing server for the website.
    //watch: Automatically recompile part of the project when files are changed.
    //--minify: Compress the build. (Has no effect when server option in use.)

    // Compile a list of paths and output files for our modules for requirejs to compile.
    // TODO: Translate the command-line code to this.

    grunt.initConfig({

        requirejs: {
            compile: {
                options: {
                    mainConfigFile: "rjs_require_config.js",
                    name: "Readium",
                    optimize: grunt.option('minify')?undefined:"none",
                    out: "out/Readium" +
                        (grunt.option('syncload')?".syncload":"") +
                        (grunt.option('minify')?".min":"") + ".js",
                    include: grunt.option('syncload')?"define-sync":undefined,
                    almond: grunt.option('minify')
                }
            }
        }

    });

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

    grunt.registerTask('default', ['requirejs']);

};

module.exports = function(grunt) {
    //"use strict";
    //This is disabled because it's picking up octal literal notation that is quoted in a string.

    //usage: grunt [server | watch | (--minify &| --syncload)]
    //server: Start a testing server for the website.
    //watch: Automatically recompile part of the project when files are changed.
    //--minify: Compress the build. (Has no effect when server option in use.)

    // Compile a list of paths and output files for our modules for requirejs to compile.
    // TODO: Translate the command-line code to this.

    grunt.initConfig({

        requirejs: {
            compile: {
                options: {
                    mainConfigFile: "rjs_require_config.js",
                    name: "Readium",
                    optimize: grunt.option('minify')?"uglify":"none",
                    out: "out/Readium" +
                        (grunt.option('syncload')?".syncload":"") +
                        (grunt.option('minify')?".min":"") + ".js",
                    include: grunt.option('syncload')?"epub-modules/readium-js/src/define-sync":undefined,
                    almond: grunt.option('minify'),
                    wrap: grunt.option('syncload')?{
                      start: "(function (root, ReadiumModuleFactory) {\nroot.Readium = ReadiumModuleFactory();\n}(this, function () {",
                      end: "var Readium = require('Readium');\nreturn Readium;\n}));",
                    }:undefined
                }
            }
        }

    });

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

    grunt.registerTask('default', ['requirejs']);

};

Fix build errors when using optional switches.


module.exports = function(grunt) {
  grunt.loadNpmTasks('grunt-babel');

  grunt.initConfig({
      babel: {
          options: {
              sourceMap: true
          },
          dist: {
              files: [{
                expand: true,
                src: '**/*.es6.js',
                dest: './',
                ext: '.js'
              }]
          }
      }
  });

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

module.exports = function(grunt) {
  grunt.initConfig({
      watch: {
        scripts: {
          files: ['**/*.es6.js'],
          tasks: ['default'],
          options: {
            spawn:false
          }
        },
        stylus: {
          files: ['./static/styles/**/*.styl'],
          tasks: ['compileCss'],
          options: {
            spawn:false
          }
        }
      },
      babel: {
        options: {
            sourceMap: true
        },
        dist: {
            files: [{
              expand: true,
              src: '**/*.es6.js',
              dest: './',
              ext: '.js',
            }]
        }
      },
      stylus: {
        compile: {
          expand: true,
          cwd: 'static/styles',
          src: ['**/*.styl'],
          dest: 'static/styles',
          filter: 'isFile',
          ext: '.css'
        }
      }
  });

  grunt.loadNpmTasks('grunt-babel');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-stylus');

  grunt.registerTask('default', ['babel']);
  grunt.registerTask('compileCss', ['stylus:compile']);

  grunt.event.on('watch', function(action, filepath, target) {
    grunt.log.writeln(target + ': ' + filepath + ' has ' + action);
  });
};

Support compilation JS & CSS


import childProcess from 'child_process'
import {promisify} from 'util'

const exec = promisify(childProcess.exec)

export default async function (name) {
  const {stdout} = await exec(`git config --get ${name}`)
  return stdout.trim()
}

import childProcess from 'child_process'
import {promisify} from 'util'

const exec = promisify(childProcess.exec)

export default async function (name) {
  try {
    const {stdout} = await exec(`git config --get ${name}`)
    return stdout.trim()
  } catch {
    return ''
  }
}

Return empty string when a config entry is not defined


module.exports = function (grunt) {
    'use strict';

    var config = require('./grunt_tasks/config');
    grunt.config.init(config);

    var packages = grunt.file.readJSON('./package.json');
    Object.keys(packages.devDependencies).forEach(function (p) {
        if (p.match(/^grunt-/)) {
            grunt.loadNpmTasks(p);
        }
    });

    grunt.registerTask('test', [
        'espower',
        'karma'
    ]);
    grunt.registerTask('development', [
        'sass:development',
        'csscomb:development',
        'csslint:lax',
        'jshint',
        'plato',
        'connect'
    ]);
    grunt.registerTask('production', [
        'sass:production',
        'csscomb:production',
        'csslint:lax',
        'jshint',
        'plato',
        'connect'
    ]);
};

module.exports = function (grunt) {
    'use strict';

    var config = require('./grunt_tasks/config');
    grunt.config.init(config);

    var packages = grunt.file.readJSON('./package.json');
    Object.keys(packages.devDependencies).forEach(function (p) {
        if (p.match(/^grunt-/)) {
            grunt.loadNpmTasks(p);
        }
    });

    grunt.registerTask('test', [
        'espower',
        'karma'
    ]);

    grunt.registerTask('script-build', [
        'jshint',
        'plato',
        'connect'
    ]);

    grunt.registerTask('style-build', [
        'sass:development',
        'csscomb:development',
        'csslint:lax'
    ]);

    grunt.registerTask('development', [
        'sass:development',
        'csscomb:development',
        'csslint:lax',
        'jshint',
        'plato',
        'connect'
    ]);

    grunt.registerTask('production', [
        'sass:production',
        'csscomb:production',
        'csslint:lax',
        'jshint',
        'plato',
        'connect'
    ]);
};

Add tasks (script-build & style-build)


angular.module("yds").controller("TrafficCountsController", ["$scope", "$timeout", "DashboardService",
    function ($scope, $timeout, DashboardService) {
        var scope = $scope;

        scope.galwayProjectId = "http://linkedeconomy.org/resource/Contract/AwardNotice/2013208591/5795646";
        scope.lang = "en";
        scope.showGrid = true;
        scope.showProjectInfo = false;

        // Create the object for the clicked traffic point
        scope.selectedPoint = {
            "point": null
        };

        /**
         * Get the selected contract from the DashboardService, and show or hide the Contract details
         */
        var gridSelectionHandler = function () {
            var selectedContract = _.first(DashboardService.getGridSelection("galway_contract"));

            DashboardService.setSelectedProject(selectedContract, null);
            scope.showProjectInfo = false;

            $timeout(function () {
                scope.showProjectInfo = !_.isUndefined(selectedContract);
            });
        };

        // Watch changes in the selected point, and set it as selected in the DashboardService
        scope.$watch("selectedPoint.point", function (newPoint) {
            // Force a refresh of the related contracts grid
            scope.showGrid = false;
            scope.showProjectInfo = false;

            $timeout(function () {
                scope.showGrid = true;
                DashboardService.setGridSelection("galway_traffic_point", newPoint);
            });
        });

        // Watch for changes in the selected contract, to show the Contract details page
        DashboardService.subscribeGridSelectionChanges(scope, gridSelectionHandler);
    }
]);

angular.module("yds").controller("TrafficCountsController", ["$scope", "$timeout", "DashboardService",
    function ($scope, $timeout, DashboardService) {
        var scope = $scope;

        scope.galwayProjectId = "http://linkedeconomy.org/resource/Contract/AwardNotice/2013208591/5795646";
        scope.lang = "en";
        scope.showGrid = true;
        scope.showProjectInfo = false;

        // Create the object for the clicked traffic point
        scope.selectedPoint = {
            "point": null
        };

        /**
         * Get the selected contract from the DashboardService, and show or hide the Contract details
         */
        var gridSelectionHandler = function () {
            var selectedContract = _.first(DashboardService.getGridSelection("galway_contract"));

            DashboardService.setSelectedProject(selectedContract, null);
            scope.showProjectInfo = false;

            $timeout(function () {
                scope.showProjectInfo = !_.isUndefined(selectedContract);
            });
        };

        // Watch changes in the selected point, and set it as selected in the DashboardService
        scope.$watch("selectedPoint.point", function (newPoint) {
            // Force a refresh of the related contracts grid
            scope.showGrid = false;
            scope.showProjectInfo = false;

            $timeout(function () {
                scope.showGrid = true;
                DashboardService.setGridSelection("galway_contract", undefined);
                DashboardService.setGridSelection("galway_traffic_point", newPoint);
            });
        });

        // Watch for changes in the selected contract, to show the Contract details page
        DashboardService.subscribeGridSelectionChanges(scope, gridSelectionHandler);
    }
]);

Hide the Contract details when the selected point changes


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

const DEFAULT_CONFIG = {
    extends: 'kokarn'
};
const DEFAULT_TEST_COMMAND = 'eslint *.js';
const DEFAULT_ENGINE = '^6.9.4';
const PACKAGE_PATH = path.join( __dirname, '../../../', 'package.json' );
let packageData = '';
let write = false;

try {
    packageData = JSON.parse( fs.readFileSync( PACKAGE_PATH, 'utf8' ) );
} catch ( error ) {
    console.log( `Failed to load package.json in ${ PACKAGE_PATH }, skipping setup` );
    process.exit( 0 );
}

if( !packageData.scripts ){
    packageData.scripts = {
        pretest: DEFAULT_TEST_COMMAND
    };

    write = true;
} else if ( packageData.scripts && !packageData.scripts.pretest ){
    packageData.scripts.pretest = DEFAULT_TEST_COMMAND;

    write = true;
}

if ( !packageData.engines ){
    packageData.engines = {
        node: DEFAULT_ENGINE
    };

    write = true;
}

if ( !packageData.eslintConfig ) {
    packageData.eslintConfig = DEFAULT_CONFIG;

    write = true;
}

if ( write ) {
    fs.writeFileSync( PACKAGE_PATH, JSON.stringify( packageData, null, 2 ) );
}

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

const DEFAULT_CONFIG = {
    extends: 'kokarn'
};
const DEFAULT_TEST_COMMAND = 'eslint *.js';
const DEFAULT_ENGINE = process.version.replace( 'v', '^' ) || '^10.10.0';
const PACKAGE_PATH = path.join( __dirname, '../../../', 'package.json' );
let packageData = '';
let write = false;

try {
    packageData = JSON.parse( fs.readFileSync( PACKAGE_PATH, 'utf8' ) );
} catch ( error ) {
    console.log( `Failed to load package.json in ${ PACKAGE_PATH }, skipping setup` );
    process.exit( 0 );
}

if( !packageData.scripts ){
    packageData.scripts = {
        pretest: DEFAULT_TEST_COMMAND
    };

    write = true;
} else if ( packageData.scripts && !packageData.scripts.pretest ){
    packageData.scripts.pretest = DEFAULT_TEST_COMMAND;

    write = true;
}

if ( !packageData.engines ){
    packageData.engines = {
        node: DEFAULT_ENGINE
    };

    write = true;
}

if ( !packageData.eslintConfig ) {
    packageData.eslintConfig = DEFAULT_CONFIG;

    write = true;
}

if ( write ) {
    fs.writeFileSync( PACKAGE_PATH, JSON.stringify( packageData, null, 2 ) );
}

Use current version as default range with fallback to a new version


/**
 * Module dependencies.
 */
import fs from 'fs';

export function createReadStream( ...args ) {
	return fs.createReadStream( ...args );
}

Add newline to end of file


angular.module('zeus.editReview', [])
.controller('editReviewController', function($location, $stateParams, Details) {
  var EditReviewVm = this;
  var id = $stateParams.id;
  var currentUser = JSON.parse(localStorage.getItem('profile'));
  EditReviewVm.title = '';
  EditReviewVm.content = '';
  EditReviewVm.rating = '';

  Details.getReviewById(id)
    .then(function(reviewInfo){
      console.log(currentUser)
      if(currentUser === null || currentUser.user_id !== reviewInfo.review.user_id){
        return EditReviewVm.cancel();
      }

      EditReviewVm.title = reviewInfo.review.title;
      EditReviewVm.content = reviewInfo.review.content;
      EditReviewVm.rating = reviewInfo.review.rating;
    });

  EditReviewVm.edit = function(){
    var updatedReview = {
      content: EditReviewVm.content,
      title: EditReviewVm.title,
      rating: EditReviewVm.rating
    };
    Details.editReview(id, updatedReview)
    .then(function(){
      EditReviewVm.cancel();
    });
  };

  EditReviewVm.cancel = function(){
    $location.path('/review/' + id);
  };
});

angular.module('zeus.editReview', [])
.controller('editReviewController', function($location, $stateParams, Reviews) {
  var EditReviewVm = this;
  var id = $stateParams.id;
  var currentUser = JSON.parse(localStorage.getItem('profile'));
  EditReviewVm.title = '';
  EditReviewVm.content = '';
  EditReviewVm.rating = '';

  Reviews.getReviewById(id)
    .then(function(reviewInfo){
      console.log(currentUser);
      if(currentUser === null || currentUser.user_id !== reviewInfo.review.user_id){
        return EditReviewVm.cancel();
      }

      EditReviewVm.title = reviewInfo.review.title;
      EditReviewVm.content = reviewInfo.review.content;
      EditReviewVm.rating = reviewInfo.review.rating;
    });

  EditReviewVm.edit = function(){
    var updatedReview = {
      content: EditReviewVm.content,
      title: EditReviewVm.title,
      rating: EditReviewVm.rating
    };
    Reviews.editReview(id, updatedReview)
    .then(function(){
      EditReviewVm.cancel();
    });
  };

  EditReviewVm.cancel = function(){
    $location.path('/review/' + id);
  };
});

Change functions removed from Details factory to run from new Reviews Factory


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

process.env.CHROME_BIN = require('puppeteer').executablePath();

module.exports = function (config) {
  config.set({
    basePath: '.',
    frameworks: ['mocha'],
    reporters: ['mocha'],
    client: {
      captureConsole: true,
    },
    files: [
      {pattern: path.resolve('./build/injector.js'), watched: false},
      {pattern: process.env.KARMA_FILE_PATTERN, watched: false}
    ],
    preprocessors: {
      'build/injector.js': ['webpack'],
      'src/*.spec.ts': ['webpack', 'sourcemap']
    },
    mime: {
      'text/x-typescript': ['ts','tsx']
    },
    webpack: webpack,
    webpackMiddleware: {
      noInfo: true,
      stats: 'errors-only'
    },
    port: 9876,
    colors: true,
    singleRun: true,
    logLevel: config.LOG_INFO
  });
};

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

process.env.CHROME_BIN = require('puppeteer').executablePath();

module.exports = function (config) {
  config.set({
    basePath: '.',
    frameworks: ['mocha'],
    reporters: ['mocha'],
    client: {
      captureConsole: true,
      mocha: {
        timeout : 10000, // 10 seconds - upped from 2 seconds
        retries: 3 // Allow for slow server on CI.
      }
    },
    files: [
      {pattern: path.resolve('./build/injector.js'), watched: false},
      {pattern: process.env.KARMA_FILE_PATTERN, watched: false}
    ],
    preprocessors: {
      'build/injector.js': ['webpack'],
      'src/*.spec.ts': ['webpack', 'sourcemap']
    },
    mime: {
      'text/x-typescript': ['ts','tsx']
    },
    webpack: webpack,
    webpackMiddleware: {
      noInfo: true,
      stats: 'errors-only'
    },
    browserNoActivityTimeout: 31000, // 31 seconds - upped from 10 seconds
    browserDisconnectTimeout: 31000, // 31 seconds - upped from 2 seconds
    browserDisconnectTolerance: 2,
    port: 9876,
    colors: true,
    singleRun: true,
    logLevel: config.LOG_INFO
  });
};

Revert "Decrease high timeout in ci"


import client from '@sanity/client-next'
import getUserConfig from './getUserConfig'

/**
 * Creates a wrapper/getter function to retrieve a Sanity API client.
 * Instead of spreading the error checking logic around the project,
 * we call it here when (and only when) a command needs to use the API
 */
const defaults = {
  requireUser: true,
  requireProject: true
}

export default function clientWrapper(manifest, path) {
  return function (opts = {}) {
    const {requireUser, requireProject, api} = {...defaults, ...opts}
    const token = getUserConfig().get('authToken')
    const apiConfig = api || (manifest && manifest.api) || {}

    if (requireUser && !token) {
      throw new Error('You must login first')
    }

    if (requireProject && !apiConfig.projectId) {
      throw new Error(
        `"${path}" does not contain a project identifier ("api.projectId"), `
        + 'which is required for the Sanity CLI to communicate with the Sanity API'
      )
    }

    return client({
      ...apiConfig,
      dataset: apiConfig.dataset || 'dummy',
      token: token,
      useProjectHostname: requireProject
    })
  }
}

import client from '@sanity/client-next'
import getUserConfig from './getUserConfig'

/**
 * Creates a wrapper/getter function to retrieve a Sanity API client.
 * Instead of spreading the error checking logic around the project,
 * we call it here when (and only when) a command needs to use the API
 */
const defaults = {
  requireUser: true,
  requireProject: true
}

export default function clientWrapper(manifest, path) {
  return function (opts = {}) {
    const {requireUser, requireProject, api} = {...defaults, ...opts}
    const userConfig = getUserConfig()
    const userApiConf = userConfig.get('api')
    const token = userConfig.get('authToken')
    const apiConfig = api || (manifest && manifest.api) || userApiConf || {}

    if (requireUser && !token) {
      throw new Error('You must login first')
    }

    if (requireProject && !apiConfig.projectId) {
      throw new Error(
        `"${path}" does not contain a project identifier ("api.projectId"), `
        + 'which is required for the Sanity CLI to communicate with the Sanity API'
      )
    }

    return client({
      ...apiConfig,
      dataset: apiConfig.dataset || 'dummy',
      token: token,
      useProjectHostname: requireProject
    })
  }
}

Allow API config to be specified in user configuration


app.controller('SearchController', ['$http', '$mdDialog', function($http, $mdDialog) {
  console.log('SearchController running');
  var self = this;

  self.mentors = [];

  self.newSearch = {
    first_name: null,
    last_name: null,
    email: null,
    company: null,
    job_title: null,
    zip: null,
    race: null,
    gender: null,
    orientation: null,
    birthday: null,
    school: null,
    degree: null,
    major: null,
    language: null
  };

  self.test = function() {
    console.log(self.newSearch);
  };

  self.getMentors = function() {
    console.log(self.newSearch);
    var newSearchString = JSON.stringify(self.newSearch);
    return $http({
        method: 'GET',
        url: '/mentor-search/search',
        headers: {
          newSearchString: newSearchString
        }
      })
      .then(function(response) {
        self.mentors = response.data;
        console.log("Mentors list:", self.mentors);
      }),
      function(err) {
        console.log("Error with search get request ", err);
      };
  };

  self.createMessage = function(ev) {
    $mdDialog.show({
      controller: 'MessageController as message',
      templateUrl: '../../views/message-modal.html',
      targetEvent: ev,
      clickOutsideToClose: true
    });
  };

}]);

/**
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that can be foundin the LICENSE file at http://material.angularjs.org/HEAD/license.
**/

app.controller('SearchController', ['$http', '$mdDialog', 'BioFactory', function($http, $mdDialog, BioFactory) {
  console.log('SearchController running');
  var self = this;

  self.mentors = BioFactory.mentors;

  self.newSearch = {
    first_name: null,
    last_name: null,
    email: null,
    company: null,
    job_title: null,
    zip: null,
    race: null,
    gender: null,
    orientation: null,
    birthday: null,
    school: null,
    degree: null,
    major: null,
    language: null
  };

  self.test = function() {
    console.log(self.newSearch);
  };

  self.getMentor = function(mentorId){
    console.log(mentorId);
    BioFactory.setMentorId(mentorId);
  }

  self.getMentors = function() {
    console.log("SEARCH controller new.Search:", self.newSearch)
    BioFactory.getMentors(self.newSearch);
  };

  self.createMessage = function(ev) {
    $mdDialog.show({
      controller: 'MessageController as message',
      templateUrl: '../../views/message-modal.html',
      targetEvent: ev,
      clickOutsideToClose: true
    });
  };

}]);

/**
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that can be foundin the LICENSE file at http://material.angularjs.org/HEAD/license.
**/

Add getMentor and getMentors functions


import { ADD_MESSAGE } from './actionTypes'

const initialState = {
  messages: []
}

export default function MainReducer(state = initialState, action) {
  switch (action.type) {
    case ADD_MESSAGE:
      return Object.assign({}, state, {
        messages: [
          ...state.messages,
          {
            message: action.message,
            author: action.author
          }
        ]
      })
    default:
      return state;
  }
}

import { combineReducers } from 'redux'
import { ADD_MESSAGE } from './actionTypes'

let nextMessageId = 0;
function messagesReducer(state = [], action) {
  switch (action.type) {
    case ADD_MESSAGE:
      return [
        ...state, {
          id: nextMessageId++,
          message: action.message,
          author: action.author
        }]
    default:
      return state;
  }
}

export default combineReducers({
  messages: messagesReducer
})

Move messagesReducer into it's own reducer


/*jslint browser: true, undef: true *//*global Ext*/
Ext.define('JarvusAceDemo.view.editor.Panel', {
    extend: 'Ext.Panel',
    xtype: 'editor-panel',

    requires: [
        'Jarvus.ace.Editor'
    ],

    layout: 'fit',

    items: [{
        xtype: 'jarvus-ace-editor',

        // Ace configuration
        options: {
            theme: 'ace/theme/monokai',
            mode: 'ace/mode/javascript',
            keyboardHandler: 'ace/keyboard/vim',
            showPrintMargin: true,
            printMarginColumn: 20,
            fontSize: 24
        },

        // subcribe to ACE events
        subscribe: {
            'Document': [
                'change'
            ],
            'Editor': [
                'blur',
                'change'
            ],
            'EditorSession': [
                'change'
            ],
            'Selection': [
                'selectionchange'
            ]
        }
    }]

});

/*jslint browser: true, undef: true *//*global Ext*/
Ext.define('JarvusAceDemo.view.editor.Panel', {
    extend: 'Ext.Panel',
    xtype: 'editor-panel',

    requires: [
        'Jarvus.ace.Editor'
    ],

    layout: 'fit',

    items: [{
        xtype: 'jarvus-ace-editor',

        // Ace configuration
        options: {
            theme: 'ace/theme/monokai',
            mode: 'ace/mode/javascript',
            keyboardHandler: 'ace/keyboard/vim',
            showPrintMargin: true,
            printMarginColumn: 20,
            fontSize: 24
        },

        // subcribe to ACE events
        subscribe: {
            'Document': [
                'change'
            ],
            'Editor': [
                'blur',
                'change'
            ],
            'EditSession': [
                'change'
            ],
            'Selection': [
                'selectionchange'
            ]
        }
    }]

});

Correct ACE class name in subscibe config


import { testColors } from '../components/constants'

export const FAILING = 'failing'
export const PASSING = 'passing'
export const PENDING = 'pending'

export const getTestResult = (mainBrick, unitTest) => {
  const testOutputId = mainBrick.testOutputIds[0]
  const brickValue = mainBrick.outputSlots[testOutputId].value
  const value = unitTest.values[brickValue && brickValue.slotId]
  const testOutput = unitTest.values[testOutputId]

  if(value && value.type && value.value &&
     testOutput && testOutput.type && testOutput.value
  ) {
    if(value.type == testOutput.type && value.value == testOutput.value) {
      return PASSING
    } else {
      return FAILING
    }
  }

  return PENDING
}

export const getTestResultColor = (unitTest) => {
  return testColors[unitTest.result]
}

import { testColors } from '../components/constants'

export const FAILING = 'failing'
export const PASSING = 'passing'
export const PENDING = 'pending'

export const getTestResult = (mainBrick, unitTest) => {
  const testOutputId = mainBrick.testOutputIds[0]

  if(!testOutputId) {
    return PENDING
  }

  const brickValue = mainBrick.outputSlots[testOutputId].value
  const value = unitTest.values[brickValue && brickValue.slotId]
  const testOutput = unitTest.values[testOutputId]

  if(value && value.type && value.value &&
     testOutput && testOutput.type && testOutput.value
  ) {
    if(value.type == testOutput.type && value.value == testOutput.value) {
      return PASSING
    } else {
      return FAILING
    }
  }

  return PENDING
}

export const getTestResultColor = (unitTest) => {
  return testColors[unitTest.result]
}

Return PENDING from 'getTestResult' if mainBrick has no testOutput


/* @flow weak */
import { createElement, PropTypes } from 'react'

export default function createComponent(rule, type = 'div', passThroughProps = []) {
  const FelaComponent = ({ children, className, style, passThrough = [], ...ruleProps }, { renderer, theme }) => {

    // filter props to extract props to pass through
    const componentProps = [ ...passThroughProps, ...passThrough ].reduce((output, prop) => {
      output[prop] = ruleProps[prop]
      return output
    }, { })

    componentProps.style = style

    const cls = className ? className + ' ' : ''
    ruleProps.theme = theme || { }

    componentProps.className = cls + renderer.renderRule(rule, ruleProps)
    return createElement(type, componentProps, children)
  }

  FelaComponent.contextTypes = {
    renderer: PropTypes.object,
    theme: PropTypes.object
  }

  // use the rule name as display name to better debug with react inspector
  FelaComponent.displayName = rule.name && rule.name || 'FelaComponent'
  return FelaComponent
}

/* @flow weak */
import { createElement, PropTypes } from 'react'

export default function createComponent(rule, type = 'div', passThroughProps = []) {
  const FelaComponent = ({ children, className, id, style, passThrough = [], ...ruleProps }, { renderer, theme }) => {

    // filter props to extract props to pass through
    const componentProps = [ ...passThroughProps, ...passThrough ].reduce((output, prop) => {
      output[prop] = ruleProps[prop]
      return output
    }, { })

    componentProps.style = style
    componentProps.id = id

    const cls = className ? className + ' ' : ''
    ruleProps.theme = theme || { }

    componentProps.className = cls + renderer.renderRule(rule, ruleProps)
    return createElement(type, componentProps, children)
  }

  FelaComponent.contextTypes = {
    renderer: PropTypes.object,
    theme: PropTypes.object
  }

  // use the rule name as display name to better debug with react inspector
  FelaComponent.displayName = rule.name && rule.name || 'FelaComponent'
  return FelaComponent
}

Allow `id` to be passed by default


import Model from 'ember-data/model';
import {belongsTo, hasMany} from 'ember-data/relationships';
import attr from 'ember-data/attr';

export default Model.extend({

    show: belongsTo('show'),
    showname: attr('string'),
    host: attr('string'),
    date: attr('string'),
    notes: attr('string'),
    complete: attr('boolean'),
    tracks: hasMany('playlistentry', {inverse: 'playlist'})

});

import Model from 'ember-data/model';
import {belongsTo, hasMany} from 'ember-data/relationships';
import attr from 'ember-data/attr';

export default Model.extend({

    show: belongsTo('show'),
    showname: attr('string'),
    host: attr('string'),
    date: attr('string'),
    notes: attr('string'),
    complete: attr('boolean', {defaultValue: false}),
    tracks: hasMany('playlistentry', {inverse: 'playlist'})

});

Set default value for complete.


/**
 * @license
 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

(function(scope) {

  'use strict';

  if (scope.flags.shadydom) {
    window.ShadyDOM = window.ShadyDOM || {};
    ShadyDOM.force = scope.flags.shadydom;
  }

  if (window.customElements) {
    customElements.forcePolyfill = scope.flags.register;
  }

})(window.WebComponents);

/**
 * @license
 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

(function(scope) {

  'use strict';

  var forceShady = scope.flags.shadydom;
  if (forceShady) {
    window.ShadyDOM = window.ShadyDOM || {};
    ShadyDOM.force = forceShady;
  }

  var forceCE = scope.flags.register || scope.flags.ce;
  if (forceCE && window.customElements) {
    customElements.forcePolyfill = forceCE;
  }

})(window.WebComponents);

Allow forcing CE polyfill via script.


class LobbyController {
  constructor($scope, $state, $stateParams, SocketService) {
    'ngInject';

    this.$state = $state;
    this.SocketService = SocketService;
    this.roomName = $stateParams.roomName;

    $scope.$on('owner_disconnect', function(event, args) {
      alert('Computer disconnected from the game. Game ended.');
      $state.go('main');
    })
  }

  startGame() {
    this.SocketService.send({
      type:'players_ready',
      role:'player'
    });

    this.SocketService.extendedHandler = (message) => {
      if(message.type === 'players_ready') {
        this.handlePlayersReady();
      }
    }
  }

  handlePlayersReady() {
    this.$state.go('loading');
  }
}

export default LobbyController;

class LobbyController {
  constructor($scope, $state, $stateParams, SocketService) {
    'ngInject';

    this.$state = $state;
    this.SocketService = SocketService;
    this.roomName = $stateParams.roomName;

    $scope.$on('owner_disconnect', function(event, args) {
      alert('Computer disconnected from the game. Game ended.');
      $state.go('main');
    })

    this.SocketService.extendedHandler = (message) => {
      if(message.type === 'players_ready') {
        this.handlePlayersReady();
      }
    }
  }

  startGame() {
    this.SocketService.send({
      type:'players_ready',
      role:'player'
    });
  }

  handlePlayersReady() {
    this.$state.go('loading');
  }
}

export default LobbyController;

Fix other devices not moving to loading page


/*jshint browser:true, yui:true */
YUI.add("plugin-lazy-images", function(Y) {
    "use strict";

    var plugins = Y.namespace("Plugins"),
        LazyImages;

    LazyImages = Y.Base.create("lazyImages", Y.Plugin.Base, [], {
        // Y.Base lifecycle fns
        initializer : function() {
            var host = this.get("host");

            host.plug(Y.Plugin.ScrollInfo, {
                scrollMargin : this.get("distance")
            });

            this._handles = [
                host.scrollInfo.after([ "scrollDown", "scrollUp" ], this.loadVisible, this)
            ];
        },

        destructor : function() {
            this.get("host").unplug(Y.Plugin.ScrollInfo);

            new Y.EventTarget(this._handles).detach();

            this._handles = null;
        },

        // Public API
        loadVisible : function() {
            host.scrollInfo.getOnscreenNodes("[data-src]").each(function(img) {
                img.set("src", img.getData("src"));

                img.removeAttribute("data-src");
            });
        }
    }, {
        NS : "lazyimg",

        ATTRS : {
            distance : {
                value : 100
            }
        }
    });

    plugins.LazyImages = LazyImages;

}, "@VERSION@", {
    requires : [
        // YUI
        "base-build",
        "plugin",
        "node-scroll-info"
    ]
});

/*jshint browser:true, yui:true */
YUI.add("plugin-lazy-images", function(Y) {
    "use strict";

    var plugins = Y.namespace("Plugins"),
        LazyImages;

    LazyImages = Y.Base.create("lazyImages", Y.Plugin.Base, [], {
        // Y.Base lifecycle fns
        initializer : function() {
            var host = this.get("host");

            host.plug(Y.Plugin.ScrollInfo, {
                scrollMargin : this.get("distance")
            });

            this._handles = [
                host.scrollInfo.after([ "scrollDown", "scrollUp" ], this.loadVisible, this)
            ];

            this._host = host;
        },

        destructor : function() {
            this.get("host").unplug(Y.Plugin.ScrollInfo);

            new Y.EventTarget(this._handles).detach();

            this._handles = this._host = null;
        },

        // Public API
        loadVisible : function() {
            this._host.scrollInfo.getOnscreenNodes("[data-src]").each(function(img) {
                img.set("src", img.getData("src"));

                img.removeAttribute("data-src");
            });
        }
    }, {
        NS : "lazyimg",

        ATTRS : {
            distance : {
                value : 100
            }
        }
    });

    plugins.LazyImages = LazyImages;

}, "@VERSION@", {
    requires : [
        // YUI
        "base-build",
        "plugin",
        "node-scroll-info"
    ]
});

Fix bad reference to host node


$(function() {

  // Unhover on add hover
  $('.project .menu .add').hover(function() {
    $('.project .menu ul li').removeClass('hover');
  }, function() {});

  // Edit project if selected from the menu
  $('.project .menu li').live("click.pontoon", function (e) {
    e.preventDefault();
    $('.url').val($(this).find('.project-name').html());
    window.location = 'admin/project/' + $(this).find('.project-name').html();
  });

  // Edit or add project if URL typed and Enter pressed
  $('.url').unbind("keydown.pontoon").bind("keydown.pontoon", function (e) {
    var key = e.keyCode || e.which;
    if (key === 13) { // Enter
      window.location = 'admin/project/' + $(this).val();
      return false;
    }
  });

});

$(function() {

  // Edit project if selected from the menu
  $('.project .menu li').click(function (e) {
    e.preventDefault();
    window.location = 'admin/project/' + $(this).find('.project-name').html();
  });

});

Remove obsolete code and re-enable selecting projects


angular.module('starter.controllers', [])

.controller('AppCtrl', function($scope, $ionicModal, $timeout) {
  // Form data for the login modal
  $scope.loginData = {};

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/login.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  // Triggered in the login modal to close it
  $scope.closeLogin = function() {
    $scope.modal.hide();
  };

  // Open the login modal
  $scope.login = function() {
    $scope.modal.show();
  };

  // Perform the login action when the user submits the login form
  $scope.doLogin = function() {
    console.log('Doing login', $scope.loginData);

    // Simulate a login delay. Remove this and replace with your login
    // code if using a login system
    $timeout(function() {
      $scope.closeLogin();
    }, 1000);
  };
})

.controller('PlaylistsCtrl', function($scope) {
  $scope.playlists = [
    { title: 'Reggae', id: 1 },
    { title: 'Chill', id: 2 },
    { title: 'Dubstep', id: 3 },
    { title: 'Indie', id: 4 },
    { title: 'Rap', id: 5 },
    { title: 'Cowbell', id: 6 }
  ];
})

.controller('PlaylistCtrl', function($scope, $stateParams) {
});

angular.module('confboilerplate.controllers', [])

.controller('AppCtrl', function($scope) {

})

.controller('AboutCtrl', function($scope) {

})

.controller('LocationCtrl', function($scope) {

})

.controller('SpeakersCtrl', function($scope) {

})

.controller('ScheduleCtrl', function($scope) {

})

.controller('DetailsCtrl', function($scope, $stateParams) {
  $scope.detailsId = $stateParams.detailsId;
})

.controller('SponsorsCtrl', function($scope) {

})

.controller('PartnersCtrl', function($scope) {

})

;

Add a basic controller for each view


import './main.scss';

/* eslint indent: 0 */
const template = [
  '
',
    '',
    '<highlights class="section"></highlights>',
    '<github-activity class="section" ',
      'user="jordond" ',
      'repo="powerhour-site" ',
      'limit="4" ',
      'enable-commit-status="true">',
    '</github-activity>',
    '<feature-list></feature-list>',
  '
'
].join('');

const mainComponent = {
  bindings: {},
  template
};

export default mainComponent;

import './main.scss';

/* eslint indent: 0 */
const template = [
  '
',
    '',
    '<highlights class="section"></highlights>',
    '<github-activity class="section" ',
      'user="jordond" ',
      'repo="powerhour" ',
      'limit="4" ',
      'enable-commit-status="true">',
    '</github-activity>',
    '<feature-list></feature-list>',
  '
'
].join('');

const mainComponent = {
  bindings: {},
  template
};

export default mainComponent;

Change repo back to app


module.exports = {
  /*
  ** Headers of the page
  */
  head: {
    title: 'client',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Nuxt.js project' }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
    script: [{ src: 'https://js.stripe.com/v3' }]
  },

  /*
  ** Customize the progress bar color
  */

  loading: { color: '#3B8070' },
  /*
  ** Build configuration
  */

  build: {
    /*
    ** Run ESLint on save
    */
    extend(config, { isDev, isClient }) {
      if (isDev && isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
    }
  },
  modules: ['bootstrap-vue/nuxt']
}

module.exports = {
  /*
  ** Headers of the page
  */
  head: {
    title: 'client',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Nuxt.js project' }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
    script: [{ src: 'https://js.stripe.com/v3' }]
  },

  /*
  ** Expose env variables
  */
  env: {
    API_URL: process.env.API_URL
  },

  /*
  ** Customize the progress bar color
  */
  loading: { color: '#3B8070' },

  /*
  ** Build configuration
  */
  build: {
    /*
    ** Run ESLint on save
    */
    extend(config, { isDev, isClient }) {
      if (isDev && isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
    }
  },
  modules: ['bootstrap-vue/nuxt']
}

Fix expose API host env


module.exports = {
    'extends': 'airbnb',
    'rules': {
        'no-console': 0,
        'indent': ['error', 4],
        'prefer-const': 'off',
        'comma-dangle': ['error', 'never'],
        'object-curly-spacing': ['error', 'never']
    }
};

module.exports = {
    'extends': 'airbnb',
    'rules': {
        'no-console': 'off',
        'indent': ['error', 4],
        'prefer-const': 'off',
        'comma-dangle': ['error', 'never'],
        'object-curly-spacing': ['error', 'never']
    }
};

Revert "Code climate doesn't understand `off`"


Template.header.helpers({
    displayRegister: function () {
        if (Meteor.user().profile) {return "none";}
    }
})

Template.heading.helpers({
    heading: function () {
        return pageTitle;
    }
})

Template.header.helpers({
    displayRegister: function () {
        if (Meteor.user().profile) {return "none";}
    }
});

Fix error causing degraded performance


class GameboardController {
  constructor(Game, GlobalEvents) {
    'ngInject';

    this.currentAnswer = '';
    this.currentMangledWord = Game.currentWord.mangled;
    this.game = Game;
    this.remainingTime = Game.remainingSeconds;
    this.score = 0;
    GlobalEvents.on(Game.NEW_WORD, (newWord) => this.onNewWord(newWord));
    GlobalEvents.on(Game.SCORE_UPDATED, (newScore) => this.onNewScore(newScore));
    GlobalEvents.on(Game.TIME_UPDATED, (newTime) => this.onTimeUpdated(newTime));
    GlobalEvents.on(Game.TIME_IS_UP, () => this.onTimeIsUp());
  }

  get isGameActive() {
    return this.game.isActive;
  }

  get playerName() {
    return this.game.playerName;
  }

  onAnswerChange() {
    this.game.setAnswer(this.currentAnswer);
  }

  onNewScore(newScore) {
    this.score = newScore;
  }

  onNewWord(newWord) {
    this.currentAnswer = '';
    this.currentMangledWord = newWord.mangled;
  }

  onTimeIsUp() {
    // TODO
  }

  onTimeUpdated(newTime) {
    this.remainingTime = newTime;
  }
}

export default GameboardController;

class GameboardController {
  constructor(Game, GlobalEvents) {
    'ngInject';

    this.currentAnswer = '';
    this.currentMangledWord = Game.currentWord.mangled;
    this.game = Game;
    this.remainingTime = Game.remainingSeconds;
    this.score = 0;
    GlobalEvents.on(Game.NEW_WORD, (newWord) => this.onNewWord(newWord));
    GlobalEvents.on(Game.SCORE_UPDATED, (newScore) => this.onNewScore(newScore));
    GlobalEvents.on(Game.TIME_UPDATED, (newTime) => this.onTimeUpdated(newTime));
    GlobalEvents.on(Game.TIME_IS_UP, () => this.onTimeIsUp());
  }

  get isGameActive() {
    return this.game.isActive;
  }

  get playerName() {
    return this.game.playerName;
  }

  onAnswerChange() {
    this.game.setAnswer(this.currentAnswer);
  }

  onNewScore(newScore) {
    this.score = newScore;
  }

  onNewWord(newWord) {
    this.currentAnswer = '';
    this.currentMangledWord = newWord.mangled;
    console.log(`Psst, the answer is: ${newWord.original}.`);
  }

  onTimeIsUp() {
    // TODO
  }

  onTimeUpdated(newTime) {
    this.remainingTime = newTime;
  }
}

export default GameboardController;

Add answer hint to the console.log


$(function() {
    var moving = false;
    var availableDays = JSON.parse($('#available-log-days').text());
    var $dateInput = $('#log-date');
    $dateInput.datepicker({
        format: "yyyy/mm/dd",
        endDate: "today",
        todayBtn: "linked",
        language: "en-GB",
        orientation: "top right",
        forceParse: false,
        beforeShowDay: function (date) {
            for(var i = 0; i < availableDays.length; ++i) {
                if(date.getDate() === availableDays[i].day
                        && date.getMonth() + 1 === availableDays[i].month
                        && date.getYear() + 1900 === availableDays[i].year) {
                    return 'has-data';
                }
            }
            return true;
        }
    });
    $('label[for=log-date]').click(function() {
        $dateInput.datepicker('show');
    });

    $dateInput.change(function() {
        if(moving) {
            return;
        }
        moving = true;
        window.location = window.location.href.replace(/logs\/.*/, 'logs/' + $dateInput.val());
    })
});

$(function() {
    var moving = false;
    var availableDays = JSON.parse($('#available-log-days').text());
    var $dateInput = $('#log-date');
    $dateInput.datepicker({
        format: "yyyy/mm/dd",
        endDate: "today",
        todayBtn: "linked",
        language: "en-GB",
        orientation: "top right",
        forceParse: false,
        beforeShowDay: function (date) {
            for(var i = 0; i < availableDays.length; ++i) {
                if(date.getDate() === availableDays[i].day
                        && date.getMonth() + 1 === availableDays[i].month
                        && date.getYear() + 1900 === availableDays[i].year) {
                    return 'has-data';
                }
            }
            return true;
        }
    });
    $('label[for=log-date]').click(function() {
        $dateInput.datepicker('show');
    });

    $dateInput.change(function() {
        if(moving) {
            return;
        }
        moving = true;
        window.location = window.location.href.replace(/logs\/?.*/, 'logs/' + $dateInput.val());
    })
});

Fix regex when no date is specified in the url, thx @kashike


$(function () {
    $('.tree li:has(ul)').addClass('parent_li').find(' > span').attr('title', 'Collapse this branch');
    $('.tree li.parent_li > span').on('click', function (e) {
        var children = $(this).parent('li.parent_li').find(' > ul > li');
        if (children.is(":visible")) {
            children.hide('fast');
            $(this).attr('title', 'Expand this branch').find(' > i').addClass('glyphicon-plus-sign').removeClass('glyphicon-minus-sign');
        } else {
            children.show('fast');
            $(this).attr('title', 'Collapse this branch').find(' > i').addClass('glyphicon-minus-sign').removeClass('glyphicon-plus-sign');
        }
        e.stopPropagation();
    });
});

$(function () {
    $('.tree li:has(ul)').addClass('parent_li').find(' > span').attr('title', 'Expand this branch');

    var children = $('.tree li.parent_li').find(' > ul > li');
    children.hide('fast');
    $('.tree li.parent_li > span').find(' > i').addClass('glyphicon-plus-sign').removeClass('glyphicon-minus-sign');

    $('.tree li.parent_li > span').on('click', function (e) {
        var children = $(this).parent('li.parent_li').find(' > ul > li');
        if (children.is(":visible")) {
            children.hide('fast');
            $(this).attr('title', 'Expand this branch').find(' > i').addClass('glyphicon-plus-sign').removeClass('glyphicon-minus-sign');
        } else {
            children.show('fast');
            $(this).attr('title', 'Collapse this branch').find(' > i').addClass('glyphicon-minus-sign').removeClass('glyphicon-plus-sign');
        }
        e.stopPropagation();
    });
});

Make Jobqueue view start collapsed


import Ember from 'ember';
import { inject as service } from '@ember/service';
import config from '../config/environment';

export default Ember.Route.extend({
  queryParams: {
    rd: {
      refreshModel: true
    }
  },
  routerService: service('-routing'),
  model: function(params) {
    // console.log("In login route");
    var http = location.protocol;
    var slashes = http.concat("//");
    var ishttp = (location.port === '') || (location.port === 80) || (location.port === 443);
    var host = slashes.concat(window.location.hostname) + (ishttp? "": ':'+location.port);
    var pathSuffix = decodeURIComponent(params.rd) || "";
    // Append to query string if on exists, otherwise add one
    if (pathSuffix.indexOf("?") !== -1) {
      pathSuffix += "&token={girderToken}"
    } else {
      pathSuffix += "?token={girderToken}"
    }
    var redirectUrl = host + pathSuffix;
    let url = config.apiUrl + '/oauth/provider?redirect=' + encodeURIComponent(redirectUrl);

    return Ember.$.getJSON(url);
  }
});

import Ember from 'ember';
import { inject as service } from '@ember/service';
import config from '../config/environment';

export default Ember.Route.extend({
  queryParams: {
    rd: {
      refreshModel: true
    }
  },
  routerService: service('-routing'),
  model: function(params) {
    // console.log("In login route");
    var http = location.protocol;
    var slashes = http.concat("//");
    var ishttp = (location.port === '') || (location.port === 80) || (location.port === 443);
    var host = slashes.concat(window.location.hostname) + (ishttp? "": ':'+location.port);
    var pathSuffix = decodeURIComponent(params.rd) || "";
    var redirectUrl = host;
    // Append return route if one exists, ignore login route
    if (pathSuffix && pathSuffix.indexOf('/login') === -1) {
      redirectUrl += pathSuffix
    }
    // Append to query string if one exists, otherwise add one
    if (redirectUrl.indexOf("?") !== -1) {
      redirectUrl += "&token={girderToken}"
    } else {
      redirectUrl += "?token={girderToken}"
    }
    let url = config.apiUrl + '/oauth/provider?redirect=' + encodeURIComponent(redirectUrl);

    return Ember.$.getJSON(url);
  }
});

Handle the case when pathSuffix is falsey


;(function(){
  angular.module('flockTogether', ['ngRoute'], function($routeProvider, $httpProvider) {
      $routeProvider
      .when('/', {
        templateUrl: 'partials/public_event_list.html',
        controller: 'publicListCtrl'
      })//END .when '/home'
      .when('/login', {
        templateUrl: 'partials/login.html',
        controller: 'loginCtrl'
      })//END .when '/login'
      .when('/create-event', {
        templateUrl: 'partials/create_event.html',
        controller: 'createEventCtrl'
      })
      .when('/event-detail/:id', {
        templateUrl: 'partials/event_detail.html',
        controller: 'detailCtrl'
      })
  })//END angular.module 'flock'
    .controller('MainController', function($http, $scope){
      $http.get('api/event.json')
        .then(function(response){
          $scope.events = response.data;
        })//END get event.json
    })//END MainController

})();//END IIFE

;(function(){
  angular.module('flockTogether', ['ngRoute'], function($routeProvider, $httpProvider) {
      $routeProvider
      .when('/', {
        templateUrl: 'partials/event_list.html',
        controller: 'eventListCtrl'
      })//END .when '/home'
      .when('/login', {
        templateUrl: 'partials/login.html',
        controller: 'loginCtrl'
      })//END .when '/login'
      .when('/create-event', {
        templateUrl: 'partials/create_event.html',
        controller: 'createEventCtrl'
      })
      .when('/event-detail/:id', {
        templateUrl: 'partials/event_detail.html',
        controller: 'detailCtrl'
      })
  })//END angular.module 'flock'
    .controller('MainController', function($http, $scope){
      $http.get('api/event.json')
        .then(function(response){
          $scope.events = response.data;
        })//END get event.json
    })//END MainController

})();//END IIFE

Change public event to event list.


module.exports = function(grunt) {

  'use strict';

  grunt.initConfig({

    /**
     * Pull in the package.json file so we can read its metadata.
     */
    pkg: grunt.file.readJSON('package.json'),

    /**
     * LESS: https://github.com/gruntjs/grunt-contrib-less
     *
     * Compile LESS files to CSS.
     */
    less: {
      legacy: {
        options: {
          paths: ["src"],
          yuicompress: false
        },
        files: {
          'dist/ghost.css': ['src/ghost-legacy.less'],
          'src/examples/grid/static/example.css': ['src/examples/grid/static/example.less']
        }
      }
    }

  });

  /**
   * The above tasks are loaded here.
   */
  grunt.loadNpmTasks('grunt-contrib-less');

  /**
   * The 'default' task will run whenever `grunt` is run without specifying a task
   */
  grunt.registerTask('default', ['less']);

};

module.exports = function(grunt) {

  'use strict';

  grunt.initConfig({

    /**
     * Pull in the package.json file so we can read its metadata.
     */
    pkg: grunt.file.readJSON('package.json'),

    /**
     * LESS: https://github.com/gruntjs/grunt-contrib-less
     *
     * Compile LESS files to CSS.
     */
    less: {
      legacy: {
        options: {
          paths: ["src"],
          yuicompress: false
        },
        files: {
          'demo/static/css/ghost.css': ['src/ghost-legacy.less'],
          'src/examples/grid/static/example.css': ['src/examples/grid/static/example.less']
        }
      }
    }

  });

  /**
   * The above tasks are loaded here.
   */
  grunt.loadNpmTasks('grunt-contrib-less');

  /**
   * The 'default' task will run whenever `grunt` is run without specifying a task
   */
  grunt.registerTask('default', ['less']);

};

Change where legacy outputs to in order to match current components.


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

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

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

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

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

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

  initialize: function(options) {

  },

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

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

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

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

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

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

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

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

    return false;
  },

  initialize: function(options) {

  },

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

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

Make post creation work again.


'use strict';

angular.module('gisto.filter.dotToDash', []).filter('dotToDash', function () {
    return function (input) {
        return input.replace('.','-');
    };
});

'use strict';

angular.module('gisto.filter.dotToDash', []).filter('dotToDash', function () {
    return function (input) {
        var output = input;
        if(input.charAt(0) === '.') {
            output = input.substr(1);
        }
        return output.replace('.','-');
    };
});

FIX (dotfiles in gist): fix links of dotfiles


var ui_settings = (function() {

var externalDisplayOn = false;

$(document).on("ui-settings", function(event, data) {

	if (data.header == "externalDisplay") {
		if (canUseExternalDisplay) {
			document.querySelector(".external-display-settings").classList.remove("hidden");
			if (data.content.enabled) {
				externalDisplayOn = true;
				document.querySelector("#external-display-toggle").classList.add("on");
			} else {
				externalDisplayOn = false;
				document.querySelector("#external-display-toggle").classList.remove("on");
			}
		}
		beo.notify(false, "ui-settings");
	}
});

function toggleDisplay() {
	beo.sendToProduct("ui-settings", "externalDisplayOn", {enabled: (!externalDisplayOn) ? true : false});
	if (!externalDisplayOn) {
		beo.notify({title: "Turning external display on...", icon: "attention", timeout: false});
	} else {
		beo.notify({title: "Turning external display off...", icon: "attention", timeout: false});
	}
}

return {
	toggleDisplay: toggleDisplay
}

})();

var ui_settings = (function() {

var externalDisplayOn = false;

$(document).on("ui-settings", function(event, data) {

	if (data.header == "externalDisplay") {
		if (data.content.canUseExternalDisplay) {
			document.querySelector(".external-display-settings").classList.remove("hidden");
			if (data.content.enabled) {
				externalDisplayOn = true;
				document.querySelector("#external-display-toggle").classList.add("on");
			} else {
				externalDisplayOn = false;
				document.querySelector("#external-display-toggle").classList.remove("on");
			}
		}
		beo.notify(false, "ui-settings");
	}
});

function toggleDisplay() {
	beo.sendToProduct("ui-settings", "externalDisplayOn", {enabled: (!externalDisplayOn) ? true : false});
	if (!externalDisplayOn) {
		beo.notify({title: "Turning external display on...", icon: "attention", timeout: false});
	} else {
		beo.notify({title: "Turning external display off...", icon: "attention", timeout: false});
	}
}

return {
	toggleDisplay: toggleDisplay
}

})();

Fix reading the "can use" data


import PropTypes from 'prop-types'
import React from 'react'
import { Button } from 'react-bootstrap'

import FormNavigationButtons from './form-navigation-buttons'
import { PageHeading, StackedPaneContainer } from './styled'

/**
 * This component handles the flow between screens for new OTP user accounts.
 */
const StackedPaneDisplay = ({ onCancel, paneSequence, title }) => (
  <>
    {title && (
      <PageHeading>
        <Button bsStyle='primary' className='pull-right' type='submit'>Save</Button>
        {title}
      </PageHeading>
    )}
    {
      paneSequence.map(({ pane: Pane, props, title }, index) => (
        <StackedPaneContainer key={index}>

{title}

<Pane {...props} />

        </StackedPaneContainer>
      ))
    }

    <FormNavigationButtons
      backButton={{
        onClick: onCancel,
        text: 'Cancel'
      }}
      okayButton={{
        text: 'Save',
        type: 'submit'
      }}
    />
  </>
)

StackedPaneDisplay.propTypes = {
  onCancel: PropTypes.func.isRequired,
  paneSequence: PropTypes.array.isRequired
}

export default StackedPaneDisplay

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

import FormNavigationButtons from './form-navigation-buttons'
import { PageHeading, StackedPaneContainer } from './styled'

/**
 * This component handles the flow between screens for new OTP user accounts.
 */
const StackedPaneDisplay = ({ onCancel, paneSequence, title }) => (
  <>
    {title && <PageHeading>{title}</PageHeading>}
    {
      paneSequence.map(({ pane: Pane, props, title }, index) => (
        <StackedPaneContainer key={index}>

{title}

<Pane {...props} />

        </StackedPaneContainer>
      ))
    }

    <FormNavigationButtons
      backButton={{
        onClick: onCancel,
        text: 'Cancel'
      }}
      okayButton={{
        text: 'Save Preferences',
        type: 'submit'
      }}
    />
  </>
)

StackedPaneDisplay.propTypes = {
  onCancel: PropTypes.func.isRequired,
  paneSequence: PropTypes.array.isRequired
}

export default StackedPaneDisplay

Revert "refactor(StackedPaneDisplay): Experiment with Save button on top."


module.exports = function(deployer) {
  deployer.deploy(ConvertLib);
  deployer.autolink(MetaCoin);
  deployer.deploy(MetaCoin);
};

module.exports = function(deployer) {
  deployer.deploy(ConvertLib);
  deployer.autolink();
  deployer.deploy(MetaCoin);
};

Make example deploy a bit simpler.


import React from 'react';
import { connect } from 'react-redux';

import config from '../config'
import actions from '../actions';

class Messenger extends React.Component {

  sendMessage() {
    const message = this.messageInput.value;
    this.props.sendMessage(this.props.chatId, message);
  }

  render() {
    let messengerAttachmentClass = `c-messenger__attachment ${ this.props.showAttachment ? 'state-active' : '' }`;

    let inputHeight = { height: `${ this.props.messengerHeight }px` };

    return (

        <button className={ messengerAttachmentClass } onClick={ this.props.toggleAttachment }>

        </button>

        <textarea ref={ input => this.messageInput = input }
          style={ inputHeight }
          placeholder="Share knowledge"
          onKeyUp={ this.props.keyUpInteraction }
        ></textarea>

        <button className="c-messenger__submit" onClick={ () => this.sendMessage() }>

        </button>

    );
  }
}

const mapStateToProps = (state, ownProps) => state[config.stateName];

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    sendMessage: (chatId, message) => dispatch(actions.chats.sendMessage(chatId, message)),
  };
};

const MessengerConnect = connect(mapStateToProps, mapDispatchToProps)(Messenger);

export default MessengerConnect;

import React from 'react';
import { connect } from 'react-redux';

import config from '../config'
import actions from '../actions';

class Messenger extends React.Component {

  sendMessage() {
    const message = this.messageInput.value;
    this.props.sendMessage(this.props.chatId, message);
    this.messageInput.value = '';
  }

  render() {
    let messengerAttachmentClass = `c-messenger__attachment ${ this.props.showAttachment ? 'state-active' : '' }`;

    let inputHeight = { height: `${ this.props.messengerHeight }px` };

    return (

        <button className={ messengerAttachmentClass } onClick={ this.props.toggleAttachment }>

        </button>

        <textarea ref={ input => this.messageInput = input }
          style={ inputHeight }
          placeholder="Share knowledge"
          onKeyUp={ this.props.keyUpInteraction }
        ></textarea>

        <button className="c-messenger__submit" onClick={ () => this.sendMessage() }>

        </button>

    );
  }
}

const mapStateToProps = (state, ownProps) => state[config.stateName];

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    sendMessage: (chatId, message) => dispatch(actions.chats.sendMessage(chatId, message)),
  };
};

const MessengerConnect = connect(mapStateToProps, mapDispatchToProps)(Messenger);

export default MessengerConnect;

Reset message input after sending a message.


import React from 'react'
import styles from './input-styles'

export default ({ className, errors, onChange, onCommit, property, value }) => (
  <input
    className={`${className} ${styles.input} ct-number-input`}
    data-tip={errors}
    disabled={property.disabled}
    id={property.id}
    onBlur={() => onCommit()}
    onChange={e => onChange(e.target.valueAsNumber)}
    title={property.title}
    type='number'
    value={value} />
)

import React from 'react'
import styles from './input-styles'

export default ({ className, errors, onChange, onCommit, property, value }) => (
  <input
    className={`${className} ${styles.input} ct-number-input`}
    data-tip={errors}
    disabled={property.disabled}
    id={property.id}
    onBlur={() => onCommit()}
    onChange={e => onChange(e.target.value)}
    title={property.title}
    type='number'
    value={value} />
)

Fix bug which stopped users from submitting decimal values in number fields


import React from 'react';
import { connect } from 'react-redux';

import { clearNotices } from 'lib/actions/general';
import { doAuthWithPassword, parseAuthToken, getProfile } from 'lib/actions/auth';
import Layout from 'components/layout';
import LogInBox from 'components/log-in-box';

class App extends React.Component {
  componentWillMount() {
    if ( ! this.props.auth.token || this.props.auth.expiredToken ) {
      this.props.parseAuthToken();
    }
  }

  componentDidMount() {
    this.getUserInfo( this.props );
  }

  componentDidUpdate() {
    this.getUserInfo( this.props );
  }

  getUserInfo( props ) {
    if ( props.auth.token && ! props.auth.user && ! props.auth.expiredToken && ! props.errors.length ) {
      props.getProfile();
    }
  }

  render() {
    if ( this.props.auth.token ) {
      return ( <Layout children={ this.props.children } /> );
    }
    return ( <LogInBox showAuth={ this.props.doAuthWithPassword } errors={ this.props.errors } onClearNotices={ this.props.clearNotices } /> );
  }
}

App.propTypes = {
  auth: React.PropTypes.object.isRequired,
};

function mapStateToProps( state ) {
  const { auth, notices } = state;
  return { auth, errors: notices.errors };
}

export default connect( mapStateToProps, { doAuthWithPassword, getProfile, parseAuthToken, clearNotices } )( App );

import React from 'react';
import { connect } from 'react-redux';

import { clearNotices } from 'lib/actions/general';
import { doAuthWithPassword, parseAuthToken, getProfile } from 'lib/actions/auth';
import Layout from 'components/layout';
import LogInBox from 'components/log-in-box';

class App extends React.Component {
  componentWillMount() {
    if ( ! this.props.auth.token || this.props.auth.expiredToken ) {
      this.props.parseAuthToken();
    }
  }

  componentDidMount() {
    this.getUserInfo( this.props );
  }

  componentDidUpdate() {
    this.getUserInfo( this.props );
  }

  getUserInfo( props ) {
    if ( props.auth.token && ! props.auth.user && ! props.auth.expiredToken && ! props.errors.length ) {
      // FIXME: the token is always invalid for some reason
      // props.getProfile();
    }
  }

  render() {
    if ( this.props.auth.token ) {
      return ( <Layout children={ this.props.children } /> );
    }
    return ( <LogInBox showAuth={ this.props.doAuthWithPassword } errors={ this.props.errors } onClearNotices={ this.props.clearNotices } /> );
  }
}

App.propTypes = {
  auth: React.PropTypes.object.isRequired,
};

function mapStateToProps( state ) {
  const { auth, notices } = state;
  return { auth, errors: notices.errors };
}

export default connect( mapStateToProps, { doAuthWithPassword, getProfile, parseAuthToken, clearNotices } )( App );

Disable fetching profile for now


'use strict';

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

// Retrieve `rpcDef.args.populate` using GraphQL selection sets
const addPopulate = function ({ args, args: { select }, commandName }) {
  if (!commandName.startsWith('find_')) { return args; }

  const selects = select
    .split(',')
    .map(selectA => selectA.replace(PARENT_SELECT_REGEXP, ''))
    .filter(selectA => selectA !== '');
  const selectsA = uniq(selects);
  const populate = selectsA.join(',');

  const argsA = { ...args, populate };
  return argsA;
};

// Keep only parent path, e.g. 'parent.child' -> 'parent'
const PARENT_SELECT_REGEXP = /\.?[^.]+$/;

module.exports = {
  addPopulate,
};

'use strict';

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

// Retrieve `rpcDef.args.populate` using GraphQL selection sets
const addPopulate = function ({ args, args: { select }, commandName }) {
  if (!commandName.startsWith('find_')) { return args; }

  const selects = select
    .split(',')
    .map(selectA => selectA.replace(PARENT_SELECT_REGEXP, ''))
    .filter(selectA => selectA !== '');
  const selectsA = uniq(selects);

  if (selectsA.length === 0) { return args; }

  const populate = selectsA.join(',');

  const argsA = { ...args, populate };
  return argsA;
};

// Keep only parent path, e.g. 'parent.child' -> 'parent'
const PARENT_SELECT_REGEXP = /\.?[^.]+$/;

module.exports = {
  addPopulate,
};

Fix GraphQL queries with no nesting


var React = require("react");
var ReactCSSTransitionGroup = require("react-addons-css-transition-group");

var Navigation = require("../component/Navigation");

var defaultState = {
  transitionName: "in-from-right",
  transitionDuration: 1000,
};

class PageLayout extends React.Component {
  constructor (props) {
    super(props);
    this.state = Object.assign({}, defaultState);
    this.setTransitionName.bind(this);
  }

  render () {
    var { pathname } = this.props.location;
    var self = this;
    return (
      <div>
        <Navigation/>
        <ReactCSSTransitionGroup transitionName={ this.state.transitionName } transitionEnterTimeout={ this.state.transitionDuration } transitionLeaveTimeout={ this.state.transitionDuration } component="div" className="animation-wrapper">
          { React.cloneElement(this.props.children, { key: pathname, setTransitionName: (transitionName) => {
            self.setTransitionName(transitionName);
          } }) }
        </ReactCSSTransitionGroup>
      </div>
    );
  }

  setTransitionName(transitionName) {
    this.setState({transitionName});
    // revert animation to default when done
    setTimeout(() => {
      this.setState({transitionName: defaultState.transitionName});
    }, this.state.transitionDuration);
  }
}

export default PageLayout;

var React = require("react");
var ReactCSSTransitionGroup = require("react-addons-css-transition-group");

var Navigation = require("../component/Navigation");

var defaultState = {
  transitionName: "in-from-right",
  transitionDuration: 1000,
};

class PageLayout extends React.Component {
  constructor (props) {
    super(props);
    this.state = Object.assign({}, defaultState);
    this.setTransitionName.bind(this);
  }

  render () {
    var { pathname } = this.props.location;
    var self = this;
    return (
      <div>
        <Navigation/>
        <ReactCSSTransitionGroup transitionName={ this.state.transitionName } transitionEnterTimeout={ this.state.transitionDuration } transitionLeaveTimeout={ this.state.transitionDuration } component="div" className="animation-wrapper">
          { React.cloneElement(this.props.children, { key: pathname, setTransitionName: (transitionName) => {
            self.setTransitionName(transitionName);
          } }) }
        </ReactCSSTransitionGroup>
      </div>
    );
  }

  setTransitionName(transitionName) {
    this.setState({transitionName});
    // revert animation to default for next request
    setTimeout(() => {
      this.setState({transitionName: defaultState.transitionName});
    }, 0);
  }
}

export default PageLayout;

Revert to default transition next frame instead of anim duration.


'use strict';
module.exports = (function() {
  var PI = Math.PI;

  let area = function(r) {
    return PI * r * r;
  };

  let circumference = function(r) {
    return 2 * PI * r;
  };

}());

'use strict';
module.exports = (function() {
  var PI = Math.PI;

  let area = function(r) {
    return PI * r * r;
  };

  let circumference = function(r) {
    return 2 * PI * r;
  };

  return {
    area: area,
    circumference: circumference
  };
}());

Modify sample module for the unit test


import Ember from 'ember';

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

var testNotification = {options: {type: 'error', twitch: true}};

moduleForComponent('growl-instance', 'Growl Instance');

test('assert that the element class exists', function() {
  expect(1);

  ok(this.subject().classNames.indexOf('growl-instance') > -1, 'CSS class exists');
});

test('assert that the notification type is reflected as a classname', function() {
  expect(1);
  var subject = this.subject();

  subject.set('notification', testNotification);
  equal(subject._classStringForProperty('type'), 'error', 'The instance has a class of error');
});

test('assert that the instance will close when clicked', function() {
  expect(2);

  var subject = this.subject();
  subject.sendAction = function(name, value) {
    equal(name, 'action', 'The parent action was called');
  };

  subject.click();

  // now override destroyAlert to make sure it is what called the action
  subject.destroyAlert = function() {
    ok(true, 'The instance was closed');
  };

  subject.click();
});

import Ember from 'ember';

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

var testNotification = {options: {type: 'error', twitch: true}};

moduleForComponent('growl-instance', 'Growl Instance');

test('assert that the element class exists', function() {
  expect(1);

  ok(this.subject().classNames.indexOf('growl-instance') > -1, 'CSS class exists');
});

test('assert that the notification type is reflected as a classname', function() {
  expect(1);
  var subject = this.subject();

  subject.set('notification', testNotification);
  equal(subject._classStringForProperty('type'), 'error', 'The instance has a class of error');
});

test('assert that the instance will close when clicked', function() {
  expect(3);

  var subject = this.subject();
  subject.set('notification', testNotification);
  subject.sendAction = function(name, value) {
    equal(name, 'action', 'The parent action was called');
    equal(value, testNotification, 'The notification is passed to the parent action');
  };

  subject.click();

  // now override destroyAlert to make sure it is what called the action
  subject.destroyAlert = function() {
    ok(true, 'The instance was closed');
  };

  subject.click();
});

Test the value passed to the growl manager component


import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';

export default function startApp(attrs) {
  let application;

  let attributes = Ember.assign({}, config.APP);
  attributes = Ember.assign(attributes, attrs); // use defaults, but you can override;

  Ember.run(() => {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}

import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';

export default function startApp(attrs) {
  let application;

  let attributes = Ember.merge({}, config.APP);
  attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;

  Ember.run(() => {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}

Revert to Ember.merge so 1.13 tests pass


var profile = require('../profile.js');

var ctx = window.contextVars;

new profile.Names('#names', ctx.nameUrls, ['edit']);
new profile.Social('#social', ctx.socialUrls, ['edit']);
new profile.Jobs('#jobs', ctx.jobsUrls, ['edit']);
new profile.Schools('#schools', ctx.schoolsUrls, ['edit']);

// Reusable function to fix affix widths to columns.
function fixAffixWidth() {
    $('.affix, .affix-top, .affix-bottom').each(function (){
        var el = $(this);
        var colsize = el.parent('.affix-parent').width();
        el.outerWidth(colsize);
    });
}

$(document).ready(function() {

    $(window).resize(function (){ fixAffixWidth(); });
    $('.profile-settings-page .panel').on('affixed.bs.affix', function(){ fixAffixWidth(); });

});

Add affix to profile page


function PPTennisTournament(name) {
  this.superclass(name);
  this.class = PPTennisTournament.className();
}

// This must be in between the constructor definition and
// new method definitions in order for it to work.
PPUtils.extend (PPTennisTournament, PPTournament);

PPTennisTournament.className = function () {
 return "PPTennisTournament";
}

PPTennisTournament.labelName = function () {
 return "Tennis";
}

function PPTennisTournament(name) {
  PPTennisTournament.superclass.call(this, name);
  this.class = PPTennisTournament.className();
}

// This must be in between the constructor definition and
// new method definitions in order for it to work.
PPUtils.extend (PPTennisTournament, PPTournament);

PPTennisTournament.className = function () {
 return "PPTennisTournament";
}

PPTennisTournament.labelName = function () {
 return "Tennis";
}

Implement new way to call superclass


var five = require('johnny-five');
var ChipIO = require('../index'); // or require('chip-io');

var board = new five.Board({
  io: new ChipIO()
});

board.on('ready', function() {
  var thermometer = new five.Thermometer({
    controller: ChipIO.Controllers.INTERNAL_TEMP
  });

  thermometer.on('change', function(data) {
    console.log('Internal temperature is ' + data.celsius.toFixed(2) + '°C');
  });
});

var five = require('johnny-five');
var chipio = require('../index'); // or require('chip-io');

var board = new five.Board({
  io: new chipio()
});

board.on('ready', function() {
  var thermometer = new chipio.InternalTemperature();

  thermometer.on('change', function(data) {
    console.log('Internal temperature is ' + data.celsius.toFixed(2) + '°C');
  });
});

Update internal temperature example to use chipio.InternalTemperature


require.paths.unshift('lib')
require.paths.unshift('deps/jsdom/lib')
var  HTML5 = require('html5'),
    Script = process.binding('evals').Script,
       sys = require('sys'),
        fs = require('fs'),
     jsdom = require('jsdom'),
    window = jsdom.createWindow(null, null, {parser: HTML5});

var parser = new HTML5.Parser({document: window.document});

var inputfile = fs.readFileSync('doc/jquery-example.html');
parser.parse(inputfile);

jsdom.jQueryify(window, 'deps/jquery/dist/jquery.js', function(window, jquery) {
	Script.runInNewContext('jQuery("p").append("<b>Hi!</b>")', window);
	sys.puts(window.document.innerHTML);

});

require.paths.unshift('lib')
require.paths.unshift('deps/jsdom/lib')
var  HTML5 = require('html5'),
    Script = process.binding('evals').Script,
       sys = require('sys'),
        fs = require('fs'),
     jsdom = require('jsdom'),
    window = jsdom.createWindow(null, null, {parser: HTML5, document: new jsdom.dom.level1.core.Document()});

window.document.removeChild(window.document.childNodes[0]); // Clear the stub document that jsdom gives us

var parser = new HTML5.Parser({document: window.document});

var inputfile = fs.readFileSync('doc/jquery-example.html');
parser.parse(inputfile);

jsdom.jQueryify(window, 'deps/jquery/dist/jquery.js', function(window, jquery) {
	Script.runInNewContext('jQuery("p").append("<b>Hi!</b>")', window);
	sys.puts(window.document.innerHTML);

});

Clear the jsdom document created in createWindow


module.exports = function(config) {
  config.set({
    browsers     : ['Chrome', 'Firefox'],
    frameworks   : ['jasmine'],
    reporters    : ['mocha'],
    singleRun    : true,
    preprocessors: {'./karma-test-runner.js': ['webpack']},
    files        : [{pattern: './karma-test-runner.js', watched: false}],
    webpack      : require('./webpack.test.config.js'),
    webpackServer: {noInfo: true}
  });
};

module.exports = function(config) {
  config.set({
    browsers     : ['Firefox'],
    frameworks   : ['jasmine'],
    reporters    : ['mocha'],
    singleRun    : true,
    preprocessors: {'./karma-test-runner.js': ['webpack']},
    files        : [{pattern: './karma-test-runner.js', watched: false}],
    webpack      : require('./webpack.test.config.js'),
    webpackServer: {noInfo: true}
  });
};

Disable Chrome in karma as it is not available in travis


const About = () => {
  return (

Velkommen til Online, linjeforeningen for informatikkstudenter ved NTNU.

Det er vi som sørger for at studietiden blir den beste tiden i ditt liv! Vi i Online arrangerer utflukter, turer, fester, holder kurs og bedriftspresentasjoner gjennom hele året.

  );
};

export default About;

Add class to header description


'use strict';

eventsApp.directive('mySample', function($compile) {
	return {
		restrict: 'E',
		link: function(scope, element, attrs, controller) {
			var markup = "<input type='text' ng-model='sampleData' /> {{sampleData}}<br/>";
			angular.element(element).html($compile(markup)(scope));
		}
	};
});

'use strict';

eventsApp.directive('mySample', function($compile) {
	return {
		restrict: 'E',
		template: "<input type='text' ng-model='sampleData' /> {{sampleData}}
"
		// link: function(scope, element, attrs, controller) {
		// 	var markup = "<input type='text' ng-model='sampleData' /> {{sampleData}}
";
		// 	angular.element(element).html($compile(markup)(scope));
		// }
	};
});

Change my-sample directive (using template property)


export const testSiteNotification = {
	id: 'test-notification-id',
	title: 'Test notification title',
	content: 'Test notification content',
	dismissible: true,
	dismiss_label: 'test dismiss site notification',
};

export const testSiteNotification = {
	id: 'test-notification-id',
	title: 'Test notification title',
	content: 'Test notification content',
	ctaURL: '',
	ctaLabel: '',
	ctaTarget: '',
	dismissible: true,
	dismissLabel: 'test dismiss site notification',
	learnMoreURL: '',
	learnMoreLabel: '',
};

Update test site notification to use remote format.


const compressor = require('node-minify');
const { readdirSync } = require('fs');
const { basename, join } = require('path');

const resources = (...dir) => join(...[__dirname, 'src', 'resources'].concat(dir));

const Logger = require(resources('js', 'Logger'));

function minifyAssets() {
	const cssPath = resources('css');
	const cssFiles = readdirSync(cssPath).filter(f => !f.endsWith('.min.css'));

	const jsPath = resources('js');
	const jsFiles = readdirSync(jsPath).filter(f => !f.endsWith('.min.js'));

	jsFiles.splice(0, 1); // Remove eslintrc

	cssFiles.forEach(fileName => {
		compressor.minify({
			compressor: 'clean-css',
			input: `${cssPath}${fileName}`,
			output: `${cssPath}${basename(fileName, '.css')}.min.css`
		});
	});

	Logger.info('CSS minification complete.');

	jsFiles.forEach(fileName => {
		compressor.minify({
			compressor: 'uglify-es',
			input: `${jsPath}${fileName}`,
			output: `${jsPath}${basename(fileName, '.js')}.min.js`
		});
	});

	Logger.info('JS minification complete.');
}

module.exports = minifyAssets;

const compressor = require('node-minify');
const { readdirSync } = require('fs');
const { basename, join } = require('path');

const resources = (...dir) => join(...[__dirname, 'src', 'resources'].concat(dir));

const Logger = require(resources('js', 'Logger'));

function minifyAssets() {
	const cssPath = resources('css');
	const cssFiles = readdirSync(cssPath).filter(f => !f.endsWith('.min.css'));

	const jsPath = resources('js');
	const jsFiles = readdirSync(jsPath).filter(f => !f.endsWith('.min.js'));

	jsFiles.splice(0, 1); // Remove eslintrc

	cssFiles.forEach(fileName => {
		compressor.minify({
			compressor: 'clean-css',
			input: join(cssPath, fileName),
			output: join(cssPath, `${basename(fileName, '.css')}.min.css`),
		});
	});

	Logger.info('CSS minification complete.');

	jsFiles.forEach(fileName => {
		compressor.minify({
			compressor: 'uglify-es',
			input: join(jsPath, fileName),
			output: join(jsPath, `${basename(fileName, '.js')}.min.js`),
		});
	});

	Logger.info('JS minification complete.');
}

module.exports = minifyAssets;

Change string concat to join() call


/* jslint node: true */
const fs = require('fs')
const path = require('path')
const sequelizeNoUpdateAttributes = require('sequelize-noupdate-attributes')
const Sequelize = require('sequelize')
const sequelize = new Sequelize('database', 'username', 'password', {
  dialect: 'sqlite',
  storage: 'data/juiceshop.sqlite',
  logging: false,
  retry: {
    max: 10
  }
})
sequelizeNoUpdateAttributes(sequelize)
const db = {}

fs.readdirSync(__dirname)
  .filter(file => (file.indexOf('.') !== 0) && (file !== 'index.js'))
  .forEach(file => {
    const model = sequelize['import'](path.join(__dirname, file))
    db[model.name] = model
  })

Object.keys(db).forEach(modelName => {
  if ('associate' in db[modelName]) {
    db[modelName].associate(db)
  }
})

db.sequelize = sequelize
db.Sequelize = Sequelize

module.exports = db

/* jslint node: true */
const fs = require('fs')
const path = require('path')
const sequelizeNoUpdateAttributes = require('sequelize-noupdate-attributes')
const Sequelize = require('sequelize')
const sequelize = new Sequelize('database', 'username', 'password', {
  dialect: 'sqlite',
  storage: 'data/juiceshop.sqlite',
  logging: false
})
sequelizeNoUpdateAttributes(sequelize)
const db = {}

fs.readdirSync(__dirname)
  .filter(file => (file.indexOf('.') !== 0) && (file !== 'index.js'))
  .forEach(file => {
    const model = sequelize['import'](path.join(__dirname, file))
    db[model.name] = model
  })

Object.keys(db).forEach(modelName => {
  if ('associate' in db[modelName]) {
    db[modelName].associate(db)
  }
})

db.sequelize = sequelize
db.Sequelize = Sequelize

module.exports = db

Revert "Retry queries up to 10 times on SQLite"


/* global $ */
/* global requirejs */

'use strict';

var request = require('request');
var ipc = require('electron-safe-ipc/guest');
var pjson = require('./package.json');

exports.init = function() {
	ipc.on('checkForUpdates', exports.checkForUpdates);
}

exports.checkForUpdates = function(bSilentCheck) {
	try {
		request(pjson.config.versionCheckURL, function (error, response, body) {
			if (!error && response.statusCode == 200) {
				var json = JSON.parse(body);
				if(json.version > pjson.version) {
					$('#modalUpdateAvailable').modal('show');
				} else if(!bSilentCheck) {
					//$('#modalNoUpdateAvailable').modal('show');
					$('#modalUpdateAvailable').modal('show');
				}
			} else {
				console.log(error.toString());
			}
		})
	} catch(error) {
		console.log(error.toString());
	}
}

/* global $ */
/* global requirejs */

'use strict';

var request = require('request');
var ipc = require('electron-safe-ipc/guest');
var pjson = require('./package.json');

exports.init = function() {
	ipc.on('checkForUpdates', exports.checkForUpdates);
	exports.checkForUpdates(true);
}

exports.checkForUpdates = function(bSilentCheck) {
	try {
		request(pjson.config.versionCheckURL, function (error, response, body) {
			if (!error && response.statusCode == 200) {
				var json = JSON.parse(body);
				if(json.version > pjson.version) {
					$('#modalUpdateAvailable').modal('show');
				} else if(!bSilentCheck) {
					$('#modalNoUpdateAvailable').modal('show');
				}
			} else {
				console.log(error.toString());
			}
		})
	} catch(error) {
		console.log(error.toString());
	}
}

Check for updates on start.


app.factory('stocks', ['$http', function($http) {
	var endPoint = 'https://query.yahooapis.com/v1/public/yql?q=',
			symbols = [
				"W",
				"FIT"
			],
			query = "select * from yahoo.finance.quotes where symbol IN(\"" + symbols.join('","') + "\")",
			args = "&format=json&env=http://datatables.org/alltables.env",
			url = endPoint + encodeURIComponent(query) + args;

	// return $http.get(url)
	// .success(function(data) {
	// 	return data;
	// })
	// .error(function(data) {
	// 	return data;
	// });

	// Used for no internet access only
	return $http.get('http://localhost:8000/app/components/stocks.json');
}]);

app.factory('stocks', ['$http', function($http) {
	var endPoint = 'https://query.yahooapis.com/v1/public/yql?q=',
			symbols = [
				"W",
				"FIT"
			],
			query = "select * from yahoo.finance.quotes where symbol IN(\"" + symbols.join('","') + "\")",
			args = "&format=json&env=http://datatables.org/alltables.env",
			url = endPoint + encodeURIComponent(query) + args;

	return $http.get('http://localhost:8000/app/components/stocks.json');

	return $http.get(url)
	.success(function(data) {
		return data;
	})
	.error(function(data) {
		return data;
	});
}]);

Rearrange temp support for no internet


var Promise = require('es6-promise').Promise;
var engine = require('static-engine');
var compose = require('static-compose');

module.exports = function (name, plugins) {

    var composed = compose(plugins);

    return function (pages) {

        var promises = pages.map(function (page) {

            return new Promise(function(resolve, reject){

                var current_pages = page[name] && Array.isArray(page[name]) ? page[name] : [];

                composed(current_pages).then(function (pages) {

                    page[name] = pages;

                    resolve(page);
                });
            });
        });

        return Promise.all(promises).then(function(results){

            var pages = [];

            Array.prototype.push.apply(pages, results);

            return Promise.resolve(pages);
        });
    };
};

var Promise = require('es6-promise').Promise;
var engine = require('static-engine');
var compose = require('static-compose');

module.exports = function (name, plugins) {

    if(!Array.isArray(plugins) || arguments.length > 2) {

        plugins = [].slice.call(arguments, 1);
    }

    var composed = compose(plugins);

    return function (pages) {

        var promises = pages.map(function (page) {

            return new Promise(function(resolve, reject){

                var current_pages = page[name] && Array.isArray(page[name]) ? page[name] : [];

                composed(current_pages).then(function (pages) {

                    page[name] = pages;

                    resolve(page);
                });
            });
        });

        return Promise.all(promises).then(function(results){

            var pages = [];

            Array.prototype.push.apply(pages, results);

            return Promise.resolve(pages);
        });
    };
};

Allow for a single array or multiple arguments