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

// import { matchPattern, formatPattern, getParams } from 'react-router/lib/PatternUtils.js';

const reg = /(\/.+?)(?:#|\?|$)/;

export function getAvailableRoute (existingRoutes, checkPathname) {
  let candidateRootKey = undefined;
  if (existingRoutes && existingRoutes.length > 0) {
    if (checkPathname === '/' || checkPathname === '/structor-deskpage' || checkPathname === '/structor-deskpage/') {
      candidateRootKey = existingRoutes[0];
    } else {
      const match = reg.exec(checkPathname);
      if (match && match.length > 0) {
        candidateRootKey = existingRoutes.find(i => match[1].indexOf(i) >= 0);
      }
    }
  }
  if (!candidateRootKey) {
    console.error('Path name ' + checkPathname + ' was not found in project model.');
  }
  return candidateRootKey;
}

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

// import { matchPattern, formatPattern, getParams } from 'react-router/lib/PatternUtils.js';

const reg = /(\/.+?)(?:#|\?|$)/;

export function getAvailableRoute (existingRoutes, checkPathname) {
  let candidateRootKey = undefined;
  if (existingRoutes && existingRoutes.length > 0) {
    if (checkPathname === '/' || checkPathname === '/structor-deskpage' || checkPathname === '/structor-deskpage/') {
      candidateRootKey = existingRoutes[0];
    } else {
      const match = reg.exec(checkPathname);
      if (match && match.length > 0) {
        candidateRootKey = existingRoutes.find(i => match[1] === i);
      }
    }
  }
  if (!candidateRootKey) {
    console.error('Path name ' + checkPathname + ' was not found in project model.');
  }
  return candidateRootKey;
}

Fix finding page by route


import api from '../api';
import style from './style';

export default () => {
    let map = new google.maps.Map(document.getElementsByClassName('map')[0], {
        center: {lat: -34.397, lng: 150.644},
        zoom: 3,
        disableDefaultUI: true,
        scrollwheel: false,
        styles: style,
    });

    api.getDirections(locations.from, locations.to)
        .then(result => {
            let path = google.maps.geometry.encoding.decodePath(result);

            new google.maps.Polyline({
                map: map,
                path: path,
                strokeColor: "#d80000",
                strokeWeight: 7,
            });

            var center = new google.maps.LatLngBounds();

            for (var i = 0; i < path.length; i++) {
                center.extend(path[i]);
            }

            $('.map').show();
            $('.map-loading').hide();
            google.maps.event.trigger(map, 'resize');

            map.fitBounds(center);
            map.setZoom(5);
        })
        .catch(() => {
            $('.map-container').hide();
        });
};

import api from '../api';
import style from './style';

export default () => {
    let map = new google.maps.Map(document.getElementsByClassName('map')[0], {
        center: {lat: -34.397, lng: 150.644},
        zoom: 3,
        disableDefaultUI: true,
        disableDoubleClickZoom: true,
        draggable: false,
        scrollwheel: false,
        styles: style,
    });

    api.getDirections(locations.from, locations.to)
        .then(result => {
            let path = google.maps.geometry.encoding.decodePath(result);

            new google.maps.Polyline({
                clickable: false,
                map: map,
                path: path,
                strokeColor: "#d80000",
                strokeWeight: 7,
            });

            var center = new google.maps.LatLngBounds();

            for (var i = 0; i < path.length; i++) {
                center.extend(path[i]);
            }

            $('.map').show();
            $('.map-loading').hide();
            google.maps.event.trigger(map, 'resize');

            map.fitBounds(center);
            map.setZoom(5);
        })
        .catch(() => {
            $('.map-container').hide();
        });
};

Disable more interaction with the map


var express = require('express'),
    router  = express.Router();

module.exports = function (app) {
  app.use('/', router);
};

router.get('/', function (req, res) {
    res.render('../views/index');
});

Format whitespace to tab indentation.


import { getHostAddress, isSameHostAddress } from './helpers';

export function getCurrentHost (hosts) {
  const currentHostAddress = getHostAddress();
  const hostId = hosts.filter(hostId => currentHostAddress === hosts[hostId].address);
  return hostId ? hosts[hostId] : undefined;
}

import { getHostAddress, isSameHostAddress } from './helpers';

export function getCurrentHost (hosts) {
  const currentHostAddress = getHostAddress();
  const hostId = Object.getOwnPropertyNames(hosts).filter(hostId => currentHostAddress === hosts[hostId].address);
  return hostId ? hosts[hostId] : undefined;
}

Fix incorrect use of filter()


//jshint esversion: 6
Package.describe({
    name: 'elmarti:video-chat',
    version: '2.1.1',
    summary: 'Simple WebRTC Video Chat for your app.',
    git: 'https://github.com/elmarti/meteor-video-chat',
    documentation: 'README.md'
});

Package.onUse(api => {

    Npm.depends({
        "rtcfly": "0.1.5"
    });

    api.versionsFrom('1.5');
    api.use('ecmascript');
    api.use("rocketchat:streamer@0.5.0");
    api.use("mizzao:user-status@0.6.6");
    api.addFiles(['lib/index.js'], "client");
    api.addFiles(['lib/publish.js'], "server");
    api.addFiles(['lib/index.server.js'], 'server');
    api.mainModule('lib/index.js', 'client');
});

//jshint esversion: 6
Package.describe({
    name: 'elmarti:video-chat',
    version: '2.1.1',
    summary: 'Simple WebRTC Video Chat for your app.',
    git: 'https://github.com/elmarti/meteor-video-chat',
    documentation: 'README.md'
});

Package.onUse(api => {

    Npm.depends({
        "rtcfly": "0.1.5"
    });

    api.versionsFrom('1.5');
    api.use('ecmascript');
    api.use("rocketchat:streamer@0.6.1");
    api.use("mizzao:user-status@0.6.7");
    api.addFiles(['lib/index.js'], "client");
    api.addFiles(['lib/publish.js'], "server");
    api.addFiles(['lib/index.server.js'], 'server');
    api.mainModule('lib/index.js', 'client');
});

Update dependencies for Meteor 1.6.1


const mongoose = require('mongoose');

const encryption = require('./../utilities/encryption');

let userSchema = mongoose.Schema( {
        email: {type: String, required: true, unique: true},
        passwordHash: {type: String, required: true},
        fullName: {type: String, required: true},
        articles: { type: [mongoose.Schema.Types.ObjectId], default: []},

        salt: {type: String, required: true},
    }
);

userSchema.method ({
    authenticate: function (password) {
        let inputPasswordHash = encryption.hashPassword(password, this.salt);
        let isSamePasswordHash = inputPasswordHash === this.passwordHash;

        return isSamePasswordHash;
    }});

const User = mongoose.model('User', userSchema);

module.exports = User;

const mongoose = require('mongoose');
const Role = mongoose.model('Role');
const ObjectId = mongoose.Schema.Types.ObjectId;
const encryption = require('./../utilities/encryption');

let userSchema = mongoose.Schema( {
        email: {type: String, required: true, unique: true},
        passwordHash: {type: String, required: true},
        fullName: {type: String, required: true},
        articles: [{ type: ObjectId, ref: 'Article'}],
        maleOrFemale:{type: String, required: true},
        birth:{type:String, required: true},
        roles: [{type: ObjectId, ref: 'Role'}],
        salt: {type: String, required: true},
    }
);

userSchema.method ({
    authenticate: function (password) {
        let inputPasswordHash = encryption.hashPassword(password, this.salt);
        let isSamePasswordHash = inputPasswordHash === this.passwordHash;

        return isSamePasswordHash;
    },
    isAuthor: function(article) {
        if (!article){
            return false;
        }

        let isAuthor = article.author.equals(this.id);

        return isAuthor;
    },
    isInRole: function (roleName) {
        return Role.findOne({name: roleName}).then(role=>{
            if(!role){
                return false;
            }

            let isInRole = this.roles.indexOf(role.id) !==-1;
            return isInRole;
        })

    }
});

const User = mongoose.model('User', userSchema);

module.exports = User;

module.exports.initialize=()=>{
  let email = 'admin@mysite.com';
  User.findOne({email: email}).then(admin => {
      if (admin) {
          return;
      }

      Role.findOne({name: 'Admin'}).then(role => {
          if(!role){
              return;
          }
          let salt = encryption.generateSalt();
          let passwordHash = encryption.hashPassword('123456', salt);

          let adminUser = {
              email: email,
              fullName: 'Admin',
              roles: [role.id],
              articles: [],
              salt: salt,
              passwordHash: passwordHash

          };

          User.create(adminUser).then(user=>{
              role.users.push(user.id);
              role.save();
          });
      })
  })
};

Implement user/role functionality and edit


var hoverZoomPlugins = hoverZoomPlugins || [];
hoverZoomPlugins.push({
    name:'photo.net',
    version:'0.1',
    prepareImgLinks:function (callback) {
        var res = [];

        hoverZoom.urlReplace(res,
            'img[src*="photo.net"]',
            ['thumbs.', '-sm', '-md'],
            ['gallery.', '-lg', '-lg']
        );
        callback($(res));
    }
});

var hoverZoomPlugins = hoverZoomPlugins || [];
hoverZoomPlugins.push({
    name:'photo.net',
    version:'0.2',
    prepareImgLinks:function (callback) {
        var res = [];

        hoverZoom.urlReplace(res,
            'img[src]',
            ['thumbs.', '-sm', '-md', '-lg'],
            ['gallery.', '-orig', '-orig', '-orig']
        );

        hoverZoom.urlReplace(res,
            'img[src]',
            /\?.*$/,
            ''
        );

        callback($(res), this.name);
    }
});

Update for plug-in : photo.net


'use strict';

var mongoose = require('mongoose');
var slack = require('./slack.js');

var Rejection = mongoose.model('Rejection');

exports.help = help;
exports.reject = reject;

function help(args, message) {
  var channel = slack.getChannelGroupOrDMByID(message.channel);
  channel.send('I\'m codybot! \n\n\
    Usage: `@codybot: <command>`\n\n\
    Commands: \n\
    reject <comanyName> - Records that you were rejected from that company. \n\
    help - Prints this prompt \
    ');
}

function reject(args, message) {
  var channel = slack.getChannelGroupOrDMByID(message.channel);

  var companyName = args[0];
  var rejection = new Rejection({
    companyName: companyName,
    user: message.user,
    timestamp: { type: Date, default: Date.now }
  });

  Rejection.find({
    companyName: companyName,
    user: message.user
  }).exec(function (err, rejections) {
    if(rejections.length > 0) {
      channel.send('This information is already in my database. Thanks for reminding me though.');
    } else {
      rejection.save(function (err, rejection) {
        if (err) {
          return console.error(err);
        }

        channel.send('Sounds like you\'re too awesome for ' + rejection.companyName + ' anyways!');
        channel.send('/giphy celebrate');
      });
    }
  });
}

'use strict';

var mongoose = require('mongoose');
var slack = require('./slack.js');

var Rejection = mongoose.model('Rejection');

exports.help = help;
exports.reject = reject;

function help(args, message) {
  var channel = slack.getChannelGroupOrDMByID(message.channel);
  channel.send('I\'m codybot! \n\n\
    Usage: `@codybot: <command>`\n\n\
    Commands: \n\
    reject <comanyName> - Records that you were rejected from that company. \n\
    help - Prints this prompt \
    ');
}

function reject(args, message) {
  var channel = slack.getChannelGroupOrDMByID(message.channel);

  var companyName = args[0];
  var rejection = new Rejection({
    companyName: companyName,
    user: message.user,
    timestamp: { type: Date, default: Date.now }
  });

  Rejection.find({
    companyName: companyName,
    user: message.user
  }).exec(function (err, rejections) {
    if(rejections.length > 0) {
      channel.send('This information is already in my database. Thanks for reminding me though.');
    } else {
      rejection.save(function (err, rejection) {
        if (err) {
          return console.error(err);
        }

        channel.send('Sounds like you\'re too awesome for ' + rejection.companyName + ' anyways!');
      });
    }
  });
}

Remove giphy since it doesn't work


'use strict'

const { env, platform } = process

module.exports = {
  extends: [
    'eslint:recommended',
    'eslint-config-airbnb-base',
    'plugin:prettier/recommended',
  ],

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

  rules: {
    // TODO FIXME turn off temporary, to make eslint pass
    'class-methods-use-this': 'off',
    'consistent-return': 'off',
    'no-console': 'off',
    'no-multi-assign': 'off',
    'no-param-reassign': 'off',
    'no-restricted-syntax': 'off',
    'no-shadow': 'off',
    'no-underscore-dangle': 'off',
    'no-use-before-define': 'off',
    radix: 'off',
    strict: 'off',
    // workaround for git + eslint line ending issue on Travis for Windows OS:
    // https://travis-ci.community/t/files-in-checkout-have-eol-changed-from-lf-to-crlf/349/2
    ...(env.TRAVIS &&
      platform === 'win32' && {
        ['linebreak-style']: 'off',
      }),
  },
}

'use strict'

const { env, platform } = process

module.exports = {
  extends: [
    'eslint:recommended',
    'eslint-config-airbnb-base',
    'plugin:prettier/recommended',
  ],

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

  parserOptions: {
    sourceType: 'script',
  },

  rules: {
    // TODO FIXME turn off temporary, to make eslint pass
    'class-methods-use-this': 'off',
    'consistent-return': 'off',
    'no-console': 'off',
    'no-multi-assign': 'off',
    'no-param-reassign': 'off',
    'no-restricted-syntax': 'off',
    'no-shadow': 'off',
    'no-underscore-dangle': 'off',
    'no-use-before-define': 'off',
    radix: 'off',
    // workaround for git + eslint line ending issue on Travis for Windows OS:
    // https://travis-ci.community/t/files-in-checkout-have-eol-changed-from-lf-to-crlf/349/2
    ...(env.TRAVIS &&
      platform === 'win32' && {
        ['linebreak-style']: 'off',
      }),
  },
}

Fix eslint strict mode option


module.exports = {
  extends: ['fyndiq', 'plugin:jest/recommended'],
  plugins: ['jest'],
  rules: {
    // This rules causes issues because of nested packages.json, disabling
    'import/no-extraneous-dependencies': 0,
  },
  env: {
    jest: true,
  },
}

module.exports = {
  extends: ['fyndiq', 'plugin:jest/recommended'],
  plugins: ['jest'],
  rules: {
    // This rules causes issues because of nested packages.json, disabling
    'import/no-extraneous-dependencies': 0,
    'jsx-a11y/label-has-for': ['error', {
      required: {
        every: ['nesting'],
      },
    }],
  },
  env: {
    jest: true,
  },
}

Allow nested input in labels without htmlFor


"use strict";

import endpoint from "./endpoint";
import Project from "./project";
import * as requests from "./requests";

/**
 * Abstract representation of projects.
 */
export default class Projects {

  /**
   * Constructor.
   *
   * @param  {Tenant} tenant The tenant instance.
   */
  constructor(tenant) {

    /**
     * The tenant.
     * @type {Tenant}
     */
    this.tenant = tenant;
  }

  /**
   * Retrieves the list of projects in the current tenant.
   *
   * @param  {Object} options         The options object.
   * @return {Promise<Array<Object>, Error>}
   */
  list(options={}) {
    return this.tenant.execute({ path: endpoint("projects")}, options);
  }

  /**
   * Retrieve a project object to perform operations on it.
   *
   * @param  {String} id The id of the project.
   * @return {Project}
   */
  project(id) {
    return new Project(this.tenant, id);
  }

  /**
   * Creates the project with the specified properties.
   *
   * @param  {String}  name           The name of the project.
   * @param  {Object} options         The options object.
   * @return {Promise<Object, Error>}
   */
  create(name, options = {}) {
    return this.tenant.execute(
      requests.createProject(name),
      options
    );
  }
}

"use strict";

import endpoint from "./endpoint";
import Project from "./project";
import * as requests from "./requests";

/**
 * Abstract representation of projects.
 */
export default class Projects {

  /**
   * Constructor.
   *
   * @param  {Tenant} tenant The tenant instance.
   */
  constructor(tenant) {

    /**
     * The tenant.
     * @type {Tenant}
     */
    this.tenant = tenant;
  }

  /**
   * Retrieves the list of projects in the current tenant.
   *
   * @param  {Object} options         The options object.
   * @return {Promise<Array<Object>, Error>}
   */
  list(options={}) {
    return this.tenant.execute({ path: endpoint("projects")}, options)
      .then((response) => {
        return {
          projects: response["_embedded"]["be:project"]
        }
      });
  }

  /**
   * Retrieve a project object to perform operations on it.
   *
   * @param  {String} id The id of the project.
   * @return {Project}
   */
  project(id) {
    return new Project(this.tenant, id);
  }

  /**
   * Creates the project with the specified properties.
   *
   * @param  {String}  name           The name of the project.
   * @param  {Object} options         The options object.
   * @return {Promise<Object, Error>}
   */
  create(name, options = {}) {
    return this.tenant.execute(
      requests.createProject(name),
      options
    );
  }
}

Deal with HAL response in client


module.exports = {
  context: __dirname,
  entry: './src/index.jsx',
  output: {
    path: './build',
    filename: 'index.js',
    library: 'CalendarHeatmap',
    libraryTarget: 'var'
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
    modulesDirectories: ['node_modules']
  },
  externals: {
    'react': {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      amd: 'react'
    }
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel'
      }
    ]
  }
};

