<commit_before>var path = require('path');
var mongo = require('mongodb');
var express = require('express');
var morgan = require('morgan');
// var methodOverride = require('method-override');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var bodyParser = require('body-parser');
var multer = require('multer');
var favicon = require('serve-favicon');
var compression = require('compression')
var errorHandler = require('errorhandler');
var fs = require('fs');
var stylus = require('stylus');
var browserify = require('browserify');

var _ = require('./utils.js');
var Parser = require('./parser.js');
var Evaluator = require('./evaluator.js');
var StreamInterface = require('./serverStreamInterface.js');
var Model = require('./model.js');
var ViewModel = require('./viewModel.js');
var Collection = require('./collection.js');
var Query = require('./query.js');
var DataInterface = require('./serverDataInterface.js');
var REST = require('./REST.js');

var ServerApplication = function(options) {
  // Create express app
  var expressApp = express();

  // Default options
  options = _.merge({
    mongoUrl: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://127.0.0.1:27017/declaire',
    viewsFolder: __dirname + '/../../../src/views/',
    npmPublic: ['/public']
  }, options);
  if(options.mongoDevUrl && expressApp.get('env') == 'development') {
    options.mongoUrl = options.mongoDevUrl;
  }

  // Logging
  expressApp.use(morgan('combined'));

  // Fake http verbs for dumb clients
  // expressApp.use(methodOverride());

  // Mongo based sessions
  if(!process.env.SESSION_SECRET) console.warn("Warning: No SESSION_SECRET environment variable set!")
  expressApp.use(session({
    secret: process.env.SESSION_SECRET || 'devSecret',
    store: new MongoStore({url: options.mongoUrl}),
    saveUninitialized: true,
    resave: true
  }));

  // Parse form data
  expressApp.use(bodyParser.json());
  expressApp.use(bodyParser.urlencoded({ extended: true }));
  // multipart/form-data
  expressApp.use(multer());

  // Compile Stylus stylesheets
  expressApp.use(stylus.middleware({
    src: __dirname + '/../../../',
    dest: __dirname + '/../../../public',
    compress: true,
    compile: function compile(str, path) {
      return stylus(str).set('filename', path).set('compress', true).use(require('nib')());
    }
  }));

  // Serve public files
  expressApp.use(express.static(__dirname + '/../../../public'));
  _.each(options.npmPublic, function(folder) {
    expressApp.use('/' + folder, express.static(__dirname + '/../../../node_modules/' + folder));
  });

  // Serve favicon
  try { expressApp.use(favicon(__dirname + '/../public/favicon.png')) } catch(e) {}

  // Gzip compression
  expressApp.use(compression());

  // Fix Safari caching bug
  expressApp.use(require('jumanji'));

  //XXX Remove this
  expressApp.get('/', function(req, res) {
    res.redirect('/pages/index');
  });

  // Package and minify JavaScript
  // Exchanges require calls to this very module with the client side implementation
  var bundle;
  var prepareBundle = function(cb) {
    if(bundle) return cb(bundle);
    process.stdout.write("Preparing Bundle...");
    // Use executed application as main script on the client as well
    var appPath = process.argv[1];
    var b = new browserify({debug: true});
    b.add(appPath);
    b.ignore('newrelic');
    b.ignore('express');
    b.ignore('connect');
    // Exchange require calls
    b.transform(require('aliasify'), {
      aliases: {
        "declaire": "./node_modules/declaire/src/clientAPI.js"
      },
      verbose: false
    });
    if(expressApp.get('env') == 'production') {
      b.plugin(require('minifyify'), {output: 'public/bundle.js.map', map: 'bundle.js.map'});
    }
    b.bundle(function(err, buf) {
      if(err) throw err;
      bundle = buf;
      cb(bundle);
    });
  };

  expressApp.get('/bundle.js', function(req, res) {
    res.setHeader('Content-Type', 'application/javascript');
    prepareBundle(function(bundle) {
      res.send(bundle);
    });
  });

  // Let New Relic measure uptime
  expressApp.get('/ping', function(req, res) { res.send('pong'); });

  // Create main model singleton instance
  var mainModel = Model('_main', {
    _page: null
  }).create();

  // Save view model declarations for lookup in templates
  var viewModels = {};

  // Build an evaluator for the main layout
  // and add the main model instance to its scope
  var evaluator;
  var setupEvaluator = function() {
    var topNode = parseTrees['layout.tmpl'];
    evaluator = Evaluator(topNode, viewModels, parseTrees, StreamInterface());
    // Also add another, neutral layer to which subsequent vars can be added
    evaluator.baseScope.addLayer(mainModel).addLayer();
  };

  // Inject bootstrapping script and bundle reference into head tag
  var injectScripts = function(layout) {
    var bootstrap = fs.readFileSync(__dirname + '/../../../node_modules/declaire/src/bootstrap.js', 'utf8');
    _.each(layout.children, function(node) {
      if(node.tag == 'head') {
        // Inject bootstrapping script
        var scriptTag = {
          type: 'HTMLTag',
          tag: 'script',
          children: [{
            type: 'Text',
            content: bootstrap
          }]
        };
        // node.children.push(scriptTag);
        // Inject bundle
        node.children.push({
          type: 'HTMLTag',
          tag: 'script',
          attributes: {src: '/bundle.js', async: 'async'},
          children: []
        });
        return false;
      }
    });
  };

  // Load and parse all templates in the views folder
  var parseTrees;
  var parseTemplates = function() {
    parseTrees = {};
    _.each(fs.readdirSync(options.viewsFolder), function(file) {
      if(path.extname(file) == '.tmpl'){
        console.log("Parsing " + file);
        var fn = options.viewsFolder + file;
        _.improveExceptions(fn, function() {
          var node = Parser.parseTemplate(fs.readFileSync(fn, 'utf8'));
          parseTrees[file] = node;
        });
      }
    });
    injectScripts(parseTrees['layout.tmpl']);
    setupEvaluator();
  };
  parseTemplates();

  // Make parse trees available to client-side evaluator
  expressApp.get('/templates.json', function(req, res) {
    res.send(JSON.stringify(parseTrees));
  });

  // Render layout for the requested page
  expressApp.get('/pages/*', function(req, res) {
    res.setHeader('Content-Type', 'text/html');
    if(expressApp.get('env') == 'development') parseTemplates();
    mainModel.set('_page', req.url);
    // Stream chunks of rendered html
    evaluator.render().render(function(chunk) {
      console.log(chunk);
      res.write(chunk.data);
      res.flush();
      if(chunk.eof) {
        res.end();
      }
    });
  });

  // Show stack traces in development
  if(expressApp.get('env') == 'development') {
    expressApp.use(errorHandler({dumpExceptions: true, showStack: true}));
  }

  return {
    // Export main model
    mainModel: mainModel,

    // Register models and view models for use with this application
    use: function(model) {
      model.app = this;
      if(model.klass == 'ViewModel') {
        viewModels[model.name] = model;
      } else if(model.klass == 'Model') {
        var dataface = DataInterface(this, model.name);
        model.dataInterface = dataface;
        REST(model.name, expressApp, dataface).serveResource();
      }
      return model;
    },

    // Proxy model constructor
    Model: function(name, reference) {
      return this.use(Model(name, reference));
    },

    // Proxy view model constructor
    ViewModel: function(name, reference, constructor, postCb) {
      return this.use(ViewModel(name, reference, constructor, postCb));
    },

    // Proxy query constructor
    Query: function(modelOrCollection, query, options) {
      return this.use(Query(modelOrCollection, query, options));
    },

    // Connect to backend services, prepare bundle, call back
    init: function(cb) {
      var self = this;
      // Connect to database
      process.stdout.write("Connecting to database...");
      mongo.MongoClient.connect(options.mongoUrl, function(err, dbs) {
        if(err) throw err;
        console.log("done");
        self.db = dbs;
        // Mongo PubSub
        process.stdout.write("Preparing PubSub...");
        self.pubSub = require('./serverPublisher.js')(expressApp, self.db).init(function() {
          console.log("done");
          // start must be called by application code to listen for requests
          var start = function(cb) {
            var port = options.port || process.env.PORT || 3000;
            var server = expressApp.listen(port, function () {
              console.log('Listening on port ' + port);
              cb && cb();
            });
          };
          // Make sure we have a cached bundle ready before listening for requests
          prepareBundle(function() {
            console.log("done");
            cb(start, expressApp, self.db)
          });
        });
      });
    }
  };
};

module.exports = ServerApplication;
<commit_msg>Less logging<commit_after>var path = require('path');
var mongo = require('mongodb');
var express = require('express');
var morgan = require('morgan');
// var methodOverride = require('method-override');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var bodyParser = require('body-parser');
var multer = require('multer');
var favicon = require('serve-favicon');
var compression = require('compression')
var errorHandler = require('errorhandler');
var fs = require('fs');
var stylus = require('stylus');
var browserify = require('browserify');

var _ = require('./utils.js');
var Parser = require('./parser.js');
var Evaluator = require('./evaluator.js');
var StreamInterface = require('./serverStreamInterface.js');
var Model = require('./model.js');
var ViewModel = require('./viewModel.js');
var Collection = require('./collection.js');
var Query = require('./query.js');
var DataInterface = require('./serverDataInterface.js');
var REST = require('./REST.js');

