<commit_before>import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';

import RaisedButton from 'src/RaisedButton';
import Guide from 'src/Guide';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import ButtonRadioGroup from 'src/ButtonRadioGroup';
import MaterialTextField from 'src/MaterialTextField';
import Dialog from 'src/Dialog';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Guide.json';

import 'scss/containers/app/modules/pop/PopExamples.scss';
import 'scss/containers/app/modules/pop/GuideExamples.scss';

class GuideExamples extends Component {

    constructor(props) {

        super(props);

        this.Type = Object.keys(Guide.Type).map(item => ({
            className: `type-${item.toLowerCase()}`,
            iconCls: 'fas fa-check',
            text: item,
            value: Guide.Type[item]
        }));

        this.state = {
            type: Guide.Type.INFO,
            message: 'Message',
            guideVisible: {}
        };

    }

    updateField = (key, value) => {
        let state = {};
        state[key] = value;
        this.setState(state);
    };

    show = id => {

        const {guideVisible} = this.state;

        guideVisible[id] = true;

        this.setState({
            guideVisible
        });

    };

    hide = id => {

        const {guideVisible} = this.state;

        guideVisible[id] = false;

        this.setState({
            guideVisible
        });

    };

    render() {

        const {type, message, guideVisible} = this.state;

        return (

Guide

                    Guide
                    is a global display notification alert information .

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="Basic"/>

                                <ButtonRadioGroup data={this.Type}
                                                  value={type}
                                                  onChange={item => this.updateField('type', item.value)}/>

                                <MaterialTextField theme={MaterialTextField.Theme.HIGHLIGHT}
                                                   value={message}
                                                   onChange={value => this.updateField('message', value)}/>

                                        <RaisedButton ref={el => this.trigger5 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Top Left"
                                                      onClick={() => this.show(5)}/>
                                        <RaisedButton ref={el => this.trigger6 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Top"
                                                      onClick={() => this.show(6)}/>
                                        <RaisedButton ref={el => this.trigger7 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Top right"
                                                      onClick={() => this.show(7)}/>

                                        <RaisedButton ref={el => this.trigger11 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Right Top"
                                                      onClick={() => this.show(11)}/>
                                        <RaisedButton ref={el => this.trigger12 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Right"
                                                      onClick={() => this.show(12)}/>
                                        <RaisedButton ref={el => this.trigger13 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Right Bottom"
                                                      onClick={() => this.show(13)}/>

                                        <RaisedButton ref={el => this.trigger2 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Bottom Left"
                                                      onClick={() => this.show(2)}/>
                                        <RaisedButton ref={el => this.trigger3 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Bottom"
                                                      onClick={() => this.show(3)}/>
                                        <RaisedButton ref={el => this.trigger4 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Bottom Right"
                                                      onClick={() => this.show(4)}/>

                                        <RaisedButton ref={el => this.trigger8 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Left Top"
                                                      onClick={() => this.show(8)}/>
                                        <RaisedButton ref={el => this.trigger9 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Left"
                                                      onClick={() => this.show(9)}/>
                                        <RaisedButton ref={el => this.trigger10 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Left Bottom"
                                                      onClick={() => this.show(10)}/>

                                        <RaisedButton ref={el => this.trigger14 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Center"
                                                      onClick={() => this.show(14)}/>

                                <Guide visible={guideVisible[2]}
                                       type={type}
                                       triggerEl={this.trigger2}
                                       position={Guide.Position.BOTTOM_LEFT}
                                       onRequestClose={() => this.hide(2)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[3]}
                                       type={type}
                                       triggerEl={this.trigger3}
                                       position={Guide.Position.BOTTOM}
                                       onRequestClose={() => this.hide(3)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[4]}
                                       type={type}
                                       triggerEl={this.trigger4}
                                       position={Guide.Position.BOTTOM_RIGHT}
                                       onRequestClose={() => this.hide(4)}>
                                    {message}
                                </Guide>

                                <Guide visible={guideVisible[5]}
                                       type={type}
                                       triggerEl={this.trigger5}
                                       position={Guide.Position.TOP_LEFT}
                                       onRequestClose={() => this.hide(5)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[6]}
                                       type={type}
                                       triggerEl={this.trigger6}
                                       position={Guide.Position.TOP}
                                       onRequestClose={() => this.hide(6)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[7]}
                                       type={type}
                                       triggerEl={this.trigger7}
                                       position={Guide.Position.TOP_RIGHT}
                                       onRequestClose={() => this.hide(7)}>
                                    {message}
                                </Guide>

                                <Guide visible={guideVisible[8]}
                                       type={type}
                                       triggerEl={this.trigger8}
                                       position={Guide.Position.LEFT_TOP}
                                       onRequestClose={() => this.hide(8)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[9]}
                                       type={type}
                                       triggerEl={this.trigger9}
                                       position={Guide.Position.LEFT}
                                       onRequestClose={() => this.hide(9)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[10]}
                                       type={type}
                                       triggerEl={this.trigger10}
                                       position={Guide.Position.LEFT_BOTTOM}
                                       onRequestClose={() => this.hide(10)}>
                                    {message}
                                </Guide>

                                <Guide visible={guideVisible[11]}
                                       type={type}
                                       triggerEl={this.trigger11}
                                       position={Guide.Position.RIGHT_TOP}
                                       onRequestClose={() => this.hide(11)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[12]}
                                       type={type}
                                       triggerEl={this.trigger12}
                                       position={Guide.Position.RIGHT}
                                       onRequestClose={() => this.hide(12)}>
                                    {message}
                                </Guide>
                                <Guide visible={guideVisible[13]}
                                       type={type}
                                       triggerEl={this.trigger13}
                                       position={Guide.Position.RIGHT_BOTTOM}
                                       onRequestClose={() => this.hide(13)}>
                                    {message}
                                </Guide>

                                <Guide visible={guideVisible[14]}
                                       type={type}
                                       triggerEl={this.trigger14}
                                       position={Guide.Position.CENTER}
                                       onRequestClose={() => this.hide(14)}>
                                    {message}
                                </Guide>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Guide in Dialog"/>

                                <RaisedButton className="trigger-button"
                                              value="Show Dialog"
                                              onClick={() => this.show(15)}/>

                                <Dialog visible={guideVisible[15]}
                                        onRequestClose={() => this.hide(15)}>
                                    {
                                        dialogContentEl =>

                                                <RaisedButton ref={el => this.trigger16 = findDOMNode(el)}
                                                              className="dialog-trigger-button"
                                                              value="Toggle Guide"
                                                              onClick={() => this.show(16)}/>
                                                <Guide visible={guideVisible[16]}
                                                       type={type}
                                                       triggerEl={this.trigger16}
                                                       parentEl={dialogContentEl}
                                                       position={Guide.Position.BOTTOM_LEFT}
                                                       onRequestClose={() => this.hide(16)}>
                                                    {message}
                                                </Guide>

                                    }
                                </Dialog>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};

export default GuideExamples;
<commit_msg>update GuideExamples<commit_after>import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';

import RaisedButton from 'src/RaisedButton';
import Guide from 'src/Guide';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import ButtonRadioGroup from 'src/ButtonRadioGroup';
import MaterialTextField from 'src/MaterialTextField';
import Dialog from 'src/Dialog';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Guide.json';

import 'scss/containers/app/modules/pop/PopExamples.scss';
import 'scss/containers/app/modules/pop/GuideExamples.scss';

class GuideExamples extends Component {

    constructor(props) {

        super(props);

        this.Type = Object.keys(Guide.Type).map(item => ({
            className: `type-${item.toLowerCase()}`,
            iconCls: 'fas fa-check',
            text: item,
            value: Guide.Type[item]
        }));

        this.state = {
            type: Guide.Type.INFO,
            message: 'Message',
            popVisible: {}
        };

    }

    updateField = (key, value) => {
        let state = {};
        state[key] = value;
        this.setState(state);
    };

    show = id => {

        const popVisible = {...this.state.popVisible};
        popVisible[id] = true;

        this.setState({
            popVisible
        });

    };

    hide = id => {

        const popVisible = {...this.state.popVisible};
        popVisible[id] = false;

        this.setState({
            popVisible
        });

    };

    render() {

        const {type, message, popVisible} = this.state;

        return (

Guide

                    Guide
                    is a global display notification alert information .

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="Basic"/>

                                <ButtonRadioGroup data={this.Type}
                                                  value={type}
                                                  onChange={item => this.updateField('type', item.value)}/>

                                <MaterialTextField theme={MaterialTextField.Theme.HIGHLIGHT}
                                                   value={message}
                                                   onChange={value => this.updateField('message', value)}/>

                                        <RaisedButton ref={el => this.trigger5 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Top Left"
                                                      onClick={() => this.show(5)}/>
                                        <RaisedButton ref={el => this.trigger6 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Top"
                                                      onClick={() => this.show(6)}/>
                                        <RaisedButton ref={el => this.trigger7 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Top right"
                                                      onClick={() => this.show(7)}/>

                                        <RaisedButton ref={el => this.trigger11 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Right Top"
                                                      onClick={() => this.show(11)}/>
                                        <RaisedButton ref={el => this.trigger12 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Right"
                                                      onClick={() => this.show(12)}/>
                                        <RaisedButton ref={el => this.trigger13 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Right Bottom"
                                                      onClick={() => this.show(13)}/>

                                        <RaisedButton ref={el => this.trigger2 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Bottom Left"
                                                      onClick={() => this.show(2)}/>
                                        <RaisedButton ref={el => this.trigger3 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Bottom"
                                                      onClick={() => this.show(3)}/>
                                        <RaisedButton ref={el => this.trigger4 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Bottom Right"
                                                      onClick={() => this.show(4)}/>

                                        <RaisedButton ref={el => this.trigger8 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Left Top"
                                                      onClick={() => this.show(8)}/>
                                        <RaisedButton ref={el => this.trigger9 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Left"
                                                      onClick={() => this.show(9)}/>
                                        <RaisedButton ref={el => this.trigger10 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Left Bottom"
                                                      onClick={() => this.show(10)}/>

                                        <RaisedButton ref={el => this.trigger14 = findDOMNode(el)}
                                                      className="trigger-position-button"
                                                      value="Center"
                                                      onClick={() => this.show(14)}/>

                                <Guide visible={popVisible[2]}
                                       type={type}
                                       triggerEl={this.trigger2}
                                       position={Guide.Position.BOTTOM_LEFT}
                                       onRequestClose={() => this.hide(2)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[3]}
                                       type={type}
                                       triggerEl={this.trigger3}
                                       position={Guide.Position.BOTTOM}
                                       onRequestClose={() => this.hide(3)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[4]}
                                       type={type}
                                       triggerEl={this.trigger4}
                                       position={Guide.Position.BOTTOM_RIGHT}
                                       onRequestClose={() => this.hide(4)}>
                                    {message}
                                </Guide>

                                <Guide visible={popVisible[5]}
                                       type={type}
                                       triggerEl={this.trigger5}
                                       position={Guide.Position.TOP_LEFT}
                                       onRequestClose={() => this.hide(5)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[6]}
                                       type={type}
                                       triggerEl={this.trigger6}
                                       position={Guide.Position.TOP}
                                       onRequestClose={() => this.hide(6)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[7]}
                                       type={type}
                                       triggerEl={this.trigger7}
                                       position={Guide.Position.TOP_RIGHT}
                                       onRequestClose={() => this.hide(7)}>
                                    {message}
                                </Guide>

                                <Guide visible={popVisible[8]}
                                       type={type}
                                       triggerEl={this.trigger8}
                                       position={Guide.Position.LEFT_TOP}
                                       onRequestClose={() => this.hide(8)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[9]}
                                       type={type}
                                       triggerEl={this.trigger9}
                                       position={Guide.Position.LEFT}
                                       onRequestClose={() => this.hide(9)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[10]}
                                       type={type}
                                       triggerEl={this.trigger10}
                                       position={Guide.Position.LEFT_BOTTOM}
                                       onRequestClose={() => this.hide(10)}>
                                    {message}
                                </Guide>

                                <Guide visible={popVisible[11]}
                                       type={type}
                                       triggerEl={this.trigger11}
                                       position={Guide.Position.RIGHT_TOP}
                                       onRequestClose={() => this.hide(11)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[12]}
                                       type={type}
                                       triggerEl={this.trigger12}
                                       position={Guide.Position.RIGHT}
                                       onRequestClose={() => this.hide(12)}>
                                    {message}
                                </Guide>
                                <Guide visible={popVisible[13]}
                                       type={type}
                                       triggerEl={this.trigger13}
                                       position={Guide.Position.RIGHT_BOTTOM}
                                       onRequestClose={() => this.hide(13)}>
                                    {message}
                                </Guide>

                                <Guide visible={popVisible[14]}
                                       type={type}
                                       triggerEl={this.trigger14}
                                       position={Guide.Position.CENTER}
                                       onRequestClose={() => this.hide(14)}>
                                    {message}
                                </Guide>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Guide in Dialog"/>

                                <RaisedButton className="trigger-button"
                                              value="Show Dialog"
                                              onClick={() => this.show(15)}/>

                                <Dialog visible={popVisible[15]}
                                        onRequestClose={() => this.hide(15)}>
                                    {
                                        dialogContentEl =>

                                                <RaisedButton ref={el => this.trigger16 = findDOMNode(el)}
                                                              className="dialog-trigger-button"
                                                              value="Toggle Guide"
                                                              onClick={() => this.show(16)}/>
                                                <Guide visible={popVisible[16]}
                                                       type={type}
                                                       triggerEl={this.trigger16}
                                                       parentEl={dialogContentEl}
                                                       position={Guide.Position.BOTTOM_LEFT}
                                                       onRequestClose={() => this.hide(16)}>
                                                    {message}
                                                </Guide>

                                    }
                                </Dialog>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};

export default GuideExamples;
<|endoftext|>


<commit_before>//TODO: resolve data/@src and script/@src. either here, or in a separate module.
//TODO: remove nodejs dependencies
//TODO: decide on a friendly, portable interface to this module. streaming is possible, but maybe not very portable.

var sax = require("@jbeard/sax"),
    strict = true, // set to false for html-mode
    parser;

function merge(o1,o2){
    Object.keys(o2).forEach(function(k){
        o1[k] = o2[k];
    });
    return o1;
}

function getNormalizedAttributeName(attr){
  return attr.uri ? '{' + attr.uri + '}' + attr.local : attr.local;
}

function copyNsAttrObj(o){
    var r = {};
    Object.keys(o).forEach(function(k){
        var attr = o[k];
        r[getNormalizedAttributeName(attr)] = attr.value;
    });
    return r;
}

function transform(xmlString){
    parser = sax.parser(strict,{trim : false, xmlns : true});

    var rootJson,
        currentJson,
        expressionAttributeCache,      //we cache them because in sax-js attributes get processed before the nodes they're attached to,
                                            //and this is the only way we can capture their row/col numbers.
                                            //so when we finally find one, it gets popped off the stack.
        jsonStack = [],
        allTransitions = [],                 //we keep a reference to these so we can clean up the onTransition property later
        traversingInContentTagStack = [],
        cachedContentTagStartPosition,
        attributeValueLineColumnCache = {},
        idCount = {},
        cachedOpenWakaPosition;

    function createInvokeJson(node){
        var invoke = merge(
                    {
                        $line : cachedOpenWakaPosition.line,
                        $column : cachedOpenWakaPosition.column,
                        $type: node.local
                    },
                    copyNsAttrObj(node.attributes));

        //FIXME: for now, assume that document is valid, and currentJson is a state.
        //TODO: maybe verify that we are in a state
        currentJson.invokes = currentJson.invokes || [];
        currentJson.invokes.push(invoke);

        return currentJson = invoke;
    }

    function createActionJson(node){
        var action = merge(
                    {
                        $line : cachedOpenWakaPosition.line,
                        $column : cachedOpenWakaPosition.column,
                        $type: node.local
                    },
                    copyNsAttrObj(node.attributes));

        //console.log('action node',node);

        var actionContainer;
        if(Array.isArray(currentJson)){
            //this will be onExit and onEntry
            currentJson.push(action);
        }else if(currentJson.$type === 'scxml' && action.$type === 'script'){
            //top-level script
            currentJson.rootScripts = currentJson.rootScripts || [];
            currentJson.rootScripts.push(action);
        }else{
            //if it's any other action
            currentJson.actions = currentJson.actions || [];
            currentJson.actions.push(action);
        }

        return currentJson = action;
    }

    function createDataJson(node){
        currentJson =
            merge({
                $line : cachedOpenWakaPosition.line,
                $column : cachedOpenWakaPosition.column,
                $type : 'data'
            },
            copyNsAttrObj(node.attributes));
        return currentJson;
    }

    //TODO: avoid duplicate code
    function generateId(type){
        if(idCount[type] === undefined) idCount[type] = 0;

        var count = idCount[type]++;
        return '$generated-' + type + '-' + count;
    }

    function createStateJson(node, isRoot){
        var state = copyNsAttrObj(node.attributes);

        if(state.initial){
          state.initial = state.initial.split(/\s+/);
          if(state.initial.length === 1) state.initial = state.initial[0];
        }

        if(state.type){
            state.isDeep = state.type === 'deep' ? true : false;
        }

        //"state" is the default, so you don't need to explicitly write it
        if(node.local !== 'schema') state.$type = node.local;

        if(!state.id){
          state.id = generateId(state.$type);
        }

        if(currentJson){
            if(isRoot){
              currentJson.rootState = state;
              delete currentJson.rootState.datamodel;   //delete "datamodel" attribute on scxml root element
            }else {
              if(!currentJson.states){
                  currentJson.states = [];
              }
              currentJson.states.push(state);
            }
        }

        return currentJson = state;
    }

    function createTransitionJson(node){

        var transition = copyNsAttrObj(node.attributes);

        //target can either be a string, an array (for multiple targets, e.g. targeting, or undefined
        if(transition.target){
            //console.log('transition',transition);
            transition.target = transition.target.trim().split(/\s+/);
            if(transition.target.length === 1){
                transition.target = transition.target[0];
            }
        }

        if(currentJson){
            if(!currentJson.transitions){
                currentJson.transitions = [];
            }

            currentJson.transitions.push(transition);
        }

        allTransitions.push(transition);

        return currentJson = transition;
    }

    function createExpression(attrName, attrValue){
        var pos = attributeValueLineColumnCache[attrName];
        return {
            $line : pos.line,
            $column : pos.column,
            expr : attrValue
        };
    }

    var tagActions = {
        "scxml": function(node){
            if(!rootJson){
              return rootJson = createStateJson(node, true);
            } else if(currentJson.$type === 'content'){
              return createStateJson(node, true);
            } else {
              throw new Error('Unexpected scxml open tag');
            }
        },
        "initial": createStateJson,
        "history":createStateJson,
        "state":createStateJson,
        "parallel":createStateJson,
        "final":createStateJson,

        //transitions/action containers
        "transition" : createTransitionJson,

        "onentry":function(node){
            currentJson.onEntry = currentJson.onEntry || [];
            let block = [];
            currentJson.onEntry.push(block);
            currentJson = block;
        },
        "onexit":function(node){
            currentJson.onExit = currentJson.onExit || [];
            let block = [];
            currentJson.onExit.push(block);
            currentJson = block;
        },

        //actions
        "foreach" : createActionJson,
        "raise" : createActionJson,
        "log": createActionJson,
        "assign": function(node){
          traversingInContentTagStack.push(node);
          cachedContentTagStartPosition = {
            line : parser.line,
            column : parser.column,
            position : parser.position
          };
          createActionJson.apply(this, arguments);
        },
        "script":createActionJson,
        "cancel":createActionJson,
        "send":createActionJson,

        //children of send/invoke
        "param": function(node){
          currentJson.params = currentJson.params || [];
          var attr = copyNsAttrObj(node.attributes);
          currentJson.params.push(attr);
          currentJson = attr;
        },
        "content":function(node){
          //on invoke
          if(currentJson.$type === 'invoke'){
            currentJson.content = {
              $line : parser.line,
              $column : parser.column,
              $type : 'content'
            };
            currentJson = currentJson.content;
          }else{
            traversingInContentTagStack.push(node);
            cachedContentTagStartPosition = {
              line : parser.line,
              column : parser.column,
              position : parser.position
            }
          };
        },

        //these are treated a bit special - TODO: normalize/decide on a representation
        "if" : createActionJson,
        "elseif" : createActionJson,
        "else" : createActionJson,

        //data
        "datamodel":function(node){
          //console.log('datamodel currentJson',currentJson);
          var datamodel = merge(
            {
                $line : cachedOpenWakaPosition.line,
                $column : cachedOpenWakaPosition.column,
                $type: node.local,
                declarations : []
            },
            copyNsAttrObj(node.attributes));

          currentJson.datamodel = datamodel;
          currentJson = datamodel;
        },
        "data":function(node){
          //console.log('data currentJson',currentJson);
          traversingInContentTagStack.push(node);
          cachedContentTagStartPosition = {
            line : parser.line,
            column : parser.column,
            position : parser.position
          };
          currentJson.declarations.push(createDataJson(node));
        },

        "invoke": createInvokeJson,
        "finalize": function(node){
          return currentJson = currentJson.finalize = node;
        },
        "donedata" : function(node){
          return currentJson = currentJson.donedata = {};
        }
    };

    expressionAttributeCache = {};  //TODO: put in onstart or something like that

    parser.onopentag = function (node) {
        //console.log("open tag",node.local, parser.line, parser.column, parser.position);

        if(traversingInContentTagStack.length){
          traversingInContentTagStack.push(node);
          return;
        }

        if(tagActions[node.local]){
            tagActions[node.local](node);

            jsonStack.push(currentJson);
            //console.log('current json now',currentJson,jsonStack.length);

            //merge in the current expression attribute cache
            merge(currentJson,expressionAttributeCache);

            expressionAttributeCache = {};  //clear the expression attribute cache
        } else {
            createActionJson(node);
            jsonStack.push(currentJson);
            merge(currentJson,expressionAttributeCache);
            expressionAttributeCache = {};
        }
        //console.log('currentJson',currentJson,'jsonStack',jsonStack);
    };

    var EXPRESSION_ATTRS = [ 'cond',
                            'array',
                            'location',
                            'namelist',
                            'idlocation'];

    parser.onopentagstart = function(tagName){
      //console.log('onopentagstart',tagName,parser.line,parser.column);
    };

    parser.onopenwaka = function(){
      //console.log('onopenwaka',parser.line,parser.column);
      cachedOpenWakaPosition = { line :  parser.line, column : parser.column };
    };

    parser.onclosetag = function(tag){
        //console.log("close tag",tag);
        var localName = tag.split(':').pop();

        //console.log('currentJson', currentJson);

        if(traversingInContentTagStack.length){
          var lastTag = traversingInContentTagStack.pop();
          if(lastTag.local !== tag){
            throw new Error(`Mismatched start and end tags: start ${lastTag.local}, end ${tag}`);
          }
          if(!traversingInContentTagStack.length){    //we reached the bottom. capture the content string based on parser position
            let re = new RegExp(`</${tag}\\s*>`, 'g')
            let content = xmlString.substring(cachedContentTagStartPosition.position, parser.position);
            let match, lastMatch;
            while (match = re.exec(content)) {
              lastMatch = match;
            }
            if(lastMatch){
              content = content.slice(0, lastMatch.index);
              if(!currentJson) throw new Error('No currentJson for tag ${tag}');
              else
              currentJson.content = {
                $line : cachedContentTagStartPosition.line,
                $column : cachedContentTagStartPosition.column,
                content : content
              }
              //FIXME: make sure that we have an accurate start position.
              cachedContentTagStartPosition = null;
            }
          }
        }

        if(!traversingInContentTagStack.length){
          jsonStack.pop();
          currentJson = jsonStack[jsonStack.length - 1];
          attributeValueLineColumnCache = {};
          //console.log('currentJson',currentJson,'jsonStack',jsonStack);
        }
    };

    //parser.onattributenameend = function(attrName){
    //  console.log('onattributenameend', attrName, parser.line, parser.column);
    //}

    parser.onattributevaluestart = function () {
      if(traversingInContentTagStack.length) return;
      //console.log('onattributevaluestart', parser.attribName, parser.line, parser.column);
      attributeValueLineColumnCache[parser.attribName] = { line :  parser.line, column : parser.column };
    }

    //parser.onattributevalueend = function(){
    //  console.log('onattributevalueend', parser.attribName, parser.attribValue, parser.line, parser.column);
    //}

    parser.onattribute = function (attr) {
        if(traversingInContentTagStack.length) return;

        //console.log('onattribute ',attr, parser.line, parser.column, parser.position);
        //if attribute name ends with 'expr' or is one of the other ones enumerated above
        //then cache him and his position
        if( attr.name.match(/^.*expr$/) ||
            EXPRESSION_ATTRS.indexOf(attr.name) > -1){
            expressionAttributeCache[getNormalizedAttributeName(attr)] = createExpression(attr.name, attr.value);
        }
    };

    parser.onerror = function (e) {
        // an error happened.
        throw e;
    };

    parser.ontext = function (t) {
        if(traversingInContentTagStack.length) return;
        //console.log(t, traversingInContentTag, currentJson);
        //the only text we care about is that inside of <script> and <content>
        if(currentJson && currentJson.$type){
            if(currentJson.$type === 'script'){
                currentJson.content = t;        //I don't think we need a separate expression for this w/ line/col mapping
            }
        }
    };

    parser.oncdata = function (t) {
        currentJson.content = t;
    }

    parser.onend = function () {
        //do some scrubbing of root attributes
        delete rootJson.xmlns;
        //delete rootJson.type;     //it can be useful to leave in 'type' === 'scxml'
        delete rootJson.version;

        if(typeof rootJson.datamodel === 'string') delete rootJson.datamodel;       //this would happen if we have, e.g. state.datamodel === 'ecmascript'

        //change the property name of transition event to something nicer
        allTransitions.forEach(function(transition){
            transition.onTransition = transition.actions;
            delete transition.actions;
        });
    };

    parser.write(xmlString).close();

    return rootJson;

}

module.exports = transform;
<commit_msg>Added trim to initial state parsing<commit_after>//TODO: resolve data/@src and script/@src. either here, or in a separate module.
//TODO: remove nodejs dependencies
//TODO: decide on a friendly, portable interface to this module. streaming is possible, but maybe not very portable.

var sax = require("@jbeard/sax"),
    strict = true, // set to false for html-mode
    parser;

function merge(o1,o2){
    Object.keys(o2).forEach(function(k){
        o1[k] = o2[k];
    });
    return o1;
}

function getNormalizedAttributeName(attr){
  return attr.uri ? '{' + attr.uri + '}' + attr.local : attr.local;
}

function copyNsAttrObj(o){
    var r = {};
    Object.keys(o).forEach(function(k){
        var attr = o[k];
        r[getNormalizedAttributeName(attr)] = attr.value;
    });
    return r;
}

function transform(xmlString){
    parser = sax.parser(strict,{trim : false, xmlns : true});

    var rootJson,
        currentJson,
        expressionAttributeCache,      //we cache them because in sax-js attributes get processed before the nodes they're attached to,
                                            //and this is the only way we can capture their row/col numbers.
                                            //so when we finally find one, it gets popped off the stack.
        jsonStack = [],
        allTransitions = [],                 //we keep a reference to these so we can clean up the onTransition property later
        traversingInContentTagStack = [],
        cachedContentTagStartPosition,
        attributeValueLineColumnCache = {},
        idCount = {},
        cachedOpenWakaPosition;

    function createInvokeJson(node){
        var invoke = merge(
                    {
                        $line : cachedOpenWakaPosition.line,
                        $column : cachedOpenWakaPosition.column,
                        $type: node.local
                    },
                    copyNsAttrObj(node.attributes));

        //FIXME: for now, assume that document is valid, and currentJson is a state.
        //TODO: maybe verify that we are in a state
        currentJson.invokes = currentJson.invokes || [];
        currentJson.invokes.push(invoke);

        return currentJson = invoke;
    }

    function createActionJson(node){
        var action = merge(
                    {
                        $line : cachedOpenWakaPosition.line,
                        $column : cachedOpenWakaPosition.column,
                        $type: node.local
                    },
                    copyNsAttrObj(node.attributes));

        //console.log('action node',node);

        var actionContainer;
        if(Array.isArray(currentJson)){
            //this will be onExit and onEntry
            currentJson.push(action);
        }else if(currentJson.$type === 'scxml' && action.$type === 'script'){
            //top-level script
            currentJson.rootScripts = currentJson.rootScripts || [];
            currentJson.rootScripts.push(action);
        }else{
            //if it's any other action
            currentJson.actions = currentJson.actions || [];
            currentJson.actions.push(action);
        }

        return currentJson = action;
    }

    function createDataJson(node){
        currentJson =
            merge({
                $line : cachedOpenWakaPosition.line,
                $column : cachedOpenWakaPosition.column,
                $type : 'data'
            },
            copyNsAttrObj(node.attributes));
        return currentJson;
    }

    //TODO: avoid duplicate code
    function generateId(type){
        if(idCount[type] === undefined) idCount[type] = 0;

        var count = idCount[type]++;
        return '$generated-' + type + '-' + count;
    }

    function createStateJson(node, isRoot){
        var state = copyNsAttrObj(node.attributes);

        if(state.initial){
          state.initial = state.initial.trim().split(/\s+/);
          if(state.initial.length === 1) state.initial = state.initial[0];
        }

        if(state.type){
            state.isDeep = state.type === 'deep' ? true : false;
        }

        //"state" is the default, so you don't need to explicitly write it
        if(node.local !== 'schema') state.$type = node.local;

        if(!state.id){
          state.id = generateId(state.$type);
        }

        if(currentJson){
            if(isRoot){
              currentJson.rootState = state;
              delete currentJson.rootState.datamodel;   //delete "datamodel" attribute on scxml root element
            }else {
              if(!currentJson.states){
                  currentJson.states = [];
              }
              currentJson.states.push(state);
            }
        }

        return currentJson = state;
    }

    function createTransitionJson(node){

        var transition = copyNsAttrObj(node.attributes);

        //target can either be a string, an array (for multiple targets, e.g. targeting, or undefined
        if(transition.target){
            //console.log('transition',transition);
            transition.target = transition.target.trim().split(/\s+/);
            if(transition.target.length === 1){
                transition.target = transition.target[0];
            }
        }

        if(currentJson){
            if(!currentJson.transitions){
                currentJson.transitions = [];
            }

            currentJson.transitions.push(transition);
        }

        allTransitions.push(transition);

        return currentJson = transition;
    }

    function createExpression(attrName, attrValue){
        var pos = attributeValueLineColumnCache[attrName];
        return {
            $line : pos.line,
            $column : pos.column,
            expr : attrValue
        };
    }

    var tagActions = {
        "scxml": function(node){
            if(!rootJson){
              return rootJson = createStateJson(node, true);
            } else if(currentJson.$type === 'content'){
              return createStateJson(node, true);
            } else {
              throw new Error('Unexpected scxml open tag');
            }
        },
        "initial": createStateJson,
        "history":createStateJson,
        "state":createStateJson,
        "parallel":createStateJson,
        "final":createStateJson,

        //transitions/action containers
        "transition" : createTransitionJson,

        "onentry":function(node){
            currentJson.onEntry = currentJson.onEntry || [];
            let block = [];
            currentJson.onEntry.push(block);
            currentJson = block;
        },
        "onexit":function(node){
            currentJson.onExit = currentJson.onExit || [];
            let block = [];
            currentJson.onExit.push(block);
            currentJson = block;
        },

        //actions
        "foreach" : createActionJson,
        "raise" : createActionJson,
        "log": createActionJson,
        "assign": function(node){
          traversingInContentTagStack.push(node);
          cachedContentTagStartPosition = {
            line : parser.line,
            column : parser.column,
            position : parser.position
          };
          createActionJson.apply(this, arguments);
        },
        "script":createActionJson,
        "cancel":createActionJson,
        "send":createActionJson,

        //children of send/invoke
        "param": function(node){
          currentJson.params = currentJson.params || [];
          var attr = copyNsAttrObj(node.attributes);
          currentJson.params.push(attr);
          currentJson = attr;
        },
        "content":function(node){
          //on invoke
          if(currentJson.$type === 'invoke'){
            currentJson.content = {
              $line : parser.line,
              $column : parser.column,
              $type : 'content'
            };
            currentJson = currentJson.content;
          }else{
            traversingInContentTagStack.push(node);
            cachedContentTagStartPosition = {
              line : parser.line,
              column : parser.column,
              position : parser.position
            }
          };
        },

        //these are treated a bit special - TODO: normalize/decide on a representation
        "if" : createActionJson,
        "elseif" : createActionJson,
        "else" : createActionJson,

        //data
        "datamodel":function(node){
          //console.log('datamodel currentJson',currentJson);
          var datamodel = merge(
            {
                $line : cachedOpenWakaPosition.line,
                $column : cachedOpenWakaPosition.column,
                $type: node.local,
                declarations : []
            },
            copyNsAttrObj(node.attributes));

          currentJson.datamodel = datamodel;
          currentJson = datamodel;
        },
        "data":function(node){
          //console.log('data currentJson',currentJson);
          traversingInContentTagStack.push(node);
          cachedContentTagStartPosition = {
            line : parser.line,
            column : parser.column,
            position : parser.position
          };
          currentJson.declarations.push(createDataJson(node));
        },

        "invoke": createInvokeJson,
        "finalize": function(node){
          return currentJson = currentJson.finalize = node;
        },
        "donedata" : function(node){
          return currentJson = currentJson.donedata = {};
        }
    };

    expressionAttributeCache = {};  //TODO: put in onstart or something like that

    parser.onopentag = function (node) {
        //console.log("open tag",node.local, parser.line, parser.column, parser.position);

        if(traversingInContentTagStack.length){
          traversingInContentTagStack.push(node);
          return;
        }

        if(tagActions[node.local]){
            tagActions[node.local](node);

            jsonStack.push(currentJson);
            //console.log('current json now',currentJson,jsonStack.length);

            //merge in the current expression attribute cache
            merge(currentJson,expressionAttributeCache);

            expressionAttributeCache = {};  //clear the expression attribute cache
        } else {
            createActionJson(node);
            jsonStack.push(currentJson);
            merge(currentJson,expressionAttributeCache);
            expressionAttributeCache = {};
        }
        //console.log('currentJson',currentJson,'jsonStack',jsonStack);
    };

    var EXPRESSION_ATTRS = [ 'cond',
                            'array',
                            'location',
                            'namelist',
                            'idlocation'];

    parser.onopentagstart = function(tagName){
      //console.log('onopentagstart',tagName,parser.line,parser.column);
    };

    parser.onopenwaka = function(){
      //console.log('onopenwaka',parser.line,parser.column);
      cachedOpenWakaPosition = { line :  parser.line, column : parser.column };
    };

    parser.onclosetag = function(tag){
        //console.log("close tag",tag);
        var localName = tag.split(':').pop();

        //console.log('currentJson', currentJson);

        if(traversingInContentTagStack.length){
          var lastTag = traversingInContentTagStack.pop();
          if(lastTag.local !== tag){
            throw new Error(`Mismatched start and end tags: start ${lastTag.local}, end ${tag}`);
          }
          if(!traversingInContentTagStack.length){    //we reached the bottom. capture the content string based on parser position
            let re = new RegExp(`</${tag}\\s*>`, 'g')
            let content = xmlString.substring(cachedContentTagStartPosition.position, parser.position);
            let match, lastMatch;
            while (match = re.exec(content)) {
              lastMatch = match;
            }
            if(lastMatch){
              content = content.slice(0, lastMatch.index);
              if(!currentJson) throw new Error('No currentJson for tag ${tag}');
              else
              currentJson.content = {
                $line : cachedContentTagStartPosition.line,
                $column : cachedContentTagStartPosition.column,
                content : content
              }
              //FIXME: make sure that we have an accurate start position.
              cachedContentTagStartPosition = null;
            }
          }
        }

        if(!traversingInContentTagStack.length){
          jsonStack.pop();
          currentJson = jsonStack[jsonStack.length - 1];
          attributeValueLineColumnCache = {};
          //console.log('currentJson',currentJson,'jsonStack',jsonStack);
        }
    };

    //parser.onattributenameend = function(attrName){
    //  console.log('onattributenameend', attrName, parser.line, parser.column);
    //}

    parser.onattributevaluestart = function () {
      if(traversingInContentTagStack.length) return;
      //console.log('onattributevaluestart', parser.attribName, parser.line, parser.column);
      attributeValueLineColumnCache[parser.attribName] = { line :  parser.line, column : parser.column };
    }

    //parser.onattributevalueend = function(){
    //  console.log('onattributevalueend', parser.attribName, parser.attribValue, parser.line, parser.column);
    //}

    parser.onattribute = function (attr) {
        if(traversingInContentTagStack.length) return;

        //console.log('onattribute ',attr, parser.line, parser.column, parser.position);
        //if attribute name ends with 'expr' or is one of the other ones enumerated above
        //then cache him and his position
        if( attr.name.match(/^.*expr$/) ||
            EXPRESSION_ATTRS.indexOf(attr.name) > -1){
            expressionAttributeCache[getNormalizedAttributeName(attr)] = createExpression(attr.name, attr.value);
        }
    };

    parser.onerror = function (e) {
        // an error happened.
        throw e;
    };

    parser.ontext = function (t) {
        if(traversingInContentTagStack.length) return;
        //console.log(t, traversingInContentTag, currentJson);
        //the only text we care about is that inside of <script> and <content>
        if(currentJson && currentJson.$type){
            if(currentJson.$type === 'script'){
                currentJson.content = t;        //I don't think we need a separate expression for this w/ line/col mapping
            }
        }
    };

    parser.oncdata = function (t) {
        currentJson.content = t;
    }

    parser.onend = function () {
        //do some scrubbing of root attributes
        delete rootJson.xmlns;
        //delete rootJson.type;     //it can be useful to leave in 'type' === 'scxml'
        delete rootJson.version;

        if(typeof rootJson.datamodel === 'string') delete rootJson.datamodel;       //this would happen if we have, e.g. state.datamodel === 'ecmascript'

        //change the property name of transition event to something nicer
        allTransitions.forEach(function(transition){
            transition.onTransition = transition.actions;
            delete transition.actions;
        });
    };

    parser.write(xmlString).close();

    return rootJson;

}

module.exports = transform;
<|endoftext|>


<commit_before>angular.module('app.modules')
       .controller('aboutCtrl',aboutCtrl);

function aboutCtrl () {
  var vm = this;
  vm.aboutData = [
    {
      title: 'Road to V2',
      time: 1456751208000,
      text: 'The Codename Of this Library is now officialy Juicy(namespace: jc)!\nTODO:Create a backend based on Express. \nTODO:Build up a compiling workflow with Gulp + Browserify\nTODO:Comment and tag function to add in further releases \nTODO:Compose and Analysis module to add in further releases(optional)',
      featured: true
    },
    {
      title: 'Recent Release v1.4.2',
      time: 1457162347000,
      text: 'Ready For Express Backend',
      featured: true,
    },
    {
      title: 'AngularJS Libs',
      time: 1456420305000,
      text: 'Modified Angular-materialize(including Materialize)\nModified Angular-grid by s-yadav (https://github.com/s-yadav/angulargrid)',
      featured: false,
    },
    {
      title: 'About Me',
      time: 1456420305000,
      text: 'Author : POJOa\nSite : http://src.moe/',
      featured: false
    },
    {
      title: 'v1.4.1',
      time: 1457162347000,
      text: 'Initialization of Compose Module',
      featured: false,
    },
    {
      title: 'Stable Release v1.4 (Nozomi)',
      time: 1456751208000,
      text: 'Optimized performance',
      featured: true,
    },
    {
      title: 'v1.4 RC1 2016.02.28',
      time: 1456675603000,
      text: 'Nozomi is a Stable Version Milestone , from then I\'ll create a backend in express for it.\nOptimized Documentation.\nRenewed Card Style\nRefractor and Added Navbar Order\nRefresh Policy Change',
      featured: false,
    },
    {
      title: 'v1.3 2016.02.25',
      time: 1456420305000,
      text: 'Heavy Refractor of Card/Cards View and components\nUpdated angular-grid\nSolved various tiny bugs\n',
      featured: false,
    },
    {
      title: 'v1.2 2016.02.24',
      time: 1456243200000,
      text: 'Refractor jcSubNav\nEnhancement of Picture Displaying\nDisabled Slider (will be taken into account after next major release)\nAdded App Drawer For Mobile Devices\n',
    },
    {
      title: 'v1.1 2016.02.23',
      time: 1456156800000,
      text: 'Added Navbar Customize Configuration Provider\nAdded Event Service.\nFixed (and disabled) Card Control.\nFixed Navbar Bug , added version badge.\nMinimalized data for Github.',
    },
    {
      title: 'Release v1 2016.02.13',
      time: 1455292800000,
      text: 'Adjust Navbar Style.\nAdded Loading Bar.\nSpecified Feature Cards.\n',
      featured: true
    },
    {
      title: 'Pre-release 2016.02.12',
      time: 1455206400000,
      text: 'Fixed height issue.',
    },
    {
      title: 'v0.4 2016.02.11',
      time: 1455120000000,
      text: 'Unlimited Refreshing! Featured Filter!!',
    },
    {
      title: 'v0.3 2016.02.10',
      time: 1455033600000,
      text: 'Added Cascade Displaying , switched to UI-Router',
    },
    {
      title: 'v0.2 2016.02.09',
      time: 1454947200000,
      text: 'Built Project Skeleton , added cascade displaying',
    },
    {
      title: 'v0.1 2016.02.08',
      time: 1454860800000,
      text: 'Simplified JSON structure',
    }
  ];

}
<commit_msg>timestamp<commit_after>angular.module('app.modules')
       .controller('aboutCtrl',aboutCtrl);

function aboutCtrl () {
  var vm = this;
  vm.aboutData = [
    {
      title: 'Road to V2',
      time: 1456751208000,
      text: 'The Codename Of this Library is now officialy Juicy(namespace: jc)!\nTODO:Create a backend based on Express. \nTODO:Build up a compiling workflow with Gulp + Browserify\nTODO:Comment and tag function to add in further releases \nTODO:Compose and Analysis module to add in further releases(optional)',
      featured: true
    },
    {
      title: 'Recent Release v1.4.2',
      time: 1458012771000,
      text: 'Ready For Express Backend',
      featured: true,
    },
    {
      title: 'AngularJS Libs',
      time: 1456420305000,
      text: 'Modified Angular-materialize(including Materialize)\nModified Angular-grid by s-yadav (https://github.com/s-yadav/angulargrid)',
      featured: false,
    },
    {
      title: 'About Me',
      time: 1456420305000,
      text: 'Author : POJOa\nSite : http://src.moe/',
      featured: false
    },
    {
      title: 'v1.4.1',
      time: 1457162347000,
      text: 'Initialization of Compose Module',
      featured: false,
    },
    {
      title: 'Stable Release v1.4 (Nozomi)',
      time: 1456751208000,
      text: 'Optimized performance',
      featured: true,
    },
    {
      title: 'v1.4 RC1 2016.02.28',
      time: 1456675603000,
      text: 'Nozomi is a Stable Version Milestone , from then I\'ll create a backend in express for it.\nOptimized Documentation.\nRenewed Card Style\nRefractor and Added Navbar Order\nRefresh Policy Change',
      featured: false,
    },
    {
      title: 'v1.3 2016.02.25',
      time: 1456420305000,
      text: 'Heavy Refractor of Card/Cards View and components\nUpdated angular-grid\nSolved various tiny bugs\n',
      featured: false,
    },
    {
      title: 'v1.2 2016.02.24',
      time: 1456243200000,
      text: 'Refractor jcSubNav\nEnhancement of Picture Displaying\nDisabled Slider (will be taken into account after next major release)\nAdded App Drawer For Mobile Devices\n',
    },
    {
      title: 'v1.1 2016.02.23',
      time: 1456156800000,
      text: 'Added Navbar Customize Configuration Provider\nAdded Event Service.\nFixed (and disabled) Card Control.\nFixed Navbar Bug , added version badge.\nMinimalized data for Github.',
    },
    {
      title: 'Release v1 2016.02.13',
      time: 1455292800000,
      text: 'Adjust Navbar Style.\nAdded Loading Bar.\nSpecified Feature Cards.\n',
      featured: true
    },
    {
      title: 'Pre-release 2016.02.12',
      time: 1455206400000,
      text: 'Fixed height issue.',
    },
    {
      title: 'v0.4 2016.02.11',
      time: 1455120000000,
      text: 'Unlimited Refreshing! Featured Filter!!',
    },
    {
      title: 'v0.3 2016.02.10',
      time: 1455033600000,
      text: 'Added Cascade Displaying , switched to UI-Router',
    },
    {
      title: 'v0.2 2016.02.09',
      time: 1454947200000,
      text: 'Built Project Skeleton , added cascade displaying',
    },
    {
      title: 'v0.1 2016.02.08',
      time: 1454860800000,
      text: 'Simplified JSON structure',
    }
  ];

}
<|endoftext|>


<commit_before>'use strict';

const fetch = require('node-fetch');
const logger = require('winston');

const BlinkRetryError = require('../errors/BlinkRetryError');
const Worker = require('./Worker');

class TwilioSmsInboundGambitRelayWorker extends Worker {
  constructor(blink) {
    super(blink);
    this.blink = blink;

    this.baseURL = this.blink.config.gambit.converationsBaseUrl;
    this.apiKey = this.blink.config.gambit.converationsApiKey;

    // Bind process method to queue context
    this.consume = this.consume.bind(this);
  }

  setup() {
    this.queue = this.blink.queues.twilioSmsInboundGambitRelayQ;
  }

  async consume(message) {
    throw new BlinkRetryError('testing', message);
    return;

    const body = JSON.stringify(message.getData());
    const headers = this.getRequestHeaders(message);
    const response = await fetch(
      `${this.baseURL}/receive-message`,
      {
        method: 'POST',
        headers,
        body,
      },
    );

    if (response.status === 200) {
      this.log(
        'debug',
        message,
        response,
        'success_gambit_inbound_relay_response_200',
      );
      return true;
    }

    if (this.checkRetrySuppress(response)) {
      this.log(
        'debug',
        message,
        response,
        'success_gambit_inbound_relay_retry_suppress',
      );
      return true;
    }

    if (response.status === 422) {
      this.log(
        'warning',
        message,
        response,
        'error_gambit_inbound_relay_response_422',
      );
      return false;
    }

    this.log(
      'warning',
      message,
      response,
      'error_gambit_inbound_relay_response_not_200_retry',
    );

    throw new BlinkRetryError(
      `${response.status} ${response.statusText}`,
      message,
    );
  }

  async log(level, message, response, code = 'unexpected_code') {
    const cleanedBody = (await response.text()).replace(/\n/g, '\\n');

    const meta = {
      env: this.blink.config.app.env,
      code,
      worker: this.constructor.name,
      request_id: message ? message.getRequestId() : 'not_parsed',
      response_status: response.status,
      response_status_text: `"${response.statusText}"`,
    };
    // Todo: log error?
    logger.log(level, cleanedBody, meta);
  }

  getRequestHeaders(message) {
    const headers = {
      Authorization: `Basic ${this.apiKey}`,
      'X-Request-ID': message.getRequestId(),
      'Content-type': 'application/json',
    };

    if (message.getRetryAttempt() > 0) {
      headers['x-blink-retry-count'] = message.getRetryAttempt();
    }

    return headers;
  }

  checkRetrySuppress(response) {
    // TODO: create common helper
    const headerResult = response.headers.get(this.blink.config.app.retrySuppressHeader);
    if (!headerResult) {
      return false;
    }
    return headerResult.toLowerCase() === 'true';
  }
}

module.exports = TwilioSmsInboundGambitRelayWorker;
<commit_msg>Remove BlinkRetryError() test in TwilioSmsInboundGambitRelayWorker<commit_after>'use strict';

const fetch = require('node-fetch');
const logger = require('winston');

const BlinkRetryError = require('../errors/BlinkRetryError');
const Worker = require('./Worker');

class TwilioSmsInboundGambitRelayWorker extends Worker {
  constructor(blink) {
    super(blink);
    this.blink = blink;

    this.baseURL = this.blink.config.gambit.converationsBaseUrl;
    this.apiKey = this.blink.config.gambit.converationsApiKey;

    // Bind process method to queue context
    this.consume = this.consume.bind(this);
  }

  setup() {
    this.queue = this.blink.queues.twilioSmsInboundGambitRelayQ;
  }

  async consume(message) {
    const body = JSON.stringify(message.getData());
    const headers = this.getRequestHeaders(message);
    const response = await fetch(
      `${this.baseURL}/receive-message`,
      {
        method: 'POST',
        headers,
        body,
      },
    );

    if (response.status === 200) {
      this.log(
        'debug',
        message,
        response,
        'success_gambit_inbound_relay_response_200',
      );
      return true;
    }

    if (this.checkRetrySuppress(response)) {
      this.log(
        'debug',
        message,
        response,
        'success_gambit_inbound_relay_retry_suppress',
      );
      return true;
    }

    if (response.status === 422) {
      this.log(
        'warning',
        message,
        response,
        'error_gambit_inbound_relay_response_422',
      );
      return false;
    }

    this.log(
      'warning',
      message,
      response,
      'error_gambit_inbound_relay_response_not_200_retry',
    );

    throw new BlinkRetryError(
      `${response.status} ${response.statusText}`,
      message,
    );
  }

  async log(level, message, response, code = 'unexpected_code') {
    const cleanedBody = (await response.text()).replace(/\n/g, '\\n');

    const meta = {
      env: this.blink.config.app.env,
      code,
      worker: this.constructor.name,
      request_id: message ? message.getRequestId() : 'not_parsed',
      response_status: response.status,
      response_status_text: `"${response.statusText}"`,
    };
    // Todo: log error?
    logger.log(level, cleanedBody, meta);
  }

  getRequestHeaders(message) {
    const headers = {
      Authorization: `Basic ${this.apiKey}`,
      'X-Request-ID': message.getRequestId(),
      'Content-type': 'application/json',
    };

    if (message.getRetryAttempt() > 0) {
      headers['x-blink-retry-count'] = message.getRetryAttempt();
    }

    return headers;
  }

  checkRetrySuppress(response) {
    // TODO: create common helper
    const headerResult = response.headers.get(this.blink.config.app.retrySuppressHeader);
    if (!headerResult) {
      return false;
    }
    return headerResult.toLowerCase() === 'true';
  }
}

module.exports = TwilioSmsInboundGambitRelayWorker;
<|endoftext|>


<commit_before>/**
 * Active dialog.
 */

var active;

/**
 * Expose `Dialog`.
 */

exports.Dialog = Dialog;

/**
 * Return a new `Dialog` with the given
 * (optional) `title` and `msg`.
 *
 * @param {String} title or msg
 * @param {String} msg
 * @return {Dialog}
 * @api public
 */

exports.dialog = function(title, msg){
  switch (arguments.length) {
    case 2:
      return new Dialog({ title: title, message: msg });
    case 1:
      return new Dialog({ message: title });
  }
};

/**
 * Initialize a new `Dialog`.
 *
 * Options:
 *
 *    - `title` dialog title
 *    - `message` a message to display
 *
 * Emits:
 *
 *    - `show` when visible
 *    - `hide` when hidden
 *
 * @param {Object} options
 * @api public
 */

function Dialog(options) {
  ui.Emitter.call(this);
  options = options || {};
  this.template = html;
  this.el = $(this.template);
  this.render(options);
  if (active && !active.hiding) active.hide();
  if (Dialog.effect) this.effect(Dialog.effect);
  active = this;
};

/**
 * Inherit from `Emitter.prototype`.
 */

Dialog.prototype = new ui.Emitter;

/**
 * Render with the given `options`.
 *
 * @param {Object} options
 * @api public
 */

Dialog.prototype.render = function(options){
  var el = this.el
    , title = options.title
    , msg = options.message
    , self = this;

  el.find('.close').click(function(){
    self.emit('close');
    self.hide();
    return false;
  });

  el.find('h1').text(title);
  if (!title) el.find('h1').remove();

  // message
  if ('string' == typeof msg) {
    el.find('p').text(msg);
  } else if (msg) {
    el.find('p').replaceWith(msg.el || msg);
  }

  setTimeout(function(){
    el.removeClass('hide');
  }, 0);
};

/**
 * Enable the dialog close link.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.closable = function(){
  this.el.addClass('closable');
  return this;
};

/**
 * Set the effect to `type`.
 *
 * @param {String} type
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.effect = function(type){
  this._effect = type;
  this.el.addClass(type);
  return this;
};

/**
 * Make it modal!
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.modal = function(){
  this._overlay = ui.overlay();
  return this;
};

/**
 * Add an overlay.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.overlay = function(){
  var self = this;
  var overlay = ui.overlay({ closable: true });

  overlay.on('hide', function(){
    self.closedOverlay = true;
    self.hide();
  });

  overlay.on('close', function(){
    self.emit('close');
  });

  this._overlay = overlay;

  return this;
};

/**
 * Close the dialog when the escape key is pressed.
 *
 * @api private
 */

Dialog.prototype.escapable = function(){
  var self = this;
  $(document).bind('keydown.dialog', function(e){
    if (27 != e.which) return;
    $(this).unbind('keydown.dialog');
    self.emit('escape');
    self.hide();
  });
};

/**
 * Show the dialog.
 *
 * Emits "show" event.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.show = function(){
  var overlay = this._overlay;

  this.emit('show');

  if (overlay) {
    overlay.show();
    this.el.addClass('modal');
  }

  // escape
  if (!overlay || overlay.closable) this.escapable();

  this.el.appendTo('body');
  this.el.css({ marginLeft: -(this.el.width() / 2) + 'px' });
  this.emit('show');
  return this;
};

/**
 * Hide the dialog with optional delay of `ms`,
 * otherwise the dialog is removed immediately.
 *
 * Emits "hide" event.
 *
 * @return {Number} ms
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.hide = function(ms){
  var self = this;

  // prevent thrashing
  this.hiding = true;

  // duration
  if (ms) {
    setTimeout(function(){
      self.hide();
    }, ms);
    return this;
  }

  // hide / remove
  this.el.addClass('hide');
  if (this._effect) {
    setTimeout(function(){
      self.remove();
    }, 500);
  } else {
    self.remove();
  }

  // modal
  if (this._overlay && !self.closedOverlay) this._overlay.hide();

  return this;
};

/**
 * Hide the dialog without potential animation.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.remove = function(){
  this.emit('hide');
  this.el.remove();
  $(document).unbind('keydown.dialog');
  return this;
};
<commit_msg>dialog: refactor Dialog#overlay()<commit_after>/**
 * Active dialog.
 */

var active;

/**
 * Expose `Dialog`.
 */

exports.Dialog = Dialog;

/**
 * Return a new `Dialog` with the given
 * (optional) `title` and `msg`.
 *
 * @param {String} title or msg
 * @param {String} msg
 * @return {Dialog}
 * @api public
 */

exports.dialog = function(title, msg){
  switch (arguments.length) {
    case 2:
      return new Dialog({ title: title, message: msg });
    case 1:
      return new Dialog({ message: title });
  }
};

/**
 * Initialize a new `Dialog`.
 *
 * Options:
 *
 *    - `title` dialog title
 *    - `message` a message to display
 *
 * Emits:
 *
 *    - `show` when visible
 *    - `hide` when hidden
 *
 * @param {Object} options
 * @api public
 */

function Dialog(options) {
  ui.Emitter.call(this);
  options = options || {};
  this.template = html;
  this.el = $(this.template);
  this.render(options);
  if (active && !active.hiding) active.hide();
  if (Dialog.effect) this.effect(Dialog.effect);
  active = this;
};

/**
 * Inherit from `Emitter.prototype`.
 */

Dialog.prototype = new ui.Emitter;

/**
 * Render with the given `options`.
 *
 * @param {Object} options
 * @api public
 */

Dialog.prototype.render = function(options){
  var el = this.el
    , title = options.title
    , msg = options.message
    , self = this;

  el.find('.close').click(function(){
    self.emit('close');
    self.hide();
    return false;
  });

  el.find('h1').text(title);
  if (!title) el.find('h1').remove();

  // message
  if ('string' == typeof msg) {
    el.find('p').text(msg);
  } else if (msg) {
    el.find('p').replaceWith(msg.el || msg);
  }

  setTimeout(function(){
    el.removeClass('hide');
  }, 0);
};

/**
 * Enable the dialog close link.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.closable = function(){
  this.el.addClass('closable');
  return this;
};

/**
 * Set the effect to `type`.
 *
 * @param {String} type
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.effect = function(type){
  this._effect = type;
  this.el.addClass(type);
  return this;
};

/**
 * Make it modal!
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.modal = function(){
  this._overlay = ui.overlay();
  return this;
};

/**
 * Add an overlay.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.overlay = function(){
  var self = this;
  var overlay = ui.overlay({ closable: true });

  overlay.on('hide', function(){
    self.closedOverlay = true;
    self.hide();
  });

  overlay.on('close', function(){
    self.emit('close');
  });

  this._overlay = overlay;
  return this;
};

/**
 * Close the dialog when the escape key is pressed.
 *
 * @api private
 */

Dialog.prototype.escapable = function(){
  var self = this;
  $(document).bind('keydown.dialog', function(e){
    if (27 != e.which) return;
    $(this).unbind('keydown.dialog');
    self.emit('escape');
    self.hide();
  });
};

/**
 * Show the dialog.
 *
 * Emits "show" event.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.show = function(){
  var overlay = this._overlay;

  this.emit('show');

  if (overlay) {
    overlay.show();
    this.el.addClass('modal');
  }

  // escape
  if (!overlay || overlay.closable) this.escapable();

  this.el.appendTo('body');
  this.el.css({ marginLeft: -(this.el.width() / 2) + 'px' });
  this.emit('show');
  return this;
};

/**
 * Hide the dialog with optional delay of `ms`,
 * otherwise the dialog is removed immediately.
 *
 * Emits "hide" event.
 *
 * @return {Number} ms
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.hide = function(ms){
  var self = this;

  // prevent thrashing
  this.hiding = true;

  // duration
  if (ms) {
    setTimeout(function(){
      self.hide();
    }, ms);
    return this;
  }

  // hide / remove
  this.el.addClass('hide');
  if (this._effect) {
    setTimeout(function(){
      self.remove();
    }, 500);
  } else {
    self.remove();
  }

  // modal
  if (this._overlay && !self.closedOverlay) this._overlay.hide();

  return this;
};

/**
 * Hide the dialog without potential animation.
 *
 * @return {Dialog} for chaining
 * @api public
 */

Dialog.prototype.remove = function(){
  this.emit('hide');
  this.el.remove();
  $(document).unbind('keydown.dialog');
  return this;
};
<|endoftext|>


<commit_before>define(function(require) {
  var dataHub = require('app/data/DataHub'),
      stateModel = require('app/models/global/StateModel');

  var dataOperationMixin = function(TSuper) {
    return {
      setupDataHandling: function() {
        this._dataHandles = [];

        // Add individual properties based on the dataStatus
        // property of the stateModel
        _setStatusProperties.call(this);
        this._statusChangeHandler = _setStatusProperties.bind(this);
        stateModel.on('change', 'dataStatus', this._statusChangeHandler);
      },
      onDataChange: function(data) {},
      setPrimaryDataHandle: function(handle) {
        handle.done(this.onDataChange.bind(this));
      },
      addDataOperation: function(callbacks, fireOnDataChange) {
        callbacks = Array.isArray(callbacks) ? callbacks : [callbacks];
        callbacks.forEach(function(cb) {
          var handle = dataHub.createDataHandle();
          cb.call(this, handle);
          if (fireOnDataChange !== false) {
            handle.done(this.onDataChange.bind(this));
          }
          this._dataHandles.push(handle);
        }.bind(this));
      },
      dispose: function() {
        // In case this gets called twice, for example,
        // if the model is shared by multiple views that
        // are getting disposed at the same time
        if (!this._hasBeenDisposed) {
          this._dataHandles.forEach(function(handle) {
            handle.dispose();
          });
          stateModel.off(this._statusChangeHandler);
          this._hasBeenDisposed = true;
        }
        TSuper.prototype.dispose.apply(this, arguments);
      }
    };
  };

  // Private functions
  function _setStatusProperties() {
    var dataStatus = stateModel.get('dataStatus');
    this.set('ready', dataStatus === 'ready');
    this.set('error', dataStatus === 'error');
    this.set('loading', dataStatus === 'loading');
  }

  return dataOperationMixin;
});<commit_msg>Fix case issue in require call<commit_after>define(function(require) {
  var dataHub = require('app/data/dataHub'),
      stateModel = require('app/models/global/StateModel');

  var dataOperationMixin = function(TSuper) {
    return {
      setupDataHandling: function() {
        this._dataHandles = [];

        // Add individual properties based on the dataStatus
        // property of the stateModel
        _setStatusProperties.call(this);
        this._statusChangeHandler = _setStatusProperties.bind(this);
        stateModel.on('change', 'dataStatus', this._statusChangeHandler);
      },
      onDataChange: function(data) {},
      setPrimaryDataHandle: function(handle) {
        handle.done(this.onDataChange.bind(this));
      },
      addDataOperation: function(callbacks, fireOnDataChange) {
        callbacks = Array.isArray(callbacks) ? callbacks : [callbacks];
        callbacks.forEach(function(cb) {
          var handle = dataHub.createDataHandle();
          cb.call(this, handle);
          if (fireOnDataChange !== false) {
            handle.done(this.onDataChange.bind(this));
          }
          this._dataHandles.push(handle);
        }.bind(this));
      },
      dispose: function() {
        // In case this gets called twice, for example,
        // if the model is shared by multiple views that
        // are getting disposed at the same time
        if (!this._hasBeenDisposed) {
          this._dataHandles.forEach(function(handle) {
            handle.dispose();
          });
          stateModel.off(this._statusChangeHandler);
          this._hasBeenDisposed = true;
        }
        TSuper.prototype.dispose.apply(this, arguments);
      }
    };
  };

  // Private functions
  function _setStatusProperties() {
    var dataStatus = stateModel.get('dataStatus');
    this.set('ready', dataStatus === 'ready');
    this.set('error', dataStatus === 'error');
    this.set('loading', dataStatus === 'loading');
  }

  return dataOperationMixin;
});<|endoftext|>


<commit_before>let async = require('async');

class DeployManager {
  constructor(options) {
    const self = this;
    this.config = options.config;
    this.logger = options.logger;
    this.blockchainConfig = this.config.blockchainConfig;

    this.events = options.events;
    this.plugins = options.plugins;
    this.blockchain = options.blockchain;
    this.gasLimit = false;
    this.fatalErrors = false;
    this.deployOnlyOnConfig = false;
    this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false;

    this.events.setCommandHandler('deploy:contracts', (cb) => {
      self.deployContracts(cb);
    });
  }

  deployAll(done) {
    let self = this;
    this.logger.info(__("deploying contracts"));
    this.events.emit("deploy:beforeAll");

    self.events.request('contracts:list', (contracts) => {
      async.eachOfSeries(contracts,
        function (contract, key, callback) {
          contract._gasLimit = self.gasLimit;
          self.events.request('deploy:contract', contract, () => {
            callback();
          });
        },
        function (err, _results) {
          if (err) {
            self.logger.error(__("error deploying contracts"));
            self.logger.error(err.message);
            self.logger.debug(err.stack);
          }
          if (contracts.length === 0) {
            self.logger.info(__("no contracts found"));
            return done();
          }
          self.logger.info(__("finished deploying contracts"));
          self.logger.trace(arguments);
          done(err);
        }
      );
    });
  }

  deployContracts(done) {
    let self = this;

    if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
      self.logger.info(__("Blockchain component is disabled in the config").underline);
      this.events.emit('blockchainDisabled', {});
      return done();
    }

    async.waterfall([
      function buildContracts(callback) {
        self.events.request("contracts:build", self.deployOnlyOnConfig, (cb) => {
          callback();
        });
      },

      // TODO: shouldn't be necessary
      function checkCompileOnly(callback){
        if(self.onlyCompile){
          self.events.emit('contractsDeployed');
          return done();
        }
        return callback();
      },

      // TODO: could be implemented as an event (beforeDeployAll)
      function checkIsConnectedToBlockchain(callback) {
        self.blockchain.onReady(() => {
          self.blockchain.assertNodeConnection((err) => {
            callback(err);
          });
        });
      },

      // TODO: this can be done on the fly or as part of the initialization
      function determineDefaultAccount(callback) {
        self.blockchain.determineDefaultAccount((err) => {
          callback(err);
        });
      },

      function deployAllContracts(callback) {
        self.deployAll(function (err) {
          if (!err) {
            self.events.emit('contractsDeployed');
          }
          if (err && self.fatalErrors) {
            return callback(err);
          }
          callback();
        });
      },
      function runAfterDeploy(callback) {
        self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback);
      }
    ], function (err, _result) {
      done(err);
    });
  }

}

module.exports = DeployManager;
<commit_msg>remove unused var<commit_after>let async = require('async');

class DeployManager {
  constructor(options) {
    const self = this;
    this.config = options.config;
    this.logger = options.logger;
    this.blockchainConfig = this.config.blockchainConfig;

    this.events = options.events;
    this.plugins = options.plugins;
    this.blockchain = options.blockchain;
    this.gasLimit = false;
    this.fatalErrors = false;
    this.deployOnlyOnConfig = false;
    this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false;

    this.events.setCommandHandler('deploy:contracts', (cb) => {
      self.deployContracts(cb);
    });
  }

  deployAll(done) {
    let self = this;
    this.logger.info(__("deploying contracts"));
    this.events.emit("deploy:beforeAll");

    self.events.request('contracts:list', (contracts) => {
      async.eachOfSeries(contracts,
        function (contract, key, callback) {
          contract._gasLimit = self.gasLimit;
          self.events.request('deploy:contract', contract, () => {
            callback();
          });
        },
        function (err, _results) {
          if (err) {
            self.logger.error(__("error deploying contracts"));
            self.logger.error(err.message);
            self.logger.debug(err.stack);
          }
          if (contracts.length === 0) {
            self.logger.info(__("no contracts found"));
            return done();
          }
          self.logger.info(__("finished deploying contracts"));
          self.logger.trace(arguments);
          done(err);
        }
      );
    });
  }

  deployContracts(done) {
    let self = this;

    if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
      self.logger.info(__("Blockchain component is disabled in the config").underline);
      this.events.emit('blockchainDisabled', {});
      return done();
    }

    async.waterfall([
      function buildContracts(callback) {
        self.events.request("contracts:build", self.deployOnlyOnConfig, () => {
          callback();
        });
      },

      // TODO: shouldn't be necessary
      function checkCompileOnly(callback){
        if(self.onlyCompile){
          self.events.emit('contractsDeployed');
          return done();
        }
        return callback();
      },

      // TODO: could be implemented as an event (beforeDeployAll)
      function checkIsConnectedToBlockchain(callback) {
        self.blockchain.onReady(() => {
          self.blockchain.assertNodeConnection((err) => {
            callback(err);
          });
        });
      },

      // TODO: this can be done on the fly or as part of the initialization
      function determineDefaultAccount(callback) {
        self.blockchain.determineDefaultAccount((err) => {
          callback(err);
        });
      },

      function deployAllContracts(callback) {
        self.deployAll(function (err) {
          if (!err) {
            self.events.emit('contractsDeployed');
          }
          if (err && self.fatalErrors) {
            return callback(err);
          }
          callback();
        });
      },
      function runAfterDeploy(callback) {
        self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback);
      }
    ], function (err, _result) {
      done(err);
    });
  }

}

module.exports = DeployManager;
<|endoftext|>


<commit_before>$(document).ready(function(){
	showComments();
	hideComments();
})

var showComments = function(){
	$('.show-comments,.comment-count').on('click',function(){
		$('.show-comments').addClass('hide');
		$('.hide-comments').removeClass('hide');
		$('#link-comments').show('slow',function(){
			//animation complete
		})
	});
};

var hideComments = function(){
	$('.hide-comments').on('click',function(){
		$('.hide-comments').addClass('hide');
		$('.show-comments').removeClass('hide');
		$('#link-comments').hide('slow',function(){
			//animation complete
		});
	});
};<commit_msg>Fixed javascript error with showing comments<commit_after>$(document).ready(function(){
	showComments();
	hideComments();
})

var showComments = function(){
	$('.show-comments,.comment-count').on('click',function(){
		$(this).parent().find('.show-comments').addClass('hide');
		$(this).parent().find('.hide-comments').removeClass('hide');
		$(this).parent().find('#link-comments').show('slow',function(){
			//animation complete
		})
	});
};

var hideComments = function(){
	$('.hide-comments').on('click',function(){
		$(this).addClass('hide');
		$(this).parent().find('.show-comments').removeClass('hide');
		$(this).parent().find('#link-comments').hide('slow',function(){
			//animation complete
		});
	});
};<|endoftext|>


<commit_before>import React from 'react';
import { Text, View, TouchableHighlight, ScrollView } from 'react-native';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PropTypes from 'prop-types';
import styles from './styles/LevelPickerStyles';
import { ActionCreators } from '../actions';

class LevelPicker extends React.Component {
    getLevelRow(value, key) {
        const startingLevel = value * 4;
        const levels = [startingLevel + 1, startingLevel + 2, startingLevel + 3, startingLevel + 4];
        return (
            <View key={key} style={styles.columns}>
                {levels.map((lvl, innerKey) => this.getLevelCell(lvl, innerKey))}
            </View>
        );
    }

    getLevelCell(level, key) {
        return level <= this.props.highestLevel ?
        (
            <TouchableHighlight
              underlayColor="#CECDCD"
              activeOpacity={0.5}
              key={key}
              style={styles.cell}
              onPress={() => this.selectLevel(level)}
            >
                <Text style={styles.cellText}>{level}</Text>
            </TouchableHighlight>
        ) : (
            <View key={key} style={styles.cellDisabled} >
                <Text style={styles.cellText}>{level}</Text>
            </View>
        );
    }

    selectLevel(level) {
        this.props.setBoardStateCache(null);
        this.props.setLevel(level);
        this.props.setCompleteRoute('game');
    }

    render() {
        const levelRows = Array.from(Array(10).keys());
        return (
            <View style={styles.levelPicker}>
                <View style={styles.levelPickerHeader}>
                    <TouchableHighlight
                      style={styles.menuButton}
                      underlayColor="#CECDCD"
                      activeOpacity={0.5}
                      onPress={() => this.props.setCompleteRoute('menu')}
                    >
                        <View style={styles.menuContainer}>
                            <View style={styles.backToMenu}>
                                <Text style={styles.menuText}>MENU</Text>
                            </View>
                        </View>
                    </TouchableHighlight>
                    <View style={styles.levelPickerElement}>
                        <View style={styles.menuContainer}>
                            <View style={styles.levelPickerBox}>
                                <Text style={[styles.menuText, styles.levelPickerText]}>
                                    CHOOSE A LEVEL
                                </Text>
                            </View>
                        </View>
                    </View>
                </View>
                <View style={{ flex: 7, marginBottom: 30, width: '80%' }}>
                    <ScrollView>
                        <View style={styles.rows}>
                            {levelRows.map((value, key) => this.getLevelRow(value, key))}
                        </View>
                    </ScrollView>
                </View>
            </View>
        );
    }
}

LevelPicker.propTypes = {
    setCompleteRoute: PropTypes.func.isRequired,
    setLevel: PropTypes.func.isRequired,
    highestLevel: PropTypes.number.isRequired,
    setBoardStateCache: PropTypes.func.isRequired,
};

function mapDispatchToProps(dispatch) {
    return bindActionCreators(ActionCreators, dispatch);
}

function mapStateToProps(state) {
    return {
        level: state.level,
        highestLevel: state.highestLevel,
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(LevelPicker);
<commit_msg>reduce level header size<commit_after>import React from 'react';
import { Text, View, TouchableHighlight, ScrollView } from 'react-native';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PropTypes from 'prop-types';
import styles from './styles/LevelPickerStyles';
import { ActionCreators } from '../actions';

class LevelPicker extends React.Component {
    getLevelRow(value, key) {
        const startingLevel = value * 4;
        const levels = [startingLevel + 1, startingLevel + 2, startingLevel + 3, startingLevel + 4];
        return (
            <View key={key} style={styles.columns}>
                {levels.map((lvl, innerKey) => this.getLevelCell(lvl, innerKey))}
            </View>
        );
    }

    getLevelCell(level, key) {
        return level <= this.props.highestLevel ?
        (
            <TouchableHighlight
              underlayColor="#CECDCD"
              activeOpacity={0.5}
              key={key}
              style={styles.cell}
              onPress={() => this.selectLevel(level)}
            >
                <Text style={styles.cellText}>{level}</Text>
            </TouchableHighlight>
        ) : (
            <View key={key} style={styles.cellDisabled} >
                <Text style={styles.cellText}>{level}</Text>
            </View>
        );
    }

    selectLevel(level) {
        this.props.setBoardStateCache(null);
        this.props.setLevel(level);
        this.props.setCompleteRoute('game');
    }

    render() {
        const levelRows = Array.from(Array(10).keys());
        return (
            <View style={styles.levelPicker}>
                <View style={styles.levelPickerHeader}>
                    <TouchableHighlight
                      style={styles.menuButton}
                      underlayColor="#CECDCD"
                      activeOpacity={0.5}
                      onPress={() => this.props.setCompleteRoute('menu')}
                    >
                        <View style={styles.menuContainer}>
                            <View style={styles.backToMenu}>
                                <Text style={styles.menuText}>MENU</Text>
                            </View>
                        </View>
                    </TouchableHighlight>
                    <View style={styles.levelPickerElement}>
                        <View style={styles.menuContainer}>
                            <View style={styles.levelPickerBox}>
                                <Text style={[styles.menuText, styles.levelPickerText]}>
                                    LEVELS
                                </Text>
                            </View>
                        </View>
                    </View>
                </View>
                <View style={{ flex: 7, marginBottom: 30, width: '80%' }}>
                    <ScrollView>
                        <View style={styles.rows}>
                            {levelRows.map((value, key) => this.getLevelRow(value, key))}
                        </View>
                    </ScrollView>
                </View>
            </View>
        );
    }
}

LevelPicker.propTypes = {
    setCompleteRoute: PropTypes.func.isRequired,
    setLevel: PropTypes.func.isRequired,
    highestLevel: PropTypes.number.isRequired,
    setBoardStateCache: PropTypes.func.isRequired,
};

function mapDispatchToProps(dispatch) {
    return bindActionCreators(ActionCreators, dispatch);
}

function mapStateToProps(state) {
    return {
        level: state.level,
        highestLevel: state.highestLevel,
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(LevelPicker);
<|endoftext|>