<commit_before>const Path = require('path');
const chokidar = require('chokidar');
const globParent = require('glob-parent');
const resolveGlob = require('to-absolute-glob');

// Use the specific library entity from outside
function use(Rx) {

  // To support both RxJS 4 and RxJS 5
  const proto = Rx.Subject.prototype;
  var rxjs5Supported = !!proto.next && !!proto.error && !!proto.complete;
  const callOnNext = (rxjs5Supported) ? "next" : "onNext";
  const callOnError = (rxjs5Supported) ? "error" : "onError";
  const callOnCompleted = (rxjs5Supported) ? "complete" : "onCompleted";

  return { watch, onAll, onInitial, onChange };

  /*
   * Use chokidar to observe file system events and send events by Rx.Observable.
   *
   * The `next` value of Observable should be an object containing `event` and
   * `path`. Possible event types:
   *
   * - `add`: file has been added.
   * - `change`: file has been changed/modified.
   * - `unlink`: file has been removed.
   * - `addDir`: directory has been added.
   * - `unlinkDir`: directory has been removed.
   * - `ready`: initial scan completes; ready for changes (only for `onAll()`).
   *   The event doesn't have `path` value.
   *
   * @param  {(string|string[])} globs - A glob pattern for `chokidar.watch()` to match files/dirs.
   * @param  {Object} options - For `chokidar.watch()`.
   * @param  {Function} eventBindings - A callback for binding node stream events with `subscriber`.
   * @return {Observable} - a Rx.Observable sending events from `chokidar.watch()`.
   *
   * @see {@link https://github.com/paulmillr/chokidar}
   */
  function watch(globs, opt, eventBindings) {
    const sepRe = (process.platform === 'win32' ? /[\/\\]/ : /\/+/);
    const cwd = opt.cwd || process.cwd();
    const base = (opt.cwdbase) ? cwd : getBasePath(globs, opt);

    // Match to the glob-stream format with extra prop `event`.
    //
    // @see {@link https://github.com/gulpjs/glob-stream/blob/v5.3.4/index.js#L49}
    function fileEventWrapper(event, filename) {
      const path = (filename) ? Path.normalize(filename) : undefined
      return { event, path, cwd, base };
    };

    // @see {@link https://github.com/gulpjs/glob-stream/blob/v5.3.4/index.js#L193}
    function getBasePath(ourGlob, opt) {
      var basePath;
      var parent = globParent(ourGlob);

      if (parent === '/' && opt && opt.root) {
        basePath = Path.normalize(opt.root);
      } else {
        basePath = resolveGlob(parent, opt);
      }

      if (!sepRe.test(basePath.charAt(basePath.length - 1))) {
        basePath += Path.sep;
      }

      return basePath;
    }

    return Rx.Observable.create((subscriber) => {
      const fsWatcher = chokidar.watch(globs, opt);
      const bindings = eventBindings(subscriber, fileEventWrapper);
      Object.keys(bindings).forEach(event => {
        fsWatcher.on(event, bindings[event])
      });
      return () => {
        fsWatcher.close();
      }
    }).publish().refCount();
  }

  /**
   * An Observable sending file/dir events for both **initials** and **changes**.
   *
   * - i: initials (files/dirs)
   * - r: ready for emitting changes
   * - c: changes (files/dirs)
   *
   * real-event:       '-i--i--i--i--r--c-----c--'
   * fsWatch-sending:  '-i--i--i--i--r--c-----c--'
   */
  function onAll(globs, options) {

    const overridingOpts = {
      persistent: true,
      ignoreInitial: false
    };
    const opts = Object.assign({}, options, overridingOpts);

    return watch(globs, opts, (subscriber, wrapFileEvent) => ({
      all: (event, path) => subscriber[callOnNext](wrapFileEvent(event, path)),
      ready: () => subscriber[callOnNext](wrapFileEvent('ready')),   // send ready as next
      error: (error) => subscriber[callOnError](error)
    }));
  }

  /**
   * An Observable sending file/dir events for **ONLY initials**. Drop the change
   * events and send `complete` when ready.
   *
   * - i: initials (files/dirs)
   * - r: ready for emitting changes
   * - c: changes (files/dirs)
   * - |: complete
   *
   * real-event:       '-i--i--i--i--r--c-----c--'
   * fsWatch-sending:  '-i--i--i--i--|'
   */
  function onInitial(globs, options) {

    const overridingOpts = {
      persistent: false,
      ignoreInitial: false
    };
    const opts = Object.assign({}, options, overridingOpts);

    return watch(globs, opts, (subscriber, wrapFileEvent) => ({
      all: (event, path) => subscriber[callOnNext](wrapFileEvent(event, path)),
      ready: () => subscriber[callOnCompleted](),       // send ready as complete
      error: (error) => subscriber[callOnError](error)
    }));
  }

  /*
   * An Observable sending file/dir events for **ONLY changes**. Drop the initials
   * and ready events.
   *
   * - i: initials (files/dirs)
   * - r: ready for emitting changes
   * - c: changes (files/dirs)
   *
   * real-event:       '-i--i--i--i--r--c-----c--'
   * fsWatch-sending:  '             ---c-----c--'
   */
  function onChange(globs, options) {

    const overridingOpts = {
      persistent: true,
      ignoreInitial: true
    };
    const opts = Object.assign({}, options, overridingOpts);

    return watch(globs, opts, (subscriber, wrapFileEvent) => ({
      all: (event, path) => subscriber[callOnNext](wrapFileEvent(event, path)),
      error: (error) => subscriber[callOnError](error)       // don't send ready
    }));
  };
}

module.exports = { use };
<commit_msg>feat(watchCount): add fs watch count number for values<commit_after>const Path = require('path');
const chokidar = require('chokidar');
const globParent = require('glob-parent');
const resolveGlob = require('to-absolute-glob');

// Use the specific library entity from outside
function use(Rx) {

  // To support both RxJS 4 and RxJS 5
  const proto = Rx.Subject.prototype;
  var rxjs5Supported = !!proto.next && !!proto.error && !!proto.complete;
  const callOnNext = (rxjs5Supported) ? "next" : "onNext";
  const callOnError = (rxjs5Supported) ? "error" : "onError";
  const callOnCompleted = (rxjs5Supported) ? "complete" : "onCompleted";

  return { watch, onAll, onInitial, onChange };

  /*
   * Use chokidar to observe file system events and send events by Rx.Observable.
   *
   * The `next` value of Observable should be an object containing `event` and
   * `path`. Possible event types:
   *
   * - `add`: file has been added.
   * - `change`: file has been changed/modified.
   * - `unlink`: file has been removed.
   * - `addDir`: directory has been added.
   * - `unlinkDir`: directory has been removed.
   * - `ready`: initial scan completes; ready for changes (only for `onAll()`).
   *   The event doesn't have `path` value.
   *
   * @param  {(string|string[])} globs - A glob pattern for `chokidar.watch()` to match files/dirs.
   * @param  {Object} options - For `chokidar.watch()`.
   * @param  {Function} eventBindings - A callback for binding node stream events with `subscriber`.
   * @return {Observable} - a Rx.Observable sending events from `chokidar.watch()`.
   *
   * @see {@link https://github.com/paulmillr/chokidar}
   */
  function watch(globs, opt, eventBindings) {
    const sepRe = (process.platform === 'win32' ? /[\/\\]/ : /\/+/);
    const cwd = opt.cwd || process.cwd();
    const base = (opt.cwdbase) ? cwd : getBasePath(globs, opt);

    // Match to the glob-stream format with extra prop `event`.
    //
    // @see {@link https://github.com/gulpjs/glob-stream/blob/v5.3.4/index.js#L49}
    function fileEventWrapper(event, filename) {
      const path = (filename) ? Path.normalize(filename) : undefined
      return { event, path, cwd, base };
    };

    // @see {@link https://github.com/gulpjs/glob-stream/blob/v5.3.4/index.js#L193}
    function getBasePath(ourGlob, opt) {
      var basePath;
      var parent = globParent(ourGlob);

      if (parent === '/' && opt && opt.root) {
        basePath = Path.normalize(opt.root);
      } else {
        basePath = resolveGlob(parent, opt);
      }

      if (!sepRe.test(basePath.charAt(basePath.length - 1))) {
        basePath += Path.sep;
      }

      return basePath;
    }

    const fsWatch$ = Rx.Observable.create((subscriber) => {
      const fsWatcher = chokidar.watch(globs, opt);
      const bindings = eventBindings(subscriber, fileEventWrapper);
      Object.keys(bindings).forEach(event => {
        fsWatcher.on(event, bindings[event])
      });
      return () => {
        fsWatcher.close();
      }
    })

    let watchCount = 0;

    return fsWatch$
      .map(f => {
        f.watchCount = ++watchCount;
        return f;
      })
      .publish().refCount();
  }

  /**
   * An Observable sending file/dir events for both **initials** and **changes**.
   *
   * - i: initials (files/dirs)
   * - r: ready for emitting changes
   * - c: changes (files/dirs)
   *
   * real-event:       '-i--i--i--i--r--c-----c--'
   * fsWatch-sending:  '-i--i--i--i--r--c-----c--'
   */
  function onAll(globs, options) {

    const overridingOpts = {
      persistent: true,
      ignoreInitial: false
    };
    const opts = Object.assign({}, options, overridingOpts);

    return watch(globs, opts, (subscriber, wrapFileEvent) => ({
      all: (event, path) => subscriber[callOnNext](wrapFileEvent(event, path)),
      ready: () => subscriber[callOnNext](wrapFileEvent('ready')),   // send ready as next
      error: (error) => subscriber[callOnError](error)
    }));
  }

  /**
   * An Observable sending file/dir events for **ONLY initials**. Drop the change
   * events and send `complete` when ready.
   *
   * - i: initials (files/dirs)
   * - r: ready for emitting changes
   * - c: changes (files/dirs)
   * - |: complete
   *
   * real-event:       '-i--i--i--i--r--c-----c--'
   * fsWatch-sending:  '-i--i--i--i--|'
   */
  function onInitial(globs, options) {

    const overridingOpts = {
      persistent: false,
      ignoreInitial: false
    };
    const opts = Object.assign({}, options, overridingOpts);

    return watch(globs, opts, (subscriber, wrapFileEvent) => ({
      all: (event, path) => subscriber[callOnNext](wrapFileEvent(event, path)),
      ready: () => subscriber[callOnCompleted](),       // send ready as complete
      error: (error) => subscriber[callOnError](error)
    }));
  }

  /*
   * An Observable sending file/dir events for **ONLY changes**. Drop the initials
   * and ready events.
   *
   * - i: initials (files/dirs)
   * - r: ready for emitting changes
   * - c: changes (files/dirs)
   *
   * real-event:       '-i--i--i--i--r--c-----c--'
   * fsWatch-sending:  '             ---c-----c--'
   */
  function onChange(globs, options) {

    const overridingOpts = {
      persistent: true,
      ignoreInitial: true
    };
    const opts = Object.assign({}, options, overridingOpts);

    return watch(globs, opts, (subscriber, wrapFileEvent) => ({
      all: (event, path) => subscriber[callOnNext](wrapFileEvent(event, path)),
      error: (error) => subscriber[callOnError](error)       // don't send ready
    }));
  };
}

