<commit_before>// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode');
const _ = require('lodash');

const findDiagram = require('./find-diagram');

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
function activate(context) {
    class MermaidDocumentContentProvider {
        constructor () {
            this._onDidChange =  new vscode.EventEmitter();
            this.graph = '';
            this.update = _.throttle(this.unthrottledUpdate, 250);
        }

        provideTextDocumentContent (uri, token) {
            const config = JSON.stringify(vscode.workspace.getConfiguration('mermaid'));

            return `<!DOCTYPE html>

                ${this.graph}

            `;
        }

        get onDidChange () {
            return this._onDidChange.event;
        }

        unthrottledUpdate (uri) {
            const editor = vscode.window.activeTextEditor;
            const text = editor.document.getText();
            const selStart = editor.document.offsetAt(editor.selection.anchor);

            const graph = findDiagram(text, selStart);

            if (graph) {
                this.graph = graph;
            } else {
                console.log("Cannot determine the rule's properties.");
                this.graph = 'select a diagram...'
            }

            this._onDidChange.fire(uri);
        }
    }

    const registerCommand = vscode.commands.registerCommand;
    let previewUri = vscode.Uri.parse('mermaid-preview://authority/mermaid-preview');

    let provider = new MermaidDocumentContentProvider();
    let registration = vscode.workspace.registerTextDocumentContentProvider('mermaid-preview', provider);

    // Use the console to output diagnostic information (console.log) and errors (console.error)
    // This line of code will only be executed once when your extension is activated
    console.log('Congratulations, your extension "mermaid-preview" is now active!');

    // The command has been defined in the package.json file
    // Now provide the implementation of the command with  registerCommand
    // The commandId parameter must match the command field in package.json
    let disposable = registerCommand('extension.previewMermaidDiagram', () => {
        return vscode.commands.executeCommand('vscode.previewHtml', previewUri, vscode.ViewColumn.Two, 'Mermaid Preview').then((success) => {
        }, (reason) => {
            vscode.window.showErrorMessage(reason);
        });
    });

    vscode.workspace.onDidChangeTextDocument((e) => {
        if (e.document === vscode.window.activeTextEditor.document) {
            provider.update(previewUri);
        }
    });

    vscode.window.onDidChangeTextEditorSelection((e) => {
        if (e.textEditor === vscode.window.activeTextEditor) {
            provider.update(previewUri);
        }
    });

    context.subscriptions.push(disposable, registration);
}
exports.activate = activate;

// this method is called when your extension is deactivated
function deactivate() {
}
exports.deactivate = deactivate;<commit_msg>refactored content provider class and html<commit_after>// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode');
const _ = require('lodash');

const findDiagram = require('./find-diagram');

class MermaidDocumentContentProvider {
    constructor (context) {
        this._onDidChange =  new vscode.EventEmitter();
        this.graph = '';
        this.update = _.throttle(this.unthrottledUpdate, 250);

        this.context = context;
    }

    provideTextDocumentContent (uri, token) {
        const config = JSON.stringify(vscode.workspace.getConfiguration('mermaid'));

        return `<!DOCTYPE html>

            ${this.graph}

        `;
    }

    get onDidChange () {
        return this._onDidChange.event;
    }

    unthrottledUpdate (uri) {
        const editor = vscode.window.activeTextEditor;
        const text = editor.document.getText();
        const selStart = editor.document.offsetAt(editor.selection.anchor);

        const graph = findDiagram(text, selStart);

        if (graph) {
            this.graph = graph;
        } else {
            console.log("Cannot determine the rule's properties.");
            this.graph = 'select a diagram...'
        }

        this._onDidChange.fire(uri);
    }
}

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
function activate(context) {
    const registerCommand = vscode.commands.registerCommand;
    let previewUri = vscode.Uri.parse('mermaid-preview://authority/mermaid-preview');

    let provider = new MermaidDocumentContentProvider(context);
    let registration = vscode.workspace.registerTextDocumentContentProvider('mermaid-preview', provider);

    // Use the console to output diagnostic information (console.log) and errors (console.error)
    // This line of code will only be executed once when your extension is activated
    console.log('Congratulations, your extension "mermaid-preview" is now active!');

    // The command has been defined in the package.json file
    // Now provide the implementation of the command with  registerCommand
    // The commandId parameter must match the command field in package.json
    let disposable = registerCommand('extension.previewMermaidDiagram', () => {
        return vscode.commands.executeCommand('vscode.previewHtml', previewUri, vscode.ViewColumn.Two, 'Mermaid Preview').then((success) => {
        }, (reason) => {
            vscode.window.showErrorMessage(reason);
        });
    });

    vscode.workspace.onDidChangeTextDocument((e) => {
        if (e.document === vscode.window.activeTextEditor.document) {
            provider.update(previewUri);
        }
    });

    vscode.window.onDidChangeTextEditorSelection((e) => {
        if (e.textEditor === vscode.window.activeTextEditor) {
            provider.update(previewUri);
        }
    });

    context.subscriptions.push(disposable, registration);
}
exports.activate = activate;

// this method is called when your extension is deactivated
function deactivate() {
}
exports.deactivate = deactivate;<|endoftext|>


<commit_before>/**
 * Slidy main file
 */

/* global Modernizr */

require('./vendor/modernizr-touch');

const Emitter = require('tiny-emitter');
const Hammer = require('hammerjs');
const bind = require('lodash/bind');
const debounce = require('lodash/debounce');
const forEach = require('lodash/forEach');

import { Controls } from './Controls';
import { Nav } from './Nav';
import { Queue } from './Queue';

export class Slidy {

  /**
   * Slidy constructor
   * @param  {HTMLElement|string} el - Slider container (element or selector)
   * @param  {Object} opts - Configuration settings
   */
  constructor(el, opts) {
    // Check and get element(s)
    if (typeof el === 'string') {
      el = document.querySelectorAll(el);
    }

    if (!el || el.length === 0) {
      console.error('Slidy: no element matching!');
      return;
    }

    if (el.length > 1) {
      console.warn('Slidy: multiple elements matching!');
    }

    this._el = el[0];

    // Check and get options
    this._opts = Object.assign({
      auto: false, // Boolean: start slider automaticaly
      click: true, // Boolean: enable click on slider
      controls: false, // Boolean: create prev/next buttons
      height: 'auto', // Mixed: integer (px) or 'auto'
      index: 0, // Integer: initial index
      interval: 2000, // Integer: time between 2 transitions
      nav: false, // Boolean: create navigation
      pause: true, // Boolean: pause on hover
      swipe: false, // Boolean: enable swipe
      tap: false, // Boolean: enable tap
      touch: false, // Boolean: enable BOTH tap/swipe (deprecated)
      transition: null,
    }, opts);

    if (this._opts.transition === null) {
      console.error('Slidy: you should define a transition!');
      return;
    }

    if (this._opts.touch) {
      this._opts.swipe = true;
      this._opts.tap = true;
    }

    this._currentIndex = this._opts.index;
    this._newIndex = this._currentIndex;
    this._oldIndex = this._oldIndex;
    this._items = this._el.children;
    this._length = this._items.length;

    this._dispatcher = new Emitter();
    // Public events
    this._dispatcher.on('beforeInit', () => {
      this.beforeInit();
    });
    this._dispatcher.on('afterInit', () => {
      this.afterInit();
    });
    this._dispatcher.on('beforeSlide', (direction) => {
      this.beforeSlide(direction);
    });
    this._dispatcher.on('afterSlide', (direction) => {
      this.afterSlide(direction);
    });

    this.init();
    this.bind();
  }

  /**
   * Getters/setters
   */
  get outer() {
    return this._outer;
  }

  get el() {
    return this._el;
  }

  get items() {
    return this._items;
  }

  get currentIndex() {
    return this._currentIndex;
  }

  set currentIndex(i) {
    this._currentIndex = i;
  }

  get newIndex() {
    return this._newIndex;
  }

  set newIndex(i) {
    this._newIndex = i;
  }

  get oldIndex() {
    return this._oldIndex;
  }

  set oldIndex(i) {
    this._oldIndex = i;
  }

  get options() {
    return this._opts;
  }

  get dispatcher() {
    return this._dispatcher;
  }

  /**
   * Init & binding
   */
  init() {
    this._dispatcher.emit('beforeInit');

    // Add HTML wrapper
    this._outer = document.createElement('div');
    this._el.before(this._outer);
    this._outer.append(this._el);

    // Add CSS classes
    this._outer.classList.add('slidy-outer');
    this._el.classList.add('slidy');
    forEach(this._items, (slide) => {
      slide.classList.add('slidy__item');
    });

    if (this._opts.click) {
      this._el.style.cursor = 'pointer';
    }

    this._queue = new Queue(this, this._opts.transition);

    // Add controls
    if (this._opts.controls) {
      this._controls = new Controls(this);
    }

    // Add nav
    if (this._opts.nav) {
      this._nav = new Nav(this);
    }

    if (this._opts.height !== 'auto') {
      this._el.style.height = this._opts.height + 'px';
    } else {
      this.reset();
    }

    if (this._opts.auto) {
      setTimeout(this.start.bind(this), this._opts.interval);
    }

    this._dispatcher.emit('afterInit');
  }

  bind() {
    this.onEnter = this.enter.bind(this);
    this.onLeave = this.leave.bind(this);
    this.onClick = this.click.bind(this);
    this.onTap = this.tap.bind(this);
    this.onSwipe = this.swipe.bind(this);
    this.onResize = bind(debounce(this.resize, 100), this);

    window.addEventListener('resize', this.onResize);

    if (this._opts.pause && this._opts.auto) {
      this._el.addEventListener('mouseenter', this.onEnter);
    }

    if (this._opts.click && !Modernizr.touchevents) {
      this._el.addEventListener('click', this.onClick);
    }

    if ((this._opts.tap || this._opts.swipe) && Modernizr.touchevents) {
      const options = {
        recognizers: [],
      };
      this._mc = new Hammer.Manager(this._el, options);
    }

    if (this._opts.tap && Modernizr.touchevents) {
      let tap = new Hammer.Tap();
      this._mc.add(tap);
      this._mc.on('tap', this.onTap);
    }

    if (this._opts.swipe && Modernizr.touchevents) {
      let swipe = new Hammer.Swipe({ direction: Hammer.DIRECTION_HORIZONTAL });
      this._mc.add(swipe);
      this._mc.on('swipeleft swiperight', this.onSwipe);
    }
  }

  /**
   * API
   */

  /**
   * Previous, next or "byIndex" navigation
   */
  slidePrev() {
    let newIndex = this._currentIndex - 1;
    if (newIndex < 0) {
      newIndex = this._length - 1;
    }
    this.slide('prev');
  }

  slideNext() {
    let newIndex = this._currentIndex + 1;
    if (newIndex === this._length) {
      newIndex = 0;
    }
    this.slide('next');
  }

  slideTo(index) {
    this.slide('to', index);
  }

  slide(move, index = null) {
    this._queue.add(move, index);
  }

  /**
   * Height calculation if auto.
   * Called on 'init' and 'resize'
   */
  reset() {
    if (this._opts.height === 'auto') {
      this._el.style.height = this._items[0].offsetHeight + 'px';
    }
  }

  /**
   * Start autoplay
   * Enabled via "auto" and used by "pause" options
   */
  start() {
    this.slideNext();
    this._t = setInterval(this.slideNext.bind(this), this._opts.interval);
  }

  /**
   * Pause autoplay
   * Used by "pause" options
   */
  stop() {
    clearInterval(this._t);
  }

  destroy() {
    // Remove interval
    this.stop();

    // Empty queue
    this._queue.empty();

    // Remove listeners
    window.removeEventListener('resize', this.onResize);
    this._el.removeEventListener('mouseenter', this.onEnter);
    this._el.removeEventListener('mouseleave', this.onLeave);
    this._el.removeEventListener('click', this.onClick);

    // Remove Hammer.manager
    if (this._mc) {
      this._mc.destroy();
    }

    // Remove controls
    if (this._controls) {
      this._controls.destroy();
    }

    // Remove nav
    if (this._nav) {
      this._nav.destroy();
    }

    // Remove HTML wrapper
    this._outer.before(this._el);
    this._outer.parentNode.removeChild(this._outer);

    // Remove CSS classes
    this._el.classList.remove('slidy');
    forEach(this._items, (slide) => {
      slide.classList.remove('slidy__item');
      slide.removeAttribute('style');
      forEach(slide.children, (child) => {
        child.removeAttribute('style');
      });
    });

    this._el.removeAttribute('style');
  }

  /**
   * Events
   */

