<commit_before>const mocha = require('mocha');
const utils = mocha.utils;

const defaults = require('lodash.defaults');
const getStacktrace = require('./util/get-stacktrace');
const getErrorMessage = require('./util/get-error-message');

const http = require('http');
const https = require('https');

const defaultConfig = {
  port: 3000,
  hostname: 'localhost',
  path: '/graphql',
  protocol: 'http',
  // flowDetails: {}, // TODO: move inside after finalinzing the interface
  // jobDetails: {},
};

const ReflowReporter = function(runner, options = {}) {
  const reporterOptions = options.reporterOptions || {};
  const {
    flowDetails, // TODO: move inside after finalinzing the interface
    jobDetails,
    port,
    protocol,
    hostname,
    path,
    headers,
  } = defaults(reporterOptions, defaultConfig);

  const tcpModule = protocol === 'https' ? https : http;

  const keepAliveAgent = new tcpModule.Agent({ keepAlive: true });

  mocha.reporters.Base.call(this, runner);
  const stats = this.stats;

  let results = [];
  let startTime;
  let level = 1;
  let numberOfSuites;

  function report (type, data) {
    switch(type) {
      case "case":
        results[results.length - 1].tests.push(data);
        break;
      case "suite":
        results.push(data);
        break;
    }
  }
  function sendRequest(type, data) {
    process.stdout.write(`\nSending request (${type}) to: ${hostname}:${port}${path}`);
    const postData = JSON.stringify(data);
    const reqOptions = {
      agent: keepAliveAgent,
      method: 'POST',
      port,
      hostname,
      path,
      protocol: `${protocol}:`,
      headers: Object.assign({
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(postData),
      }, headers),
    };
    const req = tcpModule.request(reqOptions, (res) => {
      if(type === 'request track') {
        console.log(`STATUS: ${res.statusCode}`);
        console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
        res.setEncoding('utf8');
        res.on('data', (chunk) => {
          console.log(`BODY: ${chunk}`);
        });
        res.on('end', () => {
          console.log('No more data in response.');
        });
      }
    });

    req.on('error', (e) => {
      console.error(e);
    });

    req.write(postData);
    req.end();
    process.stdout.write('\nRequest sent.\n');
  }

  function submitReport() {
    try {

      process.stdout.write('\nGenerating Report ... ');
      const report = {
        suites: results,
        pending: stats.pending,
        passes: stats.passes,
        failures: stats.failures,
        skipped: stats.tests - stats.failures - stats.passes,
        endTime: Date.parse(new Date()),
        duration: (stats.duration / 1000) || 0,
        result: stats.failures? 'FAILURE' : 'SUCCESS',
        numberOfSuites,
        startTime: startTime,
        flowDetails,
        jobDetails: Object.assign({}, jobDetails, {
          startTime: Date.parse(jobDetails.startTime),
        }),
      }
      process.stdout.write('Done');

      const postData = {
        operationName: "insertCombination",
        query: "mutation insertCombination($combination: CombinationInput!) {\n  insertCombination(input: $combination) {\n    id\n  }\n}\n",
        variables: {
          combination: report,
        },
      };

      sendRequest('combination', postData);
      results = [];
    } catch(err) {
      console.log('err::', err)
    }

  }

  runner.on('start', function() {
    startTime = Date.parse(new Date());
    numberOfSuites = runner.grepTotal(runner.suite);
  });

  runner.on('suite', function (suite) {
    level = level + 1;
    report('suite', {
      title: utils.escape(suite.title),
      tests: [],
      level,
    });
  });

  runner.on('suite end', function () {
    level = level - 1;
  });

  let metadataContent = [];
  global.trackRequest = function(request) {
    const postData = {
      operationName: "trackRequest",
      query: "mutation trackRequest($request: RequestEventInput!) {\n  trackRequest(input: $request) {\n    name\n  }\n}\n",
      variables: {
        request: {
          ...request,
          jobID: jobDetails.id,
        }
      },
    };

    sendRequest('request track', postData)
  }
  global.metadata = function(message, meta) {
    metadataContent.push({
      message: JSON.stringify(message),
      meta: JSON.stringify(meta),
    });
  }

  // runner.on('hook end', function() {
  //   console.log(metadataContent);
  // });

  runner.on('pass', function (test) {
    report('case', {
      title: utils.escape(test.title),
      code: utils.escape(utils.clean(test.body)),
      speed: test.speed,
      metadata: metadataContent.length? metadataContent : undefined,
      duration: test.duration,
      result: "SUCCESS"
    });

    metadataContent = [];
  });

  runner.on('pending', function (test) {
    report('case', {
      result: 'PENDING',
      title: utils.escape(test.title),
    })
  });

  runner.on('fail', function (test) {
    const err = test.err;
    report('case', {
      result: 'FAILURE',
      title: utils.escape(test.title),
      code: utils.escape(utils.clean(test.body)),
      speed: test.speed,
      duration: test.duration,
      err: {
        stacktrace: utils.escape(getStacktrace(err)),
        message: utils.escape(getErrorMessage(err)),
        htmlMessage: err.htmlMessage,
      }
    })
  });

  runner.on('end', function() {
    submitReport();
  })
}

module.exports = ReflowReporter;
<commit_msg>return id<commit_after>const mocha = require('mocha');
const utils = mocha.utils;

const defaults = require('lodash.defaults');
const getStacktrace = require('./util/get-stacktrace');
const getErrorMessage = require('./util/get-error-message');

const http = require('http');
const https = require('https');

const defaultConfig = {
  port: 3000,
  hostname: 'localhost',
  path: '/graphql',
  protocol: 'http',
  // flowDetails: {}, // TODO: move inside after finalinzing the interface
  // jobDetails: {},
};

