<commit_before>// ==========================================================================
// Project:   The M-Project - Mobile HTML5 Application Framework
// Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved.
// Creator:   Dominik
// Date:      23.11.2010
// License:   Dual licensed under the MIT or GPL Version 2 licenses.
//            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
//            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
// ==========================================================================

m_require('ui/dialog.js');

/**
 * @class
 *
 * This is the prototype for any alert dialog view. It is derived from M.DialogView
 * and mainly used for implementing a alert dialog view specific render method.
 *
 * @extends M.DialogView
 */
M.AlertDialogView = M.DialogView.extend(
/** @scope M.AlertDialogView.prototype */ {

    /**
     * The type of this object.
     *
     * @type String
     */
    type: 'M.AlertDialogView',

    /**
     * The default title of an alert dialog.
     *
     * @type String
     */
    title: 'Alert',

    /**
     * The default message of an alert dialog.
     *
     * @type String
     */
    message: '',

    /**
     * Determines whether the alert dialog gets a default ok button.
     *
     * @type Boolean
     */
    hasOkButton: YES,

    /**
     * Determines the value of the button, means the text label on it.
     *
     * @type String
     */
    confirmButtonValue: 'Ok',

    /**
     * Renders an alert dialog as a pop up
     *
     * @private
     * @returns {String} The alert dialog view's html representation.
     */
    render: function() {
        this.html = '

';
        this.html += '
';
        this.html += '
';
        this.html += this.title ? this.title : '';
        this.html +='
';
        this.html += '
';
        this.html += this.message;
        this.html +='
';
        var button;
        if(this.hasOkButton) {
            this.html += '
';
            var that = this;
            button = M.ButtonView.design({
                value: this.confirmButtonValue,
                cssClass: 'b tmp-dialog-smallerbtn',
                events: {
                    tap: {
                        target: that,
                        action: 'hide'
                    }
                }
            });
            this.html += button.render();
            this.html += '
';
        }
        this.html += '
';

        $('body').append(this.html);
        if(button.type) {
            button.registerEvents();
            button.theme();
        }
    },

    show: function() {
        /* call the dialog's render() */
        this.render();
        var dialog = $('#' + this.id);
        dialog.addClass('pop in');
    },

    hide: function() {
        var dialog = $('#' + this.id);
        dialog.addClass('pop out');
		$('.tmp-dialog-background').remove();
        this.destroy();
    }

});<commit_msg>added optional confirm callback to alert dialog<commit_after>// ==========================================================================
// Project:   The M-Project - Mobile HTML5 Application Framework
// Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved.
// Creator:   Dominik
// Date:      23.11.2010
// License:   Dual licensed under the MIT or GPL Version 2 licenses.
//            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
//            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
// ==========================================================================

m_require('ui/dialog.js');

/**
 * @class
 *
 * This is the prototype for any alert dialog view. It is derived from M.DialogView
 * and mainly used for implementing a alert dialog view specific render method.
 *
 * @extends M.DialogView
 */
M.AlertDialogView = M.DialogView.extend(
/** @scope M.AlertDialogView.prototype */ {

    /**
     * The type of this object.
     *
     * @type String
     */
    type: 'M.AlertDialogView',

    /**
     * The default title of an alert dialog.
     *
     * @type String
     */
    title: 'Alert',

    /**
     * The default message of an alert dialog.
     *
     * @type String
     */
    message: '',

    /**
     * Determines whether the alert dialog gets a default ok button.
     *
     * @type Boolean
     */
    hasConfirmButton: YES,

    /**
     * Determines the value of the button, means the text label on it.
     *
     * @type String
     */
    confirmButtonValue: 'Ok',

    /**
     * Renders an alert dialog as a pop up
     *
     * @private
     * @returns {String} The alert dialog view's html representation.
     */
    render: function() {
        this.html = '

';
        this.html += '
';
        this.html += '
';
        this.html += this.title ? this.title : '';
        this.html +='
';
        this.html += '
';
        this.html += this.message;
        this.html +='
';
        var button;
        if(this.hasConfirmButton) {
            this.html += '
';
            var that = this;
            button = M.ButtonView.design({
                value: this.confirmButtonValue,
                cssClass: 'b tmp-dialog-smallerbtn',
                events: {
                    tap: {
                        target: that,
                        action: 'handleCallback'
                    }
                }
            });
            this.html += button.render();
            this.html += '
';
        }
        this.html += '
';

        $('body').append(this.html);
        if(button.type) {
            button.registerEvents();
            button.theme();
        }
    },

    show: function() {
        /* call the dialog's render() */
        this.render();
        var dialog = $('#' + this.id);
        dialog.addClass('pop in');
    },

    hide: function() {
        var dialog = $('#' + this.id);
        dialog.addClass('pop out');
        $('.tmp-dialog-background').remove();
        this.destroy();
    },

    handleCallback: function() {
        this.hide();
        if(this.callbacks) {
            if(!this.callbacks.confirm) {
                M.Logger.log('There must be a sub object named "confirm" with target (type object) and action (type string) in callback object of alert dialog.', M.ERR);
            }
            this.bindToCaller(this.callbacks.confirm.target, this.callbacks.confirm.target[this.callbacks.confirm.action])();
        }
    }
});<|endoftext|>


<commit_before>#!/bin/env node

'use strict';

const chokidar = require('chokidar');
const exec = require('child_process').exec;
const fs = require('fs-extra');
const path = require('path');
const program = require('commander');

const debug = require('../lib/util/debug')('bin:import');
const die = require('../lib/util/die');
const home = require('../lib/config/home');
const imp = require('../lib/import/import');

var processChain = Promise.resolve();
const importFiles = {};
const createdDirs = {};

program
    .usage('<file>')
    .option('-l, --limit <number>', 'Limit of files to import')
    .option('-w, --watch', 'Watch files')
    .option('-c --config <path>', 'Path to custom config file')
    .parse(process.argv);

let prom = Promise.resolve();
if (program.args[0]) {
    debug(`file argument: ${program.args[0]}`);
    // TODO add 2 arguments: db and import names
    throw new Error('not ready');
    //const file = path.resolve(program.args[0]);
    //
    //prom = prom.then(() => {
    //    return imp.import(config, file);
    //});
} else if (!program.watch) {
    debug('no watch');
    // import all
    let homeDir = getHomeDir();

    prom = prom.then(() => findFiles(homeDir))
        .then(paths => {
            const limit = +program.limit || paths.length;
            debug(`limit is ${limit}`);
            var i = 0, count = 0;
            var p = Promise.resolve();
            while (count < limit && i < paths.length) {
                let file = checkFile(homeDir, paths[i]);
                if (file) {
                    count++;
                    p = processFile(file.database, file.importName, homeDir, paths[i]);
                }
                i++;
            }
            return p;
        });
} else if (program.watch) {
    // watch files to import
    let homeDir = getHomeDir();
    debug(`watch ${homeDir}`);
    chokidar.watch(homeDir, {
        ignored: /[\/\\](\.|processed|errored|node_modules)/,
        persistent: true
    }).on('all', function (event, p) {
        debug.trace(`watch event: ${event} - ${p}`);
        let file = checkFile(homeDir, p);
        if (event !== 'add' && event !== 'change' || !file) {
            return;
        }
        processFile(file.database, file.importName, homeDir, p);
    });
} else {
    die('UNREACHABLE');
}

prom.then(function () {
    debug('finished');
}, function (err) {
    die(err.message || err);
});

function findFiles(homeDir) {
    return new Promise(function (resolve, reject) {
        exec("find . -maxdepth 4 -mindepth 4 -type f -not -regex '.*/\\(processed\\|errored\\|node_modules\\|\\.\\).*'", {
            cwd: homeDir,
            maxBuffer: 10 * 1000 * 1024
        }, function (err, stdout) {
            if (err) return reject(err);
            let paths = stdout.split('\n');
            paths = paths.filter(path => path);
            debug(`findFiles found ${paths.length} files`);
            resolve(paths);
        });
    });
}

function getHomeDir() {
    let homeDir = home.homeDir;
    if (!homeDir) {
        die('homeDir must be set to import all');
    }
    return homeDir;
}

function checkFile(homeDir, p) {
    p = path.resolve(homeDir, p);
    const relpath = path.relative(homeDir, p);
    const elements = relpath.split('/');
    if (elements.length !== 4) return false;
    if (elements[2] !== 'to_process') return false;

    if (hasImportFile(p)) {
        return {
            database: elements[0],
            importName: elements[1]
        };
    }
}

function processFile(database, importName, homeDir, p) {
    debug.trace(`process file ${p}`);
    p = path.resolve(homeDir, p);
    let parsedPath = path.parse(p);

    processChain = processChain.then(() => {
        return imp.import(database, importName, p);
    }).then(() => {
        // mv to processed
        return new Promise(function (resolve, reject) {
            let dir = path.join(parsedPath.dir, '../processed/' + getMonth());
            createDir(dir);
            fs.rename(p, path.join(dir, parsedPath.base), function (err) {
                if (err) return reject(err);
                resolve();
            });
        });
    }).catch(e => {
        // mv to errored
        return new Promise(function (resolve) {
            if (e.message.startsWith('no import config')) {
                debug.warn('no import configuration found, skipping this file');
                return resolve();
            }
            debug.error(e + '\n' + e.stack);
            let dir = path.join(parsedPath.dir, '../errored/' + getMonth());
            createDir(dir);
            let toPath = path.join(dir, parsedPath.base);
            fs.rename(p, toPath, function (err) {
                if (err) debug.error(`Could could rename ${p} to ${toPath}: ${err}`);
                resolve();
            });
        });
    });

    return processChain;
}

function hasImportFile(p) {
    const importFile = path.resolve(p, '../../import.js');
    if (importFiles[p]) return true;

    try {
        fs.accessSync(importFile);
        return true;
    } catch (e) {
        return false;
    }
}

function createDir(dir) {
    if (createdDirs[dir]) return;

    fs.mkdirpSync(dir);
    createdDirs[dir] = true;
}

function getMonth() {
    var now = new Date();
    return now.getFullYear() + ('0' + (now.getMonth() + 1)).slice(-2);
}
<commit_msg>import: allow subdirectories of to_process to be scanned<commit_after>#!/bin/env node

'use strict';

const chokidar = require('chokidar');
const exec = require('child_process').exec;
const fs = require('fs-extra');
const path = require('path');
const program = require('commander');

const debug = require('../lib/util/debug')('bin:import');
const die = require('../lib/util/die');
const home = require('../lib/config/home');
const imp = require('../lib/import/import');

var processChain = Promise.resolve();
const importFiles = {};
const createdDirs = {};

program
    .usage('<file>')
    .option('-l, --limit <number>', 'Limit of files to import')
    .option('-w, --watch', 'Watch files')
    .option('-c --config <path>', 'Path to custom config file')
    .parse(process.argv);

