<commit_before>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('node-uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;

const apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
const sessionIds = new Map();

function processEvent(event) {
    var sender = event.sender.id.toString();

    if ((event.message && event.message.text) || (event.postback && event.postback.payload)) {
        var text = event.message ? event.message.text : event.postback.payload;
        // Handle a text message from this sender

        if (!sessionIds.has(sender)) {
            sessionIds.set(sender, uuid.v1());
        }

        console.log("Text", text);

        let apiaiRequest = apiAiService.textRequest(text,
            {
                sessionId: sessionIds.get(sender)
            });

        apiaiRequest.on('response', (response) => {
            if (isDefined(response.result)) {
                //asd
                let responseText = response.result.fulfillment.speech;
                let responseData = response.result.fulfillment.data;
                let action = response.result.action;
                /*console.log(responseText);
                console.log(responseData);
                console.log(action);*/
                if (isDefined(responseData) && isDefined(responseData.facebook)) {
                    if (!Array.isArray(responseData.facebook)) {
                        try {
                            console.log('Response as formatted message');
                            sendFBMessage(sender, responseData.facebook);
                        } catch (err) {
                            sendFBMessage(sender, {text: err.message});
                        }
                    } else {
                        responseData.facebook.forEach((facebookMessage) => {
                            try {
                                if (facebookMessage.sender_action) {
                                    console.log('Response as sender action');
                                    sendFBSenderAction(sender, facebookMessage.sender_action);
                                }
                                else {
                                    console.log('Response as formatted message');
                                    sendFBMessage(sender, facebookMessage);
                                }
                            } catch (err) {
                                sendFBMessage(sender, {text: err.message});
                            }
                        });
                    }
                //} else if (isDefined(responseText)) {
                } else if (isDefined(action) && isDefined(responseText)) {
                    console.log('Response as text message');
                    // facebook API limit for text length is 320,
                    // so we must split message if needed
                    var splittedText = splitResponse(responseText);
                    /*switch (action){
                        case 'show_prod':
                            console.log('generic');
                            async.eachSeries(splittedText, (textPart, callback) => {
                                sendFBMessage(sender, {text: textPart}, callback);
                            });
                            sendFBMessage(sender, generic_message, null);
                            break;
                        default:
                            console.log('default');
                            async.eachSeries(splittedText, (textPart, callback) => {
                                sendFBMessage(sender, {text: textPart}, callback);
                            });
                    }*/
                    async.eachSeries(splittedText, (textPart, callback) => {
                        sendFBMessage(sender, {text: textPart}, callback);
                    });
                }

            }
        });

        apiaiRequest.on('error', (error) => console.error(error));
        apiaiRequest.end();
    }
}

function splitResponse(str) {
    if (str.length <= 320) {
        return [str];
    }

    return chunkString(str, 300);
}

function chunkString(s, len) {
    var curr = len, prev = 0;

    var output = [];

    while (s[curr]) {
        if (s[curr++] == ' ') {
            output.push(s.substring(prev, curr));
            prev = curr;
            curr += len;
        }
        else {
            var currReverse = curr;
            do {
                if (s.substring(currReverse - 1, currReverse) == ' ') {
                    output.push(s.substring(prev, currReverse));
                    prev = currReverse;
                    curr = currReverse + len;
                    break;
                }
                currReverse--;
            } while (currReverse > prev)
        }
    }
    output.push(s.substr(prev));
    //console.log(output);
    //output = ['Length of param message[text] must be less than or equal to 320'];
    return output;
}

/*const generic_message = {
    attachment: {
        type: "template",
        payload: {
            template_type: "generic",
            elements: [{
                title: "rift",
                subtitle: "Next-generation virtual reality",
                item_url: "https://www.oculus.com/en-us/rift/",
                image_url: "http://messengerdemo.parseapp.com/img/rift.png",
                buttons: [{
                    type: "web_url",
                    url: "https://www.oculus.com/en-us/rift/",
                    title: "Open Web URL"
                }, {
                    type: "postback",
                    title: "Call Postback",
                    payload: "Payload for first bubble"
                }]
            }, {
                title: "touch",
                subtitle: "Your Hands, Now in VR",
                item_url: "https://www.oculus.com/en-us/touch/",
                image_url: "http://messengerdemo.parseapp.com/img/touch.png",
                buttons: [{
                    type: "web_url",
                    url: "https://www.oculus.com/en-us/touch/",
                    title: "Open Web URL"
                }, {
                    type: "postback",
                    title: "Call Postback",
                    payload: "Payload for second bubble"
                }]
            }]
        }
    }
};*/

function sendFBMessage(sender, messageData, callback) {
    //console.log(sender);
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: sender},
            message: messageData
            //message: generic_message
        }
    }, (error, response, body) => {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }

        if (callback) {
            callback();
        }
    });
}

function sendFBSenderAction(sender, action, callback) {
    setTimeout(() => {
        request({
            url: 'https://graph.facebook.com/v2.6/me/messages',
            qs: {access_token: FB_PAGE_ACCESS_TOKEN},
            method: 'POST',
            json: {
                recipient: {id: sender},
                sender_action: action
            }
        }, (error, response, body) => {
            if (error) {
                console.log('Error sending action: ', error);
            } else if (response.body.error) {
                console.log('Error: ', response.body.error);
            }
            if (callback) {
                callback();
            }
        });
    }, 1000);
}

function doSubscribeRequest() {
    request({
            method: 'POST',
            uri: "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=" + FB_PAGE_ACCESS_TOKEN
        },
        (error, response, body) => {
            if (error) {
                console.error('Error while subscription: ', error);
            } else {
                console.log('Subscription result: ', response.body);
            }
        });
}

function isDefined(obj) {
    if (typeof obj == 'undefined') {
        return false;
    }

    if (!obj) {
        return false;
    }

    return obj != null;
}

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        var data = JSONbig.parse(req.body);
        var asd = data;
        //console.log(asd);
        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                        //console.log(event);
                        if (event.message && !event.message.is_echo ||
                            event.postback && event.postback.payload) {
                            processEvent(event);
                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.post('/webhook_apiai/', (req, res) => {

    //var weather_query = new Boolean(false);
    var weather_query = 'false';

    const generic_message = {
        attachment: {
            type: "template",
            payload: {
                template_type: "generic",
                elements: [{
                    title: "Fresh Pizza",
                    subtitle: "Be carefull and don't eat your fingers!!!",
                    item_url: "https://en.wikipedia.org/wiki/Pizza",
                    //image_url: "http://www.cbc.ca/inthekitchen/assets_c/2012/11/MargheritaPizza21-thumb-596x350-247022.jpg",
                    buttons: [{
                        type: "web_url",
                        url: "https://en.wikipedia.org/wiki/Pizza",
                        title: "Open Web URL"
                    }/*, {
                     type: "postback",
                     title: "Call Postback",
                     payload: "Payload for first bubble"
                     }*/]
                }]
            }
        }
    };

    try {
        var data = JSONbig.parse(req.body);
        //console.log(data);
        switch(data.result.action){
            case 'show_prod':
                switch(data.result.parameters.pizza_type){
                    case 'Margherita':
                        generic_message.attachment.payload.elements[0].title = data.result.parameters.pizza_type;
                        generic_message.attachment.payload.elements[0].image_url = "http://www.cbc.ca/inthekitchen/assets_c/2012/11/MargheritaPizza21-thumb-596x350-247022.jpg";
                }
            case 'show_weather':
                weather_query = 'true';
                console.log(data.result.parameters['geo-city']);
                console.log(isDefined(data.result.parameters['geo-city']));
                if(data.result.parameters['geo-city']){
                    var city = data.result.parameters['geo-city'];
                    var base_url = "https://query.yahooapis.com/v1/public/yql?" + "q=select+%2A+from+weather.forecast+where+woeid+in+%28select+woeid+from+geo.places%281%29+where+text%3D%27"+city+"%27%29" + "&format=json";
                    request({
                        url: base_url,
                        method: 'GET', //Specify the method
                    }, function(error, response, body){
                        if(error) {
                            console.log(error);
                            return res.status(400).json({
                                status: "error",
                                error: err
                            });
                        } else {
                            var query = JSON.parse(body).query;
                            var results = query.results;
                            var channel = results.channel;
                            var item = channel.item;
                            var location = channel.location;
                            var units = channel.units;
                            var condition = item.condition;
                            //console.log(channel)
                            var string = "Today in " + location.city + ": " + condition.text + ", the temperature is " + condition.temp + " " + units.temperature
                            generic_message.attachment.payload.elements[0].title = 'Weather in' + city;
                            generic_message.attachment.payload.elements[0].subtitle = string;
                            generic_message.attachment.payload.elements[0].item_url = channel.link;
                            generic_message.attachment.payload.elements[0].image_url = channel.image.url;
                            generic_message.attachment.payload.elements[0].buttons[0].url = channel.link;
                            return res.status(200).json({
                                data: {
                                    facebook: generic_message
                                }
                            })
                        }
                    });
                }
                weather_query = 'false';
                break;
        }

        if (weather_query != 'true'){
            return res.status(200).json({
                data: {
                    facebook: generic_message
                }
            })
        } else {
            return res.status(200).json({
                data: {
                    facebook: {test: 'error'}
                }
            })}
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }
});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

doSubscribeRequest();
<commit_msg>'webhook_test'<commit_after>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('node-uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;

const apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
const sessionIds = new Map();

function processEvent(event) {
    var sender = event.sender.id.toString();

    if ((event.message && event.message.text) || (event.postback && event.postback.payload)) {
        var text = event.message ? event.message.text : event.postback.payload;
        // Handle a text message from this sender

        if (!sessionIds.has(sender)) {
            sessionIds.set(sender, uuid.v1());
        }

        console.log("Text", text);

        let apiaiRequest = apiAiService.textRequest(text,
            {
                sessionId: sessionIds.get(sender)
            });

        apiaiRequest.on('response', (response) => {
            if (isDefined(response.result)) {
                //asd
                let responseText = response.result.fulfillment.speech;
                let responseData = response.result.fulfillment.data;
                let action = response.result.action;
                /*console.log(responseText);
                console.log(responseData);
                console.log(action);*/
                if (isDefined(responseData) && isDefined(responseData.facebook)) {
                    if (!Array.isArray(responseData.facebook)) {
                        try {
                            console.log('Response as formatted message');
                            sendFBMessage(sender, responseData.facebook);
                        } catch (err) {
                            sendFBMessage(sender, {text: err.message});
                        }
                    } else {
                        responseData.facebook.forEach((facebookMessage) => {
                            try {
                                if (facebookMessage.sender_action) {
                                    console.log('Response as sender action');
                                    sendFBSenderAction(sender, facebookMessage.sender_action);
                                }
                                else {
                                    console.log('Response as formatted message');
                                    sendFBMessage(sender, facebookMessage);
                                }
                            } catch (err) {
                                sendFBMessage(sender, {text: err.message});
                            }
                        });
                    }
                //} else if (isDefined(responseText)) {
                } else if (isDefined(action) && isDefined(responseText)) {
                    console.log('Response as text message');
                    // facebook API limit for text length is 320,
                    // so we must split message if needed
                    var splittedText = splitResponse(responseText);
                    /*switch (action){
                        case 'show_prod':
                            console.log('generic');
                            async.eachSeries(splittedText, (textPart, callback) => {
                                sendFBMessage(sender, {text: textPart}, callback);
                            });
                            sendFBMessage(sender, generic_message, null);
                            break;
                        default:
                            console.log('default');
                            async.eachSeries(splittedText, (textPart, callback) => {
                                sendFBMessage(sender, {text: textPart}, callback);
                            });
                    }*/
                    async.eachSeries(splittedText, (textPart, callback) => {
                        sendFBMessage(sender, {text: textPart}, callback);
                    });
                }

            }
        });

        apiaiRequest.on('error', (error) => console.error(error));
        apiaiRequest.end();
    }
}

function splitResponse(str) {
    if (str.length <= 320) {
        return [str];
    }

    return chunkString(str, 300);
}

function chunkString(s, len) {
    var curr = len, prev = 0;

    var output = [];

    while (s[curr]) {
        if (s[curr++] == ' ') {
            output.push(s.substring(prev, curr));
            prev = curr;
            curr += len;
        }
        else {
            var currReverse = curr;
            do {
                if (s.substring(currReverse - 1, currReverse) == ' ') {
                    output.push(s.substring(prev, currReverse));
                    prev = currReverse;
                    curr = currReverse + len;
                    break;
                }
                currReverse--;
            } while (currReverse > prev)
        }
    }
    output.push(s.substr(prev));
    //console.log(output);
    //output = ['Length of param message[text] must be less than or equal to 320'];
    return output;
}

/*const generic_message = {
    attachment: {
        type: "template",
        payload: {
            template_type: "generic",
            elements: [{
                title: "rift",
                subtitle: "Next-generation virtual reality",
                item_url: "https://www.oculus.com/en-us/rift/",
                image_url: "http://messengerdemo.parseapp.com/img/rift.png",
                buttons: [{
                    type: "web_url",
                    url: "https://www.oculus.com/en-us/rift/",
                    title: "Open Web URL"
                }, {
                    type: "postback",
                    title: "Call Postback",
                    payload: "Payload for first bubble"
                }]
            }, {
                title: "touch",
                subtitle: "Your Hands, Now in VR",
                item_url: "https://www.oculus.com/en-us/touch/",
                image_url: "http://messengerdemo.parseapp.com/img/touch.png",
                buttons: [{
                    type: "web_url",
                    url: "https://www.oculus.com/en-us/touch/",
                    title: "Open Web URL"
                }, {
                    type: "postback",
                    title: "Call Postback",
                    payload: "Payload for second bubble"
                }]
            }]
        }
    }
};*/

function sendFBMessage(sender, messageData, callback) {
    //console.log(sender);
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: sender},
            message: messageData
            //message: generic_message
        }
    }, (error, response, body) => {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }

        if (callback) {
            callback();
        }
    });
}