  /**
   * RWD reset
   * Mainly for height…
   */
  resize() {
    this.reset();
  }

  /**
   * Click on slider to go to the next slide
   * Enabled via "click" option,
   */
  click() {
    this.slideNext();
  }

  /**
   * Same as click but for touch devices
   * Enabled via "touch" option
   */
  tap() {
    this.slideNext();
  }

  /**
   * Complement gesture for "tap"
   * Enabled via "touch" option
   */
  swipe(e) {
    if (e.direction === Hammer.DIRECTION_LEFT) {
      this.slideNext();
    }
    if (e.direction === Hammer.DIRECTION_RIGHT) {
      this.slidePrev();
    }
  }

  /**
   * Play/pause on hover
   * Enabled via "auto" + "pause" options
   */
  enter() {
    this._el.removeEventListener('mouseenter', this.onEnter);
    this.stop();
    this._el.addEventListener('mouseleave', this.onLeave);
  }

  leave() {
    this._el.removeEventListener('mouseleave', this.onLeave);
    this.start();
    this._el.addEventListener('mouseenter', this.onEnter);
  }

  /**
   * Callbacks
   */

  beforeInit() {
    if (this._opts.beforeInit) {
      this._opts.beforeInit.call(this, this._el);
    }
  }

  afterInit() {
    if (this._opts.afterInit) {
      this._opts.afterInit.call(this, this._el);
    }
  }

  beforeSlide(direction) {
    if (this._opts.beforeSlide) {
      this._opts.beforeSlide.call(
        this,
        this.currentIndex,
        this.newIndex,
        direction
      );
    }
  }

  afterSlide(direction) {
    if (this._opts.afterSlide) {
      this._opts.afterSlide.call(
        this,
        this.currentIndex,
        this.oldIndex,
        direction
      );
    }
  }
}
<commit_msg>:bug: bugfix when passing a DOM element<commit_after>/**
 * Slidy main file
 */

/* global Modernizr */

require('./vendor/modernizr-touch');

const Emitter = require('tiny-emitter');
const Hammer = require('hammerjs');
const bind = require('lodash/bind');
const debounce = require('lodash/debounce');
const forEach = require('lodash/forEach');

import { Controls } from './Controls';
import { Nav } from './Nav';
import { Queue } from './Queue';

export class Slidy {

  /**
   * Slidy constructor
   * @param  {HTMLElement|string} el - Slider container (element or selector)
   * @param  {Object} opts - Configuration settings
   */
  constructor(el, opts) {
    // Check and get element(s)
    if (typeof el === 'string') {
      el = document.querySelectorAll(el);
    }

    if (!el || el.length === 0) {
      console.error('Slidy: no element matching!');
      return;
    }

    if (el.length > 1) {
      console.warn('Slidy: multiple elements matching!');
    }

    this._el = el[0] || el;

    // Check and get options
    this._opts = Object.assign({
      auto: false, // Boolean: start slider automaticaly
      click: true, // Boolean: enable click on slider
      controls: false, // Boolean: create prev/next buttons
      height: 'auto', // Mixed: integer (px) or 'auto'
      index: 0, // Integer: initial index
      interval: 2000, // Integer: time between 2 transitions
      nav: false, // Boolean: create navigation
      pause: true, // Boolean: pause on hover
      swipe: false, // Boolean: enable swipe
      tap: false, // Boolean: enable tap
      touch: false, // Boolean: enable BOTH tap/swipe (deprecated)
      transition: null,
    }, opts);

    if (this._opts.transition === null) {
      console.error('Slidy: you should define a transition!');
      return;
    }

    if (this._opts.touch) {
      this._opts.swipe = true;
      this._opts.tap = true;
    }

    this._currentIndex = this._opts.index;
    this._newIndex = this._currentIndex;
    this._oldIndex = this._oldIndex;
    this._items = this._el.children;
    this._length = this._items.length;

    this._dispatcher = new Emitter();
    // Public events
    this._dispatcher.on('beforeInit', () => {
      this.beforeInit();
    });
    this._dispatcher.on('afterInit', () => {
      this.afterInit();
    });
    this._dispatcher.on('beforeSlide', (direction) => {
      this.beforeSlide(direction);
    });
    this._dispatcher.on('afterSlide', (direction) => {
      this.afterSlide(direction);
    });

    this.init();
    this.bind();
  }

  /**
   * Getters/setters
   */
  get outer() {
    return this._outer;
  }

  get el() {
    return this._el;
  }

  get items() {
    return this._items;
  }

  get currentIndex() {
    return this._currentIndex;
  }

  set currentIndex(i) {
    this._currentIndex = i;
  }

  get newIndex() {
    return this._newIndex;
  }

  set newIndex(i) {
    this._newIndex = i;
  }

  get oldIndex() {
    return this._oldIndex;
  }

  set oldIndex(i) {
    this._oldIndex = i;
  }

  get options() {
    return this._opts;
  }

  get dispatcher() {
    return this._dispatcher;
  }

  /**
   * Init & binding
   */
  init() {
    this._dispatcher.emit('beforeInit');

    // Add HTML wrapper
    this._outer = document.createElement('div');
    this._el.before(this._outer);
    this._outer.append(this._el);

    // Add CSS classes
    this._outer.classList.add('slidy-outer');
    this._el.classList.add('slidy');
    forEach(this._items, (slide) => {
      slide.classList.add('slidy__item');
    });

    if (this._opts.click) {
      this._el.style.cursor = 'pointer';
    }

    this._queue = new Queue(this, this._opts.transition);

    // Add controls
    if (this._opts.controls) {
      this._controls = new Controls(this);
    }

    // Add nav
    if (this._opts.nav) {
      this._nav = new Nav(this);
    }

    if (this._opts.height !== 'auto') {
      this._el.style.height = this._opts.height + 'px';
    } else {
      this.reset();
    }

    if (this._opts.auto) {
      setTimeout(this.start.bind(this), this._opts.interval);
    }

    this._dispatcher.emit('afterInit');
  }

  bind() {
    this.onEnter = this.enter.bind(this);
    this.onLeave = this.leave.bind(this);
    this.onClick = this.click.bind(this);
    this.onTap = this.tap.bind(this);
    this.onSwipe = this.swipe.bind(this);
    this.onResize = bind(debounce(this.resize, 100), this);

    window.addEventListener('resize', this.onResize);

    if (this._opts.pause && this._opts.auto) {
      this._el.addEventListener('mouseenter', this.onEnter);
    }

    if (this._opts.click && !Modernizr.touchevents) {
      this._el.addEventListener('click', this.onClick);
    }

    if ((this._opts.tap || this._opts.swipe) && Modernizr.touchevents) {
      const options = {
        recognizers: [],
      };
      this._mc = new Hammer.Manager(this._el, options);
    }

    if (this._opts.tap && Modernizr.touchevents) {
      let tap = new Hammer.Tap();
      this._mc.add(tap);
      this._mc.on('tap', this.onTap);
    }

    if (this._opts.swipe && Modernizr.touchevents) {
      let swipe = new Hammer.Swipe({ direction: Hammer.DIRECTION_HORIZONTAL });
      this._mc.add(swipe);
      this._mc.on('swipeleft swiperight', this.onSwipe);
    }
  }

  /**
   * API
   */

  /**
   * Previous, next or "byIndex" navigation
   */
  slidePrev() {
    let newIndex = this._currentIndex - 1;
    if (newIndex < 0) {
      newIndex = this._length - 1;
    }
    this.slide('prev');
  }

  slideNext() {
    let newIndex = this._currentIndex + 1;
    if (newIndex === this._length) {
      newIndex = 0;
    }
    this.slide('next');
  }

  slideTo(index) {
    this.slide('to', index);
  }

  slide(move, index = null) {
    this._queue.add(move, index);
  }

  /**
   * Height calculation if auto.
   * Called on 'init' and 'resize'
   */
  reset() {
    if (this._opts.height === 'auto') {
      this._el.style.height = this._items[0].offsetHeight + 'px';
    }
  }

  /**
   * Start autoplay
   * Enabled via "auto" and used by "pause" options
   */
  start() {
    this.slideNext();
    this._t = setInterval(this.slideNext.bind(this), this._opts.interval);
  }

  /**
   * Pause autoplay
   * Used by "pause" options
   */
  stop() {
    clearInterval(this._t);
  }

  destroy() {
    // Remove interval
    this.stop();

    // Empty queue
    this._queue.empty();

    // Remove listeners
    window.removeEventListener('resize', this.onResize);
    this._el.removeEventListener('mouseenter', this.onEnter);
    this._el.removeEventListener('mouseleave', this.onLeave);
    this._el.removeEventListener('click', this.onClick);

    // Remove Hammer.manager
    if (this._mc) {
      this._mc.destroy();
    }

    // Remove controls
    if (this._controls) {
      this._controls.destroy();
    }

    // Remove nav
    if (this._nav) {
      this._nav.destroy();
    }

    // Remove HTML wrapper
    this._outer.before(this._el);
    this._outer.parentNode.removeChild(this._outer);

    // Remove CSS classes
    this._el.classList.remove('slidy');
    forEach(this._items, (slide) => {
      slide.classList.remove('slidy__item');
      slide.removeAttribute('style');
      forEach(slide.children, (child) => {
        child.removeAttribute('style');
      });
    });

    this._el.removeAttribute('style');
  }

  /**
   * Events
   */

  /**
   * RWD reset
   * Mainly for height…
   */
  resize() {
    this.reset();
  }

  /**
   * Click on slider to go to the next slide
   * Enabled via "click" option,
   */
  click() {
    this.slideNext();
  }

  /**
   * Same as click but for touch devices
   * Enabled via "touch" option
   */
  tap() {
    this.slideNext();
  }

  /**
   * Complement gesture for "tap"
   * Enabled via "touch" option
   */
  swipe(e) {
    if (e.direction === Hammer.DIRECTION_LEFT) {
      this.slideNext();
    }
    if (e.direction === Hammer.DIRECTION_RIGHT) {
      this.slidePrev();
    }
  }

  /**
   * Play/pause on hover
   * Enabled via "auto" + "pause" options
   */
  enter() {
    this._el.removeEventListener('mouseenter', this.onEnter);
    this.stop();
    this._el.addEventListener('mouseleave', this.onLeave);
  }

  leave() {
    this._el.removeEventListener('mouseleave', this.onLeave);
    this.start();
    this._el.addEventListener('mouseenter', this.onEnter);
  }

  /**
   * Callbacks
   */

  beforeInit() {
    if (this._opts.beforeInit) {
      this._opts.beforeInit.call(this, this._el);
    }
  }

  afterInit() {
    if (this._opts.afterInit) {
      this._opts.afterInit.call(this, this._el);
    }
  }

  beforeSlide(direction) {
    if (this._opts.beforeSlide) {
      this._opts.beforeSlide.call(
        this,
        this.currentIndex,
        this.newIndex,
        direction
      );
    }
  }

  afterSlide(direction) {
    if (this._opts.afterSlide) {
      this._opts.afterSlide.call(
        this,
        this.currentIndex,
        this.oldIndex,
        direction
      );
    }
  }
}
<|endoftext|>


<commit_before>import * as types from '../actions/types';

const initialState = {
    focusedInput: '',
    name: '',
    email: '',
    nickname: '',
    password: '',
    invalidateInputs: new Set(),
    inputs: [
        {
            inputType: 'text',
            inputLabel: 'Name'
        },
        {
            inputType: 'email',
            inputLabel: 'Email'
        },
        {
            inputType: 'text',
            inputLabel: 'Nickname'
        },
        {
            inputType: 'password',
            inputLabel: 'Password'
        },
    ]
};