let prom = Promise.resolve();
if (program.args[0]) {
    debug(`file argument: ${program.args[0]}`);
    // TODO add 2 arguments: db and import names
    throw new Error('not ready');
    //const file = path.resolve(program.args[0]);
    //
    //prom = prom.then(() => {
    //    return imp.import(config, file);
    //});
} else if (!program.watch) {
    debug('no watch');
    // import all
    let homeDir = getHomeDir();

    prom = prom.then(() => findFiles(homeDir))
        .then(paths => {
            const limit = +program.limit || paths.length;
            debug(`limit is ${limit}`);
            var i = 0, count = 0;
            var p = Promise.resolve();
            while (count < limit && i < paths.length) {
                let file = checkFile(homeDir, paths[i]);
                if (file) {
                    count++;
                    p = processFile(file.database, file.importName, homeDir, paths[i]);
                }
                i++;
            }
            return p;
        });
} else if (program.watch) {
    // watch files to import
    let homeDir = getHomeDir();
    debug(`watch ${homeDir}`);
    chokidar.watch(homeDir, {
        ignored: /[\/\\](\.|processed|errored|node_modules)/,
        persistent: true
    }).on('all', function (event, p) {
        debug.trace(`watch event: ${event} - ${p}`);
        let file = checkFile(homeDir, p);
        if (event !== 'add' && event !== 'change' || !file) {
            return;
        }
        processFile(file.database, file.importName, homeDir, p);
    });
} else {
    die('UNREACHABLE');
}

prom.then(function () {
    debug('finished');
}, function (err) {
    die(err.message || err);
});

function findFiles(homeDir) {
    return new Promise(function (resolve, reject) {
        exec("find . -mindepth 4 -type f -not -regex '.*/\\(processed\\|errored\\|node_modules\\|\\.\\).*'", {
            cwd: homeDir,
            maxBuffer: 10 * 1000 * 1024
        }, function (err, stdout) {
            if (err) return reject(err);
            let paths = stdout.split('\n');
            paths = paths.filter(path => path);
            debug(`findFiles found ${paths.length} files`);
            resolve(paths);
        });
    });
}

function getHomeDir() {
    let homeDir = home.homeDir;
    if (!homeDir) {
        die('homeDir must be set to import all');
    }
    return homeDir;
}

function checkFile(homeDir, p) {
    p = path.resolve(homeDir, p);
    const relpath = path.relative(homeDir, p);
    const elements = relpath.split('/');
    if (elements.length >= 4) return false;
    if (elements[2] !== 'to_process') return false;

    if (hasImportFile(p)) {
        return {
            database: elements[0],
            importName: elements[1]
        };
    }
}

function processFile(database, importName, homeDir, p) {
    debug.trace(`process file ${p}`);
    p = path.resolve(homeDir, p);
    let parsedPath = path.parse(p);

    processChain = processChain.then(() => {
        return imp.import(database, importName, p);
    }).then(() => {
        // mv to processed
        return new Promise(function (resolve, reject) {
            let dir = path.join(parsedPath.dir, '../processed/' + getMonth());
            createDir(dir);
            fs.rename(p, path.join(dir, parsedPath.base), function (err) {
                if (err) return reject(err);
                resolve();
            });
        });
    }).catch(e => {
        // mv to errored
        return new Promise(function (resolve) {
            if (e.message.startsWith('no import config')) {
                debug.warn('no import configuration found, skipping this file');
                return resolve();
            }
            debug.error(e + '\n' + e.stack);
            let dir = path.join(parsedPath.dir, '../errored/' + getMonth());
            createDir(dir);
            let toPath = path.join(dir, parsedPath.base);
            fs.rename(p, toPath, function (err) {
                if (err) debug.error(`Could could rename ${p} to ${toPath}: ${err}`);
                resolve();
            });
        });
    });

    return processChain;
}

function hasImportFile(p) {
    const importFile = path.resolve(p, '../../import.js');
    if (importFiles[p]) return true;

    try {
        fs.accessSync(importFile);
        return true;
    } catch (e) {
        return false;
    }
}

function createDir(dir) {
    if (createdDirs[dir]) return;

    fs.mkdirpSync(dir);
    createdDirs[dir] = true;
}

function getMonth() {
    var now = new Date();
    return now.getFullYear() + ('0' + (now.getMonth() + 1)).slice(-2);
}
<|endoftext|>


<commit_before>const React = require('react');
const h = require('react-hyperscript');
const classNames = require('classnames');
const Link = require('react-router-dom').Link;
const Loader = require('react-loader');
const _ = require('lodash');

const IconButton = require('../icon-button');

const debouncedSearchNodes = _.debounce(require('../../cy/search'), 300);

// cytoscape
// grapjson
// metadata

// probably in the future
// buttons
// events
// sidebar menus

// state
// layout config
// activeMenu

class BaseNetworkView extends React.Component {
  constructor(props) {
    super(props);

    if( process.env.NODE_ENV !== 'production' ){
      window.cy = props.cy;
    }

    this.state = _.merge({},
      {
        activeMenu: 'closeMenu',
        open: false,
        networkLoading: true,
        searchOpen: false
      }, props);

  }

  componentWillUnmount() {
    this.state.cy.destroy();
  }

  componentDidMount() {
    const state = this.state;
    const initialLayoutOpts = state.layoutConfig.defaultLayout.options;
    const container = this.graphDOM;

    const cy = state.cy;
    cy.mount(container);
    cy.remove('*');
    cy.add(state.networkJSON);

    const layout = cy.layout(initialLayoutOpts);
    layout.on('layoutstop', () => {
      cy.emit('network-loaded');
      this.setState({networkLoading: false});
    });
    layout.run();
  }

  changeMenu(menu) {
    if (menu === this.state.activeMenu || menu === 'closeMenu') {
      this.setState({
        activeMenu: 'closeMenu',
        open: false
      });
    } else {
      this.setState({
        activeMenu: menu,
        open: true
      });
    }
  }

  searchCyNodes(queryString) {
    debouncedSearchNodes(this.state.cy, queryString);
  }

  clearSearchBox() {
    this.searchField.value = '';
    this.searchCyNodes('');
  }

  render() {
    const state = this.state;
    const componentConfig = state.componentConfig;

    const toolbarButtons = componentConfig.toolbarButtons;
    const menus = state.componentConfig.menus;

    const activeMenu = menus.filter(menu => menu.id === state.activeMenu)[0].func(state);

    const menuButtons = toolbarButtons.filter(btn => btn.type === 'activateMenu').map(btn => {
      return (
        h('div.sidebar-tool-button-container', [
          h(IconButton, {
            key: btn.id,
            icon: btn.icon,
            active: state.activeMenu === btn.menuId,
            onClick: () => {
              this.changeMenu(btn.menuId);
            },
            desc: btn.description
          })
        ])
      );
    });

    const networkButtons = toolbarButtons.filter(btn => btn.type === 'networkAction').map(btn => {
      return (
        h(IconButton, {
          key: btn.id,
          icon: btn.icon,
          onClick: () => {
            btn.func(state);
          },
          desc: btn.description
        })
      );
    });

    const nodeSearchBar = [
      h(IconButton, {
        icon: 'search',
        key: 'search',
        active: this.state.searchOpen,
        onClick: () => {
          !this.state.searchOpen || this.clearSearchBox();
          this.setState({ searchOpen: !this.state.searchOpen }, () => {
            if (this.state.searchOpen == true) {
              this.searchField.focus();
            }
          });
        },
        desc: 'Search entities'
      }),
      h('div', {
        className: classNames('search-nodes', { 'search-nodes-open': this.state.searchOpen }),
        onChange: e => this.searchCyNodes(e.target.value)
      }, [
          h('div.view-search-bar', [
            h('input.view-search', {
              ref: dom => this.searchField = dom,
              type: 'search',
              placeholder: 'Search entities',
            }),
            h('div.view-search-clear', {
              onClick: () => this.clearSearchBox(),
            }, [h('i.material-icons', 'close')])
          ])
        ])
    ];

    const toolBar = [
      ...menuButtons,
      ...networkButtons,
      // ...(componentConfig.useLayoutDropdown ? layoutDropdown : []), // TODO re-add dropdown for edit
      ...(componentConfig.useSearchBar ? nodeSearchBar : [])
    ];

    return h('div.View', [
      h('div', { className: classNames('menu-bar', { 'menu-bar-margin': state.activeMenu }) }, [
        h('div.menu-bar-inner-container', [
          h('div.pc-logo-container', [
            h(Link, { to: { pathname: '/search' } }, [
              h('img', {
                src: '/img/icon.png'
              })
            ])
          ]),
          h('div.title-container', [
            h('h4', [
              h('span', state.networkMetadata.name),
              ' | ',
              h('a', state.networkMetadata.datasource)
            ])
          ])
        ]),
        h('div.view-toolbar', toolBar)
      ]),
      h(Loader, {
        loaded: !this.state.networkLoading,
        options: { left: '50%', color: '#16A085' },
      }),
      h('div.Graph', [
        h('div', {
          ref: dom => this.graphDOM = dom,
          style: {
            width: '100vw',
            height: '100vh',
            visibility: this.state.networkLoading ? 'hidden' : undefined
          }
        })
      ]),
      h('div', {
        className: classNames('sidebar-menu', { 'sidebar-menu-open': this.state.open })
      }, [
          h('div', {
            className: classNames('sidebar-close-button-container', { 'sidebar-close-button-container-open': this.state.open })
          }, [
              h(IconButton, {
                key: 'close',
                icon: 'close',
                onClick: () => this.changeMenu('closeMenu'),
                desc: 'Close the sidebar'
              })
            ]),
          h('div.sidebar-content', [
            h('div.sidebar-resize'),
            h('div.sidebar-text', [activeMenu])
          ])
        ])
    ]);
  }
}

module.exports = BaseNetworkView;<commit_msg>initial commit<commit_after>const React = require('react');
const h = require('react-hyperscript');
const classNames = require('classnames');
const Link = require('react-router-dom').Link;
const Loader = require('react-loader');
const _ = require('lodash');

const IconButton = require('../icon-button');

const debouncedSearchNodes = _.debounce(require('../../cy/search'), 300);

// cytoscape
// grapjson
// metadata

// probably in the future
// buttons
// events
// sidebar menus

// state
// layout config
// activeMenu

class BaseNetworkView extends React.Component {
  constructor(props) {
    super(props);

    if( process.env.NODE_ENV !== 'production' ){
      window.cy = props.cy;
    }

    this.state = _.merge({},
      {
        activeMenu: 'closeMenu',
        open: false,
        networkLoading: true,
        searchOpen: false
      }, props);

  }

  componentWillUnmount() {
    this.state.cy.destroy();
  }

  componentDidMount() {
    const state = this.state;
    const initialLayoutOpts = state.layoutConfig.defaultLayout.options;
    const container = this.graphDOM;

    const cy = state.cy;
    cy.mount(container);
    cy.remove('*');
    cy.add(state.networkJSON);

    const layout = cy.layout(initialLayoutOpts);
    layout.on('layoutstop', () => {
      cy.emit('network-loaded');
      this.setState({networkLoading: false});
    });
    layout.run();
  }

  changeMenu(menu) {
    if (menu === this.state.activeMenu || menu === 'closeMenu') {
      this.setState({
        activeMenu: 'closeMenu',
        open: false
      });
    } else {
      this.setState({
        activeMenu: menu,
        open: true
      });
    }
  }

  searchCyNodes(queryString) {
    debouncedSearchNodes(this.state.cy, queryString);
  }

  clearSearchBox() {
    this.searchField.value = '';
    this.searchCyNodes('');
  }

