<commit_before>'use strict'

const util = require('util')
const path = require('path')
const fs = require('fs')
const sass = require('./sass')
const postcss = require('./postcss')

/**
 * Load SASS and transform to CSS, add vendor prefixes and minify.
 * @public
 * @param {String} filePath - Absolute path to file.
 * @param {?Object} opts - Options.
 * @returns {Promise<String>} CSS.
 */
module.exports = async function(filePath, opts = {}) {

	if (typeof filePath !== 'string') throw new Error(`'filePath' must be a string`)
	if (typeof opts !== 'object') throw new Error(`'opts' must be undefined or an object`)

	const folderPath = path.dirname(filePath)

	opts = Object.assign({
		optimize: false
	}, opts)

	let output = null

	output = await util.promisify(fs.readFile)(filePath, 'utf8')
	output = await sass(folderPath, output, opts)
	output = await postcss(filePath, output, opts)

	return output

}

/**
 * Tell Rosid with which file extension it should load the file.
 * @public
 * @param {?Object} opts - Options.
 * @returns {String} File extension.
 */
module.exports.in = function(opts) {

	return (opts != null && opts.in != null) ? opts.in : '.sass'

}

/**
 * Tell Rosid with which file extension it should save the file.
 * @public
 * @param {?Object} opts - Options.
 * @returns {String} File extension.
 */
module.exports.out = function(opts) {

	return (opts != null && opts.out != null) ? opts.out : '.css'

}

/**
 * Attach an array to the function, which contains a list of
 * file patterns used by the handler. The array will be used by Rosid for caching purposes.
 * @public
 */
module.exports.cache = [
	'**/*.sass',
	'**/*.scss',
	'**/*.css'
]<commit_msg>Use fs.promises<commit_after>'use strict'

const path = require('path')
const fs = require('fs').promises
const sass = require('./sass')
const postcss = require('./postcss')

/**
 * Load SASS and transform to CSS, add vendor prefixes and minify.
 * @public
 * @param {String} filePath - Absolute path to file.
 * @param {?Object} opts - Options.
 * @returns {Promise<String>} CSS.
 */
module.exports = async function(filePath, opts = {}) {

	if (typeof filePath !== 'string') throw new Error(`'filePath' must be a string`)
	if (typeof opts !== 'object') throw new Error(`'opts' must be undefined or an object`)

	const folderPath = path.dirname(filePath)

	opts = Object.assign({
		optimize: false
	}, opts)

	let output = null

	output = await fs.readFile(filePath, 'utf8')
	output = await sass(folderPath, output, opts)
	output = await postcss(filePath, output, opts)

	return output

}

/**
 * Tell Rosid with which file extension it should load the file.
 * @public
 * @param {?Object} opts - Options.
 * @returns {String} File extension.
 */
module.exports.in = function(opts) {

	return (opts != null && opts.in != null) ? opts.in : '.sass'

}

/**
 * Tell Rosid with which file extension it should save the file.
 * @public
 * @param {?Object} opts - Options.
 * @returns {String} File extension.
 */
module.exports.out = function(opts) {

	return (opts != null && opts.out != null) ? opts.out : '.css'

}

/**
 * Attach an array to the function, which contains a list of
 * file patterns used by the handler. The array will be used by Rosid for caching purposes.
 * @public
 */
module.exports.cache = [
	'**/*.sass',
	'**/*.scss',
	'**/*.css'
]<|endoftext|>


<commit_before>'use strict';

const { startServer } = require('./server');
const { propertiesPlugin } = require('./idl');

const { inspect } = require('util');

Error.stackTraceLimit = 100;

Object.assign(inspect.defaultOptions, {
  colors: true,
  depth: 10,
});

const printer = level => function (...args) {
  if (level === 'info') { return; }
  const beautifiedArgs = args.map(arg => typeof arg === 'string' ? arg : inspect(arg).replace(/\\n/g, '\n'));
  global.console[level](...beautifiedArgs);
};

startServer({
  conf: './examples/pet.schema.yml',
  // This will be fired on request errors. Startup errors are thrown instead
  /* onRequestError(error) {
    global.console.error('Sending error to monitoring tool', error);
  }, */
  // Can overwrite logging (by default, uses console)
  logger: printer,
  // arg.data length is limited to 1000 by default. This can be changed, or disabled (using 0)
  /* maxDataLength: 1000, */
  // Pagination default size. Defaults to 100. 0 to disable pagination.
  /* defaultPageSize: 100, */
  // User can override pagination size. This sets an upper limit. Defaults to 100.
  /* maxPageSize: 100, */
})
.then(() => {
  printer('log')('Server started');
})
.catch(exception => {
  printer('error')('Exception at server startup:', exception);
});

module.exports = {
  startServer,
  propertiesPlugin,
};
<commit_msg>Fix line width<commit_after>'use strict';

const { startServer } = require('./server');
const { propertiesPlugin } = require('./idl');

const { inspect } = require('util');

Error.stackTraceLimit = 100;

Object.assign(inspect.defaultOptions, {
  colors: true,
  depth: 10,
});

const printer = level => function (...args) {
  if (level === 'info') { return; }
  const beautifiedArgs = args.map(arg => {
    return typeof arg === 'string' ? arg : inspect(arg).replace(/\\n/g, '\n');
  });
  global.console[level](...beautifiedArgs);
};

startServer({
  conf: './examples/pet.schema.yml',
  // This will be fired on request errors. Startup errors are thrown instead
  /* onRequestError(error) {
    global.console.error('Sending error to monitoring tool', error);
  }, */
  // Can overwrite logging (by default, uses console)
  logger: printer,
  // arg.data length is limited to 1000 by default.
  // This can be changed, or disabled (using 0)
  /* maxDataLength: 1000, */
  // Pagination default size. Defaults to 100. 0 to disable pagination.
  /* defaultPageSize: 100, */
  // User can override pagination size. This sets an upper limit.
  // Defaults to 100.
  /* maxPageSize: 100, */
})
.then(() => {
  printer('log')('Server started');
})
.catch(exception => {
  printer('error')('Exception at server startup:', exception);
});

module.exports = {
  startServer,
  propertiesPlugin,
};
<|endoftext|>


<commit_before>import { dirname } from 'path'
import { writeFileSync } from 'fs'
import { renderSync } from 'node-sass'
import { isString, isFunction } from 'util'
import { createFilter } from 'rollup-pluginutils'
import { insertStyle } from './style.js'
import { ensureFileSync } from 'fs-extra'

export default function plugin (options = {}) {
  const filter = createFilter(options.include || [ '**/*.sass', '**/*.scss' ], options.exclude || 'node_modules/**')
  const insertFnName = '___$insertStyle'
  const styles = []
  const styleMaps = {}
  let dest = ''

  options.output = options.output || false
  options.insert = options.insert || false
  options.processor = options.processor || null
  options.options = options.options || null

  return {
    name: 'sass',

    intro () {
      if (options.insert) {
        return insertStyle.toString().replace(/insertStyle/, insertFnName)
      }
    },

    options (opts) {
      dest = opts.dest || opts.entry
    },

    async transform (code, id) {
      if (!filter(id)) {
        return null
      }

      const paths = [dirname(id), process.cwd()]
      const sassConfig = Object.assign({ data: code }, options.options)

      sassConfig.includePaths = sassConfig.includePaths
            ? sassConfig.includePaths.concat(paths)
            : paths

      try {
        let css = renderSync(sassConfig).css.toString()
        let code = ''

        if (css.trim()) {
          if (isFunction(options.processor)) {
            css = await options.processor(css, id)
          }
          if (styleMaps[id]) {
            styleMaps[id].content = css
          } else {
            styles.push(styleMaps[id] = {
              id: id,
              content: css
            })
          }
          css = JSON.stringify(css)

          if (options.insert === true) {
            code = `${insertFnName}(${css});`
          } else if (options.output === false) {
            code = css
          } else {
            code = `"";`
          }
        }

        return {
          code: `export default ${code};`,
          map: { mappings: '' }
        }
      } catch (error) {
        throw error
      }
    },

    async ongenerate (opts, result) {
      if (!options.insert && (!styles.length || options.output === false)) {
        return
      }

      const css = styles.map((style) => {
        return style.content
      }).join('')

      if (isString(options.output)) {
        ensureFileSync(options.output, (err) => {
          if (err) throw err
        })
        return writeFileSync(options.output, css)
      } else if (isFunction(options.output)) {
        return options.output(css, styles)
      } else if (!options.insert && dest) {
        if (dest.endsWith('.js')) {
          dest = dest.slice(0, -3)
        }
        dest = `${dest}.css`
        ensureFileSync(dest, (err) => {
          if (err) throw err
        })
        return writeFileSync(dest, css)
      }
    }
  }
}
<commit_msg>Fix #34<commit_after>import { dirname } from 'path'
import { writeFileSync } from 'fs'
import { renderSync } from 'node-sass'
import { isString, isFunction } from 'util'
import { createFilter } from 'rollup-pluginutils'
import { insertStyle } from './style.js'
import { ensureFileSync } from 'fs-extra'

export default function plugin (options = {}) {
  const filter = createFilter(options.include || [ '**/*.sass', '**/*.scss' ], options.exclude || 'node_modules/**')
  const insertFnName = '___$insertStyle'
  const styles = []
  const styleMaps = {}
  let dest = ''
  let prependSass = ''

  options.output = options.output || false
  options.insert = options.insert || false
  options.processor = options.processor || null
  options.options = options.options || null

  if (options.options && options.options.data) {
    prependSass = options.options.data
    delete options.options.data
  }

  return {
    name: 'sass',

    intro () {
      if (options.insert) {
        return insertStyle.toString().replace(/insertStyle/, insertFnName)
      }
    },

    options (opts) {
      dest = opts.dest || opts.entry
    },

    async transform (code, id) {
      if (!filter(id)) {
        return null
      }

      const paths = [dirname(id), process.cwd()]
      const sassConfig = Object.assign({ data: prependSass + code }, options.options)

      sassConfig.includePaths = sassConfig.includePaths
            ? sassConfig.includePaths.concat(paths)
            : paths

      try {
        let css = renderSync(sassConfig).css.toString()
        let code = ''

        if (css.trim()) {
          if (isFunction(options.processor)) {
            css = await options.processor(css, id)
          }
          if (styleMaps[id]) {
            styleMaps[id].content = css
          } else {
            styles.push(styleMaps[id] = {
              id: id,
              content: css
            })
          }
          css = JSON.stringify(css)

          if (options.insert === true) {
            code = `${insertFnName}(${css});`
          } else if (options.output === false) {
            code = css
          } else {
            code = `"";`
          }
        }

        return {
          code: `export default ${code};`,
          map: { mappings: '' }
        }
      } catch (error) {
        throw error
      }
    },

    async ongenerate (opts, result) {
      if (!options.insert && (!styles.length || options.output === false)) {
        return
      }

      const css = styles.map((style) => {
        return style.content
      }).join('')

      if (isString(options.output)) {
        ensureFileSync(options.output, (err) => {
          if (err) throw err
        })
        return writeFileSync(options.output, css)
      } else if (isFunction(options.output)) {
        return options.output(css, styles)
      } else if (!options.insert && dest) {
        if (dest.endsWith('.js')) {
          dest = dest.slice(0, -3)
        }
        dest = `${dest}.css`
        ensureFileSync(dest, (err) => {
          if (err) throw err
        })
        return writeFileSync(dest, css)
      }
    }
  }
}
<|endoftext|>


