<commit_before>'use strict';
/**
 * A class representation of the BSON RegExp type.
 *
 * @class
 * @return {BSONRegExp} A MinKey instance
 */
function BSONRegExp(pattern, options) {
  if (!(this instanceof BSONRegExp)) return new BSONRegExp();

  // Execute
  this._bsontype = 'BSONRegExp';
  this.pattern = pattern || '';
  this.options = options || '';

  // Validate options
  for (var i = 0; i < this.options.length; i++) {
    if (
      !(
        this.options[i] === 'i' ||
        this.options[i] === 'm' ||
        this.options[i] === 'x' ||
        this.options[i] === 'l' ||
        this.options[i] === 's' ||
        this.options[i] === 'u'
      )
    ) {
      throw new Error('the regular expression options [' + this.options[i] + '] is not supported');
    }
  }
}

module.exports = BSONRegExp;
module.exports.BSONRegExp = BSONRegExp;
<commit_msg>refactor(regexp): ensure options are alphabetically sorted<commit_after>'use strict';

function alphabetize(str) {
  return str
    .split('')
    .sort()
    .join('');
}

/**
 * A class representation of the BSON RegExp type.
 *
 * @class
 * @return {BSONRegExp} A MinKey instance
 */
function BSONRegExp(pattern, options) {
  if (!(this instanceof BSONRegExp)) return new BSONRegExp();

  // Execute
  this._bsontype = 'BSONRegExp';
  this.pattern = pattern || '';
  this.options = options ? alphabetize(options) : '';

  // Validate options
  for (var i = 0; i < this.options.length; i++) {
    if (
      !(
        this.options[i] === 'i' ||
        this.options[i] === 'm' ||
        this.options[i] === 'x' ||
        this.options[i] === 'l' ||
        this.options[i] === 's' ||
        this.options[i] === 'u'
      )
    ) {
      throw new Error('the regular expression options [' + this.options[i] + '] is not supported');
    }
  }
}

module.exports = BSONRegExp;
module.exports.BSONRegExp = BSONRegExp;
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var auth = require('./authentication.js');
var passport = require('passport');
var User = require('./user.js')
var fs = require('fs')
var Twit = require('twit')
var config = require('./oauth.js')

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'SECRETA' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

// serialize and deserialize
passport.serializeUser(function(user, done) {
  console.log('serializeUser: ' + user._id)
  done(null, user._id);
});
passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user){
    console.log(user)
    if(!err) done(null, user);
    else done(err, null)
  })
});

app.get('/', routes.index);
app.get('/users', user.list);
app.get('/drake', routes.drake);
app.get('/auth/twitter', passport.authenticate('twitter'));
app.get('/auth/twitter/callback',
        passport.authenticate('twitter', { successRedirect: '/drake',
                                           failureRedirect: '/' }));
// app.get('/auth/facebook', passport.authenticate('facebook'));
// app.get('/auth/facebook/callback',
//         passport.authenticate('facebook', { successRedirect: '/drake',
//                                             failureRedirect: '/',
//                                             scope: 'read_stream'
//                                             }));

var server = http.createServer(app).listen(app.get('port'), function() {
  console.log('Express server listening on port ' + app.get('port'));
});

//Twitter
var T = new Twit({
  consumer_key: config.twitter.consumerKey,
  consumer_secret: config.twitter.consumerSecret,
  access_token: config.twitter.accessToken,
  access_token_secret: config.twitter.accessTokenSecret
})

//Socket.io
var io = require('socket.io').listen(server);
//var stream = T.stream('statuses/sample')
var stream = T.stream('statuses/filter', { track: '#drakethetype', language: 'en' })

stream.on('tweet', function (tweet) {
  console.log('tweet captured via tweet');
})

io.sockets.on('connection', function (socket) {
  stream.on('tweet', function(tweet) {
    socket.emit('info', { tweet: tweet});
    console.log('socket tweeted');
  });
});
<commit_msg>tag filter update<commit_after>
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var auth = require('./authentication.js');
var passport = require('passport');
var User = require('./user.js')
var fs = require('fs')
var Twit = require('twit')
var config = require('./oauth.js')

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'SECRETA' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

// serialize and deserialize
passport.serializeUser(function(user, done) {
  console.log('serializeUser: ' + user._id)
  done(null, user._id);
});
passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user){
    console.log(user)
    if(!err) done(null, user);
    else done(err, null)
  })
});

app.get('/', routes.index);
app.get('/users', user.list);
app.get('/drake', routes.drake);
app.get('/auth/twitter', passport.authenticate('twitter'));
app.get('/auth/twitter/callback',
        passport.authenticate('twitter', { successRedirect: '/drake',
                                           failureRedirect: '/' }));
// app.get('/auth/facebook', passport.authenticate('facebook'));
// app.get('/auth/facebook/callback',
//         passport.authenticate('facebook', { successRedirect: '/drake',
//                                             failureRedirect: '/',
//                                             scope: 'read_stream'
//                                             }));

var server = http.createServer(app).listen(app.get('port'), function() {
  console.log('Express server listening on port ' + app.get('port'));
});

//Twitter
var T = new Twit({
  consumer_key: config.twitter.consumerKey,
  consumer_secret: config.twitter.consumerSecret,
  access_token: config.twitter.accessToken,
  access_token_secret: config.twitter.accessTokenSecret
})

//Socket.io
var io = require('socket.io').listen(server);
//var stream = T.stream('statuses/sample')
var stream = T.stream('statuses/filter', { track: '#drake', language: 'en' })

stream.on('tweet', function (tweet) {
  console.log('tweet captured via tweet');
})

io.sockets.on('connection', function (socket) {
  stream.on('tweet', function(tweet) {
    socket.emit('info', { tweet: tweet});
    console.log('socket tweeted');
  });
});
<|endoftext|>


<commit_before>import { createStore, combineReducers, applyMiddleware } from 'redux';
import Actions from '../constants/actions';
import Api from '../utils/api';
import { createAction } from '../utils/ActionCreator';
import Immutable from 'immutable';
import { Maybe } from 'monet';
import { routerReducer } from 'react-router-redux';
import { reducer as UserReducer } from './Users';
import createSagaMiddleware from 'redux-saga';
import mySaga from './sagas';

const sagaMiddleware = createSagaMiddleware();

const initialState = Immutable.Map({
    questions: Immutable.List(),
    answers: Immutable.List(),
    currentQuestion: Maybe.None(),
    user: Maybe.None(),
    users: Immutable.List(),
    gameType: 'freetext'
});

const getAnswer = (question, answerGiven) => Immutable.Map({
    questionId: question.id,
    answerGiven: answerGiven,
    correct: question.answer === answerGiven
});

const getCurrentQuestion = (state) => state.get('currentQuestion').map(n => state.get('questions').get(n));

const isLastQuestion = (questionNo, questions) => questionNo >= questions.size - 1;

const getNextQuestionNo = (questionNo, questions) =>
    questionNo.flatMap(n => isLastQuestion(n, questions) ? Maybe.None() : Maybe.Some(n + 1));

/* eslint-disable no-use-before-define */
function reducer(state = initialState, action) {
    switch (action.type) {
        case Actions.REQUEST_QUESTION_LIST:
            Api.json('/api/questions').then(questions => store.dispatch(createAction(Actions.QUESTION_LIST_LOADED, {questions})));
            return state;
        case Actions.QUESTION_LIST_LOADED:
            return state.set('questions', Immutable.List(action.questions));
        case Actions.QUESTION_ANSWERED:
            console.log('answered', action);
            return state
                .set('answers', state.get('answers').push(getAnswer(getCurrentQuestion(state).some(), action.answer)))
                .set('currentQuestion', getNextQuestionNo(state.get('currentQuestion'), state.get('questions')));
        case Actions.START_GAME:
            return state
                .set('answers', Immutable.List())
                .set('currentQuestion', Maybe.Some(0));
        case Actions.STOP_GAME:
            return state
                .set('currentQuestion', Maybe.None());
        case Actions.GAME_TYPE_CHANGED:
            return state
                .set('gameType', action.gameType);
        case Actions.REQUEST_USER_INFO:
            Api.json('/api/user').then(user =>
                store.dispatch(createAction(Actions.USER_CHANGED, {user: user.logged ? user : null}))
            );
            return state;
        case Actions.USER_CHANGED:
            if (action.user) {
                return state.set('user', Maybe.Some(action.user));
            } else {
                return state.set('user', Maybe.None());
            }
        case Actions.ADD_QUESTION:
            Api.post('/api/questions', {question: action.question, answer: action.answer})
                .then(() => store.dispatch(createAction(Actions.REQUEST_QUESTION_LIST)));
            return state;
        case Actions.DELETE_QUESTION:
            Api.del(`/api/questions/${action.id}`)
                .then(() => store.dispatch(createAction(Actions.REQUEST_QUESTION_LIST)));
            return state;
        default:
            return state;
    }
}

/* eslint-enable no-use-before-define */

const reducers = combineReducers({
    users: UserReducer,
    main: reducer,
    routing: routerReducer
});