var ServerApplication = function(options) {
  // Create express app
  var expressApp = express();

  // Default options
  options = _.merge({
    mongoUrl: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://127.0.0.1:27017/declaire',
    viewsFolder: __dirname + '/../../../src/views/',
    npmPublic: ['/public']
  }, options);
  if(options.mongoDevUrl && expressApp.get('env') == 'development') {
    options.mongoUrl = options.mongoDevUrl;
  }

  // Logging
  expressApp.use(morgan('combined'));

  // Fake http verbs for dumb clients
  // expressApp.use(methodOverride());

  // Mongo based sessions
  if(!process.env.SESSION_SECRET) console.warn("Warning: No SESSION_SECRET environment variable set!")
  expressApp.use(session({
    secret: process.env.SESSION_SECRET || 'devSecret',
    store: new MongoStore({url: options.mongoUrl}),
    saveUninitialized: true,
    resave: true
  }));

  // Parse form data
  expressApp.use(bodyParser.json());
  expressApp.use(bodyParser.urlencoded({ extended: true }));
  // multipart/form-data
  expressApp.use(multer());

  // Compile Stylus stylesheets
  expressApp.use(stylus.middleware({
    src: __dirname + '/../../../',
    dest: __dirname + '/../../../public',
    compress: true,
    compile: function compile(str, path) {
      return stylus(str).set('filename', path).set('compress', true).use(require('nib')());
    }
  }));

  // Serve public files
  expressApp.use(express.static(__dirname + '/../../../public'));
  _.each(options.npmPublic, function(folder) {
    expressApp.use('/' + folder, express.static(__dirname + '/../../../node_modules/' + folder));
  });

  // Serve favicon
  try { expressApp.use(favicon(__dirname + '/../public/favicon.png')) } catch(e) {}

  // Gzip compression
  expressApp.use(compression());

  // Fix Safari caching bug
  expressApp.use(require('jumanji'));

  //XXX Remove this
  expressApp.get('/', function(req, res) {
    res.redirect('/pages/index');
  });

  // Package and minify JavaScript
  // Exchanges require calls to this very module with the client side implementation
  var bundle;
  var prepareBundle = function(cb) {
    if(bundle) return cb(bundle);
    process.stdout.write("Preparing Bundle...");
    // Use executed application as main script on the client as well
    var appPath = process.argv[1];
    var b = new browserify({debug: true});
    b.add(appPath);
    b.ignore('newrelic');
    b.ignore('express');
    b.ignore('connect');
    // Exchange require calls
    b.transform(require('aliasify'), {
      aliases: {
        "declaire": "./node_modules/declaire/src/clientAPI.js"
      },
      verbose: false
    });
    if(expressApp.get('env') == 'production') {
      b.plugin(require('minifyify'), {output: 'public/bundle.js.map', map: 'bundle.js.map'});
    }
    b.bundle(function(err, buf) {
      if(err) throw err;
      bundle = buf;
      cb(bundle);
    });
  };

  expressApp.get('/bundle.js', function(req, res) {
    res.setHeader('Content-Type', 'application/javascript');
    prepareBundle(function(bundle) {
      res.send(bundle);
    });
  });

  // Let New Relic measure uptime
  expressApp.get('/ping', function(req, res) { res.send('pong'); });

  // Create main model singleton instance
  var mainModel = Model('_main', {
    _page: null
  }).create();

  // Save view model declarations for lookup in templates
  var viewModels = {};

  // Build an evaluator for the main layout
  // and add the main model instance to its scope
  var evaluator;
  var setupEvaluator = function() {
    var topNode = parseTrees['layout.tmpl'];
    evaluator = Evaluator(topNode, viewModels, parseTrees, StreamInterface());
    // Also add another, neutral layer to which subsequent vars can be added
    evaluator.baseScope.addLayer(mainModel).addLayer();
  };

  // Inject bootstrapping script and bundle reference into head tag
  var injectScripts = function(layout) {
    var bootstrap = fs.readFileSync(__dirname + '/../../../node_modules/declaire/src/bootstrap.js', 'utf8');
    _.each(layout.children, function(node) {
      if(node.tag == 'head') {
        // Inject bootstrapping script
        var scriptTag = {
          type: 'HTMLTag',
          tag: 'script',
          children: [{
            type: 'Text',
            content: bootstrap
          }]
        };
        // node.children.push(scriptTag);
        // Inject bundle
        node.children.push({
          type: 'HTMLTag',
          tag: 'script',
          attributes: {src: '/bundle.js', async: 'async'},
          children: []
        });
        return false;
      }
    });
  };

  // Load and parse all templates in the views folder
  var parseTrees;
  var parseTemplates = function() {
    parseTrees = {};
    _.each(fs.readdirSync(options.viewsFolder), function(file) {
      if(path.extname(file) == '.tmpl'){
        console.log("Parsing " + file);
        var fn = options.viewsFolder + file;
        _.improveExceptions(fn, function() {
          var node = Parser.parseTemplate(fs.readFileSync(fn, 'utf8'));
          parseTrees[file] = node;
        });
      }
    });
    injectScripts(parseTrees['layout.tmpl']);
    setupEvaluator();
  };
  parseTemplates();

  // Make parse trees available to client-side evaluator
  expressApp.get('/templates.json', function(req, res) {
    res.send(JSON.stringify(parseTrees));
  });

  // Render layout for the requested page
  expressApp.get('/pages/*', function(req, res) {
    res.setHeader('Content-Type', 'text/html');
    if(expressApp.get('env') == 'development') parseTemplates();
    mainModel.set('_page', req.url);
    // Stream chunks of rendered html
    evaluator.render().render(function(chunk) {
      // console.log(chunk);
      res.write(chunk.data);
      res.flush();
      if(chunk.eof) {
        res.end();
      }
    });
  });

  // Show stack traces in development
  if(expressApp.get('env') == 'development') {
    expressApp.use(errorHandler({dumpExceptions: true, showStack: true}));
  }

  return {
    // Export main model
    mainModel: mainModel,

    // Register models and view models for use with this application
    use: function(model) {
      model.app = this;
      if(model.klass == 'ViewModel') {
        viewModels[model.name] = model;
      } else if(model.klass == 'Model') {
        var dataface = DataInterface(this, model.name);
        model.dataInterface = dataface;
        REST(model.name, expressApp, dataface).serveResource();
      }
      return model;
    },

    // Proxy model constructor
    Model: function(name, reference) {
      return this.use(Model(name, reference));
    },

    // Proxy view model constructor
    ViewModel: function(name, reference, constructor, postCb) {
      return this.use(ViewModel(name, reference, constructor, postCb));
    },

    // Proxy query constructor
    Query: function(modelOrCollection, query, options) {
      return this.use(Query(modelOrCollection, query, options));
    },

    // Connect to backend services, prepare bundle, call back
    init: function(cb) {
      var self = this;
      // Connect to database
      process.stdout.write("Connecting to database...");
      mongo.MongoClient.connect(options.mongoUrl, function(err, dbs) {
        if(err) throw err;
        console.log("done");
        self.db = dbs;
        // Mongo PubSub
        process.stdout.write("Preparing PubSub...");
        self.pubSub = require('./serverPublisher.js')(expressApp, self.db).init(function() {
          console.log("done");
          // start must be called by application code to listen for requests
          var start = function(cb) {
            var port = options.port || process.env.PORT || 3000;
            var server = expressApp.listen(port, function () {
              console.log('Listening on port ' + port);
              cb && cb();
            });
          };
          // Make sure we have a cached bundle ready before listening for requests
          prepareBundle(function() {
            console.log("done");
            cb(start, expressApp, self.db)
          });
        });
      });
    }
  };
};

module.exports = ServerApplication;
<|endoftext|>


<commit_before>var specify  = require('specify')
  , helpers  = require('../helpers')
  , timeout  = helpers.timeout
  , nano     = helpers.nano
  , nock     = helpers.nock
  , pixel    = helpers.pixel
  , rev
  ;

var mock = nock(helpers.couch, "att/update")
  , db   = nano.use("att_update")
  ;

specify("att_update:setup", timeout, function (assert) {
  nano.db.create("att_update", function (err) {
    assert.equal(err, undefined, "Failed to create database");
  });
});

specify("att_update:test", timeout, function (assert) {
  var buffer = new Buffer(pixel, 'base64');
    db.attachment.insert("new", "att", "Hello", "text/plain",
    function(error, hello) {
      assert.equal(error, undefined, "Should store hello");
      assert.equal(hello.ok, true, "Response should be ok");
      assert.ok(hello.rev, "Should have a revision number");
      db.attachment.insert("new", "att", buffer, "image/bmp",
      { rev: hello.rev }, function (error, bmp) {
        assert.equal(error, undefined, "Should store the pixel");
        assert.ok(bmp.rev, "Should have a revision number");
        rev = bmp.rev;
      });
    });
});

specify("att_update:metadata", timeout, function (assert) {
  db.get("new", function (error, new_doc) {
    assert.equal(error, undefined, "Should get new");
    new_doc.works = true;
    db.insert(new_doc, "new", function (error, response) {
      assert.equal(error, undefined, "Should update doc");
      assert.equal(response.ok, true, "Response should be ok");
    });
  })
});

specify("att_update:teardown", timeout, function (assert) {
  nano.db.destroy("att_update", function (err) {
    assert.equal(err, undefined, "Failed to destroy database");
    assert.ok(mock.isDone(), "Some mocks didn't run");
  });
});

specify.run(process.argv.slice(2));<commit_msg>[minor] semi colon madness<commit_after>var specify  = require('specify')
  , helpers  = require('../helpers')
  , timeout  = helpers.timeout
  , nano     = helpers.nano
  , nock     = helpers.nock
  , pixel    = helpers.pixel
  , rev
  ;

var mock = nock(helpers.couch, "att/update")
  , db   = nano.use("att_update")
  ;

specify("att_update:setup", timeout, function (assert) {
  nano.db.create("att_update", function (err) {
    assert.equal(err, undefined, "Failed to create database");
  });
});

specify("att_update:test", timeout, function (assert) {
  var buffer = new Buffer(pixel, 'base64');
    db.attachment.insert("new", "att", "Hello", "text/plain",
    function(error, hello) {
      assert.equal(error, undefined, "Should store hello");
      assert.equal(hello.ok, true, "Response should be ok");
      assert.ok(hello.rev, "Should have a revision number");
      db.attachment.insert("new", "att", buffer, "image/bmp",
      { rev: hello.rev }, function (error, bmp) {
        assert.equal(error, undefined, "Should store the pixel");
        assert.ok(bmp.rev, "Should have a revision number");
        rev = bmp.rev;
      });
    });
});

specify("att_update:metadata", timeout, function (assert) {
  db.get("new", function (error, new_doc) {
    assert.equal(error, undefined, "Should get new");
    new_doc.works = true;
    db.insert(new_doc, "new", function (error, response) {
      assert.equal(error, undefined, "Should update doc");
      assert.equal(response.ok, true, "Response should be ok");
    });
  });
});

specify("att_update:teardown", timeout, function (assert) {
  nano.db.destroy("att_update", function (err) {
    assert.equal(err, undefined, "Failed to destroy database");
    assert.ok(mock.isDone(), "Some mocks didn't run");
  });
});

specify.run(process.argv.slice(2));<|endoftext|>


<commit_before>import ActionButton from 'action-button'
import forEach from 'lodash/forEach'
import includes from 'lodash/includes'
import isEmpty from 'lodash/isEmpty'
import keyBy from 'lodash/keyBy'
import map from 'lodash/map'
import orderBy from 'lodash/orderBy'
import React, { Component } from 'react'
import { confirm } from 'modal'
import { error } from 'notification'
import { SelectSubject } from 'select-objects'
import { Text } from 'editable'

import {
  addUserToGroup,
  createGroup,
  deleteGroup,
  removeUserFromGroup,
  setGroupName,
  subscribeGroups,
  subscribeUsers
} from 'xo'

/**
 * @prop id: the id of a xo user
 * @prop group: the id of a xo group
 */
class UserDisplay extends Component {
  constructor (props) {
    super(props)
    this.state = {
      users: {}
    }
  }

  componentWillMount () {
    const unsubscribeUsers = subscribeUsers(users => {
      users = keyBy(users, 'id')
      this.setState({
        users
      })
    })

    this.componentWillUnmount = () => {
      unsubscribeUsers()
    }
  }

  _removeUser = () => {
    const {id, group} = this.props
    return removeUserFromGroup(id, group)
      .catch(err => error('Remove User', err.message || String(err)))
  }

  render () {
    const { id } = this.props
    const {
      users
    } = this.state
    return
      {id && (users[id] && users[id].email) || <unknown user or group>}
      {' '}
      <ActionButton btnStyle='primary' size='small' icon='remove' handler={this._removeUser} />

  }
}

export default class Groups extends Component {
  constructor (props) {
    super(props)
    this.state = {
      groups: []
    }
  }

  componentWillMount () {
    const unsubscribeGroups = subscribeGroups(groups => this.setState({groups: orderBy(groups, ['name'])}))

    this.componentWillUnmount = () => {
      unsubscribeGroups()
    }
  }

