<commit_before>import React from 'react'
import { LinearProgress, Typography, makeStyles } from '@material-ui/core'
import { defineMessages, useIntl } from 'react-intl'
import Button from '@material-ui/core/Button'
import FormattedDuration from 'react-intl-formatted-duration'
import ErrorIcon from '@material-ui/icons/Error'
import Paper from '@material-ui/core/Paper'
import Loader from '../Loader'

import STATES from './states'
export { default as STATES } from './states'

const m = defineMessages({
  // Title on sync screen when searching for devices
  updateAvailable: 'Update Available',
  updateNotAvailable: 'Mapeo is up to date! You are on the latest version.',
  downloadButtonText: 'Download now',
  calculatingProgress: 'Estimating...',
  downloadProgress: 'Download Progress',
  restartMapeoText: 'An update to Mapeo has been downloaded. Restart Mapeo to update.',
  restartMapeoButton: 'Restart Mapeo.',
  errorTitle: 'Error',
  errorMessage: 'There was an error and Mapeo could not update. Try again later.',
  patchUpdate: 'This update includes changes that fix critical errors. Please update as soon as possible.',
  minorUpdate: 'This update includes improvements that may change your experience.',
  majorUpdate: 'This update will make your application incompatible with earlier verions.',
  unknownDownloadSpeed: 'Unknown',
  estimatedDownloadTime: 'Estimated download time is'
})

const errors = {
  ERR_UPDATER_CHANNEL_FILE_NOT_FOUND: 'This channel does not have any updates'
}

export const UpdateTab = ({ update }) => {
  const cx = useStyles()
  const { formatMessage: t } = useIntl()

  var internal = function () {
    switch (update.state) {
      case STATES.AVAILABLE:
        return <Typography>{t(m.updateAvailable)}</Typography>
      case STATES.DOWNLOADING:
        return <Typography>{t(m.calculatingProgress)}</Typography>
      case STATES.PROGRESS:
        return <Typography>{t(m.downloadProgress)}</Typography>
      case STATES.READY_FOR_RESTART:
        return <Typography>{t(m.restartMapeoButton)}</Typography>
      case STATES.ERROR:
        return (
          <Typography style={{ color: 'red' }}>
            {t(m.errorTitle)}
          </Typography>
        )
      default: // STATES.IDLE, STATES.UPDATE_NOT_AVAILABLE:
        return null
    }
  }

  return
{internal()}

}

export const UpdaterView = ({ update, setUpdate }) => {
  const cx = useStyles()
  const { formatMessage: t } = useIntl()

  var internal = function () {
    switch (update.state) {
      case STATES.AVAILABLE:
        return <UpdateAvailableView cx={cx} update={update} setUpdate={setUpdate} />
      case STATES.DOWNLOADING:
        return <Typography>{t(m.calculatingProgress)}</Typography>
      case STATES.PROGRESS:
        return <DownloadProgressView cx={cx} percent={update.progress.percent} update={update} />
      case STATES.READY_FOR_RESTART:
        return <RestartView cx={cx} />
      case STATES.UPDATE_NOT_AVAILABLE:
        return <UpdateNotAvailableView cx={cx} />
      case STATES.ERROR:
        return (
          <Typography>
            <ErrorIcon
              fontSize='inherit'
              className={cx.icon}
              style={{ color: 'red' }}
            />
            {t(m.errorMessage)}
            {update.updateInfo.code}
            {errors[update.updateInfo.code]}
          </Typography>
        )
      default: // STATES.IDLE
        return null
    }
  }

  return (

          {internal()}

  )
}

const RestartView = ({ cx }) => {
  const { formatMessage: t } = useIntl()
  return (

      <Typography gutterBottom variant='h2' className={cx.searchingTitle}>
        {t(m.restartMapeoText)}
      </Typography>

  )
}

const DownloadProgressView = ({ cx, update, percent }) => {
  /*
      {
        progress: {
          total: 141164463,
          delta: 1655048,
          transferred: 11384326,
          percent: 8.064583506402741,
          bytesPerSecond: 2244544
        }
      }
  */

  const progress = update.progress
  let estimatedTimeLeft

  if (progress) {
    estimatedTimeLeft = progress.total ? (progress.total - progress.transferred) / progress.bytesPerSecond : 0
  }

  return (

      <Loader />
      <LinearProgress variant='determinate' value={percent} color='secondary' />
      <Typography>
        {estimatedTimeLeft && <FormattedDuration seconds={estimatedTimeLeft} />}
      </Typography>

  )
}

const UpdateAvailableView = ({ cx, update, setUpdate }) => {
  const { formatMessage: t } = useIntl()

  const { size, downloadSpeed, major, minor, patch } = update.updateInfo

  const handleDownlaoadClick = setUpdate.downloadUpdate

  const estimatedDownloadTime = downloadSpeed
    ? <FormattedDuration seconds={size / downloadSpeed.bps} />
    : t(m.unknownDownloadSpeed)

  return (

      <Typography gutterBottom variant='h2' className={cx.searchingTitle}>
        {t(m.updateAvailable)}
      </Typography>
      <Paper className={cx.wrapper}>

          <Typography>
            {
              major
                ? t(m.majorUpdate)
                : minor
                  ? t(m.minorUpdate)
                  : patch
                    ? t(m.patchUpdate)
                    : ''
            }
          </Typography>

          <Typography className={cx.estimatedDownloadTime}>
            {t(m.estimatedDownloadTime)} {estimatedDownloadTime}
          </Typography>

          <Button
            onClick={handleDownlaoadClick}
            className={cx.button}
            variant='contained'
            size='large'
            color='primary'
          >
            {t(m.downloadButtonText)}
          </Button>

      </Paper>

  )
}
/*

const ExpandedNotes = ({ releaseSummary }) => {
  return

    <Typography variant='body'>{releaseSummary}</Typography>

}

const HiddenNotes = ({ releaseSummary }) => {
  return

    <Typography variant='body'>{releaseSummary}</Typography>

}
*/

const UpdateNotAvailableView = ({ cx, update, downloadUpdateClick }) => {
  const { formatMessage: t } = useIntl()
  return (

      <Typography gutterBottom variant='h2' className={cx.searchingTitle}>
        {t(m.updateNotAvailable)}
      </Typography>

  )
}

const useStyles = makeStyles(theme => ({
  searchingText: {
    maxWidth: 300,
    marginLeft: theme.spacing(2)
  },
  searchingWrapper: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    flex: 1,
    alignSelf: 'stretch',
    justifySelf: 'stretch'
  },
  searching: {
    color: '#00052b',
    display: 'flex',
    alignItems: 'flex-start',
    justifyContent: 'center'
  },
  searchingTitle: {
    fontSize: '2em',
    fontWeight: 400
  },
  root: {
    height: '100%',
    width: '100%',
    position: 'relative',
    display: 'flex',
    flexDirection: 'column',
    backgroundColor: '#F5F5F5'
  },
  wrapper: {
    alignItems: 'center',
    justifyContent: 'center',
    display: 'flex',
    flexDirection: 'column',
    padding: '10%'
  },
  content: {
    flex: 1,
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center'
  },
  button: {
    marginTop: '15px'
  },
  estimatedDownloadTime: {
    margin: '10px 0px'
  },
  icon: {
    fontSize: 48
  }
}))
<commit_msg>fix: Make left-hand side copy more simple<commit_after>import React from 'react'
import { LinearProgress, Typography, makeStyles } from '@material-ui/core'
import { defineMessages, useIntl } from 'react-intl'
import Button from '@material-ui/core/Button'
import FormattedDuration from 'react-intl-formatted-duration'
import ErrorIcon from '@material-ui/icons/Error'
import Paper from '@material-ui/core/Paper'
import Loader from '../Loader'

import STATES from './states'
export { default as STATES } from './states'

const m = defineMessages({
  // Title on sync screen when searching for devices
  updateAvailable: 'Update',
  updateNotAvailable: 'Mapeo is up to date! You are on the latest version.',
  downloadButtonText: 'Download',
  calculatingProgress: 'Estimating...',
  downloadProgress: 'Downloading',
  restartMapeoText: 'An update to Mapeo has been downloaded. Restart Mapeo to update.',
  restartMapeoButton: 'Restart',
  errorTitle: 'Error',
  errorMessage: 'There was an error and Mapeo could not update. Try again later.',
  patchUpdate: 'This update includes changes that fix critical errors. Please update as soon as possible.',
  minorUpdate: 'This update includes improvements that may change your experience.',
  majorUpdate: 'This update will make your application incompatible with earlier verions.',
  unknownDownloadSpeed: 'Unknown',
  estimatedDownloadTime: 'Estimated download time is'
})

const errors = {
  ERR_UPDATER_CHANNEL_FILE_NOT_FOUND: 'This channel does not have any updates'
}

export const UpdateTab = ({ update }) => {
  const cx = useStyles()
  const { formatMessage: t } = useIntl()

  var internal = function () {
    switch (update.state) {
      case STATES.AVAILABLE:
        return <Typography>{t(m.updateAvailable)}</Typography>
      case STATES.DOWNLOADING:
        return <Typography>{t(m.calculatingProgress)}</Typography>
      case STATES.PROGRESS:
        return <Typography>{t(m.downloadProgress)}</Typography>
      case STATES.READY_FOR_RESTART:
        return <Typography>{t(m.restartMapeoButton)}</Typography>
      case STATES.ERROR:
        return (
          <Typography style={{ color: 'red' }}>
            {t(m.errorTitle)}
          </Typography>
        )
      default: // STATES.IDLE, STATES.UPDATE_NOT_AVAILABLE:
        return null
    }
  }

  return
{internal()}

}

export const UpdaterView = ({ update, setUpdate }) => {
  const cx = useStyles()
  const { formatMessage: t } = useIntl()

  var internal = function () {
    switch (update.state) {
      case STATES.AVAILABLE:
        return <UpdateAvailableView cx={cx} update={update} setUpdate={setUpdate} />
      case STATES.DOWNLOADING:
        return <Typography>{t(m.calculatingProgress)}</Typography>
      case STATES.PROGRESS:
        return <DownloadProgressView cx={cx} percent={update.progress.percent} update={update} />
      case STATES.READY_FOR_RESTART:
        return <RestartView cx={cx} />
      case STATES.UPDATE_NOT_AVAILABLE:
        return <UpdateNotAvailableView cx={cx} />
      case STATES.ERROR:
        return (
          <Typography>
            <ErrorIcon
              fontSize='inherit'
              className={cx.icon}
              style={{ color: 'red' }}
            />
            {t(m.errorMessage)}
            {update.updateInfo.code}
            {errors[update.updateInfo.code]}
          </Typography>
        )
      default: // STATES.IDLE
        return null
    }
  }

  return (

          {internal()}

  )
}

const RestartView = ({ cx }) => {
  const { formatMessage: t } = useIntl()
  return (

      <Typography gutterBottom variant='h2' className={cx.searchingTitle}>
        {t(m.restartMapeoText)}
      </Typography>

  )
}

const DownloadProgressView = ({ cx, update, percent }) => {
  /*
      {
        progress: {
          total: 141164463,
          delta: 1655048,
          transferred: 11384326,
          percent: 8.064583506402741,
          bytesPerSecond: 2244544
        }
      }
  */

  const progress = update.progress
  let estimatedTimeLeft

  if (progress) {
    estimatedTimeLeft = progress.total ? (progress.total - progress.transferred) / progress.bytesPerSecond : 0
  }

  return (

      <Loader />
      <LinearProgress variant='determinate' value={percent} color='secondary' />
      <Typography>
        {estimatedTimeLeft && <FormattedDuration seconds={estimatedTimeLeft} />}
      </Typography>

  )
}