function sendFBSenderAction(sender, action, callback) {
    setTimeout(() => {
        request({
            url: 'https://graph.facebook.com/v2.6/me/messages',
            qs: {access_token: FB_PAGE_ACCESS_TOKEN},
            method: 'POST',
            json: {
                recipient: {id: sender},
                sender_action: action
            }
        }, (error, response, body) => {
            if (error) {
                console.log('Error sending action: ', error);
            } else if (response.body.error) {
                console.log('Error: ', response.body.error);
            }
            if (callback) {
                callback();
            }
        });
    }, 1000);
}

function doSubscribeRequest() {
    request({
            method: 'POST',
            uri: "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=" + FB_PAGE_ACCESS_TOKEN
        },
        (error, response, body) => {
            if (error) {
                console.error('Error while subscription: ', error);
            } else {
                console.log('Subscription result: ', response.body);
            }
        });
}

function isDefined(obj) {
    if (typeof obj == 'undefined') {
        return false;
    }

    if (!obj) {
        return false;
    }

    return obj != null;
}

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        var data = JSONbig.parse(req.body);
        var asd = data;
        //console.log(asd);
        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                        //console.log(event);
                        if (event.message && !event.message.is_echo ||
                            event.postback && event.postback.payload) {
                            processEvent(event);
                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.post('/webhook_apiai/', (req, res) => {

    //var weather_query = new Boolean(false);
    var weather_query = 'false';

    const generic_message = {
        attachment: {
            type: "template",
            payload: {
                template_type: "generic",
                elements: [{
                    title: "Fresh Pizza",
                    subtitle: "Be carefull and don't eat your fingers!!!",
                    item_url: "https://en.wikipedia.org/wiki/Pizza",
                    //image_url: "http://www.cbc.ca/inthekitchen/assets_c/2012/11/MargheritaPizza21-thumb-596x350-247022.jpg",
                    buttons: [{
                        type: "web_url",
                        url: "https://en.wikipedia.org/wiki/Pizza",
                        title: "Open Web URL"
                    }/*, {
                     type: "postback",
                     title: "Call Postback",
                     payload: "Payload for first bubble"
                     }*/]
                }]
            }
        }
    };

    try {
        var data = JSONbig.parse(req.body);
        //console.log(data);
        switch(data.result.action){
            case 'show_prod':
                switch(data.result.parameters.pizza_type){
                    case 'Margherita':
                        generic_message.attachment.payload.elements[0].title = data.result.parameters.pizza_type;
                        generic_message.attachment.payload.elements[0].image_url = "http://www.cbc.ca/inthekitchen/assets_c/2012/11/MargheritaPizza21-thumb-596x350-247022.jpg";
                }
            case 'show_weather':
                weather_query = 'true';
                //console.log(data.result.parameters['geo-city']);
                console.log(isDefined(data.result.parameters['geo-city']));
                if(data.result.parameters['geo-city']){
                    var city = data.result.parameters['geo-city'];
                    var base_url = "https://query.yahooapis.com/v1/public/yql?" + "q=select+%2A+from+weather.forecast+where+woeid+in+%28select+woeid+from+geo.places%281%29+where+text%3D%27"+city+"%27%29" + "&format=json";
                    request({
                        url: base_url,
                        method: 'GET', //Specify the method
                    }, function(error, response, body){
                        if(error) {
                            console.log(error);
                            return res.status(400).json({
                                status: "error",
                                error: err
                            });
                        } else {
                            var query = JSON.parse(body).query;
                            var results = query.results;
                            var channel = results.channel;
                            var item = channel.item;
                            var location = channel.location;
                            var units = channel.units;
                            var condition = item.condition;
                            //console.log(channel)
                            var string = "Today in " + location.city + ": " + condition.text + ", the temperature is " + condition.temp + " " + units.temperature
                            generic_message.attachment.payload.elements[0].title = 'Weather in' + city;
                            generic_message.attachment.payload.elements[0].subtitle = string;
                            generic_message.attachment.payload.elements[0].item_url = channel.link;
                            generic_message.attachment.payload.elements[0].image_url = channel.image.url;
                            generic_message.attachment.payload.elements[0].buttons[0].url = channel.link;
                            return res.status(200).json({
                                data: {
                                    facebook: generic_message
                                }
                            })
                        }
                    });
                }
                weather_query = 'false';
                break;
        }

        if (weather_query != 'true'){
            return res.status(200).json({
                data: {
                    facebook: generic_message
                }
            })
        } else {
            return res.status(200).json({
                data: {
                    facebook: {test: 'error'}
                }
            })}
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }
});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

doSubscribeRequest();
<|endoftext|>


<commit_before>angular.module('ct.ui.router.extras').provider('$futureState',
  [ '$stateProvider', '$urlRouterProvider', '$urlMatcherFactoryProvider',
    function _futureStateProvider($stateProvider, $urlRouterProvider, $urlMatcherFactory) {
      var stateFactories = {}, futureStates = {};
      var transitionPending = false, resolveFunctions = [], initPromise, initDone = false;
      var provider = this;

      // This function registers a promiseFn, to be resolved before the url/state matching code
      // will reject a route.  The promiseFn is injected/executed using the runtime $injector.
      // The function should return a promise.
      // When all registered promises are resolved, then the route is re-sync'ed.

      // Example: function($http) {
      //  return $http.get('//server.com/api/DynamicFutureStates').then(function(data) {
      //    angular.forEach(data.futureStates, function(fstate) { $futureStateProvider.futureState(fstate); });
      //  };
      // }
      this.addResolve = function (promiseFn) {
        resolveFunctions.push(promiseFn);
      };

      // Register a state factory function for a particular future-state type.  This factory, given a future-state object,
      // should create a ui-router state.
      // The factory function is injected/executed using the runtime $injector.  The future-state is injected as 'futureState'.

      // Example:
      //    $futureStateProvider.stateFactory('test', function(futureState) {
      //      return {
      //        name: futureState.stateName,
      //        url: futureState.urlFragment,
      //        template: '
Future State Template
',
      //        controller: function() {
      //          console.log("Entered state " + futureState.stateName);
      //        }
      //      }
      //    });
      this.stateFactory = function (futureStateType, factory) {
        stateFactories[futureStateType] = factory;
      };

      this.futureState = function (futureState) {
        if (futureState.stateName)  // backwards compat for now
          futureState.name = futureState.stateName;
        if (futureState.urlPrefix)  // backwards compat for now
          futureState.url = "^" + futureState.urlPrefix;

        futureStates[futureState.name] = futureState;
        var parentMatcher,  parentName = futureState.name.split(/\./).slice(0, -1).join("."),
          realParent = findState(futureState.parent || parentName);
        if (realParent) {
          parentMatcher = realParent.url;
        } else {
          var futureParent = findState((futureState.parent || parentName), true);
          if (!futureParent) throw new Error("Couldn't determine parent state of future state. FutureState:" + angular.toJson(futureState));
          var pattern = futureParent.urlMatcher.source.replace(/\*rest$/, "");
          parentMatcher = $urlMatcherFactory.compile(pattern);
          futureState.parentFutureState = futureParent;
        }
        futureState.urlMatcher = futureState.url.charAt(0) === "^" ?
          $urlMatcherFactory.compile(futureState.url.substring(1) + "*rest") :
          parentMatcher.concat(futureState.url + "*rest");
      };

      this.get = function () {
        return angular.extend({}, futureStates);
      };

      function findState(stateOrName, findFutureState) {
        var statename = angular.isObject(stateOrName) ? stateOrName.name : stateOrName;
        if (!findFutureState) {
          return internalStates[statename];
        }
        return futureStates[statename];
      }

      /* options is an object with at least a name or url attribute */
      function findFutureState($state, options) {
        if (options.name) {
          var nameComponents = options.name.split(/\./);
          if (options.name.charAt(0) === '.')
            nameComponents[0] = $state.current.name;
          while (nameComponents.length) {
            var stateName = nameComponents.join(".");
            if ($state.get(stateName, { relative: $state.current }))
              return null; // State is already defined; nothing to do
            if (futureStates[stateName])
              return futureStates[stateName];
            nameComponents.pop();
          }
        }

        if (options.url) {
          var matches = [];
          for(var future in futureStates) {
            if (futureStates[future].urlMatcher.exec(options.url)) {
              matches.push(futureStates[future]);
            }
          }
          // Find most specific by ignoring matching parents from matches
          var copy = matches.slice(0);
          for (var i = matches.length - 1; i >= 0; i--) {
            for (var j = 0; j < copy.length; j++) {
              if (matches[i] === copy[j].parentFutureState) matches.splice(i, 1);
            }
          }
          return matches[0];
        }
      }

      function lazyLoadState($injector, futureState) {
        if (!futureState) {
          var deferred = $q.defer();
          deferred.reject("No lazyState passed in " + futureState);
          return deferred.promise;
        }

        var promise = $q.when(true), parentFuture = futureState.parentFutureState;
        if (parentFuture && futureStates[parentFuture.name]) {
          promise = lazyLoadState($injector, futureStates[parentFuture.name]);
        }

        var type = futureState.type;
        var factory = stateFactories[type];
        if (!factory) throw Error("No state factory for futureState.type: " + (futureState && futureState.type));
        return promise
          .then(function() {
            return $injector.invoke(factory, factory, { futureState: futureState });
          })
          .finally(function() {
            delete(futureStates[futureState.name]);
          });
      }

      var otherwiseFunc = [ '$log', '$location',
        function otherwiseFunc($log, $location) {
          $log.debug("Unable to map " + $location.path());
        }];

      function futureState_otherwise($injector, $location) {
        var resyncing = false;

        var lazyLoadMissingState =
          ['$rootScope', '$urlRouter', '$state',
            function lazyLoadMissingState($rootScope, $urlRouter, $state) {
              if (!initDone) {
                // Asynchronously load state definitions, then resync URL
                initPromise().then(function initialResync() {
                  resyncing = true;
                  $urlRouter.sync();
                  resyncing = false;
                });
                initDone = true;
                return;
              }

              var futureState = findFutureState($state, { url: $location.path() });
              if (!futureState) {
                return $injector.invoke(otherwiseFunc);
              }

              transitionPending = true;
              // Config loaded.  Asynchronously lazy-load state definition from URL fragment, if mapped.
              lazyLoadState($injector, futureState).then(function lazyLoadedStateCallback(state) {
                // TODO: Should have a specific resolve value that says 'dont register a state because I already did'
                if (state && (!$state.get(state) || (state.name && !$state.get(state.name))))
                  $stateProvider.state(state);
                resyncing = true;
                $urlRouter.sync();
                resyncing = false;
                transitionPending = false;
              }, function lazyLoadStateAborted() {
                transitionPending = false;
                return $injector.invoke(otherwiseFunc);
              });
            }];
        if (transitionPending) return;

        var nextFn = resyncing ? otherwiseFunc : lazyLoadMissingState;
        return $injector.invoke(nextFn);
      }

      $urlRouterProvider.otherwise(futureState_otherwise);

      $urlRouterProvider.otherwise = function(rule) {
        if (angular.isString(rule)) {
          var redirect = rule;
          rule = function () { return redirect; };
        }
        else if (!angular.isFunction(rule)) throw new Error("'rule' must be a function");
        otherwiseFunc = rule;
        return $urlRouterProvider;
      };

      var serviceObject = {
        getResolvePromise: function () {
          return initPromise();
        }
      };

      // Used in .run() block to init
      this.$get = [ '$injector', '$state', '$q', '$rootScope', '$urlRouter', '$timeout', '$log',
        function futureStateProvider_get($injector, $state, $q, $rootScope, $urlRouter, $timeout, $log) {
          function init() {
            $rootScope.$on("$stateNotFound", function futureState_notFound(event, unfoundState, fromState, fromParams) {
              if (transitionPending) return;
              $log.debug("event, unfoundState, fromState, fromParams", event, unfoundState, fromState, fromParams);

              var futureState = findFutureState($state, { name: unfoundState.to });
              if (!futureState) return;

              event.preventDefault();
              transitionPending = true;

              var promise = lazyLoadState($injector, futureState);
              promise.then(function (state) {
                // TODO: Should have a specific resolve value that says 'dont register a state because I already did'
                if (state && (!$state.get(state) || (state.name && !$state.get(state.name))))
                  $stateProvider.state(state);
                $state.go(unfoundState.to, unfoundState.toParams);
                transitionPending = false;
              }, function (error) {
                console.log("failed to lazy load state ", error);
                $state.go(fromState, fromParams);
                transitionPending = false;
              });
            });

            // Do this better.  Want to load remote config once, before everything else
            if (!initPromise) {
              var promises = [];
              angular.forEach(resolveFunctions, function (promiseFn) {
                promises.push($injector.invoke(promiseFn));
              });
              initPromise = function () {
                return $q.all(promises);
              };
//          initPromise = _.once(function flattenFutureStates() {
//            var allPromises = $q.all(promises);
//            return allPromises.then(function(data) {
//              return _.flatten(data);
//            });
//          });
            }

            // TODO: analyze this. I'm calling $urlRouter.sync() in two places for retry-initial-transition.
            // TODO: I should only need to do this once.  Pick the better place and remove the extra resync.
            initPromise().then(function retryInitialState() {
              $timeout(function () {
                if ($state.transition) {
                  $state.transition.then($urlRouter.sync, $urlRouter.sync);
                } else {
                  $urlRouter.sync();
                }
              });
            });
          }

          init();

          serviceObject.state = $stateProvider.state;
          serviceObject.futureState = provider.futureState;
          serviceObject.get = provider.get;

          return serviceObject;
        }];
    }]);

angular.module('ct.ui.router.extras').run(['$futureState',
  // Just inject $futureState so it gets initialized.
  function ($futureState) {
  }
]);
<commit_msg>chore(): cleaned up an if block<commit_after>angular.module('ct.ui.router.extras').provider('$futureState',
  [ '$stateProvider', '$urlRouterProvider', '$urlMatcherFactoryProvider',
    function _futureStateProvider($stateProvider, $urlRouterProvider, $urlMatcherFactory) {
      var stateFactories = {}, futureStates = {};
      var transitionPending = false, resolveFunctions = [], initPromise, initDone = false;
      var provider = this;

      // This function registers a promiseFn, to be resolved before the url/state matching code
      // will reject a route.  The promiseFn is injected/executed using the runtime $injector.
      // The function should return a promise.
      // When all registered promises are resolved, then the route is re-sync'ed.

      // Example: function($http) {
      //  return $http.get('//server.com/api/DynamicFutureStates').then(function(data) {
      //    angular.forEach(data.futureStates, function(fstate) { $futureStateProvider.futureState(fstate); });
      //  };
      // }
      this.addResolve = function (promiseFn) {
        resolveFunctions.push(promiseFn);
      };

      // Register a state factory function for a particular future-state type.  This factory, given a future-state object,
      // should create a ui-router state.
      // The factory function is injected/executed using the runtime $injector.  The future-state is injected as 'futureState'.

      // Example:
      //    $futureStateProvider.stateFactory('test', function(futureState) {
      //      return {
      //        name: futureState.stateName,
      //        url: futureState.urlFragment,
      //        template: '
Future State Template
',
      //        controller: function() {
      //          console.log("Entered state " + futureState.stateName);
      //        }
      //      }
      //    });
      this.stateFactory = function (futureStateType, factory) {
        stateFactories[futureStateType] = factory;
      };

      this.futureState = function (futureState) {
        if (futureState.stateName)  // backwards compat for now
          futureState.name = futureState.stateName;
        if (futureState.urlPrefix)  // backwards compat for now
          futureState.url = "^" + futureState.urlPrefix;

        futureStates[futureState.name] = futureState;
        var parentMatcher,  parentName = futureState.name.split(/\./).slice(0, -1).join("."),
          realParent = findState(futureState.parent || parentName);
        if (realParent) {
          parentMatcher = realParent.url;
        } else {
          var futureParent = findState((futureState.parent || parentName), true);
          if (!futureParent) throw new Error("Couldn't determine parent state of future state. FutureState:" + angular.toJson(futureState));
          var pattern = futureParent.urlMatcher.source.replace(/\*rest$/, "");
          parentMatcher = $urlMatcherFactory.compile(pattern);
          futureState.parentFutureState = futureParent;
        }
        futureState.urlMatcher = futureState.url.charAt(0) === "^" ?
          $urlMatcherFactory.compile(futureState.url.substring(1) + "*rest") :
          parentMatcher.concat(futureState.url + "*rest");
      };

      this.get = function () {
        return angular.extend({}, futureStates);
      };

      function findState(stateOrName, findFutureState) {
        var statename = angular.isObject(stateOrName) ? stateOrName.name : stateOrName;
        return !findFutureState ? internalStates[statename] : futureStates[statename];
      }

      /* options is an object with at least a name or url attribute */
      function findFutureState($state, options) {
        if (options.name) {
          var nameComponents = options.name.split(/\./);
          if (options.name.charAt(0) === '.')
            nameComponents[0] = $state.current.name;
          while (nameComponents.length) {
            var stateName = nameComponents.join(".");
            if ($state.get(stateName, { relative: $state.current }))
              return null; // State is already defined; nothing to do
            if (futureStates[stateName])
              return futureStates[stateName];
            nameComponents.pop();
          }
        }

        if (options.url) {
          var matches = [];
          for(var future in futureStates) {
            if (futureStates[future].urlMatcher.exec(options.url)) {
              matches.push(futureStates[future]);
            }
          }
          // Find most specific by ignoring matching parents from matches
          var copy = matches.slice(0);
          for (var i = matches.length - 1; i >= 0; i--) {
            for (var j = 0; j < copy.length; j++) {
              if (matches[i] === copy[j].parentFutureState) matches.splice(i, 1);
            }
          }
          return matches[0];
        }
      }

      function lazyLoadState($injector, futureState) {
        if (!futureState) {
          var deferred = $q.defer();
          deferred.reject("No lazyState passed in " + futureState);
          return deferred.promise;
        }

        var promise = $q.when(true), parentFuture = futureState.parentFutureState;
        if (parentFuture && futureStates[parentFuture.name]) {
          promise = lazyLoadState($injector, futureStates[parentFuture.name]);
        }

        var type = futureState.type;
        var factory = stateFactories[type];
        if (!factory) throw Error("No state factory for futureState.type: " + (futureState && futureState.type));
        return promise
          .then(function() {
            return $injector.invoke(factory, factory, { futureState: futureState });
          })
          .finally(function() {
            delete(futureStates[futureState.name]);
          });
      }

      var otherwiseFunc = [ '$log', '$location',
        function otherwiseFunc($log, $location) {
          $log.debug("Unable to map " + $location.path());
        }];

      function futureState_otherwise($injector, $location) {
        var resyncing = false;

        var lazyLoadMissingState =
          ['$rootScope', '$urlRouter', '$state',
            function lazyLoadMissingState($rootScope, $urlRouter, $state) {
              if (!initDone) {
                // Asynchronously load state definitions, then resync URL
                initPromise().then(function initialResync() {
                  resyncing = true;
                  $urlRouter.sync();
                  resyncing = false;
                });
                initDone = true;
                return;
              }

              var futureState = findFutureState($state, { url: $location.path() });
              if (!futureState) {
                return $injector.invoke(otherwiseFunc);
              }

              transitionPending = true;
              // Config loaded.  Asynchronously lazy-load state definition from URL fragment, if mapped.
              lazyLoadState($injector, futureState).then(function lazyLoadedStateCallback(state) {
                // TODO: Should have a specific resolve value that says 'dont register a state because I already did'
                if (state && (!$state.get(state) || (state.name && !$state.get(state.name))))
                  $stateProvider.state(state);
                resyncing = true;
                $urlRouter.sync();
                resyncing = false;
                transitionPending = false;
              }, function lazyLoadStateAborted() {
                transitionPending = false;
                return $injector.invoke(otherwiseFunc);
              });
            }];
        if (transitionPending) return;

        var nextFn = resyncing ? otherwiseFunc : lazyLoadMissingState;
        return $injector.invoke(nextFn);
      }

      $urlRouterProvider.otherwise(futureState_otherwise);

      $urlRouterProvider.otherwise = function(rule) {
        if (angular.isString(rule)) {
          var redirect = rule;
          rule = function () { return redirect; };
        }
        else if (!angular.isFunction(rule)) throw new Error("'rule' must be a function");
        otherwiseFunc = rule;
        return $urlRouterProvider;
      };

      var serviceObject = {
        getResolvePromise: function () {
          return initPromise();
        }
      };

      // Used in .run() block to init
      this.$get = [ '$injector', '$state', '$q', '$rootScope', '$urlRouter', '$timeout', '$log',
        function futureStateProvider_get($injector, $state, $q, $rootScope, $urlRouter, $timeout, $log) {
          function init() {
            $rootScope.$on("$stateNotFound", function futureState_notFound(event, unfoundState, fromState, fromParams) {
              if (transitionPending) return;
              $log.debug("event, unfoundState, fromState, fromParams", event, unfoundState, fromState, fromParams);

              var futureState = findFutureState($state, { name: unfoundState.to });
              if (!futureState) return;

              event.preventDefault();
              transitionPending = true;

              var promise = lazyLoadState($injector, futureState);
              promise.then(function (state) {
                // TODO: Should have a specific resolve value that says 'dont register a state because I already did'
                if (state && (!$state.get(state) || (state.name && !$state.get(state.name))))
                  $stateProvider.state(state);
                $state.go(unfoundState.to, unfoundState.toParams);
                transitionPending = false;
              }, function (error) {
                console.log("failed to lazy load state ", error);
                $state.go(fromState, fromParams);
                transitionPending = false;
              });
            });

            // Do this better.  Want to load remote config once, before everything else
            if (!initPromise) {
              var promises = [];
              angular.forEach(resolveFunctions, function (promiseFn) {
                promises.push($injector.invoke(promiseFn));
              });
              initPromise = function () {
                return $q.all(promises);
              };
//          initPromise = _.once(function flattenFutureStates() {
//            var allPromises = $q.all(promises);
//            return allPromises.then(function(data) {
//              return _.flatten(data);
//            });
//          });
            }

            // TODO: analyze this. I'm calling $urlRouter.sync() in two places for retry-initial-transition.
            // TODO: I should only need to do this once.  Pick the better place and remove the extra resync.
            initPromise().then(function retryInitialState() {
              $timeout(function () {
                if ($state.transition) {
                  $state.transition.then($urlRouter.sync, $urlRouter.sync);
                } else {
                  $urlRouter.sync();
                }
              });
            });
          }

          init();

          serviceObject.state = $stateProvider.state;
          serviceObject.futureState = provider.futureState;
          serviceObject.get = provider.get;

          return serviceObject;
        }];
    }]);

angular.module('ct.ui.router.extras').run(['$futureState',
  // Just inject $futureState so it gets initialized.
  function ($futureState) {
  }
]);
<|endoftext|>


<commit_before>describe('personal log', function() {

  beforeEach(function() {
    browser().navigateTo('../personalLog.html');
  });

  afterEach(function() {
    clearCookies();
  });

  it('should create new logs and order them in reverse chronological order', function() {
    //create first msg
    input('newMsg').enter('my first message');
    element('form input[type="submit"]').click();

    expect(repeater('ul li').count()).toEqual(1);
    expect(repeater('ul li').column('log.msg')).toEqual('my first message');

    //create second msg
    input('newMsg').enter('my second message');
    element('form input[type="submit"]').click();

    expect(repeater('ul li').count()).toEqual(2);
    expect(repeater('ul li').column('log.msg')).toEqual(['my second message', 'my first message']);
  });

  it('should delete a log when user clicks on the related X link', function() {
    //create first msg
    input('newMsg').enter('my first message');
    element('form input[type="submit"]').click();
    //create second msg
    input('newMsg').enter('my second message');
    element('form input[type="submit"]').click();
    expect(repeater('ul li').count()).toEqual(2);

    element('ul li a:eq(1)').click();
    expect(repeater('ul li').count()).toEqual(1);
    expect(repeater('ul li').column('log.msg')).toEqual('my second message');

    element('ul li a:eq(0)').click();
    expect(repeater('ul li').count()).toEqual(0);
  });

  it('should delete all cookies when user clicks on "remove all" button', function() {
    //create first msg
    input('newMsg').enter('my first message');
    element('form input[type="submit"]').click();
    //create second msg
    input('newMsg').enter('my second message');
    element('form input[type="submit"]').click();
    expect(repeater('ul li').count()).toEqual(2);

    element('input[value="remove all"]').click();
    expect(repeater('ul li').count()).toEqual(0);
  });

  it('should preserve logs over page reloads', function() {
    input('newMsg').enter('my persistent message');
    element('form input[type="submit"]').click();
    expect(repeater('ul li').count()).toEqual(1);

    browser().reload();

    expect(repeater('ul li').column('log.msg')).toEqual('my persistent message');
    expect(repeater('ul li').count()).toEqual(1);
  });
});

/**
 * DSL for deleting all cookies.
 */
angular.scenario.dsl('clearCookies', function() {
  /**
   * Deletes cookies by interacting with the cookie service within the application under test.
   */
  return function() {
    this.addFutureAction('clear all cookies', function($window, $document, done) {
      var rootScope = $window.angular.element($document[0]).data('$scope'),
          $cookies = rootScope.$service('$cookies'),
          cookieName;

      for (cookieName in $cookies) {
        delete $cookies[cookieName];
      }
      rootScope.$eval();

      done();
    });
  };
});
<commit_msg>fix(example): fixes for personalLog e2e tests<commit_after>describe('personal log', function() {

  beforeEach(function() {
    browser().navigateTo('../personalLog.html');
  });

  afterEach(function() {
    clearCookies();
  });

  it('should create new logs and order them in reverse chronological order', function() {
    //create first msg
    input('newMsg').enter('my first message');
    element('form input[type="submit"]').click();

    expect(repeater('ul li').count()).toEqual(1);
    expect(repeater('ul li').column('log.msg')).toEqual(['my first message']);

    //create second msg
    input('newMsg').enter('my second message');
    element('form input[type="submit"]').click();

    expect(repeater('ul li').count()).toEqual(2);
    expect(repeater('ul li').column('log.msg')).toEqual(['my second message', 'my first message']);
  });

  it('should delete a log when user clicks on the related X link', function() {
    //create first msg
    input('newMsg').enter('my first message');
    element('form input[type="submit"]').click();
    //create second msg
    input('newMsg').enter('my second message');
    element('form input[type="submit"]').click();
    expect(repeater('ul li').count()).toEqual(2);

    element('ul li a:eq(1)').click();
    expect(repeater('ul li').count()).toEqual(1);
    expect(repeater('ul li').column('log.msg')).toEqual(['my second message']);

    element('ul li a:eq(0)').click();
    expect(repeater('ul li').count()).toEqual(0);
  });

  it('should delete all cookies when user clicks on "remove all" button', function() {
    //create first msg
    input('newMsg').enter('my first message');
    element('form input[type="submit"]').click();
    //create second msg
    input('newMsg').enter('my second message');
    element('form input[type="submit"]').click();
    expect(repeater('ul li').count()).toEqual(2);

    element('input[value="remove all"]').click();
    expect(repeater('ul li').count()).toEqual(0);
  });

  it('should preserve logs over page reloads', function() {
    input('newMsg').enter('my persistent message');
    element('form input[type="submit"]').click();
    expect(repeater('ul li').count()).toEqual(1);

    browser().reload();

    expect(repeater('ul li').column('log.msg')).toEqual(['my persistent message']);
    expect(repeater('ul li').count()).toEqual(1);
  });
});

/**
 * DSL for deleting all cookies.
 */
angular.scenario.dsl('clearCookies', function() {
  /**
   * Deletes cookies by interacting with the cookie service within the application under test.
   */
  return function() {
    this.addFutureAction('clear all cookies', function($window, $document, done) {
      var rootScope = $window.angular.element($document[0]).data('$scope'),
          $cookies = rootScope.$service('$cookies'),
          cookieName;

      rootScope.$apply(function() {
        for (cookieName in $cookies) {
          delete $cookies[cookieName];
        }
      });

      done();
    });
  };
});
<|endoftext|>


<commit_before>'use strict';
var sendTxCtrl = function($scope, $sce, walletService) {
    $scope.ajaxReq = ajaxReq;
    $scope.unitReadable = ajaxReq.type;
    $scope.sendTxModal = new Modal(document.getElementById('sendTransaction'));
    walletService.wallet = null;
    walletService.password = '';
    $scope.showAdvance = $scope.showRaw = false;
    $scope.dropdownEnabled = true;
    $scope.Validator = Validator;
    $scope.gasLimitChanged = false;
    var currentTab = $scope.globalService.currentTab;
    var tabs = $scope.globalService.tabs;

    if(currentTab == tabs.sendTransaction.id){
        //this is for you @tayvano
    }
    // Tokens
    $scope.tokenVisibility = "hidden";
    $scope.tokenTx = {
        to: '',
        value: 0,
        id: -1
    };
    $scope.customGasMsg = ''

    $scope.customGas = CustomGasMessages

    $scope.tx = {
        // if there is no gasLimit or gas key in the URI, use the default value. Otherwise use value of gas or gasLimit. gasLimit wins over gas if both present
        gasLimit: globalFuncs.urlGet('gaslimit') != null || globalFuncs.urlGet('gas') != null ? globalFuncs.urlGet('gaslimit') != null ? globalFuncs.urlGet('gaslimit') : globalFuncs.urlGet('gas') : globalFuncs.defaultTxGasLimit,
        data: globalFuncs.urlGet('data') == null ? "" : globalFuncs.urlGet('data'),
        to: globalFuncs.urlGet('to') == null ? "" : globalFuncs.urlGet('to'),
        unit: "ether",
        value: globalFuncs.urlGet('value') == null ? "" : globalFuncs.urlGet('value'),
        nonce: null,
        gasPrice: null,
        donate: false,
        tokenSymbol: globalFuncs.urlGet('tokenSymbol') == null ? false : globalFuncs.urlGet('tokenSymbol'),
        readOnly: globalFuncs.urlGet('readOnly') == null ? false : true
    }
    $scope.setSendMode = function(sendMode, tokenId = '', tokenSymbol = '') {
        $scope.tx.sendMode = sendMode;
        $scope.unitReadable = '';
        if (sendMode == 'ether') {
            $scope.unitReadable = ajaxReq.type;
        } else {
            $scope.unitReadable = tokenSymbol;
            $scope.tokenTx.id = tokenId;
        }
        $scope.dropdownAmount = false;
    }
    $scope.setTokenSendMode = function() {
        if ($scope.tx.sendMode == 'token' && !$scope.tx.tokenSymbol) {
            $scope.tx.tokenSymbol = $scope.wallet.tokenObjs[0].symbol;
            $scope.wallet.tokenObjs[0].type = "custom";
            $scope.setSendMode($scope.tx.sendMode, 0, $scope.tx.tokenSymbol);
        } else if ($scope.tx.tokenSymbol) {
            for (var i = 0; i < $scope.wallet.tokenObjs.length; i++) {
                if ($scope.wallet.tokenObjs[i].symbol.toLowerCase().indexOf($scope.tx.tokenSymbol.toLowerCase()) !== -1) {
                    $scope.wallet.tokenObjs[i].type = "custom";
                    $scope.setSendMode('token', i, $scope.wallet.tokenObjs[i].symbol);
                    break;
                } else $scope.tokenTx.id = -1;
            }
        }
        if ($scope.tx.sendMode != 'token') $scope.tokenTx.id = -1;
    }
    var applyScope = function() {
        if (!$scope.$$phase) $scope.$apply();
    }
    var defaultInit = function() {
        globalFuncs.urlGet('sendMode') == null ? $scope.setSendMode('ether') : $scope.setSendMode(globalFuncs.urlGet('sendMode'));
        $scope.showAdvance = globalFuncs.urlGet('gaslimit') != null || globalFuncs.urlGet('gas') != null || globalFuncs.urlGet('data') != null;
        if (globalFuncs.urlGet('data') || globalFuncs.urlGet('value') || globalFuncs.urlGet('to') || globalFuncs.urlGet('gaslimit') || globalFuncs.urlGet('sendMode') || globalFuncs.urlGet('gas') || globalFuncs.urlGet('tokenSymbol')) $scope.hasQueryString = true // if there is a query string, show an warning at top of page

    }
    $scope.$watch(function() {
        if (walletService.wallet == null) return null;
        return walletService.wallet.getAddressString();
    }, function() {
        if (walletService.wallet == null) return;
        $scope.wallet = walletService.wallet;
        $scope.wd = true;
        $scope.wallet.setBalance(applyScope);
        $scope.wallet.setTokens();
        if ($scope.parentTxConfig) {
            var setTxObj = function() {
                $scope.addressDrtv.ensAddressField = $scope.parentTxConfig.to;
                $scope.tx.value = $scope.parentTxConfig.value;
                $scope.tx.sendMode = $scope.parentTxConfig.sendMode ? $scope.parentTxConfig.sendMode : 'ether';
                $scope.tx.tokenSymbol = $scope.parentTxConfig.tokenSymbol ? $scope.parentTxConfig.tokenSymbol : '';
                $scope.tx.readOnly = $scope.addressDrtv.readOnly = $scope.parentTxConfig.readOnly ? $scope.parentTxConfig.readOnly : false;
                $scope.tx.gasPrice = $scope.parentTxConfig.gasPrice ? $scope.parentTxConfig.gasPrice : null;
                $scope.tx.nonce = $scope.parentTxConfig.nonce ? $scope.parentTxConfig.nonce : null;
                $scope.tx.data = $scope.parentTxConfig.data ? $scope.parentTxConfig.data : "";
                if ($scope.parentTxConfig.gasLimit) {
                    $scope.tx.gasLimit = $scope.parentTxConfig.gasLimit;
                    $scope.gasLimitChanged = true;
                }
            }
            $scope.$watch('parentTxConfig', function() {
                setTxObj();
            }, true);
        }
        $scope.setTokenSendMode();
        defaultInit();
    });
    $scope.$watch('ajaxReq.key', function() {
        if ($scope.wallet) {
            $scope.setSendMode('ether');
            $scope.wallet.setBalance(applyScope);
            $scope.wallet.setTokens();
        }
    });
    $scope.$watch('tokenTx', function() {
        if ($scope.wallet && $scope.wallet.tokenObjs !== undefined && $scope.wallet.tokenObjs[$scope.tokenTx.id] !== undefined && $scope.Validator.isValidAddress($scope.tokenTx.to) && $scope.Validator.isPositiveNumber($scope.tokenTx.value)) {
            if ($scope.estimateTimer) clearTimeout($scope.estimateTimer);
            $scope.estimateTimer = setTimeout(function() {
                $scope.estimateGasLimit();
            }, 500);
        }
    }, true);
    $scope.$watch('tx', function(newValue, oldValue) {
        $scope.showRaw = false;
        if (oldValue.sendMode != newValue.sendMode && newValue.sendMode == 'ether') {
            $scope.tx.data = "";
            $scope.tx.gasLimit = globalFuncs.defaultTxGasLimit;
        }
        if (newValue.gasLimit == oldValue.gasLimit && $scope.wallet && $scope.Validator.isValidAddress($scope.tx.to) && $scope.Validator.isPositiveNumber($scope.tx.value) && $scope.Validator.isValidHex($scope.tx.data) && $scope.tx.sendMode != 'token') {
            if ($scope.estimateTimer) clearTimeout($scope.estimateTimer);
            $scope.estimateTimer = setTimeout(function() {
                $scope.estimateGasLimit();
            }, 500);
        }
        if ($scope.tx.sendMode == 'token') {
            $scope.tokenTx.to = $scope.tx.to;
            $scope.tokenTx.value = $scope.tx.value;
        }
        if (newValue.to !== oldValue.to) {
            for (var i in $scope.customGas) {
                if ($scope.tx.to.toLowerCase() == $scope.customGas[i].to.toLowerCase()) {
                    $scope.customGasMsg = $scope.customGas[i].msg != '' ? $scope.customGas[i].msg : ''
                    return;
                }
            }

            $scope.customGasMsg = ''
        }
    }, true);
    $scope.estimateGasLimit = function() {
        $scope.customGasMsg = ''
        if ($scope.gasLimitChanged) return;
        for (var i in $scope.customGas) {
            if ($scope.tx.to.toLowerCase() == $scope.customGas[i].to.toLowerCase()) {
                $scope.showAdvance = $scope.customGas[i].data != '' ? true : false;
                $scope.tx.gasLimit = $scope.customGas[i].gasLimit;
                $scope.tx.data = $scope.customGas[i].data;
                $scope.customGasMsg = $scope.customGas[i].msg != '' ? $scope.customGas[i].msg : ''
                return;
            }
        }
        if (globalFuncs.lightMode) {
            $scope.tx.gasLimit = globalFuncs.defaultTokenGasLimit;
            return;
        }
        var estObj = {
            to: $scope.tx.to,
            from: $scope.wallet.getAddressString(),
            value: ethFuncs.sanitizeHex(ethFuncs.decimalToHex(etherUnits.toWei($scope.tx.value, $scope.tx.unit)))
        }
        if ($scope.tx.data != "") estObj.data = ethFuncs.sanitizeHex($scope.tx.data);
        if ($scope.tx.sendMode == 'token') {
            estObj.to = $scope.wallet.tokenObjs[$scope.tokenTx.id].getContractAddress();
            estObj.data = $scope.wallet.tokenObjs[$scope.tokenTx.id].getData($scope.tokenTx.to, $scope.tokenTx.value).data;
            estObj.value = '0x00';
        }
        ethFuncs.estimateGas(estObj, function(data) {

            if (!data.error) {
                if (data.data == '-1') $scope.notifier.danger(globalFuncs.errorMsgs[21]);
                $scope.tx.gasLimit = data.data;
            } else $scope.notifier.danger(data.msg);
        });
    }
    var isEnough = function(valA, valB) {
        return new BigNumber(valA).lte(new BigNumber(valB));
    }
    $scope.hasEnoughBalance = function() {
        if ($scope.wallet.balance == 'loading') return false;
        return isEnough($scope.tx.value, $scope.wallet.balance);
    }
    $scope.onDonateClick = function() {
        $scope.addressDrtv.ensAddressField = globalFuncs.donateAddress;
        $scope.tx.value = "1";
        $scope.tx.donate = true;
    }
    $scope.generateTx = function() {
        if (!$scope.Validator.isValidAddress($scope.tx.to)) {
            $scope.notifier.danger(globalFuncs.errorMsgs[5]);
            return;
        }
        var txData = uiFuncs.getTxData($scope);
        txData.gasPrice = $scope.tx.gasPrice ? '0x' + new BigNumber($scope.tx.gasPrice).toString(16) : null;
        txData.nonce = $scope.tx.nonce ? '0x' + new BigNumber($scope.tx.nonce).toString(16) : null;

        // set to true for offline tab and txstatus tab
        // on sendtx tab, it pulls gas price from the gasprice slider & nonce
        // if its true the whole txData object is set - don't try to change it
        // if false, replace gas price and nonce. gas price from slider. nonce from server.
        if (txData.gasPrice && txData.nonce) txData.isOffline = true;

        if ($scope.tx.sendMode == 'token') {
            // if the amount of tokens you are trying to send > tokens you have, throw error
            if (!isEnough($scope.tx.value, $scope.wallet.tokenObjs[$scope.tokenTx.id].balance)) {
                $scope.notifier.danger(globalFuncs.errorMsgs[0]);
                return;
            }
            txData.to = $scope.wallet.tokenObjs[$scope.tokenTx.id].getContractAddress();
            txData.data = $scope.wallet.tokenObjs[$scope.tokenTx.id].getData($scope.tokenTx.to, $scope.tokenTx.value).data;
            txData.value = '0x00';
        }
        uiFuncs.generateTx(txData, function(rawTx) {
            if (!rawTx.isError) {
                $scope.rawTx = rawTx.rawTx;
                $scope.signedTx = rawTx.signedTx;
                $scope.showRaw = true;
            } else {
                $scope.showRaw = false;
                $scope.notifier.danger(rawTx.error);
            }
            if (!$scope.$$phase) $scope.$apply();
        });
    }
    $scope.sendTx = function() {
        $scope.sendTxModal.close();
        uiFuncs.sendTx($scope.signedTx, function(resp) {
            if (!resp.isError) {
                var txHashLink = $scope.ajaxReq.blockExplorerTX.replace("[[txHash]]", resp.data)
                var bExStr = $scope.ajaxReq.type != nodes.nodeTypes.Custom ? "Verify Transaction" : '';
                var checkTXLink = ' Check TX Status ';
                var emailLink = '<a class="btn btn-xs btn-info" href="mailto:support@myetherwallet.com?Subject=Issue%20regarding%20my%20TX%20&Body=I%20was%20trying%20to..............%0A%0A%0A%0ABut%20I%27m%20confused%20because...............%0A%0A%0A%0A%0A' + "%0ATo%20Address%3A%20https%3A%2F%2Fetherscan.io%2Faddress%2F" + $scope.tx.to + "%0AFrom%20Address%3A%20https%3A%2F%2Fetherscan.io%2Faddress%2F" + $scope.wallet.getAddressString() + "%0ATX%20Hash%3A%20https%3A%2F%2Fetherscan.io%2Ftx%2F" + resp.data + "%0AAmount%3A%20" + $scope.tx.value + "%20" + $scope.unitReadable + "%0ANode%3A%20" + $scope.ajaxReq.type + "%0AToken%20To%20Addr%3A%20" + $scope.tokenTx.to + "%0AToken%20Amount%3A%20" + $scope.tokenTx.value + "%20" + $scope.unitReadable + "%0AData%3A%20" + $scope.tx.data + "%0AGas%20Limit%3A%20" + $scope.tx.gasLimit + "%0AGas%20Price%3A%20" + $scope.tx.gasPrice + '" target="_blank" rel="noopener">Confused? Email Us.';
                var completeMsg = "
" + globalFuncs.successMsgs[2] + '' + resp.data + "

" + bExStr + " " + checkTXLink + " " + emailLink + "
";
                $scope.notifier.success( completeMsg, 0 );
                $scope.wallet.setBalance(applyScope);
                if ($scope.tx.sendMode == 'token') $scope.wallet.tokenObjs[$scope.tokenTx.id].setBalance();
            } else {
                $scope.notifier.danger(resp.error);
            }
        });
    }
    $scope.transferAllBalance = function() {
        if ($scope.tx.sendMode != 'token') {
            uiFuncs.transferAllBalance($scope.wallet.getAddressString(), $scope.tx.gasLimit, function(resp) {
                if (!resp.isError) {
                    $scope.tx.unit = resp.unit;
                    $scope.tx.value = resp.value;
                } else {
                    $scope.showRaw = false;
                    $scope.notifier.danger(resp.error);
                }
            });
        } else {
            $scope.tx.value = $scope.wallet.tokenObjs[$scope.tokenTx.id].getBalance();
        }
    }
};
module.exports = sendTxCtrl;
<commit_msg>update send TX messaging<commit_after>'use strict';
var sendTxCtrl = function($scope, $sce, walletService) {
    $scope.ajaxReq = ajaxReq;
    $scope.unitReadable = ajaxReq.type;
    $scope.sendTxModal = new Modal(document.getElementById('sendTransaction'));
    walletService.wallet = null;
    walletService.password = '';
    $scope.showAdvance = $scope.showRaw = false;
    $scope.dropdownEnabled = true;
    $scope.Validator = Validator;
    $scope.gasLimitChanged = false;
    var currentTab = $scope.globalService.currentTab;
    var tabs = $scope.globalService.tabs;

    if(currentTab == tabs.sendTransaction.id){
        //this is for you @tayvano
    }
    // Tokens
    $scope.tokenVisibility = "hidden";
    $scope.tokenTx = {
        to: '',
        value: 0,
        id: -1
    };
    $scope.customGasMsg = ''

    $scope.customGas = CustomGasMessages

    $scope.tx = {
        // if there is no gasLimit or gas key in the URI, use the default value. Otherwise use value of gas or gasLimit. gasLimit wins over gas if both present
        gasLimit: globalFuncs.urlGet('gaslimit') != null || globalFuncs.urlGet('gas') != null ? globalFuncs.urlGet('gaslimit') != null ? globalFuncs.urlGet('gaslimit') : globalFuncs.urlGet('gas') : globalFuncs.defaultTxGasLimit,
        data: globalFuncs.urlGet('data') == null ? "" : globalFuncs.urlGet('data'),
        to: globalFuncs.urlGet('to') == null ? "" : globalFuncs.urlGet('to'),
        unit: "ether",
        value: globalFuncs.urlGet('value') == null ? "" : globalFuncs.urlGet('value'),
        nonce: null,
        gasPrice: null,
        donate: false,
        tokenSymbol: globalFuncs.urlGet('tokenSymbol') == null ? false : globalFuncs.urlGet('tokenSymbol'),
        readOnly: globalFuncs.urlGet('readOnly') == null ? false : true
    }
    $scope.setSendMode = function(sendMode, tokenId = '', tokenSymbol = '') {
        $scope.tx.sendMode = sendMode;
        $scope.unitReadable = '';
        if (sendMode == 'ether') {
            $scope.unitReadable = ajaxReq.type;
        } else {
            $scope.unitReadable = tokenSymbol;
            $scope.tokenTx.id = tokenId;
        }
        $scope.dropdownAmount = false;
    }
    $scope.setTokenSendMode = function() {
        if ($scope.tx.sendMode == 'token' && !$scope.tx.tokenSymbol) {
            $scope.tx.tokenSymbol = $scope.wallet.tokenObjs[0].symbol;
            $scope.wallet.tokenObjs[0].type = "custom";
            $scope.setSendMode($scope.tx.sendMode, 0, $scope.tx.tokenSymbol);
        } else if ($scope.tx.tokenSymbol) {
            for (var i = 0; i < $scope.wallet.tokenObjs.length; i++) {
                if ($scope.wallet.tokenObjs[i].symbol.toLowerCase().indexOf($scope.tx.tokenSymbol.toLowerCase()) !== -1) {
                    $scope.wallet.tokenObjs[i].type = "custom";
                    $scope.setSendMode('token', i, $scope.wallet.tokenObjs[i].symbol);
                    break;
                } else $scope.tokenTx.id = -1;
            }
        }
        if ($scope.tx.sendMode != 'token') $scope.tokenTx.id = -1;
    }
    var applyScope = function() {
        if (!$scope.$$phase) $scope.$apply();
    }
    var defaultInit = function() {
        globalFuncs.urlGet('sendMode') == null ? $scope.setSendMode('ether') : $scope.setSendMode(globalFuncs.urlGet('sendMode'));
        $scope.showAdvance = globalFuncs.urlGet('gaslimit') != null || globalFuncs.urlGet('gas') != null || globalFuncs.urlGet('data') != null;
        if (globalFuncs.urlGet('data') || globalFuncs.urlGet('value') || globalFuncs.urlGet('to') || globalFuncs.urlGet('gaslimit') || globalFuncs.urlGet('sendMode') || globalFuncs.urlGet('gas') || globalFuncs.urlGet('tokenSymbol')) $scope.hasQueryString = true // if there is a query string, show an warning at top of page

    }
    $scope.$watch(function() {
        if (walletService.wallet == null) return null;
        return walletService.wallet.getAddressString();
    }, function() {
        if (walletService.wallet == null) return;
        $scope.wallet = walletService.wallet;
        $scope.wd = true;
        $scope.wallet.setBalance(applyScope);
        $scope.wallet.setTokens();
        if ($scope.parentTxConfig) {
            var setTxObj = function() {
                $scope.addressDrtv.ensAddressField = $scope.parentTxConfig.to;
                $scope.tx.value = $scope.parentTxConfig.value;
                $scope.tx.sendMode = $scope.parentTxConfig.sendMode ? $scope.parentTxConfig.sendMode : 'ether';
                $scope.tx.tokenSymbol = $scope.parentTxConfig.tokenSymbol ? $scope.parentTxConfig.tokenSymbol : '';
                $scope.tx.readOnly = $scope.addressDrtv.readOnly = $scope.parentTxConfig.readOnly ? $scope.parentTxConfig.readOnly : false;
                $scope.tx.gasPrice = $scope.parentTxConfig.gasPrice ? $scope.parentTxConfig.gasPrice : null;
                $scope.tx.nonce = $scope.parentTxConfig.nonce ? $scope.parentTxConfig.nonce : null;
                $scope.tx.data = $scope.parentTxConfig.data ? $scope.parentTxConfig.data : "";
                if ($scope.parentTxConfig.gasLimit) {
                    $scope.tx.gasLimit = $scope.parentTxConfig.gasLimit;
                    $scope.gasLimitChanged = true;
                }
            }
            $scope.$watch('parentTxConfig', function() {
                setTxObj();
            }, true);
        }
        $scope.setTokenSendMode();
        defaultInit();
    });
    $scope.$watch('ajaxReq.key', function() {
        if ($scope.wallet) {
            $scope.setSendMode('ether');
            $scope.wallet.setBalance(applyScope);
            $scope.wallet.setTokens();
        }
    });
    $scope.$watch('tokenTx', function() {
        if ($scope.wallet && $scope.wallet.tokenObjs !== undefined && $scope.wallet.tokenObjs[$scope.tokenTx.id] !== undefined && $scope.Validator.isValidAddress($scope.tokenTx.to) && $scope.Validator.isPositiveNumber($scope.tokenTx.value)) {
            if ($scope.estimateTimer) clearTimeout($scope.estimateTimer);
            $scope.estimateTimer = setTimeout(function() {
                $scope.estimateGasLimit();
            }, 500);
        }
    }, true);
    $scope.$watch('tx', function(newValue, oldValue) {
        $scope.showRaw = false;
        if (oldValue.sendMode != newValue.sendMode && newValue.sendMode == 'ether') {
            $scope.tx.data = "";
            $scope.tx.gasLimit = globalFuncs.defaultTxGasLimit;
        }
        if (newValue.gasLimit == oldValue.gasLimit && $scope.wallet && $scope.Validator.isValidAddress($scope.tx.to) && $scope.Validator.isPositiveNumber($scope.tx.value) && $scope.Validator.isValidHex($scope.tx.data) && $scope.tx.sendMode != 'token') {
            if ($scope.estimateTimer) clearTimeout($scope.estimateTimer);
            $scope.estimateTimer = setTimeout(function() {
                $scope.estimateGasLimit();
            }, 500);
        }
        if ($scope.tx.sendMode == 'token') {
            $scope.tokenTx.to = $scope.tx.to;
            $scope.tokenTx.value = $scope.tx.value;
        }
        if (newValue.to !== oldValue.to) {
            for (var i in $scope.customGas) {
                if ($scope.tx.to.toLowerCase() == $scope.customGas[i].to.toLowerCase()) {
                    $scope.customGasMsg = $scope.customGas[i].msg != '' ? $scope.customGas[i].msg : ''
                    return;
                }
            }

            $scope.customGasMsg = ''
        }
    }, true);
    $scope.estimateGasLimit = function() {
        $scope.customGasMsg = ''
        if ($scope.gasLimitChanged) return;
        for (var i in $scope.customGas) {
            if ($scope.tx.to.toLowerCase() == $scope.customGas[i].to.toLowerCase()) {
                $scope.showAdvance = $scope.customGas[i].data != '' ? true : false;
                $scope.tx.gasLimit = $scope.customGas[i].gasLimit;
                $scope.tx.data = $scope.customGas[i].data;
                $scope.customGasMsg = $scope.customGas[i].msg != '' ? $scope.customGas[i].msg : ''
                return;
            }
        }
        if (globalFuncs.lightMode) {
            $scope.tx.gasLimit = globalFuncs.defaultTokenGasLimit;
            return;
        }
        var estObj = {
            to: $scope.tx.to,
            from: $scope.wallet.getAddressString(),
            value: ethFuncs.sanitizeHex(ethFuncs.decimalToHex(etherUnits.toWei($scope.tx.value, $scope.tx.unit)))
        }
        if ($scope.tx.data != "") estObj.data = ethFuncs.sanitizeHex($scope.tx.data);
        if ($scope.tx.sendMode == 'token') {
            estObj.to = $scope.wallet.tokenObjs[$scope.tokenTx.id].getContractAddress();
            estObj.data = $scope.wallet.tokenObjs[$scope.tokenTx.id].getData($scope.tokenTx.to, $scope.tokenTx.value).data;
            estObj.value = '0x00';
        }
        ethFuncs.estimateGas(estObj, function(data) {

            if (!data.error) {
                if (data.data == '-1') $scope.notifier.danger(globalFuncs.errorMsgs[21]);
                $scope.tx.gasLimit = data.data;
            } else $scope.notifier.danger(data.msg);
        });
    }
    var isEnough = function(valA, valB) {
        return new BigNumber(valA).lte(new BigNumber(valB));
    }
    $scope.hasEnoughBalance = function() {
        if ($scope.wallet.balance == 'loading') return false;
        return isEnough($scope.tx.value, $scope.wallet.balance);
    }
    $scope.onDonateClick = function() {
        $scope.addressDrtv.ensAddressField = globalFuncs.donateAddress;
        $scope.tx.value = "1";
        $scope.tx.donate = true;
    }
    $scope.generateTx = function() {
        if (!$scope.Validator.isValidAddress($scope.tx.to)) {
            $scope.notifier.danger(globalFuncs.errorMsgs[5]);
            return;
        }
        var txData = uiFuncs.getTxData($scope);
        txData.gasPrice = $scope.tx.gasPrice ? '0x' + new BigNumber($scope.tx.gasPrice).toString(16) : null;
        txData.nonce = $scope.tx.nonce ? '0x' + new BigNumber($scope.tx.nonce).toString(16) : null;

        // set to true for offline tab and txstatus tab
        // on sendtx tab, it pulls gas price from the gasprice slider & nonce
        // if its true the whole txData object is set - don't try to change it
        // if false, replace gas price and nonce. gas price from slider. nonce from server.
        if (txData.gasPrice && txData.nonce) txData.isOffline = true;

        if ($scope.tx.sendMode == 'token') {
            // if the amount of tokens you are trying to send > tokens you have, throw error
            if (!isEnough($scope.tx.value, $scope.wallet.tokenObjs[$scope.tokenTx.id].balance)) {
                $scope.notifier.danger(globalFuncs.errorMsgs[0]);
                return;
            }
            txData.to = $scope.wallet.tokenObjs[$scope.tokenTx.id].getContractAddress();
            txData.data = $scope.wallet.tokenObjs[$scope.tokenTx.id].getData($scope.tokenTx.to, $scope.tokenTx.value).data;
            txData.value = '0x00';
        }
        uiFuncs.generateTx(txData, function(rawTx) {
            if (!rawTx.isError) {
                $scope.rawTx = rawTx.rawTx;
                $scope.signedTx = rawTx.signedTx;
                $scope.showRaw = true;
            } else {
                $scope.showRaw = false;
                $scope.notifier.danger(rawTx.error);
            }
            if (!$scope.$$phase) $scope.$apply();
        });
    }
    $scope.sendTx = function() {
        $scope.sendTxModal.close();
        uiFuncs.sendTx($scope.signedTx, function(resp) {
            if (!resp.isError) {
                var checkTxLink = "https://www.myetherwallet.com?txHash=" + resp.data + "#check-tx-status";
                var txHashLink  = $scope.ajaxReq.blockExplorerTX.replace("[[txHash]]", resp.data);
                var emailBody   = 'I%20was%20trying%20to..............%0A%0A%0A%0ABut%20I%27m%20confused%20because...............%0A%0A%0A%0A%0A%0ATo%20Address%3A%20https%3A%2F%2Fetherscan.io%2Faddress%2F' + $scope.tx.to + '%0AFrom%20Address%3A%20https%3A%2F%2Fetherscan.io%2Faddress%2F' + $scope.wallet.getAddressString() + '%0ATX%20Hash%3A%20https%3A%2F%2Fetherscan.io%2Ftx%2F' + resp.data + '%0AAmount%3A%20' + $scope.tx.value + '%20' + $scope.unitReadable + '%0ANode%3A%20' + $scope.ajaxReq.type + '%0AToken%20To%20Addr%3A%20' + $scope.tokenTx.to + '%0AToken%20Amount%3A%20' + $scope.tokenTx.value + '%20' + $scope.unitReadable + '%0AData%3A%20' + $scope.tx.data + '%0AGas%20Limit%3A%20' + $scope.tx.gasLimit + '%0AGas%20Price%3A%20' + $scope.tx.gasPrice;
                var verifyTxBtn = $scope.ajaxReq.type != nodes.nodeTypes.Custom ? 'Verify Transaction' : '';
                var checkTxBtn  = ' Check TX Status ';
                var emailBtn    = 'Confused? Email Us.';
                var completeMsg = '
' + globalFuncs.successMsgs[2] + '' + resp.data + '

' + verifyTxBtn + ' ' + checkTxBtn + '
';
                $scope.notifier.success( completeMsg, 0 );
                $scope.wallet.setBalance(applyScope);
                if ($scope.tx.sendMode == 'token') $scope.wallet.tokenObjs[$scope.tokenTx.id].setBalance();
            } else {
                $scope.notifier.danger(resp.error);
            }
        });
    }
    $scope.transferAllBalance = function() {
        if ($scope.tx.sendMode != 'token') {
            uiFuncs.transferAllBalance($scope.wallet.getAddressString(), $scope.tx.gasLimit, function(resp) {
                if (!resp.isError) {
                    $scope.tx.unit = resp.unit;
                    $scope.tx.value = resp.value;
                } else {
                    $scope.showRaw = false;
                    $scope.notifier.danger(resp.error);
                }
            });
        } else {
            $scope.tx.value = $scope.wallet.tokenObjs[$scope.tokenTx.id].getBalance();
        }
    }
};
module.exports = sendTxCtrl;
<|endoftext|>


<commit_before>
const express = require("express")
const morgan = require("morgan")
const cors = require("cors")
const compression = require("compression")
const helmet = require("helmet")
const config = require("../config/config.json")
const MongoClient = require("mongodb")
const app = express()

const v2_home  = require("./v2-routes/v2-home")
const v2_info  = require("./v2-routes/v2-info")
const v2_rockets  = require("./v2-routes/v2-rockets")
const v2_capsules  = require("./v2-routes/v2-capsules")
const v2_launchpad  = require("./v2-routes/v2-launchpad")
const v2_launches  = require("./v2-routes/v2-launches")
const v2_upcoming  = require("./v2-routes/v2-upcoming")
const v2_parts  = require("./v2-routes/v2-parts")

app.use(compression())
app.use(helmet())
app.use(cors())
app.use(morgan("common"))

// Global HTTP headers
app.use((req, res, next) => {
  res.header("Content-Type","application/json")
  res.header("Last-Modified", new Date().toUTCString())
  next()
})

app.use("/v2", v2_home)
app.use("/v2/info", v2_info)
app.use("/v2/rockets", v2_rockets)
app.use("/v2/capsules", v2_capsules)
app.use("/v2/launchpads", v2_launchpad)
app.use("/v2/launches", v2_launches)
app.use("/v2/launches/upcoming", v2_upcoming)
app.use("/v2/parts", v2_parts)

// 404 Error Handler
app.use((req, res) => {
  res.status(404)
  res.json({
    error: "No results found"
  })
})

// generic error handler - must have 4 parameters
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
  res.status(500)
  res.json({
    error: "Internal Server Error"
  })
})