module.exports = { use };
<|endoftext|>


<commit_before>'use strict';

import React from 'react';
import ActionButton from './ActionButton';

const buttonSpaceDefaultProps = {
	buttons: null,
	className: null,
	onOk: null,
	onClose: null,
	buttonClick: null,
	btnClass: null,
	href: null
};

class ButtonsSpace extends React.Component {

	constructor(props) {
		super(props);
	}

    onOk() {
        if (this.props.onOk) {
            return this.props.onOk();
        }
    }

    onClose() {
        if (this.props.onClose) {
            return this.props.onClose();
        }
    }

    buttonClick(action) {
		if (this.props.buttonClick) {
            return this.props.buttonClick(action);
        }
    }

    wildClass(className, base) {
        if (!className) {
            return null;
        }

        if (this.props.wildClasses) {
            return className;
        }

        var finalClass = [],
            classNames = className.split(' ');

        classNames.forEach(function (className) {
            finalClass.push(base + '--' + className);
        });

        return finalClass.join(' ');
    }

    render() {
        if (!this.props.buttons) {
            return null;
        }

        let btns = [];

        for (let i in this.props.buttons) {
            if (this.props.buttons.hasOwnProperty(i)) {
                let btn = this.props.buttons[i];
                let url = (btn.url) ? btn.url : null;

                if (typeof btn === 'string') {
                    if (btn === 'ok') {
                        btns.push(<ActionButton className={this.props.btnClass + ' ' + this.props.btnClass + '--ok'} key={i} onClick={() => this.onOk()}>{this.props.defaultOk}</ActionButton>);
                    } else if (btn === 'cancel') {
                        btns.push(<ActionButton className={this.props.btnClass + ' ' + this.props.btnClass + '--cancel'} key={i} onClick={() => this.onClose()}>{this.props.defaultCancel}</ActionButton>);
                    }
                } else {
                    let className = this.props.btnClass + ' ' + this.wildClass(btn.className, this.props.btnClass);
                    btns.push(<ActionButton className={className} key={i} url={url} onClick={() => this.buttonClick(btn.action)} dangerouslySetInnerHTML={{ __html: btn.text }} />);
                }
            }
        }

        return (

                {btns}

        );
    }

}

ButtonsSpace.displayName = 'PopupFooterButtons';
ButtonsSpace.defaultProps = buttonSpaceDefaultProps;

const defaultProps = {
	buttons: null,
	className: null,
	wildClasses: false,
	btnClass: null,
	defaultOk: null,
	defaultCancel: null,
	buttonClick: null,
	onOk: null,
	onClose: null
};

class Component extends React.Component {

	constructor(props) {
		super(props);
	}

    render() {
        if (this.props.buttons) {
            return (

                    <ButtonsSpace
                        buttonClick={this.props.buttonClick}
                        onOk={this.props.onOk}
                        onClose={this.props.onClose}
                        className={this.props.className + '__left-space'}
                        wildClasses={this.props.wildClasses}
                        btnClass={this.props.btnClass}
                        defaultOk={this.props.defaultOk}
                        defaultCancel={this.props.defaultCancel}
                        buttons={this.props.buttons.left}
					/>

                    <ButtonsSpace
                        buttonClick={this.props.buttonClick}
                        onOk={this.props.onOk}
                        onClose={this.props.onClose}
                        className={this.props.className + '__right-space'}
                        wildClasses={this.props.wildClasses}
                        btnClass={this.props.btnClass}
                        defaultOk={this.props.defaultOk}
                        defaultCancel={this.props.defaultCancel}
                        buttons={this.props.buttons.right}
					/>

            );
        }

        return null;
    }

}

Component.displayName = 'PopupFooter';
Component.defaultProps = defaultProps;

export default Component;
<commit_msg>Update Footer.react.js<commit_after>'use strict';

import React from 'react';
import ActionButton from './ActionButton';

const buttonSpaceDefaultProps = {
	buttons: null,
	className: null,
	onOk: null,
	onClose: null,
	buttonClick: null,
	btnClass: null,
	href: null
};

class ButtonsSpace extends React.Component {

	constructor(props) {
		super(props);
	}

    onOk() {
        if (this.props.onOk) {
            return this.props.onOk();
        }
    }

    onClose() {
        if (this.props.onClose) {
            return this.props.onClose();
        }
    }

    buttonClick(action) {
		if (this.props.buttonClick) {
            return this.props.buttonClick(action);
        }
    }

    wildClass(className, base) {
        if (!className) {
            return null;
        }

        if (this.props.wildClasses) {
            return className;
        }

        var finalClass = [],
            classNames = className.split(' ');

        classNames.forEach(function (className) {
            finalClass.push(base + '--' + className);
        });

        return finalClass.join(' ');
    }

    render() {
        if (!this.props.buttons) {
            return null;
        }

        let btns = [];

        for (let i in this.props.buttons) {
            if (this.props.buttons.hasOwnProperty(i)) {
                let btn = this.props.buttons[i];
                let url = (btn.url) ? btn.url : null;

                if (typeof btn === 'string') {
                    if (btn === 'ok') {
                        btns.push(<ActionButton className={this.props.btnClass + ' ' + this.props.btnClass + '--ok'} key={i} onClick={() => this.onOk()}>{this.props.defaultOk}</ActionButton>);
                    } else if (btn === 'cancel') {
                        btns.push(<ActionButton className={this.props.btnClass + ' ' + this.props.btnClass + '--cancel'} key={i} onClick={() => this.onClose()}>{this.props.defaultCancel}</ActionButton>);
                    }
                } else {
                    let className = this.props.btnClass + ' ' + this.wildClass(btn.className, this.props.btnClass);
                    btns.push(<ActionButton className={className} key={i} url={url} onClick={() => this.buttonClick(btn.action)} html={btn.html}>{btn.text}</ActionButton>);
                }
            }
        }

        return (

                {btns}

        );
    }

}

ButtonsSpace.displayName = 'PopupFooterButtons';
ButtonsSpace.defaultProps = buttonSpaceDefaultProps;

const defaultProps = {
	buttons: null,
	className: null,
	wildClasses: false,
	btnClass: null,
	defaultOk: null,
	defaultCancel: null,
	buttonClick: null,
	onOk: null,
	onClose: null
};

class Component extends React.Component {

	constructor(props) {
		super(props);
	}

    render() {
        if (this.props.buttons) {
            return (

                    <ButtonsSpace
                        buttonClick={this.props.buttonClick}
                        onOk={this.props.onOk}
                        onClose={this.props.onClose}
                        className={this.props.className + '__left-space'}
                        wildClasses={this.props.wildClasses}
                        btnClass={this.props.btnClass}
                        defaultOk={this.props.defaultOk}
                        defaultCancel={this.props.defaultCancel}
                        buttons={this.props.buttons.left}
					/>

                    <ButtonsSpace
                        buttonClick={this.props.buttonClick}
                        onOk={this.props.onOk}
                        onClose={this.props.onClose}
                        className={this.props.className + '__right-space'}
                        wildClasses={this.props.wildClasses}
                        btnClass={this.props.btnClass}
                        defaultOk={this.props.defaultOk}
                        defaultCancel={this.props.defaultCancel}
                        buttons={this.props.buttons.right}
					/>

            );
        }

        return null;
    }

}

Component.displayName = 'PopupFooter';
Component.defaultProps = defaultProps;

export default Component;
<|endoftext|>


<commit_before>import * as utils from './utils.js';
import baseLogger from './logger.js';

class Interpolator {
  constructor(options = {}) {
    this.logger = baseLogger.create('interpolator');

    this.init(options, true);
  }

  /* eslint no-param-reassign: 0 */
  init(options = {}, reset) {
    if (reset) {
      this.options = options;
      this.format = (options.interpolation && options.interpolation.format) || (value => value);
      this.escape = (options.interpolation && options.interpolation.escape) || utils.escape;
    }
    if (!options.interpolation) options.interpolation = { escapeValue: true };

    const iOpts = options.interpolation;

    this.escapeValue = iOpts.escapeValue !== undefined ? iOpts.escapeValue : true;

    this.prefix = iOpts.prefix ? utils.regexEscape(iOpts.prefix) : iOpts.prefixEscaped || '{{';
    this.suffix = iOpts.suffix ? utils.regexEscape(iOpts.suffix) : iOpts.suffixEscaped || '}}';

    this.formatSeparator = iOpts.formatSeparator ? iOpts.formatSeparator : iOpts.formatSeparator || ',';

    this.unescapePrefix = iOpts.unescapeSuffix ? '' : iOpts.unescapePrefix || '-';
    this.unescapeSuffix = this.unescapePrefix ? '' : iOpts.unescapeSuffix || '';

    this.nestingPrefix = iOpts.nestingPrefix ? utils.regexEscape(iOpts.nestingPrefix) : iOpts.nestingPrefixEscaped || utils.regexEscape('$t(');
    this.nestingSuffix = iOpts.nestingSuffix ? utils.regexEscape(iOpts.nestingSuffix) : iOpts.nestingSuffixEscaped || utils.regexEscape(')');

    this.maxReplaces = iOpts.maxReplaces ? iOpts.maxReplaces : 1000;

    // the regexp
    this.resetRegExp();
  }