const UpdateAvailableView = ({ cx, update, setUpdate }) => {
  const { formatMessage: t } = useIntl()

  const { size, downloadSpeed, major, minor, patch } = update.updateInfo

  const handleDownlaoadClick = setUpdate.downloadUpdate

  const estimatedDownloadTime = downloadSpeed
    ? <FormattedDuration seconds={size / downloadSpeed.bps} />
    : t(m.unknownDownloadSpeed)

  return (

      <Typography gutterBottom variant='h2' className={cx.searchingTitle}>
        {t(m.updateAvailable)}
      </Typography>
      <Paper className={cx.wrapper}>

          <Typography>
            {
              major
                ? t(m.majorUpdate)
                : minor
                  ? t(m.minorUpdate)
                  : patch
                    ? t(m.patchUpdate)
                    : ''
            }
          </Typography>

          <Typography className={cx.estimatedDownloadTime}>
            {t(m.estimatedDownloadTime)} {estimatedDownloadTime}
          </Typography>

          <Button
            onClick={handleDownlaoadClick}
            className={cx.button}
            variant='contained'
            size='large'
            color='primary'
          >
            {t(m.downloadButtonText)}
          </Button>

      </Paper>

  )
}
/*

const ExpandedNotes = ({ releaseSummary }) => {
  return

    <Typography variant='body'>{releaseSummary}</Typography>

}

const HiddenNotes = ({ releaseSummary }) => {
  return

    <Typography variant='body'>{releaseSummary}</Typography>

}
*/

const UpdateNotAvailableView = ({ cx, update, downloadUpdateClick }) => {
  const { formatMessage: t } = useIntl()
  return (

      <Typography gutterBottom variant='h2' className={cx.searchingTitle}>
        {t(m.updateNotAvailable)}
      </Typography>

  )
}

const useStyles = makeStyles(theme => ({
  searchingText: {
    maxWidth: 300,
    marginLeft: theme.spacing(2)
  },
  searchingWrapper: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    flex: 1,
    alignSelf: 'stretch',
    justifySelf: 'stretch'
  },
  searching: {
    color: '#00052b',
    display: 'flex',
    alignItems: 'flex-start',
    justifyContent: 'center'
  },
  searchingTitle: {
    fontSize: '2em',
    fontWeight: 400
  },
  root: {
    height: '100%',
    width: '100%',
    position: 'relative',
    display: 'flex',
    flexDirection: 'column',
    backgroundColor: '#F5F5F5'
  },
  wrapper: {
    alignItems: 'center',
    justifyContent: 'center',
    display: 'flex',
    flexDirection: 'column',
    padding: '10%'
  },
  content: {
    flex: 1,
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center'
  },
  button: {
    marginTop: '15px'
  },
  estimatedDownloadTime: {
    margin: '10px 0px'
  },
  icon: {
    fontSize: 48
  }
}))
<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react'
import {Layer, Stage, Image} from 'react-konva';

export default class Canvas extends Component {
 state = {
  image: null,
  width: 0,
  height: 0
}
  componentDidUpdate() {
  const image = new window.Image()
  image.src = this.props.image.file
  image.onload = () => {
    this.setState({
      image: image,
      width: image.width,
      height: image.height
    });
  }
}

  render() {
    return

              <Stage width={this.state.width} height={this.state.height}>
                  <Layer>
                    <Image image={this.state.image} />
                  </Layer>
              </Stage>

  }
}

Canvas.propTypes = {
  image: PropTypes.object.isRequired
}
<commit_msg>For size in props<commit_after>import React, { PropTypes, Component } from 'react'
import {Layer, Stage, Image} from 'react-konva';

export default class Canvas extends Component {
    state = {
        image: null
    }
    componentDidUpdate() {
        const image = new window.Image()
        image.src = this.props.image.file
        image.onload = () => {
            this.setState({
                image: image
            });
        }
    }

    render() {
        const { width, height } = this.props.image
        return (

                <Stage width={width} height={height}>
                    <Layer>
                        <Image image={this.state.image} />
                    </Layer>
                </Stage>

      )
    }
}

Canvas.propTypes = {
    image: PropTypes.object.isRequired
}
<|endoftext|>


<commit_before>/*
Language: Haskell
Author: Jeremy Hull <sourdrums@gmail.com>
Contributors: Zena Treep <zena.treep@gmail.com>
*/

function(hljs) {

  var COMMENT1 = {
    className: 'comment',
    begin: '--', end: '$'
  };

  var COMMENT2 = {
    className: 'comment',
    contains: ['self'],
    begin: '{-', end: '-}'
  };

  var PRAGMA = {
    className: 'pragma',
    begin: '{-#', end: '#-}'
  };

  var PREPROCESSOR = {
    className: 'preprocessor',
    begin: '^#', end: '$'
  };

  var CONSTRUCTOR = {
    className: 'type',
    begin: '\\b[A-Z][\\w\']*', // TODO: other constructors (build-in, infix).
    relevance: 0
  };

  var LIST = {
    className: 'container',
    begin: '\\(', end: '\\)',
    illegal: '"',
    contains: [
      PRAGMA,
      COMMENT1,
      COMMENT2,
      PREPROCESSOR,
      {className: 'type', begin: '\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?'},
      { className: 'title', begin: '[_a-z][\\w\']*' }
    ]
  };

  var RECORD = {
    className: 'container',
    begin: '{', end: '}',
    contains: LIST.contains
  };

  return {
    keywords:
      'let in if then else case of where do module import hiding qualified type data ' +
      'newtype deriving class instance as default infix infixl infixr ' +
      'foreign export ccall stdcall cplusplus jvm dotnet safe unsafe ' +
      'family forall mdo proc rec',
    contains: [

      // Top-level constructions.

      {
        className: 'module',
        begin: '\\bmodule ', end: 'where',
        keywords: 'module where',
        contains: [LIST, COMMENT2],
        illegal: '\\W\\.|;'
      },
      {
        className: 'import',
        begin: '\\bimport ', end: '$',
        keywords: 'import qualified as hiding',
        contains: [LIST, COMMENT1, COMMENT2],
        illegal: '\\W\\.|;'
      },

      {
        className: 'class',
        begin: '\\b(class |instance )', end: 'where',
        keywords: 'class family instance where',
        contains: [CONSTRUCTOR, LIST, COMMENT2]
      },
      {
        className: 'typedef',
        begin: '\\b(data |(new)?type )', end: '$',
        keywords: 'data family type newtype deriving',
        contains: [PRAGMA, COMMENT1, COMMENT2, CONSTRUCTOR, LIST, RECORD]
      },
      {
        className: 'default',
        begin: '\\bdefault ', end: '$',
        keywords: 'default',
        contains: [CONSTRUCTOR, LIST, COMMENT1, COMMENT2]
      },
      {
        className: 'infix',
        begin: '\\b(infix |infixl |infixr )', end: '$',
        keywords: 'infix infixl infixr',
        contains: [hljs.C_NUMBER_MODE, COMMENT1, COMMENT2]
      },
      {
        className: 'foreign',
        begin: '\\bforeign ', end: '$',
        keywords: 'foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe',
        contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE, COMMENT1, COMMENT2]
      },
      {
        className: 'shebang',
        begin: '#!\\/usr\\/bin\\/env\ runhaskell', end: '$'
      },

      // "Whitespaces".

      PRAGMA,
      COMMENT1,
      COMMENT2,
      PREPROCESSOR,

      // Literals and names.

      // TODO: characters.
      hljs.QUOTE_STRING_MODE,
      hljs.C_NUMBER_MODE,
      CONSTRUCTOR,
      { className: 'title', begin: '^[_a-z][\\w\']*' },

      {begin: '->|<-'} // No markup, relevance booster
    ]
  };
}
<commit_msg>Make keywords better aligned<commit_after>/*
Language: Haskell
Author: Jeremy Hull <sourdrums@gmail.com>
Contributors: Zena Treep <zena.treep@gmail.com>
*/

function(hljs) {

  var COMMENT1 = {
    className: 'comment',
    begin: '--', end: '$'
  };

  var COMMENT2 = {
    className: 'comment',
    contains: ['self'],
    begin: '{-', end: '-}'
  };

  var PRAGMA = {
    className: 'pragma',
    begin: '{-#', end: '#-}'
  };

  var PREPROCESSOR = {
    className: 'preprocessor',
    begin: '^#', end: '$'
  };

  var CONSTRUCTOR = {
    className: 'type',
    begin: '\\b[A-Z][\\w\']*', // TODO: other constructors (build-in, infix).
    relevance: 0
  };

  var LIST = {
    className: 'container',
    begin: '\\(', end: '\\)',
    illegal: '"',
    contains: [
      PRAGMA,
      COMMENT1,
      COMMENT2,
      PREPROCESSOR,
      {className: 'type', begin: '\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?'},
      { className: 'title', begin: '[_a-z][\\w\']*' }
    ]
  };

  var RECORD = {
    className: 'container',
    begin: '{', end: '}',
    contains: LIST.contains
  };

  return {
    keywords:
      'let in if then else case of where do module import hiding ' +
      'qualified type data newtype deriving class instance as default ' +
      'infix infixl infixr foreign export ccall stdcall cplusplus ' +
      'jvm dotnet safe unsafe family forall mdo proc rec',
    contains: [

      // Top-level constructions.

      {
        className: 'module',
        begin: '\\bmodule ', end: 'where',
        keywords: 'module where',
        contains: [LIST, COMMENT2],
        illegal: '\\W\\.|;'
      },
      {
        className: 'import',
        begin: '\\bimport ', end: '$',
        keywords: 'import qualified as hiding',
        contains: [LIST, COMMENT1, COMMENT2],
        illegal: '\\W\\.|;'
      },

      {
        className: 'class',
        begin: '\\b(class |instance )', end: 'where',
        keywords: 'class family instance where',
        contains: [CONSTRUCTOR, LIST, COMMENT2]
      },
      {
        className: 'typedef',
        begin: '\\b(data |(new)?type )', end: '$',
        keywords: 'data family type newtype deriving',
        contains: [PRAGMA, COMMENT1, COMMENT2, CONSTRUCTOR, LIST, RECORD]
      },
      {
        className: 'default',
        begin: '\\bdefault ', end: '$',
        keywords: 'default',
        contains: [CONSTRUCTOR, LIST, COMMENT1, COMMENT2]
      },
      {
        className: 'infix',
        begin: '\\b(infix |infixl |infixr )', end: '$',
        keywords: 'infix infixl infixr',
        contains: [hljs.C_NUMBER_MODE, COMMENT1, COMMENT2]
      },
      {
        className: 'foreign',
        begin: '\\bforeign ', end: '$',
        keywords: 'foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe',
        contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE, COMMENT1, COMMENT2]
      },
      {
        className: 'shebang',
        begin: '#!\\/usr\\/bin\\/env\ runhaskell', end: '$'
      },

      // "Whitespaces".

      PRAGMA,
      COMMENT1,
      COMMENT2,
      PREPROCESSOR,

      // Literals and names.

      // TODO: characters.
      hljs.QUOTE_STRING_MODE,
      hljs.C_NUMBER_MODE,
      CONSTRUCTOR,
      { className: 'title', begin: '^[_a-z][\\w\']*' },

      {begin: '->|<-'} // No markup, relevance booster
    ]
  };
}
<|endoftext|>


<commit_before>import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import { Container, Button } from "reactstrap";
import randomWords from "random-words";
import CardContainer from "../containers/Card";
import gql from "graphql-tag";
import { graphql, withApollo } from "react-apollo";
import Caching from "./caching";
import playSound from "./generic/SoundPlayer";
import "./client.css";

