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

var sys = require('sys');
var ProgressBar = require('progress');

var AIInputManager = require('./ai_input_manager.js');
var AIPlayer = require('./ai_player.js');
var AIWeights = require('./ai_weights.js');
var DummyActuator = require('./dummy_actuator.js');
var GameManager = require('./game_manager.js');
var LocalStorageManager = require('./dummy_storage_manager.js');

var opts = {
    verbose: false,
    popSize: 500,
    mutationRate: 0.05,
    maxGenerations: 1000,
    runsPerCandidate: 5,
    fitnessMeasure: 'score',
    save: false,
};

var stash = {};

var args = process.argv.slice(2);
args.forEach(function (val, index, array) {
    if (val === '--verbose' || val === '-v') {
        opts.verbose = true;
    }
    else if (val.match(/(-s|--save)/)) {
        opts.save = true;
    }
    else if (val.match(/(-p|--popsize)=\d+/)) {
        opts.popSize = parseInt( val.split('=')[1] );
    }
    else if (val.match(/(-g|--max_generations)=\d+/)) {
        opts.maxGenerations = parseInt( val.split('=')[1] );
    }
    else if (val.match(/(-m|--mutation_rate)=\d+(\.\d+)?/)) {
        opts.mutationRate = parseFloat( val.split('=')[1] );
    }
    else if (val.match(/(-r|--runs)=\d+/)) {
        opts.runsPerCandidate = parseInt( val.split('=')[1] );
    }
    else if (val.match(/(-f|--fitness)=(score|maxval)/)) {
        opts.fitnessMeasure = val.split('=')[1];
    }
    else if (val.match(/(-w|--weights_key)=\w+/)) {
        opts.weightsKey = val.split('=')[1];
    }
    else if (val === '--help') {
        help();
        process.exit(0);
    }
    else {
        console.log('Invalid argument ' + val);
        process.exit(1);
    }
});

function help() {
    var helpStr =
"USAGE: run_GA.js [OPTIONS]\r\n" +
'\r\n'+
'Runs genetic algorithm to train (breed?) progressively better 2048 AI players \r\n' +
'\r\n'+
'Options:\r\n' +
'    --popsize -p\r\n' +
'        Number of candidates per generation. Default: 500.\r\n' +
'    --max_generations -g\r\n' +
'        Generations to run GA. Default 1000.\r\n' +
'    --mutation_rate -m\r\n' +
'        Likelihood of mutation in new offspring. Default: 0.05 (i.e. 5%).\r\n' +
'    --runs -r\r\n' +
'        How many games each candidate should play to calculate averaged fitness.\r\n' +
'        Default: 5\r\n' +
'    --fitness -f\r\n' +
'        Fitness measure to use. One of:\r\n' +
'           score  - player score upon game over (default).\r\n' +
'           maxval - the highest value grid cell achieved upon game over.\r\n' +
'    --weights_key -w\r\n' +
'        Save best candidate weights under the given key.\r\n' +
'\r\n'+
'    --save\r\n' +
'        Save the best candidate\'s weights to the weights file.\r\n' +
'    --verbose\r\n' +
'        Print detailed output.\r\n' +
'\r\n'+
'    --help\r\n' +
'        Display this help dialog.\r\n' +
'\r\n'+
'Examples:' +
'\r\n'+
'    Run a GA with a population size of 50, averaging fitness scores over 10 runs per candidate,\r\n' +
'    using the highest grid cell value as the fitness measure:\r\n' +
'\r\n'+
'        run_GA.js -p=50 -r=10 -f=maxval' +
'\r\n'+
'\r\n'+
'    Run a GA with a population size of 1000, mutation rate of 0.15 for 100 generations:\r\n' +
'\r\n'+
'        run_GA.js -m=0.15 -g=100 -p=1000' +
'\r\n'+
'\r\n'+
'    Run a GA with a population size of 500, save the best candidate under the key \'test\'.\r\n' +
'\r\n'+
'        run_GA.js -g=100 --save -w=test' +
'\r\n';

    console.log(helpStr);
}

function getRandomSolution(callback) {
    var solution = {
        weights: AIWeights.getRandom(),
    };
    callback(solution);
}

function crossover(parent1, parent2, callback) {
    var child = { weights: {} }
    for (var key in parent1.weights) {
        child.weights[key] = {};
        var weightSet = parent1.weights[key];
        for (var dir in weightSet) {
            if (Math.random() > 0.5) {
                child.weights[key][dir] = parent1.weights[key][dir];
            }
            else {
                child.weights[key][dir] = parent2.weights[key][dir];
            }
        }
    }
    callback(child);
}

function mutate(solution, callback) {
    for (var key in solution.weights) {
        for (var dir in solution.weights[key]) {
            if (Math.random() < opts.mutationRate) {
                solution.weights[key][dir] = Math.random()*2-1;
            }
        }
    }
    callback(solution);
}

function fitness(solution, callback) {
    var fitness = 0;

    for (var i=0; i<opts.runsPerCandidate; i++) {
        var aiPlayer = new AIPlayer(solution.weights);
        var aiInputManager = new AIInputManager(aiPlayer);

        var GM = new GameManager(4, aiInputManager, DummyActuator, LocalStorageManager);
        aiInputManager.setGameManager(GM);
        aiInputManager.run(function() { return GM.isGameTerminated() }, GM);

        if (opts.fitnessMeasure === 'score') {
          fitness += GM.score;
        }
        else if (opts.fitnessMeasure === 'maxval') {
            fitness += GM.grid.maxValue();
        }
    }
    fitness = fitness / opts.runsPerCandidate;
    if (stash.bar) {
        stash.bar.tick();
    }
    callback(fitness);
}

function stopCriteria() {
    return (this.generation == opts.maxGenerations)
}

var Task = require('./node_modules/genetic/lib').Task,
    options = {
    getRandomSolution : getRandomSolution,
    popSize : opts.popSize,
    stopCriteria : stopCriteria,
    fitness : fitness,
    minimize : false,
    mutateProbability : opts.mutationRate,
    mutate : mutate,
    crossoverProbability : 0.3,
    crossover : crossover
}

t = new Task(options);

var bestHistoricalCandidate;

//TODO: allow for more granular control of GA output
if (opts.verbose) {
    t.on('run start', function () { console.log('run start');})
    t.on('init start', function () { console.log('init start') })
 //   t.on('init end', function (pop) { console.log('init end', pop) })
    t.on('loop start', function () { console.log('loop start') })
    t.on('loop end', function () { console.log('loop end') })
    t.on('iteration start', function (generation) { console.log('\r\nITERATION',generation,'START') })
    t.on('iteration end', function () { console.log('iteration end') })
    t.on('calcFitness start', function () {
        console.log('calcFitness start (' + opts.popSize*opts.runsPerCandidate + ' games total).');
        stash.bar = new ProgressBar('[:current/:total] [:bar] [:elapseds elapsed]', {
            total: opts.popSize,
            width: 100,
        });
    });
//    t.on('calcFitness end', function (pop) { console.log('calcFitness end', pop) })
    t.on('parent selection start', function () { console.log('parent selection start') })
    //t.on('parent selection end', function (parents) { console.log('parent selection end ',parents) })
    t.on('reproduction start', function () { console.log('reproduction start') })

//    t.on('find sum', function () { console.log('find sum') })
//    t.on('find sum end', function (sum) { console.log('find sum end', sum) })
    t.on('statistics', function (statistics) {
        console.log('statistics:');
        console.log('    minScore: ',statistics.minScore);
        console.log('    maxScore: ',statistics.maxScore);
        console.log('    avgScore: ',statistics.avg);
        if (typeof bestHistoricalCandidate === 'undefined'
            || statistics.max.score > bestHistoricalCandidate.score) {
            bestHistoricalCandidate = statistics.max;
        }
        if (bestHistoricalCandidate) console.log('    (bestOverallScore:',bestHistoricalCandidate.score+')');
    });

    t.on('normalize start', function () { console.log('normalize start') })
    t.on('normalize end', function (normalized) { console.log('normalize end',normalized) })
    t.on('child forming start', function () { console.log('child forming start') })
    //t.on('child forming end', function (children) { console.log('child forming end',children) })
    t.on('child selection start', function () { console.log('child selection start') })
    //t.on('child selection end', function (population) { console.log('child selection end',population) })

//    t.on('mutate', function () { console.log('MUTATION!') })

    //t.on('reproduction end', function (children) { console.log('reproduction end',children) })
}
t.on('error', function (error) { console.log('ERROR - ', error) })
t.on('run finished', function (results) {
    console.log('RUN FINISHED - ', JSON.stringify(results,null,2) );

    var bestCandidate = results.max.score > bestHistoricalCandidate.score
        ? results.max
        : bestHistoricalCandidate;
    console.log('BEST OVERALL CANDIDATE: ', JSON.stringify(bestCandidate,null,2));

    if (opts.save) {
        var weightsKey = opts.weightsKey || opts.fitnessMeasure;
        bestCandidate.fitness = bestCandidate.score;
        bestCandidate.fitnessMeasure = opts.fitnessMeasure;
        delete bestCandidate.score;

        AIWeights.set( weightsKey, bestCandidate );
        AIWeights.save();
    }
    process.exit(0);
});

t.run();
<commit_msg>Enable output of GA run stats with gnuplot<commit_after>#!/usr/bin/env node

var fs          = require('fs');
var gnuplot     = require('gnuplot');
var ProgressBar = require('progress');
var tmp         = require('tmp');

var AIInputManager      = require('./ai_input_manager.js');
var AIPlayer            = require('./ai_player.js');
var AIWeights           = require('./ai_weights.js');
var DummyActuator       = require('./dummy_actuator.js');
var GameManager         = require('./game_manager.js');
var LocalStorageManager = require('./dummy_storage_manager.js');