// Mongo Connection + Server Start
MongoClient.connect(config.url, (err, database) => {
  if (err) {
    console.log(err)
    process.exit(1)
  }
  global.db = database

  app.set("port", (process.env.PORT || 5000))
  app.listen(app.get("port"), "0.0.0.0", () => {
    console.log("SpaceX API listening on port: " + app.get("port"))
    app.emit("ready")
  })
})

module.exports = app
<commit_msg>format app.js with airbnb style<commit_after>
const express = require('express');
const morgan = require('morgan');
const cors = require('cors');
const compression = require('compression');
const helmet = require('helmet');
const config = require('../config/config.json');
const MongoClient = require('mongodb');

const app = express();

const home = require('./v2-routes/v2-home');
const info = require('./v2-routes/v2-info');
const rockets = require('./v2-routes/v2-rockets');
const capsules = require('./v2-routes/v2-capsules');
const launchpad = require('./v2-routes/v2-launchpad');
const launches = require('./v2-routes/v2-launches');
const upcoming = require('./v2-routes/v2-upcoming');
const parts = require('./v2-routes/v2-parts');

app.use(compression());
app.use(helmet());
app.use(cors());
app.use(morgan('common'));

// Global HTTP headers
app.use((req, res, next) => {
  res.header('Content-Type', 'application/json');
  res.header('Last-Modified', new Date().toUTCString());
  next();
});

