<commit_before>import React from 'react-native';
import Router from './Router';
import Route from './Route';
import * as Components from './Common';
import ExNavigator from '@exponent/react-native-navigator';
import ExNavigatorStyles from '@exponent/react-native-navigator/ExNavigatorStyles';
import { BackIcon } from '@exponent/react-native-navigator/ExNavigatorIcons';
import Animations from './Animations';
const {TouchableOpacity, Navigator, StyleSheet, View, Text} = React;
import ReactRouter from './ReactRouter';
import Actions from './Actions';
import debug from './debug';

export class ExRouteAdapter {
    name: string;
    navigator: ExNavigator;
    route: Route;
    props: { [key: string]: any};

    constructor(route: Route, props:{ [key: string]: any} = {}){
        debug("ExRouter constructor"+props.schema);
        if (!route){
            throw new Error("route is not defined ");
        }
        this.route = route;
        this.name = route.name;
        this.title = props.title || route.title;
        if (!this.name){
            throw new Error("name is not defined for route");
        }
        this.props = props || {};
        this.renderScene = this.renderScene.bind(this);
        if (this.route.props.renderRightButton){
            this.renderRightButton = this.route.props.renderRightButton.bind(this.route);
        }
        if (this.route.props.renderTitle){
            this.renderTitle = this.route.props.renderTitle.bind(this.route);
        }
        if (this.route.props.renderLeftButton){
            this.renderLeftButton = this.route.props.renderLeftButton.bind(this.route);
        }
    }

    configureScene() {
        return this.route.props.sceneConfig || Animations.None;
    }

    renderScene(navigator) {
        console.log("PROPS:"+this.props);
        const Component = this.route.component;
        const child = Component ?
            !this.route.wrapRouter ? <Component key={this.route.name} name={this.route.name} {...this.route.props} {...this.props} route={this.route}/>:
                <ReactRouter name={this.route.name+"Router"} {...this.route.props} {...this.props} route={this.route} router={ExRouter}  initial={"_"+this.route.name} footer={null} header={null}>
                    <Components.Route {...this.route.props}  {...this.props} component={Component} name={"_"+this.route.name} type="push" wrapRouter={false} initial={true}/>
                </ReactRouter>
            :
            React.cloneElement(React.Children.only(this.route.children), {...this.route.props, ...this.props, route:this.route});

        const Header = this.route.header;
        const header = Header ? <Header {...this.route.props} {...this.props}/> : null;

        const Footer = this.route.footer;
        const footer = Footer ? <Footer {...this.route.props} {...this.props}/> : null;

        return (
            <View style={styles.transparent}>
                {header}
                {child}
                {footer}
            </View>
        );
    }

    getName(){
        return this.route.name;
    }

    getTitle() {
        debug("TITLE ="+this.route.title+" for route="+this.route.name);
        return this.title || "";
    }

    getBackButtonTitle(navigator, index, state){
        let previousIndex = index - 1;
        let previousRoute = state.routeStack[previousIndex];
        let title = previousRoute.getTitle(navigator, previousIndex, state);
        const res = title.length>10 ? null : title;
        return this.route.props.leftTitle || res;
    }

    renderLeftButton(navigator, index, state){
        if (this.route.props.onLeft && this.route.props.leftTitle) {
            return (<TouchableOpacity
              touchRetentionOffset={ExNavigator.Styles.barButtonTouchRetentionOffset}
              onPress={() => this.route.props.onLeft({...this.route.props, ...this.props})}
              style={[ExNavigator.Styles.barLeftButton, this.route.props.leftButtonStyle]}>
                <Text
                  style={[ExNavigator.Styles.barLeftButtonText, this.route.props.leftButtonTextStyle]}>{this.route.props.leftTitle}</Text>
            </TouchableOpacity>);
        }

        if (index === 0 || index < navigator.getCurrentRoutes().length-1) {
            return null;
        }

        let previousIndex = index - 1;
        let previousRoute = state.routeStack[previousIndex];
        if (previousRoute.renderBackButton) {
            return previousRoute.renderBackButton(navigator, previousIndex, state);
        }

        let title = this.getBackButtonTitle(navigator, index, state);

        if (title) {
            var buttonText =
                <Text
                    numberOfLines={1}
                    style={[
            ExNavigatorStyles.barButtonText,
            ExNavigatorStyles.barBackButtonText,
            navigator.props.barButtonTextStyle,
          ]}
                >
                    {title}
                </Text>;
        }

        return (
            <TouchableOpacity
                pressRetentionOffset={ExNavigatorStyles.barButtonPressRetentionOffset}
                onPress={() => Actions.pop()}
                style={[ExNavigatorStyles.barBackButton, styles.backButtonStyle]}>
                <BackIcon
                    style={[
            ExNavigatorStyles.barButtonIcon,
            navigator.props.barButtonIconStyle,
          ]}
                />
                {buttonText}
            </TouchableOpacity>
        );
    }

    renderRightButton(navigator, index, state) {
        if (this.route.props.onRight && this.route.props.rightTitle){
            return (<TouchableOpacity
                touchRetentionOffset={ExNavigator.Styles.barButtonTouchRetentionOffset}
                onPress={() => this.route.props.onRight({...this.route.props, ...this.props})}
                style={[ExNavigator.Styles.barRightButton, this.route.props.rightButtonStyle]}>
                <Text style={[ExNavigator.Styles.barRightButtonText, this.route.props.rightButtonTextStyle]}>{this.route.props.rightTitle}</Text>
            </TouchableOpacity>);
        } else {
            return null;
        }
    }
}

class ExNavigationBar extends Navigator.NavigationBar {
    constructor(props){
        super(props);
        this.state = {};
    }
    render(){
        const route = this.props.router.nextRoute || this.props.router.currentRoute;
        if (route.props.hideNavBar === false){
            return super.render();
        }
        if (this.props.router.props.hideNavBar || route.props.hideNavBar){
            return null;
        }
        return super.render();
    }
}

export default class ExRouter extends React.Component {
    router: Router;

    constructor(props){
        super(props);
        this.onPop = this.onPop.bind(this);
        this.onPush = this.onPush.bind(this);
        this.onPop = this.onPop.bind(this);
        this.onPush = this.onPush.bind(this);
        this.onReset = this.onReset.bind(this);
        this.onReplace = this.onReplace.bind(this);
        this.onJump = this.onJump.bind(this);
        this.state = {};
    }

    onPush(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onPush){
            const res = this.props.onPush(route, props);
            if (!res){
                return false;
            }
        }
        this.refs.nav.push(new ExRouteAdapter(route, props));
        debug("PUSHED TO:"+route.name);
        return true;
    }

    onReplace(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onReplace){
            const res = this.props.onReplace(route, props);
            if (!res){
                return false;
            }
        }
        this.refs.nav.replace(new ExRouteAdapter(route, props));
        return true;
    }

    /***
     * Reset every scene with an array of routes
     * @param route defined route
     */

     onReset(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onReset){
            const res = this.props.onReset(route, props);
            if (!res){
                return false;
            }
        }
        this.refs.nav.immediatelyResetRouteStack([new ExRouteAdapter(route, props)]);
        return true;
    }

    onJump(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onJump){
            const res = this.props.onJump(route, props);
            if (!res){
                return false;
            }
        }
        const navigator = this.refs.nav;
        const routes = navigator.getCurrentRoutes();
        const exist = routes.filter(el=>el.getName()==route.name);
        if (exist.length){
            navigator.jumpTo(exist[0]);
        } else {
            navigator.push(new ExRouteAdapter(route, props));

        }
        this.setState({selected: route.name});
        return true;
    }

    onPop(num: number){
        if (this.props.onPop){
            const res = this.props.onPop(num);
            if (!res){
                return false;
            }
        }
        this.refs.nav.pop();
        return true;
    }

    onModal(route: Route, props:{ [key: string]: any}):boolean {
        let element = React.createElement(route.component, Object.assign({}, route.props, props));
        this.setState({modal: element});
        return true;
    }

    onDismiss(){
        this.setState({modal: null});
    }

    render() {
        const router = this.props.router;
        if (!router){
            throw new Error("No router is defined");
        }
        const Header = this.props.header;
        const header = Header ? <Header {...this.props} {...this.state}/> : null;

        const Footer = this.props.footer;
        const footer = Footer ? <Footer {...this.props} {...this.state}/> : null;
        debug("RENDER ROUTER:",router.name);
        debug(Object.keys(router.routes));
        debug(router.stack);

        return (
            <View style={styles.transparent}>
                {header}
                <ExNavigator ref="nav" initialRouteStack={router.stack.map(route => new ExRouteAdapter(router.routes[route]))}
                         style={styles.transparent}
                         sceneStyle={{ paddingTop: 0 }}
                         renderNavigationBar={props=><ExNavigationBar navigationStyles={Navigator.NavigationBar.StylesIOS} {...props} router={router}/>}
                    {...this.props}
                />
                {footer}
                {this.state.modal}
            </View>
        );
    }

}

var styles = StyleSheet.create({
    container: {
        position: 'absolute',
        top:0,
        bottom:0,
        left:0,
        right:0,
        backgroundColor:'transparent',
        justifyContent: 'center',
        alignItems: 'center',
    },
    transparent: {
        flex:1,
        backgroundColor: "transparent"
    },
    barTitleText: {
        fontFamily: '.HelveticaNeueInterface-MediumP4',
        fontSize: 17,
        marginTop: 11,
    },

});

<commit_msg>remove debug info<commit_after>import React from 'react-native';
import Router from './Router';
import Route from './Route';
import * as Components from './Common';
import ExNavigator from '@exponent/react-native-navigator';
import ExNavigatorStyles from '@exponent/react-native-navigator/ExNavigatorStyles';
import { BackIcon } from '@exponent/react-native-navigator/ExNavigatorIcons';
import Animations from './Animations';
const {TouchableOpacity, Navigator, StyleSheet, View, Text} = React;
import ReactRouter from './ReactRouter';
import Actions from './Actions';
import debug from './debug';

