<commit_before>#!/usr/bin/env node

// Manages User CLI interactions

// load utils
var _cli = require('commander');
var _progressbar = require('cli-progress');
var _pkg = require('../package.json')
var _prompt = require('prompt')
var _nodemcutool = require('../lib/NodeMCU-Tool');
var _colors = require('colors');
var _fs = require('fs');

// setup CLI/TTY message handler (colorized output)
_nodemcutool.onError(function(context, message){
    if (context && context.length > 0){
        console.error(_colors.red('[' + context + ']'), message);
    }else{
        console.error(message);
    }
});

_nodemcutool.onOutput(function(message){
    console.log(message);
});

// helper to enable silent mode
var SilentMode = function(enable){
    if (enable){
        // ignore status messages
        _nodemcutool.onStatus(function(context, message){
        });
    }else{
        _nodemcutool.onStatus(function(context, message){
            if (context && context.length > 0){
                console.log(_colors.cyan('[' + context + ']'), message);
            }else{
                console.log(message);
            }
        });
    }
};

// initialize default config
var defaults = (function(){

    // standard configuration
    var config = {
        baudrate: '9600',
        port: '/dev/ttyUSB0',
        optimize: false,
        compile: false,
        keeppath: false
    };

    try{
        // try to load project based configuration
        var data = _fs.readFileSync('.nodemcutool', 'utf8');

        if (data){
            // decode json based data
            var d = JSON.parse(data);

            // extract values
            config.baudrate = d.baudrate || config.baudrate;
            config.port = d.port || config.port;
            config.optimize = (d.optimize && d.optimize === true);
            config.compile = (d.compile && d.compile === true);
            config.keeppath = (d.keeppath && d.keeppath === true);
            console.log(_colors.cyan('[NodeMCU-Tool]'), 'Project based configuration loaded');
        }
    }catch (err){
    }

    return config;
})();

// CLI setup
_cli
    // read file version package.json
    .version(_pkg.version)

    // serial port device
    .option('-p, --port <port>', 'Serial port device name e.g. /dev/ttyUSB0, COM1', defaults.port)

    // serial port baudrate
    .option('-b, --baud <baudrate>', 'Serial Port Baudrate in bps, default 9600', defaults.baudrate)

    // silent mode - no status messages are shown
    .option('--silent', 'Enable silent mode - no status messages are shown', false);

_cli
    .command('fsinfo')
    .description('Show file system info (current files, memory usage)')

    // json output mode
    .option('--json', 'Display output JSON encoded', false)

    .action(function(options){
        // force silent mode!
        SilentMode(options.json===true);

        _nodemcutool.fsinfo(_cli.port, _cli.baud, options.json);
    });

_cli
    .command('run <file>')
    .description('Executes an existing .lua or .lc file on NodeMCU')
    .action(function(filename){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.run(_cli.port, _cli.baud, filename);
    });

_cli
    .command('upload <file>')
    .description('Upload Files to NodeMCU (ESP8266) target')

    // file cleanup
    .option('-o, --optimize', 'Removes comments and empty lines from file before uploading', false)

    // compile files after upload
    .option('-c, --compile', 'Compile LUA file to bytecode (.lc) and remove the original file after upload', false)

    // keep-path
    .option('-k, --keeppath', 'Keep a relative file path in the destination filename (i.e: static/test.html will be named static/test.html)', false)

    // sets the remote filename
    .option('-n, --remotename <remotename>', 'Set destination file name. Default is same as original', false)

    .action(function(localFile, options){
        // silent mode ?
        SilentMode(_cli.silent===true);

        // initialize a new progress bar
        var bar = new _progressbar.Bar({
            format: 'Upload Status {percentage}% [{bar}] | ETA {eta}s',
            clearOnComplete: true
        });

        // append global defaults
        if (!options.compile){
            options.compile = defaults.compile;
        }
        if (!options.optimize){
            options.optimize = defaults.optimize;
        }
        if (!options.keeppath){
          options.keeppath = defaults.keeppath;
        }

        _nodemcutool.upload(_cli.port, _cli.baud, localFile, options, function(current, total){
            // bar initialized ?
            if (current == 0) {
                bar.start(total, 0);
            }else {
                bar.update(current);

                // finished ?
                if (current >= total) {
                    bar.stop();
                }
            }
        });
    });

_cli
    .command('download <file>')
    .description('Download files from NodeMCU (ESP8266) target')

    .action(function(remoteFilename){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.download(_cli.port, _cli.baud, remoteFilename);
    });

_cli
    .command('remove <file>')
    .description('Removes a file from NodeMCU filesystem')
    .action(function(filename){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.remove(_cli.port, _cli.baud, filename);
    });

_cli
    .command('mkfs')
    .description('Format the SPIFFS filesystem - ALL FILES ARE REMOVED')

    // force fs creation without prompt
    .option('--noninteractive', 'Execute command without user interaction', false)

    .action(function(options){
        // silent mode ?
        SilentMode(_cli.silent===true);

        // no prompt!
        if (options.noninteractive){
            // format
            _nodemcutool.mkfs(_cli.port, _cli.baud);

            return;
        }

        // user confirmation required!
        _prompt.start();
        _prompt.message = '';
        _prompt.delimiter = '';
        _prompt.colors = false;

        _prompt.get({
            properties: {
                confirm: {
                    pattern: /^(yes|no|y|n)$/gi,
                    description: '[NodeMCU-Tool] Do you really want to format the filesystem and delete all file ?',
                    message: 'Type yes/no',
                    required: true,
                    default: 'no'
                }
            }
        }, function (err, result){
            if (err){
                console.log('\n[NodeMCU-Tool] Formatting aborted')
                return;
            }

            // transform to lower case
            var c = result.confirm.toLowerCase();

            // check
            if (c!='y' && c!='yes'){
                console.log('[NodeMCU-Tool] Formatting aborted');
                return;
            }

            // format
            _nodemcutool.mkfs(_cli.port, _cli.baud);
        });

    });

_cli
    .command('terminal')
    .description('Opens a Terminal connection to NodeMCU')
    .action(function(){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.terminal(_cli.port, _cli.baud);
    });

_cli
    .command('init')
    .description('Initialize a project-based Configuration (file) within current directory')
    .action(function(){
        console.log('[NodeMCU-Tool] Creating project based configuration file..');

        // get user input
        _prompt.start();
        _prompt.message = '';
        _prompt.delimiter = '';
        _prompt.colors = false;

        _prompt.get({
            properties: {
                baudrate: {
                    pattern: /^\d+$/,
                    description: '[NodeMCU-Tool] Baudrate in Bit per Seconds, e.g. 9600 (default)',
                    required: false,
                    message: 'Only Integers allowed!',
                    default: 9600
                },
                port: {
                    pattern: /^.+$/,
                    description: '[NodeMCU-Tool] Serial connection to use, e.g. COM1 or /dev/ttyUSB2',
                    required: false,
                    default: '/dev/ttyUSB0'
                }
            }
        }, function (err, data){

            if (err){
                console.error(err);
            }else{
                // set defaults
                data.optimize = false;
                data.compile = false;

                // write config to file
                _fs.writeFileSync('.nodemcutool', JSON.stringify(data, null, 4));
            }
        });
    });

_cli
    .command('devices')
    .description('Shows a list of all available NodeMCU Modules/Serial Devices')

    // disable the device filter based on vendorId's of common NodeMCU modules
    .option('--all', 'Show all Serial Devices, not only NodeMCU Modules', false)

    .action(function(options){
        // silent mode ?
        SilentMode(_cli.silent===true);

        // show all devices ?
        var showAll = options.all || false;

        _nodemcutool.devices(_cli.port, _cli.baud, showAll);
    });

_cli
    .command('cloudconnect')
    .action(function(c){
        console.log(_colors.cyan('[NodeMCU-Tool]'), 'http://nodemcutool.aenon.de/34234234 "' + c + '"');
    });

_cli
    .command('*')
    .action(function(c){
        console.log(_colors.cyan('[NodeMCU-Tool]'), 'Unknown command "' + c + '"');
        _cli.outputHelp();
    });

// run the commander dispatcher
_cli.parse(process.argv);

// default action (no command provided)
if (!process.argv.slice(2).length) {
    _cli.outputHelp();
}<commit_msg>fixed silent mode for fsinfo command<commit_after>#!/usr/bin/env node

// Manages User CLI interactions

// load utils
var _cli = require('commander');
var _progressbar = require('cli-progress');
var _pkg = require('../package.json')
var _prompt = require('prompt')
var _nodemcutool = require('../lib/NodeMCU-Tool');
var _colors = require('colors');
var _fs = require('fs');

// setup CLI/TTY message handler (colorized output)
_nodemcutool.onError(function(context, message){
    if (context && context.length > 0){
        console.error(_colors.red('[' + context + ']'), message);
    }else{
        console.error(message);
    }
});

_nodemcutool.onOutput(function(message){
    console.log(message);
});

// helper to enable silent mode
var SilentMode = function(enable){
    if (enable){
        // ignore status messages
        _nodemcutool.onStatus(function(context, message){
        });
    }else{
        _nodemcutool.onStatus(function(context, message){
            if (context && context.length > 0){
                console.log(_colors.cyan('[' + context + ']'), message);
            }else{
                console.log(message);
            }
        });
    }
};

// initialize default config
var defaults = (function(){

    // standard configuration
    var config = {
        baudrate: '9600',
        port: '/dev/ttyUSB0',
        optimize: false,
        compile: false,
        keeppath: false
    };

    try{
        // try to load project based configuration
        var data = _fs.readFileSync('.nodemcutool', 'utf8');

        if (data){
            // decode json based data
            var d = JSON.parse(data);

            // extract values
            config.baudrate = d.baudrate || config.baudrate;
            config.port = d.port || config.port;
            config.optimize = (d.optimize && d.optimize === true);
            config.compile = (d.compile && d.compile === true);
            config.keeppath = (d.keeppath && d.keeppath === true);
            console.log(_colors.cyan('[NodeMCU-Tool]'), 'Project based configuration loaded');
        }
    }catch (err){
    }

    return config;
})();

// CLI setup
_cli
    // read file version package.json
    .version(_pkg.version)

    // serial port device
    .option('-p, --port <port>', 'Serial port device name e.g. /dev/ttyUSB0, COM1', defaults.port)

    // serial port baudrate
    .option('-b, --baud <baudrate>', 'Serial Port Baudrate in bps, default 9600', defaults.baudrate)

    // silent mode - no status messages are shown
    .option('--silent', 'Enable silent mode - no status messages are shown', false);