const store = createStore(reducers, applyMiddleware(sagaMiddleware));

sagaMiddleware.run(mySaga);

export default store;

store.subscribe(() =>
  console.log('store change', store.getState())
);
<commit_msg>compare answers case-insensitively<commit_after>import { createStore, combineReducers, applyMiddleware } from 'redux';
import Actions from '../constants/actions';
import Api from '../utils/api';
import { createAction } from '../utils/ActionCreator';
import Immutable from 'immutable';
import { Maybe } from 'monet';
import { routerReducer } from 'react-router-redux';
import { reducer as UserReducer } from './Users';
import createSagaMiddleware from 'redux-saga';
import mySaga from './sagas';

const sagaMiddleware = createSagaMiddleware();

const initialState = Immutable.Map({
    questions: Immutable.List(),
    answers: Immutable.List(),
    currentQuestion: Maybe.None(),
    user: Maybe.None(),
    users: Immutable.List(),
    gameType: 'freetext'
});

const getAnswer = (question, answerGiven) => Immutable.Map({
    questionId: question.id,
    answerGiven: answerGiven,
    correct: question.answer.toLowerCase() === answerGiven.toLowerCase()
});

const getCurrentQuestion = (state) => state.get('currentQuestion').map(n => state.get('questions').get(n));

const isLastQuestion = (questionNo, questions) => questionNo >= questions.size - 1;

const getNextQuestionNo = (questionNo, questions) =>
    questionNo.flatMap(n => isLastQuestion(n, questions) ? Maybe.None() : Maybe.Some(n + 1));

/* eslint-disable no-use-before-define */
function reducer(state = initialState, action) {
    switch (action.type) {
        case Actions.REQUEST_QUESTION_LIST:
            Api.json('/api/questions').then(questions => store.dispatch(createAction(Actions.QUESTION_LIST_LOADED, {questions})));
            return state;
        case Actions.QUESTION_LIST_LOADED:
            return state.set('questions', Immutable.List(action.questions));
        case Actions.QUESTION_ANSWERED:
            console.log('answered', action);
            return state
                .set('answers', state.get('answers').push(getAnswer(getCurrentQuestion(state).some(), action.answer)))
                .set('currentQuestion', getNextQuestionNo(state.get('currentQuestion'), state.get('questions')));
        case Actions.START_GAME:
            return state
                .set('answers', Immutable.List())
                .set('currentQuestion', Maybe.Some(0));
        case Actions.STOP_GAME:
            return state
                .set('currentQuestion', Maybe.None());
        case Actions.GAME_TYPE_CHANGED:
            return state
                .set('gameType', action.gameType);
        case Actions.REQUEST_USER_INFO:
            Api.json('/api/user').then(user =>
                store.dispatch(createAction(Actions.USER_CHANGED, {user: user.logged ? user : null}))
            );
            return state;
        case Actions.USER_CHANGED:
            if (action.user) {
                return state.set('user', Maybe.Some(action.user));
            } else {
                return state.set('user', Maybe.None());
            }
        case Actions.ADD_QUESTION:
            Api.post('/api/questions', {question: action.question, answer: action.answer})
                .then(() => store.dispatch(createAction(Actions.REQUEST_QUESTION_LIST)));
            return state;
        case Actions.DELETE_QUESTION:
            Api.del(`/api/questions/${action.id}`)
                .then(() => store.dispatch(createAction(Actions.REQUEST_QUESTION_LIST)));
            return state;
        default:
            return state;
    }
}

/* eslint-enable no-use-before-define */

const reducers = combineReducers({
    users: UserReducer,
    main: reducer,
    routing: routerReducer
});

const store = createStore(reducers, applyMiddleware(sagaMiddleware));

sagaMiddleware.run(mySaga);

export default store;

store.subscribe(() =>
  console.log('store change', store.getState())
);
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var Builder = require('component-builder');
var jade = require('./jade');
var fs = require('fs');
var write = fs.writeFileSync;
var log = require('debug')('democracyos:build');

/**
 * Expose component
 * builder getter
 */

module.exports.createBuilder = createBuilder;

/**
 * Expose component
 * build middleware.
 */

module.exports.middleware = middleware;

/**
 * Creates a `Builder` instance
 * ready for build
 */

function createBuilder () {
  var builder = new Builder('.');
  builder.copyFiles();
  builder.addLookup('lib'); // TODO: shouldn't be necessary
  builder.copyAssetsTo('public');
  builder.use(jade);

  return builder;
}

/**
 * Express build middleware
 */

function middleware (req, res, next) {
  // Build only script and stylesheet
  if (!~['/app.js', '/app.css'].indexOf(req.path)) {
    return next();
  };

  log('Build %s.', req.path);

  var builder = createBuilder();
  builder.build(function(err, res){
    if (err) return next(err);

    log('Write script and stylesheet');
    write('public/app.js', res.require + res.js);
    write('public/app.css', res.css);
    next();
  });
};
<commit_msg>[build] - Update middleware build check<commit_after>/**
 * Module dependencies.
 */

var Builder = require('component-builder');
var jade = require('./jade');
var fs = require('fs');
var write = fs.writeFileSync;
var log = require('debug')('democracyos:build');

/**
 * Expose component
 * builder getter
 */

module.exports.createBuilder = createBuilder;

/**
 * Expose component
 * build middleware.
 */

module.exports.middleware = middleware;

/**
 * Creates a `Builder` instance
 * ready for build
 */

function createBuilder () {
  var builder = new Builder('.');
  builder.copyFiles();
  builder.addLookup('lib'); // TODO: shouldn't be necessary
  builder.copyAssetsTo('public');
  builder.use(jade);

  return builder;
}

/**
 * Express build middleware
 */

function middleware (req, res, next) {
  // Build only script and stylesheet
  if (!/app\.(js|css)/.test(req.path)) {
    return next();
  };

  log('Build %s.', req.path);

  var builder = createBuilder();
  builder.build(function(err, res){
    if (err) return next(err);

    log('Write script and stylesheet');
    write('public/app.js', res.require + res.js);
    write('public/app.css', res.css);
    next();
  });
};
<|endoftext|>


<commit_before>'use strict';
//TODO : add namespace for client mode !

var config = require('./config/config.json'),
  transporter = [],
  _ = require('lodash'),
  util = require('util'),
  mdns = require('mdns'),
  mkdirp = require('mkdirp'),
  ip = require('ip'),
  reconnected = false,
  reconnecting = false,
  currentServiceAddress = '',
  fs = require('fs'),
  pathHelper = require('path'),
  namespaces = [],
  host = '',
  connected = false,
  app;

var findNameSpace = function(path) {
  var directoryName = pathHelper.dirname(path);
  var nsp = directoryName.replace(config.watch.path, '');
  if (nsp.length > 0) {
    nsp = (nsp[0] === '/') ? nsp : '/' + nsp;
  } else {
    nsp = '/';
  }
  return nsp;
};
var initTransporter = function() {
  if ((config.transport === 'socket.io' || config.transport === 'both') && config.state === 'server') {
    console.log('Init socket.io server mode...');
    var io = require('socket.io')(app);
    if (config.state === 'server') {
      var ad = mdns.createAdvertisement(mdns.tcp('watchy'), config.port);
      ad.start();
    }
    //var io = require('socket.io').listen(config.socketIO.port);
    var socketIO = {
      name: 'socket.io',
      sender: io,
      socketConnections: [],
      send: function(path, action) {
        if (this.socketConnections.length < 0) {
          console.log('No socket open');
        } else {
          if (config.debug == true) {
            console.log('Sending ' + action + ' using socket.io');
          }
          _.each(this.socketConnections, function(socket) {
            socket.emit(action, {
              src: path
            });
          });
        }
      }
    };

    socketIO.sender.sockets.on('connection', function(socket) {
      socket.on('hello', function(data) {
        if (config.debug == true) {
          console.log('client connected');
          console.log(data);
        }
      });
      socketIO.socketConnections.push(socket);
    });
    transporter.push(socketIO);

  } else if ((config.transport === 'socket.io' || config.transport === 'both') && config.state === 'client') {

    // Could be improved
    if (config.client) {
      initSocketIOClient(config.client.address, config.client.port);
    }
    var handleError = function(error) {
      switch (error.errorCode) {
        case mdns.kDNSServiceErr_Unknown:
          console.warn(error);
          // setTimeout(createAdvertisement, 5000);
          break;
        default:
          // throw error;
          console.log(error);
      }
    };

    try {
      var serviceBrowser = mdns.createBrowser(mdns.tcp(config.servicelookup.name));
      serviceBrowser.on('serviceUp', function(service) {
        console.log("service up: ", service.fullname);
        var serviceHost = service.host.substr(0, service.host.length - 1),
          servicePort = service.port,
          querySearch = {
            host: serviceHost,
            port: servicePort
          };

        var exist = _.find(transporter, querySearch);
        //console.log('query:', util.inspect(querySearch,{depth:4}));
        //console.log('exist: ', exist);

        if (exist == undefined) {
          console.log(serviceHost + ':' + servicePort + ' does not exist, we initiate connection');
          initSocketIOClient(service.host.substr(0, service.host.length - 1), service.port)
          //currentServiceAddress = service.host.substr(0, service.host.length - 1);
        }

      });
      serviceBrowser.on('serviceDown', function(service) {
        console.log("service down: ", service.name);
      });
      serviceBrowser.start();
    } catch (ex) {
      handleError(ex);
    }
  }

  if (config.transport === 'osc' || config.transport === 'both') {
    var osc = require('node-osc'),
      OSCclient = new osc.Client(config.osc.address, config.osc.port),
      OSCSender = {
        name: 'osc',
        sender: OSCclient,
        send: function(path, action) {
          if (config.debug == true) {
            console.log('Sending ' + action + ' using osc');
          }
          this.sender.send(action, path);
        }
      }
    transporter.push(OSCSender);
  }
};