class ClientWrapper extends Component {
  constructor(props) {
    super(props);
    let clientId = localStorage.getItem("thorium_clientId");
    if (!clientId) {
      clientId = randomWords(3).join("-");
      // Just to test out the webpack
      localStorage.setItem("thorium_clientId", clientId);
    }
    this.state = {
      clientId
    };
  }
  updateClientId = clientId => {
    const oldClientId = this.state.clientId;
    localStorage.setItem("thorium_clientId", clientId);
    this.setState({ clientId });
    this.props.client.mutate({
      mutation: gql`
        mutation RemoveClient($id: ID!) {
          clientDisconnect(client: $id)
        }
      `,
      variables: { id: oldClientId }
    });
    this.props.client.mutate({
      mutation: gql`
        mutation RegisterClient($client: ID!) {
          clientConnect(client: $client)
        }
      `,
      variables: { client: clientId }
    });
  };
  render() {
    return (
      <Client
        clientId={this.state.clientId}
        updateClientId={this.updateClientId}
      />
    );
  }
}

export default withApollo(ClientWrapper);

const creditList = [
  {
    header: "Created By:",
    content: "Alex Anderson 🚀"
  },
  {
    header: "Conceptual Design",
    content: "Matt Ricks 🤔"
  },
  {
    header: "Technical Consultant",
    content: "Brent Anderson 🤓"
  },
  {
    header: "Documentation & Training",
    content: "Crystal Anderson 💎"
  },
  {
    header: "Curve Frame Design",
    content: "BJ Warner 🎨 & Todd Rasband 🖌"
  },
  {
    header: "Docking Images (Endless Sky)",
    content: (

Maximilian Korber (CC-BY-SA-4.0)

Iaz Poolar (CC-BY-SA-4.0)

Michael Zahniser (CC-BY-SA-4.0)

    )
  },
  {
    header: "Card Icons",
    content: (

jet engine by Arthur Shlain from the Noun Project

Coolant Temperature by Ben Johnson from the Noun Project

sensor by Bakunetsu Kaito from the Noun Project

Gyroscope by Arthur Shlain from the Noun Project

Radar by Oliviu Stoian from the Noun Project

Feather Icon Pack

    )
  }
];
class Credits extends Component {
  state = { debug: false, scroll: 0 };
  toggleDebug = () => {
    this.setState({
      debug: !this.state.debug
    });
  };
  componentDidMount() {
    this.looping = true;
    this.loop();
  }
  componentWillUnmount() {
    this.looping = false;
  }
  loop = () => {
    if (!this.looping) return;
    const el = this.refs.scroll;

    this.setState({
      scroll:
        el && el.scrollHeight - el.clientHeight <= this.state.scroll
          ? 0
          : this.state.scroll + 0.5 || 1
    });
    requestAnimationFrame(this.loop);
  };
  changeClientId = evt => {
    evt.preventDefault();
    const newClientId = prompt("What is the new client ID?");
    if (newClientId) {
      this.props.updateClientId(newClientId);
    }
  };
  render() {
    const { props } = this;
    let client = {};
    let flight = {};
    let simulator = {};
    let station = {};
    if (this.refs.scroll) {
      this.refs.scroll.scrollTop = this.state.scroll;
    }
    if (!props.data.loading) {
      client = props.data.clients.length > 0 ? props.data.clients[0] : {};
      simulator = client.simulator || {};
      flight = client.flight || {};
      station = client.station || {};
    }
    return (

        <Container>

Thorium

          {this.state.debug ? (

                <Button color="info" onClick={this.changeClientId}>
                  Client ID: {client.id}
                </Button>

Flight: {flight.name}

Simulator: {simulator.name}

Station: {station.name}

Login Name: {client.loginName}

Download the client app:

                    Mac

                    Windows x64

                    Windows ia32

                    Linux x64

                    Linux ia32

                    Linux armv7l

          ) : (

              {creditList.map(c => (

{c.header}

{c.content}

              ))}

          )}
        </Container>

    );
  }
}

const CACHE_INVALID_SUB = gql`
  subscription ClearCache($client: ID!) {
    clearCache(client: $client)
  }
`;

const CLIENT_SUB = gql`
  subscription ClientChanged($client: ID!) {
    clientChanged(client: $client) {
      id
      flight {
        id
        name
        date
      }
      simulator {
        id
        name
        alertlevel
        layout
      }
      station {
        name
        login
        messageGroups
        widgets
        cards {
          name
          component
        }
      }
      loginName
      loginState
      offlineState
      training
      caches
    }
  }
`;

const SIMULATOR_SUB = gql`
  subscription SimulatorUpdate($id: ID!) {
    simulatorsUpdate(simulatorId: $id) {
      id
      name
      alertlevel
      layout
    }
  }
`;

class ClientView extends Component {
  constructor(props) {
    super(props);
    this.clientSubscription = null;
    this.simulatorSub = null;
    this.cacheSub = null;
    window.onbeforeunload = () => {
      props.client.mutate({
        mutation: gql`
          mutation RemoveClient($id: ID!) {
            clientDisconnect(client: $id)
          }
        `,
        variables: { id: props.clientId }
      });
      return null;
    };
  }
  componentWillReceiveProps(nextProps) {
    if (nextProps.data.loading) return;
    if (this.props.clientId !== nextProps.clientId) {
      this.clientSubscription && this.clientSubscription();
      this.clientSubscription = null;
    }
    if (!this.clientSubscription && !nextProps.data.loading) {
      this.clientSubscription = nextProps.data.subscribeToMore({
        document: CLIENT_SUB,
        variables: { client: nextProps.clientId }
      });
    }
    if (!this.cacheSub && !nextProps.data.loading) {
      this.cacheSub = nextProps.data.subscribeToMore({
        document: CACHE_INVALID_SUB,
        variables: { client: nextProps.clientId },
        updateQuery: previousResult => {
          this.props.playSound({ url: "/sciences.ogg" });
          setTimeout(() => this.props.client.resetStore(), 500);
          return previousResult;
        }
      });
    }
    const client = nextProps.data.clients[0];
    if (
      !client ||
      (client.simulator &&
        this.props.data.clients &&
        this.props.data.clients[0] &&
        this.props.data.clients[0].simulator &&
        client.simulator.id !== this.props.data.clients[0].simulator.id)
    ) {
      this.simulatorSub && this.simulatorSub();
      this.simulatorSub = null;
    }
    if (!this.simulatorSub && !nextProps.data.loading) {
      if (client && client.simulator) {
        this.simulatorSub = nextProps.data.subscribeToMore({
          document: SIMULATOR_SUB,
          variables: { id: client.simulator.id },
          updateQuery: (previousResult, { subscriptionData }) => {
            const sim = subscriptionData.data.simulatorsUpdate[0];
            return Object.assign({}, previousResult, {
              clients: previousResult.clients.map(
                ({
                  flight,
                  id,
                  loginName,
                  loginState,
                  offlineState,
                  station,
                  __typename
                }) => ({
                  flight,
                  id,
                  loginName,
                  loginState,
                  offlineState,
                  station,
                  __typename,
                  simulator: {
                    __typename: "Simulator",
                    id: sim.id,
                    alertlevel: sim.alertlevel,
                    layout: sim.layout,
                    name: sim.name
                  }
                })
              )
            });
          }
        });
      }
    }
    // Play the sound effect
    const c = nextProps.data.clients ? nextProps.data.clients[0] : {};
    const oldClient = this.props.data.clients ? this.props.data.clients[0] : {};
    if (!c) return;
    const { flight, simulator, station } = c;
    const {
      flight: oldFlight,
      simulator: oldSimulator,
      station: oldStation
    } = oldClient;
    if (
      flight &&
      simulator &&
      station &&
      !(oldFlight && oldSimulator && oldStation)
    ) {
      this.props.playSound({ url: "/sciences.ogg" });
    }
  }
  componentWillUnmount() {
    this.clientSubscription && this.clientSubscription();
    this.simulatorSub && this.simulatorSub();
    this.cacheSub && this.cacheSub();
  }
  componentDidMount() {
    this.props.client.mutate({
      mutation: gql`
        mutation RegisterClient($client: ID!) {
          clientConnect(client: $client)
        }
      `,
      variables: { client: this.props.clientId }
    });
  }
  render() {
    let flight;
    let simulator;
    let station;
    let client = {};
    if (!this.props.data.loading && this.props.data.clients[0]) {
      client = this.props.data.clients[0];
      flight = client.flight;
      simulator = client.simulator;
      station = client.station;
    }
    return (

        <Caching client={client} />
        {flight && simulator && station ? (
          <CardContainer
            flight={flight}
            simulator={simulator}
            station={station}
            client={client}
          />
        ) : (
          <Credits
            {...this.props}
            clientId={this.props.clientId}
            updateClientId={this.props.updateClientId}
          />
        )}

    );
  }
}

const ClientQuery = gql`
  query Clients($clientId: ID) {
    clients(clientId: $clientId) {
      id
      flight {
        id
        name
        date
      }
      simulator {
        id
        name
        alertlevel
        layout
      }
      station {
        name
        login
        messageGroups
        widgets
        cards {
          name
          component
        }
      }
      loginName
      loginState
      offlineState
      training
      caches
    }
  }
`;

const Client = withRouter(
  graphql(ClientQuery, {
    options: ownProps => ({
      fetchPolicy: "cache-and-network",
      variables: {
        clientId: ownProps.clientId
      }
    })
  })(withApollo(playSound(ClientView)))
);
<commit_msg>Add credits for Nathan King<commit_after>import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import { Container, Button } from "reactstrap";
import randomWords from "random-words";
import CardContainer from "../containers/Card";
import gql from "graphql-tag";
import { graphql, withApollo } from "react-apollo";
import Caching from "./caching";
import playSound from "./generic/SoundPlayer";
import "./client.css";

class ClientWrapper extends Component {
  constructor(props) {
    super(props);
    let clientId = localStorage.getItem("thorium_clientId");
    if (!clientId) {
      clientId = randomWords(3).join("-");
      // Just to test out the webpack
      localStorage.setItem("thorium_clientId", clientId);
    }
    this.state = {
      clientId
    };
  }
  updateClientId = clientId => {
    const oldClientId = this.state.clientId;
    localStorage.setItem("thorium_clientId", clientId);
    this.setState({ clientId });
    this.props.client.mutate({
      mutation: gql`
        mutation RemoveClient($id: ID!) {
          clientDisconnect(client: $id)
        }
      `,
      variables: { id: oldClientId }
    });
    this.props.client.mutate({
      mutation: gql`
        mutation RegisterClient($client: ID!) {
          clientConnect(client: $client)
        }
      `,
      variables: { client: clientId }
    });
  };
  render() {
    return (
      <Client
        clientId={this.state.clientId}
        updateClientId={this.updateClientId}
      />
    );
  }
}

export default withApollo(ClientWrapper);