_cli
    .command('fsinfo')
    .description('Show file system info (current files, memory usage)')

    // json output mode
    .option('--json', 'Display output JSON encoded', false)

    .action(function(options){
        // force silent mode!
        SilentMode(options.json===true || _cli.silent===true);

        _nodemcutool.fsinfo(_cli.port, _cli.baud, options.json);
    });

_cli
    .command('run <file>')
    .description('Executes an existing .lua or .lc file on NodeMCU')
    .action(function(filename){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.run(_cli.port, _cli.baud, filename);
    });

_cli
    .command('upload <file>')
    .description('Upload Files to NodeMCU (ESP8266) target')

    // file cleanup
    .option('-o, --optimize', 'Removes comments and empty lines from file before uploading', false)

    // compile files after upload
    .option('-c, --compile', 'Compile LUA file to bytecode (.lc) and remove the original file after upload', false)

    // keep-path
    .option('-k, --keeppath', 'Keep a relative file path in the destination filename (i.e: static/test.html will be named static/test.html)', false)

    // sets the remote filename
    .option('-n, --remotename <remotename>', 'Set destination file name. Default is same as original', false)

    .action(function(localFile, options){
        // silent mode ?
        SilentMode(_cli.silent===true);

        // initialize a new progress bar
        var bar = new _progressbar.Bar({
            format: 'Upload Status {percentage}% [{bar}] | ETA {eta}s',
            clearOnComplete: true
        });

        // append global defaults
        if (!options.compile){
            options.compile = defaults.compile;
        }
        if (!options.optimize){
            options.optimize = defaults.optimize;
        }
        if (!options.keeppath){
          options.keeppath = defaults.keeppath;
        }

        _nodemcutool.upload(_cli.port, _cli.baud, localFile, options, function(current, total){
            // bar initialized ?
            if (current == 0) {
                bar.start(total, 0);
            }else {
                bar.update(current);

                // finished ?
                if (current >= total) {
                    bar.stop();
                }
            }
        });
    });

_cli
    .command('download <file>')
    .description('Download files from NodeMCU (ESP8266) target')

    .action(function(remoteFilename){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.download(_cli.port, _cli.baud, remoteFilename);
    });

_cli
    .command('remove <file>')
    .description('Removes a file from NodeMCU filesystem')
    .action(function(filename){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.remove(_cli.port, _cli.baud, filename);
    });

_cli
    .command('mkfs')
    .description('Format the SPIFFS filesystem - ALL FILES ARE REMOVED')

    // force fs creation without prompt
    .option('--noninteractive', 'Execute command without user interaction', false)

    .action(function(options){
        // silent mode ?
        SilentMode(_cli.silent===true);

        // no prompt!
        if (options.noninteractive){
            // format
            _nodemcutool.mkfs(_cli.port, _cli.baud);

            return;
        }

        // user confirmation required!
        _prompt.start();
        _prompt.message = '';
        _prompt.delimiter = '';
        _prompt.colors = false;

        _prompt.get({
            properties: {
                confirm: {
                    pattern: /^(yes|no|y|n)$/gi,
                    description: '[NodeMCU-Tool] Do you really want to format the filesystem and delete all file ?',
                    message: 'Type yes/no',
                    required: true,
                    default: 'no'
                }
            }
        }, function (err, result){
            if (err){
                console.log('\n[NodeMCU-Tool] Formatting aborted')
                return;
            }

            // transform to lower case
            var c = result.confirm.toLowerCase();

            // check
            if (c!='y' && c!='yes'){
                console.log('[NodeMCU-Tool] Formatting aborted');
                return;
            }

            // format
            _nodemcutool.mkfs(_cli.port, _cli.baud);
        });

    });

_cli
    .command('terminal')
    .description('Opens a Terminal connection to NodeMCU')
    .action(function(){
        // silent mode ?
        SilentMode(_cli.silent===true);

        _nodemcutool.terminal(_cli.port, _cli.baud);
    });

_cli
    .command('init')
    .description('Initialize a project-based Configuration (file) within current directory')
    .action(function(){
        console.log('[NodeMCU-Tool] Creating project based configuration file..');

        // get user input
        _prompt.start();
        _prompt.message = '';
        _prompt.delimiter = '';
        _prompt.colors = false;

        _prompt.get({
            properties: {
                baudrate: {
                    pattern: /^\d+$/,
                    description: '[NodeMCU-Tool] Baudrate in Bit per Seconds, e.g. 9600 (default)',
                    required: false,
                    message: 'Only Integers allowed!',
                    default: 9600
                },
                port: {
                    pattern: /^.+$/,
                    description: '[NodeMCU-Tool] Serial connection to use, e.g. COM1 or /dev/ttyUSB2',
                    required: false,
                    default: '/dev/ttyUSB0'
                }
            }
        }, function (err, data){

            if (err){
                console.error(err);
            }else{
                // set defaults
                data.optimize = false;
                data.compile = false;

                // write config to file
                _fs.writeFileSync('.nodemcutool', JSON.stringify(data, null, 4));
            }
        });
    });

_cli
    .command('devices')
    .description('Shows a list of all available NodeMCU Modules/Serial Devices')

    // disable the device filter based on vendorId's of common NodeMCU modules
    .option('--all', 'Show all Serial Devices, not only NodeMCU Modules', false)

    .action(function(options){
        // silent mode ?
        SilentMode(_cli.silent===true);

        // show all devices ?
        var showAll = options.all || false;

        _nodemcutool.devices(_cli.port, _cli.baud, showAll);
    });

_cli
    .command('cloudconnect')
    .action(function(c){
        console.log(_colors.cyan('[NodeMCU-Tool]'), 'http://nodemcutool.aenon.de/34234234 "' + c + '"');
    });

_cli
    .command('*')
    .action(function(c){
        console.log(_colors.cyan('[NodeMCU-Tool]'), 'Unknown command "' + c + '"');
        _cli.outputHelp();
    });

// run the commander dispatcher
_cli.parse(process.argv);

// default action (no command provided)
if (!process.argv.slice(2).length) {
    _cli.outputHelp();
}<|endoftext|>


<commit_before>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var hash = require('./hash');
var util = require('./util');
var cache = require('./cache');
var plugins = require('./plugins/');
var extname = require('path').extname;

function transport(vinyl, options){
  if (options.cache) {
    // set hash
    vinyl.hash = hash(vinyl.stat);
    // get cache
    var cached = cache.get(vinyl);

    // if not cached, parse vinyl
    if (cached === null) {
      vinyl = parse(vinyl, options);

      // cache vinyl
      cache.set(vinyl);
    } else {
      vinyl = cached;
    }
  } else {
    vinyl = parse(vinyl, options);
  }

  return vinyl;
}

function parse(vinyl, options){
  var parsers = initParsers(options);
  var parser = chooseParser(vinyl, parsers);

  // parse vinyl
  return parser(vinyl, options);
}

function initParsers(options){
  var defaults = {
    '.js': plugins.js,
    '.css': plugins.css,
    '.tpl': plugins.tpl,
    '.json': plugins.json,
    '.html': plugins.html
  };

  var parser;
  var parsers = options.plugins || {};
  var ret = { defined: {}, other: plugins.other };

  for (var key in defaults) {
    if (defaults.hasOwnProperty(key)) {
      if (parsers.hasOwnProperty(key)) {
        parser = parsers[key];

        if (is.fn(parser)) {
          parser = parser(options);
        }

        if (!is.fn(parser)) {
          util.throwError('options.plugins[' + key + '] value should be function.');
        }
      } else {
        parser = defaults[key];
      }

      ret.defined[key] = parser;
    }
  }

  return ret;
}

function chooseParser(vinyl, parsers){
  var ext = extname(vinyl.path);
  var parser = parsers.defined[ext];

  return parser || parsers.other;
}

/**
 * Exports module.
 */

module.exports = transport;
<commit_msg>add source files<commit_after>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var hash = require('./hash');
var util = require('./util');
var cache = require('./cache');
var extname = require('path').extname;
var plugins = require('./plugins/index');

// inline plugins
var inlinePlugins = {
  '.js': plugins.js,
  '.css': plugins.css,
  '.tpl': plugins.tpl,
  '.json': plugins.json,
  '.html': plugins.html
};

function transport(vinyl, options){
  if (options.cache) {
    // set hash
    vinyl.hash = hash(vinyl.stat);
    // get cache
    var cached = cache.get(vinyl);

    // if not cached, parse vinyl
    if (cached === null) {
      vinyl = parse(vinyl, options);

      // cache vinyl
      cache.set(vinyl);
    } else {
      vinyl = cached;
    }
  } else {
    vinyl = parse(vinyl, options);
  }

  return vinyl;
}

function parse(vinyl, options){
  var plugins = initPlugins(options);
  var plugin = choosePlugin(vinyl, plugins);

  // parse vinyl
  return plugin(vinyl, options);
}

function initPlugins(options){
  var plugin;
  var customPlugins = options.plugins || {};
  var plugins = { defined: {}, other: inlinePlugins.other };

  for (var key in inlinePlugins) {
    if (inlinePlugins.hasOwnProperty(key)) {
      if (customPlugins.hasOwnProperty(key)) {
        plugin = customPlugins[key];

        if (is.fn(plugin)) {
          plugin = plugin(options);
        }

        if (!is.fn(plugin)) {
          util.throwError('options.plugins[' + key + '] value should be function.');
        }
      } else {
        plugin = inlinePlugins[key];
      }

      plugins.defined[key] = plugin;
    }
  }

  return plugins;
}

function choosePlugin(vinyl, plugins){
  var ext = extname(vinyl.path);
  var plugin = plugins.defined[ext];

  return plugin || plugins.other;
}

/**
 * Exports module.
 */

module.exports = transport;
<|endoftext|>


<commit_before>module.exports = {
    authenticate: true,
    get: function (req, res, next) {
        // the auth middleware must have been executed for the user property to be set
        if(req.user.level === 'anonymous')
            res.send("We don't know you. Who are you?");
        else
            // the user object contains the user ID and payload
            res.send("Hello " + req.user.id + "! Your payload is " + JSON.stringify(req.user.payload));
    }
}
<commit_msg>Added res.status<commit_after>module.exports = {
    authenticate: true,
    get: function (req, res, next) {
        // the auth middleware must have been executed for the user property to be set
        if(req.user.level === 'anonymous')
            res.status(401).send("We don't know you. Who are you?");
        else
            // the user object contains the user ID and payload
            res.send("Hello " + req.user.id + "! Your payload is " + JSON.stringify(req.user.payload));
    }
}
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import _ from 'lodash'
import classnames from 'classnames'
import uuid from 'node-uuid'