var opts = {
    verbose: false,
    popSize: 500,
    mutationRate: 0.05,
    maxGenerations: 1000,
    runsPerCandidate: 5,
    fitnessMeasure: 'score',
    save: false,
};

var stash = {
    stats: [],
};

var args = process.argv.slice(2);
args.forEach(function (val, index, array) {
    if (val === '--verbose' || val === '-v') {
        opts.verbose = true;
    }
    else if (val.match(/(-s|--save)/)) {
        opts.save = true;
    }
    else if (val.match(/(-p|--popsize)=\d+/)) {
        opts.popSize = parseInt( val.split('=')[1] );
    }
    else if (val.match(/(-g|--max_generations)=\d+/)) {
        opts.maxGenerations = parseInt( val.split('=')[1] );
    }
    else if (val.match(/(-m|--mutation_rate)=\d+(\.\d+)?/)) {
        opts.mutationRate = parseFloat( val.split('=')[1] );
    }
    else if (val.match(/(-r|--runs)=\d+/)) {
        opts.runsPerCandidate = parseInt( val.split('=')[1] );
    }
    else if (val.match(/(-f|--fitness)=(score|maxval)/)) {
        opts.fitnessMeasure = val.split('=')[1];
    }
    else if (val.match(/(-w|--weights_key)=\w+/)) {
        opts.weightsKey = val.split('=')[1];
    }
    else if (val.match(/(-p|--plot)=.+/)) {
        opts.plotPath = val.split('=')[1];
    }
    else if (val === '--help') {
        help();
        process.exit(0);
    }
    else {
        console.log('Invalid argument ' + val);
        process.exit(1);
    }
});

function help() {
    var helpStr =
"USAGE: run_GA.js [OPTIONS]\r\n" +
'\r\n'+
'Runs genetic algorithm to train (breed?) progressively better 2048 AI players \r\n' +
'\r\n'+
'Options:\r\n' +
'    --popsize -p\r\n' +
'        Number of candidates per generation. Default: 500.\r\n' +
'    --max_generations -g\r\n' +
'        Generations to run GA. Default 1000.\r\n' +
'    --mutation_rate -m\r\n' +
'        Likelihood of mutation in new offspring. Default: 0.05 (i.e. 5%).\r\n' +
'    --runs -r\r\n' +
'        How many games each candidate should play to calculate averaged fitness.\r\n' +
'        Default: 5\r\n' +
'    --fitness -f\r\n' +
'        Fitness measure to use. One of:\r\n' +
'           score  - player score upon game over (default).\r\n' +
'           maxval - the highest value grid cell achieved upon game over.\r\n' +
'    --weights_key -w\r\n' +
'        Save best candidate weights under the given key.\r\n' +
'    --plot -p\r\n' +
'        Output a graph of GA stats to given path\r\n' +
'\r\n'+
'    --save\r\n' +
'        Save the best candidate\'s weights to the weights file.\r\n' +
'    --verbose\r\n' +
'        Print detailed output.\r\n' +
'\r\n'+
'    --help\r\n' +
'        Display this help dialog.\r\n' +
'\r\n'+
'Examples:' +
'\r\n'+
'    Run a GA with a population size of 50, averaging fitness scores over 10 runs per candidate,\r\n' +
'    using the highest grid cell value as the fitness measure:\r\n' +
'\r\n'+
'        run_GA.js -p=50 -r=10 -f=maxval' +
'\r\n'+
'\r\n'+
'    Run a GA with a population size of 1000, mutation rate of 0.15 for 100 generations:\r\n' +
'\r\n'+
'        run_GA.js -m=0.15 -g=100 -p=1000' +
'\r\n'+
'\r\n'+
'    Run a GA with a population size of 500, save the best candidate under the key \'test\'.\r\n' +
'\r\n'+
'        run_GA.js -g=100 --save -w=test' +
'\r\n';

    console.log(helpStr);
}

function getRandomSolution(callback) {
    var solution = {
        weights: AIWeights.getRandom(),
    };
    callback(solution);
}

function crossover(parent1, parent2, callback) {
    var child = { weights: {} }
    for (var key in parent1.weights) {
        child.weights[key] = {};
        var weightSet = parent1.weights[key];
        for (var dir in weightSet) {
            if (Math.random() > 0.5) {
                child.weights[key][dir] = parent1.weights[key][dir];
            }
            else {
                child.weights[key][dir] = parent2.weights[key][dir];
            }
        }
    }
    callback(child);
}

function mutate(solution, callback) {
    for (var key in solution.weights) {
        for (var dir in solution.weights[key]) {
            if (Math.random() < opts.mutationRate) {
                solution.weights[key][dir] = Math.random()*2-1;
            }
        }
    }
    callback(solution);
}

function fitness(solution, callback) {
    var fitness = 0;

    for (var i=0; i<opts.runsPerCandidate; i++) {
        var aiPlayer = new AIPlayer(solution.weights);
        var aiInputManager = new AIInputManager(aiPlayer);

        var GM = new GameManager(4, aiInputManager, DummyActuator, LocalStorageManager);
        aiInputManager.setGameManager(GM);
        aiInputManager.run(function() { return GM.isGameTerminated() }, GM);

        if (opts.fitnessMeasure === 'score') {
          fitness += GM.score;
        }
        else if (opts.fitnessMeasure === 'maxval') {
            fitness += GM.grid.maxValue();
        }
    }
    fitness = fitness / opts.runsPerCandidate;
    if (stash.bar) {
        stash.bar.tick();
    }
    callback(fitness);
}

function stopCriteria() {
    return (this.generation == opts.maxGenerations)
}

var Task = require('./node_modules/genetic/lib').Task,
    options = {
    getRandomSolution : getRandomSolution,
    popSize : opts.popSize,
    stopCriteria : stopCriteria,
    fitness : fitness,
    minimize : false,
    mutateProbability : opts.mutationRate,
    mutate : mutate,
    crossoverProbability : 0.3,
    crossover : crossover
}

t = new Task(options);

var bestHistoricalCandidate;

//TODO: allow for more granular control of GA output
if (opts.verbose) {
    t.on('run start', function () { console.log('run start');})
    t.on('init start', function () { console.log('init start') })
 //   t.on('init end', function (pop) { console.log('init end', pop) })
    t.on('loop start', function () { console.log('loop start') })
    t.on('loop end', function () { console.log('loop end') })
    t.on('iteration start', function (generation) {
        console.log('\r\nITERATION',generation,'START')
        stash.currentGeneration = generation;
    })
    t.on('iteration end', function () { console.log('iteration end') })
    t.on('calcFitness start', function () {
        console.log('calcFitness start (' + opts.popSize*opts.runsPerCandidate + ' games total).');
        stash.bar = new ProgressBar('[:current/:total] [:bar] [:elapseds elapsed]', {
            total: opts.popSize,
            width: 100,
        });
    });
//    t.on('calcFitness end', function (pop) { console.log('calcFitness end', pop) })
    t.on('parent selection start', function () { console.log('parent selection start') })
    //t.on('parent selection end', function (parents) { console.log('parent selection end ',parents) })
    t.on('reproduction start', function () { console.log('reproduction start') })

//    t.on('find sum', function () { console.log('find sum') })
//    t.on('find sum end', function (sum) { console.log('find sum end', sum) })
    t.on('statistics', function (statistics) {
        console.log('statistics:');
        console.log('    minScore: ',statistics.minScore);
        console.log('    maxScore: ',statistics.maxScore);
        console.log('    avgScore: ',statistics.avg);
        if (typeof bestHistoricalCandidate === 'undefined'
            || statistics.max.score > bestHistoricalCandidate.score) {
            bestHistoricalCandidate = statistics.max;
        }
        if (bestHistoricalCandidate) console.log('    (bestOverallScore:',bestHistoricalCandidate.score+')');

        if (opts.plotPath) {
            stash.stats[stash.currentGeneration] = {
                min:  statistics.minScore,
                max:  statistics.maxScore,
                mean: statistics.avg,
                x: stash.currentGeneration-1,
            };
        }
    });

    t.on('normalize start', function () { console.log('normalize start') })
    t.on('normalize end', function (normalized) { console.log('normalize end',normalized) })
    t.on('child forming start', function () { console.log('child forming start') })
    //t.on('child forming end', function (children) { console.log('child forming end',children) })
    t.on('child selection start', function () { console.log('child selection start') })
    //t.on('child selection end', function (population) { console.log('child selection end',population) })

//    t.on('mutate', function () { console.log('MUTATION!') })

    //t.on('reproduction end', function (children) { console.log('reproduction end',children) })
}
t.on('error', function (error) { console.log('ERROR - ', error) })
t.on('run finished', function (results) {
    console.log('RUN FINISHED - ', JSON.stringify(results,null,2) );

    var bestCandidate = results.max.score > bestHistoricalCandidate.score
        ? results.max
        : bestHistoricalCandidate;
    console.log('BEST OVERALL CANDIDATE: ', JSON.stringify(bestCandidate,null,2));

    if (opts.save) {
        var weightsKey = opts.weightsKey || opts.fitnessMeasure;
        bestCandidate.fitness = bestCandidate.score;
        bestCandidate.fitnessMeasure = opts.fitnessMeasure;
        delete bestCandidate.score;

        AIWeights.set( weightsKey, bestCandidate );
        AIWeights.save();
    }

    if (opts.plotPath) {
        var tmpDir = tmp.dirSync();
        var tmpDataFile = tmpDir.name + '/output.dat';

        var outputStr = '';
        stash.stats.map(function (elem) {
            outputStr += [elem.x,elem.min,elem.max,elem.mean].join(' ');
            outputStr += '\r\n';
        });
        console.log(outputStr);

        fs.writeFileSync(
            tmpDataFile,
            outputStr
        );

        console.log('Saving plot to:',opts.plotPath);
        gnuplot()
            .set('term png')
            .set('output "' + opts.plotPath + '"')
            .set('title "GA statistics"')
            .set('xrange [0:' + opts.maxGenerations + ']')
            .set('yrange [0:*]')
            .set('xlabel "Generations"')
            .set('ylabel "Fitness"')
            .set('style data lines')
            .set('grid')
            .set('zeroaxis')
            .plot(
                '"' + tmpDataFile + '" using 1:2:3 w filledcurves lc rgb "#00BB00" fill solid 0.1 notitle' +
                ', "" using 4 title "mean fitness" lc rgb "#0000DD" lw 2' +
                ', "" using 2 notitle lc rgb "#EE0000" lt 2' +
                ', "" using 3 notitle lc rgb "#00BB00" lt 2' +
                ''
            )
            .end();
    }
    process.exit(0);
});