module.exports = {
  context: __dirname,
  entry: './src/index.jsx',
  output: {
    path: './build',
    filename: 'index.js',
    library: 'CalendarHeatmap',
    libraryTarget: 'umd'
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
    modulesDirectories: ['node_modules']
  },
  externals: {
    'react': {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      amd: 'react'
    }
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel'
      }
    ]
  }
};

Switch libraryTarget from var to umd


import React from 'react';
import addons from '@kadira/storybook-addons';
import {setAddon} from '@kadira/storybook';

import MarkdownPanel from './MarkdownPanel';

const ADDON_ID = 'storybook-addon-markdown';
const PANEL_ID = `${ADDON_ID}/markdown-panel`;

addons.register(ADDON_ID, (api) => {
  const channel = addons.getChannel();
  addons.addPanel(PANEL_ID, {
    title: 'Docs',
    render: () => {
      return <MarkdownPanel channel={channel} api={api} />;
    },
  });
});

import React from 'react';
import addons from '@kadira/storybook-addons';

import MarkdownPanel from './MarkdownPanel';

const ADDON_ID = 'storybook-addon-markdown';
const PANEL_ID = `${ADDON_ID}/markdown-panel`;

addons.register(ADDON_ID, (api) => {
  const channel = addons.getChannel();
  addons.addPanel(PANEL_ID, {
    title: 'Docs',
    render: () => {
      return <MarkdownPanel channel={channel} api={api} />;
    },
  });
});

Fix bug that was causing dataId error


const path = require('path')

// commonjs module
module.exports = {
  context: __dirname,
  entry: './js/ClientApp.js',
  devtool: 'eval',
  output: {
    path: path.join(__dirname, '/public'),
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['.js', '.json']
  },
  stats: {
    colors: true,
    reasons: true,
    chunks: true
  },
  module: {
    rules: [
      {
        include: path.resolve(__dirname, 'js'),
        test: /\.js$/,
        loader: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              url: false
            }
          }
        ]
      }
    ]
  }
}

const path = require('path')

// commonjs module
module.exports = {
  context: __dirname,
  entry: './js/ClientApp.js',
  devtool: 'eval',
  output: {
    path: path.join(__dirname, '/public'),
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['.js', '.json']
  },
  stats: {
    colors: true,
    reasons: true,
    chunks: true
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      },
      {
        include: path.resolve(__dirname, 'js'),
        test: /\.js$/,
        loader: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              url: false
            }
          }
        ]
      }
    ]
  }
}

Configure webpack to lint automatically


var rucksack = require('rucksack-css')
var webpack = require('webpack')
var path = require('path')

module.exports = {
  context: path.join(__dirname, './client'),
  entry: {
    jsx: './index.js',
    html: './index.html',
    vendor: ['react']
  },
  output: {
    path: path.join(__dirname, './static'),
    filename: 'bundle.js',
  },
  module: {
    loaders: [
      {
        test: /\.html$/,
        loader: 'file?name=[name].[ext]'
      },
      {
        test: /\.css$/,
        loaders: [
          'style-loader',
          'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
          'postcss-loader'
        ]
      },
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loaders: [
          'react-hot',
          'babel-loader'
        ]
      },
    ],
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  postcss: [
    rucksack({
      autoprefixer: true
    })
  ],
  plugins: [
    new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'),
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') }
    })
  ],
  devServer: {
    contentBase: './client',
    hot: true
  }
}

var rucksack = require('rucksack-css')
var webpack = require('webpack')
var path = require('path')

module.exports = {
  context: path.join(__dirname, './client'),
  entry: {
    jsx: './index.js',
    html: './index.html',
    vendor: ['react']
  },
  output: {
    path: path.join(__dirname, './static'),
    filename: 'bundle.js',
  },
  module: {
    loaders: [
      {
        test: /\.html$/,
        loader: 'file?name=[name].[ext]'
      },
      {
        test: /\.css$/,
        include: /client/,
        loaders: [
          'style-loader',
          'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
          'postcss-loader'
        ]
      },
      {
        test: /\.css$/,
        exclude: /client/,
        loader: 'style!css'
      },
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loaders: [
          'react-hot',
          'babel-loader'
        ]
      },
    ],
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  postcss: [
    rucksack({
      autoprefixer: true
    })
  ],
  plugins: [
    new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'),
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') }
    })
  ],
  devServer: {
    contentBase: './client',
    hot: true
  }
}

