import semver from 'semver';

const {major, minor, patch} = semver.parse(atom.appVersion);
const atomVersion = `${major}.${minor}.${patch}`;
const requiredVersion = '>=1.13.0';

if (atom.inDevMode() || atom.inSpecMode() || semver.satisfies(atomVersion, requiredVersion)) {
  module.exports = startPackage();
} else {
  module.exports = versionMismatch();
}

function versionMismatch() {
  return {
    activate: () => {
      atom.notifications.addWarning('Incompatible Atom Version', {
        description: `The GitHub packages requires Atom ${requiredVersion}. You are running ${atomVersion}.`,
        dismissable: true,
      });
    },
  };
}

function startPackage() {
  const GithubPackage = require('./github-package').default;

  return new GithubPackage(
    atom.workspace, atom.project, atom.commands, atom.notifications,
  );
}

const semver = require('semver');

const {major, minor, patch} = semver.parse(atom.appVersion);
const atomVersion = `${major}.${minor}.${patch}`;
const requiredVersion = '>=1.13.0';

if (atom.inDevMode() || atom.inSpecMode() || semver.satisfies(atomVersion, requiredVersion)) {
  module.exports = startPackage();
} else {
  module.exports = versionMismatch();
}

function versionMismatch() {
  return {
    activate: () => {
      atom.notifications.addWarning('Incompatible Atom Version', {
        description: 'The GitHub packages requires Atom ' + requiredVersion +
          '. You are running ' + atomVersion + '. Please check for updates and try again.',
        dismissable: true,
      });
    },
  };
}

function startPackage() {
  const GithubPackage = require('./github-package').default;

  return new GithubPackage(
    atom.workspace, atom.project, atom.commands, atom.notifications,
  );
}

Fix an atom version check oopsie

Fix an atom version check oopsie


#! /usr/bin/env node
"use strict";

var argv = require("optimist").argv;
var pjson = require("../package.json");
var defaultConfig = require("./default-config");
var cliUtils = require("./cli").utils;
var cliInfo = require("./cli-info").info;

/**
 * Handle Command-line usage
 */
if (require.main === module) {
    if (argv.version || argv.v) {
        return cliInfo.getVersion(pjson);
    }
    if (argv._[0] === "init") {
        return cliInfo.makeConfig();
    }
    var config   = cliUtils.getConfig(defaultConfig, argv),
        filesArg = cliUtils.getFilesArg(argv, config),
        files    = cliUtils.getFiles(filesArg);
    if (config.exclude) {
        files = cliUtils.mergeFiles(files, config.exclude);
    }
    cliUtils._start(files, config, pjson.version);
}

/**
 * @param {String|Array} [files]
 * @param {Object} [userConfig]
 */
module.exports.init = function (files, userConfig) {
    var config = defaultConfig;
    if (userConfig) {
        config = cliUtils.mergeConfigObjects(defaultConfig, userConfig || {});
        if (files && userConfig.exclude) {
            files = cliUtils.mergeFiles(files, userConfig.exclude);
        }
    }
    return cliUtils._start(files, config, pjson.version);
};

#! /usr/bin/env node
"use strict";

var argv = require("optimist").argv;
var pjson = require("../package.json");
var defaultConfig = require("./default-config");
var cliUtils = require("./cli").utils;
var cliInfo = require("./cli-info").info;

/**
 * Handle Command-line usage
 */
if (require.main === module) {
    if (argv.version || argv.v) {
        return cliInfo.getVersion(pjson);
    }
    if (argv._[0] === "init") {
        return cliInfo.makeConfig();
    }
    var config   = cliUtils.getConfig(defaultConfig, argv),
        filesArg = cliUtils.getFilesArg(argv, config),
        files    = cliUtils.getFiles(filesArg);
    if (config.exclude) {
        files = cliUtils.mergeFiles(files, config.exclude);
    }
    cliUtils._start(files, config, pjson.version);
}

/**
 * Return init method for external use
 * @param {String|Array} [files]
 * @param {Object} [userConfig]
 */
module.exports.init = function (files, userConfig) {
    var config = defaultConfig;
    if (userConfig) {
        config = cliUtils.mergeConfigObjects(defaultConfig, userConfig || {});
        if (files && userConfig.exclude) {
            files = cliUtils.mergeFiles(files, userConfig.exclude);
        }
    }
    return cliUtils._start(files, config, pjson.version);
};

Use read stream to ensure file is greater than 0 bytes


var Mehdown;

if (typeof exports === 'object' && typeof require === 'function') {
    Mehdown = exports;
}
else {
    Mehdown = {};
}

Mehdown.usernameRegExp = /(^|[^@\w])@(\w{1,15})\b/g;