const creditList = [
  {
    header: "Created By:",
    content: "Alex Anderson 🚀"
  },
  {
    header: "Conceptual Design",
    content: "Matt Ricks 🤔"
  },
  {
    header: "Technical Consultant",
    content: "Brent Anderson 🤓"
  },
  {
    header: "Documentation & Training",
    content: "Crystal Anderson 💎"
  },
  {
    header: "Curve Frame Design",
    content: "BJ Warner 🎨 & Todd Rasband 🖌"
  },
  {
    header: "Glass Frame Design",
    content: "Nathan King 👑"
  },
  {
    header: "Docking Images (Endless Sky)",
    content: (

Maximilian Korber (CC-BY-SA-4.0)

Iaz Poolar (CC-BY-SA-4.0)

Michael Zahniser (CC-BY-SA-4.0)

    )
  },
  {
    header: "Card Icons",
    content: (

jet engine by Arthur Shlain from the Noun Project

Coolant Temperature by Ben Johnson from the Noun Project

sensor by Bakunetsu Kaito from the Noun Project

Gyroscope by Arthur Shlain from the Noun Project

Radar by Oliviu Stoian from the Noun Project

Feather Icon Pack

Font Awesome

    )
  }
];
class Credits extends Component {
  state = { debug: false, scroll: 0 };
  toggleDebug = () => {
    this.setState({
      debug: !this.state.debug
    });
  };
  componentDidMount() {
    this.looping = true;
    this.loop();
  }
  componentWillUnmount() {
    this.looping = false;
  }
  loop = () => {
    if (!this.looping) return;
    const el = this.refs.scroll;

    this.setState({
      scroll:
        el && el.scrollHeight - el.clientHeight <= this.state.scroll
          ? 0
          : this.state.scroll + 0.5 || 1
    });
    requestAnimationFrame(this.loop);
  };
  changeClientId = evt => {
    evt.preventDefault();
    const newClientId = prompt("What is the new client ID?");
    if (newClientId) {
      this.props.updateClientId(newClientId);
    }
  };
  render() {
    const { props } = this;
    let client = {};
    let flight = {};
    let simulator = {};
    let station = {};
    if (this.refs.scroll) {
      this.refs.scroll.scrollTop = this.state.scroll;
    }
    if (!props.data.loading) {
      client = props.data.clients.length > 0 ? props.data.clients[0] : {};
      simulator = client.simulator || {};
      flight = client.flight || {};
      station = client.station || {};
    }
    return (

        <Container>

Thorium

          {this.state.debug ? (

                <Button color="info" onClick={this.changeClientId}>
                  Client ID: {client.id}
                </Button>

Flight: {flight.name}

Simulator: {simulator.name}

Station: {station.name}

Login Name: {client.loginName}

Download the client app:

                    Mac

                    Windows x64

                    Windows ia32

                    Linux x64

                    Linux ia32

                    Linux armv7l

          ) : (

              {creditList.map(c => (

{c.header}

{c.content}

              ))}

          )}
        </Container>

    );
  }
}

const CACHE_INVALID_SUB = gql`
  subscription ClearCache($client: ID!) {
    clearCache(client: $client)
  }
`;

const CLIENT_SUB = gql`
  subscription ClientChanged($client: ID!) {
    clientChanged(client: $client) {
      id
      flight {
        id
        name
        date
      }
      simulator {
        id
        name
        alertlevel
        layout
      }
      station {
        name
        login
        messageGroups
        widgets
        cards {
          name
          component
        }
      }
      loginName
      loginState
      offlineState
      training
      caches
    }
  }
`;

const SIMULATOR_SUB = gql`
  subscription SimulatorUpdate($id: ID!) {
    simulatorsUpdate(simulatorId: $id) {
      id
      name
      alertlevel
      layout
    }
  }
`;

class ClientView extends Component {
  constructor(props) {
    super(props);
    this.clientSubscription = null;
    this.simulatorSub = null;
    this.cacheSub = null;
    window.onbeforeunload = () => {
      props.client.mutate({
        mutation: gql`
          mutation RemoveClient($id: ID!) {
            clientDisconnect(client: $id)
          }
        `,
        variables: { id: props.clientId }
      });
      return null;
    };
  }
  componentWillReceiveProps(nextProps) {
    if (nextProps.data.loading) return;
    if (this.props.clientId !== nextProps.clientId) {
      this.clientSubscription && this.clientSubscription();
      this.clientSubscription = null;
    }
    if (!this.clientSubscription && !nextProps.data.loading) {
      this.clientSubscription = nextProps.data.subscribeToMore({
        document: CLIENT_SUB,
        variables: { client: nextProps.clientId }
      });
    }
    if (!this.cacheSub && !nextProps.data.loading) {
      this.cacheSub = nextProps.data.subscribeToMore({
        document: CACHE_INVALID_SUB,
        variables: { client: nextProps.clientId },
        updateQuery: previousResult => {
          this.props.playSound({ url: "/sciences.ogg" });
          setTimeout(() => this.props.client.resetStore(), 500);
          return previousResult;
        }
      });
    }
    const client = nextProps.data.clients[0];
    if (
      !client ||
      (client.simulator &&
        this.props.data.clients &&
        this.props.data.clients[0] &&
        this.props.data.clients[0].simulator &&
        client.simulator.id !== this.props.data.clients[0].simulator.id)
    ) {
      this.simulatorSub && this.simulatorSub();
      this.simulatorSub = null;
    }
    if (!this.simulatorSub && !nextProps.data.loading) {
      if (client && client.simulator) {
        this.simulatorSub = nextProps.data.subscribeToMore({
          document: SIMULATOR_SUB,
          variables: { id: client.simulator.id },
          updateQuery: (previousResult, { subscriptionData }) => {
            const sim = subscriptionData.data.simulatorsUpdate[0];
            return Object.assign({}, previousResult, {
              clients: previousResult.clients.map(
                ({
                  flight,
                  id,
                  loginName,
                  loginState,
                  offlineState,
                  station,
                  __typename
                }) => ({
                  flight,
                  id,
                  loginName,
                  loginState,
                  offlineState,
                  station,
                  __typename,
                  simulator: {
                    __typename: "Simulator",
                    id: sim.id,
                    alertlevel: sim.alertlevel,
                    layout: sim.layout,
                    name: sim.name
                  }
                })
              )
            });
          }
        });
      }
    }
    // Play the sound effect
    const c = nextProps.data.clients ? nextProps.data.clients[0] : {};
    const oldClient = this.props.data.clients ? this.props.data.clients[0] : {};
    if (!c) return;
    const { flight, simulator, station } = c;
    const {
      flight: oldFlight,
      simulator: oldSimulator,
      station: oldStation
    } = oldClient;
    if (
      flight &&
      simulator &&
      station &&
      !(oldFlight && oldSimulator && oldStation)
    ) {
      this.props.playSound({ url: "/sciences.ogg" });
    }
  }
  componentWillUnmount() {
    this.clientSubscription && this.clientSubscription();
    this.simulatorSub && this.simulatorSub();
    this.cacheSub && this.cacheSub();
  }
  componentDidMount() {
    this.props.client.mutate({
      mutation: gql`
        mutation RegisterClient($client: ID!) {
          clientConnect(client: $client)
        }
      `,
      variables: { client: this.props.clientId }
    });
  }
  render() {
    let flight;
    let simulator;
    let station;
    let client = {};
    if (!this.props.data.loading && this.props.data.clients[0]) {
      client = this.props.data.clients[0];
      flight = client.flight;
      simulator = client.simulator;
      station = client.station;
    }
    return (

        <Caching client={client} />
        {flight && simulator && station ? (
          <CardContainer
            flight={flight}
            simulator={simulator}
            station={station}
            client={client}
          />
        ) : (
          <Credits
            {...this.props}
            clientId={this.props.clientId}
            updateClientId={this.props.updateClientId}
          />
        )}

    );
  }
}

const ClientQuery = gql`
  query Clients($clientId: ID) {
    clients(clientId: $clientId) {
      id
      flight {
        id
        name
        date
      }
      simulator {
        id
        name
        alertlevel
        layout
      }
      station {
        name
        login
        messageGroups
        widgets
        cards {
          name
          component
        }
      }
      loginName
      loginState
      offlineState
      training
      caches
    }
  }
`;

const Client = withRouter(
  graphql(ClientQuery, {
    options: ownProps => ({
      fetchPolicy: "cache-and-network",
      variables: {
        clientId: ownProps.clientId
      }
    })
  })(withApollo(playSound(ClientView)))
);
<|endoftext|>


<commit_before>/*
Language: Haskell
Author: Jeremy Hull <sourdrums@gmail.com>
Contributors: Zena Treep <zena.treep@gmail.com>
Category: functional
*/

function(hljs) {
  var COMMENT_MODES = [
    hljs.COMMENT('--', '$'),
    hljs.COMMENT(
      '{-',
      '-}',
      {
        contains: ['self']
      }
    )
  ];

  var PRAGMA = {
    className: 'pragma',
    begin: '{-#', end: '#-}'
  };

  var PREPROCESSOR = {
    className: 'preprocessor',
    begin: '^#', end: '$'
  };

  var CONSTRUCTOR = {
    className: 'type',
    begin: '\\b[A-Z][\\w\']*', // TODO: other constructors (build-in, infix).
    relevance: 0
  };

  var LIST = {
    className: 'container',
    begin: '\\(', end: '\\)',
    illegal: '"',
    contains: [
      PRAGMA,
      PREPROCESSOR,
      {className: 'type', begin: '\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?'},
      hljs.inherit(hljs.TITLE_MODE, {begin: '[_a-z][\\w\']*'})
    ].concat(COMMENT_MODES)
  };

  var RECORD = {
    className: 'container',
    begin: '{', end: '}',
    contains: LIST.contains
  };

  return {
    aliases: ['hs'],
    keywords:
      'let in if then else case of where do module import hiding ' +
      'qualified type data newtype deriving class instance as default ' +
      'infix infixl infixr foreign export ccall stdcall cplusplus ' +
      'jvm dotnet safe unsafe family forall mdo proc rec',
    contains: [

      // Top-level constructions.

      {
        className: 'module',
        begin: '\\bmodule\\b', end: 'where',
        keywords: 'module where',
        contains: [LIST].concat(COMMENT_MODES),
        illegal: '\\W\\.|;'
      },
      {
        className: 'import',
        begin: '\\bimport\\b', end: '$',
        keywords: 'import|0 qualified as hiding',
        contains: [LIST].concat(COMMENT_MODES),
        illegal: '\\W\\.|;'
      },

      {
        className: 'class',
        begin: '^(\\s*)?(class|instance)\\b', end: 'where',
        keywords: 'class family instance where',
        contains: [CONSTRUCTOR, LIST].concat(COMMENT_MODES)
      },
      {
        className: 'typedef',
        begin: '\\b(data|(new)?type)\\b', end: '$',
        keywords: 'data family type newtype deriving',
        contains: [PRAGMA, CONSTRUCTOR, LIST, RECORD].concat(COMMENT_MODES)
      },
      {
        className: 'default',
        beginKeywords: 'default', end: '$',
        contains: [CONSTRUCTOR, LIST].concat(COMMENT_MODES)
      },
      {
        className: 'infix',
        beginKeywords: 'infix infixl infixr', end: '$',
        contains: [hljs.C_NUMBER_MODE].concat(COMMENT_MODES)
      },
      {
        className: 'foreign',
        begin: '\\bforeign\\b', end: '$',
        keywords: 'foreign import export ccall stdcall cplusplus jvm ' +
                  'dotnet safe unsafe',
        contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE].concat(COMMENT_MODES)
      },
      {
        className: 'shebang',
        begin: '#!\\/usr\\/bin\\/env\ runhaskell', end: '$'
      },

      // "Whitespaces".

      PRAGMA,
      PREPROCESSOR,

      // Literals and names.

      // TODO: characters.
      hljs.QUOTE_STRING_MODE,
      hljs.C_NUMBER_MODE,
      CONSTRUCTOR,
      hljs.inherit(hljs.TITLE_MODE, {begin: '^[_a-z][\\w\']*'}),

      {begin: '->|<-'} // No markup, relevance booster
    ].concat(COMMENT_MODES)
  };
}
<commit_msg>Updated haskell.js to new class names.<commit_after>/*
Language: Haskell
Author: Jeremy Hull <sourdrums@gmail.com>
Contributors: Zena Treep <zena.treep@gmail.com>
Category: functional
*/