  reset() {
    if (this.options) this.init(this.options);
  }

  resetRegExp() {
    // the regexp
    const regexpStr = `${this.prefix}(.+?)${this.suffix}`;
    this.regexp = new RegExp(regexpStr, 'g');

    const regexpUnescapeStr = `${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`;
    this.regexpUnescape = new RegExp(regexpUnescapeStr, 'g');

    const nestingRegexpStr = `${this.nestingPrefix}(.+?)${this.nestingSuffix}`;
    this.nestingRegexp = new RegExp(nestingRegexpStr, 'g');
  }

  interpolate(str, data, lng) {
    let match;
    let value;
    let replaces;

    function regexSafe(val) {
      return val.replace(/\$/g, '$$$$');
    }

    const handleFormat = (key) => {
      if (key.indexOf(this.formatSeparator) < 0) return utils.getPath(data, key);

      const p = key.split(this.formatSeparator);
      const k = p.shift().trim();
      const f = p.join(this.formatSeparator).trim();

      return this.format(utils.getPath(data, k), f, lng);
    };

    this.resetRegExp();

    replaces = 0;
    // unescape if has unescapePrefix/Suffix
    /* eslint no-cond-assign: 0 */
    while (match = this.regexpUnescape.exec(str)) {
      value = handleFormat(match[1].trim());
      str = str.replace(match[0], value);
      this.regexpUnescape.lastIndex = 0;
      replaces++;
      if (replaces >= this.maxReplaces) {
        break;
      }
    }

    replaces = 0;
    // regular escape on demand
    while (match = this.regexp.exec(str)) {
      value = handleFormat(match[1].trim());
      if (typeof value !== 'string') value = utils.makeString(value);
      if (!value) {
        this.logger.warn(`missed to pass in variable ${match[1]} for interpolating ${str}`);
        value = '';
      }
      value = this.escapeValue ? regexSafe(this.escape(value)) : regexSafe(value);
      str = str.replace(match[0], value);
      this.regexp.lastIndex = 0;
      replaces++;
      if (replaces >= this.maxReplaces) {
        break;
      }
    }
    return str;
  }

  nest(str, fc, options = {}) {
    let match;
    let value;

    let clonedOptions = { ...options };
    clonedOptions.applyPostProcessor = false; // avoid post processing on nested lookup

    // if value is something like "myKey": "lorem $(anotherKey, { "count": {{aValueInOptions}} })"
    function handleHasOptions(key) {
      if (key.indexOf(',') < 0) return key;

      const p = key.split(',');
      key = p.shift();
      let optionsString = p.join(',');
      optionsString = this.interpolate(optionsString, clonedOptions);
      optionsString = optionsString.replace(/'/g, '"');

      try {
        clonedOptions = JSON.parse(optionsString);
      } catch (e) {
        this.logger.error(`failed parsing options string in nesting for key ${key}`, e);
      }

      return key;
    }

    // regular escape on demand
    while (match = this.nestingRegexp.exec(str)) {
      value = fc(handleHasOptions.call(this, match[1].trim()), clonedOptions);

      // is only the nesting key (key1 = '$(key2)') return the value without stringify
      if (value && match[0] === str && typeof value !== 'string') return value;

      // no string to include or empty
      if (typeof value !== 'string') value = utils.makeString(value);
      if (!value) {
        this.logger.warn(`missed to resolve ${match[1]} for nesting ${str}`);
        value = '';
      }
      // Nested keys should not be escaped by default #854
      // value = this.escapeValue ? regexSafe(utils.escape(value)) : regexSafe(value);
      str = str.replace(match[0], value);
      this.regexp.lastIndex = 0;
    }
    return str;
  }
}

export default Interpolator;
<commit_msg>https://github.com/i18next/i18next/issues/1009 nested translations inherit parent's options<commit_after>import * as utils from './utils.js';
import baseLogger from './logger.js';

class Interpolator {
  constructor(options = {}) {
    this.logger = baseLogger.create('interpolator');

    this.init(options, true);
  }

  /* eslint no-param-reassign: 0 */
  init(options = {}, reset) {
    if (reset) {
      this.options = options;
      this.format = (options.interpolation && options.interpolation.format) || (value => value);
      this.escape = (options.interpolation && options.interpolation.escape) || utils.escape;
    }
    if (!options.interpolation) options.interpolation = { escapeValue: true };

    const iOpts = options.interpolation;

    this.escapeValue = iOpts.escapeValue !== undefined ? iOpts.escapeValue : true;

    this.prefix = iOpts.prefix ? utils.regexEscape(iOpts.prefix) : iOpts.prefixEscaped || '{{';
    this.suffix = iOpts.suffix ? utils.regexEscape(iOpts.suffix) : iOpts.suffixEscaped || '}}';

    this.formatSeparator = iOpts.formatSeparator ? iOpts.formatSeparator : iOpts.formatSeparator || ',';

    this.unescapePrefix = iOpts.unescapeSuffix ? '' : iOpts.unescapePrefix || '-';
    this.unescapeSuffix = this.unescapePrefix ? '' : iOpts.unescapeSuffix || '';

    this.nestingPrefix = iOpts.nestingPrefix ? utils.regexEscape(iOpts.nestingPrefix) : iOpts.nestingPrefixEscaped || utils.regexEscape('$t(');
    this.nestingSuffix = iOpts.nestingSuffix ? utils.regexEscape(iOpts.nestingSuffix) : iOpts.nestingSuffixEscaped || utils.regexEscape(')');

    this.maxReplaces = iOpts.maxReplaces ? iOpts.maxReplaces : 1000;

    // the regexp
    this.resetRegExp();
  }

  reset() {
    if (this.options) this.init(this.options);
  }

  resetRegExp() {
    // the regexp
    const regexpStr = `${this.prefix}(.+?)${this.suffix}`;
    this.regexp = new RegExp(regexpStr, 'g');

    const regexpUnescapeStr = `${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`;
    this.regexpUnescape = new RegExp(regexpUnescapeStr, 'g');

    const nestingRegexpStr = `${this.nestingPrefix}(.+?)${this.nestingSuffix}`;
    this.nestingRegexp = new RegExp(nestingRegexpStr, 'g');
  }

  interpolate(str, data, lng) {
    let match;
    let value;
    let replaces;

    function regexSafe(val) {
      return val.replace(/\$/g, '$$$$');
    }

    const handleFormat = (key) => {
      if (key.indexOf(this.formatSeparator) < 0) return utils.getPath(data, key);

      const p = key.split(this.formatSeparator);
      const k = p.shift().trim();
      const f = p.join(this.formatSeparator).trim();

      return this.format(utils.getPath(data, k), f, lng);
    };

    this.resetRegExp();

    replaces = 0;
    // unescape if has unescapePrefix/Suffix
    /* eslint no-cond-assign: 0 */
    while (match = this.regexpUnescape.exec(str)) {
      value = handleFormat(match[1].trim());
      str = str.replace(match[0], value);
      this.regexpUnescape.lastIndex = 0;
      replaces++;
      if (replaces >= this.maxReplaces) {
        break;
      }
    }

    replaces = 0;
    // regular escape on demand
    while (match = this.regexp.exec(str)) {
      value = handleFormat(match[1].trim());
      if (typeof value !== 'string') value = utils.makeString(value);
      if (!value) {
        this.logger.warn(`missed to pass in variable ${match[1]} for interpolating ${str}`);
        value = '';
      }
      value = this.escapeValue ? regexSafe(this.escape(value)) : regexSafe(value);
      str = str.replace(match[0], value);
      this.regexp.lastIndex = 0;
      replaces++;
      if (replaces >= this.maxReplaces) {
        break;
      }
    }
    return str;
  }