<commit_before>var API = require('./main.js')

function TVSAPI(){
}

TVSAPI.prototype.getUser = function(callback){
  API.get('user', {}, callback)
}

TVSAPI.prototype.getToWatch = function(options, callback){
  API.get('to-watch', options, callback)
}

TVSAPI.prototype.getAgenda = function(options, callback){
  API.get('agenda', options, callback)
}

TVSAPI.prototype.getLibrary = function(options, callback){
  API.get('library', options, callback)
}

TVSAPI.prototype.explore = function(options, callback){
  API.get('explore', options, callback)
}

TVSAPI.prototype.getShow = function(options, callback){
  API.get('show', options, callback)
}

TVSAPI.prototype.follow = function(options, callback){
  API.post('follow', options, callback)
}

TVSAPI.prototype.isfollow = function(options, callback){
  API.post('isfollow', options, callback)
}

TVSAPI.prototype.unfollow = function(options, callback){
  API.post('unfollow', options, callback)
}

TVSAPI.prototype.archive = function(options, callback){
  API.post('archive', options, callback)
}

TVSAPI.prototype.isArchived = function(options, callback){
  API.post('isarchived', options, callback)
}

TVSAPI.prototype.unArchive = function(options, callback){
  API.post('unarchive', options, callback)
}

TVSAPI.prototype.setShowProgress = function(options, callback){
  API.post('show_progress', options, callback)
}

TVSAPI.prototype.deleteShowProgress = function(options, callback){
  API.post('delete_show_progress', options, callback)
}

TVSAPI.prototype.getEpisode = function(options, callback){
  API.get('episode', options, callback)
}

TVSAPI.prototype.setWatchedEpisode = function(options, callback){
  API.post('checkin', options, callback)
}

TVSAPI.prototype.isWatchedEpisode = function(options, callback){
  API.post('ischecked', options, callback)
}

TVSAPI.prototype.unwatchEpisode = function(options, callback){
  API.post('checkout', options, callback)
}

TVSAPI.prototype.getProgess = function(options, callback){
  API.get('progress', options, callback)
}

TVSAPI.prototype.setProgess = function(options, callback){
  API.post('progress', options, callback)
}

TVSAPI.prototype.setEmotion = function(options, callback){
  API.post('emotion', options, callback)
}

TVSAPI.prototype.deleteEmotion = function(options, callback){
  API.post('delete_emotion', options, callback)
}
module.exports = new TVSAPI()
<commit_msg>fix post get<commit_after>var API = require('./main.js')

function TVSAPI(){
}

TVSAPI.prototype.getUser = function(callback){
  API.get('user', {}, callback)
}

TVSAPI.prototype.getToWatch = function(options, callback){
  API.get('to-watch', options, callback)
}

TVSAPI.prototype.getAgenda = function(options, callback){
  API.get('agenda', options, callback)
}

TVSAPI.prototype.getLibrary = function(options, callback){
  API.get('library', options, callback)
}

TVSAPI.prototype.explore = function(options, callback){
  API.get('explore', options, callback)
}

TVSAPI.prototype.getShow = function(options, callback){
  API.get('show', options, callback)
}

TVSAPI.prototype.follow = function(options, callback){
  API.post('follow', options, callback)
}

TVSAPI.prototype.isfollow = function(options, callback){
  API.get('isfollow', options, callback)
}

TVSAPI.prototype.unfollow = function(options, callback){
  API.post('unfollow', options, callback)
}

TVSAPI.prototype.archive = function(options, callback){
  API.post('archive', options, callback)
}

TVSAPI.prototype.isArchived = function(options, callback){
  API.get('isarchived', options, callback)
}

TVSAPI.prototype.unArchive = function(options, callback){
  API.post('unarchive', options, callback)
}

TVSAPI.prototype.setShowProgress = function(options, callback){
  API.post('show_progress', options, callback)
}

TVSAPI.prototype.deleteShowProgress = function(options, callback){
  API.post('delete_show_progress', options, callback)
}

TVSAPI.prototype.getEpisode = function(options, callback){
  API.get('episode', options, callback)
}

TVSAPI.prototype.setWatchedEpisode = function(options, callback){
  API.post('checkin', options, callback)
}

TVSAPI.prototype.isWatchedEpisode = function(options, callback){
  API.get('ischecked', options, callback)
}

TVSAPI.prototype.unwatchEpisode = function(options, callback){
  API.post('checkout', options, callback)
}

TVSAPI.prototype.getProgess = function(options, callback){
  API.get('progress', options, callback)
}

TVSAPI.prototype.setProgess = function(options, callback){
  API.post('progress', options, callback)
}

TVSAPI.prototype.setEmotion = function(options, callback){
  API.post('emotion', options, callback)
}

TVSAPI.prototype.deleteEmotion = function(options, callback){
  API.post('delete_emotion', options, callback)
}
module.exports = new TVSAPI()
<|endoftext|>


<commit_before>import React from 'react'
import md5 from 'md5'
import querystring from 'query-string'
import isRetina from 'is-retina'

class Gravatar extends React.Component {
  static displayName = 'Gravatar'
  static propTypes = {
    email: React.PropTypes.string,
    md5: React.PropTypes.string,
    size: React.PropTypes.number,
    rating: React.PropTypes.string,
    default: React.PropTypes.string,
    className: React.PropTypes.string,
    protocol: React.PropTypes.string,
    style: React.PropTypes.object,
  }
  static defaultProps = {
    size: 50,
    rating: 'g',
    default: 'retro',
    protocol: '//',
  }

  render() {
    const base = `${this.props.protocol}www.gravatar.com/avatar/`

    const query = querystring.stringify({
      s: this.props.size,
      r: this.props.rating,
      d: this.props.default,
    })

    const retinaQuery = querystring.stringify({
      s: this.props.size * 2,
      r: this.props.rating,
      d: this.props.default,
    })

    // Gravatar service currently trims and lowercases all registered emails
    const formattedEmail = ('' + this.props.email).trim().toLowerCase();

    let hash
    if (this.props.md5) {
      hash = this.props.md5
    } else if (typeof this.props.email === 'string') {
      hash = md5(formattedEmail)
    } else {
      console.warn(
        'Gravatar image can not be fetched. Either the "email" or "md5" prop must be specified.'
      )
      return (<script />)
    }

    const src = `${base}${hash}?${query}`
    const retinaSrc = `${base}${hash}?${retinaQuery}`

    let modernBrowser = true  // server-side, we render for modern browsers

    if (typeof window !== 'undefined') {
      // this is not NodeJS
      modernBrowser = 'srcset' in document.createElement('img')
    }

    let className = 'react-gravatar'
    if (this.props.className) {
      className = `${className} ${this.props.className}`
    }

    // Clone this.props and then delete Component specific props so we can
    // spread the rest into the img.
    let { ...rest } = this.props
    delete rest.md5
    delete rest.email
    delete rest.rating
    delete rest.size
    delete rest.style
    delete rest.className
    delete rest.default
    if (!modernBrowser && isRetina()) {
      return (
        <img
          alt={`Gravatar for ${formattedEmail}`}
          style={this.props.style}
          src={retinaSrc}
          height={this.props.size}
          width={this.props.size}
          {...rest}
          className={className}
        />
      )
    }
    return (
      <img
        alt={`Gravatar for ${formattedEmail}`}
        style={this.props.style}
        src={src}
        srcSet={`${retinaSrc} 2x`}
        height={this.props.size}
        width={this.props.size}
        {...rest}
        className={className}
      />
    )
  }
}