const ReflowReporter = function(runner, options = {}) {
  const reporterOptions = options.reporterOptions || {};
  const {
    flowDetails, // TODO: move inside after finalinzing the interface
    jobDetails,
    port,
    protocol,
    hostname,
    path,
    headers,
  } = defaults(reporterOptions, defaultConfig);

  const tcpModule = protocol === 'https' ? https : http;

  const keepAliveAgent = new tcpModule.Agent({ keepAlive: true });

  mocha.reporters.Base.call(this, runner);
  const stats = this.stats;

  let results = [];
  let startTime;
  let level = 1;
  let numberOfSuites;

  function report (type, data) {
    switch(type) {
      case "case":
        results[results.length - 1].tests.push(data);
        break;
      case "suite":
        results.push(data);
        break;
    }
  }
  function sendRequest(type, data) {
    process.stdout.write(`\nSending request (${type}) to: ${hostname}:${port}${path}`);
    const postData = JSON.stringify(data);
    const reqOptions = {
      agent: keepAliveAgent,
      method: 'POST',
      port,
      hostname,
      path,
      protocol: `${protocol}:`,
      headers: Object.assign({
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(postData),
      }, headers),
    };
    const req = tcpModule.request(reqOptions, (res) => {
      if(type === 'request track') {
        console.log(`STATUS: ${res.statusCode}`);
        console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
        res.setEncoding('utf8');
        res.on('data', (chunk) => {
          console.log(`BODY: ${chunk}`);
        });
        res.on('end', () => {
          console.log('No more data in response.');
        });
      }
    });

    req.on('error', (e) => {
      console.error(e);
    });

    req.write(postData);
    req.end();
    process.stdout.write('\nRequest sent.\n');
  }

  function submitReport() {
    try {

      process.stdout.write('\nGenerating Report ... ');
      const report = {
        suites: results,
        pending: stats.pending,
        passes: stats.passes,
        failures: stats.failures,
        skipped: stats.tests - stats.failures - stats.passes,
        endTime: Date.parse(new Date()),
        duration: (stats.duration / 1000) || 0,
        result: stats.failures? 'FAILURE' : 'SUCCESS',
        numberOfSuites,
        startTime: startTime,
        flowDetails,
        jobDetails: Object.assign({}, jobDetails, {
          startTime: Date.parse(jobDetails.startTime),
        }),
      }
      process.stdout.write('Done');

      const postData = {
        operationName: "insertCombination",
        query: "mutation insertCombination($combination: CombinationInput!) {\n  insertCombination(input: $combination) {\n    id\n  }\n}\n",
        variables: {
          combination: report,
        },
      };

      sendRequest('combination', postData);
      results = [];
    } catch(err) {
      console.log('err::', err)
    }

  }

  runner.on('start', function() {
    startTime = Date.parse(new Date());
    numberOfSuites = runner.grepTotal(runner.suite);
  });

  runner.on('suite', function (suite) {
    level = level + 1;
    report('suite', {
      title: utils.escape(suite.title),
      tests: [],
      level,
    });
  });

  runner.on('suite end', function () {
    level = level - 1;
  });

  let metadataContent = [];
  global.trackRequest = function(request) {
    const postData = {
      operationName: "trackRequest",
      query: "mutation trackRequest($request: RequestEventInput!) {\n  trackRequest(input: $request) {\n    id\n  }\n}\n",
      variables: {
        request: {
          ...request,
          jobID: jobDetails.id,
        }
      },
    };

    sendRequest('request track', postData)
  }
  global.metadata = function(message, meta) {
    metadataContent.push({
      message: JSON.stringify(message),
      meta: JSON.stringify(meta),
    });
  }

  // runner.on('hook end', function() {
  //   console.log(metadataContent);
  // });

  runner.on('pass', function (test) {
    report('case', {
      title: utils.escape(test.title),
      code: utils.escape(utils.clean(test.body)),
      speed: test.speed,
      metadata: metadataContent.length? metadataContent : undefined,
      duration: test.duration,
      result: "SUCCESS"
    });

    metadataContent = [];
  });

  runner.on('pending', function (test) {
    report('case', {
      result: 'PENDING',
      title: utils.escape(test.title),
    })
  });

  runner.on('fail', function (test) {
    const err = test.err;
    report('case', {
      result: 'FAILURE',
      title: utils.escape(test.title),
      code: utils.escape(utils.clean(test.body)),
      speed: test.speed,
      duration: test.duration,
      err: {
        stacktrace: utils.escape(getStacktrace(err)),
        message: utils.escape(getErrorMessage(err)),
        htmlMessage: err.htmlMessage,
      }
    })
  });

  runner.on('end', function() {
    submitReport();
  })
}

module.exports = ReflowReporter;
<|endoftext|>


<commit_before>import {EventEmitter} from 'events'
import {routerPlugin} from './plugin'
import compose from 'koa-compose'
import {isPromise, isAsync, isFunction, makeProp} from 'sav-util'

export class Router extends EventEmitter {
  constructor (opts) {
    super()
    this.opts = {...opts}
    this.matchRoute = null
    this.payloads = []
    if (!this.opts.noRoute) {
      this.use(routerPlugin)
    }
  }
  config (name, dval) {
    return name in this.opts ? this.opts[name] : dval
  }
  use (plugin) {
    if (typeof plugin === 'function') {
      plugin(this)
    } else if (typeof plugin === 'object') {
      for (let name in plugin) {
        if (name === 'payload') {
          this.payloads.push(plugin[name])
        } else {
          this.on(name, plugin[name])
        }
      }
    }
  }
  declare (modules) {
    if (!Array.isArray(modules)) {
      modules = [modules]
    }
    buildModules(this, modules)
  }
  route () {
    let payloads = [payloadStart.bind(this)].concat(this.payloads).concat([payloadEnd.bind(this)])
    let payload = compose(payloads)
    return payload
  }
  async exec (ctx) {
    if (this._executer) {
      return await this._executer(ctx)
    }
    this._executer = this.route()
    return await this._executer(ctx)
  }
  warn (...args) {
    this.emit('warn', ...args)
  }
}

function buildModules (ctx, modules) {
  for (let module of modules) {
    let prop = makeProp(module, false)
    prop({
      ctx
    })
    ctx.emit('module', module)
    for (let actionName in module.actions) {
      let action = module.actions[actionName]
      let prop = makeProp(action, false)
      prop({
        module,
        ctx,
        middlewares: action.config.map(([name]) => {
          return {name}
        }),
        set (name, middleware) {
          for (let it of action.middlewares) {
            if (it.name === name) {
              it.middleware = middleware
              return
            }
          }
          action.middlewares.push({name, middleware})
        },
        get (name) {
          for (let it of action.middlewares) {
            if (it.name === name) {
              return it
            }
          }
        }
      })
      ctx.emit('action', action)
    }
  }
}

async function payloadStart (ctx, next) {
  makeProp(ctx)
  await next()
}

async function payloadEnd (ctx, next) {
  let method = ctx.method.toUpperCase()
  let path = ctx.path || ctx.originalUrl
  let matched = this.matchRoute(path, method)
  if (matched) {
    let [route, params] = matched
    let {prop} = ctx
    prop({
      params,
      route,
      stack: [],
      end (data, name) {
        ctx.stack.push({name, data})
      }
    })
    prop.getter('data', (data, name) => {
      let ret = ctx.stack[ctx.stack.length - 1]
      return ret && ret.data
    })
    for (let {name, middleware} of route.middlewares) {
      if (isFunction(middleware)) {
        let ret
        if (isAsync(ctx)) {
          ret = await middleware(ctx)
        } else {
          ret = middleware(ctx)
          if (ret && isPromise(ret)) {
            ret = await ret
          }
        }
        if (name === 'route') {
          ctx.end(ret, name)
        }
      }
    }
    ctx.body = ctx.data
  } else {
    await next()
  }
}
<commit_msg>move props<commit_after>import {EventEmitter} from 'events'
import {routerPlugin} from './plugin'
import compose from 'koa-compose'
import {isPromise, isAsync, isFunction, makeProp} from 'sav-util'

export class Router extends EventEmitter {
  constructor (opts) {
    super()
    this.opts = {...opts}
    this.matchRoute = null
    this.payloads = []
    if (!this.opts.noRoute) {
      this.use(routerPlugin)
    }
  }
  config (name, dval) {
    return name in this.opts ? this.opts[name] : dval
  }
  use (plugin) {
    if (typeof plugin === 'function') {
      plugin(this)
    } else if (typeof plugin === 'object') {
      for (let name in plugin) {
        if (name === 'payload') {
          this.payloads.push(plugin[name])
        } else {
          this.on(name, plugin[name])
        }
      }
    }
  }
  declare (modules) {
    if (!Array.isArray(modules)) {
      modules = [modules]
    }
    buildModules(this, modules)
  }
  route () {
    let payloads = [payloadStart.bind(this)].concat(this.payloads).concat([payloadEnd.bind(this)])
    let payload = compose(payloads)
    return payload
  }
  async exec (ctx) {
    if (this._executer) {
      return await this._executer(ctx)
    }
    this._executer = this.route()
    return await this._executer(ctx)
  }
  warn (...args) {
    this.emit('warn', ...args)
  }
}