var initSocketIOClient = function(address, port) {
  console.log('Init socket.io client mode : ', address, port);
  var socket = require('socket.io-client')('http://' + address + ':' + port);
  socket.on('connect', function() {
    socket.emit('binding');
    host = ip.address();
    console.log(host);
    console.log('Connected to socket.io server: ', address, port);
    //TODO Should bind to a specific socket and not a global
    connected = true;
  })
    .on('disconnect', function() {
      console.log('We\'ve been disconnected');
    })
    .on('error', function() {
      console.log('error while connecting');
    })
    .on('reconnect', function(nbtry) {
      console.log('Successfull reconnect after ' + nbtry + ' trying.');
    })
    .on('reconnecting', function(nbtry) {
      if (!connected || config.multiConnect) {
        console.warn('Trying to reconnect to: ', address, port);
      }
    })
    .on('bind-nsp', function(nsp) {
      if (config.watch.path)
        if (_.contains(namespaces, nsp) === false) {
          mkdirp(config.watch.path + nsp, function(err) {
            if (err) {
              console.log('mkdirp: ' + err);
            }
          });
          namespaces.push(nsp);
      }
      console.log('Binding folder');
      var nspSocket = require('socket.io-client').connect('http://' + address + ':' + port + nsp);
      transporter.push(createSocketTransporter(nsp, nspSocket, address, port));
    });

  namespaces.push('/');
  transporter.push(createSocketTransporter('/', socket, address, port));
}

function createSocketTransporter(name, socket, host, port) {
  console.log("=============================================");
  console.log(socket.io.opts.host);
  console.log(socket.io.opts.port);
  var socketIO = {
    name: name,
    host: host,
    port: port,
    sender: socket,
    send: function(path, action) {
      if (config.debug == true) {
        console.log('Sending', action, 'using', name);
      }
      socket.emit(action, {
        src: path
      });
    }
  };
  return socketIO;
}

var initWatcher = function() {
  var chokidar = require('chokidar');

  var watcher = chokidar.watch(config.watch.path, {
    ignored: /[\/\\]\./,
    ignoreInitial: config.ignoreInitial,
    persistent: true
  });

  watcher
    .on('add', function(path) {

      if (path.indexOf('!sync') < 0) {
        //Add a slight delay to avoid error on get when too fast request are made.
        //See bug https://github.com/joyent/node/issues/4863
        //Data is not ready but someone is trying to access to ....

        setTimeout(function() {
          try {
            console.log(path);
            console.log(config.watch.path);
            var os = require("os");
            var watchPath = (config.watch.path.charAt(config.watch.path.length - 1) !== '/') ? config.watch.path : config.watch.path.substring(0, config.watch.path.length - 1);
            var relativePath = path.replace(watchPath, 'http://' + host + ":" + config.port);

            console.log(relativePath);

            /*var splitedPath = path.split('/');
            var nsp = splitedPath[splitedPath.length - 2];
            nsp = nsp === config.watch.path.split('/').pop() ? '' : nsp;*/
            var nsp = findNameSpace(path);
            var queryNamespace = nsp;
            //console.log(queryNamespace);
            var transporterSocketio = _.where(transporter, {
              name: queryNamespace
            });
            //console.log(transporter);
            if (transporterSocketio.length > 0) {
              _.each(transporterSocketio, function(senderIO, index) {
                senderIO.send(relativePath, 'image-saved');
              })
            } else {
              console.log('Sorry we can not send using socket.io, no transport available, check your network\nor your namspace...');
            }

            if (config.transport === 'osc' || config.transport === 'both') {
              var transporterOsc = _.where(transporter, {
                name: 'osc'
              });
              if (transporterOsc.length > 0) {
                transporterOsc[0].send(relativePath, 'new-file');
                transporterOsc[0].send(relativePath, 'new-image'); // legacy until june 2015
              } else {
                console.log('Sorry we can not send using OSC, no transport available');
              }
            }
          } catch (err) {
            console.log(err);
          }
        }, 500);
      } else {
        console.log('Chokidar - File', path, 'should be ignored');
      }
    })
    .on('addDir', function(path) {
      console.log('Chokidar - Directory', path, 'has been added');
    })
    .on('change', function(path, stats) {
      console.log('Chokidar - File', path, 'has been changed');
      if (stats) {
        console.log(stats);
      }
    })
    .on('unlink', function(path) {
      if (path.indexOf('!sync') < 0) {
        try {
          var relativePath = path.replace(config.watch.path, 'http://' + host + ":" + config.port);
          console.log(relativePath);

          /*var splitedPath = path.split('/');
          var nsp = splitedPath[splitedPath.length - 2];
          nsp = nsp === config.watch.path.split('/').pop() ? '' : nsp;*/
          var nsp = findNameSpace(path);

          var transporterSocketio = _.where(transporter, {
            name: '/' + nsp
          });
          if (transporterSocketio.length > 0) {
            //transporterSocketio[0].send(relativePath, 'image-deleted');
            _.each(transporterSocketio, function(senderIO, index) {
              senderIO.send(relativePath, 'image-deleted');
            })
          } else {
            console.log('Sorry we can not send using OSC, no transport available');
          }
          if (config.transport === 'osc' || config.transport === 'both') {
            var transporterOsc = _.where(transporter, {
              name: 'osc'
            });
            if (transporterOsc.length > 0) {
              transporterOsc[0].send(relativePath, 'image-deleted');
            } else {
              console.log('Sorry we can not send using OSC, no transport available');
            }

          }
        } catch (err) {
          console.log(err);
        }
      } else {
        console.log('File', path, 'should be ignored');
      }
      console.log('File', path, 'has been removed');
    })
    .on('unlinkDir', function(path) {
      console.log('Chokidar - Directory', path, 'has been removed');
    })
    .on('error', function(error) {
      console.error('Chokidar - Error happened', error);
    })
    .on('ready', function() {
      console.info('Chokidar - Initial scan complete. Ready for changes.');
    })
    .on('raw', function(event, path, details) {
      //console.info('Raw event info:', event, path, details)
    })
}

var initStatiqueServer = function() {

  var staticServer = require('node-static'),
    fileServer = new staticServer.Server(config.watch.path, {
      cache: 7200,
      serverInfo: "watchy/" + host
    });

  app = require('http').createServer(function(request, response) {
    request.addListener('end', function() {
      fileServer.serve(request, response).addListener('error', function(err) {
        util.error("Error serving " + request.url + " - " + err.message);
        response.end();
      });
    }).resume();
  });

  /* Does not provide meaning full message when error occur
  var Statique = require("statique");

  // Create *Le Statique* server
  var server = new Statique({
    root: config.watch.path
  }).setRoutes({
    "/": "/html/index.html"
  });

  // Create server
  app = require('http').createServer(server.serve);*/
}

console.log("Initializing...");

if (fs.existsSync(config.watch.path)) {
  initStatiqueServer();
  initTransporter();
  //TODO add some ready event to tell the watcher to init.
  initWatcher();
  console.log("...Initialized");
  // Output
  var os = require("os");
  host = os.hostname();
  if (os.platform() === 'linux') {
    var child_process = require("child_process");
    child_process.exec("hostname -f", function(err, stdout, stderr) {
      host = stdout.trim();
      //hot and dirty fix
      if (host.indexOf('local') < 0) {
        host += '.local'
      }
    });
  }
  require('dns').resolve('www.google.com', function(err) {
    if (err) {
      console.log('No internet connection, serving from localhost');
      host = '127.0.0.1';
    } else {
      console.log('All fine, we have access to internet');
    }
  });
  console.log("Listening on: " + config.port);
  app.listen(config.port)
    .on('error', function(err) {
      console.log(err);
      process.exit(1);
    });
} else {
  console.log('Sorry, we can\'t watch something that does not exist: ', config.watch.path);
}<commit_msg>adding file path information<commit_after>'use strict';
//TODO : add namespace for client mode !

var config = require('./config/config.json'),
  transporter = [],
  _ = require('lodash'),
  util = require('util'),
  mdns = require('mdns'),
  mkdirp = require('mkdirp'),
  ip = require('ip'),
  reconnected = false,
  reconnecting = false,
  currentServiceAddress = '',
  fs = require('fs'),
  pathHelper = require('path'),
  namespaces = [],
  host = '',
  connected = false,
  app;