module.exports = Gravatar
<commit_msg>Remove protocol prop from img attributes (#133)<commit_after>import React from 'react'
import md5 from 'md5'
import querystring from 'query-string'
import isRetina from 'is-retina'

class Gravatar extends React.Component {
  static displayName = 'Gravatar'
  static propTypes = {
    email: React.PropTypes.string,
    md5: React.PropTypes.string,
    size: React.PropTypes.number,
    rating: React.PropTypes.string,
    default: React.PropTypes.string,
    className: React.PropTypes.string,
    protocol: React.PropTypes.string,
    style: React.PropTypes.object,
  }
  static defaultProps = {
    size: 50,
    rating: 'g',
    default: 'retro',
    protocol: '//',
  }

  render() {
    const base = `${this.props.protocol}www.gravatar.com/avatar/`

    const query = querystring.stringify({
      s: this.props.size,
      r: this.props.rating,
      d: this.props.default,
    })

    const retinaQuery = querystring.stringify({
      s: this.props.size * 2,
      r: this.props.rating,
      d: this.props.default,
    })

    // Gravatar service currently trims and lowercases all registered emails
    const formattedEmail = ('' + this.props.email).trim().toLowerCase();

    let hash
    if (this.props.md5) {
      hash = this.props.md5
    } else if (typeof this.props.email === 'string') {
      hash = md5(formattedEmail)
    } else {
      console.warn(
        'Gravatar image can not be fetched. Either the "email" or "md5" prop must be specified.'
      )
      return (<script />)
    }

    const src = `${base}${hash}?${query}`
    const retinaSrc = `${base}${hash}?${retinaQuery}`

    let modernBrowser = true  // server-side, we render for modern browsers

    if (typeof window !== 'undefined') {
      // this is not NodeJS
      modernBrowser = 'srcset' in document.createElement('img')
    }

    let className = 'react-gravatar'
    if (this.props.className) {
      className = `${className} ${this.props.className}`
    }

    // Clone this.props and then delete Component specific props so we can
    // spread the rest into the img.
    let { ...rest } = this.props
    delete rest.md5
    delete rest.email
    delete rest.protocol
    delete rest.rating
    delete rest.size
    delete rest.style
    delete rest.className
    delete rest.default
    if (!modernBrowser && isRetina()) {
      return (
        <img
          alt={`Gravatar for ${formattedEmail}`}
          style={this.props.style}
          src={retinaSrc}
          height={this.props.size}
          width={this.props.size}
          {...rest}
          className={className}
        />
      )
    }
    return (
      <img
        alt={`Gravatar for ${formattedEmail}`}
        style={this.props.style}
        src={src}
        srcSet={`${retinaSrc} 2x`}
        height={this.props.size}
        width={this.props.size}
        {...rest}
        className={className}
      />
    )
  }
}

module.exports = Gravatar
<|endoftext|>


<commit_before><commit_msg>modify keyboard layout<commit_after><|endoftext|>


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

'use strict';

const yargs = require('yargs');
const fs = require('fs');
const path = require('path');

const k8s = require('auto-kubernetes-client');

const logger = require('log4js').getLogger();

const argv = yargs
	.alias('s', 'server').describe('server', 'The address and port of the Kubernetes API server')
	.alias('cacert', 'certificate-authority').describe('certificate-authority', 'Path to a cert. file for the certificate authority')
	.alias('cert', 'client-certificate').describe('client-certificate', 'Path to a client certificate file for TLS')
	.alias('key', 'client-key').describe('client-key', 'Path to a client key file for TLS')
	.boolean('insecure-skip-tls-verify').describe('insecure-skip-tls-verify', 'If true, the server\'s certificate will not be checked for validity. This will make your HTTPS connections insecure')
	.describe('token', 'Bearer token for authentication to the API server')
	.describe('namespace', 'The namespace to watch').demandOption('namespace')
	.help()
	.argv;

/**
 * Creates basic configuration for accessing the Kubernetes API server
 *
 * @param {Object} argv Command line arguments
 * @returns {Object} Kubernetes client configuration
 */
function createK8sConfig(argv) {
	let k8sConfig;
	if (argv.server) {
		// For local development
		k8sConfig = {
			url: argv.server,
			insecureSkipTlsVerify: argv.insecureSkipTlsVerify
		};
		if (argv.certificateAuthority) {
			k8sConfig.ca = fs.readFileSync(argv.certificateAuthority, 'utf8');
		}
		if (argv.token) {
			k8sConfig.auth = { bearer: argv.token };
		} else if (argv.username && argv.password) {
			k8sConfig.auth = { user: argv.username, pass: argv.password };
		} else if (argv.clientCertificate && argv.clientKey) {
			k8sConfig.cert = fs.readFileSync(argv.clientCertificate, 'utf8');
			k8sConfig.key = fs.readFileSync(argv.clientKey, 'utf8');
		}
	} else if (process.env.KUBERNETES_SERVICE_HOST) {
		// Runs in Kubernetes
		const credentialsPath = '/var/run/secrets/kubernetes.io/serviceaccount/';
		k8sConfig = {
			url: `https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT}`,
			ca: fs.readFileSync(path.resolve(credentialsPath, 'ca.crt'), 'utf8'),
			auth: { bearer: fs.readFileSync(path.resolve(credentialsPath, 'token'), 'utf8') }
		}
	} else {
		throw new Error('Unknown Kubernetes API server');
	}

	return k8sConfig;
}

const sqsClientOptions = {
	endpoint: process.env.AWS_SQS_ENDPOINT_URL_OVERRIDE,
	region: process.env.AWS_REGION,
};

const SQSQueue = require('./resources/sqs');
const PromisesQueue = require('./promises-queue');

const k8sConfig = createK8sConfig(argv);
k8s(k8sConfig).then(function onConnected(k8sClient) {
	const awsResourcesClient = k8sClient.group('aws.k8s.collaborne.com', 'v1').ns(argv.namespace);

	const resourceDescriptions = [{
		type: 'queues',
		resourceClient: new SQSQueue(sqsClientOptions)
	}];

	function resourceLoop(type, k8sResourceClient, resourceClient, promisesQueue) {
		k8sResourceClient.list()
			.then(list => {
				const resourceVersion = list.metadata.resourceVersion;

				// Treat all resources we see as "update", which will trigger a creation/update of attributes accordingly.
				for (const resource of list.items) {
					const name = resource.metadata.name;
					promisesQueue.enqueue(name, function() {
						logger.info(`[${name}]: Syncing`);
						return resourceClient.update(resource);
					}).then(function(data) {
						logger.info(`[${name}]: ${JSON.stringify(data)}`);
					}, function(err) {
						logger.error(`[${name}]: ${err.message} (${err.code})`);
					});
				}

				return resourceVersion;
			}).then(resourceVersion => {
				// Start watching the resources from that version on
				logger.info(`Watching ${type} at ${resourceVersion}...`);
				k8sResourceClient.watch(resourceVersion)
					.on('data', function(item) {
						const resource = item.object;
						const name = resource.metadata.name;

						let next;

						switch (item.type) {
						case 'ADDED':
							next = function() {
								logger.info(`[${name}]: Creating resource`);
								return resourceClient.create(resource);
							};
							break;
						case 'MODIFIED':
							next = function() {
								logger.info(`[${name}]: Updating resource attributes`);
								return resourceClient.update(resource);
							};
							break;
						case 'DELETED':
							next = function() {
								logger.info(`[${name}]: Deleting resource`);
								return resourceClient.delete(resource);
							};
							break;
						case 'ERROR':
							// Log the message, and continue: usually the stream would end now, but there might be more events
							// in it that we do want to consume.
							logger.warn(`Error while watching: ${item.object.message}, ignoring`);
							return;
						default:
							logger.warn(`Unkown watch event type ${item.type}, ignoring`);
							return;
						}

						// Note that we retain the 'rejected' state here: an existing resource that ended in a rejection
						// will effectively stay rejected.
						const result = promisesQueue.enqueue(name, next).then(function(data) {
							logger.info(`[${name}]: ${JSON.stringify(data)}`);
						}, function(err) {
							logger.error(`[${name}]: ${err.message} (${err.code})`);
						});

						return result;
					})
					.on('end', function() {
						// Restart the watch from the last known version.
						logger.info('Watch ended, restarting');
						return resourceLoop(type, k8sResourceClient, resourceClient, promisesQueue);
					});
			})
	}

	resourceDescriptions.forEach(resourceDescription => {
		const k8sResourceClient = awsResourcesClient[resourceDescription.type];
		if (k8sResourceClient) {
			const promisesQueue = new PromisesQueue();
			resourceLoop(resourceDescription.type, resourceDescription.k8sResourceClient, resourceDescription.resourceClient, promisesQueue);
		} else {
			console.error(`Resources of type ${resourceDescription.type} are not defined as Kubernetes ThirdPartyResource. Available ThirdPartyResources ${Object.keys(awsResourcesClient)}.`);
		}
	});
}).catch(function(err) {
	logger.error(`Uncaught error, aborting: ${err.message}`);
	process.exit(1);
});
<commit_msg>Actually use the kubernetes resource client we created<commit_after>#!/usr/bin/env node

'use strict';

const yargs = require('yargs');
const fs = require('fs');
const path = require('path');

const k8s = require('auto-kubernetes-client');

const logger = require('log4js').getLogger();

const argv = yargs
	.alias('s', 'server').describe('server', 'The address and port of the Kubernetes API server')
	.alias('cacert', 'certificate-authority').describe('certificate-authority', 'Path to a cert. file for the certificate authority')
	.alias('cert', 'client-certificate').describe('client-certificate', 'Path to a client certificate file for TLS')
	.alias('key', 'client-key').describe('client-key', 'Path to a client key file for TLS')
	.boolean('insecure-skip-tls-verify').describe('insecure-skip-tls-verify', 'If true, the server\'s certificate will not be checked for validity. This will make your HTTPS connections insecure')
	.describe('token', 'Bearer token for authentication to the API server')
	.describe('namespace', 'The namespace to watch').demandOption('namespace')
	.help()
	.argv;

/**
 * Creates basic configuration for accessing the Kubernetes API server
 *
 * @param {Object} argv Command line arguments
 * @returns {Object} Kubernetes client configuration
 */
function createK8sConfig(argv) {
	let k8sConfig;
	if (argv.server) {
		// For local development
		k8sConfig = {
			url: argv.server,
			insecureSkipTlsVerify: argv.insecureSkipTlsVerify
		};
		if (argv.certificateAuthority) {
			k8sConfig.ca = fs.readFileSync(argv.certificateAuthority, 'utf8');
		}
		if (argv.token) {
			k8sConfig.auth = { bearer: argv.token };
		} else if (argv.username && argv.password) {
			k8sConfig.auth = { user: argv.username, pass: argv.password };
		} else if (argv.clientCertificate && argv.clientKey) {
			k8sConfig.cert = fs.readFileSync(argv.clientCertificate, 'utf8');
			k8sConfig.key = fs.readFileSync(argv.clientKey, 'utf8');
		}
	} else if (process.env.KUBERNETES_SERVICE_HOST) {
		// Runs in Kubernetes
		const credentialsPath = '/var/run/secrets/kubernetes.io/serviceaccount/';
		k8sConfig = {
			url: `https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT}`,
			ca: fs.readFileSync(path.resolve(credentialsPath, 'ca.crt'), 'utf8'),
			auth: { bearer: fs.readFileSync(path.resolve(credentialsPath, 'token'), 'utf8') }
		}
	} else {
		throw new Error('Unknown Kubernetes API server');
	}

	return k8sConfig;
}

const sqsClientOptions = {
	endpoint: process.env.AWS_SQS_ENDPOINT_URL_OVERRIDE,
	region: process.env.AWS_REGION,
};

const SQSQueue = require('./resources/sqs');
const PromisesQueue = require('./promises-queue');

const k8sConfig = createK8sConfig(argv);
k8s(k8sConfig).then(function onConnected(k8sClient) {
	const awsResourcesClient = k8sClient.group('aws.k8s.collaborne.com', 'v1').ns(argv.namespace);

	const resourceDescriptions = [{
		type: 'queues',
		resourceClient: new SQSQueue(sqsClientOptions)
	}];

	function resourceLoop(type, k8sResourceClient, resourceClient, promisesQueue) {
		k8sResourceClient.list()
			.then(list => {
				const resourceVersion = list.metadata.resourceVersion;

				// Treat all resources we see as "update", which will trigger a creation/update of attributes accordingly.
				for (const resource of list.items) {
					const name = resource.metadata.name;
					promisesQueue.enqueue(name, function() {
						logger.info(`[${name}]: Syncing`);
						return resourceClient.update(resource);
					}).then(function(data) {
						logger.info(`[${name}]: ${JSON.stringify(data)}`);
					}, function(err) {
						logger.error(`[${name}]: ${err.message} (${err.code})`);
					});
				}

				return resourceVersion;
			}).then(resourceVersion => {
				// Start watching the resources from that version on
				logger.info(`Watching ${type} at ${resourceVersion}...`);
				k8sResourceClient.watch(resourceVersion)
					.on('data', function(item) {
						const resource = item.object;
						const name = resource.metadata.name;

						let next;

						switch (item.type) {
						case 'ADDED':
							next = function() {
								logger.info(`[${name}]: Creating resource`);
								return resourceClient.create(resource);
							};
							break;
						case 'MODIFIED':
							next = function() {
								logger.info(`[${name}]: Updating resource attributes`);
								return resourceClient.update(resource);
							};
							break;
						case 'DELETED':
							next = function() {
								logger.info(`[${name}]: Deleting resource`);
								return resourceClient.delete(resource);
							};
							break;
						case 'ERROR':
							// Log the message, and continue: usually the stream would end now, but there might be more events
							// in it that we do want to consume.
							logger.warn(`Error while watching: ${item.object.message}, ignoring`);
							return;
						default:
							logger.warn(`Unkown watch event type ${item.type}, ignoring`);
							return;
						}

						// Note that we retain the 'rejected' state here: an existing resource that ended in a rejection
						// will effectively stay rejected.
						const result = promisesQueue.enqueue(name, next).then(function(data) {
							logger.info(`[${name}]: ${JSON.stringify(data)}`);
						}, function(err) {
							logger.error(`[${name}]: ${err.message} (${err.code})`);
						});

						return result;
					})
					.on('end', function() {
						// Restart the watch from the last known version.
						logger.info('Watch ended, restarting');
						return resourceLoop(type, k8sResourceClient, resourceClient, promisesQueue);
					});
			})
	}

	resourceDescriptions.forEach(resourceDescription => {
		const k8sResourceClient = awsResourcesClient[resourceDescription.type];
		if (k8sResourceClient) {
			const promisesQueue = new PromisesQueue();
			resourceLoop(resourceDescription.type, k8sResourceClient, resourceDescription.resourceClient, promisesQueue);
		} else {
			console.error(`Resources of type ${resourceDescription.type} are not defined as Kubernetes ThirdPartyResource. Available ThirdPartyResources ${Object.keys(awsResourcesClient)}.`);
		}
	});
}).catch(function(err) {
	logger.error(`Uncaught error, aborting: ${err.message}`);
	process.exit(1);
});
<|endoftext|>


<commit_before>'use strict';

import App from './common/components/App';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route } from 'react-router';