  render() {
    const state = this.state;
    const componentConfig = state.componentConfig;

    const toolbarButtons = componentConfig.toolbarButtons;
    const menus = state.componentConfig.menus;

    const activeMenu = menus.filter(menu => menu.id === state.activeMenu)[0].func(state);

    const menuButtons = toolbarButtons.filter(btn => btn.type === 'activateMenu').map(btn => {
      return (
        h('div.sidebar-tool-button-container', [
          h(IconButton, {
            key: btn.id,
            icon: btn.icon,
            active: state.activeMenu === btn.menuId,
            onClick: () => {
              this.changeMenu(btn.menuId);
            },
            desc: btn.description
          })
        ])
      );
    });

    const networkButtons = toolbarButtons.filter(btn => btn.type === 'networkAction').map(btn => {
      return (
        h(IconButton, {
          key: btn.id,
          icon: btn.icon,
          onClick: () => {
            btn.func(state);
          },
          desc: btn.description
        })
      );
    });

    const nodeSearchBar = [
      h(IconButton, {
        icon: 'search',
        key: 'search',
        active: this.state.searchOpen,
        onClick: () => {
          !this.state.searchOpen || this.clearSearchBox();
          this.setState({ searchOpen: !this.state.searchOpen }, () => {
            if (this.state.searchOpen == true) {
              this.searchField.focus();
            }
          });
        },
        desc: 'Search entities'
      }),
      h('div', {
        className: classNames('search-nodes', { 'search-nodes-open': this.state.searchOpen }),
        onChange: e => this.searchCyNodes(e.target.value)
      }, [
          h('div.view-search-bar', [
            h('input.view-search', {
              ref: dom => this.searchField = dom,
              type: 'search',
              placeholder: 'Search entities',
            }),

            h('div.view-search-clear', {
              onClick: () => this.clearSearchBox(),
              }, [ // check if the search bar is empty
                h('i.material-icons', 'close')])

          ])
        ])
    ];

    const toolBar = [
      ...menuButtons,
      ...networkButtons,
      // ...(componentConfig.useLayoutDropdown ? layoutDropdown : []), // TODO re-add dropdown for edit
      ...(componentConfig.useSearchBar ? nodeSearchBar : [])
    ];

    return h('div.View', [
      h('div', { className: classNames('menu-bar', { 'menu-bar-margin': state.activeMenu }) }, [
        h('div.menu-bar-inner-container', [
          h('div.pc-logo-container', [
            h(Link, { to: { pathname: '/search' } }, [
              h('img', {
                src: '/img/icon.png'
              })
            ])
          ]),
          h('div.title-container', [
            h('h4', [
              h('span', state.networkMetadata.name),
              ' | ',
              h('a', state.networkMetadata.datasource)
            ])
          ])
        ]),
        h('div.view-toolbar', toolBar)
      ]),
      h(Loader, {
        loaded: !this.state.networkLoading,
        options: { left: '50%', color: '#16A085' },
      }),
      h('div.Graph', [
        h('div', {
          ref: dom => this.graphDOM = dom,
          style: {
            width: '100vw',
            height: '100vh',
            visibility: this.state.networkLoading ? 'hidden' : undefined
          }
        })
      ]),
      h('div', {
        className: classNames('sidebar-menu', { 'sidebar-menu-open': this.state.open })
      }, [
          h('div', {
            className: classNames('sidebar-close-button-container', { 'sidebar-close-button-container-open': this.state.open })
          }, [
              h(IconButton, {
                key: 'close',
                icon: 'close',
                onClick: () => this.changeMenu('closeMenu'),
                desc: 'Close the sidebar'
              })
            ]),
          h('div.sidebar-content', [
            h('div.sidebar-resize'),
            h('div.sidebar-text', [activeMenu])
          ])
        ])
    ]);
  }
}

module.exports = BaseNetworkView;<|endoftext|>


<commit_before>var Stremio = require("stremio-addons");
var needle = require("needle");
var _ = require("lodash");

var twitch_chans = [];

var stremioCentral = "http://api9.strem.io";

var pkg = require("./package");
var manifest = {
    "id": "org.stremio.twitch",
    "types": ["tv"],
    "filter": { "query.twitch_id": { "$exists": true }, "query.type": { "$in":["tv"] } },
    icon: "http://s.jtvnw.net/jtv_user_pictures/hosted_images/GlitchIcon_purple.png",
    logo: "https://rack1.chipmeup.com/assets/twitch/logo-cd148048b88ce417a0c815548e7e4681.png",
    repository: "http://github.com/jaruba/stremio-twitch",
    endpoint: "http://twitch.strem.io/stremioget/stremio/v1",
    name: pkg.displayName, version: pkg.version, description: pkg.description,
    isFree: true,
    sorts: [{prop: "popularities.twitch", name: "Twitch.tv", types:["tv"]}]
};

var expire = [];

// Get all channels
function twitchStreams(cb, limit, offset) {

    if (expire[offset] && expire[offset] > Date.now()) {
        if (twitch_chans[offset] && twitch_chans[offset].length && cb) {
            cb(null, twitch_chans[offset]);
            return;
        }
    }

    needle.get('https://api.twitch.tv/kraken/streams?limit=' + (limit || 75) + '\u0026offset=' + (offset || 0), function(err, res) {
        if (err) {
            cb && cb(err);
            return;
        }
        twitch_chans[offset] = [];
        if (res && res.body && res.body.streams && res.body.streams.length) {
            var channel = res.body.streams[0].channel.name;
            res.body.streams.forEach( function(el, ij) {
                twitch_chans[offset].push({
                    id: 'twitch_id:' + el.channel.name,
                    name: el.channel.status,
                    poster: el.preview.medium,
                    posterShape: 'landscape',
                    backgroundShape: 'contain',
                    logoShape: 'hidden',
                    banner: el.channel.video_banner || el.preview.template.replace('{width}', '1920').replace('{height}', '1080'),
                    genre: [ 'Entertainment' ],
                    isFree: 1,
                    popularity: el.viewers,
                    popularities: { twitch: el.viewers },
                    type: 'tv'
                });
            });
            expire[offset] = Date.now() + 1800000; // expire in 30 mins
            cb && cb(null, twitch_chans[offset]);
        }
    });
}

function searchMeta(args, cb) {

    var searcher = encodeURIComponent(args.query).split('%20').join('+');

    needle.get('https://api.twitch.tv/kraken/search/streams?limit=' + (args.limit || 75) + '&offset=' + (args.skip || 0) + '&q=' + searcher, function(err, res) {
        if (err) {
            cb && cb(err);
            return;
        }
        var results = [];
        if (res && res.body && res.body.streams && res.body.streams.length) {
            var channel = res.body.streams[0].channel.name;
            res.body.streams.forEach( function(el, ij) {
                results.push({
                    id: 'twitch_id:' + el.channel.name,
                    name: el.channel.status,
                    poster: el.preview.medium,
                    posterShape: 'landscape',
                    backgroundShape: 'contain',
                    logoShape: 'hidden',
                    banner: el.channel.video_banner || el.preview.template.replace('{width}', '1920').replace('{height}', '1080'),
                    genre: [ 'Entertainment' ],
                    isFree: 1,
                    popularity: el.viewers,
                    popularities: { twitch: el.viewers },
                    type: 'tv'
                });
            });
            cb && cb(null, { results: results, query: args.query });
        }
    });
}

function getStream(args, callback) {
    var channel = args.query.twitch_id;
    if (channel) {
        needle.get('http://api.twitch.tv/api/channels/' + channel + '/access_token', function(err, res) {
            if (err) {
                callback(err);
                return;
            }
            if (res && res.body && res.body.sig && res.body.token) {
                var title = res.body.status;
                var token = res.body.token;
                var sig = res.body.sig;
                var rand = Math.floor((Math.random() * 999999) + 1);
                var mrl = 'http://usher.twitch.tv/api/channel/hls/' + channel + '.m3u8?player=twitchweb&token=' + token + '&sig=' + sig + '&allow_audio_only=true&allow_source=true&type=any&p=' + rand;
                callback(null, [{
                    availability: 1,
                    url: mrl,
                    title: 'HD',
                    tag: ['hls'],
                    isFree: 1,
                    twitch_id: args.query.twitch_id
                }]);
            }
        });
    } else
        callback(new Error('Stream Missing'))
}

function getMeta(args, callback) {
    var offset = args.skip || 0;
    var limit = args.limit || 75;
    if (args.query.twitch_id) {
        var found = twitch_chans.some( function(chans) {
            return chans.some( function(el) {
                if (el.id == 'twitch_id:' + args.query.twitch_id) {
                    callback(null, [el]);
                    return true;
                }
            });
        });
        if (!found) {
            needle.get('http://api.twitch.tv/api/channels/' + args.query.twitch_id, function(err, res) {
                if (err) {
                    callback(err);
                    return;
                }
                if (res && res.body) {
                    callback(null, [{
                        id: 'twitch_id:' + args.query.twitch_id,
                        name: res.body.status,
                        poster: res.body.video_banner,
                        posterShape: 'landscape',
                        backgroundShape: 'contain',
                        logoShape: 'hidden',
                        banner: res.body.video_banner,
                        genre: [ 'Entertainment' ],
                        isFree: 1,
                        type: 'tv'
                    }]);
                } else
                    callback(new Error('No Results'));
            });
        }
    } else {
        twitchStreams(function(err, chans) {
            if (err) cb(err);
            else {
                callback(null, args.limit ? chans.slice(0, args.limit) : chans);
            }
        }, limit, offset);
    }
}
var addon = new Stremio.Server({
    "stream.find": function(args, callback, user) {
        getStream(args, function(err, resp) { callback(err, resp || undefined) })
    },
    "meta.get": function(args, callback, user) {
        args.projection = args.projection || { }; // full
        getMeta(_.extend(args, { limit: 1 }), function(err, res) {
            if (err) return callback(err);

            res = res && res[0];
            if (! res) return callback(null, null);

            callback(null, res);
        });
    },
    "meta.search": function(args, callback, user) {
        searchMeta(args, callback);
    },
    "meta.find": function(args, callback, user) {
        getMeta(args, callback); // push to pipe so we wait for channels to be crawled
    }
}, { stremioget: true, cacheTTL: { "meta.find": 30*60, "stream.find": 19*60, "meta.get": 4*60*60 }, allow: ["http://api8.herokuapp.com","http://api9.strem.io"] /* secret: mySecret */ }, manifest);

var server = require("http").createServer(function (req, res) {
    addon.middleware(req, res, function() { res.end() }); // wire the middleware - also compatible with connect / express
}).on("listening", function()
{
    console.log("Twitch.tv Stremio Addon listening on "+server.address().port);
})
if (module.parent) module.exports = server;
else server.listen(process.env.PORT || 9028);

var catchMyExceptions = require('catch-my-exceptions');
if (process.env.SLACK_HOOK) catchMyExceptions(process.env.SLACK_HOOK, { slackUsername: "twitch" });
<commit_msg>Handle Errors Better<commit_after>var Stremio = require("stremio-addons");
var needle = require("needle");
var _ = require("lodash");

var twitch_chans = [];

var stremioCentral = "http://api9.strem.io";

var pkg = require("./package");
var manifest = {
    "id": "org.stremio.twitch",
    "types": ["tv"],
    "filter": { "query.twitch_id": { "$exists": true }, "query.type": { "$in":["tv"] } },
    icon: "http://s.jtvnw.net/jtv_user_pictures/hosted_images/GlitchIcon_purple.png",
    logo: "https://rack1.chipmeup.com/assets/twitch/logo-cd148048b88ce417a0c815548e7e4681.png",
    repository: "http://github.com/jaruba/stremio-twitch",
    endpoint: "http://twitch.strem.io/stremioget/stremio/v1",
    name: pkg.displayName, version: pkg.version, description: pkg.description,
    isFree: true,
    sorts: [{prop: "popularities.twitch", name: "Twitch.tv", types:["tv"]}]
};

