<commit_before>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual([1, 3]);
    expect(odd.length).toBe(2);
    expect(numbers.length).toBe(3);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual([2, 3, 4]);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
            function(/* result from last call */ memo, /* current */ x) { return memo + x }, /* initial */ 0);

    expect(reduction).toBe(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).all(isEven)).toBe(FILL_ME_IN);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).any(isEven)).toBe(FILL_ME_IN);
  });

  it("should use range to generate an array", function() {
      expect(_.range(3)).toEqual(FILL_ME_IN);
      expect(_.range(1, 4)).toEqual(FILL_ME_IN);
      expect(_.range(0, -4, -1)).toEqual(FILL_ME_IN);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
      expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(FILL_ME_IN);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
      var result = _([ [0, 1], 2 ]).chain()
                       .flatten()
                       .map(function(x) { return x+1 } )
                       .reduce(function (sum, x) { return sum + x })
                       .value();

      expect(result).toEqual(FILL_ME_IN);
  });

});
<commit_msg>Solve the second issue of the 32nd koan<commit_after>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual([1, 3]);
    expect(odd.length).toBe(2);
    expect(numbers.length).toBe(3);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual([2, 3, 4]);
    expect(numbers).toEqual([1, 2, 3]);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
            function(/* result from last call */ memo, /* current */ x) { return memo + x }, /* initial */ 0);

    expect(reduction).toBe(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).all(isEven)).toBe(FILL_ME_IN);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).any(isEven)).toBe(FILL_ME_IN);
  });

  it("should use range to generate an array", function() {
      expect(_.range(3)).toEqual(FILL_ME_IN);
      expect(_.range(1, 4)).toEqual(FILL_ME_IN);
      expect(_.range(0, -4, -1)).toEqual(FILL_ME_IN);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
      expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(FILL_ME_IN);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
      var result = _([ [0, 1], 2 ]).chain()
                       .flatten()
                       .map(function(x) { return x+1 } )
                       .reduce(function (sum, x) { return sum + x })
                       .value();

      expect(result).toEqual(FILL_ME_IN);
  });

});
<|endoftext|>


<commit_before>var config = require('../lib/config').get(process.env);
var server = require('../lib/server').getServer(config);

config_path = process.env.CONFIG_PATH || '../config/';

testserver_env = {};
testserver_env.CONFIG_PATH = config_path;
testserver_env.NODE_ENV = 'testserver';

development_env = {};
development_env.CONFIG_PATH = config_path;
development_env.NODE_ENV = 'development';

production_env = {};
production_env.CONFIG_PATH = config_path;
production_env.NODE_ENV = 'production';

var testserver_config   = require('../lib/config').get(testserver_env);
var development_config  = require('../lib/config').get(development_env);
var production_config   = require('../lib/config').get(production_env);

/** Config */
exports['htpasswd should NOT be set on development env'] = function(beforeExit, assert){
  assert.isUndefined(development_config.core.htpasswd);
};
exports['htpasswd should be set on testserver env'] = function(beforeExit, assert){
  assert.eql(testserver_config.core.htpasswd.username, "proxyuser");
};
exports['htpasswd should be set on production env'] = function(beforeExit, assert){
  assert.eql(production_config.core.htpasswd.username, "proxyuser");
};

/** Server */
exports['The index should render succesful'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/',
      method: 'GET'
  }, {
      status: 200
  });
};
exports['The header should render'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/header',
      method: 'GET'
  }, {
      status: 200
  });
};

exports['The proxied page should be succesful'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/?url=http://www.google.com',
      method: 'GET'
  }, {
      status: 200
  });
};

exports['The proxied page should be succesful'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/?url=http://www.google.com',
      method: 'GET'
  }, {
      status: 200
  });
};<commit_msg>Created test for the empty url not to throw a 500<commit_after>var config = require('../lib/config').get(process.env);
var server = require('../lib/server').getServer(config);

config_path = process.env.CONFIG_PATH || '../config/';

testserver_env = {};
testserver_env.CONFIG_PATH = config_path;
testserver_env.NODE_ENV = 'testserver';

development_env = {};
development_env.CONFIG_PATH = config_path;
development_env.NODE_ENV = 'development';

production_env = {};
production_env.CONFIG_PATH = config_path;
production_env.NODE_ENV = 'production';

var testserver_config   = require('../lib/config').get(testserver_env);
var development_config  = require('../lib/config').get(development_env);
var production_config   = require('../lib/config').get(production_env);

/** Config */
exports['htpasswd should NOT be set on development env'] = function(beforeExit, assert){
  assert.isUndefined(development_config.core.htpasswd);
};
exports['htpasswd should be set on testserver env'] = function(beforeExit, assert){
  assert.eql(testserver_config.core.htpasswd.username, "proxyuser");
};
exports['htpasswd should be set on production env'] = function(beforeExit, assert){
  assert.eql(production_config.core.htpasswd.username, "proxyuser");
};

/** Server */
exports['The index should render succesful'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/',
      method: 'GET'
  }, {
      status: 200
  });
};
exports['The header should render'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/header',
      method: 'GET'
  }, {
      status: 200
  });
};

exports['The proxied page should be succesful'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/parse?url=http://www.google.com',
      method: 'GET'
  }, {
      status: 200
  });
};

exports['The proxied page should be succesful'] = function(beforeExit, assert){
  assert.response(server, {
      url: '/parse?url=http://www.google.com',
      method: 'GET'
  }, {
      status: 200
  });
};

exports["When an empty url is given, the route should not throw an error"] = function(beforeExit, assert) {
  assert.response(server, {
    url: '/parse?url=',
    method: "GET"
  }, {
    status: 200
  });
}<|endoftext|>


<commit_before>// Web to Plex - Toloka Plugin
// Aurthor(s) - @chmez (2017)

// REQUIRED [plugin:object]: The plugin object
let plugin = {
    // REQUIRED [plugin.url]: this is what you ask Web to Plex access to; currently limited to a single domain
    "url": "https://toloka.to/",

    // OPTIONAL: this is purely for your code functionality
    "getID": () => {
        let links = document.querySelectorAll('.postlink'),
            regex = /^https?\:\/\/(?:w{3}\.)?imdb\.com\/title\/(tt\d+)/i;

        for(let link in links)
            if(regex.test(links[link]))
                return RegExp.$1;
    },

    // REQUIRED [plugin.init]: this is what Web to Plex will call on when the url is detected
    // it will always be fired after the page and Web to Plex have been loaded
    "init": () => {
        let title = document.querySelector('.maintitle').textContent.replace(/^[^\/]+\/\s+([^\(]+)\(([\d]{4})/, '$1').trim(),
                // REQUIRED [title:string]
            year = RegExp.$2,
                // PREFERRED [year:number, null, undefined]
            image = document.querySelector('.postbody img').src,
                // OPTIONAL [image:string]
            id = plugin.getID();
                // the rest of the code is up to you, but should be limited to a layout similar to this

        // REQUIRED [{ type:'movie', 'show'; title:string; year:number }]
        // PREFERRED [{ image:string; IMDbID:string; TMDbID:string, number; TVDbID:string, number }]
        return { type: 'movie', title, year, image, IMDbID };
    }
};
<commit_msg>Update toloka.js<commit_after>// Web to Plex - Toloka Plugin
// Aurthor(s) - @chmez (2017)

// REQUIRED [plugin:object]: The plugin object
let plugin = {
    // REQUIRED [plugin.url]: this is what you ask Web to Plex access to; currently limited to a single domain
    "url": "https://toloka.to/",

    // OPTIONAL: this is purely for your code functionality
    "getID": () => {
        let links = document.querySelectorAll('.postlink'),
            regex = /^https?\:\/\/(?:w{3}\.)?imdb\.com\/title\/(tt\d+)/i;

        for(let link in links)
            if(regex.test(links[link]))
                return RegExp.$1;
    },

    // REQUIRED [plugin.init]: this is what Web to Plex will call on when the url is detected
    // it will always be fired after the page and Web to Plex have been loaded
    "init": () => {
        let title = document.querySelector('.maintitle').textContent.replace(/^[^\/]+\/\s+([^\(]+)\(([\d]{4})/, '$1').trim(),
                // REQUIRED [title:string]
            year = RegExp.$2,
                // PREFERRED [year:number, null, undefined]
            image = document.querySelector('.postbody img').src,
                // OPTIONAL [image:string]
            IMDbID = plugin.getID();
                // the rest of the code is up to you, but should be limited to a layout similar to this

        // REQUIRED [{ type:'movie', 'show'; title:string; year:number }]
        // PREFERRED [{ image:string; IMDbID:string; TMDbID:string, number; TVDbID:string, number }]
        return { type: 'movie', title, year, image, IMDbID };
    }
};
<|endoftext|>


<commit_before>import React from 'react';

import configureStore from './configureStore';
import { reloadAllComponents, reloadComponent } from './routerModule';

export default class RouterHookContext extends React.Component {
  static propTypes = {
    children: React.PropTypes.node.isRequired,
    components: React.PropTypes.array.isRequired,
    locals: React.PropTypes.object,
    location: React.PropTypes.object.isRequired,
    params: React.PropTypes.object,
    routerDidEnterHooks: React.PropTypes.array,
    routerWillEnterHooks: React.PropTypes.array,
    onAborted: React.PropTypes.func,
    onCompleted: React.PropTypes.func,
    onError: React.PropTypes.func,
    onStarted: React.PropTypes.func,
  };

  static defaultProps = {
    locals: {},
    routerDidEnterHooks: [],
    routerWillEnterHooks: [],
    onAborted: () => {},
    onCompleted: () => {},
    onError: () => {},
    onStarted: () => {},
  };

  static childContextTypes = {
    routerHookContext: React.PropTypes.object,
  };

  constructor(props) {
    super(props);
    this.store = configureStore({
      ...props.locals,
      routerDidEnterHooks: props.routerDidEnterHooks,
      routerWillEnterHooks: props.routerWillEnterHooks,
      onAborted: props.onAborted,
      onCompleted: props.onCompleted,
      onError: props.onError,
      onStarted: props.onStarted,
    });
    this.reloadComponent = component => this.store.dispatch(reloadComponent(component, this.props));
    this.reloadAllComponents = (components, renderProps) =>
      this.store.dispatch(reloadAllComponents(components, renderProps));
  }

  getChildContext() {
    return {
      routerHookContext: {
        dispatch: this.store.dispatch,
        getState: this.store.getState,
        subscribe: this.store.subscribe,
        reloadComponent: this.reloadComponent,
        reloadAllComponents: this.reloadAllComponents,
      },
    };
  }

  componentDidMount() {
    this.reloadAllComponents(this.props.components, this.props);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.location === this.props.location) {
      return;
    }
    this.reloadAllComponents(nextProps.components, nextProps);
  }

  render() {
    return this.props.children;
  }
}
<commit_msg>use static get defaultProps()<commit_after>import React from 'react';

import configureStore from './configureStore';
import { reloadAllComponents, reloadComponent } from './routerModule';

export default class RouterHookContext extends React.Component {
  static propTypes = {
    children: React.PropTypes.node.isRequired,
    components: React.PropTypes.array.isRequired,
    locals: React.PropTypes.object,
    location: React.PropTypes.object.isRequired,
    params: React.PropTypes.object,
    routerDidEnterHooks: React.PropTypes.array,
    routerWillEnterHooks: React.PropTypes.array,
    onAborted: React.PropTypes.func,
    onCompleted: React.PropTypes.func,
    onError: React.PropTypes.func,
    onStarted: React.PropTypes.func,
  };

  static get defaultProps() {
    return {
      locals: {},
      routerDidEnterHooks: [],
      routerWillEnterHooks: [],
      onAborted: () => {},
      onCompleted: () => {},
      onError: () => {},
      onStarted: () => {},
    };
  }

  static childContextTypes = {
    routerHookContext: React.PropTypes.object,
  };

  constructor(props) {
    super(props);
    this.store = configureStore({
      ...props.locals,
      routerDidEnterHooks: props.routerDidEnterHooks,
      routerWillEnterHooks: props.routerWillEnterHooks,
      onAborted: props.onAborted,
      onCompleted: props.onCompleted,
      onError: props.onError,
      onStarted: props.onStarted,
    });
    this.reloadComponent = component => this.store.dispatch(reloadComponent(component, this.props));
    this.reloadAllComponents = (components, renderProps) =>
      this.store.dispatch(reloadAllComponents(components, renderProps));
  }

  getChildContext() {
    return {
      routerHookContext: {
        dispatch: this.store.dispatch,
        getState: this.store.getState,
        subscribe: this.store.subscribe,
        reloadComponent: this.reloadComponent,
        reloadAllComponents: this.reloadAllComponents,
      },
    };
  }

  componentDidMount() {
    this.reloadAllComponents(this.props.components, this.props);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.location === this.props.location) {
      return;
    }
    this.reloadAllComponents(nextProps.components, nextProps);
  }

  render() {
    return this.props.children;
  }
}
<|endoftext|>


<commit_before>// Whoo! Welcome to spopsh's source code!! ❤ ahstro \\

// TODO:
// Re-render last command on resize
// Add config to set order of songs/index/time etc. on qls/ls, custom prompt
// Improve colors (theme vs direct)
// Make ^C clear line
// Make ^D exit
// "Random" crashses might be because telnet doesn't output JSON, e.g. 'bye' outputs 'Bye bye!'

var telnet = new require('telnet-client')();

var colors = require('colors');
colors.setTheme({
    help: ['magenta', 'bold'],
    info: ['blue', 'bold'],
    error: 'red',
    win: 'green'
});

var rl = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});
rl.setPrompt('❤ '.red);
rl.on('line', function(cmd) {
    rl.pause();
    execute(cmd);
});