// CSS
require('normalize.css');
require('./styles/main.css');

var content = document.getElementById('content');

ReactDOM.render((
  <Router>
    <Route path="/" component={App} />
  </Router>
), content);
<commit_msg>Remove use strict<commit_after>import App from './common/components/App';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route } from 'react-router';

// CSS
require('normalize.css');
require('./styles/main.css');

var content = document.getElementById('content');

ReactDOM.render((
  <Router>
    <Route path="/" component={App} />
  </Router>
), content);
<|endoftext|>


<commit_before>import express from 'express';
import leagueTips from 'league-tooltips';
import runTask from './cronTask';
import taskGenerator from './cronTasks/generator';
import config from './config';
import routes from './routes';

// ==== Server ====

const app = express();

app.use(leagueTips(config.key.riot, 'euw', { url: '/tooltips', fileName: 'league-tips.min.js', protocol: 'https' }));

app.use('/sprites', routes.sprites);
app.use('/tooltips', routes.tooltips);
app.use('/', routes.index);

app.listen(config.port, () => {
  console.log('[SERVER] Listening on port ' + config.port);
});

// ==== Generator ====

const version = require('../package.json').version;
console.log(`[GENERATOR] Generator version : ${version}.`);

runTask(taskGenerator, config.cron);
<commit_msg>Set league-tooltips CORS.<commit_after>import express from 'express';
import leagueTips from 'league-tooltips';
import runTask from './cronTask';
import taskGenerator from './cronTasks/generator';
import config from './config';
import routes from './routes';

// ==== Server ====

const app = express();

app.use(leagueTips(config.key.riot, 'euw', {
  url: '/tooltips',
  fileName: 'league-tips.min.js',
  protocol: 'https',
  cors: {
    origin: 'lol-item-sets-generator.org',
    methods: 'GET',
    headers: 'Content-Type'
  }
}));

app.use('/sprites', routes.sprites);
app.use('/tooltips', routes.tooltips);
app.use('/', routes.index);

app.listen(config.port, () => {
  console.log('[SERVER] Listening on port ' + config.port);
});

// ==== Generator ====

const version = require('../package.json').version;
console.log(`[GENERATOR] Generator version : ${version}.`);

runTask(taskGenerator, config.cron);
<|endoftext|>


<commit_before>'use strict';

(function () {

  var _ = require('underscore');
  var request = require('superagent');
  var cheerio = require('cheerio');
  var wordCount = require('word-count');

  var utils = require('./utils');

  var isSameDomain = utils.isSameDomain;
  var resolveUrl = utils.resolveUrl;
  var isValidBaseUrl = utils.isValidBaseUrl;

  function markHrefsAsFailed (scope) {
    _.each(scope.json.urls, function (crawledUrl, index) {
      if (crawledUrl.hrefs) {
        _.each(crawledUrl.hrefs.internal, function (href, hrefIndex) {
          if (href.resolved in scope.json) {
            scope.json.urls[index].hrefs.internal[hrefIndex].crawled = true;
            scope.json.urls[index].hrefs.internal[hrefIndex].failed = scope.json[href.resolved].failed;
            scope.json.urls[index].hrefs.internal[hrefIndex].type = scope.json[href.resolved].type;
            scope.json.urls[index].hrefs.internal[hrefIndex].status = scope.json[href.resolved].status;
          } else {
            scope.json.urls[index].hrefs.internal[hrefIndex].crawled = false;
          }
        });
      }
    });
  }

  function getFailedUrls (scope) {
    return _.chain(scope.json.urls)
    .filter(function (crawledUrl) {
      return crawledUrl.failed;
    })
    .map(function (crawledUrl) {
      return {
        url: crawledUrl.url,
        resolved: crawledUrl.resolved,
        linkedFrom: _.chain(scope.json.urls)
        .filter(function (possiblyLinkedFrom) {
          return possiblyLinkedFrom.hrefs && _.any(possiblyLinkedFrom.hrefs.internal, function (href) {
            return href.url === crawledUrl.url;
          });
        })
        .map(function (linkedFrom) {
          return linkedFrom.resolved;
        })
      };
    })
    .value();
  }

  function getHrefs (scope, url, $) {
    return _.chain($('a[href]').toArray().map(function (el) {
      var element = $(el);

      return element.attr('href');
    }))
    .groupBy(_.identity)
    .map(function (values, key) {
      return {
        url: key,
        resolved: resolveUrl(key, url.resolved),
        references: values.length
      };
    })
    .sortBy('url')
    .groupBy(function (href) {
      if (href.url.indexOf('#') === 0) {
        return 'samePage';
      }

      if (href.url.indexOf('tel:') === 0) {
        return 'phone';
      }

      if (href.url.indexOf('mailto:') === 0) {
        return 'email';
      }

      return isSameDomain(href.url, scope.baseUrl.resolved) ? 'internal' : 'external';
    })
    .value();
  }

  function getMeta ($) {
    return _.chain($('meta[name],meta[property]').toArray())
    .map(function (el) {
      var element = $(el);

      return [element.attr('name') || element.attr('property'), element.attr('content')];
    })
    .object()
    .value();
  }

  function getData (scope, res, url) {
    var $ = cheerio.load(res.text);

    var hrefs = getHrefs(scope, url, $);

    return {
      url: url.url,
      resolved: url.resolved,
      failed: false,
      type: res.type,
      status: res.status,
      title: $('title').text() || null,
      wordCount: wordCount($('body').text()),
      charset: $('meta[charset]').attr('charset') || null,
      meta: getMeta($),
      h1: $('h1').first().text() || null,
      h2: $('h2').first().text() || null,
      h3: $('h3').first().text() || null,
      p: $('p').first().text() || null,
      hrefs: {
        internal: hrefs.internal || [],
        external: hrefs.external || [],
        samePage: hrefs.samePage || [],
        email: hrefs.email || [],
        phone: hrefs.phone || []
      }
    };
  }

  function continueCrawl (scope, url, currentDepth) {
    request
    .get(url.resolved)
    .accept('text/html')
    .send()
    .end(function (err, res) {
      scope.urlsCrawled.push(url.resolved);

      if (err) {
        scope.json.urls.push({
          url: url.url,
          resolved: url.resolved,
          failed: true,
          type: err.type || null,
          status: err.status || null
        });
      } else if (res.type === 'text/html' && res.text) {
        scope.json.urls.push(getData(scope, res, url));

        var index = scope.json.urls.length - 1;

        if (currentDepth < scope.depth) {
          _.each(scope.json.urls[index].hrefs.internal, function (href) {
            if (scope.urlsToCrawl.indexOf(href.resolved) < 0) {
              scope.urlsToCrawl.push(href.resolved);
              continueCrawl(scope, href, currentDepth + 1);
            }
          });
        }
      } else {
        scope.json.urls.push({
          url: url.url,
          resolved: url.resolved,
          failed: false,
          type: res.type,
          status: res.status
        });
      }

      if (scope.urlsToCrawl.length === scope.urlsCrawled.length) {
        markHrefsAsFailed(scope);

        scope.json.failedUrls = getFailedUrls(scope);;
        scope.json.totalUrlsCrawled = _.size(scope.json.urls);
        scope.json.totalFailedUrls = _.size(scope.json.failedUrls);;

        if (typeof process === 'object') {
          process.stdout.write(JSON.stringify(scope.json, null, 2) + '\n'); // eslint-disable-line no-undef
        } else if (typeof scope.callback === 'function') {
          scope.callback(JSON.stringify(scope.json, null, 2) + '\n');
        }
      }
    });
  }

  function crawl (options, callback) {
    isValidBaseUrl(options.url);

    var resolvedUrl = resolveUrl(options.url);

    var scope = {
      json: {
        urls: []
      },
      baseUrl: {
        url: options.url,
        resolved: resolvedUrl
      },
      urlsToCrawl: [resolvedUrl],
      urlsCrawled: [],
      depth: options.depth,
      format: options.format,

      callback: callback
    };

    continueCrawl(scope, scope.baseUrl, 0);

  }

  module.exports = {
    crawl: crawl
  };

})();
<commit_msg>Get meta & link attribs<commit_after>'use strict';

(function () {

  var _ = require('underscore');
  var request = require('superagent');
  var cheerio = require('cheerio');
  var wordCount = require('word-count');

  var utils = require('./utils');

  var isSameDomain = utils.isSameDomain;
  var resolveUrl = utils.resolveUrl;
  var isValidBaseUrl = utils.isValidBaseUrl;

  function markHrefsAsFailed (scope) {
    _.each(scope.json.urls, function (crawledUrl, index) {
      if (crawledUrl.hrefs) {
        _.each(crawledUrl.hrefs.internal, function (href, hrefIndex) {
          if (href.resolved in scope.json) {
            scope.json.urls[index].hrefs.internal[hrefIndex].crawled = true;
            scope.json.urls[index].hrefs.internal[hrefIndex].failed = scope.json[href.resolved].failed;
            scope.json.urls[index].hrefs.internal[hrefIndex].type = scope.json[href.resolved].type;
            scope.json.urls[index].hrefs.internal[hrefIndex].status = scope.json[href.resolved].status;
          } else {
            scope.json.urls[index].hrefs.internal[hrefIndex].crawled = false;
          }
        });
      }
    });
  }

  function getFailedUrls (scope) {
    return _.chain(scope.json.urls)
    .filter(function (crawledUrl) {
      return crawledUrl.failed;
    })
    .map(function (crawledUrl) {
      return {
        url: crawledUrl.url,
        resolved: crawledUrl.resolved,
        linkedFrom: _.chain(scope.json.urls)
        .filter(function (possiblyLinkedFrom) {
          return possiblyLinkedFrom.hrefs && _.any(possiblyLinkedFrom.hrefs.internal, function (href) {
            return href.url === crawledUrl.url;
          });
        })
        .map(function (linkedFrom) {
          return linkedFrom.resolved;
        })
      };
    })
    .value();
  }

  function getHrefs (scope, url, $) {
    return _.chain($('a[href]').toArray().map(function (el) {
      var element = $(el);

      return element.attr('href');
    }))
    .groupBy(_.identity)
    .map(function (values, key) {
      return {
        url: key,
        resolved: resolveUrl(key, url.resolved),
        references: values.length
      };
    })
    .sortBy('url')
    .groupBy(function (href) {
      if (href.url.indexOf('#') === 0) {
        return 'samePage';
      }

      if (href.url.indexOf('tel:') === 0) {
        return 'phone';
      }

      if (href.url.indexOf('mailto:') === 0) {
        return 'email';
      }

      return isSameDomain(href.url, scope.baseUrl.resolved) ? 'internal' : 'external';
    })
    .value();
  }

  function getAttribs ($, selector) {
    return _.chain($(selector).toArray())
    .map(function (link) {
      return link.attribs;
    })
    .value();
  }

  function getData (scope, res, url) {
    var $ = cheerio.load(res.text);

    var hrefs = getHrefs(scope, url, $);

    return {
      url: url.url,
      resolved: url.resolved,
      failed: false,
      type: res.type,
      status: res.status,
      title: $('title').text() || null,
      wordCount: wordCount($('body').text()),
      charset: $('meta[charset]').attr('charset') || null,
      meta: getAttribs($, 'meta[name],meta[property]'),
      links: getAttribs($, 'link[rel]'),
      h1: $('h1').first().text() || null,
      h2: $('h2').first().text() || null,
      h3: $('h3').first().text() || null,
      p: $('p').first().text() || null,
      hrefs: {
        internal: hrefs.internal || [],
        external: hrefs.external || [],
        samePage: hrefs.samePage || [],
        email: hrefs.email || [],
        phone: hrefs.phone || []
      }
    };
  }

  function continueCrawl (scope, url, currentDepth) {
    request
    .get(url.resolved)
    .accept('text/html')
    .send()
    .end(function (err, res) {
      scope.urlsCrawled.push(url.resolved);

      if (err) {
        scope.json.urls.push({
          url: url.url,
          resolved: url.resolved,
          failed: true,
          type: err.type || null,
          status: err.status || null
        });
      } else if (res.type === 'text/html' && res.text) {
        scope.json.urls.push(getData(scope, res, url));

        var index = scope.json.urls.length - 1;

        if (currentDepth < scope.depth) {
          _.each(scope.json.urls[index].hrefs.internal, function (href) {
            if (scope.urlsToCrawl.indexOf(href.resolved) < 0) {
              scope.urlsToCrawl.push(href.resolved);
              continueCrawl(scope, href, currentDepth + 1);
            }
          });
        }
      } else {
        scope.json.urls.push({
          url: url.url,
          resolved: url.resolved,
          failed: false,
          type: res.type,
          status: res.status
        });
      }

      if (scope.urlsToCrawl.length === scope.urlsCrawled.length) {
        markHrefsAsFailed(scope);

        scope.json.failedUrls = getFailedUrls(scope);;
        scope.json.totalUrlsCrawled = _.size(scope.json.urls);
        scope.json.totalFailedUrls = _.size(scope.json.failedUrls);;

        if (typeof process === 'object') {
          process.stdout.write(JSON.stringify(scope.json, null, 2) + '\n'); // eslint-disable-line no-undef
        } else if (typeof scope.callback === 'function') {
          scope.callback(JSON.stringify(scope.json, null, 2) + '\n');
        }
      }
    });
  }

  function crawl (options, callback) {
    isValidBaseUrl(options.url);

    var resolvedUrl = resolveUrl(options.url);

    var scope = {
      json: {
        urls: []
      },
      baseUrl: {
        url: options.url,
        resolved: resolvedUrl
      },
      urlsToCrawl: [resolvedUrl],
      urlsCrawled: [],
      depth: options.depth,
      format: options.format,

      callback: callback
    };

    continueCrawl(scope, scope.baseUrl, 0);

  }

  module.exports = {
    crawl: crawl
  };

})();
<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react';