export class ExRouteAdapter {
    name: string;
    navigator: ExNavigator;
    route: Route;
    props: { [key: string]: any};

    constructor(route: Route, props:{ [key: string]: any} = {}){
        debug("ExRouter constructor"+props.schema);
        if (!route){
            throw new Error("route is not defined ");
        }
        this.route = route;
        this.name = route.name;
        this.title = props.title || route.title;
        if (!this.name){
            throw new Error("name is not defined for route");
        }
        this.props = props || {};
        this.renderScene = this.renderScene.bind(this);
        if (this.route.props.renderRightButton){
            this.renderRightButton = this.route.props.renderRightButton.bind(this.route);
        }
        if (this.route.props.renderTitle){
            this.renderTitle = this.route.props.renderTitle.bind(this.route);
        }
        if (this.route.props.renderLeftButton){
            this.renderLeftButton = this.route.props.renderLeftButton.bind(this.route);
        }
    }

    configureScene() {
        return this.route.props.sceneConfig || Animations.None;
    }

    renderScene(navigator) {
        const Component = this.route.component;
        const child = Component ?
            !this.route.wrapRouter ? <Component key={this.route.name} name={this.route.name} {...this.route.props} {...this.props} route={this.route}/>:
                <ReactRouter name={this.route.name+"Router"} {...this.route.props} {...this.props} route={this.route} router={ExRouter}  initial={"_"+this.route.name} footer={null} header={null}>
                    <Components.Route {...this.route.props}  {...this.props} component={Component} name={"_"+this.route.name} type="push" wrapRouter={false} initial={true}/>
                </ReactRouter>
            :
            React.cloneElement(React.Children.only(this.route.children), {...this.route.props, ...this.props, route:this.route});

        const Header = this.route.header;
        const header = Header ? <Header {...this.route.props} {...this.props}/> : null;

        const Footer = this.route.footer;
        const footer = Footer ? <Footer {...this.route.props} {...this.props}/> : null;

        return (
            <View style={styles.transparent}>
                {header}
                {child}
                {footer}
            </View>
        );
    }

    getName(){
        return this.route.name;
    }

    getTitle() {
        debug("TITLE ="+this.route.title+" for route="+this.route.name);
        return this.title || "";
    }

    getBackButtonTitle(navigator, index, state){
        let previousIndex = index - 1;
        let previousRoute = state.routeStack[previousIndex];
        let title = previousRoute.getTitle(navigator, previousIndex, state);
        const res = title.length>10 ? null : title;
        return this.route.props.leftTitle || res;
    }

    renderLeftButton(navigator, index, state){
        if (this.route.props.onLeft && this.route.props.leftTitle) {
            return (<TouchableOpacity
              touchRetentionOffset={ExNavigator.Styles.barButtonTouchRetentionOffset}
              onPress={() => this.route.props.onLeft({...this.route.props, ...this.props})}
              style={[ExNavigator.Styles.barLeftButton, this.route.props.leftButtonStyle]}>
                <Text
                  style={[ExNavigator.Styles.barLeftButtonText, this.route.props.leftButtonTextStyle]}>{this.route.props.leftTitle}</Text>
            </TouchableOpacity>);
        }

        if (index === 0 || index < navigator.getCurrentRoutes().length-1) {
            return null;
        }

        let previousIndex = index - 1;
        let previousRoute = state.routeStack[previousIndex];
        if (previousRoute.renderBackButton) {
            return previousRoute.renderBackButton(navigator, previousIndex, state);
        }

        let title = this.getBackButtonTitle(navigator, index, state);

        if (title) {
            var buttonText =
                <Text
                    numberOfLines={1}
                    style={[
            ExNavigatorStyles.barButtonText,
            ExNavigatorStyles.barBackButtonText,
            navigator.props.barButtonTextStyle,
          ]}
                >
                    {title}
                </Text>;
        }

        return (
            <TouchableOpacity
                pressRetentionOffset={ExNavigatorStyles.barButtonPressRetentionOffset}
                onPress={() => Actions.pop()}
                style={[ExNavigatorStyles.barBackButton, styles.backButtonStyle]}>
                <BackIcon
                    style={[
            ExNavigatorStyles.barButtonIcon,
            navigator.props.barButtonIconStyle,
          ]}
                />
                {buttonText}
            </TouchableOpacity>
        );
    }

    renderRightButton(navigator, index, state) {
        if (this.route.props.onRight && this.route.props.rightTitle){
            return (<TouchableOpacity
                touchRetentionOffset={ExNavigator.Styles.barButtonTouchRetentionOffset}
                onPress={() => this.route.props.onRight({...this.route.props, ...this.props})}
                style={[ExNavigator.Styles.barRightButton, this.route.props.rightButtonStyle]}>
                <Text style={[ExNavigator.Styles.barRightButtonText, this.route.props.rightButtonTextStyle]}>{this.route.props.rightTitle}</Text>
            </TouchableOpacity>);
        } else {
            return null;
        }
    }
}

class ExNavigationBar extends Navigator.NavigationBar {
    constructor(props){
        super(props);
        this.state = {};
    }
    render(){
        const route = this.props.router.nextRoute || this.props.router.currentRoute;
        if (route.props.hideNavBar === false){
            return super.render();
        }
        if (this.props.router.props.hideNavBar || route.props.hideNavBar){
            return null;
        }
        return super.render();
    }
}

export default class ExRouter extends React.Component {
    router: Router;

    constructor(props){
        super(props);
        this.onPop = this.onPop.bind(this);
        this.onPush = this.onPush.bind(this);
        this.onPop = this.onPop.bind(this);
        this.onPush = this.onPush.bind(this);
        this.onReset = this.onReset.bind(this);
        this.onReplace = this.onReplace.bind(this);
        this.onJump = this.onJump.bind(this);
        this.state = {};
    }

    onPush(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onPush){
            const res = this.props.onPush(route, props);
            if (!res){
                return false;
            }
        }
        this.refs.nav.push(new ExRouteAdapter(route, props));
        debug("PUSHED TO:"+route.name);
        return true;
    }

    onReplace(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onReplace){
            const res = this.props.onReplace(route, props);
            if (!res){
                return false;
            }
        }
        this.refs.nav.replace(new ExRouteAdapter(route, props));
        return true;
    }

    /***
     * Reset every scene with an array of routes
     * @param route defined route
     */

     onReset(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onReset){
            const res = this.props.onReset(route, props);
            if (!res){
                return false;
            }
        }
        this.refs.nav.immediatelyResetRouteStack([new ExRouteAdapter(route, props)]);
        return true;
    }

    onJump(route: Route, props:{ [key: string]: any}):boolean {
        if (this.props.onJump){
            const res = this.props.onJump(route, props);
            if (!res){
                return false;
            }
        }
        const navigator = this.refs.nav;
        const routes = navigator.getCurrentRoutes();
        const exist = routes.filter(el=>el.getName()==route.name);
        if (exist.length){
            navigator.jumpTo(exist[0]);
        } else {
            navigator.push(new ExRouteAdapter(route, props));

        }
        this.setState({selected: route.name});
        return true;
    }

    onPop(num: number){
        if (this.props.onPop){
            const res = this.props.onPop(num);
            if (!res){
                return false;
            }
        }
        this.refs.nav.pop();
        return true;
    }

    onModal(route: Route, props:{ [key: string]: any}):boolean {
        let element = React.createElement(route.component, Object.assign({}, route.props, props));
        this.setState({modal: element});
        return true;
    }

    onDismiss(){
        this.setState({modal: null});
    }

    render() {
        const router = this.props.router;
        if (!router){
            throw new Error("No router is defined");
        }
        const Header = this.props.header;
        const header = Header ? <Header {...this.props} {...this.state}/> : null;

        const Footer = this.props.footer;
        const footer = Footer ? <Footer {...this.props} {...this.state}/> : null;
        debug("RENDER ROUTER:",router.name);
        debug(Object.keys(router.routes));
        debug(router.stack);

        return (
            <View style={styles.transparent}>
                {header}
                <ExNavigator ref="nav" initialRouteStack={router.stack.map(route => new ExRouteAdapter(router.routes[route]))}
                         style={styles.transparent}
                         sceneStyle={{ paddingTop: 0 }}
                         renderNavigationBar={props=><ExNavigationBar navigationStyles={Navigator.NavigationBar.StylesIOS} {...props} router={router}/>}
                    {...this.props}
                />
                {footer}
                {this.state.modal}
            </View>
        );
    }

}

var styles = StyleSheet.create({
    container: {
        position: 'absolute',
        top:0,
        bottom:0,
        left:0,
        right:0,
        backgroundColor:'transparent',
        justifyContent: 'center',
        alignItems: 'center',
    },
    transparent: {
        flex:1,
        backgroundColor: "transparent"
    },
    barTitleText: {
        fontFamily: '.HelveticaNeueInterface-MediumP4',
        fontSize: 17,
        marginTop: 11,
    },

});

<|endoftext|>


<commit_before>require('fileapi');

var backbone = require('backbone');
var backboneBase = require('backbone-base');
var getUri = require('get-uri');
var Goodtables = require('../goodtables');
var jsonEditor = require('json-editor');
var jtsInfer = require('jts-infer');
var highlight = require('highlight-redux');
var UploadView = require('./upload');
var registry = require('./registry');
var _ = require('underscore');
var $ = require('jquery');

