<commit_before>(function() {
	"use strict";

	function requestPermission() {
		require(['notify'], function(Notify) {
			(new Notify('NodeBB')).requestPermission();
		});
	}

	jQuery('document').ready(function() {
		var logo = $('.forum-logo').attr('src');

		requestPermission();

		jQuery('#notif_dropdown').on('click', function() {
			requestPermission();
		});

		jQuery('*').on('click', function() {
			requestPermission();
		});

		socket.on('event:new_notification', function(data) {
			if (data.text) {
				var notification = new Notify('NodeBB', {
					body: data.text.replace(/<strong>/g, '').replace(/<\/strong>/g, ''),
					icon: logo,
					notifyClick: function() {
						ajaxify.go(data.path.substring(1));
					}
				});

				notification.show();
			}
		});
	});
}());<commit_msg>fixed another bug, I really shouldn't be coding this late<commit_after>(function() {
	"use strict";

	function requestPermission() {
		require(['notify'], function(Notify) {
			(new Notify('NodeBB')).requestPermission();
		});
	}

	jQuery('document').ready(function() {
		var logo = $('.forum-logo').attr('src');

		requestPermission();

		jQuery('#notif_dropdown').on('click', function() {
			requestPermission();
		});

		jQuery('*').on('click', function() {
			requestPermission();
		});

		socket.on('event:new_notification', function(data) {
			if (data.text) {
				require(['notify'], function(Notify) {
					var notification = new Notify('NodeBB', {
						body: data.text.replace(/<strong>/g, '').replace(/<\/strong>/g, ''),
						icon: logo,
						notifyClick: function() {
							ajaxify.go(data.path.substring(1));
						}
					});
				});

				notification.show();
			}
		});
	});
}());<|endoftext|>


<commit_before>import React from 'react';
import {shallow} from 'enzyme';
import {shallowToJson} from 'enzyme-to-json';
import configureStore from 'redux-mock-store';
import Work from './Work';
import initialState from '../reducers/initialState';

describe('Work Component', () => {
  let middlewares, mockStore, store;
  beforeEach(() => {
    middlewares = [];
    mockStore = configureStore(middlewares);
    store = mockStore(initialState);
  });

  it('renders the work component', () => {
    const wrapper = shallow(<Work store={store}/>);
    expect(shallowToJson(wrapper)).toMatchSnapshot();
  });
});<commit_msg>Work spec formatting<commit_after>import React from 'react';
import {shallow} from 'enzyme';
import {shallowToJson} from 'enzyme-to-json';
import configureStore from 'redux-mock-store';
import Work from './Work';
import initialState from '../reducers/initialState';

describe('Work Component', () => {
  let middlewares, mockStore, store;
  beforeEach(() => {
    middlewares = [];
    mockStore = configureStore(middlewares);
    store = mockStore(initialState);
  });

  it('renders the work component', () => {
    const wrapper = shallow(<Work store={store} />);
    expect(shallowToJson(wrapper)).toMatchSnapshot();
  });
});<|endoftext|>


<commit_before>/* jshint node: true */
/* global $: true */
"use strict";

var gulp = require( "gulp" ),
	/** @type {Object} Loader of Gulp plugins from `package.json` */
	$ = require( "gulp-load-plugins" )(),
	/** @type {Array} JS source files to concatenate and uglify */
	uglifySrc = [
		/** Modernizr */
		"src/bower_components/modernizr/modernizr.js",
		/** Conditionizr */
		"src/js/lib/conditionizr-4.3.0.min.js",
		/** jQuery */
		"src/bower_components/jquery/dist/jquery.js",
		/** Page scripts */
		"src/js/scripts.js"
	],
	/** @type {Object of Array} CSS source files to concatenate and minify */
	cssminSrc = {
		development: [
			/** The banner of `style.css` */
			"src/css/banner.css",
			/** Theme style */
			"src/css/style.css"
		],
		production: [
			/** The banner of `style.css` */
			"src/css/banner.css",
			/** Normalize */
			"src/bower_components/normalize.css/normalize.css",
			/** Theme style */
			"src/css/style.css"
		]
	},
	/** @type {String} Used inside task for set the mode to 'development' or 'production' */
	env = (function() {
		/** @type {String} Default value of env */
		var env = "development";

		/** Test if there was a different value from CLI to env
			Example: gulp styles --env=production
			When ES6 will be default. `find` will replace `some`  */
		process.argv.some(function( key ) {
			var matches = key.match( /^\-{2}env\=([A-Za-z]+)$/ );

			if ( matches && matches.length === 2 ) {
				env = matches[1];
				return true;
			}
		});

		return env;
	} ());

/** Clean */
gulp.task( "clean", require( "del" ).bind( null, [ ".tmp", "dist" ] ) );

/** Copy */
gulp.task( "copy", function() {
	return gulp.src([
			"src/*.{php,png,css}",
			"src/modules/*.php",
			"src/img/**/*.{jpg,png,svg,gif,webp,ico}",
			"src/fonts/*.{woff,woff2,ttf,otf,eot,svg}",
			"src/languages/*.{po,mo,pot}"
		], {
			base: "src"
		})
		.pipe( gulp.dest( "dist" ) );
});

/** CSS Preprocessors */
gulp.task( "sass", function () {
	return gulp.src( "src/css/sass/style.scss" )
		.pipe( $.sourcemaps.init() )
		.pipe( $.sass() )
		.pipe( $.sourcemaps.write( "./maps" ) )
		.on( "error", function( e ) {
			console.error( e );
		})
		.pipe( gulp.dest( "src/css" ) );
});

/** STYLES */
gulp.task( "styles", [ "sass" ], function() {
	console.log( "`styles` task run in `" + env + "` environment" );

	var stream = gulp.src( cssminSrc[ env ] )
		.pipe( $.concat( "style.css" ))
		.pipe( $.autoprefixer( "last 2 version" ) );

	if ( env === "production" ) {
		stream = stream.pipe( $.csso() );
	}

	return stream.on( "error", function( e ) {
			console.error( e );
		})
		.pipe( gulp.dest( "src" ) );
});

/** JSHint */
gulp.task( "jshint", function () {
	/** Test all `js` files exclude those in the `lib` folder */
	return gulp.src( "src/js/{!(lib)/*.js,*.js}" )
		.pipe( $.jshint() )
		.pipe( $.jshint.reporter( "jshint-stylish" ) )
		.pipe( $.jshint.reporter( "fail" ) );
});

/** Templates */
gulp.task( "template", function() {
	console.log( "`template` task run in `" + env + "` environment" );

    var is_debug = ( env === "production" ? "false" : "true" );

    return gulp.src( "src/dev-templates/is-debug.php" )
        .pipe( $.template({ is_debug: is_debug }) )
        .pipe( gulp.dest( "src/modules" ) );
});

/** Uglify */
gulp.task( "uglify", function() {
	return gulp.src( uglifySrc )
		.pipe( $.concat( "scripts.min.js" ) )
		.pipe( $.uglify() )
		.pipe( gulp.dest( "dist/js" ) );
});

/** `env` to 'production' */
gulp.task( "envProduction", function() {
	env = "production";
});

/** Livereload */
gulp.task( "watch", [ "template", "styles", "jshint" ], function() {
	var server = $.livereload();

	/** Watch for livereoad */
	gulp.watch([
		"src/js/**/*.js",
		"src/*.php",
		"src/*.css"
	]).on( "change", function( file ) {
		console.log( file.path );
		server.changed( file.path );
	});

	/** Watch for autoprefix */
	gulp.watch( [
		"src/css/*.css",
		"src/css/sass/**/*.scss"
	], [ "styles" ] );

	/** Watch for JSHint */
	gulp.watch( "src/js/{!(lib)/*.js,*.js}", ["jshint"] );
});

/** Build */
gulp.task( "build", [
	"envProduction",
	"clean",
	"template",
	"styles",
	"jshint",
	"copy",
	"uglify"
], function () {
	console.log("Build is finished");
});

/** Gulp default task */
gulp.task( "default", ["watch"] );
<commit_msg>remove sourcemaps subdirectory<commit_after>/* jshint node: true */
/* global $: true */
"use strict";

var gulp = require( "gulp" ),
	/** @type {Object} Loader of Gulp plugins from `package.json` */
	$ = require( "gulp-load-plugins" )(),
	/** @type {Array} JS source files to concatenate and uglify */
	uglifySrc = [
		/** Modernizr */
		"src/bower_components/modernizr/modernizr.js",
		/** Conditionizr */
		"src/js/lib/conditionizr-4.3.0.min.js",
		/** jQuery */
		"src/bower_components/jquery/dist/jquery.js",
		/** Page scripts */
		"src/js/scripts.js"
	],
	/** @type {Object of Array} CSS source files to concatenate and minify */
	cssminSrc = {
		development: [
			/** The banner of `style.css` */
			"src/css/banner.css",
			/** Theme style */
			"src/css/style.css"
		],
		production: [
			/** The banner of `style.css` */
			"src/css/banner.css",
			/** Normalize */
			"src/bower_components/normalize.css/normalize.css",
			/** Theme style */
			"src/css/style.css"
		]
	},
	/** @type {String} Used inside task for set the mode to 'development' or 'production' */
	env = (function() {
		/** @type {String} Default value of env */
		var env = "development";

		/** Test if there was a different value from CLI to env
			Example: gulp styles --env=production
			When ES6 will be default. `find` will replace `some`  */
		process.argv.some(function( key ) {
			var matches = key.match( /^\-{2}env\=([A-Za-z]+)$/ );

			if ( matches && matches.length === 2 ) {
				env = matches[1];
				return true;
			}
		});

		return env;
	} ());

/** Clean */
gulp.task( "clean", require( "del" ).bind( null, [ ".tmp", "dist" ] ) );

/** Copy */
gulp.task( "copy", function() {
	return gulp.src([
			"src/*.{php,png,css}",
			"src/modules/*.php",
			"src/img/**/*.{jpg,png,svg,gif,webp,ico}",
			"src/fonts/*.{woff,woff2,ttf,otf,eot,svg}",
			"src/languages/*.{po,mo,pot}"
		], {
			base: "src"
		})
		.pipe( gulp.dest( "dist" ) );
});

/** CSS Preprocessors */
gulp.task( "sass", function () {
	return gulp.src( "src/css/sass/style.scss" )
		.pipe( $.sourcemaps.init() )
		.pipe( $.sass() )
		.pipe( $.sourcemaps.write( "." ) )
		.on( "error", function( e ) {
			console.error( e );
		})
		.pipe( gulp.dest( "src/css" ) );
});