function(hljs) {
  var COMMENT_MODES = [
    hljs.COMMENT('--', '$'),
    hljs.COMMENT(
      '{-',
      '-}',
      {
        contains: ['self']
      }
    )
  ];

  var PRAGMA = {
    className: 'meta',
    begin: '{-#', end: '#-}'
  };

  var PREPROCESSOR = {
    className: 'meta',
    begin: '^#', end: '$'
  };

  var CONSTRUCTOR = {
    className: 'type',
    begin: '\\b[A-Z][\\w\']*', // TODO: other constructors (build-in, infix).
    relevance: 0
  };

  var LIST = {
    begin: '\\(', end: '\\)',
    illegal: '"',
    contains: [
      PRAGMA,
      PREPROCESSOR,
      {className: 'type', begin: '\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?'},
      hljs.inherit(hljs.TITLE_MODE, {begin: '[_a-z][\\w\']*'})
    ].concat(COMMENT_MODES)
  };

  var RECORD = {
    begin: '{', end: '}',
    contains: LIST.contains
  };

  return {
    aliases: ['hs'],
    keywords:
      'let in if then else case of where do module import hiding ' +
      'qualified type data newtype deriving class instance as default ' +
      'infix infixl infixr foreign export ccall stdcall cplusplus ' +
      'jvm dotnet safe unsafe family forall mdo proc rec',
    contains: [

      // Top-level constructions.

      {
        begin: '\\bmodule\\b', end: 'where',
        keywords: 'module where',
        contains: [LIST].concat(COMMENT_MODES),
        illegal: '\\W\\.|;'
      },
      {
        begin: '\\bimport\\b', end: '$',
        keywords: 'import|0 qualified as hiding',
        contains: [LIST].concat(COMMENT_MODES),
        illegal: '\\W\\.|;'
      },

      {
        className: 'class',
        begin: '^(\\s*)?(class|instance)\\b', end: 'where',
        keywords: 'class family instance where',
        contains: [CONSTRUCTOR, LIST].concat(COMMENT_MODES)
      },
      {
        className: 'class',
        begin: '\\b(data|(new)?type)\\b', end: '$',
        keywords: 'data family type newtype deriving',
        contains: [PRAGMA, CONSTRUCTOR, LIST, RECORD].concat(COMMENT_MODES)
      },
      {
        beginKeywords: 'default', end: '$',
        contains: [CONSTRUCTOR, LIST].concat(COMMENT_MODES)
      },
      {
        beginKeywords: 'infix infixl infixr', end: '$',
        contains: [hljs.C_NUMBER_MODE].concat(COMMENT_MODES)
      },
      {
        begin: '\\bforeign\\b', end: '$',
        keywords: 'foreign import export ccall stdcall cplusplus jvm ' +
                  'dotnet safe unsafe',
        contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE].concat(COMMENT_MODES)
      },
      {
        className: 'meta',
        begin: '#!\\/usr\\/bin\\/env\ runhaskell', end: '$'
      },

      // "Whitespaces".

      PRAGMA,
      PREPROCESSOR,

      // Literals and names.

      // TODO: characters.
      hljs.QUOTE_STRING_MODE,
      hljs.C_NUMBER_MODE,
      CONSTRUCTOR,
      hljs.inherit(hljs.TITLE_MODE, {begin: '^[_a-z][\\w\']*'}),

      {begin: '->|<-'} // No markup, relevance booster
    ].concat(COMMENT_MODES)
  };
}
<|endoftext|>


<commit_before><commit_msg>学习了下node的http模块<commit_after><|endoftext|>


<commit_before>window.cls || (window.cls = {});

/**
 * @constructor
 * @extends ViewBase
 */
cls.ResourceDetailView = function(id, name, container_class, html, default_handler, network_logger) {
  if (cls.ResourceDetailView.instance)
  {
    return cls.ResourceDetailView.instance;
  }
  cls.ResourceDetailView.instance = this;

  this._service = new cls.ResourceManagerService(this, network_logger);

	this.createView = function(container)
	{
		if (this.resource && this.resource.data)
      container.clearAndRender( templates.resource_detail.formatting_data(this.resource) );

    container.clearAndRender( templates.resource_detail.update(this.resource) );
    if(this.data)
      this.go_to_line(container,this.data);

//    if (this.resource && this.resource.type in {'markup':1,})
    {
      //this.text_search.set_query_selector(".resource-detail-container");
      this.text_search.update_search();
    }

		this.data = null;
	};

  this.create_disabled_view = function(container)
  {
    container.clearAndRender(window.templates.disabled_view());
  };

  const HIGHLIGHTED_LINE_CLASSNAME = 'highlighted-line';
  const RESOURCE_DETAIL_CONTAINER_CLASSNAME = 'resource-detail-container';
  const TEXT = document.TEXT_NODE;
  const ELE  = document.ELEMENT_NODE;
  this._span = document.createElement('span');
  this._span.textContent = ' ';
  this._line_count = 0;
  this._line_found = false;
  this._target_line = 0;
  this._root_ele = null;
  this._tops = [];

  this._highlight_line = function(ele)
  {
    const CR = "\r";
    const LF = "\n";
    var child = ele.firstChild;
    while (child && !this._line_found)
    {
      if (child.nodeType == ELE)
      {
        this._highlight_line(child);
      }
      else if (child.nodeType == TEXT)
      {
        var value = child.nodeValue;
        for (var pos = 0, len = value.length; pos < len; pos++)
        {
          var c = value.charAt(pos);
          // Linefeed recognition will not support Acorn BBC spooled text output
          if ((c == CR ) || (c == LF))
          {
            this._line_count++;
            if (this._line_count == this._target_line)
            {
              var target_pos = child.splitText(pos);
              child.parentNode.insertBefore(this._span, target_pos);
              this._tops.push(this._span.getBoundingClientRect().top);
              child.parentNode.removeChild(this._span);
              child.parentNode.normalize();
              if (this._tops.length < 2)
              {
                this._target_line+=1;
              }
              else
              {
                var scroll_container = ele;
                var container_top = scroll_container.getBoundingClientRect().top;
                var delta = this._tops[1] - this._tops[0];
                var scroll_top = scroll_container.scrollTop;
                ele.addClass(HIGHLIGHTED_LINE_CLASSNAME);
                ele.style.cssText =
                  "background-size: 100% " + delta + "px;" +
                  "background-position: 0 " +
                    (this._tops[0] - container_top + scroll_top) + "px;";

                var scroll_position = scroll_top + this._tops[0] - container_top;
                if (scroll_position <= this._root_ele.parentNode.clientHeight)
                {
                  scroll_position-=64;
                }
                this._root_ele.scrollTop = scroll_position;
                this._line_found = true;
                return;
              }
            }
            if ((c == CR) && (value.charAt(pos+1) == LF))
            {
              pos++;
            }
          }
        }
      }
      child = child && child.nextSibling;
    }
  }

  this.clear_line_highlight = function(container)
  {
    // reset all properties
    this._line_count = 0;
    this._line_found = false;
    this._target_line = 0;
    this._tops = [];
    var _ele = container.querySelectorAll('.'+HIGHLIGHTED_LINE_CLASSNAME)[0];
    if (_ele)
    {
      _ele.removeClass(HIGHLIGHTED_LINE_CLASSNAME)
    }
  }

  this.go_to_line = function(container, data)
  {
		if (!data || !(data.lines && data.lines.length)) return;
    this._root_ele = container.getElementsByClassName(RESOURCE_DETAIL_CONTAINER_CLASSNAME)[0];
    if (this._root_ele)
    {
      this.clear_line_highlight(this._root_ele)
      this._target_line = parseInt(data.lines[0]);
      this._highlight_line(this._root_ele);
    }
  }

	this.on_resource_data_bound = function(type, data)
	{
		var id = data[0];
		var resource = this._service.get_resource(id);
		if(resource)
		{
			resource.data = new cls.ResourceManager["1.0"].ResourceData( data );
		}
		return resource;
	}.bind(this);

  this._show_resource_by_instance = function(resource)
  {
      this.resource = resource;
      if (resource && !resource.data)
        resource.fetch_data(cls.ResourceDetailView.instance.update.bind(cls.ResourceDetailView.instance));
  }

  this._show_resource_by_id = function(id)
  {
    var resource = this._service.get_resource(resource);
    this._show_resource_by_instance(resource);
  }

  this._show_resource_url = function(url)
  {
    var resource = this._service.get_resource_for_url(url);
    if (resource)
      this._show_resource_by_instance(resource);
    else
      new cls.ResourceRequest(url, this.show_resource.bind(this), this.data);
  }

  this.show_resource = function(resource, data)
  {
    this.data = data;

    this.resource = resource;
    /*
    if(resource instanceof cls.Resource)
      this._show_resource_by_instance(resource);
    else if (resource==Number(resource))
      this._show_resource_by_id(resource);
    else if (resource==String(resource))
      this._show_resource_url(resource);
*/
    this.update();
    window.UI.instance.show_view( window.views.resource_detail_view.id );
  }

  //  WIP
  this.show_resource_group = function(resourceGroup)
	{
    return;

		this.resources = [];
		for( var i=0; i<group.ids.length; i++)
		{
			var id = group.ids[i];
			var resource = this._service.get_resource(id);
			if (resource)
			{
				this.resources.push( resource );
				if (!resource.data)
				{
					var responseType = cls.ResourceUtil.type_to_content_mode(resource.type);
					this._service.fetch_resource_data( this.on_resource_data_bound, id, responseType );
				}
			}
		}
		this.update();
	}

  this.init(id, name, container_class, html, default_handler);
};

cls.ResourceDetailView.create_ui_widgets = function()
{
  new ToolbarConfig(
  {
    view:'resource_detail_view',
    groups:
    [
      {
        type: UI.TYPE_INPUT,
        items:
        [
          {
            handler: "resource-text-search",
            shortcuts: "resource-text-search",
            title: ui_strings.S_SEARCH_INPUT_TOOLTIP,
            label: ui_strings.S_INPUT_DEFAULT_TEXT_SEARCH
          }
        ]
      }
    ]
  });

  var text_search = window.views.resource_detail_view.text_search = new TextSearch();

  window.eventHandlers.input["resource-text-search"] = function(event, target)
  {
    text_search.searchDelayed(target.value);
  };

  ActionBroker.
    get_instance().
    get_global_handler().
      register_shortcut_listener("resource-text-search", cls.Helpers.shortcut_search_cb.bind(text_search));

  var on_view_created = function(msg)
  {
    if (msg.id === "resource_detail_view")
    {
      var scroll_container = msg.container.querySelector(".request-details");
      if (!scroll_container)
        scroll_container = msg.container.querySelector(".resource-detail-container");

      if (scroll_container)
      {
        text_search.setContainer(scroll_container);
        text_search.setFormInput(
          views.resource_detail_view.getToolbarControl(msg.container, "resource-text-search")
        );
      }
    }
  }

  var on_view_destroyed = function(msg)
  {
    if (msg.id == "resource_detail_view")
      text_search.cleanup();
  }

  window.messages.addListener("view-created", on_view_created);
  window.messages.addListener("view-destroyed", on_view_destroyed);
}

cls.ResourceDetailView.prototype = ViewBase;

<commit_msg>Fixed _show_resource_by_id Switch from cls.Resource to cls.ResourceInfo<commit_after>window.cls || (window.cls = {});

/**
 * @constructor
 * @extends ViewBase
 */