function buildModules (ctx, modules) {
  for (let module of modules) {
    let prop = makeProp(module, false)
    prop({
      ctx
    })
    ctx.emit('module', module)
    for (let actionName in module.actions) {
      let action = module.actions[actionName]
      let prop = makeProp(action, false)
      prop({
        module,
        ctx,
        middlewares: action.config.map(([name]) => {
          return {name}
        }),
        set (name, middleware) {
          for (let it of action.middlewares) {
            if (it.name === name) {
              it.middleware = middleware
              return
            }
          }
          action.middlewares.push({name, middleware})
        },
        get (name) {
          for (let it of action.middlewares) {
            if (it.name === name) {
              return it
            }
          }
        }
      })
      ctx.emit('action', action)
    }
  }
}

async function payloadStart (ctx, next) {
  let prop = makeProp(ctx)
  prop({
    stack: [],
    end (data, name) {
      ctx.stack.push({name, data})
    }
  })
  prop.getter('data', (data, name) => {
    let ret = ctx.stack[ctx.stack.length - 1]
    return ret && ret.data
  })
  await next()
}

async function payloadEnd (ctx, next) {
  let method = ctx.method.toUpperCase()
  let path = ctx.path || ctx.originalUrl
  let matched = this.matchRoute(path, method)
  if (matched) {
    let [route, params] = matched
    let {prop} = ctx
    prop({
      params,
      route
    })
    for (let {name, middleware} of route.middlewares) {
      if (isFunction(middleware)) {
        let ret
        if (isAsync(ctx)) {
          ret = await middleware(ctx)
        } else {
          ret = middleware(ctx)
          if (ret && isPromise(ret)) {
            ret = await ret
          }
        }
        if (name === 'route') {
          ctx.end(ret, name)
        }
      }
    }
    ctx.body = ctx.data
  } else {
    await next()
  }
}
<|endoftext|>


<commit_before>'use strict';
const cp = require('child_process');
const fs = require('fs');
const chalk = require('chalk');
const async = require('async');

let successfulTests = 0;

fs.stat('../Lang', function (err, stats) {
  if (err) {
    console.error(chalk.red('Could not stat executable'));
    return;
  }
  runTests();
});

function equalityTest(name, expectedOutput, command) {
  return function (callback) {
    cp.exec(`../Lang ${command}`, function (err, stdout, stderr) {
      if (err) {
        testFinished(name, `${err.message}\nSignal: ${chalk.red(err.signal)}`, callback);
        return;
      }
      if (stdout === expectedOutput) testFinished(name, callback);
      else testFinished(name, `Command: ${command}\nExpected output: ${expectedOutput}\nRecieved output: ${stdout}`, callback);
    });
  };
}

let tests = {
  integers: equalityTest('Integers', '1', '-e "print(1)"'),
  strings: equalityTest('Strings', 'qwerty1234{}/*-~?', '-e \'print("qwerty1234{}/*-~?")\''),
  booleans: equalityTest('Booleans', 'true', '-e \'print(true)\''),
  floats: equalityTest('Floats', '1.2', '-e \'print(1.2)\''),
  intPlus: equalityTest('Integer Addition', '16', '-e \'print(8 + 8)\''),
  fltPlus: equalityTest('Float Addition', '16.32', '-e \'print(8.16 + 8.16)\''),
  strPlus: equalityTest('String Concatenation', 'abcdef', '-e \'print("abc" + "def")\''),
  assignment: equalityTest('Basic Assignment', '123abc', '-e \'define a = 123; print(a); a = "abc"; print(a);\''),
  multiTypeDef: equalityTest('Multiple Types', '03.14',
  `-e '
  Integer, Float number = 0;
  print(number);
  number = 3.14;
  print(number);
  '`),
  booleanCond: equalityTest('Boolean Expression', 'false',
  `-e '
  !(true || false && true || false)
  '`),
  ifTest: equalityTest('Simple Conditional', '42',
  `-e '
  if true do
    print(42);
  end
  '`),
  ifComplexTest: equalityTest('Full Conditional', '42',
  `-e '
  if true do
    print(42);
  else
    print(420);
  end
  '`),
};

function testFinished(testName, errorString, callback) {
  if (arguments.length == 2) callback = errorString;
  if (errorString && typeof errorString === 'string') {
    console.error(`Test '${chalk.yellow(testName)}' ${chalk.red('failed')}\n${errorString}`);
    callback();
    return;
  }
  console.log(`Test '${chalk.yellow(testName)}' ok ${chalk.green('✓')}`);
  successfulTests++;
  callback();
}

function runTests() {
  let testCount = Object.keys(tests).length;
  async.parallel(tests, function (err) {
    if (successfulTests === testCount) {
      console.log(chalk.underline.green('All tests ok!'));
    } else {
      console.log(`${chalk.green(successfulTests)} tests ok.\n${chalk.red(String(testCount - successfulTests))} tests failed`);
    }
  });
}
<commit_msg>Fixed missing function call in test<commit_after>'use strict';
const cp = require('child_process');
const fs = require('fs');
const chalk = require('chalk');
const async = require('async');

let successfulTests = 0;

fs.stat('../Lang', function (err, stats) {
  if (err) {
    console.error(chalk.red('Could not stat executable'));
    return;
  }
  runTests();
});

function equalityTest(name, expectedOutput, command) {
  return function (callback) {
    cp.exec(`../Lang ${command}`, function (err, stdout, stderr) {
      if (err) {
        testFinished(name, `${err.message}\nSignal: ${chalk.red(err.signal)}`, callback);
        return;
      }
      if (stdout === expectedOutput) testFinished(name, callback);
      else testFinished(name, `Command: ${command}\nExpected output: ${expectedOutput}\nRecieved output: ${stdout}`, callback);
    });
  };
}

let tests = {
  integers: equalityTest('Integers', '1', '-e "print(1)"'),
  strings: equalityTest('Strings', 'qwerty1234{}/*-~?', '-e \'print("qwerty1234{}/*-~?")\''),
  booleans: equalityTest('Booleans', 'true', '-e \'print(true)\''),
  floats: equalityTest('Floats', '1.2', '-e \'print(1.2)\''),
  intPlus: equalityTest('Integer Addition', '16', '-e \'print(8 + 8)\''),
  fltPlus: equalityTest('Float Addition', '16.32', '-e \'print(8.16 + 8.16)\''),
  strPlus: equalityTest('String Concatenation', 'abcdef', '-e \'print("abc" + "def")\''),
  assignment: equalityTest('Basic Assignment', '123abc', '-e \'define a = 123; print(a); a = "abc"; print(a);\''),
  multiTypeDef: equalityTest('Multiple Types', '03.14',
  `-e '
  Integer, Float number = 0;
  print(number);
  number = 3.14;
  print(number);
  '`),
  booleanCond: equalityTest('Boolean Expression', 'false',
  `-e '
  print(!(true || false && true || false));
  '`),
  ifTest: equalityTest('Simple Conditional', '42',
  `-e '
  if true do
    print(42);
  end
  '`),
  ifComplexTest: equalityTest('Full Conditional', '42',
  `-e '
  if true do
    print(42);
  else
    print(420);
  end
  '`),
};