  _createGroup = () => {
    const { name } = this.refs
    if (name) {
      return createGroup(name.value)
        .then(() => { name.value = '' })
        .catch(err => error('Create Group', err.message || String(err)))
    }
  }

  _deleteGroup = async id => {
    try {
      await confirm({
        title: 'Delete group',
        body:
Are you sure you want to delete this group ?

      })
      return deleteGroup(id)
      .catch(err => error('Delete Group', err.message || String(err)))
    } catch (_) {
      return
    }
  }

  _getPredicate = users => {
    return entity => entity.email && !includes(users, entity.id) // Entity is a user and is not already in list
  }

  _addUser = (user, group) => {
    return addUserToGroup(user.id, group.id)
      .catch(err => error('Add User', err.message || String(err)))
  }

  render () {
    const {
      groups
    } = this.state

    return

      <form>

                Name

              Members
              Add member

            {isEmpty(groups) &&
No groups found
}
            {map(groups, group =>

                    <Text value={group.name} onChange={value => setGroupName(group.id, value)} />

                  {isEmpty(group.users) && No users in group}
                  {map(group.users, user => <UserDisplay id={user} group={group.id} /> )}

                    <SelectSubject predicate={this._getPredicate(group.users)} onChange={user => this._addUser(user, group)} defaultValue={null} />

                  <ActionButton icon='delete' handler={this._deleteGroup} handlerParam={group.id} btnStyle='danger' />

            )}

      </form>

      <form id='newGroupForm' className='form-inline'>

          <input type='text' ref='name' placeholder='New Group name' required className='form-control' />

        {' '}

          <ActionButton type='submit' form='newGroupForm' icon='add' btnStyle='success' handler={this._createGroup}>Create</ActionButton>

      </form>

  }
}
<commit_msg>chore(Groups): remove unused import<commit_after>import ActionButton from 'action-button'
import includes from 'lodash/includes'
import isEmpty from 'lodash/isEmpty'
import keyBy from 'lodash/keyBy'
import map from 'lodash/map'
import orderBy from 'lodash/orderBy'
import React, { Component } from 'react'
import { confirm } from 'modal'
import { error } from 'notification'
import { SelectSubject } from 'select-objects'
import { Text } from 'editable'

import {
  addUserToGroup,
  createGroup,
  deleteGroup,
  removeUserFromGroup,
  setGroupName,
  subscribeGroups,
  subscribeUsers
} from 'xo'

/**
 * @prop id: the id of a xo user
 * @prop group: the id of a xo group
 */
class UserDisplay extends Component {
  constructor (props) {
    super(props)
    this.state = {
      users: {}
    }
  }

  componentWillMount () {
    const unsubscribeUsers = subscribeUsers(users => {
      users = keyBy(users, 'id')
      this.setState({
        users
      })
    })

    this.componentWillUnmount = () => {
      unsubscribeUsers()
    }
  }

  _removeUser = () => {
    const {id, group} = this.props
    return removeUserFromGroup(id, group)
      .catch(err => error('Remove User', err.message || String(err)))
  }

  render () {
    const { id } = this.props
    const {
      users
    } = this.state
    return
      {id && (users[id] && users[id].email) || <unknown user or group>}
      {' '}
      <ActionButton btnStyle='primary' size='small' icon='remove' handler={this._removeUser} />

  }
}

export default class Groups extends Component {
  constructor (props) {
    super(props)
    this.state = {
      groups: []
    }
  }

  componentWillMount () {
    const unsubscribeGroups = subscribeGroups(groups => this.setState({groups: orderBy(groups, ['name'])}))

    this.componentWillUnmount = () => {
      unsubscribeGroups()
    }
  }

  _createGroup = () => {
    const { name } = this.refs
    if (name) {
      return createGroup(name.value)
        .then(() => { name.value = '' })
        .catch(err => error('Create Group', err.message || String(err)))
    }
  }

  _deleteGroup = async id => {
    try {
      await confirm({
        title: 'Delete group',
        body:
Are you sure you want to delete this group ?

      })
      return deleteGroup(id)
      .catch(err => error('Delete Group', err.message || String(err)))
    } catch (_) {
      return
    }
  }

  _getPredicate = users => {
    return entity => entity.email && !includes(users, entity.id) // Entity is a user and is not already in list
  }

  _addUser = (user, group) => {
    return addUserToGroup(user.id, group.id)
      .catch(err => error('Add User', err.message || String(err)))
  }

  render () {
    const {
      groups
    } = this.state

    return

      <form>

                Name

              Members
              Add member

            {isEmpty(groups) &&
No groups found
}
            {map(groups, group =>

                    <Text value={group.name} onChange={value => setGroupName(group.id, value)} />

                  {isEmpty(group.users) && No users in group}
                  {map(group.users, user => <UserDisplay id={user} group={group.id} /> )}

                    <SelectSubject predicate={this._getPredicate(group.users)} onChange={user => this._addUser(user, group)} defaultValue={null} />

                  <ActionButton icon='delete' handler={this._deleteGroup} handlerParam={group.id} btnStyle='danger' />

            )}

      </form>

      <form id='newGroupForm' className='form-inline'>

          <input type='text' ref='name' placeholder='New Group name' required className='form-control' />

        {' '}

          <ActionButton type='submit' form='newGroupForm' icon='add' btnStyle='success' handler={this._createGroup}>Create</ActionButton>

      </form>

  }
}
<|endoftext|>