import {Table, Column, Cell} from 'fixed-data-table';
import 'fixed-data-table/dist/fixed-data-table.css';
import csv from './lib/csv.js';

var SortTypes = {
  ASC: 'ASC',
  DESC: 'DESC',
};

var FlybaseTable = React.createClass({

  //  static propTypes = {
  //   bom: PropTypes.bool,
  //   children: PropTypes.oneOfType([
  //     PropTypes.array,
  //     PropTypes.string,
  //     PropTypes.element
  //   ]),
  //   columns: PropTypes.oneOfType([
  //     PropTypes.bool,
  //     PropTypes.array,
  //     PropTypes.arrayOf(PropTypes.object)
  //   ]),
  //   datas: PropTypes.arrayOf(PropTypes.oneOfType([
  //     PropTypes.object,
  //     PropTypes.array
  //   ])).isRequired,
  //   filename: PropTypes.string.isRequired,
  //   noHeader: PropTypes.bool,
  //   prefix: PrefixSuffixType,
  //   separator: PropTypes.string,
  //   text: PropTypes.string,
  //   suffix: PrefixSuffixType
  // };

  // static defaultProps = {
  //   separator: ',',
  //   columns: false,
  //   bom: true,
  //   noHeader: false
  // };

  // constructor(props) {
  //   super();

  //   this.state = {
  //     csv: csv(props.columns, props.datas, props.separator, props.noHeader)
  //   };
  // }

  getInitialState() {
 this._download = this._download.bind(this);

// this.state = {
//       csv: csv(props.columns, props.datas, props.separator, props.noHeader)
//     };

    return {
      rows: [
        {id:1, title: "Citizen Kane", rank: "1", year: "2000"},
        {id:2, title: "The Shawshank Redemption", rank: "2", year: "1995"},
        {id:3, title: "The Godfather", rank: "3", year: "1971"}
      ],
      filteredRows: null,
      filterBy: null,
      sortBy: 'id',
      sortDir: null,

      // csv: this.rows,
    };
  },

_download(e){

// console.debug(this.state.rows);

  const a = document.createElement('a');
    a.textContent = 'download';
    a.download = 'filename';

    var bomCode = '%EF%BB%BF';
    a.href = 'data:text/csv;charset=utf-8,' + bomCode + encodeURIComponent(['a','b']);
    // a.href = `data:text/csv;charset=utf-8,${encodeURIComponent(this.state.csv)}`;
    a.click();

 },

  componentWillMount() {
    this._filterRowsBy(this.state.filterBy);
  },

  _rowGetter(rowIndex) {
    return this.state.filteredRows[rowIndex];
  },

  _filterRowsBy(filterBy) {
    var rows = this.state.rows.slice();
    var filteredRows = filterBy ? rows.filter(function(row){
      return row.title.toLowerCase().indexOf(filterBy.toLowerCase()) >= 0
    }) : rows;

    this.setState({
      filteredRows,
      filterBy,
    });
  },

  _onFilterChange(e) {
    this._filterRowsBy(e.target.value);
  },

  _sortRowsBy(cellDataKey) {
    var sortDir = this.state.sortDir;
    var sortBy = cellDataKey;
    if (sortBy === this.state.sortBy) {
      sortDir = this.state.sortDir === SortTypes.ASC ? SortTypes.DESC : SortTypes.ASC;
    } else {
      sortDir = SortTypes.DESC;
    }

    var rows = this.state.filteredRows.slice();
    rows.sort(function(a, b){
      var sortVal = 0;
      if (a[sortBy] > b[sortBy]) {
        sortVal = 1;
      }
      if (a[sortBy] < b[sortBy]) {
        sortVal = -1;
      }

      if (sortDir === SortTypes.DESC) {
        sortVal = sortVal * -1;
      }

      return sortVal;
    });

    this.setState({
      filteredRows: rows,
      sortBy,
      sortDir,
    });
  },

  _renderHeader(label, cellDataKey) {
    return (
      {label}

    );
  },

  render() {
      var sortDirArrow = "";
      var fileDownload = require('react-file-download');

    if (this.state.sortDir !== null){
      sortDirArrow = this.state.sortDir === SortTypes.DESC ? ' ↓' : ' ↑';
    }

    return (

        Filter by <input onChange={this._onFilterChange} />

        <button onClick={this._download}> Download </button>

          <Column
            headerRenderer={this._renderHeader}
            label={'Movie Title' + (this.state.sortBy === 'title' ? sortDirArrow : '')}
            width={270}
            dataKey="title"
          />

          <Column
            headerRenderer={this._renderHeader}
            label={'Rank' + (this.state.sortBy === 'rank' ? sortDirArrow : '')}
            width={100}
            dataKey="rank"
          />

          <Column
            headerRenderer={this._renderHeader}
            label={'Year' + (this.state.sortBy === 'year' ? sortDirArrow : '')}
            width={80}
            dataKey="year"
          />

    );
  },
});

export default FlybaseTable;
<commit_msg>conflict fix<commit_after>import React, { PropTypes, Component } from 'react';

import {Table, Column, Cell} from 'fixed-data-table';
import 'fixed-data-table/dist/fixed-data-table.css';
import csv from './lib/csv.js';

var SortTypes = {
  ASC: 'ASC',
  DESC: 'DESC',
};

var FlybaseTable = React.createClass({
  getInitialState() {
 this._download = this._download.bind(this);

    return {
      rows: [
        {id:1, title: "Citizen Kane", rank: "1", year: "2000"},
        {id:2, title: "The Shawshank Redemption", rank: "2", year: "1995"},
        {id:3, title: "The Godfather", rank: "3", year: "1971"}
      ],
      filteredRows: null,
      filterBy: null,
      sortBy: 'id',
      sortDir: null,
    };
  },

getHeader(objArray){
   return Object.keys(objArray[0]);
},

toCSV(objArray){
        var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
        var str = '';

        for (var i = 0; i < array.length; i++) {
            var line = '';
            for (var index in array[i]) {
                if (line != '') line += ','

                    line += array[i][index];
            }

             str += line + '\r\n';
        }
        return str;
},

_download(e){

console.debug(this.state.rows);

  const a = document.createElement('a');
    a.textContent = 'download';
    a.download = 'filename';

    var bomCode = '%EF%BB%BF';

    var header = this.getHeader(this.state.rows);
    var data = this.toCSV(this.state.rows);
    var datas = header + '\n' + data;
    a.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(datas);
    a.click();

 },

  componentWillMount() {
    this._filterRowsBy(this.state.filterBy);
  },

  _rowGetter(rowIndex) {
    return this.state.filteredRows[rowIndex];
  },

  _filterRowsBy(filterBy) {
    var rows = this.state.rows.slice();
    var filteredRows = filterBy ? rows.filter(function(row){
      return row.title.toLowerCase().indexOf(filterBy.toLowerCase()) >= 0
    }) : rows;

    this.setState({
      filteredRows,
      filterBy,
    });
  },

  _onFilterChange(e) {
    this._filterRowsBy(e.target.value);
  },

  _sortRowsBy(cellDataKey) {
    var sortDir = this.state.sortDir;
    var sortBy = cellDataKey;
    if (sortBy === this.state.sortBy) {
      sortDir = this.state.sortDir === SortTypes.ASC ? SortTypes.DESC : SortTypes.ASC;
    } else {
      sortDir = SortTypes.DESC;
    }

    var rows = this.state.filteredRows.slice();
    rows.sort(function(a, b){
      var sortVal = 0;
      if (a[sortBy] > b[sortBy]) {
        sortVal = 1;
      }
      if (a[sortBy] < b[sortBy]) {
        sortVal = -1;
      }

      if (sortDir === SortTypes.DESC) {
        sortVal = sortVal * -1;
      }

      return sortVal;
    });

    this.setState({
      filteredRows: rows,
      sortBy,
      sortDir,
    });
  },

  _renderHeader(label, cellDataKey) {
    return (
      {label}

    );
  },

  render() {
      var sortDirArrow = "";
      var fileDownload = require('react-file-download');

    if (this.state.sortDir !== null){
      sortDirArrow = this.state.sortDir === SortTypes.DESC ? ' ↓' : ' ↑';
    }

    return (

        Filter by <input onChange={this._onFilterChange} />

        <button onClick={this._download}> Download </button>

          <Column
            headerRenderer={this._renderHeader}
            label={'Movie Title' + (this.state.sortBy === 'title' ? sortDirArrow : '')}
            width={270}
            dataKey="title"
          />

          <Column
            headerRenderer={this._renderHeader}
            label={'Rank' + (this.state.sortBy === 'rank' ? sortDirArrow : '')}
            width={100}
            dataKey="rank"
          />

          <Column
            headerRenderer={this._renderHeader}
            label={'Year' + (this.state.sortBy === 'year' ? sortDirArrow : '')}
            width={80}
            dataKey="year"
          />

    );
  },
});