function testFinished(testName, errorString, callback) {
  if (arguments.length == 2) callback = errorString;
  if (errorString && typeof errorString === 'string') {
    console.error(`Test '${chalk.yellow(testName)}' ${chalk.red('failed')}\n${errorString}`);
    callback();
    return;
  }
  console.log(`Test '${chalk.yellow(testName)}' ok ${chalk.green('✓')}`);
  successfulTests++;
  callback();
}

function runTests() {
  let testCount = Object.keys(tests).length;
  async.parallel(tests, function (err) {
    if (successfulTests === testCount) {
      console.log(chalk.underline.green('All tests ok!'));
    } else {
      console.log(`${chalk.green(successfulTests)} tests ok.\n${chalk.red(String(testCount - successfulTests))} tests failed`);
    }
  });
}
<|endoftext|>


<commit_before>// Dependencies

let assign = require('object-assign');
let type = require('focus').component.types;
let builder = require('focus').component.builder;
let React = require('react');

// Components

let SearchBar = require('../../../search/search-bar').component;

// Mixins

let ScrollInfoMixin = require('../common/scroll-info-mixin').mixin;
let GroupByMixin = require('../common/group-by-mixin').mixin;
let SearchMixin = require('../common/search-mixin').mixin;
let referenceBehaviour = require('../../../common/form/mixin/reference-behaviour');

/**
 * General search mixin.
 * Contains a search bar, and a results list.
 * @type {Object}
 */
let QuickSearchComponent = {
    mixins: [ScrollInfoMixin, GroupByMixin, SearchMixin, referenceBehaviour],
    /**
     * Tag name.
     */
    displayName: 'quick-search',
    /**
     * Component initialization
     */
    componentDidMount() {
        this._registerListeners();
    },
    componentWillMount() {
        this._loadReference();
    },
    /**
     * Actions before component will unmount.
     * @constructor
     */
    componentWillUnmount() {
        this._unRegisterListeners();
    },
    getDefaultProps() {
        return {
            isSelection: false,
            idField: 'id',
            SearchBar: SearchBar,
            groupMaxRows: 3
        };
    },
    /**
     * properties validation
     */
    propTypes: {
        lineMap: type('object'),
        isSelection: type('bool'),
        lineOperationList: type('array'),
        idField: type('string'),
        SearchBar: type('func'),
        groupMaxRows: type('number')
    },
    /**
     * Initial state of the list component.
     * @returns {{list: (*|Array)}} the state
     */
    getInitialState() {
        return {
            isAllSelected: false,
            selected: []
        };
    },
    getCriteria() {
        if (!this.refs.searchBar) {
            return {};
        }
        return this.refs.searchBar.getValue();
    },
    /**
     * Register a listener on the store.
     * @private
     */
    _registerListeners() {
        this.props.store.addSearchChangeListener(this.onSearchChange);
        Focus.search.builtInStore.queryStore.addQueryChangeListener(this._onQueryStoreChange);
        Focus.search.builtInStore.queryStore.addScopeChangeListener(this._onQueryStoreChange);
    },
    /**
     * Unregister a listener on the store.
     * @private
     */
    _unRegisterListeners() {
        this.props.store.removeSearchChangeListener(this.onSearchChange);
        Focus.search.builtInStore.queryStore.removeQueryChangeListener(this._onQueryStoreChange);
        Focus.search.builtInStore.queryStore.removeScopeChangeListener(this._onQueryStoreChange);
    },
    /**
     * Handler when store emit a change event.
     */
    onSearchChange() {
        this.setState(assign({isLoadingSearch: false}, this.getScrollState()));
    },
    _onQueryStoreChange(event) {
        this.setState(
            assign(
                {isLoadingSearch: true},
                this.getNoFetchState()
            ),
            () => {
                if (event.informations.callerId === this.refs.searchBar._uuid) {
                    this.search()
                }
            }
        );
    },
    /**
     * Action on item selection.
     * @param {object} item selected
     */
    _selectItem(item) {
        let selected = this.state.selected;
        let index = selected.indexOf(item);
        if (index) {
            selected.splice(index, index);
        } else {
            selected.push(item);
        }
        this.setState({selected});
    },
    /**
     * Action on line click.
     * @param {object} item  the item clicked
     */
    _lineClick(item) {
        if (this.props.onLineClick) {
            this.props.onLineClick(item);
        }
    },
    //_prepareSearch(searchValues){
    //    clearTimeout(this._searchTimeout);
    //    this._searchTimeout = setTimeout(() => {
    //        this.setState(
    //            assign(
    //                {isLoadingSearch: true},
    //                searchValues,
    //                this.getNoFetchState()
    //            ),
    //            this.search
    //        );
    //    }, 500);
    //},
    /**
     * return a SearchBar
     * @returns {XML} the component
     */
    getSearchBarComponent() {
        return (
            <this.props.SearchBar
                data-focus='search-bar'
                ref='searchBar'
                scope={this.props.scope}
                scopes={this.state.reference.scopes}
                loading={this.state.isLoadingSearch}
                />
        );
    },
    render() {
        return (

                {this.getSearchBarComponent()}
                {this.getResultListComponent()}

        );
    }
};

module.exports = builder(QuickSearchComponent);
<commit_msg>[quick-search] Add missing mixin<commit_after>// Dependencies

let assign = require('object-assign');
let type = require('focus').component.types;
let builder = require('focus').component.builder;
let React = require('react');

// Components

let SearchBar = require('../../../search/search-bar').component;

// Mixins

let ScrollInfoMixin = require('../common/scroll-info-mixin').mixin;
let GroupByMixin = require('../common/group-by-mixin').mixin;
let SearchMixin = require('../common/search-mixin').mixin;
let referenceBehaviour = require('../../../common/form/mixin/reference-behaviour');
let storeBehaviour = require('../../../common/mixin/store-behaviour');

/**
 * General search mixin.
 * Contains a search bar, and a results list.
 * @type {Object}
 */