<commit_before>(function(global) {

  'use strict';

  var fabric = global.fabric || (global.fabric = { }),
      extend = fabric.util.object.extend,
      coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 },
      supportsLineDash = fabric.StaticCanvas.supports('setLineDash');

  if (fabric.Line) {
    fabric.warn('fabric.Line is already defined');
    return;
  }

  /**
   * Line class
   * @class fabric.Line
   * @extends fabric.Object
   * @see {@link fabric.Line#initialize} for constructor definition
   */
  fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {

    /**
     * Type of an object
     * @type String
     * @default
     */
    type: 'line',

    /**
     * x value or first line edge
     * @type Number
     * @default
     */
    x1: 0,

    /**
     * y value or first line edge
     * @type Number
     * @default
     */
    y1: 0,

    /**
     * x value or second line edge
     * @type Number
     * @default
     */
    x2: 0,

    /**
     * y value or second line edge
     * @type Number
     * @default
     */
    y2: 0,

    /**
     * Constructor
     * @param {Array} [points] Array of points
     * @param {Object} [options] Options object
     * @return {fabric.Line} thisArg
     */
    initialize: function(points, options) {
      options = options || { };

      if (!points) {
        points = [0, 0, 0, 0];
      }

      this.callSuper('initialize', options);

      this.set('x1', points[0]);
      this.set('y1', points[1]);
      this.set('x2', points[2]);
      this.set('y2', points[3]);

      this._setWidthHeight(options);
    },

    /**
     * @private
     * @param {Object} [options] Options
     */
    _setWidthHeight: function(options) {
      options || (options = { });

      this.width = Math.abs(this.x2 - this.x1) || 1;
      this.height = Math.abs(this.y2 - this.y1) || 1;

      this.left = 'left' in options
        ? options.left
        : this._getLeftToOriginX();

      this.top = 'top' in options
        ? options.top
        : this._getTopToOriginY();
    },

    /**
     * @private
     * @param {String} key
     * @param {Any} value
     */
    _set: function(key, value) {
      this[key] = value;
      if (typeof coordProps[key] !== 'undefined') {
        this._setWidthHeight();
      }
      return this;
    },

    /**
     * @private
     * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line.
     */
    _getLeftToOriginX: makeEdgeToOriginGetter(
      { // property names
        origin: 'originX',
        axis1: 'x1',
        axis2: 'x2',
        dimension: 'width'
      },
      { // possible values of origin
        nearest: 'left',
        center: 'center',
        farthest: 'right'
      }
    ),

    /**
     * @private
     * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line.
     */
    _getTopToOriginY: makeEdgeToOriginGetter(
      { // property names
        origin: 'originY',
        axis1: 'y1',
        axis2: 'y2',
        dimension: 'height'
      },
      { // possible values of origin
        nearest: 'top',
        center: 'center',
        farthest: 'bottom'
      }
    ),

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _render: function(ctx) {
      ctx.beginPath();

      var isInPathGroup = this.group && this.group.type === 'path-group';
      if (isInPathGroup) {
        //  Line coords are distances from left-top of canvas to origin of line.
        //
        //  To render line in a path-group, we need to translate them to
        //  distances from center of path-group to center of line.
        var cp = this.getCenterPoint();
        ctx.translate(
          cp.x,
          cp.y
        );
        if (!this.transformMatrix) {
          ctx.translate(-this.group.width / 2, -this.group.height / 2);
        }
      }

      if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {

        // move from center (of virtual box) to its left/top corner
        // we can't assume x1, y1 is top left and x2, y2 is bottom right
        var xMult = this.x1 <= this.x2 ? -1 : 1,
            yMult = this.y1 <= this.y2 ? -1 : 1;

        ctx.moveTo(
          this.width === 1 ? 0 : (xMult * this.width / 2),
          this.height === 1 ? 0 : (yMult * this.height / 2));

        ctx.lineTo(
          this.width === 1 ? 0 : (xMult * -1 * this.width / 2),
          this.height === 1 ? 0 : (yMult * -1 * this.height / 2));
      }

      ctx.lineWidth = this.strokeWidth;

      // TODO: test this
      // make sure setting "fill" changes color of a line
      // (by copying fillStyle to strokeStyle, since line is stroked, not filled)
      var origStrokeStyle = ctx.strokeStyle;
      ctx.strokeStyle = this.stroke || ctx.fillStyle;
      this.stroke && this._renderStroke(ctx);
      ctx.strokeStyle = origStrokeStyle;
    },

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _renderDashedStroke: function(ctx) {
      var
        xMult = this.x1 <= this.x2 ? -1 : 1,
        yMult = this.y1 <= this.y2 ? -1 : 1,
        x = this.width === 1 ? 0 : xMult * this.width / 2,
        y = this.height === 1 ? 0 : yMult * this.height / 2;

      ctx.beginPath();
      fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray);
      ctx.closePath();
    },

    /**
     * Returns object representation of an instance
     * @methd toObject
     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
     * @return {Object} object representation of an instance
     */
    toObject: function(propertiesToInclude) {
      return extend(this.callSuper('toObject', propertiesToInclude), {
        x1: this.get('x1'),
        y1: this.get('y1'),
        x2: this.get('x2'),
        y2: this.get('y2')
      });
    },

    /* _TO_SVG_START_ */
    /**
     * Returns SVG representation of an instance
     * @param {Function} [reviver] Method for further parsing of svg representation.
     * @return {String} svg representation of an instance
     */
    toSVG: function(reviver) {
      var markup = this._createBaseSVGMarkup();

      markup.push(
        '<line ',
          'x1="', this.get('x1'),
          '" y1="', this.get('y1'),
          '" x2="', this.get('x2'),
          '" y2="', this.get('y2'),
          '" style="', this.getSvgStyles(),
        '"/>'
      );

      return reviver ? reviver(markup.join('')) : markup.join('');
    },
    /* _TO_SVG_END_ */

    /**
     * Returns complexity of an instance
     * @return {Number} complexity
     */
    complexity: function() {
      return 1;
    }
  });

  /* _FROM_SVG_START_ */
  /**
   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})
   * @static
   * @memberOf fabric.Line
   * @see http://www.w3.org/TR/SVG/shapes.html#LineElement
   */
  fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));

  /**
   * Returns fabric.Line instance from an SVG element
   * @static
   * @memberOf fabric.Line
   * @param {SVGElement} element Element to parse
   * @param {Object} [options] Options object
   * @return {fabric.Line} instance of fabric.Line
   */
  fabric.Line.fromElement = function(element, options) {
    var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES),
        points = [
          parsedAttributes.x1 || 0,
          parsedAttributes.y1 || 0,
          parsedAttributes.x2 || 0,
          parsedAttributes.y2 || 0
        ];
    return new fabric.Line(points, extend(parsedAttributes, options));
  };
  /* _FROM_SVG_END_ */

  /**
   * Returns fabric.Line instance from an object representation
   * @static
   * @memberOf fabric.Line
   * @param {Object} object Object to create an instance from
   * @return {fabric.Line} instance of fabric.Line
   */
  fabric.Line.fromObject = function(object) {
    var points = [object.x1, object.y1, object.x2, object.y2];
    return new fabric.Line(points, object);
  };

  /**
   * Produces a function that calculates distance from canvas edge to Line origin.
   */
  function makeEdgeToOriginGetter(propertyNames, originValues) {
    var origin = propertyNames.origin,
        axis1 = propertyNames.axis1,
        axis2 = propertyNames.axis2,
        dimension = propertyNames.dimension,
        nearest = originValues.nearest,
        center = originValues.center,
        farthest = originValues.farthest;

    return function() {
      switch (this.get(origin)) {
      case nearest:
        return Math.min(this.get(axis1), this.get(axis2));
      case center:
        return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));
      case farthest:
        return Math.max(this.get(axis1), this.get(axis2));
      }
    };

  }

})(typeof exports !== 'undefined' ? exports : this);
<commit_msg>Fixed toSVG for line, changes in rendering logic<commit_after>(function(global) {

  'use strict';

  var fabric = global.fabric || (global.fabric = { }),
      extend = fabric.util.object.extend,
      coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 },
      supportsLineDash = fabric.StaticCanvas.supports('setLineDash');

  if (fabric.Line) {
    fabric.warn('fabric.Line is already defined');
    return;
  }

  /**
   * Line class
   * @class fabric.Line
   * @extends fabric.Object
   * @see {@link fabric.Line#initialize} for constructor definition
   */
  fabric.Line = fabric.util.createClass(fabric.Object, /** @lends fabric.Line.prototype */ {

    /**
     * Type of an object
     * @type String
     * @default
     */
    type: 'line',

    /**
     * x value or first line edge
     * @type Number
     * @default
     */
    x1: 0,

    /**
     * y value or first line edge
     * @type Number
     * @default
     */
    y1: 0,

    /**
     * x value or second line edge
     * @type Number
     * @default
     */
    x2: 0,

    /**
     * y value or second line edge
     * @type Number
     * @default
     */
    y2: 0,

    /**
     * Constructor
     * @param {Array} [points] Array of points
     * @param {Object} [options] Options object
     * @return {fabric.Line} thisArg
     */
    initialize: function(points, options) {
      options = options || { };

      if (!points) {
        points = [0, 0, 0, 0];
      }

      this.callSuper('initialize', options);

      this.set('x1', points[0]);
      this.set('y1', points[1]);
      this.set('x2', points[2]);
      this.set('y2', points[3]);

      this._setWidthHeight(options);
    },

    /**
     * @private
     * @param {Object} [options] Options
     */
    _setWidthHeight: function(options) {
      options || (options = { });

      this.width = Math.abs(this.x2 - this.x1) || 1;
      this.height = Math.abs(this.y2 - this.y1) || 1;

      this.left = 'left' in options
        ? options.left
        : this._getLeftToOriginX();

      this.top = 'top' in options
        ? options.top
        : this._getTopToOriginY();
    },

    /**
     * @private
     * @param {String} key
     * @param {Any} value
     */
    _set: function(key, value) {
      this[key] = value;
      if (typeof coordProps[key] !== 'undefined') {
        this._setWidthHeight();
      }
      return this;
    },

    /**
     * @private
     * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line.
     */
    _getLeftToOriginX: makeEdgeToOriginGetter(
      { // property names
        origin: 'originX',
        axis1: 'x1',
        axis2: 'x2',
        dimension: 'width'
      },
      { // possible values of origin
        nearest: 'left',
        center: 'center',
        farthest: 'right'
      }
    ),

    /**
     * @private
     * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line.
     */
    _getTopToOriginY: makeEdgeToOriginGetter(
      { // property names
        origin: 'originY',
        axis1: 'y1',
        axis2: 'y2',
        dimension: 'height'
      },
      { // possible values of origin
        nearest: 'top',
        center: 'center',
        farthest: 'bottom'
      }
    ),

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _render: function(ctx, noTransform) {
      ctx.beginPath();

      if (noTransform) {
        //  Line coords are distances from left-top of canvas to origin of line.
        //
        //  To render line in a path-group, we need to translate them to
        //  distances from center of path-group to center of line.
        var cp = this.getCenterPoint();
        ctx.translate(
          cp.x,
          cp.y
        );
      }

      if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {

        // move from center (of virtual box) to its left/top corner
        // we can't assume x1, y1 is top left and x2, y2 is bottom right
        var xMult = this.x1 <= this.x2 ? -1 : 1,
            yMult = this.y1 <= this.y2 ? -1 : 1;

        ctx.moveTo(
          this.width === 1 ? 0 : (xMult * this.width / 2),
          this.height === 1 ? 0 : (yMult * this.height / 2));

        ctx.lineTo(
          this.width === 1 ? 0 : (xMult * -1 * this.width / 2),
          this.height === 1 ? 0 : (yMult * -1 * this.height / 2));
      }

      ctx.lineWidth = this.strokeWidth;

      // TODO: test this
      // make sure setting "fill" changes color of a line
      // (by copying fillStyle to strokeStyle, since line is stroked, not filled)
      var origStrokeStyle = ctx.strokeStyle;
      ctx.strokeStyle = this.stroke || ctx.fillStyle;
      this.stroke && this._renderStroke(ctx);
      ctx.strokeStyle = origStrokeStyle;
    },

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     */
    _renderDashedStroke: function(ctx) {
      var
        xMult = this.x1 <= this.x2 ? -1 : 1,
        yMult = this.y1 <= this.y2 ? -1 : 1,
        x = this.width === 1 ? 0 : xMult * this.width / 2,
        y = this.height === 1 ? 0 : yMult * this.height / 2;

      ctx.beginPath();
      fabric.util.drawDashedLine(ctx, x, y, -x, -y, this.strokeDashArray);
      ctx.closePath();
    },

    /**
     * Returns object representation of an instance
     * @methd toObject
     * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
     * @return {Object} object representation of an instance
     */
    toObject: function(propertiesToInclude) {
      return extend(this.callSuper('toObject', propertiesToInclude), {
        x1: this.get('x1'),
        y1: this.get('y1'),
        x2: this.get('x2'),
        y2: this.get('y2')
      });
    },

    /* _TO_SVG_START_ */
    /**
     * Returns SVG representation of an instance
     * @param {Function} [reviver] Method for further parsing of svg representation.
     * @return {String} svg representation of an instance
     */
    toSVG: function(reviver) {
      var markup = this._createBaseSVGMarkup(), addTranslate = '';
      if (!this.group) {
        addTranslate = 'translate(' + (-this.width/2) + ', ' + (-this.height/2) + ') ';
      }
      markup.push(
        '<line ',
          'x1="', this.get('x1'),
          '" y1="', this.get('y1'),
          '" x2="', this.get('x2'),
          '" y2="', this.get('y2'),
          '" style="', this.getSvgStyles(),
          '" transform="', this.getSvgTransform(), addTranslate,
          this.getSvgTransformMatrix(),
        '"/>\n'
      );

      return reviver ? reviver(markup.join('')) : markup.join('');
    },
    /* _TO_SVG_END_ */

    /**
     * Returns complexity of an instance
     * @return {Number} complexity
     */
    complexity: function() {
      return 1;
    }
  });

  /* _FROM_SVG_START_ */
  /**
   * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement})
   * @static
   * @memberOf fabric.Line
   * @see http://www.w3.org/TR/SVG/shapes.html#LineElement
   */
  fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' '));

  /**
   * Returns fabric.Line instance from an SVG element
   * @static
   * @memberOf fabric.Line
   * @param {SVGElement} element Element to parse
   * @param {Object} [options] Options object
   * @return {fabric.Line} instance of fabric.Line
   */
  fabric.Line.fromElement = function(element, options) {
    var parsedAttributes = fabric.parseAttributes(element, fabric.Line.ATTRIBUTE_NAMES),
        points = [
          parsedAttributes.x1 || 0,
          parsedAttributes.y1 || 0,
          parsedAttributes.x2 || 0,
          parsedAttributes.y2 || 0
        ];
    return new fabric.Line(points, extend(parsedAttributes, options));
  };
  /* _FROM_SVG_END_ */

  /**
   * Returns fabric.Line instance from an object representation
   * @static
   * @memberOf fabric.Line
   * @param {Object} object Object to create an instance from
   * @return {fabric.Line} instance of fabric.Line
   */
  fabric.Line.fromObject = function(object) {
    var points = [object.x1, object.y1, object.x2, object.y2];
    return new fabric.Line(points, object);
  };

  /**
   * Produces a function that calculates distance from canvas edge to Line origin.
   */
  function makeEdgeToOriginGetter(propertyNames, originValues) {
    var origin = propertyNames.origin,
        axis1 = propertyNames.axis1,
        axis2 = propertyNames.axis2,
        dimension = propertyNames.dimension,
        nearest = originValues.nearest,
        center = originValues.center,
        farthest = originValues.farthest;

    return function() {
      switch (this.get(origin)) {
      case nearest:
        return Math.min(this.get(axis1), this.get(axis2));
      case center:
        return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));
      case farthest:
        return Math.max(this.get(axis1), this.get(axis2));
      }
    };

  }

})(typeof exports !== 'undefined' ? exports : this);
<|endoftext|>