/** STYLES */
gulp.task( "styles", [ "sass" ], function() {
	console.log( "`styles` task run in `" + env + "` environment" );

	var stream = gulp.src( cssminSrc[ env ] )
		.pipe( $.concat( "style.css" ))
		.pipe( $.autoprefixer( "last 2 version" ) );

	if ( env === "production" ) {
		stream = stream.pipe( $.csso() );
	}

	return stream.on( "error", function( e ) {
			console.error( e );
		})
		.pipe( gulp.dest( "src" ) );
});

/** JSHint */
gulp.task( "jshint", function () {
	/** Test all `js` files exclude those in the `lib` folder */
	return gulp.src( "src/js/{!(lib)/*.js,*.js}" )
		.pipe( $.jshint() )
		.pipe( $.jshint.reporter( "jshint-stylish" ) )
		.pipe( $.jshint.reporter( "fail" ) );
});

/** Templates */
gulp.task( "template", function() {
	console.log( "`template` task run in `" + env + "` environment" );

    var is_debug = ( env === "production" ? "false" : "true" );

    return gulp.src( "src/dev-templates/is-debug.php" )
        .pipe( $.template({ is_debug: is_debug }) )
        .pipe( gulp.dest( "src/modules" ) );
});

/** Uglify */
gulp.task( "uglify", function() {
	return gulp.src( uglifySrc )
		.pipe( $.concat( "scripts.min.js" ) )
		.pipe( $.uglify() )
		.pipe( gulp.dest( "dist/js" ) );
});

/** `env` to 'production' */
gulp.task( "envProduction", function() {
	env = "production";
});

/** Livereload */
gulp.task( "watch", [ "template", "styles", "jshint" ], function() {
	var server = $.livereload();

	/** Watch for livereoad */
	gulp.watch([
		"src/js/**/*.js",
		"src/*.php",
		"src/*.css"
	]).on( "change", function( file ) {
		console.log( file.path );
		server.changed( file.path );
	});

	/** Watch for autoprefix */
	gulp.watch( [
		"src/css/*.css",
		"src/css/sass/**/*.scss"
	], [ "styles" ] );

	/** Watch for JSHint */
	gulp.watch( "src/js/{!(lib)/*.js,*.js}", ["jshint"] );
});

/** Build */
gulp.task( "build", [
	"envProduction",
	"clean",
	"template",
	"styles",
	"jshint",
	"copy",
	"uglify"
], function () {
	console.log("Build is finished");
});

/** Gulp default task */
gulp.task( "default", ["watch"] );
<|endoftext|>


<commit_before>// @flow

import {
  type ClientReportCreationRequest,
  type ReportCreationResponse,
  type ClearDeliveredReportsPayload,
  queuedClientReportCreationRequestPropType,
} from '../types/report-types';
import type { DispatchActionPromise } from '../utils/action-utils';
import type { AppState } from '../types/redux-types';

import * as React from 'react';
import PropTypes from 'prop-types';

import { connect } from '../utils/redux-utils';
import { sendReportActionTypes, sendReport } from '../actions/report-actions';
import { queuedReports } from '../selectors/socket-selectors';
import { ServerError } from '../utils/errors';

type Props = {|
  canSendReports: boolean,
  // Redux state
  queuedReports: $ReadOnlyArray<ClientReportCreationRequest>,
  // Redux dispatch functions
  dispatchActionPromise: DispatchActionPromise,
  // async functions that hit server APIs
  sendReport: (
    request: ClientReportCreationRequest,
  ) => Promise<ReportCreationResponse>,
|};
class ReportHandler extends React.PureComponent<Props> {
  static propTypes = {
    canSendReports: PropTypes.bool.isRequired,
    queuedReports: PropTypes.arrayOf(queuedClientReportCreationRequestPropType)
      .isRequired,
    dispatchActionPromise: PropTypes.func.isRequired,
    sendReport: PropTypes.func.isRequired,
  };

  componentDidMount() {
    if (this.props.canSendReports) {
      this.sendResponses(this.props.queuedReports);
    }
  }

  componentDidUpdate(prevProps: Props) {
    if (!this.props.canSendReports) {
      return;
    }

    const couldSend = prevProps.canSendReports;
    const curReports = this.props.queuedReports;
    if (!couldSend) {
      this.sendResponses(curReports);
      return;
    }

    const prevReports = prevProps.queuedReports;
    if (curReports !== prevReports) {
      const prevResponses = new Set(prevReports);
      const newResponses = curReports.filter(
        response => !prevResponses.has(response),
      );
      this.sendResponses(newResponses);
    }
  }

  render() {
    return null;
  }

  sendResponses(responses: $ReadOnlyArray<ClientReportCreationRequest>) {
    for (let response of responses) {
      this.props.dispatchActionPromise(
        sendReportActionTypes,
        this.sendResponse(response),
      );
    }
  }

  async sendResponse(report: ClientReportCreationRequest) {
    await this.sendReport(report);
    return ({ reports: [report] }: ClearDeliveredReportsPayload);
  }

  async sendReport(report: ClientReportCreationRequest) {
    try {
      await this.props.sendReport(report);
    } catch (e) {
      if (e instanceof ServerError && e.message === 'ignored_report') {
        // nothing
      } else {
        throw e;
      }
    }
  }
}

export default connect(
  (state: AppState) => ({
    queuedReports: queuedReports(state),
  }),
  { sendReport },
)(ReportHandler);
<commit_msg>[lib] Use new multi-report creation endpoint in ReportHandler<commit_after>// @flow

import {
  type ClientReportCreationRequest,
  type ClearDeliveredReportsPayload,
  queuedClientReportCreationRequestPropType,
} from '../types/report-types';
import type { DispatchActionPromise } from '../utils/action-utils';
import type { AppState } from '../types/redux-types';

import * as React from 'react';
import PropTypes from 'prop-types';

import { connect } from '../utils/redux-utils';
import { sendReportsActionTypes, sendReports } from '../actions/report-actions';
import { queuedReports } from '../selectors/socket-selectors';

type Props = {|
  canSendReports: boolean,
  // Redux state
  queuedReports: $ReadOnlyArray<ClientReportCreationRequest>,
  // Redux dispatch functions
  dispatchActionPromise: DispatchActionPromise,
  // async functions that hit server APIs
  sendReports: (
    reports: $ReadOnlyArray<ClientReportCreationRequest>,
  ) => Promise<void>,
|};
class ReportHandler extends React.PureComponent<Props> {
  static propTypes = {
    canSendReports: PropTypes.bool.isRequired,
    queuedReports: PropTypes.arrayOf(queuedClientReportCreationRequestPropType)
      .isRequired,
    dispatchActionPromise: PropTypes.func.isRequired,
    sendReports: PropTypes.func.isRequired,
  };

  componentDidMount() {
    if (this.props.canSendReports) {
      this.dispatchSendReports(this.props.queuedReports);
    }
  }

  componentDidUpdate(prevProps: Props) {
    if (!this.props.canSendReports) {
      return;
    }

    const couldSend = prevProps.canSendReports;
    const curReports = this.props.queuedReports;
    if (!couldSend) {
      this.dispatchSendReports(curReports);
      return;
    }

    const prevReports = prevProps.queuedReports;
    if (curReports !== prevReports) {
      const prevResponses = new Set(prevReports);
      const newResponses = curReports.filter(
        response => !prevResponses.has(response),
      );
      this.dispatchSendReports(newResponses);
    }
  }

  render() {
    return null;
  }

  dispatchSendReports(reports: $ReadOnlyArray<ClientReportCreationRequest>) {
    if (reports.length === 0) {
      return;
    }
    this.props.dispatchActionPromise(
      sendReportsActionTypes,
      this.sendReports(reports),
    );
  }

  async sendReports(reports: $ReadOnlyArray<ClientReportCreationRequest>) {
    await this.props.sendReports(reports);
    return ({ reports }: ClearDeliveredReportsPayload);
  }
}

export default connect(
  (state: AppState) => ({
    queuedReports: queuedReports(state),
  }),
  { sendReports },
)(ReportHandler);
<|endoftext|>


<commit_before>import faker from 'faker';
import Chance from 'chance';
import Base from './base';
import { objectSearch } from './utils';
import { set, get } from 'lodash';
import to from 'to-js';

////
/// @name Document
/// @page api/document
////

/// @name Document
/// @description This is used to generate documents based off a model
export default class Document extends Base {
  constructor(options, documents = {}, globals = {}, inputs = {}) {
    super(options);
    this.options = this.options || {};
    this.documents = documents;
    this.globals = globals;
    this.inputs = inputs;
    // set chance and faker without a seed by default
    // so it can still be used
    this.chance = new Chance();
    this.faker = faker;
    this.updateFakers(this.options.seed);
  }

  ///# @name build
  ///# @description
  ///# This builds the documents from the passed model
  ///# @arg {object} model - The model to generate data from
  ///# @returns {array} - The array of documents that were generated
  build(model) {
    if (!this.documents[model.name]) {
      this.documents[model.name] = [];
    }

    this.updateFakers(model.seed);

    if (!model.data) {
      model.data = { count: 1 };
    }
    const key_type = to.type(model.key);

    // if there is a pre_run function call it
    this.runData(model.data.pre_run, model);

    this.log('info', `Generating ${this.options.count || model.count} document(s) for ${model.name} model`);

    for (let i = 0; i < model.data.count; i++) { // loop over each model and execute in order of dependency
      const doc = this.buildDocument(model, i);
      // build the key for the document
      let key;
      if (key_type === 'object') {
        key = this.buildValue({ data: model.key }, null, doc, i);
      } else if (key_type === 'string') {
        key = doc[model.key];
      } else {
        key = `${model.name}${i}`;
      }

      // @todo update this to use `new Map`, or `new WeakMap`;
      Object.defineProperty(doc, '__key', { value: key });
      Object.defineProperty(doc, '__name', { value: model.name });
      this.documents[model.name].push(doc);
    }

    this.runData(model.data.post_run, model);
    return this.documents[model.name];
  }

  ///# @name updateFakers
  ///# @description
  ///# If a usable seed is passed then this updates the instances of chance and faker to use a seed version
  ///# @arg {number, null} seed - The seed to use for this instance
  ///# @arg {number} modifier
  updateFakers(seed) {
    // if the seed is a number then update
    // the instance of chance and faker
    if (seed && seed !== this.options.seed) {
      this.chance = new Chance(seed);
      this.faker.seed(seed);
    }
  }