t.run();
<|endoftext|>


<commit_before>require('dotenv').config()

import express from 'express'
import mongoose from 'mongoose'
import bodyParser from 'body-parser'
import logger from './lib/logger'
import routes from './routes'

const app = express()
const PORT = process.env.PORT || 8080

// Service middleware
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())
app.use(require('morgan')('short', {stream: logger.stream}))

// Mongo connection
let mongoOpts = {
  poolSize: Number(process.env.MONGO_POOLSIZE) || 4,
  useMongoClient: true
}
let mongoUri = `mongodb://${process.env.MONGO_HOST}/${process.env.MONGO_DB}`
mongoose.connect(mongoUri, mongoOpts)

// Service routes
app.use('/auth', routes)

// Service status route
app.get('/status', (req, res) => {
  res.status(200).send('OK')
})

// If Route not found, 404
app.all('*', (req, res) => {
  res.status(404).send('Not Found')
})

// Run service
app.listen(PORT, () => {
  logger.debug(`[${process.env.NODE_ENV}] Auth-Service ready on port ${PORT}`)
})

export default app
<commit_msg>Added redis session<commit_after>require('dotenv').config()

import express from 'express'
import mongoose from 'mongoose'
import bodyParser from 'body-parser'
import logger from './lib/logger'
import routes from './routes'
import session from 'express-session'
import redis from 'redis'
import connectRedis from 'connect-redis'

const app = express()
const PORT = process.env.PORT || 8080

const redisStore = connectRedis(session)
const redisClient = redis.createClient()

// Service middleware
app.use(require('morgan')('short', {stream: logger.stream}))
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())

// Redis Session
let sessionOpts = {
  secret: process.env.REDIS_SECRET,
  store: new redisStore({
    host: process.env.REDIS_HOST,
    port: process.env.REDIS_PORT,
    client: redisClient,
    ttl: 2260
  }),
  saveUninitialized: true,
  resave: false
}
app.use(session(sessionOpts))

// Mongo connection
let mongoOpts = {
  poolSize: Number(process.env.MONGO_POOLSIZE) || 4,
  useMongoClient: true
}
let mongoUri = `mongodb://${process.env.MONGO_HOST}/${process.env.MONGO_DB}`
mongoose.connect(mongoUri, mongoOpts)

// Service routes
app.use('/auth', routes)

// Service status route
app.get('/status', (req, res) => {
  res.status(200).send('OK')
})

// If Route not found, 404
app.all('*', (req, res) => {
  res.status(404).send('Not Found')
})

// Run service
app.listen(PORT, () => {
  logger.debug(`[${process.env.NODE_ENV}] Auth-Service ready on port ${PORT}`)
})

export default app
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Fri Jun 26 2015 07:47:18 GMT+0100 (BST)

module.exports = function(config) {
  config.set({

    // list of files / patterns to load in the browser
    files: [
      'test/**/*.js'
//      'app/scripts/**/*.js'
    ],

    // base path that will be used to resolve all patterns (eg. files, exclude)
    //basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files to exclude
    exclude: [
      'app/scripts/app.js'
    ],

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      '**/app/scripts/**/*.js': ['coverage']
    },

    // optionally, configure the reporter
    coverageReporter: {
      dir: 'test/reports/coverage',
      reporters: [
        // reporters not supporting the `file` property
        { type: 'html', subdir: 'report-html' },
        { type: 'lcov', subdir: 'report-lcov' },
        // reporters supporting the `file` property, use `subdir` to directly
        // output them in the `dir` directory
        { type: 'cobertura', subdir: '.', file: 'cobertura.txt' },
        { type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt' },
        { type: 'teamcity', subdir: '.', file: 'teamcity.txt' },
        { type: 'text', subdir: '.', file: 'text.txt' },
        { type: 'text-summary', subdir: '.', file: 'text-summary.txt' },
      ]
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_DEBUG,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    //browsers: ['Chrome'],
    browsers: ['PhantomJS'],

    captureTimeout: 60000,

    plugins : [
             'karma-jasmine',
             'karma-coverage',
             'karma-phantomjs-launcher',
             'karma-chrome-launcher',
             'karma-firefox-launcher',
             'karma-ie-launcher'
    ],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  });
};
<commit_msg>fix:commented browsers plugins<commit_after>// Karma configuration
// Generated on Fri Jun 26 2015 07:47:18 GMT+0100 (BST)

module.exports = function(config) {
  config.set({

    // list of files / patterns to load in the browser
    files: [
      'test/**/*.js'
//      'app/scripts/**/*.js'
    ],

    // base path that will be used to resolve all patterns (eg. files, exclude)
    //basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files to exclude
    exclude: [
      'app/scripts/app.js'
    ],

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      '**/app/scripts/**/*.js': ['coverage']
    },

    // optionally, configure the reporter
    coverageReporter: {
      dir: 'test/reports/coverage',
      reporters: [
        // reporters not supporting the `file` property
        { type: 'html', subdir: 'report-html' },
        { type: 'lcov', subdir: 'report-lcov' },
        // reporters supporting the `file` property, use `subdir` to directly
        // output them in the `dir` directory
        { type: 'cobertura', subdir: '.', file: 'cobertura.txt' },
        { type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt' },
        { type: 'teamcity', subdir: '.', file: 'teamcity.txt' },
        { type: 'text', subdir: '.', file: 'text.txt' },
        { type: 'text-summary', subdir: '.', file: 'text-summary.txt' },
      ]
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_DEBUG,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    //browsers: ['Chrome'],
    browsers: ['PhantomJS'],

    captureTimeout: 60000,

    plugins : [
             'karma-jasmine',
             'karma-coverage',
//             'karma-phantomjs-launcher',
//             'karma-chrome-launcher',
//             'karma-firefox-launcher',
//             'karma-ie-launcher'
    ],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  });
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import {AutoSizer, Column, Table, SortDirection} from 'react-virtualized';
import {apiFetchJson} from '../helpers/apiFetchJson';
import {rankedByGradeLevel} from '../helpers/SortHelpers';
import {maybeCapitalize} from '../helpers/pretty';
import {prettyProgramText} from '../helpers/PerDistrict';
import {updateGlobalStylesToTakeFullHeight} from '../helpers/globalStylingWorkarounds';
import GenericLoader from '../components/GenericLoader';
import SectionHeading from '../components/SectionHeading';
import HouseBadge from '../components/HouseBadge';
import School from '../components/School';
import FilterStudentsBar from './FilterStudentsBar';

// Shows a list of students for the educator.  Intended as a directory
// for navigation, showing everything that's in the student searchbar all at once.
// This isn't for doing analysis or looking at data.
export default class MyStudentsPage extends React.Component {
  constructor(props) {
    super(props);
    this.fetchStudents = this.fetchStudents.bind(this);
    this.renderStudents = this.renderStudents.bind(this);
  }

  componentDidMount() {
    updateGlobalStylesToTakeFullHeight();
  }

  fetchStudents() {
    const url = `/api/educators/my_students_json`;
    return apiFetchJson(url);
  }

  render() {
    return (

        <GenericLoader
          promiseFn={this.fetchStudents}
          style={styles.flexVertical}
          render={this.renderStudents} />

    );
  }

  renderStudents(json) {
    const {students} = json;
    return <MyStudentsPageView students={students} />;
  }
}

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

    this.state = {
      sortBy: 'name',
      sortDirection: SortDirection.ASC,
    };
    this.onTableSort = this.onTableSort.bind(this);
    this.renderName = this.renderName.bind(this);
    this.renderSchool = this.renderSchool.bind(this);
  }

  orderedStudents(students) {
    const {sortBy, sortDirection} = this.state;

    // map dataKey to an accessor/sort function
    const sortFns = {
      fallback(student) { return student[sortBy]; },
      grade(student) { return rankedByGradeLevel(student.grade); },
      school(student) { return student.school.name; },
      name(student) { return `${student.last_name}, ${student.first_name}`; }
    };
    const sortFn = sortFns[sortBy] || sortFns.fallback;
    const sortedRows = _.sortBy(students, sortFn);

    // respect direction
    return (sortDirection == SortDirection.DESC)
      ? sortedRows.reverse()
      : sortedRows;
  }

  onTableSort({defaultSortDirection, event, sortBy, sortDirection}) {
    if (sortBy === this.state.sortBy) {
      const oppositeSortDirection = (this.state.sortDirection == SortDirection.DESC)
        ? SortDirection.ASC
        : SortDirection.DESC;
      this.setState({ sortDirection: oppositeSortDirection });
    } else {
      this.setState({sortBy});
    }
  }

  render() {
    const {students} = this.props;

    return (

        <SectionHeading>My students</SectionHeading>
        <FilterStudentsBar students={students} style={{...styles.flexVertical, marginLeft: 10, marginTop: 20}}>
          {filteredStudents => this.renderTable(filteredStudents)}
        </FilterStudentsBar>

    );
  }

  renderTable(filteredStudents) {
    const {sortDirection, sortBy} = this.state;
    const sortedStudents = this.orderedStudents(filteredStudents);
    const rowHeight = 30;

    // In conjuction with the filtering, this can lead to a warning in development.
    // See https://github.com/bvaughn/react-virtualized/issues/1119 for more.
    return (
      <AutoSizer style={{marginTop: 20}}>
        {({width, height}) => (

 sortedStudents[index]}
            sort={this.onTableSort}
            sortBy={sortBy}
            sortDirection={sortDirection}
            >
            <Column
              label='Name'
              dataKey='name'
              cellRenderer={this.renderName}
              flexGrow={1}
              width={150}
            />
            <Column
              label='School'
              dataKey='school'
              cellRenderer={this.renderSchool}
              width={200}
            />
            <Column
              label='Grade'
              dataKey='grade'
              width={80}
            />
            <Column
             label='Program'
             dataKey='program'
             cellRenderer={this.renderProgram}
             width={150}
            />
            <Column
              label='House'
              dataKey='house'
              cellRenderer={this.renderHouse}
              width={150}
            />
            <Column
              label='Counselor'
              dataKey='counselor'
              cellDataGetter={({rowData}) => maybeCapitalize(rowData.counselor)}
              width={150}
            />
            <Column
              label='SPED Liaison'
              dataKey='sped_liaison'
              cellDataGetter={({rowData}) => maybeCapitalize(rowData.sped_liaison)}
              width={150}
            />

        )}
      </AutoSizer>
    );
  }

  renderName(cellProps) {
    const student = cellProps.rowData;
    return <a style={{fontSize: 14}} href={`/students/${student.id}`} target="_blank">{student.first_name} {student.last_name};
  }

  renderSchool(cellProps) {
    const student = cellProps.rowData;
    return <School {...student.school} />;
  }

  renderHouse(cellProps) {
    const student = cellProps.rowData;
    return student.house && <HouseBadge house={student.house} />;
  }

  renderProgram(cellProps) {
    const student = cellProps.rowData;
    return prettyProgramText(student.program_assigned, student.sped_placement);
  }
}
MyStudentsPageView.propTypes = {
  students: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number.isRequired,
    first_name: PropTypes.string.isRequired,
    last_name: PropTypes.string.isRequired,
    house: PropTypes.string,
    counselor: PropTypes.string,
    grade: PropTypes.string.isRequired,
    school: PropTypes.shape({
      id: PropTypes.number.isRequired,
      name: PropTypes.string.isRequired
    }).isRequired,
  })).isRequired
};