<commit_before>define(["child-node"], function (ChildNode) {
    return function (problem) {

        // this function gets a node and add to the this.seq the sequence
        // of states passed to get from the initial state to node.
        this.solution = function (node) {
            this.seq = [];
            while (node.pathCost != 0) {
                this.seq.push(node.state);
                node = node.parent;
            }
            this.seq.push(node.state);
        };

        // this function returns true if state is in the explored region, false otherwise.
        this.inExplored = function (state) {
            for (var i = 0; i < this.explored.length; i++) {
                if (this.explored[i].equals(state)) {
                    return true;
                }
            }
            return false;
        };

        // this function returns true if state is in the frontier, false otherwise.
        this.inFrontier = function (state) {
            for (var i = 0; i < this.frontier.length; i++) {
                if (this.frontier[i].state.equals(state)) {
                    return true;
                }
            }
            return false;
        };

        // this function returns the index of the node in the frontier which has the smallest sum
        // of the path cost and the estimated distance to the goal.
        this.getSmallestEstimatedIndex = function () {
            var smallestEstimatedCost = Infinity;
            var index = -1;
            var goal = this.problem.goal;

            for (var i = 0; i < this.frontier.length; i++) {
                var node = this.frontier[i];
                var estimatedDistance = Math.floor(this.distanceBetween(node.state, goal));
                if (node.pathCost + estimatedDistance < smallestEstimatedCost) {
                    smallestEstimatedCost = node.pathCost + estimatedDistance;
                    index = i;
                }
            }

            return index;
        };

        // this function calculates the distance between states a and b
        this.distanceBetween = function (a, b) {
            var x = a.x - b.x;
            var y = a.y - b.y;
            return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        };

        // this is the function to expand the next node using depth-first search
        this.expandNextNodeDFS = function () {
            var node = this.frontier.pop();
            this.explored.push(node.state);

            this.problem.grid.highlightExploredState(node.state.x, node.state.y);

            var actions = this.problem.actions(node.state);
            for (var i = 0; i < actions.length; i++) {
                var child = new ChildNode(this.problem, node, actions[i]);
                if (!this.inExplored(child.state) && !this.inFrontier(child.state)) {
                    if (this.problem.goalTest(child.state)) {
                        this.solution(child);
                        this.searching = false;
                        this.executing = true;
                        return;
                    }
                    this.frontier.push(child);

                    this.problem.grid.highlightFrontierState(child.state.x, child.state.y);
                }
            }
        };

        // this is the function to expand the next node using breadth-first search
        this.expandNextNodeBFS = function () {
            var node = this.frontier.shift();
            this.explored.push(node.state);

            this.problem.grid.highlightExploredState(node.state.x, node.state.y);

            var actions = this.problem.actions(node.state);
            for (var i = 0; i < actions.length; i++) {
                var child = new ChildNode(this.problem, node, actions[i]);
                if (!this.inExplored(child.state) && !this.inFrontier(child.state)) {
                    if (this.problem.goalTest(child.state)) {
                        this.solution(child);
                        this.searching = false;
                        this.executing = true;
                        return;
                    }
                    this.frontier.push(child);

                    this.problem.grid.highlightFrontierState(child.state.x, child.state.y);
                }
            }
        };

        // this is the function to expand the next node using A* search
        this.expandNextNodeAS = function () {
            var index = this.getSmallestEstimatedIndex();
            var node = this.frontier[index];
            this.frontier.splice(index, 1);

            this.explored.push(node.state);

            this.problem.grid.highlightExploredState(node.state.x, node.state.y);

            var actions = this.problem.actions(node.state);
            for (var i = 0; i < actions.length; i++) {
                var child = new ChildNode(this.problem, node, actions[i]);
                if (!this.inExplored(child.state) && !this.inFrontier(child.state)) {
                    if (this.problem.goalTest(child.state)) {
                        this.solution(child);
                        this.searching = false;
                        this.executing = true;
                        return;
                    }
                    this.frontier.push(child);

                    this.problem.grid.highlightFrontierState(child.state.x, child.state.y);
                }
            }
        };

        // Initializing the agent object

        this.problem = problem;
        this.seq = [];
        this.searching = true;
        this.executing = false;
        this.frontier = [];

        var node = {
            state: this.problem.initialState,
            pathCost: 0
        }
        this.frontier.push(node);

        if (this.problem.goalTest(node.state)) {
            this.solution(node);
            this.frontier.pop();
            this.searching = false;
        }

        this.explored = [];
    }
});<commit_msg>Revert "correcting A* search"<commit_after>define(["child-node"], function (ChildNode) {
    return function (problem) {

        // this function gets a node and add to the this.seq the sequence
        // of states passed to get from the initial state to node.
        this.solution = function (node) {
            this.seq = [];
            while (node.pathCost != 0) {
                this.seq.push(node.state);
                node = node.parent;
            }
            this.seq.push(node.state);
        };

        // this function returns true if state is in the explored region, false otherwise.
        this.inExplored = function (state) {
            for (var i = 0; i < this.explored.length; i++) {
                if (this.explored[i].equals(state)) {
                    return true;
                }
            }
            return false;
        };

        // this function returns true if state is in the frontier, false otherwise.
        this.inFrontier = function (state) {
            for (var i = 0; i < this.frontier.length; i++) {
                if (this.frontier[i].state.equals(state)) {
                    return true;
                }
            }
            return false;
        };

        // this function returns the index of the node in the frontier that's nearest to the goal
        this.getNearestToGoalIndex = function () {
            var smallestDistance = Infinity;
            var index = -1;
            var goal = this.problem.goal;

            for (var i = 0; i < this.frontier.length; i++) {
                var state = this.frontier[i].state;
                var distance = this.distanceBetween(state, goal);
                if (distance < smallestDistance) {
                    smallestDistance = distance;
                    index = i;
                }
            }

            return index;
        };

        // this function calculates the distance between states a and b
        this.distanceBetween = function (a, b) {
            var x = a.x - b.x;
            var y = a.y - b.y;
            return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        };

        // this is the function to expand the next node using depth-first search
        this.expandNextNodeDFS = function () {
            var node = this.frontier.pop();
            this.explored.push(node.state);

            this.problem.grid.highlightExploredState(node.state.x, node.state.y);

            var actions = this.problem.actions(node.state);
            for (var i = 0; i < actions.length; i++) {
                var child = new ChildNode(this.problem, node, actions[i]);
                if (!this.inExplored(child.state) && !this.inFrontier(child.state)) {
                    if (this.problem.goalTest(child.state)) {
                        this.solution(child);
                        this.searching = false;
                        this.executing = true;
                        return;
                    }
                    this.frontier.push(child);

                    this.problem.grid.highlightFrontierState(child.state.x, child.state.y);
                }
            }
        };

        // this is the function to expand the next node using breadth-first search
        this.expandNextNodeBFS = function () {
            var node = this.frontier.shift();
            this.explored.push(node.state);

            this.problem.grid.highlightExploredState(node.state.x, node.state.y);

            var actions = this.problem.actions(node.state);
            for (var i = 0; i < actions.length; i++) {
                var child = new ChildNode(this.problem, node, actions[i]);
                if (!this.inExplored(child.state) && !this.inFrontier(child.state)) {
                    if (this.problem.goalTest(child.state)) {
                        this.solution(child);
                        this.searching = false;
                        this.executing = true;
                        return;
                    }
                    this.frontier.push(child);

                    this.problem.grid.highlightFrontierState(child.state.x, child.state.y);
                }
            }
        };

        // this is the function to expand the next node using A* search
        this.expandNextNodeAS = function () {
            var index = this.getNearestToGoalIndex();
            var node = this.frontier[index];
            this.frontier.splice(index, 1);

            this.explored.push(node.state);

            this.problem.grid.highlightExploredState(node.state.x, node.state.y);

            var actions = this.problem.actions(node.state);
            for (var i = 0; i < actions.length; i++) {
                var child = new ChildNode(this.problem, node, actions[i]);
                if (!this.inExplored(child.state) && !this.inFrontier(child.state)) {
                    if (this.problem.goalTest(child.state)) {
                        this.solution(child);
                        this.searching = false;
                        this.executing = true;
                        return;
                    }
                    this.frontier.push(child);

                    this.problem.grid.highlightFrontierState(child.state.x, child.state.y);
                }
            }
        };

        // Initializing the agent object

        this.problem = problem;
        this.seq = [];
        this.searching = true;
        this.executing = false;
        this.frontier = [];

        var node = {
            state: this.problem.initialState,
            pathCost: 0
        }
        this.frontier.push(node);

        if (this.problem.goalTest(node.state)) {
            this.solution(node);
            this.frontier.pop();
            this.searching = false;
        }

        this.explored = [];
    }
});<|endoftext|>


<commit_before>import {
  Component, TextPropertyEditor, isArrayEqual
} from 'substance'

import { getSyntaxTokens } from '../engine/expressionHelpers'

export default
class CodeEditor extends Component {

  render($$) {
    let el = $$('div').addClass('sc-code-editor')
    // the source code
    const path = this.props.path
    const commands = this.props.commands
    const excludedCommands = this.props.excludedCommands
    const markers = this._getMarkers()
    let content = $$(TextPropertyEditor, {
      // TextPropertyEditor props
      name: this.props.name,
      path,
      withoutBreak: this.props.multiline,
      multiLine: this.props.multiline,
      // Surface props
      commands,
      excludedCommands,
      markers,
      handleTab: false
    }).ref('contentEditor')
      // EXPERIMENTAL: adding 2 spaces if at begin of line
      .on('tab', this._onTabKey)
      .on('escape', this._onEscapeKey)
    content.addClass('se-content')
    el.append(content)
    return el
  }

  _getMarkers() {
    const path = this.props.path
    return getSyntaxTokens(path, this.props.tokens)
  }

  _onEscapeKey() {
    this.send('escape')
  }

  _onTabKey() {
    const editorSession = this.context.editorSession
    const head = this._getCurrentLineHead()
    // console.log('head', head)
    if (/^\s*$/.exec(head)) {
      editorSession.transaction((tx) => {
        tx.insertText('  ')
      })
    }
  }

  _insertNewLine() {
    const editorSession = this.context.editorSession
    const indent = this._getCurrentIndent() || ''
    editorSession.transaction((tx) => {
      tx.insertText('\n' + indent)
    })
  }

  _getCurrentIndent() {
    const line = this._getCurrentLineHead()
    const match = /^(\s+)/.exec(line)
    if (match) {
      return match[1]
    }
  }

  _getCurrentLineHead() {
    const editorSession = this.context.editorSession
    const doc = editorSession.getDocument()
    const sel = editorSession.getSelection()
    if (!sel || !sel.isPropertySelection() || !isArrayEqual(sel.path, this.props.path)) {
      return
    }
    const offset = sel.start.offset
    const exprStr = doc.get(this.props.path)
    const head = exprStr.slice(0, offset)
    const lastNL = Math.max(0, head.lastIndexOf('\n'))
    return head.slice(lastNL+1)
  }
}
<commit_msg>Fix CodeEditor.<commit_after>import {
  Component, TextPropertyEditor, isArrayEqual
} from 'substance'

import { getSyntaxTokens } from '../engine/expressionHelpers'

export default
class CodeEditor extends Component {

  render($$) {
    let el = $$('div').addClass('sc-code-editor')
    // the source code
    const path = this.props.path
    const commands = this.props.commands
    const excludedCommands = this.props.excludedCommands
    const markers = this._getMarkers()
    let content = $$(TextPropertyEditor, {
      // TextPropertyEditor props
      name: this.props.name,
      path,
      withoutBreak: this.props.multiline,
      multiLine: this.props.multiline,
      // Surface props
      commands,
      excludedCommands,
      markers,
      handleTab: false
    }).ref('contentEditor')
      // EXPERIMENTAL: adding 2 spaces if at begin of line
      .on('tab', this._onTabKey)
    content.addClass('se-content')
    el.append(content)
    return el
  }