cls.ResourceDetailView = function(id, name, container_class, html, default_handler, network_logger) {
  if (cls.ResourceDetailView.instance)
  {
    return cls.ResourceDetailView.instance;
  }
  cls.ResourceDetailView.instance = this;

  this._service = new cls.ResourceManagerService(this, network_logger);

	this.createView = function(container)
	{
		if (this.resource && this.resource.data)
      container.clearAndRender( templates.resource_detail.formatting_data(this.resource) );

    container.clearAndRender( templates.resource_detail.update(this.resource) );
    if(this.data)
      this.go_to_line(container,this.data);

//    if (this.resource && this.resource.type in {'markup':1,})
    {
      //this.text_search.set_query_selector(".resource-detail-container");
      this.text_search.update_search();
    }

		this.data = null;
	};

  this.create_disabled_view = function(container)
  {
    container.clearAndRender(window.templates.disabled_view());
  };

  const HIGHLIGHTED_LINE_CLASSNAME = 'highlighted-line';
  const RESOURCE_DETAIL_CONTAINER_CLASSNAME = 'resource-detail-container';
  const TEXT = document.TEXT_NODE;
  const ELE  = document.ELEMENT_NODE;
  this._span = document.createElement('span');
  this._span.textContent = ' ';
  this._line_count = 0;
  this._line_found = false;
  this._target_line = 0;
  this._root_ele = null;
  this._tops = [];

  this._highlight_line = function(ele)
  {
    const CR = "\r";
    const LF = "\n";
    var child = ele.firstChild;
    while (child && !this._line_found)
    {
      if (child.nodeType == ELE)
      {
        this._highlight_line(child);
      }
      else if (child.nodeType == TEXT)
      {
        var value = child.nodeValue;
        for (var pos = 0, len = value.length; pos < len; pos++)
        {
          var c = value.charAt(pos);
          // Linefeed recognition will not support Acorn BBC spooled text output
          if ((c == CR ) || (c == LF))
          {
            this._line_count++;
            if (this._line_count == this._target_line)
            {
              var target_pos = child.splitText(pos);
              child.parentNode.insertBefore(this._span, target_pos);
              this._tops.push(this._span.getBoundingClientRect().top);
              child.parentNode.removeChild(this._span);
              child.parentNode.normalize();
              if (this._tops.length < 2)
              {
                this._target_line+=1;
              }
              else
              {
                var scroll_container = ele;
                var container_top = scroll_container.getBoundingClientRect().top;
                var delta = this._tops[1] - this._tops[0];
                var scroll_top = scroll_container.scrollTop;
                ele.addClass(HIGHLIGHTED_LINE_CLASSNAME);
                ele.style.cssText =
                  "background-size: 100% " + delta + "px;" +
                  "background-position: 0 " +
                    (this._tops[0] - container_top + scroll_top) + "px;";

                var scroll_position = scroll_top + this._tops[0] - container_top;
                if (scroll_position <= this._root_ele.parentNode.clientHeight)
                {
                  scroll_position-=64;
                }
                this._root_ele.scrollTop = scroll_position;
                this._line_found = true;
                return;
              }
            }
            if ((c == CR) && (value.charAt(pos+1) == LF))
            {
              pos++;
            }
          }
        }
      }
      child = child && child.nextSibling;
    }
  }

  this.clear_line_highlight = function(container)
  {
    // reset all properties
    this._line_count = 0;
    this._line_found = false;
    this._target_line = 0;
    this._tops = [];
    var _ele = container.querySelectorAll('.'+HIGHLIGHTED_LINE_CLASSNAME)[0];
    if (_ele)
    {
      _ele.removeClass(HIGHLIGHTED_LINE_CLASSNAME)
    }
  }

  this.go_to_line = function(container, data)
  {
		if (!data || !(data.lines && data.lines.length)) return;
    this._root_ele = container.getElementsByClassName(RESOURCE_DETAIL_CONTAINER_CLASSNAME)[0];
    if (this._root_ele)
    {
      this.clear_line_highlight(this._root_ele)
      this._target_line = parseInt(data.lines[0]);
      this._highlight_line(this._root_ele);
    }
  }

	this.on_resource_data_bound = function(type, data)
	{
		var id = data[0];
		var resource = this._service.get_resource(id);
		if(resource)
		{
			resource.data = new cls.ResourceManager["1.0"].ResourceData( data );
		}
		return resource;
	}.bind(this);

  this._show_resource_by_instance = function(resource)
  {
      this.resource = resource;
      if (resource && !resource.data)
        resource.fetch_data(cls.ResourceDetailView.instance.update.bind(cls.ResourceDetailView.instance));
  }

  this._show_resource_by_id = function(id)
  {
    var resource = this._service.get_resource(id);
    this._show_resource_by_instance(resource);
  }

  this._show_resource_url = function(url)
  {
    var resource = this._service.get_resource_for_url(url);
    if (resource)
      this._show_resource_by_instance(resource);
    else
      new cls.ResourceRequest(url, this.show_resource.bind(this), this.data);
  }

  this.show_resource = function(resource, data)
  {
    this.data = data;
    this.resource = resource;

    if (resource instanceof cls.ResourceInfo)
      this._show_resource_by_instance(resource);
    else if (resource==Number(resource))
      this._show_resource_by_id(resource);
    else if (resource==String(resource))
      this._show_resource_url(resource);

    this.update();
    window.UI.instance.show_view( window.views.resource_detail_view.id );
  }

  //  WIP
  this.show_resource_group = function(resourceGroup)
	{
    return;

		this.resources = [];
		for( var i=0; i<group.ids.length; i++)
		{
			var id = group.ids[i];
			var resource = this._service.get_resource(id);
			if (resource)
			{
				this.resources.push( resource );
				if (!resource.data)
				{
					var responseType = cls.ResourceUtil.type_to_content_mode(resource.type);
					this._service.fetch_resource_data( this.on_resource_data_bound, id, responseType );
				}
			}
		}
		this.update();
	}

  this.init(id, name, container_class, html, default_handler);
};

cls.ResourceDetailView.create_ui_widgets = function()
{
  new ToolbarConfig(
  {
    view:'resource_detail_view',
    groups:
    [
      {
        type: UI.TYPE_INPUT,
        items:
        [
          {
            handler: "resource-text-search",
            shortcuts: "resource-text-search",
            title: ui_strings.S_SEARCH_INPUT_TOOLTIP,
            label: ui_strings.S_INPUT_DEFAULT_TEXT_SEARCH
          }
        ]
      }
    ]
  });

  var text_search = window.views.resource_detail_view.text_search = new TextSearch();

  window.eventHandlers.input["resource-text-search"] = function(event, target)
  {
    text_search.searchDelayed(target.value);
  };

  ActionBroker.
    get_instance().
    get_global_handler().
      register_shortcut_listener("resource-text-search", cls.Helpers.shortcut_search_cb.bind(text_search));

  var on_view_created = function(msg)
  {
    if (msg.id === "resource_detail_view")
    {
      var scroll_container = msg.container.querySelector(".request-details");
      if (!scroll_container)
        scroll_container = msg.container.querySelector(".resource-detail-container");

      if (scroll_container)
      {
        text_search.setContainer(scroll_container);
        text_search.setFormInput(
          views.resource_detail_view.getToolbarControl(msg.container, "resource-text-search")
        );
      }
    }
  }

  var on_view_destroyed = function(msg)
  {
    if (msg.id == "resource_detail_view")
      text_search.cleanup();
  }

  window.messages.addListener("view-created", on_view_created);
  window.messages.addListener("view-destroyed", on_view_destroyed);
}

cls.ResourceDetailView.prototype = ViewBase;

<|endoftext|>


<commit_before>/*jshint esversion: 6 */
// Load required libraries
'use strict';
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const dynamodb = new AWS.DynamoDB.DocumentClient();
const geoip = require('geoip-lite');
// Create a unique ID to describe this item in DynamoDB
function makeId() {
  let text = '';
  const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for (var i = 0; i < 64; i++)
    text += possible.charAt(Math.floor(Math.random() * possible.length));

  return text;
}

exports.handler = (event, context, callback) => {
  // Look up the IP address of the client and get the coordinates
  const ip = event.sourceIP.split(',', 1)[0]
  console.log('Looking up IP ' + ip)
  const geo = geoip.lookup(ip);
  console.log('Location is ' + geo.ll)
  // Get ID for the item
  let id = makeId();
  // Set the current time and the time when the item should expire
  const currentTime = Math.floor(new Date());
  const currentTimePlusTwentyFourHours = (Math.floor(new Date())) + 86400;
  // Sets the parameters for writing to DynamoDB
  const params = {
    TableName: 'impact-map',
    Item: {
      'Id': id,
      'Added': currentTime,
      'Expire': currentTimePlusTwentyFourHours,
      'Coordinates': geo.ll,
      'Action': event.action
    },
  };

  // Creates the item
  dynamodb.put(params, function(err, data) {
    if (err) {
      console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2)); // Handles error in console.
      // Return an error message back to the user
      callback('Entry was not successful');
    } else {
      console.log("Added item:", JSON.stringify(data, null, 2));
      // Return a success message back to the client
      callback(null, 'Added item');
    }
  });
};
<commit_msg>Fix indents<commit_after>/*jshint esversion: 6 */
// Load required libraries
'use strict';
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const dynamodb = new AWS.DynamoDB.DocumentClient();
const geoip = require('geoip-lite');
// Create a unique ID to describe this item in DynamoDB
function makeId() {
	let text = '';
	const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

	for (var i = 0; i < 64; i++)
		text += possible.charAt(Math.floor(Math.random() * possible.length));

	return text;
}

exports.handler = (event, context, callback) => {
	// Look up the IP address of the client and get the coordinates
	const ip = event.sourceIP.split(',', 1)[0];
	console.log('Looking up IP ' + ip);
	const geo = geoip.lookup(ip);
	console.log('Location is ' + geo.ll);
	// Get ID for the item
	let id = makeId();
	// Set the current time and the time when the item should expire
	const currentTime = Math.floor(new Date());
	const currentTimePlusTwentyFourHours = (Math.floor(new Date())) + 86400;
	// Sets the parameters for writing to DynamoDB
	const params = {
		TableName: 'impact-map',
		Item: {
			'Id': id,
			'Added': currentTime,
			'Expire': currentTimePlusTwentyFourHours,
			'Coordinates': geo.ll,
			'Action': event.action
		},
	};

	// Creates the item
	dynamodb.put(params, function(err, data) {
		if (err) {
			console.error('Unable to add item. Error JSON:', JSON.stringify(err, null, 2)); // Handles error in console.
			// Return an error message back to the user
			callback('Entry was not successful');
		} else {
			console.log('Added item:', JSON.stringify(data, null, 2));
			// Return a success message back to the client
			callback(null, 'Added item');
		}
	});
};
<|endoftext|>


<commit_before>import _ from 'lodash'
import dl from 'datalib'

const calculalateX = x => {
	const midway = 89
	const diff = x - midway
	return midway - diff
}

const calculalateY = y => {
	const midway = 42.5
	const diff = y - midway
	return midway - diff
}

const calculateDistance = (x, y) => Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)).toFixed(2)

const getLatestDate = (rows) => {
	const sorted = rows.sort((a, b) => (+a.gameDate) - (+b.gameDate))
	const str = sorted[sorted.length - 1].gameDate
	const year = +str.substring(0, 4)
	const month = +str.substring(4, 6) - 1
	const day = +str.substring(6, 8)

	const d = new Date(year, month, day)
	const dateString = d.toDateString()
	const split = dateString.split(' ')
	const output = `${split[1]}. ${+split[2]}`
	return output
}

const clean = (data) => {
	// the row is column definitions, so must get season from second row
	const season = data[0].season
	return _.filter(data, d => d.season === season)
}

const createShotObj = (datum) => {
	// everything we (might) need
	const season = datum.season
	const gameDate = datum.gamedate
	const teamLocation = datum['team-location']
	const teamNickname = datum['team-nickname']
	const opponentLocation = datum['opponent-location']
	const opponentNickname = datum['opponent-nickname']
	const home = datum['home-away'] === 'home'
	const period = +datum.period
	const time = datum.time
	const player = datum.player
	const x = calculalateX(datum['player-x'])
	const y = calculalateY(datum['player-y'])
	const powerPlay = datum.strength.toLowerCase() !== 'even'
	const distance = +calculateDistance(x, y)
	const made = datum.event.toLowerCase().indexOf('shot') < 0

	return {
		season,
		gameDate,
		teamLocation,
		teamNickname,
		opponentLocation,
		opponentNickname,
		home,
		period,
		time,
		player,
		x,
		y,
		powerPlay,
		made,
		distance,
	}
}