var findNameSpace = function(path) {
  var directoryName = pathHelper.dirname(path);
  var nsp = directoryName.replace(config.watch.path, '');
  if (nsp.length > 0) {
    nsp = (nsp[0] === '/') ? nsp : '/' + nsp;
  } else {
    nsp = '/';
  }
  return nsp;
};
var initTransporter = function() {
  if ((config.transport === 'socket.io' || config.transport === 'both') && config.state === 'server') {
    console.log('Init socket.io server mode...');
    var io = require('socket.io')(app);
    if (config.state === 'server') {
      var ad = mdns.createAdvertisement(mdns.tcp('watchy'), config.port);
      ad.start();
    }
    //var io = require('socket.io').listen(config.socketIO.port);
    var socketIO = {
      name: 'socket.io',
      sender: io,
      socketConnections: [],
      send: function(path, action) {
        if (this.socketConnections.length < 0) {
          console.log('No socket open');
        } else {
          if (config.debug == true) {
            console.log('Sending ' + action + ' using socket.io');
          }
          _.each(this.socketConnections, function(socket) {
            socket.emit(action, {
              src: path
            });
          });
        }
      }
    };

    socketIO.sender.sockets.on('connection', function(socket) {
      socket.on('hello', function(data) {
        if (config.debug == true) {
          console.log('client connected');
          console.log(data);
        }
      });
      socketIO.socketConnections.push(socket);
    });
    transporter.push(socketIO);

  } else if ((config.transport === 'socket.io' || config.transport === 'both') && config.state === 'client') {

    // Could be improved
    if (config.client) {
      initSocketIOClient(config.client.address, config.client.port);
    }
    var handleError = function(error) {
      switch (error.errorCode) {
        case mdns.kDNSServiceErr_Unknown:
          console.warn(error);
          // setTimeout(createAdvertisement, 5000);
          break;
        default:
          // throw error;
          console.log(error);
      }
    };

    try {
      var serviceBrowser = mdns.createBrowser(mdns.tcp(config.servicelookup.name));
      serviceBrowser.on('serviceUp', function(service) {
        console.log("service up: ", service.fullname);
        var serviceHost = service.host.substr(0, service.host.length - 1),
          servicePort = service.port,
          querySearch = {
            host: serviceHost,
            port: servicePort
          };

        var exist = _.find(transporter, querySearch);
        //console.log('query:', util.inspect(querySearch,{depth:4}));
        //console.log('exist: ', exist);

        if (exist == undefined) {
          console.log(serviceHost + ':' + servicePort + ' does not exist, we initiate connection');
          initSocketIOClient(service.host.substr(0, service.host.length - 1), service.port)
          //currentServiceAddress = service.host.substr(0, service.host.length - 1);
        }

      });
      serviceBrowser.on('serviceDown', function(service) {
        console.log("service down: ", service.name);
      });
      serviceBrowser.start();
    } catch (ex) {
      handleError(ex);
    }
  }

  if (config.transport === 'osc' || config.transport === 'both') {
    var osc = require('node-osc'),
      OSCclient = new osc.Client(config.osc.address, config.osc.port),
      OSCSender = {
        name: 'osc',
        sender: OSCclient,
        send: function(path, action) {
          if (config.debug == true) {
            console.log('Sending ' + action + ' using osc');
          }
          this.sender.send(action, path);
        }
      }
    transporter.push(OSCSender);
  }
};

var initSocketIOClient = function(address, port) {
  console.log('Init socket.io client mode : ', address, port);
  var socket = require('socket.io-client')('http://' + address + ':' + port);
  socket.on('connect', function() {
    socket.emit('binding');
    host = ip.address();
    console.log(host);
    console.log('Connected to socket.io server: ', address, port);
    //TODO Should bind to a specific socket and not a global
    connected = true;
  })
    .on('disconnect', function() {
      console.log('We\'ve been disconnected');
    })
    .on('error', function() {
      console.log('error while connecting');
    })
    .on('reconnect', function(nbtry) {
      console.log('Successfull reconnect after ' + nbtry + ' trying.');
    })
    .on('reconnecting', function(nbtry) {
      if (!connected || config.multiConnect) {
        console.warn('Trying to reconnect to: ', address, port);
      }
    })
    .on('bind-nsp', function(nsp) {
      if (config.watch.path)
        if (_.contains(namespaces, nsp) === false) {
          mkdirp(config.watch.path + nsp, function(err) {
            if (err) {
              console.log('mkdirp: ' + err);
            }
          });
          namespaces.push(nsp);
      }
      console.log('Binding folder');
      var nspSocket = require('socket.io-client').connect('http://' + address + ':' + port + nsp);
      transporter.push(createSocketTransporter(nsp, nspSocket, address, port));
    });

  namespaces.push('/');
  transporter.push(createSocketTransporter('/', socket, address, port));
}

function createSocketTransporter(name, socket, host, port) {
  console.log("=============================================");
  console.log(socket.io.opts.host);
  console.log(socket.io.opts.port);
  var socketIO = {
    name: name,
    host: host,
    port: port,
    sender: socket,
    send: function(path, action) {
      if (config.debug == true) {
        console.log('Sending', action, 'using', name);
      }
      socket.emit(action, {
        src: path
      });
    }
  };
  return socketIO;
}

var initWatcher = function() {
  var chokidar = require('chokidar');

  var watcher = chokidar.watch(config.watch.path, {
    ignored: /[\/\\]\./,
    ignoreInitial: config.ignoreInitial,
    persistent: true
  });

  watcher
    .on('add', function(path) {

      if (path.indexOf('!sync') < 0) {
        //Add a slight delay to avoid error on get when too fast request are made.
        //See bug https://github.com/joyent/node/issues/4863
        //Data is not ready but someone is trying to access to ....

        setTimeout(function() {
          try {
            console.log(path);
            console.log(config.watch.path);
            var os = require("os");
            var watchPath = (config.watch.path.charAt(config.watch.path.length - 1) !== '/') ? config.watch.path : config.watch.path.substring(0, config.watch.path.length - 1);
            var relativePath = path.replace(watchPath, 'http://' + host + ":" + config.port);

            console.log(relativePath);

            /*var splitedPath = path.split('/');
            var nsp = splitedPath[splitedPath.length - 2];
            nsp = nsp === config.watch.path.split('/').pop() ? '' : nsp;*/
            var nsp = findNameSpace(path);
            var queryNamespace = nsp;
            //console.log(queryNamespace);
            var transporterSocketio = _.where(transporter, {
              name: queryNamespace
            });
            //console.log(transporter);
            if (transporterSocketio.length > 0) {
              _.each(transporterSocketio, function(senderIO, index) {
                senderIO.send(relativePath, 'image-saved');
              })
            } else {
              console.log('Sorry we can not send using socket.io, no transport available, check your network\nor your namspace...');
            }

            if (config.transport === 'osc' || config.transport === 'both') {
              var transporterOsc = _.where(transporter, {
                name: 'osc'
              });
              if (transporterOsc.length > 0) {
                transporterOsc[0].send(relativePath, 'new-file');
                transporterOsc[0].send(relativePath, 'new-image'); // legacy until june 2015
              } else {
                console.log('Sorry we can not send using OSC, no transport available');
              }
            }
          } catch (err) {
            console.log(err);
          }
        }, 500);
      } else {
        console.log('Chokidar - File', path, 'should be ignored');
      }
    })
    .on('addDir', function(path) {
      console.log('Chokidar - Directory', path, 'has been added');
    })
    .on('change', function(path, stats) {
      console.log('Chokidar - File', path, 'has been changed');
      if (stats) {
        console.log(stats);
      }
    })
    .on('unlink', function(path) {
      if (path.indexOf('!sync') < 0) {
        try {
          var relativePath = path.replace(config.watch.path, 'http://' + host + ":" + config.port);
          console.log(relativePath);

          /*var splitedPath = path.split('/');
          var nsp = splitedPath[splitedPath.length - 2];
          nsp = nsp === config.watch.path.split('/').pop() ? '' : nsp;*/
          var nsp = findNameSpace(path);

          var transporterSocketio = _.where(transporter, {
            name: '/' + nsp
          });
          if (transporterSocketio.length > 0) {
            //transporterSocketio[0].send(relativePath, 'image-deleted');
            _.each(transporterSocketio, function(senderIO, index) {
              senderIO.send(relativePath, 'image-deleted');
            })
          } else {
            console.log('Sorry we can not send using OSC, no transport available');
          }
          if (config.transport === 'osc' || config.transport === 'both') {
            var transporterOsc = _.where(transporter, {
              name: 'osc'
            });
            if (transporterOsc.length > 0) {
              transporterOsc[0].send(relativePath, 'image-deleted');
            } else {
              console.log('Sorry we can not send using OSC, no transport available');
            }

          }
        } catch (err) {
          console.log(err);
        }
      } else {
        console.log('File', path, 'should be ignored');
      }
      console.log('File', path, 'has been removed');
    })
    .on('unlinkDir', function(path) {
      console.log('Chokidar - Directory', path, 'has been removed');
    })
    .on('error', function(error) {
      console.error('Chokidar - Error happened', error);
    })
    .on('ready', function() {
      console.info('Chokidar - Initial scan complete. Ready for changes.');
    })
    .on('raw', function(event, path, details) {
      //console.info('Raw event info:', event, path, details)
    })
}