  ///# @name runData
  ///# @description used to run the different functions that the users can pass in into the data object
  ///# @arg {function} fn - The function to run
  ///# @arg {*} context - The `this` context
  ///# @arg {number} index [0] - The current index of the generated items
  ///# @returns {*} - What ever the function that runs returns
  runData(fn, context, index = 0) {
    if (to.type(fn) === 'function') {
      try {
        return fn.call(context, this.documents, this.globals, this.inputs, this.faker, this.chance, index);
      } catch (e) {
        this.log('error', `${fn.name} failed\n`, e);
      }
    }
  }

  ///# @name buildDocument
  ///# @description
  ///# builds a document
  ///# @arg {object} model - The model to build the document from
  ///# @arg {number} index [0] - The place in the list this item is being run from
  buildDocument(model, index = 0) {
    const paths = getPaths(model);
    // generate the initial values
    let doc = this.initializeDocument(model, paths);

    // if there is a pre_build function for the document call it
    this.runData(model.data.pre_build, doc, index);

    doc = this.buildObject(model, doc, paths, index);
    doc = this.postProcess(model, doc, paths, index);

    // if there is a post_build function for the document call it
    this.runData(model.data.post_build, doc, index);

    return doc;
  }

  ///# @name initializeDocument
  ///# @description initializes a documents default values
  ///# @arg {object} model - The model to parse
  ///# @arg {object} paths - The paths to loop over
  ///# @returns {object} - The document with the defaults
  initializeDocument(model, paths) {
    if (!paths || !paths.model || !paths.document) {
      paths = getPaths(model);
    }
    const doc = {};
    for (let [ i, str ] of to.entries(paths.model)) {
      let key = paths.document[i]; // set a key for error messaging
      try {
        set(doc, key, typeToValue(get(model, str).type));
      } catch (e) {
        this.log('error', `Initializing Properties in Model: "${model.name}" for Key: "${key}"\n`, e);
      }
    }
    return doc;
  }

  ///# @name buildObject
  ///# @description builds an object based on a model
  ///# @arg {object} model - The model to parse
  ///# @arg {object} doc - The document to update
  ///# @arg {object} paths - The paths to loop over
  ///# @arg {number} index - The current index
  ///# @returns {object} - The document with the defaults
  buildObject(model, doc, paths, index) {
    for (let [ i, str ] of to.entries(paths.model)) {
      let key = paths.document[i]; // set a key for error messaging
      try {
        const value = this.buildValue(get(model, str), get(doc, key), doc, index);
        set(doc, key, value);
      } catch (e) {
        this.log('error', `Building Properties in Model: "${model.name}" for Key: "${key}"\n`, e);
      }
    }

    return doc;
  }

  ///# @name buildValue
  ///# @description builds a single value based on a property definition
  ///# @arg {object} property - The property to run
  ///# To build a normal value
  ///# ```js
  ///# {
  ///#   type: '',  // 'object', 'structure', 'string', 'number', 'float', 'integer', etc..
  ///#   data: {
  ///#     pre_build() {}, // optional
  ///#     value: '', // optional
  ///#     build() {}, // optional
  ///#     fake: '', // optional
  ///#   }
  ///# }
  ///# ```
  ///# To build an array
  ///# ```js
  ///# {
  ///#   type: 'array',
  ///#   items: {
  ///#     type: '',  // 'object', 'structure', 'string', 'number', 'float', 'integer', etc..
  ///#     data: {
  ///#       pre_build() {}, // optional
  ///#       value: '', // optional
  ///#       build() {}, // optional
  ///#       fake: '', // optional
  ///#     }
  ///#   }
  ///# }
  ///# ```
  ///# @arg {*} value - The default value
  ///# @arg {object} doc [{}] - The current document
  ///# @arg {number} index [0] - The place in the list this item is being run from
  ///# @return {*} - The result
  buildValue(property, value, doc = {}, index = 0) {
    if (property.data) {
      if (property.data.pre_build) {
        value = this.runData(property.data.pre_build, doc, index);
      }
      if (property.data.value) {
        return property.data.value;
      } else if (property.data.build) {
        return this.runData(property.data.build, doc, index);
      } else if (property.data.fake) {
        return this.faker.fake(property.data.fake);
      }
    } else if (
      property.type === 'array' &&
      property.items
    ) {
      let { count, min, max } = property.items.data;
      if (count <= 0 && !!max) {
        count = this.chance.integer({ min, max });
      }

      // builds a complex array
      if (property.items.type === 'object') {
        for (let i = 0; i < count; i++) {
          value[i] = this.buildDocument(property.items, index);
        }
        return value;
      }

      // builds a simple array
      for (let i = 0; i < count; i++) {
        const result = this.buildValue(property.items, typeToValue(property.items.type), doc, index);
        if (result !== undefined) { // eslint-disable-line no-undefined
          value.push(result);
        }
      }
      return value;
    }

    return value;
  }

  ///# @name postProcess
  ///# @description Post process a document after generation
  ///# @arg {object} model - The model to parse
  ///# @arg {object} doc - The document to update
  ///# @arg {object} paths - The paths to loop over
  ///# @arg {number} index [0] - The current index
  ///# @returns {object} - The updated document
  postProcess(model, doc, paths, index = 0) {
    for (let [ i, str ] of to.entries(paths.model)) {
      let key = paths.document[i]; // set a key for error messaging
      try {
        const { data = {}, items = {}, type } = get(model, str);
        let value = get(doc, key);

        // if there is a post_build block
        if (data.post_build) {
          let temp = this.runData(data.post_build, doc, index);
          if (temp != null) {
            value = temp;
          }
        } else if (
          (items.data || {}).post_build &&
          items.type !== 'object' // if the type is an object it will run each item through this function already
        ) {
          for (let a = 0; a < value.length; a++) {
            let temp = transformValueToType(items.type, this.runData(items.data.post_build, doc[key][a], index));
            if (temp != null) {
              value[a] = temp;
            }
          }
        }

        set(doc, key, transformValueToType(type, value));
      } catch (e) {
        this.log('error', `Transforming Properties in Model: "${model.name}" for Key: "${key}"\n`, e);
      }
    }

    return doc;
  }
}

/// @name transformValueToType
/// @description This will transform a value to the correct type
/// @arg {string} type - The type to convert the value to
/// @arg {*} value - The actual value
/// @returns {*} - The converted value
export function transformValueToType(type, value) {
  if (
    type == null ||
    value == null ||
    type === 'array'
  ) {
    return value;
  }

  // if it is an integer make sure it is treated as such
  if ('number,integer,long'.includes(type)) {
    return parseInt(value);
  }
  // if it is a double / float make sure it is treated as such
  if ('double,float'.includes(type)) {
    return parseFloat(value);
  }

  // if it is a string make sure it is treated as such
  if (type === 'string') {
    return value.toString();
  }

  // if it is a string make sure it is treated as such
  if ('boolean,bool'.includes(type)) {
    // if the value is a string that is 'false', '0', 'undefined', or 'null' as a string set a boolean false
    if (
      typeof value === 'string' && (
        value === 'false' ||
        value === '0' ||
        value === 'undefined' ||
        value === 'null'
      )
    ) {
      return false;
    }
    return Boolean(value);
  }

  return value;
}

/// @name getPaths
/// @description finds all the paths to be used
/// @arg {object} obj - The object to be searched
/// @returns {object}
/// ```js
/// {
///   model: [],
///   document: [],
/// }
/// ```
export function getPaths(obj) {
  // finds all of the properties paths in a model
  const model = objectSearch(obj, /^properties\.([^.]+|(?!items\.).+properties\.[^.]+)$/)
    .filter((str) => !str.includes('items.properties'));

  return {
    model,
    // finds all of the paths that will be used by a rendered document
    document: model.join(',').replace(/properties\./g, '').split(','),
  };
}

/// @name typeToValue
/// @description generates the initial value for a variable based on the data type
/// @arg {string} type
/// @returns {*} - What ever the value is that matches it.
/// @raw-code
export function typeToValue(type) {
  const types = {};
  types.string = '';
  types.object = types.structure = {};
  types.number = types.integer = types.double = types.long = types.float = 0;
  types.array = [];
  types.boolean = types.bool = false;

  return types[type] != null ? types[type] : null;
}
<commit_msg>Check for a typeof number instead of this.optionsoptions<commit_after>import faker from 'faker';
import Chance from 'chance';
import Base from './base';
import { objectSearch } from './utils';
import { set, get } from 'lodash';
import to from 'to-js';

////
/// @name Document
/// @page api/document
////

/// @name Document
/// @description This is used to generate documents based off a model
export default class Document extends Base {
  constructor(options, documents = {}, globals = {}, inputs = {}) {
    super(options);
    this.options = this.options || {};
    this.documents = documents;
    this.globals = globals;
    this.inputs = inputs;
    // set chance and faker without a seed by default
    // so it can still be used
    this.chance = new Chance();
    this.faker = faker;
    this.updateFakers(this.options.seed);
  }

  ///# @name build
  ///# @description
  ///# This builds the documents from the passed model
  ///# @arg {object} model - The model to generate data from
  ///# @returns {array} - The array of documents that were generated
  build(model) {
    if (!this.documents[model.name]) {
      this.documents[model.name] = [];
    }

    this.updateFakers(model.seed);

    if (!model.data) {
      model.data = { count: 1 };
    }
    const key_type = to.type(model.key);

    // if there is a pre_run function call it
    this.runData(model.data.pre_run, model);

    this.log('info', `Generating ${this.options.count || model.count} document(s) for ${model.name} model`);

    for (let i = 0; i < model.data.count; i++) { // loop over each model and execute in order of dependency
      const doc = this.buildDocument(model, i);
      // build the key for the document
      let key;
      if (key_type === 'object') {
        key = this.buildValue({ data: model.key }, null, doc, i);
      } else if (key_type === 'string') {
        key = doc[model.key];
      } else {
        key = `${model.name}${i}`;
      }

      // @todo update this to use `new Map`, or `new WeakMap`;
      Object.defineProperty(doc, '__key', { value: key });
      Object.defineProperty(doc, '__name', { value: model.name });
      this.documents[model.name].push(doc);
    }

    this.runData(model.data.post_run, model);
    return this.documents[model.name];
  }

  ///# @name updateFakers
  ///# @description
  ///# If a usable seed is passed then this updates the instances of chance and faker to use a seed version
  ///# @arg {number, null} seed - The seed to use for this instance
  ///# @arg {number} modifier
  updateFakers(seed) {
    // if the seed is a number then update
    // the instance of chance and faker
    if (typeof seed === 'number') {
      this.chance = new Chance(seed);
      this.faker.seed(seed);
    }
  }