export const form = (state = initialState, action) => {
    let {name, email, nickname, password, focusedInput} = action;
    let {invalidateInputs, inputs} = state;
    let newInvalidateInputs = [];

    switch (action.type) {
        case types.SET_FOCUSED_INPUT:
            return (focusedInput !== undefined) ? {
                ...state,
                focusedInput
            } : state;

        case types.CLEAN_FOCUSED_INPUT:
            return {
                ...state,
                focusedInput: ''
            };

        case types.SET_NAME_INPUT_VALUE:
            if (name.length > 3 && regExpValidation(name)) {
                newInvalidateInputs = [...invalidateInputs].filter(x => x !== inputs[0].inputLabel);
                return {
                    ...state,
                    invalidateInputs: new Set(...newInvalidateInputs),
                    name
                };
            }
            return {
                ...state,
                invalidateInputs: new Set([...invalidateInputs, inputs[0].inputLabel]),
                name
            };

        case types.SET_EMAIL_INPUT_VALUE:
            return {
                ...state,
                email
            };

        case types.SET_NICKNAME_INPUT_VALUE:
            if (nickname.length > 3 && regExpValidation(nickname)) {
                newInvalidateInputs = [...invalidateInputs].filter(x => x !== inputs[2].inputLabel);
                console.log('nickname:', newInvalidateInputs);
                return {
                    ...state,
                    invalidateInputs: new Set(newInvalidateInputs),
                    nickname
                };
            }
            return {
                ...state,
                invalidateInputs: new Set([...invalidateInputs, inputs[2].inputLabel]),
                nickname
            };

        case types.SET_PASSWORD_INPUT_VALUE:
            if (password.length > 6 && regExpValidation(password)) {
                newInvalidateInputs = [...invalidateInputs].filter(x => x !== inputs[3].inputLabel);
                console.log('password:', newInvalidateInputs);
                return {
                    ...state,
                    invalidateInputs: new Set(newInvalidateInputs),
                    password
                };
            }
            return {
                ...state,
                invalidateInputs: new Set([...invalidateInputs, inputs[3].inputLabel]),
                password
            };

        default:
            return state;
    }
};

const regExpValidation = (str) => {
    const pattern = new RegExp('^[a-zA-Z0-9\d\\-\\_.,\s]+$');
    return pattern.test(str);
};
<commit_msg>message in reducer added<commit_after>import * as types from '../actions/types';

const initialState = {
    focusedInput: '',
    name: '',
    email: '',
    nickname: '',
    password: '',
    invalidateInputs: new Set(),
    inputs: [
        {
            inputType: 'text',
            inputLabel: 'Name',
            inputMessage: ''
        },
        {
            inputType: 'email',
            inputLabel: 'Email',
            inputMessage: ''
        },
        {
            inputType: 'text',
            inputLabel: 'Nickname',
            inputMessage: ''
        },
        {
            inputType: 'password',
            inputLabel: 'Password',
            inputMessage: ''
        },
    ]
};

export const form = (state = initialState, action) => {
    let {name, email, nickname, password, focusedInput} = action;
    let {invalidateInputs, inputs} = state;
    let newInvalidateInputs;
    let currentInput;
    let setToInvalidateInputs;
    let newInputMessage;

    switch (action.type) {
        case types.SET_FOCUSED_INPUT:
            return (focusedInput !== undefined) ? {
                ...state,
                focusedInput
            } : state;

        case types.CLEAN_FOCUSED_INPUT:
            return {
                ...state,
                focusedInput: ''
            };

        case types.SET_NAME_INPUT_VALUE:
            currentInput = inputs[0];
            setToInvalidateInputs = [];
            newInputMessage = '';
            newInvalidateInputs = [...invalidateInputs].filter(x => x !== currentInput.inputLabel);

            if (name.length < 4) {
                setToInvalidateInputs = [...invalidateInputs, currentInput.inputLabel];
                newInputMessage = 'At least 4 chars!';
            } else if (regExpValidation(name)) {
                setToInvalidateInputs = [...invalidateInputs, currentInput.inputLabel];
                newInputMessage = 'Do not use special chars!';
            } else {
                setToInvalidateInputs = newInvalidateInputs;
                newInputMessage = '';
            }
            inputs[0] = {
                ...currentInput,
                inputMessage: newInputMessage
            };

            return {
                ...state,
                name,
                inputs,
                invalidateInputs: new Set(setToInvalidateInputs)
            };

        case types.SET_EMAIL_INPUT_VALUE:
            return {
                ...state,
                email
            };

        case types.SET_NICKNAME_INPUT_VALUE:
            currentInput = inputs[2];
            setToInvalidateInputs = [];
            newInputMessage = '';
            newInvalidateInputs = [...invalidateInputs].filter(x => x !== currentInput.inputLabel);

            if (nickname.length < 4) {
                setToInvalidateInputs = [...invalidateInputs, currentInput.inputLabel];
                newInputMessage = 'At least 4 chars!';
            } else if (regExpValidation(nickname)) {
                setToInvalidateInputs = [...invalidateInputs, currentInput.inputLabel];
                newInputMessage = 'Do not use special chars!';
            } else {
                setToInvalidateInputs = newInvalidateInputs;
                newInputMessage = '';
            }
            inputs[2] = {
                ...currentInput,
                inputMessage: newInputMessage
            };

            return {
                ...state,
                nickname,
                inputs,
                invalidateInputs: new Set(setToInvalidateInputs)
            };

        case types.SET_PASSWORD_INPUT_VALUE:
            currentInput = inputs[3];
            setToInvalidateInputs = [];
            newInputMessage = '';
            newInvalidateInputs = [...invalidateInputs].filter(x => x !== currentInput.inputLabel);

            if (password.length < 4) {
                setToInvalidateInputs = [...invalidateInputs, currentInput.inputLabel];
                newInputMessage = 'At least 4 chars!';
            } else if (regExpValidation(password)) {
                setToInvalidateInputs = [...invalidateInputs, currentInput.inputLabel];
                newInputMessage = 'Do not use special chars!';
            } else {
                setToInvalidateInputs = newInvalidateInputs;
                newInputMessage = '';
            }
            inputs[3] = {
                ...currentInput,
                inputMessage: newInputMessage
            };

            return {
                ...state,
                password,
                inputs,
                invalidateInputs: new Set(setToInvalidateInputs)
            };

        default:
            return state;
    }
};

const regExpValidation = (str) => {
    const pattern = new RegExp('^[a-zA-Z0-9\d\\-\\_.,\s]+$');
    return !pattern.test(str);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

	var VERSION_TEMPLATE = '/*! <%= pkg.name %> - <%= pkg.version %> - ' +
	'<%= grunt.template.today("yyyy-mm-dd HH:MM:ss") %> */' +
	'\n\n';

	function getFiles ( ) {

		return [
			'src/js/intro.js',
			'src/js/helpers.js',
			'src/js/constants.js',
			'src/js/range.js',
			'src/js/options.js',
			'src/js/scope_start.js',
			'src/js/structure.js',
			'src/js/tooltips.js',
			'src/js/pips.js',
			'src/js/scope_helpers.js',
			'src/js/scope_events.js',
			'src/js/scope.js',
			'src/js/scope_end.js',
			'src/js/interface.js',
			'src/js/outro.js'
		];
	}

	var releaseFiles = [
		{ src: ['**/*'], dest: '', cwd: 'distribute/', expand: true },
		{ src: ['**/*.css'], dest: '', cwd: 'src/', expand: true }
	];

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		concat: {
			options: {
				banner: VERSION_TEMPLATE
			},
			basic: {
				src: getFiles(),
				dest: 'distribute/nouislider.js',
				nonull: true
			},
			css: {
				src: ['src/nouislider.css', 'src/nouislider.pips.css', 'src/nouislider.tooltips.css'],
				dest: 'distribute/nouislider.css',
				nonull: true
			}
		},
		cssmin: {
			all: {
				options: {
					banner: VERSION_TEMPLATE
				},
				files: {
					'distribute/nouislider.min.css': ['src/nouislider.css', 'src/nouislider.pips.css', 'src/nouislider.tooltips.css']
				}
			}
		},
		jshint: {
			options: {
				browser: true,
				indent: false,
				laxbreak: true,
				laxcomma: true,
				validthis: true,
				curly: true,
				latedef: true,
				undef: true,
				unused: true,
				globals: { module: true, define: true, __dirname: true, require: true }
			},
			basic: ['distribute/nouislider.js']
		},
		uglify: {
			all: {
				options: {
					banner: VERSION_TEMPLATE
				},
				files: {
					'distribute/nouislider.min.js': 'distribute/nouislider.js'
				}
			}
		},
		compress: {
			all: {
				options: {
					archive: 'noUiSlider.<%= pkg.version %>.zip'
				},
				files: releaseFiles
			}
		},
		qunit: {
			files: ['tests/range.html', 'tests/slider.html'],
			options: {
				page : {
					viewportSize : { width: 1280, height: 800 }
				}
			}
		}
	});

	// https://github.com/gruntjs/grunt-contrib-concat
	grunt.loadNpmTasks('grunt-contrib-concat');

	// https://github.com/gruntjs/grunt-contrib-uglify
	grunt.loadNpmTasks('grunt-contrib-uglify');

	// https://github.com/gruntjs/grunt-contrib-jshint
	grunt.loadNpmTasks('grunt-contrib-jshint');

	// https://github.com/gruntjs/grunt-contrib-cssmin
	grunt.loadNpmTasks('grunt-contrib-cssmin');

	// https://github.com/gruntjs/grunt-contrib-compress
	grunt.loadNpmTasks('grunt-contrib-compress');

	// https://github.com/gruntjs/grunt-contrib-qunit
	grunt.loadNpmTasks('grunt-contrib-qunit');

	grunt.registerTask('default', ['concat', 'jshint']);
	grunt.registerTask('test', ['concat', 'jshint', 'qunit']);
	grunt.registerTask('create', ['concat', 'uglify', 'cssmin', 'qunit']);
	grunt.registerTask('release', ['jshint', 'compress', 'qunit']);
};
<commit_msg>Don't include source in zip<commit_after>module.exports = function(grunt) {

	var VERSION_TEMPLATE = '/*! <%= pkg.name %> - <%= pkg.version %> - ' +
	'<%= grunt.template.today("yyyy-mm-dd HH:MM:ss") %> */' +
	'\n\n';

	function getFiles ( ) {

		return [
			'src/js/intro.js',
			'src/js/helpers.js',
			'src/js/constants.js',
			'src/js/range.js',
			'src/js/options.js',
			'src/js/scope_start.js',
			'src/js/structure.js',
			'src/js/tooltips.js',
			'src/js/pips.js',
			'src/js/scope_helpers.js',
			'src/js/scope_events.js',
			'src/js/scope.js',
			'src/js/scope_end.js',
			'src/js/interface.js',
			'src/js/outro.js'
		];
	}

	var releaseFiles = [
		{ src: ['**/*'], dest: '', cwd: 'distribute/', expand: true }
	];

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		concat: {
			options: {
				banner: VERSION_TEMPLATE
			},
			basic: {
				src: getFiles(),
				dest: 'distribute/nouislider.js',
				nonull: true
			},
			css: {
				src: ['src/nouislider.css', 'src/nouislider.pips.css', 'src/nouislider.tooltips.css'],
				dest: 'distribute/nouislider.css',
				nonull: true
			}
		},
		cssmin: {
			all: {
				options: {
					banner: VERSION_TEMPLATE
				},
				files: {
					'distribute/nouislider.min.css': ['src/nouislider.css', 'src/nouislider.pips.css', 'src/nouislider.tooltips.css']
				}
			}
		},
		jshint: {
			options: {
				browser: true,
				indent: false,
				laxbreak: true,
				laxcomma: true,
				validthis: true,
				curly: true,
				latedef: true,
				undef: true,
				unused: true,
				globals: { module: true, define: true, __dirname: true, require: true }
			},
			basic: ['distribute/nouislider.js']
		},
		uglify: {
			all: {
				options: {
					banner: VERSION_TEMPLATE
				},
				files: {
					'distribute/nouislider.min.js': 'distribute/nouislider.js'
				}
			}
		},
		compress: {
			all: {
				options: {
					archive: 'noUiSlider.<%= pkg.version %>.zip'
				},
				files: releaseFiles
			}
		},
		qunit: {
			files: ['tests/range.html', 'tests/slider.html'],
			options: {
				page : {
					viewportSize : { width: 1280, height: 800 }
				}
			}
		}
	});

	// https://github.com/gruntjs/grunt-contrib-concat
	grunt.loadNpmTasks('grunt-contrib-concat');

	// https://github.com/gruntjs/grunt-contrib-uglify
	grunt.loadNpmTasks('grunt-contrib-uglify');

	// https://github.com/gruntjs/grunt-contrib-jshint
	grunt.loadNpmTasks('grunt-contrib-jshint');

	// https://github.com/gruntjs/grunt-contrib-cssmin
	grunt.loadNpmTasks('grunt-contrib-cssmin');

	// https://github.com/gruntjs/grunt-contrib-compress
	grunt.loadNpmTasks('grunt-contrib-compress');

	// https://github.com/gruntjs/grunt-contrib-qunit
	grunt.loadNpmTasks('grunt-contrib-qunit');

	grunt.registerTask('default', ['concat', 'jshint']);
	grunt.registerTask('test', ['concat', 'jshint', 'qunit']);
	grunt.registerTask('create', ['concat', 'uglify', 'cssmin', 'qunit']);
	grunt.registerTask('release', ['jshint', 'compress', 'qunit']);
};
<|endoftext|>


