<commit_before>import React from 'react';
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  Animated,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

const CustomTabBar = React.createClass({
  tabIcons: [],

  propTypes: {
    goToPage: React.PropTypes.func,
    activeTab: React.PropTypes.number,
    tabs: React.PropTypes.array,
  },

  componentDidMount() {
    this._listener = this.props.scrollValue.addListener(this.setAnimationValue);
  },

  setAnimationValue({ value, }) {
    this.tabIcons.forEach((icon, i) => {
      const progress = Math.min(1, Math.abs(value - i));
      icon.setNativeProps({
        style: {
          color: this.iconColor(progress),
        },
      });
    });
  },

  //color between rgb(59,89,152) and rgb(204,204,204)
  iconColor(progress) {
    const red = 59 + (204 - 59) * progress;
    const green = 89 + (204 - 89) * progress;
    const blue = 152 + (204 - 152) * progress;
    return `rgb(${red}, ${green}, ${blue})`;
  },

  render() {
    const containerWidth = this.props.containerWidth;
    const numberOfTabs = this.props.tabs.length;
    const tabUnderlineStyle = {
      position: 'absolute',
      width: containerWidth / numberOfTabs,
      height: 3,
      backgroundColor: 'navy',
      bottom: 0,
    };

    const offset = containerWidth * 0.1;
    const left = this.props.scrollValue.interpolate({
      inputRange: [0, 1, ], outputRange: [0,  containerWidth / numberOfTabs, ],
    });
    return <View style={[styles.tabs, this.props.style, ]}>
      {this.props.tabs.map((tab, i) => {
        return <TouchableOpacity key={tab} onPress={() => this.props.goToPage(i)} style={styles.tab}>
          <Icon
            name={tab}
            size={30}
            ref={(icon) => { this.tabIcons[i] = icon; }}
          />
        </TouchableOpacity>;
      })}
      <Animated.View style={[tabUnderlineStyle, { left, }, this.props.underlineStyle, ]} />
    </View>;
  },
});

const styles = StyleSheet.create({
  tab: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: 15,
    paddingBottom: 10,
  },
  tabs: {
    height: 55,
    flexDirection: 'row',
    borderWidth: 1,
    borderTopWidth: 0,
    borderLeftWidth: 0,
    borderRightWidth: 0,
    borderBottomColor: 'rgba(0,0,0,0.05)',
  },
});

export default CustomTabBar;
<commit_msg>Move header separator line from being a border to a 1px view, save 1 px vertical space<commit_after>import React from 'react';
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  Animated,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

const CustomTabBar = React.createClass({
  tabIcons: [],

  propTypes: {
    goToPage: React.PropTypes.func,
    activeTab: React.PropTypes.number,
    tabs: React.PropTypes.array,
  },

  componentDidMount() {
    this._listener = this.props.scrollValue.addListener(this.setAnimationValue);
  },

  setAnimationValue({ value, }) {
    this.tabIcons.forEach((icon, i) => {
      const progress = Math.min(1, Math.abs(value - i));
      icon.setNativeProps({
        style: {
          color: this.iconColor(progress),
        },
      });
    });
  },

  //color between rgb(59,89,152) and rgb(204,204,204)
  iconColor(progress) {
    const red = 59 + (204 - 59) * progress;
    const green = 89 + (204 - 89) * progress;
    const blue = 152 + (204 - 152) * progress;
    return `rgb(${red}, ${green}, ${blue})`;
  },

  render() {
    const containerWidth = this.props.containerWidth;
    const numberOfTabs = this.props.tabs.length;
    const tabUnderlineStyle = {
      position: 'absolute',
      width: containerWidth / numberOfTabs,
      height: 3,
      backgroundColor: 'navy',
      bottom: 0,
    };

    const offset = containerWidth * 0.1;
    const left = this.props.scrollValue.interpolate({
      inputRange: [0, 1, ], outputRange: [0,  containerWidth / numberOfTabs, ],
    });
    return <View style={[styles.tabs, this.props.style, ]}>
      {this.props.tabs.map((tab, i) => {
        return <TouchableOpacity key={tab} onPress={() => this.props.goToPage(i)} style={styles.tab}>
          <Icon
            name={tab}
            size={30}
            ref={(icon) => { this.tabIcons[i] = icon; }}
          />
        </TouchableOpacity>;
      })}
      <View style={{position:'absolute', width:containerWidth, height:1, backgroundColor: 'rgba(0,0,0,0.05)', bottom:0}} />
      <Animated.View style={[tabUnderlineStyle, { left, }, this.props.underlineStyle, ]} />
    </View>;
  },
});

const styles = StyleSheet.create({
  tab: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: 15,
    paddingBottom: 10,
  },
  tabs: {
    height: 55,
    flexDirection: 'row',
  },
});

export default CustomTabBar;
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import cn from '../../utils/cn'
import prism from '../../utils/prism'
import normalizeCode from '../../utils/normalizeCode'
import normalizeHtml from '../../utils/normalizeHtml'
import htmlToPlain from '../../utils/htmlToPlain'
import selectionRange from '../../vendor/selection-range'
import { getIndent, getDeindentLevel } from '../../utils/getIndent'

class Editor extends Component {
  static defaultProps = {
    contentEditable: true,
    language: 'jsx'
  }

  undoStack = []
  undoOffset = 0
  undoTimestamp = 0

  state = {
    html: ''
  }

  onRef = node => {
    this.ref = node
  }

  getPlain = () => {
    if (this._innerHTML === this.ref.innerHTML) {
      return this._plain
    }

    const plain = htmlToPlain(normalizeHtml(this.ref.innerHTML))

    this._plain = plain
    this._innerHTML = this.ref.innerHTML

    return this._plain
  }

  recordChange = (plain, selection) => {
    if (plain === this.undoStack[this.undoStack.length - 1]) {
      return
    }

    if (this.undoOffset > 0) {
      this.undoStack = this.undoStack.slice(0, -this.undoOffset)
      this.undoOffset = 0
    }

    const timestamp = Date.now()
    const record = { plain, selection }

    // Overwrite last record if threshold is not crossed
    if (timestamp - this.undoTimestamp < 3000) {
      this.undoStack[this.undoStack.length - 1] = record
    } else {
      this.undoStack.push(record)

      if (this.undoStack.length > 50) {
        this.undoStack.shift()
      }
    }

    this.undoTimestamp = timestamp
  }

  updateContent = plain => {
    this.setState({ html: prism(plain, this.props.language) })

    if (this.props.onChange) {
      this.props.onChange(plain)
    }
  }

  restoreStackState = offset => {
    const { plain, selection } = this.undoStack[this.undoStack.length - 1 - offset]

    this.selection = selection
    this.undoOffset = offset
    this.updateContent(plain)
  }

  undo = () => {
    const offset = this.undoOffset + 1
    if (offset >= this.undoStack.length) {
      return
    }

    this.restoreStackState(offset)
  }

  redo = () => {
    const offset = this.undoOffset - 1
    if (offset < 0) {
      return
    }

    this.restoreStackState(offset)
  }

  onKeyDown = evt => {
    if (this.props.onKeyDown) {
      this.props.onKeyDown(evt)
    }

    if (evt.keyCode === 9 && !this.props.ignoreTabKey) { // Tab Key
      document.execCommand('insertHTML', false, '  ')
      evt.preventDefault()
    } else if (evt.keyCode === 8) { // Backspace Key
      const { start: cursorPos, end: cursorEndPos } = selectionRange(this.ref)
      if (cursorPos !== cursorEndPos) {
        return // Bail on selections
      }

      const deindent = getDeindentLevel(this.getPlain(), cursorPos)
      if (deindent <= 0) {
        return // Bail when deindent level defaults to 0
      }

      // Delete chars `deindent` times
      for (let i = 0; i < deindent; i++) {
        document.execCommand('delete', false)
      }

      evt.preventDefault()
    } else if (evt.keyCode === 13) { // Enter Key
      const { start: cursorPos } = selectionRange(this.ref)
      const indentation = getIndent(this.getPlain(), cursorPos)
      document.execCommand('insertHTML', false, '\n' + indentation)
      evt.preventDefault()
    } else if (
      // Undo / Redo
      evt.keyCode === 90 &&
      evt.metaKey !== evt.ctrlKey &&
      !evt.altKey
    ) {
      if (evt.shiftKey) {
        this.redo()
      } else {
        this.undo()
      }

      evt.preventDefault()
    }
  }

  onKeyUp = evt => {
    if (this.props.onKeyUp) {
      this.props.onKeyUp(evt)
    }
    if (
      evt.keyCode === 91 || // left cmd
      evt.keyCode === 93 || // right cmd
      evt.ctrlKey ||
      evt.metaKey
    ) {
      return
    }

    // Enter key
    if (evt.keyCode === 13) {
      this.undoTimestamp = 0
    }

    this.selection = selectionRange(this.ref)

    if (
      evt.keyCode !== 37 && // left
      evt.keyCode !== 38 && // up
      evt.keyCode !== 39 && // right
      evt.keyCode !== 40 // down
    ) {
      const plain = this.getPlain()

      this.recordChange(plain, this.selection)
      this.updateContent(plain)
    } else {
      this.undoTimestamp = 0
    }
  }

  onClick = evt => {
    if (this.props.onClick) {
      this.props.onClick(evt)
    }
    this.undoTimestamp = 0 // Reset timestamp
    this.selection = selectionRange(this.ref)
  }

  componentWillMount() {
    const html = prism(normalizeCode(this.props.code), this.props.language)
    this.setState({ html })
  }

  componentDidMount() {
    this.recordChange(this.getPlain())
    this.undoTimestamp = 0 // Reset timestamp
  }