import RuleMessageOptions from 'src/kapacitor/components/RuleMessageOptions'
import RuleMessageText from 'src/kapacitor/components/RuleMessageText'
import RuleMessageTemplates from 'src/kapacitor/components/RuleMessageTemplates'
import Dropdown from 'shared/components/Dropdown'

import {DEFAULT_ALERTS, RULE_ALERT_OPTIONS} from 'src/kapacitor/constants'

class RuleMessage extends Component {
  constructor(props) {
    super(props)

    this.state = {
      selectedAlertNodeName: null,
      endpointsOnThisAlert: [],
    }
  }

  handleChangeMessage = e => {
    const {actions, rule} = this.props
    actions.updateMessage(rule.id, e.target.value)
  }

  handleChooseAlert = item => () => {
    const {actions} = this.props
    actions.updateAlerts(item.ruleID, [item.text])
    actions.updateAlertNodes(item.ruleID, item.text, '')
    this.setState({selectedAlertNodeName: item.text})
  }

  handleAddNewAlertEndpoint = selectedItem => {
    this.setState({
      endpointsOnThisAlert: _.concat(
        this.state.endpointsOnThisAlert,
        selectedItem
      ),
    })
  }

  render() {
    const {rule, actions, enabledAlerts} = this.props
    const defaultAlertEndpoints = DEFAULT_ALERTS.map(text => {
      return {text, ruleID: rule.id}
    })

    const alerts = [
      ...defaultAlertEndpoints,
      ...enabledAlerts.map(text => {
        return {text, ruleID: rule.id}
      }),
    ]

    const selectedAlertNodeName = rule.alerts[0] || alerts[0].text

    return (

Alert Message

Send this Alert to:

              {this.state.endpointsOnThisAlert
                // only display alert endpoints that have rule alert options configured
                .filter(alert => _.get(RULE_ALERT_OPTIONS, alert.text, false))
                .map(alert =>

                    {alert.text}

                )}

            <Dropdown
              items={alerts}
              menuClass="dropdown-malachite"
              selected="Add an Endpoint"
              onChoose={this.handleAddNewAlertEndpoint}
              className="dropdown-140 rule-message--add-endpoint"
            />

          <RuleMessageOptions
            rule={rule}
            alertNodeName={selectedAlertNodeName}
            updateAlertNodes={actions.updateAlertNodes}
            updateDetails={actions.updateDetails}
            updateAlertProperty={actions.updateAlertProperty}
          />
          <RuleMessageText
            rule={rule}
            updateMessage={this.handleChangeMessage}
          />
          <RuleMessageTemplates
            rule={rule}
            updateMessage={actions.updateMessage}
          />

    )
  }
}

const {arrayOf, func, shape, string} = PropTypes

RuleMessage.propTypes = {
  rule: shape({}).isRequired,
  actions: shape({
    updateAlertNodes: func.isRequired,
    updateMessage: func.isRequired,
    updateDetails: func.isRequired,
    updateAlertProperty: func.isRequired,
  }).isRequired,
  enabledAlerts: arrayOf(string.isRequired).isRequired,
}

export default RuleMessage
<commit_msg>Add new alert endpoints by kind and number<commit_after>import React, {Component, PropTypes} from 'react'
import _ from 'lodash'
import classnames from 'classnames'
import uuid from 'node-uuid'

import RuleMessageOptions from 'src/kapacitor/components/RuleMessageOptions'
import RuleMessageText from 'src/kapacitor/components/RuleMessageText'
import RuleMessageTemplates from 'src/kapacitor/components/RuleMessageTemplates'
import Dropdown from 'shared/components/Dropdown'

import {DEFAULT_ALERTS, RULE_ALERT_OPTIONS} from 'src/kapacitor/constants'

class RuleMessage extends Component {
  constructor(props) {
    super(props)

    this.state = {
      selectedAlertNodeName: null,
      endpointsOnThisAlert: [],
      endpointsOfKind: {},
    }
  }

  handleChangeMessage = e => {
    const {actions, rule} = this.props
    actions.updateMessage(rule.id, e.target.value)
  }

  handleChooseAlert = item => () => {
    const {actions} = this.props
    actions.updateAlerts(item.ruleID, [item.text]) // TODO: this seems to be doing a lot more than it needs to.
    actions.updateAlertNodes(item.ruleID, item.text, '')
    this.setState({selectedAlertNodeName: item.text})
  }

  handleAddNewAlertEndpoint = selectedItem => {
    const {endpointsOnThisAlert, endpointsOfKind} = this.state
    const newItemNumbering = _.get(endpointsOfKind, selectedItem.text, 0) + 1
    const newItemName = selectedItem.text + newItemNumbering
    this.setState({
      endpointsOnThisAlert: _.concat(endpointsOnThisAlert, {
        text: newItemName,
        kind: selectedItem.text,
        ruleID: selectedItem.ruleID,
      }),
      endpointsOfKind: {
        ...endpointsOfKind,
        [selectedItem.text]: newItemNumbering,
      },
    })
    console.log(this.state.endpointsOnThisAlert)
  }
  handleRemoveAlertEndpoint = removedItem => {
    console.log(removedItem)
  }

  render() {
    const {rule, actions, enabledAlerts} = this.props
    const defaultAlertEndpoints = DEFAULT_ALERTS.map(text => {
      return {text, kind: text, ruleID: rule.id}
    })

    const alerts = [
      ...defaultAlertEndpoints,
      ...enabledAlerts.map(text => {
        return {text, kind: text, ruleID: rule.id}
      }),
    ]

    const selectedAlertNodeName = rule.alerts[0] || alerts[0].text

    return (

Alert Message

Send this Alert to:

              {this.state.endpointsOnThisAlert
                .filter(alert => _.get(RULE_ALERT_OPTIONS, alert.kind, false)) // / TODO this looks like a problem
                .map(alert =>

                    {alert.text}

                )}

            <Dropdown
              items={alerts}
              menuClass="dropdown-malachite"
              selected="Add an Endpoint"
              onChoose={this.handleAddNewAlertEndpoint}
              className="dropdown-140 rule-message--add-endpoint"
            />

          <RuleMessageOptions
            rule={rule}
            alertNodeName={selectedAlertNodeName}
            updateAlertNodes={actions.updateAlertNodes}
            updateDetails={actions.updateDetails}
            updateAlertProperty={actions.updateAlertProperty}
          />
          <RuleMessageText
            rule={rule}
            updateMessage={this.handleChangeMessage}
          />
          <RuleMessageTemplates
            rule={rule}
            updateMessage={actions.updateMessage}
          />

    )
  }
}

const {arrayOf, func, shape, string} = PropTypes

RuleMessage.propTypes = {
  rule: shape({}).isRequired,
  actions: shape({
    updateAlertNodes: func.isRequired,
    updateMessage: func.isRequired,
    updateDetails: func.isRequired,
    updateAlertProperty: func.isRequired,
  }).isRequired,
  enabledAlerts: arrayOf(string.isRequired).isRequired,
}

export default RuleMessage
<|endoftext|>


<commit_before>var util = require('util');
var net = require('net');
var winston = require('winston');
var _ = require('lodash');
var Readable = require('stream').Readable;

function compactObject(obj) {
    _.forOwn(obj, function(val, key) {
       if (_.isEmpty(val)) delete obj[key];
    });
    return obj;
}
_.mixin({'compactObject': compactObject});

function Remote(opts) {
    var defaults = {
        host: '0.0.0.0',
        port: 9003
    };
    _.extend(this, this, opts);
}

util.inherits(Remote, winston.Transport);

Remote.prototype.client = function() {
    var client = net.connect({host: this.host, port: this.port});
    client.on('error', function(err) {
        throw new Error(err);
    });
    return client;
};

Remote.prototype.log = function(level, message, meta, callback) {
    callback = _.isFunction(callback) ? callback : _.noop();

    var log = _.compactObject({level: level, message: message, meta: meta, timestamp: (new Date()).toString()});

    var stream = Readable();
    stream.push([JSON.stringify(log),'\n'].join(''));
    stream.push(null);
    stream.pipe(this.client());

    callback();
};

module.exports = Remote;
<commit_msg>show line info<commit_after>var util = require('util');
var net = require('net');
var winston = require('winston');
var _ = require('lodash');
var Readable = require('stream').Readable;

function compactObject(obj) {
    _.forOwn(obj, function(val, key) {
       if (_.isEmpty(val)) delete obj[key];
    });
    return obj;
}
_.mixin({'compactObject': compactObject});

function Remote(opts) {
    var defaults = {
        host: '0.0.0.0',
        port: 9003,
        label: 'Client'
    };
    _.extend(this, opts, defaults);
    this.name = 'Remote';

    Remote.super_.apply(this, arguments);
}

util.inherits(Remote, winston.Transport);

Remote.prototype.client = function() {
    var client = net.connect({host: this.host, port: this.port});
    client.on('error', function(err) {
        throw new Error(err);
    });
    return client;
};

function getLineInfo() {
    var stack = (new Error()).stack.split('\n').slice(3);
    // Stack trace format :
    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
    var s = stack[7],
        sp = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi.exec(s) || /at\s+()(.*):(\d*):(\d*)/gi.exec(s);
    var data = {};
    if (sp.length === 5) {
        data.method = sp[1];
        data.path = sp[2];
        data.line = sp[3];
        data.pos = sp[4];
        data.file = require('path').basename(data.path);
    }
    delete stack;
    return [' at ', data.path.replace(process.__basePath + '/', ''), (':' + data.line) || '', (':' + data.pos) || '', ' ', data.method || ''].join('');
}

Remote.prototype.log = function(level, message, meta, callback) {
    var self = this;

    var log = _.compactObject({level: level, message: self.label + '::' + message + getLineInfo(), meta: meta , timestamp: (new Date()).toString()});
    var stream = Readable();
    stream.push([JSON.stringify(log),'\n'].join(''));
    stream.push(null);
    stream.pipe(self.client());

    self.emit('logged');
    if (callback) callback(null, true); // winston 0.8.x
};

module.exports = Remote;
<|endoftext|>


<commit_before>let PropertyObject = {
  address: '',
  active: false,
  admin_fee_amt: 0,
  admin_fee_refund: false,
  airconditioning: false,
  appalcart: false,
  bathroom_no: 1,
  bedroom_no: 1,
  campus_distance: 0,
  clean_fee_amt: 0,
  clean_fee_refund: false,
  clubhouse: false,
  contact_id: 0,
  contract_length: 0,
  created: 0,
  description: '',
  dishwasher: false,
  efficiency: false,
  furnished: false,
  heat_type: [],
  internet_type: 0,
  lease_type: 0,
  laundry_type: 0,
  monthly_rent: '',
  move_in_date: 0,
  name: '',
  other_fees: '',
  parking_fee: 0,
  parking_per_unit: 1,
  pet_deposit: 0,
  pet_dep_refund: false,
  pets_allowed: false,
  pet_fee: 0,
  pet_type: '',
  security_amt: 0,
  security_refund: false,
  student_type: 0,
  sublease: false,
  timeout: 0,
  trash_type: 0,
  updated: 0,
  util_cable: '',
  util_internet: '',
  util_fuel: '',
  util_phone: '',
  util_power: '',
  util_trash: '',
  util_water: '',
  utilities_inc: false,
  tv_type: 0,
  window_number: true,
  workout_room: false,
  id : 0
}