app.use('/v2', home);
app.use('/v2/info', info);
app.use('/v2/rockets', rockets);
app.use('/v2/capsules', capsules);
app.use('/v2/launchpads', launchpad);
app.use('/v2/launches', launches);
app.use('/v2/launches/upcoming', upcoming);
app.use('/v2/parts', parts);

// 404 Error Handler
app.use((req, res) => {
  res.status(404);
  res.json({
    error: 'No results found',
  });
});

// generic error handler - must have 4 parameters
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
  res.status(500);
  res.json({
    error: 'Internal Server Error',
  });
});

// Mongo Connection + Server Start
MongoClient.connect(config.url, (err, database) => {
  if (err) {
    console.log(err);
    process.exit(1);
  }
  global.db = database;

  const port = process.env.PORT || 5000;
  app.listen(port, '0.0.0.0', () => {
    console.log(`SpaceX API running on port: ${port}`);
    app.emit('ready');
  });
});

module.exports = app;
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import deepEqual from 'deep-equal'

import { isBrowser } from '../util'
import { colours } from 'style'

// conditionally import Leaflet + plugins -> requires `window`
let L
if (isBrowser) {

  L = require('leaflet')
  require('leaflet.markercluster')

}

export default class Map extends Component {

  constructor() {

    super()

    this.onMapDragEnd = this.onMapDragEnd.bind(this)
    this.onMarkerClick = this.onMarkerClick.bind(this)

    // init marker layer cache
    this.markerLayerCache = []

  }