telnet.on('ready', function() {
    console.log("Welcome to spopsh!\nType 'help' for a list of commands");
    var args = process.argv.splice(2).join(' ');
    getCommand(args);
});

telnet.on('error', function() {
    console.log("Fatal error! Your spop daemon might not be running.");
    process.exit(5);
});

telnet.on('close', function() {
    process.exit();
});

// TODO: Add to separate file?
var customCommands = [
    {
        name: 'about',
        args: '',
        summary: 'information about spopsh and spop'
    },
    {
        name: 'clear',
        args: '',
        summary: 'clears the screen, same as ctrl+l'
    }
];

function getPlaylist(json, i) {
    var name = json.name || '★';
    var index = json.index || i; // Can't get json if offline; i should be same
    index = index < 10 ? '0' + index : index;
    index += ' ';
    var offline = ' [' + (json.offline ? '✓': '✕') + ']';
    var spacer = getSpacer([index, name], [offline]);
    // Setting color in the original declaration of 'offline'
    // messes with the .length property used by getSpacer()
    offline = offline.replace(/[✓✕]/, function(p1) {
        return p1 === '✓' ? '✓'.win : '✕'.error;
    });
    return '\n' + index.info + (name === '★' ? name.yellow : name) + spacer + offline;
}

function getTrack(json) {
    var index = (json.index < 10 ? '0' + json.index : json.index.toString());
    var song = ' ' + json.artist + ' - ' + json.title;
    var album = ' [' + json.album + '] ';
    var time = getTime(json.duration);
    var spacer = getSpacer([index, song], [album, time]);

    // Grey out song if not available (offline doesn't grey. bug in spop?)
    if(json.available) {
        return '\n' + index.info + song + spacer + album + time.yellow;
    } else {
        return '\n' + index.grey + song.grey + spacer + album + time.grey;
    }
}

function getSpacer(leftArr, rightArr) {
    var leftLength = 0;
    for(var i = 0; i < leftArr.length; i++) {
        leftLength += leftArr[i].length;
    }
    var rightLength = 0;
    for(var i = 0; i < rightArr.length; i++) {
        rightLength += rightArr[i].length;
    }
    var spacerLength = (process.stdout.columns - (leftLength + rightLength));
    var spacer = '';
    for(var j = 0; j < spacerLength; j++) spacer += ' ';
    return spacer;
}

function getTime(duration) {
    var minutes = Math.floor((duration / 1000) / 60);
    var seconds = Math.floor((duration / 1000) % 60);
        seconds = seconds < 10 ? '0' + seconds : seconds;
    return minutes + ':' + seconds;
}

function parse(cmd, json) {
    cmd = cmd.split(' ');
    var output = '';
    switch(cmd[0]) {
        case 'help':
            if(cmd[1]) {
                output += "'help' doesn't take arguments";
                break;
            }
            output += "Available commands:".help;
            for(var i = 0; i < json.commands.length; i++) {
                var name = json.commands[i].command;
                var args = '';
                json.commands[i].args.forEach(function(arg) {
                    args += ' [' + arg.blue + ']';
                });
                var summary = json.commands[i].summary;

                output += '\n' + name.info + args + '\n  ' + summary;
            }
            for(var i = 0; i < customCommands.length; i++) {
                output += '\n' + customCommands[i].name.info + customCommands[i].args + '\n  ' + customCommands[i].summary;
            }
            break;

        case 'ls':
            if(!cmd[1]) {
                // TODO: Add argument support
                output += "Playlists:".help;
                for(var i = 0; i < json.playlists.length; i++) {
                    output += getPlaylist(json.playlists[i], i);
                }
            } else if (!isNaN(cmd[1]) && !cmd[2]) {
                output += "Tracks:".help;
                for(var i = 0; i < json.tracks.length; i++) {
                    output += getTrack(json.tracks[i], i);
                }
            } else {
                output += "'ls' doesn't take that many arguments";
                // TODO: Add ability to search for playlist names
            }

            break;

        case 'next':
        case 'prev':
        //TODO: Make sure these make sense
        case 'qclear':
        case 'stop':
        case 'status':
        case 'notify':
        case 'repeat':
        case 'shuffle':
        case 'toggle':
        case 'play':
            var stat, song;
            if(json.status === 'playing' || json.status === 'paused' ) {
                stat = json.status === 'playing' ? '♪' + ' Playing: ' :  '▮▮' + ' Paused: ';
                song = json.artist  + ' - ' + json.title + ' - ' + json.album;
            } else {
                stat = '■' + ' Stopped';
                song = '';
            }
            var shuffle = ' Shuffle: ' + (json.shuffle ? '↝' : '→');
            var repeat = ' Repeat: ' + (json.repeat ? '↺' : '→');
            var track = ' Track: ' + (json.current_track || 'X') + '/' + json.total_tracks;
            var progress = ' ' + getTime(json.position * 1000) + '/' + getTime(json.duration);
            var spacer = getSpacer([stat, song], [repeat, shuffle, track, progress]);
            stat = stat.replace(/[♪▮■]/g, function(p1) {
                if(p1 === '♪') {
                    return '♪'.win;
                } else if (p1 === '▮') {
                    return '▮'.yellow;
                } else if (p1 === '■'){
                    return '■'.error;
                }
            });
            output += stat + song + spacer + repeat + shuffle + track + progress + '\n';
            for(var i = 0; i < process.stdout.columns; i++) {
                output += i < (json.position / (json.duration / 1000)) * process.stdout.columns ? '='.blue : '-'.info;
            }
            break;

        // TODO
        // TODO: Currently playing?
        case 'qls':
            output += "Queue:".help;
            for(var i = 0; i < json.tracks.length; i++) {
                output += getTrack(json.tracks[i]);
            }
            break;

        case 'qrm':
        case 'add':
        case 'seek':
        case 'goto':
        case 'offline-status':
        case 'offline-toggle':
        case 'image':
        case 'uinfo':
        case 'uadd':
        case 'uplay':
        case 'uimage':
        case 'search':
        case 'bye':
        case 'quit':
        case 'idle':
            output = json;
            break;

        case 'about':
            output = "spopsh is pretty much a prettifier of spop's telnet interface.\nYou can check out the spopsh's source code at https://github.com/ahstro/spopsh and spop over at https://github.com/Schnouki/spop\n  ❤ ahstro";
            break;

        // TODO: Add monitor command to show status dynamically

        case '':
            // Stops 'Invalid command!' output for custom command
            return;

        default:
            output = 'Invalid command!'.error + "\nTry the 'help' command for a list of available commands";
    }

    console.log(output);
}