  ///# @name runData
  ///# @description used to run the different functions that the users can pass in into the data object
  ///# @arg {function} fn - The function to run
  ///# @arg {*} context - The `this` context
  ///# @arg {number} index [0] - The current index of the generated items
  ///# @returns {*} - What ever the function that runs returns
  runData(fn, context, index = 0) {
    if (to.type(fn) === 'function') {
      try {
        return fn.call(context, this.documents, this.globals, this.inputs, this.faker, this.chance, index);
      } catch (e) {
        this.log('error', `${fn.name} failed\n`, e);
      }
    }
  }

  ///# @name buildDocument
  ///# @description
  ///# builds a document
  ///# @arg {object} model - The model to build the document from
  ///# @arg {number} index [0] - The place in the list this item is being run from
  buildDocument(model, index = 0) {
    const paths = getPaths(model);
    // generate the initial values
    let doc = this.initializeDocument(model, paths);

    // if there is a pre_build function for the document call it
    this.runData(model.data.pre_build, doc, index);

    doc = this.buildObject(model, doc, paths, index);
    doc = this.postProcess(model, doc, paths, index);

    // if there is a post_build function for the document call it
    this.runData(model.data.post_build, doc, index);

    return doc;
  }

  ///# @name initializeDocument
  ///# @description initializes a documents default values
  ///# @arg {object} model - The model to parse
  ///# @arg {object} paths - The paths to loop over
  ///# @returns {object} - The document with the defaults
  initializeDocument(model, paths) {
    if (!paths || !paths.model || !paths.document) {
      paths = getPaths(model);
    }
    const doc = {};
    for (let [ i, str ] of to.entries(paths.model)) {
      let key = paths.document[i]; // set a key for error messaging
      try {
        set(doc, key, typeToValue(get(model, str).type));
      } catch (e) {
        this.log('error', `Initializing Properties in Model: "${model.name}" for Key: "${key}"\n`, e);
      }
    }
    return doc;
  }

  ///# @name buildObject
  ///# @description builds an object based on a model
  ///# @arg {object} model - The model to parse
  ///# @arg {object} doc - The document to update
  ///# @arg {object} paths - The paths to loop over
  ///# @arg {number} index - The current index
  ///# @returns {object} - The document with the defaults
  buildObject(model, doc, paths, index) {
    for (let [ i, str ] of to.entries(paths.model)) {
      let key = paths.document[i]; // set a key for error messaging
      try {
        const value = this.buildValue(get(model, str), get(doc, key), doc, index);
        set(doc, key, value);
      } catch (e) {
        this.log('error', `Building Properties in Model: "${model.name}" for Key: "${key}"\n`, e);
      }
    }

    return doc;
  }

  ///# @name buildValue
  ///# @description builds a single value based on a property definition
  ///# @arg {object} property - The property to run
  ///# To build a normal value
  ///# ```js
  ///# {
  ///#   type: '',  // 'object', 'structure', 'string', 'number', 'float', 'integer', etc..
  ///#   data: {
  ///#     pre_build() {}, // optional
  ///#     value: '', // optional
  ///#     build() {}, // optional
  ///#     fake: '', // optional
  ///#   }
  ///# }
  ///# ```
  ///# To build an array
  ///# ```js
  ///# {
  ///#   type: 'array',
  ///#   items: {
  ///#     type: '',  // 'object', 'structure', 'string', 'number', 'float', 'integer', etc..
  ///#     data: {
  ///#       pre_build() {}, // optional
  ///#       value: '', // optional
  ///#       build() {}, // optional
  ///#       fake: '', // optional
  ///#     }
  ///#   }
  ///# }
  ///# ```
  ///# @arg {*} value - The default value
  ///# @arg {object} doc [{}] - The current document
  ///# @arg {number} index [0] - The place in the list this item is being run from
  ///# @return {*} - The result
  buildValue(property, value, doc = {}, index = 0) {
    if (property.data) {
      if (property.data.pre_build) {
        value = this.runData(property.data.pre_build, doc, index);
      }
      if (property.data.value) {
        return property.data.value;
      } else if (property.data.build) {
        return this.runData(property.data.build, doc, index);
      } else if (property.data.fake) {
        return this.faker.fake(property.data.fake);
      }
    } else if (
      property.type === 'array' &&
      property.items
    ) {
      let { count, min, max } = property.items.data;
      if (count <= 0 && !!max) {
        count = this.chance.integer({ min, max });
      }

      // builds a complex array
      if (property.items.type === 'object') {
        for (let i = 0; i < count; i++) {
          value[i] = this.buildDocument(property.items, index);
        }
        return value;
      }

      // builds a simple array
      for (let i = 0; i < count; i++) {
        const result = this.buildValue(property.items, typeToValue(property.items.type), doc, index);
        if (result !== undefined) { // eslint-disable-line no-undefined
          value.push(result);
        }
      }
      return value;
    }

    return value;
  }

  ///# @name postProcess
  ///# @description Post process a document after generation
  ///# @arg {object} model - The model to parse
  ///# @arg {object} doc - The document to update
  ///# @arg {object} paths - The paths to loop over
  ///# @arg {number} index [0] - The current index
  ///# @returns {object} - The updated document
  postProcess(model, doc, paths, index = 0) {
    for (let [ i, str ] of to.entries(paths.model)) {
      let key = paths.document[i]; // set a key for error messaging
      try {
        const { data = {}, items = {}, type } = get(model, str);
        let value = get(doc, key);

        // if there is a post_build block
        if (data.post_build) {
          let temp = this.runData(data.post_build, doc, index);
          if (temp != null) {
            value = temp;
          }
        } else if (
          (items.data || {}).post_build &&
          items.type !== 'object' // if the type is an object it will run each item through this function already
        ) {
          for (let a = 0; a < value.length; a++) {
            let temp = transformValueToType(items.type, this.runData(items.data.post_build, doc[key][a], index));
            if (temp != null) {
              value[a] = temp;
            }
          }
        }

        set(doc, key, transformValueToType(type, value));
      } catch (e) {
        this.log('error', `Transforming Properties in Model: "${model.name}" for Key: "${key}"\n`, e);
      }
    }

    return doc;
  }
}

/// @name transformValueToType
/// @description This will transform a value to the correct type
/// @arg {string} type - The type to convert the value to
/// @arg {*} value - The actual value
/// @returns {*} - The converted value
export function transformValueToType(type, value) {
  if (
    type == null ||
    value == null ||
    type === 'array'
  ) {
    return value;
  }

  // if it is an integer make sure it is treated as such
  if ('number,integer,long'.includes(type)) {
    return parseInt(value);
  }
  // if it is a double / float make sure it is treated as such
  if ('double,float'.includes(type)) {
    return parseFloat(value);
  }

  // if it is a string make sure it is treated as such
  if (type === 'string') {
    return value.toString();
  }

  // if it is a string make sure it is treated as such
  if ('boolean,bool'.includes(type)) {
    // if the value is a string that is 'false', '0', 'undefined', or 'null' as a string set a boolean false
    if (
      typeof value === 'string' && (
        value === 'false' ||
        value === '0' ||
        value === 'undefined' ||
        value === 'null'
      )
    ) {
      return false;
    }
    return Boolean(value);
  }

  return value;
}

/// @name getPaths
/// @description finds all the paths to be used
/// @arg {object} obj - The object to be searched
/// @returns {object}
/// ```js
/// {
///   model: [],
///   document: [],
/// }
/// ```
export function getPaths(obj) {
  // finds all of the properties paths in a model
  const model = objectSearch(obj, /^properties\.([^.]+|(?!items\.).+properties\.[^.]+)$/)
    .filter((str) => !str.includes('items.properties'));

  return {
    model,
    // finds all of the paths that will be used by a rendered document
    document: model.join(',').replace(/properties\./g, '').split(','),
  };
}

/// @name typeToValue
/// @description generates the initial value for a variable based on the data type
/// @arg {string} type
/// @returns {*} - What ever the value is that matches it.
/// @raw-code
export function typeToValue(type) {
  const types = {};
  types.string = '';
  types.object = types.structure = {};
  types.number = types.integer = types.double = types.long = types.float = 0;
  types.array = [];
  types.boolean = types.bool = false;

  return types[type] != null ? types[type] : null;
}
<|endoftext|>


<commit_before>var irc = require('irc');
var api = require('./services/lib/api');
var config = api.load_config('bot.json');
var pub = api.get_redis_client(config.redis);
var sub = api.get_redis_client(config.redis);

function server_config_for(idx) {
    var cfg = config.servers[idx];
    /* server-generic options */
    cfg.debug = config.options.debug;
    cfg.floodProtection = config.options.floodProtection;
    cfg.showErrors = config.options.debug;
    cfg.stripColors = config.options.stripColors;
    return cfg;
}

function output_version_1(bot, message) {
    switch (message.type) {
    case 'privmsg':
        console.log('  privmsg');
        bot.say(message.data.to, message.data.message);
        break;
    case 'raw':
        console.log('  raw');
        bot.send(message.command);
        break;
    }
}

function setup() {
    var cfg = server_config_for(0);
    console.log('irc server: '+cfg.hostname+' nick: '+cfg.nick);
    var bot = new irc.Client(cfg.hostname, cfg.nick, cfg);

    bot.addListener('message', function(nick, to, text, message) {
        console.log(nick + ' said ' + text + ' to ' + to);
        var msg = {
            version: 1,
            type: 'privmsg',
            data: {
                sender: nick,
                channel: to,
                message: text,
            },
        };
        pub.publish('in', JSON.stringify(msg));
    });

    bot.addListener('bot_nick_change', function(oldNick, newNick) {
        pub.set('zenircbot:nick', newNick);
    });

    bot.addListener('part', function(channel, nick, reason, message) {
        console.log(nick + ' left ' + channel + ' because ' + reason);
        var msg = {
            version: 1,
            type: 'part',
            data: {
                sender: nick,
                channel: channel,
            },
        };
        pub.publish('in', JSON.stringify(msg));
    });

    bot.addListener('quit', function(nick, reason, channels, message) {
        console.log(nick + ' quit');
        var msg = {
            version: 1,
            type: 'quit',
            data: {
                sender: nick,
            },
        };
        pub.publish('in', JSON.stringify(msg));
    });

    var output_handlers = {
        1: output_version_1,
    };

    sub.subscribe('out');
    sub.on('message', function(channel, message) {
        var msg = JSON.parse(message);
        output_handlers[msg.version](bot, msg);
    });
}

setup();
<commit_msg>send pull request to upstream before commiting<commit_after>var irc = require('irc');
var api = require('./services/lib/api');
var config = api.load_config('bot.json');
var pub = api.get_redis_client(config.redis);
var sub = api.get_redis_client(config.redis);