Add a css loader to import global style from external components


#!/usr/bin/env node

var http = require('http'),
    docopt = require('docopt').docopt,
    rosters = {};

var doc =
"Usage:\n\
  main.js [--roster ROSTER]\n\
  main.js -h | --help\n\
  main.js --version\n\
Options:\n\
  -h --help     Show this screen.\n\
  --roster ROSTER Name of the roster module you would like to scrape.\n  --version Show version."

var options = docopt(doc, {help: true, version: getVersion()});

function getVersion(){
  var pjson = require('./package.json');
  return pjson.version
};

console.log(options);

/*
http.get("url", function(res) {
  console.log("Got response: " + res.statusCode);
}).on('error', function(e) {
  console.log("Got error: " + e.message);
});
*/

#!/usr/bin/env node

var http = require('http'),
    docopt = require('docopt').docopt,
    rosters = {};

var doc =
"Usage:\n\
  main.js [--roster ROSTER]\n\
  main.js -h | --help\n\
  main.js --version\n\
Options:\n\
  -h --help     Show this screen.\n\
  --roster ROSTER Name of the roster module you would like to scrape.\n  --version Show version."

var options = docopt(doc, {help: true, version: getVersion()});

function getVersion(){
  var pjson = require('../package.json');
  return pjson.version
};

console.log(options);

/*
http.get("url", function(res) {
  console.log("Got response: " + res.statusCode);
}).on('error', function(e) {
  console.log("Got error: " + e.message);
});
*/

Fix package.json location in getVersion


// Run after the DOM loads
$(function () {
  'use strict';

  var map = geo.map({
    node: '#map',
    center: {
      x: -122.445,
      y: 37.8
    },
    zoom: 6
  });

  $.ajax('https://s3.amazonaws.com/uploads.hipchat.com/446632/3114847/4dZfl0YfZpTfYzq/AdderallCities2015.csv', {
    success: function (resp) {
      var rows = resp.split(/\r\n|\n|\r/);
      rows = rows.map( function (r) {
        var fields = r.split(',');
        return [fields[12], fields[24], fields[25]].map(parseFloat);
      });
      rows.splice(0, 1);

      var layer = map.createLayer('feature', {renderer: 'canvas'});
      var heatmap = layer.createFeature('heatmap')
                      .data(rows)
                      .intensity(function (d) {
                        return d[0];
                      })
                      .position(function (d) {
                        return {
                          x: d[2],
                          y: d[1]
                        };
                      })
                      .maxIntensity(20)
                      .style('radius', 5)
                      .style('blurRadius', 15)
                      .style('opacity', 0.5);
      map.draw();
    }
  });

  var base = map.createLayer('osm');
  map.draw();
});

// Run after the DOM loads
$(function () {
  'use strict';

  var map = geo.map({
    node: '#map',
    center: {
      x: -122.445,
      y: 37.8
    },
    zoom: 6
  });

  $.ajax('https://s3.amazonaws.com/uploads.hipchat.com/446632/3114847/4dZfl0YfZpTfYzq/AdderallCities2015.csv', {
    success: function (resp) {
      var rows = resp.split(/\r\n|\n|\r/);
      rows = rows.map( function (r) {
        var fields = r.split(',');
        return [fields[12], fields[24], fields[25]].map(parseFloat);
      });
      rows.splice(0, 1);

      var layer = map.createLayer('feature', {renderer: 'canvas'});
      var heatmap = layer.createFeature('heatmap')
                      .data(rows)
                      .intensity(function (d) {
                        return d[0];
                      })
                      .position(function (d) {
                        return {
                          x: d[2],
                          y: d[1]
                        };
                      })
                      .maxIntensity(20)
                      .style('radius', 5)
                      .style('blurRadius', 15)
                      .style('opacity', 1.0);
      map.draw();
    }
  });

  var base = map.createLayer('osm');
  map.draw();
});

Set default opacity to 1.0


/*jshint node:true*/
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function(defaults) {
  var app = new EmberApp(defaults, {
    storeConfigInMeta: false,
  });

  // Use `app.import` to add additional libraries to the generated
  // output files.
  //
  // If you need to use different assets in different
  // environments, specify an object as the first parameter. That
  // object's keys should be the environment name and the values
  // should be the asset to use in that environment.
  //
  // If the library that you are including contains AMD or ES6
  // modules that you would like to import into your application
  // please specify an object with the list of modules as keys
  // along with the exports of each module as its value.

  return app.toTree();
};

/*jshint node:true*/
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function(defaults) {
  var app = new EmberApp(defaults, {
    storeConfigInMeta: false,

    fingerprint: {
      enabled: false,
    },
  });

  // Use `app.import` to add additional libraries to the generated
  // output files.
  //
  // If you need to use different assets in different
  // environments, specify an object as the first parameter. That
  // object's keys should be the environment name and the values
  // should be the asset to use in that environment.
  //
  // If the library that you are including contains AMD or ES6
  // modules that you would like to import into your application
  // please specify an object with the list of modules as keys
  // along with the exports of each module as its value.

  return app.toTree();
};

Disable finger-printing in production mode


/*
 * Copyright (c) 2014-2020 Bjoern Kimminich.
 * SPDX-License-Identifier: MIT
 */

/* 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',
  retry: {
    match: [
      /SQLITE_BUSY/
    ],
    name: 'query',
    max: 5
  },
  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

/*
 * Copyright (c) 2014-2020 Bjoern Kimminich.
 * SPDX-License-Identifier: MIT
 */

/* 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 "increase retries on sqlite connection"


'use strict';

var path = require('path');
var helpers = require('yeoman-generator').test;
var assert = require('yeoman-generator').assert;

describe('simple node package generator', function(){
  beforeEach(function (done) {
    helpers.run(path.join( __dirname, '../app'))
      .inDir(path.join( __dirname, './tmp'))
      .withOptions({ 'skip-install': true })
      .withPrompts({ cli: true })
      .on('end', done);
  });

  it('create cli file', function(){
    assert.file('cli.js');
  });

  it('package.json should contain correct bin script', function(){
    var pkg = require('package.json');

    assert.deepEqual(pkg.bin, { tmp: 'cli.js' });
  });
});

'use strict';

var path = require('path');
var helpers = require('yeoman-generator').test;
var assert = require('yeoman-generator').assert;

describe('simple node package generator', function(){
  beforeEach(function (done) {
    helpers.run(path.join( __dirname, '../app'))
      .inDir(path.join( __dirname, './tmp'))
      .withOptions({ 'skip-install': true })
      .withPrompts({ cli: true })
      .on('end', done);
  });

  it('create cli file', function(){
    assert.file('cli.js');
  });

  it('package.json should contain correct bin script', function(){
    var pkg = require('./tmp/package.json');

    assert.deepEqual(pkg.bin, { tmp: 'cli.js' });
  });
});

Fix failing CLI unit test


/*
 * Javacript for the Dropdown sections
 */

/* jshint browser: true */
/* jshint -W097 */

function expandSection(id) {
  var x = document.getElementById(id);
  var y = document.getElementById(id + '_arrow');
  if (x.className.indexOf('w3-show') == -1) {
    x.className += ' w3-show';
    y.className = 'fa fa-caret-up';
  } else {
    x.className = x.className.replace(' w3-show', '');
    y.className = 'fa fa-caret-down';
  }

}

/*
 * Javacript for the Dropdown sections
 */

/* jshint browser: true */
/* jshint -W097 */

function expandSection(id) {
  var x = [document.getElementById(id)];
  if (x[0] === null) {
    x = document.getElementsByClassName(id);
  }
  if (x === null || x.length === 0) {
    x = document.getElementsByName(id);
  }
  if (x === null || x.length === 0) {
    return;
  }
  var y = document.getElementById(id + '_arrow');
  for (var i = 0; i < x.length; i++) {
    if (x[i].className.indexOf('w3-show') == -1) {
      x[i].className += ' w3-show';
      y.className = 'fa fa-caret-up';
    } else {
      x[i].className = x[i].className.replace(' w3-show', '');
      y.className = 'fa fa-caret-down';
    }
  }

}

Allow dropdown sections to be identified by class and name


function dechex(number) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philippe Baumann
    // +   bugfixed by: Onno Marsman
    // +   improved by: pilus
    // *     example 1: dechex(10);
    // *     returns 1: 'a'
    // *     example 2: dechex(47);
    // *     returns 2: '2f'
	if (number < 0)	{
	   return (0xFFFFFFFF+number+1).toString(16);
	}
    return parseInt(number, 10).toString(16);
}

Change tabs to 4 spaces


/*jshint node:true*/
var RSVP = require('rsvp');

module.exports = {
  description: 'Add bower dependency for froala-wysiwyg-editor and also a project dep for ember-cli-font-awesome',

  normalizeEntityName: function() {
    // allows us to run ember -g ember-bootstrap-switch and not blow up
    // because ember cli normally expects the format
    // ember generate <entitiyName> <blueprint>
  }, // :normalizeEntityName

  afterInstall: function() {
    return RSVP.all([
      this.addBowerPackageToProject( 'froala-wysiwyg-editor',  '~2.2.1' ),
      this.addAddonToProject(        'ember-cli-font-awesome', '^1.4.2' )
    ]);
  } // :afterInstall

}; // module.exports

/*jshint node:true*/
var RSVP = require('rsvp');

module.exports = {
  description: 'Add bower dependency for froala-wysiwyg-editor and also a project dep for ember-cli-font-awesome',

  normalizeEntityName: function() {
    // allows us to run ember -g ember-bootstrap-switch and not blow up
    // because ember cli normally expects the format
    // ember generate <entitiyName> <blueprint>
  }, // :normalizeEntityName

  afterInstall: function() {
    return RSVP.all([
      this.addBowerPackageToProject( 'froala-wysiwyg-editor',  '~2.2.1' ),
      this.addAddonToProject(        'ember-cli-font-awesome', '^1.5.0' )
    ]);
  } // :afterInstall

}; // module.exports

Update the blueprints ember-cli-font-awesome dep version


$(document).on('hidden.bs.modal', '.modal', function () {
  $('.panel', this).remove();
});

$(document).on('hidden.bs.modal', '.modal', function () {
  $('.panel', this).remove();
  $('form', this)[0].reset();
});

Reset form on modal close