const transform = ({ values }) => {
	if (values.length) {
		const rows = clean(values).map(createShotObj)
		const types = dl.type.inferAll([rows[0]])
		return { rows, types }
	}
	return { rows: [], types: {} }
}

const hed = ({ rows, filters }) => {
	if (rows.length) {
		// get season
		const seasonStr = rows[0].season.toString()

		// if more than one player, show team name
		const who = filters.player ? filters.player : filters.teamNickname
		const when = `${seasonStr.substring(0, 4)}-${seasonStr.substring(4, 6)}`

		return `${who} ${when}`
	}

	return ''
}

const subhed = ({ rows }) => {
	if (rows.length) {
		const date = getLatestDate(rows)
		return `All shots through ${date}`
	}

	return ''
}

const trimData = (data) => ({
	...data,
	rows: data.rows.map(row =>
		_.pick(row, [
			'gameDate',
			'x',
			'y',
			'made',
		])),
})

export default {
	transform,
	hed,
	subhed,
	trimData,
}
<commit_msg>hockey subhed scenarios<commit_after>import _ from 'lodash'
import dl from 'datalib'

const calculalateX = x => {
	const midway = 89
	const diff = x - midway
	return midway - diff
}

const calculalateY = y => {
	const midway = 42.5
	const diff = y - midway
	return midway - diff
}

const calculateDistance = (x, y) => Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)).toFixed(2)

const getLatestDate = (rows) => {
	const sorted = rows.sort((a, b) => (+a.gameDate) - (+b.gameDate))
	const str = sorted[sorted.length - 1].gameDate
	const year = +str.substring(0, 4)
	const month = +str.substring(4, 6) - 1
	const day = +str.substring(6, 8)

	const d = new Date(year, month, day)
	const dateString = d.toDateString()
	const split = dateString.split(' ')
	const output = `${split[1]}. ${+split[2]}`
	return output
}

const clean = (data) => {
	// the row is column definitions, so must get season from second row
	const season = data[0].season
	return _.filter(data, d => d.season === season)
}

const createShotObj = (datum) => {
	// everything we (might) need
	const season = datum.season
	const gameDate = datum.gamedate
	const teamLocation = datum['team-location']
	const teamNickname = datum['team-nickname']
	const opponentLocation = datum['opponent-location']
	const opponentNickname = datum['opponent-nickname']
	const home = datum['home-away'] === 'home'
	const period = +datum.period
	const time = datum.time
	const player = datum.player
	const x = calculalateX(datum['player-x'])
	const y = calculalateY(datum['player-y'])
	const powerPlay = datum.strength.toLowerCase() !== 'even'
	const distance = +calculateDistance(x, y)
	const made = datum.event.toLowerCase().indexOf('shot') < 0

	return {
		season,
		gameDate,
		teamLocation,
		teamNickname,
		opponentLocation,
		opponentNickname,
		home,
		period,
		time,
		player,
		x,
		y,
		powerPlay,
		made,
		distance,
	}
}

const transform = ({ values }) => {
	if (values.length) {
		const rows = clean(values).map(createShotObj)
		const types = dl.type.inferAll([rows[0]])
		return { rows, types }
	}
	return { rows: [], types: {} }
}

const hed = ({ rows, filters }) => {
	if (rows.length) {
		// get season
		const seasonStr = rows[0].season.toString()

		// if more than one player, show team name
		const who = filters.player ? filters.player : filters.teamNickname
		const when = `${seasonStr.substring(0, 4)}-${seasonStr.substring(4, 6)}`

		return `${who} ${when}`
	}

	return ''
}

const subhed = ({ rows, filters }) => {
	const filterValue = {
		home: v => v ? 'at home' : 'on the road',
		powerPlay: v => v ? 'on a power play' : 'on even strength',
		opponentNickname: v => `against the ${v}`,
	}

	if (rows.length) {
		const date = getLatestDate(rows)

		const keys = Object.keys(filters)
		const result = keys.reduce((previous, current) => {
			if (current !== 'player' && current !== 'teamNickname') {
				console.log(current)
				const val = filters[current]
				const subhedVal = filterValue[current](val)
				return `${previous} ${subhedVal}`
			}
			return previous
		}, 'All shots')

		return `${result} through ${date}`
	}

	return ''
}

const trimData = (data) => ({
	...data,
	rows: data.rows.map(row =>
		_.pick(row, [
			'gameDate',
			'x',
			'y',
			'made',
		])),
})

export default {
	transform,
	hed,
	subhed,
	trimData,
}
<|endoftext|>


<commit_before><commit_msg>Status with callback<commit_after><|endoftext|>


<commit_before>function _debug(msg){
    DEBUG && console.log(msg);
}

function callBotAPI(newmsg,callback,sendto,jumpback) {
    //jsonp proxy
    var url = 'https://cuhk.me/wx/jsonp.php';
    $.ajax({
        'url': url,
        'data': {msg: encodeURIComponent(newmsg), s: session_id} ,
        'dataType': 'jsonp',
        'timeout': 60000,
        'success': function(response) {
            if (typeof(response)=='undefined') {
                _debug("no response error");
                ans = '太累了，我想休息一下，zzz～';
                callback(ans,sendto,jumpback,'err');
            } else {
                ans = response.text;
                callback(ans,sendto,jumpback);
            }
        },
        'error': function() {
            _debug("ajax error occured");
            ans = '太累了，我想休息一下，zzz～';
            callback(ans,sendto,jumpback,'err');
        }
    });
}

function sendmsg_callback(ans,sendto,jumpback,flag){
    _debug("bot resp with: " + ans);
    sendto && $(sendto).click();
    $('#editArea').text(ans);
    $('.chatSend').click();
    $(jumpback).click();
    var name = $(sendto).find(".nickname_text").text();
    setTimeout(function(){
        $(sendto).removeClass('read'); //clear read mark
    }, (typeof(flag)!=='undefined' && flag=='err') ? 60*1000 : 100 ); // dirty: prevent extreme timing case
    _debug('msg sent to: '+name);
}

function installbot(chats){
    //add bot notes
    for (i=0;i<chats.length;i++) {
        var bot = document.createElement('div');
        bot.className='bot';
        chats[i].appendChild(bot);
    }

    //listen on bot click event
    $(chats).children('.bot').click(function(e){
        e.stopPropagation();
        $(this).toggleClass('active');
        typeof(observer) !== 'undefined' && observer.disconnect();
    });

    //add drag drop event to bot div
    jQuery.event.props.push('dataTransfer');
    $(chats).parent().on({
        dragenter: function(e) {
            $(this).addClass('over');
        },
        dragover: function(e) {
            e.preventDefault();
        },
        dragleave: function(e) {
            $(this).removeClass('over');
        },
        drop: function() {
            $(this).find('.bot').toggleClass('active');
        },
    });

    _debug("installed "+chats.length.toString()+" bots");
}