const styles = {
  flexVertical: {
    display: 'flex',
    flex: 1,
    flexDirection: 'column'
  }
};<commit_msg>Tune MyStudents column widths<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import {AutoSizer, Column, Table, SortDirection} from 'react-virtualized';
import {apiFetchJson} from '../helpers/apiFetchJson';
import {rankedByGradeLevel} from '../helpers/SortHelpers';
import {maybeCapitalize} from '../helpers/pretty';
import {prettyProgramText} from '../helpers/PerDistrict';
import {updateGlobalStylesToTakeFullHeight} from '../helpers/globalStylingWorkarounds';
import GenericLoader from '../components/GenericLoader';
import SectionHeading from '../components/SectionHeading';
import HouseBadge from '../components/HouseBadge';
import School from '../components/School';
import FilterStudentsBar from './FilterStudentsBar';

// Shows a list of students for the educator.  Intended as a directory
// for navigation, showing everything that's in the student searchbar all at once.
// This isn't for doing analysis or looking at data.
export default class MyStudentsPage extends React.Component {
  constructor(props) {
    super(props);
    this.fetchStudents = this.fetchStudents.bind(this);
    this.renderStudents = this.renderStudents.bind(this);
  }

  componentDidMount() {
    updateGlobalStylesToTakeFullHeight();
  }

  fetchStudents() {
    const url = `/api/educators/my_students_json`;
    return apiFetchJson(url);
  }

  render() {
    return (

        <GenericLoader
          promiseFn={this.fetchStudents}
          style={styles.flexVertical}
          render={this.renderStudents} />

    );
  }

  renderStudents(json) {
    const {students} = json;
    return <MyStudentsPageView students={students} />;
  }
}

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

    this.state = {
      sortBy: 'name',
      sortDirection: SortDirection.ASC,
    };
    this.onTableSort = this.onTableSort.bind(this);
    this.renderName = this.renderName.bind(this);
    this.renderSchool = this.renderSchool.bind(this);
  }

  orderedStudents(students) {
    const {sortBy, sortDirection} = this.state;

    // map dataKey to an accessor/sort function
    const sortFns = {
      fallback(student) { return student[sortBy]; },
      grade(student) { return rankedByGradeLevel(student.grade); },
      school(student) { return student.school.name; },
      name(student) { return `${student.last_name}, ${student.first_name}`; }
    };
    const sortFn = sortFns[sortBy] || sortFns.fallback;
    const sortedRows = _.sortBy(students, sortFn);

    // respect direction
    return (sortDirection == SortDirection.DESC)
      ? sortedRows.reverse()
      : sortedRows;
  }

  onTableSort({defaultSortDirection, event, sortBy, sortDirection}) {
    if (sortBy === this.state.sortBy) {
      const oppositeSortDirection = (this.state.sortDirection == SortDirection.DESC)
        ? SortDirection.ASC
        : SortDirection.DESC;
      this.setState({ sortDirection: oppositeSortDirection });
    } else {
      this.setState({sortBy});
    }
  }

  render() {
    const {students} = this.props;

    return (

        <SectionHeading>My students</SectionHeading>
        <FilterStudentsBar students={students} style={{...styles.flexVertical, marginLeft: 10, marginTop: 20}}>
          {filteredStudents => this.renderTable(filteredStudents)}
        </FilterStudentsBar>

    );
  }

  renderTable(filteredStudents) {
    const {sortDirection, sortBy} = this.state;
    const sortedStudents = this.orderedStudents(filteredStudents);
    const rowHeight = 40; // for two lines of student names

    // In conjuction with the filtering, this can lead to a warning in development.
    // See https://github.com/bvaughn/react-virtualized/issues/1119 for more.
    return (
      <AutoSizer style={{marginTop: 20}}>
        {({width, height}) => (

 sortedStudents[index]}
            sort={this.onTableSort}
            sortBy={sortBy}
            sortDirection={sortDirection}
            >
            <Column
              label='Name'
              dataKey='name'
              cellRenderer={this.renderName}
              flexGrow={1}
              width={250}
            />
            <Column
              label='School'
              dataKey='school'
              cellRenderer={this.renderSchool}
              width={100}
            />
            <Column
              label='Grade'
              dataKey='grade'
              width={80}
            />
            <Column
             label='Program'
             dataKey='program'
             cellRenderer={this.renderProgram}
             width={150}
            />
            <Column
              label='House'
              dataKey='house'
              cellRenderer={this.renderHouse}
              width={150}
            />
            <Column
              label='Counselor'
              dataKey='counselor'
              cellDataGetter={({rowData}) => maybeCapitalize(rowData.counselor)}
              width={100}
            />
            <Column
              label='SPED Liaison'
              dataKey='sped_liaison'
              cellDataGetter={({rowData}) => maybeCapitalize(rowData.sped_liaison)}
              width={100}
            />

        )}
      </AutoSizer>
    );
  }

  renderName(cellProps) {
    const student = cellProps.rowData;
    return <a style={{fontSize: 14}} href={`/students/${student.id}`} target="_blank">{student.first_name} {student.last_name};
  }

  renderSchool(cellProps) {
    const student = cellProps.rowData;
    return <School {...student.school} />;
  }

  renderHouse(cellProps) {
    const student = cellProps.rowData;
    return student.house && <HouseBadge house={student.house} />;
  }

  renderProgram(cellProps) {
    const student = cellProps.rowData;
    return prettyProgramText(student.program_assigned, student.sped_placement);
  }
}
MyStudentsPageView.propTypes = {
  students: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number.isRequired,
    first_name: PropTypes.string.isRequired,
    last_name: PropTypes.string.isRequired,
    house: PropTypes.string,
    counselor: PropTypes.string,
    grade: PropTypes.string.isRequired,
    school: PropTypes.shape({
      id: PropTypes.number.isRequired,
      name: PropTypes.string.isRequired
    }).isRequired,
  })).isRequired
};

const styles = {
  flexVertical: {
    display: 'flex',
    flex: 1,
    flexDirection: 'column'
  }
};<|endoftext|>