export default PropertyObject
<commit_msg>changed some defaults<commit_after>const PropertyObject = {
  address: '',
  active: false,
  admin_fee_amt: 0,
  admin_fee_refund: false,
  airconditioning: false,
  appalcart: false,
  bathroom_no: 1,
  bedroom_no: 1,
  campus_distance: 0,
  clean_fee_amt: 0,
  clean_fee_refund: false,
  clubhouse: false,
  contact_id: 0,
  contract_length: 3,
  created: 0,
  description: '',
  dishwasher: false,
  efficiency: false,
  furnished: false,
  heat_type: [],
  internet_type: 1,
  lease_type: 0,
  laundry_type: 0,
  monthly_rent: '',
  move_in_date: 0,
  name: '',
  other_fees: '',
  parking_fee: 0,
  parking_per_unit: 1,
  pet_deposit: 0,
  pet_dep_refund: false,
  pets_allowed: false,
  pet_fee: 0,
  pet_type: '',
  security_amt: 0,
  security_refund: false,
  student_type: 0,
  sublease: false,
  timeout: 0,
  trash_type: 0,
  updated: 0,
  util_cable: '',
  util_internet: '',
  util_fuel: '',
  util_phone: '',
  util_power: '',
  util_trash: '',
  util_water: '',
  utilities_inc: false,
  tv_type: 0,
  window_number: true,
  workout_room: false,
  id : 0
}

export default PropertyObject
<|endoftext|>


<commit_before>module.exports = function(HAPnode, config, functions)
{
    var Accessory       = HAPnode.Accessory;
    var Service         = HAPnode.Service;
    var Characteristic  = HAPnode.Characteristic;
    var uuid            = HAPnode.uuid;
    var debug           = HAPnode.debug;

    var module  = {};

    module.newDevice = function(device)
    {
        var VeraController = require("./../vera.js")(HAPnode, config, device);
        var Fan = {
            powerOn: (parseInt(device.status) === 1)?true:false,
            rotationSpeed: 100,
            onproc: false,
            changespeed: false,

            setPowerOn: function(on)
            {
                if (on === Fan.powerOn)
                   return;

                Fan.powerOn = on;
                if (on)
                {
                    binaryState     = 1;
                    return this.setRotationSpeed(this.rotationSpeed);
                }
                else
                {
                    binaryState     = 0;
                    Fan.powerOn  = false;
                }

                return HAPnode.request({method:'GET',uri:"http://"+config.veraIP+":3480/data_request?id=lu_action&output_format=xml&DeviceNum=" + device.id + "&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=" + binaryState, resolveWithFullResponse: true}).then(function (res)
                {
                    if (res.statusCode === 200)
                    {
                        status = (Fan.powerOn === 1)?'On':'Off';
                        debug("The %s has been turned %s", device.name, status);
                    }
                    else
                    {
                        debug("Error while turning the %s on/off %s", device.name);
                    }
                }).catch(function (err) {
                    HAPnode.debug("Request error:"+err);
                });
            },
            setRotationSpeed: function(rotationSpeed)
            {
                // Apple sends 31.4043253660202 for Low, 66.52949452400208 for Mid, and 100 for High
                // On Leviton RZF01 66 is the upper threshold of the Mid level, so 67 results in High speed
                // For safety we'll translate these to 25 for Low, 50 for Mid, and leave 100 for High
                rotationSpeed = Math.floor(rotationSpeed);
                if (rotationSpeed < 50) {
                    rotationSpeed = 25;
                } else if (rotationSpeed < 100){
                    rotationSpeed = 50;
                }
                if(this.onproc === false)
                {
                    this.onproc = true;
                    this.rotationSpeed = rotationSpeed;
                    var self = this;

                    HAPnode.request({method:'GET',uri:"http://"+config.veraIP+":3480/data_request?id=lu_action&output_format=xml&DeviceNum=" + device.id + "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget=" + this.rotationSpeed, resolveWithFullResponse: true}).then(function (res)
                    {
                        if (res.statusCode === 200)
                        {
                            debug("The %s rotation speed has been changed to %d%", device.name, rotationSpeed);
                        }
                        else
                        {
                            debug("Error while changing %s rotation speed", device.name);
                        }
                        self.onproc = false;
                        if(self.changespeed)
                        {
                             self.rotationSpeed = self.changespeed;
                             self.changespeed = false;
                             return self.setRotationSpeed(self.rotationSpeed);
                        }
                    }).catch(function (err) {
                        HAPnode.debug("Request error:"+err);
                    });

                }
                else
                {
                    this.changespeed = rotationSpeed;
                    return;
                }
            },
            getStatus: function()
            {
              debug("Making status request for device %s", device.name);
              var status = parseInt(functions.getVariable(device.id, 'status'));
              debug("Status is ", status);
              return status;
            },
            getRotationSpeed: function()
            {
                var speed = parseInt(functions.getVariable(device.id, 'level'));
                return speed;

            },
            identify: function()
            {
                debug("Identify the fan %s", device.name);
            }
        };

        var fanUUID = uuid.generate('device:fan:'+config.cardinality+':'+device.id);

        var fan = new Accessory(device.name, fanUUID);

        fan.username  = functions.genMac('device:'+config.cardinality+':'+device.id);
        fan.pincode   = config.pincode;
        fan.deviceid  = device.id;

        fan
            .getService(Service.AccessoryInformation)
            .setCharacteristic(Characteristic.Manufacturer, "Leviton")
            .setCharacteristic(Characteristic.Model, "RZF01")
            .setCharacteristic(Characteristic.SerialNumber, "A1S2NASF88EW");

        fan.on('identify', function(paired, callback) {
            Fan.identify();
            callback(); // success
        });

        fan
            .addService(Service.Fan, device.name)
            .getCharacteristic(Characteristic.On)
            .on('set', function(value, callback) {
                Fan.setPowerOn(value);
                callback();
            });

        fan
            .getService(Service.Fan)
            .getCharacteristic(Characteristic.On)
            .on('get', function(callback) {
                var err = null;

                callback(err, Fan.getStatus());
                });

        fan
            .getService(Service.Fan)
            .addCharacteristic(Characteristic.RotationSpeed)
            .on('get', function(callback) {
                var err = null;
                callback(err, Fan.getRotationSpeed());
            })
            .on('set', function(value, callback) {
                Fan.setRotationSpeed(value);
                callback();
            });

        return fan;

    };

    return module;
};
<commit_msg>setting fan power off when speed is zero<commit_after>module.exports = function(HAPnode, config, functions)
{
    var Accessory       = HAPnode.Accessory;
    var Service         = HAPnode.Service;
    var Characteristic  = HAPnode.Characteristic;
    var uuid            = HAPnode.uuid;
    var debug           = HAPnode.debug;

    var module  = {};

    module.newDevice = function(device)
    {
        var VeraController = require("./../vera.js")(HAPnode, config, device);
        var Fan = {
            powerOn: (parseInt(device.status) === 1)?true:false,
            rotationSpeed: 100,
            onproc: false,
            changespeed: false,

            setPowerOn: function(on)
            {
                if (on === Fan.powerOn)
                   return;

                Fan.powerOn = on;
                if (on)
                {
                    binaryState     = 1;
                    return this.setRotationSpeed(this.rotationSpeed);
                }
                else
                {
                    binaryState     = 0;
                    Fan.powerOn  = false;
                }

                return HAPnode.request({method:'GET',uri:"http://"+config.veraIP+":3480/data_request?id=lu_action&output_format=xml&DeviceNum=" + device.id + "&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=" + binaryState, resolveWithFullResponse: true}).then(function (res)
                {
                    if (res.statusCode === 200)
                    {
                        status = (Fan.powerOn === 1)?'On':'Off';
                        debug("The %s has been turned %s", device.name, status);
                    }
                    else
                    {
                        debug("Error while turning the %s on/off %s", device.name);
                    }
                }).catch(function (err) {
                    HAPnode.debug("Request error:"+err);
                });
            },
            setRotationSpeed: function(rotationSpeed)
            {
                // Apple sends 31.4043253660202 for Low, 66.52949452400208 for Mid, and 100 for High
                // On Leviton RZF01 66 is the upper threshold of the Mid level, so 67 results in High speed
                // For safety we'll translate these to 25 for Low, 50 for Mid, and leave 100 for High
                rotationSpeed = Math.floor(rotationSpeed);
                if (rotationSpeed < 50) {
                    rotationSpeed = 25;
                } else if (rotationSpeed < 100){
                    rotationSpeed = 50;
                }
                if(this.onproc === false)
                {
                    this.onproc = true;
                    this.rotationSpeed = rotationSpeed;
                    var self = this;

                    HAPnode.request({method:'GET',uri:"http://"+config.veraIP+":3480/data_request?id=lu_action&output_format=xml&DeviceNum=" + device.id + "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget=" + this.rotationSpeed, resolveWithFullResponse: true}).then(function (res)
                    {
                        if (res.statusCode === 200)
                        {
                            debug("The %s rotation speed has been changed to %d%", device.name, rotationSpeed);
                        }
                        else
                        {
                            debug("Error while changing %s rotation speed", device.name);
                        }
                        self.onproc = false;
                        if(self.changespeed)
                        {
                             self.rotationSpeed = self.changespeed;
                             self.changespeed = false;
                             return self.setRotationSpeed(self.rotationSpeed);
                        }
                    }).catch(function (err) {
                        HAPnode.debug("Request error:"+err);
                    });

                }
                else
                {
                    this.changespeed = rotationSpeed;
                    return;
                }
            },
            getStatus: function()
            {
              debug("Making status request for device %s", device.name);
              var status = parseInt(functions.getVariable(device.id, 'status'));
              debug("Status is ", status);
              return status;
            },
            getRotationSpeed: function()
            {
                var speed = parseInt(functions.getVariable(device.id, 'level'));
                return speed;

            },
            identify: function()
            {
                debug("Identify the fan %s", device.name);
            }
        };

        var fanUUID = uuid.generate('device:fan:'+config.cardinality+':'+device.id);

        var fan = new Accessory(device.name, fanUUID);

        fan.username  = functions.genMac('device:'+config.cardinality+':'+device.id);
        fan.pincode   = config.pincode;
        fan.deviceid  = device.id;

        fan
            .getService(Service.AccessoryInformation)
            .setCharacteristic(Characteristic.Manufacturer, "Leviton")
            .setCharacteristic(Characteristic.Model, "RZF01")
            .setCharacteristic(Characteristic.SerialNumber, "A1S2NASF88EW");

        fan.on('identify', function(paired, callback) {
            Fan.identify();
            callback(); // success
        });

        fan
            .addService(Service.Fan, device.name)
            .getCharacteristic(Characteristic.On)
            .on('set', function(value, callback) {
                Fan.setPowerOn(value);
                callback();
            });

        fan
            .getService(Service.Fan)
            .getCharacteristic(Characteristic.On)
            .on('get', function(callback) {
                var err = null;

                callback(err, Fan.getStatus());
                });

        fan
            .getService(Service.Fan)
            .addCharacteristic(Characteristic.RotationSpeed)
            .on('get', function(callback) {
                var err = null;
                callback(err, Fan.getRotationSpeed());
            })
            .on('set', function(value, callback) {
                if(!value){
                  Fan.setPowerOn(false);
                }else{
                  Fan.setRotationSpeed(value);
                }
                callback();
            });

        return fan;

    };

    return module;
};
<|endoftext|>