(function($) {
  return $.fn.noiseGen = function(options) {
    var defaultOptions = {
      width: 32,
      height: 32,
      opacity: 0.2,
      fallbackImage: false,
      depth: 60
    },
    canvas = document.createElement("canvas"),
    options = $.extend(defaultOptions, options);
    if (!canvas.getContext || !canvas.getContext("2d")) {
      // Canvas not supported :(
      if (!!options.fallbackImage) {
        // Fallback image provided, set it as background
        return this.css("background-image", "url(" + options.fallbackImage + ")");
      } else {
        // Fallback background image not provided, just return maintaining chainability
        return this;
      }
    } else {
      // Canvas supported :)
      var ctx = canvas.getContext("2d"),
      x = 0,
      y = 0;
      canvas.width = options.width;
      canvas.height = options.height;
      while (x < canvas.width) {
        y = 0;
        while (y < canvas.height) {
          number = Math.floor(Math.random() * options.depth);
          ctx.fillStyle = "rgba(" + number + "," + number + "," + number + "," + options.opacity + ")";
          ctx.fillRect(x, y, 1, 1);
          y++;
        }
        x++;
      }
      return this.css("background-image", "url(" + canvas.toDataURL("image/png") + ")");
    }
  };
})(jQuery);

(function($) {
  return $.fn.noiseGen = function(options) {
    var defaultOptions = {
      width: 32,
      height: 32,
      opacity: 0.2,
      fallbackImage: false,
      depth: 60
    },
    canvas = document.createElement("canvas");
    options = $.extend(defaultOptions, options);
    if (!canvas.getContext || !canvas.getContext("2d")) {
      // Canvas not supported :(
      if (!!options.fallbackImage) {
        // Fallback image provided, set it as background
        return this.css("background-image", "url(" + options.fallbackImage + ")");
      } else {
        // Fallback background image not provided, just return maintaining chainability
        return this;
      }
    } else {
      // Canvas supported :)
      var ctx = canvas.getContext("2d"),
      x = 0,
      y = 0;
      canvas.width = options.width;
      canvas.height = options.height;
      while (x < canvas.width) {
        while (y < canvas.height) {
          var r = Math.floor(Math.random() * options.depth);
          ctx.fillStyle = "rgba(" + r + "," + r + "," + r + "," + options.opacity + ")";
          ctx.fillRect(x, y, 1, 1);
          y++;
        }
        y = 0;
        x++;
      }
      return this.css("background-image", "url(" + canvas.toDataURL("image/png") + ")");
    }
  };
})(jQuery);

Correct bug in var declarations


/* jshint ignore:start */

import Ember from 'ember';

var feature_flags = EMBER_CLI_CONDITIONAL_COMPILE_INJECTIONS;

var initializer = {
  name: 'ember-cli-conditional-compile-helpers',
  initialize: function(container, application) {
    Object.keys(feature_flags).map(function(flag) {
      Ember.Handlebars.registerHelper('if-flag-' + flag, function(options) {
        if (feature_flags[flag]) {
          return options.fn(this);
        } else {
          return options.inverse(this);
        }
      });
    });
  }
};

export default initializer;

/* jshint ignore:end */

/* jshint ignore:start */

import Ember from 'ember';

var feature_flags = EMBER_CLI_CONDITIONAL_COMPILE_INJECTIONS;

var initializer = {
  name: 'ember-cli-conditional-compile-helpers',
  initialize: function(container, application) {
    Object.keys(feature_flags).map(function(flag) {
      Ember.Handlebars.registerHelper('if-flag-' + flag, function(options) {
        if (feature_flags[flag]) {
          return options.fn(this);
        } else if (options.inverse) {
          return options.inverse(this);
        }
      });
    });
  }
};

export default initializer;

/* jshint ignore:end */

Put condition to check undefined inverse functions


// http://stackoverflow.com/questions/30223265/how-to-use-jquery-with-jsdom5/30223890#30223890

import {jsdom} from 'jsdom';
const document = jsdom('<html></html>', {});
const window = document.defaultView;
import jQueryFactory from 'jquery';
const jQuery = jQueryFactory(window);

// http://stackoverflow.com/questions/3176962/jquery-object-equality/3177083#3177083

jQuery.fn.equals = function (compareTo) {
  if (!compareTo || this.length !== compareTo.length) {
    return false;
  }
  for (let i = 0; i < this.length; ++i) {
    if (this[i] !== compareTo[i]) {
      return false;
    }
  }
  return true;
};

jQuery.fn.outerHTML = function () {
  jQuery('<div/>').append(this.clone()).html();
};

jQuery.fn.inspect = function () {
  return '$("' + this.selector + '")';
};

export default jQuery;

// http://stackoverflow.com/questions/30223265/how-to-use-jquery-with-jsdom5/30223890#30223890

import {jsdom} from 'jsdom';
const document = jsdom('<html></html>', {});
const window = document.defaultView;
import jQueryFactory from 'jquery';
const jQuery = jQueryFactory(window);

// http://stackoverflow.com/questions/3176962/jquery-object-equality/3177083#3177083

jQuery.fn.equals = function (compareTo) {
  if (!compareTo || this.length !== compareTo.length) {
    return false;
  }
  for (let i = 0; i < this.length; ++i) {
    if (this[i] !== compareTo[i]) {
      return false;
    }
  }
  return true;
};

jQuery.fn.outerHTML = function () {
  return jQuery('<div/>').append(this.clone()).html();
};

jQuery.fn.inspect = function () {
  return '$("' + (this.selector || this.outerHTML()) + '")';
};

export default jQuery;

Fix and improve jQuery test helpers


'use strict';

// module Web.Firebase.Authentication.Eff

exports._onAuth = function (callback, firebase) {
  return function() {
    return firebase.onAuth(callback);
  };
};

exports._authWithOAuthRedirect = function (provider, errorCallback, ref) {
  var errorCbEffect = function(error) {
    return errorCallback(error)(); // ensure effect gets used
  };
  ref.authWithOAuthRedirect(provider, errorCbEffect);
};

'use strict';

// module Web.Firebase.Authentication.Eff

exports._onAuth = function (callback, firebase) {
  var cbEffect = function(data) {
    return cbEffect(data)(); // ensure effect gets used
  };
  return function() {
    return firebase.onAuth(cbEffect);
  };
};

exports._authWithOAuthRedirect = function (provider, errorCallback, ref) {
  var errorCbEffect = function(error) {
    return errorCallback(error)(); // ensure effect gets used
  };
  ref.authWithOAuthRedirect(provider, errorCbEffect);
};

Fix - process effects in onAuth


function checkUsersValid(goodUsers) {
     return function allUsersValid(submittedUsers) {
       // SOLUTION GOES HERE
     };
}

function checkUsersValid(goodUsers) {
     return function allUsersValid(submittedUsers) {
       return submittedUsers.every(function(elem){
         return goodUsers.some(function(val){
           return val.id == elem.id;
         });
       });
     };
}

module.exports = checkUsersValid

Add check valid users solution


// test for ternary

result = (true?3:4)==3 && (false?5:6)==6;

// test for ternary

assert ((true?3:4) == 3, "First check");
assert ((false?5:6)==6, "Second check");

result = 1;

Test refactored to get better error location.


"use strict";

let name = "Brook";
let totalReplies = 249;
let avatar = "/user/avatars/brook-user-1.jpg";

let user = ;

addUserToSidebar(user);

"use strict";

let name = "Brook";
let totalReplies = 249;
let avatar = "/user/avatars/brook-user-1.jpg";

let user = {name, totalReplies, avatar};

addUserToSidebar(user);