  componentWillReceiveProps({ code, language }) {
    if (code !== this.props.code || language !== this.props.language) {
      const html = prism(normalizeCode(code), language)
      this.setState({ html })
    }
  }

  componentDidUpdate() {
    const { selection } = this
    if (selection) {
      selectionRange(this.ref, selection)
    }
  }

  render() {
    const {
      contentEditable,
      className,
      style,
      code, // ignored & unused
      ignoreTabKey, // ignored & unused
      language, // ignored & unused
      ...rest
    } = this.props
    const { html } = this.state

    return (
      <pre
        {...rest}
        ref={this.onRef}
        className={cn('prism-code', className)}
        style={style}
        spellCheck="false"
        contentEditable={contentEditable}
        onKeyDown={contentEditable ? this.onKeyDown : undefined}
        onKeyUp={contentEditable ? this.onKeyUp : undefined}
        onClick={contentEditable ? this.onClick : undefined}
        dangerouslySetInnerHTML={{ __html: html }}
      />
    )
  }
}

export default Editor
<commit_msg>Fix: input chinese bug.<commit_after>import React, { Component } from 'react'
import cn from '../../utils/cn'
import prism from '../../utils/prism'
import normalizeCode from '../../utils/normalizeCode'
import normalizeHtml from '../../utils/normalizeHtml'
import htmlToPlain from '../../utils/htmlToPlain'
import selectionRange from '../../vendor/selection-range'
import { getIndent, getDeindentLevel } from '../../utils/getIndent'

class Editor extends Component {
  static defaultProps = {
    contentEditable: true,
    language: 'jsx'
  }

  undoStack = []
  undoOffset = 0
  undoTimestamp = 0
  compositing = false

  state = {
    html: ''
  }

  onRef = node => {
    this.ref = node
  }

  getPlain = () => {
    if (this._innerHTML === this.ref.innerHTML) {
      return this._plain
    }

    const plain = htmlToPlain(normalizeHtml(this.ref.innerHTML))

    this._plain = plain
    this._innerHTML = this.ref.innerHTML

    return this._plain
  }

  recordChange = (plain, selection) => {
    if (plain === this.undoStack[this.undoStack.length - 1]) {
      return
    }

    if (this.undoOffset > 0) {
      this.undoStack = this.undoStack.slice(0, -this.undoOffset)
      this.undoOffset = 0
    }

    const timestamp = Date.now()
    const record = { plain, selection }

    // Overwrite last record if threshold is not crossed
    if (timestamp - this.undoTimestamp < 3000) {
      this.undoStack[this.undoStack.length - 1] = record
    } else {
      this.undoStack.push(record)

      if (this.undoStack.length > 50) {
        this.undoStack.shift()
      }
    }

    this.undoTimestamp = timestamp
  }

  updateContent = plain => {
    this.setState({ html: prism(plain, this.props.language) })

    if (this.props.onChange) {
      this.props.onChange(plain)
    }
  }

  restoreStackState = offset => {
    const { plain, selection } = this.undoStack[this.undoStack.length - 1 - offset]

    this.selection = selection
    this.undoOffset = offset
    this.updateContent(plain)
  }

  undo = () => {
    const offset = this.undoOffset + 1
    if (offset >= this.undoStack.length) {
      return
    }

    this.restoreStackState(offset)
  }

  redo = () => {
    const offset = this.undoOffset - 1
    if (offset < 0) {
      return
    }

    this.restoreStackState(offset)
  }

  onKeyDown = evt => {
    if (this.props.onKeyDown) {
      this.props.onKeyDown(evt)
    }

    if (evt.keyCode === 9 && !this.props.ignoreTabKey) { // Tab Key
      document.execCommand('insertHTML', false, '  ')
      evt.preventDefault()
    } else if (evt.keyCode === 8) { // Backspace Key
      const { start: cursorPos, end: cursorEndPos } = selectionRange(this.ref)
      if (cursorPos !== cursorEndPos) {
        return // Bail on selections
      }

      const deindent = getDeindentLevel(this.getPlain(), cursorPos)
      if (deindent <= 0) {
        return // Bail when deindent level defaults to 0
      }

      // Delete chars `deindent` times
      for (let i = 0; i < deindent; i++) {
        document.execCommand('delete', false)
      }

      evt.preventDefault()
    } else if (evt.keyCode === 13) { // Enter Key
      const { start: cursorPos } = selectionRange(this.ref)
      const indentation = getIndent(this.getPlain(), cursorPos)
      document.execCommand('insertHTML', false, '\n' + indentation)
      evt.preventDefault()
    } else if (
      // Undo / Redo
      evt.keyCode === 90 &&
      evt.metaKey !== evt.ctrlKey &&
      !evt.altKey
    ) {
      if (evt.shiftKey) {
        this.redo()
      } else {
        this.undo()
      }

      evt.preventDefault()
    }
  }

  onKeyUp = evt => {
    if (this.props.onKeyUp) {
      this.props.onKeyUp(evt)
    }
    if (
      evt.keyCode === 91 || // left cmd
      evt.keyCode === 93 || // right cmd
      evt.ctrlKey ||
      evt.metaKey
    ) {
      return
    }

    // Enter key
    if (evt.keyCode === 13) {
      this.undoTimestamp = 0
    }

    this.selection = selectionRange(this.ref)

    if (
      evt.keyCode !== 37 && // left
      evt.keyCode !== 38 && // up
      evt.keyCode !== 39 && // right
      evt.keyCode !== 40 // down
    ) {
      const plain = this.getPlain()

      this.recordChange(plain, this.selection)
      !this.compositing && this.updateContent(plain);
    } else {
      this.undoTimestamp = 0
    }
  }

  onCompositionStart = evt => {
    if (this.props.onCompositionStart) {
      this.props.onCompositionStart(evt)
    }
    this.compositing = true;
  }

  onCompositionEnd = evt => {
    if (this.props.onCompositionEnd) {
      this.props.onCompositionEnd(evt)
    }
    this.compositing = false;
  }

  onClick = evt => {
    if (this.props.onClick) {
      this.props.onClick(evt)
    }
    this.undoTimestamp = 0 // Reset timestamp
    this.selection = selectionRange(this.ref)
  }

  componentWillMount() {
    const html = prism(normalizeCode(this.props.code), this.props.language)
    this.setState({ html })
  }

  componentDidMount() {
    this.recordChange(this.getPlain())
    this.undoTimestamp = 0 // Reset timestamp
  }

  componentWillReceiveProps({ code, language }) {
    if (code !== this.props.code || language !== this.props.language) {
      const html = prism(normalizeCode(code), language)
      this.setState({ html })
    }
  }

  componentDidUpdate() {
    const { selection } = this
    if (selection) {
      selectionRange(this.ref, selection)
    }
  }

  render() {
    const {
      contentEditable,
      className,
      style,
      code, // ignored & unused
      ignoreTabKey, // ignored & unused
      language, // ignored & unused
      ...rest
    } = this.props
    const { html } = this.state

    return (
      <pre
        {...rest}
        ref={this.onRef}
        className={cn('prism-code', className)}
        style={style}
        spellCheck="false"
        contentEditable={contentEditable}
        onCompositionEnd={contentEditable ? this.onCompositionEnd : undefined}
        onCompositionStart={contentEditable ? this.onCompositionStart : undefined}
        onKeyDown={contentEditable ? this.onKeyDown : undefined}
        onKeyUp={contentEditable ? this.onKeyUp : undefined}
        onClick={contentEditable ? this.onClick : undefined}
        dangerouslySetInnerHTML={{ __html: html }}
      />
    )
  }
}

export default Editor
<|endoftext|>


<commit_before>import React from 'react';
import {
    History
}
from 'react-router';
import HeaderStore from './store';
import HeaderActions from './actions';

export
default React.createClass({

    mixins: [History],

    getInitialState() {
        return {
            maximized: false,
            minimized: false,
            view: false
        };
    },
    componentWillMount() {
        HeaderStore.listen(this.update);
        this.history.listen(this.updatehistory);
    },
    componentWillUnmount() {
        HeaderStore.unlisten(this.update);
        this.history.unlisten(this.updatehistory);
    },
    updatehistory(n, location) {
        if (location.pathname)
            this.setState({
                view: location.pathname.substr(1)
            });
    },
    update() {
        if (this.isMounted()) {
            this.setState({
                maximized: HeaderStore.getState().maximized,
                minimized: HeaderStore.getState().minimized
            });
        }
    },
    render() {
        var headerClass = 'header ' + process.platform + ((this.state.view === 'player') ? ' player' : '');
        return (

Powder Player

                    clear

                    crop_landscape

                    remove

        );
    }
});<commit_msg>Fix header class<commit_after>import React from 'react';
import {
    History
}
from 'react-router';
import HeaderStore from './store';
import HeaderActions from './actions';

export
default React.createClass({

    mixins: [History],

    getInitialState() {
        return {
            maximized: false,
            minimized: false,
            view: 'dashboard'
        };
    },
    componentWillMount() {
        HeaderStore.listen(this.update);
        this.history.listen(this.updatehistory);
    },
    componentWillUnmount() {
        HeaderStore.unlisten(this.update);
        this.history.unlisten(this.updatehistory);
    },
    updatehistory(n, location) {
        if (location.location.pathname)
            this.setState({
                view: (location.location.pathname.substr(1) === '') ? 'dashboard' : location.location.pathname.substr(1)
            });
    },
    update() {
        if (this.isMounted()) {
            this.setState({
                maximized: HeaderStore.getState().maximized,
                minimized: HeaderStore.getState().minimized
            });
        }
    },
    render() {
        var headerClass = 'header ' + process.platform + ' ' + this.state.view;
        return (

Powder Player

                    clear

                    crop_landscape

                    remove

        );
    }
});<|endoftext|>