  _getMarkers() {
    const path = this.props.path
    return getSyntaxTokens(path, this.props.tokens)
  }

  _onTabKey() {
    const editorSession = this.context.editorSession
    const head = this._getCurrentLineHead()
    // console.log('head', head)
    if (/^\s*$/.exec(head)) {
      editorSession.transaction((tx) => {
        tx.insertText('  ')
      })
    }
  }

  _insertNewLine() {
    const editorSession = this.context.editorSession
    const indent = this._getCurrentIndent() || ''
    editorSession.transaction((tx) => {
      tx.insertText('\n' + indent)
    })
  }

  _getCurrentIndent() {
    const line = this._getCurrentLineHead()
    const match = /^(\s+)/.exec(line)
    if (match) {
      return match[1]
    }
  }

  _getCurrentLineHead() {
    const editorSession = this.context.editorSession
    const doc = editorSession.getDocument()
    const sel = editorSession.getSelection()
    if (!sel || !sel.isPropertySelection() || !isArrayEqual(sel.path, this.props.path)) {
      return
    }
    const offset = sel.start.offset
    const exprStr = doc.get(this.props.path)
    const head = exprStr.slice(0, offset)
    const lastNL = Math.max(0, head.lastIndexOf('\n'))
    return head.slice(lastNL+1)
  }
}
<|endoftext|>


<commit_before>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var h = document.createElement("H5");
var t = document.createTextNode("Formulario para obtener información sobre complementos en GitHub");
h.appendChild(t);
aside.appendChild(h);
var form = document.createElement("FORM");
form.setAttribute("role", "form");
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "repo");
t = document.createTextNode("cuenta/repositorio de GitHub");
label.appendChild(t);
var input = document.createElement("INPUT");
input.setAttribute("type", "text");
input.setAttribute("id", "repo");
input.setAttribute("name", "repo");
input.setAttribute("placeholder", "Ejemplo: nvdaes/emoticons");
label.appendChild(input);
var submit = document.createElement("INPUT");
submit.setAttribute("id", "submit");
submit.setAttribute("type", "button");
submit.setAttribute("value", "Consultar descargas de última versión");
p.appendChild(label);
form.appendChild(p);
form.appendChild(submit);
aside.appendChild(form);

$(document).ready(function () {
	$("#submit").click(function () {
		$.getJSON("https://api.github.com/repos/" + input.value + "/releases/latest", function(json) {
			if (json == null) {
				alert("Repositorio no encontrado");
			} else {
				var assetName = json.assets[0].name;
				var downloadCount = json.assets[0].download_count;
				alert(assetName + " " + downloadCount);
			}
		});
	});
});

<commit_msg>Use try to handle errors<commit_after>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var h = document.createElement("H5");
var t = document.createTextNode("Formulario para obtener información sobre complementos en GitHub");
h.appendChild(t);
aside.appendChild(h);
var form = document.createElement("FORM");
form.setAttribute("role", "form");
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "repo");
t = document.createTextNode("cuenta/repositorio de GitHub");
label.appendChild(t);
var input = document.createElement("INPUT");
input.setAttribute("type", "text");
input.setAttribute("id", "repo");
input.setAttribute("name", "repo");
input.setAttribute("placeholder", "Ejemplo: nvdaes/emoticons");
label.appendChild(input);
var submit = document.createElement("INPUT");
submit.setAttribute("id", "submit");
submit.setAttribute("type", "button");
submit.setAttribute("value", "Consultar descargas de última versión");
p.appendChild(label);
form.appendChild(p);
form.appendChild(submit);
aside.appendChild(form);

$(document).ready(function () {
	$("#submit").click(function () {
		$.getJSON("https://api.github.com/repos/" + input.value + "/releases/latest", function(json) {
			try {
				var assetName = json.assets[0].name;
				var downloadCount = json.assets[0].download_count;
				alert(assetName + " " + downloadCount);
			}
			catch (err) {
				alert(err.message);
				}
		});
	});
});

<|endoftext|>


<commit_before>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var h = document.createElement("H5");
var t = document.createTextNode("Formulario para obtener información sobre complementos en GitHub");
h.appendChild(t);
aside.appendChild(h);
var form = document.createElement("FORM");
form.setAttribute("role", "form");
// First form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "repo");
t = document.createTextNode("cuenta/repositorio de GitHub (requerido)");
label.appendChild(t);
var inputRepo = document.createElement("INPUT");
inputRepo.setAttribute("type", "text");
inputRepo.setAttribute("id", "repo");
inputRepo.setAttribute("name", "repo");
inputRepo.setAttribute("placeholder", "Ejemplo: nvdaes/emoticons");
label.appendChild(inputRepo);
p.appendChild(label);
form.appendChild(p);
// Second form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "version");
t = document.createTextNode("Versión (opcional). Por defecto se usará la última estable:");
label.appendChild(t);
var inputVersion = document.createElement("INPUT");
inputVersion.setAttribute("type", "text");
inputVersion.setAttribute("id", "version");
inputVersion.setAttribute("name", "version");
inputVersion.setAttribute("placeholder", "Ejemplo: 7.0-dev");
label.appendChild(inputVersion);
p.appendChild(label);
form.appendChild(p);

var p = document.createElement("P");
var submitCount = document.createElement("INPUT");
submitCount.setAttribute("id", "submitCount");
submitCount.setAttribute("type", "button");
submitCount.setAttribute("value", "Consultar número de descargas");
p.appendChild(submitCount);
form.appendChild(p);

var p = document.createElement("P");
var submitId = document.createElement("INPUT");
submitId.setAttribute("id", "submitId");
submitId.setAttribute("type", "button");
submitId.setAttribute("value", "Consultar lista de versiones");
p.appendChild(submitId);
form.appendChild(p);

aside.appendChild(form);

$(document).ready(function () {
	$("#submitCount").click(function () {
		var version;
		if ($.trim(inputVersion.value).length === 0) {
			version = "latest";
		} else {
			version = inputVersion.value;
		}
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases/" + version, function(json) {
			var assetName = json.assets[0].name;
			var downloadCount = json.assets[0].download_count;
			alert(assetName + " - " + downloadCount);
		});
	});

	$("#submitId").click(function () {
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases", function(json) {
			$.each(json, function(i, field){
				message + = field.id.toString();
			}
		alert(message);
			//alert (json[0].id.toString());
		});
	});
});
<commit_msg>Fix function<commit_after>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var h = document.createElement("H5");
var t = document.createTextNode("Formulario para obtener información sobre complementos en GitHub");
h.appendChild(t);
aside.appendChild(h);
var form = document.createElement("FORM");
form.setAttribute("role", "form");
// First form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "repo");
t = document.createTextNode("cuenta/repositorio de GitHub (requerido)");
label.appendChild(t);
var inputRepo = document.createElement("INPUT");
inputRepo.setAttribute("type", "text");
inputRepo.setAttribute("id", "repo");
inputRepo.setAttribute("name", "repo");
inputRepo.setAttribute("placeholder", "Ejemplo: nvdaes/emoticons");
label.appendChild(inputRepo);
p.appendChild(label);
form.appendChild(p);
// Second form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "version");
t = document.createTextNode("Versión (opcional). Por defecto se usará la última estable:");
label.appendChild(t);
var inputVersion = document.createElement("INPUT");
inputVersion.setAttribute("type", "text");
inputVersion.setAttribute("id", "version");
inputVersion.setAttribute("name", "version");
inputVersion.setAttribute("placeholder", "Ejemplo: 7.0-dev");
label.appendChild(inputVersion);
p.appendChild(label);
form.appendChild(p);

var p = document.createElement("P");
var submitCount = document.createElement("INPUT");
submitCount.setAttribute("id", "submitCount");
submitCount.setAttribute("type", "button");
submitCount.setAttribute("value", "Consultar número de descargas");
p.appendChild(submitCount);
form.appendChild(p);

var p = document.createElement("P");
var submitId = document.createElement("INPUT");
submitId.setAttribute("id", "submitId");
submitId.setAttribute("type", "button");
submitId.setAttribute("value", "Consultar lista de versiones");
p.appendChild(submitId);
form.appendChild(p);

aside.appendChild(form);

$(document).ready(function () {
	$("#submitCount").click(function () {
		var version;
		if ($.trim(inputVersion.value).length === 0) {
			version = "latest";
		} else {
			version = inputVersion.value;
		}
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases/" + version, function(json) {
			var assetName = json.assets[0].name;
			var downloadCount = json.assets[0].download_count;
			alert(assetName + " - " + downloadCount);
		});
	});

	$("#submitId").click(function () {
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases", function(json) {
			var message = "";
			$.each(json, function(i, field){
				message + = field.id.toString();
			}
			alert(message);
			//alert (json[0].id.toString());
		});
	});
});
<|endoftext|>


<commit_before>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var h = document.createElement("H5");
var t = document.createTextNode("Formulario para obtener información sobre complementos en GitHub");
h.appendChild(t);
aside.appendChild(h);
var form = document.createElement("FORM");
form.setAttribute("role", "form");
// First form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "repo");
t = document.createTextNode("cuenta/repositorio de GitHub (requerido)");
label.appendChild(t);
var inputRepo = document.createElement("INPUT");
inputRepo.setAttribute("type", "text");
inputRepo.setAttribute("id", "repo");
inputRepo.setAttribute("name", "repo");
inputRepo.setAttribute("placeholder", "Ejemplo: nvdaes/emoticons");
label.appendChild(inputRepo);
p.appendChild(label);
form.appendChild(p);
// Second form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "version");
t = document.createTextNode("Versión (opcional). Por defecto se usará la última estable:");
label.appendChild(t);
var inputVersion = document.createElement("INPUT");
inputVersion.setAttribute("type", "text");
inputVersion.setAttribute("id", "version");
inputVersion.setAttribute("name", "version");
inputVersion.setAttribute("placeholder", "Ejemplo: 7.0-dev");
label.appendChild(inputVersion);
p.appendChild(label);
form.appendChild(p);

var p = document.createElement("P");
var submitCount = document.createElement("INPUT");
submitCount.setAttribute("id", "submitCount");
submitCount.setAttribute("type", "button");
submitCount.setAttribute("value", "Consultar número de descargas");
p.appendChild(submitCount);
form.appendChild(p);

var p = document.createElement("P");
var submitId = document.createElement("INPUT");
submitId.setAttribute("id", "submitId");
submitId.setAttribute("type", "button");
submitId.setAttribute("value", "Consultar lista de versiones");
p.appendChild(submitId);
form.appendChild(p);

aside.appendChild(form);