  componentDidMount() {

    this.initMap()

  }

  componentDidUpdate(prevProps) {

    const { fitToBounds, markers, selectedResultIndex } = this.props
    const { markers: prevMarkers, selectedResultIndex: prevSelectedResultIndex } = prevProps

    // check if `selectedResultIndex` has changed
    if ( selectedResultIndex && selectedResultIndex !== prevSelectedResultIndex ) {

      // center map to selected result
      this.setMapCenter(markers[selectedResultIndex].coordinates, { animate: true })

      // close marker tooltips
      this.markerLayer.eachLayer( l => l.isTooltipOpen() && l.closeTooltip() )

      // open marker's tooltip
      this.markerLayerCache[selectedResultIndex].openTooltip()

    }

    // check if `markers` has changed
    if ( !deepEqual(markers, prevMarkers) ) {

      // clear pubs
      this.clearMarkers()

      // plot pubs
      this.plotMarkers(markers, this.generateMarkerIcon(), fitToBounds)

    }

  }

  initMap() {

    const { center: [ lng, lat ], fitToBounds, geolocation, markers, mapOptions, tileOptions, tileURL, zoomControlOptions } = this.props

    // override default center if available
    if (lat && lng) mapOptions.center = { lat, lng }

    // init Leaflet map
    this.map = L.map('map', mapOptions )

    // add map events
    this.map.on('dragend', this.onMapDragEnd)

    // configure Leaflet
    L.tileLayer(tileURL, tileOptions).addTo(this.map)

    // add zoom control
    L.control.zoom(zoomControlOptions).addTo(this.map)

    // clear pubs
    this.clearMarkers()

    // plot geolocation
    this.plotGeolocation(geolocation, this.generateGeolocationIcon())

    // plot pubs
    this.plotMarkers(markers, this.generateMarkerIcon(), fitToBounds)

  }