<commit_before>module.exports = {
  icons: [
    'addAccount',
    'americanExpress',
    'americanExpressSq',
    'americanExpressSquare',
    'animal',
    'application',
    'armchair',
    'autoColor3X',
    'autogenius',
    'autogenius',
    'back',
    'backRebrand',
    'badWeather',
    'bag',
    'bandagedFinger',
    'bandagedHead',
    'basicChair',
    'bbb',
    'birthdayHat',
    'boneJar',
    'bookSearch',
    'books',
    'calculator',
    'calendar',
    'camera',
    'car',
    'cart',
    'chat',
    'checkCircle',
    'checkMark-1',
    'checklist',
    'checklistFolded',
    'checkmark',
    'chevronDown',
    'chevronLeft',
    'chevronRight',
    'chevronUp',
    'clock',
    'close',
    'closeAccent',
    'computer',
    'dashboard',
    'digicert',
    'disability',
    'disabilityColor3X',
    'discount',
    'discountBadge',
    'discountBlue',
    'discountGreen',
    'discover',
    'discoverSquare',
    'dog-1',
    'dog',
    'dogBones',
    'dogBowl',
    'dogCone',
    'down',
    'earch',
    'earchRebrand',
    'earthquake',
    'ellipsis',
    'email',
    'excellentFace',
    'excellentFaceGreen',
    'eyePatch',
    'facebook',
    'fallingObjects',
    'family',
    'fineArt',
    'fireExtinguisher',
    'firearm',
    'flood',
    'forYou',
    'foundation',
    'fourBedroom',
    'furCoat',
    'furCoatGray',
    'golfEquipment',
    'goodFace',
    'goodFaceGrey',
    'googlePlus',
    'greenCar',
    'greenCheckWithCircle',
    'greenCheckmark',
    'guaranteedIssue',
    'hamburger',
    'hamburgerRebrand',
    'headAside',
    'health-1',
    'health',
    'healthColor3X',
    'healthPlan',
    'healthgenius',
    'healthgenius',
    'heart',
    'hmoPpo',
    'home',
    'homeBlack',
    'homeWhite',
    'hsaFsa',
    'hurricane',
    'idTheft',
    'ignOut',
    'ilverware',
    'ilverwareGray',
    'infinity',
    'instruments',
    'insurancegenius',
    'insurancegenius',
    'invite',
    'jewelry',
    'largeHome',
    'life',
    'lifeColor3X',
    'linkedin',
    'lock',
    'lockBlue',
    'luxurySofa',
    'madeInNy',
    'mastercard',
    'mastercardSquare',
    'medExam',
    'medicalExam',
    'medicalPayments',
    'medicalPaymentsBlue',
    'metlife',
    'moneyCloud',
    'moneygenius',
    'moneygenius',
    'more',
    'noMedExamNeededGreen',
    'noMedicalExamNeeded',
    'norton',
    'nortonSecured',
    'nortonW',
    'openBook',
    'overflow',
    'pawprint',
    'pencil',
    'personalLiability',
    'pet',
    'petColor3X',
    'petgenius',
    'petgenius',
    'pgLogo',
    'pgLogoBlack',
    'pgLogoOrange',
    'phone',
    'phoneRebrand',
    'pinterest',
    'plus',
    'policygeniusSymbol',
    'policygeniusSymbolCenter',
    'priceSticker',
    'priceTag',
    'questionMark',
    'questionMarkWhite',
    'quoteCards',
    'quotes',
    'rclLogo',
    'renters',
    'rentersColor3X',
    'returnOfPremium',
    'scales-1',
    'scales',
    'search',
    'searchRebrand',
    'shoppingCart',
    'signOut',
    'silverware',
    'silverwareGray',
    'star',
    'steeringWheel',
    'stethoscope',
    'stillwaterLogoBlack',
    'stillwaterLogoWhite',
    'studio',
    'stuff',
    'tar',
    'techgenius',
    'techgenius',
    'theftProtection',
    'thumbsUp-1',
    'thumbsUp',
    'tooltip',
    'tooltipBlack',
    'travelersColor3X',
    'tudio',
    'tuff',
    'tv',
    'twitter',
    'twoBedroom',
    'user',
    'usingTablet',
    'vandalizism',
    'veryPopular',
    'visa',
    'visaSquare',
    'visionColor3X',
    'waterDamage',
    'who',
    'xIcon',
    'yellowTriangle',
  ]
};
<commit_msg>Add circlePlus icon to icon constants<commit_after>module.exports = {
  icons: [
    'addAccount',
    'americanExpress',
    'americanExpressSq',
    'americanExpressSquare',
    'animal',
    'application',
    'armchair',
    'autoColor3X',
    'autogenius',
    'autogenius',
    'back',
    'backRebrand',
    'badWeather',
    'bag',
    'bandagedFinger',
    'bandagedHead',
    'basicChair',
    'bbb',
    'birthdayHat',
    'boneJar',
    'bookSearch',
    'books',
    'calculator',
    'calendar',
    'camera',
    'car',
    'cart',
    'chat',
    'checkCircle',
    'checkMark-1',
    'checklist',
    'checklistFolded',
    'checkmark',
    'chevronDown',
    'chevronLeft',
    'chevronRight',
    'chevronUp',
    'circlePlus',
    'clock',
    'close',
    'closeAccent',
    'computer',
    'dashboard',
    'digicert',
    'disability',
    'disabilityColor3X',
    'discount',
    'discountBadge',
    'discountBlue',
    'discountGreen',
    'discover',
    'discoverSquare',
    'dog-1',
    'dog',
    'dogBones',
    'dogBowl',
    'dogCone',
    'down',
    'earch',
    'earchRebrand',
    'earthquake',
    'ellipsis',
    'email',
    'excellentFace',
    'excellentFaceGreen',
    'eyePatch',
    'facebook',
    'fallingObjects',
    'family',
    'fineArt',
    'fireExtinguisher',
    'firearm',
    'flood',
    'forYou',
    'foundation',
    'fourBedroom',
    'furCoat',
    'furCoatGray',
    'golfEquipment',
    'goodFace',
    'goodFaceGrey',
    'googlePlus',
    'greenCar',
    'greenCheckWithCircle',
    'greenCheckmark',
    'guaranteedIssue',
    'hamburger',
    'hamburgerRebrand',
    'headAside',
    'health-1',
    'health',
    'healthColor3X',
    'healthPlan',
    'healthgenius',
    'healthgenius',
    'heart',
    'hmoPpo',
    'home',
    'homeBlack',
    'homeWhite',
    'hsaFsa',
    'hurricane',
    'idTheft',
    'ignOut',
    'ilverware',
    'ilverwareGray',
    'infinity',
    'instruments',
    'insurancegenius',
    'insurancegenius',
    'invite',
    'jewelry',
    'largeHome',
    'life',
    'lifeColor3X',
    'linkedin',
    'lock',
    'lockBlue',
    'luxurySofa',
    'madeInNy',
    'mastercard',
    'mastercardSquare',
    'medExam',
    'medicalExam',
    'medicalPayments',
    'medicalPaymentsBlue',
    'metlife',
    'moneyCloud',
    'moneygenius',
    'moneygenius',
    'more',
    'noMedExamNeededGreen',
    'noMedicalExamNeeded',
    'norton',
    'nortonSecured',
    'nortonW',
    'openBook',
    'overflow',
    'pawprint',
    'pencil',
    'personalLiability',
    'pet',
    'petColor3X',
    'petgenius',
    'petgenius',
    'pgLogo',
    'pgLogoBlack',
    'pgLogoOrange',
    'phone',
    'phoneRebrand',
    'pinterest',
    'plus',
    'policygeniusSymbol',
    'policygeniusSymbolCenter',
    'priceSticker',
    'priceTag',
    'questionMark',
    'questionMarkWhite',
    'quoteCards',
    'quotes',
    'rclLogo',
    'renters',
    'rentersColor3X',
    'returnOfPremium',
    'scales-1',
    'scales',
    'search',
    'searchRebrand',
    'shoppingCart',
    'signOut',
    'silverware',
    'silverwareGray',
    'star',
    'steeringWheel',
    'stethoscope',
    'stillwaterLogoBlack',
    'stillwaterLogoWhite',
    'studio',
    'stuff',
    'tar',
    'techgenius',
    'techgenius',
    'theftProtection',
    'thumbsUp-1',
    'thumbsUp',
    'tooltip',
    'tooltipBlack',
    'travelersColor3X',
    'tudio',
    'tuff',
    'tv',
    'twitter',
    'twoBedroom',
    'user',
    'usingTablet',
    'vandalizism',
    'veryPopular',
    'visa',
    'visaSquare',
    'visionColor3X',
    'waterDamage',
    'who',
    'xIcon',
    'yellowTriangle',
  ]
};
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import Group from 'react-group'
import map from 'lodash/map'
import Styled from 'rsg-components/Styled'
import Arguments from 'rsg-components/Arguments'
import Code from 'rsg-components/Code'
import JsDoc from 'rsg-components/JsDoc'
import Markdown from 'rsg-components/Markdown'
import Name from 'rsg-components/Name'
import Type from 'rsg-components/Type'
import Para from 'rsg-components/Para'
import Table from 'rsg-components/Table'
import getOriginColumn from 'rsg-components/OriginColumn'
import { unquote, showSpaces } from '../../utils/utils'
import propStyles from '../../utils/propStyles'

function renderType(type) {
	if (!type) {
		return 'unknown'
	}
	let name = type.name
	const names = type.names

	if (names) {
		name = names.join('|')
	}
	switch (name) {
		case 'arrayOf':
			return `${type.value.name}[]`
		case 'objectOf':
			return `{${renderType(type.value)}}`
		case 'instanceOf':
			return type.value
		default:
			return name
	}
}

function renderEnum(prop) {
	if (!Array.isArray(prop.type.value)) {
		return {prop.type.value}
	}

	const values = prop.type.value.map(({ value }) => (
		{showSpaces(unquote(value))}
	))
	return (

			One of:{' '}
			<Group separator=", " inline>
				{values}
			</Group>

	)
}

function renderShape(props) {
	const rows = []
	for (const name in props) {
		const prop = props[name]
		const description = prop.description
		rows.push(

				<Name>{name}</Name>
				{': '}
				<Type>{renderType(prop)}</Type>
				{description && ' — '}
				{description && <Markdown text={description} inline />}

		)
	}
	return rows
}