$(document).ready(function () {
	$("#submitCount").click(function () {
		var version;
		if ($.trim(inputVersion.value).length === 0) {
			version = "latest";
		} else {
			version = inputVersion.value;
		}
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases/" + version, function(json) {
			var assetName = json.assets[0].name;
			var downloadCount = json.assets[0].download_count;
			alert(assetName + " - " + downloadCount);
		});
	});

	$("#submitId").click(function () {
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases", function(json) {
			alert (json[0].id.toString());
		});
	});
});
<commit_msg>Test with each<commit_after>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var h = document.createElement("H5");
var t = document.createTextNode("Formulario para obtener información sobre complementos en GitHub");
h.appendChild(t);
aside.appendChild(h);
var form = document.createElement("FORM");
form.setAttribute("role", "form");
// First form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "repo");
t = document.createTextNode("cuenta/repositorio de GitHub (requerido)");
label.appendChild(t);
var inputRepo = document.createElement("INPUT");
inputRepo.setAttribute("type", "text");
inputRepo.setAttribute("id", "repo");
inputRepo.setAttribute("name", "repo");
inputRepo.setAttribute("placeholder", "Ejemplo: nvdaes/emoticons");
label.appendChild(inputRepo);
p.appendChild(label);
form.appendChild(p);
// Second form field
var p = document.createElement("P");
var label = document.createElement("LABEL");
label.setAttribute("for", "version");
t = document.createTextNode("Versión (opcional). Por defecto se usará la última estable:");
label.appendChild(t);
var inputVersion = document.createElement("INPUT");
inputVersion.setAttribute("type", "text");
inputVersion.setAttribute("id", "version");
inputVersion.setAttribute("name", "version");
inputVersion.setAttribute("placeholder", "Ejemplo: 7.0-dev");
label.appendChild(inputVersion);
p.appendChild(label);
form.appendChild(p);

var p = document.createElement("P");
var submitCount = document.createElement("INPUT");
submitCount.setAttribute("id", "submitCount");
submitCount.setAttribute("type", "button");
submitCount.setAttribute("value", "Consultar número de descargas");
p.appendChild(submitCount);
form.appendChild(p);

var p = document.createElement("P");
var submitId = document.createElement("INPUT");
submitId.setAttribute("id", "submitId");
submitId.setAttribute("type", "button");
submitId.setAttribute("value", "Consultar lista de versiones");
p.appendChild(submitId);
form.appendChild(p);

aside.appendChild(form);

$(document).ready(function () {
	$("#submitCount").click(function () {
		var version;
		if ($.trim(inputVersion.value).length === 0) {
			version = "latest";
		} else {
			version = inputVersion.value;
		}
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases/" + version, function(json) {
			var assetName = json.assets[0].name;
			var downloadCount = json.assets[0].download_count;
			alert(assetName + " - " + downloadCount);
		});
	});

	$("#submitId").click(function () {
		$.getJSON("https://api.github.com/repos/" + inputRepo.value + "/releases", function(json) {
			$.each(result, function(i, field){
				message + = field.id.toString();
			}
		alert(message);
			//alert (json[0].id.toString());
		});
	});
});
<|endoftext|>


<commit_before>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var button = document.createElement("BUTTON");
button.setAttribute("id", "addonsButton");
var buttonText = document.createTextNode("Información sobre complementos de nvdaes");
button.appendChild(buttonText);
aside.appendChild(button);

addons = [
	"clipContentsDesigner",
	"emoticons",
	"eMule",
	"placeMarkers",
	"readFeeds",
	"reportSymbols",
]

var addonsLength = addons.length;

$(document).ready(function () {
	$("#addonsButton").click(function () {
		for (var i = 0; i < addonsLength; i++) {
			var details = document.createElement("DETAILS");
			var summary = document.createElement("SUMMARY");
			var t = document.createTextNode(addons[i]);
			summary.appendChild(t);
			details.appendChild(summary);
			$.getJSON("https://api.github.com/repos/nvdaes/" + addons[i] + "/releases/latest", function(json) {
				var t = document.createTextNode(json.name);
				this.aside.appendChild(t);
			});
			aside.appendChild(details);
		}
	});
});
<commit_msg>Update script<commit_after>document.getElementById("ayuda").setAttribute("aria-current", "page");

var aside = document.getElementById("complementario");
var button = document.createElement("BUTTON");
button.setAttribute("id", "addonsButton");
var buttonText = document.createTextNode("Información sobre complementos de nvdaes");
button.appendChild(buttonText);
aside.appendChild(button);

addons = [
	"clipContentsDesigner",
	"emoticons",
	"eMule",
	"placeMarkers",
	"readFeeds",
	"reportSymbols",
]

var addonsLength = addons.length;

$(document).ready(function () {
	$("#addonsButton").click(function () {
		for (var i = 0; i < addonsLength; i++) {
			var details = document.createElement("DETAILS");
			var summary = document.createElement("SUMMARY");
			var t = document.createTextNode(addons[i]);
			summary.appendChild(t);
			// details.appendChild(summary);
			$.getJSON("https://api.github.com/repos/nvdaes/" + addons[i] + "/releases/latest", function(json) {
				var t = document.createTextNode(json.name);
				this.details.appendChild(this.summary);
			});
			aside.appendChild(details);
		}
	});
});
<|endoftext|>


<commit_before>import * as React from 'react/addons'
import * as Reflux from 'reflux'
import * as _ from 'lodash'
import mapStore from '../stores/mapStore'

let RenderedMap = React.createClass({
	mixins: [Reflux.listenTo(mapStore, 'onMapChanged', 'onMapChanged')],
	onMapChanged(maps) {
		this.setState({maps})
		this.findMap(this.props.mapId)
	},
	findMap(mapId) {
		if (mapId instanceof Parse.Object)
			mapId = mapId.id

		let map = _.find(this.state.maps, (map) => map.id === mapId)
		console.log(this.state.maps, mapId, map)
		if (map) {
			this.setState({
				map: {
					width: map.get('width'),
					height: map.get('height'),
					countries: map.get('countries'),
					spaces: map.get('spaces'),
				}
			})
		}
	},
	componentWillReceiveProps(nextProps) {
		this.findMap(nextProps.mapId)
	},
	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	},
	getInitialState() {
		return {
			maps: [],
			map: {
				spaces: [],
				countries: [],
				width: 0,
				height: 0,
			},
		}
	},
	render() {
		let spaces = React.createElement('defs', null,
			_.map(this.state.map.spaces, (space) => {
				// todo: clean up this logic, if possible
				let vectorPath = space.path;

				let paths = [];
				let cantUsePath = false;
				let args = {
					className: React.addons.classSet({
						space: true,
						'supply-center': Boolean(space.supply),
					}) + ' space-type-' + space.type,
					id: 'space-' + space.id,
					space: space,
					key: space.id,
				}

				if ( typeof vectorPath === 'number') {
					// it's referencing another path, so we use a <use>.
					cantUsePath = true;
					args.dangerouslySetInnerHTML = {__html: `<use xlink:href="#space-${vectorPath}" />`}
				}
				else if (vectorPath instanceof Array) {
					// it has multiple paths; probably islands.
					paths = _.map(vectorPath, (path, index) => React.createElement('path', {d: path, key: index}))
				}
				else {
					// it has only a single path
					paths = [React.createElement('path', {d: vectorPath, key: 0})]
				}

				return React.createElement('g', args, cantUsePath ? null : paths)
			}))

		let countries = _.map(this.state.map.countries, (country) =>
			React.createElement('g',
				{
					className: 'country',
					id: country.name.toLowerCase(),
					key: country.name,
					fill: country.vacantColor,
					country: country,
				},
				_.map(country.startSpaces, (spaceId) => {
					return React.createElement('g', {
						key: country.name + '-' + spaceId,
						id: country.name + '-' + spaceId,
						dangerouslySetInnerHTML: {__html: `<use xlink:href="#space-${spaceId}" />`},
					})
				}))
		)

		// todo: perhaps find a better way to render the spaces
		let occupiedSpaces = _.union(
			_.flatten(this.state.map.countries, 'startSpaces'),
			_.compact(_.flatten(_.map(this.state.map.countries, (country) => {
				return _.map(country.startSpaces, (spaceId) => {
					return _.find(this.state.map.spaces, { 'id': spaceId }).territory
				})
		}))))

		let emptySpaces = _.reject(this.state.map.spaces, (space) => _.contains(occupiedSpaces, space.id))

		let otherSpaces = React.createElement('g',
			{
				className: 'empty country',
				id: 'vacant',
				key: 'vacant',
				country: null,
			},
			_.map(emptySpaces, (space) => {
				return React.createElement('g',
					{
						id: 'empty-' + space.id,
						key: 'empty-' + space.id,
						dangerouslySetInnerHTML: {__html: `<use xlink:href="#space-${space.id}" />`},
					}
				)
			}))

		return React.createElement('svg',
			{
				className: 'map',
				style: {
					width: this.state.map.width + 'px',
					height: this.state.map.height + 'px',
				},
			},
			spaces,
			countries,
			otherSpaces)
	},
})

export default RenderedMap
<commit_msg>Remove an extra space<commit_after>import * as React from 'react/addons'
import * as Reflux from 'reflux'
import * as _ from 'lodash'
import mapStore from '../stores/mapStore'

let RenderedMap = React.createClass({
	mixins: [Reflux.listenTo(mapStore, 'onMapChanged', 'onMapChanged')],
	onMapChanged(maps) {
		this.setState({maps})
		this.findMap(this.props.mapId)
	},
	findMap(mapId) {
		if (mapId instanceof Parse.Object)
			mapId = mapId.id

		let map = _.find(this.state.maps, (map) => map.id === mapId)
		console.log(this.state.maps, mapId, map)
		if (map) {
			this.setState({
				map: {
					width: map.get('width'),
					height: map.get('height'),
					countries: map.get('countries'),
					spaces: map.get('spaces'),
				}
			})
		}
	},
	componentWillReceiveProps(nextProps) {
		this.findMap(nextProps.mapId)
	},
	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	},
	getInitialState() {
		return {
			maps: [],
			map: {
				spaces: [],
				countries: [],
				width: 0,
				height: 0,
			},
		}
	},
	render() {
		let spaces = React.createElement('defs', null,
			_.map(this.state.map.spaces, (space) => {
				// todo: clean up this logic, if possible
				let vectorPath = space.path;

				let paths = [];
				let cantUsePath = false;
				let args = {
					className: React.addons.classSet({
						space: true,
						'supply-center': Boolean(space.supply),
					}) + ' space-type-' + space.type,
					id: 'space-' + space.id,
					space: space,
					key: space.id,
				}

				if ( typeof vectorPath === 'number') {
					// it's referencing another path, so we use a <use>.
					cantUsePath = true;
					args.dangerouslySetInnerHTML = {__html: `<use xlink:href="#space-${vectorPath}" />`}
				}
				else if (vectorPath instanceof Array) {
					// it has multiple paths; probably islands.
					paths = _.map(vectorPath, (path, index) => React.createElement('path', {d: path, key: index}))
				}
				else {
					// it has only a single path
					paths = [React.createElement('path', {d: vectorPath, key: 0})]
				}

				return React.createElement('g', args, cantUsePath ? null : paths)
			}))

		let countries = _.map(this.state.map.countries, (country) =>
			React.createElement('g',
				{
					className: 'country',
					id: country.name.toLowerCase(),
					key: country.name,
					fill: country.vacantColor,
					country: country,
				},
				_.map(country.startSpaces, (spaceId) => {
					return React.createElement('g', {
						key: country.name + '-' + spaceId,
						id: country.name + '-' + spaceId,
						dangerouslySetInnerHTML: {__html: `<use xlink:href="#space-${spaceId}" />`},
					})
				}))
		)

		// todo: perhaps find a better way to render the spaces
		let occupiedSpaces = _.union(
			_.flatten(this.state.map.countries, 'startSpaces'),
			_.compact(_.flatten(_.map(this.state.map.countries, (country) => {
				return _.map(country.startSpaces, (spaceId) => {
					return _.find(this.state.map.spaces, { 'id': spaceId }).territory
				})
		}))))

		let emptySpaces = _.reject(this.state.map.spaces, (space) => _.contains(occupiedSpaces, space.id))

		let otherSpaces = React.createElement('g',
			{
				className: 'empty country',
				id: 'vacant',
				key: 'vacant',
				country: null,
			},
			_.map(emptySpaces, (space) => {
				return React.createElement('g',
					{
						id: 'empty-' + space.id,
						key: 'empty-' + space.id,
						dangerouslySetInnerHTML: {__html: `<use xlink:href="#space-${space.id}" />`},
					}
				)
			}))

		return React.createElement('svg',
			{
				className: 'map',
				style: {
					width: this.state.map.width + 'px',
					height: this.state.map.height + 'px',
				},
			},
			spaces,
			countries,
			otherSpaces)
	},
})