var expire = [];

// Get all channels
function twitchStreams(cb, limit, offset) {

    if (expire[offset] && expire[offset] > Date.now()) {
        if (twitch_chans[offset] && twitch_chans[offset].length && cb) {
            cb(null, twitch_chans[offset]);
            return;
        }
    }

    needle.get('https://api.twitch.tv/kraken/streams?limit=' + (limit || 75) + '\u0026offset=' + (offset || 0), function(err, res) {
        if (err) {
            cb && cb(err);
            return;
        }
        twitch_chans[offset] = [];
        if (res && res.body && res.body.streams && res.body.streams.length) {
            var channel = res.body.streams[0].channel.name;
            res.body.streams.forEach( function(el, ij) {
                twitch_chans[offset].push({
                    id: 'twitch_id:' + el.channel.name,
                    name: el.channel.status,
                    poster: el.preview.medium,
                    posterShape: 'landscape',
                    backgroundShape: 'contain',
                    logoShape: 'hidden',
                    banner: el.channel.video_banner || el.preview.template.replace('{width}', '1920').replace('{height}', '1080'),
                    genre: [ 'Entertainment' ],
                    isFree: 1,
                    popularity: el.viewers,
                    popularities: { twitch: el.viewers },
                    type: 'tv'
                });
            });
            expire[offset] = Date.now() + 1800000; // expire in 30 mins
            cb && cb(null, twitch_chans[offset]);
        } else if (cb)
            cb(new Error('Network Error'));
    });
}

function searchMeta(args, cb) {

    var searcher = encodeURIComponent(args.query).split('%20').join('+');

    needle.get('https://api.twitch.tv/kraken/search/streams?limit=' + (args.limit || 75) + '&offset=' + (args.skip || 0) + '&q=' + searcher, function(err, res) {
        if (err) {
            cb && cb(err);
            return;
        }
        var results = [];
        if (res && res.body && res.body.streams && res.body.streams.length) {
            var channel = res.body.streams[0].channel.name;
            res.body.streams.forEach( function(el, ij) {
                results.push({
                    id: 'twitch_id:' + el.channel.name,
                    name: el.channel.status,
                    poster: el.preview.medium,
                    posterShape: 'landscape',
                    backgroundShape: 'contain',
                    logoShape: 'hidden',
                    banner: el.channel.video_banner || el.preview.template.replace('{width}', '1920').replace('{height}', '1080'),
                    genre: [ 'Entertainment' ],
                    isFree: 1,
                    popularity: el.viewers,
                    popularities: { twitch: el.viewers },
                    type: 'tv'
                });
            });
            cb && cb(null, { results: results, query: args.query });
        } else if (cb)
            cb(new Error('Network Error'));
    });
}

function getStream(args, callback) {
    var channel = args.query.twitch_id;
    if (channel) {
        needle.get('http://api.twitch.tv/api/channels/' + channel + '/access_token', function(err, res) {
            if (err) {
                callback(err);
                return;
            }
            if (res && res.body && res.body.sig && res.body.token) {
                var title = res.body.status;
                var token = res.body.token;
                var sig = res.body.sig;
                var rand = Math.floor((Math.random() * 999999) + 1);
                var mrl = 'http://usher.twitch.tv/api/channel/hls/' + channel + '.m3u8?player=twitchweb&token=' + token + '&sig=' + sig + '&allow_audio_only=true&allow_source=true&type=any&p=' + rand;
                callback(null, [{
                    availability: 1,
                    url: mrl,
                    title: 'HD',
                    tag: ['hls'],
                    isFree: 1,
                    twitch_id: args.query.twitch_id
                }]);
            } else if (callback)
                callback(new Error('Network Error'));
        });
    } else
        callback(new Error('Stream Missing'))
}

function getMeta(args, callback) {
    var offset = args.skip || 0;
    var limit = args.limit || 75;
    if (args.query.twitch_id) {
        var found = twitch_chans.some( function(chans) {
            return chans.some( function(el) {
                if (el.id == 'twitch_id:' + args.query.twitch_id) {
                    callback(null, [el]);
                    return true;
                }
            });
        });
        if (!found) {
            needle.get('http://api.twitch.tv/api/channels/' + args.query.twitch_id, function(err, res) {
                if (err) {
                    callback(err);
                    return;
                }
                if (res && res.body) {
                    callback(null, [{
                        id: 'twitch_id:' + args.query.twitch_id,
                        name: res.body.status,
                        poster: res.body.video_banner,
                        posterShape: 'landscape',
                        backgroundShape: 'contain',
                        logoShape: 'hidden',
                        banner: res.body.video_banner,
                        genre: [ 'Entertainment' ],
                        isFree: 1,
                        type: 'tv'
                    }]);
                } else if (callback)
                    callback(new Error('No Results'));
            });
        }
    } else {
        twitchStreams(function(err, chans) {
            if (err) callback(err);
            else {
                callback(null, args.limit ? chans.slice(0, args.limit) : chans);
            }
        }, limit, offset);
    }
}
var addon = new Stremio.Server({
    "stream.find": function(args, callback, user) {
        getStream(args, function(err, resp) { callback(err, resp || undefined) })
    },
    "meta.get": function(args, callback, user) {
        args.projection = args.projection || { }; // full
        getMeta(_.extend(args, { limit: 1 }), function(err, res) {
            if (err) return callback(err);

            res = res && res[0];
            if (! res) return callback(null, null);

            callback(null, res);
        });
    },
    "meta.search": function(args, callback, user) {
        searchMeta(args, callback);
    },
    "meta.find": function(args, callback, user) {
        getMeta(args, callback); // push to pipe so we wait for channels to be crawled
    }
}, { stremioget: true, cacheTTL: { "meta.find": 30*60, "stream.find": 19*60, "meta.get": 4*60*60 }, allow: ["http://api8.herokuapp.com","http://api9.strem.io"] /* secret: mySecret */ }, manifest);

var server = require("http").createServer(function (req, res) {
    addon.middleware(req, res, function() { res.end() }); // wire the middleware - also compatible with connect / express
}).on("listening", function()
{
    console.log("Twitch.tv Stremio Addon listening on "+server.address().port);
})
if (module.parent) module.exports = server;
else server.listen(process.env.PORT || 9028);

var catchMyExceptions = require('catch-my-exceptions');
if (process.env.SLACK_HOOK) catchMyExceptions(process.env.SLACK_HOOK, { slackUsername: "twitch" });
<|endoftext|>


<commit_before>/* Contains code related to in-game battles. */

const RG = require('./rg');
const debug = require('debug')('bitn:game.battle');

/* Army is a collection of actors associated with a battle. This is useful for
 *  battle commanders to have access to their full army. */
const Army = function(name) {
    const _name = name;
    let _actors = []; // All actors inside this army

    let _battle = null;
    let _casualties = 0;
    let _defeatThreshold = 0;

    this.getName = () => _name;

    this.setDefeatThreshold = numActors => {
        _defeatThreshold = numActors;
    };

    /* Default defeat is when all actors have been eliminated.*/
    this.isDefeated = () => {
        if (_actors.length <= _defeatThreshold) {
            return true;
        }
        return false;
    };

    this.setBattle = battle => {_battle = battle;};
    this.getBattle = () => _battle;

    this.getCasualties = () => _casualties;

    this.getActors = () => _actors;

    this.hasActor = actor => {
        const id = actor.getID();
        const index = _actors.findIndex(actor => actor.getID() === id);
        return index >= 0;
    };

    /* Tries to add an actor and returns true if success.*/
    this.addActor = function(actor) {
        if (!this.hasActor(actor)) {
            _actors.push(actor);
            return true;
        }
        else {
            RG.err('Game.Army', 'addActor',
                'Actor already in army ' + this.getName());
        }
        return false;
    };

    /* Removes an actor from the army.*/
    this.removeActor = actor => {
        const index = _actors.findIndex(
            a => a.getID() === actor.getID()
        );
        if (index >= 0) {
            _actors.splice(index, 1);
            return true;
        }
        else {
            return false;
        }
    };

    this.removeAllActors = () => {_actors = [];};

    /* Monitor killed actors and remove them from the army.*/
    this.hasNotify = true;
    this.notify = function(evtName, msg) {
        if (evtName === RG.EVT_ACTOR_KILLED) {
            const actor = msg.actor;
            if (this.hasActor(actor)) {
                if (!this.removeActor(actor)) {
                    const bName = this.getBattle().getName();
                    let msg = 'Battle: ' + bName;
                    msg += "Couldn't remove the actor " + actor.getName();
                    RG.err('Game.Army', 'notify', msg);
                }
                else {
                    ++_casualties;
                    console.log(`\tCasualties: ${_casualties}`);
                    const armyObj = {
                        type: 'Actor killed', army: this
                    };
                    RG.POOL.emitEvent(RG.EVT_ARMY_EVENT, armyObj);
                    if (_actors.length === 0) {
                        console.log('<><> Army ' + _name + ' decimated');
                        console.log(`\tCasualties: ${_casualties}`);
                        RG.POOL.removeListener(this);
                    }
                }
            }
        }
    };
    RG.POOL.listenEvent(RG.EVT_ACTOR_KILLED, this);

    this.toJSON = function() {
        return {
            name: _name,
            actors: _actors.map(actor => actor.getID()),
            defeatThreshold: _defeatThreshold
        };
    };
};

/* Battle is "mini-game" which uses its own scheduling and engine.*/
const Battle = function(name) {

    const _name = name;
    let _armies = [];
    let _level = null;

    this.getType = () => 'battle';

    // Keeps track of battles statistics
    let _stats = {
        duration: 0,
        casualties: 0,
        survivors: 0
    };
    this.getArmies = () => _armies;
    this.setArmies = armies => {
        _armies = armies;
        _armies.forEach(army => {
            army.setBattle(this);
        });
    };

    this.getName = () => _name;

    this.setLevel = level => {
        _level = level;
        _level.setParent(this);
    };
    this.getLevel = () => _level;

    this.getStats = () => _stats;
    this.setStats = stats => {_stats = stats;};

    /* Adds an army to given x,y location.*/
    this.addArmy = (army, x, y, horizontal = true) => {
        if (!RG.isNullOrUndef([_level])) {
            _armies.push(army);
            const actors = army.getActors();
            if (horizontal) {
                for (let i = 0; i < actors.length; i++) {
                    _level.addActor(actors[i], x + i, y);
                }
            }
            else {
                for (let i = 0; i < actors.length; i++) {
                    _level.addActor(actors[i], x, y + i);
                }
            }
        }
        else {
            RG.err('Game.Battle', 'addArmy',
                'Level must exist before adding army.');
        }
        army.setBattle(this);
    };

    this.armyInThisBattle = army => {
        const index = _armies.indexOf(army);
        return index >= 0;
    };

    /* Returns true if the battle is over.*/
    this.isOver = () => {
        if (_armies.length > 1) {
            let numArmies = 0;
            _armies.forEach(army => {
                if (!army.isDefeated()) {
                    ++numArmies;
                }
            });
            if (numArmies <= 1) {
                return true;
            }
        }
        else {
            RG.err('Game.Battle', 'isOver', 'Battle should have >= 2 armies.');
        }
        return false;
    };

    this.hasNotify = true;
    this.notify = function(evtName, msg) {
        if (evtName === RG.EVT_ARMY_EVENT) {
            const {type, army} = msg;
            if (this.armyInThisBattle(army) && type === 'Actor killed') {
                if (this.isOver()) {
                    debug(`Battle |${this.getName()}| is over!`);
                    debug('\tRemoving all event listeners');
                    RG.POOL.removeListener(this);
                    /* for (let i = 0; i < _armies.length; i++) {
                        RG.POOL.removeListener(_armies[i]);
                    }*/
                    const obj = {battle: this};
                    RG.POOL.emitEvent(RG.EVT_BATTLE_OVER, obj);
                }
            }
        }
    };
    RG.POOL.listenEvent(RG.EVT_ARMY_EVENT, this);

    /* Serialies the object into JSON. */
    this.toJSON = function() {
        return {
            name: _name,
            level: _level.getID(),
            armies: _armies.map(army => army.toJSON()),
            stats: _stats
        };
    };

};