Mehdown.parse = function(text) {
	// Hashtags
	text = text.replace(/(^|[^#\w])#([a-z0-9_-]+)\b/gi, '$1' + Mehdown.hashtag('$2'));

	// Usernames
	text = text.replace(Mehdown.usernameRegExp, '$1' + Mehdown.username('$2'));

	return text;
};

Mehdown.hashtag = function(hashtag) {
	return '#' + hashtag + '';
}

Mehdown.username = function(username) {
	//return '@' + username + '';
	return '@' + username + '';
}

var Mehdown;

if (typeof exports === 'object' && typeof require === 'function') {
    Mehdown = exports;
}
else {
    Mehdown = {};
}

Mehdown.usernameRegExp = /(^|[^@\w])@(\w{1,15})\b/g;

Mehdown.parse = function(text) {
    // Replace newlines with
 tags
    text = text.replace(/\n/g, '
\n');

    // Hashtags
    text = text.replace(/(^|[^#\w])#([a-z0-9_-]+)\b/gi, '$1' + Mehdown.hashtag('$2'));

    // Usernames
    text = text.replace(Mehdown.usernameRegExp, '$1' + Mehdown.username('$2'));

    return text;
};

Mehdown.hashtag = function(hashtag) {
    return '#' + hashtag + '';
}

Mehdown.username = function(username) {
    //return '@' + username + '';
    return '@' + username + '';
}

Replace newlines with <br /> tags

Replace newlines with <br /> tags


/*jshint browser:true, node:true*/

'use strict';

/**
 * @preserve Create and manage a DOM event delegator.
 *
 * @version 0.3.0
 * @codingstandard ftlabs-jsv2
 * @copyright The Financial Times Limited [All Rights Reserved]
 * @license MIT License (see LICENSE.txt)
 */
var Delegate = require('./delegate');

module.exports = function(root) {
  return new Delegate(root);
};

module.exports.Delegate = Delegate;

/*jshint browser:true, node:true*/

'use strict';

/**
 * @preserve Create and manage a DOM event delegator.
 *
 * @codingstandard ftlabs-jsv2
 * @copyright The Financial Times Limited [All Rights Reserved]
 * @license MIT License (see LICENSE.txt)
 */
var Delegate = require('./delegate');

module.exports = function(root) {
  return new Delegate(root);
};

module.exports.Delegate = Delegate;

Remove version out of date version number


var email = new (require('./emailer'))(),
  backdrop = new (require('./integrations/backdrop'))(),
  stagecraft = new (require('./integrations/stagecraft'))(),
  message = new (require('./message'))(),
  Q = require('q'),
  queue = [];

// Query backdrop for out of date datasets
backdrop.getDataSets().then(function (data) {
  // console.log('datasets', data);
  // Got some datasets, now find emails for them
  data.data_sets.forEach( function (dataSet) {

    // Set email message
    dataSet.message = message.dataSetReminder(dataSet);

    // Queue up email query for this dataset
    queue.push(stagecraft.queryEmail(dataSet));
  });

  // When all the email queries are finished, send some notifications
  return Q.all(queue).then( function (dataSets) {
    console.log(dataSets);
    // email.send({
    //   to: config.notificationsEmail,
    //   subject: 'Datasets out of date',
    //   text: 'There are ' + data.message + '\n\n' + JSON.stringify(data.data_sets)
    // });
  });
}).fail(function (err) {
  throw err;
}).done();

var email = new (require('./emailer'))(),
  backdrop = new (require('./integrations/backdrop'))(),
  stagecraft = new (require('./integrations/stagecraft'))(),
  message = new (require('./message'))(),
  Q = require('q'),
  queue = [];

// Query backdrop for out of date datasets
backdrop.getDataSets().then(function (data) {
  // console.log('datasets', data);
  // Got some datasets, now find emails for them
  data.data_sets.forEach( function (dataSet) {

    // Set email message
    dataSet.message = message.dataSetReminder(dataSet);

    // Queue up email query for this dataset
    queue.push(stagecraft.queryEmail(dataSet));
  });

  // When all the email queries are finished, send some notifications
  return Q.all(queue).then( function (dataSets) {
    console.log(dataSets);
    dataSets.forEach( function (dataSet) {
      email.send({
        to: dataSet.emails.toString(),
        subject: 'Datasets out of date',
        text: dataSet.message
      });
    });
  });
}).fail(function (err) {
  throw err;
}).done();

Send emails once we have them

Send emails once we have them


// Apply login on current session and change session id for security reasons.

'use strict';

var rnd = require('nodeca.core/lib/rnd');

module.exports = function login(env, userId) {
  env.session.user_id = userId;
  env.origin.req.sid = rnd(); // Generate cryptostrong random hex string.
};

// Apply login on current session and change session id for security reasons.

'use strict';

var rnd = require('nodeca.core/lib/rnd');

module.exports = function login(env, userId) {
  env.session.user_id = userId;
  env.session_id = rnd(); // Generate cryptostrong random hex string.
};

Use `env.session_id` instead of deprecated `req.sid`.


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

@connect(state => ({ tickTrade: state.tickTrade }))
export default class TickTradePane extends React.Component {

	render() {
		return (
			<div>
			</div>
		);
	}
}

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

@connect(state => ({ tickTrade: state.tickTrade }))
export default class TickTradePane extends React.Component {

	render() {
		return (

					<button>Change Time Settings</button>
					<fieldset>
						USD/JPY will RISE over next 5 ticks
					</fieldset>

CHART HERE

					<fieldset>
						Payout: USD<input type="number" defaultValue={15} /> <button>+</button><button>-</button>
					</fieldset>
					<fieldset>
						Price: USD 7.1<button>Buy!</button>
					</fieldset>

Buy Price	7.1

Final Price	15

Profit	7.3

Account Balance	45.53

					Select Underlying
					<fieldset>
						<button>Forex</button><button>Randoms</button>
					</fieldset>
					USD/JPY
					Select Trade
					<fieldset>
						<button>Up</button><button>Down</button><button>Digit Match</button><button>Digit Differs</button>
					</fieldset>
					<fieldset>
						No. ticks:<input type="number" defaultValue={5} /> <button>+</button><button>-</button>
					</fieldset>
					Select Amount
					<fieldset>
						<button>Payout</button><button>Stake</button>
					</fieldset>
					USD<input type="number" defaultValue={15} />
					<fieldset>
						<button>Save</button>
					</fieldset>

		);
	}
}

Add html code implementing the mockups for trading


// @flow
import {createSelector} from 'reselect'

import selectCurrentBundle from './current-bundle'

export default createSelector(
  (state) => state.scenario.feeds,
  selectCurrentBundle,
  (feeds, bundle) => feeds.map((feed) => {
    const bundleFeed = bundle && bundle.feeds
      .find(({feedId}) => feedId === feed.id)
    return bundleFeed
      ? {...feed, name: bundleFeed.name}
      : {...feed, name: feed.checksum}
  })
)

// @flow
import {createSelector} from 'reselect'

import selectCurrentBundle from './current-bundle'

export default createSelector(
  (state) => state.scenario.feeds,
  selectCurrentBundle,
  (feeds, bundle) => feeds.map((feed) => {
    const bundleFeed = bundle && bundle.feeds
      .find(({feedId}) => feedId === feed.id)
    return bundleFeed
      ? {...feed, name: bundleFeed.name}
      : {...feed, name: feed.id}
  })
)

fix(feeds): Use feed id instead of checksum as back up feed name.


var Serializer = require("./serialization/serializer").Serializer,
    serialize = require("./serialization/serializer").serialize,
    Deserializer = require("./deserialization/deserializer").Deserializer,
    deserialize = require("./deserialization/deserializer").deserialize;

exports.Serializer = Serializer;
exports.serialize = serialize;

exports.Deserializer = Deserializer;
exports.deserialize = deserialize;

var serializer = require("./serialization/serializer"),
    deserializer = require("./deserialization/deserializer");

exports.Serializer = serializer.Serializer;
exports.serialize = serializer.serialize;

exports.Deserializer = deserializer.Deserializer;
exports.deserialize = deserializer.deserialize;

Make the root requires a bit nicer

Make the root requires a bit nicer


// @license
// Copyright (c) 2017 Google Inc. All rights reserved.
// This code may only be used under the BSD style license found at
// http://polymer.github.io/LICENSE.txt
// Code distributed by Google as part of this project is also
// subject to an additional IP rights grant found at
// http://polymer.github.io/PATENTS.txt
"use strict";

class ParticleExecutionContext {
  constructor() {
  }

  // Instantiates `particle` in this context, connecting `views` to the particle's inputs and outputs.
  // `mutateCallback` will be called each time the particle mutates a view or entity.
  // Returns an identifier to refer to the particle (in `dispatch`).
  instantiate(particle, views, mutateCallback) {
    // views => [[name, viewId]]
    // returns particleId
    throw 'unimplemented';
  }

  // Dispatches an event to the particle identified by `particleId` for the view or entity identified
  // by `entityId` concerning `eventDetails. The `complete` flag indicates whether there are any further
  // events to be dispatched to the same particle.
  dispatch(particleId, entityId, eventDetails, complete) {
    throw 'unimplemented';
  }

  // Returns a promise which resolves when the PEC becomes idle (no known input processing).
  get idle() {
    throw 'unimplemented';
  }

  // TODO: Where did relevance go?
}

module.exports = ParticleExecutionContext;

// @license
// Copyright (c) 2017 Google Inc. All rights reserved.
// This code may only be used under the BSD style license found at
// http://polymer.github.io/LICENSE.txt
// Code distributed by Google as part of this project is also
// subject to an additional IP rights grant found at
// http://polymer.github.io/PATENTS.txt
"use strict";

class ParticleExecutionContext {
  constructor() {
  }

  // Instantiates `particle` in this context, connecting `views` to the particle's inputs and outputs.
  // `mutateCallback` will be called each time the particle mutates a view or entity.
  // Returns an identifier to refer to the particle (in `dispatch`).
  instantiate(particle, views, mutateCallback) {
    // views => {name => viewId}
    throw 'unimplemented';
  }

  // Dispatches an event to the particle identified by `particleId` for the view or entity identified
  // by `entityId` concerning `eventDetails. The `morePending` flag indicates whether there are any
  // known further events to be dispatched to the same particle.
  dispatch(particleId, entityId, eventDetails, morePending) {
    throw 'unimplemented';
  }

  // Returns a promise which resolves when the PEC becomes idle (no known input processing).
  get idle() {
    throw 'unimplemented';
  }

  // Returns a promise which resolves to a map from particle identifier to a list of the relevance
  // entries generated by that particle.
  get relevance() {
    throw 'unimplemented';
  }
}

module.exports = ParticleExecutionContext;

Rename complete => morePending, add relevance getter


import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { openModal, closeModal } from '../../actions/modals'
import ConfirmDialog from '../dialogs/ConfirmDialog'
import { DragIcon, DeleteIcon } from './EditorIcons'

class RegionTools extends Component {

  static propTypes = {
    dispatch: PropTypes.func.isRequired,
  };

  closeModal = () => {
    const { dispatch } = this.props
    dispatch(closeModal())
  };

  deleteContentConfirmed = () => {
    // const { dispatch } = this.props
    this.closeModal()
    // dispatch(commentActions.deleteComment(comment))
  };

  handleDeleteBlock = () => {
    const { dispatch } = this.props
    dispatch(openModal(
      <ConfirmDialog
        title="Remove this content?"
        onConfirm={ this.deleteCommentConfirmed }
        onRejected={ this.closeModal }
      />))
  };

  render() {
    return (
      <div className="RegionTools">
        <button
          onClick={this.handleDeleteBlock}
        >
          <DeleteIcon />
        </button>
        <button>
          <DragIcon />
        </button>
      </div>
    )
  }
}

export default connect()(RegionTools)

import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { openModal, closeModal } from '../../actions/modals'
import ConfirmDialog from '../dialogs/ConfirmDialog'
import { DragIcon, DeleteIcon } from './EditorIcons'

class RegionTools extends Component {

  static propTypes = {
    dispatch: PropTypes.func.isRequired,
  };

  closeModal = () => {
    const { dispatch } = this.props
    dispatch(closeModal())
  };

  deleteContentConfirmed = () => {
    // const { dispatch } = this.props
    this.closeModal()
    // dispatch(commentActions.deleteComment(comment))
  };

  handleDeleteBlock = () => {
    const { dispatch } = this.props
    dispatch(openModal(
      <ConfirmDialog
        title="Remove this content?"
        onConfirm={ this.deleteContentConfirmed }
        onRejected={ this.closeModal }
      />))
  };

  render() {
    return (
      <div className="RegionTools">
        <button
          onClick={this.handleDeleteBlock}
        >
          <DeleteIcon />
        </button>
        <button>
          <DragIcon />
        </button>
      </div>
    )
  }
}

export default connect()(RegionTools)

Call through to the correct method

Call through to the correct method


const RSBuddy = `
	type RSBuddy {
		ts: String
		buyingPrice: Int
		buyingCompleted: Int
		sellingPrice: Int
		sellingCompleted: Int
		overallPrice: Int
		overallCompleted: Int
	}
`

export default RSBuddy

const RSBuddy = `
	type RSBuddy {
		ts: String
		buyingPrice: String
		buyingCompleted: String
		sellingPrice: String
		sellingCompleted: String
		overallPrice: String
		overallCompleted: String
	}
`

export default RSBuddy

Change ints to strings for Int32 errors

Change ints to strings for Int32 errors


pageflow.ConfigurationEditorView.register('video', {
  configure: function() {
    this.tab('general', function() {
      this.group('general');

      this.input('additional_title', pageflow.TextInputView);
      this.input('additional_description', pageflow.TextAreaInputView, {size: 'short'});
    });

    this.tab('files', function() {
      this.input('video_file_id', pageflow.FileInputView, {
        collection: pageflow.videoFiles,
        positioning: false
      });
      this.input('poster_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        positioning: false
      });
      this.input('thumbnail_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        positioning: false
      });
      this.input('mobile_poster_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        imagePositioning: false
      });
    });

    this.tab('options', function() {
      this.input('autoplay', pageflow.CheckBoxInputView);

      if (pageflow.features.isEnabled('auto_change_page')) {
        this.input('auto_change_page_on_ended', pageflow.CheckBoxInputView);
      }

      this.group('options');
    });
  }
});

pageflow.ConfigurationEditorView.register('video', {
  configure: function() {
    this.tab('general', function() {
      this.group('general');

      this.input('additional_title', pageflow.TextInputView);
      this.input('additional_description', pageflow.TextAreaInputView, {size: 'short'});
    });

    this.tab('files', function() {
      this.input('video_file_id', pageflow.FileInputView, {
        collection: pageflow.videoFiles,
        positioning: false
      });
      this.input('poster_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        positioning: false
      });
      this.input('thumbnail_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        positioning: false
      });
      this.input('mobile_poster_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        imagePositioning: false
      });
    });

    this.tab('options', function() {
      this.input('autoplay', pageflow.CheckBoxInputView);

      if (pageflow.features.isEnabled('auto_change_page')) {
        this.input('auto_change_page_on_ended', pageflow.CheckBoxInputView);
      }

      this.group('options', {canPauseAtmo: true});
    });
  }
});

Allow Pausing Atmo for Video Playback

Allow Pausing Atmo for Video Playback

Was missing in #332


var fs = require('fs');
var browserify = require('browserify');
var uglifyify = require('uglifyify');

var path = function (d) {
  var p = require('path');
  return p.resolve(__dirname, d);
};

var b = browserify({ cache: {}, entries: [path('../public/javascripts/index.js')], packageCache: {} });
b.transform({
    global: true,
    sourcemap: false
}, 'uglifyify');

var prod = function () {
  b.bundle().pipe(fs.createWriteStream(path('../public/javascripts/scripts.js')));
};

if (module.parent) {
  module.exports = prod;
} else {
  prod();
}

var fs = require('fs');
var browserify = require('browserify');
var uglifyify = require('uglifyify');

var path = function (d) {
  var p = require('path');
  return p.resolve(__dirname, d);
};

var b = browserify({ cache: {}, entries: [path('../public/javascripts/index.js')], packageCache: {} });
b.transform({
    global: true,
    sourcemap: false
}, uglifyify);

var prod = function () {
  b.bundle().pipe(fs.createWriteStream(path('../public/javascripts/scripts.js')));
};

if (module.parent) {
  module.exports = prod;
} else {
  prod();
}

Remove quotes to import uglifyify

Remove quotes to import uglifyify


import React from 'react';

import ChronosStore from '../../stores/ChronosStore';
import DescriptionList from '../../components/DescriptionList';

class JobRunHistoryTable extends React.Component {
  render() {
    let job = ChronosStore.getJobDetail(this.props.jobID);

    return (
      <DescriptionList
        hash={{
          Command: job.getCommand(),
          Schedule: job.getSchedule().schedule
        }} />
    );
  }
}

module.exports = JobRunHistoryTable;

import React from 'react';

import ChronosStore from '../../stores/ChronosStore';
import DescriptionList from '../../components/DescriptionList';

class JobRunHistoryTable extends React.Component {
  render() {
    let job = ChronosStore.getJob(this.props.jobID);

    return (
      <DescriptionList
        hash={{
          Command: job.getCommand(),
          Schedule: job.getSchedules()[0].cron
        }} />
    );
  }
}

module.exports = JobRunHistoryTable;

Fix bad method calls from rebase error

Fix bad method calls from rebase error


(function sceneHighlight() {
  'use strict';

  function highlightLines(query) {
    var elements = document.querySelectorAll(query);

    Array.from(document.querySelectorAll('.highlight')).forEach(function removePreviousHighlight(element) {
      element.classList.remove('.highlight');
    });

    Array.from(elements).forEach(function iterateElements(element) {
      element.classList.add('highlight');
    });

    elements[0].scrollIntoView({behavior: 'smooth'});

  }

  window.addEventListener('hashchange', function hashChangeCallback(event) {
    var query = '.' + event.newURL.split('#')[1];
    highlightLines(query);
  });

  window.addEventListener('load', function loadCallback(event) {
    var query = window.location.hash;
    if (query) {
      highlightLines('.' + query.split('#')[1]);
    }
  });

})();

(function sceneHighlight() {
  'use strict';

  function highlightLines(query) {
    var elements = document.querySelectorAll(query);

    Array.from(document.querySelectorAll('.highlight')).forEach(function removePreviousHighlight(element) {
      element.classList.remove('.highlight');
    });

    Array.from(elements).forEach(function iterateElements(element) {
      element.classList.add('highlight');
    });

    elements[0].scrollIntoView({behavior: 'smooth'});

  }

  window.addEventListener('hashchange', function hashChangeCallback(event) {
    var query = '.' + event.newURL.split('#')[1];
    highlightLines(query);
  });

  window.addEventListener('load', function loadCallback() {
    var query = window.location.hash;
    if (query) {
      highlightLines('.' + query.split('#')[1]);
    }
  });

})();

Remove event from scene highlight params

Dumb style stuff.


$(document).ready(function () {
    var height = $(window).innerHeight();
    var headerHeight = $('header').innerHeight();
    $('main').css('height', height);
    window.scrollTo(0, headerHeight);
});

$(document).ready(function () {
    if ($('.oe_website_login_container').length) {
        var height = $(window).innerHeight();
        var headerHeight = $('header').innerHeight();
        $('main').css('height', height);
        window.scrollTo(0, headerHeight);
    }
});

Add check if its correct page

Add check if its correct page


// ==UserScript==
// @name         UkBay without clicking
// @namespace    https://github.com/rohanorton
// @version      0.1
// @description  Go straight to Piratebay mirror without having to click image
// @author       Rohan Orton
// @match        https://ukbay.org/
// @grant        none
// ==/UserScript==

// Why?
// ====
// I couldn't be bothered clicking on the image, and having it open a pop up
// window. This all seemed unecessary.

/*jslint browser:true */
/*globals randomlinks */

(function (randomlinks) {
  "use strict";
    window.location = (randomlinks[Math.floor(Math.random()*randomlinks.length)]);
} (randomlinks));

// ==UserScript==
// @name         UkBay without clicking
// @namespace    https://github.com/rohanorton
// @version      0.1
// @description  Go straight to Piratebay mirror without having to click image
// @author       Rohan Orton
// @include      https://ukbay.*
// @grant        none
// ==/UserScript==

// Why?
// ====
// I couldn't be bothered clicking on the image, and having it open a pop up
// window. This all seemed unecessary.

/*jslint browser:true */
/*globals randomlinks */

(function (randomlinks) {
  "use strict";

  function random(n) {
    return Math.floor(Math.random() * n);
  }

  function getLink() {
    var index = random(randomlinks.length));
    return randomlinks[index]
  }

  if (randomlinks) {
    window.location = getLink();
  }
} (randomlinks));