export default FlybaseTable;
<|endoftext|>


<commit_before><commit_msg>Fix bug in composition handling on Firefox<commit_after><|endoftext|>


<commit_before>"use strict";

var puckt = puckt || {};
puckt.ui = (function () {
    function openPopup(props) {
        var message = document.createElement("aside"),
            section = document.createElement("section"),
            button;
        // Set class name
        message.className = "message";
        // Add content to message box
        section.innerHTML = props.content;
        // Ensure dimensions are the same dimensions as the canvas
        message.style.width = puckt.canvas.width + "px";
        message.style.height = puckt.canvas.height + puckt.canvas.navHeight + "px";
        // Make transparent (for fading)
        message.style.opacity = "0";
        // Add buttons to message
        if (props.buttons) {
            for (var i=0; i<props.buttons.length; i++) {
                button = document.createElement("a");
                button.href = "";
                button.className = "button";
                button.innerHTML = props.buttons[i].text;
                buttonEvent(button, props.buttons[i]);
                section.appendChild(button);
            }
        }
        // Append section to message
        message.appendChild(section);
        // Append message to body
        document.body.appendChild(message);
        // Set opacity to opaque
        setTimeout(function () {
            message.style.opacity = "1";
        }, 1);
    };

    function buttonEvent (button, props) {
        // Listens for button click
        button.addEventListener("click", function (e) {
            e.preventDefault();
            // Calls callback
            props.callback();
        })
    };

    function closePopup () {
        var message = document.querySelectorAll(".message");
        // Sets opacity to 0
        message[0].style.opacity = "0";
        // Remove element from DOM after transition is over (0.25 seconds)
        setTimeout(function () {
            if (message[0])
                message[0].parentNode.removeChild(message[0]);
        }, 250);
    };

    function drawNavigation (currentGame) {
        var navigation = document.createElement("nav"),
            backButton = document.createElement("a"),
            resetButton = document.createElement("a"),
            levelText = document.createElement("span");
        // Set up navigation properties
        navigation.style.width = puckt.canvas.width + "px";
        navigation.style.height = puckt.canvas.navHeight + "px";
        // Set up level text
        levelText.id = "level_text";
        levelText.innerHTML = "Level " + currentGame.number;
        // Set up back button properties
        backButton.className = "left";
        backButton.href = "";
        backButton.innerHTML = "";
        backButton.style.height = puckt.canvas.navHeight + "px";
        backButton.style.width = puckt.canvas.navHeight + "px";
        backButton.addEventListener("click", function () {
            console.log("back");
        });
        // Set up reset button properties
        resetButton.className = "right";
        resetButton.href = "";
        resetButton.innerHTML = "";
        resetButton.style.height = puckt.canvas.navHeight + "px";
        resetButton.style.width = puckt.canvas.navHeight + "px";
        resetButton.addEventListener("click", function (e) {
            e.preventDefault();
            currentGame.reset();
        });
        // Add buttons to navigation
        navigation.appendChild(backButton);
        navigation.appendChild(resetButton);
        navigation.appendChild(levelText);
        // Add navigation to document
        document.body.appendChild(navigation);
    };

    return {
        openPopup: openPopup,
        closePopup: closePopup,
        drawNavigation: drawNavigation
    }
})();<commit_msg>Bug fix: updated reset button to call the level begin method<commit_after>"use strict";

var puckt = puckt || {};
puckt.ui = (function () {
    function openPopup(props) {
        var message = document.createElement("aside"),
            section = document.createElement("section"),
            button;
        // Set class name
        message.className = "message";
        // Add content to message box
        section.innerHTML = props.content;
        // Ensure dimensions are the same dimensions as the canvas
        message.style.width = puckt.canvas.width + "px";
        message.style.height = puckt.canvas.height + puckt.canvas.navHeight + "px";
        // Make transparent (for fading)
        message.style.opacity = "0";
        // Add buttons to message
        if (props.buttons) {
            for (var i=0; i<props.buttons.length; i++) {
                button = document.createElement("a");
                button.href = "";
                button.className = "button";
                button.innerHTML = props.buttons[i].text;
                buttonEvent(button, props.buttons[i]);
                section.appendChild(button);
            }
        }
        // Append section to message
        message.appendChild(section);
        // Append message to body
        document.body.appendChild(message);
        // Set opacity to opaque
        setTimeout(function () {
            message.style.opacity = "1";
        }, 1);
    };

    function buttonEvent (button, props) {
        // Listens for button click
        button.addEventListener("click", function (e) {
            e.preventDefault();
            // Calls callback
            props.callback();
        })
    };

    function closePopup () {
        var message = document.querySelectorAll(".message");
        // Sets opacity to 0
        message[0].style.opacity = "0";
        // Remove element from DOM after transition is over (0.25 seconds)
        setTimeout(function () {
            if (message[0])
                message[0].parentNode.removeChild(message[0]);
        }, 250);
    };

    function drawNavigation (currentGame) {
        var navigation = document.createElement("nav"),
            backButton = document.createElement("a"),
            resetButton = document.createElement("a"),
            levelText = document.createElement("span");
        // Set up navigation properties
        navigation.style.width = puckt.canvas.width + "px";
        navigation.style.height = puckt.canvas.navHeight + "px";
        // Set up level text
        levelText.id = "level_text";
        levelText.innerHTML = "Level " + currentGame.number;
        // Set up back button properties
        backButton.className = "left";
        backButton.href = "";
        backButton.innerHTML = "";
        backButton.style.height = puckt.canvas.navHeight + "px";
        backButton.style.width = puckt.canvas.navHeight + "px";
        backButton.addEventListener("click", function () {
            console.log("back");
        });
        // Set up reset button properties
        resetButton.className = "right";
        resetButton.href = "";
        resetButton.innerHTML = "";
        resetButton.style.height = puckt.canvas.navHeight + "px";
        resetButton.style.width = puckt.canvas.navHeight + "px";
        resetButton.addEventListener("click", function (e) {
            e.preventDefault();
            currentGame.begin();
        });
        // Add buttons to navigation
        navigation.appendChild(backButton);
        navigation.appendChild(resetButton);
        navigation.appendChild(levelText);
        // Add navigation to document
        document.body.appendChild(navigation);
    };

    return {
        openPopup: openPopup,
        closePopup: closePopup,
        drawNavigation: drawNavigation
    }
})();<|endoftext|>


<commit_before><commit_msg>:blush:<commit_after><|endoftext|>


<commit_before><commit_msg>button title wrapped in span #148<commit_after><|endoftext|>


<commit_before><commit_msg>Continue listeners processing when receiveng error<commit_after><|endoftext|>


<commit_before>// differences with swipe
// - only touch support (no mouse)
// - no slideshow support
// - no continuous support for 2 slides
// - intended use: full screen navigation component
// - support css to trigger animation inside slides efficiently
// - heavy use of requestAnimationFrame -> performance
// - limit the number of redraws aggressively -> performance
// - mobile-friendly: my device skips the first few touched pixels - animate that away
// - ES6 only
// - no prefixes for css properties

/*
    .swipe-nav {
        overflow: hidden;
        visibility: hidden;
        position: relative;
    }
    .swipe-nav-wrap {
        overflow: hidden;
        position: relative;
    }
    .swipe-nav-wrap > div {
        float: left;
        width: 100%;
        position: relative;
    }
*/

class SwipeNav {

    constructor (options) {
        // DOM nodes
        this._container = options.container;
        this._element = this._container.children[0];
        this._slides = Array.prototype.slice.call(this._element.children);

        // event callbacks (bound methods)
        this._resizeCallback = this._resize.bind(this);
        this._touchStartCallback = this._touchStart.bind(this);
        this._touchMoveCallback = this._touchMove.bind(this);
        this._touchEndCallback = this._touchEnd.bind(this);

        // constants
        this._SLIDE_MASS = 1;
        this._SWIPE_ENERGY_THRESHOLD = 0.25;

        // render state
        this._animationFrameId = null; // current touchmove animation frame
        this._width = 0; // window width

        this._startX = null; // touch start pageX
        this._startY = null; // touch start pageY
        this._startTime = null; // touch start timestamp
        this._isScrolling = null;

        this._deltaX = null; // horizontal distance from touch start
        this._deltaY = null; // vertical distance from touch start
        this._deltaT = null; // time since swipe start
        this._distance = null; // actual horizontal slide movement
        this._velocity = 0; // current horizontal (X) velocity
        this._energy = 0; // energy applied during a swipe

        this._slideIndex = 0; // currently displayed slide
        this._slidePositions = [];

        this.setup();
    }

    // permanently (update _slidePositions) move a slide to targetPosition
    _moveSlide (index, targetPosition, speed) {
        const slide = this._slides[index];

        if (!slide) {
            return;
        }

        this._slidePositions[index] = targetPosition;

        slide.style.transitionDuration = `${speed || 0}ms`;
        slide.style.transform = `translateX(${targetPosition}px)`;
    }

    // move a slide temporarily by distance pixels relative to their current
    // permanent position
    _translateSlide (index, distance, speed) {
        const slide = this._slides[index];

        if (!slide) {
            return;
        }

        slide.style.transitionDuration = `${speed || 0}ms`;
        slide.style.transform = `translateX(${this._slidePositions[index] + distance}px)`;
    }

    // event callback methods
    _touchStart (event) {
        // disable the default action (zoom) to not loose the first few move
        // events - loosing them results in a badly stuttering swipe start
        event.preventDefault();

        // get initial touch points (for delta computation)
        this._startX = event.touches[0].pageX;
        this._startY = event.touches[0].pageY;

        // reset all other points
        this._startTime = event.timeStamp;
        this._isScrolling = null;
        this._deltaX = 0;
        this._deltaY = 0;
        this._deltaT = 0;
        this._distance = 0;
        this._velocity = 0;
        this._energy = 0;

        // attach listeners
        this._element.addEventListener('touchmove', this._touchMoveCallback, false);
        this._element.addEventListener('touchend', this._touchEndCallback, false);
    }