function renderDescription(myClasses) {
	return function renderDesc(prop) {
		const { description, tags = {} } = prop

		const extra = renderExtra(prop)

		return (

					{description && <Markdown text={description} />}

				{extra && <Para>{extra}</Para>}
				<JsDoc {...tags} />

		)
	}
}

function renderProperties(prop) {
	let { properties } = prop
	if (Array.isArray(properties)) {
		properties = properties.reduce((total, current) => {
			total.push({
				name: current.name,
				type: {
					name: renderType(
						total.length || current.type.names[0] !== 'undefined' ? current.type : prop.type
					)
				},
				description: current.description,

				// make each arguments display on its own line
				block: true
			})
			return total
		}, [])
	} else if (prop.type) {
		properties = [
			{
				name: '<anonymous>',
				type: {
					name: renderType(prop.type)
				}
			}
		]
	}

	return properties && properties.length > 0 ? <Arguments args={properties} /> : null
}

function renderExtra(prop) {
	const type = prop.type

	if (!type) {
		return null
	}
	switch (type.name) {
		case 'enum':
			return renderEnum(prop)
		case 'union':
			return renderUnion(prop)
		case 'shape':
			return renderShape(prop.type.value)
		case 'arrayOf':
			if (type.value.name === 'shape') {
				return renderShape(prop.type.value.value)
			}
			return null
		case 'objectOf':
			if (type.value.name === 'shape') {
				return renderShape(prop.type.value.value)
			}
			return null
		default:
			return null
	}
}

function renderUnion(prop) {
	if (!Array.isArray(prop.type.value)) {
		return {prop.type.value}
	}

	const values = prop.type.value.map((value, index) => (
		<Type key={`${value.name}-${index}`}>{renderType(value)}</Type>
	))
	return (

			One of type:{' '}
			<Group separator=", " inline>
				{values}
			</Group>

	)
}

function renderName(prop) {
	const { name, tags = {} } = prop
	return <Name deprecated={!!tags.deprecated}>{name}</Name>
}

export function getRowKey(row) {
	return row.name
}

export function propsToArray(props) {
	return map(props, (prop, name) => ({ ...prop, name }))
}

export const columns = (events, classes) => [
	{
		caption: 'Event name',
		render: renderName,
		className: classes.name
	},
	{
		caption: 'Description',
		render: renderDescription(classes),
		className: classes.description
	},
	...(events.some(p => p.properties || p.type)
		? [
				{
					caption: 'Properties',
					render: renderProperties
				}
		  ]
		: []),
	...getOriginColumn(events)
]

function EventsRenderer({ props, classes }) {
	const evts = propsToArray(props)
	return

}

EventsRenderer.propTypes = {
	props: PropTypes.object.isRequired,
	classes: PropTypes.object.isRequired
}

export default Styled(propStyles)(EventsRenderer)
<commit_msg>refactor: remove all the fat from EventsRenderer<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import map from 'lodash/map'
import Styled from 'rsg-components/Styled'
import Arguments from 'rsg-components/Arguments'
import JsDoc from 'rsg-components/JsDoc'
import Markdown from 'rsg-components/Markdown'
import Name from 'rsg-components/Name'
import Table from 'rsg-components/Table'
import getOriginColumn from 'rsg-components/OriginColumn'
import propStyles from '../../utils/propStyles'

function renderType(type) {
	if (!type) {
		return 'unknown'
	}
	let name = type.name
	const names = type.names

	if (names) {
		name = names.join('|')
	}
	switch (name) {
		case 'arrayOf':
			return `${type.value.name}[]`
		case 'objectOf':
			return `{${renderType(type.value)}}`
		case 'instanceOf':
			return type.value
		default:
			return name
	}
}

function renderDescription(myClasses) {
	return function renderDesc(prop) {
		const { description, tags = {} } = prop

		return (

					{description && <Markdown text={description} />}

				<JsDoc {...tags} />

		)
	}
}

function renderProperties(prop) {
	let { properties } = prop
	if (Array.isArray(properties)) {
		properties = properties.reduce((total, current) => {
			total.push({
				name: current.name,
				type: {
					name: renderType(
						total.length || current.type.names[0] !== 'undefined' ? current.type : prop.type
					)
				},
				description: current.description,

				// make each arguments display on its own line
				block: true
			})
			return total
		}, [])
	} else if (prop.type) {
		properties = [
			{
				name: '<anonymous>',
				type: {
					name: renderType(prop.type)
				}
			}
		]
	}

	return properties && properties.length > 0 ? <Arguments args={properties} /> : null
}

function renderName(prop) {
	const { name, tags = {} } = prop
	return <Name deprecated={!!tags.deprecated}>{name}</Name>
}

export function getRowKey(row) {
	return row.name
}

export function propsToArray(props) {
	return map(props, (prop, name) => ({ ...prop, name }))
}

export const columns = (events, classes) => [
	{
		caption: 'Event name',
		render: renderName,
		className: classes.name
	},
	{
		caption: 'Description',
		render: renderDescription(classes),
		className: classes.description
	},
	...(events.some(p => p.properties || p.type)
		? [
				{
					caption: 'Properties',
					render: renderProperties
				}
		  ]
		: []),
	...getOriginColumn(events)
]

function EventsRenderer({ props, classes }) {
	const evts = propsToArray(props)
	return

}

EventsRenderer.propTypes = {
	props: PropTypes.object.isRequired,
	classes: PropTypes.object.isRequired
}

export default Styled(propStyles)(EventsRenderer)
<|endoftext|>


<commit_before>var http = require("http");
var static = require('node-static');
var mongo = require('mongodb');
var formidable = require('formidable');

// Mongo server
var server = mongo.Server("127.0.0.1", 27017);
var db = new mongo.Db('peopleInformationDb', server, { safe: true });

// Node static: public_html folder
var file = new(static.Server)('./public');

// Create server
var srv = http.createServer(function(req, res){
    if(req.method === "GET"){
        req.on('end', function(){
            file.serve(req, res);
        });
    }
    else{
        var form = new formidable.IncomingForm();
        var fieldsInformation = null;
        form.parse(req, function(err, fields) {
            fieldsInformation = fields;
        });

        db.open(function(err, db) {
            if (err) return res.end("A problem ocured. Try again later.");

            db.collection("col_one", function(err, myCol) {
                if (err) return res.end("A problem ocured. Try again later.");

                var objectToInsert = {
                    "firstName" : fieldsInformation.firstName,
                    "lastName" : fieldsInformation.lastName,
                    "age" : fieldsInformation.age,
                    "gender" : fieldsInformation.gender,
                };

                myCol.insert(objectToInsert, function(){
                    res.end("Successfully saved.");
                    db.close();
                });
            });
        });
    }
});

srv.listen(8080);
<commit_msg>Removed end handler<commit_after>var http = require("http");
var static = require('node-static');
var mongo = require('mongodb');
var formidable = require('formidable');

// Mongo server
var server = mongo.Server("127.0.0.1", 27017);
var db = new mongo.Db('peopleInformationDb', server, { safe: true });

// Node static: public_html folder
var file = new(static.Server)('./public');

// Create server
var srv = http.createServer(function(req, res){
    if(req.method === "GET"){
        file.serve(req, res);
    }
    else{
        var form = new formidable.IncomingForm();
        var fieldsInformation = null;
        form.parse(req, function(err, fields) {
            fieldsInformation = fields;
        });

        db.open(function(err, db) {
            if (err) return res.end("A problem ocured. Try again later.");

            db.collection("col_one", function(err, myCol) {
                if (err) return res.end("A problem ocured. Try again later.");

                var objectToInsert = {
                    "firstName" : fieldsInformation.firstName,
                    "lastName" : fieldsInformation.lastName,
                    "age" : fieldsInformation.age,
                    "gender" : fieldsInformation.gender,
                };

                myCol.insert(objectToInsert, function(){
                    res.end("Successfully saved.");
                    db.close();
                });
            });
        });
    }
});

srv.listen(8080);
<|endoftext|>