  fitMapToBounds(bounds) {

    const { map } = this

    map.fitBounds(bounds)

  }

  setMapCenter([ lng, lat ], options={}) {

    const { map } = this

    map.panTo({ lat, lng }, options)

  }

  generateClusterIcon(cluster) {

    return L.divIcon({ html: `<span>${cluster.getChildCount()}</span>`, className: 'marker-cluster', iconSize: [ 30, 30 ] })

  }

  generateGeolocationIcon() {

    return L.divIcon({ className: 'leaflet-geolocation-icon', iconSize: [ 20, 20 ] })

  }

  generateMarkerIcon() {

    return L.divIcon({ className: 'leaflet-pub-icon', iconSize: [ 20, 20 ] })

  }

  plotGeolocation(geolocation, icon) {

    // no geolocation? abort!
    if (!geolocation.length) return

    return L.marker(geolocation, { icon }).addTo(this.map)

  }

  plotMarkers(markers, icon, fitToBounds) {

    // no markers? abort!
    if (!markers.length) return

    // reset marker layers cache
    this.markerLayerCache.length = 0

    // init layers
    this.markerLayer = L.markerClusterGroup({ iconCreateFunction: this.generateClusterIcon, polygonOptions: { color: colours.dark } })

    markers.map( ({ coordinates: [ lng, lat ], name }, index) => {

      // init tooltip
      let tooltip = new L.tooltip({ direction: 'bottom', offset: [ 0, 10 ] })
        .setLatLng([ lat, lng ])
        .setContent(name)

      // init marker
      let marker = new L.marker([ lat, lng ], { icon })
        .bindTooltip(tooltip)

      // marker events
      marker.on('click', () => this.onMarkerClick(index))

      // add marker to layer cache
      this.markerLayerCache.push(marker)

      // add marker to layer
      return this.markerLayer.addLayer(marker)

    } )

    // add marker layer to map
    this.markerLayer.addTo(this.map)

    // should map be fitted to bounds?
    if (fitToBounds) {

      // get layer bounds
      const layerBounds = this.markerLayer.getBounds()

      // center/zoom map to markerLayer bounds if required
      this.fitMapToBounds(layerBounds)

    }

  }