<commit_before>var childProcess = require('child_process');
var fs = require('fs');
var AWS = require('aws-sdk');
var codepipeline = new AWS.CodePipeline();
var cloudformation = new AWS.CloudFormation();
var s3;

// for NPM, it needs a writable home directory
process.env.HOME = '/tmp';

process.on('unhandledRejection', function(error, promise) {
  console.error("UNHANDLED REJECTION", error.stack);
});

exports.deployFrontendAction = function(event, context) {
    doAction(deployFrontendAction, event, context);
}

exports.deployBackendAction = function(event, context) {
    doAction(deployBackendAction, event, context);
}

  // run an action
function doAction(actionFunction, event, context) {

    // init s3 here as we have the event object
    var job = event['CodePipeline.job'];
    s3 = new AWS.S3({
      "signatureVersion":"v4",
      "accessKeyId": job.data.artifactCredentials.accessKeyId,
      "secretAccessKey": job.data.artifactCredentials.secretAccessKey,
      "sessionToken": job.data.artifactCredentials.sessionToken
    });

    var promise;
    try {
        promise = actionFunction(event["CodePipeline.job"])
    } catch (e) {
        promise = Promise.reject(e);
    }

    handlePromise(promise, event, context);
}

// handle promise by notifying code pipeline
function handlePromise(promise, event, context) {
    promise
    .then(function() {
        console.log("Success!");

        var params = {
            jobId: event["CodePipeline.job"].id
        };
        codepipeline.putJobSuccessResult(params, function(err, data) {
            if(err) {
                context.fail(err);
            } else {
                context.succeed("Action complete.");
            }
        });
    }).catch( function(message) {
            var m = JSON.stringify(message);
            console.error("Failure: "+m);

            var params = {
                jobId: event["CodePipeline.job"].id,
                failureDetails: {
                    message: m,
                    type: 'JobFailed',
                    externalExecutionId: context.invokeid
                }
            };

            codepipeline.putJobFailureResult(params, function(err, data) {
                context.fail(m);
            });
    });
}

// return: promise
function deployFrontendAction(jobDetails) {
    var artifactName = 'SourceOutput';
    var artifactZipPath = '/tmp/source.zip';
    var artifactExtractPath = '/tmp/source/';
    var sourceFrontendPath = artifactExtractPath + 'frontend/'
    var sourceFrontendBuildPath = sourceFrontendPath + 'build/'
    return downloadInputArtifact(jobDetails, artifactName, artifactZipPath)
        .then(function () {
            return rmdir(artifactExtractPath);
        }).then(function () {
            return extractZip(artifactZipPath, artifactExtractPath);
        }).then(function () {
            return npmInstallAndBuild(sourceFrontendPath);
        }).then(function () {
            return downloadInputArtifact(jobDetails, 'DeployInfrastructureStackOutput', '/tmp/DeployInfrastructureStackOutput.zip')
        }).then(function () {
            return uploadBuildToWebsiteBucket(sourceFrontendBuildPath);
        });
}

// return: promise
function deployBackendAction(jobDetails) {
    var artifactName = 'SourceOutput';
    var artifactZipPath = '/tmp/source.zip';
    var artifactExtractPath = '/tmp/source/';
    var sourcePath = artifactExtractPath + 'backend/'

    var outArtifactName = 'BackendOutput';
    var outArtifactZipPath = '/tmp/backend_output.zip';

    return downloadInputArtifact(jobDetails, artifactName, artifactZipPath)
        .then(function () {
            return rmdir(artifactExtractPath);
        }).then(function () {
            return extractZip(artifactZipPath, artifactExtractPath);
        }).then(function () {
            return npmInstallAndServerlessDeploy(sourcePath);
        }).then(function () {
            return describeCloudFormationStack('serverless-boilerplate-dev');
        }).then(function (cloudformationStack) {
            return zipBackendOutputs(outArtifactZipPath, cloudformationStack);
//        }).then(function () {
//            return uploadOutputArtifact(jobDetails, outArtifactName, outArtifactZipPath);
        });
}

// get input artifact
//
// return: promise
function downloadInputArtifact(jobDetails, artifactName, dest) {
    console.log("Downloading input artifact '" + artifactName + "' to '"+dest+"'");

    // Get the input artifact
    var artifact = null;
    jobDetails.data.inputArtifacts.forEach(function (a) {

        if (a.name == artifactName) {
            artifact = a;
        }
    });

    if (artifact != null && artifact.location.type == 'S3') {
        var params = {
            Bucket: artifact.location.s3Location.bucketName,
            Key: artifact.location.s3Location.objectKey
        };
        return getS3Object(params, dest);
    } else {
        return Promise.reject("Unknown Source Type:" + JSON.stringify(sourceOutput));
    }
}

function getS3Object(params, dest) {
    return new Promise(function(resolve,reject) {
        console.log("Getting S3 Object '" + params.Bucket+"/"+params.Key + "' to '"+dest+"'");
        var file = fs.createWriteStream(dest);
        s3.getObject(params)
            .createReadStream()
            .on('error', reject)
            .pipe(file)
            .on('close', resolve);
    });
}

function exec(command,options) {
    return new Promise(function (resolve, reject) {
        var child = childProcess.exec(command,options);

        var lastMessage = ""
        child.stdout.on('data', function(data) {
            lastMessage = data.toString('utf-8');
            process.stdout.write(data);
        });
        child.stderr.on('data', function(data) {
            lastMessage = data.toString('utf-8');
            process.stderr.write(data);
        });
        child.on('close', function (code) {
            if(!code) {
                resolve(true);
            } else {
                reject("Error("+code+") - "+lastMessage);
            }
        });
    });
}

function rmdir(dir) {
    if(!dir || dir == '/') {
        throw new Error('Invalid directory '+dir);
    }

    console.log("Cleaning directory '"+dir+"'");
    return exec('rm -rf '+dir);
}

function extractZip(sourceZip,destDirectory) {
    return new Promise(function (resolve, reject) {
        console.log("Extracting zip: '"+sourceZip+"' to '"+destDirectory+"'");
        try {
            fs.mkdirSync(destDirectory);
            process.chdir(destDirectory);
            childProcess.execSync('unzip -o ' + sourceZip, {encoding: 'utf-8'});
            resolve(true);
        } catch (e) {
            reject(e);
        }
    });
}

function npmInstallAndBuild(destDirectory) {
    return new Promise(function (resolve, reject) {
        try {
            process.chdir(destDirectory);
            childProcess.execSync('npm install --progress=false ', {encoding: 'utf-8'});
            childProcess.execSync('npm run build', {encoding: 'utf-8'});
            resolve(true);
        } catch (e) {
            reject(e);
        }
    });
}

function npmInstallAndServerlessDeploy(destDirectory) {
    return new Promise(function (resolve, reject) {
        try {
            childProcess.execSync('npm install serverless@1.2.0 -g --prefix=/tmp', {encoding: 'utf-8'});

            process.chdir(destDirectory);
            childProcess.execSync('npm install --progress=false', {encoding: 'utf-8'});
            console.log(childProcess.execSync('/tmp/lib/node_modules/serverless/bin/serverless deploy', {encoding: 'utf-8'}));
            resolve(true);
        } catch (e) {
            reject(e);
        }
    });
}

function describeCloudFormationStack(stackName) {
    return new Promise(function (resolve, reject) {
        try {
            var params = {
                "StackName": stackName
            };
                cloudformation.describeStacks(params, function(err, data) {
                if (err) {
                    reject(err);
                } else {
                    resolve(data['Stacks'][0]);
                }
            });
        } catch (e) {
            promise.reject(e);
        }
    });
}

function zipBackendOutputs(outArtifactZipPath, cloudformationStack) {
    return new Promise(function (resolve, reject) {
        try {
            console.log(JSON.stringify(cloudformationStack["Outputs"]));

            var zip = new JSZip();
            zip.file('cfn.json', JSON.stringify(cloudformationStack["Outputs"]));
            zip
                .generateNodeStream()
                .pipe(fs.createWriteStream(outArtifactZipPath))
                .on('finish', function () {
                    console.log(outArtifactZipPath + "written.");
                    resolve();
                });
        } catch (e) {
            reject(e);
        }
    });
}

function uploadBuildToWebsiteBucket(destDirectory) {
    return new Promise(function (resolve, reject) {
        try {
            process.chdir('/tmp');
            childProcess.execSync('unzip -o /tmp/DeployInfrastructureStackOutput.zip');
            config = JSON.parse(fs.readFileSync('/tmp/cfn.json'));
            s3WebsiteBucketClient = new AWS.S3();

            process.chdir(destDirectory);
            var files = walkSync(destDirectory);
            files.forEach(function(file) {
                contentType = contentTypeMap(file)
                relativeFilePath = file.replace(destDirectory, '');
                s3WebsiteBucketClient.putObject({
                    'Bucket': config['WebsiteBucket'],
                    'Key': relativeFilePath,
                    'Body': fs.createReadStream(file),
                    'ContentType': contentType
                }, function(err, data) {
                      if (err) {
                        console.log(err);
                      } else {
                        console.log('Success');
                      }
                });
              });

            resolve(true);
        } catch (e) {
            console.log(e);
            reject(e);
        }
    });
}

function uploadOutputArtifact(jobDetails, artifactName, path) {
    console.log("Uploading output artifact '" + artifactName + "' from '"+path+"'");

    // Get the output artifact
    var artifact = null;
    jobDetails.data.outputArtifacts.forEach(function (a) {
        if (a.name == artifactName) {
            artifact = a;
        }
    });

    if (artifact != null && artifact.location.type == 'S3') {
        var params = {
            Bucket: artifact.location.s3Location.bucketName,
            Key: artifact.location.s3Location.objectKey
        };
        return putS3Object(params, path);
    } else {
        return Promise.reject("Unknown Source Type:" + JSON.stringify(sourceOutput));
    }
}