export default RenderedMap
<|endoftext|>


<commit_before>let $ = selector => document.querySelector(selector);

function modify({ type, title, year, info }) {
    let object = { title, year, ...info };

    $('#example').setAttribute('type', type);

    $('#movie').removeAttribute('active');
    $('#tv-show').removeAttribute('active');

    $(`#${ type }`).setAttribute('active', true);

    let element;
    for(let key in object)
        if(element = $(`#${ key }`))
            element.innerHTML = object[key] || "";

    $('#body').setAttribute('style', `background-image: url("${ type }.poster.jpg")`);
    $('#poster').setAttribute('src', `${ type }.poster.jpg`);

    let { imdb, tmdb, tvdb } = object,
        ids = { imdb, tmdb, tvdb };

    for(let id in ids)
        $(`#${ id }`).setAttribute('href', (
            ids[id]?
                id == 'imdb'?
                    `https://www.imdb.com/videoembed/${ object[id.toUpperCase()] }/`:
                id == 'tmdb'?
                    `https://www.youtube.com/embed/${ object[id.toUpperCase()] }`:
                `https://www.youtube.com/embed/${ object[id.toUpperCase()] }`:
            'blank.html'
        ));
}

function as(type) {
    open('blank.html', 'frame');

    return modify({
        "movie": {
            'type':  "movie",
            'title': "Being John Malkovich",
            'year':  1999,
            'info': {
                'rating':       "R",
                'runtime':      "1:53",
                'genre':        "Comedy, Drama, Fantasy",
                'release-date': "December 3, 1999 (USA)",

                'imdb': "tt0120601",
                'IMDB': "vi3568894233",
                'tmdb': 492,
                'TMDB': "HdVvjvW_OEo",
                'tvdb': null,
                'TVDB': null,
            },
        },

        "tv-show": {
            'type': "tv-show",
            'title': "Love, Death & Robots",
            'year':  2019,
            'info': {
                'rating':       "TV-MA",
                'runtime':      "0:15",
                'genre':        "Animation, Comedy, Fantasy, Horror, Science-Fiction",
                'release-date': "May 15, 2019 (USA)",

                'imdb': "tt9561862",
                'IMDB': "vi1035648281",
                'tmdb': 86831,
                'TMDB': "wUFwunMKa4E",
                'tvdb': 357888,
                'TVDB': "wUFwunMKa4E",
            },
        },
    }[type]);
}

document.querySelectorAll('#movie, #tv-show').forEach(element => {
    element.onmouseup = event => {
        let self = event.target;

        as(self.id);
    };
});

document.querySelectorAll('[target="frame"]').forEach(element => {
    let body = document.body,
        frame = $('#frame'),
        loading = $('#loading');

    element.onmouseup = event =>
        loading.setAttribute('loading', true);

    frame.onload = frame.onerror = event =>
        loading.setAttribute('loading', false);
});

document.body.onload = event => /#(movie|tv-show)/i.test(location.hash)? as(`${ location.hash.replace('#', '') }`): as('movie');
<commit_msg>Update index.js<commit_after>let $ = selector => document.querySelector(selector);

function modify({ type, title, year, info }) {
    let object = { title, year, ...info };

    $('#example').setAttribute('type', type);

    $('#movie').removeAttribute('active');
    $('#tv-show').removeAttribute('active');

    $(`#${ type }`).setAttribute('active', true);

    let element;
    for(let key in object)
        if(element = $(`#${ key }`))
            element.innerHTML = object[key] || "";

    $('#body').setAttribute('style', `background-image: url("${ type }.poster.jpg")`);
    $('#poster').setAttribute('src', `${ type }.poster.jpg`);

    let { imdb, tmdb, tvdb } = object,
        ids = { imdb, tmdb, tvdb };

    for(let id in ids)
        $(`#${ id }`).setAttribute('href', (
            ids[id]?
                id == 'imdb'?
                    `https://www.imdb.com/videoembed/${ object[id.toUpperCase()] }/`:
                id == 'tmdb'?
                    `https://www.youtube.com/embed/${ object[id.toUpperCase()] }`:
                `https://www.youtube.com/embed/${ object[id.toUpperCase()] }`:
            'blank.html'
        ));
}

function as(type) {
    open('blank.html', 'frame');

    return modify({
        "movie": {
            'type':  "movie",
            'title': "Being John Malkovich",
            'year':  1999,
            'info': {
                'rating':       "R",
                'runtime':      "1:53",
                'genre':        "Comedy, Drama, Fantasy",
                'release-date': "December 3, 1999 (USA)",

                'imdb': "tt0120601",
                'IMDB': "vi3568894233",
                'tmdb': 492,
                'TMDB': "HdVvjvW_OEo",
                'tvdb': null,
                'TVDB': null,
            },
        },

        "tv-show": {
            'type': "tv-show",
            'title': "Love, Death & Robots",
            'year':  2019,
            'info': {
                'rating':       "TV-MA",
                'runtime':      "0:15",
                'genre':        "Animation, Comedy, Fantasy, Horror, Science-Fiction",
                'release-date': "May 15, 2019 (USA)",

                'imdb': "tt9561862",
                'IMDB': "vi1035648281",
                'tmdb': 86831,
                'TMDB': "wUFwunMKa4E",
                'tvdb': 357888,
                'TVDB': "wUFwunMKa4E",
            },
        },
    }[type]);
}

document.querySelectorAll('#movie, #tv-show').forEach(element => {
    element.onmouseup = event => {
        let self = event.target;

        as(self.id);
    };
});

document.querySelectorAll('[target="frame"]').forEach(element => {
    let body = document.body,
        frame = $('#frame'),
        loading = $('#loading');

    element.onmouseup = event => {
        loading.setAttribute('loading', true);
        loading.removeAttribute('style');
    }

    frame.onload = frame.onerror = event => {
        loading.setAttribute('loading', false);
        setTimeout(() => loading.setAttribute('style', 'display:none'), 500);
    }
});

document.body.onload = event => /#(movie|tv-show)/i.test(location.hash)? as(`${ location.hash.replace('#', '') }`): as('movie');
<|endoftext|>


<commit_before>process.chdir(__dirname)

var fs = require('fs')
var sass = require('node-sass')
var CleanCSS = require('clean-css')
var pkg = require('../package.json')

sass.render({
  file: '../source/top-bar.scss',
  success: buildCSS
})

function buildCSS (result) {
  var style = new CleanCSS().minify(result.css).styles
  var banner = '/* ' + pkg.name + ' v' + pkg.version + ' - ' +
    getDate() + ' - ' + pkg.homepage + ' */\n'
  fs.writeFile('../top-bar.css', banner + style, function (err) {
    if (err) throw err
    console.log('built top-bar.css')
  })
}

function getDate () {
  var d = new Date()
  var dd = d.getDate()
  var mm = d.getMonth() + 1
  var yyyy = d.getFullYear()

  if (dd < 10) dd = '0' + dd
  if (mm < 10) mm = '0' + mm

  return mm + '/' + dd + '/' + ('' + yyyy).substr(2)
}
<commit_msg>:art: update build script for new node-sass<commit_after>process.chdir(__dirname)

var fs = require('fs')
var sass = require('node-sass')
var CleanCSS = require('clean-css')
var pkg = require('../package.json')

sass.render({
  file: '../source/top-bar.scss'
}, buildCSS)

function buildCSS (err, result) {
  if (err) {
    console.error(err)
    process.exit(1)
  }

  var style = new CleanCSS().minify(result.css).styles
  var banner = '/* ' + pkg.name + ' v' + pkg.version + ' - ' +
    getDate() + ' - ' + pkg.homepage + ' */\n'

  fs.writeFile('../top-bar.css', banner + style, function (err) {
    if (err) throw err
    console.log('built top-bar.css')
  })
}

function getDate () {
  var d = new Date()
  var dd = d.getDate()
  var mm = d.getMonth() + 1
  var yyyy = d.getFullYear()

  if (dd < 10) dd = '0' + dd
  if (mm < 10) mm = '0' + mm

  return mm + '/' + dd + '/' + ('' + yyyy).substr(2)
}
<|endoftext|>


<commit_before>const env = require('./env.js');
const fs = require('fs');
const shell = require('shelljs');

function exec(action) {
    const res = shell.exec(action);

    if (res.code !== 0) {
        shell.echo('Unable to build zookeeper library');
        shell.exit(1);
    }
}

const isAlreadyBuilt = fs.existsSync(`${env.BUILD}/lib/libzookeeper_st.la`);

if (isAlreadyBuilt) {
    shell.echo('Zookeeper has already been built');
    shell.exit(0);
    return;
}

shell.cd(`${env.ZK_DEPS}/src/c`);

exec('./configure --without-syncapi --enable-static --disable-shared --with-pic');
exec('make');

shell.cd(env.ROOT);

<commit_msg>fix: handle SunOS scenario<commit_after>const os = require('os');
const fs = require('fs');
const shell = require('shelljs');
const env = require('./env.js');

function exec(action) {
    const res = shell.exec(action);

    if (res.code !== 0) {
        shell.echo('Unable to build zookeeper library');
        shell.exit(1);
    }
}

function handleSunOS() {
    const uname = shell.exec('uname -v');

    if (uname.match('joyent_.*')) {
        const res = shell.exec(`pkgin list | grep zookeeper-client-${env.ZK_VERSION}`);

        if (res.code !== 0) {
            shell.echo('You must install zookeeper before installing this module. Try:');
            shell.echo(`pkgin install zookeeper-client-${env.ZK_VERSION}`);
        }
    }
}

if (os.platform() === 'SunOS') {
    handleSunOS();
    return;
}

const isAlreadyBuilt = fs.existsSync(`${env.BUILD}/lib/libzookeeper_st.la`);

if (isAlreadyBuilt) {
    shell.echo('Zookeeper has already been built');
    shell.exit(0);
    return;
}

shell.cd(`${env.ZK_DEPS}/src/c`);

exec('./configure --without-syncapi --enable-static --disable-shared --with-pic');
exec('make');

shell.cd(env.ROOT);

<|endoftext|>