  clearMarkers() {

    this.markerLayer && this.markerLayer.clearLayers()

  }

  onMapDragEnd() {

    const { setPoint } = this.props
    const { lat, lng } = this.map.getCenter()

    setPoint([ lng, lat ])

  }

  onMarkerClick(index) {

    const { setSelectedResult } = this.props

    setSelectedResult(index)

  }

  render() {

    return (

    )

  }

}
<commit_msg>close pub panel on map drag<commit_after>import React, { Component } from 'react'
import deepEqual from 'deep-equal'

import { isBrowser } from '../util'
import { colours } from 'style'

// conditionally import Leaflet + plugins -> requires `window`
let L
if (isBrowser) {

  L = require('leaflet')
  require('leaflet.markercluster')

}

export default class Map extends Component {

  constructor() {

    super()

    this.onMapDragStart = this.onMapDragStart.bind(this)
    this.onMapDragEnd = this.onMapDragEnd.bind(this)
    this.onMarkerClick = this.onMarkerClick.bind(this)

    // init marker layer cache
    this.markerLayerCache = []

  }

  componentDidMount() {

    this.initMap()

  }

  componentDidUpdate(prevProps) {

    const { fitToBounds, markers, selectedResultIndex } = this.props
    const { markers: prevMarkers, selectedResultIndex: prevSelectedResultIndex } = prevProps

    // check if `selectedResultIndex` has changed
    if ( selectedResultIndex && selectedResultIndex !== prevSelectedResultIndex ) {

      // center map to selected result
      this.setMapCenter(markers[selectedResultIndex].coordinates, { animate: true })

      // close marker tooltips
      this.markerLayer.eachLayer( l => l.isTooltipOpen() && l.closeTooltip() )

      // open marker's tooltip
      this.markerLayerCache[selectedResultIndex].openTooltip()

    }

    // check if `markers` has changed
    if ( !deepEqual(markers, prevMarkers) ) {

      // clear pubs
      this.clearMarkers()

      // plot pubs
      this.plotMarkers(markers, this.generateMarkerIcon(), fitToBounds)

    }

  }