    _touchMove (event) {
        // ensure swiping with one touch and not pinching
        if (event.touches.length > 1 || event.scale && event.scale !== 1) {
            // TODO: better way of stopping this?
            // should touch event listeners (move, end) be removed here?
            return;
        }

        const prevDeltaX = this._deltaX;

        // measure change in x and y
        this._deltaX = event.touches[0].pageX - this._startX;
        this._deltaY = event.touches[0].pageY - this._startY;

        // determine if scrolling test has run - one time test
        if (this._isScrolling === null) {
            this._isScrolling = Math.abs(this._deltaX) < Math.abs(this._deltaY);
        }

        if (this._isScrolling) {
            // TODO: also remove listeners here?
            return;
        }

        // prevent native scrolling
        event.preventDefault();

        // skip this frame if deltaX has not been changed to not cause needless redraws
        if (prevDeltaX === this._deltaX) {
            return;
        }

        // check boundaries and apply a resistance

        // swiping === moving your thumb over the screen
        // - isSwipingLeft: move thumb to the left - new slide comes from the right
        // - isWwipingRight: move thumb to the right - slide comes from the left
        const isSwipingLeft = this._deltaX < 0; // <---(thumb)
        const isSwipingRight = this._deltaX > 0; // (thumb)--->

        const isFirstSlide = this._slideIndex === 0;
        const isLastSlide = this._slideIndex === this._slides.length - 1;

        // TODO: compute these via callback on touchStart
        // or provide methods .setSlidingLeftAllowed or setSlidePermissions({left:true, right:false})
        const isSwipingLeftAllowed = true;
        const isSwipingRightAllowed = true;

        const applyResistance =
                  (isSwipingRight && (isFirstSlide || !isSwipingRightAllowed))
                  || (isSwipingLeft && (isLastSlide || !isSwipingLeftAllowed));

        if (applyResistance) {
            this._distance = this._deltaX / (Math.abs(this._deltaX) / this._width + 1);
        } else {
            this._distance = this._deltaX;
        }

        const prevDeltaT = this._deltaT;
        const prevVelocity = this._velocity || 0;

        this._deltaT = event.timeStamp - this._startTime;
        this._velocity = (this._deltaX - prevDeltaX) / (this._deltaT - prevDeltaT);

        // Compute the energy applied while swiping to create slides that
        // behave like a *real* thing using classical mechanics:
        //   Force = Mass * Acceleration
        //   Acceleration = deltaVelocity / deltaT
        //   Energy = F over time ~= sum(F * deltaT) = sum(m * a * deltaT) = sum(m * deltaVelocity)
        this._energy += (this._velocity - prevVelocity) * this._SLIDE_MASS;

        // render changes in a new frame unless we are already waiting for one
        // (mobile devices seem to fire touch events really fast, faster than
        //  screen refresh and even when not moving the thumb)
        if (this._animationFrameId === null) {
            this._animationFrameId = window.requestAnimationFrame(() => {
                this._translateSlide(this._slideIndex - 1, this._distance, 0);
                this._translateSlide(this._slideIndex, this._distance, 0);
                this._translateSlide(this._slideIndex + 1, this._distance, 0);
                this._animationFrameId = null;
            });
        }
    }

    _touchEnd () {
        if (this._isScrolling) {
            return;
        }

        const isSwipingLeft = this._distance < 0;
        const isSwipingRight = this._distance > 0;

        // did the touch gesture apply enough energy to move the slide
        const isValidSwipeGesture = Math.abs(this._energy) > this._SWIPE_ENERGY_THRESHOLD;

        const isSwipingLeftAllowed = true;
        const isSwipingRightAllowed = true;

        const isSwipingPossible =
                  (isSwipingRight
                   && this._slideIndex !== 0
                   && isSwipingRightAllowed)
                  ||
                  (isSwipingLeft
                   && this._slideIndex !== this._slides.length - 1
                   && isSwipingLeftAllowed);

        // remove listeners
        this._element.removeEventListener('touchmove', this._touchMoveCallback, false);
        this._element.removeEventListener('touchend', this._touchEndCallback, false);

        // cancel any existing translate draws
        if (this._animationFrameId !== null) {
            window.cancelAnimationFrame(this._animationFrameId);
            this._animationFrameId = null;
        }

        // finish the swipe using a css transition
        window.requestAnimationFrame(() => {
            // Use the current (kinetic) energy of the slide to project its velocity via:
            //   Energy = 0.5 * Mass * Velocity => Velocity = sqrt(Energy / 0.5*Mass)
            //   Velocity = Distance / Time => Time = Distance / Velocity
            // and reorder the equation to get time we need for the css transition.
            const remainingDistance = Math.max(0, this._width - Math.abs(this._deltaX));
            const transitionVelocity = Math.sqrt(Math.abs(this._energy) / (0.5 * this._SLIDE_MASS));
            const transitionTime =  remainingDistance / transitionVelocity;

            if (isValidSwipeGesture && isSwipingPossible) {
                if (isSwipingLeft) {
                    this._moveSlide(this._slideIndex - 1, -this._width, 0);
                    this._moveSlide(this._slideIndex, this._slidePositions[this._slideIndex] - this._width, transitionTime);
                    this._moveSlide(this._slideIndex + 1, this._slidePositions[this._slideIndex + 1] - this._width, transitionTime);
                    this._slideIndex += 1;
                } else {
                    this._moveSlide(this._slideIndex + 1, this._width, 0);
                    this._moveSlide(this._slideIndex, this._slidePositions[this._slideIndex] + this._width, transitionTime);
                    this._moveSlide(this._slideIndex - 1, this._slidePositions[this._slideIndex - 1] + this._width, transitionTime);
                    this._slideIndex -= 1;
                }
            } else {
                // move slides back into their current position
                this._moveSlide(this._slideIndex - 1, -this._width, 300);
                this._moveSlide(this._slideIndex, 0, 300);
                this._moveSlide(this._slideIndex + 1, this._width, 300);
            }
        });
    }

    _resize () {
        this.kill();
        this.setup();
    }

    setup () {
        this._width = this._container.getBoundingClientRect().width || this._container.offsetWidth;

        // set container width
        this._element.style.width = `${this._slides.length * this._width * 2}px`;

        // setup slides and remember slide positions
        this._slidePositions = new Array(this._slides.length);
        this._slides.forEach((slide, index) => {
            slide.style.width = `${this._width}px`;
            slide.setAttribute('data-index', index);

            // stack each slide
            slide.style.left = `${index * - this._width}px`;

            // divide the stack into three: left, right, center
            let position;

            if (this._slideIndex > index) {
                position = -this._width; // left
            } else if (this._slideIndex < index) {
                position = this._width; // right
            } else {
                position = 0; // center
            }

            this._moveSlide(index, position, 0);
        });

        // setup event listeners
        this._element.addEventListener('touchstart', this._touchStartCallback, false);
        window.addEventListener('resize', this._resizeCallback, false);

        // done
        this._container.style.visibility = 'visible';
    }

    kill () {
        // reset element
        this._element.style.width = '';
        this._element.style.left = '';

        // reset slides
        this._slides.forEach((slide, index) => {
            slide.style.width = '';
            slide.style.left = '';
            this._moveSlide(index, 0, 0);
        });

        // remove event listeners
        this._element.removeEventListener('touchstart', this._touchStartCallback, false);
        this._element.removeEventListener('touchstart', this._touchMoveCallback, false);
        this._element.removeEventListener('touchstart', this._touchEndCallback, false);
        window.removeEventListener('resize', this._resizeCallback);
    }
}
<commit_msg>click detection and content control<commit_after>// differences with swipe
// - only touch support (no mouse)
// - no slideshow support
// - no continuous support for 2 slides
// - intended use: full screen navigation component
// - support css to trigger animation inside slides efficiently
// - heavy use of requestAnimationFrame -> performance
// - limit the number of redraws aggressively -> performance
// - mobile-friendly: my device skips the first few touched pixels - animate that away
// - ES6 only
// - no prefixes for css properties

/*
    .swipe-nav {
        overflow: hidden;
        visibility: hidden;
        position: relative;
    }
    .swipe-nav-wrap {
        overflow: hidden;
        position: relative;
    }
    .swipe-nav-wrap > div {
        float: left;
        width: 100%;
        position: relative;
    }
*/

// create a mouse click event on element
function simulateClick (element) {
    const event = new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true
    });

    element.dispatchEvent(event);
}

class SwipeNav {

    constructor (options) {
        // DOM nodes
        this._container = options.container;
        this._element = this._container.children[0];
        this._slides = Array.prototype.slice.call(this._element.children);

        // event callbacks (bound methods)
        this._resizeCallback = this._resize.bind(this);
        this._touchStartCallback = this._touchStart.bind(this);
        this._touchMoveCallback = this._touchMove.bind(this);
        this._touchEndCallback = this._touchEnd.bind(this);

        // constants
        this._SLIDE_MASS = 1;
        this._SWIPE_ENERGY_THRESHOLD = 0.25;
        this._CLICK_ENERGY_THRESHOLD = 0.03;
        this._CLICK_TIME_MAX = 350;

        // render state
        this._animationFrameId = null; // current touchmove animation frame
        this._width = 0; // window width

        this._startX = null; // touch start pageX
        this._startY = null; // touch start pageY
        this._startTime = null; // touch start timestamp
        this._isScrolling = null;

        this._deltaX = null; // horizontal distance from touch start
        this._deltaY = null; // vertical distance from touch start
        this._deltaT = null; // time since swipe start
        this._distance = null; // actual horizontal slide movement
        this._velocity = 0; // current horizontal (X) velocity
        this._energy = 0; // energy applied during a swipe

        this._slideIndex = 0; // currently displayed slide
        this._slidePositions = [];

        // set artificial swipe bounds
        this._isSwipeLeftAllowed = true;
        this._isSwipeRightAllowed = true;

        this.setup();
    }

    // permanently (update _slidePositions) move a slide to targetPosition
    _moveSlide (index, targetPosition, speed) {
        const slide = this._slides[index];

        if (!slide) {
            return;
        }

        this._slidePositions[index] = targetPosition;

        slide.style.transitionDuration = `${speed || 0}ms`;
        slide.style.transform = `translateX(${targetPosition}px)`;
    }

    // move a slide temporarily by distance pixels relative to their current
    // permanent position
    _translateSlide (index, distance, speed) {
        const slide = this._slides[index];

        if (!slide) {
            return;
        }

        slide.style.transitionDuration = `${speed || 0}ms`;
        slide.style.transform = `translateX(${this._slidePositions[index] + distance}px)`;
    }

    // event callback methods
    _touchStart (event) {
        // disable the default action (zoom) to not loose the first few move
        // events - loosing them results in a badly stuttering swipe start
        event.preventDefault();

        // get initial touch points (for delta computation)
        this._startX = event.touches[0].pageX;
        this._startY = event.touches[0].pageY;

        // reset all other points
        this._startTime = event.timeStamp;
        this._isScrolling = null;
        this._deltaX = 0;
        this._deltaY = 0;
        this._deltaT = 0;
        this._distance = 0;
        this._velocity = 0;
        this._energy = 0;

        // attach listeners
        this._element.addEventListener('touchmove', this._touchMoveCallback, false);
        this._element.addEventListener('touchend', this._touchEndCallback, false);
    }