function alias(cmd) {
    // Aliases
    // TODO: Add to 'help' somehow
    switch(cmd) {
        case 's':
            return 'status';

        case 'b':
        case 'q':
        case 'e':
        case 'exit':
            return 'bye';

        case 'n':
            return 'next';

        case 'p':
        case 'previous':
            return 'prev';

        case 'dir':
        case 'list':
        case 'playlists':
            return 'ls';

        case 'clear':
            rl.write(null, {ctrl: true, name: 'l'});
            return '';

        default:
            return cmd;
    }
}

function execute(cmd) {
    cmd = alias(cmd);

    telnet.exec(cmd, { echoLines: -1 }, function(res) {
        // TODO: Add subcommands, e.g. 'help notify' to bring up help on just notify command
        //cmd = cmd.split(' ');

        // TODO: Fix hack
        // Might be unnecessary
        if(cmd === 'bye' || cmd === 'quit') process.exit();

        try {
            var json = JSON.parse(res);
            parse(cmd, json);
        } catch (e) {
            // TODO
            console.log(e);
        } finally {
            getCommand();
        }
    });
}

function getCommand(arg) {
    if(arg) execute(arg);
    rl.prompt();
    rl.resume();
}

telnet.connect({
    host: '127.0.0.1',
    port: 6602,
    irs: '\n',
    shellPrompt: '\n',
    timeout: 0
});
<commit_msg>Added proper functionality ot a few more commands<commit_after>// Whoo! Welcome to spopsh's source code!! ❤ ahstro \\

// TODO:
// Re-render last command on resize
// Add config to set order of songs/index/time etc. on qls/ls, custom prompt
// Improve colors (theme vs direct)
// Make ^C clear line
// Make ^D exit
// "Random" crashses might be because telnet doesn't output JSON, e.g. 'bye' outputs 'Bye bye!'

var telnet = new require('telnet-client')();

var colors = require('colors');
colors.setTheme({
    help: ['magenta', 'bold'],
    info: ['blue', 'bold'],
    error: 'red',
    win: 'green'
});

var rl = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});
rl.setPrompt('❤ '.red);
rl.on('line', function(cmd) {
    rl.pause();
    execute(cmd);
});

telnet.on('ready', function() {
    console.log("Welcome to spopsh!\nType 'help' for a list of commands");
    var args = process.argv.splice(2).join(' ');
    getCommand(args);
});

telnet.on('error', function() {
    console.log("Fatal error! Your spop daemon might not be running.");
    process.exit(5);
});

telnet.on('close', function() {
    process.exit();
});

// TODO: Add to separate file?
var customCommands = [
    {
        name: 'about',
        args: '',
        summary: 'information about spopsh and spop'
    },
    {
        name: 'clear',
        args: '',
        summary: 'clears the screen, same as ctrl+l'
    }
];

function getPlaylist(json, i) {
    var name = json.name || '★';
    var index = json.index || i; // Can't get json if offline; i should be same
    index = index < 10 ? '0' + index : index;
    index += ' ';
    var offline = ' [' + (json.offline ? '✓': '✕') + ']';
    var spacer = getSpacer([index, name], [offline]);
    // Setting color in the original declaration of 'offline'
    // messes with the .length property used by getSpacer()
    offline = offline.replace(/[✓✕]/, function(p1) {
        return p1 === '✓' ? '✓'.win : '✕'.error;
    });
    return '\n' + index.info + (name === '★' ? name.yellow : name) + spacer + offline;
}

function getTrack(json) {
    var index = (json.index < 10 ? '0' + json.index : json.index.toString());
    var song = ' ' + json.artist + ' - ' + json.title;
    var album = ' [' + json.album + '] ';
    var time = getTime(json.duration);
    var spacer = getSpacer([index, song], [album, time]);

    // Grey out song if not available (offline doesn't grey. bug in spop?)
    if(json.available) {
        return '\n' + index.info + song + spacer + album + time.yellow;
    } else {
        return '\n' + index.grey + song.grey + spacer + album + time.grey;
    }
}

function getSpacer(leftArr, rightArr) {
    var leftLength = 0;
    for(var i = 0; i < leftArr.length; i++) {
        leftLength += leftArr[i].length;
    }
    var rightLength = 0;
    for(var i = 0; i < rightArr.length; i++) {
        rightLength += rightArr[i].length;
    }
    var spacerLength = (process.stdout.columns - (leftLength + rightLength));
    var spacer = '';
    for(var j = 0; j < spacerLength; j++) spacer += ' ';
    return spacer;
}

function getTime(duration) {
    var minutes = Math.floor((duration / 1000) / 60);
    var seconds = Math.floor((duration / 1000) % 60);
        seconds = seconds < 10 ? '0' + seconds : seconds;
    return minutes + ':' + seconds;
}

function parse(cmd, json) {
    cmd = cmd.split(' ');
    var output = '';
    switch(cmd[0]) {
        case 'help':
            if(cmd[1]) {
                output += "'help' doesn't take arguments";
                break;
            }
            output += "Available commands:".help;
            for(var i = 0; i < json.commands.length; i++) {
                var name = json.commands[i].command;
                var args = '';
                json.commands[i].args.forEach(function(arg) {
                    args += ' [' + arg.blue + ']';
                });
                var summary = json.commands[i].summary;

                output += '\n' + name.info + args + '\n  ' + summary;
            }
            for(var i = 0; i < customCommands.length; i++) {
                output += '\n' + customCommands[i].name.info + customCommands[i].args + '\n  ' + customCommands[i].summary;
            }
            break;

        case 'ls':
            if(!cmd[1]) {
                // TODO: Add argument support
                output += "Playlists:".help;
                for(var i = 0; i < json.playlists.length; i++) {
                    output += getPlaylist(json.playlists[i], i);
                }
            } else if (!isNaN(cmd[1]) && !cmd[2]) {
                output += "Tracks:".help;
                for(var i = 0; i < json.tracks.length; i++) {
                    output += getTrack(json.tracks[i], i);
                }
            } else {
                output += "'ls' doesn't take that many arguments";
                // TODO: Add ability to search for playlist names
            }

            break;

        case 'goto':
        case 'next':
        case 'prev':
        //TODO: Make sure these make sense
        case 'qclear':
        case 'stop':
        case 'status':
        case 'notify':
        case 'repeat':
        case 'shuffle':
        case 'toggle':
        case 'play':
            var stat, song;
            if(json.status === 'playing' || json.status === 'paused' ) {
                stat = json.status === 'playing' ? '♪' + ' Playing: ' :  '▮▮' + ' Paused: ';
                song = json.artist  + ' - ' + json.title + ' - ' + json.album;
            } else {
                stat = '■' + ' Stopped';
                song = '';
            }
            var shuffle = ' Shuffle: ' + (json.shuffle ? '↝' : '→');
            var repeat = ' Repeat: ' + (json.repeat ? '↺' : '→');
            var track = ' Track: ' + (json.current_track || 'X') + '/' + json.total_tracks;
            var progress = ' ' + getTime(json.position * 1000) + '/' + getTime(json.duration);
            var spacer = getSpacer([stat, song], [repeat, shuffle, track, progress]);
            stat = stat.replace(/[♪▮■]/g, function(p1) {
                if(p1 === '♪') {
                    return '♪'.win;
                } else if (p1 === '▮') {
                    return '▮'.yellow;
                } else if (p1 === '■'){
                    return '■'.error;
                }
            });
            output += stat + song + spacer + repeat + shuffle + track + progress + '\n';
            for(var i = 0; i < process.stdout.columns; i++) {
                output += i < (json.position / (json.duration / 1000)) * process.stdout.columns ? '='.blue : '-'.info;
            }
            break;

        // TODO
        // TODO: Currently playing?
        case 'qls':
            output += "Queue:".help;
            for(var i = 0; i < json.tracks.length; i++) {
                output += getTrack(json.tracks[i]);
            }
            break;

        case 'qrm':
            // TODO: Say which song was removed. Add feature upstream?
            if(!cmd[1]) {
                output = "'qrm' takes at least one argument.";
            } else if(!cmd[2]) {
                output = 'Removed song number ' + cmd[1].info + ' from the queue.';
            } else if(!cmd[3]) {
                output = 'Removed songs ' + cmd[1].info + ' through ' + cmd[2].info + ' from the queue.';
            } else {
                output = "'qrm' doesn't take that many arguments.";
            }
            break;

        case 'add':
            // TODO: Name of playlist. Add feature upstream?
            if(!cmd[1]) {
                output = "'add' takes at least one argument.";
            } else if(!cmd[2]) {
                output = 'Added playlist number ' + cmd[1].info + ' to the queue.';
            } else if(!cmd[3]) {
                output = 'Added song ' + cmd[1].info + ' from playlist number ' + cmd[2].info + ' to the queue.';
            } else {
                output = "'qrm' doesn't take that many arguments.";
            }
            break;

        case 'seek':
            // TODO: Allow seeking with min:sec instead of millisecs
            if(!cmd[1]) {
                output = "'seek' takes an argument.";
            } else if(!cmd[2]) {
                parse('status', json);
            } else {
                output = "'seek' doesn't take that many arguments.";
            }
            break;

        case 'image':
            if(json.status === 'ok') {
                // TODO: require('fs') and 'opener', save and open
                output += 'Trying to show the cover image with your default image viewer';
                output += json.data;
                //opener(json.data);
            } else {
                output += 'Something went wrong.';
            }
            output = json;
            break;

        case 'uinfo':
            if(!cmd[1]) {
                output += "'uinfo' takes an argument.";
            } else if(!cmd[2]) {
                switch(json.type) {
                    case 'track':
                        var artist = 'Artist: ';
                        var title = ' Song: ';
                        var album = ' Album: ';
                        var duration = getTime(json.duration);
                        var spacer = getSpacer([artist, json.artist, title, json.title, album, json.album], [duration]);
                        output += artist.info + json.artist + title.info + json.title + album.info + json.album + spacer + duration.yellow;
                        break;

                    case 'playlist':
                        // TODO
                        output = json;
                        break;

                    case 'album':
                        // TODO
                        output = json;
                        break;
                }
            } else {
                output += "'uinfo' doesn't take that many arguments.";
            }
            break;

        case 'search':
            output += 'Search results for '.info + json.query.blue;

            output += '\n\n' + json.total_tracks.toString().info + ' total tracks:';
            for(var i = 0; i < json.tracks.length; i++) {
                output += getTrack(json.tracks[i]);
            }

            output += '\n\n' + json.total_albums.toString().info + ' total albums:';
            for(var i = 0; i < json.albums.length; i++) {
                //output = JSON.stringify(json.albums[i]);
                var index = i < 10 ? '0' + i : i.toString();
                output += '\n' + index.info + ' ' + json.albums[i].artist + ' - ' + json.albums[i].title;
            }

            output += '\n\n' + json.total_artists.toString().info + ' total artists:';
            for(var i = 0; i < json.artists.length; i++) {
                var index = i < 10 ? '0' + i : i.toString();
                output += '\n' + index.info + ' ' + json.artists[i].artist;
            }

            output += '\n\n' + json.total_playlists.toString().info + ' total playlists:';
            for(var i = 0; i < json.playlists.length; i++) {
                output += getPlaylist(json.playlists[i], i);
            }
            output = json;
            break;

        case 'offline-status':
        case 'offline-toggle':
        case 'uadd':
        case 'uplay':
        case 'uimage':
        case 'idle':
            output = json;
            break;

        case 'about':
            output = "spopsh is pretty much a prettifier of spop's telnet interface.\nYou can check out the spopsh's source code at https://github.com/ahstro/spopsh and spop over at https://github.com/Schnouki/spop\n  ❤ ahstro";
            break;

        // TODO: Add monitor command to show status dynamically

        case '':
            // Stops 'Invalid command!' output for custom command
            return;

        default:
            output = 'Invalid command!'.error + "\nTry the 'help' command for a list of available commands";
    }

    console.log(output);
}