module.exports = {
    Army, Battle
};
<commit_msg>Added finished variable to battle.<commit_after>/* Contains code related to in-game battles. */

const RG = require('./rg');
const debug = require('debug')('bitn:game.battle');

/* Army is a collection of actors associated with a battle. This is useful for
 *  battle commanders to have access to their full army. */
const Army = function(name) {
    const _name = name;
    let _actors = []; // All actors inside this army

    let _battle = null;
    let _casualties = 0;
    let _defeatThreshold = 0;

    this.getName = () => _name;

    this.setDefeatThreshold = numActors => {
        _defeatThreshold = numActors;
    };

    /* Default defeat is when all actors have been eliminated.*/
    this.isDefeated = () => {
        if (_actors.length <= _defeatThreshold) {
            return true;
        }
        return false;
    };

    this.setBattle = battle => {_battle = battle;};
    this.getBattle = () => _battle;

    this.getCasualties = () => _casualties;

    this.getActors = () => _actors;

    this.hasActor = actor => {
        const id = actor.getID();
        const index = _actors.findIndex(actor => actor.getID() === id);
        return index >= 0;
    };

    /* Tries to add an actor and returns true if success.*/
    this.addActor = function(actor) {
        if (!this.hasActor(actor)) {
            _actors.push(actor);
            return true;
        }
        else {
            RG.err('Game.Army', 'addActor',
                'Actor already in army ' + this.getName());
        }
        return false;
    };

    /* Removes an actor from the army.*/
    this.removeActor = actor => {
        const index = _actors.findIndex(
            a => a.getID() === actor.getID()
        );
        if (index >= 0) {
            _actors.splice(index, 1);
            return true;
        }
        else {
            return false;
        }
    };

    this.removeAllActors = () => {_actors = [];};

    /* Monitor killed actors and remove them from the army.*/
    this.hasNotify = true;
    this.notify = function(evtName, msg) {
        if (evtName === RG.EVT_ACTOR_KILLED) {
            const actor = msg.actor;
            if (this.hasActor(actor)) {
                if (!this.removeActor(actor)) {
                    const bName = this.getBattle().getName();
                    let msg = 'Battle: ' + bName;
                    msg += "Couldn't remove the actor " + actor.getName();
                    RG.err('Game.Army', 'notify', msg);
                }
                else {
                    ++_casualties;
                    console.log(`\tCasualties: ${_casualties}`);
                    const armyObj = {
                        type: 'Actor killed', army: this
                    };
                    RG.POOL.emitEvent(RG.EVT_ARMY_EVENT, armyObj);
                    if (_actors.length === 0) {
                        console.log('<><> Army ' + _name + ' decimated');
                        console.log(`\tCasualties: ${_casualties}`);
                        RG.POOL.removeListener(this);
                    }
                }
            }
        }
    };
    RG.POOL.listenEvent(RG.EVT_ACTOR_KILLED, this);

    this.toJSON = function() {
        return {
            name: _name,
            actors: _actors.map(actor => actor.getID()),
            defeatThreshold: _defeatThreshold
        };
    };
};

/* Battle is "mini-game" which uses its own scheduling and engine.*/
const Battle = function(name) {

    const _name = name;
    let _armies = [];
    let _level = null;
    this.finished = false;

    this.getType = () => 'battle';

    // Keeps track of battles statistics
    let _stats = {
        duration: 0,
        casualties: 0,
        survivors: 0
    };
    this.getArmies = () => _armies;
    this.setArmies = armies => {
        _armies = armies;
        _armies.forEach(army => {
            army.setBattle(this);
        });
    };

    this.getName = () => _name;

    this.setLevel = level => {
        _level = level;
        _level.setParent(this);
    };
    this.getLevel = () => _level;

    this.getStats = () => _stats;
    this.setStats = stats => {_stats = stats;};

    /* Adds an army to given x,y location.*/
    this.addArmy = (army, x, y, horizontal = true) => {
        if (!RG.isNullOrUndef([_level])) {
            _armies.push(army);
            const actors = army.getActors();
            if (horizontal) {
                for (let i = 0; i < actors.length; i++) {
                    _level.addActor(actors[i], x + i, y);
                }
            }
            else {
                for (let i = 0; i < actors.length; i++) {
                    _level.addActor(actors[i], x, y + i);
                }
            }
        }
        else {
            RG.err('Game.Battle', 'addArmy',
                'Level must exist before adding army.');
        }
        army.setBattle(this);
    };

    this.armyInThisBattle = army => {
        const index = _armies.indexOf(army);
        return index >= 0;
    };

    /* Returns true if the battle is over.*/
    this.isOver = () => {
        if (_armies.length > 1) {
            let numArmies = 0;
            _armies.forEach(army => {
                if (!army.isDefeated()) {
                    ++numArmies;
                }
            });
            if (numArmies <= 1) {
                return true;
            }
        }
        else {
            RG.err('Game.Battle', 'isOver', 'Battle should have >= 2 armies.');
        }
        return false;
    };

    this.hasNotify = true;
    this.notify = function(evtName, msg) {
        if (evtName === RG.EVT_ARMY_EVENT) {
            const {type, army} = msg;
            if (this.armyInThisBattle(army) && type === 'Actor killed') {
                if (this.isOver()) {
                    debug(`Battle |${this.getName()}| is over!`);
                    debug('\tRemoving all event listeners');
                    RG.POOL.removeListener(this);
                    const obj = {battle: this};
                    RG.POOL.emitEvent(RG.EVT_BATTLE_OVER, obj);
                    this.finished = true;
                }
            }
        }
    };
    RG.POOL.listenEvent(RG.EVT_ARMY_EVENT, this);

    /* Serialies the object into JSON. */
    this.toJSON = function() {
        return {
            name: _name,
            level: _level.getID(),
            armies: _armies.map(army => army.toJSON()),
            stats: _stats,
            finished: this.finished
        };
    };

};

module.exports = {
    Army, Battle
};
<|endoftext|>


<commit_before>'use strict';

var path  = require('path');
var spawn = require('win-spawn');

module.exports = function (grunt) {

  var _ = grunt.util._;

  var defaultOpts = {
    root: '.',

    manageScript: 'appcfg.py',
    manageFlags: {
      oauth2: true
    },

    runScript: 'dev_appserver.py',
    runFlags: {
      // empty
    },

    stdio: 'inherit'
  };

  function spawned(done, cmd, args, opts) {
    function spawnFunc() {
      spawn(cmd, args || [], opts || {}).on('exit', function (status) {
        done(status === 0);
      });
    }

    return spawnFunc;
  }

  function createPath(opts) {
    var res = [];
    var root = opts['root'] || '.';
    var paths = opts['GOPATH'] || [];

    if (paths) {
      for (var i in paths) {
        res.push(path.resolve(path.join(root, paths[i])));
      }
    }

    return res;
  }

  // expecting 'appengine:<command>:<target>(:<profile>)'
  function validateArgs(args) {
    if (args.length === 0) {
      grunt.log.error('Unable to run task: no action specified (e.g. run or update)');
      return false;
    } else if (args.length === 1) {
      grunt.log.error('Unable to run task: no target specified');
      return false;
    } else if (args.length > 3) {
      grunt.log.error('Unable to run task: too many arguments (up to 4 allowed)');
      return false;
    }

    return true;
  }

  // ==== INTERFACE

  var exports = {
    execute: function (dryRun) {
      var self = this;
      var name = self.name || 'appengine';

      // ==== read task parameters

      var taskArgs = this.args || [];
      grunt.log.debug('Task args: ' + taskArgs);
      if (validateArgs(taskArgs) === false) {
        return false;
      }
      var action = taskArgs[0];
      var target = taskArgs[1];
      var profile = taskArgs[2] || "";

      if (!target || !grunt.config([name, target])) {
        grunt.log.error('Unable to run task: target \'' + target + '\' not found');
        return false;
      }

      var gruntTaskTargetProfileOpts = grunt.config([name, target, profile]) || {};
      var gruntTaskTargetOpts = grunt.config([name, target]) || {};
      var gruntTaskOpts = grunt.config([name, 'options']) || {};
      var taskOpts = _.defaults(
        gruntTaskTargetProfileOpts,
        gruntTaskTargetOpts,
        gruntTaskOpts,
        defaultOpts
      );
      //console.log(grunt.config([name, target, profile]));
      grunt.log.debug('Task opts: ' + JSON.stringify(taskOpts));
      var appDir = taskOpts['root'];

      // ==== assemble script name

      var cmd = taskOpts['manageScript'];
      var optsFlagsName = 'manageFlags';
      if (action === 'run') {
        cmd = taskOpts['runScript'];
        optsFlagsName = 'runFlags';
      }

      var taskFlagsOpts = _.defaults(
        gruntTaskTargetProfileOpts[optsFlagsName] || {},
        gruntTaskTargetOpts[optsFlagsName] || {},
        gruntTaskOpts[optsFlagsName] || {},
        defaultOpts[optsFlagsName] || {}
      );

      var sdk = taskOpts['sdk'];
      if (sdk) {
        cmd = sdk + '/' + cmd;
      }

      // ==== assemble script action

      var cmdAction = [];
      if (taskOpts['backend'] === true) {
        cmdAction.push('backends');
        cmdAction.push(appDir);
        cmdAction.push(action);

        var backendName = taskOpts['backendName'];
        if (backendName) {
          cmdAction.push(backendName);
        }
      } else {
        if (action !== 'run') {
          cmdAction.push(action);
        }
        var modules = taskOpts['modules'];
        if (modules) {
          for (var i in modules) {
            cmdAction.push(path.join(appDir, modules[i]));
          }
        } else {
          cmdAction.push(appDir);
        }
      }

      // ==== assemble script flags

      var cmdFlags = [];
      for (var attrname in taskFlagsOpts) {
        var attrval = taskFlagsOpts[attrname];
        if (attrval === true) {
          cmdFlags.push('--' + attrname);
        } else {
          cmdFlags.push('--' + attrname + '=' + attrval);
        }
      }

      // ==== assemble script process opts

      var cmdOpts = {};
      cmdOpts['env'] = process.env || {};

      var envTaskOpts = taskOpts['env'] || {};
      for (var envName in envTaskOpts) {
        cmdOpts['env'][envName] = envTaskOpts[envName];
      }

      cmdOpts['env'].GOPATH =
        createPath(gruntTaskOpts)
          .concat(createPath(gruntTaskTargetOpts))
          .concat(createPath(gruntTaskTargetProfileOpts)).join(':');

      cmdOpts['stdio'] = taskOpts['stdio'];

      grunt.log.debug('CMD opts: ' + JSON.stringify(cmdOpts));

      // ==== execute and return

      var cmdArgs = cmdFlags.concat(cmdAction);
      var fullCmd = cmd + ' ' + cmdArgs.join(' ');
      grunt.log.writeln('executing: ' + fullCmd);

      if (dryRun !== true) {
        var done = this.async();
        spawned(done, cmd, cmdArgs, cmdOpts)();
      } else {
        grunt.log.write('(dry run: script not executed)');
      }

      return {
        cmd: fullCmd,
        opts: cmdOpts
      };
    }
  };

  // ==== TASK

  grunt.registerTask('appengine', 'Managing App Engine.', exports.execute);

  return exports;
};
<commit_msg>Added the ability to pass in task target specific options.<commit_after>'use strict';