Use shorthand to create an object


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

  grunt.config.init({
    pkg: grunt.file.readJSON('package.json')
  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.config('clean', {
    dist: 'dist'
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.config('copy', {
    dist: {
      files: {
        'dist/sticky-header.js': 'sticky-header.js'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.config('jasmine', {
    test: {
      src: 'dist/sticky-header.js',
      options: {
        specs: 'test/*-spec.js'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.config('uglify', {
    options: {
      preserveComments: 'some'
    },
    dist: {
      files: {
        'dist/sticky-header.min.js': [
          'sticky-header.js'
        ]
      }
    }
  });

  grunt.registerTask('dist', [
    'clean:dist',
    'copy:dist',
    'uglify:dist'
  ]);

  grunt.registerTask('test', [
    'jasmine:test',
  ]);

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

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

  grunt.config.init({
    pkg: grunt.file.readJSON('package.json')
  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.config('clean', {
    dist: 'dist'
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.config('copy', {
    dist: {
      files: {
        'dist/sticky-header.js': 'sticky-header.js'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.config('jasmine', {
    test: {
      src: 'dist/sticky-header.js',
      options: {
        specs: 'test/*-spec.js'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.config('uglify', {
    options: {
      preserveComments: 'some'
    },
    dist: {
      files: {
        'dist/sticky-header.min.js': [
          'sticky-header.js'
        ]
      }
    }
  });

  grunt.registerTask('dist', [
    'clean:dist',
    'copy:dist',
    'uglify:dist'
  ]);

  grunt.registerTask('test', [
    //'jasmine:test',
  ]);

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

Disable test command (no tests)


module.exports = function (grunt) {

	grunt.initConfig({

		pkg: grunt.file.readJSON('package.json')
	});

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

module.exports = function (grunt) {

	grunt.initConfig({

		pkg: grunt.file.readJSON('package.json'),

		clean: {
			build: {
				src: "build"
			}
		},

		copy: {
			build: {
				files: [
					{
						expand: true,
						cwd: 'source/',
						src: ['clever-style-switcher.js'],
						dest: 'build/'
					}
				]
			}
		}
	});

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

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

Add clean and copy tasks for Grunt.


#ifndef __DOMAIN_MANAGER__
#define __DOMAIN_MANAGER__

#include "lib/common.js"
#include "data/suffix-list.js"

rndphrase.DomainManager = {
    get_reg_domain: function(rules, doms) {
        var node = rules[doms[0]];
        if(node == undefined) node = rules['*'];
        if(node == undefined || (node.L==1 && node['!'] == 1)) {
            return doms[0];
        } else if (node.L == 1) return node;
        var dom = this.get_reg_domain(node, doms.splice(1));
        if(dom != undefined)
            return dom + '.' + doms[0];
        return undefined;
    },
    get_host: function(domain) {
        var doms = domain.split('.').reverse();
        return this.get_reg_domain(SUFFIX_LIST, doms);
    }
};

#endif

#ifndef __DOMAIN_MANAGER__
#define __DOMAIN_MANAGER__

#include "lib/common.js"
#include "data/suffix-list.js"

rndphrase.DomainManager = {
    get_reg_domain: function(rules, doms) {
        var node = rules[doms[0]];
        if(node == undefined) node = rules['*'];
        if(node == undefined || (node.L==1 && node['!'] == 1)) {
            return doms[0];
        } else if (node.L == 1) return node;
        var dom = this.get_reg_domain(node, doms.splice(1));
        if(dom != undefined)
            return dom + '.' + doms[0];
        return undefined;
    },
    get_host: function(domain) {
        // Try to use Firefox' built in list
        var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
                  .getService(Components.interfaces.nsIEffectiveTLDService);
        if(eTLDService) {
            dumpln("Using eTLDService.");
            return eTLDService.getBaseDomainFromHost(domain);
        }
        // Fall back to own list
        var doms = domain.split('.').reverse();
        return this.get_reg_domain(SUFFIX_LIST, doms);
    }
};

#endif

Use built in public suffix list in Firefox-based browsers


Template.createBetForm.helpers({
  photo: function(){
    return Session.get("photo");
  }
})

Template.createBetForm.events({
  "submit .create-bet" : function(event){
    event.preventDefault();

    var title = event.target.betTitle.value,
        wager = event.target.betWager.value,
        user = Meteor.user(),
        username = user.username,
        defender = event.target.defender.value,
        type = "new";

    if (Meteor.users.find({username: defender}).count() === 0){
      throw new Meteor.Error(
        alert( "Sorry the Username you are trying to challenge is not valid!" )
      );
    }

    if (defender === username) {
      throw new Meteor.Error(
        alert( "You can't bet yourself!" )
      );
    }

    Meteor.call("createBet", username, defender, title, wager);
    Meteor.call("createBetNotification", username, defender, type);
    Router.go('/bets');
  },

  "click .take-photo" : function(event){
    event.preventDefault();

    var cameraOptions = {
      width: 700,
      height: 500
    };

    MeteorCamera.getPicture(cameraOptions, function(error, data){
      Images.insert(data);
      Session.set("photo", data);
    });
  }
});

Template.createBetForm.helpers({
  photo: function(){
    return Session.get("photo");
  }
})

Template.createBetForm.events({
  "submit .create-bet" : function(event){
    event.preventDefault();

    var title = event.target.betTitle.value,
        wager = event.target.betWager.value,
        user = Meteor.user(),
        username = user.username,
        defender = event.target.defender.value,
        type = "new";

    if (Meteor.users.find({username: defender}).count() === 0){
      throw new Meteor.Error(
        alert( "Sorry the Username you are trying to challenge is not valid!" )
      );
    }

    if (defender === username) {
      throw new Meteor.Error(
        alert( "You can't bet yourself!" )
      );
    }

    Meteor.call('createBet', username, defender, title, wager, betImage);
    Meteor.call('createBetNotification', username, defender, type);
    Router.go('/bets');
  },

  "click .take-photo" : function(event){
    event.preventDefault();

    var cameraOptions = {
      width: 700,
      height: 500
    };

    MeteorCamera.getPicture(cameraOptions, function(error, data){
      var image = Images.insert(data);
      Session.set('image', data);
      Session.set('image._id', image._id);
    });
  }
});

Set Session variable for image and image._id


const url = require('url');
const webpack = require('webpack');
const BrowserSyncPlugin = require('browsersync-webpack-plugin');

module.exports = (config) => {
  /**
   * We do this to enable injection over SSL.
   */
  const target = process.env.DEVURL || config.devUrl;
  if (url.parse(target).protocol === 'https:') {
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
  }

  return {
    output: {
      pathinfo: true,
      publicPath: config.proxyUrl + config.publicPath,
    },
    devtool: '#cheap-module-source-map',
    stats: false,
    plugins: [
      new webpack.optimize.OccurrenceOrderPlugin(),
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NoEmitOnErrorsPlugin(),
      new BrowserSyncPlugin({
        target,
        open: config.open,
        proxyUrl: config.proxyUrl,
        watch: config.watch,
        delay: 500,
        advanced: {
          browserSync: {
            https: config.devSsl
          }
        }
      })
    ]
  };
};

const url = require('url');
const webpack = require('webpack');
const BrowserSyncPlugin = require('browsersync-webpack-plugin');

module.exports = (config) => {
  /**
   * We do this to enable injection over SSL.
   */
  const target = process.env.DEVURL || config.devUrl;
  if (url.parse(target).protocol === 'https:') {
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
  }

  return {
    output: {
      pathinfo: true,
      publicPath: config.proxyUrl + config.publicPath,
    },
    devtool: '#cheap-module-source-map',
    stats: false,
    plugins: [
      new webpack.optimize.OccurrenceOrderPlugin(),
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NoEmitOnErrorsPlugin(),
      new BrowserSyncPlugin({
        target,
        open: config.open,
        proxyUrl: config.proxyUrl,
        watch: config.watch,
        delay: 500,
        disableHostCheck: true,
        advanced: {
          browserSync: {
            https: config.devSsl,
          },
        },
      }),
    ],
  };
};

Add option to disable host check in DevServer


define(['mac/roman'], function(macintoshRoman) {

  'use strict';

  return function(resource) {

    var text = macintoshRoman(resource.data, 0, resource.data.length);
    debugger;

  };

});

define(['mac/roman'], function(macintoshRoman) {

  'use strict';

  return function(item) {
    return item.getBytes().then(function(bytes) {
      var text = macintoshRoman(bytes, 0, bytes.length);
      debugger;
    });
  };

});

Change ATXT to new loader format


function LevelPalette( numberColor, boardColors ) {
    this.numberColor = numberColor;
    this.boardColors = boardColors;
}

function LevelPalette(numberColor, boardColors) {
    this.numberColor = numberColor;
    this.boardColors = boardColors;
}

Remove extra space from parameters


import modules, { locatePluginDir } from '../load-plugins';
import { expect } from 'chai';

describe('load-plugins', () => {
  it('should load included plugins', () => {
    expect(Object.keys(modules)).to.have.length.greaterThan(4);
    expect(Object.keys(modules)).to.contain('default');
  });

  describe('locatePluginDir', () => {
    it('should identify paths', () => {
      const configPath = '/projects/test/mup.js';

      expect(locatePluginDir('./test', configPath)).to.equal('/projects/test/test');
      expect(locatePluginDir('~/test', configPath)).to.contain('/test');
      expect(locatePluginDir('/test', configPath)).to.equal('/test');
    });
  });
});

import modules, { locatePluginDir } from '../load-plugins';
import { expect } from 'chai';

describe('load-plugins', () => {
  it('should load included plugins', () => {
    expect(Object.keys(modules)).to.have.length.greaterThan(4);
    expect(Object.keys(modules)).to.contain('default');
  });

  describe('locatePluginDir', () => {
    it('should identify paths', () => {
      const configPath = '/projects/a/mup.js';

      function createResult(value) {
        return locatePluginDir(value, configPath).replace(/\\/g, '/');
      }

      expect(createResult('./test')).to.contain('/projects/a/test');
      expect(createResult('~/test')).to.contain('/test');
      expect(createResult('/test')).to.length.lessThan(10);
    });
  });
});

Fix running locatePluginDir tests on windows


'use strict';

/**
 * Module dependencies
 */
const cors = require('@koa/cors');

const defaults = {
  origin: '*',
  maxAge: 31536000,
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
  headers: [
    'Content-Type',
    'Authorization',
    'Origin',
    'Accept',
    'X-Forwarded-Host',
  ],
  keepHeadersOnError: false,
};

module.exports = strapi => {
  return {
    /**
     * Initialize the hook
     */
    initialize() {
      if (strapi.config.currentEnvironment.security.cors.enabled !== true)
        return;

      const {
        origin,
        expose,
        maxAge,
        credentials,
        methods,
        headers,
        keepHeadersOnError,
      } = Object.assign({}, defaults, strapi.config.middleware.settings.cors);

      strapi.app.use(
        cors({
          origin,
          exposeHeaders: expose,
          maxAge,
          credentials,
          allowMethods: methods,
          allowHeaders: headers,
          keepHeadersOnError,
        })
      );
    },
  };
};

'use strict';

/**
 * Module dependencies
 */
const cors = require('@koa/cors');

const defaults = {
  origin: '*',
  maxAge: 31536000,
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
  headers: [
    'Content-Type',
    'Authorization',
    'Origin',
    'Accept',
    'X-Forwarded-Host',
  ],
  keepHeadersOnError: false,
};

module.exports = strapi => {
  return {
    /**
     * Initialize the hook
     */
    initialize() {
      if (strapi.config.currentEnvironment.security.cors.enabled !== true)
        return;

      const {
        origin,
        expose,
        maxAge,
        credentials,
        methods,
        headers,
        keepHeadersOnError,
      } = Object.assign({}, defaults, strapi.config.middleware.settings.cors);

      strapi.app.use(
        cors({
          origin: function(ctx) {
            const whitelist = Array.isArray(origin)
              ? origin
              : origin.split(/\s*,\s*/);

            const requestOrigin = ctx.accept.headers.origin;
            if (whitelist.includes('*')) {
              return '*';
            }

            if (!whitelist.includes(requestOrigin)) {
              return ctx.throw(`${requestOrigin} is not a valid origin`);
            }
            return requestOrigin;
          },
          exposeHeaders: expose,
          maxAge,
          credentials,
          allowMethods: methods,
          allowHeaders: headers,
          keepHeadersOnError,
        })
      );
    },
  };
};

Allow multiple origins to be provided to the cors middleware, array or coma separated


class ManageController {
  constructor($scope, toastr, _, PlaceFactory) {
    'ngInject';

    $scope.headers = [
      'ID',
      'Name',
      'Country',
      'Image',
      'Enabled',
      'Actions'
    ];
    $scope.places = [];

    $scope.delete = function(id, name) {
      var result = confirm("Are you sure you want to delete place " + name + "?");

      if(result) {
        PlaceFactory.delete(id).then(function(data) {
          $scope.places = _.remove($scope.places, function(place) {
            return place.country_id !== id;
          });

          toastr.success('Place deleted.');
        }, function(error) {
          toastr.error('Failed to delete place: ' + error.data.detail);
        });
      }
    };

    PlaceFactory.getList().success(function(data) {
      data = _.sortBy(data, "country_id");
      data = _.each(data, function(place) {
        place.continent = place.continent === null ? "-" : place.continent;
        place.image = place.image === null ? "" : place.image;
      });
      $scope.places = data;
    });
  }
}

export default ManageController;

class ManageController {
  constructor($scope, toastr, _, PlaceFactory) {
    'ngInject';

    $scope.headers = [
      'ID',
      'Name',
      'Country',
      'Image',
      'Enabled',
      'Actions'
    ];
    $scope.places = [];

    $scope.delete = function(id, name) {
      var result = confirm("Are you sure you want to delete place " + name + "?");

      if(result) {
        PlaceFactory.delete(id).then(function(data) {
          $scope.places = _.remove($scope.places, function(place) {
            return place.place_id !== id;
          });

          toastr.success('Place deleted.');
        }, function(error) {
          toastr.error('Failed to delete place: ' + error.data.detail);
        });
      }
    };

    PlaceFactory.getList().success(function(data) {
      data = _.sortBy(data, "place_id");
      data = _.each(data, function(place) {
        place.continent = place.continent === null ? "-" : place.continent;
        place.image = place.image === null ? "" : place.image;
      });
      $scope.places = data;
    });
  }
}

export default ManageController;

Fix place deletion view logic


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

  self.mentors = [];

  self.newSearch = {
    generic_search: null,
    first_name: null,
    last_name: null,
    email: null,
    company: null,
    job_title: null,
    zip: null,
    race: null,
    sex: 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);
    };
  };

}]);

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

  self.mentors = [];

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

  self.setMentor = function(mentor){
    console.log(mentor.id);
    BioFactory.setMentor(mentor);
  };

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

}]);

Fix bug with profile loading


// Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0.

var React = require('react');

var ScoreMessage = React.createClass({
    getInitialState : function() {
       return { showMe : false };
    },

    render: function() {
            return(

                    "Please remember to click save button to save the scorring."

            );
     },

    checkAction: function(value) {
        this.setState({ showMe : value}) ;
    }
});

module.exports = ScoreMessage;

// Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0.

var React = require('react');

var ScoreMessage = React.createClass({
    getInitialState : function() {
       return { showMe : false };
    },

    render: function() {
            return(

                    "Click the 'Save' button when you’re finished scoring"

            );
     },

    checkAction: function(value) {
        this.setState({ showMe : value}) ;
    }
});

module.exports = ScoreMessage;

Change warning message for scoring data


function y(){
var a=prompt("Jouer");
var b = Math.floor((Math.random() * 3) + 1);

if(b==1){
  b="pierre";
} else if (b==2){
   b="papier";
} else {
  b="ciseaux";
}

Add random js for 1 2 3


$(document).ready(function() {

  BVB.init();

  $(document).on("click", "#menu a", function() {
    href = $(this).attr("href");
    window.location.hash = href;
  });

  $(document).on("click", ".fav-star", function() {
    var recipe_id = $(this).data("recipe-id");
    var fav_span = BVB.getFavSpan(recipe_id);
    $("span[data-recipe-id=" + recipe_id + "]").replaceWith(fav_span);
  });

});

$(document).ready(function() {

  BVB.init();

  $(document).on("click", "#menu a", function() {
    href = $(this).attr("href");
    window.location.hash = href;
  });

  $(document).on("click", ".fav-star", function() {
    var recipe_id = $(this).data("recipe-id");
    var fav_span = BVB.getFavSpan(recipe_id);
    $("span[data-recipe-id=" + recipe_id + "]").replaceWith(fav_span);
  });

  $(document).on("click", "#burger_button", function(e) {
    $("#menu").data( "mmenu" ).open();
  });

});

Add mmenu action to burger button


/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'SystemAuthService',
  extends: 'foam.nanos.auth.ProxyAuthService',
  methods: [
    {
      name: 'check',
      javaCode: `
        foam.nanos.auth.User user = (foam.nanos.auth.User) x.get("user");
        return ( user != null && user.getId() == 1 ) || getDelegate().check(x, permission);
      `
    }
  ]
});

/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'SystemAuthService',
  extends: 'foam.nanos.auth.ProxyAuthService',
  methods: [
    {
      name: 'check',
      javaCode: `
        foam.nanos.auth.User user = (foam.nanos.auth.User) x.get("user");
        return user != null && ( user.getId() == 1 || user.getGroup().equals("admin") || user.getGroup().equals("system") ) || getDelegate().check(x, permission);
      `
    }
  ]
});

Speed up authorization checks for superadmins


import React from 'react';
import ClipboardJS from 'clipboard';
import 'balloon-css/balloon.css';

export default class CopyButton extends React.PureComponent {
  constructor(props) {
    super(props);
    this.copyBtnRef = React.createRef();
    this.clipboardRef = React.createRef();
  }

  static defaultProps = {
    content: '',
  };
  state = {
    tooltipAttrs: {},
  };

  componentDidMount() {
    this.clipboardRef.current = new ClipboardJS(this.copyBtnRef.current, {
      text: () => this.props.content,
    });
    this.clipboardRef.current.on('success', () => {
      const self = this;
      this.setState({
        tooltipAttrs: {
          'data-balloon': '複製成功！',
          'data-balloon-visible': '',
          'data-balloon-pos': 'up',
        },
      });

      setTimeout(function() {
        self.setState({ tooltipAttrs: {} });
      }, 1000);
    });
  }

  render() {
    const { tooltipAttrs } = this.state;
    return (
      <button ref={this.copyBtnRef} className="btn-copy" {...tooltipAttrs}>
        複製到剪貼簿
        <style jsx>{`
          .btn-copy {
            margin-left: 10px;
          }
        `}</style>
      </button>
    );
  }
}

import React from 'react';
import ClipboardJS from 'clipboard';
import 'balloon-css/balloon.css';

export default class CopyButton extends React.PureComponent {
  constructor(props) {
    super(props);
    this.copyBtnRef = React.createRef();
  }

  static defaultProps = {
    content: '',
  };
  state = {
    tooltipAttrs: {},
  };

  componentDidMount() {
    const clipboard = new ClipboardJS(this.copyBtnRef.current, {
      text: () => this.props.content,
    });
    clipboard.on('success', () => {
      const self = this;
      this.setState({
        tooltipAttrs: {
          'data-balloon': '複製成功！',
          'data-balloon-visible': '',
          'data-balloon-pos': 'up',
        },
      });

      setTimeout(function() {
        self.setState({ tooltipAttrs: {} });
      }, 1000);
    });
  }

  render() {
    const { tooltipAttrs } = this.state;
    return (
      <button ref={this.copyBtnRef} className="btn-copy" {...tooltipAttrs}>
        複製到剪貼簿
        <style jsx>{`
          .btn-copy {
            margin-left: 10px;
          }
        `}</style>
      </button>
    );
  }
}

Use local variable for clipboard created by ClipboardJS instead of ref


import TYPES from 'types';

function isMember(element) {
  if (element.element) {
    return element.element === TYPES.MEMBER;
  }

  return element === TYPES.MEMBER;
}

function getValueType({element, content}) {
  if (isMember(element)) {
    return content.value.element;
  }

  return element;
}

function getType(element) {
  if (isMember(element.element)) {
    return getValueType(element);
  }

  return element.element;
}

function isObject(element) {
  if (!element) {
    return false;
  }

  if (element.element) {
    return getType(element) === TYPES.OBJECT;
  }

  return element === TYPES.OBJECT;
}

function isArray(element) {
  if (!element) {
    return false;
  }

  if (element.element) {
    return getType(element) === TYPES.ARRAY;
  }

  return element === TYPES.ARRAY;
}

function isEnum(element) {
  if (element.element) {
    return getType(element) === TYPES.ARRAY;
  }

  return element === TYPES.ENUM;
}

function isNestedObject(element) {
  return isObject(element) || isArray(element) || isEnum(element);
}

export {
  getValueType,
  getType,
  isMember,
  isEnum,
  isObject,
  isArray,
  isNestedObject,
};

import TYPES from 'types';

function isMember(element) {
  if (element.element) {
    return element.element === TYPES.MEMBER;
  }

  return element === TYPES.MEMBER;
}

function getValueType({element, content}) {
  if (isMember(element)) {
    return content.value.element;
  }

  return element;
}

function getType(element) {
  if (isMember(element.element)) {
    return getValueType(element);
  }

  return element.element;
}

function isObject(element) {
  if (!element) {
    return false;
  }

  if (element.element) {
    return getType(element) === TYPES.OBJECT;
  }

  return element === TYPES.OBJECT;
}

function isArray(element) {
  if (!element) {
    return false;
  }

  if (element.element) {
    return getType(element) === TYPES.ARRAY;
  }

  return element === TYPES.ARRAY;
}

function isEnum(element) {
  if (element.element) {
    return getType(element) === TYPES.ARRAY;
  }

  return element === TYPES.ENUM;
}

function isNestedObject(element) {
  return isObject(element) || isArray(element) || isEnum(element);
function hasSamples(element) {
  const attributes = element.attributes;

  let samples = null;

  if (attributes) {
    return !!attributes.samples;
  } else {
    return false;
  }
}
}

export {
  getValueType,
  getType,
  isMember,
  isEnum,
  isObject,
  isArray,
  isNestedObject,
  hasSamples,
};

Add a new helper ‘hasSamples.’


import Koa from 'koa'
import bodyParser from 'koa-bodyparser'
import convert from 'koa-convert'
import logger from 'koa-logger'
import mongoose from 'mongoose'
import session from 'koa-generic-session'
import passport from 'koa-passport'
import mount from 'koa-mount'
import serve from 'koa-static'

import config from '../config'
import { errorMiddleware } from '../src/middleware'

const app = new Koa()
app.keys = [config.session]

mongoose.connect(config.database)

app.use(convert(logger()))
app.use(convert(bodyParser()))
app.use(convert(session()))
app.use(errorMiddleware())

app.use(convert(mount('/docs', serve(`${process.cwd()}/docs`))))

require('../config/passport')
app.use(passport.initialize())
app.use(passport.session())

const router = require('../src/controllers')
router(app)

app.listen(config.port, () => {
  console.log(`Server started on ${config.port}`)
})

export default app

import Koa from 'koa'
import bodyParser from 'koa-bodyparser'
import convert from 'koa-convert'
import logger from 'koa-logger'
import mongoose from 'mongoose'
import session from 'koa-generic-session'
import passport from 'koa-passport'
import mount from 'koa-mount'
import serve from 'koa-static'

import config from '../config'
import { errorMiddleware } from '../src/middleware'

const app = new Koa()
app.keys = [config.session]

mongoose.connect(config.database)

app.use(convert(logger()))
app.use(convert(bodyParser()))
app.use(convert(session()))
app.use(errorMiddleware())

app.use(convert(mount('/docs', serve(`${process.cwd()}/docs`))))

require('../config/passport')
app.use(passport.initialize())
app.use(passport.session())

const modules = require('../src/modules')
modules(app)

app.listen(config.port, () => {
  console.log(`Server started on ${config.port}`)
})

export default app

Change router import to module init


var cubes, list, math, num, number, opposite, race, square,
    __slice = [].slice;

number = 42;

opposite = true;

if (opposite) {
  number = -42;
}

square = function(x) {
  return x * x;
};

list = [1, 2, 3, 4, 5];

math = {
  root: Math.sqrt,
  square: square,
  cube: function(x) {
    return x * square(x);
  }
};

race = function() {
  var runners, winner;
  winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  return print(winner, runners);
};

if (typeof elvis !== "undefined" && elvis !== null) {
  alert("I knew it!");
}

cubes = (function() {
  var _i, _len, _results;
  _results = [];
  for (_i = 0, _len = list.length; _i < _len; _i++) {
    num = list[_i];
    _results.push(math.cube(num));
  }
  return _results;
})();

Update expected output to match what is actually generated by coffeescript


const {join, resolve} = require('path');

const {CheckerPlugin} = require('awesome-typescript-loader');

const loaders = require('./webpack/loaders');

module.exports = {
  target: 'node',
  entry: {
    server: ['./server/index.ts'],
  },
  output: {
    filename: 'index.js',
    path: resolve(join(__dirname, 'dist-server')),
    libraryTarget: 'commonjs2',
  },
  devtool: 'source-map',
  resolve: {
    extensions: ['.ts', '.js', '.json'],
  },
  module: {
    rules: [
      loaders.tsjit,
      loaders.html,
      loaders.css
    ]
  },
  plugins: [
    new CheckerPlugin(),
  ],
  externals: [
    '@angular/cli',
    '@angular/common',
    '@angular/compiler',
    '@angular/compiler-cli',
    '@angular/core',
    '@angular/forms',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/router',
    '@angular/tsc-wrapped',
    '@angular/service-worker',
    'angular-ssr',
    function(context, request, callback) {
      const exclusions = [/\@ngrx/, /rxjs/, /zone\.js/, /reflect-metadata/];

      if (exclusions.some(expr => expr.test(request))) {
        callback(null, `commonjs ${request.replace(/^.*?(\\|\/)node_modules(\\|\/)/, String())}`);
      }
      else {
        callback();
      }
    },
  ],
  node: {
    __dirname: true,
    __filename: true
  }
};

const {join, resolve} = require('path');

const {CheckerPlugin} = require('awesome-typescript-loader');

const loaders = require('./webpack/loaders');

module.exports = {
  target: 'node',
  entry: {
    server: ['./server/index.ts'],
  },
  output: {
    filename: 'index.js',
    path: resolve(join(__dirname, 'dist-server')),
    libraryTarget: 'commonjs2',
  },
  devtool: 'source-map',
  resolve: {
    extensions: ['.ts', '.js', '.json'],
  },
  module: {
    rules: [
      loaders.tsjit,
      loaders.html,
      loaders.css
    ]
  },
  plugins: [
    new CheckerPlugin(),
  ],
  externals: [
    '@angular/cli',
    '@angular/common',
    '@angular/compiler',
    '@angular/compiler-cli',
    '@angular/core',
    '@angular/forms',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/router',
    '@angular/tsc-wrapped',
    '@angular/service-worker',
    'angular-ssr',
    'express',
    function(context, request, callback) {
      const exclusions = [/\@ngrx/, /rxjs/, /zone\.js/, /reflect-metadata/];

      if (exclusions.some(expr => expr.test(request))) {
        callback(null, `commonjs ${request.replace(/^.*?(\\|\/)node_modules(\\|\/)/, String())}`);
      }
      else {
        callback();
      }
    },
  ],
  node: {
    __dirname: true,
    __filename: true
  }
};

Add express to externals list in demand-express


import React, { Component, PropTypes } from 'react';

import '../../styles/search-form.css';

class SearchForm extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      keyword: props.keyword ? props.keyword : ''
    };
  }

  componentWillReceiveProps(nextProps) {
    const keyword = nextProps.keyword ? nextProps.keyword : '';
    this.setState({
      keyword
    });
  }

  handleSubmit = (e) => {
    e.preventDefault();
    const onSearch = this.props.onSearch;
    onSearch(this.state.keyword);
  };

  handleChange = (e) => {
    const keyword = e.target.value.substring(0,20);
    this.setState({
      keyword
    });
  };

  render() {
    const onSearch = this.props.onSearch;
    return (
      <div className="search-form">
        <form onSubmit={this.handleSubmit}>
          <input
            type="text"
            value={this.state.keyword}
            onChange={this.handleChange}
          />
          <input type="submit" value="Search" />
        </form>
      </div>
    );
  }
}

SearchForm.propTypes = {
  keyword: PropTypes.string,
  onSearch: PropTypes.func.isRequired
};

export default SearchForm;

import React, { Component, PropTypes } from 'react';

import '../../styles/search-form.css';

class SearchForm extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      keyword: props.keyword ? props.keyword : '',
      timer: -1
    };
  }

  componentWillReceiveProps(nextProps) {
    const keyword = nextProps.keyword ? nextProps.keyword : '';
    this.setState({
      keyword
    });
  }

  handleSubmit = (e) => {
    if(e) {
      e.preventDefault();
    }

    this.clearTimer();

    // Execute searching
    const onSearch = this.props.onSearch;
    onSearch(this.state.keyword);
  };

  handleChange = (e) => {
    const keyword = e.target.value.substring(0,20);

    this.clearTimer();
    const timer = setTimeout(() => {
      this.handleSubmit(null);
    }, 2000);

    this.setState({
      timer,
      keyword
    });
  };

  clearTimer() {
    // Clear the timeout if exists
    if (this.state.timer > 0) {
      clearTimeout(this.state.timer);
      this.setState({
        timer: -1
      });
    }
  }

  render() {
    const onSearch = this.props.onSearch;
    return (
      <div className="search-form">
        <form onSubmit={this.handleSubmit}>
          <input
            type="text"
            value={this.state.keyword}
            onChange={this.handleChange}
          />
          <input type="submit" value="Search" />
        </form>
      </div>
    );
  }
}

SearchForm.propTypes = {
  keyword: PropTypes.string,
  onSearch: PropTypes.func.isRequired
};

export default SearchForm;

Add timer and auto submit to the search form


import * as React from 'react';
import {getField} from "./utils/getField";

/**
 * Main List Element to be displayed on the Navigation.
 *
 * @param {Object} props
 * @param {string} props.href hyperlink for the href attribute.
 * @param {string} props.innerText rendered text content of node.
 */
const NavigationItem = (props) => {
  return (

      {props.innerText}

  );
}

/**
  * Main Navigation List.
  * Instance will be embedded in ./Header component.
  *
  * @param {Object} props
  * @param {Object} props.options an array of navigation options.
  * @param {string} props.options[].link an external URL attached to option.
  * @param {string} props.options[].text the displayed text for the option.
  */
export const Navigation = (props) => {
  const options = getField(props, 'options', []);

  return (

      {options.map ((option, idx) =>
          <NavigationItem key={idx} href={option.link} innerText={option.text}/>
      )}

  );
}

Add target and rel attributes to a tags


/**
 * FCViz
 * Payload script for the individual loan iframe within the Sell page
 */
var app = angular.element(document.querySelector("div"));
var $scope = app.scope();
var SellableLoanParts = app.injector().get("SellableLoanParts");

$scope.updateSaleInfoAll = function (loanPart) {

  function removeFromArray(arr, e) {
    var index = arr.indexOf(e);
    if (index != -1) {
      arr.splice(index, 1);
    }
  }

  function makeDroppedText(dropped) {
    var msg = "The following loan parts were deselected because\n" +
              "the premium of " + premium + "% is too high,\n" +
              "making the buyer rate below " + minBuyerRate + "%:\n\n";
    angular.forEach(dropped, function(d){
      msg += d.id + " " + d.loan_title + ": " + d.buyer_rate + "%\n";
    });
    return msg;
  }

  var dropped = [], toQuery = [], minBuyerRate = 0, premium = loanPart.markup;
  var callback = function (thisPart, response){
    thisPart.sale_price = response.data.sale_price;
    thisPart.buyer_rate = response.data.buyer_rate;
    thisPart.markup = premium;
    if (minBuyerRate < response.data.meta.min_buyer_rate) {
      minBuyerRate = response.data.meta.min_buyer_rate;
    }
    if (thisPart.buyer_rate < minBuyerRate) {
      thisPart.sell = false;
      thisPart.sellable = false;
      removeFromArray($scope.loanPartsToBeSold, thisPart);
      dropped.push(thisPart);
    }

    removeFromArray(toQuery, thisPart);
    if (toQuery.length == 0) {
      $scope.totals = SellableLoanParts.toBeSoldTotals($scope.loanPartsToBeSold);
      if (dropped.length > 0) {
        window.alert(makeDroppedText(dropped));
      }
    }
  };

  angular.forEach($scope.loanParts, function(thisPart){
    if ($scope.loanPartsToBeSold.indexOf(thisPart) != -1 && thisPart.id !== loanPart.id) {
      toQuery.push(thisPart);
      SellableLoanParts.getSaleInfo(thisPart.id, premium).then(callback.bind(this, thisPart));
    }
  });
}

Implement the bulk of updateSaleInfoAll


const {PUSH, POP, REPLACE} = require('../constants/navigation');

module.exports = function navigate(state, {type, payload}) {
  if (!state) {
    return {};
  }

  const stack = state.__navRedux.stack;
  const index = state.__navRedux.index;

  switch (type) {
    case PUSH:
      return Object.assign({}, state, {
        __navRedux: {
          stack: stack.push(payload),
          index: 0,
        },
      });

    case POP:
      if (stack.count() === 1) {
        return state;
      }

      return Object.assign({}, state, {
        __navRedux: {
          stack: stack.shift(),
          index: 0,
        },
      });

    case REPLACE:
      if (!stack.count()) {
        return state;
      }

      return Object.assign({}, state, {
        stack: stack.splice(index, 1, payload),
        index: index,
      });

    default:
      return state;
  }
};

const {PUSH, POP, REPLACE} = require('../constants/navigation');

module.exports = function navigate(state, {type, payload}) {
  if (!state) {
    return {};
  }

  const stack = state.stack;
  const index = state.index;

  switch (type) {
    case PUSH:
      return Object.assign({}, state, {
        stack: stack.push(payload),
        index: 0,
      });

    case POP:
      if (stack.count() === 1) {
        return state;
      }

      return Object.assign({}, state, {
        stack: stack.shift(),
        index: 0,
      });

    case REPLACE:
      if (!stack.count()) {
        return state;
      }

      return Object.assign({}, state, {
        stack: stack.splice(index, 1, payload),
        index: index,
      });

    default:
      return state;
  }
};

Remove extra wrapper for nav state


// Define the tour!
var tour = {
  id: "hello-hopscotch",
  steps: [
    {
      title: "Pick Your Level",
      content: "These are the different lessons you can choose from. Every time you complete a lesson, it will turn green",
      target: "navbar_popup",
      placement: "bottom"
    },
    {
      title: "Information",
      content: "Here is information about each topic you will be learning",
      target: "instruction-template",
      placement: "bottom"
    },
    {
      title: "Terminal",
      content: "Type your responses here and press enter to move on to the next level",
      target: "terminal_popup",
      placement: "top"
    },
    {
      title: "Finder",
      content: "This is your finder that will update when you type commands in the terminal.",
      target: "popup-folder",
      placement: "bottom" //maybe change
    }
  ]
};

// Start the tour!
if (localStorage.lessons == ""){
    hopscotch.startTour(tour);
}

// Define the tour!
var tour = {
  id: "hello-hopscotch",
  steps: [
    {
      title: "Pick Your Level",
      content: "These are the different lessons you can choose from. Every time you complete a lesson, it will turn green",
      target: "navbar_popup",
      placement: "bottom"
    },
    {
      title: "Information",
      content: "Here is information about each topic you will be learning",
      target: "instruction-template",
      placement: "bottom"
    },
    {
      title: "Task",
      content: "Complete each task specified here",
      target: "popup_task",
      placement: "bottom"
    },
    {
      title: "Terminal",
      content: "Type your responses here and press enter to move on to the next level",
      target: "terminal_popup",
      placement: "top"
    },
    {
      title: "Finder",
      content: "This is your finder that will update when you type commands in the terminal.",
      target: "popup-folder",
      placement: "bottom" //maybe change
    }
  ]
};

// Start the tour!
if (localStorage.lessons == ""){
    hopscotch.startTour(tour);
}

Add popup intro for task


define(['licensing/controllers/preprocessors/partial_experience_warning'],
function (preprocessor) {
  describe("Browser message pre-processor", function () {
    afterEach(function () {
      $('#global-browser-prompt').remove();
    });

    it ("Should update the GOV.UK banner with performance platform content", function () {
      $('body').append('

Foo

');
      preprocessor();
      expect($('#global-browser-prompt').html()).toBe('
Your browser is unable to display some of the content on this page.

Foo
');
    });
  });
});

define(['licensing/controllers/preprocessors/partial_experience_warning'],
function (preprocessor) {
  describe("Browser message pre-processor", function () {
    afterEach(function () {
      $('#global-browser-prompt').remove();
      $('html').removeClass('lte-ie8');
    });

    it ("Should update the GOV.UK banner with performance platform content", function () {
      $('html').addClass('lte-ie8');
      $('body').append('

Foo

');
      preprocessor();
      expect($('#global-browser-prompt').html()).toBe('
Your browser is unable to display some of the content on this page.

Foo
');
    });

    it ("Should not update the GOV.UK banner when on newer browsers", function () {
      // default state = not lte-ie8 class on html tag
      $('body').append('

Foo

');
      preprocessor();
      expect($('#global-browser-prompt').html()).toBe('
Foo
');
    });
  });
});

Fix test to make it look like old ie browser


(function(){
  "use strict";
  xtag.register("sam-tabbar", {
    lifecycle: {
      created: function() {
        if (!this.role) {
          this.role = "tablist";
        }
      },
      inserted: function() {
        this.activeTabId = this.querySelector("[data-start-active]").id;
      },
      removed: function() {},
      attributeChanged: function() {}
    },
    events: {
      "press": function (event) {
        var el = event.originalTarget,
            eventName = "activeTabPress";
        //Checks if a tab was pressed
        if (!el || el.getAttribute("role") !== "tab") return;
        var tabid = el.id;
        //Checks if the active tab wasn't pressed
        if (this.activeTabId !== tabid) {
          document.getElementById(this.activeTabId).dataset.active = false;
          this.activeTabId = tabid;
          document.getElementById(this.activeTabId).dataset.active = true;
          eventName = "tabChange";
        }
        xtag.fireEvent(this, eventName, {detail: this.activeTabId});
      }
    },
    accessors: {
      role: {
        attribute: {}
      }
    },
    methods: {

    }
  });

})();

(function(){
  "use strict";
  xtag.register("sam-tabbar", {
    lifecycle: {
      created: function() {
        if (!this.role) {
          this.role = "tablist";
        }
      },
      inserted: function() {
        this.activeTabId = this.querySelector("[role='tab'][data-start-active]").id;
      },
      removed: function() {},
      attributeChanged: function() {}
    },
    events: {
      "press": function (event) {
        var el = event.originalTarget,
            eventName = "activeTabPress";
        //Checks if a tab was pressed
        if (!el || el.getAttribute("role") !== "tab") return;
        var tabid = el.id;
        //Checks if the active tab wasn't pressed
        if (this.activeTabId !== tabid) {
          document.getElementById(this.activeTabId).dataset.active = false;
          this.activeTabId = tabid;
          document.getElementById(this.activeTabId).dataset.active = true;
          eventName = "tabChange";
        }
        xtag.fireEvent(this, eventName, {detail: this.activeTabId});
      }
    },
    accessors: {
      role: {
        attribute: {}
      }
    },
    methods: {

    }
  });

})();

Make active tab rules stricter


var express = require('express');
var router = express.Router();

var items = [
  { name: 'item 1' },
  { name: 'item 2' },
  { name: 'item 3' }
];

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('items', { title: 'Item List', items: items });
});

module.exports = router;

var express = require('express');
var router = express.Router();

var items = [
  { name: 'item 1' },
  { name: 'item 2' },
  { name: 'item 3' }
];

var auth = function(req, res, next) {
  var name = req.query.name;
  if(name === 'Dan') {
    next();
  } else {
    var err = new Error('Unauthorized');
    err.status = 403;
    next(err);
  }
};

router.use('/', function(req, res, next) {
  console.log('hit!');
  next();
});

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('items', { title: 'Item List', items: items });
});

router.get('/protected', auth, function(req, res, next) {
  res.render('items', { title: 'Protected Item List', items: items });
});

module.exports = router;

Add “auth” functionality for a protected endpoint


var io;
var connections = {};

var events = {
  init: function(data) {
    connections[data.userToken] = this;
    this.emit('init');
  },

  update: function() {
    console.log('user updated');
  },

  disconnect: function() {
    console.log('user disconnected');
  }
};

exports.initialize = function(server) {
  io = server;
  io.on('connection', function(socket) {
    for (var e in events) {
      socket.on(e, events[e]);
    }
  });
};

var models = require('../db/models.js');
var io;
var connections = {};

var events = {
  //input: {userToken: string}
  init: function(data) {
    connections[data.userToken] = this;
    this.emit('init');
  },

  //input: {userToken: string, messageId: string}
  upvote: function(data) {
    models.createVote(data)
    .then(function(success) {
      return models.retrieveUserScore(data.userToken);
    }).then(function(user) {
      exports.sendUserScore(user[0]);
    });
  },

  disconnect: function() {
    console.log('user disconnected');
  }
};

exports.initialize = function(server) {
  io = server;
  io.on('connection', function(socket) {
    for (var e in events) {
      socket.on(e, events[e]);
    }
  });
};

exports.sendUserScore = function(user) {
  connections[user.token].emit('score', {score: user.total_votes});
};

Add upvote event to socket handler


import { GraphQLString, GraphQLBoolean } from 'graphql';

import { Page } from '../models';

const setPage = {
  type: GraphQLBoolean,
  args: {
    id: { type: GraphQLString },
    accessToken: { type: GraphQLString },
    name: { type: GraphQLString },
  },
  async resolve(fieldName, args, context, { rootValue: { request } }) {
    if (!request.user || !request.user.admin) {
      return false;
    }

    await Page.destroy({ where: {} });
    const page = await Page.create(args);

    if (page) {
      return true;
    } else {
      return false;
    }
  },
}

export default setPage;

import { GraphQLString, GraphQLBoolean } from 'graphql';

import fetch from 'node-fetch';
import { auth as config } from '../../config';
import { Page } from '../models';

const setPage = {
  type: GraphQLBoolean,
  args: {
    id: { type: GraphQLString },
    accessToken: { type: GraphQLString },
    name: { type: GraphQLString },
  },
  async resolve(fieldName, { id, accessToken, name }, context, { rootValue: { request } }) {
    if (!request.user || !request.user.admin) {
      return false;
    }

    await Page.destroy({ where: {} });

    // https://graph.facebook.com/oauth/access_token?client_id=576248362575567&client_secret=cc0208ef35d7bee877d6af59bc2123d8&grant_type=fb_exchange_token&fb_exchange_token=${accessToken}
    // Exchange short-token to long-token.
    const response = await fetch(`https://graph.facebook.com/oauth/access_token?client_id=${config.facebook.id}&client_secret=${config.facebook.secret}&grant_type=fb_exchange_token&fb_exchange_token=${accessToken}`)
      .then((res) => {
        return res.text();
      });

    const result = response
      .split('&')
      .map((parameterBundle) => {
        const parameterPair = parameterBundle.split('=');

        let returnObject = {};
        returnObject[parameterPair[0]] = parameterPair[1];

        return returnObject;
      });

    const page = await Page.create({
      id: id,
      accessToken: result.access_token,
      name: name,
    });

    if (page) {
      return true;
    } else {
      return false;
    }
  },
}

export default setPage;

Store page information, access token need to be transform to long term access token.


"use strict";
/* eslint-disable import/no-unresolved */
/* eslint-disable no-console */
import mongoose from 'mongoose';
import chalk from 'chalk';
import bluebird from 'bluebird';

const connectDB = () => {
  mongoose.Promise = bluebird;

  if (process.env.NODE_ENV !== 'test') {
    // Connect to MongoDB
    mongoose.connect(process.env.MONGODB_URI, { promiseLibrary: bluebird });

    //============================
    // CONNECTION EVENT LISTENERS
    //============================

    // When successfully connected
    mongoose.connection.on('connected', () => {
      if (process.env.NODE_ENV === 'development') {
        console.log(chalk.green('Mongoose connection open to'), chalk.blue(process.env.MONGODB_URI));
      } else {
        console.log(chalk.green('Mongoose connection'), chalk.blue('OPEN'));
      }
    });
    // If the connection throws an error
    mongoose.connection.on('error', err => {
      console.log(chalk.red('Mongoose connection error:', err));
    });
    // When the connection is disconnected
    mongoose.connection.on('disconnected', () => {
      console.log(chalk.yellow('\nMongoose connection disconnected'));
    });
    // If the Node process ends, close the Mongoose connection
    process.on('SIGINT', () => {
      mongoose.connection.close(() => {
        console.log(chalk.yellow('Mongoose connection disconnected through app termination'));
        process.exit(0);
      });
    });
  }
};

export default connectDB;

"use strict";
/* eslint-disable import/no-unresolved */
/* eslint-disable no-console */
import mongoose from 'mongoose';
import chalk from 'chalk';
import bluebird from 'bluebird';

const connectDB = () => {
  mongoose.Promise = bluebird;

  if (process.env.NODE_ENV !== 'test') {
    // Connect to MongoDB
    mongoose.connect(process.env.MONGODB_URI, { promiseLibrary: bluebird, useMongoClient: true });

    //============================
    // CONNECTION EVENT LISTENERS
    //============================

    // When successfully connected
    mongoose.connection.on('connected', () => {
      if (process.env.NODE_ENV === 'development') {
        console.log(chalk.green('Mongoose connection open to'), chalk.blue(process.env.MONGODB_URI));
      } else {
        console.log(chalk.green('Mongoose connection'), chalk.blue('OPEN'));
      }
    });
    // If the connection throws an error
    mongoose.connection.on('error', err => {
      console.log(chalk.red('Mongoose connection error:', err));
    });
    // When the connection is disconnected
    mongoose.connection.on('disconnected', () => {
      console.log(chalk.yellow('\nMongoose connection disconnected'));
    });
    // If the Node process ends, close the Mongoose connection
    process.on('SIGINT', () => {
      mongoose.connection.close(() => {
        console.log(chalk.yellow('Mongoose connection disconnected through app termination'));
        process.exit(0);
      });
    });
  }
};

export default connectDB;

Add a new key/pair to mongoose connect options to fix deprecation warning