function alias(cmd) {
    // Aliases
    // TODO: Add to 'help' somehow
    switch(cmd) {
        case 's':
            return 'status';

        case '': // Enter toggles playback
        case 'pause':
            return 'toggle';

        case 'b':
        case 'q':
        case 'e':
        case 'exit':
            return 'bye';

        case 'n':
            return 'next';

        case 'p':
        case 'previous':
            return 'prev';

        case 'dir':
        case 'list':
        case 'playlists':
            return 'ls';

        case 'clear':
            rl.write(null, {ctrl: true, name: 'l'});
            return '';

        default:
            return cmd;
    }
}

function execute(cmd) {
    cmd = alias(cmd);

    telnet.exec(cmd, { echoLines: -1 }, function(res) {
        // TODO: Add subcommands, e.g. 'help notify' to bring up help on just notify command
        //cmd = cmd.split(' ');

        // TODO: Fix hack
        // Might be unnecessary
        if(cmd === 'bye' || cmd === 'quit') process.exit();

        try {
            var json = JSON.parse(res);
            parse(cmd, json);
        } catch (e) {
            // TODO
            console.log(e);
        } finally {
            getCommand();
        }
    });
}

function getCommand(arg) {
    if(arg) execute(arg);
    rl.prompt();
    rl.resume();
}

telnet.connect({
    host: '127.0.0.1',
    port: 6602,
    irs: '\n',
    shellPrompt: '\n',
    timeout: 0
});
<|endoftext|>


<commit_before>/* eslint default-case: 0 */
/* eslint guard-for-in: 0 */
import React, { Component, PropTypes } from 'react';
import classSet from 'classnames';
import Const from './Const';
import Util from './util';
import DateFilter from './filters/Date';
import TextFilter from './filters/Text';
import RegexFilter from './filters/Regex';
import SelectFilter from './filters/Select';
import NumberFilter from './filters/Number';

class TableHeaderColumn extends Component {