Make ukbay script to work on different ukbay URLs


// Reverse Array In Place

/*RULES:
  Take array as parameter
    Reverse array
    Return reversed array

  NOTES:
  Can't create new empty array to push in
  Must modify given array
  Can't use array.reverse();
*/

/*PSEUDOCODE

  1) Find array length
  2) Create variable "stopper" for last element in array
  2) (array.length - 1) times do:
    2a) Push element previous to "stopper" to the end of the array
    2b) Splice that same element out from in front of 'stopper'
  3) When done, return reversed array
*/

function reverseArray(arr){
  var count = arr.length;
  var stopper = arr[count - 1];

  for (var i = 0; i < count; i++){
    arr.push(arr[arr.indexOf(stopper) - 1]);
    arr.splice((arr.indexOf(stopper) - 1), 1);
  }

  return arr;
}

// Reverse Array In Place

/*RULES:
  Take array as parameter
    Reverse array
    Return reversed array

  NOTES:
  Can't create new empty array to push in
  Must modify given array
  Can't use array.reverse();
*/

/*PSEUDOCODE

  1) Find array length
  2) Create variable "stopper" for last element in array
  2) (array.length - 1) times do:
    2a) Push element previous to "stopper" to the end of the array
    2b) Splice that same element out from in front of 'stopper'
  3) When done, return reversed array
*/

// This is the solution I came up with and it works!  But, will add the course solution underneath.  Considerably faster, since it only loops through half of the array rather than the whole array like mine does.

// function reverseArray(arr){
//   var count = arr.length;
//   var stopper = arr[count - 1];

//   for (var i = 0; i < count; i++){
//     arr.push(arr[arr.indexOf(stopper) - 1]);
//     arr.splice((arr.indexOf(stopper) - 1), 1);
//   }

//   return arr;
// }

function reverseArrayInPlace(arr) {
  for (var i = 0; i < arr.length / 2; i++) {
    var tempVar = arr[i];
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = tempVar;
  }

  return arr;
}

Comment out initial solution, include faster course solution


'use strict';

angular.module('Teem')
  .directive('needWidget', function() {
    return {
      scope: {},
      controller: [
      '$scope',
      function($scope) {
        $scope.toggleCompleted = function (need) {
          event.stopPropagation();
          // Needed by the magic of material design
          event.preventDefault();

          $scope.project.toggleNeedCompleted(need);
        };
      }],
      templateUrl: 'pad/need-widget.html'
    };
  });

'use strict';

angular.module('Teem')
  .directive('needWidget', function() {
    return {
      scope: {},
      controller: [
      '$scope',
      function($scope) {
        $scope.toggleCompleted = function (need, event) {
          event.stopPropagation();
          // Needed by the magic of material design
          event.preventDefault();

          $scope.project.toggleNeedCompleted(need);
        };
      }],
      templateUrl: 'pad/need-widget.html'
    };
  });

Add missing reference to event

Add missing reference to event


import React from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'

import Notification from 'src/shared/components/Notification'

const Notifications = ({notifications, inPresentationMode}) =>
  <div
    className={`${inPresentationMode
      ? 'notification-center__presentation-mode'
      : 'notification-center'}`}
  >
    {notifications.map(n => <Notification key={n.id} notification={n} />)}
  </div>

const {arrayOf, bool, number, shape, string} = PropTypes

Notifications.propTypes = {
  notifications: arrayOf(
    shape({
      id: string.isRequired,
      type: string.isRequired,
      message: string.isRequired,
      duration: number.isRequired,
      icon: string,
    })
  ),
  inPresentationMode: bool,
}

const mapStateToProps = ({
  notifications,
  app: {ephemeral: {inPresentationMode}},
}) => ({
  notifications,
  inPresentationMode,
})

export default connect(mapStateToProps, null)(Notifications)

import React from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'

import Notification from 'shared/components/Notification'

const Notifications = ({notifications, inPresentationMode}) =>
  <div
    className={`${inPresentationMode
      ? 'notification-center__presentation-mode'
      : 'notification-center'}`}
  >
    {notifications.map(n => <Notification key={n.id} notification={n} />)}
  </div>

const {arrayOf, bool, number, shape, string} = PropTypes

Notifications.propTypes = {
  notifications: arrayOf(
    shape({
      id: string.isRequired,
      type: string.isRequired,
      message: string.isRequired,
      duration: number.isRequired,
      icon: string,
    })
  ),
  inPresentationMode: bool,
}

const mapStateToProps = ({
  notifications,
  app: {ephemeral: {inPresentationMode}},
}) => ({
  notifications,
  inPresentationMode,
})

export default connect(mapStateToProps, null)(Notifications)

Replace reference to src/shared/ with shared/


/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule Promise
 * @flow
 */
'use strict';

const Promise = require('fbjs/lib/Promise.native');

if (__DEV__) {
  require('promise/setimmediate/rejection-tracking').enable({
    allRejections: true,
    onUnhandled: (id, error) => {
      const {message, stack} = error;
      const warning =
        `Possible Unhandled Promise Rejection (id: ${id}):\n` +
        (message == null ? '' : `${message}\n`) +
        (stack == null ? '' : stack);
      console.warn(warning);
    },
    onHandled: (id) => {
      const warning =
        `Promise Rejection Handled (id: ${id})\n` +
        'This means you can ignore any previous messages of the form ' +
        `"Possible Unhandled Promise Rejection (id: ${id}):"`;
      console.warn(warning);
    },
  });
}

module.exports = Promise;

/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule Promise
 * @flow
 */
'use strict';

const Promise = require('fbjs/lib/Promise.native');

if (__DEV__) {
  require('promise/setimmediate/rejection-tracking').enable({
    allRejections: true,
    onUnhandled: (id, error = {}) => {
      const {message = null, stack = null} = error;
      const warning =
        `Possible Unhandled Promise Rejection (id: ${id}):\n` +
        (message == null ? '' : `${message}\n`) +
        (stack == null ? '' : stack);
      console.warn(warning);
    },
    onHandled: (id) => {
      const warning =
        `Promise Rejection Handled (id: ${id})\n` +
        'This means you can ignore any previous messages of the form ' +
        `"Possible Unhandled Promise Rejection (id: ${id}):"`;
      console.warn(warning);
    },
  });
}

module.exports = Promise;

Make onUnhandled safe for undefined errors

Summary:
This pull request fixes cases where the `error` argument of the `onUnhandled` method in `Libraries/Promise.js` is undefined. Previously this would result in a redbox with the helpful message: `Cannot read property message of undefined`. With this pull request, unhandled promise rejections result in the desired yellowbox saying that a promise rejection went unhandled.

I still do not know what would cause the error argument to be undefined, but this change makes the module behave as expected in an app I am building.

cc bestander

Relevant issue: #8452
Closes https://github.com/facebook/react-native/pull/9119

Differential Revision: D3655589

Pulled By: bestander

fbshipit-source-id: a975a0ab58701240ba06574c04521cd542700ff7


var fs = require('fs');

var home = process.env.HOME;
var fname = home + '/.nodewar';

module.exports = {
  save:function(session){
    var fd = fs.openSync(fname, 'w', 0600);

    if (fs.writeSync(fd, session)){
      console.log('Session configuration saved');
    } else {
      console.warn('Failed to write configuration');
    }
  },

  read:function(){
    return fs.readFileSync(fname).toString();
  }
};

var fs = require('fs');

var home = process.env.HOME;
var fname = home + '/.nodewar';

module.exports = {
  save:function(session){
    var fd = fs.openSync(fname, 'w', 0600);

    if (fs.writeSync(fd, session)){
      console.log('Session configuration saved');
    } else {
      console.warn('Failed to write configuration');
    }
  },

  read:function(){
    var fd = fs.openSync(fname, 'w', 0600);
    return fs.readFileSync(fname).toString();
  }
};

Create .nodewar if it doesn't exist.

Create .nodewar if it doesn't exist.


import { injectCSS } from 'src/search-injection/dom'
import { setupRibbonUI } from './components'

export function loader(promiseCreator) {
    let promise

    return (...args) => {
        if (!promise) {
            promise = promiseCreator(...args).then(res => {
                promise.loaded = true
                return res
            })
        }

        return promise
    }
}

export const bodyLoader = loader(() => {
    return new Promise(resolve => {
        if (
            document.readyState === 'complete' ||
            document.readyState === 'interactive'
        ) {
            return resolve()
        }

        document.addEventListener('DOMContentLoaded', resolve)
    })
})

const init = async () => {
    await bodyLoader()

    const target = document.createElement('div')
    target.setAttribute('id', 'memex-annotations-ribbon')
    document.body.appendChild(target)

    const cssFile = browser.extension.getURL('content_script.css')
    injectCSS(cssFile)

    setupRibbonUI(target)
}

init()

import { injectCSS } from 'src/search-injection/dom'
import { setupRibbonUI } from './components'
import { bodyLoader } from 'src/util/loader'

import { getLocalStorage } from 'src/util/storage'
import { TOOLTIP_STORAGE_NAME } from 'src/content-tooltip/constants'

const init = async () => {
    const isTooltipEnabled = await getLocalStorage(TOOLTIP_STORAGE_NAME)
    if (!isTooltipEnabled) return

    await bodyLoader()

    const target = document.createElement('div')
    target.setAttribute('id', 'memex-annotations-ribbon')
    document.body.appendChild(target)

    const cssFile = browser.extension.getURL('content_script.css')
    injectCSS(cssFile)

    setupRibbonUI(target)
}