// Upload data file and populate .resource array with item
DataUploadView = backbone.BaseView.extend({
  events: {
    // Set up and append .resources row
    'change [data-id=input]': function(E) {
      FileAPI.readAsText(FileAPI.getFiles(E.currentTarget)[0], (function (EV) {
        if(EV.type === 'load') {
          getUri(['data', EV.target.type, 'utf-8'].join(':') + ',' + EV.result, (function (E, R) {
            if(E) throw E;

            jtsInfer(R, (function(E, S, SR) {
              if(E) throw E;

              this.options.form.getEditor('root.resources').addRow({
                name: EV.target.name,
                path: EV.target.name,
                schema: S
              });

              // Save data source
              _.last(this.options.form.getEditor('root.resources').rows).dataSource = EV.result;
            }).bind(this));
          }).bind(this));
        } else if( EV.type ==='progress' ) {
          this.setProgress(EV.loaded/EV.total * 100);
        } else {
          this.setError('File upload failed');
        }

        this.$(E.currentTarget).val('');
      }).bind(this));
    },

    'click [data-id=upload-data-file]': function() { this.$('[data-id=input]').trigger('click'); }
  },

  render: function() {
    this.$el
      .append('<input data-id="input" type="file" accept="text/csv" style="display: none;">')

      .append(
        $(this.options.form.theme.getButton('Upload data file', '', 'Upload data file'))
          .attr('data-id', 'upload-data-file')
      );

    return this;
  },

  setError: function() { return this; },
  setProgress: function() { return this; }
});