<commit_before>var ShexParser = require('../shex').Parser;

var fs = require('fs'),
    expect = require('chai').expect;

var schemasPath = __dirname + '/../schemas/';
var parsedSchemasPath = __dirname + '/../test/parsedSchemas/';
var negSyntaxTestsPath = __dirname + '/../negativeSyntax/';

describe('A SHEX parser', function () {
  // var b = function () {  };
  // it('is a toy', function () {
  //   expect({a:1, b: b}).to.deep.equal({a:1, b: b});
  // });

  var parser = new ShexParser();

  // Ensure the same blank node identifiers are used in every test
  beforeEach(function () { parser._resetBlanks(); });

  var schemas = fs.readdirSync(schemasPath);
  schemas = schemas.map(function (q) { return q.replace(/\.shex$/, ''); });
  schemas.sort();

  schemas.forEach(function (schema) {

    var parsedSchemaFile = parsedSchemasPath + schema + '.json';
    if (!fs.existsSync(parsedSchemaFile)) return;

    it('should correctly parse schema "' + schema + '"', function () {
      var parsedSchema = parseJSON(fs.readFileSync(parsedSchemaFile, 'utf8'));

      console.log(schema);
      schema = fs.readFileSync(schemasPath + schema + '.shex', 'utf8');
      console.log("parsed   :"+  JSON.stringify(parser.parse(schema)));
      console.log("expected :"+JSON.stringify(parsedSchema));
      expect(parser.parse(schema)).to.deep.equal(parsedSchema);
    });
  });

  // make sure errors are reported
  it('should throw an error on an invalid schema', function () {
    var schema = 'invalid', error = null;
    try { parser.parse(schema); }
    catch (e) { error = e; }

    expect(error).to.exist;
    expect(error).to.be.an.instanceof(Error);
    expect(error.message).to.include('Parse error on line 1');
  });

  // negative syntax tests
  var negSyntaxTests = fs.readdirSync(negSyntaxTestsPath);
  negSyntaxTests = negSyntaxTests.map(function (q) { return q.replace(/\.err$/, ''); });
  negSyntaxTests.sort();

  negSyntaxTests.forEach(function (schema) {

    it('should correctly parse schema "' + schema + '"', function () {
      console.log(schema);
      schema = fs.readFileSync(negSyntaxTestsPath + schema + '.err', 'utf8');
      try { parser.parse(schema); }
      catch (e) { error = e; }

      expect(error).to.exist;
      expect(error).to.be.an.instanceof(Error);
      expect(error.message).to.include('Parse error');
    });
  });

  describe('with pre-defined prefixes', function () {
    var prefixes = { a: 'abc#', b: 'def#' };
    var parser = new ShexParser(prefixes);

    it('should use those prefixes', function () {
      var schema = 'a:a { b:b .+ }';
      expect(parser.parse(schema).shapes['abc#a'].predicate)
        .to.deep.equal('def#b');
    });

    it('should allow temporarily overriding prefixes', function () {
      var schema = 'PREFIX a: <xyz#> a:a { b:b .+ }';
      expect(parser.parse(schema).shapes['xyz#a'].predicate)
        .to.deep.equal('def#b');
      expect(parser.parse('a:a { b:b .+ }').shapes['abc#a'].predicate)
        .to.deep.equal('def#b');
    });

    it('should not change the original prefixes', function () {
      expect(prefixes).to.deep.equal({ a: 'abc#', b: 'def#' });
    });

    it('should not take over changes to the original prefixes', function () {
      prefixes.a = 'xyz#';
      expect(parser.parse('a:a { b:b .+ }').shapes['abc#a'].predicate)
        .to.deep.equal('def#b');
    });
  });

  describe('PNAME_NS with pre-defined prefixes', function () {
    var prefixes = { a: 'abc#', b: 'def#' };
    var parser = new ShexParser(prefixes);

    it('should use those prefixes', function () {
      var schema = 'a: { b: .+ }';
      expect(parser.parse(schema).shapes['abc#'].predicate)
        .to.deep.equal('def#');
    });

    it('should allow temporarily overriding prefixes', function () {
      var schema = 'PREFIX a: <xyz#> a: { b: .+ }';
      expect(parser.parse(schema).shapes['xyz#'].predicate)
        .to.deep.equal('def#');
      expect(parser.parse('a: { b: .+ }').shapes['abc#'].predicate)
        .to.deep.equal('def#');
    });

  });
});

// Parses a JSON object, restoring `undefined` values
function parseJSON(string) {
  var object = JSON.parse(string);
  return /"\{undefined\}"/.test(string) ? restoreUndefined(object) : object;
}

// Recursively replace values of "{undefined}" by `undefined`
function restoreUndefined(object) {
  for (var key in object) {
    var item = object[key];
    if (typeof item === 'object')
      object[key] = restoreUndefined(item);
    else if (item === '{undefined}')
      object[key] = undefined;
  }
  return object;
}
<commit_msg>~ renamed some vars in ShexParser-test.js<commit_after>var ShexParser = require('../shex').Parser;

var fs = require('fs'),
    expect = require('chai').expect;

var schemasPath = __dirname + '/../schemas/';
var jsonSchemasPath = __dirname + '/../test/parsedSchemas/';
var negSyntaxTestsPath = __dirname + '/../negativeSyntax/';

describe('A SHEX parser', function () {
  // var b = function () {  };
  // it('is a toy', function () {
  //   expect({a:1, b: b}).to.deep.equal({a:1, b: b});
  // });

  var parser = new ShexParser();

  // Ensure the same blank node identifiers are used in every test
  beforeEach(function () { parser._resetBlanks(); });

  var schemas = fs.readdirSync(schemasPath);
  schemas = schemas.map(function (q) { return q.replace(/\.shex$/, ''); });
  schemas.sort();

  schemas.forEach(function (schema) {

    var jsonSchemaFile = jsonSchemasPath + schema + '.json';
    if (!fs.existsSync(jsonSchemaFile)) return;

    it('should correctly parse schema "' + schema + '"', function () {
      var jsonSchema = parseJSON(fs.readFileSync(jsonSchemaFile, 'utf8'));

      console.log(schema);
      schema = fs.readFileSync(schemasPath + schema + '.shex', 'utf8');
      var parsedSchema = parser.parse(schema);
      console.log("parsed   :" + JSON.stringify(parsedSchema));
      console.log("expected :" + JSON.stringify(jsonSchema));
      expect(parsedSchema).to.deep.equal(jsonSchema);
    });
  });

  // make sure errors are reported
  it('should throw an error on an invalid schema', function () {
    var schema = 'invalid', error = null;
    try { parser.parse(schema); }
    catch (e) { error = e; }

    expect(error).to.exist;
    expect(error).to.be.an.instanceof(Error);
    expect(error.message).to.include('Parse error on line 1');
  });

  // negative syntax tests
  var negSyntaxTests = fs.readdirSync(negSyntaxTestsPath);
  negSyntaxTests = negSyntaxTests.map(function (q) { return q.replace(/\.err$/, ''); });
  negSyntaxTests.sort();

  negSyntaxTests.forEach(function (schema) {

    it('should correctly parse schema "' + schema + '"', function () {
      console.log(schema);
      schema = fs.readFileSync(negSyntaxTestsPath + schema + '.err', 'utf8');
      try { parser.parse(schema); }
      catch (e) { error = e; }

      expect(error).to.exist;
      expect(error).to.be.an.instanceof(Error);
      expect(error.message).to.include('Parse error');
    });
  });

  describe('with pre-defined prefixes', function () {
    var prefixes = { a: 'abc#', b: 'def#' };
    var parser = new ShexParser(prefixes);

    it('should use those prefixes', function () {
      var schema = 'a:a { b:b .+ }';
      expect(parser.parse(schema).shapes['abc#a'].predicate)
        .to.deep.equal('def#b');
    });

    it('should allow temporarily overriding prefixes', function () {
      var schema = 'PREFIX a: <xyz#> a:a { b:b .+ }';
      expect(parser.parse(schema).shapes['xyz#a'].predicate)
        .to.deep.equal('def#b');
      expect(parser.parse('a:a { b:b .+ }').shapes['abc#a'].predicate)
        .to.deep.equal('def#b');
    });

    it('should not change the original prefixes', function () {
      expect(prefixes).to.deep.equal({ a: 'abc#', b: 'def#' });
    });

    it('should not take over changes to the original prefixes', function () {
      prefixes.a = 'xyz#';
      expect(parser.parse('a:a { b:b .+ }').shapes['abc#a'].predicate)
        .to.deep.equal('def#b');
    });
  });

  describe('PNAME_NS with pre-defined prefixes', function () {
    var prefixes = { a: 'abc#', b: 'def#' };
    var parser = new ShexParser(prefixes);

    it('should use those prefixes', function () {
      var schema = 'a: { b: .+ }';
      expect(parser.parse(schema).shapes['abc#'].predicate)
        .to.deep.equal('def#');
    });

    it('should allow temporarily overriding prefixes', function () {
      var schema = 'PREFIX a: <xyz#> a: { b: .+ }';
      expect(parser.parse(schema).shapes['xyz#'].predicate)
        .to.deep.equal('def#');
      expect(parser.parse('a: { b: .+ }').shapes['abc#'].predicate)
        .to.deep.equal('def#');
    });

  });
});