function putS3Object(params, path) {
    return new Promise(function(resolve,reject) {
        console.log("Putting S3 Object '" + params.Bucket+"/"+params.Key + "' from '"+path+"'");
        params.Body = fs.createReadStream(path);
        s3.putObject(params, function(err, data) {
            if(err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
    });
}

function walkSync(dir, filelist) {
  var path = path || require('path');
  files = fs.readdirSync(dir);
  filelist = filelist || [];
  files.forEach(function(file) {
    if (fs.statSync(path.join(dir, file)).isDirectory()) {
      filelist = walkSync(path.join(dir, file), filelist);
    }
    else {
      filelist.push(path.join(dir, file));
    }
  });
  return filelist;
};

function contentTypeMap(filename) {
     var map = {
         'jpg':  'image/jpeg',
         'png':  'image/png',
         'svg':  'image/svg+xml',
         'html': 'text/html',
         'css':  'text/css',
         'json': 'text/json',
         'ico':  'image/x-icon'
     };

     extension = filename.split('.').pop();
     if (extension in map) {
         return map[extension];
     } else {
         return 'application/octet-stream';
     }

}<commit_msg>require jszip<commit_after>var childProcess = require('child_process');
var fs = require('fs');
var AWS = require('aws-sdk');
var JSZip = require("jszip");

var codepipeline = new AWS.CodePipeline();
var cloudformation = new AWS.CloudFormation();
var s3;

// for NPM, it needs a writable home directory
process.env.HOME = '/tmp';

process.on('unhandledRejection', function(error, promise) {
  console.error("UNHANDLED REJECTION", error.stack);
});

exports.deployFrontendAction = function(event, context) {
    doAction(deployFrontendAction, event, context);
}

exports.deployBackendAction = function(event, context) {
    doAction(deployBackendAction, event, context);
}

  // run an action
function doAction(actionFunction, event, context) {

    // init s3 here as we have the event object
    var job = event['CodePipeline.job'];
    s3 = new AWS.S3({
      "signatureVersion":"v4",
      "accessKeyId": job.data.artifactCredentials.accessKeyId,
      "secretAccessKey": job.data.artifactCredentials.secretAccessKey,
      "sessionToken": job.data.artifactCredentials.sessionToken
    });

    var promise;
    try {
        promise = actionFunction(event["CodePipeline.job"])
    } catch (e) {
        promise = Promise.reject(e);
    }

    handlePromise(promise, event, context);
}

// handle promise by notifying code pipeline
function handlePromise(promise, event, context) {
    promise
    .then(function() {
        console.log("Success!");

        var params = {
            jobId: event["CodePipeline.job"].id
        };
        codepipeline.putJobSuccessResult(params, function(err, data) {
            if(err) {
                context.fail(err);
            } else {
                context.succeed("Action complete.");
            }
        });
    }).catch( function(message) {
            var m = JSON.stringify(message);
            console.error("Failure: "+m);

            var params = {
                jobId: event["CodePipeline.job"].id,
                failureDetails: {
                    message: m,
                    type: 'JobFailed',
                    externalExecutionId: context.invokeid
                }
            };

            codepipeline.putJobFailureResult(params, function(err, data) {
                context.fail(m);
            });
    });
}

// return: promise
function deployFrontendAction(jobDetails) {
    var artifactName = 'SourceOutput';
    var artifactZipPath = '/tmp/source.zip';
    var artifactExtractPath = '/tmp/source/';
    var sourceFrontendPath = artifactExtractPath + 'frontend/'
    var sourceFrontendBuildPath = sourceFrontendPath + 'build/'
    return downloadInputArtifact(jobDetails, artifactName, artifactZipPath)
        .then(function () {
            return rmdir(artifactExtractPath);
        }).then(function () {
            return extractZip(artifactZipPath, artifactExtractPath);
        }).then(function () {
            return npmInstallAndBuild(sourceFrontendPath);
        }).then(function () {
            return downloadInputArtifact(jobDetails, 'DeployInfrastructureStackOutput', '/tmp/DeployInfrastructureStackOutput.zip')
        }).then(function () {
            return uploadBuildToWebsiteBucket(sourceFrontendBuildPath);
        });
}

// return: promise
function deployBackendAction(jobDetails) {
    var artifactName = 'SourceOutput';
    var artifactZipPath = '/tmp/source.zip';
    var artifactExtractPath = '/tmp/source/';
    var sourcePath = artifactExtractPath + 'backend/'

    var outArtifactName = 'BackendOutput';
    var outArtifactZipPath = '/tmp/backend_output.zip';

    return downloadInputArtifact(jobDetails, artifactName, artifactZipPath)
        .then(function () {
            return rmdir(artifactExtractPath);
        }).then(function () {
            return extractZip(artifactZipPath, artifactExtractPath);
        }).then(function () {
            return npmInstallAndServerlessDeploy(sourcePath);
        }).then(function () {
            return describeCloudFormationStack('serverless-boilerplate-dev');
        }).then(function (cloudformationStack) {
            return zipBackendOutputs(outArtifactZipPath, cloudformationStack);
//        }).then(function () {
//            return uploadOutputArtifact(jobDetails, outArtifactName, outArtifactZipPath);
        });
}

// get input artifact
//
// return: promise
function downloadInputArtifact(jobDetails, artifactName, dest) {
    console.log("Downloading input artifact '" + artifactName + "' to '"+dest+"'");

    // Get the input artifact
    var artifact = null;
    jobDetails.data.inputArtifacts.forEach(function (a) {

        if (a.name == artifactName) {
            artifact = a;
        }
    });

    if (artifact != null && artifact.location.type == 'S3') {
        var params = {
            Bucket: artifact.location.s3Location.bucketName,
            Key: artifact.location.s3Location.objectKey
        };
        return getS3Object(params, dest);
    } else {
        return Promise.reject("Unknown Source Type:" + JSON.stringify(sourceOutput));
    }
}

function getS3Object(params, dest) {
    return new Promise(function(resolve,reject) {
        console.log("Getting S3 Object '" + params.Bucket+"/"+params.Key + "' to '"+dest+"'");
        var file = fs.createWriteStream(dest);
        s3.getObject(params)
            .createReadStream()
            .on('error', reject)
            .pipe(file)
            .on('close', resolve);
    });
}

function exec(command,options) {
    return new Promise(function (resolve, reject) {
        var child = childProcess.exec(command,options);

        var lastMessage = ""
        child.stdout.on('data', function(data) {
            lastMessage = data.toString('utf-8');
            process.stdout.write(data);
        });
        child.stderr.on('data', function(data) {
            lastMessage = data.toString('utf-8');
            process.stderr.write(data);
        });
        child.on('close', function (code) {
            if(!code) {
                resolve(true);
            } else {
                reject("Error("+code+") - "+lastMessage);
            }
        });
    });
}

function rmdir(dir) {
    if(!dir || dir == '/') {
        throw new Error('Invalid directory '+dir);
    }

    console.log("Cleaning directory '"+dir+"'");
    return exec('rm -rf '+dir);
}

function extractZip(sourceZip,destDirectory) {
    return new Promise(function (resolve, reject) {
        console.log("Extracting zip: '"+sourceZip+"' to '"+destDirectory+"'");
        try {
            fs.mkdirSync(destDirectory);
            process.chdir(destDirectory);
            childProcess.execSync('unzip -o ' + sourceZip, {encoding: 'utf-8'});
            resolve(true);
        } catch (e) {
            reject(e);
        }
    });
}

function npmInstallAndBuild(destDirectory) {
    return new Promise(function (resolve, reject) {
        try {
            process.chdir(destDirectory);
            childProcess.execSync('npm install --progress=false ', {encoding: 'utf-8'});
            childProcess.execSync('npm run build', {encoding: 'utf-8'});
            resolve(true);
        } catch (e) {
            reject(e);
        }
    });
}

function npmInstallAndServerlessDeploy(destDirectory) {
    return new Promise(function (resolve, reject) {
        try {
            childProcess.execSync('npm install serverless@1.2.0 -g --prefix=/tmp', {encoding: 'utf-8'});

            process.chdir(destDirectory);
            childProcess.execSync('npm install --progress=false', {encoding: 'utf-8'});
            console.log(childProcess.execSync('/tmp/lib/node_modules/serverless/bin/serverless deploy', {encoding: 'utf-8'}));
            resolve(true);
        } catch (e) {
            reject(e);
        }
    });
}

function describeCloudFormationStack(stackName) {
    return new Promise(function (resolve, reject) {
        try {
            var params = {
                "StackName": stackName
            };
                cloudformation.describeStacks(params, function(err, data) {
                if (err) {
                    reject(err);
                } else {
                    resolve(data['Stacks'][0]);
                }
            });
        } catch (e) {
            promise.reject(e);
        }
    });
}

function zipBackendOutputs(outArtifactZipPath, cloudformationStack) {
    return new Promise(function (resolve, reject) {
        try {
            console.log(JSON.stringify(cloudformationStack["Outputs"]));

            var zip = new JSZip();
            zip.file('cfn.json', JSON.stringify(cloudformationStack["Outputs"]));
            zip
                .generateNodeStream()
                .pipe(fs.createWriteStream(outArtifactZipPath))
                .on('finish', function () {
                    console.log(outArtifactZipPath + "written.");
                    resolve();
                });
        } catch (e) {
            reject(e);
        }
    });
}

function uploadBuildToWebsiteBucket(destDirectory) {
    return new Promise(function (resolve, reject) {
        try {
            process.chdir('/tmp');
            childProcess.execSync('unzip -o /tmp/DeployInfrastructureStackOutput.zip');
            config = JSON.parse(fs.readFileSync('/tmp/cfn.json'));
            s3WebsiteBucketClient = new AWS.S3();

            process.chdir(destDirectory);
            var files = walkSync(destDirectory);
            files.forEach(function(file) {
                contentType = contentTypeMap(file)
                relativeFilePath = file.replace(destDirectory, '');
                s3WebsiteBucketClient.putObject({
                    'Bucket': config['WebsiteBucket'],
                    'Key': relativeFilePath,
                    'Body': fs.createReadStream(file),
                    'ContentType': contentType
                }, function(err, data) {
                      if (err) {
                        console.log(err);
                      } else {
                        console.log('Success');
                      }
                });
              });

            resolve(true);
        } catch (e) {
            console.log(e);
            reject(e);
        }
    });
}

function uploadOutputArtifact(jobDetails, artifactName, path) {
    console.log("Uploading output artifact '" + artifactName + "' from '"+path+"'");

    // Get the output artifact
    var artifact = null;
    jobDetails.data.outputArtifacts.forEach(function (a) {
        if (a.name == artifactName) {
            artifact = a;
        }
    });

    if (artifact != null && artifact.location.type == 'S3') {
        var params = {
            Bucket: artifact.location.s3Location.bucketName,
            Key: artifact.location.s3Location.objectKey
        };
        return putS3Object(params, path);
    } else {
        return Promise.reject("Unknown Source Type:" + JSON.stringify(sourceOutput));
    }
}

function putS3Object(params, path) {
    return new Promise(function(resolve,reject) {
        console.log("Putting S3 Object '" + params.Bucket+"/"+params.Key + "' from '"+path+"'");
        params.Body = fs.createReadStream(path);
        s3.putObject(params, function(err, data) {
            if(err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
    });
}

function walkSync(dir, filelist) {
  var path = path || require('path');
  files = fs.readdirSync(dir);
  filelist = filelist || [];
  files.forEach(function(file) {
    if (fs.statSync(path.join(dir, file)).isDirectory()) {
      filelist = walkSync(path.join(dir, file), filelist);
    }
    else {
      filelist.push(path.join(dir, file));
    }
  });
  return filelist;
};

function contentTypeMap(filename) {
     var map = {
         'jpg':  'image/jpeg',
         'png':  'image/png',
         'svg':  'image/svg+xml',
         'html': 'text/html',
         'css':  'text/css',
         'json': 'text/json',
         'ico':  'image/x-icon'
     };

     extension = filename.split('.').pop();
     if (extension in map) {
         return map[extension];
     } else {
         return 'application/octet-stream';
     }

}<|endoftext|>


<commit_before>import React, {Component}                    from 'react';
import _ from 'lodash';
import moment from 'moment-timezone';
import {Line} from 'react-chartjs-2';

export default class GlucoseChart extends Component {
    constructor(props) {
        super(props);
        this.formatTime = this.formatTime.bind(this);
    }

    componentWillMount() {
        this.setState(this.props);
    }

    componentWillReceiveProps(nextProps) {
        this.setState(nextProps);
    }

    formatTime(ticks, t, cb) {
        if (ticks % 6 == 0) {
            var AMPM = 'AM';
            var m = moment.tz(t, 'America/Chicago').format('HH:mm');
            var s = m.split(':');
            var h;
            var mins;
            if (s[0] == 0) {
                h = 12;
            } else if (s[0] == 12) {
                h = 12;
                AMPM = 'PM';
            } else if (s[0] > 12) {
                h = s[0] - 12;
                AMPM = 'PM';
            } else {
                h = s[0];
            }

            cb(h + ':' + s[1] + ' ' + AMPM);
        } else {
            cb("");
        }
    }

    render() {
        var history =

        var historicalData;
        if (this.state.history) {
            var ticks = 0;
            var comptime;
            var historicalData = [];
            var labels = [];

            for (var x = this.state.history.length - 1; x >= 0; x--) {
                ticks++;
                var utcTime = new Date(this.state.history[x].time).getTime();
                if (ticks === 1) {
                    comptime = utcTime;
                    historicalData.push(this.state.history[x].glucose);
                    this.formatTime(6, utcTime, function (ft) {
                        labels.push(ft);
                    });
                } else if (((comptime + 4 * 60 * 1000) < utcTime) && (utcTime < (comptime + 6 * 60 * 1000))) {
                    this.formatTime(ticks, utcTime, function (ft) {
                        labels.push(ft);
                    });
                    historicalData.push(this.state.history[x].glucose);
                    comptime = utcTime;
                } else {
                    while (utcTime > (comptime + 5.5 * 60 * 1000)) {
                        this.formatTime(ticks, comptime, function (ft) {
                            labels.push(ft);
                        });
                        ticks++;
                        historicalData.push(null);
                        comptime += 5 * 60 * 1000;
                    }
                    comptime = utcTime;
                    this.formatTime(ticks, utcTime, function (ft) {
                        labels.push(ft);
                    });
                    historicalData.push(this.state.history[x].glucose);
                }
            }
            var h = 275;
            var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
            if (w > 768) {
                h = 100;
            }
            var data = {
                labels: labels,
                datasets: [
                    {
                        label: '',
                        fill: false,
                        lineTension: 0.1,
                        backgroundColor: 'rgba(75,192,192,0.4)',
                        borderColor: 'rgba(75,192,192,1)',
                        borderCapStyle: 'butt',
                        borderDash: [],
                        borderDashOffset: 0.0,
                        borderJoinStyle: 'miter',
                        pointBorderColor: 'rgba(75,192,192,1)',
                        pointBackgroundColor: '#fff',
                        pointBorderWidth: 1,
                        pointHoverRadius: 5,
                        pointHoverBackgroundColor: 'rgba(75,192,192,1)',
                        pointHoverBorderColor: 'rgba(220,220,220,1)',
                        pointHoverBorderWidth: 2,
                        pointRadius: 1,
                        pointHitRadius: 10,
                        data: historicalData
                    }
                ]
            };
            var options = {
                title: {
                    display: true,
                    text: 'Trend Data'
                },
                legend: {
                    display: false
                },
                scales: {
                    yAxes: [{
                        //type: 'logarithmic',
                        ticks: {
                            min: 0,
                            max: 400,
                        }
                    }],
                    range: [
                        {
                            start: 0,
                            end: 80,
                            color: 'rgba(250,0,0,0.5)'
                        },
                        {
                            start: 280,
                            end: 400,
                            color: 'rgba(250,0,0,0.5)'
                        }
                    ]
                }
            };
            history =
<Line data={data} options={options} height={h}/>

        }
        return (

{history}

        );
    }
}
<commit_msg>one more adjustment<commit_after>import React, {Component}                    from 'react';
import _ from 'lodash';
import moment from 'moment-timezone';
import {Line} from 'react-chartjs-2';

export default class GlucoseChart extends Component {
    constructor(props) {
        super(props);
        this.formatTime = this.formatTime.bind(this);
    }

    componentWillMount() {
        this.setState(this.props);
    }

    componentWillReceiveProps(nextProps) {
        this.setState(nextProps);
    }

    formatTime(ticks, t, cb) {
        if (ticks % 6 == 0) {
            var AMPM = 'AM';
            var m = moment.tz(t, 'America/Chicago').format('HH:mm');
            var s = m.split(':');
            var h;
            var mins;
            if (s[0] == 0) {
                h = 12;
            } else if (s[0] == 12) {
                h = 12;
                AMPM = 'PM';
            } else if (s[0] > 12) {
                h = s[0] - 12;
                AMPM = 'PM';
            } else {
                h = s[0];
            }

            cb(h + ':' + s[1] + ' ' + AMPM);
        } else {
            cb("");
        }
    }

    render() {
        var history =

        var historicalData;
        if (this.state.history) {
            var ticks = 0;
            var comptime;
            var historicalData = [];
            var labels = [];

            for (var x = this.state.history.length - 1; x >= 0; x--) {
                ticks++;
                var utcTime = new Date(this.state.history[x].time).getTime();
                if (ticks === 1) {
                    comptime = utcTime;
                    historicalData.push(this.state.history[x].glucose);
                    this.formatTime(6, utcTime, function (ft) {
                        labels.push(ft);
                    });
                } else if (((comptime + 4 * 60 * 1000) < utcTime) && (utcTime < (comptime + 6 * 60 * 1000))) {
                    this.formatTime(ticks, utcTime, function (ft) {
                        labels.push(ft);
                    });
                    historicalData.push(this.state.history[x].glucose);
                    comptime = utcTime;
                } else {
                    while (utcTime > (comptime + 5.5 * 60 * 1000)) {
                        this.formatTime(ticks, comptime, function (ft) {
                            labels.push(ft);
                        });
                        ticks++;
                        historicalData.push(null);
                        comptime += 5 * 60 * 1000;
                    }
                    comptime = utcTime;
                    this.formatTime(ticks, utcTime, function (ft) {
                        labels.push(ft);
                    });
                    historicalData.push(this.state.history[x].glucose);
                }
            }
            var h = 300;
            var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
            if (w > 768) {
                h = 100;
            }
            var data = {
                labels: labels,
                datasets: [
                    {
                        label: '',
                        fill: false,
                        lineTension: 0.1,
                        backgroundColor: 'rgba(75,192,192,0.4)',
                        borderColor: 'rgba(75,192,192,1)',
                        borderCapStyle: 'butt',
                        borderDash: [],
                        borderDashOffset: 0.0,
                        borderJoinStyle: 'miter',
                        pointBorderColor: 'rgba(75,192,192,1)',
                        pointBackgroundColor: '#fff',
                        pointBorderWidth: 1,
                        pointHoverRadius: 5,
                        pointHoverBackgroundColor: 'rgba(75,192,192,1)',
                        pointHoverBorderColor: 'rgba(220,220,220,1)',
                        pointHoverBorderWidth: 2,
                        pointRadius: 1,
                        pointHitRadius: 10,
                        data: historicalData
                    }
                ]
            };
            var options = {
                title: {
                    display: true,
                    text: 'Trend Data'
                },
                legend: {
                    display: false
                },
                scales: {
                    yAxes: [{
                        //type: 'logarithmic',
                        ticks: {
                            min: 0,
                            max: 400,
                        }
                    }],
                    range: [
                        {
                            start: 0,
                            end: 80,
                            color: 'rgba(250,0,0,0.5)'
                        },
                        {
                            start: 280,
                            end: 400,
                            color: 'rgba(250,0,0,0.5)'
                        }
                    ]
                }
            };
            history =
<Line data={data} options={options} height={h}/>

        }
        return (

{history}

        );
    }
}
<|endoftext|>


<commit_before>/*jshint node:true, indent:2, curly:false, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
regexp:true, undef:true, strict:true, trailing:true, white:true */
/*global XT:true, XM:true, XV: true */

// global objects
XT = {};
XM = {};
XV = {};

var assert = require('assert'),
  zombie = require('zombie');

/**
Usage:

  var zombieTest = require('./vows/zombie_auth');
  zombieTest.testLoad('username', 'password');

*/
(function () {
  "use strict";

  var secondsToWait = 20;

  var loadApp = function (username, password, host, masterCallback) {
    var siteRoot = host || 'https://localhost';
    zombie.visit(siteRoot, {debug: true}, function (e, browser) {
      //
      // This is the login screen
      //
      browser
        .fill('id', username)
        .fill('password', password)
        .pressButton('submit', function () {
          //
          // We skip the scope screen because we're using a user that only has one org
          //
          // Note: make sure the app is built

          // not quite sure why zombie doesn't do this redirect, but oh well.
          browser.visit(siteRoot + '/client/index.html', function (e, browser) {
            setTimeout(function () {
              // add the global objects to our global namespace
              XM = browser.window.XM;
              XT = browser.window.XT;
              XV = browser.window.XV;

              console.log(XT.app.state);
              // give control back to whoever called us
              masterCallback();
            }, 10000);
          });
        });
    });
  };

  exports.loadAdd = loadApp;

  exports.testLoad = function (username, password, host) {
    console.log("Testing loadup of app.");

    loadApp(username, password, host, function () {
      if (!XT.app.state || XT.app.state < 6) {
        console.log("App did not fully load");
        process.exit(1);
      }
      console.log("App loaded successfully.");
      process.exit(0);
    });
  };

}());

<commit_msg>issue #19379: got zombie auth working with ssl<commit_after>/*jshint node:true, indent:2, curly:false, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
regexp:true, undef:true, strict:true, trailing:true, white:true */
/*global XT:true, XM:true, XV: true */

// global objects
XT = {};
XM = {};
XV = {};

var assert = require('assert'),
  zombie = require('zombie');

/**
Usage:

  var zombieTest = require('./vows/zombie_auth');
  zombieTest.testLoad('username', 'password');

*/
(function () {
  "use strict";

  var secondsToWait = 10;

  var loadApp = function (username, password, host, masterCallback) {
    var siteRoot = host || 'https://localhost';
    zombie.visit(siteRoot, {debug: false}, function (e, browser) {
      //
      // This is the login screen
      //
      browser
        .fill('id', username)
        .fill('password', password)
        .pressButton('submit', function () {
          //
          // We skip the scope screen because we're using a user that only has one org
          // XXX this limitation should be fixed, to allow a test on users with >1 org

          // Note: make sure the app is built
          // XXX this limitation should be fixed, to allow testing off of debug.html

          // Plan to give up after a set time
          setTimeout(function () {
            masterCallback();
          }, secondsToWait * 1000);

          // Check frequently to see if the app is loaded, and move forward when it is
          setInterval(function () {
            if (browser.window.XT && browser.window.XT.app && browser.window.XT.app.state === 6) {
              // add the global objects to our global namespace
              XM = browser.window.XM;
              XT = browser.window.XT;
              XV = browser.window.XV;

              // give control back to whoever called us
              masterCallback();
            }
          }, 100);
        });
    });
  };

  exports.loadAdd = loadApp;

  exports.testLoad = function (username, password, host) {
    console.log("Testing loadup of app.");

    loadApp(username, password, host, function () {
      if (!XT || !XT.app || !XT.app.state || XT.app.state < 6) {
        console.log("App did not fully load");
        process.exit(1);
      }
      console.log("App loaded successfully.");
      process.exit(0);
    });
  };

}());

<|endoftext|>


<commit_before>/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Plotly = require('../../plotly');
var d3 = require('d3');
var isNumeric = require('fast-isnumeric');

var plots = Plotly.Plots;

var Titles = module.exports = {};

// titles - (re)draw titles on the axes and plot
// title can be 'xtitle', 'ytitle', 'gtitle',
//  or empty to draw all
Titles.draw = function(gd, title) {
    var fullLayout = gd._fullLayout,
        gs = fullLayout._size,
        axletter = title.charAt(0),
        colorbar = title.substr(1,2)==='cb';

    var cbnum, cont, options;

    if(colorbar) {
        var uid = title.substr(3).replace('title','');
        gd._fullData.some(function(trace, i) {
            if(trace.uid===uid) {
                cbnum = i;
                cont = gd.calcdata[i][0].t.cb.axis;
                return true;
            }
        });
    }
    else cont = fullLayout[Plotly.Axes.id2name(title.replace('title',''))] || fullLayout;

    var prop = cont===fullLayout ? 'title' : cont._name+'.title',
        name = colorbar ? 'colorscale' :
            ((cont._id||axletter).toUpperCase()+' axis'),
        font = cont.titlefont.family,
        fontSize = cont.titlefont.size,
        fontColor = cont.titlefont.color,
        x,
        y,
        transform = '',
        xa,
        ya,
        avoid = {
            selection:d3.select(gd).selectAll('g.'+cont._id+'tick'),
            side:cont.side
        },
        // multiples of fontsize to offset label from axis
        offsetBase = colorbar ? 0 : 1.5,
        avoidTransform;

    // find the transform applied to the parents of the avoid selection
    // which doesn't get picked up by Plotly.Drawing.bBox
    if(colorbar) {
        avoid.offsetLeft = gs.l;
        avoid.offsetTop = gs.t;
    }
    else if(avoid.selection.size()) {
        avoidTransform = d3.select(avoid.selection.node().parentNode)
            .attr('transform')
            .match(/translate\(([-\.\d]+),([-\.\d]+)\)/);
        if(avoidTransform) {
            avoid.offsetLeft = +avoidTransform[1];
            avoid.offsetTop = +avoidTransform[2];
        }
    }

    if(colorbar && cont.titleside) {
        // argh, we only make it here if the title is on top or bottom,
        // not right
        x = gs.l+cont.titlex*gs.w;
        y = gs.t+(1-cont.titley)*gs.h + ((cont.titleside==='top') ?
                3+fontSize*0.75 : - 3-fontSize*0.25);
        options = {x: x, y: y, 'text-anchor':'start'};
        avoid = {};

        // convertToTspans rotates any 'y...' by 90 degrees...
        // TODO: need a better solution than this hack
        title = 'h'+title;
    }
    else if(axletter==='x'){
        xa = cont;
        ya = (xa.anchor==='free') ?
            {_offset:gs.t+(1-(xa.position||0))*gs.h, _length:0} :
            Plotly.Axes.getFromId(gd, xa.anchor);
        x = xa._offset+xa._length/2;
        y = ya._offset + ((xa.side==='top') ?
            -10 - fontSize*(offsetBase + (xa.showticklabels ? 1 : 0)) :
            ya._length + 10 +
                fontSize*(offsetBase + (xa.showticklabels ? 1.5 : 0.5)));
        options = {x: x, y: y, 'text-anchor': 'middle'};
        if(!avoid.side) { avoid.side = 'bottom'; }
    }
    else if(axletter==='y'){
        ya = cont;
        xa = (ya.anchor==='free') ?
            {_offset:gs.l+(ya.position||0)*gs.w, _length:0} :
            Plotly.Axes.getFromId(gd, ya.anchor);
        y = ya._offset+ya._length/2;
        x = xa._offset + ((ya.side==='right') ?
            xa._length + 10 +
                fontSize*(offsetBase + (ya.showticklabels ? 1 : 0.5)) :
            -10 - fontSize*(offsetBase + (ya.showticklabels ? 0.5 : 0)));
        options = {x: x, y: y, 'text-anchor': 'middle'};
        transform = {rotate: '-90', offset: 0};
        if(!avoid.side) { avoid.side = 'left'; }
    }
    else{
        // plot title
        name = 'Plot';
        fontSize = fullLayout.titlefont.size;
        x = fullLayout.width/2;
        y = fullLayout._size.t/2;
        options = {x: x, y: y, 'text-anchor': 'middle'};
        avoid = {};
    }

    var opacity = 1,
        isplaceholder = false,
        txt = cont.title.trim();
    if(txt === '') { opacity = 0; }
    if(txt.match(/Click to enter .+ title/)) {
        opacity = 0.2;
        isplaceholder = true;
    }

    var group;
    if(colorbar) {
        group = d3.select(gd)
            .selectAll('.'+cont._id.substr(1)+' .cbtitle');
        // this class-to-rotate thing with convertToTspans is
        // getting hackier and hackier... delete groups with the
        // wrong class
        var otherClass = title.charAt(0)==='h' ?
            title.substr(1) : ('h'+title);
        group.selectAll('.'+otherClass+',.'+otherClass+'-math-group')
            .remove();
    }
    else {
        group = fullLayout._infolayer.selectAll('.g-'+title)
            .data([0]);
        group.enter().append('g')
            .classed('g-'+title, true);
    }

    var el = group.selectAll('text')
        .data([0]);
    el.enter().append('text');
    el.text(txt)
        // this is hacky, but convertToTspans uses the class
        // to determine whether to rotate mathJax...
        // so we need to clear out any old class and put the
        // correct one (only relevant for colorbars, at least
        // for now) - ie don't use .classed
        .attr('class', title);

    function titleLayout(titleEl){
        Plotly.Lib.syncOrAsync([drawTitle,scootTitle], titleEl);
    }

    function drawTitle(titleEl) {
        titleEl.attr('transform', transform ?
            'rotate(' + [transform.rotate, options.x, options.y] +
                ') translate(0, '+transform.offset+')' :
            null);

        titleEl.style({
            'font-family': font,
            'font-size': d3.round(fontSize,2)+'px',
            fill: Plotly.Color.rgb(fontColor),
            opacity: opacity*Plotly.Color.opacity(fontColor),
            'font-weight': plots.fontWeight
        })
        .attr(options)
        .call(Plotly.util.convertToTspans)
        .attr(options);

        titleEl.selectAll('tspan.line')
            .attr(options);
        return plots.previousPromises(gd);
    }

    function scootTitle(titleElIn) {
        var titleGroup = d3.select(titleElIn.node().parentNode);

        if(avoid && avoid.selection && avoid.side && txt){
            titleGroup.attr('transform',null);

            // move toward avoid.side (= left, right, top, bottom) if needed
            // can include pad (pixels, default 2)
            var shift = 0,
                backside = {
                    left: 'right',
                    right: 'left',
                    top: 'bottom',
                    bottom: 'top'
                }[avoid.side],
                shiftSign = (['left','top'].indexOf(avoid.side)!==-1) ?
                    -1 : 1,
                pad = isNumeric(avoid.pad) ? avoid.pad : 2,
                titlebb = Plotly.Drawing.bBox(titleGroup.node()),
                paperbb = {
                    left: 0,
                    top: 0,
                    right: fullLayout.width,
                    bottom: fullLayout.height
                },
                maxshift = colorbar ? fullLayout.width:
                    (paperbb[avoid.side]-titlebb[avoid.side]) *
                    ((avoid.side==='left' || avoid.side==='top') ? -1 : 1);
            // Prevent the title going off the paper
            if(maxshift<0) shift = maxshift;
            else {
                // so we don't have to offset each avoided element,
                // give the title the opposite offset
                titlebb.left -= avoid.offsetLeft;
                titlebb.right -= avoid.offsetLeft;
                titlebb.top -= avoid.offsetTop;
                titlebb.bottom -= avoid.offsetTop;

                // iterate over a set of elements (avoid.selection)
                // to avoid collisions with
                avoid.selection.each(function(){
                    var avoidbb = Plotly.Drawing.bBox(this);

                    if(Plotly.Lib.bBoxIntersect(titlebb,avoidbb,pad)) {
                        shift = Math.max(shift, shiftSign * (
                            avoidbb[avoid.side] - titlebb[backside]) + pad);
                    }
                });
                shift = Math.min(maxshift, shift);
            }
            if(shift>0 || maxshift<0) {
                var shiftTemplate = {
                    left: [-shift, 0],
                    right: [shift, 0],
                    top: [0, -shift],
                    bottom: [0, shift]
                }[avoid.side];
                titleGroup.attr('transform',
                    'translate(' + shiftTemplate + ')');
            }
        }
    }

    el.attr({'data-unformatted': txt})
        .call(titleLayout);

    var placeholderText = 'Click to enter '+name.replace(/\d+/,'')+' title';

    function setPlaceholder(){
        opacity = 0;
        isplaceholder = true;
        txt = placeholderText;
        fullLayout._infolayer.select('.'+title)
            .attr({'data-unformatted': txt})
            .text(txt)
            .on('mouseover.opacity',function(){
                d3.select(this).transition()
                    .duration(100).style('opacity',1);
            })
            .on('mouseout.opacity',function(){
                d3.select(this).transition()
                    .duration(1000).style('opacity',0);
            });
    }

    if(gd._context.editable){
        if(!txt) setPlaceholder();

        el.call(Plotly.util.makeEditable)
            .on('edit', function(text){
                if(colorbar) {
                    var trace = gd._fullData[cbnum];
                    if(plots.traceIs(trace, 'markerColorscale')) {
                        Plotly.restyle(gd, 'marker.colorbar.title', text, cbnum);
                    } else Plotly.restyle(gd, 'colorbar.title', text, cbnum);
                }
                else Plotly.relayout(gd,prop,text);
            })
            .on('cancel', function(){
                this.text(this.attr('data-unformatted'))
                    .call(titleLayout);
            })
            .on('input', function(d){
                this.text(d || ' ').attr(options)
                    .selectAll('tspan.line')
                        .attr(options);
            });
    }
    else if(!txt || txt.match(/Click to enter .+ title/)) {
        el.remove();
    }
    el.classed('js-placeholder',isplaceholder);
};
<commit_msg>require dependencies into title directly,<commit_after>/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var d3 = require('d3');
var isNumeric = require('fast-isnumeric');

var Plotly = require('../../plotly');
var Plots = require('../../plots/plots');
var Lib = require('../../lib');
var Drawing = require('../drawing');
var Color = require('../color');
var svgTextUtils = require('../../lib/svg_text_utils');
var axisIds = require('../../plots/cartesian/axis_ids');

var Titles = module.exports = {};

// titles - (re)draw titles on the axes and plot
// title can be 'xtitle', 'ytitle', 'gtitle',
//  or empty to draw all
Titles.draw = function(gd, title) {
    var fullLayout = gd._fullLayout,
        gs = fullLayout._size,
        axletter = title.charAt(0),
        colorbar = title.substr(1,2)==='cb';

    var cbnum, cont, options;

    if(colorbar) {
        var uid = title.substr(3).replace('title','');
        gd._fullData.some(function(trace, i) {
            if(trace.uid===uid) {
                cbnum = i;
                cont = gd.calcdata[i][0].t.cb.axis;
                return true;
            }
        });
    }
    else cont = fullLayout[axisIds.id2name(title.replace('title', ''))] || fullLayout;

    var prop = cont===fullLayout ? 'title' : cont._name+'.title',
        name = colorbar ? 'colorscale' :
            ((cont._id||axletter).toUpperCase()+' axis'),
        font = cont.titlefont.family,
        fontSize = cont.titlefont.size,
        fontColor = cont.titlefont.color,
        x,
        y,
        transform = '',
        xa,
        ya,
        avoid = {
            selection:d3.select(gd).selectAll('g.'+cont._id+'tick'),
            side:cont.side
        },
        // multiples of fontsize to offset label from axis
        offsetBase = colorbar ? 0 : 1.5,
        avoidTransform;

    // find the transform applied to the parents of the avoid selection
    // which doesn't get picked up by Plotly.Drawing.bBox
    if(colorbar) {
        avoid.offsetLeft = gs.l;
        avoid.offsetTop = gs.t;
    }
    else if(avoid.selection.size()) {
        avoidTransform = d3.select(avoid.selection.node().parentNode)
            .attr('transform')
            .match(/translate\(([-\.\d]+),([-\.\d]+)\)/);
        if(avoidTransform) {
            avoid.offsetLeft = +avoidTransform[1];
            avoid.offsetTop = +avoidTransform[2];
        }
    }

    if(colorbar && cont.titleside) {
        // argh, we only make it here if the title is on top or bottom,
        // not right
        x = gs.l+cont.titlex*gs.w;
        y = gs.t+(1-cont.titley)*gs.h + ((cont.titleside==='top') ?
                3+fontSize*0.75 : - 3-fontSize*0.25);
        options = {x: x, y: y, 'text-anchor':'start'};
        avoid = {};

        // convertToTspans rotates any 'y...' by 90 degrees...
        // TODO: need a better solution than this hack
        title = 'h'+title;
    }
    else if(axletter==='x'){
        xa = cont;
        ya = (xa.anchor==='free') ?
            {_offset:gs.t+(1-(xa.position||0))*gs.h, _length:0} :
        x = xa._offset+xa._length/2;
        y = ya._offset + ((xa.side==='top') ?
            axisIds.getFromId(gd, xa.anchor);
            -10 - fontSize*(offsetBase + (xa.showticklabels ? 1 : 0)) :
            ya._length + 10 +
                fontSize*(offsetBase + (xa.showticklabels ? 1.5 : 0.5)));
        options = {x: x, y: y, 'text-anchor': 'middle'};
        if(!avoid.side) { avoid.side = 'bottom'; }
    }
    else if(axletter==='y'){
        ya = cont;
        xa = (ya.anchor==='free') ?
            {_offset:gs.l+(ya.position||0)*gs.w, _length:0} :
        y = ya._offset+ya._length/2;
        x = xa._offset + ((ya.side==='right') ?
            axisIds.getFromId(gd, ya.anchor);
            xa._length + 10 +
                fontSize*(offsetBase + (ya.showticklabels ? 1 : 0.5)) :
            -10 - fontSize*(offsetBase + (ya.showticklabels ? 0.5 : 0)));
        options = {x: x, y: y, 'text-anchor': 'middle'};
        transform = {rotate: '-90', offset: 0};
        if(!avoid.side) { avoid.side = 'left'; }
    }
    else{
        // plot title
        name = 'Plot';
        fontSize = fullLayout.titlefont.size;
        x = fullLayout.width/2;
        y = fullLayout._size.t/2;
        options = {x: x, y: y, 'text-anchor': 'middle'};
        avoid = {};
    }

    var opacity = 1,
        isplaceholder = false,
        txt = cont.title.trim();
    if(txt === '') { opacity = 0; }
    if(txt.match(/Click to enter .+ title/)) {
        opacity = 0.2;
        isplaceholder = true;
    }

    var group;
    if(colorbar) {
        group = d3.select(gd)
            .selectAll('.'+cont._id.substr(1)+' .cbtitle');
        // this class-to-rotate thing with convertToTspans is
        // getting hackier and hackier... delete groups with the
        // wrong class
        var otherClass = title.charAt(0)==='h' ?
            title.substr(1) : ('h'+title);
        group.selectAll('.'+otherClass+',.'+otherClass+'-math-group')
            .remove();
    }
    else {
        group = fullLayout._infolayer.selectAll('.g-'+title)
            .data([0]);
        group.enter().append('g')
            .classed('g-'+title, true);
    }

    var el = group.selectAll('text')
        .data([0]);
    el.enter().append('text');
    el.text(txt)
        // this is hacky, but convertToTspans uses the class
        // to determine whether to rotate mathJax...
        // so we need to clear out any old class and put the
        // correct one (only relevant for colorbars, at least
        // for now) - ie don't use .classed
        .attr('class', title);

    function titleLayout(titleEl){
        Lib.syncOrAsync([drawTitle,scootTitle], titleEl);
    }

    function drawTitle(titleEl) {
        titleEl.attr('transform', transform ?
            'rotate(' + [transform.rotate, options.x, options.y] +
                ') translate(0, '+transform.offset+')' :
            null);

        titleEl.style({
            'font-family': font,
            'font-size': d3.round(fontSize,2) + 'px',
            fill: Color.rgb(fontColor),
            opacity: opacity * Color.opacity(fontColor),
            'font-weight': Plots.fontWeight
        })
        .attr(options)
        .call(svgTextUtils.convertToTspans)
        .attr(options);

        titleEl.selectAll('tspan.line')
            .attr(options);
        return Plots.previousPromises(gd);
    }

    function scootTitle(titleElIn) {
        var titleGroup = d3.select(titleElIn.node().parentNode);

        if(avoid && avoid.selection && avoid.side && txt){
            titleGroup.attr('transform',null);

            // move toward avoid.side (= left, right, top, bottom) if needed
            // can include pad (pixels, default 2)
            var shift = 0,
                backside = {
                    left: 'right',
                    right: 'left',
                    top: 'bottom',
                    bottom: 'top'
                }[avoid.side],
                shiftSign = (['left','top'].indexOf(avoid.side)!==-1) ?
                    -1 : 1,
                pad = isNumeric(avoid.pad) ? avoid.pad : 2,
                titlebb = Drawing.bBox(titleGroup.node()),
                paperbb = {
                    left: 0,
                    top: 0,
                    right: fullLayout.width,
                    bottom: fullLayout.height
                },
                maxshift = colorbar ? fullLayout.width:
                    (paperbb[avoid.side]-titlebb[avoid.side]) *
                    ((avoid.side==='left' || avoid.side==='top') ? -1 : 1);
            // Prevent the title going off the paper
            if(maxshift<0) shift = maxshift;
            else {
                // so we don't have to offset each avoided element,
                // give the title the opposite offset
                titlebb.left -= avoid.offsetLeft;
                titlebb.right -= avoid.offsetLeft;
                titlebb.top -= avoid.offsetTop;
                titlebb.bottom -= avoid.offsetTop;

                // iterate over a set of elements (avoid.selection)
                // to avoid collisions with
                avoid.selection.each(function(){
                    var avoidbb = Drawing.bBox(this);

                    if(Lib.bBoxIntersect(titlebb,avoidbb,pad)) {
                        shift = Math.max(shift, shiftSign * (
                            avoidbb[avoid.side] - titlebb[backside]) + pad);
                    }
                });
                shift = Math.min(maxshift, shift);
            }
            if(shift>0 || maxshift<0) {
                var shiftTemplate = {
                    left: [-shift, 0],
                    right: [shift, 0],
                    top: [0, -shift],
                    bottom: [0, shift]
                }[avoid.side];
                titleGroup.attr('transform',
                    'translate(' + shiftTemplate + ')');
            }
        }
    }

    el.attr({'data-unformatted': txt})
        .call(titleLayout);

    var placeholderText = 'Click to enter '+name.replace(/\d+/,'')+' title';

    function setPlaceholder(){
        opacity = 0;
        isplaceholder = true;
        txt = placeholderText;
        fullLayout._infolayer.select('.'+title)
            .attr({'data-unformatted': txt})
            .text(txt)
            .on('mouseover.opacity',function(){
                d3.select(this).transition()
                    .duration(100).style('opacity',1);
            })
            .on('mouseout.opacity',function(){
                d3.select(this).transition()
                    .duration(1000).style('opacity',0);
            });
    }

    if(gd._context.editable){
        if(!txt) setPlaceholder();

        el.call(svgTextUtils.makeEditable)
            .on('edit', function(text) {
                if(colorbar) {
                    var trace = gd._fullData[cbnum];
                    if(plots.traceIs(trace, 'markerColorscale')) {
                        Plotly.restyle(gd, 'marker.colorbar.title', text, cbnum);
                    } else Plotly.restyle(gd, 'colorbar.title', text, cbnum);
                }
                else Plotly.relayout(gd,prop,text);
            })
            .on('cancel', function(){
                this.text(this.attr('data-unformatted'))
                    .call(titleLayout);
            })
            .on('input', function(d){
                this.text(d || ' ').attr(options)
                    .selectAll('tspan.line')
                        .attr(options);
            });
    }
    else if(!txt || txt.match(/Click to enter .+ title/)) {
        el.remove();
    }
    el.classed('js-placeholder',isplaceholder);
};
<|endoftext|>


<commit_before>/* eslint-disable react/require-default-props */
/* Taken from https://github.com/react-native-training/react-native-elements
 * since we only need badge component. Tweaked the component class since we do not
 * need extra logic present in the code.
 */

import React from 'react';

import PropTypes from 'prop-types';
import { StyleSheet, Dimensions, Text, View, TouchableOpacity, ViewPropTypes } from 'react-native';
import { SUSSOL_ORANGE } from '../globalStyles/index';

const Badge = props => {
  const {
    containerStyle,
    textStyle,
    badgeStyle,
    onPress,
    Component = onPress ? TouchableOpacity : View,
    value,
    ...attributes
  } = props;

  return (
    <View style={containerStyle}>
      <Component {...attributes} style={badgeStyle} onPress={onPress}>
        <Text style={textStyle}>{value}</Text>
      </Component>
    </View>
  );
};

Badge.propTypes = {
  containerStyle: ViewPropTypes.style,
  badgeStyle: ViewPropTypes.style,
  textStyle: Text.propTypes.style,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  onPress: PropTypes.func,
  Component: PropTypes.elementType,
};

Badge.defaultProps = {
  containerStyle: {},
  textStyle: { fontSize: 16, color: '#FFF', paddingHorizontal: 4, fontWeight: 'bold' },
  badgeStyle: {
    alignSelf: 'center',
    width: Dimensions.get('window').width / 25,
    height: Dimensions.get('window').height / 30,
    borderRadius: 10,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: SUSSOL_ORANGE,
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: '#fff',
  },
};

export default Badge;
<commit_msg>Add use of forwardRef in Badge component<commit_after>/* eslint-disable react/prop-types */
/* eslint-disable react/require-default-props */

import React from 'react';

import PropTypes from 'prop-types';
import { StyleSheet, Dimensions, Text, View, TouchableOpacity, ViewPropTypes } from 'react-native';
import { SUSSOL_ORANGE } from '../globalStyles/index';

const BadgeComponent = (props, ref) => {
  const {
    containerStyle = localStyles.badgeStyle,
    textStyle = localStyles.textStyle,
    badgeStyle,
    onPress,
    Component = onPress ? TouchableOpacity : View,
    value,
    ...attributes
  } = props;

  return (
    <Component {...attributes} ref={ref} style={containerStyle} onPress={onPress}>
      <Text style={textStyle}>{value}</Text>
    </Component>
  );
};

const localStyles = StyleSheet.create({
  badgeStyle: {
    alignSelf: 'center',
    width: Dimensions.get('window').width / 25,
    height: Dimensions.get('window').height / 30,
    borderRadius: 10,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: SUSSOL_ORANGE,
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: '#fff',
  },
  textStyle: { fontSize: 16, color: '#FFF', paddingHorizontal: 4, fontWeight: 'bold' },
});

const Badge = React.forwardRef(BadgeComponent);

Badge.propTypes = {
  containerStyle: ViewPropTypes.style,
  badgeStyle: ViewPropTypes.style,
  textStyle: Text.propTypes.style,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  onPress: PropTypes.func,
  Component: PropTypes.elementType,
};

export default Badge;
<|endoftext|>


<commit_before>'use strict';

Connector.trackSelector = '.player-controls__title';

Connector.artistSelector = '.player-controls__artists';

Connector.trackArtSelector = '.slider__item_playing .track__cover';

Connector.isPlaying = () => $('body').hasClass('body_state_playing');

(function() {
	let actualObserver;
	let playerObserver = new MutationObserver(() => {
		let playerSelector = document.querySelector('.page-station');
		if (playerSelector !== null) {
			if (!actualObserver) {
				actualObserver = new MutationObserver(Connector.onStateChanged);
				actualObserver.observe(playerSelector, {
					subtree: true,
					childList: true,
					attributes: true,
					characterData: true
				});
			}
		} else if (actualObserver) {
			actualObserver.disconnect();
			actualObserver = null;
		}
	});

	playerObserver.observe(document.body, {
		subtree: true,
		childList: true,
		attributes: false,
		characterData: false
	});
})();
<commit_msg>Remove unused file<commit_after><|endoftext|>