  nest(str, fc, options = {}) {
    let match;
    let value;

    let clonedOptions = { ...options };
    clonedOptions.applyPostProcessor = false; // avoid post processing on nested lookup

    // if value is something like "myKey": "lorem $(anotherKey, { "count": {{aValueInOptions}} })"
    function handleHasOptions(key, inheritedOptions) {
      if (key.indexOf(',') < 0) return key;

      const p = key.split(',');
      key = p.shift();
      let optionsString = p.join(',');
      optionsString = this.interpolate(optionsString, clonedOptions);
      optionsString = optionsString.replace(/'/g, '"');

      try {
        clonedOptions = JSON.parse(optionsString);

        if(inheritedOptions)
            clonedOptions = { ...inheritedOptions, ...clonedOptions};
      } catch (e) {
        this.logger.error(`failed parsing options string in nesting for key ${key}`, e);
      }

      return key;
    }

    // regular escape on demand
    while (match = this.nestingRegexp.exec(str)) {
      value = fc(handleHasOptions.call(this, match[1].trim(), clonedOptions), clonedOptions);

      // is only the nesting key (key1 = '$(key2)') return the value without stringify
      if (value && match[0] === str && typeof value !== 'string') return value;

      // no string to include or empty
      if (typeof value !== 'string') value = utils.makeString(value);
      if (!value) {
        this.logger.warn(`missed to resolve ${match[1]} for nesting ${str}`);
        value = '';
      }
      // Nested keys should not be escaped by default #854
      // value = this.escapeValue ? regexSafe(utils.escape(value)) : regexSafe(value);
      str = str.replace(match[0], value);
      this.regexp.lastIndex = 0;
    }
    return str;
  }
}

export default Interpolator;
<|endoftext|>


<commit_before>//import //

var _elm_lang$core$Native_Utils = function() {

// COMPARISONS

function eq(rootX, rootY)
{
	var stack = [{ x: rootX, y: rootY }];
	while (stack.length > 0)
	{
		var front = stack.pop();
		var x = front.x;
		var y = front.y;
		if (x === y)
		{
			continue;
		}
		if (typeof x === 'object')
		{
			var c = 0;
			for (var key in x)
			{
				++c;
				if (!(key in y))
				{
					return false;
				}
				if (key === 'ctor')
				{
					continue;
				}
				stack.push({ x: x[key], y: y[key] });
			}
			if ('ctor' in x)
			{
				stack.push({ x: x.ctor, y: y.ctor});
			}
			if (c !== Object.keys(y).length)
			{
				return false;
			}
		}
		else if (typeof x === 'function')
		{
			throw new Error('Equality error: general function equality is ' +
							'undecidable, and therefore, unsupported');
		}
		else
		{
			return false;
		}
	}
	return true;
}

// Code in Generate/JavaScript.hs, Basics.js, and List.js depends on
// the particular integer values assigned to LT, EQ, and GT.

var LT = -1, EQ = 0, GT = 1;

function cmp(x, y)
{
	var ord;
	if (typeof x !== 'object')
	{
		return x === y ? EQ : x < y ? LT : GT;
	}
	else if (x instanceof String)
	{
		var a = x.valueOf();
		var b = y.valueOf();
		return a === b
			? EQ
			: a < b
				? LT
				: GT;
	}
	else if (x.ctor === '::' || x.ctor === '[]')
	{
		while (true)
		{
			if (x.ctor === '[]' && y.ctor === '[]')
			{
				return EQ;
			}
			if (x.ctor !== y.ctor)
			{
				return x.ctor === '[]' ? LT : GT;
			}
			ord = cmp(x._0, y._0);
			if (ord !== EQ)
			{
				return ord;
			}
			x = x._1;
			y = y._1;
		}
	}
	else if (x.ctor.slice(0, 6) === '_Tuple')
	{
		var n = x.ctor.slice(6) - 0;
		var err = 'cannot compare tuples with more than 6 elements.';
		if (n === 0) return EQ;
		if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
		if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
		if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
		if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
		if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
		if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
		if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
		return EQ;
	}
	else
	{
		throw new Error('Comparison error: comparison is only defined on ints, ' +
						'floats, times, chars, strings, lists of comparable values, ' +
						'and tuples of comparable values.');
	}
}

// COMMON VALUES

var Tuple0 = {
	ctor: '_Tuple0'
};

function Tuple2(x, y)
{
	return {
		ctor: '_Tuple2',
		_0: x,
		_1: y
	};
}

function chr(c)
{
	return new String(c);
}

// GUID

var count = 0;
function guid(_)
{
	return count++;
}

// RECORDS

function update(oldRecord, updatedFields)
{
	var newRecord = {};
	for (var key in oldRecord)
	{
		var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key];
		newRecord[key] = value;
	}
	return newRecord;
}

//// LIST STUFF ////

var Nil = { ctor: '[]' };

function Cons(hd, tl)
{
	return {
		ctor: '::',
		_0: hd,
		_1: tl
	};
}

function append(xs, ys)
{
	// append Strings
	if (typeof xs === 'string')
	{
		return xs + ys;
	}

	// append Lists
	if (xs.ctor === '[]')
	{
		return ys;
	}
	var root = Cons(xs._0, Nil);
	var curr = root;
	xs = xs._1;
	while (xs.ctor !== '[]')
	{
		curr._1 = Cons(xs._0, Nil);
		xs = xs._1;
		curr = curr._1;
	}
	curr._1 = ys;
	return root;
}

// CRASHES

function crash(moduleName, region)
{
	return function(message) {
		throw new Error(
			'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n'
			+ 'The message provided by the code author is:\n\n    '
			+ message
		);
	};
}

function crashCase(moduleName, region, value)
{
	return function(message) {
		throw new Error(
			'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n'
			+ 'This was caused by the `case` expression ' + regionToString(region) + '.\n'
			+ 'One of the branches ended with a crash and the following value got through:\n\n    ' + toString(value) + '\n\n'
			+ 'The message provided by the code author is:\n\n    '
			+ message
		);
	};
}

function regionToString(region)
{
	if (region.start.line == region.end.line)
	{
		return 'on line ' + region.start.line;
	}
	return 'between lines ' + region.start.line + ' and ' + region.end.line;
}

// TO STRING

function toString(v)
{
	var type = typeof v;
	if (type === 'function')
	{
		var name = v.func ? v.func.name : v.name;
		return '<function' + (name === '' ? '' : ': ') + name + '>';
	}

	if (type === 'boolean')
	{
		return v ? 'True' : 'False';
	}

	if (type === 'number')
	{
		return v + '';
	}

	if (v instanceof String)
	{
		return '\'' + addSlashes(v, true) + '\'';
	}

	if (type === 'string')
	{
		return '"' + addSlashes(v, false) + '"';
	}

	if (v === null)
	{
		return 'null';
	}

	if (type === 'object' && 'ctor' in v)
	{
		var ctorStarter = v.ctor.substring(0, 5);

		if (ctorStarter === '_Tupl')
		{
			var output = [];
			for (var k in v)
			{
				if (k === 'ctor') continue;
				output.push(toString(v[k]));
			}
			return '(' + output.join(',') + ')';
		}

		if (ctorStarter === '_Task')
		{
			return '<task>'
		}

		if (v.ctor === '_Array')
		{
			var list = _elm_lang$core$Array$toList(v);
			return 'Array.fromList ' + toString(list);
		}

		if (v.ctor === '_Process')
		{
			return '<process:' + v.id + '>';
		}

		if (v.ctor === '::')
		{
			var output = '[' + toString(v._0);
			v = v._1;
			while (v.ctor === '::')
			{
				output += ',' + toString(v._0);
				v = v._1;
			}
			return output + ']';
		}

		if (v.ctor === '[]')
		{
			return '[]';
		}

		if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin' || v.ctor === 'Set_elm_builtin')
		{
			var name, list;
			if (v.ctor === 'Set_elm_builtin')
			{
				name = 'Set';
				list = A2(
					_elm_lang$core$List$map,
					function(x) {return x._0; },
					_elm_lang$core$Dict$toList(v._0)
				);
			}
			else
			{
				name = 'Dict';
				list = _elm_lang$core$Dict$toList(v);
			}
			return name + '.fromList ' + toString(list);
		}

		var output = '';
		for (var i in v)
		{
			if (i === 'ctor') continue;
			var str = toString(v[i]);
			var parenless = str[0] === '{' || str[0] === '<' || str.indexOf(' ') < 0;
			output += ' ' + (parenless ? str : '(' + str + ')');
		}
		return v.ctor + output;
	}

	if (type === 'object')
	{
		var output = [];
		for (var k in v)
		{
			output.push(k + ' = ' + toString(v[k]));
		}
		if (output.length === 0)
		{
			return '{}';
		}
		return '{ ' + output.join(', ') + ' }';
	}

	return '<internal structure>';
}

function addSlashes(str, isChar)
{
	var s = str.replace(/\\/g, '\\\\')
			  .replace(/\n/g, '\\n')
			  .replace(/\t/g, '\\t')
			  .replace(/\r/g, '\\r')
			  .replace(/\v/g, '\\v')
			  .replace(/\0/g, '\\0');
	if (isChar)
	{
		return s.replace(/\'/g, '\\\'');
	}
	else
	{
		return s.replace(/\"/g, '\\"');
	}
}

return {
	eq: eq,
	cmp: cmp,
	Tuple0: Tuple0,
	Tuple2: Tuple2,
	chr: chr,
	update: update,
	guid: guid,

	append: F2(append),

	crash: crash,
	crashCase: crashCase,

	toString: toString
};

}();<commit_msg>Add parens less aggressively<commit_after>//import //

var _elm_lang$core$Native_Utils = function() {

// COMPARISONS

function eq(rootX, rootY)
{
	var stack = [{ x: rootX, y: rootY }];
	while (stack.length > 0)
	{
		var front = stack.pop();
		var x = front.x;
		var y = front.y;
		if (x === y)
		{
			continue;
		}
		if (typeof x === 'object')
		{
			var c = 0;
			for (var key in x)
			{
				++c;
				if (!(key in y))
				{
					return false;
				}
				if (key === 'ctor')
				{
					continue;
				}
				stack.push({ x: x[key], y: y[key] });
			}
			if ('ctor' in x)
			{
				stack.push({ x: x.ctor, y: y.ctor});
			}
			if (c !== Object.keys(y).length)
			{
				return false;
			}
		}
		else if (typeof x === 'function')
		{
			throw new Error('Equality error: general function equality is ' +
							'undecidable, and therefore, unsupported');
		}
		else
		{
			return false;
		}
	}
	return true;
}

// Code in Generate/JavaScript.hs, Basics.js, and List.js depends on
// the particular integer values assigned to LT, EQ, and GT.

var LT = -1, EQ = 0, GT = 1;

function cmp(x, y)
{
	var ord;
	if (typeof x !== 'object')
	{
		return x === y ? EQ : x < y ? LT : GT;
	}
	else if (x instanceof String)
	{
		var a = x.valueOf();
		var b = y.valueOf();
		return a === b
			? EQ
			: a < b
				? LT
				: GT;
	}
	else if (x.ctor === '::' || x.ctor === '[]')
	{
		while (true)
		{
			if (x.ctor === '[]' && y.ctor === '[]')
			{
				return EQ;
			}
			if (x.ctor !== y.ctor)
			{
				return x.ctor === '[]' ? LT : GT;
			}
			ord = cmp(x._0, y._0);
			if (ord !== EQ)
			{
				return ord;
			}
			x = x._1;
			y = y._1;
		}
	}
	else if (x.ctor.slice(0, 6) === '_Tuple')
	{
		var n = x.ctor.slice(6) - 0;
		var err = 'cannot compare tuples with more than 6 elements.';
		if (n === 0) return EQ;
		if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
		if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
		if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
		if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
		if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
		if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
		if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
		return EQ;
	}
	else
	{
		throw new Error('Comparison error: comparison is only defined on ints, ' +
						'floats, times, chars, strings, lists of comparable values, ' +
						'and tuples of comparable values.');
	}
}

// COMMON VALUES

var Tuple0 = {
	ctor: '_Tuple0'
};

function Tuple2(x, y)
{
	return {
		ctor: '_Tuple2',
		_0: x,
		_1: y
	};
}

function chr(c)
{
	return new String(c);
}

// GUID

var count = 0;
function guid(_)
{
	return count++;
}

// RECORDS

function update(oldRecord, updatedFields)
{
	var newRecord = {};
	for (var key in oldRecord)
	{
		var value = (key in updatedFields) ? updatedFields[key] : oldRecord[key];
		newRecord[key] = value;
	}
	return newRecord;
}

//// LIST STUFF ////

var Nil = { ctor: '[]' };

function Cons(hd, tl)
{
	return {
		ctor: '::',
		_0: hd,
		_1: tl
	};
}

function append(xs, ys)
{
	// append Strings
	if (typeof xs === 'string')
	{
		return xs + ys;
	}

	// append Lists
	if (xs.ctor === '[]')
	{
		return ys;
	}
	var root = Cons(xs._0, Nil);
	var curr = root;
	xs = xs._1;
	while (xs.ctor !== '[]')
	{
		curr._1 = Cons(xs._0, Nil);
		xs = xs._1;
		curr = curr._1;
	}
	curr._1 = ys;
	return root;
}

// CRASHES

function crash(moduleName, region)
{
	return function(message) {
		throw new Error(
			'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n'
			+ 'The message provided by the code author is:\n\n    '
			+ message
		);
	};
}

function crashCase(moduleName, region, value)
{
	return function(message) {
		throw new Error(
			'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n'
			+ 'This was caused by the `case` expression ' + regionToString(region) + '.\n'
			+ 'One of the branches ended with a crash and the following value got through:\n\n    ' + toString(value) + '\n\n'
			+ 'The message provided by the code author is:\n\n    '
			+ message
		);
	};
}

function regionToString(region)
{
	if (region.start.line == region.end.line)
	{
		return 'on line ' + region.start.line;
	}
	return 'between lines ' + region.start.line + ' and ' + region.end.line;
}

// TO STRING

function toString(v)
{
	var type = typeof v;
	if (type === 'function')
	{
		var name = v.func ? v.func.name : v.name;
		return '<function' + (name === '' ? '' : ': ') + name + '>';
	}

	if (type === 'boolean')
	{
		return v ? 'True' : 'False';
	}

	if (type === 'number')
	{
		return v + '';
	}

	if (v instanceof String)
	{
		return '\'' + addSlashes(v, true) + '\'';
	}

	if (type === 'string')
	{
		return '"' + addSlashes(v, false) + '"';
	}

	if (v === null)
	{
		return 'null';
	}

	if (type === 'object' && 'ctor' in v)
	{
		var ctorStarter = v.ctor.substring(0, 5);

		if (ctorStarter === '_Tupl')
		{
			var output = [];
			for (var k in v)
			{
				if (k === 'ctor') continue;
				output.push(toString(v[k]));
			}
			return '(' + output.join(',') + ')';
		}

		if (ctorStarter === '_Task')
		{
			return '<task>'
		}

		if (v.ctor === '_Array')
		{
			var list = _elm_lang$core$Array$toList(v);
			return 'Array.fromList ' + toString(list);
		}

		if (v.ctor === '_Process')
		{
			return '<process:' + v.id + '>';
		}

		if (v.ctor === '::')
		{
			var output = '[' + toString(v._0);
			v = v._1;
			while (v.ctor === '::')
			{
				output += ',' + toString(v._0);
				v = v._1;
			}
			return output + ']';
		}

		if (v.ctor === '[]')
		{
			return '[]';
		}

		if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin' || v.ctor === 'Set_elm_builtin')
		{
			var name, list;
			if (v.ctor === 'Set_elm_builtin')
			{
				name = 'Set';
				list = A2(
					_elm_lang$core$List$map,
					function(x) {return x._0; },
					_elm_lang$core$Dict$toList(v._0)
				);
			}
			else
			{
				name = 'Dict';
				list = _elm_lang$core$Dict$toList(v);
			}
			return name + '.fromList ' + toString(list);
		}

		var output = '';
		for (var i in v)
		{
			if (i === 'ctor') continue;
			var str = toString(v[i]);
			var c0 = str[0];
			var parenless = c0 === '{' || c0 === '(' || c0 === '<' || c0 === '"' || str.indexOf(' ') < 0;
			output += ' ' + (parenless ? str : '(' + str + ')');
		}
		return v.ctor + output;
	}

	if (type === 'object')
	{
		var output = [];
		for (var k in v)
		{
			output.push(k + ' = ' + toString(v[k]));
		}
		if (output.length === 0)
		{
			return '{}';
		}
		return '{ ' + output.join(', ') + ' }';
	}

	return '<internal structure>';
}

function addSlashes(str, isChar)
{
	var s = str.replace(/\\/g, '\\\\')
			  .replace(/\n/g, '\\n')
			  .replace(/\t/g, '\\t')
			  .replace(/\r/g, '\\r')
			  .replace(/\v/g, '\\v')
			  .replace(/\0/g, '\\0');
	if (isChar)
	{
		return s.replace(/\'/g, '\\\'');
	}
	else
	{
		return s.replace(/\"/g, '\\"');
	}
}

return {
	eq: eq,
	cmp: cmp,
	Tuple0: Tuple0,
	Tuple2: Tuple2,
	chr: chr,
	update: update,
	guid: guid,

	append: F2(append),

	crash: crash,
	crashCase: crashCase,

	toString: toString
};

}();<|endoftext|>


<commit_before>import React from 'react';
import jQuery from 'jquery';

class ProjectInput extends React.Component {
  constructor() {
    super();
  }

  onSubmitForm(event) {
    event.preventDefault();

    let component = this;
    let title = this.refs.newProjectInput.value;
    let newProject = {
      id: null,
      title: title
    };

    console.log(newProject);
  }

  render() {
    return (

        <form onSubmit={this.onSubmitForm.bind(this)}>
          <input ref="newProjectInput" />
          <button type="submit">Add</button>
        </form>

    );
  }
}

export default ProjectInput;
<commit_msg>sync with database for adding projects<commit_after>import React from 'react';
import jQuery from 'jquery';

class ProjectInput extends React.Component {
  constructor() {
    super();
  }

  onSubmitForm(event) {
    event.preventDefault();

    let component = this;
    let title = this.refs.newProjectInput.value;
    let newProject = {
      id: null,
      title: title
    };

    jQuery.ajax({
      type: "POST",
      url: "https://projectapitask.herokuapp.com/projects.json",
      data: JSON.stringify({
          project: newProject
      }),
      contentType: "application/json",
      dataType: "json"
    })

    .done(function(data) {
      component.props.onChange();
      component.refs.newProjectInput.value = "";
    })

    .fail(function(error) {
      console.log(error);
    });
  }

  render() {
    return (

        <form onSubmit={this.onSubmitForm.bind(this)}>
          <input ref="newProjectInput" />
          <button type="submit">Add</button>
        </form>

    );
  }
}

export default ProjectInput;
<|endoftext|>


<commit_before>const request = require('request');

const _ = require('lodash');
const config = require('../../config');
const moment = require('moment');
const telegram = require('../telegram');
const models = require('../models');

const striptags = require('striptags');

const {
    REFRESH_ARTICLES
} = require('../socket_actions');

// Set moment locale
moment.locale('nl')

function prepareContent(message) {
    return striptags(message.content.replace('
', '\n\n').replace('
', ' * ').replace('
', '\n').replace(' ', ' '), allowed_tags = ['a', 'strong', 'b', 's', 'i', 'u', 'code', 'pre']);
}

module.exports = {
    poll(io) {
        request(`${process.env.API_URI}articles`, (error, response, body) => {
            if (error) {
                telegram.sendMessage('Debug', error);
            }
            try {
                const data = JSON.parse(body).data;
                _.each(data, (article, id) => {
                    let articleType;
                    switch (article.type) {
                        case "news":
                            articleType = config.dbMappings.type.Nieuws;
                            break;
                        case "hint":
                            articleType = config.dbMappings.type.Hint;
                            break;
                        case "assignment":
                            articleType = config.dbMappings.type.Opdracht;
                            break;
                    }

                    const start = isNaN(Date.parse(article.publish_at)) ? null : Date.parse(article.publish_at)
                    const end = isNaN(Date.parse(article.message.end_time)) ? null : Date.parse(article.message.end_time)

                    const message = {
                        id: article.id,
                        title: article.title,
                        content: article.message.content,
                        start,
                        end,
                        points: article.message.max_points || null,
                        ApiTypeId: articleType
                    }

                    models.Api.upsert(message, {
                        returning: true
                    }).then((obj) => {

                        if (obj[1]) {
                            // New object was added, we'll submit a message to telegram
                            const message = obj[0].dataValues

                            switch (article.type) {
                                case "news":
                                    const newsMessage = `<b>${message.title}</b> \n<i>Tijdstip: ${moment(message.start).add(2, 'hours').calendar()}</i> \n${prepareContent(message)}`;
                                    telegram.sendMessage("Nieuws", newsMessage);
                                    break;
                                case "hint":
                                    const hintMessage = `<b>Nieuwe hint</b> \n<i>Tijdstip: ${moment(message.start).add(2, 'hours').calendar()}</i> \nEr is een nieuwe hint binnen, we zijn ermee bezig!`;
                                    telegram.sendMessage('Alpha', hintMessage);
                                    telegram.sendMessage('Bravo', hintMessage);
                                    telegram.sendMessage('Charlie', hintMessage);
                                    telegram.sendMessage('Delta', hintMessage);
                                    telegram.sendMessage('Echo', hintMessage);
                                    telegram.sendMessage('Foxtrot', hintMessage);
                                    break;
                                case "assignment":
                                    const assignmentMessage = `<b>${message.title}</b> \n<i>Deadline: ${moment(message.end).add(2, 'hours').calendar()}</i> \nPunten: ${message.points} \n ${prepareContent(message)}`;
                                    telegram.sendMessage('Opdracht', assignmentMessage);
                                    break;
                            }

                            io.emit(REFRESH_ARTICLES);
                        }
                    });
                });
            } catch (e) {
                console.error(e.message);
            }
        });
    },
};

module.exports.poll()<commit_msg>Catch Jotihunt error<commit_after>const request = require('request');

const _ = require('lodash');
const config = require('../../config');
const moment = require('moment');
const telegram = require('../telegram');
const models = require('../models');

const striptags = require('striptags');

const {
    REFRESH_ARTICLES
} = require('../socket_actions');

// Set moment locale
moment.locale('nl')

function prepareContent(message) {
    return striptags(message.content.replace('
', '\n\n').replace('
', ' * ').replace('
', '\n').replace(' ', ' '), allowed_tags = ['a', 'strong', 'b', 's', 'i', 'u', 'code', 'pre']);
}

module.exports = {
    poll(io) {
        request(`${process.env.API_URI}articles`, (error, response, body) => {
            if (error) {
                telegram.sendMessage('Debug', error);
            }
            try {
                const data = JSON.parse(body).data;
                _.each(data, (article, id) => {
                    let articleType;
                    switch (article.type) {
                        case "news":
                            articleType = config.dbMappings.type.Nieuws;
                            break;
                        case "hint":
                            articleType = config.dbMappings.type.Hint;
                            break;
                        case "assignment":
                            articleType = config.dbMappings.type.Opdracht;
                            break;
                    }

                    const start = isNaN(Date.parse(article.publish_at)) ? null : Date.parse(article.publish_at)
                    const end = isNaN(Date.parse(article.message.end_time)) ? null : Date.parse(article.message.end_time)

                    const message = {
                        id: article.id,
                        title: article.title,
                        content: article.message.content,
                        start,
                        end,
                        points: article.message.max_points || null,
                        ApiTypeId: articleType
                    }

                    models.Api.upsert(message, {
                        returning: true
                    }).then((obj) => {

                        if (obj[1]) {
                            // New object was added, we'll submit a message to telegram
                            const message = obj[0].dataValues

                            switch (article.type) {
                                case "news":
                                    const newsMessage = `<b>${message.title}</b> \n<i>Tijdstip: ${moment(message.start).add(2, 'hours').calendar()}</i> \n${prepareContent(message)}`;
                                    telegram.sendMessage("Nieuws", newsMessage);
                                    break;
                                case "hint":
                                    const hintMessage = `<b>Nieuwe hint</b> \n<i>Tijdstip: ${moment(message.start).add(2, 'hours').calendar()}</i> \nEr is een nieuwe hint binnen, we zijn ermee bezig!`;
                                    telegram.sendMessage('Alpha', hintMessage);
                                    telegram.sendMessage('Bravo', hintMessage);
                                    telegram.sendMessage('Charlie', hintMessage);
                                    telegram.sendMessage('Delta', hintMessage);
                                    telegram.sendMessage('Echo', hintMessage);
                                    telegram.sendMessage('Foxtrot', hintMessage);
                                    break;
                                case "assignment":
                                    const assignmentMessage = `<b>${message.title}</b> \n<i>Deadline: ${moment(message.end).add(2, 'hours').calendar()}</i> \nPunten: ${message.points} \n ${prepareContent(message)}`;
                                    telegram.sendMessage('Opdracht', assignmentMessage);
                                    break;
                            }

                            io.emit(REFRESH_ARTICLES);
                        }
                    }).catch((err) => {
                        console.log(err);
                    });
                });
            } catch (e) {
                console.error(e.message);
            }
        });
    },
};

module.exports.poll()<|endoftext|>


<commit_before>/* fadeer.js
 * This makes the load screen fade in nicely.
 * This prevents falshing
 * I actually need to do the animation in JS
 * Otherwise the loadscreen would fade in and vanish
 * If the load time was under 400ms
 */
var totalTimeStep = 400
var timeSingleStep = 10
var totalSteps = Math.round(totalTimeStep / timeSingleStep)
var opacityStep = Math.round(100 / totalSteps) / 100
window.altboiler_stopStepping = false
function fadeIn () {
  var targetElem = document.getElementById('altboiler_boilerPlateLoader')
  fadeInALittle(targetElem, 0)
}
function fadeInALittle (targetElem, oldOpacity) {
  if(window.altboiler_stopStepping || oldOpacity > 1) return
  newOpacity = targetElem.style.opacity = oldOpacity + opacityStep
  setTimeout(fadeInALittle.bind(null, targetElem, newOpacity), timeSingleStep)
}
setTimeout(fadeIn, 0)

altboiler.loader.onLoad(function stopFadeIn (next) {
  window.altboiler_stopStepping = true
  document.getElementById('altboiler_boilerPlateLoader').style.opacity = 0
  next()
})
<commit_msg>Fix the fader<commit_after>/* fadeer.js
 * This makes the load screen fade in nicely.
 * This prevents falshing
 * I actually need to do the animation in JS
 * Otherwise the loadscreen would fade in and vanish
 * If the load time was under 400ms
 */

var Fader = {
  frameRate: 100,
  time: 1000,
  direction: 1,
  opacity: 0,

  calculateStep: function () {
    this.step = 1 / this.time * this.frameRate
  },

  fade: function () {
    var newOpacity = this.opacity + this.step * this.direction
    if(this.stop || newOpacity < 0 || newOpacity > 1) return
    this.target.style.opacity = this.opacity = newOpacity
    setTimeout(this.fade.bind(this), this.frameRate)
  }
}

var inFader = Object.create(Fader)
inFader.target = document.getElementById('altboiler_boilerPlateLoader')
inFader.calculateStep()
inFader.fade()

altboiler.loader.onLoad(function stopFadeIn (next) {
  var outFader = Object.create(Fader)
  inFader.stop = true
  outFader.opacity = inFader.opacity
  outFader.target = inFader.target
  outFader.direction = -1
  outFader.calculateStep()
  outFader.fade()

  setTimeout(
    next,
    (outFader.time / outFader.opacity)
  )
})
<|endoftext|>


<commit_before>'use strict'

const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
const {STATIC_ORIGIN} = process.env

let assets = {}
let integrity = {}

try {
  const manifest = JSON.parse(fs.readFileSync('public/assets/.manifest.json'))
  assets = manifest.assets
  integrity = manifest.integrity
} catch (error) { }

exports.path = (asset) => path.join(STATIC_ORIGIN || '/', assets[asset] || asset)

exports.integrity = (path) => integrity[path] || ''

exports.version = crypto
  .createHash('sha256')
  .update(JSON.stringify(assets))
  .digest('hex')

exports.digestPath = (asset) => {
  const {dir, name, ext} = path.parse(asset)
  const buffer = fs.readFileSync(path.join('public', asset))
  const digest = crypto.createHash('sha256').update(buffer).digest('hex')
  return path.join('assets', dir, `${name}-${digest + ext}`)
}
<commit_msg>ASSET_VERSION<commit_after>'use strict'

const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
const {ASSET_VERSION, STATIC_ORIGIN} = process.env

let assets = {}
let integrity = {}

try {
  const manifest = JSON.parse(fs.readFileSync('public/assets/.manifest.json'))
  assets = manifest.assets
  integrity = manifest.integrity
} catch (error) { }

exports.path = (asset) => path.join(STATIC_ORIGIN || '/', assets[asset] || asset)

exports.integrity = (path) => integrity[path] || ''

exports.version = crypto
  .createHash('sha256')
  .update(JSON.stringify(assets))
  .digest('hex')

exports.digestPath = (asset) => {
  const {dir, name, ext} = path.parse(asset)
  const buffer = fs.readFileSync(path.join('public', asset))
  const hash = crypto.createHash('sha256').update(buffer)
  if (ASSET_VERSION) hash.update(ASSET_VERSION)
  const digest = hash.digest('hex')
  return path.join('assets', dir, `${name}-${digest + ext}`)
}
<|endoftext|>


<commit_before>$('body').delegate('.menu li a', 'click', function () {
    var $thisLi = $(this).parents('li:first');
    var $ul = $thisLi.parents('ul:first');
    if (!$thisLi.hasClass('active')) {
        $ul.find('li.active').removeClass('active');
        $thisLi.addClass('active');
    }
});<commit_msg>Remove unwanted code<commit_after><|endoftext|>


<commit_before>var doNotTrack = navigator.doNotTrack || navigator.msDoNotTrack || window.doNotTrack;
if (!doNotTrack || doNotTrack === 'no') {
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  if (typeof ga === "function") {
    ga('create', 'UA-49796218-32', 'auto');
    ga('send' ,'pageview');
  }
}
<commit_msg>Fixing dnt (#2019)<commit_after>var doNotTrack = navigator.doNotTrack || navigator.msDoNotTrack || window.doNotTrack;
if (!doNotTrack || doNotTrack === 'no' || doNotTrack === "unspecified") {
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  if (typeof ga === "function") {
    ga('create', 'UA-49796218-32', 'auto');
    ga('send' ,'pageview');
  }
}
<|endoftext|>


<commit_before>/**
 * @file Tfoot component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Tf from '../_Tf';

import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableCalculation from '../_vendors/TableCalculation';

class Tfoot extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    handleClick = e => {
        const {data, disabled, onFootClick} = this.props;
        !disabled && onFootClick && onFootClick(data, e);
    };

    render() {

        const {
                className, columns, data, disabled,
                onCellClick
            } = this.props,

            columnsWithSpan = TableCalculation.getColumnsWithSpan(TableFragment.FOOT, columns);

        return (

                    {
                        columnsWithSpan && columnsWithSpan.map(({column, span}, index) =>
                            <Tf key={index}
                                className={column.footClassName}
                                style={column.footStyle}
                                colIndex={index}
                                data={data}
                                renderer={column.footRenderer}
                                align={column.footAlign}
                                span={span}
                                disabled={disabled}
                                onCellClick={onCellClick}/>
                        )
                    }

        );

    }
}

Tfoot.propTypes = {

    className: PropTypes.string,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in header.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        headRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table.
         * (1) data key，example： 'id'
         * (2) data key tamplate，example：'${id} - ${name}'
         * (3) callback，example：function (rowData, rowIndex, colIndex) {return rowData.id;}
         */
        bodyRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in footer.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        footRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.array,
    disabled: PropTypes.bool,

    onFootClick: PropTypes.func,
    onCellClick: PropTypes.func

};

Tfoot.defaultProps = {
    disabled: false
};

export default Tfoot;
<commit_msg>update Tfoot<commit_after>/**
 * @file Tfoot component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Tf from '../_Tf';

import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableCalculation from '../_vendors/TableCalculation';

class Tfoot extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    handleClick = e => {
        const {data, disabled, onFootClick} = this.props;
        !disabled && onFootClick && onFootClick(data, e);
    };

    render() {

        const {
                className, columns, data, disabled, baseColIndex,
                onCellClick
            } = this.props,

            columnsWithSpan = TableCalculation.getColumnsWithSpan(TableFragment.FOOT, columns);

        return (

                    {
                        columnsWithSpan && columnsWithSpan.map(({column, span}, colIndex) =>
                            <Tf key={colIndex}
                                className={column.footClassName}
                                style={column.footStyle}
                                colIndex={baseColIndex + colIndex}
                                data={data}
                                renderer={column.footRenderer}
                                align={column.footAlign}
                                span={span}
                                disabled={disabled}
                                onCellClick={onCellClick}/>
                        )
                    }

        );

    }
}

Tfoot.propTypes = {

    className: PropTypes.string,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in header.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        headRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table.
         * (1) data key，example： 'id'
         * (2) data key tamplate，example：'${id} - ${name}'
         * (3) callback，example：function (rowData, rowIndex, colIndex) {return rowData.id;}
         */
        bodyRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in footer.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        footRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.array,
    disabled: PropTypes.bool,
    baseColIndex: PropTypes.number,

    onFootClick: PropTypes.func,
    onCellClick: PropTypes.func

};

Tfoot.defaultProps = {
    disabled: false,
    baseColIndex: 0
};

export default Tfoot;
<|endoftext|>


<commit_before>const express = require('express');
const Project = require('../models').Project;
const Errors = require('../lib/errors');

const router = express.Router({ mergeParams: true });

/**
 * @api {get} /projects Get all projects
 * @apiName GetProjects
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  name
 *
 * @apiSuccess  {Object[]}  projects
 * @apiSuccess  {String}    projects._id
 * @apiSuccess  {String}    projects.name
 * @apiSuccess  {Process[]} projects.processes
 * @apiSuccess  {Object[]}  projects.subscribers
 * @apiSuccess  {Boolean}   projects.subscribers.isAdmin
 * @apiSuccess  {User}      projects.subscribers.user
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    const options = {};
    if (req.body.name) {
      options.name = req.body.name;
    }

    Project.find(options)
      .populate(['owner', 'subscribers', 'processes'])
      .then((projects) => {
        res.body = projects;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {get} /projects/:projectId Get specific project
 * @apiName GetProjectId
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiSuccess  {String}    _id
 * @apiSuccess  {String}    name
 * @apiSuccess  {Process[]} processes
 * @apiSuccess  {Object[]}  subscribers
 * @apiSuccess  {Boolean}   subscribers.isAdmin
 * @apiSuccess  {User}      subscribers.user
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/:projectId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Project.findById(req.params.projectId)
      .populate(['owner', 'subscribers', 'processes'])
      .then((project) => {
        res.body = project;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /projects Create a project
 * @apiName PostProject
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  name
 *
 * @apiSuccess  {String}    _id
 * @apiSuccess  {String}    name
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.post('/', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else if (!req.body.name) {
    next(new Errors.Generic('Name required', 400));
  } else {
    const project = new Project({
      name: req.body.name,
      owner: req.session.user._id,
    });
    project.subscribers.push(req.session.user._id);
    project.save()
      .then((newProject) => {
        res.body = newProject;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {put} /projects/:projectId Update a project
 * @apiName PutProjectId
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  projectId
 * @apiParam  {String}  name
 *
 * @apiSuccess  {String}    _id
 * @apiSuccess  {String}    name
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.put('/:projectId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Project.findById(req.params.projectId)
      .then((project) => {
        if (`${project.owner}` !== req.session.user._id) {
          return Promise.reject(new Errors.Unauthorized());
        }
        project.name = req.body.name || project.name;
        project.owner = req.body.owner || project.owner;
        return project.save();
      })
      .then((response) => {
        res.body = response;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {delete} /projects/:projectId Delete a project
 * @apiName DeleteProjectId
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  projectId
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.delete('/:projectId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Project.findById(req.params.projectId)
      .then((project) => {
        if (project.owner !== req.session.user._id) {
          return Promise.reject(new Errors.Unauthorized());
        }
        return project.remove();
      })
      .then(() => {
        res.status(204);
        next();
      })
      .catch(next);
  }
});

module.exports = router;

<commit_msg>Missing projectId<commit_after>const express = require('express');
const Project = require('../models').Project;
const Errors = require('../lib/errors');

const router = express.Router({ mergeParams: true });

/**
 * @api {get} /projects Get all projects
 * @apiName GetProjects
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  name
 *
 * @apiSuccess  {Object[]}  projects
 * @apiSuccess  {String}    projects._id
 * @apiSuccess  {String}    projects.name
 * @apiSuccess  {Process[]} projects.processes
 * @apiSuccess  {Object[]}  projects.subscribers
 * @apiSuccess  {Boolean}   projects.subscribers.isAdmin
 * @apiSuccess  {User}      projects.subscribers.user
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    const options = {};
    if (req.body.name) {
      options.name = req.body.name;
    }

    Project.find(options)
      .populate(['owner', 'subscribers', 'processes'])
      .then((projects) => {
        res.body = projects;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {get} /projects/:projectId Get specific project
 * @apiName GetProjectId
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  projectId
 *
 * @apiSuccess  {String}    _id
 * @apiSuccess  {String}    name
 * @apiSuccess  {Process[]} processes
 * @apiSuccess  {Object[]}  subscribers
 * @apiSuccess  {Boolean}   subscribers.isAdmin
 * @apiSuccess  {User}      subscribers.user
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.get('/:projectId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Project.findById(req.params.projectId)
      .populate(['owner', 'subscribers', 'processes'])
      .then((project) => {
        res.body = project;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {post} /projects Create a project
 * @apiName PostProject
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  name
 *
 * @apiSuccess  {String}    _id
 * @apiSuccess  {String}    name
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.post('/', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else if (!req.body.name) {
    next(new Errors.Generic('Name required', 400));
  } else {
    const project = new Project({
      name: req.body.name,
      owner: req.session.user._id,
    });
    project.subscribers.push(req.session.user._id);
    project.save()
      .then((newProject) => {
        res.body = newProject;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {put} /projects/:projectId Update a project
 * @apiName PutProjectId
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  projectId
 * @apiParam  {String}  name
 *
 * @apiSuccess  {String}    _id
 * @apiSuccess  {String}    name
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.put('/:projectId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Project.findById(req.params.projectId)
      .then((project) => {
        if (`${project.owner}` !== req.session.user._id) {
          return Promise.reject(new Errors.Unauthorized());
        }
        project.name = req.body.name || project.name;
        project.owner = req.body.owner || project.owner;
        return project.save();
      })
      .then((response) => {
        res.body = response;
        next();
      })
      .catch(next);
  }
});

/**
 * @api {delete} /projects/:projectId Delete a project
 * @apiName DeleteProjectId
 * @apiGroup Projects
 * @apiVersion 0.1.0
 *
 * @apiParam  {String}  projectId
 *
 * @apiUse UnauthorizedError
 *
 * @apiPermission user
 */
router.delete('/:projectId', (req, res, next) => {
  if (!req.session.user) {
    next(new Errors.Unauthorized());
  } else {
    Project.findById(req.params.projectId)
      .then((project) => {
        if (project.owner !== req.session.user._id) {
          return Promise.reject(new Errors.Unauthorized());
        }
        return project.remove();
      })
      .then(() => {
        res.status(204);
        next();
      })
      .catch(next);
  }
});

module.exports = router;

<|endoftext|>


<commit_before>var util = require('../lib/util'),
    Project = require('../models/projects').Project,
    Event = require('../models/projects').Event;

module.exports.index = function (req, res, next) {
    Project.find().exec(function (err, projects) {
        if (err) {
            return next(err);
        }
        res.format({
            json: function () {
                res.json(200, projects);
            },
            html: function () {
                res.render('projects/index', {
                    projects: projects
                });
            }
        });
    });
};

module.exports.create_project = function (req, res, next) {
    var title = req.body.title,
        tag = req.body.tag,
        private_mdtext = req.body.private_mdtext,
        public_mdtext = req.body.public_mdtext,
        start = req.body.start,
        end = req.body.end;

    var project = new Project();
    project.title = title;
    project.tag = tag;
    project.private_mdtext = private_mdtext;
    project.public_mdtext = public_mdtext;
    project.start = req.body.start;
    project.end = req.body.end;

    project.save(function (err) {
        if (err) { return next(err); }
        res.format({
            json: function () {
                res.json(200, project);
            },
            html: function () {
                res.redirect('/projects/' + util.h2b64(project.id));
            }
        });
    });
};

module.exports.delete_project = function (req, res, next) {
    var id = req.params.id;

    Project.findByIdAndRemove(id, function (err, project) {
        if (err) { return next(err); }
        res.json(200, project);
    });
};

module.exports.project = function (req, res, next) {
    var id = util.b642h(req.params.id);

    Project.findById(id, function (err, project) {
        if (err) { return next(err); }
        Event.find({tags: project.tag}, function (err, events) {
            project.events = events;
            res.format({
                json: function () {
                    res.json(200, project);
                },
                html: function () {
                    res.render('projects/project', {
                        project: project
                    });
                }
            });
        });
    });
};

module.exports.project_create_event = function (req, res, next) {
    var id = req.params.id,
        title = req.body.title,
        location = req.body.location,
        start = req.body.start,
        end = req.body.end;

    Project.findById(id, function (err, project) {
        if (err) { return next(err); }

        var event = new Event();
        event.tags = [project.tag];
        event.title = title;
        event.location = location;
        event.start = start;
        event.end = end;

        event.save(function (err) {
            if (err) { return next(err); }
            res.format({
                json: function () {
                    res.json(200, event);
                },
                html: function () {
                    req.flash('success', 'Aktiviteten ble lagret');
                    res.redirect('/projects/' + util.h2b64(project.id));
                }
            });
        });
    });
};

// TODO: Only hide. Or remove project tag. Or ask.
module.exports.project_delete_event = function (req, res, next) {
    var event_id = req.params.event_id;
    Event.findByIdAndRemove(event_id, function (err, event) {
        if (err) { return next(err); }
        res.json(200, event);
    });
};
<commit_msg>Usernames are very handy<commit_after>var util = require('../lib/util'),
    Project = require('../models/projects').Project,
    Event = require('../models/projects').Event;

module.exports.index = function (req, res, next) {
    Project.find().exec(function (err, projects) {
        if (err) {
            return next(err);
        }
        res.format({
            json: function () {
                res.json(200, projects);
            },
            html: function () {
                res.render('projects/index', {
                    projects: projects
                });
            }
        });
    });
};

module.exports.create_project = function (req, res, next) {
    var title = req.body.title,
        tag = req.body.tag,
        private_mdtext = req.body.private_mdtext,
        public_mdtext = req.body.public_mdtext,
        start = req.body.start,
        end = req.body.end;

    var project = new Project();
    project.title = title;
    project.tag = tag;
    project.private_mdtext = private_mdtext;
    project.public_mdtext = public_mdtext;
    project.start = req.body.start;
    project.end = req.body.end;
    project.creator = req.user;

    project.save(function (err) {
        if (err) { return next(err); }
        res.format({
            json: function () {
                res.json(200, project);
            },
            html: function () {
                res.redirect('/projects/' + util.h2b64(project.id));
            }
        });
    });
};

module.exports.delete_project = function (req, res, next) {
    var id = req.params.id;

    Project.findByIdAndRemove(id, function (err, project) {
        if (err) { return next(err); }
        res.json(200, project);
    });
};

module.exports.project = function (req, res, next) {
    var id = util.b642h(req.params.id);

    Project.findById(id, function (err, project) {
        if (err) { return next(err); }
        Event.find({tags: project.tag}, function (err, events) {
            project.events = events;
            res.format({
                json: function () {
                    res.json(200, project);
                },
                html: function () {
                    res.render('projects/project', {
                        project: project
                    });
                }
            });
        });
    });
};

module.exports.project_create_event = function (req, res, next) {
    var id = req.params.id,
        title = req.body.title,
        location = req.body.location,
        start = req.body.start,
        end = req.body.end;

    Project.findById(id, function (err, project) {
        if (err) { return next(err); }

        var event = new Event();
        event.tags = [project.tag];
        event.title = title;
        event.location = location;
        event.start = start;
        event.end = end;
        event.creator = req.user;

        event.save(function (err) {
            if (err) { return next(err); }
            res.format({
                json: function () {
                    res.json(200, event);
                },
                html: function () {
                    req.flash('success', 'Aktiviteten ble lagret');
                    res.redirect('/projects/' + util.h2b64(project.id));
                }
            });
        });
    });
};

// TODO: Only hide. Or remove project tag. Or ask.
module.exports.project_delete_event = function (req, res, next) {
    var event_id = req.params.event_id;
    Event.findByIdAndRemove(event_id, function (err, event) {
        if (err) { return next(err); }
        res.json(200, event);
    });
};
<|endoftext|>


<commit_before>Andamio.View = Backbone.View.extend({
  constructor: function () {
    _.bindAll(this);
    if (this.model) {
      this.model = new this.model;
    }
    Backbone.View.apply(this, arguments);
  },

  render: function () {
    this.isClosed = false;

    var data = this._serializeData();
    this.$el.html(this.template(data));

    this._bindRegions();
    this._bindUIElements();

    if (_.isFunction(this.afterRender)) {
      this.afterRender();
    }

    return this;
  },

  _serializeData: function () {
    return this.model ? this.model.toJSON() : this.collection ? {items: this.collection.toJSON()} : {};
  },

  _bindRegions: function () {
    var view = this;
    var $regions = view.$('[data-region]');

    if (!$regions.length) {
      return;
    }

    // regions hash
    view.regions = {};

    // populate regions hash
    $regions.each(function (i, el) {
      var $el = $(el);
      var key = $el.attr('data-region');
      var Subview = view.subviews[key];
      // manage a new region
      view.regions[key] = new Andamio.Region({$el: $el});
      // find subview match to set the region
      if (Subview && _.isFunction(Subview)) {
        view.subviews[key] = new Subview({el: $el});
      } else if (Subview) {
        Subview.setElement($el).render();
      }
    });
  },

  _unbindRegions: function () {
    if (!this.regions) {
      return;
    }

    // delete region bindings
    this._deleteProp('regions');
  },

  _bindUIElements: function () {
    if (!this.ui) {
      return;
    }

    if (!this._ui) {
      this._ui = this.ui;
    }

    this.ui = {};

    _.each(_.keys(this._ui), function (key) {
      this.ui[key] = this.$(this._ui[key]);
    }, this);
  },

  // this method unbinds the elements specified in the "ui" hash
  _unbindUIElements: function () {
    if (!this.ui) {
      return;
    }

    this._deleteProp('ui');
    this.ui = this._ui;
    delete this._ui;
  },

  _removeSubviews: function () {
    if (!this.subviews) {
      return;
    }
    _.invoke(this.subviews, 'close');
    this._deleteProp('subviews');
  },

  // clean up the view and remove from DOM
  close: function () {
    if (this.isClosed) {
      return;
    }
    this.isClosed = true;

    // remove subviews
    this._removeSubviews();
    // unbind regions and ui
    this._unbindRegions();
    this._unbindUIElements();

    // call backbone's remove
    this.remove();
  },

  // override Backbone's delegateEvents to bind model and collection events
  delegateEvents: function (events) {
    Andamio.bindEvents(this, this.model, this.modelEvents);
    Andamio.bindEvents(this, this.collection, this.collectionEvents);
    Backbone.View.prototype.delegateEvents.call(this, events);
  },

  // override Backbone's undelegateEvents to unbind model and collection events
  undelegateEvents: function () {
    Backbone.View.prototype.undelegateEvents.apply(this, arguments);
    Andamio.unbindEvents(this, this.model, this.modelEvents);
    Andamio.unbindEvents(this, this.collection, this.collectionEvents);
  },

  // helper method to correctly delete properties
  _deleteProp: function (prop) {
    var obj = this[prop];
    _.each(obj, function (item, name) {
      delete obj[name];
    }, this);
    delete this[prop];
  }
});
<commit_msg>fix delegateEvents initialization order, auto-create a collection if specified<commit_after>Andamio.View = Backbone.View.extend({
  constructor: function () {
    _.bindAll(this);
    if (this.model) {
      this.model = new this.model;
    }
    if (this.collection) {
      this.collection = new this.collection;
    }
    Backbone.View.apply(this, arguments);
  },

  render: function () {
    this.isClosed = false;

    var data = this._serializeData();
    this.$el.html(this.template(data));

    this._bindRegions();
    this._bindUIElements();

    if (_.isFunction(this.afterRender)) {
      this.afterRender();
    }

    return this;
  },

  _serializeData: function () {
    return this.model ? this.model.toJSON() : this.collection ? {items: this.collection.toJSON()} : {};
  },

  _bindRegions: function () {
    var view = this;
    var $regions = view.$('[data-region]');

    if (!$regions.length) {
      return;
    }

    // regions hash
    view.regions = {};

    // populate regions hash
    $regions.each(function (i, el) {
      var $el = $(el);
      var key = $el.attr('data-region');
      var Subview = view.subviews[key];
      // manage a new region
      view.regions[key] = new Andamio.Region({$el: $el});
      // find subview match to set the region
      if (Subview && _.isFunction(Subview)) {
        view.subviews[key] = new Subview({el: $el});
      } else if (Subview) {
        Subview.setElement($el).render();
      }
    });
  },

  _unbindRegions: function () {
    if (!this.regions) {
      return;
    }

    // delete region bindings
    this._deleteProp('regions');
  },

  _bindUIElements: function () {
    if (!this.ui) {
      return;
    }

    if (!this._ui) {
      this._ui = this.ui;
    }

    this.ui = {};

    _.each(_.keys(this._ui), function (key) {
      this.ui[key] = this.$(this._ui[key]);
    }, this);
  },

  // this method unbinds the elements specified in the "ui" hash
  _unbindUIElements: function () {
    if (!this.ui) {
      return;
    }

    this._deleteProp('ui');
    this.ui = this._ui;
    delete this._ui;
  },

  _removeSubviews: function () {
    if (!this.subviews) {
      return;
    }
    _.invoke(this.subviews, 'close');
    this._deleteProp('subviews');
  },

  // clean up the view and remove from DOM
  close: function () {
    if (this.isClosed) {
      return;
    }
    this.isClosed = true;

    // remove subviews
    this._removeSubviews();
    // unbind regions and ui
    this._unbindRegions();
    this._unbindUIElements();

    // call backbone's remove
    this.remove();
  },

  // override Backbone's delegateEvents to bind model and collection events
  delegateEvents: function (events) {
    Backbone.View.prototype.delegateEvents.call(this, events);
    Andamio.bindEvents(this, this.model, this.modelEvents);
    Andamio.bindEvents(this, this.collection, this.collectionEvents);
  },

  // override Backbone's undelegateEvents to unbind model and collection events
  undelegateEvents: function () {
    Backbone.View.prototype.undelegateEvents.apply(this, arguments);
    Andamio.unbindEvents(this, this.model, this.modelEvents);
    Andamio.unbindEvents(this, this.collection, this.collectionEvents);
  },

  // helper method to correctly delete properties
  _deleteProp: function (prop) {
    var obj = this[prop];
    _.each(obj, function (item, name) {
      delete obj[name];
    }, this);
    delete this[prop];
  }
});
<|endoftext|>