let QuickSearchComponent = {
    mixins: [ScrollInfoMixin, GroupByMixin, SearchMixin, referenceBehaviour, storeBehaviour],
    /**
     * Tag name.
     */
    displayName: 'quick-search',
    /**
     * Component initialization
     */
    componentDidMount() {
        this.__registerListeners();
    },
    componentWillMount() {
        this._loadReference();
    },
    /**
     * Actions before component will unmount.
     * @constructor
     */
    componentWillUnmount() {
        this.__unRegisterListeners();
    },
    getDefaultProps() {
        return {
            isSelection: false,
            idField: 'id',
            SearchBar: SearchBar,
            groupMaxRows: 3
        };
    },
    referenceNames: ['scopes'],
    /**
     * properties validation
     */
    propTypes: {
        lineMap: type('object'),
        isSelection: type('bool'),
        lineOperationList: type('array'),
        idField: type('string'),
        SearchBar: type('func'),
        groupMaxRows: type('number')
    },
    /**
     * Initial state of the list component.
     * @returns {{list: (*|Array)}} the state
     */
    getInitialState() {
        return {
            isAllSelected: false,
            selected: []
        };
    },
    getCriteria() {
        if (!this.refs.searchBar) {
            return {};
        }
        return this.refs.searchBar.getValue();
    },
    /**
     * Register a listener on the store.
     * @private
     */
    __registerListeners() {
        this.props.store.addSearchChangeListener(this.onSearchChange);
        Focus.search.builtInStore.queryStore.addQueryChangeListener(this._onQueryStoreChange);
        Focus.search.builtInStore.queryStore.addScopeChangeListener(this._onQueryStoreChange);
    },
    /**
     * Unregister a listener on the store.
     * @private
     */
    __unRegisterListeners() {
        this.props.store.removeSearchChangeListener(this.onSearchChange);
        Focus.search.builtInStore.queryStore.removeQueryChangeListener(this._onQueryStoreChange);
        Focus.search.builtInStore.queryStore.removeScopeChangeListener(this._onQueryStoreChange);
    },
    /**
     * Handler when store emit a change event.
     */
    onSearchChange() {
        this.setState(assign({isLoadingSearch: false}, this.getScrollState()));
    },
    _onQueryStoreChange(event) {
        this.setState(
            assign(
                {isLoadingSearch: true},
                this.getNoFetchState()
            ),
            () => {
                if (event.informations.callerId === this.refs.searchBar._uuid) {
                    this.search()
                }
            }
        );
    },
    /**
     * Action on item selection.
     * @param {object} item selected
     */
    _selectItem(item) {
        let selected = this.state.selected;
        let index = selected.indexOf(item);
        if (index) {
            selected.splice(index, index);
        } else {
            selected.push(item);
        }
        this.setState({selected});
    },
    /**
     * Action on line click.
     * @param {object} item  the item clicked
     */
    _lineClick(item) {
        if (this.props.onLineClick) {
            this.props.onLineClick(item);
        }
    },
    //_prepareSearch(searchValues){
    //    clearTimeout(this._searchTimeout);
    //    this._searchTimeout = setTimeout(() => {
    //        this.setState(
    //            assign(
    //                {isLoadingSearch: true},
    //                searchValues,
    //                this.getNoFetchState()
    //            ),
    //            this.search
    //        );
    //    }, 500);
    //},
    /**
     * return a SearchBar
     * @returns {XML} the component
     */
    getSearchBarComponent() {
        return (
            <this.props.SearchBar
                data-focus='search-bar'
                ref='searchBar'
                scope={this.props.scope}
                scopes={this.state.reference.scopes}
                loading={this.state.isLoadingSearch}
                />
        );
    },
    render() {
        return (

                {this.getSearchBarComponent()}
                {this.getResultListComponent()}

        );
    }
};

module.exports = builder(QuickSearchComponent);
<|endoftext|>


<commit_before>var fs = require('fs');

exports.Statistics = function (config) {
	var me = this;

	me.calculateSpeed = function (positions) {
		console.log('Calc Speed');

		var degToKm = 40074/360;

		var speed = [];
		var maxV = 0;

		for (var i = 0; i < positions.length-1; i++) {
			var dx = positions[i].x - positions[i+1].x;
			var dy = positions[i].y - positions[i+1].y;

			dx *= degToKm*Math.cos(positions[i].y*Math.PI/180);
			dy *= degToKm;

			var r = Math.sqrt(dx*dx + dy*dy);
			var v = r/(config.timeStepSeconds/3600);

			speed[i] = v;
			if (maxV < v) maxV = v;
		}

		console.log(maxV);
	}

	me.calculateGraph = function (events) {
		console.log('Calc Graph');

		var nodes = {};
		var edges = {};
		var ignoreContacts = {
			'Balthasar Glättli': true,
			'adwords-noreply@google.com': true,
			'twitter.com': true,
			'facebook': true,
			'undisclosed-recipient': true
		};
		var count = 0;

		var connections = events.map(function (event) {
			var addresses = event.to.concat([event.from]);

			// remove duplicates
			for (var i = 0; i < addresses.length; i++) {
				if (addresses[i]) {
					for (var j = i+1; j < addresses.length; j++) {
						if (addresses[i].contact == addresses[j].contact) {
							addresses[i] = false;
							break;
						}
					}
				}
			}

			// Filter
			addresses = addresses.filter(function (address) {
				if (!address) return false;
				if (ignoreContacts[address.contact]) return false;
				return true;
			})

			// Add nodes
			addresses.forEach(function (address) {
				var contact = address.contact;
				if (!nodes[contact]) nodes[contact] = {label:contact, count:0, intensity:0, weight:0, edges:0, use:false};
				nodes[contact].count++;
				nodes[contact].intensity += 1/addresses.length;
			})

			return addresses;
		});

		connections.forEach(function (addresses) {
			// Add edge
			if (addresses.length > 1) {
				var weight = 1/(addresses.length-1) + 0.01;
				for (var i = 0; i < addresses.length; i++) {
					var contact1 = addresses[i].contact;
					for (var j = i+1; j < addresses.length; j++) {
						var contact2 = addresses[j].contact;

						if (nodes[contact1] && nodes[contact2]) {
							var contactA, contactB;
							if (contact1 < contact2) {
								contactA = contact1; contactB = contact2;
							} else {
								contactA = contact2; contactB = contact1;
							}

							var edgeName = contactA+'_'+contactB;

							if (!edges[edgeName]) edges[edgeName] = {source:contactA, target:contactB, weight:0};

							nodes[contact1].edges  += 1;
							nodes[contact2].edges  += 1;

							nodes[contact1].weight += weight;
							nodes[contact2].weight += weight;

							edges[edgeName].weight += weight;
						}
					}
				}
			}
		})

		nodeList = Object.keys(nodes).map(function (key) {
			var node = nodes[key];

			node.ok = false;
			if (!node) return false;
			if (node.weight < 10) return false; //5
			if (node.edges  < 10) return false;
			if (node.count  < 20) return false; //10

			var size = node.weight + node.intensity;

			node.ok = true;
			node.maxWeight = 0;
			return [node.label, node.label, size.toFixed(2), node.weight, node.edges, node.count].join('\t');
		}).filter(function (node) {
			return node;
		});
		nodeList.unshift('Id\tLabel\tSize');

		fs.writeFileSync('nodes.csv', nodeList.join('\n'), 'utf8');

		edgeList = Object.keys(edges).map(function (key) {
			var edge = edges[key];

			if (!nodes[edge.source].ok) return false;
			if (!nodes[edge.target].ok) return false;

			if (nodes[edge.source].maxWeight < edge.weight) nodes[edge.source].maxWeight = edge.weight;
			if (nodes[edge.target].maxWeight < edge.weight) nodes[edge.target].maxWeight = edge.weight;

			return edge;
		}).filter(function (edge) {
			return edge;
		});

		edgeList = edgeList.map(function (edge) {
			var f = Math.min(nodes[edge.source].maxWeight, nodes[edge.target].maxWeight);
			return [edge.source, edge.target, edge.weight/f, 'Undirected'].join('\t');
		})
		;
		edgeList.unshift('Source\tTarget\tWeight\tType');

		fs.writeFileSync('edges.csv', edgeList.join('\n'), 'utf8');

		console.log(nodeList.length, edgeList.length);
	}

	return me;
}
<commit_msg>reimplement ignore nodes<commit_after>var fs = require('fs');