var initStatiqueServer = function() {

  var staticServer = require('node-static'),
    fileServer = new staticServer.Server(config.watch.path, {
      cache: 7200,
      serverInfo: "watchy/" + host
    });

  app = require('http').createServer(function(request, response) {
    request.addListener('end', function() {
      fileServer.serve(request, response).addListener('error', function(err) {
        util.error("Error serving " + request.url + " - " + err.message);
        response.end();
      });
    }).resume();
  });

  /* Does not provide meaning full message when error occur
  var Statique = require("statique");

  // Create *Le Statique* server
  var server = new Statique({
    root: config.watch.path
  }).setRoutes({
    "/": "/html/index.html"
  });

  // Create server
  app = require('http').createServer(server.serve);*/
}

console.log("Initializing...");

if (fs.existsSync(config.watch.path)) {
  initStatiqueServer();
  initTransporter();
  //TODO add some ready event to tell the watcher to init.
  initWatcher();
  console.log("...Initialized");
  // Output
  var os = require("os");
  host = os.hostname();
  if (os.platform() === 'linux') {
    var child_process = require("child_process");
    child_process.exec("hostname -f", function(err, stdout, stderr) {
      host = stdout.trim();
      //hot and dirty fix
      if (host.indexOf('local') < 0) {
        host += '.local'
      }
    });
  }
  require('dns').resolve('www.google.com', function(err) {
    if (err) {
      console.log('No internet connection, serving from localhost');
      host = '127.0.0.1';
    } else {
      console.log('All fine, we have access to internet');
    }
  });
  console.log("Listening on: " + config.port);
  console.log("Watching: "+config.watch.path);
  app.listen(config.port)
    .on('error', function(err) {
      console.log(err);
      process.exit(1);
    });
} else {
  console.log('Sorry, we can\'t watch something that does not exist: ', config.watch.path);
}<|endoftext|>


<commit_before>
import { observable, computed, toJS } from 'mobx';

// TODO
import fakeFetch from 'utils/fakeFetch';

export default class Store {
	@observable total = 0;
	@observable isFetching = false;
	@observable page = 1;

	@computed get dataSource() {
		return this.collection.get(this.page);
	}

	collections = observable.map();

	size = 20;

	constructor(schema) {
		this._schema = schema;
		this.columns = schema.map(({ title, key, render }) => ({
			title,
			key,
			render,
			dataIndex: key,
		}));
	}

	async fetch(page = 1) {
		if (this.collection.has(page)) { return this; }

		this.isFetching = true;

		const { total, list } = await fakeFetch({
			count: this.size,
		});

		const collection = list.map((data, index) => {

			// TODO: should depend on `schema.unique`
			data.key = data.key || index;

			return data;
		});

		this.page = page;
		this.isFetching = false;
		this.total = total;
		this.collections.set(page, collection);
		return this;
	}
}
<commit_msg>fix store bug<commit_after>
import { observable, computed, toJS } from 'mobx';

// TODO
import fakeFetch from 'utils/fakeFetch';

export default class Store {
	@observable total = 0;
	@observable isFetching = false;
	@observable page = 1;

	@computed get dataSource() {
		return toJS(this.collections.get(this.page));
	}

	collections = observable.map();

	size = 20;

	constructor(schema) {
		this._schema = schema;
		this.columns = schema.map(({ title, key, render }) => ({
			title,
			key,
			render,
			dataIndex: key,
		}));
	}

	async fetch(page = 1) {
		if (this.collections.has(page)) { return this; }

		this.isFetching = true;

		const { total, list } = await fakeFetch({
			count: this.size,
		});

		const collection = list.map((data, index) => {

			// TODO: should depend on `schema.unique`
			data.key = data.key || index;

			return data;
		});

		this.page = page;
		this.isFetching = false;
		this.total = total;
		this.collections.set(page, collection);
		return this;
	}
}
<|endoftext|>


<commit_before>/**
 * @file Popup component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';
import Transition from 'react-transition-group/Transition';
import classNames from 'classnames';

import Portal from '../Portal';
import Paper from '../Paper';
import Theme from '../Theme';

import Position from '../_statics/Position';
import TriggerMode from '../_statics/TriggerMode';
import Event from '../_vendors/Event';
import PopupCalculation from '../_vendors/PopupCalculation';
import PopupManagement from '../_vendors/PopupManagement';
import Dom from '../_vendors/Dom';
import Util from '../_vendors/Util';
import PropTypes from 'prop-types';

class Popup extends Component {

    static Position = Position;
    static TriggerMode = TriggerMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            enter: false,
            exited: true
        };

        this.enterHandler = ::this.enterHandler;
        this.exitHandler = ::this.exitHandler;
        this.exitedHandler = ::this.exitedHandler;
        this.mousedownHandler = ::this.mousedownHandler;
        this.resizeHandler = ::this.resizeHandler;

    }

    enterHandler(el) {

        this.transitionEl = el;

        const {triggerEl, position, isTriggerPositionFixed} = this.props;
        PopupCalculation.setStyle(triggerEl, el, position, isTriggerPositionFixed);

        this.setState({
            enter: true
        });

    }

    exitHandler() {
        this.setState({
            enter: false
        });
    }

    exitedHandler() {
        this.setState({
            exited: true
        });
    }

    triggerHandler(el, triggerEl, popupEl, triggerMode, currentVisible, isAutoClose) {

        while (el) {
            if (el == popupEl) {
                return currentVisible;
            }
            el = el.parentNode;
        }

        return isAutoClose ? false : currentVisible;

    }

    mousedownHandler(e) {

        const {visible, triggerEl, triggerMode, isAutoClose, triggerHandler, onRequestClose} = this.props;

        let currVisible;

        if (triggerHandler) {
            currVisible = triggerHandler(e.target, triggerEl, this.popupEl, triggerMode, visible, isAutoClose);
        } else if (!Dom.isParent(e.target, triggerEl)) {
            currVisible = this.triggerHandler(e.target, triggerEl, this.popupEl, triggerMode, visible, isAutoClose);
        }

        if (currVisible === false) {
            onRequestClose && onRequestClose(e);
        }

    }

    resizeHandler = _.debounce(() => {
        const {triggerEl, position, isTriggerPositionFixed} = this.props;
        PopupCalculation.setStyle(triggerEl, this.transitionEl, position, isTriggerPositionFixed);
    }, 250);

    componentDidMount() {

        this.popupEl = findDOMNode(this.refs.popup);

        Event.addEvent(document, 'mousedown', this.mousedownHandler);
        Event.addEvent(window, 'resize', this.resizeHandler);

        this.props.isEscClose && PopupManagement.push(this);

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.visible) {
            this.setState({
                exited: false
            });
        }
    }

    // componentDidUpdate() {
    //     const {visible, onRender} = this.props;
    //     visible && onRender && onRender(this.popupEl, this.props.triggerEl);
    // }

    componentWillUnmount() {
        Event.removeEvent(document, 'mousedown', this.mousedownHandler);
        Event.removeEvent(window, 'resize', this.resizeHandler);
    }

    render() {

        const {

                children,

                className, style, theme, hasTriangle, triangle, position, isAnimated, visible,

                // not passing down these props
                isEscClose, isAutoClose, shouldPreventContainerScroll, triggerMode, triggerEl, isTriggerPositionFixed,
                onRender, onRequestClose, triggerHandler,

                ...restProps

            } = this.props,
            {enter, exited} = this.state,

            popupClassName = classNames('popup', {
                hidden: !enter,
                'popup-has-triangle': hasTriangle,
                [`theme-${theme}`]: theme,
                [`popup-position-${position}`]: position,
                'popup-animated': isAnimated,
                [className]: className
            });

        return (
            <Portal visible={!exited}>
                <Transition appear
                            in={visible}
                            timeout={250}
                            onEnter={this.enterHandler}
                            onExit={this.exitHandler}
                            onExited={this.exitedHandler}>
                    <Paper {...restProps}
                           className={popupClassName}
                           style={style}
                           onWheel={e => {
                               Event.wheelHandler(e, this.props);
                           }}>

                        {
                            hasTriangle ?

                                    {triangle}

                                :
                                null
                        }

 {
                                 Event.wheelHandler(e, this.props);
                             }}>
                            {children}

                    </Paper>
                </Transition>
            </Portal>
        );

    }

};

Popup.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * This is the DOM element that will be used to set the position of the popover.
     */
    triggerEl: PropTypes.object,

    /**
     * If true,the popover is visible.
     */
    visible: PropTypes.bool,

    /**
     * If true,the popover will have a triangle on the top of the DOM element.
     */
    hasTriangle: PropTypes.bool,

    triangle: PropTypes.element,

    /**
     * The popover theme.Can be primary,highlight,success,warning,error.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The popover alignment.The value can be Popup.Position.LEFT or Popup.Position.RIGHT.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true,popup will have animation effects.
     */
    isAnimated: PropTypes.bool,

    /**
     * The status of popup-triangle.Can be open or toggle.
     */
    triggerMode: PropTypes.oneOf(Util.enumerateValue(TriggerMode)),

    /**
     * The depth of Paper component.
     */
    depth: PropTypes.number,

    isAutoClose: PropTypes.bool,
    isEscClose: PropTypes.bool,
    shouldPreventContainerScroll: PropTypes.bool,
    isTriggerPositionFixed: PropTypes.bool,

    /**
     * The function of popup event handler.
     */
    triggerHandler: PropTypes.func,

    /**
     * The function of popup render.
     */
    onRender: PropTypes.func,

    /**
     * Callback function fired when the popover is requested to be closed.
     */
    onRequestClose: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func

};