  initMap() {

    const { center: [ lng, lat ], fitToBounds, geolocation, markers, mapOptions, tileOptions, tileURL, zoomControlOptions } = this.props

    // override default center if available
    if (lat && lng) mapOptions.center = { lat, lng }

    // init Leaflet map
    this.map = L.map('map', mapOptions )

    // add map events
    this.map.on('dragstart', this.onMapDragStart)
    this.map.on('dragend', this.onMapDragEnd)

    // configure Leaflet
    L.tileLayer(tileURL, tileOptions).addTo(this.map)

    // add zoom control
    L.control.zoom(zoomControlOptions).addTo(this.map)

    // clear pubs
    this.clearMarkers()

    // plot geolocation
    this.plotGeolocation(geolocation, this.generateGeolocationIcon())

    // plot pubs
    this.plotMarkers(markers, this.generateMarkerIcon(), fitToBounds)

  }

  fitMapToBounds(bounds) {

    const { map } = this

    map.fitBounds(bounds)

  }

  setMapCenter([ lng, lat ], options={}) {

    const { map } = this

    map.panTo({ lat, lng }, options)

  }

  generateClusterIcon(cluster) {

    return L.divIcon({ html: `<span>${cluster.getChildCount()}</span>`, className: 'marker-cluster', iconSize: [ 30, 30 ] })

  }

  generateGeolocationIcon() {

    return L.divIcon({ className: 'leaflet-geolocation-icon', iconSize: [ 20, 20 ] })

  }

  generateMarkerIcon() {

    return L.divIcon({ className: 'leaflet-pub-icon', iconSize: [ 20, 20 ] })

  }

  plotGeolocation(geolocation, icon) {

    // no geolocation? abort!
    if (!geolocation.length) return

    return L.marker(geolocation, { icon }).addTo(this.map)

  }

  plotMarkers(markers, icon, fitToBounds) {

    // no markers? abort!
    if (!markers.length) return

    // reset marker layers cache
    this.markerLayerCache.length = 0

    // init layers
    this.markerLayer = L.markerClusterGroup({ iconCreateFunction: this.generateClusterIcon, polygonOptions: { color: colours.dark } })

    markers.map( ({ coordinates: [ lng, lat ], name }, index) => {

      // init tooltip
      let tooltip = new L.tooltip({ direction: 'bottom', offset: [ 0, 10 ] })
        .setLatLng([ lat, lng ])
        .setContent(name)

      // init marker
      let marker = new L.marker([ lat, lng ], { icon })
        .bindTooltip(tooltip)

      // marker events
      marker.on('click', () => this.onMarkerClick(index))

      // add marker to layer cache
      this.markerLayerCache.push(marker)

      // add marker to layer
      return this.markerLayer.addLayer(marker)

    } )

    // add marker layer to map
    this.markerLayer.addTo(this.map)

    // should map be fitted to bounds?
    if (fitToBounds) {

      // get layer bounds
      const layerBounds = this.markerLayer.getBounds()

      // center/zoom map to markerLayer bounds if required
      this.fitMapToBounds(layerBounds)

    }

  }

  clearMarkers() {

    this.markerLayer && this.markerLayer.clearLayers()

  }

  onMapDragStart() {

    const { setSelectedResult } = this.props

    // reset selectedResult to default
    setSelectedResult()

  }

  onMapDragEnd() {

    const { setPoint } = this.props
    const { lat, lng } = this.map.getCenter()

    setPoint([ lng, lat ])

  }

  onMarkerClick(index) {

    const { setSelectedResult } = this.props

    setSelectedResult(index)

  }

  render() {

    return (

    )

  }

}
<|endoftext|>