function server_config_for(idx) {
    var cfg = config.servers[idx];
    /* server-generic options */
    cfg.debug = config.options.debug;
    cfg.floodProtection = config.options.floodProtection;
    cfg.showErrors = config.options.debug;
    cfg.stripColors = config.options.stripColors;
    return cfg;
}

function output_version_1(bot, message) {
    switch (message.type) {
    case 'privmsg':
        console.log('  privmsg');
        bot.say(message.data.to, message.data.message);
        break;
    case 'raw':
        console.log('  raw');
        bot.send(message.command);
        break;
    }
}

function setup() {
    var cfg = server_config_for(0);
    console.log('irc server: '+cfg.hostname+' nick: '+cfg.nick);
    var bot = new irc.Client(cfg.hostname, cfg.nick, cfg);
    pub.set('zenircbot:nick', cfg.nick);
    bot.addListener('message', function(nick, to, text, message) {
        console.log(nick + ' said ' + text + ' to ' + to);
        var msg = {
            version: 1,
            type: 'privmsg',
            data: {
                sender: nick,
                channel: to,
                message: text,
            },
        };
        pub.publish('in', JSON.stringify(msg));
    });

    // bot.addListener('bot_nick_change', function(oldNick, newNick) {
    //     pub.set('zenircbot:nick', newNick);
    // });

    bot.addListener('part', function(channel, nick, reason, message) {
        console.log(nick + ' left ' + channel + ' because ' + reason);
        var msg = {
            version: 1,
            type: 'part',
            data: {
                sender: nick,
                channel: channel,
            },
        };
        pub.publish('in', JSON.stringify(msg));
    });

    bot.addListener('quit', function(nick, reason, channels, message) {
        console.log(nick + ' quit');
        var msg = {
            version: 1,
            type: 'quit',
            data: {
                sender: nick,
            },
        };
        pub.publish('in', JSON.stringify(msg));
    });

    var output_handlers = {
        1: output_version_1,
    };

    sub.subscribe('out');
    sub.on('message', function(channel, message) {
        var msg = JSON.parse(message);
        output_handlers[msg.version](bot, msg);
    });
}

setup();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchSvg } from '../actions/index';

class Portfolio extends Component {
	constructor(props) {
    super(props);

    this.state= {
    	show: "default",
      loaded: false
    }
   this.renderSvg = this.renderSvg.bind(this);
   this.changeView = this.changeView.bind(this);
  }
  handleImageLoaded() {
    his.setState({ loaded: true })
  }
  renderSvg(svgtype) {
  let testExp = new RegExp('Android|webOS|iPhone|iPad|' + 'BlackBerry|Windows Phone|' + 'Opera Mini|IEMobile|Mobile', 'i');
   if (svgtype.type == this.state.show) {
  	return (
        {!this.state.loaded &&
Loading...
}
        {this.state.loaded &&

            {!testExp.test(navigator.userAgent) && }

            {!testExp.test(navigator.userAgent) && }

{svgtype.title}

{svgtype.descrip}

Code

Site

}
      );
    }
  }
  changeView(e) {
    e.preventDefault();

    this.props.fetchSvg();

    this.setState({ show: e.target.value });
  }
	render() {
    let allProjects = this.props.svg;
		return (

Select Projects

        <button onClick={this.changeView} type="button" value="react" className="btn">React</button>
        <button onClick={this.changeView} type="button" value="bot" className="btn">Bots</button>
        <button onClick={this.changeView} type="button" value="frontend" className="btn">fCC Front End</button>

 				{allProjects.length > 0 && allProjects[0].map(this.renderSvg)}

		);
	}
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchSvg }, dispatch);
}

function mapStateToProps({ svg }) {
  return { svg };
}

export default connect(mapStateToProps, mapDispatchToProps)(Portfolio);<commit_msg>loading msg<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchSvg } from '../actions/index';

class Portfolio extends Component {
	constructor(props) {
    super(props);

    this.state= {
    	show: "default",
      loaded: false
    }
   this.renderSvg = this.renderSvg.bind(this);
   this.changeView = this.changeView.bind(this);
  }
  handleImageLoaded() {
    this.setState({ loaded: true });
  }
  renderSvg(svgtype) {
  let testExp = new RegExp('Android|webOS|iPhone|iPad|' + 'BlackBerry|Windows Phone|' + 'Opera Mini|IEMobile|Mobile', 'i');
   if (svgtype.type == this.state.show) {
  	return (
        {!this.state.loaded &&
Loading...
}
        {this.state.loaded &&

            {!testExp.test(navigator.userAgent) && }

            {!testExp.test(navigator.userAgent) && }

{svgtype.title}

{svgtype.descrip}

Code

Site

}
      );
    }
  }
  changeView(e) {
    e.preventDefault();

    this.props.fetchSvg();

    this.setState({ show: e.target.value });
  }
	render() {
    let allProjects = this.props.svg;
		return (

Select Projects

        <button onClick={this.changeView} type="button" value="react" className="btn">React</button>
        <button onClick={this.changeView} type="button" value="bot" className="btn">Bots</button>
        <button onClick={this.changeView} type="button" value="frontend" className="btn">fCC Front End</button>

 				{allProjects.length > 0 && allProjects[0].map(this.renderSvg)}

		);
	}
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchSvg }, dispatch);
}

function mapStateToProps({ svg }) {
  return { svg };
}

export default connect(mapStateToProps, mapDispatchToProps)(Portfolio);<|endoftext|>


<commit_before>describe("the scheduler", function() {

    var event1 = {summary: "one", dtstart: "2011-01-30T17:00"};
    var event2 = {summary: "two", dtstart: "2011-01-30T20:00"};

    it("should order events by time", function() {
        var schedule = Lange.schedule([event2, event1]);
        expect(schedule).toEqual([
            {dtstart: event1.dtstart, event: event1},
            {dtstart: event2.dtstart, event: event2},
            ]);
    });

    it("should handle events with no time", function() {
        var eventWithNoDate = {summary: "foo"};
        var schedule = Lange.schedule([event1, eventWithNoDate]);
        expect(schedule).toEqual([
            {dtstart: event1.dtstart, event: event1},
            {dtstart: eventWithNoDate.dtstart, event: eventWithNoDate},
            ]);
    });

    it("should recognise conflicts and return them in the result", function(){
        var eventWhichConflictsWithEvent2 = {summary: "three", dtstart: "2011-01-30T20:00"};
        var schedule = Lange.schedule([event1, event2, eventWhichConflictsWithEvent2]);
        expect(schedule).toEqual([
            {dtstart: event1.dtstart, event: event1},
            {dtstart: event2.dtstart, conflict: true, events: [event2, eventWhichConflictsWithEvent2]}
            ]);

    });

    it("should throw exception if not given an array of events", function(){

    });

});        <commit_msg>refactor test code<commit_after>var event1 = {summary: "one", dtstart: "2011-01-30T17:00"};
var event2 = {summary: "two", dtstart: "2011-01-30T20:00"};
var eventWhichConflictsWithEvent2 = {summary: "three", dtstart: "2011-01-30T20:00"};

function conflict(events){
    return {conflict: true, events: events}
};

function scheduleWith(eventSpecs){
    return eventSpecs.map(function(eventSpec){
        var slot = {};
        if (eventSpec.conflict){
           slot.conflict = true;
           slot.dtstart = eventSpec.events[0].dtstart;
           slot.events = eventSpec.events;
        }
        else {
         slot.dtstart = eventSpec.dtstart;
         slot.event = eventSpec;
        };
        return slot;
    });
}

describe("test helper code", function(){
    it("should generate the correct expected representation", function(){
        expect(scheduleWith([event1, conflict([event2, eventWhichConflictsWithEvent2])])).toEqual([
            {dtstart: event1.dtstart, event: event1},
            {dtstart: event2.dtstart, conflict: true, events: [event2, eventWhichConflictsWithEvent2]},
            ]);
    });
});

describe("the scheduler", function() {
    it("should order events by time", function() {
        var schedule = Lange.schedule([event2, event1]);
        expect(schedule).toEqual(scheduleWith([event1, event2]));
    });

    it("should handle events with no time", function() {
        var eventWithNoDate = {summary: "foo"};
        var schedule = Lange.schedule([event1, eventWithNoDate]);
        expect(schedule).toEqual(scheduleWith([event1, eventWithNoDate]));
    });

    it("should recognise conflicts and return them in the result", function(){
        var schedule = Lange.schedule([event1, event2, eventWhichConflictsWithEvent2]);
        expect(schedule).toEqual(scheduleWith([event1, conflict([event2, eventWhichConflictsWithEvent2])]));
    });

    it("should throw exception if not given an array of events", function(){

    });

});        <|endoftext|>


<commit_before>$('h1').text('New header');
<commit_msg>Remove variation2<commit_after><|endoftext|>