  constructor(props) {
    super(props);
    this.handleFilter = this.handleFilter.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.reset) {
      this.cleanFiltered();
    }
  }

  handleColumnClick = () => {
    if (this.props.isOnlyHead || !this.props.dataSort) return;
    const order = this.props.sort === Const.SORT_DESC ? Const.SORT_ASC : Const.SORT_DESC;
    this.props.onSort(order, this.props.dataField);
  }

  handleFilter(value, type) {
    const { filter } = this.props;
    filter.emitter.handleFilter(this.props.dataField, value, type, filter);
  }

  getFilters() {
    const { headerText, children } = this.props;
    switch (this.props.filter.type) {
    case Const.FILTER_TYPE.TEXT: {
      return (
        <TextFilter ref='textFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.REGEX: {
      return (
        <RegexFilter ref='regexFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.SELECT: {
      return (
        <SelectFilter ref='selectFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.NUMBER: {
      return (
        <NumberFilter ref='numberFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.DATE: {
      return (
        <DateFilter ref='dateFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.CUSTOM: {
      const elm = this.props.filter.getElement(this.handleFilter,
          this.props.filter.customFilterParameters);

      return React.cloneElement(elm, { ref: 'customFilter' });
    }
    }
  }

  componentDidMount() {
    this.refs['header-col'].setAttribute('data-field', this.props.dataField);
  }

  render() {
    let defaultCaret;
    let sortCaret;
    const {
      headerText,
      dataAlign,
      dataField,
      headerAlign,
      headerTitle,
      hidden,
      sort,
      dataSort,
      sortIndicator,
      children,
      caretRender,
      className,
      isOnlyHead,
      thStyle: style
    } = this.props;
    const thStyle = {
      textAlign: headerAlign || dataAlign,
      display: hidden ? 'none' : null,
      ...style
    };
    if (!isOnlyHead) {
      if (sortIndicator) {
        defaultCaret = (!dataSort) ? null : (

        );
      }
      sortCaret = sort ? Util.renderReactSortCaret(sort) : defaultCaret;
      if (caretRender) {
        sortCaret = caretRender(sort, dataField);
      }
    }

    const classes = classSet(
      typeof className === 'function' ? className() : className,
      !isOnlyHead && dataSort ? 'sort-column' : '');

    const title = {
      title: ((headerTitle && typeof children === 'string') ? children : headerText)
    };
    return (

        { children }{ sortCaret }

 e.stopPropagation() }>
          { this.props.filter && !isOnlyHead ? this.getFilters() : null }

    );
  }

  cleanFiltered() {
    if (this.props.filter === undefined) {
      return;
    }

    switch (this.props.filter.type) {
    case Const.FILTER_TYPE.TEXT: {
      this.refs.textFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.REGEX: {
      this.refs.regexFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.SELECT: {
      this.refs.selectFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.NUMBER: {
      this.refs.numberFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.DATE: {
      this.refs.dateFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.CUSTOM: {
      this.refs.customFilter.cleanFiltered();
      break;
    }
    }
  }

  applyFilter(val) {
    if (this.props.filter === undefined) return;
    switch (this.props.filter.type) {
    case Const.FILTER_TYPE.TEXT: {
      this.refs.textFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.REGEX: {
      this.refs.regexFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.SELECT: {
      this.refs.selectFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.NUMBER: {
      this.refs.numberFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.DATE: {
      this.refs.dateFilter.applyFilter(val);
      break;
    }
    }
  }
}

const filterTypeArray = [];
for (const key in Const.FILTER_TYPE) {
  filterTypeArray.push(Const.FILTER_TYPE[key]);
}

TableHeaderColumn.propTypes = {
  dataField: PropTypes.string,
  dataAlign: PropTypes.string,
  headerAlign: PropTypes.string,
  headerTitle: PropTypes.bool,
  headerText: PropTypes.string,
  dataSort: PropTypes.bool,
  onSort: PropTypes.func,
  dataFormat: PropTypes.func,
  csvFormat: PropTypes.func,
  csvHeader: PropTypes.string,
  isKey: PropTypes.bool,
  editable: PropTypes.any,
  hidden: PropTypes.bool,
  hiddenOnInsert: PropTypes.bool,
  searchable: PropTypes.bool,
  className: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func
  ]),
  width: PropTypes.string,
  sortFunc: PropTypes.func,
  sortFuncExtraData: PropTypes.any,
  columnClassName: PropTypes.any,
  editColumnClassName: PropTypes.any,
  invalidEditColumnClassName: PropTypes.any,
  columnTitle: PropTypes.bool,
  filterFormatted: PropTypes.bool,
  filterValue: PropTypes.func,
  sort: PropTypes.string,
  caretRender: PropTypes.func,
  formatExtraData: PropTypes.any,
  csvFormatExtraData: PropTypes.any,
  filter: PropTypes.shape({
    type: PropTypes.oneOf(filterTypeArray),
    delay: PropTypes.number,
    options: PropTypes.oneOfType([
      PropTypes.object, // for SelectFilter
      PropTypes.arrayOf(PropTypes.number) // for NumberFilter
    ]),
    numberComparators: PropTypes.arrayOf(PropTypes.string),
    emitter: PropTypes.object,
    placeholder: PropTypes.string,
    getElement: PropTypes.func,
    customFilterParameters: PropTypes.object,
    condition: PropTypes.oneOf([ Const.FILTER_COND_EQ, Const.FILTER_COND_LIKE ])
  }),
  sortIndicator: PropTypes.bool,
  export: PropTypes.bool,
  expandable: PropTypes.bool,
  tdAttr: PropTypes.object,
  tdStyle: PropTypes.object,
  thStyle: PropTypes.object
};

TableHeaderColumn.defaultProps = {
  dataAlign: 'left',
  headerAlign: undefined,
  headerTitle: true,
  dataSort: false,
  dataFormat: undefined,
  csvFormat: undefined,
  csvHeader: undefined,
  isKey: false,
  editable: true,
  onSort: undefined,
  hidden: false,
  hiddenOnInsert: false,
  searchable: true,
  className: '',
  columnTitle: false,
  width: null,
  sortFunc: undefined,
  columnClassName: '',
  editColumnClassName: '',
  invalidEditColumnClassName: '',
  filterFormatted: false,
  filterValue: undefined,
  sort: undefined,
  formatExtraData: undefined,
  sortFuncExtraData: undefined,
  filter: undefined,
  sortIndicator: true,
  expandable: true,
  tdAttr: undefined,
  tdStyle: undefined,
  thStyle: undefined
};

export default TableHeaderColumn;
<commit_msg>fix #1182<commit_after>/* eslint default-case: 0 */
/* eslint guard-for-in: 0 */
import React, { Component, PropTypes } from 'react';
import classSet from 'classnames';
import Const from './Const';
import Util from './util';
import DateFilter from './filters/Date';
import TextFilter from './filters/Text';
import RegexFilter from './filters/Regex';
import SelectFilter from './filters/Select';
import NumberFilter from './filters/Number';

class TableHeaderColumn extends Component {

  constructor(props) {
    super(props);
    this.handleFilter = this.handleFilter.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.reset) {
      this.cleanFiltered();
    }
  }

  handleColumnClick = () => {
    if (this.props.isOnlyHead || !this.props.dataSort) return;
    const order = this.props.sort === Const.SORT_DESC ? Const.SORT_ASC : Const.SORT_DESC;
    this.props.onSort(order, this.props.dataField);
  }

  handleFilter(value, type) {
    const { filter } = this.props;
    filter.emitter.handleFilter(this.props.dataField, value, type, filter);
  }

  getFilters() {
    const { headerText, children } = this.props;
    switch (this.props.filter.type) {
    case Const.FILTER_TYPE.TEXT: {
      return (
        <TextFilter ref='textFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.REGEX: {
      return (
        <RegexFilter ref='regexFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.SELECT: {
      return (
        <SelectFilter ref='selectFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.NUMBER: {
      return (
        <NumberFilter ref='numberFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.DATE: {
      return (
        <DateFilter ref='dateFilter' { ...this.props.filter }
          columnName={ headerText || children } filterHandler={ this.handleFilter } />
      );
    }
    case Const.FILTER_TYPE.CUSTOM: {
      const elm = this.props.filter.getElement(this.handleFilter,
          this.props.filter.customFilterParameters);

      return React.cloneElement(elm, { ref: 'customFilter' });
    }
    }
  }

  componentDidMount() {
    this.refs['header-col'].setAttribute('data-field', this.props.dataField);
  }

  render() {
    let defaultCaret;
    let sortCaret;
    const {
      headerText,
      dataAlign,
      dataField,
      headerAlign,
      headerTitle,
      hidden,
      sort,
      dataSort,
      sortIndicator,
      children,
      caretRender,
      className,
      isOnlyHead,
      thStyle: style
    } = this.props;
    const thStyle = {
      textAlign: headerAlign || dataAlign,
      display: hidden ? 'none' : null,
      ...style
    };
    if (!isOnlyHead) {
      if (sortIndicator) {
        defaultCaret = (!dataSort) ? null : (

        );
      }
      sortCaret = sort ? Util.renderReactSortCaret(sort) : defaultCaret;
      if (caretRender) {
        sortCaret = caretRender(sort, dataField);
      }
    }

    const classes = classSet(
      typeof className === 'function' ? className() : className,
      !isOnlyHead && dataSort ? 'sort-column' : '');

    const attr = {};
    if (headerTitle) {
      if (typeof children === 'string' && !headerText) {
        attr.title = children;
      } else {
        attr.title = headerText;
      }
    }
    return (

        { children }{ sortCaret }

 e.stopPropagation() }>
          { this.props.filter && !isOnlyHead ? this.getFilters() : null }

    );
  }

  cleanFiltered() {
    if (this.props.filter === undefined) {
      return;
    }

    switch (this.props.filter.type) {
    case Const.FILTER_TYPE.TEXT: {
      this.refs.textFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.REGEX: {
      this.refs.regexFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.SELECT: {
      this.refs.selectFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.NUMBER: {
      this.refs.numberFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.DATE: {
      this.refs.dateFilter.cleanFiltered();
      break;
    }
    case Const.FILTER_TYPE.CUSTOM: {
      this.refs.customFilter.cleanFiltered();
      break;
    }
    }
  }

  applyFilter(val) {
    if (this.props.filter === undefined) return;
    switch (this.props.filter.type) {
    case Const.FILTER_TYPE.TEXT: {
      this.refs.textFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.REGEX: {
      this.refs.regexFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.SELECT: {
      this.refs.selectFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.NUMBER: {
      this.refs.numberFilter.applyFilter(val);
      break;
    }
    case Const.FILTER_TYPE.DATE: {
      this.refs.dateFilter.applyFilter(val);
      break;
    }
    }
  }
}

const filterTypeArray = [];
for (const key in Const.FILTER_TYPE) {
  filterTypeArray.push(Const.FILTER_TYPE[key]);
}

TableHeaderColumn.propTypes = {
  dataField: PropTypes.string,
  dataAlign: PropTypes.string,
  headerAlign: PropTypes.string,
  headerTitle: PropTypes.bool,
  headerText: PropTypes.string,
  dataSort: PropTypes.bool,
  onSort: PropTypes.func,
  dataFormat: PropTypes.func,
  csvFormat: PropTypes.func,
  csvHeader: PropTypes.string,
  isKey: PropTypes.bool,
  editable: PropTypes.any,
  hidden: PropTypes.bool,
  hiddenOnInsert: PropTypes.bool,
  searchable: PropTypes.bool,
  className: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func
  ]),
  width: PropTypes.string,
  sortFunc: PropTypes.func,
  sortFuncExtraData: PropTypes.any,
  columnClassName: PropTypes.any,
  editColumnClassName: PropTypes.any,
  invalidEditColumnClassName: PropTypes.any,
  columnTitle: PropTypes.bool,
  filterFormatted: PropTypes.bool,
  filterValue: PropTypes.func,
  sort: PropTypes.string,
  caretRender: PropTypes.func,
  formatExtraData: PropTypes.any,
  csvFormatExtraData: PropTypes.any,
  filter: PropTypes.shape({
    type: PropTypes.oneOf(filterTypeArray),
    delay: PropTypes.number,
    options: PropTypes.oneOfType([
      PropTypes.object, // for SelectFilter
      PropTypes.arrayOf(PropTypes.number) // for NumberFilter
    ]),
    numberComparators: PropTypes.arrayOf(PropTypes.string),
    emitter: PropTypes.object,
    placeholder: PropTypes.string,
    getElement: PropTypes.func,
    customFilterParameters: PropTypes.object,
    condition: PropTypes.oneOf([ Const.FILTER_COND_EQ, Const.FILTER_COND_LIKE ])
  }),
  sortIndicator: PropTypes.bool,
  export: PropTypes.bool,
  expandable: PropTypes.bool,
  tdAttr: PropTypes.object,
  tdStyle: PropTypes.object,
  thStyle: PropTypes.object
};

TableHeaderColumn.defaultProps = {
  dataAlign: 'left',
  headerAlign: undefined,
  headerTitle: true,
  dataSort: false,
  dataFormat: undefined,
  csvFormat: undefined,
  csvHeader: undefined,
  isKey: false,
  editable: true,
  onSort: undefined,
  hidden: false,
  hiddenOnInsert: false,
  searchable: true,
  className: '',
  columnTitle: false,
  width: null,
  sortFunc: undefined,
  columnClassName: '',
  editColumnClassName: '',
  invalidEditColumnClassName: '',
  filterFormatted: false,
  filterValue: undefined,
  sort: undefined,
  formatExtraData: undefined,
  sortFuncExtraData: undefined,
  filter: undefined,
  sortIndicator: true,
  expandable: true,
  tdAttr: undefined,
  tdStyle: undefined,
  thStyle: undefined
};

export default TableHeaderColumn;
<|endoftext|>


<commit_before>import React from 'react';
import classSet from 'classnames';
import Const from './Const';
import Util from './util';
import DateFilter from './filters/Date';
import TextFilter from './filters/Text';
import SelectFilter from './filters/Select';
import NumberFilter from './filters/Number';

class TableHeaderColumn extends React.Component{

  constructor(props) {
    super(props);
    this.handleFilter = this.handleFilter.bind(this);
  }

  handleColumnClick(e){
    if(!this.props.dataSort)return;
    let order = this.props.sort == Const.SORT_DESC?Const.SORT_ASC:Const.SORT_DESC;
    this.props.onSort(order, this.props.dataField);
  }

  handleFilter(value, type) {
    this.props.filter.emitter.handleFilter(this.props.dataField, value, type);
  }

  getFilters() {
    switch (this.props.filter.type) {
      case Const.FILTER_TYPE.TEXT: {
        return <TextFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.SELECT: {
        return <SelectFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.NUMBER: {
        return <NumberFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.DATE: {
        return <DateFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.CUSTOM: {
        return this.props.filter.getElement(this.handleFilter, this.props.filter.customFilterParameters);
      }
    }
  }

  componentDidMount(){
    this.refs["header-col"].setAttribute("data-field", this.props.dataField);
  }

  render(){
    let defaultCaret;
    var thStyle = {
      textAlign: this.props.dataAlign,
      display: this.props.hidden?"none":null
    };
    if(this.props.sortIndicator) {
      defaultCaret = (!this.props.dataSort) ? null : (

      );
    }
    const sortCaret = this.props.sort ? Util.renderReactSortCaret(this.props.sort) : defaultCaret;

    var classes = this.props.className+" "+(this.props.dataSort?"sort-column":"");
    return(

        {this.props.children}{sortCaret}
        {this.props.filter ? this.getFilters() : null}

    )
  }
}

var filterTypeArray = [];
for (let key in Const.FILTER_TYPE) {
  filterTypeArray.push(Const.FILTER_TYPE[key]);
}

TableHeaderColumn.propTypes = {
  dataField: React.PropTypes.string,
  dataAlign: React.PropTypes.string,
  dataSort: React.PropTypes.bool,
  onSort: React.PropTypes.func,
  dataFormat: React.PropTypes.func,
  isKey: React.PropTypes.bool,
  editable: React.PropTypes.any,
  hidden: React.PropTypes.bool,
  searchable: React.PropTypes.bool,
  className:React.PropTypes.string,
  width: React.PropTypes.string,
  sortFunc: React.PropTypes.func,
  columnClassName: React.PropTypes.any,
  filterFormatted: React.PropTypes.bool,
  sort: React.PropTypes.string,
  formatExtraData: React.PropTypes.any,
  filter: React.PropTypes.shape({
    type: React.PropTypes.oneOf(filterTypeArray),
    delay: React.PropTypes.number,
    options: React.PropTypes.oneOfType([
      React.PropTypes.object, // for SelectFilter
      React.PropTypes.arrayOf(React.PropTypes.number) //for NumberFilter
        ]),
    numberComparators: React.PropTypes.arrayOf(React.PropTypes.string),
    emitter: React.PropTypes.object,
    placeholder: React.PropTypes.string,
    getElement: React.PropTypes.func,
    customFilterParameters: React.PropTypes.object
  }),
  sortIndicator: React.PropTypes.bool
};

TableHeaderColumn.defaultProps = {
  dataAlign: "left",
  dataSort: false,
  dataFormat: undefined,
  isKey: false,
  editable: true,
  onSort: undefined,
  hidden: false,
  searchable: true,
  className: "",
  width: null,
  sortFunc: undefined,
  columnClassName: '',
  filterFormatted: false,
  sort: undefined,
  formatExtraData: undefined,
  filter: undefined,
  sortIndicator: true
};

export default TableHeaderColumn;
<commit_msg>fix conflict<commit_after>import React from 'react';
import classSet from 'classnames';
import Const from './Const';
import Util from './util';
import DateFilter from './filters/Date';
import TextFilter from './filters/Text';
import SelectFilter from './filters/Select';
import NumberFilter from './filters/Number';

class TableHeaderColumn extends React.Component{

  constructor(props) {
    super(props);
    this.handleFilter = this.handleFilter.bind(this);
  }

  handleColumnClick(e){
    if(!this.props.dataSort)return;
    let order = this.props.sort == Const.SORT_DESC?Const.SORT_ASC:Const.SORT_DESC;
    this.props.onSort(order, this.props.dataField);
  }

  handleFilter(value, type) {
    this.props.filter.emitter.handleFilter(this.props.dataField, value, type);
  }

  getFilters() {
    switch (this.props.filter.type) {
      case Const.FILTER_TYPE.TEXT: {
        return <TextFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.SELECT: {
        return <SelectFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.NUMBER: {
        return <NumberFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.DATE: {
        return <DateFilter {...this.props.filter} columnName={this.props.children} filterHandler={this.handleFilter} />;
      }
      case Const.FILTER_TYPE.CUSTOM: {
        return this.props.filter.getElement(this.handleFilter, this.props.filter.customFilterParameters);
      }
    }
  }

  componentDidMount(){
    this.refs["header-col"].setAttribute("data-field", this.props.dataField);
  }

  render(){
    let defaultCaret;
    var thStyle = {
      textAlign: this.props.dataAlign,
      display: this.props.hidden?"none":null
    };
    if(this.props.sortIndicator) {
      defaultCaret = (!this.props.dataSort) ? null : (

      );
    }
    const sortCaret = this.props.sort ? Util.renderReactSortCaret(this.props.sort) : defaultCaret;

    var classes = this.props.className+" "+(this.props.dataSort?"sort-column":"");
    return(

        {this.props.children}{sortCaret}
        {this.props.filter ? this.getFilters() : null}

    )
  }
}

var filterTypeArray = [];
for (let key in Const.FILTER_TYPE) {
  filterTypeArray.push(Const.FILTER_TYPE[key]);
}

TableHeaderColumn.propTypes = {
  dataField: React.PropTypes.string,
  dataAlign: React.PropTypes.string,
  dataSort: React.PropTypes.bool,
  onSort: React.PropTypes.func,
  dataFormat: React.PropTypes.func,
  isKey: React.PropTypes.bool,
  editable: React.PropTypes.any,
  hidden: React.PropTypes.bool,
  searchable: React.PropTypes.bool,
  className:React.PropTypes.string,
  width: React.PropTypes.string,
  sortFunc: React.PropTypes.func,
  columnClassName: React.PropTypes.any,
  filterFormatted: React.PropTypes.bool,
  sort: React.PropTypes.string,
  formatExtraData: React.PropTypes.any,
  filter: React.PropTypes.shape({
    type: React.PropTypes.oneOf(filterTypeArray),
    delay: React.PropTypes.number,
    options: React.PropTypes.oneOfType([
      React.PropTypes.object, // for SelectFilter
      React.PropTypes.arrayOf(React.PropTypes.number) //for NumberFilter
        ]),
    numberComparators: React.PropTypes.arrayOf(React.PropTypes.string),
    emitter: React.PropTypes.object,
    placeholder: React.PropTypes.string,
    getElement: React.PropTypes.func,
    customFilterParameters: React.PropTypes.object
  }),
  sortIndicator: React.PropTypes.bool
};

TableHeaderColumn.defaultProps = {
  dataAlign: "left",
  dataSort: false,
  dataFormat: undefined,
  isKey: false,
  editable: true,
  onSort: undefined,
  hidden: false,
  searchable: true,
  className: "",
  width: null,
  sortFunc: undefined,
  columnClassName: '',
  filterFormatted: false,
  sort: undefined,
  formatExtraData: undefined,
  filter: undefined,
  sortIndicator: true
};

export default TableHeaderColumn;
<|endoftext|>


<commit_before>var showDelay = 2;
var hideDelay = 2;
var customColors = true;
var foreground = "#FF0000";
var background = "#FFFFFF";

self.port.on("pref-init", function(prefs) {
    var showDelay = prefs[0];
    var hideDelay = prefs[1];
    var customColors = prefs[2];
    var foreground = prefs[3];
    var background = prefs[4];
});

self.port.on("pref-changed", function(prefs) {
    switch (prefs[0]) {
        case "showDelay":
            showDelay = prefs[1];
            break;
        case "hideDelay":
            hideDelay = prefs[1];
            break;
        case "customColors":
            customColors = prefs[1];
            break;
        case "foreground":
            foreground = prefs[1];
            break;
        case "background":
            background = prefs[1];
            break;
    }
});

function ShowPasswordField(obj) {
    var self = this;
    self.obj = obj;
    self.showed = false;
    self.hiddenWithoutExit = false;
    self.showTimer = null;
    self.hideTimer = null;

    self.foreground = self.obj.style.color;
    self.background = self.obj.style.background;

    self.onEnter = function() {
        if (self.hiddenWithoutExit) return; // Avoid re-show after an hide for blur
        // Cancel hide action
        if (self.hideTimer != null) {
            window.clearTimeout(self.hideTimer);
            self.hideTimer = null;
        }
        // Set show action
        if (self.showTimer == null) {
            self.showTimer = window.setTimeout(
                function() {
                    self.showTimer = null;
                    self.show();
                },
                showDelay * 1000
            );
        }
    };
    self.onExit = function() {
        // Cancel show action
        if (self.showTimer != null) {
            window.clearTimeout(self.showTimer);
            self.showTimer = null;
        }
        // Set hide action
        if (self.hideTimer == null) {
            self.hideTimer = window.setTimeout(
                function() {
                    self.hideTimer = null;
                    self.hide();
                    self.hiddenWithoutExit = false;
                },
                hideDelay * 1000
            );
        }
    };

    self.change = function(type, fg, bg) {
        // Save selection
        var selectionStart = self.obj.selectionStart;
        var selectionEnd = self.obj.selectionEnd;

        // Apply custom colors
        if (customColors) {
            self.obj.style.color = fg;
            self.obj.style.background = bg;
        }

        // Change field type
        self.obj.type = type;

        // Restore selection
        self.obj.selectionStart = selectionStart;
        self.obj.selectionEnd = selectionEnd;
    };
    self.show = function() {
        if (!self.showed) {
            self.change("text", foreground, background);
            self.showed = true;
        }
    };
    self.hide = function() {
        if (self.showed) {
            self.change("password", self.foreground, self.background);
            self.showed = false;
            self.hiddenWithoutExit = true;
        }
    };

    self.obj.addEventListener("mouseover", self.onEnter, false);
    self.obj.addEventListener("mouseout", self.onExit, false);
    self.obj.addEventListener("blur", self.hide, false);
}

var passwordFields = document.evaluate('.//input[@type="password"]', document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
var num_passwordFields = passwordFields.snapshotLength;
for (var i = 0; i < num_passwordFields; ++i) {
    console.log("Found - " + passwordFields.snapshotItem(i).name);
    new ShowPasswordField(passwordFields.snapshotItem(i));
}
console.log("Setup done for " + num_passwordFields + " password fields");
<commit_msg>Changed field scanning<commit_after>var showDelay = 2;
var hideDelay = 2;
var customColors = true;
var foreground = "#FF0000";
var background = "#FFFFFF";

self.port.on("pref-init", function(prefs) {
    var showDelay = prefs[0];
    var hideDelay = prefs[1];
    var customColors = prefs[2];
    var foreground = prefs[3];
    var background = prefs[4];
});

self.port.on("pref-changed", function(prefs) {
    switch (prefs[0]) {
        case "showDelay":
            showDelay = prefs[1];
            break;
        case "hideDelay":
            hideDelay = prefs[1];
            break;
        case "customColors":
            customColors = prefs[1];
            break;
        case "foreground":
            foreground = prefs[1];
            break;
        case "background":
            background = prefs[1];
            break;
    }
});

function ShowPasswordField(obj) {
    var self = this;
    self.obj = obj;
    self.showed = false;
    self.hiddenWithoutExit = false;
    self.showTimer = null;
    self.hideTimer = null;

    self.foreground = self.obj.style.color;
    self.background = self.obj.style.background;

    self.onEnter = function() {
        if (self.hiddenWithoutExit) return; // Avoid re-show after an hide for blur
        // Cancel hide action
        if (self.hideTimer != null) {
            window.clearTimeout(self.hideTimer);
            self.hideTimer = null;
        }
        // Set show action
        if (self.showTimer == null) {
            self.showTimer = window.setTimeout(
                function() {
                    self.showTimer = null;
                    self.show();
                },
                showDelay * 1000
            );
        }
    };
    self.onExit = function() {
        // Cancel show action
        if (self.showTimer != null) {
            window.clearTimeout(self.showTimer);
            self.showTimer = null;
        }
        // Set hide action
        if (self.hideTimer == null) {
            self.hideTimer = window.setTimeout(
                function() {
                    self.hideTimer = null;
                    self.hide();
                    self.hiddenWithoutExit = false;
                },
                hideDelay * 1000
            );
        }
    };

    self.change = function(type, fg, bg) {
        // Save selection
        var selectionStart = self.obj.selectionStart;
        var selectionEnd = self.obj.selectionEnd;

        // Apply custom colors
        if (customColors) {
            self.obj.style.color = fg;
            self.obj.style.background = bg;
        }

        // Change field type
        self.obj.type = type;

        // Restore selection
        self.obj.selectionStart = selectionStart;
        self.obj.selectionEnd = selectionEnd;
    };
    self.show = function() {
        if (!self.showed) {
            self.change("text", foreground, background);
            self.showed = true;
        }
    };
    self.hide = function() {
        if (self.showed) {
            self.change("password", self.foreground, self.background);
            self.showed = false;
            self.hiddenWithoutExit = true;
        }
    };

    self.obj.addEventListener("mouseover", self.onEnter, false);
    self.obj.addEventListener("mouseout", self.onExit, false);
    self.obj.addEventListener("blur", self.hide, false);
}

var inputFields = document.getElementsByTagName("input");
var num_inputFields = inputFields.length;
var num_passwordFields = 0;
for (var i = 0; i < num_inputFields; ++i) {
    var field = inputFields[i];
    if (field.type.toLowerCase() != "password")
        continue;
    console.log("Found - " + field.name);
    new ShowPasswordField(field);
    ++num_passwordFields;
}
console.log("Setup done for " + num_passwordFields + " password fields");
<|endoftext|>


<commit_before>var path = require('path');
var webpack = require('webpack');
var DirectoryNamedWebpackPlugin = require("directory-named-webpack-plugin");
var WebpackNotifierPlugin = require('webpack-notifier');

module.exports = {
  devtool: 'source-map', // 'eval'
  entry: [
    'webpack-hot-middleware/client',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/'
  },
  plugins: [
    new webpack.ResolverPlugin(new DirectoryNamedWebpackPlugin()),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"development"'
    }),
    new WebpackNotifierPlugin()
  ],
  resolve: {
    extensions: ['', '.js', '.jsx'],
    root: path.resolve('./src/'),
    modulesDirectories: ['node_modules']
  },
  module: {
    loaders: [
      {
        test: /(\.js|\.jsx)$/,
        loaders: ['babel'],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        loader: "style-loader!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]"
      },
      {
        test: /\.less$/,
        loaders: [
          'style',
          'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
          'less'
        ]
      },
      {
        test: /\.png$/,
        loader: "url-loader?limit=100000"
      },
      {
        test: /\.jpg$/,
        loader: "file-loader"
      },
      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: "url-loader?limit=10000&mimetype=application/font-woff"
      },
      {
        test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: "file-loader"
      }
    ]
  }
};
<commit_msg>Enabled CSS source maps <commit_after>var path = require('path');
var webpack = require('webpack');
var DirectoryNamedWebpackPlugin = require("directory-named-webpack-plugin");
var WebpackNotifierPlugin = require('webpack-notifier');

module.exports = {
  devtool: 'source-map', // 'eval'
  entry: [
    'webpack-hot-middleware/client',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/'
  },
  plugins: [
    new webpack.ResolverPlugin(new DirectoryNamedWebpackPlugin()),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"development"'
    }),
    new WebpackNotifierPlugin()
  ],
  resolve: {
    extensions: ['', '.js', '.jsx'],
    root: path.resolve('./src/'),
    modulesDirectories: ['node_modules']
  },
  module: {
    loaders: [
      {
        test: /(\.js|\.jsx)$/,
        loaders: ['babel'],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        loader: "style-loader!css-loader?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]"
      },
      {
        test: /\.less$/,
        loaders: [
          'style',
          'css?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
          'less'
        ]
      },
      {
        test: /\.png$/,
        loader: "url-loader?limit=100000"
      },
      {
        test: /\.jpg$/,
        loader: "file-loader"
      },
      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: "url-loader?limit=10000&mimetype=application/font-woff"
      },
      {
        test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: "file-loader"
      }
    ]
  }
};
<|endoftext|>


<commit_before>hqDefine("userreports/js/widgets", [
    'jquery',
], function ($) {
    $(function () {
        $(".submit-dropdown-form").click(function (e) {
            e.preventDefault();
            var $form = $("#dropdown-form");
            $form.attr("action", $(this).data("action"));
            $form.submit();
        });
    });
});
<commit_msg>initialize popover in JS<commit_after>hqDefine("userreports/js/widgets", [
    'jquery',
], function ($) {
    $(function () {
        $('#data-source-rebuild-btn').popover();
        $(".submit-dropdown-form").click(function (e) {
            e.preventDefault();
            var $form = $("#dropdown-form");
            $form.attr("action", $(this).data("action"));
            $form.submit();
        });
    });
});
<|endoftext|>


<commit_before>orion.attributes.registerAttribute('createdBy', {
  previewTemplate: 'createdByPreview',
  getSchema: function(options) {
    return {
      type: String,
      index: 1,
      autoform: {
        omit: true
      },
      optional: true,
      autoValue: function() {
        if (this.isInsert) {
          return this.userId;
        } else if (this.isUpsert) {
          return { $setOnInsert: this.userId };
        } else {
          this.unset();
        }
      }
    };
  }
});

if (Meteor.isServer) {
  Meteor.publish('userProfileForCreatedByAttributeColumn', function(userId) {
    check(userId, String);
    return Meteor.users.find({ _id: userId }, { fields: { profile: 1 } });
  });
}
if (Meteor.isClient) {
  ReactiveTemplates.onRendered('attributePreview.createdBy', function() {
    this.subscribe('userProfileForCreatedByAttributeColumn', this.data.value);
  });
  ReactiveTemplates.helpers('attributePreview.createdBy', {
    name: function() {
      var user = Meteor.users.findOne(this.value);
      return user && user.profile.name;
    }
  });
}
<commit_msg>Fix bug with createdBy attribute column<commit_after>orion.attributes.registerAttribute('createdBy', {
  previewTemplate: 'createdByPreview',
  getSchema: function(options) {
    return {
      type: String,
      index: 1,
      autoform: {
        omit: true,
      },
      optional: true,
      autoValue: function() {
        if (this.isInsert) {
          return this.userId;
        } else if (this.isUpsert) {
          return { $setOnInsert: this.userId };
        } else {
          this.unset();
        }
      },
    };
  },
});

if (Meteor.isServer) {
  Meteor.publish('userProfileForCreatedByAttributeColumn', function(userId) {
    check(userId, String);
    return Meteor.users.find({ _id: userId }, { fields: { profile: 1 } });
  });
}

if (Meteor.isClient) {
  ReactiveTemplates.onRendered('attributePreview.createdBy', function() {
    this.subscribe('userProfileForCreatedByAttributeColumn', this.data.value);
  });

  ReactiveTemplates.helpers('attributePreview.createdBy', {
    name: function() {
      var user = Meteor.users.findOne(this.value);
      return user && user.profile && user.profile.name;
    },
  });
}
<|endoftext|>


<commit_before>var outputFile = require("output-file-sync");
var template   = require("babel-template");
var helpers    = require("babel-helpers");
var babel      = require("../../babel-core");
var each       = require("lodash/collection/each");
var util       = require("../../babel-core/lib/util");
var fs         = require("fs");
var t          = require("../../babel-types");
var _          = require("lodash");

function relative(filename) {
  return __dirname + "/../" + filename;
}

function readFile(filename, shouldDefaultify) {
  var file = fs.readFileSync(require.resolve(filename), "utf8");

  if (shouldDefaultify) {
    file += "\n" + defaultify("module.exports") + "\n";
  }

  return file;
}

function defaultify(name) {
  return 'module.exports = { "default": ' + name + ', __esModule: true };';
}

function writeRootFile(filename, content) {
  filename = relative(filename);
  console.log(filename);
  outputFile(filename, content);
}

var buildHelperHead = template("exports.default = HELPER; exports.__esModule = true;");

function writeFile(filename, content) {
  return writeRootFile(filename, content);
}

var transformOpts = {
  presets: [
    require("../../babel-preset-es2015")
  ],

  plugins: [
    require("../../babel-plugin-transform-runtime"),
    require("../../babel-plugin-transform-es2015-modules-commonjs")
  ]
};

function selfContainify(code) {
  return babel.transform(code, transformOpts).code;
}

function buildHelper(helperName) {
  var tree = t.program(
    buildHelperHead({
      HELPER: helpers.get(helperName)
    })
  );

  return babel.transformFromAst(tree, null, transformOpts).code;
}

each(helpers.list, function (helperName) {
  writeFile("helpers/" + helperName + ".js", buildHelper(helperName));
});

writeFile("regenerator/index.js", readFile("regenerator/runtime-module", true));
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator/runtime")));

var coreDefinitions = require("babel-plugin-transform-runtime/lib/definitions");

var paths = ["is-iterable", "get-iterator"];

each(coreDefinitions.builtins, function (path) {
  paths.push(path);
});

each(coreDefinitions.methods, function (props) {
  each(props, function (path) {
    paths.push(path);
  });
});

each(paths, function (path) {
  writeFile("core-js/" + path + ".js", defaultify('require("core-js/library/fn/' + path + '")'));
});
<commit_msg>Remove unused Lodash import<commit_after>var outputFile = require("output-file-sync");
var template   = require("babel-template");
var helpers    = require("babel-helpers");
var babel      = require("../../babel-core");
var each       = require("lodash/collection/each");
var util       = require("../../babel-core/lib/util");
var fs         = require("fs");
var t          = require("../../babel-types");

function relative(filename) {
  return __dirname + "/../" + filename;
}

function readFile(filename, shouldDefaultify) {
  var file = fs.readFileSync(require.resolve(filename), "utf8");

  if (shouldDefaultify) {
    file += "\n" + defaultify("module.exports") + "\n";
  }

  return file;
}

function defaultify(name) {
  return 'module.exports = { "default": ' + name + ', __esModule: true };';
}

function writeRootFile(filename, content) {
  filename = relative(filename);
  console.log(filename);
  outputFile(filename, content);
}

var buildHelperHead = template("exports.default = HELPER; exports.__esModule = true;");

function writeFile(filename, content) {
  return writeRootFile(filename, content);
}

var transformOpts = {
  presets: [
    require("../../babel-preset-es2015")
  ],

  plugins: [
    require("../../babel-plugin-transform-runtime"),
    require("../../babel-plugin-transform-es2015-modules-commonjs")
  ]
};

function selfContainify(code) {
  return babel.transform(code, transformOpts).code;
}

function buildHelper(helperName) {
  var tree = t.program(
    buildHelperHead({
      HELPER: helpers.get(helperName)
    })
  );

  return babel.transformFromAst(tree, null, transformOpts).code;
}

each(helpers.list, function (helperName) {
  writeFile("helpers/" + helperName + ".js", buildHelper(helperName));
});

writeFile("regenerator/index.js", readFile("regenerator/runtime-module", true));
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator/runtime")));

var coreDefinitions = require("babel-plugin-transform-runtime/lib/definitions");

var paths = ["is-iterable", "get-iterator"];

each(coreDefinitions.builtins, function (path) {
  paths.push(path);
});

each(coreDefinitions.methods, function (props) {
  each(props, function (path) {
    paths.push(path);
  });
});

each(paths, function (path) {
  writeFile("core-js/" + path + ".js", defaultify('require("core-js/library/fn/' + path + '")'));
});
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var chai = require('chai');
var sinon = require('sinon');
var should = chai.should();
var Lock = require('../lib/lock');
var helpers = require('./integration/helpers');

describe('Locks', function() {
  var lock, clock, order = [];

  before(function(done) {
    helpers.before(function(res) {
      done();
    });
  });
  beforeEach(function(done) {
    var self = this;
    helpers.beforeEach(function(res) {
      let storage = res.storage;
      lock = new Lock(storage);
      order = [];
      done();
    });
  });
  afterEach(function() {
  });

  function pushEvent(i) {
    order.push(i);
  }

  it('should lock tasks using the same token', function(done) {
    var a = false,
      b = false,
      step = 100;

    pushEvent(0);

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      setTimeout(function() {
        release();
      }, step);
      lock.acquire('123', {}, function(err, release) {
        should.not.exist(err);
        pushEvent(2);
        setTimeout(function() {
          release();
        }, step);
        lock.acquire('123', {}, function(err, release) {
          should.not.exist(err);
          pushEvent(3);
          setTimeout(function() {
            release();
            order.should.be.deep.equal([0,4,1,5,2,6,3]);
            done();
          },step);
        });
        pushEvent(6);
      });
      pushEvent(5);
    });
    pushEvent(4);

  });

  it('should call waiting tasks', function(done) {
    var a = false,
      b = false,
      step = 100;

    pushEvent(0);

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      setTimeout(function() {
        release();
      }, step);
    }, 1);
    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(2);
      setTimeout(function() {
        release();
      }, step);
    }, 2);
    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(3);
      setTimeout(function() {
        release();
      }, step);
    }, 3);
    pushEvent(4);

    setTimeout(function() {
      order[1].should.equal(4);

      //order is not assured
      _.difference([0,4,1,2,3], order).should.be.empty();

      done();
    }, 3*step);

  });

  it('should not lock tasks using different tokens', function(done) {
    var step=100;

    pushEvent(0);

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      setTimeout(function() {
        release();
      }, step);
      lock.acquire('123', {}, function(err, release) {
        should.not.exist(err);
        pushEvent(2);
        setTimeout(function() {
          release();
          order.indexOf(3).should.be.below(order.indexOf(2));
          done();
        }, step);
      });

    });

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(3);
      setTimeout(function() {
        release();
      }, step);
    });
  });
  it('should return error if unable to acquire lock', function(done) {

    var step=100, err1;

    pushEvent(0);

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      setTimeout(function() {
        release();
        err1.should.contain('LOCKED');
        done();
      }, step);
      lock.acquire('123', {waitTime:1}, function(err, release) {
        err1 = err;
      },2);
    }, 1);
  });
  it('should release lock if acquired for a long time', function(done) {

    var step=100;

    lock.acquire('123', {lockTime:10}, function(err, release) {
      should.not.exist(err);
      lock.acquire('123', {waitTime:1000}, function(err, release) {
        should.not.exist(err);
        done();
      },2);
    }, 1);
  });

  describe("#runLocked", () => {
    it('should run a locked function', function(done) {
      var step=100;
      var called =0;

      function end() {
        called++;
      }

      function task() {
        setTimeout(() => {
          called.should.equal(0);
          done();
        },200);
      }

      lock.runLocked('123', {}, end, task);
    });

    it('should lock locked functions', function(done) {
      var step=100;
      var called =0;

      function end() {
        called++;
        called.should.equal(1);
        done();
      }

      function task() {
        lock.runLocked('123', {waitTime:100}, end, () => {
          setTimeout(() => {
          },200);
        });
     }

      lock.runLocked('123', {}, end, task);
    });

  });

});
<commit_msg>better tests<commit_after>'use strict';

var _ = require('lodash');
var chai = require('chai');
var sinon = require('sinon');
var should = chai.should();
var Lock = require('../lib/lock');
var helpers = require('./integration/helpers');

    var step=50;

describe('Locks', function() {
  var lock, clock, order = [];

  before(function(done) {
    helpers.before(function(res) {
      done();
    });
  });
  beforeEach(function(done) {
    var self = this;
    helpers.beforeEach(function(res) {
      let storage = res.storage;
      lock = new Lock(storage);
      order = [];
      done();
    });
  });
  afterEach(function() {
  });

  function pushEvent(i) {
    order.push(i);
  }

  it('should lock tasks using the same token', function(done) {
    pushEvent(0);

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      setTimeout(function() {
        release();
      }, step);
      lock.acquire('123', {}, function(err, release) {
        should.not.exist(err);
        pushEvent(2);
        setTimeout(function() {
          release();
        }, step);
        lock.acquire('123', {}, function(err, release) {
          should.not.exist(err);
          pushEvent(3);
          setTimeout(function() {
            release();
            order.should.be.deep.equal([0,4,1,5,2,6,3]);
            done();
          },step);
        });
        pushEvent(6);
      });
      pushEvent(5);
    });
    pushEvent(4);

  });

  it('should call waiting tasks', function(done) {
    pushEvent(0);

    function testDone() {
      if ( _.isEmpty(_.difference([0,4,1,2,3], order)) ) {
        pushEvent('done');
        done();
      }
    }

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      setTimeout(function() {
        release();
        testDone();
      }, step);
    }, 1);
    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(2);
      setTimeout(function() {
        release();
        testDone();
      }, step);
    }, 2);
    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(3);
      setTimeout(function() {
        release();
        testDone();
      }, step);
    }, 3);
    pushEvent(4);

  });

  it('should not lock tasks using different tokens', function(done) {

    pushEvent(0);

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      setTimeout(function() {
        release();
      }, step);
      lock.acquire('123', {}, function(err, release) {
        should.not.exist(err);
        pushEvent(2);
        setTimeout(function() {
          release();
          order.indexOf(3).should.be.below(order.indexOf(2));
          done();
        }, step);
      });

    });

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(3);
      setTimeout(function() {
        release();
      }, step);
    });
  });
  it('should return error if unable to acquire lock', function(done) {

    var err1;

    pushEvent(0);

    lock.acquire('123', {}, function(err, release) {
      should.not.exist(err);
      pushEvent(1);
      lock.acquire('123', {waitTime:1}, function(err, release2) {
        release();
        err.should.contain('LOCKED');
        done();
      },2);
    }, 1);
  });
  it('should release lock if acquired for a long time', function(done) {

    lock.acquire('123', {lockTime:10}, function(err, release) {
      should.not.exist(err);
      lock.acquire('123', {waitTime:1000}, function(err, release) {
        should.not.exist(err);
        done();
      },2);
    }, 1);
  });

  describe("#runLocked", () => {
    it('should run a locked function', function(done) {
      var called =0;

      function end() {
        called++;
      }

      function task() {
        setTimeout(() => {
          called.should.equal(0);
          done();
        },200);
      }

      lock.runLocked('123', {}, end, task);
    });

    it('should lock locked functions', function(done) {
      var called =0;

      function end() {
        called++;
        called.should.equal(1);
        done();
      }

      function task() {
        lock.runLocked('123', {waitTime:100}, end, () => {
          setTimeout(() => {
          },200);
        });
     }

      lock.runLocked('123', {}, end, task);
    });

  });

});
<|endoftext|>