<commit_before>import path from 'path';
export default class ES6Analyzer {
    constructor(fileReader) {
        this.fileReader = fileReader;
    }
    generateDependencyObject(filePath, deps = {}) {
        const basename = path.basename(filePath, '.js');
        deps[basename] = [];
        const tokens = this.fileReader.tokenize(filePath);
        let imports = getImportsFromTokens(tokens);
        if (imports.length === 0) {
            return deps;
        }
        imports.forEach((importedModule) => {
            let imported = {};
            imported[importedModule] = [];
            deps[basename].push(imported);
        });
        return deps;

        function getImportsFromTokens(tokens) {
            let index = 0;
            let imports = [];
            //stop condition: after a ";" token comes something different of "import"
            while (1) {
                while (index < tokens.length && tokens[index].value !== 'import')
                    index += 1;
                if (index === tokens.length)
                    break;
                while (tokens[index].value !== ';')
                    index += 1;
                imports.push(path.basename(tokens[index - 1].value.replace(/'/g,''), '.js'));
            }
            return imports;
        }
    }
}<commit_msg>Refactor. Need it for the next feature<commit_after>import path from 'path';
import fs from 'fs';
export default class ES6Analyzer {
    constructor(fileReader) {
        this.fileReader = fileReader;
    }
    generateDependencyObject(filePath, deps = {}) {
        const basename = path.basename(filePath, '.js');
        deps[basename] = [];
        const tokens = this.fileReader.tokenize(filePath);
        let imports = getImportsFromTokens(tokens);
        if (imports.length === 0) {
            return deps;
        }
        imports.forEach((importedPathFile) => {
            let imported = {};
            let moduleName = path.basename(importedPathFile.replace(/'/g,''), '.js');
            imported[moduleName] = [];
            deps[basename].push(imported);
        });
        return deps;

        function getImportsFromTokens(tokens) {
            let index = 0;
            let imports = [];
            //stop condition: after a ";" token comes something different of "import"
            while (1) {
                while (index < tokens.length && tokens[index].value !== 'import')
                    index += 1;
                if (index === tokens.length)
                    break;
                while (tokens[index].value !== ';')
                    index += 1;
                imports.push(tokens[index - 1].value);
            }
            return imports;
        }
    }
}<|endoftext|>


<commit_before>odoo.define('mail/static/src/models/activity/activity/js', function (require) {
'use strict';

const { registerNewModel } = require('mail/static/src/model/model_core.js');
const { attr, many2many, many2one } = require('mail/static/src/model/model_field.js');

function factory(dependencies) {

    class Activity extends dependencies['mail.model'] {

        //----------------------------------------------------------------------
        // Public
        //----------------------------------------------------------------------

        /**
         * Delete the record from database and locally.
         */
        async deleteServerRecord() {
            await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'unlink',
                args: [[this.id]],
            }));
            this.delete();
        }

        //----------------------------------------------------------------------
        // Public
        //----------------------------------------------------------------------

        /**
         * @static
         * @param {Object} data
         * @return {Object}
         */
        static convertData(data) {
            const data2 = {};
            if ('activity_category' in data) {
                data2.category = data.activity_category;
            }
            if ('can_write' in data) {
                data2.canWrite = data.can_write;
            }
            if ('create_data' in data) {
                data2.dateCreate = data.create_date;
            }
            if ('date_deadline' in data) {
                data2.dateDeadline = data.date_deadline;
            }
            if ('force_next' in data) {
                data2.force_next = data.force_next;
            }
            if ('icon' in data) {
                data2.icon = data.icon;
            }
            if ('id' in data) {
                data2.id = data.id;
            }
            if ('note' in data) {
                data2.note = data.note;
            }
            if ('res_id' in data) {
                data2.res_id = data.res_id;
            }
            if ('res_model' in data) {
                data2.res_model = data.res_model;
            }
            if ('state' in data) {
                data2.state = data.state;
            }
            if ('summary' in data) {
                data2.summary = data.summary;
            }

            // relation
            if ('activity_type_id' in data) {
                if (!data.activity_type_id) {
                    data2.type = [['unlink-all']];
                } else {
                    data2.type = [
                        ['insert', {
                            displayName: data.activity_type_id[1],
                            id: data.activity_type_id[0],
                        }],
                    ];
                }
            }
            if ('create_uid' in data) {
                if (!data.create_uid) {
                    data2.creator = [['unlink-all']];
                } else {
                    data2.creator = [
                        ['insert', {
                            id: data.create_uid[0],
                            partnerDisplayName: data.create_uid[1],
                        }],
                    ];
                }
            }
            if ('mail_template_ids' in data) {
                data2.mailTemplates = [['insert', data.mail_template_ids]];
            }
            if ('user_id' in data) {
                if (!data.user_id) {
                    data2.assignee = [['unlink-all']];
                } else {
                    data2.assignee = [
                        ['insert', {
                            id: data.user_id[0],
                            partnerDisplayName: data.user_id[1],
                        }],
                    ];
                }
            }

            return data2;
        }

        /**
         * Opens (legacy) form view dialog to edit current activity and updates
         * the activity when dialog is closed.
         */
        edit() {
            const action = {
                type: 'ir.actions.act_window',
                name: this.env._t("Schedule Activity"),
                res_model: 'mail.activity',
                view_mode: 'form',
                views: [[false, 'form']],
                target: 'new',
                context: {
                    default_res_id: this.res_id,
                    default_res_model: this.res_model,
                },
                res_id: this.id,
            };
            this.env.bus.trigger('do-action', {
                action,
                options: { on_close: () => this.fetchAndUpdate() },
            });
        }

        async fetchAndUpdate() {
            const [data] = await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'activity_format',
                args: [this.id],
            }));
            this.update(this.constructor.convertData(data));
            if (this.chatter) {
                this.chatter.refresh();
            }
        }

        /**
         * @param {Object} param0
         * @param {mail.attachment[]} [param0.attachments=[]]
         * @param {string|boolean} [param0.feedback=false]
         */
        async markAsDone({ attachments = [], feedback = false }) {
            const attachmentIds = attachments.map(attachment => attachment.id);
            await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'action_feedback',
                args: [[this.id]],
                kwargs: {
                    attachment_ids: attachmentIds,
                    feedback,
                },
                context: this.chatter ? this.chatter.context : {},
            }));
            if (this.chatter) {
                this.chatter.refresh();
            }
            this.delete();
        }

        /**
         * @param {Object} param0
         * @param {string} param0.feedback
         * @returns {Object}
         */
        async markAsDoneAndScheduleNext({ feedback }) {
            const action = await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'action_feedback_schedule_next',
                args: [[this.id]],
                kwargs: { feedback },
            }));
            const chatter = this.chatter;
            if (chatter) {
                this.chatter.refresh();
            }
            this.delete();
            this.env.bus.trigger('do-action', {
                action,
                options: {
                    on_close: () => {
                        if (chatter) {
                            chatter.refreshActivities();
                        }
                    },
                },
            });
        }

        //----------------------------------------------------------------------
        // Private
        //----------------------------------------------------------------------

        /**
         * @override
         */
        static _createRecordLocalId(data) {
            return `${this.modelName}_${data.id}`;
        }

        /**
         * @private
         * @returns {boolean}
         */
        _computeIsCurrentPartnerAssignee() {
            if (!this.assigneePartner || !this.messagingCurrentPartner) {
                return false;
            }
            return this.assigneePartner === this.messagingCurrentPartner;
        }

        /**
         * @private
         * @returns {mail.messaging}
         */
        _computeMessaging() {
            return [['link', this.env.messaging]];
        }
    }

    Activity.fields = {
        assignee: many2one('mail.user'),
        assigneePartner: many2one('mail.partner', {
            related: 'assignee.partner',
        }),
        attachments: many2many('mail.attachment', {
            inverse: 'activities',
        }),
        canWrite: attr({
            default: false,
        }),
        category: attr(),
        chatter: many2one('mail.chatter', {
            inverse: 'activities',
        }),
        creator: many2one('mail.user'),
        dateCreate: attr(),
        dateDeadline: attr(),
        force_next: attr({
            default: false,
        }),
        icon: attr(),
        id: attr(),
        isCurrentPartnerAssignee: attr({
            compute: '_computeIsCurrentPartnerAssignee',
            default: false,
            dependencies: [
                'assigneePartner',
                'messagingCurrentPartner',
            ],
        }),
        mailTemplates: many2many('mail.mail_template', {
            inverse: 'activities',
        }),
        messaging: many2one('mail.messaging', {
            compute: '_computeMessaging',
        }),
        messagingCurrentPartner: many2one('mail.partner', {
            related: 'messaging.currentPartner',
        }),
        /**
         * This value is meant to be returned by the server
         * (and has been sanitized before stored into db).
         * Do not use this value in a 't-raw' if the activity has been created
         * directly from user input and not from server data as it's not escaped.
         */
        note: attr(),
        res_id: attr(),
        res_model: attr(),
        state: attr(),
        summary: attr(),
        type: many2one('mail.activity_type', {
            inverse: 'activities',
        }),
    };

    Activity.modelName = 'mail.activity';

    return Activity;
}