<commit_before>$(document).ready(function(){
	//Canvas stuff
	var canvas = $("#canvas")[0];
	var ctx = canvas.getContext("2d");
	var w = $("#canvas").width();
	var h = $("#canvas").height();

	var state = "running";
	var cw = 10;
	var snake=[]; //array representing snake coordinates
	var score;

	var fw = Math.floor((Math.random()*w/10)+1);
	var fh = Math.floor((Math.random()*h/10)+1);
	var handle = 0;

	var dir = "right";

	function paint_cell(x,y)
	{
		ctx.fillStyle = "blue";
		ctx.fillRect(x*cw, y*cw, cw, cw);
		ctx.strokeStyle = "white";
		ctx.strokeRect(x*cw, y*cw, cw, cw);
	}

	function make_snake()
	{
		var snake_length = 5; //starting length of snake
		for(var i=0;i<snake_length;i++)
		{
			//Create horizontal snake from top left
			snake.push({x: i,y: 0});
			paint_cell(snake[i].x,snake[i].y);
		}
	}

	function draw_snake()
	{
		for(var i = snake.length-1; i >= 0; i--)
		{
			paint_cell(snake[i].x,snake[i].y);
		}
	}

	function if_collide_self(x,y){
		for(var i = 0; i<snake.length;i++){
			if (x===snake[i].x && y===snake[i].y){
				return true;
			}
		}
		return false;
	}

	function game_logic()
	{
		ctx.fillStyle = "white";
		ctx.fillRect(0, 0, w, h);
		ctx.strokeStyle = "black";
		ctx.strokeRect(0, 0, w, h);

		if (dir==="right") {
			new_pos_x = snake[snake.length-1].x +1;
			new_pos_y = snake[snake.length-1].y;
		}
		else if (dir==="left") {
			new_pos_x = snake[snake.length-1].x - 1;
			new_pos_y = snake[snake.length-1].y;
		}
		else if (dir==="up") {
			new_pos_x = snake[snake.length-1].x;
			new_pos_y = snake[snake.length-1].y-1;
		}
		else if (dir==="down") {
			new_pos_x = snake[snake.length-1].x;
			new_pos_y = snake[snake.length-1].y+1;
		}

		if (new_pos_x > w/cw || new_pos_y > h/cw || new_pos_x < 0 || new_pos_y < 0 || if_collide_self(new_pos_x,new_pos_y))
		{
			clearInterval(handle);
			game();
		}
		else if (new_pos_x===fw && new_pos_y===fh)
		{
			score++;
			make_food(true);
			snake.push({x: new_pos_x, y: new_pos_y});
			draw_snake();
		}
		else {
			make_food();
			snake.shift();
			snake.push({x: new_pos_x, y: new_pos_y});
			draw_snake();
		}
		var score_text = "Score: " + score;
		ctx.fillText(score_text, 5, h-5);

	}

	function game()
	{
		//Draw canvas
		score = 0;
		ctx.fillStyle = "white";
		ctx.fillRect(0, 0, w, h);
		ctx.strokeStyle = "black";
		ctx.strokeRect(0, 0, w, h);

		snake = [];
		dir = "right";
		make_snake();
		make_food(true);
		handle = setInterval(game_logic, 50);

	}
	game();

    function make_food(is_new)
    {
        fw = typeof is_new !== 'undefined' ? Math.floor((Math.random()*w/10)+1) : fw;
        fh = typeof is_new !== 'undefined' ? Math.floor((Math.random()*h/10)+1) : fh;
        paint_cell(fw,fh);
    }

    //Create special food with higher points, but also could end game
    function make_special()
    {

    }

    $(document).keydown(function(e){
    	if (e.keyCode===32) dir="paused";
    	if (e.keyCode===37 && dir!=="right") dir="left";
    	if (e.keyCode===38 && dir!=="down") dir="up";
    	if (e.keyCode===39 && dir!=="left") dir="right";
    	if (e.keyCode===40 && dir!=="up") dir="down";
    });

})
<commit_msg>Add structure for levels<commit_after>$(document).ready(function(){
	//Canvas stuff
	var canvas = $("#canvas")[0];
	var ctx = canvas.getContext("2d");
	var w = $("#canvas").width();
	var h = $("#canvas").height();

	var state = "running";
	var cw = 10;
	var snake=[]; //array representing snake coordinates
	var score;
	var level;

	var fw = Math.floor((Math.random()*w/10)+1);
	var fh = Math.floor((Math.random()*h/10)+1);
	var handle = 0;

	var dir = "right";

	function paint_cell(x,y)
	{
		ctx.fillStyle = "blue";
		ctx.fillRect(x*cw, y*cw, cw, cw);
		ctx.strokeStyle = "white";
		ctx.strokeRect(x*cw, y*cw, cw, cw);
	}

	function make_snake()
	{
		var snake_length = 5; //starting length of snake
		for(var i=0;i<snake_length;i++)
		{
			//Create horizontal snake from top left
			snake.push({x: i,y: 0});
			paint_cell(snake[i].x,snake[i].y);
		}
	}

	function draw_snake()
	{
		for(var i = snake.length-1; i >= 0; i--)
		{
			paint_cell(snake[i].x,snake[i].y);
		}
	}

	function if_collide_self(x,y){
		for(var i = 0; i<snake.length;i++){
			if (x===snake[i].x && y===snake[i].y){
				return true;
			}
		}
		return false;
	}

	function game_logic()
	{
		ctx.fillStyle = "white";
		ctx.fillRect(0, 0, w, h);
		ctx.strokeStyle = "black";
		ctx.strokeRect(0, 0, w, h);

		if (dir==="right") {
			new_pos_x = snake[snake.length-1].x +1;
			new_pos_y = snake[snake.length-1].y;
		}
		else if (dir==="left") {
			new_pos_x = snake[snake.length-1].x - 1;
			new_pos_y = snake[snake.length-1].y;
		}
		else if (dir==="up") {
			new_pos_x = snake[snake.length-1].x;
			new_pos_y = snake[snake.length-1].y-1;
		}
		else if (dir==="down") {
			new_pos_x = snake[snake.length-1].x;
			new_pos_y = snake[snake.length-1].y+1;
		}

		if (new_pos_x > w/cw || new_pos_y > h/cw || new_pos_x < 0 || new_pos_y < 0 || if_collide_self(new_pos_x,new_pos_y))
		{
			clearInterval(handle);
			game();
		}
		else if (new_pos_x===fw && new_pos_y===fh)
		{
			score++;
			make_food(true);
			snake.push({x: new_pos_x, y: new_pos_y});
			draw_snake();
		}
		else {
			make_food();
			snake.shift();
			snake.push({x: new_pos_x, y: new_pos_y});
			draw_snake();
		}
		var score_text = "Score: " + score;
		ctx.fillText(score_text, 5, h-5);

		var level = "Level: " + level;
		ctx.fillText(level, w-50, h-5);

	}

	function game()
	{
		//Draw canvas
		score = 0;
		ctx.fillStyle = "white";
		ctx.fillRect(0, 0, w, h);
		ctx.strokeStyle = "black";
		ctx.strokeRect(0, 0, w, h);

		level = 3;
		snake = [];
		dir = "right";
		make_snake();
		make_food(true);
		handle = setInterval(game_logic, (level+2)*10);

	}
	game();

    function make_food(is_new)
    {
        fw = typeof is_new !== 'undefined' ? Math.floor((Math.random()*w/10)+1) : fw;
        fh = typeof is_new !== 'undefined' ? Math.floor((Math.random()*h/10)+1) : fh;
        paint_cell(fw,fh);
    }

    //Create special food with higher points, but also could end game
    function make_special()
    {

    }

    $(document).keydown(function(e){
    	if (e.keyCode===32) dir="paused";
    	if (e.keyCode===49) level=1;
    	if (e.keyCode===50) level=2;
    	if (e.keyCode===51) level=3;
    	if (e.keyCode===52) level=4;
    	if (e.keyCode===53) level=5;
    	if (e.keyCode===37 && dir!=="right") dir="left";
    	if (e.keyCode===38 && dir!=="down") dir="up";
    	if (e.keyCode===39 && dir!=="left") dir="right";
    	if (e.keyCode===40 && dir!=="up") dir="down";
    });

})
<|endoftext|>


<commit_before>var gulp = require('gulp');
var pkg = require('./package.json');
var common = require('./gulp/common.js');
var plug = require('gulp-load-plugins')();
var env = plug.util.env;
var log = plug.util.log;

/**
 * @desc  Add a task to render the output
 */
gulp.task('help', plug.taskListing);

/**
 * @desc Lint the code
 */
gulp.task('jshint', function () {
    log('Linting the JavaScript');

    var sources = [].concat(pkg.paths.js, pkg.paths.nodejs);
    return gulp
        .src(sources)
        .pipe(plug.jshint('./.jshintrc'))
        //.pipe(plug.jshint.reporter('default'));
        .pipe(plug.jshint.reporter('jshint-stylish'));
});

/**
 * @desc Create $templateCache from the html templates
 */
gulp.task('templatecache', function () {
    log('Creating an AngularJS $templateCache');

    return gulp
        .src(pkg.paths.htmltemplates)
        .pipe(plug.angularTemplatecache('templates.js', {
            module: 'app.core',
            standalone: false,
            root: 'app/'
        }))
        .pipe(gulp.dest(pkg.paths.stage));
});

/**
 * @desc Add injection code for @ngInject annotations
 */
gulp.task('ngAnnotate', function () {
    log('Annotating AngularJS dependencies');

    return gulp
        .src(pkg.paths.js)
        .pipe(plug.ngAnnotate({
            // true helps add where @ngInject is not used. It infers.
            // Doesn't work with resolve, so we must be explicit there
            add: true,
            single_quotes: true
        }))
        .pipe(gulp.dest(pkg.paths.stage));
});

/**
 * @desc Minify and bundle the app's JavaScript
 */
gulp.task('js', ['jshint', 'templatecache'], function () {
    log('Bundling, minifying, and copying the app\'s  JavaScript');

    var source = [].concat(pkg.paths.js, pkg.paths.stage + 'templates.js');

    return gulp
        .src(source)
        .pipe(plug.sourcemaps.init())
        .pipe(plug.concat('all.min.js'))
        .pipe(plug.ngAnnotate({
            add: true,
            single_quotes: true
        }))
        .pipe(plug.bytediff.start())
        .pipe(plug.uglify({mangle: true}))
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
        .pipe(plug.sourcemaps.write('./'))
        .pipe(gulp.dest(pkg.paths.stage));
});

/**
 * @desc Copy the Vendor JavaScript
 */
gulp.task('vendorjs', function () {
    log('Bundling, minifying, and copying the Vendor JavaScript');
    return gulp.src(pkg.paths.vendorjs)
        .pipe(plug.concat('vendor.min.js'))
        .pipe(plug.bytediff.start())
        .pipe(plug.uglify())
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
        .pipe(gulp.dest(pkg.paths.stage + 'vendor'));
});

/**
 * @desc Minify and bundle the CSS
 */
gulp.task('css', function () {
    log('Bundling, minifying, and copying the app\'s CSS');
    return gulp.src(pkg.paths.css)
//        .pipe(plug.size({showFiles: true}))
        .pipe(plug.concat('all.min.css')) // Before bytediff or after
        .pipe(plug.bytediff.start())
        .pipe(plug.minifyCss({}))
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
//        .pipe(plug.concat('all.min.css')) // Before bytediff or after
        .pipe(gulp.dest(pkg.paths.stage + 'content'));
//        .pipe(plug.size({showFiles: true}));
});

/**
 * @desc Minify and bundle the Vendor CSS
 */
gulp.task('vendorcss', function () {
    log('Compressing, bundling, compying vendor CSS');
    return gulp.src(pkg.paths.vendorcss)
        .pipe(plug.concat('vendor.min.css'))
        .pipe(plug.bytediff.start())
        .pipe(plug.minifyCss({}))
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
        .pipe(gulp.dest(pkg.paths.stage + 'content'));
});

/**
 * @desc Copy fonts
 */
gulp.task('fonts', function () {
    var dest = pkg.paths.stage + 'fonts';
    log('Copying fonts');
    return gulp
        .src(pkg.paths.fonts)
        .pipe(gulp.dest(dest));
});

/**
 * @desc Compress images
 */
gulp.task('images', function () {
    var dest = pkg.paths.stage + 'content/images';
    log('Compressing, caching, and copying images');
    return gulp
        .src(pkg.paths.images)
        .pipe(plug.cache(plug.imagemin({optimizationLevel: 3})))
        .pipe(gulp.dest(dest));
});