// Parses a JSON object, restoring `undefined` values
function parseJSON(string) {
  var object = JSON.parse(string);
  return /"\{undefined\}"/.test(string) ? restoreUndefined(object) : object;
}

// Recursively replace values of "{undefined}" by `undefined`
function restoreUndefined(object) {
  for (var key in object) {
    var item = object[key];
    if (typeof item === 'object')
      object[key] = restoreUndefined(item);
    else if (item === '{undefined}')
      object[key] = undefined;
  }
  return object;
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

var pkg,
    deps,
    all = 0,
    rt = require('../require-time');

try {
    pkg = require(process.cwd() + '/package.json');
} catch(e) {
    console.error(e.message);
    process.exit(1);
}

rt.run(pkg, process.argv[2]);
<commit_msg>Insulate against modules whose main is meant to be a CLI tool and exits with usage during startup<commit_after>#!/usr/bin/env node

'use strict';

var pkg,
    deps,
    all = 0,
    rt = require('../require-time');

var exit = process.exit;
process.exit = function noop () { };
try {
    pkg = require(process.cwd() + '/package.json');
} catch(e) {
    console.error(e.message);
    exit(1);
}

rt.run(pkg, process.argv[2]);
exit(0);
<|endoftext|>


<commit_before>var usb = require('usb'),
    _ = require('lodash');

exports.getDevices = function() {
    return usb.getDeviceList();
};

exports.setDebugLevel = function(level) {
    return usb.setDebugLevel(level);
}

exports.findDevice = function(vid, pid) {
    return new Promise(function(fulfill, reject) {
        if (!vid) {
            reject(new Error('Vendor ID must be a non-empty'));
        }

        if (!pid) {
            reject(new Error('Product ID  must be a non-empty'));
        }

        var device = usb.findByIds(vid, pid);
        var callback_data = [];

        if (device) {
            usb.on('detach', function(detached) {
                var descriptor = detached.deviceDescriptor;
                if (descriptor.idVendor == vid && descriptor.idProduct == pid) {
                    callback_data[0].dispatchEvent("detached", {
                        device: detached
                    });
                }
            });

            var usbDevice = WebUSBDevice(device);
            callback_data.push(usbDevice);
            fulfill(usbDevice);
        } else {
            reject(new Error('USB device not found'));
        }
    });
};

var WebUSBDevice = function(device) {
    if (!this._isWebUSBDevice) {
        return new WebUSBDevice(device);
    }
    this._device = device;
};

require('util').inherits(WebUSBDevice, require('events').EventEmitter);

_.extend(WebUSBDevice.prototype, {
    _isWebUSBDevice: true,
    _inEndpoint: null,
    _outEndpoint: null,
    _claimedInterface: null,

    _inDataEvent: function(data) {
        if (data && data.length > 0) {
            this.dispatchEvent('data', {
                type: 'In endpoint',
                data: data
            });
        }
    },

    _inErrorEvent: function(err) {
        this.dispatchEvent('error', {
            type: 'InEndpoint',
            error: err
        });
    },

    _outErrorEvent: function(err) {
        this.dispatchEvent('error', {
            type: 'OutEndpoint',
            error: err
        });
    },

    open: function() {
        return new Promise(_.bind(function(fulfill, reject) {
            if (this._device) {
                this._device.open();
                fulfill();
            } else {
                reject(new Error('Failed to open USB device!'));
            }
        }, this));
    },

    claimInterface: function(interfacce) {
        return new Promise(_.bind(function(fulfill, reject) {
            this._claimedInterface = this._device.interfaces[interfacce];
            if (this._claimedInterface) {
                this._inEndpoint = this._claimedInterface.endpoints[0];
                this._outEndpoint = this._claimedInterface.endpoints[1];

                this._inEndpoint.on('error', this._inErrorEvent.bind(this));
                this._inEndpoint.on('data', this._inDataEvent.bind(this));
                this._outEndpoint.on('error', this._outErrorEvent.bind(this));

                this._claimedInterface.claim();
                fulfill();
            } else {
                reject(new Error('Failed to claim the interface!'));
            }
        }, this));
    },

    listen: function() {
        return new Promise(_.bind(function(fulfill, reject) {
            if (this._inEndpoint) {
                this._inEndpoint.startPoll();
                fulfill();
            } else {
                reject(new Error('Claim the interface before start polling'));
            }
        }, this));
    },

    addEventListener: WebUSBDevice.prototype.addListener,

    removeEventListener: WebUSBDevice.prototype.removeListener,

    dispatchEvent: function(event, request) {
        this.emit(event, request);
        if (typeof this[ 'on' + event ] === 'function') {
            this[ 'on' + event ](request);
        }
    }
});

exports.WebUSBDevice = WebUSBDevice;
<commit_msg>usb: Add method to close the device<commit_after>var usb = require('usb'),
    _ = require('lodash');

exports.getDevices = function() {
    return usb.getDeviceList();
};

exports.setDebugLevel = function(level) {
    return usb.setDebugLevel(level);
}

exports.findDevice = function(vid, pid) {
    return new Promise(function(fulfill, reject) {
        if (!vid) {
            reject(new Error('Vendor ID must be a non-empty'));
        }

        if (!pid) {
            reject(new Error('Product ID  must be a non-empty'));
        }

        var device = usb.findByIds(vid, pid);
        var callback_data = [];

        if (device) {
            usb.on('detach', function(detached) {
                var descriptor = detached.deviceDescriptor;
                if (descriptor.idVendor == vid && descriptor.idProduct == pid) {
                    callback_data[0].dispatchEvent("detached", {
                        device: detached
                    });
                }
            });

            var usbDevice = WebUSBDevice(device);
            callback_data.push(usbDevice);
            fulfill(usbDevice);
        } else {
            reject(new Error('USB device not found'));
        }
    });
};

var WebUSBDevice = function(device) {
    if (!this._isWebUSBDevice) {
        return new WebUSBDevice(device);
    }
    this._device = device;
};

require('util').inherits(WebUSBDevice, require('events').EventEmitter);

_.extend(WebUSBDevice.prototype, {
    _isWebUSBDevice: true,
    _inEndpoint: null,
    _outEndpoint: null,
    _claimedInterface: null,

    _inDataEvent: function(data) {
        if (data && data.length > 0) {
            this.dispatchEvent('data', {
                type: 'In endpoint',
                data: data
            });
        }
    },

    _inErrorEvent: function(err) {
        this.dispatchEvent('error', {
            type: 'InEndpoint',
            error: err
        });
    },

    _outErrorEvent: function(err) {
        this.dispatchEvent('error', {
            type: 'OutEndpoint',
            error: err
        });
    },

    open: function() {
        return new Promise(_.bind(function(fulfill, reject) {
            if (this._device) {
                this._device.open();
                fulfill();
            } else {
                reject(new Error('Failed to open USB device!'));
            }
        }, this));
    },

    claimInterface: function(interfacce) {
        return new Promise(_.bind(function(fulfill, reject) {
            this._claimedInterface = this._device.interfaces[interfacce];
            if (this._claimedInterface) {
                this._inEndpoint = this._claimedInterface.endpoints[0];
                this._outEndpoint = this._claimedInterface.endpoints[1];

                this._inEndpoint.on('error', this._inErrorEvent.bind(this));
                this._inEndpoint.on('data', this._inDataEvent.bind(this));
                this._outEndpoint.on('error', this._outErrorEvent.bind(this));

                this._claimedInterface.claim();
                fulfill();
            } else {
                reject(new Error('Failed to claim the interface!'));
            }
        }, this));
    },

    listen: function() {
        return new Promise(_.bind(function(fulfill, reject) {
            if (this._inEndpoint) {
                this._inEndpoint.startPoll();
                fulfill();
            } else {
                reject(new Error('Claim the interface before start polling'));
            }
        }, this));
    },

    close: function() {
        return new Promise(_.bind(function(fulfill, reject) {
            if (this._claimedInterface) {
                this._inEndpoint.stopPoll(function() {
                    this._claimedInterface.release(true, function(err) {
                        if (err) {
                            reject(new Error('Failed to release the interface'));
                        } else {
                            this._device.close();
                            fulfill();
                        }
                    }.bind(this));
                }.bind(this));
            } else {
                this._device.close();
                fulfill();
            }
        }, this));
    },

    addEventListener: WebUSBDevice.prototype.addListener,

    removeEventListener: WebUSBDevice.prototype.removeListener,

    dispatchEvent: function(event, request) {
        this.emit(event, request);
        if (typeof this[ 'on' + event ] === 'function') {
            this[ 'on' + event ](request);
        }
    }
});

exports.WebUSBDevice = WebUSBDevice;
<|endoftext|>


<commit_before>var Path = require('path');
var env = require('env2')('config.env');

var Firebase = require('firebase');
var userRef = new Firebase("https://blistering-torch-1660.firebaseio.com/users/");

var FirebaseTokenGenerator = require("firebase-token-generator");
var tokenGenerator = new FirebaseTokenGenerator(process.env.FIREBASE_SECRET);

exports.register = function(server,options,next) {

  server.route({
    method: 'POST',
    path: '/login',
    handler: function (request, reply) {
      console.log(request.payload);
      userRef.once("value", function(snapshot){
        var users = snapshot.val();

        for(var uid in users) {
          var userData = users[uid];
          console.log(userData);
          //if user exists return
          if(request.payload.tel == userData.tel ){
            if (request.payload.password == userData.password) {
              var token = tokenGenerator.createToken(
                {uid: uid, tel: userData.tel}
              );
              //http://hapijs.com/tutorials/cookies`
              return reply.redirect("/user/restList.html").state('firebase_token', token, {encoding: 'none'} );
            }
            else {
              console.log("incorrect pw");
              return reply.redirect("/user/userLogin.html?error=password");
              }
          }
        }
        //if reached this point, means we didn't find the user
        console.log("incorrect user");
        return reply.redirect("/user/userLogin.html?error=password");

      });
    }
  });

  server.route({
    method: 'GET',
    path: '/logout',
    handler: function (request, reply) {
        return reply.redirect("/user/userLogin.html").state('firebase_token', null, {encoding: 'none'});
    }
  });

  return next();
};

exports.register.attributes = {
  name: 'userLogin'
};
<commit_msg>#85 hashed pw is checked on userLogin<commit_after>var Path = require('path');
var env = require('env2')('config.env');
var Firebase = require('firebase');
var userRef = new Firebase("https://blistering-torch-1660.firebaseio.com/users/");
var FirebaseTokenGenerator = require("firebase-token-generator");
var tokenGenerator = new FirebaseTokenGenerator(process.env.FIREBASE_SECRET);
var bcrypt = require('bcrypt');

exports.register = function(server,options,next) {

  server.route({
    method: 'POST',
    path: '/login',
    handler: function (request, reply) {
      userRef.once("value", function(snapshot){
        var users = snapshot.val();
        var pw_correct = false;
        for(var uid in users) {
          var userData = users[uid];
          //if user exists return
          if(request.payload.tel == userData.tel ){
            bcrypt.compare(request.payload.password, userData.password, function(err, res){
              pw_correct = res;
              if (pw_correct) {
                var token = tokenGenerator.createToken(
                  {uid: uid, tel: userData.tel}
                );
                //http://hapijs.com/tutorials/cookies`
                return reply.redirect("/user/restList").state('firebase_token', token, {encoding: 'none'} );
            }
            else {
              console.log("incorrect login");
              return reply.redirect("/user/userLogin.html?error=password");
              }
            });
          }
        }
      });
    }
  });

  server.route({
    method: 'GET',
    path: '/logout',
    handler: function (request, reply) {
        return reply.redirect("/user/userLogin.html").state('firebase_token', null, {encoding: 'none'});
    }
  });

  return next();
};

exports.register.attributes = {
  name: 'userLogin'
};
<|endoftext|>


<commit_before>var term = require( 'terminal-kit' ).terminal ;
var child_process = require('child_process');

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function term_grab() {
    term.grabInput( { mouse: 'motion' } ) ;
    term.hideCursor(true);
}

function term_release() {
    term.hideCursor( false );
    term.grabInput( false ) ;
}

function terminate() {
    term_release();
    // Add a 100ms delay, so the terminal will be ready when the process effectively exit, preventing bad escape sequences drop
    setTimeout( function() { process.exit() ; } , 100 ) ;
}

async function choice(items, pre_select=0, pad_last=0) {

    term_grab();

    var button_padding = 4;
    var top_left = "┌";
    var top_bar = "─";
    var top_right = "┐";
    var bar_left = "│";
    var bar_right = "│";
    var bottom_left = "└";
    var bottom_bar = "─";
    var bottom_right = "┘";

    // get longest word
    var longest = 0;
    for(var i=0; i<items.length; i++) {
        if(items[i][0].length > longest) longest = items[i][0].length;
    }
    longest += 6; // Add button inside padding

    // create formatted_items
    var menu_height = 0;
    var formatted_items = [];
    for(var i=0; i<items.length; i++) {
        var padlength = longest - items[i][0].length;
        var fstr =
                " ".repeat(button_padding) + top_left + top_bar.repeat(longest)
                    + top_right + "\n" +
                " ".repeat(button_padding) + bar_left + " ".repeat(Math.floor(padlength/2)) + items[i][0]
                    + " ".repeat(Math.floor((padlength+1)/2)) + bar_right + "\n" +
                " ".repeat(button_padding) + bottom_left + bottom_bar.repeat(longest)
                    + bottom_right + " ".repeat(button_padding);
        formatted_items.push(fstr);
        menu_height += 3;
    }
    for( var i=0; i<pad_last; i++) {
        // add line before last
        formatted_items[items.length-1] = "\n" + formatted_items[items.length-1];
        menu_height ++;
    }

    // if negative count back from the last
    if(pre_select<0) pre_select = formatted_items.length + pre_select;

    const extra_lines = 2
    menu_height += extra_lines;

    // make space for menu (term.nextLine seems to be buggy or not scroll correctly)
    for(var i=0; i<menu_height; i++)
        term("\n");
    // go up again
    term.previousLine(menu_height);

    function clean_up() {
        term_release();
        term.up(menu_height-extra_lines); // why is extra_lines needed here?
        term.eraseDisplayBelow();
    }

    term.singleColumnMenu( formatted_items,
        {
            leftPadding: "",
            selectedLeftPadding: "",
            cancelable: true,
            selectedIndex: pre_select,
            itemMaxWidth: 2*(button_padding+1)+longest,
            extraLines: extra_lines,
            style: term.bgBrightWhite.black,
            selectedStyle: term.bgGreen.black,
            submittedStyle: term.bgWhite.black,
            exitOnUnexpectedKey: true, // catch other keys
            continueOnSubmit: false
        } ,
        function( error , response ) {
            // term( '\n' ).eraseLineAfter.green(
            //     "#%s" ,
            //     response.selectedIndex
            // );
            clean_up();
            if(response.unexpectedKey != undefined) {
                function check_key(name, key, cb) {
                    if(name.toUpperCase() === key.toUpperCase()) {
                        cb();
                        return true;
                    }
                    return false;
                }

                var name = response.unexpectedKey;
                for(var i=0; i<items.length; i++) {
                    if(items[i][1] instanceof Array) {
                        for(var k of items[i][1]) {
                            if(check_key(name, k, items[i][2])) return; // match found
                        }
                    } else {
                        if(check_key(name, items[i][1], items[i][2])) return; // match found
                    }
                } // end for
                // not returned, so wo need to end as not matched
                terminate();
            } else {
                if(response.selectedIndex == undefined) terminate();
                else {
                    var cb = items[response.selectedIndex][2];
                    if(cb == undefined) { terminate(); }
                    else { cb(); }
                }
            }
        }
    ) ;
    // Attention: this is Javascript, so execution directly continues here,
    // so everything needs to be done in callbacks and via recursion if
    // deterministic behavior is expected
    // Careful: while menu is running, cursor changes all the time, so
    // nothing can decently be printed (maybe modal)
}

function run_command(command, directory = null) {
    var args = ['-q', '-e', '-c', command, '/dev/null' ];
//    if(directory)
//        cmd = 'cd "' + directory + '"; ' + cmd;
    term.wrap("\nRunning ", command, "\n\n");
    var result = child_process.spawnSync("script", args,
                    { stdio: [0,0,0], cwd: directory });
    if( result.status == 0) {
        term.green.wrap('\nThe command ',command,' seems to have completed successful. OK to continue.\n');
        choice([
            ["OK, continue (O, Enter)", "O", terminate]
        ], pre_select=-1);
    } else {
        term.red.wrap('\nAn error occurred running ',command,'. Check output, continue, and eventually try again later.\n');
        choice([
            ["Continue (C, Enter)", "C", terminate]
        ], pre_select=-1);
    }
}

function shell_command(question, command, directory = null) {
    if(question) {
        term.wrap("\n", question, "\n");

        choice([
            ["Yes, run " + command + " (Y)", "Y", function() { run_command(command, directory); } ],
            ["No, go back (N)", "N", terminate]
        ], pre_select=-1);
    } else {
        term("\n\n");
        run_command(command, directory);
    }
}

function shell_command_in_path(before_path, after_path, command) {
    term.wrap('\n\n', before_path, '\n');
    var d = process.env.ACTIVE_DIR;
    var fulldir = d;
    if(!d) {
        d = process.cwd();
        fulldir = d;
    }
    // Strip home directory
    var home = process.env.HOME;
    if(d.startsWith(home)) d = d.slice(home.length+1);
    term.wrap(d,'\n');

    shell_command(after_path, command, fulldir);
}

function deploy() {
    shell_command_in_path('You are about to deploy from the following path:',
        'Are you sure?', "deploy");
}

function compile() {
    shell_command_in_path('You are about to run compile in the following path:',
        'Are you sure?', "compile");
}

function initialize() {
    shell_command_in_path('You are about to initialize from the following path:',
        'Are you sure and have you successfully put one node in adoption mode?',
        "initialize");
}

function create_node_template() {
    shell_command_in_path('You are about to create a folder called node_template in the following path:',
        'Are you sure?',
        "create_node_template");
}

function upgrade() {
    shell_command("This will get the newest version of ulnoiot out of the internet."
        + " Are you sure you want to run this?", "upgrade");
}

function initialize_serial() {
    shell_command_in_path('You are about to initialize'
        + ' a device that is locally connected to the gateway via usb or serial'
        + ' from the following path:',
        'Are you sure, and have you connected only one node to the gateway?',
        "initialize serial");
}

function pre_flash_wemos() {
    shell_command('You are about to flash a connected Wemos D1 mini with'
        + ' a default ulnoiot firmware. Are you sure, and have you connected '
        + 'exactly one Wemos D1 mini via USB to the gateway?',
        "pre_flash_wemos");
}

function shell_escape() {
    shell_command_in_path("Starting the shell (bash) now. "
        + "Remember to type exit to leave. Initial path will be:",
        null, "bash");
}

function advanced() {
    choice([
        ["Pre-Flash Wemos D1 mini (P)", "P", pre_flash_wemos],
        ["Initialize Serial (I)", "I", initialize_serial],
        ["Compile (C)", "C", compile],
        ["Upgrade (U)", "U", upgrade],
        ["Shell Escape (S)", "S", shell_escape],
        ["Back (B,X,ESC)", ["B","X"], terminate]
    ], pre_select=-1, pad_last=1);
}

function menu_default() {
    //term.clear();
    term("\n\n");
    term.bgBrightWhite.black.wrap( '^+ul^rno^-^kiot^: Simple Shell\n' ) ;
    term("\n");
    term.wrap('Use mouse, arrow keys, enter, or shortcut key to select.\n')
    term("\n");

    choice([
        ["Deploy (D)", "D", deploy],
        ["Initialize (I)", "I", initialize],
        ["Create Node Template (N)", "N", create_node_template],
        ["Advanced (A)", "A", advanced],
    //    "Exit (X,ESC)"
    ], pre_select=0, pad_last=0);
}

menu_default();<commit_msg>add power off<commit_after>var term = require( 'terminal-kit' ).terminal ;
var child_process = require('child_process');

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function term_grab() {
    term.grabInput( { mouse: 'motion' } ) ;
    term.hideCursor(true);
}

function term_release() {
    term.hideCursor( false );
    term.grabInput( false ) ;
}

function terminate() {
    term_release();
    // Add a 100ms delay, so the terminal will be ready when the process effectively exit, preventing bad escape sequences drop
    setTimeout( function() { process.exit() ; } , 100 ) ;
}

async function choice(items, pre_select=0, pad_last=0) {

    term_grab();

    var button_padding = 4;
    var top_left = "┌";
    var top_bar = "─";
    var top_right = "┐";
    var bar_left = "│";
    var bar_right = "│";
    var bottom_left = "└";
    var bottom_bar = "─";
    var bottom_right = "┘";

    // get longest word
    var longest = 0;
    for(var i=0; i<items.length; i++) {
        if(items[i][0].length > longest) longest = items[i][0].length;
    }
    longest += 6; // Add button inside padding

    // create formatted_items
    var menu_height = 0;
    var formatted_items = [];
    for(var i=0; i<items.length; i++) {
        var padlength = longest - items[i][0].length;
        var fstr =
                " ".repeat(button_padding) + top_left + top_bar.repeat(longest)
                    + top_right + "\n" +
                " ".repeat(button_padding) + bar_left + " ".repeat(Math.floor(padlength/2)) + items[i][0]
                    + " ".repeat(Math.floor((padlength+1)/2)) + bar_right + "\n" +
                " ".repeat(button_padding) + bottom_left + bottom_bar.repeat(longest)
                    + bottom_right + " ".repeat(button_padding);
        formatted_items.push(fstr);
        menu_height += 3;
    }
    for( var i=0; i<pad_last; i++) {
        // add line before last
        formatted_items[items.length-1] = "\n" + formatted_items[items.length-1];
        menu_height ++;
    }

    // if negative count back from the last
    if(pre_select<0) pre_select = formatted_items.length + pre_select;

    const extra_lines = 2
    menu_height += extra_lines;

    // make space for menu (term.nextLine seems to be buggy or not scroll correctly)
    for(var i=0; i<menu_height; i++)
        term("\n");
    // go up again
    term.previousLine(menu_height);

    function clean_up() {
        term_release();
        term.up(menu_height-extra_lines); // why is extra_lines needed here?
        term.eraseDisplayBelow();
    }

    term.singleColumnMenu( formatted_items,
        {
            leftPadding: "",
            selectedLeftPadding: "",
            cancelable: true,
            selectedIndex: pre_select,
            itemMaxWidth: 2*(button_padding+1)+longest,
            extraLines: extra_lines,
            style: term.bgBrightWhite.black,
            selectedStyle: term.bgGreen.black,
            submittedStyle: term.bgWhite.black,
            exitOnUnexpectedKey: true, // catch other keys
            continueOnSubmit: false
        } ,
        function( error , response ) {
            // term( '\n' ).eraseLineAfter.green(
            //     "#%s" ,
            //     response.selectedIndex
            // );
            clean_up();
            if(response.unexpectedKey != undefined) {
                function check_key(name, key, cb) {
                    if(name.toUpperCase() === key.toUpperCase()) {
                        cb();
                        return true;
                    }
                    return false;
                }

                var name = response.unexpectedKey;
                for(var i=0; i<items.length; i++) {
                    if(items[i][1] instanceof Array) {
                        for(var k of items[i][1]) {
                            if(check_key(name, k, items[i][2])) return; // match found
                        }
                    } else {
                        if(check_key(name, items[i][1], items[i][2])) return; // match found
                    }
                } // end for
                // not returned, so wo need to end as not matched
                terminate();
            } else {
                if(response.selectedIndex == undefined) terminate();
                else {
                    var cb = items[response.selectedIndex][2];
                    if(cb == undefined) { terminate(); }
                    else { cb(); }
                }
            }
        }
    ) ;
    // Attention: this is Javascript, so execution directly continues here,
    // so everything needs to be done in callbacks and via recursion if
    // deterministic behavior is expected
    // Careful: while menu is running, cursor changes all the time, so
    // nothing can decently be printed (maybe modal)
}

function run_command(command, directory = null) {
    var args = ['-q', '-e', '-c', command, '/dev/null' ];
//    if(directory)
//        cmd = 'cd "' + directory + '"; ' + cmd;
    term.wrap("\nRunning ", command, "\n\n");
    var result = child_process.spawnSync("script", args,
                    { stdio: [0,0,0], cwd: directory });
    if( result.status == 0) {
        term.green.wrap('\nThe command ',command,' seems to have completed successful. OK to continue.\n');
        choice([
            ["OK, continue (O, Enter)", "O", terminate]
        ], pre_select=-1);
    } else {
        term.red.wrap('\nAn error occurred running ',command,'. Check output, continue, and eventually try again later.\n');
        choice([
            ["Continue (C, Enter)", "C", terminate]
        ], pre_select=-1);
    }
}

function shell_command(question, command, directory = null) {
    if(question) {
        term.wrap("\n", question, "\n");

        choice([
            ["Yes, run " + command + " (Y)", "Y", function() { run_command(command, directory); } ],
            ["No, go back (N)", "N", terminate]
        ], pre_select=-1);
    } else {
        term("\n\n");
        run_command(command, directory);
    }
}

function shell_command_in_path(before_path, after_path, command) {
    term.wrap('\n\n', before_path, '\n');
    var d = process.env.ACTIVE_DIR;
    var fulldir = d;
    if(!d) {
        d = process.cwd();
        fulldir = d;
    }
    // Strip home directory
    var home = process.env.HOME;
    if(d.startsWith(home)) d = d.slice(home.length+1);
    term.wrap(d,'\n');

    shell_command(after_path, command, fulldir);
}

function deploy() {
    shell_command_in_path('You are about to deploy from the following path:',
        'Are you sure?', "deploy");
}

function compile() {
    shell_command_in_path('You are about to run compile in the following path:',
        'Are you sure?', "compile");
}

function initialize() {
    shell_command_in_path('You are about to initialize from the following path:',
        'Are you sure and have you successfully put one node in adoption mode?',
        "initialize");
}

function create_node_template() {
    shell_command_in_path('You are about to create a folder called node_template in the following path:',
        'Are you sure?',
        "create_node_template");
}

function upgrade() {
    shell_command("This will get the newest version of ulnoiot out of the internet."
        + " Are you sure you want to run this?", "upgrade");
}

function initialize_serial() {
    shell_command_in_path('You are about to initialize'
        + ' a device that is locally connected to the gateway via usb or serial'
        + ' from the following path:',
        'Are you sure, and have you connected only one node to the gateway?',
        "initialize serial");
}

function pre_flash_wemos() {
    shell_command('You are about to flash a connected Wemos D1 mini with'
        + ' a default ulnoiot firmware. Are you sure, and have you connected '
        + 'exactly one Wemos D1 mini via USB to the gateway?',
        "pre_flash_wemos");
}

function shell_escape() {
    shell_command_in_path("Starting the shell (bash) now. "
        + "Remember to type exit to leave. Initial path will be:",
        null, "bash");
}

function poweroff() {
    shell_command("This will cleanly shut down the gateway. "
        + "Are you sure you want to shutdown and poweroff the gateway?",
        "sudo poweroff");
}

function advanced() {
    choice([
        ["Pre-Flash Wemos D1 mini (P)", "P", pre_flash_wemos],
        ["Initialize Serial (I)", "I", initialize_serial],
        ["Compile (C)", "C", compile],
        ["Upgrade (U)", "U", upgrade],
        ["Shell Escape (S)", "S", shell_escape],
        ["Shutdown/Poweroff (O)", "O", poweroff],
        ["Back (B,X,ESC)", ["B","X"], terminate]
    ], pre_select=-1, pad_last=1);
}

function menu_default() {
    //term.clear();
    term("\n\n");
    term.bgBrightWhite.black.wrap( '^+ul^rno^-^kiot^: Simple Shell\n' ) ;
    term("\n");
    term.wrap('Use mouse, arrow keys, enter, or shortcut key to select.\n')
    term("\n");

    choice([
        ["Deploy (D)", "D", deploy],
        ["Initialize (I)", "I", initialize],
        ["Create Node Template (N)", "N", create_node_template],
        ["Advanced (A)", "A", advanced],
    //    "Exit (X,ESC)"
    ], pre_select=0, pad_last=0);
}

menu_default();<|endoftext|>


<commit_before>Ext.define('devilry.statistics.sidebarplugin.qualifiesforexam.RequirePointsOnSubset', {
    extend: 'devilry.statistics.sidebarplugin.qualifiesforexam.RequirePointsBase',
    requires: [
        'devilry.statistics.ChooseAssignmentsGrid'
    ],

    initComponent: function() {
        Ext.apply(this, {
            items: [{
                xtype: 'statistics-chooseassignmentsgrid',
                margin: {bottom: 10},
                selectedAssignmentIds: this.settings? this.settings.assignment_ids: undefined,
                store: this.loader.assignment_store
            }, {
                xtype: 'numberfield',
                fieldLabel: 'Minumum total points on selected',
                minValue: 0,
                value: this.settings? this.settings.minimumScaledPoints: '',
                margin: {bottom: 10}
            }, this.defaultButtonPanel]
        });
        this.callParent(arguments);
    },

    _getGrid: function() {
        return this.down('statistics-chooseassignmentsgrid');
    },

    filter: function(student) {
        var assignment_ids = this.down('statistics-chooseassignmentsgrid').getIdOfSelected();
        var minimumScaledPoints = this.down('numberfield').getValue();
        return student.hasMinimalNumberOfScaledPointsOn(assignment_ids, minimumScaledPoints);
    },

    validInput: function() {
        return this.validPointInput() && this.down('statistics-chooseassignmentsgrid').checkAtLeastOneSelected();
    },

    getSettings: function() {
        var settings = this.callParent(arguments);
        settings.assignment_ids = this._getGrid().getIdOfSelected();
        console.log(settings);
        return settings;
    }
});
<commit_msg>apps.statistics: Remove console.log.<commit_after>Ext.define('devilry.statistics.sidebarplugin.qualifiesforexam.RequirePointsOnSubset', {
    extend: 'devilry.statistics.sidebarplugin.qualifiesforexam.RequirePointsBase',
    requires: [
        'devilry.statistics.ChooseAssignmentsGrid'
    ],

    initComponent: function() {
        Ext.apply(this, {
            items: [{
                xtype: 'statistics-chooseassignmentsgrid',
                margin: {bottom: 10},
                selectedAssignmentIds: this.settings? this.settings.assignment_ids: undefined,
                store: this.loader.assignment_store
            }, {
                xtype: 'numberfield',
                fieldLabel: 'Minumum total points on selected',
                minValue: 0,
                value: this.settings? this.settings.minimumScaledPoints: '',
                margin: {bottom: 10}
            }, this.defaultButtonPanel]
        });
        this.callParent(arguments);
    },

    _getGrid: function() {
        return this.down('statistics-chooseassignmentsgrid');
    },

    filter: function(student) {
        var assignment_ids = this.down('statistics-chooseassignmentsgrid').getIdOfSelected();
        var minimumScaledPoints = this.down('numberfield').getValue();
        return student.hasMinimalNumberOfScaledPointsOn(assignment_ids, minimumScaledPoints);
    },

    validInput: function() {
        return this.validPointInput() && this.down('statistics-chooseassignmentsgrid').checkAtLeastOneSelected();
    },

    getSettings: function() {
        var settings = this.callParent(arguments);
        settings.assignment_ids = this._getGrid().getIdOfSelected();
        return settings;
    }
});
<|endoftext|>