exports.Statistics = function (config) {
	var me = this;

	me.calculateSpeed = function (positions) {
		console.log('Calc Speed');

		var degToKm = 40074/360;

		var speed = [];
		var maxV = 0;

		for (var i = 0; i < positions.length-1; i++) {
			var dx = positions[i].x - positions[i+1].x;
			var dy = positions[i].y - positions[i+1].y;

			dx *= degToKm*Math.cos(positions[i].y*Math.PI/180);
			dy *= degToKm;

			var r = Math.sqrt(dx*dx + dy*dy);
			var v = r/(config.timeStepSeconds/3600);

			speed[i] = v;
			if (maxV < v) maxV = v;
		}

		console.log(maxV);
	}

	me.calculateGraph = function (events) {
		console.log('Calc Graph');

		var ignoreContacts = {};
		fs.readFileSync('data/contacts/ignore_nodes.tsv', 'utf8').split('\n').forEach(function (contact) {
			ignoreContacts[contact] = true;
		});

		var nodes = {};
		var edges = {};
		var count = 0;

		var connections = events.map(function (event) {
			var addresses = event.to.concat([event.from]);

			// remove duplicates
			for (var i = 0; i < addresses.length; i++) {
				if (addresses[i]) {
					for (var j = i+1; j < addresses.length; j++) {
						if (addresses[i].contact == addresses[j].contact) {
							addresses[i] = false;
							break;
						}
					}
				}
			}

			// Filter
			addresses = addresses.filter(function (address) {
				if (!address) return false;
				if (ignoreContacts[address.contact]) return false;
				return true;
			})

			// Add nodes
			addresses.forEach(function (address) {
				var contact = address.contact;
				if (!nodes[contact]) nodes[contact] = {label:contact, count:0, intensity:0, weight:0, edges:0, use:false};
				nodes[contact].count++;
				nodes[contact].intensity += 1/addresses.length;
			})

			return addresses;
		});

		connections.forEach(function (addresses) {
			// Add edge
			if (addresses.length > 1) {
				var weight = 1/(addresses.length-1) + 0.01;
				for (var i = 0; i < addresses.length; i++) {
					var contact1 = addresses[i].contact;
					for (var j = i+1; j < addresses.length; j++) {
						var contact2 = addresses[j].contact;

						if (nodes[contact1] && nodes[contact2]) {
							var contactA, contactB;
							if (contact1 < contact2) {
								contactA = contact1; contactB = contact2;
							} else {
								contactA = contact2; contactB = contact1;
							}

							var edgeName = contactA+'_'+contactB;

							if (!edges[edgeName]) edges[edgeName] = {source:contactA, target:contactB, weight:0};

							nodes[contact1].edges  += 1;
							nodes[contact2].edges  += 1;

							nodes[contact1].weight += weight;
							nodes[contact2].weight += weight;

							edges[edgeName].weight += weight;
						}
					}
				}
			}
		})

		nodeList = Object.keys(nodes).map(function (key) {
			var node = nodes[key];

			node.ok = false;
			if (!node) return false;
			if (node.weight < 10) return false; //5
			if (node.edges  < 10) return false;
			if (node.count  < 20) return false; //10

			var size = node.weight + node.intensity;

			node.ok = true;
			node.maxWeight = 0;
			return [node.label, node.label, size.toFixed(2), node.weight, node.edges, node.count].join('\t');
		}).filter(function (node) {
			return node;
		});
		nodeList.unshift('Id\tLabel\tSize');

		fs.writeFileSync('nodes.csv', nodeList.join('\n'), 'utf8');

		edgeList = Object.keys(edges).map(function (key) {
			var edge = edges[key];

			if (!nodes[edge.source].ok) return false;
			if (!nodes[edge.target].ok) return false;

			if (nodes[edge.source].maxWeight < edge.weight) nodes[edge.source].maxWeight = edge.weight;
			if (nodes[edge.target].maxWeight < edge.weight) nodes[edge.target].maxWeight = edge.weight;

			return edge;
		}).filter(function (edge) {
			return edge;
		});

		edgeList = edgeList.map(function (edge) {
			var f = Math.min(nodes[edge.source].maxWeight, nodes[edge.target].maxWeight);
			return [edge.source, edge.target, edge.weight/f, 'Undirected'].join('\t');
		})
		;
		edgeList.unshift('Source\tTarget\tWeight\tType');

		fs.writeFileSync('edges.csv', edgeList.join('\n'), 'utf8');

		console.log(nodeList.length, edgeList.length);
	}

	return me;
}
<|endoftext|>


<commit_before>/**
 * Created by jbbrokaw on 12/19/2014.
 */
var gameCollectionSource = $("#game-collection-template").html();
var gameSource = $("#game-template").html();
var userSource = $('#user-template').html();
var ratingSource = $('#rating-template').html();
var gameCollectionTemplate = Handlebars.compile(gameCollectionSource);
var gameTemplate = Handlebars.compile(gameSource);
var userTemplate = Handlebars.compile(userSource);
var ratingTemplate = Handlebars.compile(ratingSource);

var GameModel = Backbone.Model.extend({});

var GameCollection = Backbone.Collection.extend({
  group: 'all',
  urlBase: $('#url-root').val(),

  model: GameModel,

  url: function () {
    return this.urlBase + '/' + this.group;
  }
});

var UserModel = Backbone.Model.extend({
  defaults: {
    'csrf_token': $('#csrf').val(),
    'route': $('#follow-route').val()
  }
});

var RatingModel = Backbone.Model.extend({
  defaults: {
    'csrf_token': $('#csrf').val(),
    'route': $('#rate-route').val()
  }
});

var GameCollectionView = Backbone.View.extend({
  events: {
    'click #all-games': 'allGames',
    'click #my-games': 'myGames',
    'click #friends-games': 'friendsGames',
    'click .arrow-left.g-active': 'previousGame',
    'click .arrow-right.g-active': 'nextGame'
  },

  render: function () {
    $(this.el).html(gameCollectionTemplate({}));
    $('#content').empty().append(this.el);
    return this;
  },

  allGames: function () {
    $('#all-games').addClass('g-selected')
      .siblings().removeClass('g-selected');
    this.model.group = "all";
    this.model.fetch({
      success: function (model, response, options) {
        model.trigger('load');
      }
    });
    return this;
  },

  myGames: function () {
    $('#my-games').addClass('g-selected')
      .siblings().removeClass('g-selected');
    this.model.group = "mine";
    this.model.fetch({
      success: function (model, response, options) {
        model.trigger('load');
      }
    });
    return this;
  },

  friendsGames: function () {
    $('#friends-games').addClass('g-selected')
      .siblings().removeClass('g-selected');
    this.model.group = "friends";
    this.model.fetch({
      success: function (model, response, options) {
        model.trigger('load');
      }
    });
    return this;
  },

  previousGame: function () {
    this.model.selected -= 1;
    this.model.trigger('selection');
  },

  nextGame: function () {
    this.model.selected += 1;
    this.model.trigger('selection');
  }
});