init()

Disable Ribbon if Memex.Link is disabled.


function setAriaCurrent() {
	var id = document.getElementById("inicio");
	id.textContent = document.title
}

setAriaCurrent();

function setAriaCurrent() {
	var title = document.title;
	if title== "Comunidad hispanohablante de NVDA" {
		var id = "inicio"
	}
	document.getElementById(id).setAttribute("aria-current", "page");
}

setAriaCurrent();

Set aria-current for first link of nav

Set aria-current for first link of nav


import Promise from 'bluebird';
import express from 'express';
import assert from 'assert';
import request from 'superagent'

const ROTTEN_TOMATOES_API_KEY = process.env.ROTTEN_TOMATOES_API_KEY;
assert(ROTTEN_TOMATOES_API_KEY, 'Application needs a rotten tomatoes API key.');
const ROTTEN_TOMATOES_SEARCH_URL = `http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=${ROTTEN_TOMATOES_API_KEY}`;

const router = new express.Router();
export default router;

router.get('/search', (req, res) => {
  const query = req.query.q;
  const page = req.query.page || '1';
  const finalUrl = ROTTEN_TOMATOES_SEARCH_URL + '&q=' + query + '&page=' + page
  return request.get(
    finalUrl
  ).end((err, response) => {
    res.send(JSON.parse(response.text));
  });
});

import express from 'express';
import assert from 'assert';
import request from 'superagent';

const apikey = process.env.ROTTEN_TOMATOES_API_KEY;
assert(apikey, 'Application needs a rotten tomatoes API key.');
const ROTTEN_TOMATOES_SEARCH_URL = 'http://api.rottentomatoes.com/api/public/v1.0/movies.json';

const router = new express.Router();
export default router;

router.get('/search', async ({query: {q, page}}, res) => {
  const response = await request.get(
    ROTTEN_TOMATOES_SEARCH_URL
  ).query({q, page, apikey});
  res.send(JSON.parse(response.text));
});

Tidy up handler a bit

Tidy up handler a bit


import Ember from 'ember';

export default function(app, prefix) {
  var regex = new RegExp('^' + prefix + '\/((?:instance-)?initializers)\/');
  var getKeys = (Object.keys || Ember.keys);
  var moduleNames = getKeys(requirejs._eak_seen);

  for (var i = 0; i < moduleNames.length; i++) {
    var moduleName = moduleNames[i];
    var matches = regex.exec(moduleName);

    if (matches && matches.length === 2) {
      var module = require(moduleName, null, null, true);
      if (!module) { throw new Error(moduleName + ' must export an initializer.'); }

      var initializerType = Ember.String.camelize(matches[1].substring(0, matches[1].length - 1));
      var initializer = module['default'];
      if (!initializer.name) {
        var initializerName = moduleName.match(/[^\/]+\/?$/)[0];
        initializer.name = initializerName;
      }

      if (app[initializerType]) {
        app[initializerType](initializer);
      }
    }
  }
}

function resolveInitializer(moduleName) {
  var module = require(moduleName, null, null, true);
  if (!module) {
    throw new Error(moduleName + ' must export an initializer.');
  }
  var initializer = module['default'];
  if (!initializer.name) {
    initializer.name = moduleName.slice(moduleName.lastIndexOf('/') + 1);
  }
  return initializer;
}

function registerInitializers(app, moduleNames) {
  for (var i = 0; i < moduleNames.length; i++) {
    app.initializer(resolveInitializer(moduleNames[i]));
  }
}

function registerInstanceInitializers(app, moduleNames) {
  for (var i = 0; i < moduleNames.length; i++) {
    app.instanceInitializer(resolveInitializer(moduleNames[i]));
  }
}

export default function (app, prefix) {
  var initializerPrefix =  prefix + '/initializers/';
  var instanceInitializerPrefix =  prefix + '/instance-initializers/';
  var initializers = [];
  var instanceInitializers = [];
  // this is 2 pass because generally the first pass is the problem
  // and is reduced, and resolveInitializer has potential to deopt
  var moduleNames = Object.keys(requirejs._eak_seen);
  for (var i = 0; i < moduleNames.length; i++) {
    var moduleName = moduleNames[i];
    if (moduleName.lastIndexOf(initializerPrefix, 0) === 0) {
      initializers.push(moduleName);
    } else if (moduleName.lastIndexOf(instanceInitializerPrefix, 0) === 0) {
      instanceInitializers.push(moduleName);
    }
  }
  registerInitializers(app, initializers);
  registerInstanceInitializers(app, instanceInitializers);
}

Fix deopt with regex matches field load optimizing to undefined.

Looping over a large array is fast if you minimize the work done on the
loop. In the app I tested there were 3000+ modules, 23 initializers, and
13 instance initializers. It is best to save the require work that has a
higher chance to cause JIT issues.


"use strict";
var
  OS = require('os'),
  Net = require('net'),
  CPP = require('childprocess-promise');
class Main{
  constructor(Port){
    this.Port = Port;
    this.Server = null;
    this.Children = [];
  }
  Run(){
    let NumCPUs = OS.cpus().length;
    let SupportedEvents = [];
    for(let Name in Main){
      if (typeof Main[Name] === 'function' && Name.substr(0, 6) === 'Action')
        SupportedEvents.push(Name.substr(6));
    }
    for(var i = 0; i < NumCPUs; ++i){
      let Child = new CPP(__dirname + '/../Main.js');
      SupportedEvents.forEach(function(Event){
        Child.on(Event, Main['Action' + Event].bind(this, Child));
      }.bind(this));
      Child.Send('SupportedEvents', SupportedEvents);
      this.Children.push(Child);
    }
    let Server = this.Server = Net.createServer();
    this.Server.listen(this.Port, this.Children.forEach.bind(this.Children, function(Child){
      Child.Target.send('Server', Server);
    }));
  }
}
var Inst = new Main(9004, 4);
Inst.Run();

"use strict";
var
  OS = require('os'),
  Net = require('net'),
  CPP = require('childprocess-promise');
class Main{
  constructor(Port){
    this.Port = Port;
    this.Server = null;
    this.Children = [];
    this.DataBase = new Map();
  }
  Run(){
    let NumCPUs = OS.cpus().length;
    let SupportedEvents = [];
    for(let Name in Main){
      if (typeof Main[Name] === 'function' && Name.substr(0, 6) === 'Action')
        SupportedEvents.push(Name.substr(6));
    }
    for(var i = 0; i < NumCPUs; ++i){
      let Child = new CPP(__dirname + '/../Main.js');
      SupportedEvents.forEach(function(Event){
        Child.on(Event, Main['Action' + Event].bind(this, Child));
      }.bind(this));
      Child.Send('SupportedEvents', SupportedEvents);
      this.Children.push(Child);
    }
    let Server = this.Server = Net.createServer();
    this.Server.listen(this.Port, this.Children.forEach.bind(this.Children, function(Child){
      Child.Target.send('Server', Server);
    }));
  }
}
var Inst = new Main(9004, 4);
Inst.Run();

Use ES6 Map as Database

:new: Use ES6 Map as Database


var chai = require('chai');
var expect = chai.expect;
var jsdom = require('mocha-jsdom');

var helpers = require('../spec-helpers');

describe('DrawerTabsView', function() {
  jsdom();

  describe('::initialize', function() {
    describe('with forceOpen', function() {
      var $fixture, view;

      beforeEach(function() {
        var DrawerTabsView = require('../../../source/views/drawer/drawer-tabs-view');

        $fixture = $('

');
        $fixture.append('

'

        ).appendTo('body');

        view = new DrawerTabsView({forceOpen: true});
      });

      afterEach(function() {
        view.remove();
        $fixture.remove();
      });

      it('is in the open state', function() {
        expect(view).to.be.ok;
        expect(view.drawerState).to.eql('open');
        expect(view.$toggleArrow.attr('class')).to.match(/\bopen\b/);
      });
    });
  });
});

var chai = require('chai');
var expect = chai.expect;
var jsdom = require('mocha-jsdom');

describe('DrawerTabsView', function() {
  jsdom();

  describe('::initialize', function() {
    describe('with forceOpen', function() {
      var $fixture, view;

      beforeEach(function() {
        var DrawerTabsView = require('../../../source/views/drawer/drawer-tabs-view');

        $fixture = $('

');
        $fixture.append('

'

        ).appendTo('body');

        view = new DrawerTabsView({forceOpen: true});
      });

      afterEach(function() {
        view.remove();
        $fixture.remove();
      });

      it('is in the open state', function() {
        expect(view).to.be.ok;
        expect(view.drawerState).to.eql('open');
        expect(view.$toggleArrow.attr('class')).to.match(/\bopen\b/);
      });
    });
  });
});

Remove reference to non-existent file

Remove reference to non-existent file


define(['jquery', 'controllers/analystController', 'Ladda'], function ($, analystController, Ladda) {

  function sessionView() {

    $(function () {
      $('#generate').on('click', function (e) {
        e.preventDefault();

        var la = Ladda.create(document.getElementById('generate'));
        la.start();

        analystController.generateSession('infoDiv', 'sessionID', 'passwordID', 'pubkeyID', 'privkeyID', 'link-id', 'session-title', 'session-description')
          .then(function () {
            la.stop();
            $('#session-details').removeClass('hidden');
          });
      });
    });
  }

  return sessionView;
});

define(['jquery', 'controllers/analystController', 'Ladda'], function ($, analystController, Ladda) {

  function sessionView() {

    $(function () {
      $('#generate').on('click', function (e) {
        e.preventDefault();

        var la = Ladda.create(document.getElementById('generate'));
        la.start();

        var result = analystController.generateSession('infoDiv', 'sessionID', 'passwordID', 'pubkeyID', 'privkeyID', 'link-id', 'session-title', 'session-description');
        if (result == null) {
          la.stop();
        } else {
          result.then(function () {
            la.stop();
            $('#session-details').removeClass('hidden');
          });
        }
      });
    });
  }

  return sessionView;
});

Fix in creating session error message

Fix in creating session error message


const express = require('express');
const router = express.Router();
const cms = require('../cms.js');
const mongoose = require('mongoose');
const Shuttle = require("../schema/shuttle.js");
const helperLib = require("../helper.js").helpers;
const helper = new helperLib();
module.exports = router;
router.get('/', function(req, res) {

	//checks if user is logged in
	if (!req.session || !req.session.cas_user) {
		res.redirect("/login");
		return;
	}

	var rcs_id = req.session.cas_user.toLowerCase();
	//if the user is an admin
	if (helper.isAdmin(rcs_id)) {
		//query the database and return all information on all shuttles
		var query = Shuttle.find({}).lean();
		query.exec(function(err, docs) {
			res.send(docs);
		});
	} else {
		var query = Shuttle.find({}).lean();
		// Ensure non-admin users cannot see other riders, nor the waitlist for a shuttle.
		query.select('-riders');
		query.select('-waitlist');
		query.exec(function(err, docs) {
			res.send(docs);
		});
	}
});

const express = require('express');
const router = express.Router();
const cms = require('../cms.js');
const mongoose = require('mongoose');
const Shuttle = require("../schema/shuttle.js");
const helperLib = require("../helper.js").helpers;
const helper = new helperLib();
module.exports = router;
router.get('/', function(req, res) {

	//checks if user is logged in
	if (!req.session || !req.session.cas_user) {
		res.redirect("/login");
		return;
	}

	var rcs_id = req.session.cas_user.toLowerCase();
	//if the user is an admin
	if (helper.isAdmin(rcs_id)) {
		//query the database and return all information on all shuttles
		var query = Shuttle.find({}).lean();
		query.exec(function(err, docs) {

			res.send({"data":docs});
		});
	} else {
		var query = Shuttle.find({}).lean();
		// Ensure non-admin users cannot see other riders, nor the waitlist for a shuttle.
		query.select('-riders');
		query.select('-waitlist');
		query.exec(function(err, docs) {
			res.send(docs);
		});
	}
});

Make get shuttles api route more secure by encapsulating array in data key

This is better as per this article: https://www.owasp.org/index.php/AJAX_Security_Cheat_Sheet#Always_return_JSON_with_an_Object_on_the_outside


import Ember from 'ember';

const FONT_SIZE_PATTERN = /font-size/;

export default Ember.Helper.helper(function ([prefix, ...classNames]) {
  return classNames.reduce(function(string, name) {
    if (!name) return string;

    let trimmedName = name.replace(/\s/g, '');
    if (trimmedName === '') return string;

    switch (true) {
      case (trimmedName === ':component'):
        return string += `${prefix} `;
      case (FONT_SIZE_PATTERN.test(trimmedName)):
        return string += `${trimmedName} `;
      default:
        return string += `${prefix}${trimmedName} `;
    }
  }, '');
});

import Ember from 'ember';

const FONT_SIZE_PATTERN = /font-size/;

export default Ember.Helper.helper(function ([prefix, ...classNames]) {
  let normalizedClassNames = classNames.reduce(function(names, name) {
    name.split(/\s/).forEach(function(part) {
      if (part && part !== '') {
        names.push(part);
      }
    });

    return names;
  }, []);

  return normalizedClassNames.reduce(function(string, name) {
    switch (true) {
      case (name === ':component'):
        return string += `${prefix} `;
      case (FONT_SIZE_PATTERN.test(name)):
        return string += `${name} `;
      default:
        return string += `${prefix}${name} `;
    }
  }, '');
});

Normalize class names before prefixing

Normalize class names before prefixing


Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function() { return Meteor.subscribe('posts'); }
});