<commit_before>/*!
 * Grunt file
 */

/*jshint node:true */
module.exports = function ( grunt ) {
	grunt.loadNpmTasks( 'grunt-contrib-clean' );
	grunt.loadNpmTasks( 'grunt-contrib-csslint' );
	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
	grunt.loadNpmTasks( 'grunt-contrib-qunit' );
	grunt.loadNpmTasks( 'grunt-contrib-watch' );
	grunt.loadNpmTasks( 'grunt-banana-checker' );
	grunt.loadNpmTasks( 'grunt-jscs-checker' );
	grunt.loadNpmTasks( 'grunt-recess' );
	grunt.loadTasks( 'build/tasks' );

	var modules = grunt.file.readJSON( 'build/modules.json' ),
		moduleUtils = require( './build/moduleUtils' ),
		styleTargets = {
			'oojs-ui': moduleUtils.expandResources( modules['oojs-ui'].styles ),
			'oojs-ui-apex': moduleUtils.expandResources( modules['oojs-ui-apex'].styles ),
			'oojs-ui-agora': moduleUtils.expandResources( modules['oojs-ui-agora'].styles )
		},
		recessFiles = {},
		concatCssFiles = {};
		( function () {
			var distFile, target, module;
			for ( module in styleTargets ) {
				for ( target in styleTargets[module] ) {
					distFile = target === 'default' ?
						'dist/' + module + '.css' :
						'dist/' + module + '.' + target + '.css';

					recessFiles[distFile] = styleTargets[module][target];

					// Concat isn't doing much other than expanding v@VERSION...
					concatCssFiles[ module + '-css-' + target ] = {
						dest: distFile,
						src: [ distFile ]
					};
				}
			}
		}() );

	grunt.initConfig( {
		pkg: grunt.file.readJSON( 'package.json' ),
		clean: {
			dist: ['dist/*/', 'dist/*.*']
		},
		recess: {
			dist: {
				options: {
					compile: true
				},
				files: recessFiles
			}
		},
		concat: grunt.util._.extend( concatCssFiles, {
			js: {
				dest: 'dist/oojs-ui.js',
				src: modules['oojs-ui'].scripts
			}
		} ),
		copy: {
			images: {
				src: 'src/styles/images/**/*.*',
				strip: 'src/styles/images',
				dest: 'dist/images'
			},
			i18n: {
				src: 'i18n/*.json',
				dest: 'dist'
			}
		},
		jshint: {
			options: {
				jshintrc: true
			},
			dev: ['*.js', '{build,demos,src,test}/**/*.js'],
			dist: 'dist/**/*.js'
		},
		jscs: {
			dev: [
				'<%= jshint.dev %>',
				'!demos/{dist,lib}/**'
			],
			dist: '<%= jshint.dist %>'
		},
		csslint: {
			options: {
				csslintrc: '.csslintrc'
			},
			all: [
				'{demos,src}/**/*.css',
				'!demos/{dist,lib}/**'
			],
		},
		banana: {
			all: 'i18n/'
		},
		qunit: {
			all: ['test/index.html']
		},
		watch: {
			files: [
				'<%= jshint.all %>',
				'<%= csslint.all %>',
				'{demos,src}/**/*.less',
				'<%= qunit.all %>',
				'.{jshintrc,jshintignore}'
			],
			tasks: ['test']
		}
	} );

	grunt.registerTask( 'build', ['clean', 'recess', 'concat', 'copy'] );
	grunt.registerTask( 'test', ['git-build', 'build', 'jshint', 'jscs', 'csslint', 'banana', 'qunit'] );
	grunt.registerTask( 'default', 'test' );
};
<commit_msg>Watch dot files<commit_after>/*!
 * Grunt file
 */

/*jshint node:true */
module.exports = function ( grunt ) {
	grunt.loadNpmTasks( 'grunt-contrib-clean' );
	grunt.loadNpmTasks( 'grunt-contrib-csslint' );
	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
	grunt.loadNpmTasks( 'grunt-contrib-qunit' );
	grunt.loadNpmTasks( 'grunt-contrib-watch' );
	grunt.loadNpmTasks( 'grunt-banana-checker' );
	grunt.loadNpmTasks( 'grunt-jscs-checker' );
	grunt.loadNpmTasks( 'grunt-recess' );
	grunt.loadTasks( 'build/tasks' );

	var modules = grunt.file.readJSON( 'build/modules.json' ),
		moduleUtils = require( './build/moduleUtils' ),
		styleTargets = {
			'oojs-ui': moduleUtils.expandResources( modules['oojs-ui'].styles ),
			'oojs-ui-apex': moduleUtils.expandResources( modules['oojs-ui-apex'].styles ),
			'oojs-ui-agora': moduleUtils.expandResources( modules['oojs-ui-agora'].styles )
		},
		recessFiles = {},
		concatCssFiles = {};
		( function () {
			var distFile, target, module;
			for ( module in styleTargets ) {
				for ( target in styleTargets[module] ) {
					distFile = target === 'default' ?
						'dist/' + module + '.css' :
						'dist/' + module + '.' + target + '.css';

					recessFiles[distFile] = styleTargets[module][target];

					// Concat isn't doing much other than expanding v@VERSION...
					concatCssFiles[ module + '-css-' + target ] = {
						dest: distFile,
						src: [ distFile ]
					};
				}
			}
		}() );

	grunt.initConfig( {
		pkg: grunt.file.readJSON( 'package.json' ),
		clean: {
			dist: ['dist/*/', 'dist/*.*']
		},
		recess: {
			dist: {
				options: {
					compile: true
				},
				files: recessFiles
			}
		},
		concat: grunt.util._.extend( concatCssFiles, {
			js: {
				dest: 'dist/oojs-ui.js',
				src: modules['oojs-ui'].scripts
			}
		} ),
		copy: {
			images: {
				src: 'src/styles/images/**/*.*',
				strip: 'src/styles/images',
				dest: 'dist/images'
			},
			i18n: {
				src: 'i18n/*.json',
				dest: 'dist'
			}
		},
		jshint: {
			options: {
				jshintrc: true
			},
			dev: ['*.js', '{build,demos,src,test}/**/*.js'],
			dist: 'dist/**/*.js'
		},
		jscs: {
			dev: [
				'<%= jshint.dev %>',
				'!demos/{dist,lib}/**'
			],
			dist: '<%= jshint.dist %>'
		},
		csslint: {
			options: {
				csslintrc: '.csslintrc'
			},
			all: [
				'{demos,src}/**/*.css',
				'!demos/{dist,lib}/**'
			],
		},
		banana: {
			all: 'i18n/'
		},
		qunit: {
			all: ['test/index.html']
		},
		watch: {
			files: [
				'<%= jshint.all %>',
				'<%= csslint.all %>',
				'{demos,src}/**/*.less',
				'<%= qunit.all %>',
				'.{csslintrc,jscsrc,jshintignore,jshintrc}'
			],
			tasks: ['test']
		}
	} );

	grunt.registerTask( 'build', ['clean', 'recess', 'concat', 'copy'] );
	grunt.registerTask( 'test', ['git-build', 'build', 'jshint', 'jscs', 'csslint', 'banana', 'qunit'] );
	grunt.registerTask( 'default', 'test' );
};
<|endoftext|>


<commit_before>var _ = require('./lib/test');

exports.time = {
    'do' : function(test) {

        console.log('');

        console.log(_.Seconds(1).concat(_.Seconds(1)));
        console.log(_.Seconds(1).concat(_.Minutes(1)));
        console.log(_.Minutes(1).concat(_.Minutes(1)));
        console.log(_.Minutes(1).concat(_.Seconds(2)));
        console.log(_.Hours(1).concat(_.Hours(2)));
        console.log(_.Seconds(1).concat(_.Hours(2)));
        console.log(_.Hours(1).concat(_.Seconds(2)));

        console.log(_.Seconds(1).chain(function(a) {
            return _.Minutes(1 + a);
        }));

        console.log(_.Seconds(2).map(_.decSecond));

        test.ok(true);
        test.done();
    }
};
<commit_msg>Adding more logs, will replace with tests sooooooon!<commit_after>var _ = require('./lib/test');

exports.time = {
    'do' : function(test) {

        console.log('');

        console.log(_.Seconds(1).concat(_.Seconds(1)));
        console.log(_.Seconds(1).concat(_.Minutes(1)));
        console.log(_.Minutes(1).concat(_.Minutes(1)));
        console.log(_.Minutes(1).concat(_.Seconds(2)));
        console.log(_.Hours(1).concat(_.Hours(2)));
        console.log(_.Seconds(1).concat(_.Hours(2)));
        console.log(_.Hours(1).concat(_.Seconds(2)));
        console.log(_.Milliseconds(1).concat(_.Milliseconds(2)));
        console.log(_.Seconds(1).concat(_.Milliseconds(2)));
        console.log(_.Milliseconds(1).concat(_.Seconds(2)));

        console.log(_.Seconds(1).chain(function(a) {
            return _.Minutes(1 + a);
        }));

        console.log(_.Seconds(2).map(_.decSecond));

        test.ok(true);
        test.done();
    }
};
<|endoftext|>


<commit_before>// The WEBSOCKET server and port the bot should connect to.
// Most of the time this isn't the same as the URL, check the `Request URL` of
// the websocket.
// If you really don't know how to do this... Run `node getserver.js URL`.
// Fill in the URL of the client where `URL` is.
// For example: `node getserver.js http://example-server.psim.us/`
exports.server = 'cbc.pokecommunity.com';
exports.port = 8000;

// This is the server id.
// To know this one, you should check where the AJAX call 'goes' to when you
// log in.
// For example, on the Smogon server, it will say somewhere in the URL
// ~~showdown, meaning that the server id is 'showdown'.
// If you really don't know how to check this... run the said script above.
exports.serverid = 'pokecommunity';

// The nick and password to log in with
// If no password is required, leave pass empty
exports.nick = 'PokeCommBot';
exports.pass = 'filler';

// The rooms that should be joined.
// Joining Smogon's Showdown's Lobby is not allowed.
exports.rooms = ['lobby'];

// Any private rooms that should be joined.
// Private rooms will be moderated differently (since /warn doesn't work in them).
// The bot will also avoid leaking the private rooms through .seen
exports.privaterooms = ['staff'];

// The character text should start with to be seen as a command.
// Note that using / and ! might be 'dangerous' since these are used in
// Showdown itself.
// Using only alphanumeric characters and spaces is not allowed.
exports.commandcharacter = '.';

// The default rank is the minimum rank that can use a command in a room when
// no rank is specified in settings.json
exports.defaultrank = '%';

// Whether this file should be watched for changes or not.
// If you change this option, the server has to be restarted in order for it to
// take effect.
exports.watchconfig = true;

// Secondary websocket protocols should be defined here, however, Showdown
// doesn't support that yet, so it's best to leave this empty.
exports.secprotocols = [];

// What should be logged?
// 0 = error, ok, info, debug, recv, send
// 1 = error, ok, info, debug, cmdr, send
// 2 = error, ok, info, debug (recommended for development)
// 3 = error, ok, info (recommended for production)
// 4 = error, ok
// 5 = error
exports.debuglevel = 3;

// Users who can use all commands regardless of their rank. Be very cautious
// with this, especially on servers other than main.
exports.excepts = [];

// Whitelisted users are those who the bot will not enforce moderation for.
exports.whitelist = ['PokeCommBot'];

// Add a link to the help for the bot here. When there is a link here, .help and .guide
// will link to it.
exports.botguide = 'http://www.pokecommunity.com/showthread.php?t=289012#bot';

// This allows the bot to act as an automated moderator. If enabled, the bot will
// mute users who send 6 lines or more in 6 or fewer seconds for 7 minutes. NOTE: THIS IS
// BY NO MEANS A PERFECT MODERATOR OR SCRIPT. It is a bot and so cannot think for itself or
// exercise moderator discretion. In addition, it currently uses a very simple method of
// determining who to mute and so may miss people who should be muted, or mute those who
// shouldn't. Use with caution.
exports.allowmute = true;

// The punishment values system allows you to customise how you want the bot to deal with
// rulebreakers. Spamming has a points value of 2, all caps has a points value of 1, etc.
exports.punishvals = {
	1: 'warn',
	2: 'mute',
	3: 'hourmute',
	4: 'roomban',
	5: 'ban'
};