Popup.defaultProps = {

    className: '',
    style: null,
    depth: 6,

    triggerEl: null,
    visible: false,
    hasTriangle: true,
    triangle:

,
    theme: Theme.DEFAULT,
    position: Position.BOTTOM_LEFT,
    isAnimated: true,
    triggerMode: TriggerMode.TOGGLE,

    isAutoClose: true,
    isEscClose: true,
    shouldPreventContainerScroll: true,
    isTriggerPositionFixed: false

};

export default Popup;<commit_msg>update Popup<commit_after>/**
 * @file Popup component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';
import Transition from 'react-transition-group/Transition';
import classNames from 'classnames';

import Portal from '../Portal';
import Paper from '../Paper';
import Theme from '../Theme';

import Position from '../_statics/Position';
import TriggerMode from '../_statics/TriggerMode';
import Event from '../_vendors/Event';
import PopupCalculation from '../_vendors/PopupCalculation';
import PopupManagement from '../_vendors/PopupManagement';
import Dom from '../_vendors/Dom';
import Util from '../_vendors/Util';
import PropTypes from 'prop-types';

class Popup extends Component {

    static Position = Position;
    static TriggerMode = TriggerMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            enter: false,
            exited: true
        };

        this.enterHandler = ::this.enterHandler;
        this.exitHandler = ::this.exitHandler;
        this.exitedHandler = ::this.exitedHandler;
        this.mouseDownHandler = ::this.mouseDownHandler;
        this.resizeHandler = ::this.resizeHandler;

    }

    enterHandler(el) {

        this.transitionEl = el;

        const {triggerEl, position, isTriggerPositionFixed} = this.props;
        PopupCalculation.setStyle(triggerEl, el, position, isTriggerPositionFixed);

        this.setState({
            enter: true
        });

    }

    exitHandler() {
        this.setState({
            enter: false
        });
    }

    exitedHandler() {
        this.setState({
            exited: true
        });
    }

    triggerHandler(el, triggerEl, popupEl, triggerMode, currentVisible, isAutoClose) {

        while (el) {
            if (el == popupEl) {
                return currentVisible;
            }
            el = el.parentNode;
        }

        return isAutoClose ? false : currentVisible;

    }

    mouseDownHandler(e) {

        const {visible, triggerEl, triggerMode, isAutoClose, triggerHandler, onRequestClose} = this.props;

        let currVisible;

        if (triggerHandler) {
            currVisible = triggerHandler(e.target, triggerEl, this.popupEl, triggerMode, visible, isAutoClose);
        } else if (!Dom.isParent(e.target, triggerEl)) {
            currVisible = this.triggerHandler(e.target, triggerEl, this.popupEl, triggerMode, visible, isAutoClose);
        }

        if (currVisible === false) {
            setTimeout(() => {
                onRequestClose && onRequestClose(e);
            }, 0);
        }

    }

    resizeHandler = _.debounce(() => {
        const {triggerEl, position, isTriggerPositionFixed} = this.props;
        PopupCalculation.setStyle(triggerEl, this.transitionEl, position, isTriggerPositionFixed);
    }, 250);

    componentDidMount() {

        this.popupEl = findDOMNode(this.refs.popup);

        Event.addEvent(document, 'mousedown', this.mouseDownHandler);
        Event.addEvent(window, 'resize', this.resizeHandler);

        this.props.isEscClose && PopupManagement.push(this);

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.visible) {
            this.setState({
                exited: !nextProps.visible
            });
        }
    }

    // componentDidUpdate() {
    //     const {visible, onRender} = this.props;
    //     visible && onRender && onRender(this.popupEl, this.props.triggerEl);
    // }

    componentWillUnmount() {
        Event.removeEvent(document, 'mousedown', this.mouseDownHandler);
        Event.removeEvent(window, 'resize', this.resizeHandler);
    }

    render() {

        const {

                children,

                className, style, theme, hasTriangle, triangle, position, isAnimated, visible,

                // not passing down these props
                isEscClose, isAutoClose, shouldPreventContainerScroll, triggerMode, triggerEl, isTriggerPositionFixed,
                onRender, onRequestClose, triggerHandler,

                ...restProps

            } = this.props,
            {enter, exited} = this.state,

            popupClassName = classNames('popup', {
                hidden: !enter,
                'popup-has-triangle': hasTriangle,
                [`theme-${theme}`]: theme,
                [`popup-position-${position}`]: position,
                'popup-animated': isAnimated,
                [className]: className
            });

        return (
            <Portal visible={!exited}>
                <Transition appear
                            in={visible}
                            timeout={250}
                            onEnter={this.enterHandler}
                            onExit={this.exitHandler}
                            onExited={this.exitedHandler}>
                    <Paper {...restProps}
                           className={popupClassName}
                           style={style}
                           onWheel={e => {
                               Event.wheelHandler(e, this.props);
                           }}>

                        {
                            hasTriangle ?

                                    {triangle}

                                :
                                null
                        }

 {
                                 Event.wheelHandler(e, this.props);
                             }}>
                            {children}

                    </Paper>
                </Transition>
            </Portal>
        );

    }

};

Popup.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * This is the DOM element that will be used to set the position of the popover.
     */
    triggerEl: PropTypes.object,

    /**
     * If true,the popover is visible.
     */
    visible: PropTypes.bool,

    /**
     * If true,the popover will have a triangle on the top of the DOM element.
     */
    hasTriangle: PropTypes.bool,

    triangle: PropTypes.element,

    /**
     * The popover theme.Can be primary,highlight,success,warning,error.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The popover alignment.The value can be Popup.Position.LEFT or Popup.Position.RIGHT.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true,popup will have animation effects.
     */
    isAnimated: PropTypes.bool,

    /**
     * The status of popup-triangle.Can be open or toggle.
     */
    triggerMode: PropTypes.oneOf(Util.enumerateValue(TriggerMode)),

    /**
     * The depth of Paper component.
     */
    depth: PropTypes.number,

    isAutoClose: PropTypes.bool,
    isEscClose: PropTypes.bool,
    shouldPreventContainerScroll: PropTypes.bool,
    isTriggerPositionFixed: PropTypes.bool,

    /**
     * The function of popup event handler.
     */
    triggerHandler: PropTypes.func,

    /**
     * The function of popup render.
     */
    onRender: PropTypes.func,

    /**
     * Callback function fired when the popover is requested to be closed.
     */
    onRequestClose: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func

};

Popup.defaultProps = {

    className: '',
    style: null,
    depth: 6,

    triggerEl: null,
    visible: false,
    hasTriangle: true,
    triangle:

,
    theme: Theme.DEFAULT,
    position: Position.BOTTOM_LEFT,
    isAnimated: true,
    triggerMode: TriggerMode.TOGGLE,

    isAutoClose: true,
    isEscClose: true,
    shouldPreventContainerScroll: true,
    isTriggerPositionFixed: false

};

export default Popup;<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');