Router.route('/', {name: 'postsList'});

Router.route('/posts/:_id', {
  name: 'postPage',
  data: function() { return Posts.findOne(this.params._id); }
});

Router.route('/submit', {name: 'postSubmit'});

var requireLogin = function() {
  if (! Meteor.user()) {
    this.render('accessDenied');
  } else {
    this.next();
  }
}

Router.onBeforeAction('dataNotFound', {only: 'postPage'});
Router.onBeforeAction(requireLogin, {only: 'postSubmit'});

Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function() { return Meteor.subscribe('posts'); }
});

Router.route('/', {name: 'postsList'});

Router.route('/posts/:_id', {
  name: 'postPage',
  data: function() { return Posts.findOne(this.params._id); }
});

Router.route('/submit', {name: 'postSubmit'});

var requireLogin = function() {
  if (! Meteor.user()) {
    if (Meteor.loggingIn()) {
      this.render(this.loadingTemplate);
    } else {
      this.render('accessDenied');
    }
  } else {
    this.next();
  }
}

Router.onBeforeAction('dataNotFound', {only: 'postPage'});
Router.onBeforeAction(requireLogin, {only: 'postSubmit'});

Access denied post will no longer show up when logged in


'use strict';

// Declare app level module which depends on filters, and services
angular.module('myApp',
      ['myApp.config', 'myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers', 'firebase', 'ngRoute', 'waitForAuth']
   )

   // configure views; note the authRequired parameter for authenticated pages
   .config(['$routeProvider', function($routeProvider) {
      $routeProvider.when('/home', {
         templateUrl: 'partials/home.html',
         controller: 'HomeCtrl'
      });

      $routeProvider.when('/chat', {
         templateUrl: 'partials/chat.html',
         controller: 'ChatCtrl'
      });

      $routeProvider.when('/account', {
         authRequired: true, // must authenticate before viewing this page
         templateUrl: 'partials/account.html',
         controller: 'AccountCtrl'
      });

      $routeProvider.when('/login', {
         templateUrl: 'partials/login.html',
         controller: 'LoginCtrl'
      });

      $routeProvider.otherwise({redirectTo: '/home'});
   }])

   // double-check that the app has been configured
   .run(['FBURL', function(FBURL) {
      if( FBURL === 'https://INSTANCE.firebaseio.com' ) {
         angular.element(document.body).html('
Please configure app/js/config.js before running!
');
      }
   }])

   // establish authentication
   .run(['loginService', '$rootScope', 'FBURL', function(loginService, $rootScope, FBURL) {
      $rootScope.auth = loginService.init('/login');
      $rootScope.FBURL = FBURL;
   }]);

'use strict';

// Declare app level module which depends on filters, and services
angular.module('myApp',
      ['myApp.config', 'myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers', 'firebase', 'ngRoute', 'waitForAuth']
   )

   // configure views; note the authRequired parameter for authenticated pages
   .config(['$routeProvider', function($routeProvider) {
      $routeProvider.when('/home', {
         templateUrl: 'partials/home.html',
         controller: 'HomeCtrl'
      });

      $routeProvider.when('/chat', {
         templateUrl: 'partials/chat.html',
         controller: 'ChatCtrl'
      });

      $routeProvider.when('/account', {
         authRequired: true, // must authenticate before viewing this page
         templateUrl: 'partials/account.html',
         controller: 'AccountCtrl'
      });

      $routeProvider.when('/login', {
         templateUrl: 'partials/login.html',
         controller: 'LoginCtrl'
      });

      $routeProvider.otherwise({redirectTo: '/home'});
   }])

   // establish authentication
   .run(['loginService', '$rootScope', 'FBURL', function(loginService, $rootScope, FBURL) {
      if( FBURL === 'https://INSTANCE.firebaseio.com' ) {
         // double-check that the app has been configured
         angular.element(document.body).html('
Please configure app/js/config.js before running!
');
         setTimeout(function() {
            angular.element(document.body).removeClass('hide');
         }, 250);
      }
      else {
         $rootScope.auth = loginService.init('/login');
         $rootScope.FBURL = FBURL;
      }
   }]);

Fix config check to work with ngCloakAuth


(function () {
    var indicator = document.createElement("h1");
    indicator.innerHTML = "Press a key on your keyboard.";
    document.body.appendChild(indicator);

    window.addEventListener("keyup", function (e) {
        buster.multicastClient.emit("update", e.keyCode);
    }, false);

    buster.multicastClient.on("update", function (event) {
        indicator.innerHTML = String.fromCharCode(event.data);
    });
}());

(function () {
    var indicator = document.createElement("h1");
    indicator.innerHTML = "Press a key on your keyboard.";
    document.body.appendChild(indicator);

    window.addEventListener("keyup", function (e) {
        buster.multicastClient.emit("update", e.keyCode);
    }, false);

    buster.multicastClient.on("update", function (event) {
        indicator.innerHTML += String.fromCharCode(event.data);
    });
}());

Append HTML in demo app - much more fun to watch :)


define([
    'backbone',
    'models/noteModel',
    'underscore',
    'jquery',
    'text!templates/noteTemplate.html',
    'jquery.extensions'
], function (Backbone, model, _, $, template) {
    'use strict';

    var NoteView = Backbone.View.extend({
        template: _.template(template),
        events: {
            'click': 'click',
            'click button.close': 'close'
        },
        initialize: function () {
            this.listenTo(this.model, 'destroy', this.remove);
        },
        render: function () {
            var $el   = this.$el;

            this.$el.
                html(this.template(this.model.attributes)).
                addClass('note').
                children('.head').drags({handle:$el}).end().
                offset(this.model.get('offset'));

            return this;
        },
        click: function (e) {
            e.stopPropagation();
            e.preventDefault();
        },
        close: function () {
            this.model.destroy();
        }
    });

    return NoteView;
});

define([
    'backbone',
    'models/noteModel',
    'underscore',
    'jquery',
    'text!templates/noteTemplate.html',
    'jquery.extensions'
], function (Backbone, model, _, $, template) {
    'use strict';

    var NoteView = Backbone.View.extend({
        template: _.template(template),
        events: {
            'click': 'click',
            'click button.close': 'close'
        },
        initialize: function () {
            this.listenTo(this.model, 'destroy', this.remove);
        },
        render: function () {
            var $el   = this.$el,
                model = this.model;

            $el.
                html(this.template(this.model.attributes)).
                addClass('note').
                children('.head').drags({
                    handle:$el,
                    ondragstop: function (e) {
                        model.save('offset', $(e.target).offset());
                    }
                }).end().
                offset(this.model.get('offset'));

            return this;
        },
        click: function (e) {
            e.stopPropagation();
            e.preventDefault();
        },
        close: function () {
            this.model.destroy();
        }
    });

    return NoteView;
});

Add synchronization of note position after dragdrop between tabs


/* eslint-env browser */

const isFunction = require('lodash/isFunction');
const isObject = require('lodash/isObject');
const isString = require('lodash/isString');

const { deferredToPromise } = require('../deferred_to_promise');

const closeDatabase = name =>
  new Promise((resolve, reject) => {
    const request = window.indexedDB.open(name);
    request.onblocked = () => {
      reject(new Error(`Database '${name}' blocked`));
    };
    request.onupgradeneeded = (event) => {
      reject(new Error('Unexpected database upgraded needed:' +
        ` oldVersion: ${event.oldVersion}, newVersion: ${event.newVersion}`));
    };
    request.onerror = (event) => {
      reject(event.target.error);
    };
    request.onsuccess = (event) => {
      const connection = event.target.result;
      connection.close();
      resolve();
    };
  });

exports.runMigrations = async ({ Backbone, database } = {}) => {
  if (!isObject(Backbone) || !isObject(Backbone.Collection) ||
      !isFunction(Backbone.Collection.extend)) {
    throw new TypeError('"Backbone" is required');
  }

  if (!isObject(database) || !isString(database.id) ||
      !Array.isArray(database.migrations)) {
    throw new TypeError('"database" is required');
  }

  const migrationCollection = new (Backbone.Collection.extend({
    database,
    storeName: 'items',
  }))();

  await deferredToPromise(migrationCollection.fetch());
  await closeDatabase(database.id);
};

/* eslint-env browser */

const isFunction = require('lodash/isFunction');
const isObject = require('lodash/isObject');
const isString = require('lodash/isString');

const { deferredToPromise } = require('../deferred_to_promise');

const closeDatabase = name =>
  new Promise((resolve, reject) => {
    const request = window.indexedDB.open(name);
    request.onblocked = () => {
      reject(new Error(`Database '${name}' blocked`));
    };
    request.onupgradeneeded = (event) => {
      reject(new Error('Unexpected database upgraded needed:' +
        ` oldVersion: ${event.oldVersion}, newVersion: ${event.newVersion}`));
    };
    request.onerror = (event) => {
      reject(event.target.error);
    };
    request.onsuccess = (event) => {
      const connection = event.target.result;
      connection.close();
      resolve();
    };
  });

exports.runMigrations = async ({ Backbone, database } = {}) => {
  if (!isObject(Backbone) || !isObject(Backbone.Collection) ||
      !isFunction(Backbone.Collection.extend)) {
    throw new TypeError('"Backbone" is required');
  }

  if (!isObject(database) || !isString(database.id) ||
      !Array.isArray(database.migrations)) {
    throw new TypeError('"database" is required');
  }

  const migrationCollection = new (Backbone.Collection.extend({
    database,
    storeName: 'items',
  }))();

  await deferredToPromise(migrationCollection.fetch({ limit: 1 }));
  await closeDatabase(database.id);
};

Reduce work for verifying transaction completion


export class AppTemplate {
    static update(render) {
        /* eslint-disable indent */
        return render`

                    <basket></basket>
                    <assets></assets>
                    <most-used></most-used>
                    <latest></latest>
                    <other></other>

                    <stats></stats>

        `;
        /* eslint-enable indent */
    }
}

Add horizontal margin to the app.

Add horizontal margin to the app.


var union    = require('union'),
    ecstatic = require('ecstatic');

var port = process.env.PORT || 8080;

//
// ### redirect(res)
// World's simplest redirect function
//
function redirect(res) {
  var url  = 'http://2015.empirenode.org',
      body = '
301. Redirecting to ' + url + '
';

  res.writeHead(301, { 'content-type': 'text/html', location: url });
  res.end(body);
}

var server = union.createServer({
  before: [
    function (req, res) {
      var host = req.headers.host,
          parts = host.split('.');

      console.log('%s - %s%s', req.method, host, req.url);
      if (process.env.NODE_ENV === 'production'
        && (parts.length !== 3 || parts[0] === 'www')) {
        return redirect(res);
      }

      res.emit('next');
    },
    ecstatic({
      root: __dirname + '/public',
      defaultExt: true
    }),
    function (req, res) {
      return redirect(res);
    }
  ]
});

server.listen(port, function () {
  console.log('Listening on %s', port);
});

var union    = require('union'),
    ecstatic = require('ecstatic');

var port = process.env.PORT || 8080;

//
// ### redirect(res)
// World's simplest redirect function
//
function redirect(res) {
  var url  = 'http://2015.empirenode.org',
      body = '
301. Redirecting to ' + url + '
';

  res.writeHead(301, { 'content-type': 'text/html', location: url });
  res.end(body);
}

var server = union.createServer({
  before: [
    function (req, res) {
      var host = req.headers.host || '',
          parts = host.split('.');

      console.log('%s - %s%s', req.method, host, req.url);
      if (process.env.NODE_ENV === 'production'
        && (parts.length !== 3 || parts[0] === 'www')) {
        return redirect(res);
      }

      res.emit('next');
    },
    ecstatic({
      root: __dirname + '/public',
      defaultExt: true
    }),
    function (req, res) {
      return redirect(res);
    }
  ]
});

server.listen(port, function () {
  console.log('Listening on %s', port);
});

Check for lack of host header.

[fix] Check for lack of host header.


import React from 'react'
import PropTypes from 'prop-types'
import WidgetSettings from './WidgetSettingsContainer'
import SettingsChildWrapper from '../SettingsChildWrapperComponent'
import FullScreenProgress from 'general/FullScreenProgress'

class WidgetsSettings extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      userWidgets: null
    }
  }

  componentDidMount () {
    const { user } = this.props

    const userWidgets = {}
    var node

    for (var index in user.widgets.edges) {
      node = user.widgets.edges[index].node
      userWidgets[node.name] = node
    }

    this.setState({
      userWidgets: userWidgets
    })
  }

  render () {
    const { user, app, showError } = this.props

    // We need to wait for the
    // userWidgetsMap to be created before
    // mounting the WidgetSettings.
    if (!this.state.userWidgets) {
      return (<FullScreenProgress />)
    }

    const self = this
    return (
      <SettingsChildWrapper>
        <div style={{ paddingTop: 0 }} >
          {app.widgets.edges.map((edge, index) => {
            return (<WidgetSettings
              key={index}
              user={user}
              appWidget={edge.node}
              widget={self.state.userWidgets[edge.node.name]}
              showError={showError} />)
          })}
        </div>
      </SettingsChildWrapper>
    )
  }
}