<commit_msg>Update config-example.js<commit_after>// The WEBSOCKET server and port the bot should connect to.
// Most of the time this isn't the same as the URL, check the `Request URL` of
// the websocket.
// If you really don't know how to do this... Run `node getserver.js URL`.
// Fill in the URL of the client where `URL` is.
// For example: `node getserver.js http://example-server.psim.us/`
exports.server = 'cbc.pokecommunity.com';
exports.port = 8000;

// This is the server id.
// To know this one, you should check where the AJAX call 'goes' to when you
// log in.
// For example, on the Smogon server, it will say somewhere in the URL
// ~~showdown, meaning that the server id is 'showdown'.
// If you really don't know how to check this... run the said script above.
exports.serverid = 'pokecommunity';

// The nick and password to log in with
// If no password is required, leave pass empty
exports.nick = 'PokeCommBot';
exports.pass = 'filler';

// The rooms that should be joined.
// Joining Smogon's Showdown's Lobby is not allowed.
exports.rooms = ['lobby'];

// Any private rooms that should be joined.
// Private rooms will be moderated differently (since /warn doesn't work in them).
// The bot will also avoid leaking the private rooms through .seen
exports.privaterooms = ['staff'];

// The character text should start with to be seen as a command.
// Note that using / and ! might be 'dangerous' since these are used in
// Showdown itself.
// Using only alphanumeric characters and spaces is not allowed.
exports.commandcharacter = '.';

// The default rank is the minimum rank that can use a command in a room when
// no rank is specified in settings.json
exports.defaultrank = '%';

// Whether this file should be watched for changes or not.
// If you change this option, the server has to be restarted in order for it to
// take effect.
exports.watchconfig = true;

// Secondary websocket protocols should be defined here, however, Showdown
// doesn't support that yet, so it's best to leave this empty.
exports.secprotocols = [];

// What should be logged?
// 0 = error, ok, info, debug, recv, send
// 1 = error, ok, info, debug, cmdr, send
// 2 = error, ok, info, debug (recommended for development)
// 3 = error, ok, info (recommended for production)
// 4 = error, ok
// 5 = error
exports.debuglevel = 3;

// Users who can use all commands regardless of their rank. Be very cautious
// with this, especially on servers other than main.
exports.excepts = [];

// Whitelisted users are those who the bot will not enforce moderation for.
exports.whitelist = ['PokeCommBot'];

// Add a link to the help for the bot here. When there is a link here, .help and .guide
// will link to it.
exports.botguide = 'http://www.pokecommunity.com/showthread.php?t=289012#botguide';

// This allows the bot to act as an automated moderator. If enabled, the bot will
// mute users who send 6 lines or more in 6 or fewer seconds for 7 minutes. NOTE: THIS IS
// BY NO MEANS A PERFECT MODERATOR OR SCRIPT. It is a bot and so cannot think for itself or
// exercise moderator discretion. In addition, it currently uses a very simple method of
// determining who to mute and so may miss people who should be muted, or mute those who
// shouldn't. Use with caution.
exports.allowmute = true;

// The punishment values system allows you to customise how you want the bot to deal with
// rulebreakers. Spamming has a points value of 2, all caps has a points value of 1, etc.
exports.punishvals = {
	1: 'warn',
	2: 'mute',
	3: 'hourmute',
	4: 'roomban',
	5: 'ban'
};

<|endoftext|>


<commit_before>import { connect } from 'react-redux'

import GtfsEditor  from '../components/GtfsEditor'
import { componentList } from '../util/gtfs'
import { fetchFeedSourceAndProject, fetchFeedVersion } from '../../manager/actions/feeds'
import {
  fetchFeedInfo,
} from '../actions/feedInfo'
import {
  fetchStops,
  fetchStopsForTripPattern,
} from '../actions/stop'
import {
  fetchRoutes,
} from '../actions/route'
import {
  fetchTripPatterns,
  fetchTripPatternsForRoute,
  undoActiveTripPatternEdits,
  updateControlPoint,
  addControlPoint,
  removeControlPoint,
} from '../actions/tripPattern'
import {
  fetchTripsForCalendar,
  saveTripsForCalendar,
  deleteTripsForCalendar,
} from '../actions/trip'
import {
  setActiveGtfsEntity,
  newGtfsEntity,
  toggleEditSetting,
  updateMapSetting,
  saveActiveGtfsEntity,
  resetActiveGtfsEntity,
  deleteGtfsEntity,
  settingActiveGtfsEntity,
  updateActiveGtfsEntity,
  clearGtfsContent,
  addGtfsRow,
  updateGtfsField,
  deleteGtfsRow,
  saveGtfsRow,
  getGtfsTable,
  uploadGtfsFeed,
  downloadGtfsFeed,
  importGtfsFromGtfs,
  loadGtfsEntities,
  receiveGtfsEntities
} from '../actions/editor'