var path  = require('path');
var spawn = require('win-spawn');

module.exports = function (grunt) {

  var _ = grunt.util._;

  var defaultOpts = {
    root: '.',

    manageScript: 'appcfg.py',
    manageFlags: {
      oauth2: true
    },

    runScript: 'dev_appserver.py',
    runFlags: {
      // empty
    },

    stdio: 'inherit'
  };

  function spawned(done, cmd, args, opts) {
    function spawnFunc() {
      spawn(cmd, args || [], opts || {}).on('exit', function (status) {
        done(status === 0);
      });
    }

    return spawnFunc;
  }

  function createPath(opts) {
    var res = [];
    var root = opts['root'] || '.';
    var paths = opts['GOPATH'] || [];

    if (paths) {
      for (var i in paths) {
        res.push(path.resolve(path.join(root, paths[i])));
      }
    }

    return res;
  }

  // expecting 'appengine:<command>:<target>(:<profile>)'
  function validateArgs(args) {
    if (args.length === 0) {
      grunt.log.error('Unable to run task: no action specified (e.g. run or update)');
      return false;
    } else if (args.length === 1) {
      grunt.log.error('Unable to run task: no target specified');
      return false;
    } else if (args.length > 3) {
      grunt.log.error('Unable to run task: too many arguments (up to 4 allowed)');
      return false;
    }

    return true;
  }

  // ==== INTERFACE

  var exports = {
    execute: function (dryRun) {
      var self = this;
      var name = self.name || 'appengine';

      // ==== read task parameters

      var taskArgs = this.args || [];
      grunt.log.debug('Task args: ' + taskArgs);
      if (validateArgs(taskArgs) === false) {
        return false;
      }
      var action = taskArgs[0];
      var target = taskArgs[1];
      var profile = taskArgs[2] || "";

      if (!target || !grunt.config([name, target])) {
        grunt.log.error('Unable to run task: target \'' + target + '\' not found');
        return false;
      }

      var gruntTaskTargetProfileOpts = grunt.config([name, target, profile]) || {};
      var gruntTaskTargetOpts = grunt.config([name, target]) || {};
      var gruntTastTargetOptsExtra = gruntTaskTargetOpts.options || {};
      var gruntTaskOpts = grunt.config([name, 'options']) || {};
      var taskOpts = _.defaults(
        gruntTaskTargetProfileOpts,
        gruntTaskTargetOpts,
        gruntTastTargetOptsExtra,
        gruntTaskOpts,
        defaultOpts
      );
      //console.log(grunt.config([name, target, profile]));
      grunt.log.debug('Task opts: ' + JSON.stringify(taskOpts));
      var appDir = taskOpts['root'];

      // ==== assemble script name

      var cmd = taskOpts['manageScript'];
      var optsFlagsName = 'manageFlags';
      if (action === 'run') {
        cmd = taskOpts['runScript'];
        optsFlagsName = 'runFlags';
      }

      var taskFlagsOpts = _.defaults(
        gruntTaskTargetProfileOpts[optsFlagsName] || {},
        gruntTaskTargetOpts[optsFlagsName] || {},
        gruntTastTargetOptsExtra[optsFlagsName] || {},
        gruntTaskOpts[optsFlagsName] || {},
        defaultOpts[optsFlagsName] || {}
      );

      var sdk = taskOpts['sdk'];
      if (sdk) {
        cmd = sdk + '/' + cmd;
      }

      // ==== assemble script action

      var cmdAction = [];
      if (taskOpts['backend'] === true) {
        cmdAction.push('backends');
        cmdAction.push(appDir);
        cmdAction.push(action);

        var backendName = taskOpts['backendName'];
        if (backendName) {
          cmdAction.push(backendName);
        }
      } else {
        if (action !== 'run') {
          cmdAction.push(action);
        }
        var modules = taskOpts['modules'];
        if (modules) {
          for (var i in modules) {
            cmdAction.push(path.join(appDir, modules[i]));
          }
        } else {
          cmdAction.push(appDir);
        }
      }

      // ==== assemble script flags

      var cmdFlags = [];
      for (var attrname in taskFlagsOpts) {
        var attrval = taskFlagsOpts[attrname];
        if (attrval === true) {
          cmdFlags.push('--' + attrname);
        } else {
          //TODO: break out to attrubuteValidator function
          if (attrname === 'version') {
            attrval = attrval.replace(/\./g, '-');
          }
          cmdFlags.push('--' + attrname + '=' + attrval);
        }
      }

      // ==== assemble script process opts

      var cmdOpts = {};
      cmdOpts['env'] = process.env || {};

      var envTaskOpts = taskOpts['env'] || {};
      for (var envName in envTaskOpts) {
        cmdOpts['env'][envName] = envTaskOpts[envName];
      }

      cmdOpts['env'].GOPATH =
        createPath(gruntTaskOpts)
          .concat(createPath(gruntTaskTargetOpts))
          .concat(createPath(gruntTaskTargetProfileOpts)).join(':');

      cmdOpts['stdio'] = taskOpts['stdio'];

      grunt.log.debug('CMD opts: ' + JSON.stringify(cmdOpts));

      // ==== execute and return

      var cmdArgs = cmdFlags.concat(cmdAction);
      var fullCmd = cmd + ' ' + cmdArgs.join(' ');
      grunt.log.writeln('executing: ' + fullCmd);

      if (dryRun !== true) {
        var done = this.async();
        spawned(done, cmd, cmdArgs, cmdOpts)();
      } else {
        grunt.log.write('(dry run: script not executed)');
      }

      return {
        cmd: fullCmd,
        opts: cmdOpts
      };
    }
  };

  // ==== TASK

  grunt.registerTask('appengine', 'Managing App Engine.', exports.execute);

  return exports;
};
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */

import { buildMenu, showMenu } from "devtools-contextmenu";