WidgetsSettings.propTypes = {
  user: PropTypes.object.isRequired,
  app: PropTypes.object.isRequired,
  showError: PropTypes.func.isRequired
}

export default WidgetsSettings

import React from 'react'
import PropTypes from 'prop-types'
import WidgetSettings from './WidgetSettingsContainer'
import SettingsChildWrapper from '../SettingsChildWrapperComponent'
import FullScreenProgress from 'general/FullScreenProgress'

class WidgetsSettings extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      userWidgets: null
    }
  }

  componentDidMount () {
    const { user } = this.props

    const userWidgets = {}
    var node

    for (var index in user.widgets.edges) {
      node = user.widgets.edges[index].node
      userWidgets[node.name] = node
    }

    this.setState({
      userWidgets: userWidgets
    })
  }

  render () {
    const { user, app, showError } = this.props

    // We need to wait for the
    // userWidgetsMap to be created before
    // mounting the WidgetSettings.
    if (!this.state.userWidgets) {
      return (<FullScreenProgress />)
    }

    const self = this
    return (
      <SettingsChildWrapper>
        <div style={{ paddingTop: 0 }} >
          {app.widgets.edges.map((edge, index) => {
            return (<WidgetSettings
              key={index}
              user={user}
              appWidget={edge.node}
              widget={self.state.userWidgets[edge.node.name] || null}
              showError={showError} />)
          })}
        </div>
      </SettingsChildWrapper>
    )
  }
}

WidgetsSettings.propTypes = {
  user: PropTypes.object.isRequired,
  app: PropTypes.object.isRequired,
  showError: PropTypes.func.isRequired
}

export default WidgetsSettings

Allow a user’s widget data to be null on the settings page.


function setAriaCurrent() {
	var title = document.title;
	if title== "Comunidad hispanohablante de NVDA" {
		var id = "inicio"
	}
	document.getElementById(id).setAttribute("aria-current", "page");
}

setAriaCurrent();

function setAriaCurrent() {
	var title = document.title;
	if title== "Comunidad hispanohablante de NVDA" {
		var id = "inicio"
	}
	document.getElementById(id).removeAttribute("accesskey");
	document.getElementById(id).setAttribute("aria-current", "page");
}

setAriaCurrent();

Test why aria-current is not read: remove accesskey


import keys from 'ember-metal/keys';

/**
  Merge the contents of two objects together into the first object.

  ```javascript
  Ember.merge({first: 'Tom'}, {last: 'Dale'}); // {first: 'Tom', last: 'Dale'}
  var a = {first: 'Yehuda'};
  var b = {last: 'Katz'};
  Ember.merge(a, b); // a == {first: 'Yehuda', last: 'Katz'}, b == {last: 'Katz'}
  ```

  @method merge
  @for Ember
  @param {Object} original The object to merge into
  @param {Object} updates The object to copy properties from
  @return {Object}
*/
export default function merge(original, updates) {
  if (!updates || typeof updates !== 'object') {
    return original;
  }

  var props = keys(updates);
  var prop;
  var length = props.length;

  for (var i = 0; i < length; i++) {
    prop = props[i];
    original[prop] = updates[prop];
  }

  return original;
}

export function assign(original, ...args) {
  for (let i=0, l=args.length; i<l; i++) {
    let arg = args[i];
    if (!arg) { continue; }

    for (let prop in arg) {
      if (arg.hasOwnProperty(prop)) { original[prop] = arg[prop]; }
    }
  }

  return original;
}

import keys from 'ember-metal/keys';

/**
  Merge the contents of two objects together into the first object.

  ```javascript
  Ember.merge({first: 'Tom'}, {last: 'Dale'}); // {first: 'Tom', last: 'Dale'}
  var a = {first: 'Yehuda'};
  var b = {last: 'Katz'};
  Ember.merge(a, b); // a == {first: 'Yehuda', last: 'Katz'}, b == {last: 'Katz'}
  ```

  @method merge
  @for Ember
  @param {Object} original The object to merge into
  @param {Object} updates The object to copy properties from
  @return {Object}
*/
export default function merge(original, updates) {
  if (!updates || typeof updates !== 'object') {
    return original;
  }

  var props = keys(updates);
  var prop;
  var length = props.length;

  for (var i = 0; i < length; i++) {
    prop = props[i];
    original[prop] = updates[prop];
  }

  return original;
}

export function assign(original, ...args) {
  for (let i=0, l=args.length; i<l; i++) {
    let arg = args[i];
    if (!arg) { continue; }

    let updates = keys(arg);

    for (let i=0, l=updates.length; i<l; i++) {
      let prop = updates[i];
      original[prop] = arg[prop];
    }
  }

  return original;
}

Change `assign` to not use a for-in loop

Apparently, v8’s JIT engineers require that we, as JavaScript developers
perform this very simple transformation, since they do not seem capable
of performing it themselves.


if(!window.jQuery) window.$ = window.Zepto = require('zepto-browserify').$;

require('./components/polyfills.js')();

let warn = (msg) => {
    if (!window || !window.console) {
        return;
    }
    window.console.warn(msg);
};

if (typeof Object.assign !== 'function') {
    require('object.assign/shim')();
}

window.Storage = require('showcar-storage');
window.Pager = require('./components/pager.js');

require('showcar-icons');

const ctor = document.createElement('as24-tracking').constructor;

if (ctor === HTMLElement || ctor === HTMLUnknownElement) {
    // only requiring showcar-tracking when it was not already included before
    require('showcar-tracking');
}

require('./components/custom-dropdown.js');

$(_ => {
    require('./components/navigation.js');
    require('./components/rotating-arrow.js')();
    require('./components/sticky.js')();
    require('./components/collapse.js')();
    require('./components/scroll.js');
});

if (!window.notification) {
    window.notification = require('./components/notification.js');
} else {
    warn('window.notification is already registered.');
}

if(!window.jQuery) window.$ = window.Zepto = require('zepto-browserify').$;

require('./components/polyfills.js')();

let warn = (msg) => {
    if (!window || !window.console) {
        return;
    }
    window.console.warn(msg);
};

if (typeof Object.assign !== 'function') {
    require('object.assign/shim')();
}

throw new Error('test!');

window.Storage = require('showcar-storage');
window.Pager = require('./components/pager.js');

require('showcar-icons');

const ctor = document.createElement('as24-tracking').constructor;

if (ctor === HTMLElement || ctor === HTMLUnknownElement) {
    // only requiring showcar-tracking when it was not already included before
    require('showcar-tracking');
}

require('./components/custom-dropdown.js');

$(_ => {
    require('./components/navigation.js');
    require('./components/rotating-arrow.js')();
    require('./components/sticky.js')();
    require('./components/collapse.js')();
    require('./components/scroll.js');
});

if (!window.notification) {
    window.notification = require('./components/notification.js');
} else {
    warn('window.notification is already registered.');
}

Throw new error in order to test nightmare js setup


$(function(){
  $( "input[type='submit']" ).click(function() {
    $("form[data-remote]").on("ajax:success", function(e, data, status, xhr) {
      $('.flash-notice').show(300);
      $(":input:not(input[type=submit])").val("");
      $( ":input:enabled" ).focus(function() {
        $(".flash-notice").hide(1000);
      });
    })
  });
});

$(function(){
  $('#submit-button').click(function() {
    $("form[data-remote]").on("ajax:success", function(e, data, status, xhr) {
      $('.flash-notice').show(300);
      $(":input:not(input[type=submit])").val("");
      $( ":input:enabled" ).focus(function() {
        $(".flash-notice").hide(1000);
      });
    })
  });
});

Use proper target for button

Use proper target for button