var routes = require('./routes/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<commit_msg>restore last commit.<commit_after>var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<|endoftext|>


<commit_before>import { TextNodeMixin } from '../model'
import XMLDocumentNode from './XMLDocumentNode'

/*
  Note: this is slightly different to Substance TextNode
  thus this does not extend Substance.TextNode.
*/
export default class XMLTextNode extends TextNodeMixin(XMLDocumentNode) {

  getPath() {
    return [this.id, 'content']
  }

  getText() {
    return this.content
  }

  /*
    This method is used for mimicking a DOM element.
    In our system, TextNodes are substantially different to common DOM elements
    as they only have plain-text, and overlaying annotations,
    i.e., annotations are not stored hierarchically.
  */
  getChildren() {
    return this.getAnnotations()
  }

}

XMLTextNode.prototype._elementType = 'text'

XMLTextNode.isText = true
XMLTextNode.isBlock = true

XMLTextNode.type = 'text'

XMLTextNode.schema = {
  content: "text"
}
<commit_msg>Introduced XMLTextNode.setText()<commit_after>import { TextNodeMixin } from '../model'
import { DOMElement } from '../dom'
import XMLDocumentNode from './XMLDocumentNode'

/*
  Note: this is slightly different to Substance TextNode
  thus this does not extend Substance.TextNode.
*/
export default class XMLTextNode extends TextNodeMixin(XMLDocumentNode) {

  getPath() {
    return [this.id, 'content']
  }

  getText() {
    return this.content
  }

  /*
    This method is used for mimicking a DOM element.
    In our system, TextNodes are substantially different to common DOM elements
    as they only have plain-text, and overlaying annotations,
    i.e., annotations are not stored hierarchically.
  */
  getChildren() {
    return this.getAnnotations()
  }

  setText(text) {
    const doc = this.getDocument()
    const path = this.getPath()
    const oldText = this.getText()
    // delete old text first
    if (oldText.length > 0) {
      doc.update(path, { type: 'delete', start: 0, end: oldText.length })
    }
    doc.update(path, { type: 'insert', start: 0, text })
    return this
  }

  // DOMElement API (partial)

  getTextContent() {
    return this.getText()
  }

  setTextContent(text) {
    return this.setText(text)
  }

  get textContent() {
    return this.getText()
  }

  set textContent(text) {
    this.setText(text)
  }

}

XMLTextNode.prototype.text = DOMElement.prototype.text

XMLTextNode.prototype._elementType = 'text'

XMLTextNode.isText = true
XMLTextNode.isBlock = true

XMLTextNode.type = 'text'

XMLTextNode.schema = {
  content: "text"
}
<|endoftext|>


<commit_before>import React, { PropTypes } from "react";
import { PropTypes as CustomPropTypes, Style, TextSize, Helpers } from "../victory-util/index";
import { merge, isEmpty, defaults, sumBy, maxBy } from "lodash";
import VictoryLabel from "../victory-label/victory-label";
import VictoryContainer from "../victory-container/victory-container";
import VictoryTheme from "../victory-theme/victory-theme";
import Point from "../victory-primitives/point";

const defaultLegendData = [
  { name: "Series 1" },
  { name: "Series 2" }
];

export default class VictoryLegend extends React.Component {
  static displayName = "VictoryLegend";

  static role = "legend";

  static propTypes = {
    colorScale: PropTypes.oneOfType([
      PropTypes.arrayOf(PropTypes.string),
      PropTypes.oneOf([
        "grayscale", "qualitative", "heatmap", "warm", "cool", "red", "green", "blue"
      ])
    ]),
    containerComponent: PropTypes.element,
    data: PropTypes.arrayOf(
      PropTypes.shape({
        name: PropTypes.string.isRequired,
        label: PropTypes.object,
        symbol: PropTypes.object
      })
    ),
    dataComponent: PropTypes.element,
    groupComponent: PropTypes.element,
    gutter: PropTypes.number,
    height: PropTypes.oneOfType([
      CustomPropTypes.nonNegative,
      PropTypes.func
    ]),
    labelComponent: PropTypes.element,
    orientation: PropTypes.oneOf(["horizontal", "vertical"]),
    padding: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.shape({
        top: PropTypes.number,
        bottom: PropTypes.number,
        left: PropTypes.number,
        right: PropTypes.number
      })
    ]),
    standalone: PropTypes.bool,
    style: PropTypes.shape({
      symbol: PropTypes.object,
      label: PropTypes.object
    }),
    symbolSpacer: PropTypes.number,
    theme: PropTypes.object,
    width: PropTypes.oneOfType([
      CustomPropTypes.nonNegative,
      PropTypes.func
    ]),
    x: PropTypes.number.isRequired,
    y: PropTypes.number.isRequired
  };

  static defaultProps = {
    containerComponent: <VictoryContainer/>,
    dataComponent: <Point/>,
    groupComponent: <g/>,
    gutter: 10,
    labelComponent: <VictoryLabel/>,
    orientation: "vertical",
    standalone: true,
    style: {},
    symbolSpacer: 8,
    theme: VictoryTheme.grayscale,
    x: 0,
    y: 0
  };

  calculateLegendHeight(textSizes, padding, isHorizontal) {
    const { data, gutter } = this.props;
    const contentHeight = isHorizontal
      ? maxBy(textSizes, "height").height
      : sumBy(textSizes, "height") + gutter * (data.length - 1);

    return padding.top + contentHeight + padding.bottom;
  }

  calculateLegendWidth(textSizes, padding, isHorizontal) {
    const { data, gutter, symbolSpacer } = this.props;
    const contentWidth = isHorizontal
      ? sumBy(textSizes, "width") + (gutter + symbolSpacer * 3) * (data.length - 1)
      : maxBy(textSizes, "width").width + symbolSpacer * 2;

    return padding.left + contentWidth + padding.right;
  }

  getColorScale(theme) {
    const { colorScale } = this.props;
    let colorScaleOptions = colorScale || theme.colorScale;

    if (typeof colorScaleOptions === "string") {
      colorScaleOptions = Style.getColorScale(colorScaleOptions);
    }

    return !isEmpty(theme) ? colorScaleOptions || theme.colorScale : colorScaleOptions || [];
  }

  getCalculatedProps() { // eslint-disable-line max-statements
    const { role } = this.constructor;
    const { data, orientation, theme } = this.props;
    let { height, padding, width } = this.props;
    const legendTheme = theme && theme[role] ? theme[role] : {};
    const colorScale = this.getColorScale(legendTheme);
    const isHorizontal = orientation === "horizontal";
    const symbolStyles = [];
    const labelStyles = [];
    let leftOffset = 0;

    padding = Helpers.getPadding({ padding: padding || theme.padding });
    height = Helpers.evaluateProp(height || theme.height, data);
    width = Helpers.evaluateProp(width || theme.width, data);

    const textSizes = data.map((datum, i) => {
      const labelStyle = this.getStyles(datum, legendTheme, "labels");
      symbolStyles[i] = this.getStyles(datum, legendTheme, "symbol", colorScale[i]);
      labelStyles[i] = labelStyle;

      const textSize = TextSize.approximateTextSize(datum.name, labelStyle);
      textSize.leftOffset = leftOffset;
      leftOffset += textSize.width;

      return textSize;
    });

    if (!height) {
      height = this.calculateLegendHeight(textSizes, padding, isHorizontal);
    }
    if (!width) {
      width = this.calculateLegendWidth(textSizes, padding, isHorizontal);
    }

    return Object.assign({},
      this.props,
      { isHorizontal, height, labelStyles, padding, symbolStyles, textSizes, width }
    );
  }

  getStyles(datum, theme, key, color) { // eslint-disable-line max-params
    const colorScale = color ? { fill: color } : {};
    return merge({}, theme.style[key], colorScale, this.props.style[key], datum[key]);
  }

  getSymbolSize(datum, fontSize) {
    return datum.symbol && datum.symbol.size ? datum.symbol.size : fontSize / 2.5;
  }

  getSymbolProps(datum, props, i) {
    const {
      gutter, labelStyles, isHorizontal, padding, symbolSpacer, symbolStyles, textSizes
    } = props;
    const { leftOffset } = textSizes[i];
    const { fontSize } = labelStyles[i];
    const symbolShift = fontSize / 2;
    const style = symbolStyles[i];

    const symbolCoords = isHorizontal ? {
      x: padding.left + leftOffset + symbolShift + (fontSize + symbolSpacer + gutter) * i,
      y: padding.top + symbolShift
    } : {
      x: padding.left + symbolShift,
      y: padding.top + symbolShift + (fontSize + gutter) * i
    };

    return {
      key: `symbol-${i}`,
      style,
      size: this.getSymbolSize(datum, fontSize),
      symbol: style.type,
      ...symbolCoords
    };
  }

  getLabelProps(datum, props, i) {
    const { gutter, isHorizontal, symbolSpacer, labelStyles, textSizes, padding } = props;
    const style = labelStyles[i];
    const { fontSize } = style;
    const symbolShift = fontSize / 2;

    const labelCoords = isHorizontal ? {
      x: padding.left + textSizes[i].leftOffset + (fontSize + symbolSpacer) * (i + 1) + gutter * i,
      y: padding.top + symbolShift
    } : {
      x: padding.left + fontSize + symbolSpacer,
      y: padding.top + symbolShift + (fontSize + gutter) * i
    };

    return {
      key: `label-${i}`,
      style,
      text: datum.name,
      ...labelCoords
    };
  }

  renderLegendItems(props) {
    const { data, dataComponent, labelComponent } = props;
    const legendData = isEmpty(data) ? defaultLegendData : data;
    const length = legendData.length;
    const dataComponents = [];
    const labelComponents = [];

    for (let i = 0; i < length; i++) {
      const datum = legendData[i];

      dataComponents[i] = React.cloneElement(
        dataComponent,
        this.getSymbolProps(datum, props, i)
      );
      labelComponents[i] = React.cloneElement(
        labelComponent,
        this.getLabelProps(datum, props, i)
      );
    }

    return [...dataComponents, ...labelComponents];
  }

  renderGroup(props, children) {
    const { groupComponent, height, width, standalone, x, y } = props;
    const groupProps = { role: "presentation" };

    if (!standalone) {
      Object.assign(groupProps, { height, width, x, y });
    }

    return React.cloneElement(groupComponent, groupProps, children);
  }

  renderContainer(props, children) {
    const { containerComponent, height, width, x, y, style } = props;

    return React.cloneElement(
      containerComponent,
      { x, y, height, width, style: defaults({}, style) },
      children
    );
  }

  render() {
    const props = this.getCalculatedProps();
    const group = this.renderGroup(props, this.renderLegendItems(props));
    return props.standalone ? this.renderContainer(props, group) : group;
  }
}
<commit_msg>refactor style prop, allow parent container styles<commit_after>import React, { PropTypes } from "react";
import { PropTypes as CustomPropTypes, Style, TextSize, Helpers } from "../victory-util/index";
import { merge, isEmpty, defaults, sumBy, maxBy } from "lodash";
import VictoryLabel from "../victory-label/victory-label";
import VictoryContainer from "../victory-container/victory-container";
import VictoryTheme from "../victory-theme/victory-theme";
import Point from "../victory-primitives/point";