registerNewModel('mail.activity', factory);

});
<commit_msg>[FIX] mail: reduce space in activity<commit_after>odoo.define('mail/static/src/models/activity/activity/js', function (require) {
'use strict';

const { registerNewModel } = require('mail/static/src/model/model_core.js');
const { attr, many2many, many2one } = require('mail/static/src/model/model_field.js');

function factory(dependencies) {

    class Activity extends dependencies['mail.model'] {

        //----------------------------------------------------------------------
        // Public
        //----------------------------------------------------------------------

        /**
         * Delete the record from database and locally.
         */
        async deleteServerRecord() {
            await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'unlink',
                args: [[this.id]],
            }));
            this.delete();
        }

        //----------------------------------------------------------------------
        // Public
        //----------------------------------------------------------------------

        /**
         * @static
         * @param {Object} data
         * @return {Object}
         */
        static convertData(data) {
            const data2 = {};
            if ('activity_category' in data) {
                data2.category = data.activity_category;
            }
            if ('can_write' in data) {
                data2.canWrite = data.can_write;
            }
            if ('create_data' in data) {
                data2.dateCreate = data.create_date;
            }
            if ('date_deadline' in data) {
                data2.dateDeadline = data.date_deadline;
            }
            if ('force_next' in data) {
                data2.force_next = data.force_next;
            }
            if ('icon' in data) {
                data2.icon = data.icon;
            }
            if ('id' in data) {
                data2.id = data.id;
            }
            if ('note' in data) {
                data2.note = data.note;
            }
            if ('res_id' in data) {
                data2.res_id = data.res_id;
            }
            if ('res_model' in data) {
                data2.res_model = data.res_model;
            }
            if ('state' in data) {
                data2.state = data.state;
            }
            if ('summary' in data) {
                data2.summary = data.summary;
            }

            // relation
            if ('activity_type_id' in data) {
                if (!data.activity_type_id) {
                    data2.type = [['unlink-all']];
                } else {
                    data2.type = [
                        ['insert', {
                            displayName: data.activity_type_id[1],
                            id: data.activity_type_id[0],
                        }],
                    ];
                }
            }
            if ('create_uid' in data) {
                if (!data.create_uid) {
                    data2.creator = [['unlink-all']];
                } else {
                    data2.creator = [
                        ['insert', {
                            id: data.create_uid[0],
                            partnerDisplayName: data.create_uid[1],
                        }],
                    ];
                }
            }
            if ('mail_template_ids' in data) {
                data2.mailTemplates = [['insert', data.mail_template_ids]];
            }
            if ('user_id' in data) {
                if (!data.user_id) {
                    data2.assignee = [['unlink-all']];
                } else {
                    data2.assignee = [
                        ['insert', {
                            id: data.user_id[0],
                            partnerDisplayName: data.user_id[1],
                        }],
                    ];
                }
            }

            return data2;
        }

        /**
         * Opens (legacy) form view dialog to edit current activity and updates
         * the activity when dialog is closed.
         */
        edit() {
            const action = {
                type: 'ir.actions.act_window',
                name: this.env._t("Schedule Activity"),
                res_model: 'mail.activity',
                view_mode: 'form',
                views: [[false, 'form']],
                target: 'new',
                context: {
                    default_res_id: this.res_id,
                    default_res_model: this.res_model,
                },
                res_id: this.id,
            };
            this.env.bus.trigger('do-action', {
                action,
                options: { on_close: () => this.fetchAndUpdate() },
            });
        }

        async fetchAndUpdate() {
            const [data] = await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'activity_format',
                args: [this.id],
            }));
            this.update(this.constructor.convertData(data));
            if (this.chatter) {
                this.chatter.refresh();
            }
        }

        /**
         * @param {Object} param0
         * @param {mail.attachment[]} [param0.attachments=[]]
         * @param {string|boolean} [param0.feedback=false]
         */
        async markAsDone({ attachments = [], feedback = false }) {
            const attachmentIds = attachments.map(attachment => attachment.id);
            await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'action_feedback',
                args: [[this.id]],
                kwargs: {
                    attachment_ids: attachmentIds,
                    feedback,
                },
                context: this.chatter ? this.chatter.context : {},
            }));
            if (this.chatter) {
                this.chatter.refresh();
            }
            this.delete();
        }

        /**
         * @param {Object} param0
         * @param {string} param0.feedback
         * @returns {Object}
         */
        async markAsDoneAndScheduleNext({ feedback }) {
            const action = await this.async(() => this.env.services.rpc({
                model: 'mail.activity',
                method: 'action_feedback_schedule_next',
                args: [[this.id]],
                kwargs: { feedback },
            }));
            const chatter = this.chatter;
            if (chatter) {
                this.chatter.refresh();
            }
            this.delete();
            this.env.bus.trigger('do-action', {
                action,
                options: {
                    on_close: () => {
                        if (chatter) {
                            chatter.refreshActivities();
                        }
                    },
                },
            });
        }

        //----------------------------------------------------------------------
        // Private
        //----------------------------------------------------------------------

        /**
         * @override
         */
        static _createRecordLocalId(data) {
            return `${this.modelName}_${data.id}`;
        }

        /**
         * @private
         * @returns {boolean}
         */
        _computeIsCurrentPartnerAssignee() {
            if (!this.assigneePartner || !this.messagingCurrentPartner) {
                return false;
            }
            return this.assigneePartner === this.messagingCurrentPartner;
        }

        /**
         * @private
         * @returns {mail.messaging}
         */
        _computeMessaging() {
            return [['link', this.env.messaging]];
        }

        /**
         * Wysiwyg editor put `<p><br></p>` even without a note on the activity.
         * This compute replaces this almost empty value by an actual empty
         * value, to reduce the size the empty note takes on the UI.
         *
         * @private
         * @returns {string|undefined}
         */
        _computeNote() {
            if (this.note === '

') {
                return undefined;
            }
            return this.note;
        }
    }

    Activity.fields = {
        assignee: many2one('mail.user'),
        assigneePartner: many2one('mail.partner', {
            related: 'assignee.partner',
        }),
        attachments: many2many('mail.attachment', {
            inverse: 'activities',
        }),
        canWrite: attr({
            default: false,
        }),
        category: attr(),
        chatter: many2one('mail.chatter', {
            inverse: 'activities',
        }),
        creator: many2one('mail.user'),
        dateCreate: attr(),
        dateDeadline: attr(),
        force_next: attr({
            default: false,
        }),
        icon: attr(),
        id: attr(),
        isCurrentPartnerAssignee: attr({
            compute: '_computeIsCurrentPartnerAssignee',
            default: false,
            dependencies: [
                'assigneePartner',
                'messagingCurrentPartner',
            ],
        }),
        mailTemplates: many2many('mail.mail_template', {
            inverse: 'activities',
        }),
        messaging: many2one('mail.messaging', {
            compute: '_computeMessaging',
        }),
        messagingCurrentPartner: many2one('mail.partner', {
            related: 'messaging.currentPartner',
        }),
        /**
         * This value is meant to be returned by the server
         * (and has been sanitized before stored into db).
         * Do not use this value in a 't-raw' if the activity has been created
         * directly from user input and not from server data as it's not escaped.
         */
        note: attr({
            compute: '_computeNote',
            dependencies: [
                'note',
            ],
        }),
        res_id: attr(),
        res_model: attr(),
        state: attr(),
        summary: attr(),
        type: many2one('mail.activity_type', {
            inverse: 'activities',
        }),
    };

    Activity.modelName = 'mail.activity';

    return Activity;
}

registerNewModel('mail.activity', factory);

});
<|endoftext|>


<commit_before>/* globals window */
const reactruntime = require("../../reactruntime");
const React = require("react");

class Head extends React.Component {

  render() {
    return (
      <reactruntime.HeadTemplate {...this.props}>

        <link rel="stylesheet" href={this.props.staticLink("/static/css/metrics.css")} />
      </reactruntime.HeadTemplate>
    );
  }

}

class Body extends React.Component {
  render() {
    let created = new Date(this.props.data.shotsCreatedByDay);
    created = created.toLocaleString();
    return (
      <reactruntime.BodyTemplate {...this.props}>

Metrics

Generated at: {created}

        <GenericTable data={this.props.data.shotsCreatedByDay} />

        <GenericTable data={this.props.data.usersByDay} />

        <GenericTable data={this.props.data.shotsByUserHistogram} />

        <GenericTable data={this.props.data.retention} />
      </reactruntime.BodyTemplate>
    );
  }

}

class GenericTable extends React.Component {
  render() {
    return

{this.props.data.title}

{this.props.data.description} (database time: {this.props.data.timeToExecute}ms)

          {this.renderTableHeader()}

          {this.renderTableRows()}

;
  }

  renderTableHeader() {
    let headers = [];
    for (let column of this.props.data.columns) {
      headers.push({column.title}	);
    }
    return

      {headers}

;
  }

  renderTableRows() {
    let rows = [];
    let n=0;
    for (let row of this.props.data.rows) {
      n++;
      let columns = [];
      for (let i=0; i<row.length; i++) {
        let value = row[i];
        let meta = this.props.data.columns[i];
        if (meta.type) {
          if (meta.type === "date") {
            value = (new Date(value));
            value = value.toLocaleString(
              "en-US", {year: 'numeric', month: 'short', day: 'numeric'});
          } else {
            console.warn("Unknown type:", meta.type);
          }
        }
        columns.push({value}	);
      }
      rows.push(
{columns}
);
    }
    return rows;
  }

}

exports.HeadFactory = React.createFactory(Head);
exports.BodyFactory = React.createFactory(Body);
<commit_msg>Fix 'generated at' date<commit_after>/* globals window */
const reactruntime = require("../../reactruntime");
const React = require("react");

class Head extends React.Component {

  render() {
    return (
      <reactruntime.HeadTemplate {...this.props}>

        <link rel="stylesheet" href={this.props.staticLink("/static/css/metrics.css")} />
      </reactruntime.HeadTemplate>
    );
  }

}

class Body extends React.Component {
  render() {
    let created = new Date(this.props.data.shotsCreatedByDay.created);
    created = created.toLocaleString();
    return (
      <reactruntime.BodyTemplate {...this.props}>

Metrics

Generated at: {created}

        <GenericTable data={this.props.data.shotsCreatedByDay} />

        <GenericTable data={this.props.data.usersByDay} />

        <GenericTable data={this.props.data.shotsByUserHistogram} />

        <GenericTable data={this.props.data.retention} />
      </reactruntime.BodyTemplate>
    );
  }

}

class GenericTable extends React.Component {
  render() {
    return

{this.props.data.title}

{this.props.data.description} (database time: {this.props.data.timeToExecute}ms)

          {this.renderTableHeader()}

          {this.renderTableRows()}

;
  }

  renderTableHeader() {
    let headers = [];
    for (let column of this.props.data.columns) {
      headers.push({column.title}	);
    }
    return

      {headers}

;
  }

  renderTableRows() {
    let rows = [];
    let n=0;
    for (let row of this.props.data.rows) {
      n++;
      let columns = [];
      for (let i=0; i<row.length; i++) {
        let value = row[i];
        let meta = this.props.data.columns[i];
        if (meta.type) {
          if (meta.type === "date") {
            value = (new Date(value));
            value = value.toLocaleString(
              "en-US", {year: 'numeric', month: 'short', day: 'numeric'});
          } else {
            console.warn("Unknown type:", meta.type);
          }
        }
        columns.push({value}	);
      }
      rows.push(
{columns}
);
    }
    return rows;
  }

}

exports.HeadFactory = React.createFactory(Head);
exports.BodyFactory = React.createFactory(Body);
<|endoftext|>