(function() {
  // Define filter operations
  window.shared || (window.shared = {});
  var Env = window.shared.Env;

  window.shared.MixpanelUtils = {
    isMixpanelEnabled: function() {
      return (window.mixpanel && Env.shouldReportAnalytics);
    },
    registerUser: function(currentEducator) {
      if (!Mixpanel.isMixpanelEnabled()) return;

      try {
        window.mixpanel.register({
          'deployment_key': Env.deploymentKey,
          'educator_id': currentEducator.id,
          'educator_is_admin': currentEducator.admin,
          'educator_school_id': currentEducator.school_id
        });
      }
      catch (err) {
        console.error(err);
      }
    },
    track: function(key, attrs) {
      if (!Mixpanel.isMixpanelEnabled()) return;
      try {
        return window.mixpanel.track(key, attrs);
      }
      catch (err) {
        console.error(err);
      }
    }
  };
})();

(function() {
  // Define filter operations
  window.shared || (window.shared = {});
  var Env = window.shared.Env;

  window.shared.MixpanelUtils = {
    isMixpanelEnabled: function() {
      return (window.mixpanel && Env.shouldReportAnalytics);
    },
    registerUser: function(currentEducator) {
      if (!MixpanelUtils.isMixpanelEnabled()) return;

      try {
        window.mixpanel.register({
          'deployment_key': Env.deploymentKey,
          'educator_id': currentEducator.id,
          'educator_is_admin': currentEducator.admin,
          'educator_school_id': currentEducator.school_id
        });
      }
      catch (err) {
        console.error(err);
      }
    },
    track: function(key, attrs) {
      if (!MixpanelUtils.isMixpanelEnabled()) return;
      try {
        return window.mixpanel.track(key, attrs);
      }
      catch (err) {
        console.error(err);
      }
    }
  };
})();

Fix bug with guarding for MixPanel in demo env


function routerConfig ($stateProvider, $urlRouterProvider) {
  'ngInject';
  $stateProvider
    .state('home', {
      url: '/',
      templateUrl: 'app/main/main.html',
      controller: 'MainController',
      controllerAs: 'main'
    })
    .state('ambr', {
      url: '/ambr',
      templateUrl: 'app/projects/ambr.html',
      controller: 'AmbrController',
      controllerAs: 'ambr'
    })
    .state('brixton', {
      url: '/brixton',
      templateUrl: 'app/projects/brixton.html',
      controller: 'BrixtonController',
      controllerAs: 'brixton'
    })
    .state('eufn', {
      url: '/eufn',
      templateUrl: 'app/projects/eufn.html',
      controller: 'EufnController',
      controllerAs: 'eufn'
    })
    .state('lambeth', {
      url: '/lambeth',
      templateUrl: 'app/projects/lambeth.html',
      controller: 'LambethController',
      controllerAs: 'lambeth'
    })
    .state('lancastrians', {
      url: '/lancastrians',
      templateUrl: 'app/projects/lancastrians.html',
      controller: 'LancastriansController',
      controllerAs: 'lancastrians'
    })
    .state('layla', {
      url: '/layla',
      templateUrl: 'app/projects/layla.html',
      controller: 'LaylaController',
      controllerAs: 'layla'
    })
    .state('saffron', {
      url: '/saffron',
      templateUrl: 'app/projects/saffron.html',
      controller: 'SaffronController',
      controllerAs: 'saffron'
    });

  $urlRouterProvider.otherwise('/');
}

export default routerConfig;

function routerConfig ($stateProvider, $urlRouterProvider) {
  'ngInject';
  $stateProvider
    .state('home', {
      url: '/',
      templateUrl: 'app/main/main.html',
      controller: 'MainController',
      controllerAs: 'main'
    })
    .state('ambr', {
      url: '/ambr',
      templateUrl: 'app/projects/ambr.html'
    })
    .state('brixton', {
      url: '/brixton',
      templateUrl: 'app/projects/brixton.html'
    })
    .state('eufn', {
      url: '/eufn',
      templateUrl: 'app/projects/eufn.html'
    })
    .state('lambeth', {
      url: '/lambeth',
      templateUrl: 'app/projects/lambeth.html'
    })
    .state('lancastrians', {
      url: '/lancastrians',
      templateUrl: 'app/projects/lancastrians.html'
    })
    .state('layla', {
      url: '/layla',
      templateUrl: 'app/projects/layla.html'
    })
    .state('saffron', {
      url: '/saffron',
      templateUrl: 'app/projects/saffron.html'
    });

  $urlRouterProvider.otherwise('/');
}

export default routerConfig;

Remove references to controllers from project page routing


/* eslint-env mocha */
/* eslint-disable func-names, prefer-arrow-callback */

import { createUser, removeUser } from './helpers.js'

describe('APP - Log In', () => {
  beforeEach(() => removeUser());

  it('redirect to login @watch', () => {
    browser.url('http://localhost:3000')
           .waitForExist('.Login');

    expect(browser.getUrl()).to.equal('http://localhost:3000/login');
  });

  it('should allow us to login @watch', () => {
    createUser();

    browser.url('http://localhost:3000')
           .waitForExist('.Login');
    browser.setValue('[name="identifiant"]', 'admin@admin.com')
           .setValue('[name="password"]', 'password')
           .click('[type="submit"]');

    browser.waitForExist('.Index');
    expect(browser.getUrl()).to.equal('http://localhost:3000/');
  });
});

/* eslint-env mocha */
/* eslint-disable func-names, prefer-arrow-callback */

import { createUser, removeUser } from './helpers';

describe('APP - Log In', () => {
  beforeEach(() => removeUser());

  it('redirect to login @watch', () => {
    browser.url('http://localhost:3000')
           .waitForExist('.Login');

    expect(browser.getUrl()).to.equal('http://localhost:3000/login');
  });

  it('should allow us to login @watch', () => {
    createUser();

    browser.url('http://localhost:3000')
           .waitForExist('.Login');
    browser.setValue('[name="identifiant"]', 'admin@admin.com')
           .setValue('[name="password"]', 'password')
           .click('[type="submit"]');

    browser.waitForExist('.Index');
    expect(browser.getUrl()).to.equal('http://localhost:3000/');
  });
});

Update Acceptance test, fix import to app login


var webpack = require('webpack');

module.exports = {
  entry: './entry',
  externals: {
    // Add global variables you would like to import
    'react': 'React',
    'react-router': 'ReactRouter',
    'react-router-ssr': 'ReactRouterSSR',
    'react-meteor-data': 'ReactMeteorData',
    'blaze-to-react': 'BlazeToReact'
  },
  resolve: {
    extensions: ['', '.js', '.jsx', '.json', '.css', '.scss']
  },
  module: {
    loaders: [
      { test: /\.jsx?$/, loader: 'babel', query: { stage: 0 }, exclude: /node_modules/ },
      { test: /\.css$/, loader: 'style!css' },
      { test: /\.scss$/, loader: 'style!css!sass' },
      { test: /\.(png|jpe?g)(\?.*)?$/, loader: 'url?limit=8182' },
      { test: /\.(svg|ttf|woff|eot)(\?.*)?$/, loader: 'file' }
    ]
  }
};

var webpack = require('webpack');

module.exports = {
  entry: './entry',
  externals: {
    // Add global variables you would like to import
    'react': 'React',
    'react-router': 'ReactRouter',
    'react-router-ssr': 'ReactRouterSSR',
    'react-meteor-data': 'ReactMeteorData',
    'blaze-to-react': 'BlazeToReact'
  },
  resolve: {
    extensions: ['', '.js', '.jsx', '.json', '.css', '.scss']
  },
  module: {
    loaders: [
      { test: /\.jsx?$/, loader: 'babel', query: { stage: 0 }, exclude: /node_modules/ },
      { test: /\.css$/, loader: 'style-collector!css' },
      { test: /\.scss$/, loader: 'style-collector!css!sass' },
      { test: /\.(png|jpe?g)(\?.*)?$/, loader: 'url?limit=8182' },
      { test: /\.(svg|ttf|woff|eot)(\?.*)?$/, loader: 'file' }
    ]
  }
};

Fix CSS loaders for ssr

Fix CSS loaders for ssr


PANDA.views.DatasetsResults = Backbone.View.extend({
    template: PANDA.templates.datasets_results,
    pager_template: PANDA.templates.pager,

    initialize: function(options) {
        _.bindAll(this, "render");

        this.search = options.search;
        this.search.datasets.bind("reset", this.render);
    },

    render: function() {
        context = this.search.datasets.meta;
        context["settings"] = PANDA.settings;

        context["query"] = this.search.query;
        context["category"] = this.search.category;

        context["datasets"] = this.search.datasets.results()["datasets"];

        // Remove any lingering modal from previous usage
        $("#modal-dataset-search").remove();

        this.el.html(this.template(context));

        // Enable result sorting
        $("#datasets-results table").tablesorter({
            cssHeader: "no-sort-header",
            cssDesc: "sort-desc-header",
            cssAsc: "sort-asc-header",
            headers: {
                0: { sorter: "text" },
                1: { sorter: false },
                2: { sorter: "text" },
                3: { sorter: false }
            },
            textExtraction: function(node) {
                return $(node).children(".sort-value").text();
            }
        });

        // Create new modal
        $("#modal-dataset-search").modal({
            keyboard: true
        });
    }
});

PANDA.views.DatasetsResults = Backbone.View.extend({
    template: PANDA.templates.datasets_results,
    pager_template: PANDA.templates.pager,

    initialize: function(options) {
        _.bindAll(this, "render");

        this.search = options.search;
        this.search.datasets.bind("reset", this.render);
    },

    render: function() {
        context = this.search.datasets.meta;
        context["settings"] = PANDA.settings;

        context["query"] = this.search.query;
        context["category"] = this.search.category;

        context["datasets"] = this.search.datasets.results()["datasets"];

        this.el.html(this.template(context));

        // Enable result sorting
        $("#datasets-results table").tablesorter({
            cssHeader: "no-sort-header",
            cssDesc: "sort-desc-header",
            cssAsc: "sort-asc-header",
            headers: {
                0: { sorter: "text" },
                1: { sorter: false },
                2: { sorter: "text" },
                3: { sorter: false }
            },
            textExtraction: function(node) {
                return $(node).children(".sort-value").text();
            }
        });
    }
});

Remove extraneous references to modal.

Remove extraneous references to modal.


// Disable auto discover for all elements:
//Dropzone.autoDiscover = false;
var submissionDropzone;

Dropzone.options.submissionDropzone = {
    url: "/images/upload",
    maxFilesize: 2,
    paramName: "uploadfile",
    maxThumbnailFilesize: 2,
    clickable: true,
    maxFiles: 1,
    acceptedFiles: "image/jpeg,image/png",
    thumbnailWidth: 250,

    resize: function(file) {
        var ratio = 250 / file.width;
        var imgHeight = file.height * ratio;
        if (imgHeight > 250) {
            imgHeight = 250; //constrain
        }

        var resizeInfo = {
            srcX: 0,
            srcY: 0,
            trgX: 0,
            trgY: 0,
            srcWidth: file.width,
            srcHeight: file.height,
            trgWidth: this.options.thumbnailWidth,
            trgHeight: imgHeight
        };

        $('.dz-details img').height(imgHeight);

        return resizeInfo;
    },

    init: function() {
        submissionDropzone = this;

        this.on('success', function(file, json) {
            $("#imagefile").val(json.img);
        });

        this.on('error', function(file, errorMessage, xhr) {
            $(".dz-error-mark").click(function() {
                submissionDropzone.removeFile(file);
            });
        });

        this.on('addedfile', function(file) {

        });

        this.on('drop', function(file) {

        });
    }
};

// Disable auto discover for all elements:
//Dropzone.autoDiscover = false;
var submissionDropzone;