const defaultLegendData = [
  { name: "Series 1" },
  { name: "Series 2" }
];

export default class VictoryLegend extends React.Component {
  static displayName = "VictoryLegend";

  static role = "legend";

  static propTypes = {
    colorScale: PropTypes.oneOfType([
      PropTypes.arrayOf(PropTypes.string),
      PropTypes.oneOf([
        "grayscale", "qualitative", "heatmap", "warm", "cool", "red", "green", "blue"
      ])
    ]),
    containerComponent: PropTypes.element,
    data: PropTypes.arrayOf(
      PropTypes.shape({
        name: PropTypes.string.isRequired,
        label: PropTypes.object,
        symbol: PropTypes.object
      })
    ),
    dataComponent: PropTypes.element,
    groupComponent: PropTypes.element,
    gutter: PropTypes.number,
    height: PropTypes.oneOfType([
      CustomPropTypes.nonNegative,
      PropTypes.func
    ]),
    labelComponent: PropTypes.element,
    orientation: PropTypes.oneOf(["horizontal", "vertical"]),
    padding: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.shape({
        top: PropTypes.number,
        bottom: PropTypes.number,
        left: PropTypes.number,
        right: PropTypes.number
      })
    ]),
    standalone: PropTypes.bool,
    style: PropTypes.shape({
      data: PropTypes.object,
      labels: PropTypes.object,
      parent: PropTypes.object
    }),
    symbolSpacer: PropTypes.number,
    theme: PropTypes.object,
    width: PropTypes.oneOfType([
      CustomPropTypes.nonNegative,
      PropTypes.func
    ]),
    x: PropTypes.number,
    y: PropTypes.number
  };

  static defaultProps = {
    containerComponent: <VictoryContainer/>,
    dataComponent: <Point/>,
    groupComponent: <g/>,
    gutter: 10,
    labelComponent: <VictoryLabel/>,
    orientation: "vertical",
    standalone: true,
    style: {},
    symbolSpacer: 8,
    theme: VictoryTheme.grayscale,
    x: 0,
    y: 0
  };

  calculateLegendHeight(textSizes, padding, isHorizontal) {
    const { data, gutter } = this.props;
    const contentHeight = isHorizontal
      ? maxBy(textSizes, "height").height
      : sumBy(textSizes, "height") + gutter * (data.length - 1);

    return padding.top + contentHeight + padding.bottom;
  }

  calculateLegendWidth(textSizes, padding, isHorizontal) {
    const { data, gutter, symbolSpacer } = this.props;
    const contentWidth = isHorizontal
      ? sumBy(textSizes, "width") + (gutter + symbolSpacer * 3) * (data.length - 1)
      : maxBy(textSizes, "width").width + symbolSpacer * 2;

    return padding.left + contentWidth + padding.right;
  }

  getColorScale(theme) {
    const { colorScale } = this.props;
    let colorScaleOptions = colorScale || theme.colorScale;

    if (typeof colorScaleOptions === "string") {
      colorScaleOptions = Style.getColorScale(colorScaleOptions);
    }

    return !isEmpty(theme) ? colorScaleOptions || theme.colorScale : colorScaleOptions || [];
  }

  getCalculatedProps() { // eslint-disable-line max-statements
    const { role } = this.constructor;
    const { data, orientation, theme } = this.props;
    let { height, padding, width } = this.props;

    const legendTheme = theme && theme[role] ? theme[role] : {};
    const parentStyles = this.getStyles({}, legendTheme, "parent");
    const colorScale = this.getColorScale(legendTheme);
    const isHorizontal = orientation === "horizontal";
    const symbolStyles = [];
    const labelStyles = [];
    let leftOffset = 0;

    padding = Helpers.getPadding({ padding: padding || theme.padding });
    height = Helpers.evaluateProp(height || theme.height, data);
    width = Helpers.evaluateProp(width || theme.width, data);

    const textSizes = data.map((datum, i) => {
      const labelStyle = this.getStyles(datum, legendTheme, "labels");
      symbolStyles[i] = this.getStyles(datum, legendTheme, "symbol", colorScale[i]);
      labelStyles[i] = labelStyle;

      const textSize = TextSize.approximateTextSize(datum.name, labelStyle);
      textSize.leftOffset = leftOffset;
      leftOffset += textSize.width;

      return textSize;
    });

    if (!height) {
      height = this.calculateLegendHeight(textSizes, padding, isHorizontal);
    }
    if (!width) {
      width = this.calculateLegendWidth(textSizes, padding, isHorizontal);
    }

    return merge({},
      this.props,
      { isHorizontal, height, labelStyles, padding, parentStyles, symbolStyles, textSizes, width }
    );
  }

  getStyles(datum, theme, key, color) { // eslint-disable-line max-params
    const { style } = this.props;
    const styleKey = key === "symbol" ? "data" : key;
    const colorScaleStyle = color ? { fill: color } : {};
    const styles = merge({}, theme.style[styleKey], colorScaleStyle, style[styleKey], datum[key]);
    return Helpers.evaluateStyle(styles, datum);
  }

  getSymbolSize(datum, fontSize) {
    return datum.symbol && datum.symbol.size ? datum.symbol.size : fontSize / 2.5;
  }

  getSymbolProps(datum, props, i) {
    const {
      dataComponent, gutter, labelStyles, isHorizontal,
      padding, symbolSpacer, symbolStyles, textSizes
    } = props;
    const { leftOffset } = textSizes[i];
    const { fontSize } = labelStyles[i];
    const symbolShift = fontSize / 2;
    const style = symbolStyles[i];

    const symbolCoords = isHorizontal ? {
      x: padding.left + leftOffset + symbolShift + (fontSize + symbolSpacer + gutter) * i,
      y: padding.top + symbolShift
    } : {
      x: padding.left + symbolShift,
      y: padding.top + symbolShift + (fontSize + gutter) * i
    };

    return defaults({},
      dataComponent.props,
      {
        key: `symbol-${i}`,
        style,
        size: this.getSymbolSize(datum, fontSize),
        symbol: style.type,
        ...symbolCoords
      }
    );
  }

  getLabelProps(datum, props, i) {
    const {
      gutter, isHorizontal, symbolSpacer, labelComponent, labelStyles, textSizes, padding
    } = props;
    const style = labelStyles[i];
    const { fontSize } = style;
    const symbolShift = fontSize / 2;

    const labelCoords = isHorizontal ? {
      x: padding.left + textSizes[i].leftOffset + (fontSize + symbolSpacer) * (i + 1) + gutter * i,
      y: padding.top + symbolShift
    } : {
      x: padding.left + fontSize + symbolSpacer,
      y: padding.top + symbolShift + (fontSize + gutter) * i
    };

    return defaults({},
      labelComponent.props,
      {
        key: `label-${i}`,
        style,
        text: datum.name,
        ...labelCoords
      }
    );
  }

  renderLegendItems(props) {
    const { data, dataComponent, labelComponent } = props;
    const legendData = isEmpty(data) ? defaultLegendData : data;
    const length = legendData.length;
    const dataComponents = [];
    const labelComponents = [];

    for (let i = 0; i < length; i++) {
      const datum = legendData[i];

      dataComponents[i] = React.cloneElement(
        dataComponent,
        this.getSymbolProps(datum, props, i)
      );
      labelComponents[i] = React.cloneElement(
        labelComponent,
        this.getLabelProps(datum, props, i)
      );
    }

    return [...dataComponents, ...labelComponents];
  }

  renderGroup(props, children) {
    const { groupComponent, height, parentStyles, standalone, width, x, y } = props;
    let groupProps = { role: "presentation" };

    if (!standalone) {
      groupProps = merge(groupProps, { height, width, x, y, style: parentStyles });
    }

    return React.cloneElement(groupComponent, groupProps, children);
  }

  renderContainer(props, children) {
    const { containerComponent, height, parentStyles, width, x, y } = props;

    return React.cloneElement(
      containerComponent,
      { height, width, x, y, style: parentStyles },
      children
    );
  }

  render() {
    const props = this.getCalculatedProps();
    const group = this.renderGroup(props, this.renderLegendItems(props));
    return props.standalone ? this.renderContainer(props, group) : group;
  }
}
<|endoftext|>