/**
 * @desc Inject all the files into the new index.html
 */
gulp.task('stage',
    ['js', 'vendorjs', 'css', 'vendorcss', 'images', 'fonts', 'test'], function () {
        log('Building index.html to staging');

        return gulp
            .src('./client/index.html')
            .pipe(inject([pkg.paths.stage + 'content/vendor.min.css'], 'inject-vendor'))
            .pipe(inject([pkg.paths.stage + 'content/all.min.css']))
            .pipe(inject(pkg.paths.stage + 'vendor/vendor.min.js', 'inject-vendor'))
            .pipe(inject([pkg.paths.stage + 'all.min.js']))
            .pipe(gulp.dest(pkg.paths.stage))
            .pipe(plug.notify({
                onLast: true,
                message: 'Deployed code to staging!'
            }));

        function inject(glob, name) {
            var ignorePath = pkg.paths.stage.substring(1);
            var options = {ignorePath: ignorePath};
            if (name) {
                options.name = name;
            }
            return plug.inject(gulp.src(glob), options);
        }
    });

/**
 * @desc Remove all files from the output folder
 */
gulp.task('clean', function () {
    log('Cleaning: ' + plug.util.colors.blue(pkg.paths.stage));
    return gulp
        .src(pkg.paths.stage)
        .pipe(plug.clean({force: true}));
});

/**
 * @desc Watch files and build
 */
gulp.task('watch', function () {
    log('Watching CSS and JavaScript files');

    var css = ['gulpfile.js'].concat(pkg.paths.css, pkg.paths.vendorcss);
    var js = ['gulpfile.js'].concat(pkg.paths.js);

    gulp
        .watch(js, ['js', 'vendorjs'])
        .on('change', function (event) {
            log('*** File ' + event.path + ' was ' + event.type + ', running tasks...');
        });

    gulp
        .watch(css, ['css', 'vendorcss'])
        .on('change', function (event) {
            log('*** File ' + event.path + ' was ' + event.type + ', running tasks...');
        });
});

/**
 * @desc Run all tests
 */
gulp.task('test', function () {
    log('Running tests');

    var testFiles = ['client/test/**.[Ss]pec.js'];

    return gulp
        .src(testFiles)
        .pipe(plug.karma({
            configFile: pkg.paths.test + '/karma.conf.js',
            action: 'run'
        }))
        .on('error', function (err) {
            // Make sure failed tests cause gulp to exit non-zero
            throw err;
        });
});

/**
 * serve the dev environment
 */
var serveDevTasks = ['jshint', 'test'];
gulp.task('serve-dev', serveDevTasks, function () {
    serve(serveDevTasks);
    livereload('development');
});

/**
 * serve the staging environment
 */
var serveStageTasks = ['jshint', 'test', 'stage'];
gulp.task('serve-stage', serveStageTasks, function () {
    serve(serveStageTasks);
    livereload('stage');
});

function livereload(env) {
    var path = env === 'stage' ? 'build/**' : 'client/**';
    var options = {auto: true};
    //TODO: how to set options?
    plug.livereload.listen();
    gulp
        .watch(path)
        .on('change', plug.livereload.changed);

    log('Serving from ' + env);
}

function serve(tasks) {
    plug.nodemon({
        script: 'server/server.js',
        delayTime: 1,
        ext: 'html js',
        env: { 'NODE_ENV': 'dev' },
        watch: ['server/'],
//        ignore: ['build/'],
        nodeArgs: ['--debug=9999']
    })
        .on('change', tasks)
        .on('restart', function () {
            log('restarted!');
        });
}<commit_msg>modular: gulp - fixed live reload and serve with nodemon.<commit_after>var gulp = require('gulp');
var pkg = require('./package.json');
var common = require('./gulp/common.js');
var plug = require('gulp-load-plugins')();
var env = plug.util.env;
var log = plug.util.log;

/**
 * @desc  Add a task to render the output
 */
gulp.task('help', plug.taskListing);

/**
 * @desc Lint the code
 */
gulp.task('jshint', function () {
    log('Linting the JavaScript');

    var sources = [].concat(pkg.paths.js, pkg.paths.nodejs);
    return gulp
        .src(sources)
        .pipe(plug.jshint('./.jshintrc'))
        //.pipe(plug.jshint.reporter('default'));
        .pipe(plug.jshint.reporter('jshint-stylish'));
});

/**
 * @desc Create $templateCache from the html templates
 */
gulp.task('templatecache', function () {
    log('Creating an AngularJS $templateCache');

    return gulp
        .src(pkg.paths.htmltemplates)
        .pipe(plug.angularTemplatecache('templates.js', {
            module: 'app.core',
            standalone: false,
            root: 'app/'
        }))
        .pipe(gulp.dest(pkg.paths.stage));
});

/**
 * @desc Add injection code for @ngInject annotations
 */
gulp.task('ngAnnotate', function () {
    log('Annotating AngularJS dependencies');

    return gulp
        .src(pkg.paths.js)
        .pipe(plug.ngAnnotate({
            // true helps add where @ngInject is not used. It infers.
            // Doesn't work with resolve, so we must be explicit there
            add: true,
            single_quotes: true
        }))
        .pipe(gulp.dest(pkg.paths.stage));
});

/**
 * @desc Minify and bundle the app's JavaScript
 */
gulp.task('js', ['jshint', 'templatecache'], function () {
    log('Bundling, minifying, and copying the app\'s  JavaScript');

    var source = [].concat(pkg.paths.js, pkg.paths.stage + 'templates.js');

    return gulp
        .src(source)
        .pipe(plug.sourcemaps.init())
        .pipe(plug.concat('all.min.js'))
        .pipe(plug.ngAnnotate({
            add: true,
            single_quotes: true
        }))
        .pipe(plug.bytediff.start())
        .pipe(plug.uglify({mangle: true}))
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
        .pipe(plug.sourcemaps.write('./'))
        .pipe(gulp.dest(pkg.paths.stage));
});

/**
 * @desc Copy the Vendor JavaScript
 */
gulp.task('vendorjs', function () {
    log('Bundling, minifying, and copying the Vendor JavaScript');
    return gulp.src(pkg.paths.vendorjs)
        .pipe(plug.concat('vendor.min.js'))
        .pipe(plug.bytediff.start())
        .pipe(plug.uglify())
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
        .pipe(gulp.dest(pkg.paths.stage + 'vendor'));
});

/**
 * @desc Minify and bundle the CSS
 */
gulp.task('css', function () {
    log('Bundling, minifying, and copying the app\'s CSS');
    return gulp.src(pkg.paths.css)
//        .pipe(plug.size({showFiles: true}))
        .pipe(plug.concat('all.min.css')) // Before bytediff or after
        .pipe(plug.bytediff.start())
        .pipe(plug.minifyCss({}))
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
//        .pipe(plug.concat('all.min.css')) // Before bytediff or after
        .pipe(gulp.dest(pkg.paths.stage + 'content'));
//        .pipe(plug.size({showFiles: true}));
});

/**
 * @desc Minify and bundle the Vendor CSS
 */
gulp.task('vendorcss', function () {
    log('Compressing, bundling, compying vendor CSS');
    return gulp.src(pkg.paths.vendorcss)
        .pipe(plug.concat('vendor.min.css'))
        .pipe(plug.bytediff.start())
        .pipe(plug.minifyCss({}))
        .pipe(plug.bytediff.stop(common.bytediffFormatter))
        .pipe(gulp.dest(pkg.paths.stage + 'content'));
});

/**
 * @desc Copy fonts
 */
gulp.task('fonts', function () {
    var dest = pkg.paths.stage + 'fonts';
    log('Copying fonts');
    return gulp
        .src(pkg.paths.fonts)
        .pipe(gulp.dest(dest));
});

/**
 * @desc Compress images
 */
gulp.task('images', function () {
    var dest = pkg.paths.stage + 'content/images';
    log('Compressing, caching, and copying images');
    return gulp
        .src(pkg.paths.images)
        .pipe(plug.cache(plug.imagemin({optimizationLevel: 3})))
        .pipe(gulp.dest(dest));
});

/**
 * @desc Inject all the files into the new index.html
 */
gulp.task('stage',
    ['js', 'vendorjs', 'css', 'vendorcss', 'images', 'fonts', 'test'], function () {
        log('Building index.html to stage');

        return gulp
            .src('./client/index.html')
            .pipe(inject([pkg.paths.stage + 'content/vendor.min.css'], 'inject-vendor'))
            .pipe(inject([pkg.paths.stage + 'content/all.min.css']))
            .pipe(inject(pkg.paths.stage + 'vendor/vendor.min.js', 'inject-vendor'))
            .pipe(inject([pkg.paths.stage + 'all.min.js']))
            .pipe(gulp.dest(pkg.paths.stage))
            .pipe(plug.notify({
                onLast: true,
                message: 'Deployed code to stage!'
            }));

        function inject(glob, name) {
            var ignorePath = pkg.paths.stage.substring(1);
            var options = {ignorePath: ignorePath};
            if (name) {
                options.name = name;
            }
            return plug.inject(gulp.src(glob), options);
        }
    });

/**
 * @desc Remove all files from the build folder
 */
gulp.task('clean', function () {
    log('Cleaning: ' + plug.util.colors.blue(pkg.paths.stage));
    return gulp
        .src(pkg.paths.build, {read: false})
        .pipe(plug.clean({force: true}));
});

/**
 * @desc Watch files and build
 */
gulp.task('watch', function () {
    log('Watching all files');

    var css = ['gulpfile.js'].concat(pkg.paths.css, pkg.paths.vendorcss);
    var images = ['gulpfile.js'].concat(pkg.paths.images);
    var js = ['gulpfile.js'].concat(pkg.paths.js);

    gulp
        .watch(js, ['js', 'vendorjs'])
        .on('change', logWatch);

    gulp
        .watch(css, ['css', 'vendorcss'])
        .on('change', logWatch);

    gulp
        .watch(images, ['images'])
        .on('change', logWatch);

    function logWatch(event){
        log('*** File ' + event.path + ' was ' + event.type + ', running tasks...');
    }
});

/**
 * @desc Run all tests
 */
gulp.task('test', function () {
    log('Running tests');
    var testFiles = [pkg.paths.test + 'spec.mocha/**.[Ss]pec.js'];

    return gulp
        .src(testFiles)
        .pipe(plug.karma({
            configFile: pkg.paths.test + '/karma.conf.js',
            action: 'run' // or watch
        }))
        .on('error', function (err) {
            // failed tests cause gulp to exit
            throw err;
        });
});

/**
 * serve the dev environment
 */