    _touchMove (event) {
        // ensure swiping with one touch and not pinching
        if (event.touches.length > 1 || event.scale && event.scale !== 1) {
            // TODO: better way of stopping this?
            // should touch event listeners (move, end) be removed here?
            return;
        }

        const prevDeltaX = this._deltaX;

        // measure change in x and y
        this._deltaX = event.touches[0].pageX - this._startX;
        this._deltaY = event.touches[0].pageY - this._startY;

        // determine if scrolling test has run - one time test
        if (this._isScrolling === null) {
            this._isScrolling = Math.abs(this._deltaX) < Math.abs(this._deltaY);
        }

        if (this._isScrolling) {
            // TODO: also remove listeners here?
            return;
        }

        // prevent native scrolling
        event.preventDefault();

        // skip this frame if deltaX has not been changed to not cause needless redraws
        if (prevDeltaX === this._deltaX) {
            return;
        }

        // check boundaries and apply a resistance

        // swiping === moving your thumb over the screen
        // - isSwipingLeft: move thumb to the left - new slide comes from the right
        // - isWwipingRight: move thumb to the right - slide comes from the left
        const isSwipingLeft = this._deltaX < 0; // <---(thumb)
        const isSwipingRight = this._deltaX > 0; // (thumb)--->

        const isFirstSlide = this._slideIndex === 0;
        const isLastSlide = this._slideIndex === this._slides.length - 1;

        // TODO: compute these via callback on touchStart
        // or provide methods .setSlidingLeftAllowed or setSlidePermissions({left:true, right:false})
        const isSwipingLeftAllowed = true;
        const isSwipingRightAllowed = true;

        const applyResistance =
                  (isSwipingRight && (isFirstSlide || !isSwipingRightAllowed))
                  || (isSwipingLeft && (isLastSlide || !isSwipingLeftAllowed));

        if (applyResistance) {
            this._distance = this._deltaX / (Math.abs(this._deltaX) / this._width + 1);
        } else {
            this._distance = this._deltaX;
        }

        const prevDeltaT = this._deltaT;
        const prevVelocity = this._velocity || 0;

        this._deltaT = event.timeStamp - this._startTime;
        this._velocity = (this._deltaX - prevDeltaX) / (this._deltaT - prevDeltaT);

        // Compute the energy applied while swiping to create slides that
        // behave like a *real* thing using classical mechanics:
        //   Force = Mass * Acceleration
        //   Acceleration = deltaVelocity / deltaT
        //   Energy = F over time ~= sum(F * deltaT) = sum(m * a * deltaT) = sum(m * deltaVelocity)
        this._energy += (this._velocity - prevVelocity) * this._SLIDE_MASS;

        // render changes in a new frame unless we are already waiting for one
        // (mobile devices seem to fire touch events really fast, faster than
        //  screen refresh and even when not moving the thumb)
        if (this._animationFrameId === null) {
            this._animationFrameId = window.requestAnimationFrame(() => {
                this._translateSlide(this._slideIndex - 1, this._distance, 0);
                this._translateSlide(this._slideIndex, this._distance, 0);
                this._translateSlide(this._slideIndex + 1, this._distance, 0);
                this._animationFrameId = null;
            });
        }
    }

    _touchEnd (event) {
        if (this._isScrolling) {
            return;
        }

        const isSwipingLeft = this._distance < 0;
        const isSwipingRight = this._distance > 0;

        // did the touch gesture apply enough energy to move the slide
        const isValidSwipeGesture = Math.abs(this._energy) > this._SWIPE_ENERGY_THRESHOLD;

        // is there anything to show?
        const isSwipePossible =
                  (isSwipingRight
                   && this._slideIndex !== 0
                   && this._isSwipeRightAllowed)
                  ||
                  (isSwipingLeft
                   && this._slideIndex !== this._slides.length - 1
                   && this._isSwipeLeftAllowed);

        // remove listeners
        this._element.removeEventListener('touchmove', this._touchMoveCallback, false);
        this._element.removeEventListener('touchend', this._touchEndCallback, false);

        // cancel any existing translate draws
        if (this._animationFrameId !== null) {
            window.cancelAnimationFrame(this._animationFrameId);
            this._animationFrameId = null;
        }

        // click detection
        const hasNotMoved = Math.abs(this._energy) < this._CLICK_ENERGY_THRESHOLD;
        const isShortTouch = (event.timeStamp - this._startTime) < this._CLICK_TIME_MAX;

        if (hasNotMoved && isShortTouch) {
            simulateClick(event.target);
        }

        // finish the swipe using a css transition
        window.requestAnimationFrame(() => {
            // Use the current (kinetic) energy of the slide to project its velocity via:
            //   Energy = 0.5 * Mass * Velocity => Velocity = sqrt(Energy / 0.5*Mass)
            //   Velocity = Distance / Time => Time = Distance / Velocity
            // and reorder the equation to get time we need for the css transition.
            const remainingDistance = Math.max(0, this._width - Math.abs(this._deltaX));
            const transitionVelocity = Math.sqrt(Math.abs(this._energy) / (0.5 * this._SLIDE_MASS));
            const transitionTime =  remainingDistance / transitionVelocity;

            if (isValidSwipeGesture && isSwipePossible) {
                if (isSwipingLeft) {
                    this._moveSlide(this._slideIndex - 1, -this._width, 0);
                    this._moveSlide(this._slideIndex, this._slidePositions[this._slideIndex] - this._width, transitionTime);
                    this._moveSlide(this._slideIndex + 1, this._slidePositions[this._slideIndex + 1] - this._width, transitionTime);
                    this._slideIndex += 1;
                } else {
                    this._moveSlide(this._slideIndex + 1, this._width, 0);
                    this._moveSlide(this._slideIndex, this._slidePositions[this._slideIndex] + this._width, transitionTime);
                    this._moveSlide(this._slideIndex - 1, this._slidePositions[this._slideIndex - 1] + this._width, transitionTime);
                    this._slideIndex -= 1;
                }
            } else {
                // move slides back into their current position
                this._moveSlide(this._slideIndex - 1, -this._width, 300);
                this._moveSlide(this._slideIndex, 0, 300);
                this._moveSlide(this._slideIndex + 1, this._width, 300);
            }
        });
    }

    _resize () {
        this.kill();
        this.setup();
    }

    setup () {
        this._width = this._container.getBoundingClientRect().width || this._container.offsetWidth;

        // set container width
        this._element.style.width = `${this._slides.length * this._width * 2}px`;

        // setup slides and remember slide positions
        this._slidePositions = new Array(this._slides.length);
        this._slides.forEach((slide, index) => {
            slide.style.width = `${this._width}px`;
            slide.setAttribute('data-index', index);

            // stack each slide
            slide.style.left = `${index * - this._width}px`;

            // divide the stack into three: left, right, center
            let position;

            if (this._slideIndex > index) {
                position = -this._width; // left
            } else if (this._slideIndex < index) {
                position = this._width; // right
            } else {
                position = 0; // center
            }

            this._moveSlide(index, position, 0);
        });

        // setup event listeners
        this._element.addEventListener('touchstart', this._touchStartCallback, false);
        window.addEventListener('resize', this._resizeCallback, false);

        // done
        this._container.style.visibility = 'visible';
    }

    kill () {
        // reset element
        this._element.style.width = '';
        this._element.style.left = '';

        // reset slides
        this._slides.forEach((slide, index) => {
            slide.style.width = '';
            slide.style.left = '';
            this._moveSlide(index, 0, 0);
        });

        // remove event listeners
        this._element.removeEventListener('touchstart', this._touchStartCallback, false);
        this._element.removeEventListener('touchstart', this._touchMoveCallback, false);
        this._element.removeEventListener('touchstart', this._touchEndCallback, false);
        window.removeEventListener('resize', this._resizeCallback);
    }

    setIsContentAvailable ({left, right}) {
        this._isSwipeLeftAllowed = right;
        this._isSwipeRightAllowed = left;
    }
}
<|endoftext|>


<commit_before>import React, { StyleSheet, Text, Image, ScrollView, View, PropTypes } from 'react-native';

const propTypes = {
  data: PropTypes.object,
};

class TweetBig extends React.Component {
  constructor(props) {
    super(props);
    this.styles = StyleSheet.create({
      retweetContainer: {
        margin: 10,
        paddingTop: 8,
        flexDirection: 'row',
        borderTopWidth: 1,
        borderColor: '#DAE6F0',
      },
      rtBold: {
        fontSize: 14,
        marginRight: 3,
        fontWeight: '600',
      },
      rtText: {
        fontSize: 14,
        fontWeight: '400',
        color: '#748999',
      },

      tweetContainer: {
        backgroundColor: 'white',
        borderBottomWidth: 1,
        borderColor: '#DAE6F0',
        paddingTop: 4,
      },
      avatar: {
        backgroundColor: 'gray',
        width: 50,
        height: 50,
        marginLeft: 10,
        borderRadius: 4,
      },
      userContainer: {
        flexDirection: 'row',
        alignItems: 'center',
        flex: 1,
      },
      textContainer: {
        flex: 1,
        padding: 10,
        flexDirection: 'column',
      },
      username: {
        fontSize: 13,
        color: '#8999a5',
        marginTop: 2,
      },
      name: {
        fontWeight: '600',
        fontSize: 15,
      },
      text: {
        marginTop: 5,
        fontSize: 17,
        fontWeight: '300',
      },
      rightContainer: {
        flex: 1,
        padding: 10,
      },
    });
  }

  render() {
    const {
      text,
      user,
    } = this.props.data;

    return (
      <ScrollView>
        <View style={this.styles.tweetContainer}>
          <View style={this.styles.userContainer}>
            <Image source={{ uri: user.avatar }} style={this.styles.avatar} />
            <View style={this.styles.rightContainer}>
              <Text style={this.styles.name}>{user.name}</Text>
              <Text style={this.styles.username}>@{user.username}</Text>
            </View>
          </View>
          <View style={this.styles.textContainer}>
            <Text style={this.styles.text}>{text}</Text>
          </View>
          <View style={this.styles.retweetContainer}>
            <Text style={this.styles.rtBold}>1</Text>
            <Text style={this.styles.rtText}>RETWEET</Text>
          </View>
        </View>
      </ScrollView>
    );
  }
}

TweetBig.propTypes = propTypes;

export default TweetBig;
<commit_msg>Update TweetBig.js<commit_after>import React, { StyleSheet, Text, Image, ScrollView, View, PropTypes } from 'react-native';

const propTypes = {
  data: PropTypes.object,
};

class TweetBig extends React.Component {
  render() {
    const {
      text,
      user,
    } = this.props.data;

    return (
      <ScrollView>
        <View style={this.styles.tweetContainer}>
          <View style={this.styles.userContainer}>
            <Image source={{ uri: user.avatar }} style={this.styles.avatar} />
            <View style={this.styles.rightContainer}>
              <Text style={this.styles.name}>{user.name}</Text>
              <Text style={this.styles.username}>@{user.username}</Text>
            </View>
          </View>
          <View style={this.styles.textContainer}>
            <Text style={this.styles.text}>{text}</Text>
          </View>
          <View style={this.styles.retweetContainer}>
            <Text style={this.styles.rtBold}>1</Text>
            <Text style={this.styles.rtText}>RETWEET</Text>
          </View>
        </View>
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  retweetContainer: {
    margin: 10,
    paddingTop: 8,
    flexDirection: 'row',
    borderTopWidth: 1,
    borderColor: '#DAE6F0',
  },
  rtBold: {
    fontSize: 14,
    marginRight: 3,
    fontWeight: '600',
  },
  rtText: {
    fontSize: 14,
    fontWeight: '400',
    color: '#748999',
  },
    tweetContainer: {
    backgroundColor: 'white',
    borderBottomWidth: 1,
    borderColor: '#DAE6F0',
    paddingTop: 4,
  },
    avatar: {
    backgroundColor: 'gray',
    width: 50,
    height: 50,
    marginLeft: 10,
    borderRadius: 4,
  },
  userContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    flex: 1,
  },
  textContainer: {
    flex: 1,
    padding: 10,
    flexDirection: 'column',
  },
  username: {
    fontSize: 13,
    color: '#8999a5',
    marginTop: 2,
  },
  name: {
    fontWeight: '600',
    fontSize: 15,
  },
  text: {
    marginTop: 5,
    fontSize: 17,
    fontWeight: '300',
  },
  rightContainer: {
    flex: 1,
    padding: 10,
  },
});

TweetBig.propTypes = propTypes;

export default TweetBig;
<|endoftext|>