const mapStateToProps = (state, ownProps) => {
  const feedSourceId = ownProps.routeParams.feedSourceId // location.pathname.split('/')[2]
  const activeComponent = ownProps.routeParams.subpage // location.pathname.split('/')[4]
  const subComponent = ownProps.routeParams.subsubpage // location.pathname.split('/')[5]
  const subSubComponent = ownProps.routeParams.subsubcomponent // location.pathname.split('/')[6]
  const activeEntityId = ownProps.routeParams.entity // location.pathname.split('/')[7]
  const activeSubEntity = ownProps.routeParams.subentity // location.pathname.split('/')[8]
  const activeSubSubEntity = ownProps.routeParams.subsubentity // location.pathname.split('/')[9]
  const activeEntity =
    state.editor.active && state.editor.active.entity && state.editor.active.entity.id === activeEntityId
    ? state.editor.active.entity
    : state.editor.active && state.editor.active.entity && activeComponent === 'feedinfo'
    ? state.editor.active.entity
    : null
  // const activeSubEntity = state.editor.active && state.editor.active.subEntity && state.editor.active.subEntity.id === activeEntityId
  // ? state.editor.active.subEntity
  // : state.editor.active && state.editor.active.subEntity && activeComponent === 'feedinfo'
  // ? state.editor.active.subEntity
  // : null
    // ownProps.routeParams.entity && state.editor.tableData[activeComponent]
    // ? state.editor.tableData[activeComponent].find(e => ownProps.routeParams.entity === e.id)
    // : null
  const entityEdited = state.editor.active.edited

  // const isEditingGeometry = state.editor.editSettings.editGeometry
  // const isAddingStops = state.editor.editSettings.addStops
  // const isFollowingStreets = state.editor.editSettings.followStreets
  // const isSnappingToStops = state.editor.editSettings.snapToStops
  // const isHidingStops = state.editor.editSettings.hideStops
  const controlPoints = state.editor.editSettings.controlPoints && state.editor.editSettings.controlPoints.length
    ? state.editor.editSettings.controlPoints[state.editor.editSettings.controlPoints.length - 1]
    : []
  // const editActions = state.editor.editSettings.actions
  // const coordinatesHistory = state.editor.editSettings.coordinatesHistory
  const editSettings = state.editor.editSettings
  // const mapZoom = state.editor.mapState.zoom
  // const mapBounds = state.editor.mapState.bounds
  const mapState = state.editor.mapState

  const tableView = ownProps.location.query && ownProps.location.query.table === 'true'
  const entities = state.editor.tableData[activeComponent]
  let user = state.user
  // find the containing project
  let project = state.projects.all
    ? state.projects.all.find(p => {
        if (!p.feedSources) return false
        return (p.feedSources.findIndex(fs => fs.id === feedSourceId) !== -1)
      })
    : null

  let feedSource
  if (project) {
    feedSource = project.feedSources.find(fs => fs.id === feedSourceId)
  }

  let feedInfo = state.editor.tableData.feedinfo

  return {
    tableData: state.editor.tableData,
    tripPatterns: state.editor.tripPatterns,
    // gtfsEntityLookup: state.editor.gtfsEntityLookup,
    // validation: state.editor.validation,
    // currentTable: state.routing.locationBeforeTransitions.hash ? state.routing.locationBeforeTransitions.hash.split('#')[1] : 'agency',
    feedSource,
    entities,
    feedSourceId,
    feedInfo,
    entityEdited,
    tableView,
    project,
    user,
    activeComponent,
    subSubComponent,
    subComponent,
    activeEntity,
    activeEntityId,
    activeSubEntity,
    // activeSubEntityId,
    activeSubSubEntity,
    editSettings,
    mapState,
    // isAddingStops,
    // isEditingGeometry,
    // isFollowingStreets,
    // isSnappingToStops,
    // isHidingStops,
    controlPoints,
    // coordinatesHistory,
    // editActions,
    // mapZoom,
    // mapBounds
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  // console.log(ownProps)
  // console.log(ownProps.location.pathname.split('/'))
  const feedSourceId = ownProps.routeParams.feedSourceId // location.pathname.split('/')[2]
  const activeComponent = ownProps.routeParams.subpage // location.pathname.split('/')[4]
  const subComponent = ownProps.routeParams.subsubpage // location.pathname.split('/')[5]
  const subSubComponent = ownProps.routeParams.subsubcomponent // location.pathname.split('/')[6]
  const activeEntityId = ownProps.routeParams.entity // location.pathname.split('/')[7]
  const activeSubEntity = ownProps.routeParams.subentity // location.pathname.split('/')[8]
  const activeSubSubEntity = ownProps.routeParams.subsubentity // location.pathname.split('/')[9]

  return {
    onComponentMount: (initialProps) => {
      const tablesToFetch = ['calendar', 'agency', 'route', 'stop']

      // Get all GTFS tables except for the active table (activeComponent)
      if (!initialProps.feedSource || feedSourceId !== initialProps.feedSource.id) {
        dispatch(fetchFeedSourceAndProject(feedSourceId))
        .then(() => {
          dispatch(fetchFeedInfo(feedSourceId))
          for (var i = 0; i < tablesToFetch.length; i++) {
            if (tablesToFetch[i] !== activeComponent) {
              dispatch(getGtfsTable(tablesToFetch[i], feedSourceId))
            }
          }
        })
        .then(() => {
          if (componentList.indexOf(activeComponent) !== -1) {
            dispatch(getGtfsTable(activeComponent, feedSourceId))
            //// FETCH trip patterns if route selected
            .then((entities) => {
              if (activeEntityId === 'new') {
                dispatch(newGtfsEntity(feedSourceId, activeComponent))
              }
              else if (activeEntityId && entities.findIndex(e => e.id === activeEntityId) === -1) {
                console.log('bad entity id, going back to ' + activeComponent)
                return dispatch(setActiveGtfsEntity(feedSourceId, activeComponent))
              }
              dispatch(setActiveGtfsEntity(feedSourceId, activeComponent, activeEntityId, subComponent, activeSubEntity, subSubComponent, activeSubSubEntity))
              if (activeComponent === 'route' && activeEntityId) {
                dispatch(fetchTripPatternsForRoute(feedSourceId, activeEntityId))
                .then((tripPatterns) => {
                  console.log(tripPatterns)
                  let pattern = tripPatterns && tripPatterns.find(p => p.id === activeSubEntity)
                  console.log(pattern)
                  if (subSubComponent === 'timetable' && activeSubSubEntity) {
                    dispatch(fetchTripsForCalendar(feedSourceId, pattern, activeSubSubEntity))
                  }
                })
              }
            })
          }
          else {
            dispatch(setActiveGtfsEntity(feedSourceId))
          }
        })
      } else {
        dispatch(fetchFeedInfo(feedSourceId))
        for (var i = 0; i < tablesToFetch.length; i++) {
          if (tablesToFetch[i] !== activeComponent) {
            dispatch(getGtfsTable(tablesToFetch[i], feedSourceId))
          }
        }
      }

      // Clear gtfs content if no active component
      // if (!activeComponent) {
      //   dispatch(clearGtfsContent())
      // }

      // otherwise, get active table
      // else {
      //
      // }
      dispatch(fetchTripPatterns(feedSourceId))
    },
    onComponentUpdate: (prevProps, newProps) => {
      // handle back button presses by re-setting active gtfs entity
      if (prevProps.activeEntityId !== 'new' &&
        (prevProps.activeComponent !== newProps.activeComponent ||
        prevProps.activeEntityId !== newProps.activeEntityId ||
        prevProps.subComponent !== newProps.subComponent ||
        prevProps.activeSubEntity !== newProps.activeSubEntity ||
        prevProps.subSubComponent !== newProps.subSubComponent ||
        prevProps.activeSubSubEntity !== newProps.activeSubSubEntity)
      ) {
        console.log('handling back button')
        dispatch(setActiveGtfsEntity(feedSourceId, activeComponent, activeEntityId, subComponent, activeSubEntity, subSubComponent, activeSubSubEntity))
      }
    },
    newRowClicked: (tableId) => {
      dispatch(addGtfsRow(tableId))
    },
    deleteRowClicked: (tableId, rowIndex) => {
      dispatch(deleteGtfsRow(tableId, rowIndex))
    },
    getGtfsTable: (tableId, feedId) => {
      dispatch(getGtfsTable(tableId, feedId))
    },
    saveRowClicked: (tableId, rowIndex, feedId) => {
      dispatch(saveGtfsRow(tableId, rowIndex, feedId))
    },
    fieldEdited: (tableId, rowIndex, fieldName, newValue) => {
      dispatch(updateGtfsField(tableId, rowIndex, fieldName, newValue))
    },
    newRowsDisplayed: (tableId, rows, feedSource) => {
      if(feedSource) dispatch(loadGtfsEntities(tableId, rows, feedSource))
    },
    toggleEditSetting: (setting) => {
      dispatch(toggleEditSetting(setting))
    },
    updateMapSetting: (setting, value) => {
      dispatch(updateMapSetting(setting, value))
    },
    gtfsEntitySelected: (type, entity) => {
      dispatch(receiveGtfsEntities([entity]))
    },
    setActiveEntity: (feedSourceId, component, entity, subComponent, subEntity, subSubComponent, subSubEntity) => {
      let entityId = entity && entity.id
      let subEntityId = subEntity && subEntity.id
      let subSubEntityId = subSubEntity && subSubEntity.id
      dispatch(setActiveGtfsEntity(feedSourceId, component, entityId, subComponent, subEntityId, subSubComponent, subSubEntityId))
    },
    updateActiveEntity: (entity, component, props) => {
      dispatch(updateActiveGtfsEntity(entity, component, props))
    },
    resetActiveEntity: (entity, component) => {
      dispatch(resetActiveGtfsEntity(entity, component))
    },
    deleteEntity: (feedSourceId, component, entity) => {
      dispatch(deleteGtfsEntity(feedSourceId, component, entity))
    },
    saveActiveEntity: (component) => {
      return dispatch(saveActiveGtfsEntity(component))
      // .then(entity => {
      //   // dispatch(setActiveGtfsEntity(feedSourceId, component, entityId, subComponent, subEntityId, subSubComponent, subSubEntityId))
      // })
    },
    saveTripsForCalendar: (feedSourceId, pattern, calendarId, trips) => {
      return dispatch(saveTripsForCalendar(feedSourceId, pattern, calendarId, trips))
    },
    deleteTripsForCalendar: (feedSourceId, pattern, calendarId, trips) => {
      return dispatch(deleteTripsForCalendar(feedSourceId, pattern, calendarId, trips))
    },
    newEntityClicked: (feedSourceId, component, props, save) => {
      dispatch(newGtfsEntity(feedSourceId, component, props, save))
    },
    clearGtfsContent: () => { dispatch(clearGtfsContent()) },
    undoActiveTripPatternEdits: () => { dispatch(undoActiveTripPatternEdits()) },
    addControlPoint: (controlPoint, index) => { dispatch(addControlPoint(controlPoint, index)) },
    removeControlPoint: (index) => { dispatch(removeControlPoint(index)) },
    updateControlPoint: (index, point, distance) => { dispatch(updateControlPoint(index, point, distance)) },
    fetchTripPatternsForRoute: (feedSourceId, routeId) => {
      dispatch(fetchTripPatternsForRoute(feedSourceId, routeId))
    },
    fetchStopsForTripPattern: (feedSourceId, tripPatternId) => {
      dispatch(fetchStopsForTripPattern(feedSourceId, tripPatternId))
    },
    fetchStops: (feedSourceId) => {
      dispatch(fetchStops(feedSourceId))
    },
    fetchTripsForCalendar: (feedSourceId, pattern, calendarId) => {
      dispatch(fetchTripsForCalendar(feedSourceId, pattern, calendarId))
    },
  }
}

const ActiveGtfsEditor = connect(
  mapStateToProps,
  mapDispatchToProps
)(GtfsEditor)

export default ActiveGtfsEditor
<commit_msg>add cloneEntity and modify deleteEntity to use entityId<commit_after>import { connect } from 'react-redux'

import GtfsEditor  from '../components/GtfsEditor'
import { componentList } from '../util/gtfs'
import { fetchFeedSourceAndProject, fetchFeedVersion } from '../../manager/actions/feeds'
import {
  fetchFeedInfo,
} from '../actions/feedInfo'
import {
  fetchStops,
  fetchStopsForTripPattern,
} from '../actions/stop'
import {
  fetchRoutes,
} from '../actions/route'
import {
  fetchTripPatterns,
  fetchTripPatternsForRoute,
  undoActiveTripPatternEdits,
  updateControlPoint,
  addControlPoint,
  removeControlPoint,
} from '../actions/tripPattern'
import {
  fetchTripsForCalendar,
  saveTripsForCalendar,
  deleteTripsForCalendar,
} from '../actions/trip'
import {
  setActiveGtfsEntity,
  newGtfsEntity,
  cloneGtfsEntity,
  toggleEditSetting,
  updateMapSetting,
  saveActiveGtfsEntity,
  resetActiveGtfsEntity,
  deleteGtfsEntity,
  settingActiveGtfsEntity,
  updateActiveGtfsEntity,
  clearGtfsContent,
  addGtfsRow,
  updateGtfsField,
  deleteGtfsRow,
  saveGtfsRow,
  getGtfsTable,
  uploadGtfsFeed,
  downloadGtfsFeed,
  importGtfsFromGtfs,
  loadGtfsEntities,
  receiveGtfsEntities
} from '../actions/editor'

const mapStateToProps = (state, ownProps) => {
  const feedSourceId = ownProps.routeParams.feedSourceId // location.pathname.split('/')[2]
  const activeComponent = ownProps.routeParams.subpage // location.pathname.split('/')[4]
  const subComponent = ownProps.routeParams.subsubpage // location.pathname.split('/')[5]
  const subSubComponent = ownProps.routeParams.subsubcomponent // location.pathname.split('/')[6]
  const activeEntityId = ownProps.routeParams.entity // location.pathname.split('/')[7]
  const activeSubEntity = ownProps.routeParams.subentity // location.pathname.split('/')[8]
  const activeSubSubEntity = ownProps.routeParams.subsubentity // location.pathname.split('/')[9]
  const activeEntity =
    state.editor.active && state.editor.active.entity && state.editor.active.entity.id === activeEntityId
    ? state.editor.active.entity
    : state.editor.active && state.editor.active.entity && activeComponent === 'feedinfo'
    ? state.editor.active.entity
    : null
  // const activeSubEntity = state.editor.active && state.editor.active.subEntity && state.editor.active.subEntity.id === activeEntityId
  // ? state.editor.active.subEntity
  // : state.editor.active && state.editor.active.subEntity && activeComponent === 'feedinfo'
  // ? state.editor.active.subEntity
  // : null
    // ownProps.routeParams.entity && state.editor.tableData[activeComponent]
    // ? state.editor.tableData[activeComponent].find(e => ownProps.routeParams.entity === e.id)
    // : null
  const entityEdited = state.editor.active.edited

  // const isEditingGeometry = state.editor.editSettings.editGeometry
  // const isAddingStops = state.editor.editSettings.addStops
  // const isFollowingStreets = state.editor.editSettings.followStreets
  // const isSnappingToStops = state.editor.editSettings.snapToStops
  // const isHidingStops = state.editor.editSettings.hideStops
  const controlPoints = state.editor.editSettings.controlPoints && state.editor.editSettings.controlPoints.length
    ? state.editor.editSettings.controlPoints[state.editor.editSettings.controlPoints.length - 1]
    : []
  // const editActions = state.editor.editSettings.actions
  // const coordinatesHistory = state.editor.editSettings.coordinatesHistory
  const editSettings = state.editor.editSettings
  // const mapZoom = state.editor.mapState.zoom
  // const mapBounds = state.editor.mapState.bounds
  const mapState = state.editor.mapState

  const tableView = ownProps.location.query && ownProps.location.query.table === 'true'
  const entities = state.editor.tableData[activeComponent]
  let user = state.user
  // find the containing project
  let project = state.projects.all
    ? state.projects.all.find(p => {
        if (!p.feedSources) return false
        return (p.feedSources.findIndex(fs => fs.id === feedSourceId) !== -1)
      })
    : null

  let feedSource
  if (project) {
    feedSource = project.feedSources.find(fs => fs.id === feedSourceId)
  }

  let feedInfo = state.editor.tableData.feedinfo

  return {
    tableData: state.editor.tableData,
    tripPatterns: state.editor.tripPatterns,
    // gtfsEntityLookup: state.editor.gtfsEntityLookup,
    // validation: state.editor.validation,
    // currentTable: state.routing.locationBeforeTransitions.hash ? state.routing.locationBeforeTransitions.hash.split('#')[1] : 'agency',
    feedSource,
    entities,
    feedSourceId,
    feedInfo,
    entityEdited,
    tableView,
    project,
    user,
    activeComponent,
    subSubComponent,
    subComponent,
    activeEntity,
    activeEntityId,
    activeSubEntity,
    // activeSubEntityId,
    activeSubSubEntity,
    editSettings,
    mapState,
    // isAddingStops,
    // isEditingGeometry,
    // isFollowingStreets,
    // isSnappingToStops,
    // isHidingStops,
    controlPoints,
    // coordinatesHistory,
    // editActions,
    // mapZoom,
    // mapBounds
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  // console.log(ownProps)
  // console.log(ownProps.location.pathname.split('/'))
  const feedSourceId = ownProps.routeParams.feedSourceId // location.pathname.split('/')[2]
  const activeComponent = ownProps.routeParams.subpage // location.pathname.split('/')[4]
  const subComponent = ownProps.routeParams.subsubpage // location.pathname.split('/')[5]
  const subSubComponent = ownProps.routeParams.subsubcomponent // location.pathname.split('/')[6]
  const activeEntityId = ownProps.routeParams.entity // location.pathname.split('/')[7]
  const activeSubEntity = ownProps.routeParams.subentity // location.pathname.split('/')[8]
  const activeSubSubEntity = ownProps.routeParams.subsubentity // location.pathname.split('/')[9]

  return {
    onComponentMount: (initialProps) => {
      const tablesToFetch = ['calendar', 'agency', 'route', 'stop']

      // Get all GTFS tables except for the active table (activeComponent)
      if (!initialProps.feedSource || feedSourceId !== initialProps.feedSource.id) {
        dispatch(fetchFeedSourceAndProject(feedSourceId))
        .then(() => {
          dispatch(fetchFeedInfo(feedSourceId))
          for (var i = 0; i < tablesToFetch.length; i++) {
            if (tablesToFetch[i] !== activeComponent) {
              dispatch(getGtfsTable(tablesToFetch[i], feedSourceId))
            }
          }
        })
        .then(() => {
          if (componentList.indexOf(activeComponent) !== -1) {
            dispatch(getGtfsTable(activeComponent, feedSourceId))
            //// FETCH trip patterns if route selected
            .then((entities) => {
              if (activeEntityId === 'new') {
                dispatch(newGtfsEntity(feedSourceId, activeComponent))
              }
              else if (activeEntityId && entities.findIndex(e => e.id === activeEntityId) === -1) {
                console.log('bad entity id, going back to ' + activeComponent)
                return dispatch(setActiveGtfsEntity(feedSourceId, activeComponent))
              }
              dispatch(setActiveGtfsEntity(feedSourceId, activeComponent, activeEntityId, subComponent, activeSubEntity, subSubComponent, activeSubSubEntity))
              if (activeComponent === 'route' && activeEntityId) {
                dispatch(fetchTripPatternsForRoute(feedSourceId, activeEntityId))
                .then((tripPatterns) => {
                  console.log(tripPatterns)
                  let pattern = tripPatterns && tripPatterns.find(p => p.id === activeSubEntity)
                  console.log(pattern)
                  if (subSubComponent === 'timetable' && activeSubSubEntity) {
                    dispatch(fetchTripsForCalendar(feedSourceId, pattern, activeSubSubEntity))
                  }
                })
              }
            })
          }
          else {
            dispatch(setActiveGtfsEntity(feedSourceId))
          }
        })
      } else {
        dispatch(fetchFeedInfo(feedSourceId))
        for (var i = 0; i < tablesToFetch.length; i++) {
          if (tablesToFetch[i] !== activeComponent) {
            dispatch(getGtfsTable(tablesToFetch[i], feedSourceId))
          }
        }
      }

      // Clear gtfs content if no active component
      // if (!activeComponent) {
      //   dispatch(clearGtfsContent())
      // }

      // otherwise, get active table
      // else {
      //
      // }
      dispatch(fetchTripPatterns(feedSourceId))
    },
    onComponentUpdate: (prevProps, newProps) => {
      // handle back button presses by re-setting active gtfs entity
      if (prevProps.activeEntityId !== 'new' &&
        (prevProps.activeComponent !== newProps.activeComponent ||
        prevProps.activeEntityId !== newProps.activeEntityId ||
        prevProps.subComponent !== newProps.subComponent ||
        prevProps.activeSubEntity !== newProps.activeSubEntity ||
        prevProps.subSubComponent !== newProps.subSubComponent ||
        prevProps.activeSubSubEntity !== newProps.activeSubSubEntity)
      ) {
        console.log('handling back button')
        dispatch(setActiveGtfsEntity(feedSourceId, activeComponent, activeEntityId, subComponent, activeSubEntity, subSubComponent, activeSubSubEntity))
      }
    },
    newRowClicked: (tableId) => {
      dispatch(addGtfsRow(tableId))
    },
    deleteRowClicked: (tableId, rowIndex) => {
      dispatch(deleteGtfsRow(tableId, rowIndex))
    },
    getGtfsTable: (tableId, feedId) => {
      dispatch(getGtfsTable(tableId, feedId))
    },
    saveRowClicked: (tableId, rowIndex, feedId) => {
      dispatch(saveGtfsRow(tableId, rowIndex, feedId))
    },
    fieldEdited: (tableId, rowIndex, fieldName, newValue) => {
      dispatch(updateGtfsField(tableId, rowIndex, fieldName, newValue))
    },
    newRowsDisplayed: (tableId, rows, feedSource) => {
      if(feedSource) dispatch(loadGtfsEntities(tableId, rows, feedSource))
    },
    toggleEditSetting: (setting) => {
      dispatch(toggleEditSetting(setting))
    },
    updateMapSetting: (setting, value) => {
      dispatch(updateMapSetting(setting, value))
    },
    gtfsEntitySelected: (type, entity) => {
      dispatch(receiveGtfsEntities([entity]))
    },
    setActiveEntity: (feedSourceId, component, entity, subComponent, subEntity, subSubComponent, subSubEntity) => {
      let entityId = entity && entity.id
      let subEntityId = subEntity && subEntity.id
      let subSubEntityId = subSubEntity && subSubEntity.id
      dispatch(setActiveGtfsEntity(feedSourceId, component, entityId, subComponent, subEntityId, subSubComponent, subSubEntityId))
    },
    updateActiveEntity: (entity, component, props) => {
      dispatch(updateActiveGtfsEntity(entity, component, props))
    },
    resetActiveEntity: (entity, component) => {
      dispatch(resetActiveGtfsEntity(entity, component))
    },
    deleteEntity: (feedSourceId, component, entityId, routeId) => {
      dispatch(deleteGtfsEntity(feedSourceId, component, entityId, routeId))
    },
    saveActiveEntity: (component) => {
      return dispatch(saveActiveGtfsEntity(component))
      // .then(entity => {
      //   // dispatch(setActiveGtfsEntity(feedSourceId, component, entityId, subComponent, subEntityId, subSubComponent, subSubEntityId))
      // })
    },
    saveTripsForCalendar: (feedSourceId, pattern, calendarId, trips) => {
      return dispatch(saveTripsForCalendar(feedSourceId, pattern, calendarId, trips))
    },
    deleteTripsForCalendar: (feedSourceId, pattern, calendarId, trips) => {
      return dispatch(deleteTripsForCalendar(feedSourceId, pattern, calendarId, trips))
    },
    cloneEntity: (feedSourceId, component, entityId, save) => {
      dispatch(cloneGtfsEntity(feedSourceId, component, entityId, save))
    },
    newEntityClicked: (feedSourceId, component, props, save) => {
      dispatch(newGtfsEntity(feedSourceId, component, props, save))
    },
    clearGtfsContent: () => { dispatch(clearGtfsContent()) },
    undoActiveTripPatternEdits: () => { dispatch(undoActiveTripPatternEdits()) },
    addControlPoint: (controlPoint, index) => { dispatch(addControlPoint(controlPoint, index)) },
    removeControlPoint: (index) => { dispatch(removeControlPoint(index)) },
    updateControlPoint: (index, point, distance) => { dispatch(updateControlPoint(index, point, distance)) },
    fetchTripPatternsForRoute: (feedSourceId, routeId) => {
      dispatch(fetchTripPatternsForRoute(feedSourceId, routeId))
    },
    fetchStopsForTripPattern: (feedSourceId, tripPatternId) => {
      dispatch(fetchStopsForTripPattern(feedSourceId, tripPatternId))
    },
    fetchStops: (feedSourceId) => {
      dispatch(fetchStops(feedSourceId))
    },
    fetchTripsForCalendar: (feedSourceId, pattern, calendarId) => {
      dispatch(fetchTripsForCalendar(feedSourceId, pattern, calendarId))
    },
  }
}

const ActiveGtfsEditor = connect(
  mapStateToProps,
  mapDispatchToProps
)(GtfsEditor)

export default ActiveGtfsEditor
<|endoftext|>


<commit_before>// sehee88
// Sketchbook CRUD
/*
POST /sketchbook/1/word
//request
{
"word": "apple"
}

// 턴 지정하기
POST /sketchbook/1/paper/1/
{
"type": "picture" or "answer" or "word"
"userId": "B",
"data": "http:~~.jpg" or "answer"
"score": 0 //default userId
}

// 스케치북 조회하기
GET /skethbook/1/
//response
{
// 저장된 스키마를 그대로 조회하여 화면에서 분리 (angular JS에서)
}
*/

var Sketchbook = require('../models/sketchbook.server.model');
var Paper = require('../models/sketchbook.server.model');
var Room = require('../models/room.server.model');
var base64 = require('node-base64-image');
fs = require('fs');
var async = require('async');

// Create a sketchbook
/*
router.post('/:userId', function(req, res, next) {
if (!req.body) {
return res.sendStatus(400);
}
console.log(req.body);
var sketchbook = new Sketchbook({
userId: req.params.userId,
word : req.body.word,
paper : req.body.paper,
type : req.body.type
});

sketchbook.save(function (err) {
if (err) {
return res.sendStatus(500);
}
});
});
*/

// 스케치북 생성하기
// POST /sketchbook/1
exports.create = function(req, res, next) {

  console.log("::::::::::::::: createSketchbook !!!!!!!!!!!!!!");
  var sketchbookId = "";

  async.series([
    function(callback) {
      var sketchbook = new Sketchbook({
        ownerId: req.body.userId, // 스케치북 주인
      });
      sketchbook.save(function(err) {
        if (err) {
          return res.sendStatus(500);
        }
        Sketchbook.findById(sketchbook, function(err, doc) {
          if (err) return handleError(err);
          sketchbookId = doc._id;
          callback(null, doc);
        });
      });
    },
    function(callback) {
      Room.update({
        _id: req.body.roomId
      }, {
        $addToSet: {
          sketchbooks: sketchbookId
        }
      }, {
        upsert: true
      }, function(err, result) {
        callback(null, result);
      });
    }
  ], function(err, result) {
    console.log("sketchbookId : " + sketchbookId);
    res.send(sketchbookId);
  });

};

// 턴 지정하기
// POST /sketchbook/1(스케치북 id)/paper/1/
exports.countTurn = function(req, res) {

  console.log(req.body);

  Sketchbook.update({
    _id: req.params.sketchbookId
  }, {
    $addToSet: {
      papers: {
        userId: req.body.ownerId,
        type: req.body.type
      },
      word: req.body.word
    }
  }, {
    upsert: true
  }, function(err, result) {
    console.log("result papers : " + result.papers);
    res.send(result);
  });
};

// 스케치북 조회하기
// GET /skethbook/1/
exports.get = function(req, res, next) {
  Sketchbook.findOne({
    userId: req.params.userId
  }, function(err, results) {
    if (!err) {
      console.log("results : " + results);
      res.send(results);
    }
  });
};

// 스케치북 수정하기
// PUT /skethbook/1/
exports.update = function(req, res, next) {
  console.log(req.params.sketchbookId + "에 단어 :" + req.body.word + " 선택");
  Sketchbook.update({
    _id: req.params.sketchbookId
  }, {
    word: req.body.word
  }, function(err, result) {
    res.send(result);
  });

};

// 스케치북 삭제하기
// DELETE /skethbook/1/
exports.delete = function(req, res, next) {};

// 스케치북 조회하기
// GET /skethbook/1/
exports.listPaper = function(req, res, next) {
  console.log("sketchbookId : " + req.params.sketchbookId);
  Sketchbook.findOne({
    _id: req.params.sketchbookId
  }, function(err, results) {
    if (!err) {
      console.log("results papers : " + results.papers[results.papers.length - 1].picture);
      res.send(results);
    }
  });
};

// 페이서 생성하기
// POST /skethbook/1/
exports.createPaper = function(req, res) {
  console.log('createPaper In !!');

  if (!req.body) {
    return res.sendStatus(400);
  }

  // 이미지 파일명 셋팅
  var date = new Date();
  var dateString = date.getFullYear() + "" + (date.getMonth() + 1) + "" + date.getDate() + "" + date.getHours() + "" + date.getMinutes() + "" + date.getSeconds() + "" + date.getMilliseconds();
  var staticPath = '/tempSketchbookImage/sketchbook_'; // sketchbook_timestamp.png

  //console.log(req.body.picture);

  var imgUrl = req.body.picture;
  var replaceDataUrl = imgUrl.replace(/^data:image\/\w+;base64,/, "");
  var imageData = new Buffer(replaceDataUrl, 'base64');

  var fileFullPath = {
    filename: 'www' + staticPath + dateString // 저장할경로/파일명.png
  };
  var filePath = staticPath + dateString;

  //로컬에 이미지 저장
  base64.base64decoder(imageData, fileFullPath, function(err, saved) {
    if (err) {
      console.log(err);
    }
    console.log('\n\n fileFullPath.filename = ' + fileFullPath.filename);
    console.log('\n\n saved = ' + saved);
    res.send(saved);
  });

  var paperId = '';
  async.series([
    function(callback) {
      var paper = new Paper({
        userId: req.body.userId,
        type: req.body.type,
        answer: req.body.answer,
        picture: filePath,
        score: req.body.score
      });
      paper.save(function(err) {
        if (err) {
          return res.sendStatus(500);
        }
        Paper.findById(paper, function(err, doc) {
          if (err) return handleError(err);
          paperId = doc._id;
          callback(null, doc);
        });
      });
    },
    function(callback) {
      Sketchbook.update({
        _id: req.params.sketchbookId
      }, {
        $addToSet: {
          papers: {
            paperId: paperId,
            userId: req.body.userId,
            type: req.body.type,
            answer: req.body.answer,
            picture: filePath,
            score: req.body.score
          }
        }
      }, {
        upsert: true
      }, function(err, result) {
        callback(null, result);
      });
    }
  ], function(err, result) {
    console.log("paperId : " + paperId);
    res.send(result.papers);
  });
};

// 페이퍼 조회하기
// get /skethbook/1/paper/1
exports.getPaper = function(req, res, next) {};

// 페이퍼 수정하기
// put /skethbook/1/paper/1
exports.updatePaper = function(req, res, next) {};

// 페이퍼 삭제하기
// DELETE /skethbook/1/paper/1
exports.deletePaper = function(req, res, next) {};
<commit_msg>Update Sketchbook Api<commit_after>// sehee88
// Sketchbook CRUD
/*
POST /sketchbook/1/word
//request
{
"word": "apple"
}

// 턴 지정하기
POST /sketchbook/1/paper/1/
{
"type": "picture" or "answer" or "word"
"userId": "B",
"data": "http:~~.jpg" or "answer"
"score": 0 //default userId
}

// 스케치북 조회하기
GET /skethbook/1/
//response
{
// 저장된 스키마를 그대로 조회하여 화면에서 분리 (angular JS에서)
}
*/

var Sketchbook = require('../models/sketchbook.server.model');
var Paper = require('../models/sketchbook.server.model');
var Room = require('../models/room.server.model');
var base64 = require('node-base64-image');
fs = require('fs');
var async = require('async');

// Create a sketchbook
/*
router.post('/:userId', function(req, res, next) {
if (!req.body) {
return res.sendStatus(400);
}
console.log(req.body);
var sketchbook = new Sketchbook({
userId: req.params.userId,
word : req.body.word,
paper : req.body.paper,
type : req.body.type
});

sketchbook.save(function (err) {
if (err) {
return res.sendStatus(500);
}
});
});
*/

// 스케치북 생성하기
// POST /sketchbook/1
exports.create = function(req, res, next) {

  console.log("::::::::::::::: createSketchbook !!!!!!!!!!!!!!");
  var sketchbookId = "";

  async.series([
    function(callback) {
      var sketchbook = new Sketchbook({
        ownerId: req.body.userId, // 스케치북 주인
      });
      sketchbook.save(function(err) {
        if (err) {
          return res.sendStatus(500);
        }
        Sketchbook.findById(sketchbook, function(err, doc) {
          if (err) return handleError(err);
          sketchbookId = doc._id;
          callback(null, doc);
        });
      });
    },
    function(callback) {
      Room.update({
        _id: req.body.roomId
      }, {
        $addToSet: {
          sketchbooks: sketchbookId
        }
      }, {
        upsert: true
      }, function(err, result) {
        callback(null, result);
      });
    }
  ], function(err, result) {
    console.log("sketchbookId : " + sketchbookId);
    res.send(sketchbookId);
  });

};

// 턴 지정하기
// POST /sketchbook/1(스케치북 id)/paper/1/
exports.countTurn = function(req, res) {

  console.log(req.body);

  Sketchbook.update({
    _id: req.params.sketchbookId
  }, {
    $addToSet: {
      papers: {
        userId: req.body.ownerId,
        type: req.body.type
      },
      word: req.body.word
    }
  }, {
    upsert: true
  }, function(err, result) {
    console.log("result papers : " + result.papers);
    res.send(result);
  });
};

// 스케치북 조회하기
// GET /skethbook/1/
exports.get = function(req, res, next) {
  Sketchbook.findOne({
    userId: req.params.userId
  }, function(err, results) {
    if (!err) {
      console.log("results : " + results);
      res.send(results);
    }
  });
};

// 스케치북 수정하기
// PUT /skethbook/1/
exports.update = function(req, res, next) {
  console.log(req.params.sketchbookId + "에 단어 :" + req.body.word + " 선택");
  Sketchbook.update({
    _id: req.params.sketchbookId
  }, {
    word: req.body.word
  }, function(err, result) {
    res.send(result);
  });

};

// 스케치북 삭제하기
// DELETE /skethbook/1/
exports.delete = function(req, res, next) {};

// 스케치북 조회하기
// GET /skethbook/1/
exports.listPaper = function(req, res, next) {
  console.log("sketchbookId : " + req.params.sketchbookId);
  Sketchbook.findOne({
    _id: req.params.sketchbookId
  }, function(err, results) {
    if (!err) {
      console.log("results papers : " + results.papers);
      res.send(results);
    }
  });
};

// 페이서 생성하기
// POST /skethbook/1/
exports.createPaper = function(req, res) {
  console.log('createPaper In !!');

  if (!req.body) {
    return res.sendStatus(400);
  }

  // 이미지 파일명 셋팅
  var date = new Date();
  var dateString = date.getFullYear() + "" + (date.getMonth() + 1) + "" + date.getDate() + "" + date.getHours() + "" + date.getMinutes() + "" + date.getSeconds() + "" + date.getMilliseconds();
  var staticPath = '/tempSketchbookImage/sketchbook_'; // sketchbook_timestamp.png

  //console.log(req.body.picture);

  var imgUrl = req.body.picture;
  var replaceDataUrl = imgUrl.replace(/^data:image\/\w+;base64,/, "");
  var imageData = new Buffer(replaceDataUrl, 'base64');

  var fileFullPath = {
    filename: 'www' + staticPath + dateString // 저장할경로/파일명.png
  };
  var filePath = staticPath + dateString;

  //로컬에 이미지 저장
  base64.base64decoder(imageData, fileFullPath, function(err, saved) {
    if (err) {
      console.log(err);
    }
    console.log('\n\n fileFullPath.filename = ' + fileFullPath.filename);
    console.log('\n\n saved = ' + saved);
    res.send(saved);
  });

  var paperId = '';
  async.series([
    function(callback) {
      var paper = new Paper({
        userId: req.body.userId,
        type: req.body.type,
        answer: req.body.answer,
        picture: filePath,
        score: req.body.score
      });
      paper.save(function(err) {
        if (err) {
          return res.sendStatus(500);
        }
        Paper.findById(paper, function(err, doc) {
          if (err) return handleError(err);
          paperId = doc._id;
          callback(null, doc);
        });
      });
    },
    function(callback) {
      Sketchbook.update({
        _id: req.params.sketchbookId
      }, {
        $addToSet: {
          papers: {
            paperId: paperId,
            userId: req.body.userId,
            type: req.body.type,
            answer: req.body.answer,
            picture: filePath,
            score: req.body.score
          }
        }
      }, {
        upsert: true
      }, function(err, result) {
        callback(null, result);
      });
    }
  ], function(err, result) {
    console.log("paperId : " + paperId);
    res.send(result.papers);
  });
};

// 페이퍼 조회하기
// get /skethbook/1/paper/1
exports.getPaper = function(req, res, next) {};

// 페이퍼 수정하기
// put /skethbook/1/paper/1
exports.updatePaper = function(req, res, next) {};

// 페이퍼 삭제하기
// DELETE /skethbook/1/paper/1
exports.deletePaper = function(req, res, next) {};
<|endoftext|>


<commit_before>// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
var vscode = require('vscode');
var chucknorris = require('./chuck-norris.json');
var resultTodo;

var openQuickPick = vscode.commands.registerCommand('extension.openQuickPick', function() {
	if (resultTodo === undefined) {
		return;
	}
	var resultTodoName = [];
	for (var index in resultTodo) {
		for (var i = 0; i < resultTodo[index].length; i++) {
			var todo = resultTodo[index][i];
			resultTodoName.push(todo.name);
		}
	}
	vscode.window.showQuickPick(resultTodoName, {}).then(function(response) {
		var nameSplit = new String(response).split(' ');
		var file = 'file://' + nameSplit[0];
		var fileUri = vscode.Uri.parse(file);
		vscode.workspace.openTextDocument(fileUri).then(function(textDocument) {
			vscode.window.showTextDocument(textDocument, vscode.ViewColumn.One).then(function(textEditor) {
				var line = Number(nameSplit[1].split(':')[0]) - 1;
				var resultObjects = resultTodo[nameSplit[0]];
				var startPos;
				var endPos;
				for (var i = 0; i < resultObjects.length; i++) {
					var object = resultObjects[i];
					if (object.line === line) {
						startPos = new vscode.Position(object.line, 0);
						endPos = new vscode.Position(object.line, object.lineLength);
						break;
					}
				}
				vscode.window.activeTextEditor.selection = new vscode.Selection(startPos, endPos);
			});
		});
	});
});

// this method is called when the extension is activated
function activate(context) {

	// this line of code will only be executed once when the extension is activated
	console.log('Congratulations, your extension "vscode-todo" is now active!');

	var statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
	statusBarItem.text = 'TODO:s';
	statusBarItem.tooltip = 'Show TODO:s';
	statusBarItem.command = 'extension.openQuickPick';
	statusBarItem.color = '#FFFFFF';
	console.log(statusBarItem);
	statusBarItem.show();

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with  registerCommand
	// The commandId parameter must match the command field in package.json
	var disposable = vscode.commands.registerCommand('extension.chuckNorris', function () {
		var choice = ["Go", "JavaScript"];

		// vscode.window.showQuickPick(choice, {}).then(function(response) {
		// 	console.log(response);
		// });

		vscode.workspace.findFiles('**/*.go', '', 1000).then(function(files) {
			doWork(files, function(result) {
				if (result.length == 0) {
					vscode.window.showInformationMessage("No result");
				} else {
					resultTodo = result;
				}
			});
		});
	});

	context.subscriptions.push(disposable);
}

function getObject() {
	return {name: undefined, fileName: undefined, line: undefined, lineLength: undefined};
}

function doWork(files, done) {
	var message = {};
	var times = 0;
	for (var i = 0; i < files.length; i++) {
		vscode.workspace.openTextDocument(files[i]).then(function(file) {
			var uriString = String(file._uri);
			var pathWithoutFile = uriString.substring(7, uriString.length);
			for (var line = 0; line < file._lines.length; line++) {
				var textLine = String(file._lines[line]);
				if (textLine.includes('TODO:')) {
					if (!message.hasOwnProperty(textLine)) {
						message[pathWithoutFile] = [];
					}
					var object = getObject();
					object.name = pathWithoutFile + ' ' + (line + 1) + ':' + (textLine.indexOf('TODO:') + 1);
					object.fileName = pathWithoutFile;
					object.line = line;
					object.lineLength = textLine.length;
					message[pathWithoutFile].push(object);
				}
			}
		}).then(function() {
			times++;
			if (times == files.length) {
				return done(message);
			}
		});
	}
}

exports.activate = activate;
<commit_msg>Refactor vscode properties<commit_after>// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
var vscode = require('vscode');
var chucknorris = require('./chuck-norris.json');
var resultTodo;
var Workspace = vscode.workspace;
var Window = vscode.window;
var Commands = vscode.commands;

var openQuickPick = Commands.registerCommand('extension.openQuickPick', function() {
	if (resultTodo === undefined) {
		return;
	}
	var resultTodoName = [];
	for (var index in resultTodo) {
		for (var i = 0; i < resultTodo[index].length; i++) {
			var todo = resultTodo[index][i];
			resultTodoName.push(todo.name);
		}
	}
	Window.showQuickPick(resultTodoName, {}).then(function(response) {
		var nameSplit = new String(response).split(' ');
		var file = 'file://' + nameSplit[0];
		var fileUri = vscode.Uri.parse(file);
		Workspace.openTextDocument(fileUri).then(function(textDocument) {
			Window.showTextDocument(textDocument, vscode.ViewColumn.One).then(function(textEditor) {
				var line = Number(nameSplit[1].split(':')[0]) - 1;
				var resultObjects = resultTodo[nameSplit[0]];
				var startPos;
				var endPos;
				for (var i = 0; i < resultObjects.length; i++) {
					var object = resultObjects[i];
					if (object.line === line) {
						startPos = new vscode.Position(object.line, 0);
						endPos = new vscode.Position(object.line, object.lineLength);
						break;
					}
				}
				Window.activeTextEditor.selection = new vscode.Selection(startPos, endPos);
			});
		});
	});
});

// this method is called when the extension is activated
function activate(context) {

	// this line of code will only be executed once when the extension is activated
	console.log('Congratulations, your extension "vscode-todo" is now active!');

	var statusBarItem = Window.createStatusBarItem(vscode.StatusBarAlignment.Left);
	statusBarItem.text = 'TODO:s';
	statusBarItem.tooltip = 'Show TODO:s';
	statusBarItem.command = 'extension.openQuickPick';
	statusBarItem.color = '#FFFFFF';
	console.log(statusBarItem);
	statusBarItem.show();

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with  registerCommand
	// The commandId parameter must match the command field in package.json
	var disposable = Commands.registerCommand('extension.chuckNorris', function () {
		var choice = ["Go", "JavaScript"];

		// vscode.window.showQuickPick(choice, {}).then(function(response) {
		// 	console.log(response);
		// });

		Workspace.findFiles('**/*.go', '', 1000).then(function(files) {
			doWork(files, function(result) {
				if (result.length == 0) {
					Window.showInformationMessage("No result");
				} else {
					resultTodo = result;
				}
			});
		});
	});

	context.subscriptions.push(disposable);
}

function getObject() {
	return {name: undefined, fileName: undefined, line: undefined, lineLength: undefined};
}

function doWork(files, done) {
	var message = {};
	var times = 0;
	for (var i = 0; i < files.length; i++) {
		Workspace.openTextDocument(files[i]).then(function(file) {
			var uriString = String(file._uri);
			var pathWithoutFile = uriString.substring(7, uriString.length);
			for (var line = 0; line < file._lines.length; line++) {
				var textLine = String(file._lines[line]);
				if (textLine.includes('TODO:')) {
					if (!message.hasOwnProperty(textLine)) {
						message[pathWithoutFile] = [];
					}
					var object = getObject();
					object.name = pathWithoutFile + ' ' + (line + 1) + ':' + (textLine.indexOf('TODO:') + 1);
					object.fileName = pathWithoutFile;
					object.line = line;
					object.lineLength = textLine.length;
					message[pathWithoutFile].push(object);
				}
			}
		}).then(function() {
			times++;
			if (times == files.length) {
				return done(message);
			}
		});
	}
}

exports.activate = activate;
<|endoftext|>