module.exports = {
  DescriptorEditView: backbone.BaseView.extend({
    activate: function(state) {
      backbone.BaseView.prototype.activate.call(this, state);
      this.layout.upload.activate(state);
      return this;
    },

    delegateEvents: function() {
      backbone.BaseView.prototype.delegateEvents.apply(this, arguments);

      window.APP.$('#validate-resources').on('click', (function() {
        var
          goodTables = new Goodtables({method: 'post'});

        // Clear previous
        window.APP.$('#resources-validation-messages [data-id=messages]').remove();

        _.each(this.layout.form.getEditor('root.resources').rows, function(R) {
          goodTables.run(R.dataSource, JSON.stringify( {fields: _.map(R.schema.properties, function(V, K) {
            return _.extend(V, {name: K}) })}
          )).then(
            function(M) {
              // Ok
              window.APP.$('#resources-validation-messages').append(
                _.map(M.isValid() ? ['Validation Success'] : M.getValidationErrors(), function(M) {
                  return ['
', M.result_message, '
'].join('');
                }));
            }
          );
        });
      }).bind(this));
    },

    initialize: function(options) {
      highlight.configure({useBR: true});
      return backbone.BaseView.prototype.initialize.apply(this, options);
    },

    render: function() {
      this.layout.upload = new UploadView({el: window.APP.$('#upload-data-package'), parent: this});
      this.layout.registryList = new registry.ListView({el: window.APP.$('#registry-list'), parent: this});
      return this;
    },

    // Utility method to remove empty values from object recursive
    compactObject: function(data) {
      _.each(data, function(v, k) {
        if(_.isEmpty(v)) {
          delete data[k];
        } else if(_.isArray(v) || _.isObject(v)) {
          v = this.compactObject(v);

          if(_.isArray(v))
            v = _.compact(v);

          if(_.isEmpty(v))
            delete data[k];
          else data[k] = v;
        }
      }, this);

      return data;
    },

    getFilledValues: function() { return this.compactObject(this.layout.form.getValue()); },
    getValue: function () { return this.layout.form.getValue(); },
    hasChanges: function() { return Boolean(this.changed); },

    reset: function(schema) {
      var formData;

      // Clean up previous state
      if(this.layout.form) {
        formData = this.getFilledValues();
        this.layout.form.destroy();
        this.layout.uploadData.undelegateEvents().remove();
      }

      this.layout.form = new JSONEditor(this.el, {
        schema: schema,
        theme: 'bootstrap3'
      });

      this.layout.uploadData = (new DataUploadView({
        el: this.layout.form.theme.getHeaderButtonHolder(),
        form: this.layout.form,
        parent: this
      })).render();

      this.layout.form.on('ready', (function() {
        // There is no any good way to bind events to custom button or even add cutsom button
        $(this.layout.form.getEditor('root.resources').container)
          .children('h3').append(this.layout.uploadData.el);

        // Detecting changes
        this.changed = false;

        // After `ready` event fired, editor fire `change` event regarding to the initial changes
        this.layout.form.on('change', _.after(2, (function() {
          this.changed = true;
          window.APP.layout.download.reset(this.layout.form.getValue()).activate();
          this.showResult();
        }).bind(this)));

        // If on the previous form was entered values try to apply it to new form
        if(formData) {
          this.layout.form.setValue(_.extend({}, this.layout.form.getValue(formData), formData));

          // Expand editors if it have value
          _.each(this.$('[data-schemapath][data-schemapath!=root]:has(.json-editor-btn-collapse)'), function(E) {
              if(_.isEmpty(this.layout.form.getEditor($(E).data('schemapath')).getValue()))
                $(E).find('.json-editor-btn-collapse').click();
          }, this);
        } else
          // Collapse all
          this.$('.row .json-editor-btn-collapse').click();

      }).bind(this));
    },

    showResult: function() {
      $('#json-code').html(highlight.fixMarkup(
        highlight.highlight('json', JSON.stringify(this.layout.form.getValue(), undefined, 2)).value
      ));

      return this;
    },

    undelegateEvents: function() {
      backbone.BaseView.prototype.undelegateEvents.apply(this, arguments);
      window.APP.$('#validate-resources').off('click');
    }
  })
};<commit_msg>Fixed arguments list<commit_after>require('fileapi');

var backbone = require('backbone');
var backboneBase = require('backbone-base');
var getUri = require('get-uri');
var Goodtables = require('../goodtables');
var jsonEditor = require('json-editor');
var jtsInfer = require('jts-infer');
var highlight = require('highlight-redux');
var UploadView = require('./upload');
var registry = require('./registry');
var _ = require('underscore');
var $ = require('jquery');

// Upload data file and populate .resource array with item
DataUploadView = backbone.BaseView.extend({
  events: {
    // Set up and append .resources row
    'change [data-id=input]': function(E) {
      FileAPI.readAsText(FileAPI.getFiles(E.currentTarget)[0], (function (EV) {
        if(EV.type === 'load') {
          getUri(['data', EV.target.type, 'utf-8'].join(':') + ',' + EV.result, (function (E, R) {
            if(E) throw E;

            jtsInfer(R, (function(E, S, SR) {
              if(E) throw E;

              this.options.form.getEditor('root.resources').addRow({
                name: EV.target.name,
                path: EV.target.name,
                schema: S
              });

              // Save data source
              _.last(this.options.form.getEditor('root.resources').rows).dataSource = EV.result;
            }).bind(this));
          }).bind(this));
        } else if( EV.type ==='progress' ) {
          this.setProgress(EV.loaded/EV.total * 100);
        } else {
          this.setError('File upload failed');
        }

        this.$(E.currentTarget).val('');
      }).bind(this));
    },

    'click [data-id=upload-data-file]': function() { this.$('[data-id=input]').trigger('click'); }
  },

  render: function() {
    this.$el
      .append('<input data-id="input" type="file" accept="text/csv" style="display: none;">')

      .append(
        $(this.options.form.theme.getButton('Upload data file', '', 'Upload data file'))
          .attr('data-id', 'upload-data-file')
      );

    return this;
  },

  setError: function() { return this; },
  setProgress: function() { return this; }
});

module.exports = {
  DescriptorEditView: backbone.BaseView.extend({
    activate: function(state) {
      backbone.BaseView.prototype.activate.call(this, state);
      this.layout.upload.activate(state);
      return this;
    },

    delegateEvents: function() {
      backbone.BaseView.prototype.delegateEvents.apply(this, arguments);

      window.APP.$('#validate-resources').on('click', (function() {
        var
          goodTables = new Goodtables({method: 'post'});

        // Clear previous
        window.APP.$('#resources-validation-messages [data-id=messages]').remove();

        _.each(this.layout.form.getEditor('root.resources').rows, function(R) {
          goodTables.run(R.dataSource, JSON.stringify( {fields: _.map(R.schema.properties, function(V, K) {
            return _.extend(V, {name: K}) })}
          )).then(
            function(M) {
              // Ok
              window.APP.$('#resources-validation-messages').append(
                _.map(M.isValid() ? ['Validation Success'] : M.getValidationErrors(), function(M) {
                  return ['
', M.result_message, '
'].join('');
                }));
            }
          );
        });
      }).bind(this));
    },

    initialize: function(options) {
      highlight.configure({useBR: true});
      return backbone.BaseView.prototype.initialize.call(this, options);
    },

    render: function() {
      this.layout.upload = new UploadView({el: window.APP.$('#upload-data-package'), parent: this});
      this.layout.registryList = new registry.ListView({el: window.APP.$('#registry-list'), parent: this});
      return this;
    },

    // Utility method to remove empty values from object recursive
    compactObject: function(data) {
      _.each(data, function(v, k) {
        if(_.isEmpty(v)) {
          delete data[k];
        } else if(_.isArray(v) || _.isObject(v)) {
          v = this.compactObject(v);

          if(_.isArray(v))
            v = _.compact(v);

          if(_.isEmpty(v))
            delete data[k];
          else data[k] = v;
        }
      }, this);

      return data;
    },

    getFilledValues: function() { return this.compactObject(this.layout.form.getValue()); },
    getValue: function () { return this.layout.form.getValue(); },
    hasChanges: function() { return Boolean(this.changed); },

    reset: function(schema) {
      var formData;

      // Clean up previous state
      if(this.layout.form) {
        formData = this.getFilledValues();
        this.layout.form.destroy();
        this.layout.uploadData.undelegateEvents().remove();
      }

      this.layout.form = new JSONEditor(this.el, {
        schema: schema,
        theme: 'bootstrap3'
      });

      this.layout.uploadData = (new DataUploadView({
        el: this.layout.form.theme.getHeaderButtonHolder(),
        form: this.layout.form,
        parent: this
      })).render();

      this.layout.form.on('ready', (function() {
        // There is no any good way to bind events to custom button or even add cutsom button
        $(this.layout.form.getEditor('root.resources').container)
          .children('h3').append(this.layout.uploadData.el);

        // Detecting changes
        this.changed = false;

        // After `ready` event fired, editor fire `change` event regarding to the initial changes
        this.layout.form.on('change', _.after(2, (function() {
          this.changed = true;
          window.APP.layout.download.reset(this.layout.form.getValue()).activate();
          this.showResult();
        }).bind(this)));

        // If on the previous form was entered values try to apply it to new form
        if(formData) {
          this.layout.form.setValue(_.extend({}, this.layout.form.getValue(formData), formData));

          // Expand editors if it have value
          _.each(this.$('[data-schemapath][data-schemapath!=root]:has(.json-editor-btn-collapse)'), function(E) {
              if(_.isEmpty(this.layout.form.getEditor($(E).data('schemapath')).getValue()))
                $(E).find('.json-editor-btn-collapse').click();
          }, this);
        } else
          // Collapse all
          this.$('.row .json-editor-btn-collapse').click();

      }).bind(this));
    },

    showResult: function() {
      $('#json-code').html(highlight.fixMarkup(
        highlight.highlight('json', JSON.stringify(this.layout.form.getValue(), undefined, 2)).value
      ));

      return this;
    },

    undelegateEvents: function() {
      backbone.BaseView.prototype.undelegateEvents.apply(this, arguments);
      window.APP.$('#validate-resources').off('click');
    }
  })
};<|endoftext|>


<commit_before>$.register({
  rule: [
    'http://amateurfreak.org/share-*.html',
    'http://amateurfreak.org/share.php?id=*',
    'http://images.maxigame.by/share-*.html',
    'http://picfox.org/*',
    'http://www.euro-pic.eu/share.php?id=*',
    'http://www.gratisimage.dk/share-*.html',
    'http://xxx.freeimage.us/share.php?id=*',
    'http://npicture.net/share-*.html',
    'http://www.onlinepic.net/share.php?id=*',
    'http://www.pixsor.com/share.php?id=*',
  ],
  ready: function () {
    'use strict';

    var o = $('#iimg');
    $.openImage(o.src);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>holdthemoan.net<commit_after>$.register({
  rule: [
    'http://amateurfreak.org/share-*.html',
    'http://amateurfreak.org/share.php?id=*',
    'http://images.maxigame.by/share-*.html',
    'http://picfox.org/*',
    'http://www.euro-pic.eu/share.php?id=*',
    'http://www.gratisimage.dk/share-*.html',
    'http://xxx.freeimage.us/share.php?id=*',
    'http://npicture.net/share-*.html',
    'http://www.onlinepic.net/share.php?id=*',
    'http://www.pixsor.com/share.php?id=*',
    'http://holdthemoan.net/x/share-*.html',
  ],
  ready: function () {
    'use strict';

    var o = $('#iimg');
    $.openImage(o.src);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>$.register({
  rule: {
    host: /^(www\.)?(ilix\.in|priva\.us|urlink\.at)$/,
    path: /\/(\w+)/,
  },
  ready: function (m) {
    'use strict';

    var realHost = 'ilix.in';

    // If broken domain then redirect to real domain
    if (m.host[2] !== realHost) {
      var realURL = location.href.replace(m.host[2], realHost);
      $.openLink(realURL);
      return;
    }

    // Iframe redirection
    var f = $.$('iframe[name=ifram]');
    if (f) {
      $.openLink(f.src);
      return;
    }

    // Captcha not supported
    if (!$.$('img#captcha')) {
      // Auto-submit
      $('form[name=frm]').submit();
    }
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>urlink.at<commit_after>$.register({
  rule: {
    host: /^(www\.)?(ilix\.in|priva\.us)$/,
    path: /\/(\w+)/,
  },
  ready: function (m) {
    'use strict';

    var realHost = 'ilix.in';

    // If broken domain then redirect to real domain
    if (m.host[2] !== realHost) {
      var realURL = location.href.replace(m.host[2], realHost);
      $.openLink(realURL);
      return;
    }

    // Iframe redirection
    var f = $.$('iframe[name=ifram]');
    if (f) {
      $.openLink(f.src);
      return;
    }

    // Captcha not supported
    if (!$.$('img#captcha')) {
      // Auto-submit
      $('form[name=frm]').submit();
    }
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>import React, {
  Platform,
  Component,
  Text,
  TouchableOpacity,
  View,
  ListView,
} from 'react-native'
import NavigationBar from 'react-native-navbar'
import Swipeout from 'react-native-swipeout'

import styles from './Styles/RootStyle'
import _ from 'lodash'

// My Components
import Button from './Components/Button'
import ListItem from './Components/ListItem'
import DiscountPicker from './Components/DiscountPicker'
import SettingsButton from './Components/SettingsButton'

const ios = Platform.OS === 'ios'
const android = Platform.OS === 'android'

export default class Root extends React.Component {

  constructor(props) {
    super(props)

    // State
    this.state = {
      rows: [{cents: 0, discount:null}],
      listTopPadding: 0,
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      title: "Checkout Helper",
    }

    // Bind Functions
    this.pressedNumber = this.pressedNumber.bind(this)
    this.pressedClrAll = this.pressedClrAll.bind(this)
    this.pressedClearLast = this.pressedClearLast.bind(this)
    this.pressedBackspace = this.pressedBackspace.bind(this)
    this.pressedAdd = this.pressedAdd.bind(this)
    this.pressedDoubleZero = this.pressedDoubleZero.bind(this)
    this.pressedDiscount = this.pressedDiscount.bind(this)
  }

  componentDidMount() {
    this.setDataSource()

    // https://github.com/facebook/react-native/issues/953
    requestAnimationFrame(this.measureListHolderComponent.bind(this))
  }

  measureListHolderComponent() {
    this.refs.listHolder.measure((ox, oy, width, height) => {
      // TODO - 48?
      this.setState({listTopPadding: height - 48})
    })
  }

  resetDataSource() {
    console.log("resetDataSource")
    this.setState({rows: [0]})
    this.setDataSource()
    this.scrollToBottom()
  }

  convertCentsToDollars(cents, symbol = false) {
    var converted_float = (cents/100).toFixed(2)

    if (symbol === true) {
      return "$" + converted_float
    } else {
      return converted_float
    }
  }

  setRows(rows) {
    this.setState({
      rows: rows
    })

    this.setDataSource(true)
  }

  setDataSource(scroll = false) {
    var _this = this
    object_rows = _.map(this.state.rows, function(n) { return {title: _this.convertCentsToDollars(n.cents, true)} })

    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(object_rows)
    })

    if (scroll === true) {
      this.scrollToBottom()
    }
  }

  // TODO - this doesn't work.
  scrollToBottom() {
    console.log("Scrolling to bottom")
    var ul = this.refs.list
    console.log(ul.scrollProperties)
    console.log("Scrolling to:", ul.scrollProperties.contentLength - 48)
    ul.scrollTo({y: ul.scrollProperties.contentLength - 48})
  }

  renderItem(item, sectionID, rowID) {
    var deleteButton = {
      text: 'Delete',
      onPress: () => { console.log(item, sectionID, rowID) },
      type: 'delete',
      backgroundColor: 'red',
      color: 'white',
      /*
        https://github.com/dancormier/react-native-swipeout/issues/42
        The width property doesn't work yet.
       */
      width: 40,
    }

    return (
      <Swipeout
        right={[deleteButton]}
        rowID={rowID}
        sectionID={sectionID}
        autoClose={true}
        close={(rowID == 0) ? true : false}
      >
        <ListItem item={item} onPress={() => {}} />
      </Swipeout>
    )
  }

  rowFactory(cents = 0, discount = null){
    return {
      cents: cents,
      discount: discount,
    }
  }

  subtotal(){

  }

  // Button Factory
  renderButton(text, additionalStyles=null, onPress=null) {
    var buttonStyles = [styles.button]
    if (additionalStyles !== null) {
      buttonStyles.push(additionalStyles)
    }
    var pressEvent = ((onPress == null) ? this.pressedNumber : onPress )

    return(
      <Button label={text} style={buttonStyles} onPress={pressEvent} />
    )
  }

  pressedNumber(number) {
    console.log("Pressed number: " + number)

    var rows = this.state.rows
    var popped = rows.pop()
    rows.push(this.rowFactory(parseInt(popped.cents + "" + number), popped.discount))
    this.setRows(rows)
  }

  pressedClrAll() {
    console.log("Pressed Clear All")
    this.resetDataSource()
  }

  pressedClearLast() {
    console.log("Pressed Clear Last")

    var rows = this.state.rows
    rows.pop()
    rows.pop()
    rows.push(this.rowFactory())
    this.setRows(rows)
  }

  pressedBackspace() {
    console.log("Pressed Backspace")

    var rows = this.state.rows
    var popped = rows.pop()
    var lastCents = parseInt(popped.cents.toString().slice(0, -1))

    if (isNaN(lastCents)) { lastCents = 0 }
    rows.push(this.rowFactory(lastCents, popped.discount))
    this.setRows(rows)
  }

  pressedAdd() {
    console.log("Pressed Add")

    var rows = this.state.rows
    console.log(rows)
    if (this.canAddNumberToList(rows)) {
      rows.push(this.rowFactory())
      this.setRows(rows)
    }
  }

  // Determines if an operation should succeed or not
  canAddNumberToList() {
    var rows = this.state.rows
    return rows[rows.length-1] != 0
  }

  pressedDoubleZero() {
    console.log("Pressed Double Zero")

    var rows = this.state.rows
    if (this.canAddNumberToList()) {
      var popped = rows.pop()

      rows.push(this.rowFactory(parseInt(popped.cents + "00"), popped.discount))
      rows.push(this.rowFactory())
      this.setRows(rows)
    }
  }

  pressedDiscount() {
    console.log("Pressed Discount")
  }

  render() {
    const leftButtonConfig = {
      title: 'Next',
      handler: () => alert('hello!'),
    }

    return (
      <View style={styles.mainContainer}>
        <NavigationBar
          title={{title: this.state.title}}
          leftButton={
            <SettingsButton
              style={{ marginLeft: 8 }}
              onPress={() => alert('Pressed Settings Button')}/>}
          tintColor="#CCC" />
        <View style={styles.content}>
          <View style={styles.topContent} ref="listHolder">
            <ListView
              dataSource={this.state.dataSource}
              renderRow={this.renderItem.bind(this)}
              style={[styles.listView, {paddingTop: this.state.listTopPadding}]}
              ref="list"
              onContentSizeChange={(newSize)=>{
                this.scrollToBottom()
              }} />
            <View style={styles.topRight}>
              <View style={styles.subtotal}>
                <Text style={styles.medium}>Subtotal:</Text>
                <Text style={styles.largeMonospace}>$0.00</Text>
              </View>
              <View>
                <Text>$4.95 Shipping: $4.95</Text>
              </View>
              <View>
                <Text>6.75% Tax: $4.50</Text>
              </View>
              <View style={styles.total}>
                <Text style={styles.medium}>Total:</Text>
                <Text style={styles.largeMonospace}>$12.50</Text>
              </View>
            </View>
          </View>
          <View style={styles.bottomContent}>

            {/* Top Row */}
            <View style={styles.row}>
              { this.renderButton('7') }
              { this.renderButton('8') }
              { this.renderButton('9') }
              { this.renderButton('Clr All', styles.redButton, this.pressedClrAll) }
            </View>

            {/* 2nd Row */}
            <View style={styles.row}>
              { this.renderButton('4') }
              { this.renderButton('5') }
              { this.renderButton('6') }
              { this.renderButton('Clr Last', styles.redButton, this.pressedClearLast) }
            </View>

            {/* 3rd Row */}
            <View style={styles.row}>
              { this.renderButton('1') }
              { this.renderButton('2') }
              { this.renderButton('3') }
              { this.renderButton('Bksp', styles.redButton, this.pressedBackspace) }
            </View>

            {/* 4th Row */}
            <View style={styles.row}>
              { this.renderButton('0') }
              { this.renderButton('.00', null, this.pressedDoubleZero) }
              { this.renderButton('Add', styles.greenButton, this.pressedAdd) }
              { this.renderButton('Disc', styles.blueButton, this.pressedDiscount) }
            </View>

          </View>
       </View>
      </View>
    )
  }
}
<commit_msg>Subtotal is working.<commit_after>import React, {
  Platform,
  Component,
  Text,
  TouchableOpacity,
  View,
  ListView,
} from 'react-native'
import NavigationBar from 'react-native-navbar'
import Swipeout from 'react-native-swipeout'

import styles from './Styles/RootStyle'
import _ from 'lodash'

// My Components
import Button from './Components/Button'
import ListItem from './Components/ListItem'
import DiscountPicker from './Components/DiscountPicker'
import SettingsButton from './Components/SettingsButton'

const ios = Platform.OS === 'ios'
const android = Platform.OS === 'android'

export default class Root extends React.Component {

  constructor(props) {
    super(props)

    // State
    this.state = {
      rows: [{cents: 0, discount:null}],
      subtotal: 0,
      listTopPadding: 0,
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      title: "Checkout Helper",
    }

    // Bind Functions
    this.pressedNumber = this.pressedNumber.bind(this)
    this.pressedClrAll = this.pressedClrAll.bind(this)
    this.pressedClearLast = this.pressedClearLast.bind(this)
    this.pressedBackspace = this.pressedBackspace.bind(this)
    this.pressedAdd = this.pressedAdd.bind(this)
    this.pressedDoubleZero = this.pressedDoubleZero.bind(this)
    this.pressedDiscount = this.pressedDiscount.bind(this)
  }

  componentDidMount() {
    this.setDataSource()

    // https://github.com/facebook/react-native/issues/953
    requestAnimationFrame(this.measureListHolderComponent.bind(this))
  }

  measureListHolderComponent() {
    this.refs.listHolder.measure((ox, oy, width, height) => {
      // TODO - 48?
      this.setState({listTopPadding: height - 48})
    })
  }

  resetDataSource() {
    console.log("resetDataSource")
    this.setState({
      rows: [this.rowFactory()],
      subtotal: 0,
    })
    this.setDataSource()
    this.scrollToBottom()
  }

  convertCentsToDollars(cents, symbol = false) {
    var converted_float = (cents/100).toFixed(2)

    if (symbol === true) {
      return "$" + converted_float
    } else {
      return converted_float
    }
  }

  setRows(rows) {
    this.setState({
      rows: rows,
    })
    this.setState({
      subtotal: this.subtotal(),
    })

    this.setDataSource(true)
  }

  setDataSource(scroll = false) {
    var _this = this
    object_rows = _.map(this.state.rows, function(n) { return {title: _this.convertCentsToDollars(n.cents, true)} })

    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(object_rows)
    })

    if (scroll === true) {
      this.scrollToBottom()
    }
  }

  // TODO - this doesn't work.
  scrollToBottom() {
    console.log("Scrolling to bottom")
    var ul = this.refs.list
    console.log(ul.scrollProperties)
    console.log("Scrolling to:", ul.scrollProperties.contentLength - 48)
    ul.scrollTo({y: ul.scrollProperties.contentLength - 48})
  }

  renderItem(item, sectionID, rowID) {
    var deleteButton = {
      text: 'Delete',
      onPress: () => { console.log(item, sectionID, rowID) },
      type: 'delete',
      backgroundColor: 'red',
      color: 'white',
      /*
        https://github.com/dancormier/react-native-swipeout/issues/42
        The width property doesn't work yet.
       */
      width: 40,
    }

    return (
      <Swipeout
        right={[deleteButton]}
        rowID={rowID}
        sectionID={sectionID}
        autoClose={true}
        close={(rowID == 0) ? true : false}
      >
        <ListItem item={item} onPress={() => {}} />
      </Swipeout>
    )
  }

  rowFactory(cents = 0, discount = null){
    return {
      cents: cents,
      discount: discount,
    }
  }

  subtotal(){
    var rows = this.state.rows
    var mappedCents = _.map(rows, (n) => {
      return n.cents
    })
    return _.sum(mappedCents)
  }

  // Button Factory
  renderButton(text, additionalStyles=null, onPress=null) {
    var buttonStyles = [styles.button]
    if (additionalStyles !== null) {
      buttonStyles.push(additionalStyles)
    }
    var pressEvent = ((onPress == null) ? this.pressedNumber : onPress )

    return(
      <Button label={text} style={buttonStyles} onPress={pressEvent} />
    )
  }

  pressedNumber(number) {
    console.log("Pressed number: " + number)

    var rows = this.state.rows
    var popped = rows.pop()
    rows.push(this.rowFactory(parseInt(popped.cents + "" + number), popped.discount))
    this.setRows(rows)
  }

  pressedClrAll() {
    console.log("Pressed Clear All")
    this.resetDataSource()
  }

  pressedClearLast() {
    console.log("Pressed Clear Last")

    var rows = this.state.rows
    rows.pop()
    rows.pop()
    rows.push(this.rowFactory())
    this.setRows(rows)
  }

  pressedBackspace() {
    console.log("Pressed Backspace")

    var rows = this.state.rows
    var popped = rows.pop()
    var lastCents = parseInt(popped.cents.toString().slice(0, -1))

    if (isNaN(lastCents)) { lastCents = 0 }
    rows.push(this.rowFactory(lastCents, popped.discount))
    this.setRows(rows)
  }

  pressedAdd() {
    console.log("Pressed Add")

    var rows = this.state.rows
    console.log(rows)
    if (this.canAddNumberToList(rows)) {
      rows.push(this.rowFactory())
      this.setRows(rows)
    }
  }

  // Determines if an operation should succeed or not
  canAddNumberToList() {
    var rows = this.state.rows
    return rows[rows.length-1] != 0
  }

  pressedDoubleZero() {
    console.log("Pressed Double Zero")

    var rows = this.state.rows
    if (this.canAddNumberToList()) {
      var popped = rows.pop()

      rows.push(this.rowFactory(parseInt(popped.cents + "00"), popped.discount))
      rows.push(this.rowFactory())
      this.setRows(rows)
    }
  }

  pressedDiscount() {
    console.log("Pressed Discount")
  }

  render() {
    const leftButtonConfig = {
      title: 'Next',
      handler: () => alert('hello!'),
    }

    return (
      <View style={styles.mainContainer}>
        <NavigationBar
          title={{title: this.state.title}}
          leftButton={
            <SettingsButton
              style={{ marginLeft: 8 }}
              onPress={() => alert('Pressed Settings Button')}/>}
          tintColor="#CCC" />
        <View style={styles.content}>
          <View style={styles.topContent} ref="listHolder">
            <ListView
              dataSource={this.state.dataSource}
              renderRow={this.renderItem.bind(this)}
              style={[styles.listView, {paddingTop: this.state.listTopPadding}]}
              ref="list"
              onContentSizeChange={(newSize)=>{
                this.scrollToBottom()
              }} />
            <View style={styles.topRight}>
              <View style={styles.subtotal}>
                <Text style={styles.medium}>Subtotal:</Text>
                <Text style={styles.largeMonospace}>{this.convertCentsToDollars(this.state.subtotal, true)}</Text>
              </View>
              <View>
                <Text>$4.95 Shipping: $4.95</Text>
              </View>
              <View>
                <Text>Discounts: $4.95</Text>
              </View>
              <View>
                <Text>6.75% Tax: $4.50</Text>
              </View>
              <View style={styles.total}>
                <Text style={styles.medium}>Total:</Text>
                <Text style={styles.largeMonospace}>$12.50</Text>
              </View>
            </View>
          </View>
          <View style={styles.bottomContent}>

            {/* Top Row */}
            <View style={styles.row}>
              { this.renderButton('7') }
              { this.renderButton('8') }
              { this.renderButton('9') }
              { this.renderButton('Clr All', styles.redButton, this.pressedClrAll) }
            </View>

            {/* 2nd Row */}
            <View style={styles.row}>
              { this.renderButton('4') }
              { this.renderButton('5') }
              { this.renderButton('6') }
              { this.renderButton('Clr Last', styles.redButton, this.pressedClearLast) }
            </View>

            {/* 3rd Row */}
            <View style={styles.row}>
              { this.renderButton('1') }
              { this.renderButton('2') }
              { this.renderButton('3') }
              { this.renderButton('Bksp', styles.redButton, this.pressedBackspace) }
            </View>

            {/* 4th Row */}
            <View style={styles.row}>
              { this.renderButton('0') }
              { this.renderButton('.00', null, this.pressedDoubleZero) }
              { this.renderButton('Add', styles.greenButton, this.pressedAdd) }
              { this.renderButton('Disc', styles.blueButton, this.pressedDiscount) }
            </View>

          </View>
       </View>
      </View>
    )
  }
}
<|endoftext|>


<commit_before>/**
 * Automatically log in a user with a userId and key, so they can view/upload to a feedsource.
 */

var app = require('application');

module.exports = function () {
    var feedSourceId, feedVersionId, userId, key;
    if (arguments.length == 4) {
        feedSourceId = arguments[0];
        feedVersionId = arguments[1];
        userId = arguments[2];
        key = arguments[3];
    }
    else if (arguments.length == 3) {
        feedSourceId = arguments[0];
        feedVersionId = null;
        userId = arguments[1];
        key = arguments[3];
    }
    else return;

    $.post('/authenticate',
           {
               userId: userId,
               key: key
           })
        .then(function (data) {
            $('#logged-in-user').text(window.Messages('app.account.logged_in_as', data['username']));
            $('#logout').removeClass('hidden');

            // note: log out is handled in application.js

            app.user = data;

            window.location.hash = '#feed/' + feedSourceId +
                (feedVersionId != null ? '/' + feedVersionId : '');
        })
        .fail(function () {
            // TODO: alert is bad, bad error message, not translatable.
            alert('Invalid key');
        });
}

<commit_msg>Fix autologin for versioned feeds.<commit_after>/**
 * Automatically log in a user with a userId and key, so they can view/upload to a feedsource.
 */

var app = require('application');

module.exports = function () {
    var feedSourceId, feedVersionId, userId, key;

    // yes, this is in fact four arguments, not five, but the Bootstrap router throws an extra null on the end
    if (arguments.length == 5) {
        feedSourceId = arguments[0];
        feedVersionId = arguments[1];
        userId = arguments[2];
        key = arguments[3];
    }
    else if (arguments.length == 4) {
        feedSourceId = arguments[0];
        feedVersionId = null;
        userId = arguments[1];
        key = arguments[2];
    }
    else return;

    $.post('/authenticate',
           {
               userId: userId,
               key: key
           })
        .then(function (data) {
            $('#logged-in-user').text(window.Messages('app.account.logged_in_as', data['username']));
            $('#logout').removeClass('hidden');

            // note: log out is handled in application.js

            app.user = data;

            window.location.hash = '#feed/' + feedSourceId +
                (feedVersionId != null ? '/' + feedVersionId : '');
        })
        .fail(function () {
            // TODO: alert is bad, bad error message, not translatable.
            alert('Invalid key');
        });
}

<|endoftext|>


<commit_before>'use strict';

// Setting up route
angular.module('core').config(['$stateProvider', '$urlRouterProvider',
	function($stateProvider, $urlRouterProvider) {
		// Redirect to home view when route not found
		$urlRouterProvider.otherwise('/');

		// Home state routing
		$stateProvider.
		state('home', {
			url: '/',
			templateUrl: 'modules/core/views/home.client.view.html'
		}).
                state('test', {
                        url: '/test',
                        templateUrl: 'modules/core/views/test.client.view.html'
                }).
		state('item', {
			url: '/item',
			templateUrl: 'modules/core/views/item.client.view.html'
		}).
		state('itemformswizard', {
			url: '/item-form',
			templateUrl: 'modules/core/views/form.item.client.view.html'
		}).
		state('item.forms.wizarda', {
			url: '/item-forma',
			templateUrl: 'modules/core/views/form.item.client.view.html',
			resolve: {
			loadPlugin: function ($ocLazyLoad) {
			return $ocLazyLoad.load([
                        {
                            files: ['modules/core/css/plugins/steps/jquery.steps.css']
                        }
                	    ]);
                	}
            		}
		}).
        	state('item.forms.wizard.step_one', {
        		url: '/item-form/step_one',
            		templateUrl: 'modules/core/views/wizard/step_one.html'
        	})
        	.state('item.forms.wizard.step_two', {
        		url: '/item-form/step_two',
        		 templateUrl: 'modules/core/views/wizard/step_two.html'
        	})
        	.state('item.forms.wizard.step_three', {
            		url: '/item-form/step_three',
            		templateUrl: 'modules/core/views/wizard/step_three.html'
        	})

	;
	}
]);
<commit_msg>Update core.client.routes.js<commit_after>'use strict';

// Setting up route
angular.module('core').config(['$stateProvider', '$urlRouterProvider',
	function($stateProvider, $urlRouterProvider) {
		// Redirect to home view when route not found
		$urlRouterProvider.otherwise('/');

		// Home state routing
		$stateProvider.
		state('home', {
			url: '/',
			templateUrl: 'modules/core/views/home.client.view.html'
		}).
                state('test', {
                        url: '/test',
                        templateUrl: 'modules/core/views/test.client.view.html'
                }).
		state('item', {
			url: '/item',
			templateUrl: 'modules/core/views/item.client.view.html'
		}).
		state('itemformswizard', {
			url: '/item-form',
			templateUrl: 'modules/core/views/form.item.client.view.html',
			resolve: {
			loadPlugin: function ($ocLazyLoad) {
			return $ocLazyLoad.load([
                        {
                            files: ['modules/core/css/plugins/steps/jquery.steps.css']
                        }
                	    ]);
                	}
            		}
		}).
        	state('iitemformswizardstepone', {
        		url: '/item-form/step-one',
            		templateUrl: 'modules/core/views/wizard/step_one.html'
        	})
        	.state('itemformswizardsteptwo', {
        		url: '/item-form/step-two',
        		 templateUrl: 'modules/core/views/wizard/step_two.html'
        	})
        	.state('itemformswizardstepthree', {
            		url: '/item-form/step-three',
            		templateUrl: 'modules/core/views/wizard/step_three.html'
        	})

	;
	}
]);
<|endoftext|>


<commit_before>/*
We use the output messages from the cucumber runner to create Step Definitions:
the glue between features written in Gherkin and the actual system under test.
Use Given, When, Then.
*/

let request = require('request');

const {defineSupportCode} = require('cucumber');

defineSupportCode(function({Given, Then, When}) {

    Given('I have an employee insert resource', function (callback) {
        // Write code here that turns the phrase above into concrete actions

        //Simplest HTTP request to check that a POST resource exists
        request.post('http://localhost:3000/api_mpayroll/employees',
            function(error, response){
                if (error) {
                    console.log(error);
                    callback(null, 'pending');
                }
                else {
                    response.statusCode = 201;
                    callback();
                }
            }
        )
    });

    When('I submit the employee record', function (callback) {
        // Write code here that turns the phrase above into concrete actions
        callback(null, 'pending');
    });

    Then('A new hourly employee is Created', function (callback) {
        // Write code here that turns the phrase above into concrete actions
        callback(null, 'pending');
    });

});<commit_msg>Add - Simplest code to turn the Given into concrete actions (HTTP request to check that a POST resource exists)<commit_after>/*
We use the output messages from the cucumber runner to create Step Definitions:
the glue between features written in Gherkin and the actual system under test.
Use Given, When, Then.
*/

let request = require('request');

const {defineSupportCode} = require('cucumber');

defineSupportCode(function({Given, Then, When}) {

    Given('I have an employee insert resource', function (callback) {
        // Write code here that turns the phrase above into concrete actions

        //Simplest HTTP request to check that a POST resource exists
        request.post('http://localhost:3000/api_mpayroll/employees',
            function(error, response){
                if (error) {
                    console.log(error);
                    callback(null, 'pending');
                }
                else {
                    response.statusCode = 201;
                    callback();
                }
            }
        )
    });

    When('I submit the employee record', function (callback) {
        // Write code here that turns the phrase above into concrete actions
        callback(null, 'pending');
    });

    Then('A new hourly employee is Created', function (callback) {
        // Write code here that turns the phrase above into concrete actions
        callback(null, 'pending');
    });

});<|endoftext|>


<commit_before>// Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
var CONSOLE_PUSH_COUNT = 50;
var CONSOLE_PUSH_FREQ = 200;

(function initConsole() {
    window.TerminalQueue = [];
    window.Terminal = $('#terminal').terminal(function (command, term) {
        Socket.emit('send command', command);
    }, {
        greetings: '',
        name: Pterodactyl.server.uuid,
        height: 450,
        exit: false,
        prompt: Pterodactyl.server.username + ':~$ ',
        scrollOnEcho: false,
        scrollBottomOffset: 5,
        onBlur: function (terminal) {
            return false;
        }
    });

    Socket.on('initial status', function (data) {
        Terminal.clear();
        if (data.status === 1 || data.status === 2) {
            Socket.emit('send server log');
        }
    });
})();

(function pushOutputQueue() {
    if (TerminalQueue.length > CONSOLE_PUSH_COUNT) {
        // console throttled warning show
    }

    if (TerminalQueue.length > 0) {
        for (var i = 0; i < CONSOLE_PUSH_COUNT && TerminalQueue.length > 0; i++) {
            Terminal.echo(TerminalQueue[0]);
            TerminalQueue.shift();
        }
    }

    window.setTimeout(pushOutputQueue, CONSOLE_PUSH_FREQ);
})();

$(document).ready(function () {
    $('[data-attr="power"]').click(function (event) {
        if (! $(this).hasClass('disabled')) {
            Socket.emit('set status', $(this).data('action'));
        }
    });

    var ctc = $('#chart_cpu');
    var timeLabels = [];
    var cpuData = [];
    var CPUChart = new Chart(ctc, {
        type: 'line',
        data: {
            labels: timeLabels,
            datasets: [
                {
                    label: "Percent Use",
                    fill: false,
                    lineTension: 0.03,
                    backgroundColor: "#00A1CB",
                    borderColor: "#00A1CB",
                    borderCapStyle: 'butt',
                    borderDash: [],
                    borderDashOffset: 0.0,
                    borderJoinStyle: 'miter',
                    pointBorderColor: "rgba(75,192,192,1)",
                    pointBackgroundColor: "#fff",
                    pointBorderWidth: 1,
                    pointHoverRadius: 5,
                    pointHoverBackgroundColor: "rgba(75,192,192,1)",
                    pointHoverBorderColor: "rgba(220,220,220,1)",
                    pointHoverBorderWidth: 2,
                    pointRadius: 1,
                    pointHitRadius: 10,
                    data: cpuData,
                    spanGaps: false,
                }
            ]
        },
        options: {
            title: {
                display: true,
                text: 'CPU Usage (as Percent Total)'
            },
            legend: {
                display: false,
            },
            animation: {
                duration: 1,
            }
        }
    });

    var ctm = $('#chart_memory');
    var memoryData = [];
    var MemoryChart = new Chart(ctm, {
        type: 'line',
        data: {
            labels: timeLabels,
            datasets: [
                {
                    label: "Memory Use",
                    fill: false,
                    lineTension: 0.03,
                    backgroundColor: "#01A4A4",
                    borderColor: "#01A4A4",
                    borderCapStyle: 'butt',
                    borderDash: [],
                    borderDashOffset: 0.0,
                    borderJoinStyle: 'miter',
                    pointBorderColor: "rgba(75,192,192,1)",
                    pointBackgroundColor: "#fff",
                    pointBorderWidth: 1,
                    pointHoverRadius: 5,
                    pointHoverBackgroundColor: "rgba(75,192,192,1)",
                    pointHoverBorderColor: "rgba(220,220,220,1)",
                    pointHoverBorderWidth: 2,
                    pointRadius: 1,
                    pointHitRadius: 10,
                    data: memoryData,
                    spanGaps: false,
                }
            ]
        },
        options: {
            title: {
                display: true,
                text: 'Memory Usage (in Megabytes)'
            },
            legend: {
                display: false,
            },
            animation: {
                duration: 1,
            }
        }
    });
    Socket.on('proc', function (proc) {
        if (cpuData.length > 10) {
            cpuData.shift();
            memoryData.shift();
            timeLabels.shift();
        }

        var cpuUse = (Pterodactyl.server.cpu > 0) ? parseFloat(((proc.data.cpu.total / Pterodactyl.server.cpu) * 100).toFixed(3).toString()) : proc.data.cpu.total;
        cpuData.push(cpuUse);
        memoryData.push(parseInt(proc.data.memory.total / (1024 * 1024)));

        var m = new Date();
        timeLabels.push($.format.date(new Date(), 'HH:mm:ss'));

        CPUChart.update();
        MemoryChart.update();
    });

    // Update Listings on Initial Status
    Socket.on('initial status', function (data) {
        updateServerPowerControls(data.status);
    });

    // Update Listings on Status
    Socket.on('status', function (data) {
        updateServerPowerControls(data.status);
    });

    function updateServerPowerControls (data) {
        // Server is On or Starting
        if(data == 1 || data == 2) {
            $('[data-attr="power"][data-action="start"]').addClass('disabled');
            $('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').removeClass('disabled');
        } else {
            if (data == 0) {
                $('[data-attr="power"][data-action="start"]').removeClass('disabled');
            }
            $('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').addClass('disabled');
        }

        if(data !== 0) {
            $('[data-attr="power"][data-action="kill"]').removeClass('disabled');
        } else {
            $('[data-attr="power"][data-action="kill"]').addClass('disabled');
        }
    }
});
<commit_msg>switch console javascript code to revealing module pattern to avoid global variables<commit_after>// Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
var CONSOLE_PUSH_COUNT = 50;
var CONSOLE_PUSH_FREQ = 200;

const Console = (function () {

    var terminalQueue;
    var terminal;

    function initConsole() {
        termianlQueue = [];
        terminal = $('#terminal').terminal(function (command, term) {
            Socket.emit('send command', command);
        }, {
            greetings: '',
            name: Pterodactyl.server.uuid,
            height: 450,
            exit: false,
            prompt: Pterodactyl.server.username + ':~$ ',
            scrollOnEcho: false,
            scrollBottomOffset: 5,
            onBlur: function (terminal) {
                return false;
            }
        });

        Socket.on('initial status', function (data) {
            terminal.clear();
            if (data.status === 1 || data.status === 2) {
                Socket.emit('send server log');
            }
        });
    }

    function pushOutputQueue() {
        if (termianlQueue.length > CONSOLE_PUSH_COUNT) {
            // console throttled warning show
        }

        if (termianlQueue.length > 0) {
            for (var i = 0; i < CONSOLE_PUSH_COUNT && termianlQueue.length > 0; i++) {
                terminal.echo(termianlQueue[0]);
                termianlQueue.shift();
            }
        }

        window.setTimeout(pushOutputQueue, CONSOLE_PUSH_FREQ);
    }

    return {
        init: function () {
            $('[data-attr="power"]').click(function (event) {
                if (! $(this).hasClass('disabled')) {
                    Socket.emit('set status', $(this).data('action'));
                }
            });

            var ctc = $('#chart_cpu');
            var timeLabels = [];
            var cpuData = [];
            var CPUChart = new Chart(ctc, {
                type: 'line',
                data: {
                    labels: timeLabels,
                    datasets: [
                        {
                            label: "Percent Use",
                            fill: false,
                            lineTension: 0.03,
                            backgroundColor: "#00A1CB",
                            borderColor: "#00A1CB",
                            borderCapStyle: 'butt',
                            borderDash: [],
                            borderDashOffset: 0.0,
                            borderJoinStyle: 'miter',
                            pointBorderColor: "rgba(75,192,192,1)",
                            pointBackgroundColor: "#fff",
                            pointBorderWidth: 1,
                            pointHoverRadius: 5,
                            pointHoverBackgroundColor: "rgba(75,192,192,1)",
                            pointHoverBorderColor: "rgba(220,220,220,1)",
                            pointHoverBorderWidth: 2,
                            pointRadius: 1,
                            pointHitRadius: 10,
                            data: cpuData,
                            spanGaps: false,
                        }
                    ]
                },
                options: {
                    title: {
                        display: true,
                        text: 'CPU Usage (as Percent Total)'
                    },
                    legend: {
                        display: false,
                    },
                    animation: {
                        duration: 1,
                    }
                }
            });

            var ctm = $('#chart_memory');
            var memoryData = [];
            var MemoryChart = new Chart(ctm, {
                type: 'line',
                data: {
                    labels: timeLabels,
                    datasets: [
                        {
                            label: "Memory Use",
                            fill: false,
                            lineTension: 0.03,
                            backgroundColor: "#01A4A4",
                            borderColor: "#01A4A4",
                            borderCapStyle: 'butt',
                            borderDash: [],
                            borderDashOffset: 0.0,
                            borderJoinStyle: 'miter',
                            pointBorderColor: "rgba(75,192,192,1)",
                            pointBackgroundColor: "#fff",
                            pointBorderWidth: 1,
                            pointHoverRadius: 5,
                            pointHoverBackgroundColor: "rgba(75,192,192,1)",
                            pointHoverBorderColor: "rgba(220,220,220,1)",
                            pointHoverBorderWidth: 2,
                            pointRadius: 1,
                            pointHitRadius: 10,
                            data: memoryData,
                            spanGaps: false,
                        }
                    ]
                },
                options: {
                    title: {
                        display: true,
                        text: 'Memory Usage (in Megabytes)'
                    },
                    legend: {
                        display: false,
                    },
                    animation: {
                        duration: 1,
                    }
                }
            });
            Socket.on('proc', function (proc) {
                if (cpuData.length > 10) {
                    cpuData.shift();
                    memoryData.shift();
                    timeLabels.shift();
                }

                var cpuUse = (Pterodactyl.server.cpu > 0) ? parseFloat(((proc.data.cpu.total / Pterodactyl.server.cpu) * 100).toFixed(3).toString()) : proc.data.cpu.total;
                cpuData.push(cpuUse);
                memoryData.push(parseInt(proc.data.memory.total / (1024 * 1024)));

                var m = new Date();
                timeLabels.push($.format.date(new Date(), 'HH:mm:ss'));

                CPUChart.update();
                MemoryChart.update();
            });

            // Update Listings on Initial Status
            Socket.on('initial status', function (data) {
                updateServerPowerControls(data.status);
            });

            // Update Listings on Status
            Socket.on('status', function (data) {
                updateServerPowerControls(data.status);
            });

            function updateServerPowerControls (data) {
                // Server is On or Starting
                if(data == 1 || data == 2) {
                    $('[data-attr="power"][data-action="start"]').addClass('disabled');
                    $('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').removeClass('disabled');
                } else {
                    if (data == 0) {
                        $('[data-attr="power"][data-action="start"]').removeClass('disabled');
                    }
                    $('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').addClass('disabled');
                }

                if(data !== 0) {
                    $('[data-attr="power"][data-action="kill"]').removeClass('disabled');
                } else {
                    $('[data-attr="power"][data-action="kill"]').addClass('disabled');
                }
            }
        },

        getTerminal: function() {
            return terminal
        },

        getTerminalQueue: function() {
            return terminalQueue
        },
    }

});

$(document).ready(function () {
    Console.init();
});
<|endoftext|>


<commit_before>var Alloy = require('alloy'),
	_ = Alloy._,
	Backbone = Alloy.Backbone,

	fbSDK = require('facebook'),
	Acl = require('RebelFrame/Acl');

/**
 * Facebook provides a wrapper for the Facebook SDK and Ti Facebook module.
 *
 * @class Facebook
 * @singleton
 */
var FB = {
	appId: Alloy.CFG.Facebook.appId,
	permissions: Alloy.CFG.Facebook.permissions,

	login: function(options) {
		// Wrap the success function
		// options.success = _.wrap(options.success, function(func, userData) {
		// 	// Call register function on the Cloud API
		// 	Acl.registerUserWithCloud(userData, {
		// 		success: func,
		// 		error: options.error,
		// 		scope: options.scope
		// 	});
		// });

		// Make the call using the FB SDK
		_authorize(options);
	},

	connect: function(options) {
		// Wrap the success function
		options.success = _.wrap(options.success, function(func, userData) {
			// Call connect function on the Cloud API
			Acl.connectSocialMediaToUser(userData, {
				success: func,
				error: options.error,
				scope: options.scope
			});
		});

		// Make the call using the FB SDK
		_authorize(callbackObj);
	},

	requestWriteAccess: function(callback) {
		if (fbSDK.loggedIn)
			_reAuthorize(callback);
		else
			_authorize({
				success: function(userData) {
					_reAuthorize(callback);
				},
				error: function(evt) {

				},
				scope: FB
			});
	},

	isLoggedin: function() {
		return fbSDK.loggedIn;
	},

	getPermissions: function() {
		return fbSDK.permissions;
	},

	hasWritePermissions: function() {
		return _.indexOf(fbSDK.permissions, FB.permissions.write[0]) !== -1;
	}

};

function _authorize(options) {
	var callbackWrapper = function(evt) {
		fbSDK.removeEventListener('login', callbackWrapper);

		// Add network to event object
		evt.network = 'facebook';

		if (evt.success) {
			//Write to cloud storage
			var userData = {
				facebook_id: fbSDK.uid,
				facebook_access_token: fbSDK.accessToken,
				facebook_expiration: fbSDK.expirationDate,
				type: 'facebook'
			};

			options.success(userData);

			// Log this event
			// Analytics.recordEvent('facebook', 'connect', 'facebook');
		} else if (evt.cancelled) {
			options.error(evt);
		} else {
			handleError(evt);

			options.error(evt);
		}

	};

	fbSDK.addEventListener('login', callbackWrapper);
	fbSDK.appid = FB.appId;

	if (OS_IOS)
		fbSDK.permissions = FB.permissions.read;
	else
		fbSDK.permissions = _.extend(FB.permissions.read, FB.permissions.write);

	fbSDK.forceDialogAuth = false;

	if (OS_IOS)
		fbSDK.initialize();

	// If user is loggedin to Facebook, log him/her out first
	if (fbSDK.loggedIn) {
		Ti.API.info('Already loggedin!');
	} else {
		fbSDK.authorize();
	}
}

function _reAuthorize(options) {
	var callbackWrapper = function(evt) {
		Ti.API.info(evt);

		if (evt.success) {
			//Write to cloud storage
			options.success(evt);

			// Log this event
			// Analytics.recordEvent('facebook', 'connect', 'facebook');
		} else if (evt.cancelled) {
			// Do nothing?
			Ti.API.info('Cancelled');
		} else {
			handleError(evt);

			options.error(evt);
		}
	};

	if (OS_IOS)
		fbSDK.requestNewPublishPermissions(FB.permissions.write, fbSDK.audienceFriends, callbackWrapper);
	else {
		// Android already has write permissions
		options.success();
	}
}

function handleError(evt) {
	var message;

	if (OS_IOS) {
		// For all of these errors - assume the user is logged out
		// so show your login UI
		if (evt.error.indexOf('Go to Settings') === 0) {
			message = String.format(L('fb_no_premission', '%1$s needs permission to access your facebook account. You can control this by going to Settings > Facebook on your phone.'), Ti.App.name);
		} else if (evt.error.indexOf('Session Login Error') === 0) {
			// Session was invalid - e.g. the user deauthorized your app, etc
			// alert('Please login again.');
		} else if (evt.error.indexOf('OTHER:') !== 0) {
			// another error that may require user attention
			message = L('lFacebookError') + evt.error;
		} else {
			// This must be an error message that the user was already notified about
			// Due to the automatic error handling in the graph call
			// Don't surface it again
		}
	} else
		message = L('lFacebookError') + evt.error;

	if (message) {
		var dialog = Ti.UI.createAlertDialog({
			title: L('tFacebookError'),
			message: message,
			buttonNames: [L('Okay')],
			cancel: 0
		});
		dialog.show();
	}
}

module.exports = FB;
<commit_msg>When already logged in to Facebook, just call callback function<commit_after>var Alloy = require('alloy'),
	_ = Alloy._,
	Backbone = Alloy.Backbone,

	fbSDK = require('facebook'),
	Acl = require('RebelFrame/Acl');

/**
 * Facebook provides a wrapper for the Facebook SDK and Ti Facebook module.
 *
 * @class Facebook
 * @singleton
 */
var FB = {
	appId: Alloy.CFG.Facebook.appId,
	permissions: Alloy.CFG.Facebook.permissions,

	login: function(options) {
		// Wrap the success function
		// options.success = _.wrap(options.success, function(func, userData) {
		// 	// Call register function on the Cloud API
		// 	Acl.registerUserWithCloud(userData, {
		// 		success: func,
		// 		error: options.error,
		// 		scope: options.scope
		// 	});
		// });

		// Make the call using the FB SDK
		_authorize(options);
	},

	connect: function(options) {
		// Wrap the success function
		options.success = _.wrap(options.success, function(func, userData) {
			// Call connect function on the Cloud API
			Acl.connectSocialMediaToUser(userData, {
				success: func,
				error: options.error,
				scope: options.scope
			});
		});

		// Make the call using the FB SDK
		_authorize(callbackObj);
	},

	requestWriteAccess: function(callback) {
		if (fbSDK.loggedIn)
			_reAuthorize(callback);
		else
			_authorize({
				success: function(userData) {
					_reAuthorize(callback);
				},
				error: function(evt) {

				},
				scope: FB
			});
	},

	isLoggedin: function() {
		return fbSDK.loggedIn;
	},

	getPermissions: function() {
		return fbSDK.permissions;
	},

	hasWritePermissions: function() {
		return _.indexOf(fbSDK.permissions, FB.permissions.write[0]) !== -1;
	}

};

function _authorize(options) {
	var callbackWrapper = function(evt) {
		fbSDK.removeEventListener('login', callbackWrapper);

		// Add network to event object
		evt.network = 'facebook';

		if (evt.success) {
			//Write to cloud storage
			var userData = {
				facebook_id: fbSDK.uid,
				facebook_access_token: fbSDK.accessToken,
				facebook_expiration: fbSDK.expirationDate,
				type: 'facebook'
			};

			options.success(userData);

			// Log this event
			// Analytics.recordEvent('facebook', 'connect', 'facebook');
		} else if (evt.cancelled) {
			options.error(evt);
		} else {
			handleError(evt);

			options.error(evt);
		}

	};

	fbSDK.addEventListener('login', callbackWrapper);
	fbSDK.appid = FB.appId;

	if (OS_IOS)
		fbSDK.permissions = FB.permissions.read;
	else
		fbSDK.permissions = _.extend(FB.permissions.read, FB.permissions.write);

	fbSDK.forceDialogAuth = false;

	if (OS_IOS)
		fbSDK.initialize();

	// If user is loggedin to Facebook, log him/her out first
	if (fbSDK.loggedIn) {
		Ti.API.info('Already loggedin!');

		callbackWrapper({success: true});

	} else {
		fbSDK.authorize();
	}
}

function _reAuthorize(options) {
	var callbackWrapper = function(evt) {
		Ti.API.info(evt);

		if (evt.success) {
			//Write to cloud storage
			options.success(evt);

			// Log this event
			// Analytics.recordEvent('facebook', 'connect', 'facebook');
		} else if (evt.cancelled) {
			// Do nothing?
			Ti.API.info('Cancelled');
		} else {
			handleError(evt);

			options.error(evt);
		}
	};

	if (OS_IOS)
		fbSDK.requestNewPublishPermissions(FB.permissions.write, fbSDK.audienceFriends, callbackWrapper);
	else {
		// Android already has write permissions
		options.success();
	}
}

function handleError(evt) {
	var message;

	if (OS_IOS) {
		// For all of these errors - assume the user is logged out
		// so show your login UI
		if (evt.error.indexOf('Go to Settings') === 0) {
			message = String.format(L('fb_no_premission', '%1$s needs permission to access your facebook account. You can control this by going to Settings > Facebook on your phone.'), Ti.App.name);
		} else if (evt.error.indexOf('Session Login Error') === 0) {
			// Session was invalid - e.g. the user deauthorized your app, etc
			// alert('Please login again.');
		} else if (evt.error.indexOf('OTHER:') !== 0) {
			// another error that may require user attention
			message = L('lFacebookError') + evt.error;
		} else {
			// This must be an error message that the user was already notified about
			// Due to the automatic error handling in the graph call
			// Don't surface it again
		}
	} else
		message = L('lFacebookError') + evt.error;

	if (message) {
		var dialog = Ti.UI.createAlertDialog({
			title: L('tFacebookError'),
			message: message,
			buttonNames: [L('Okay')],
			cancel: 0
		});
		dialog.show();
	}
}

module.exports = FB;
<|endoftext|>