Dropzone.options.submissionDropzone = {
    url: "/images/upload",
    maxFilesize: 3,
    paramName: "uploadfile",
    maxThumbnailFilesize: 3,
    clickable: true,
    maxFiles: 1,
    acceptedFiles: "image/jpeg,image/png",
    thumbnailWidth: 250,

    resize: function(file) {
        var ratio = 250 / file.width;
        var imgHeight = file.height * ratio;
        if (imgHeight > 250) {
            imgHeight = 250; //constrain
        }

        var resizeInfo = {
            srcX: 0,
            srcY: 0,
            trgX: 0,
            trgY: 0,
            srcWidth: file.width,
            srcHeight: file.height,
            trgWidth: this.options.thumbnailWidth,
            trgHeight: imgHeight
        };

        $('.dz-details img').height(imgHeight);

        return resizeInfo;
    },

    init: function() {
        submissionDropzone = this;

        this.on('success', function(file, json) {
            $("#imagefile").val(json.img);
        });

        this.on('error', function(file, errorMessage, xhr) {
            $(".dz-error-mark").click(function() {
                submissionDropzone.removeFile(file);
            });
        });

        this.on('addedfile', function(file) {

        });

        this.on('drop', function(file) {

        });
    }
};

Increase default max image size to 3 MB. This should allow uploads from most phones with their default settings.


angular.module( 'App.Game.RatingGrowl' ).service( 'Game_RatingGrowl', function( App, Api, Growls )
{
	this.show = function( game )
	{
		// Don't show when not logged in.
		if ( !App.user ) {
			return;
		}

		// Don't show if ratings are disabled for the game.
		if ( !game.ratings_enabled ) {
			return;
		}

		// Don't show when this is the developer of the game.
		if ( App.user.id == game.developer.id ) {
			return;
		}

		Api.sendRequest( '/web/discover/games/ratings/get-user-rating/' + game.id, null, { detach: true } )
			.then( function( payload )
			{
				// If there is a rating for this user already, don't show the growl.
				if ( payload.rating ) {
					return;
				}

				Growls.success( {
					sticky: true,
					templateUrl: '/app/components/game/rating-growl/rating-growl.html',
					controller: 'Game_RatingGrowlCtrl',
					resolve: {
						game: function()
						{
							return game;
						}
					}
				} );
			} );
	};
} );

angular.module( 'App.Game.RatingGrowl' ).service( 'Game_RatingGrowl', function( App, Api, Growls )
{
	this.show = function( game )
	{
		// Don't show when not logged in.
		if ( !App.user ) {
			return;
		}

		// Don't show if ratings are disabled for the game.
		if ( !game.ratings_enabled ) {
			return;
		}

		// Don't show when this is the developer of the game.
		if ( App.user.id == game.developer.id ) {
			return;
		}

		Api.sendRequest( '/web/discover/games/ratings/get-user-rating/' + game.id, null, { detach: true } )
			.then( function( payload )
			{
				// If there is a rating for this user already, don't show the growl.
				if ( payload.rating ) {
					return;
				}

				Growls.info( {
					sticky: true,
					templateUrl: '/app/components/game/rating-growl/rating-growl.html',
					controller: 'Game_RatingGrowlCtrl',
					resolve: {
						game: function()
						{
							return game;
						}
					}
				} );
			} );
	};
} );

Use info growl for game rating growl. It fits better with the component.


/**
 * Login page
 */
'use strict';
var $ = require('jquery');

var passwordForms = require('js/passwordForms');

var activateToggleBox = function () {
    var el = $(this);

    if (el.hasClass('toggle-box-muted')) {
        $('.toggle-box-active').removeClass('toggle-box-active').addClass('toggle-box-muted');
        el.removeClass('toggle-box-muted').addClass('toggle-box-active');
    }
};

$(document).ready(function() {
    new passwordForms.SignUp('#signUpScope');
});

$('.toggle-box').on('click', activateToggleBox);
$('.toggle-box').on('focus', '*', function() {
    activateToggleBox.apply( $(this).parents('.toggle-box') );
});

/**
 * Login page
 */
'use strict';
var $ = require('jquery');

var passwordForms = require('js/passwordForms');

var activateToggleBox = function () {
    var el = $(this);

    if (el.hasClass('toggle-box-muted')) {
        $('.toggle-box-active').removeClass('toggle-box-active').addClass('toggle-box-muted');
        el.removeClass('toggle-box-muted').addClass('toggle-box-active');
    }
};

$(document).ready(function() {
    var campaign = window.contextVars.campaign;
    new passwordForms.SignUp('#signUpScope', campaign);
});

$('.toggle-box').on('click', activateToggleBox);
$('.toggle-box').on('focus', '*', function() {
    activateToggleBox.apply( $(this).parents('.toggle-box') );
});

Put back accidentally removed `campaign`.


// Delete these three lines once you have your environment variables set
// The environment-configured 'keen' variable is set in layout.erb

Keen.ready(function(){

  // ----------------------------------------
  // Pageviews Area Chart
  // ----------------------------------------
  var repos_timeline = new Keen.Query("maximum", {
    eventCollection: "repository_snapshots",
    targetProperty: "stargazers_count",
    interval: "daily",
    groupBy: "full_name",
    timeframe: "this_210_hours"
  });

  keenClient.draw(repos_timeline, document.getElementById("chart-01"), {
    chartType: "areachart",
    title: false,
    height: 250,
    width: "auto",
    chartOptions: {
      chartArea: {
        height: "85%",
        left: "5%",
        top: "5%",
        width: "80%"
      },
      isStacked: false
    }
  });

  var repos_now = new Keen.Query("maximum", {
    eventCollection: "repository_snapshots",
    targetProperty: "stargazers_count",
    groupBy: "full_name",
    timeframe: "this_1_hour"
  });

  keenClient.draw(repos_now, document.getElementById("chart-02"), {
    chartType: "piechart",
    title: false,
    height: 250,
    width: "auto",
    chartOptions: {
      chartArea: {
        height: "85%",
        left: "5%",
        top: "5%",
        width: "100%"
      }
    }
  });

});

// Delete these three lines once you have your environment variables set
// The environment-configured 'keen' variable is set in layout.erb

Keen.ready(function(){

  // ----------------------------------------
  // Pageviews Area Chart
  // ----------------------------------------
  var repos_timeline = new Keen.Query("maximum", {
    eventCollection: "repository_snapshots",
    targetProperty: "stargazers_count",
    interval: "daily",
    groupBy: "full_name",
    timeframe: "last_210_hours"
  });

  keenClient.draw(repos_timeline, document.getElementById("chart-01"), {
    chartType: "areachart",
    title: false,
    height: 250,
    width: "auto",
    chartOptions: {
      chartArea: {
        height: "85%",
        left: "5%",
        top: "5%",
        width: "80%"
      },
      isStacked: false
    }
  });

  var repos_now = new Keen.Query("maximum", {
    eventCollection: "repository_snapshots",
    targetProperty: "stargazers_count",
    groupBy: "full_name",
    timeframe: "last_1_hour"
  });

  keenClient.draw(repos_now, document.getElementById("chart-02"), {
    chartType: "piechart",
    title: false,
    height: 250,
    width: "auto",
    chartOptions: {
      chartArea: {
        height: "85%",
        left: "5%",
        top: "5%",
        width: "100%"
      }
    }
  });

});

Use last hour to avoid empty interval

Use last hour to avoid empty interval


(function() {
  var selector = "run_link";
  var waiting_id = null;
  var counting_id = null;
  var timer_dom = 'counter';
  var wait_dom = 'please_wait';
  var wait_secs = 20;
  var counter = 0;

  var hideWait = function() {
    waiting_id = null;
    clearInterval(counting_id);
    counting_id = null;
    $(timer_dom).update('completed');
    $(wait_dom).hide();
  }

  var update_counter = function() {
    $(timer_dom).update(counter);
    counter = counter -1;
  }
  var showWait = function() {
    if (waiting_id || counting_id) {
      return;
    }
    waiting_id = setTimeout(hideWait,wait_secs * 1000);
    $(timer_dom).update(wait_secs);
    counting_id = setInterval(update_counter,1000);
    counter=wait_secs;
    $(wait_dom).show();
  };

  document.observe("dom:loaded", function() {
    $$("." + selector).each(function(item) {
      item.observe("click", showWait);
    });
  });
}());

var showWait = function() {
  var selector = "run_link";
  var waiting_id = null;
  var counting_id = null;
  var timer_dom = 'counter';
  var wait_dom = 'please_wait';
  var wait_secs = 20;
  var counter = 0;

  var hideWait = function() {
    waiting_id = null;
    clearInterval(counting_id);
    counting_id = null;
    $(timer_dom).update('completed');
    $(wait_dom).hide();
  }

  var update_counter = function() {
    $(timer_dom).update(counter);
    counter = counter -1;
  }
  if (waiting_id || counting_id) {
    return;
  }
  waiting_id = setTimeout(hideWait,wait_secs * 1000);
  $(timer_dom).update(wait_secs);
  counting_id = setInterval(update_counter,1000);
  counter=wait_secs;
  $(wait_dom).show();
};

document.observe("dom:loaded", function() {
  $$(".run_link").each(function(item) {
    item.observe("click", showWait);
  });
});

Make showWait() available to other scripts.


define(["backbone", "utils"], function(B, $u) {
    return B.View.extend({
        initialize: function(options) {
            if (options.url)
                this.template = $u.templateWithUrl(options.url);
            else if (options.template)
                this.template = function(_, cb) {
                    cb(options.template());
                };

            if (!this.template)
                throw new Error("You must initialize a modal view with a URL or template.");

            this.showingClass = options.showingClass || "showing";
            this.container = options.container || "#modal";
            this.shouldShow = false;
        },

        el: "#modal-contents",

        getContainer: function() {
            return this.$el.closest(this.container);
        },

        getContext: function() {
            return {model: this.model,
                    collection: this.collection};
        },

        _update: function() {
            this.getContainer()
                .toggleClass(this.showingClass, this.shouldShow)
                .toggle(this.shouldShow);

            if (this.shouldShow && this.wasRendered)
                this.wasRendered();
        },

        render: function() {
            if (this.shouldShow) {
                var self = this;
                this.template(
                    this.getContext(),
                    function(html) {
                        self.$el.html(html);
                        self._update();
                    });
            }

            return this;
        },

        show: function() {
            this.shouldShow = true;
            this.render();
        },

        hide: function() {
            this.shouldShow = false;
            this._update();
        }
    });
});

define(["backbone", "jquery", "utils"], function(B, $, $u) {
    return B.View.extend({
        initialize: function(options) {
            if (options.url)
                this.template = $u.templateWithUrl(options.url);
            else if (options.template)
                this.template = function(_, cb) {
                    cb(options.template());
                };

            if (!this.template)
                throw new Error("You must initialize a modal view with a URL or template.");

            this.showingClass = options.showingClass || "showing";
            this.container = options.container || "#modal";
            this.shouldShow = false;
        },

        el: "#modal-contents",

        getContainer: function() {
            return this.$el.closest(this.container);
        },

        getContext: function() {
            return {model: this.model,
                    collection: this.collection};
        },

        _update: function() {
            this.getContainer()
                .toggleClass(this.showingClass, this.shouldShow)
                .toggle(this.shouldShow);

            $(document.body).toggleClass("modal", this.shouldShow);

            if (this.shouldShow && this.wasRendered)
                this.wasRendered();
        },

        render: function() {
            if (this.shouldShow) {
                var self = this;
                this.template(
                    this.getContext(),
                    function(html) {
                        self.$el.html(html);
                        self._update();
                    });
            }

            return this;
        },

        show: function() {
            this.shouldShow = true;
            this.render();
        },

        hide: function() {
            this.shouldShow = false;
            this._update();
        }
    });
});

Add modal class to body when a modal view is shown