var GameView = Backbone.View.extend({
  initialize: function() {
    this.listenTo(this.model, "gotGame", this.render);
  },

  render: function () {
    $(this.el).html(gameTemplate(this.model.attributes));
    $('.game').empty().append(this.el);

    var subAuthView = new UserView({
      model: new UserModel(this.model.get('subject_author')),
      el: $('.subject')[0]
    });
    subAuthView.render();

    var predAuthView = new UserView({
      model: new UserModel(this.model.get('predicate_author')),
      el: $('.predicate')[0]
    });
    predAuthView.render();

    var firstDrawAuthView = new UserView({
      model: new UserModel(this.model.get('first_drawing_author')),
      el: $('.first_drawing')[0]
    });
    firstDrawAuthView.render();

    var firstDescAuthView = new UserView({
      model: new UserModel(this.model.get('first_description_author')),
      el: $('.first_description')[0]
    });
    firstDescAuthView.render();

    var secDrawAuthView = new UserView({
      model: new UserModel(this.model.get('second_drawing_author')),
      el: $('.second_drawing')[0]
    });
    secDrawAuthView.render();

    var secDescAuthView = new UserView({
      model: new UserModel(this.model.get('second_description_author')),
      el: $('.second_description')[0]
    });
    secDescAuthView.render();

    $('.rating-box').remove();
    $('

').insertAfter('.game');
    var ratingView = new RatingView({
      model: new RatingModel(this.model.get('rating')),
      el: $('.rating-box')[0]
    });
    ratingView.render();

    return this;
  }
});

var UserView = Backbone.View.extend({
  events: {
    'click .f-button': 'follow',
  },

  render: function () {
    $(this.el).empty().html(userTemplate(this.model.attributes));
    if (this.model.get('followed')) {
      $(this.el).children('p').children('.f-button').text('☑');
    } else {
      $(this.el).children('p').children('.f-button').text('☐');
    }
  },

  follow: function () {
    $.post(this.model.get('route'), this.model.attributes)
      .done(this.followDone(this))
      .fail(function (response) {
        console.log(response);
      });
  },

  followDone: function (view) {
    return function (server_response) {
      view.model.set(server_response);
      view.render();
    };
  }
});

var RatingView = Backbone.View.extend({
  events: {
    'click .rating > input': 'sendRating'
  },

  render: function () {
    $(this.el).empty().html(ratingTemplate(this.model.attributes));
    var rating = this.model.get('author_score');
    if (rating ===  null) {
      $('.rating input').prop('checked', false);
    } else {
      $selected = $('.rating input').eq(-rating);
      $selected.prop('checked', true);
    }
  },

  sendRating: function (event) {
    this.model.set('author_score', $(event.currentTarget).val());
    $.post(this.model.get('route'), this.model.attributes)
      .done(this.ratingDone(this))
      .fail(function (response) {
        console.log(response);
      });
  },

  ratingDone: function (view) {
    return function (server_response) {
      view.model.set(server_response);
      view.render();
    };
  }
});

var AppRouter = Backbone.Router.extend({
  routes: {
    "*actions": "defaultRoute"
  },

  onCollectionLoad: function () {
    if (this.games.length === 0) {
      alert('No games in this category, reverting to all');
      this.mainView.allGames();
      return this;
    }
    this.games.selected = 0;
    this.games.trigger('selection');
  },

  onSelection: function () {
    if (this.games.selected <= 0) {
      $('.arrow-left').removeClass('g-active').addClass('g-inactive');
    } else {
      $('.arrow-left').removeClass('g-inactive').addClass('g-active');
    }
    if (this.games.selected >= (this.games.length - 1)) {
      $('.arrow-right').removeClass('g-active').addClass('g-inactive');
    } else {
      $('.arrow-right').removeClass('g-inactive').addClass('g-active');
    }
    if (typeof(this.subView) != 'undefined') {
      this.subView.remove();
    }
    this.subView = new GameView({
      model: this.games.models[this.games.selected]
    });
    if (this.subView.model.has('time_completed')) {
      this.subView.model.trigger('gotGame');
      //Go ahead and load old data, although followees might be out of date
    }
    this.subView.model.fetch({
      //Update data in all cases
      //(Maybe a flag could be set on follow/unfollow activity to indicate
      //when this is necessary)
      success: function (model, response, options) {
        model.trigger('gotGame');
      }
    });
  }
});

var app_router = new AppRouter();

app_router.on('route:defaultRoute', function () {
  this.games = new GameCollection();
  this.mainView = new GameCollectionView({model: this.games});
  this.mainView.render();
  this.listenTo(this.games, "load", this.onCollectionLoad);
  this.listenTo(this.games, "selection", this.onSelection);
  this.games.reset(initial);
  this.games.trigger('load');
});

Backbone.history.start();
<commit_msg>Adds router behavior for permanent links to completed games.<commit_after>/**
 * Created by jbbrokaw on 12/19/2014.
 */
var gameCollectionSource = $("#game-collection-template").html();
var gameSource = $("#game-template").html();
var userSource = $('#user-template').html();
var ratingSource = $('#rating-template').html();
var gameCollectionTemplate = Handlebars.compile(gameCollectionSource);
var gameTemplate = Handlebars.compile(gameSource);
var userTemplate = Handlebars.compile(userSource);
var ratingTemplate = Handlebars.compile(ratingSource);

var GameModel = Backbone.Model.extend({});

var GameCollection = Backbone.Collection.extend({
  group: 'all',
  urlBase: $('#url-root').val(),

  model: GameModel,

  url: function () {
    return this.urlBase + '/' + this.group;
  }
});

var UserModel = Backbone.Model.extend({
  defaults: {
    'csrf_token': $('#csrf').val(),
    'route': $('#follow-route').val()
  }
});

var RatingModel = Backbone.Model.extend({
  defaults: {
    'csrf_token': $('#csrf').val(),
    'route': $('#rate-route').val()
  }
});

var GameCollectionView = Backbone.View.extend({
  events: {
    'click #all-games': 'allGames',
    'click #my-games': 'myGames',
    'click #friends-games': 'friendsGames',
    'click .arrow-left.g-active': 'previousGame',
    'click .arrow-right.g-active': 'nextGame'
  },

  render: function () {
    $(this.el).html(gameCollectionTemplate({}));
    $('#content').empty().append(this.el);
    return this;
  },

  allGames: function () {
    $('#all-games').addClass('g-selected')
      .siblings().removeClass('g-selected');
    this.model.group = "all";
    this.model.fetch({
      success: function (model, response, options) {
        model.trigger('load');
      }
    });
    return this;
  },

  myGames: function () {
    $('#my-games').addClass('g-selected')
      .siblings().removeClass('g-selected');
    this.model.group = "mine";
    this.model.fetch({
      success: function (model, response, options) {
        model.trigger('load');
      }
    });
    return this;
  },

  friendsGames: function () {
    $('#friends-games').addClass('g-selected')
      .siblings().removeClass('g-selected');
    this.model.group = "friends";
    this.model.fetch({
      success: function (model, response, options) {
        model.trigger('load');
      }
    });
    return this;
  },

  previousGame: function () {
    this.model.selected -= 1;
    this.model.trigger('selection');
  },

  nextGame: function () {
    this.model.selected += 1;
    this.model.trigger('selection');
  }
});

var GameView = Backbone.View.extend({
  initialize: function() {
    this.listenTo(this.model, "gotGame", this.render);
  },

  render: function () {
    $(this.el).html(gameTemplate(this.model.attributes));
    $('.game').empty().append(this.el);

    var subAuthView = new UserView({
      model: new UserModel(this.model.get('subject_author')),
      el: $('.subject')[0]
    });
    subAuthView.render();

    var predAuthView = new UserView({
      model: new UserModel(this.model.get('predicate_author')),
      el: $('.predicate')[0]
    });
    predAuthView.render();

    var firstDrawAuthView = new UserView({
      model: new UserModel(this.model.get('first_drawing_author')),
      el: $('.first_drawing')[0]
    });
    firstDrawAuthView.render();

    var firstDescAuthView = new UserView({
      model: new UserModel(this.model.get('first_description_author')),
      el: $('.first_description')[0]
    });
    firstDescAuthView.render();

    var secDrawAuthView = new UserView({
      model: new UserModel(this.model.get('second_drawing_author')),
      el: $('.second_drawing')[0]
    });
    secDrawAuthView.render();

    var secDescAuthView = new UserView({
      model: new UserModel(this.model.get('second_description_author')),
      el: $('.second_description')[0]
    });
    secDescAuthView.render();

    $('.rating-box').remove();
    $('

').insertAfter('.game');
    var ratingView = new RatingView({
      model: new RatingModel(this.model.get('rating')),
      el: $('.rating-box')[0]
    });
    ratingView.render();

    return this;
  }
});

var UserView = Backbone.View.extend({
  events: {
    'click .f-button': 'follow'
  },

  render: function () {
    $(this.el).empty().html(userTemplate(this.model.attributes));
    if (this.model.get('followed')) {
      $(this.el).children('p').children('.f-button').text('☑');
    } else {
      $(this.el).children('p').children('.f-button').text('☐');
    }
  },

  follow: function () {
    $.post(this.model.get('route'), this.model.attributes)
      .done(this.followDone(this))
      .fail(function (response) {
        console.log(response);
      });
  },

  followDone: function (view) {
    return function (server_response) {
      view.model.set(server_response);
      view.render();
    };
  }
});

var RatingView = Backbone.View.extend({
  events: {
    'click .rating > input': 'sendRating'
  },

  render: function () {
    $(this.el).empty().html(ratingTemplate(this.model.attributes));
    var rating = this.model.get('author_score');
    if (rating ===  null) {
      $('.rating input').prop('checked', false);
    } else {
      $selected = $('.rating input').eq(-rating);
      $selected.prop('checked', true);
    }
  },

  sendRating: function (event) {
    this.model.set('author_score', $(event.currentTarget).val());
    $.post(this.model.get('route'), this.model.attributes)
      .done(this.ratingDone(this))
      .fail(function (response) {
        console.log(response);
      });
  },

  ratingDone: function (view) {
    return function (server_response) {
      view.model.set(server_response);
      view.render();
    };
  }
});

var AppRouter = Backbone.Router.extend({
  routes: {
    ":id": "showGame",
    "*actions": "defaultRoute"
  },

  onCollectionLoad: function () {
    if (this.games.length === 0) {
      alert('No games in this category, reverting to all');
      this.mainView.allGames();
      return this;
    }
    this.games.selected = 0;
    this.games.trigger('selection');
  },

  onSelection: function () {
    if (this.games.selected <= 0) {
      $('.arrow-left').removeClass('g-active').addClass('g-inactive');
    } else {
      $('.arrow-left').removeClass('g-inactive').addClass('g-active');
    }
    if (this.games.selected >= (this.games.length - 1)) {
      $('.arrow-right').removeClass('g-active').addClass('g-inactive');
    } else {
      $('.arrow-right').removeClass('g-inactive').addClass('g-active');
    }
    if (typeof(this.subView) != 'undefined') {
      this.subView.remove();
    }
    this.subView = new GameView({
      model: this.games.models[this.games.selected]
    });
    if (this.subView.model.has('time_completed')) {
      this.subView.model.trigger('gotGame');
      //Go ahead and load old data, although followees might be out of date
    }
    this.subView.model.fetch({
      //Update data in all cases
      //(Maybe a flag could be set on follow/unfollow activity to indicate
      //when this is necessary)
      success: function (model, response, options) {
        model.trigger('gotGame');
      }
    });
  }
});

var app_router = new AppRouter();

app_router.on('route:defaultRoute', function () {
  this.games = new GameCollection();
  this.mainView = new GameCollectionView({model: this.games});
  this.mainView.render();
  this.listenTo(this.games, "load", this.onCollectionLoad);
  this.listenTo(this.games, "selection", this.onSelection);
  this.games.reset(initial);  // initial is provided in html
  this.games.trigger('load');
});

app_router.on('route:showGame', function (id) {
  if (typeof(this.games) === 'undefined') {
    this.games = new GameCollection();
    this.listenTo(this.games, "load", this.onCollectionLoad);
    this.listenTo(this.games, "selection", this.onSelection);
    this.games.reset(initial);  // initial is provided in html
  }
  if (typeof(this.mainView) === 'undefined') {
    this.mainView = new GameCollectionView({model: this.games});
    this.mainView.render();
  }
  id = parseInt(id);
  console.log(id);
  console.log(typeof(id));
  var chosenGame = this.games.findWhere({'id': id});
  var chosenIndex = this.games.models.indexOf(chosenGame);
  if (chosenIndex === -1) {
    // TODO: Maybe explain what happened to the user?
    console.log("Bad Game Index");
    chosenIndex = 0;
  }
  this.games.selected = chosenIndex;
  this.games.trigger('selection');

});

Backbone.history.start();
<|endoftext|>


<commit_before>'use strict';

/*
 * folderElement function module:
 *   This module holds the creation logic for folder elements.
 */

// Node modules
const $ = require('jquery');
const BigNumber = require('bignumber.js');
const tools = require('./uiTools');
const fileElement = require('./fileElement');

// Update file element with jquery
function updateFolderElement(f, el) {
	el = el || $('#' + f.hashedPath);

	// Set size as empty if there are no files
	if (f.isEmpty()) {
		el.find('.size').text('empty');
		el.find('.detail').text('--');
	} else {
		el.find('.detail').text(f.count + ' items');
	}

	return el;
}

// Make folder element with jquery
function makeFolderElement(f, navigateTo) {
	var el = fileElement(f);
	el.addClass('folder');
	// add a / to distinguish folders
	el.find('.name').text(f.name + '/');

	// Populate its fields and graphics
	updateFolderElement(f, el);

	// Navigate to the folder if the element, not its buttons, is clicked
	el.off('dblclick');
	el.dblclick(function(e) {
		if (!$(e.target).is('.button, .fa')) {
			navigateTo(f);
		}
	});

	// Return the new element
	return el;
}

module.exports = function(f, funct) {
	// Determine to update or add a folder element based on if it exists already
	if (!$('#' + f.hashedPath).length) {
		return makeFolderElement(f, funct);
	} else {
		return updateFolderElement(f);
	}
};
<commit_msg>Revert "append a / to folder names"<commit_after>'use strict';

/*
 * folderElement function module:
 *   This module holds the creation logic for folder elements.
 */

// Node modules
const $ = require('jquery');
const BigNumber = require('bignumber.js');
const tools = require('./uiTools');
const fileElement = require('./fileElement');

// Update file element with jquery
function updateFolderElement(f, el) {
	el = el || $('#' + f.hashedPath);

	// Set size as empty if there are no files
	if (f.isEmpty()) {
		el.find('.size').text('empty');
		el.find('.detail').text('--');
	} else {
		el.find('.detail').text(f.count + ' items');
	}

	return el;
}

// Make folder element with jquery
function makeFolderElement(f, navigateTo) {
	var el = fileElement(f);
	el.addClass('folder');

	// Populate its fields and graphics
	updateFolderElement(f, el);

	// Navigate to the folder if the element, not its buttons, is clicked
	el.off('dblclick');
	el.dblclick(function(e) {
		if (!$(e.target).is('.button, .fa')) {
			navigateTo(f);
		}
	});

	// Return the new element
	return el;
}

module.exports = function(f, funct) {
	// Determine to update or add a folder element based on if it exists already
	if (!$('#' + f.hashedPath).length) {
		return makeFolderElement(f, funct);
	} else {
		return updateFolderElement(f);
	}
};
<|endoftext|>