function buildbothome() {
    //add bot home
    $('.header').append([
    '
',
        '',
        '',
            '
快把我拖到聊天列表上
',
            '
点击我可以 暂停/恢复
',
        '',
        '',
    '
'].join(''));

    //show tooltip for 10s
    $('img.botico').load(function(){
        $('#bot-wrapper span').show();
        setTimeout(function(){
            $('#bot-wrapper span').hide();
        },10*1000);
    });

    //clear tooltip on mousedown
    $('.bot-home').mousedown(function(){
        $('#bot-wrapper span').hide();
    });

    //listen on bot-home click event
    $('.bot-home').click(function(){
        $('.bot-home').toggleClass('paused');
    });

    //listen drag event
    jQuery.event.props.push('dataTransfer');
    $('.bot-home').on({
        dragstart: function() {
            $(this).css('opacity', '0.5');
            $('.chat_item').css('pointer-events','none');
        },
        dragend: function() {
            $(this).css('opacity', '1');
            $('.chat_item').css('pointer-events','');
            $('.chat_item').removeClass('over');
        },
    });
    _debug("bot home constructed");
}

function botinit(){
    $(document).ready(function(){
        //init bot-home
        buildbothome();
        //init bot divs
        var bots = $(['.chat_item',
            ':not([data-cm=\'{"type":"chat","username":"newsapp"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"filehelper"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"fmessage"}\'])'].join(''))
        installbot(bots);
        _debug(bots.length.toString()+" bots initiated");
        //set chat list update listener
        setupdater();
        //identify user by cookie
        C = function(k){return encodeURIComponent(document.cookie.match(k+'=([^;]*)')[1])};
        session_id = C('xsid');
        nm = encodeURIComponent($('.header .nickName').text());
    });
}

function botstart(interval){
    interval = typeof interval !== 'undefined' ? interval : 30;
    setInterval(chatbot,interval*1000);
    _debug("started with interval: "+interval.toString()+"s");
}

function botupdate(){
    uninstalled = $(['.chat_item',
            ':not([data-cm=\'{"type":"chat","username":"newsapp"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"filehelper"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"fmessage"}\'])',
            ':not(:has(".bot"))'].join(''));
    uninstalled.length && installbot(uninstalled);
}

function setupdater() {
    updater = new MutationObserver(function(mutations) {
        botupdate();
    });
    updater.observe($('.chat_list.scroll-content').children('.ng-scope')[0], { childList: true});
    _debug('updater set');
}

function chatbot() {
    //if paused
    if ( $('.bot-home').hasClass('paused') ) return;
    //if no bot-took-overed
    if ( $('.bot.active').length == 0 )  return;

    //record current chat
    var activechat = $('.chat_item.active');

    //reply in current chat window
    if ( $('.chat_item.active:has(".bot.active")').length ) {
        var lastchat = $('.message').last();
            if ($(lastchat).not('.read').hasClass('.you')) {  //has read or self msg
                var name = $('.message .avatar').attr('title');
                var newmsg = $(lastchat).text();
                _debug("msg from: " + name);
                if (newmsg) {
                    _debug("msg content: " + newmsg);
                    $(lastchat).addClass('read'); //add read mark
                    callBotAPI(newmsg,sendmsg_callback,activechat);
                } else {
                    _debug("no msg found");
                }
            }
    }

    //reply for red dotted item
    $('.web_wechat_reddot, .unreadDotS:visible').each(function()
    {
        var receiver = $(this).parent().parent();
        is_active = $(receiver).find(".bot").hasClass("active");
        if (!is_active) return;
        if ($(receiver).hasClass('read')) return;  //has read, wait for response
        var name = $(receiver).find(".nickname_text").text();
        _debug("msg from: " + name);
        var newmsg = $(receiver).find('.msg').text();
        if (newmsg) {
            _debug("msg content: " + newmsg);
            $(receiver).addClass('read'); // add read mark
            callBotAPI(newmsg,sendmsg_callback,$(receiver),$(activechat));
        } else {
            _debug("no msg found");
        }
    });
}

delete console;
DEBUG = true;
VERSION = "3.0.1";
botinit();
botstart(runtimeGlobal.interval);
botupdate();
<commit_msg>auto replier bug fix<commit_after>function _debug(msg){
    DEBUG && console.log(msg);
}

function callBotAPI(newmsg,callback,sendto,jumpback) {
    //jsonp proxy
    var url = 'https://cuhk.me/wx/jsonp.php';
    $.ajax({
        'url': url,
        'data': {msg: encodeURIComponent(newmsg), s: session_id} ,
        'dataType': 'jsonp',
        'timeout': 60000,
        'success': function(response) {
            if (typeof(response)=='undefined') {
                _debug("no response error");
                ans = '太累了，我想休息一下，zzz～';
                callback(ans,sendto,jumpback,'err');
            } else {
                ans = response.text;
                callback(ans,sendto,jumpback);
            }
        },
        'error': function() {
            _debug("ajax error occured");
            ans = '太累了，我想休息一下，zzz～';
            callback(ans,sendto,jumpback,'err');
        }
    });
}

function sendmsg_callback(ans,sendto,jumpback,flag){
    _debug("bot resp with: " + ans);
    sendto && $(sendto).click();
    $('#editArea').text(ans);
    $('.chatSend').click();
    $(jumpback).click();
    var name = $(sendto).find(".nickname_text").text();
    setTimeout(function(){
        $(sendto).removeClass('read'); //clear read mark
    }, (typeof(flag)!=='undefined' && flag=='err') ? 60*1000 : 100 ); // dirty: prevent extreme timing case
    _debug('msg sent to: '+name);
}

function installbot(chats){
    //add bot notes
    for (i=0;i<chats.length;i++) {
        var bot = document.createElement('div');
        bot.className='bot';
        chats[i].appendChild(bot);
    }

    //listen on bot click event
    $(chats).children('.bot').click(function(e){
        e.stopPropagation();
        $(this).toggleClass('active');
        typeof(observer) !== 'undefined' && observer.disconnect();
    });

    //add drag drop event to bot div
    jQuery.event.props.push('dataTransfer');
    $(chats).parent().on({
        dragenter: function(e) {
            $(this).addClass('over');
        },
        dragover: function(e) {
            e.preventDefault();
        },
        dragleave: function(e) {
            $(this).removeClass('over');
        },
        drop: function() {
            $(this).find('.bot').toggleClass('active');
        },
    });

    _debug("installed "+chats.length.toString()+" bots");
}

function buildbothome() {
    //add bot home
    $('.header').append([
    '
',
        '',
        '',
            '
快把我拖到聊天列表上
',
            '
点击我可以 暂停/恢复
',
        '',
        '',
    '
'].join(''));

    //show tooltip for 10s
    $('img.botico').load(function(){
        $('#bot-wrapper span').show();
        setTimeout(function(){
            $('#bot-wrapper span').hide();
        },10*1000);
    });

    //clear tooltip on mousedown
    $('.bot-home').mousedown(function(){
        $('#bot-wrapper span').hide();
    });

    //listen on bot-home click event
    $('.bot-home').click(function(){
        $('.bot-home').toggleClass('paused');
    });

    //listen drag event
    jQuery.event.props.push('dataTransfer');
    $('.bot-home').on({
        dragstart: function() {
            $(this).css('opacity', '0.5');
            $('.chat_item').css('pointer-events','none');
        },
        dragend: function() {
            $(this).css('opacity', '1');
            $('.chat_item').css('pointer-events','');
            $('.chat_item').removeClass('over');
        },
    });
    _debug("bot home constructed");
}

function botinit(){
    $(document).ready(function(){
        //init bot-home
        buildbothome();
        //init bot divs
        var bots = $(['.chat_item',
            ':not([data-cm=\'{"type":"chat","username":"newsapp"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"filehelper"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"fmessage"}\'])'].join(''))
        installbot(bots);
        _debug(bots.length.toString()+" bots initiated");
        //set chat list update listener
        setupdater();
        //identify user by cookie
        C = function(k){return encodeURIComponent(document.cookie.match(k+'=([^;]*)')[1])};
        session_id = C('xsid');
        nm = encodeURIComponent($('.header .nickName').text());
    });
}

function botstart(interval){
    interval = typeof interval !== 'undefined' ? interval : 30;
    setInterval(chatbot,interval*1000);
    _debug("started with interval: "+interval.toString()+"s");
}

function botupdate(){
    uninstalled = $(['.chat_item',
            ':not([data-cm=\'{"type":"chat","username":"newsapp"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"filehelper"}\'])',
            ':not([data-cm=\'{"type":"chat","username":"fmessage"}\'])',
            ':not(:has(".bot"))'].join(''));
    uninstalled.length && installbot(uninstalled);
}

function setupdater() {
    updater = new MutationObserver(function(mutations) {
        botupdate();
    });
    updater.observe($('.chat_list.scroll-content').children('.ng-scope')[0], { childList: true});
    _debug('updater set');
}

function chatbot() {
    //if paused
    if ( $('.bot-home').hasClass('paused') ) return;
    //if no bot-took-overed
    if ( $('.bot.active').length == 0 )  return;

    //record current chat
    var activechat = $('.chat_item.active');

    //reply in current chat window
    if ( $('.chat_item.active').parent(':has(".bot.active")').length ) {
        var lastchat = $('.message').last();
            if ($(lastchat).not('.read').hasClass('.you')) {  //has read or self msg
                var name = $('.message .avatar').attr('title');
                var newmsg = $(lastchat).text();
                _debug("msg from: " + name);
                if (newmsg) {
                    _debug("msg content: " + newmsg);
                    $(lastchat).addClass('read'); //add read mark
                    callBotAPI(newmsg,sendmsg_callback,activechat);
                } else {
                    _debug("no msg found");
                }
            }
    }

    //reply for red dotted item
    $('.web_wechat_reddot, .web_wechat_reddot_middle').each(function()
    {
        var receiver = $(this).parent().parent();
        is_active = $(receiver).parent().find(".bot").hasClass("active");
        if (!is_active) return;
        if ($(receiver).hasClass('read')) return;  //has read, wait for response
        var name = $(receiver).find(".nickname_text").text();
        _debug("msg from: " + name);
        var newmsg = $(receiver).find('.msg').text();
        if (newmsg) {
            _debug("msg content: " + newmsg);
            $(receiver).addClass('read'); // add read mark
            callBotAPI(newmsg,sendmsg_callback,$(receiver),$(activechat));
        } else {
            _debug("no msg found");
        }
    });
}

delete console;
DEBUG = true;
VERSION = "3.0.2";
botinit();
botstart(runtimeGlobal.interval);
botupdate();
<|endoftext|>


<commit_before>import React from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import {
  BOX_SHADOW_1,
  FONT_COLOR,
  FONT_COLOR_LIGHT
} from '../util/constants'

const Outer = styled.div`
  position: sticky;
  top: 0;
  height: 100vh;

  display: flex;
  flex-direction: column;
  overflow-y: scroll;

  border-right: 1px solid #d1d2d3;
  overflow: hidden;
`

const Header = styled.div`
  min-height: 150px;

  position: relative;
  position: sticky;
  top: 0;

  display: flex;
  overflow: hidden;

  background: #1a78c2;
  box-shadow: ${BOX_SHADOW_1};

  &::before,
  &::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
  }

  &::before {
    background: #6cbaf7;
    opacity: .8;
    transform: rotate(-45deg) scaleX(1.5);
  }

  &::after {
    background: #000202;
    opacity: .3;
    transform: rotate(45deg) scaleY(1.5);
  }
`

const Profile = styled.div`
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  text-align: center;

  flex: 1;
  padding: 16px;

  color: #fff;

  > img,
  > div {
    display: block;
    margin: auto;

    max-width: 100px;
    margin-bottom: 12px;
    border-radius: 50%;
  }

  > div {
    width: 64px;
    height: 64px;
    display: flex;
    justify-content: center;
    align-items: center;

    background: rgba(255, 255, 255, .5);
    text-transform: uppercase;
  }

  a {
    color: #fff;
    text-decoration: none;
  }
`

const Main = styled.div`
  padding: 16px;
  flex: 1;
  overflow: scroll;
`

const Section = styled.div`
  & + & {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid #d1d2d3;
  }
`

const SectionTitle = styled.div`
  text-transform: uppercase;
  margin-bottom: 8px;
  font-family: $font-secondary;
  letter-spacing: 0.1rem;
`

const itemStyle = `
  display: block;
  margin-left: 12px;

  text-decoration: none;
  cursor: pointer;
  color: ${FONT_COLOR_LIGHT};
  font-size: 14px;
  transition: color .2s ease-in;

  &:hover {
    color: ${FONT_COLOR};
  }
`

const ItemLink = styled(Link)`${itemStyle}`
const Item = styled.div`${itemStyle}`

const Drawer = ({ actions, subreddits, me }) => (
  <Outer>

      <Profile>
        {me.subreddit && (

        )}
        {!me.subreddit && (

            {me.name.substr(0, 1)}

        )}
        <Link to='/me'>/u/{me.name}</Link>
      </Profile>

        <SectionTitle>My subs</SectionTitle>

        <ItemLink to='/'>Frontpage</ItemLink>

        {subreddits.map(r => (
          <ItemLink
            key={r.id}
            to={`/r/${r.display_name}`}
          >
            {r.display_name_prefixed}
          </ItemLink>
        ))}

        <SectionTitle>Settings</SectionTitle>
        <ItemLink to='/customize'>Customize Reddix</ItemLink>

        <Item onClick={() => actions.logoutRequest()}>Log out</Item>

  </Outer>
)

export default Drawer
<commit_msg>Drawer layout box shadow<commit_after>import React from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import {
  BOX_SHADOW_1,
  FONT_COLOR,
  FONT_COLOR_LIGHT
} from '../util/constants'

const Outer = styled.div`
  position: sticky;
  top: 0;
  height: 100vh;

  display: flex;
  flex-direction: column;
  overflow-y: scroll;

  overflow: hidden;
  box-shadow: ${BOX_SHADOW_1};
`

const Header = styled.div`
  min-height: 150px;

  position: relative;
  position: sticky;
  top: 0;

  display: flex;
  overflow: hidden;

  background: #1a78c2;
  box-shadow: ${BOX_SHADOW_1};

  &::before,
  &::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
  }

  &::before {
    background: #6cbaf7;
    opacity: .8;
    transform: rotate(-45deg) scaleX(1.5);
  }

  &::after {
    background: #000202;
    opacity: .3;
    transform: rotate(45deg) scaleY(1.5);
  }
`

const Profile = styled.div`
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  text-align: center;

  flex: 1;
  padding: 16px;

  color: #fff;

  > img,
  > div {
    display: block;
    margin: auto;

    max-width: 100px;
    margin-bottom: 12px;
    border-radius: 50%;
  }

  > div {
    width: 64px;
    height: 64px;
    display: flex;
    justify-content: center;
    align-items: center;

    background: rgba(255, 255, 255, .5);
    text-transform: uppercase;
  }

  a {
    color: #fff;
    text-decoration: none;
  }
`

const Main = styled.div`
  padding: 16px;
  flex: 1;
  overflow: scroll;
`

const Section = styled.div`
  & + & {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid #d1d2d3;
  }
`

const SectionTitle = styled.div`
  text-transform: uppercase;
  margin-bottom: 8px;
  font-family: $font-secondary;
  letter-spacing: 0.1rem;
`

const itemStyle = `
  display: block;
  margin-left: 12px;

  text-decoration: none;
  cursor: pointer;
  color: ${FONT_COLOR_LIGHT};
  font-size: 14px;
  transition: color .2s ease-in;

  &:hover {
    color: ${FONT_COLOR};
  }
`

const ItemLink = styled(Link)`${itemStyle}`
const Item = styled.div`${itemStyle}`

const Drawer = ({ actions, subreddits, me }) => (
  <Outer>

      <Profile>
        {me.subreddit && (

        )}
        {!me.subreddit && (

            {me.name.substr(0, 1)}

        )}
        <Link to='/me'>/u/{me.name}</Link>
      </Profile>

        <SectionTitle>My subs</SectionTitle>

        <ItemLink to='/'>Frontpage</ItemLink>

        {subreddits.map(r => (
          <ItemLink
            key={r.id}
            to={`/r/${r.display_name}`}
          >
            {r.display_name_prefixed}
          </ItemLink>
        ))}

        <SectionTitle>Settings</SectionTitle>
        <ItemLink to='/customize'>Customize Reddix</ItemLink>

        <Item onClick={() => actions.logoutRequest()}>Log out</Item>

  </Outer>
)

export default Drawer
<|endoftext|>