export default function showContextMenu(props) {
  const {
    removeBreakpoint,
    removeBreakpoints,
    removeAllBreakpoints,
    toggleBreakpoints,
    toggleAllBreakpoints,
    toggleDisabledBreakpoint,
    selectSpecificLocation,
    setBreakpointCondition,
    openConditionalPanel,
    breakpoints,
    breakpoint,
    contextMenuEvent
  } = props;

  contextMenuEvent.preventDefault();

  const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label");
  const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label");
  const deleteOthersLabel = L10N.getStr(
    "breakpointMenuItem.deleteOthers2.label"
  );
  const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label");
  const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label");
  const enableOthersLabel = L10N.getStr(
    "breakpointMenuItem.enableOthers2.label"
  );
  const disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf2.label");
  const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label");
  const disableOthersLabel = L10N.getStr(
    "breakpointMenuItem.disableOthers2.label"
  );
  const removeConditionLabel = L10N.getStr(
    "breakpointMenuItem.removeCondition2.label"
  );
  const addConditionLabel = L10N.getStr(
    "breakpointMenuItem.addCondition2.label"
  );
  const editConditionLabel = L10N.getStr(
    "breakpointMenuItem.editCondition2.label"
  );

  const deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf2.accesskey");
  const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey");
  const deleteOthersKey = L10N.getStr(
    "breakpointMenuItem.deleteOthers2.accesskey"
  );
  const enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf2.accesskey");
  const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey");
  const enableOthersKey = L10N.getStr(
    "breakpointMenuItem.enableOthers2.accesskey"
  );
  const disableSelfKey = L10N.getStr(
    "breakpointMenuItem.disableSelf2.accesskey"
  );
  const disableAllKey = L10N.getStr("breakpointMenuItem.disableAll2.accesskey");
  const disableOthersKey = L10N.getStr(
    "breakpointMenuItem.disableOthers2.accesskey"
  );
  const removeConditionKey = L10N.getStr(
    "breakpointMenuItem.removeCondition2.accesskey"
  );
  const editConditionKey = L10N.getStr(
    "breakpointMenuItem.editCondition2.accesskey"
  );
  const addConditionKey = L10N.getStr(
    "breakpointMenuItem.addCondition2.accesskey"
  );

  const otherBreakpoints = breakpoints.filter(b => b.id !== breakpoint.id);
  const enabledBreakpoints = breakpoints.filter(b => !b.disabled);
  const disabledBreakpoints = breakpoints.filter(b => b.disabled);
  const otherEnabledBreakpoints = breakpoints.filter(
    b => !b.disabled && b.id !== breakpoint.id
  );
  const otherDisabledBreakpoints = breakpoints.filter(
    b => b.disabled && b.id !== breakpoint.id
  );

  const deleteSelfItem = {
    id: "node-menu-delete-self",
    label: deleteSelfLabel,
    accesskey: deleteSelfKey,
    disabled: false,
    click: () => removeBreakpoint(breakpoint.selectedLocation)
  };

  const deleteAllItem = {
    id: "node-menu-delete-all",
    label: deleteAllLabel,
    accesskey: deleteAllKey,
    disabled: false,
    click: () => removeAllBreakpoints()
  };

  const deleteOthersItem = {
    id: "node-menu-delete-other",
    label: deleteOthersLabel,
    accesskey: deleteOthersKey,
    disabled: false,
    click: () => removeBreakpoints(otherBreakpoints)
  };

  const enableSelfItem = {
    id: "node-menu-enable-self",
    label: enableSelfLabel,
    accesskey: enableSelfKey,
    disabled: false,
    click: () => toggleDisabledBreakpoint(breakpoint.selectedLocation.line)
  };

  const enableAllItem = {
    id: "node-menu-enable-all",
    label: enableAllLabel,
    accesskey: enableAllKey,
    disabled: false,
    click: () => toggleAllBreakpoints(false)
  };

  const enableOthersItem = {
    id: "node-menu-enable-others",
    label: enableOthersLabel,
    accesskey: enableOthersKey,
    disabled: false,
    click: () => toggleBreakpoints(false, otherDisabledBreakpoints)
  };

  const disableSelfItem = {
    id: "node-menu-disable-self",
    label: disableSelfLabel,
    accesskey: disableSelfKey,
    disabled: false,
    click: () => toggleDisabledBreakpoint(breakpoint.selectedLocation.line)
  };

  const disableAllItem = {
    id: "node-menu-disable-all",
    label: disableAllLabel,
    accesskey: disableAllKey,
    disabled: false,
    click: () => toggleAllBreakpoints(true)
  };

  const disableOthersItem = {
    id: "node-menu-disable-others",
    label: disableOthersLabel,
    accesskey: disableOthersKey,
    click: () => toggleBreakpoints(true, otherEnabledBreakpoints)
  };

  const removeConditionItem = {
    id: "node-menu-remove-condition",
    label: removeConditionLabel,
    accesskey: removeConditionKey,
    disabled: false,
    click: () => setBreakpointCondition(breakpoint.selectedLocation)
  };

  const addConditionItem = {
    id: "node-menu-add-condition",
    label: addConditionLabel,
    accesskey: addConditionKey,
    click: () => {
      selectSpecificLocation(breakpoint.selectedLocation);
      openConditionalPanel(breakpoint.selectedLocation.line);
    }
  };

  const editConditionItem = {
    id: "node-menu-edit-condition",
    label: editConditionLabel,
    accesskey: editConditionKey,
    click: () => {
      selectSpecificLocation(breakpoint.selectedLocation);
      openConditionalPanel(breakpoint.selectedLocation.line);
    }
  };

  const hideEnableSelfItem = !breakpoint.disabled;
  const hideEnableAllItem = disabledBreakpoints.length === 0;
  const hideEnableOthersItem = otherDisabledBreakpoints.length === 0;
  const hideDisableAllItem = enabledBreakpoints.length === 0;
  const hideDisableOthersItem = otherEnabledBreakpoints.length === 0;
  const hideDisableSelfItem = breakpoint.disabled;

  const items = [
    { item: enableSelfItem, hidden: () => hideEnableSelfItem },
    { item: enableAllItem, hidden: () => hideEnableAllItem },
    { item: enableOthersItem, hidden: () => hideEnableOthersItem },
    {
      item: { type: "separator" },
      hidden: () =>
        hideEnableSelfItem && hideEnableAllItem && hideEnableOthersItem
    },
    { item: deleteSelfItem },
    { item: deleteAllItem },
    { item: deleteOthersItem, hidden: () => breakpoints.length === 1 },
    {
      item: { type: "separator" },
      hidden: () =>
        hideDisableSelfItem && hideDisableAllItem && hideDisableOthersItem
    },

    { item: disableSelfItem, hidden: () => hideDisableSelfItem },
    { item: disableAllItem, hidden: () => hideDisableAllItem },
    { item: disableOthersItem, hidden: () => hideDisableOthersItem },
    {
      item: { type: "separator" }
    },
    {
      item: addConditionItem,
      hidden: () => breakpoint.condition
    },
    {
      item: editConditionItem,
      hidden: () => !breakpoint.condition
    },
    {
      item: removeConditionItem,
      hidden: () => !breakpoint.condition
    }
  ];

  showMenu(contextMenuEvent, buildMenu(items));
}
<commit_msg>Add flow types to BreakpointContextMenu props (#7393)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */

// @flow

import { buildMenu, showMenu } from "devtools-contextmenu";

import actions from "../../../actions";
import type { Breakpoint } from "../../../types";
import type { FormattedBreakpoint } from "../../../selectors/breakpointSources";

type Props = {
  breakpoint: FormattedBreakpoint,
  breakpoints: Breakpoint[],
  removeBreakpoint: typeof actions.removeBreakpoint,
  removeBreakpoints: typeof actions.removeBreakpoints,
  removeAllBreakpoints: typeof actions.removeAllBreakpoints,
  toggleBreakpoints: typeof actions.toggleBreakpoints,
  toggleAllBreakpoints: typeof actions.toggleAllBreakpoints,
  toggleDisabledBreakpoint: typeof actions.toggleDisabledBreakpoint,
  selectSpecificLocation: typeof actions.selectSpecificLocation,
  setBreakpointCondition: typeof actions.setBreakpointCondition,
  openConditionalPanel: typeof actions.openConditionalPanel,
  contextMenuEvent: SyntheticEvent<HTMLElement>
};

export default function showContextMenu(props: Props) {
  const {
    breakpoint,
    breakpoints,
    removeBreakpoint,
    removeBreakpoints,
    removeAllBreakpoints,
    toggleBreakpoints,
    toggleAllBreakpoints,
    toggleDisabledBreakpoint,
    selectSpecificLocation,
    setBreakpointCondition,
    openConditionalPanel,
    contextMenuEvent
  } = props;

  contextMenuEvent.preventDefault();

  const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label");
  const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label");
  const deleteOthersLabel = L10N.getStr(
    "breakpointMenuItem.deleteOthers2.label"
  );
  const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label");
  const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label");
  const enableOthersLabel = L10N.getStr(
    "breakpointMenuItem.enableOthers2.label"
  );
  const disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf2.label");
  const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label");
  const disableOthersLabel = L10N.getStr(
    "breakpointMenuItem.disableOthers2.label"
  );
  const removeConditionLabel = L10N.getStr(
    "breakpointMenuItem.removeCondition2.label"
  );
  const addConditionLabel = L10N.getStr(
    "breakpointMenuItem.addCondition2.label"
  );
  const editConditionLabel = L10N.getStr(
    "breakpointMenuItem.editCondition2.label"
  );

  const deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf2.accesskey");
  const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey");
  const deleteOthersKey = L10N.getStr(
    "breakpointMenuItem.deleteOthers2.accesskey"
  );
  const enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf2.accesskey");
  const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey");
  const enableOthersKey = L10N.getStr(
    "breakpointMenuItem.enableOthers2.accesskey"
  );
  const disableSelfKey = L10N.getStr(
    "breakpointMenuItem.disableSelf2.accesskey"
  );
  const disableAllKey = L10N.getStr("breakpointMenuItem.disableAll2.accesskey");
  const disableOthersKey = L10N.getStr(
    "breakpointMenuItem.disableOthers2.accesskey"
  );
  const removeConditionKey = L10N.getStr(
    "breakpointMenuItem.removeCondition2.accesskey"
  );
  const editConditionKey = L10N.getStr(
    "breakpointMenuItem.editCondition2.accesskey"
  );
  const addConditionKey = L10N.getStr(
    "breakpointMenuItem.addCondition2.accesskey"
  );

  const otherBreakpoints = breakpoints.filter(b => b.id !== breakpoint.id);
  const enabledBreakpoints = breakpoints.filter(b => !b.disabled);
  const disabledBreakpoints = breakpoints.filter(b => b.disabled);
  const otherEnabledBreakpoints = breakpoints.filter(
    b => !b.disabled && b.id !== breakpoint.id
  );
  const otherDisabledBreakpoints = breakpoints.filter(
    b => b.disabled && b.id !== breakpoint.id
  );

  const deleteSelfItem = {
    id: "node-menu-delete-self",
    label: deleteSelfLabel,
    accesskey: deleteSelfKey,
    disabled: false,
    click: () => removeBreakpoint(breakpoint.selectedLocation)
  };

  const deleteAllItem = {
    id: "node-menu-delete-all",
    label: deleteAllLabel,
    accesskey: deleteAllKey,
    disabled: false,
    click: () => removeAllBreakpoints()
  };

  const deleteOthersItem = {
    id: "node-menu-delete-other",
    label: deleteOthersLabel,
    accesskey: deleteOthersKey,
    disabled: false,
    click: () => removeBreakpoints(otherBreakpoints)
  };

  const enableSelfItem = {
    id: "node-menu-enable-self",
    label: enableSelfLabel,
    accesskey: enableSelfKey,
    disabled: false,
    click: () => toggleDisabledBreakpoint(breakpoint.selectedLocation.line)
  };

  const enableAllItem = {
    id: "node-menu-enable-all",
    label: enableAllLabel,
    accesskey: enableAllKey,
    disabled: false,
    click: () => toggleAllBreakpoints(false)
  };

  const enableOthersItem = {
    id: "node-menu-enable-others",
    label: enableOthersLabel,
    accesskey: enableOthersKey,
    disabled: false,
    click: () => toggleBreakpoints(false, otherDisabledBreakpoints)
  };

  const disableSelfItem = {
    id: "node-menu-disable-self",
    label: disableSelfLabel,
    accesskey: disableSelfKey,
    disabled: false,
    click: () => toggleDisabledBreakpoint(breakpoint.selectedLocation.line)
  };

  const disableAllItem = {
    id: "node-menu-disable-all",
    label: disableAllLabel,
    accesskey: disableAllKey,
    disabled: false,
    click: () => toggleAllBreakpoints(true)
  };

  const disableOthersItem = {
    id: "node-menu-disable-others",
    label: disableOthersLabel,
    accesskey: disableOthersKey,
    click: () => toggleBreakpoints(true, otherEnabledBreakpoints)
  };

  const removeConditionItem = {
    id: "node-menu-remove-condition",
    label: removeConditionLabel,
    accesskey: removeConditionKey,
    disabled: false,
    click: () => setBreakpointCondition(breakpoint.selectedLocation)
  };

  const addConditionItem = {
    id: "node-menu-add-condition",
    label: addConditionLabel,
    accesskey: addConditionKey,
    click: () => {
      selectSpecificLocation(breakpoint.selectedLocation);
      openConditionalPanel(breakpoint.selectedLocation.line);
    }
  };

  const editConditionItem = {
    id: "node-menu-edit-condition",
    label: editConditionLabel,
    accesskey: editConditionKey,
    click: () => {
      selectSpecificLocation(breakpoint.selectedLocation);
      openConditionalPanel(breakpoint.selectedLocation.line);
    }
  };

  const hideEnableSelfItem = !breakpoint.disabled;
  const hideEnableAllItem = disabledBreakpoints.length === 0;
  const hideEnableOthersItem = otherDisabledBreakpoints.length === 0;
  const hideDisableAllItem = enabledBreakpoints.length === 0;
  const hideDisableOthersItem = otherEnabledBreakpoints.length === 0;
  const hideDisableSelfItem = breakpoint.disabled;

  const items = [
    { item: enableSelfItem, hidden: () => hideEnableSelfItem },
    { item: enableAllItem, hidden: () => hideEnableAllItem },
    { item: enableOthersItem, hidden: () => hideEnableOthersItem },
    {
      item: { type: "separator" },
      hidden: () =>
        hideEnableSelfItem && hideEnableAllItem && hideEnableOthersItem
    },
    { item: deleteSelfItem },
    { item: deleteAllItem },
    { item: deleteOthersItem, hidden: () => breakpoints.length === 1 },
    {
      item: { type: "separator" },
      hidden: () =>
        hideDisableSelfItem && hideDisableAllItem && hideDisableOthersItem
    },

    { item: disableSelfItem, hidden: () => hideDisableSelfItem },
    { item: disableAllItem, hidden: () => hideDisableAllItem },
    { item: disableOthersItem, hidden: () => hideDisableOthersItem },
    {
      item: { type: "separator" }
    },
    {
      item: addConditionItem,
      hidden: () => breakpoint.condition
    },
    {
      item: editConditionItem,
      hidden: () => !breakpoint.condition
    },
    {
      item: removeConditionItem,
      hidden: () => !breakpoint.condition
    }
  ];

  showMenu(contextMenuEvent, buildMenu(items));
}
<|endoftext|>


<commit_before>module.exports = function (grunt) {
    'use strict';

    grunt.registerTask('livestyle', 'Description', function () {
        this.async();

        var config = grunt.config(this.name) || {},
            options = {
                root: config.root || 'app',
                port: config.port || 9000,
                proxy: config.proxy || null,
                jsx: config.jsx || true,
                less: config.less || true,
                scss: config.scss || true,
                html: config.watchHtml || true,
                cssImages: config.watchCssImages || true,
                processimage: config.processimage || true,
                debug: !!config.debug,
                mappings: {},
                browsers: config.browsers || [
                    '> 1%',
                    'last 2 versions',
                    'Firefox ESR',
                    'Opera 12.1'
                ]
            };

        if (config.mappings) {
            config.mappings.forEach(function (urlEqualsDir) {
                var matchUrlEqualsDir = urlEqualsDir.match(/^([^=]+)=([^=]+)$/);
                if (matchUrlEqualsDir) {
                    options.mappings[matchUrlEqualsDir[1]] = matchUrlEqualsDir[2];
                } else {
                    throw 'Invalid --map syntax: ' + urlEqualsDir;
                }
            });
        }

        var server = require('livestyle/lib/createLiveStyleApp')({
            watchHtml: options.html,
            watchCssImages: options.cssImages,
            dead: options.dead,
            debug: options.debug,
            root: options.root,
            compiless: options.less,
            compilesass: options.scss,
            autoprefixer: options.browsers,
            jsxtransform: options.jsx,
            processImage: options.processimage,
            mappings: options.mappings,
            proxy: options.proxy
        }).listen(options.port, '0.0.0.0');

        if (!options.dead) {
            require('livestyle/lib/installLiveCssFileWatcherInServer')(server, {
                debug: options.debug,
                root: options.root,
                mtime: false,
                watchfile: true,
                mappings: options.mappings,
                watchCssImages: options.cssImages
            }, require('socket.io'));
        }

        if (options.proxy) {
            grunt.log.writeln('Proxying to ' + options.proxy);
            if (options.root) {
                grunt.log.writeln('Serving static CSS files from ' + options.root);
            }
        } else if (options.root) {
            grunt.log.writeln('Serving static files from ' + options.root);
        }

        grunt.log.writeln('Listening to http://' + '0.0.0.0' + ':' + options.port + '/');
    });
};
<commit_msg>Actually allow disabling of middlewares. Oops<commit_after>module.exports = function (grunt) {
    'use strict';

    grunt.registerTask('livestyle', 'Description', function () {
        this.async();

        var config = grunt.config(this.name) || {},
            options = {
                root: config.root || 'app',
                port: config.port || 9000,
                proxy: config.proxy || null,
                jsx: config.jsx === false ? false : true,
                less: config.less === false ? false : true,
                scss: config.scss === false ? false : true,
                html: config.watchHtml === false ? false : true,
                cssImages: config.watchCssImages === false ? false : true,
                processimage: config.processimage === false ? false : true,
                debug: !!config.debug,
                mappings: {},
                browsers: config.browsers || [
                    '> 1%',
                    'last 2 versions',
                    'Firefox ESR',
                    'Opera 12.1'
                ]
            };

        if (config.mappings) {
            config.mappings.forEach(function (urlEqualsDir) {
                var matchUrlEqualsDir = urlEqualsDir.match(/^([^=]+)=([^=]+)$/);
                if (matchUrlEqualsDir) {
                    options.mappings[matchUrlEqualsDir[1]] = matchUrlEqualsDir[2];
                } else {
                    throw 'Invalid --map syntax: ' + urlEqualsDir;
                }
            });
        }

        var server = require('livestyle/lib/createLiveStyleApp')({
            watchHtml: options.html,
            watchCssImages: options.cssImages,
            dead: options.dead,
            debug: options.debug,
            root: options.root,
            compiless: options.less,
            compilesass: options.scss,
            autoprefixer: options.browsers,
            jsxtransform: options.jsx,
            processImage: options.processimage,
            mappings: options.mappings,
            proxy: options.proxy
        }).listen(options.port, '0.0.0.0');

        if (!options.dead) {
            require('livestyle/lib/installLiveCssFileWatcherInServer')(server, {
                debug: options.debug,
                root: options.root,
                mtime: false,
                watchfile: true,
                mappings: options.mappings,
                watchCssImages: options.cssImages
            }, require('socket.io'));
        }

        if (options.proxy) {
            grunt.log.writeln('Proxying to ' + options.proxy);
            if (options.root) {
                grunt.log.writeln('Serving static CSS files from ' + options.root);
            }
        } else if (options.root) {
            grunt.log.writeln('Serving static files from ' + options.root);
        }

        grunt.log.writeln('Listening to http://' + '0.0.0.0' + ':' + options.port + '/');
    });
};
<|endoftext|>


<commit_before>'use strict';

var LoginPage = require('../pages/login_page.js');
var LogoutPage = require('../pages/logout_page.js');
var OrgPage = require('../pages/organization_page');
var data = require('../fixtures/test_data.json');

describe('OCL Org Page', function () {
    var loginPage;
    var logoutPage;
    var orgPage;
    var id = '';

    beforeEach(function () {
        loginPage = new LoginPage();
        logoutPage = new LogoutPage();
        orgPage = new OrgPage();
    });

    it('should login', function () {
        loginPage.visit();
        loginPage.login(data.username,data.password);

        expect((loginPage.loginStatus).getText()).toEqual('Successfully signed in as awadhwa1.');
    });

    it('should create organization', function () {
        id = orgPage.getRandomString(5);
        orgPage.createNewOrg( data.org_short_code+id,
            data.org_name,
            data.website,
            data.company,
            data.org_location
        );

        expect((orgPage.status).getText()).toEqual('Organization Added');
    });

    it('should create source', function () {
        orgPage.createNewSource( data.src_code,
            data.src_full_name,
            data.supported_locale
        );

        expect((orgPage.status).getText()).toEqual('Source created');
    });

    it('should create concept', function () {
        orgPage.createNewConcept( data.concept_id,
            data.concept_name,
            data.name_type
        );

        expect((orgPage.status).getText()).toEqual('Concept created.');

        element(by.linkText('  '+data.src_code)).click();
    });

    it('should create source version', function () {
        orgPage.createNewSourceVersion(data.id,
            data.description
        );

        expect((orgPage.status).getText()).toEqual('Source version created!');
    });

    it('should create concept', function () {
        orgPage.createNewConcept( data.concept_id+id,
            data.concept_name,
            data.name_type
        );

        expect((orgPage.status).getText()).toEqual('Concept created.');

        element(by.linkText('  '+data.src_code)).click();
    });

    it('should create a mapping', function () {
        var fromConceptURL= '/orgs/'+data.org_short_code+id+'/sources/HSTP-Indicators/concepts/C1.1.1.2-/';
        var toConceptURL = '/orgs/'+data.org_short_code+id+'/sources/HSTP-Indicators/concepts/C1.1.1.2-'+id+'/';

        orgPage.createNewMapping(
            fromConceptURL,
            'SAME-AS',
            toConceptURL
        );

        expect((orgPage.status).getText()).toEqual('Mapping created.');

        element(by.linkText('  '+data.org_short_code+id)).click();
    });

    it('should create collection under org', function () {
        orgPage.createNewOrgCollection( data.short_code+id,
            data.col_name,
            data.full_name,
            data.supported_locale
        );
        expect((orgPage.status).getText()).toEqual('Collection created');
    });

    it('should add a reference of concept to a collection', function () {
        var expression = '/orgs/'+data.org_short_code+id+'/sources/HSTP-Indicators/concepts/C1.1.1.2-/';
        orgPage.createNewConceptReference(expression);
        expect((orgPage.status).getText()).toEqual('Expression added.');
        // expect(element(by.linkText(' '+expression)).isPresent()).toBe(true);
    });

     it('should logout', function () {
         logoutPage.logout();

        expect((loginPage.loginStatus).getText()).toEqual('You have signed out.');
    });

});
<commit_msg>Corrected the function name for add reference to a collection<commit_after>'use strict';

var LoginPage = require('../pages/login_page.js');
var LogoutPage = require('../pages/logout_page.js');
var OrgPage = require('../pages/organization_page');
var data = require('../fixtures/test_data.json');

describe('OCL Org Page', function () {
    var loginPage;
    var logoutPage;
    var orgPage;
    var id = '';
    var mapping_id;

    beforeEach(function () {
        loginPage = new LoginPage();
        logoutPage = new LogoutPage();
        orgPage = new OrgPage();
    });

    it('should login', function () {
        loginPage.visit();
        loginPage.login(data.username,data.password);

        expect((loginPage.loginStatus).getText()).toEqual('Successfully signed in as awadhwa1.');
    });

    it('should create organization', function () {
        id = orgPage.getRandomString(5);
        orgPage.createNewOrg( data.org_short_code+id,
            data.org_name,
            data.website,
            data.company,
            data.org_location
        );

        expect((orgPage.status).getText()).toEqual('Organization Added');
    });

    it('should create source', function () {
        orgPage.createNewSource( data.src_code,
            data.src_full_name,
            data.supported_locale
        );

        expect((orgPage.status).getText()).toEqual('Source created');
    });

    it('should create concept', function () {
        orgPage.createNewConcept( data.concept_id,
            data.concept_name,
            data.name_type
        );

        expect((orgPage.status).getText()).toEqual('Concept created.');

        element(by.linkText('  '+data.src_code)).click();
    });

    it('should create source version', function () {
        orgPage.createNewSourceVersion(data.id,
            data.description
        );

        expect((orgPage.status).getText()).toEqual('Source version created!');
    });

    it('should create concept', function () {
        orgPage.createNewConcept( data.concept_id+id,
            data.concept_name,
            data.name_type
        );

        expect((orgPage.status).getText()).toEqual('Concept created.');

        element(by.linkText('  '+data.src_code)).click();
    });

    it('should create a mapping', function () {
        var fromConceptURL= '/orgs/'+data.org_short_code+id+'/sources/HSTP-Indicators/concepts/C1.1.1.2-/';
        var toConceptURL = '/orgs/'+data.org_short_code+id+'/sources/HSTP-Indicators/concepts/C1.1.1.2-'+id+'/';

        orgPage.createNewMapping(
            fromConceptURL,
            'SAME-AS',
            toConceptURL
        );

        expect((orgPage.status).getText()).toEqual('Mapping created.');

        // mapping_id = element(by.css('#mapping_id .row .field-label-value')).getText();
        // console.log(mapping_id);
        element(by.linkText('  '+data.org_short_code+id)).click();
    });

    it('should create collection under org', function () {
        orgPage.createNewOrgCollection( data.short_code+id,
            data.col_name,
            data.full_name,
            data.supported_locale
        );
        expect((orgPage.status).getText()).toEqual('Collection created');
    });

    it('should add a reference of concept to a collection', function () {
        var concept_expression = '/orgs/'+data.org_short_code+id+'/sources/HSTP-Indicators/concepts/C1.1.1.2-/';
        orgPage.createNewReference(concept_expression);
        expect((orgPage.status).getText()).toEqual('Expression added.');
        // expect(element(by.linkText(' '+expression)).isPresent()).toBe(true);
    });

    // it('should add a reference of mapping to a collection', function () {
    //     var mapping_expression = '/orgs/'+data.org_short_code+id+'/sources/HSTP-Indicators/mappings/'+mapping_id+'/';
    //     orgPage.createNewReference(mapping_expression);
    //     console.log(mapping_expression);
    //
    //     expect((orgPage.status).getText()).toEqual('Expression added.');
    //     // expect(element(by.linkText(' '+expression)).isPresent()).toBe(true);
    // });

     it('should logout', function () {
         logoutPage.logout();

        expect((loginPage.loginStatus).getText()).toEqual('You have signed out.');
    });

});
<|endoftext|>