var serveDevTasks = ['jshint', 'test'];
gulp.task('serve-dev', serveDevTasks, function () {
    serve('dev', serveDevTasks);
    startLivereload('development');
});

/**
 * serve the staging environment
 */
var serveStageTasks = ['jshint', 'test', 'stage'];
gulp.task('serve-stage', serveStageTasks, function () {
    serve('stage', serveStageTasks);
    startLivereload('stage');
});

function startLivereload(env) {
    var path = (env === 'stage' ? pkg.paths.stage : 'client/') + '**';
    var options = {auto: true};
    plug.livereload.listen(options);
    gulp
        .watch(path)
        .on('change', function (file) {
            plug.livereload.changed(file.path);
        });

    log('Serving from ' + env);
}

function serve(env, tasks) {
    plug.nodemon({
        script: 'server/server.js',
        delayTime: 1,
        ext: 'html js',
        env: { 'NODE_ENV': env },
        watch: ['server/'],
//        ignore: ['build/'],
        nodeArgs: ['--debug=9999']
    })
        .on('change', tasks)
        .on('restart', function () {
            log('restarted!');
        });
}<|endoftext|>


<commit_before>'use strict';

$('document').ready(function () {
	function translate(text, cb) {
		require(['translator'], function (translator) {
			translator.translate(text, cb);
		});
	}
	$(window).on('action:ajaxify.end', function () {
		if (ajaxify.data.template.topic) {
			markPostAsSolved();
		} else if (ajaxify.data.template.compose && ajaxify.data.isMain && ajaxify.data.topic) {
			// seperate composer page
			var actionBar = $('.composer .action-bar');
			addQnADropdown(actionBar, parseInt(ajaxify.data.topic.isQuestion, 10) === 1);
		}
	});

	$(window).on('action:topic.tools.load', addHandlers);
	$(window).on('action:post.tools.load', addPostHandlers);

	$(window).on('action:posts.loaded', markPostAsSolved);

	$(window).on('action:composer.loaded', function (ev, data) {
		// Return early if it is a reply and not a new topic
		if (data.hasOwnProperty('composerData') && !data.composerData.isMain) {
			return;
		}
		var actionBar = $('.composer[data-uuid="' + data.post_uuid + '"] .action-bar');
		addQnADropdown(actionBar, data.composerData.isQuestion);
	});

	function addQnADropdown(actionBar, isQuestion) {
		translate('[[qanda:thread.tool.as_question]]', function (translated) {
			var $container = actionBar.find('.dropdown-menu');

			// Append a dropdown container if necessary (up to v1.18.4)
			if (!$container.length) {
				actionBar.append('<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown"></button>');
				$container = $('

');
				actionBar.append($container);
			}

			var item = $('
 ' + translated + '
');

			item.on('click', () => {
				var icon = item.find('.fa');
				icon.toggleClass('fa-circle-o').toggleClass('fa-check-circle-o');
				// Don't close dropdown on toggle (for better UX)
				return false;
			});

			$(window).one('action:composer.submit', function (ev, data) {
				var icon = item.find('.fa');
				if (icon.hasClass('fa-check-circle-o')) {
					data.composerData.isQuestion = true;
				}
			});

			$container.append(item);
		});
	}

	$(window).on('action:posts.edited', function (ev, data) {
		require(['api'], function (api) {
			api.get(`/plugins/qna/${data.topic.tid}`, {})
				.then((res) => {
					const toggled = (ajaxify.data.isQuestion || '0') !== res.isQuestion || (ajaxify.data.isSolved || '0') !== res.isSolved;
					if (toggled) {
						ajaxify.refresh();
					}
				});
		});
	});

	function addHandlers() {
		$('.toggleQuestionStatus').on('click', toggleQuestionStatus);
		$('.toggleSolved').on('click', toggleSolved);
	}

	function addPostHandlers() {
		$('[component="qanda/post-solved"]').on('click', markPostAsAnswer);
	}

	function toggleQuestionStatus() {
		var tid = ajaxify.data.tid;
		callToggleQuestion(tid, true);
	}

	function callToggleQuestion(tid, refresh) {
		socket.emit('plugins.QandA.toggleQuestionStatus', { tid: tid }, function (err, data) {
			if (err) {
				return app.alertError(err);
			}

			app.alertSuccess(data.isQuestion ? '[[qanda:thread.alert.as_question]]' : '[[qanda:thread.alert.make_normal]]');
			if (refresh) {
				ajaxify.refresh();
			}
		});
	}

	function toggleSolved() {
		var tid = ajaxify.data.tid;
		socket.emit('plugins.QandA.toggleSolved', { tid: tid }, function (err, data) {
			if (err) {
				return app.alertError(err);
			}

			app.alertSuccess(data.isSolved ? '[[qanda:thread.alert.solved]]' : '[[qanda:thread.alert.unsolved]]');
			ajaxify.refresh();
		});
	}

	function markPostAsAnswer() {
		var tid = ajaxify.data.tid;
		var pid = $(this).parents('[data-pid]').attr('data-pid');

		socket.emit('plugins.QandA.toggleSolved', { tid: tid, pid: pid }, function (err, data) {
			if (err) {
				return app.alertError(err);
			}

			app.alertSuccess(data.isSolved ? '[[qanda:post.alert.correct_answer]]' : '[[qanda:thread.alert.unsolved]]');
			ajaxify.refresh();
		});
	}

	function markPostAsSolved() {
		$('[component="post"][data-pid="' + ajaxify.data.solvedPid + '"]').addClass('isSolved');
		$('[component="post"][data-pid="' + ajaxify.data.solvedPid + '"][data-index="-1"] .post-footer').addClass('hidden');

		require(['translator'], (translator) => {
			translator.translate('[[qanda:label.solution]]', (translated) => {
				$('[component="post"][data-pid="' + ajaxify.data.solvedPid + '"][data-index="-1"]').attr('data-label', translated);
			});
		});
	}
});
<commit_msg>refactor: alerts<commit_after>'use strict';

$('document').ready(function () {
	function translate(text, cb) {
		require(['translator'], function (translator) {
			translator.translate(text, cb);
		});
	}
	function alertType(type, message) {
		require(['alerts'], function (alerts) {
			alert[type](message);
		});
	}
	$(window).on('action:ajaxify.end', function () {
		if (ajaxify.data.template.topic) {
			markPostAsSolved();
		} else if (ajaxify.data.template.compose && ajaxify.data.isMain && ajaxify.data.topic) {
			// seperate composer page
			var actionBar = $('.composer .action-bar');
			addQnADropdown(actionBar, parseInt(ajaxify.data.topic.isQuestion, 10) === 1);
		}
	});

	$(window).on('action:topic.tools.load', addHandlers);
	$(window).on('action:post.tools.load', addPostHandlers);

	$(window).on('action:posts.loaded', markPostAsSolved);

	$(window).on('action:composer.loaded', function (ev, data) {
		// Return early if it is a reply and not a new topic
		if (data.hasOwnProperty('composerData') && !data.composerData.isMain) {
			return;
		}
		var actionBar = $('.composer[data-uuid="' + data.post_uuid + '"] .action-bar');
		addQnADropdown(actionBar, data.composerData.isQuestion);
	});

	function addQnADropdown(actionBar, isQuestion) {
		translate('[[qanda:thread.tool.as_question]]', function (translated) {
			var $container = actionBar.find('.dropdown-menu');

			// Append a dropdown container if necessary (up to v1.18.4)
			if (!$container.length) {
				actionBar.append('<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown"></button>');
				$container = $('

');
				actionBar.append($container);
			}

			var item = $('
 ' + translated + '
');

			item.on('click', () => {
				var icon = item.find('.fa');
				icon.toggleClass('fa-circle-o').toggleClass('fa-check-circle-o');
				// Don't close dropdown on toggle (for better UX)
				return false;
			});

			$(window).one('action:composer.submit', function (ev, data) {
				var icon = item.find('.fa');
				if (icon.hasClass('fa-check-circle-o')) {
					data.composerData.isQuestion = true;
				}
			});

			$container.append(item);
		});
	}

	$(window).on('action:posts.edited', function (ev, data) {
		require(['api'], function (api) {
			api.get(`/plugins/qna/${data.topic.tid}`, {})
				.then((res) => {
					const toggled = (ajaxify.data.isQuestion || '0') !== res.isQuestion || (ajaxify.data.isSolved || '0') !== res.isSolved;
					if (toggled) {
						ajaxify.refresh();
					}
				});
		});
	});

	function addHandlers() {
		$('.toggleQuestionStatus').on('click', toggleQuestionStatus);
		$('.toggleSolved').on('click', toggleSolved);
	}

	function addPostHandlers() {
		$('[component="qanda/post-solved"]').on('click', markPostAsAnswer);
	}

	function toggleQuestionStatus() {
		var tid = ajaxify.data.tid;
		callToggleQuestion(tid, true);
	}

	function callToggleQuestion(tid, refresh) {
		socket.emit('plugins.QandA.toggleQuestionStatus', { tid: tid }, function (err, data) {
			if (err) {
				return alertType('error', err);
			}

			alertType('success', data.isQuestion ? '[[qanda:thread.alert.as_question]]' : '[[qanda:thread.alert.make_normal]]');
			if (refresh) {
				ajaxify.refresh();
			}
		});
	}

	function toggleSolved() {
		var tid = ajaxify.data.tid;
		socket.emit('plugins.QandA.toggleSolved', { tid: tid }, function (err, data) {
			if (err) {
				return alertType('error', err);
			}

			alertType('success', data.isSolved ? '[[qanda:thread.alert.solved]]' : '[[qanda:thread.alert.unsolved]]');
			ajaxify.refresh();
		});
	}

	function markPostAsAnswer() {
		var tid = ajaxify.data.tid;
		var pid = $(this).parents('[data-pid]').attr('data-pid');

		socket.emit('plugins.QandA.toggleSolved', { tid: tid, pid: pid }, function (err, data) {
			if (err) {
				return alertType('error', err);
			}

			alertType('success', data.isSolved ? '[[qanda:post.alert.correct_answer]]' : '[[qanda:thread.alert.unsolved]]');
			ajaxify.refresh();
		});
	}

	function markPostAsSolved() {
		$('[component="post"][data-pid="' + ajaxify.data.solvedPid + '"]').addClass('isSolved');
		$('[component="post"][data-pid="' + ajaxify.data.solvedPid + '"][data-index="-1"] .post-footer').addClass('hidden');

		translate('[[qanda:label.solution]]', (translated) => {
			$('[component="post"][data-pid="' + ajaxify.data.solvedPid + '"][data-index="-1"]').attr('data-label', translated);
		});
	}
});
<|endoftext|>