<commit_before>'use strict';

module.exports = {
    template: require('./VideosList.template.html'),

    props: [
        'filter_apis',
        'content',
        'query',
        'videos',

        ////////////////
        // Video page //
        ////////////////
        'api',
        'original_id',
    ],

    // data: function() {
    //     return {
    //         videos: {}
    //     };
    // },

    components: {
        'video-card': require('./VideoCard')
    },

    beforeCompile: function(e) {
        switch (this.content) {
            ////////////
            // Videos //
            ////////////
            case 'homeVideos':
                this.$http.get('/api/videos/home', function(videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            case 'favorites':
                this.$http.get('/api/videos/favorites', function(videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            case 'watchLater':
                this.$http.get('/api/videos/watch-later', function(videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            /////////////
            // History //
            /////////////
            case 'videosWatched':
                this.$http.get('/api/history/videos', function(videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            ////////////
            // Search //
            ////////////
            case 'search':
                var parameters = {
                    'query': this.query
                };

                this.$http.get('/api/videos/search', parameters, function(searchResults) {
                    this.$set('videos', searchResults.data);
                    this.initIsotope();
                });
                break;

            ////////////////
            // Video page //
            ////////////////
            case 'recommended':
                var parameters = {
                    'api': this.api,
                    'original_id': this.original_id
                };

                this.$http.get('/api/videos/recommended', parameters, function(results) {
                    this.$set('videos', results);
                    this.initIsotope();
                });
                break;
        }
    },

    watch: {
        "videos": function(oldVal, newVal) {
            jQuery('#preloader').fadeOut();
            jQuery('#filter-apis').removeClass('hide');
        }
    },

    methods: {
        initIsotope: function() {
            this.$nextTick(function () {
                var $grid = jQuery('#videos').isotope({
                    // columnWidth: '.video',
                    itemSelector: '.video',
                    layoutMode: 'masonry',
                    // isInitLayout: true,
                    // gutter: 200
                });

                $grid.imagesLoaded().progress( function() {
                    $grid.isotope('layout');
                });

                if (this.filter_apis == 'enabled') {
                    $('.video-source').on('click', function() {
                        var filterValue = $(this).data('filter');
                        $('.choosen-source').html('Source: '  + $(this).text());

                        $grid.isotope({
                            filter: filterValue
                        });
                    });
                }

                // // bind event
                // $grid.isotope( 'on', 'arrangeComplete', function(ev, ve) {
                //     console.log(ev);
                //     console.log(ve);
                //     console.log('arrange is complete');
                // });

                // $grid.isotope();

                // $grid.on('layoutComplete', function(event, laidOutItems) {
                //     console.log(laidOutItems);
                //     console.log( 'Isotope layout completed on ' +
                //                 laidOutItems.length + ' items' );
                // });
            });
        }
    }
};
<commit_msg>Cleanup commented code and adjust to work with new vue.resource api<commit_after>'use strict';

module.exports = {
    template: require('./VideosList.template.html'),

    props: [
        'filter_apis',
        'content',
        'query',
        'videos',

        ////////////////
        // Video page //
        ////////////////
        'custom_id'
    ],

    components: {
        'video-card': require('./VideoCard')
    },

    beforeCompile: function () {
        var baseUri = '/api';
        var uri = {
            recommendations: {
                video: baseUri + '/recommendations/video'
            },
            content: {
                home:  baseUri +'/content/related'
            },
            user: {
                favorites: baseUri + '/user/favorites',
                watchLater: baseUri + '/user/watch-later',
                history: {
                    videos: baseUri + '/user/history/videos',
                    searches: baseUri + '/user/history/searches'
                }
            },
            search: baseUri + '/search'
        };

        switch (this.content) {
            /////////////
            // Content //
            /////////////
            case 'homeVideos':
                this.$http.get(uri.content.home, function (videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            ////////////
            //  User  //
            ////////////

            case 'favorites':
                this.$http.get(uri.user.favorites, function (videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            case 'watchLater':
                this.$http.get(uri.user.watchLater, function (videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            case 'videosWatched':
                this.$http.get(uri.user.history.videos, function (videos) {
                    this.$set('videos', videos.data);
                    this.initIsotope();
                });
                break;

            ////////////
            // Search //
            ////////////
            case 'search':
                this.$http.get(uri.search, {
                    params: {
                        query: this.query
                    }
                }).then(function (searchResults) {
                    this.$set('videos', searchResults.data);
                    this.initIsotope();
                });
                break;

            ////////////////
            // Video page //
            ////////////////
            case 'recommended':
                this.$http.get(uri.recommendations.video, {
                    params: {
                        'custom_id': this.custom_id
                    }
                }).then(function (results) {
                    this.$set('videos', results);
                    this.initIsotope();
                });
                break;
        }
    },

    watch: {
        "videos": function () {
            jQuery('#preloader').fadeOut();
            jQuery('#filter-apis').removeClass('hide');
        }
    },

    methods: {
        initIsotope: function () {
            this.$nextTick(function () {
                var $grid = $('#videos').isotope({
                    itemSelector: '.video',
                    layoutMode: 'masonry'
                });

                $grid.imagesLoaded().progress(function () {
                    $grid.isotope('layout');
                });

                if (this.filter_apis == 'enabled') {
                    $('.video-source').on('click', function () {
                        var filterValue = $(this).data('filter');
                        $('.choosen-source').html('Source: ' + $(this).text());

                        $grid.isotope({
                            filter: filterValue
                        });
                    });
                };
            });
        }
    }
};
<|endoftext|>


<commit_before>function calculateFee(n, tx) {
    var estimatedGas = 21000;
    if (tx !== null) {
        estimatedGas = web3.eth.estimateGas(tx);
    }

    var gasMultiplicator = Math.pow(1.4, n).toFixed(3);
    var weiFee = web3.eth.gasPrice * gasMultiplicator * estimatedGas;
    // force fee in eth to be of BigNumber type
    var ethFee = web3.toBigNumber(web3.fromWei(weiFee, "ether"));
    // always display 7 decimal places
    return ethFee.toFixed(7);
}

function calculateGasPrice(n) {
    var gasMultiplicator = Math.pow(1.4, n).toFixed(3);
    return web3.eth.gasPrice * gasMultiplicator;
}

status.defineSubscription(
    "calculatedFee",
    {value: ["sliderValue"], tx: ["transaction"]},
    function (params) {
        return calculateFee(params.value, params.tx);
    }
);

function getFeeExplanation(n) {
    return I18n.t('send_explanation') + I18n.t('send_explanation_' + (n + 2));
}

status.defineSubscription(
    "feeExplanation",
    {value: ["sliderValue"]},
    function(params) {
        return getFeeExplanation(params.value);
    }
)

function amountParameterBox(params, context) {
    if (!params["bot-db"]) {
        params["bot-db"] = {};
    }

    var contactAddress = context.to;

    var txData;
    var amount;
    try {
        amount = params.args[0];
        txData = {
            to: contactAddress,
            value: web3.toWei(amount) || 0
        };
    } catch (err) {
        amount = null;
        txData = {
            to: contactAddress,
            value: 0
        };
    }

    var sliderValue = params["bot-db"]["sliderValue"] || 0;

    status.setDefaultDb({
        transaction: txData,
        calculatedFee: calculateFee(sliderValue, txData),
        feeExplanation: getFeeExplanation(sliderValue),
        sliderValue: sliderValue
    });

    return {
        title: I18n.t('send_title'),
        showBack: true,
        markup: status.components.scrollView(
            {
                keyboardShouldPersistTaps: "always"
            },
            [status.components.view(
                {
                    flex: 1
                },
                [
                    status.components.text(
                        {
                            style: {
                                fontSize: 14,
                                color: "rgb(147, 155, 161)",
                                paddingTop: 12,
                                paddingLeft: 16,
                                paddingRight: 16,
                                paddingBottom: 20
                            }
                        },
                        I18n.t('send_specify_amount')
                    ),
                    status.components.touchable(
                        {
                            onPress: status.components.dispatch([status.events.FOCUS_INPUT, []])
                        },
                        status.components.view(
                            {
                                flexDirection: "row",
                                alignItems: "center",
                                textAlign: "center",
                                justifyContent: "center"
                            },
                            [
                                status.components.text(
                                    {
                                        font: "light",
                                        numberOfLines: 1,
                                        ellipsizeMode: "tail",
                                        style: {
                                            maxWidth: 250,
                                            fontSize: 38,
                                            marginLeft: 8,
                                            color: "black"
                                        }
                                    },
                                    amount || "0.00"
                                ),
                                status.components.text(
                                    {
                                        font: "light",
                                        style: {
                                            fontSize: 38,
                                            marginLeft: 8,
                                            color: "rgb(147, 155, 161)"
                                        }
                                    },
                                    I18n.t('eth')
                                ),
                            ]
                        )
                    ),
                    status.components.text(
                        {
                            style: {
                                fontSize: 14,
                                color: "rgb(147, 155, 161)",
                                paddingTop: 14,
                                paddingLeft: 16,
                                paddingRight: 16,
                                paddingBottom: 5
                            }
                        },
                        I18n.t('send_fee')
                    ),
                    status.components.view(
                        {
                            flexDirection: "row"
                        },
                        [
                            status.components.text(
                                {
                                    style: {
                                        fontSize: 17,
                                        color: "black",
                                        paddingLeft: 16
                                    }
                                },
                                [status.components.subscribe(["calculatedFee"])]
                            ),
                            status.components.text(
                                {
                                    style: {
                                        fontSize: 17,
                                        color: "rgb(147, 155, 161)",
                                        paddingLeft: 4,
                                        paddingRight: 4
                                    }
                                },
                                I18n.t('eth')
                            )
                        ]
                    ),
                    status.components.slider(
                        {
                            maximumValue: 2,
                            minimumValue: -2,
                            onSlidingComplete: status.components.dispatch(
                                [status.events.UPDATE_DB, "sliderValue"]
                            ),
                            step: 1,
                            style: {
                                marginLeft: 16,
                                marginRight: 16
                            }
                        }
                    ),
                    status.components.view(
                        {
                            flexDirection: "row"
                        },
                        [
                            status.components.text(
                                {
                                    style: {
                                        flex: 1,
                                        fontSize: 14,
                                        color: "rgb(147, 155, 161)",
                                        paddingLeft: 16,
                                        alignSelf: "flex-start"
                                    }
                                },
                                I18n.t('send_cheaper')
                            ),
                            status.components.text(
                                {
                                    style: {
                                        flex: 1,
                                        fontSize: 14,
                                        color: "rgb(147, 155, 161)",
                                        paddingRight: 16,
                                        alignSelf: "flex-end",
                                        textAlign: "right"
                                    }
                                },
                                I18n.t('send_faster')
                            )
                        ]
                    ),
                    status.components.text(
                        {
                            style: {
                                fontSize: 14,
                                color: "black",
                                paddingTop: 16,
                                paddingLeft: 16,
                                paddingRight: 16,
                                paddingBottom: 16,
                                lineHeight: 24
                            }
                        },
                        [status.components.subscribe(["feeExplanation"])]
                    )
                ]
            )]
        )
    };
}

var paramsSend = [
    {
        name: "amount",
        type: status.types.NUMBER,
        suggestions: amountParameterBox
    }
];

function validateSend(params, context) {
    if (!params["bot-db"]) {
        params["bot-db"] = {};
    }

    if (!params["amount"]) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_amount_specified')
            )
        };
    }

    var amount = params["amount"].replace(",", ".");
    var amountSplitted = amount.split(".");
    if (amountSplitted.length === 2 && amountSplitted[1].length > 18) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_amount_is_too_small')
            )
        };
    }

    if (isNaN(parseFloat(params.amount.replace(",", ".")))) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_invalid_number')
            )
        };
    }

    try {
        var val = web3.toWei(amount, "ether");
        if (val < 0) {
            throw new Error();
        }
    } catch (err) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_invalid_number')
            )
        };
    }

    var balance = web3.eth.getBalance(context.from);
    var fee = calculateFee(
        params["bot-db"]["sliderValue"],
        {
            to: context.to,
            value: val
        }
    );

    if (bn(val).plus(bn(web3.toWei(fee, "ether"))).greaterThan(bn(balance))) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_insufficient_amount')
                + web3.fromWei(balance, "ether")
                + " ETH)"
            )
        };
    }
}

function handleSend(params, context) {
    var val = web3.toWei(params["amount"].replace(",", "."), "ether");

    var data = {
        from: context.from,
        to: context.to,
        value: val,
        gasPrice: calculateGasPrice(params["bot-db"]["sliderValue"])
    };

    try {
        return web3.eth.sendTransaction(data);
    } catch (err) {
        return {error: err.message};
    }
}

function previewSend(params, context) {
    var amountStyle = {
        fontSize: 36,
        color: "#000000",
        height: 40
    };

    var amount = status.components.view(
        {
            flexDirection: "column",
            alignItems: "flex-end",
            maxWidth: 250
        },
        [status.components.text(
            {
                style: amountStyle,
                numberOfLines: 1,
                ellipsizeMode: "tail",
                font: "light"
            },
            status.localizeNumber(params.amount, context.delimiter, context.separator)
        )]);

    var currency = status.components.view(
        {
            style: {
                flexDirection: "column",
                justifyContent: "flex-end",
                paddingBottom: 0
            }
        },
        [status.components.text(
            {
                style: {
                    color: "#9199a0",
                    fontSize: 16,
                    lineHeight: 18,
                    marginLeft: 7.5
                }
            },
            I18n.t('eth')
        )]
    );

    var row = status.components.view(
        {
            style: {
                flexDirection: "row",
                justifyContent: "space-between",
                marginTop: 8,
                marginBottom: 8
            }
        },
        [amount, currency]
    );

    return {
        markup: status.components.view(
            {
                style: {
                    flexDirection: "column"
                }
            },
            [row]
        )
    };
}

function shortPreviewSend(params, context) {
    return {
        markup: status.components.text(
            {},
            I18n.t('send_title') + ": "
            + status.localizeNumber(params.amount, context.delimiter, context.separator)
            + " ETH"
        )
    };
}

var send = {
    name: "send",
    scope: ["personal-chats"],
    icon: "money_white",
    color: "#5fc48d",
    title: I18n.t('send_title'),
    description: I18n.t('send_description'),
    params: paramsSend,
    validator: validateSend,
    handler: handleSend,
    preview: previewSend,
    shortPreview: shortPreviewSend
};

status.command(send);
status.response(send);

var paramsRequest = [
    {
        name: "amount",
        type: status.types.NUMBER
    }
];

status.command({
    name: "request",
    scope: ["personal-chats"],
    color: "#5fc48d",
    title: I18n.t('request_title'),
    description: I18n.t('request_description'),
    params: paramsRequest,
    handler: function (params, context) {
        var val = params["amount"].replace(",", ".");

        return {
            event: "request",
            request: {
                command: "send",
                params: {
                    amount: val
                },
                prefill: [val]
            }
        };
    },
    preview: function (params, context) {
        var row = status.components.text(
            {},
            I18n.t('request_requesting') + " "
            + status.localizeNumber(params.amount, context.delimiter, context.separator)
            + " ETH"
        );
        return {
            markup: status.components.view(
                {
                    style: {
                        flexDirection: "column"
                    }
                },
                [row]
            )
        };
    },
    shortPreview: function (params, context) {
        return {
            markup: status.components.text(
                {},
                I18n.t('request_requesting') + " "
                + status.localizeNumber(params.amount, context.delimiter, context.separator)
                + " ETH"
            )
        };
    },
    validator: function (params) {
        if (!params["bot-db"]) {
            params["bot-db"] = {};
        }

        if (!params["amount"]) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_amount_specified')
                )
            };
        }

        var amount = params.amount.replace(",", ".");
        var amountSplitted = amount.split(".");
        if (amountSplitted.length === 2 && amountSplitted[1].length > 18) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_amount_is_too_small')
                )
            };
        }

        if (isNaN(parseFloat(params.amount.replace(",", ".")))) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_invalid_number')
                )
            };
        }

        try {
            var val = web3.toWei(amount, "ether");
            if (val < 0) {
                throw new Error();
            }
        } catch (err) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_invalid_number')
                )
            };
        }
    }
});
<commit_msg>Fixed nasty regression caused by command-scopes PR<commit_after>function calculateFee(n, tx) {
    var estimatedGas = 21000;
    if (tx !== null) {
        estimatedGas = web3.eth.estimateGas(tx);
    }

    var gasMultiplicator = Math.pow(1.4, n).toFixed(3);
    var weiFee = web3.eth.gasPrice * gasMultiplicator * estimatedGas;
    // force fee in eth to be of BigNumber type
    var ethFee = web3.toBigNumber(web3.fromWei(weiFee, "ether"));
    // always display 7 decimal places
    return ethFee.toFixed(7);
}

function calculateGasPrice(n) {
    var gasMultiplicator = Math.pow(1.4, n).toFixed(3);
    return web3.eth.gasPrice * gasMultiplicator;
}

status.defineSubscription(
    "calculatedFee",
    {value: ["sliderValue"], tx: ["transaction"]},
    function (params) {
        return calculateFee(params.value, params.tx);
    }
);

function getFeeExplanation(n) {
    return I18n.t('send_explanation') + I18n.t('send_explanation_' + (n + 2));
}

status.defineSubscription(
    "feeExplanation",
    {value: ["sliderValue"]},
    function(params) {
        return getFeeExplanation(params.value);
    }
)

function amountParameterBox(params, context) {
    if (!params["bot-db"]) {
        params["bot-db"] = {};
    }

    var contactAddress = context.to;

    var txData;
    var amount;
    try {
        amount = params.args[0];
        txData = {
            to: contactAddress,
            value: web3.toWei(amount) || 0
        };
    } catch (err) {
        amount = null;
        txData = {
            to: contactAddress,
            value: 0
        };
    }

    var sliderValue = params["bot-db"]["sliderValue"] || 0;

    status.setDefaultDb({
        transaction: txData,
        calculatedFee: calculateFee(sliderValue, txData),
        feeExplanation: getFeeExplanation(sliderValue),
        sliderValue: sliderValue
    });

    return {
        title: I18n.t('send_title'),
        showBack: true,
        markup: status.components.scrollView(
            {
                keyboardShouldPersistTaps: "always"
            },
            [status.components.view(
                {
                    flex: 1
                },
                [
                    status.components.text(
                        {
                            style: {
                                fontSize: 14,
                                color: "rgb(147, 155, 161)",
                                paddingTop: 12,
                                paddingLeft: 16,
                                paddingRight: 16,
                                paddingBottom: 20
                            }
                        },
                        I18n.t('send_specify_amount')
                    ),
                    status.components.touchable(
                        {
                            onPress: status.components.dispatch([status.events.FOCUS_INPUT, []])
                        },
                        status.components.view(
                            {
                                flexDirection: "row",
                                alignItems: "center",
                                textAlign: "center",
                                justifyContent: "center"
                            },
                            [
                                status.components.text(
                                    {
                                        font: "light",
                                        numberOfLines: 1,
                                        ellipsizeMode: "tail",
                                        style: {
                                            maxWidth: 250,
                                            fontSize: 38,
                                            marginLeft: 8,
                                            color: "black"
                                        }
                                    },
                                    amount || "0.00"
                                ),
                                status.components.text(
                                    {
                                        font: "light",
                                        style: {
                                            fontSize: 38,
                                            marginLeft: 8,
                                            color: "rgb(147, 155, 161)"
                                        }
                                    },
                                    I18n.t('eth')
                                ),
                            ]
                        )
                    ),
                    status.components.text(
                        {
                            style: {
                                fontSize: 14,
                                color: "rgb(147, 155, 161)",
                                paddingTop: 14,
                                paddingLeft: 16,
                                paddingRight: 16,
                                paddingBottom: 5
                            }
                        },
                        I18n.t('send_fee')
                    ),
                    status.components.view(
                        {
                            flexDirection: "row"
                        },
                        [
                            status.components.text(
                                {
                                    style: {
                                        fontSize: 17,
                                        color: "black",
                                        paddingLeft: 16
                                    }
                                },
                                [status.components.subscribe(["calculatedFee"])]
                            ),
                            status.components.text(
                                {
                                    style: {
                                        fontSize: 17,
                                        color: "rgb(147, 155, 161)",
                                        paddingLeft: 4,
                                        paddingRight: 4
                                    }
                                },
                                I18n.t('eth')
                            )
                        ]
                    ),
                    status.components.slider(
                        {
                            maximumValue: 2,
                            minimumValue: -2,
                            onSlidingComplete: status.components.dispatch(
                                [status.events.UPDATE_DB, "sliderValue"]
                            ),
                            step: 1,
                            style: {
                                marginLeft: 16,
                                marginRight: 16
                            }
                        }
                    ),
                    status.components.view(
                        {
                            flexDirection: "row"
                        },
                        [
                            status.components.text(
                                {
                                    style: {
                                        flex: 1,
                                        fontSize: 14,
                                        color: "rgb(147, 155, 161)",
                                        paddingLeft: 16,
                                        alignSelf: "flex-start"
                                    }
                                },
                                I18n.t('send_cheaper')
                            ),
                            status.components.text(
                                {
                                    style: {
                                        flex: 1,
                                        fontSize: 14,
                                        color: "rgb(147, 155, 161)",
                                        paddingRight: 16,
                                        alignSelf: "flex-end",
                                        textAlign: "right"
                                    }
                                },
                                I18n.t('send_faster')
                            )
                        ]
                    ),
                    status.components.text(
                        {
                            style: {
                                fontSize: 14,
                                color: "black",
                                paddingTop: 16,
                                paddingLeft: 16,
                                paddingRight: 16,
                                paddingBottom: 16,
                                lineHeight: 24
                            }
                        },
                        [status.components.subscribe(["feeExplanation"])]
                    )
                ]
            )]
        )
    };
}

var paramsSend = [
    {
        name: "amount",
        type: status.types.NUMBER,
        suggestions: amountParameterBox
    }
];

function validateSend(params, context) {
    if (!params["bot-db"]) {
        params["bot-db"] = {};
    }

    if (!params["amount"]) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_amount_specified')
            )
        };
    }

    var amount = params["amount"].replace(",", ".");
    var amountSplitted = amount.split(".");
    if (amountSplitted.length === 2 && amountSplitted[1].length > 18) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_amount_is_too_small')
            )
        };
    }

    if (isNaN(parseFloat(params.amount.replace(",", ".")))) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_invalid_number')
            )
        };
    }

    try {
        var val = web3.toWei(amount, "ether");
        if (val < 0) {
            throw new Error();
        }
    } catch (err) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_invalid_number')
            )
        };
    }

    var balance = web3.eth.getBalance(context.from);
    var fee = calculateFee(
        params["bot-db"]["sliderValue"],
        {
            to: context.to,
            value: val
        }
    );

    if (bn(val).plus(bn(web3.toWei(fee, "ether"))).greaterThan(bn(balance))) {
        return {
            markup: status.components.validationMessage(
                I18n.t('validation_title'),
                I18n.t('validation_insufficient_amount')
                + web3.fromWei(balance, "ether")
                + " ETH)"
            )
        };
    }
}

function handleSend(params, context) {
    var val = web3.toWei(params["amount"].replace(",", "."), "ether");

    var gasPrice = calculateGasPrice(params["bot-db"]["sliderValue"]);
    var data = {
        from: context.from,
        to: context.to,
        value: val
    };

    if (gasPrice) {
        data.gasPrice = gasPrice;
    }

    web3.eth.sendTransaction(data, function(error, hash) {
        if (error) {
            // Do nothing, as error handling will be done as response to transaction.failed event from go
        } else {
            status.sendSignal("handler-result", {
                status: "success",
                hash: hash,
                origParams: context["orig-params"]
            });
        }
    });
    // async handler, so we don't return anything immediately
}

function previewSend(params, context) {
    var amountStyle = {
        fontSize: 36,
        color: "#000000",
        height: 40
    };

    var amount = status.components.view(
        {
            flexDirection: "column",
            alignItems: "flex-end",
            maxWidth: 250
        },
        [status.components.text(
            {
                style: amountStyle,
                numberOfLines: 1,
                ellipsizeMode: "tail",
                font: "light"
            },
            status.localizeNumber(params.amount, context.delimiter, context.separator)
        )]);

    var currency = status.components.view(
        {
            style: {
                flexDirection: "column",
                justifyContent: "flex-end",
                paddingBottom: 0
            }
        },
        [status.components.text(
            {
                style: {
                    color: "#9199a0",
                    fontSize: 16,
                    lineHeight: 18,
                    marginLeft: 7.5
                }
            },
            I18n.t('eth')
        )]
    );

    var row = status.components.view(
        {
            style: {
                flexDirection: "row",
                justifyContent: "space-between",
                marginTop: 8,
                marginBottom: 8
            }
        },
        [amount, currency]
    );

    return {
        markup: status.components.view(
            {
                style: {
                    flexDirection: "column"
                }
            },
            [row]
        )
    };
}

function shortPreviewSend(params, context) {
    return {
        markup: status.components.text(
            {},
            I18n.t('send_title') + ": "
            + status.localizeNumber(params.amount, context.delimiter, context.separator)
            + " ETH"
        )
    };
}

var send = {
    name: "send",
    scope: ["personal-chats"],
    icon: "money_white",
    color: "#5fc48d",
    title: I18n.t('send_title'),
    description: I18n.t('send_description'),
    params: paramsSend,
    validator: validateSend,
    handler: handleSend,
    asyncHandler: true,
    preview: previewSend,
    shortPreview: shortPreviewSend
};

status.command(send);
status.response(send);

var paramsRequest = [
    {
        name: "amount",
        type: status.types.NUMBER
    }
];

status.command({
    name: "request",
    scope: ["personal-chats"],
    color: "#5fc48d",
    title: I18n.t('request_title'),
    description: I18n.t('request_description'),
    params: paramsRequest,
    handler: function (params, context) {
        var val = params["amount"].replace(",", ".");

        return {
            event: "request",
            request: {
                command: "send",
                params: {
                    amount: val
                },
                prefill: [val]
            }
        };
    },
    preview: function (params, context) {
        var row = status.components.text(
            {},
            I18n.t('request_requesting') + " "
            + status.localizeNumber(params.amount, context.delimiter, context.separator)
            + " ETH"
        );
        return {
            markup: status.components.view(
                {
                    style: {
                        flexDirection: "column"
                    }
                },
                [row]
            )
        };
    },
    shortPreview: function (params, context) {
        return {
            markup: status.components.text(
                {},
                I18n.t('request_requesting') + " "
                + status.localizeNumber(params.amount, context.delimiter, context.separator)
                + " ETH"
            )
        };
    },
    validator: function (params) {
        if (!params["bot-db"]) {
            params["bot-db"] = {};
        }

        if (!params["amount"]) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_amount_specified')
                )
            };
        }

        var amount = params.amount.replace(",", ".");
        var amountSplitted = amount.split(".");
        if (amountSplitted.length === 2 && amountSplitted[1].length > 18) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_amount_is_too_small')
                )
            };
        }

        if (isNaN(parseFloat(params.amount.replace(",", ".")))) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_invalid_number')
                )
            };
        }

        try {
            var val = web3.toWei(amount, "ether");
            if (val < 0) {
                throw new Error();
            }
        } catch (err) {
            return {
                markup: status.components.validationMessage(
                    I18n.t('validation_title'),
                    I18n.t('validation_invalid_number')
                )
            };
        }
    }
});
<|endoftext|>


<commit_before>/* global $, config, JitsiMeetJS */
import 'jquery';
import { setConfigFromURLParams } from '../../react/features/base/config/functions';
import { parseURLParams } from '../../react/features/base/util/parseURLParams';
import { parseURIString } from '../../react/features/base/util/uri';

setConfigFromURLParams(config, {}, {}, window.location);

const params = parseURLParams(window.location, false, 'hash');
const { isHuman = false } = params;
const {
    localAudio = config.startWithAudioMuted !== true,
    localVideo = config.startWithVideoMuted !== true,
    remoteVideo = isHuman,
    remoteAudio = isHuman,
    autoPlayVideo = config.testing.noAutoPlayVideo !== true
} = params;

const { room: roomName } = parseURIString(window.location.toString());

let connection = null;

let isJoined = false;

let room = null;

let numParticipants = 1;

let localTracks = [];
const remoteTracks = {};

let maxFrameHeight = 0;

window.APP = {
    conference: {
        getStats() {
            return room.connectionQuality.getStats();
        },
        getConnectionState() {
            return room && room.getConnectionState();
        }
    },

    get room() {
        return room;
    },
    get connection() {
        return connection;
    },
    get numParticipants() {
        return numParticipants;
    },
    get localTracks() {
        return localTracks;
    },
    get remoteTracks() {
        return remoteTracks;
    },
    get params() {
        return {
            roomName,
            localAudio,
            localVideo,
            remoteVideo,
            remoteAudio,
            autoPlayVideo
        };
    }
};

/**
 * Simple emulation of jitsi-meet's screen layout behavior
 */
function updateMaxFrameHeight() {
    let newMaxFrameHeight;

    if (numParticipants <= 2) {
        newMaxFrameHeight = 720;
    } else if (numParticipants <= 4) {
        newMaxFrameHeight = 360;
    } else {
        newMaxFrameHeight = 180;
    }

    if (room && maxFrameHeight !== newMaxFrameHeight) {
        maxFrameHeight = newMaxFrameHeight;
        room.setReceiverVideoConstraint(maxFrameHeight);
    }
}

/**
 *
 */
function setNumberOfParticipants() {
    $('#participants').text(numParticipants);
    updateMaxFrameHeight();
}

/**
 * Handles local tracks.
 * @param tracks Array with JitsiTrack objects
 */
function onLocalTracks(tracks = []) {
    localTracks = tracks;
    for (let i = 0; i < localTracks.length; i++) {
        if (localTracks[i].getType() === 'video') {
            $('body').append(`<video ${autoPlayVideo ? 'autoplay="1" ' : ''}id='localVideo${i}' />`);
            localTracks[i].attach($(`#localVideo${i}`)[0]);
        } else {
            $('body').append(
                `<audio autoplay='1' muted='true' id='localAudio${i}' />`);
            localTracks[i].attach($(`#localAudio${i}`)[0]);
        }
        if (isJoined) {
            room.addTrack(localTracks[i]);
        }
    }
}

/**
 * Handles remote tracks
 * @param track JitsiTrack object
 */
function onRemoteTrack(track) {
    if (track.isLocal()
            || (track.getType() === 'video' && !remoteVideo) || (track.getType() === 'audio' && !remoteAudio)) {
        return;
    }
    const participant = track.getParticipantId();

    if (!remoteTracks[participant]) {
        remoteTracks[participant] = [];
    }
    const idx = remoteTracks[participant].push(track);
    const id = participant + track.getType() + idx;

    if (track.getType() === 'video') {
        $('body').append(`<video autoplay='1' id='${id}' />`);
    } else {
        $('body').append(`<audio autoplay='1' id='${id}' />`);
    }
    track.attach($(`#${id}`)[0]);
}

/**
 * That function is executed when the conference is joined
 */
function onConferenceJoined() {
    isJoined = true;
}

/**
 *
 * @param id
 */
function onUserLeft(id) {
    numParticipants--;
    setNumberOfParticipants();
    if (!remoteTracks[id]) {
        return;
    }
    const tracks = remoteTracks[id];

    for (let i = 0; i < tracks.length; i++) {
        const container = $(`#${id}${tracks[i].getType()}${i + 1}`)[0];

        if (container) {
            tracks[i].detach(container);
            container.parentElement.removeChild(container);
        }
    }
}

/**
 * That function is called when connection is established successfully
 */
function onConnectionSuccess() {
    room = connection.initJitsiConference(roomName.toLowerCase(), config);
    room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
    room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
    room.on(JitsiMeetJS.events.conference.USER_JOINED, id => {
        numParticipants++;
        setNumberOfParticipants();
        remoteTracks[id] = [];
    });
    room.on(JitsiMeetJS.events.conference.USER_LEFT, onUserLeft);

    const devices = [];

    if (localVideo) {
        devices.push('video');
    }
    if (localAudio) {
        devices.push('audio');
    }
    if (devices.length > 0) {
        JitsiMeetJS.createLocalTracks({ devices })
            .then(onLocalTracks)
            .then(() => {
                room.join();
            })
            .catch(error => {
                throw error;
            });
    } else {
        room.join();
    }

    updateMaxFrameHeight();
}

/**
 * This function is called when the connection fail.
 */
function onConnectionFailed() {
    console.error('Connection Failed!');
}

/**
 * This function is called when we disconnect.
 */
function disconnect() {
    console.log('disconnect!');
    connection.removeEventListener(
        JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
        onConnectionSuccess);
    connection.removeEventListener(
        JitsiMeetJS.events.connection.CONNECTION_FAILED,
        onConnectionFailed);
    connection.removeEventListener(
        JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
        disconnect);
}

/**
 *
 */
function unload() {
    for (let i = 0; i < localTracks.length; i++) {
        localTracks[i].dispose();
    }
    room.leave();
    connection.disconnect();
}

$(window).bind('beforeunload', unload);
$(window).bind('unload', unload);

JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);

JitsiMeetJS.init(config);

config.serviceUrl = config.bosh = `${config.websocket || config.bosh}?room=${roomName.toLowerCase()}`;

connection = new JitsiMeetJS.JitsiConnection(null, null, config);
connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED, onConnectionSuccess);
connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_FAILED, onConnectionFailed);
connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED, disconnect);
connection.connect();
<commit_msg>fix(load-test): Always create local audio track. (#8612)<commit_after>/* global $, config, JitsiMeetJS */
import 'jquery';
import { setConfigFromURLParams } from '../../react/features/base/config/functions';
import { parseURLParams } from '../../react/features/base/util/parseURLParams';
import { parseURIString } from '../../react/features/base/util/uri';

setConfigFromURLParams(config, {}, {}, window.location);

const params = parseURLParams(window.location, false, 'hash');
const { isHuman = false } = params;
const {
    localAudio = config.startWithAudioMuted !== true,
    localVideo = config.startWithVideoMuted !== true,
    remoteVideo = isHuman,
    remoteAudio = isHuman,
    autoPlayVideo = config.testing.noAutoPlayVideo !== true
} = params;

const { room: roomName } = parseURIString(window.location.toString());

let connection = null;

let room = null;

let numParticipants = 1;

let localTracks = [];
const remoteTracks = {};

let maxFrameHeight = 0;

window.APP = {
    conference: {
        getStats() {
            return room.connectionQuality.getStats();
        },
        getConnectionState() {
            return room && room.getConnectionState();
        }
    },

    get room() {
        return room;
    },
    get connection() {
        return connection;
    },
    get numParticipants() {
        return numParticipants;
    },
    get localTracks() {
        return localTracks;
    },
    get remoteTracks() {
        return remoteTracks;
    },
    get params() {
        return {
            roomName,
            localAudio,
            localVideo,
            remoteVideo,
            remoteAudio,
            autoPlayVideo
        };
    }
};

/**
 * Simple emulation of jitsi-meet's screen layout behavior
 */
function updateMaxFrameHeight() {
    let newMaxFrameHeight;

    if (numParticipants <= 2) {
        newMaxFrameHeight = 720;
    } else if (numParticipants <= 4) {
        newMaxFrameHeight = 360;
    } else {
        newMaxFrameHeight = 180;
    }

    if (room && maxFrameHeight !== newMaxFrameHeight) {
        maxFrameHeight = newMaxFrameHeight;
        room.setReceiverVideoConstraint(maxFrameHeight);
    }
}

/**
 *
 */
function setNumberOfParticipants() {
    $('#participants').text(numParticipants);
    updateMaxFrameHeight();
}

/**
 * Handles local tracks.
 * @param tracks Array with JitsiTrack objects
 */
function onLocalTracks(tracks = []) {
    localTracks = tracks;
    for (let i = 0; i < localTracks.length; i++) {
        if (localTracks[i].getType() === 'video') {
            $('body').append(`<video ${autoPlayVideo ? 'autoplay="1" ' : ''}id='localVideo${i}' />`);
            localTracks[i].attach($(`#localVideo${i}`)[0]);
        } else {
            if (!localAudio) {
                localTracks[i].mute();
            }

            $('body').append(
                `<audio autoplay='1' muted='true' id='localAudio${i}' />`);
            localTracks[i].attach($(`#localAudio${i}`)[0]);
        }
        room.addTrack(localTracks[i]);
    }
}

/**
 * Handles remote tracks
 * @param track JitsiTrack object
 */
function onRemoteTrack(track) {
    if (track.isLocal()
            || (track.getType() === 'video' && !remoteVideo) || (track.getType() === 'audio' && !remoteAudio)) {
        return;
    }
    const participant = track.getParticipantId();

    if (!remoteTracks[participant]) {
        remoteTracks[participant] = [];
    }
    const idx = remoteTracks[participant].push(track);
    const id = participant + track.getType() + idx;

    if (track.getType() === 'video') {
        $('body').append(`<video autoplay='1' id='${id}' />`);
    } else {
        $('body').append(`<audio autoplay='1' id='${id}' />`);
    }
    track.attach($(`#${id}`)[0]);
}

/**
 * That function is executed when the conference is joined
 */
function onConferenceJoined() {
    console.log('Conference joined');
}

/**
 *
 * @param id
 */
function onUserLeft(id) {
    numParticipants--;
    setNumberOfParticipants();
    if (!remoteTracks[id]) {
        return;
    }
    const tracks = remoteTracks[id];

    for (let i = 0; i < tracks.length; i++) {
        const container = $(`#${id}${tracks[i].getType()}${i + 1}`)[0];

        if (container) {
            tracks[i].detach(container);
            container.parentElement.removeChild(container);
        }
    }
}

/**
 * That function is called when connection is established successfully
 */
function onConnectionSuccess() {
    room = connection.initJitsiConference(roomName.toLowerCase(), config);
    room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
    room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
    room.on(JitsiMeetJS.events.conference.USER_JOINED, id => {
        numParticipants++;
        setNumberOfParticipants();
        remoteTracks[id] = [];
    });
    room.on(JitsiMeetJS.events.conference.USER_LEFT, onUserLeft);

    const devices = [];

    if (localVideo) {
        devices.push('video');
    }
    devices.push('audio');

    if (devices.length > 0) {
        JitsiMeetJS.createLocalTracks({ devices })
            .then(onLocalTracks)
            .then(() => {
                room.join();
            })
            .catch(error => {
                throw error;
            });
    } else {
        room.join();
    }

    updateMaxFrameHeight();
}

/**
 * This function is called when the connection fail.
 */
function onConnectionFailed() {
    console.error('Connection Failed!');
}

/**
 * This function is called when we disconnect.
 */
function disconnect() {
    console.log('disconnect!');
    connection.removeEventListener(
        JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
        onConnectionSuccess);
    connection.removeEventListener(
        JitsiMeetJS.events.connection.CONNECTION_FAILED,
        onConnectionFailed);
    connection.removeEventListener(
        JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
        disconnect);
}

/**
 *
 */
function unload() {
    for (let i = 0; i < localTracks.length; i++) {
        localTracks[i].dispose();
    }
    room.leave();
    connection.disconnect();
}

$(window).bind('beforeunload', unload);
$(window).bind('unload', unload);

JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);

JitsiMeetJS.init(config);

config.serviceUrl = config.bosh = `${config.websocket || config.bosh}?room=${roomName.toLowerCase()}`;

connection = new JitsiMeetJS.JitsiConnection(null, null, config);
connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED, onConnectionSuccess);
connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_FAILED, onConnectionFailed);
connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED, disconnect);
connection.connect();
<|endoftext|>


<commit_before>const fs = require("fs");
const check = require("./check");
const express = require('express');
const app = express();
const newCache = require('persistent-cache');
const topCache = newCache({
    name: "top-cache",
    duration: 1000 * 60 * 10, // 10 min
    memory: true,
    persist: true,
});

let log;
try {
    log = JSON.parse(fs.readFileSync("log.json"));
} catch (e) {
    console.log("No log!", e.message);
    log = {};
}

function logPackageCheck(response) {
    console.log(new Date(), JSON.stringify(response));

    const c = log[response.package] || 0;
    log[response.package] = c + 1;
    persist(log, "log.json");
    delete response.package;
}

function persist(obj, file) {
    fs.writeFile(file, JSON.stringify(obj), (err) => {
        if (err){
            console.log("Failed writing file " + file + ", " + JSON.stringify(err));
        }
    });
}

function getTop() {
    let top = topCache.getSync("top");
    if (!top) {
        console.log("Top list cache miss");
        top = doGetTop();
        topCache.put("top", top);
    }
    return top;
}

function doGetTop() {
    return Object.keys(log).sort(function(a, b) {
            return log[b] - log[a];
        })
        .splice(0, 10)
        .reduce((aggr, elem) => {aggr.push(check(elem)); return aggr;}, []);
}

app.get('/check/:packageName', function (req, res) {
    const packageName = req.params.packageName;
    const response = check(packageName, (err, response) => {
        if (err) {
            console.error("Error while responding to /check/" + packageName, err);
            res.send("could not reply to request");
        } else {
            logPackageCheck(response);
            res.send(response);
        }
    });
});

app.get('/top', function (req, res) {
    const top = getTop();
    res.send(top);
});

app.use(express.static('front-end'));

app.listen(3000, function () {
    console.log('App listening on port 3000!')
});
<commit_msg>/top is now also async<commit_after>const fs = require("fs");
const check = require("./check");
const express = require('express');
const app = express();
const newCache = require('persistent-cache');
const topCache = newCache({
    name: "top-cache",
    duration: 1000 * 60 * 10, // 10 min
    memory: true,
    persist: true,
});

let log;
try {
    log = JSON.parse(fs.readFileSync("log.json"));
} catch (e) {
    console.log("No log!", e.message);
    log = {};
}

function logPackageCheck(response) {
    console.log(new Date(), JSON.stringify(response));

    const c = log[response.package] || 0;
    log[response.package] = c + 1;
    persist(log, "log.json");
    delete response.package;
}

function persist(obj, file) {
    fs.writeFile(file, JSON.stringify(obj), (err) => {
        if (err){
            console.log("Failed writing file " + file + ", " + JSON.stringify(err));
        }
    });
}

function getTop(cb) {
    topCache.get("top", (err, top) => {
        if (err) { cb(err, undefined); }

        if (top) {
            cb(undefined, top);
        } else {
            console.log("Top list cache miss");
            doGetTop((top) => {
                topCache.put("top", top);
                cb(undefined, top);
            });
        }
    });
}

function doGetTop(cb) {
    const topPackageNames = Object.keys(log).sort(function(a, b) {
            return log[b] - log[a];
        })
        .splice(0, 10);

    let agg = [];
    const counter = (err, pkg) => {
        if (err) {
            agg.push({});
        } else {
            agg.push(pkg);
        }

        if (agg.length === topPackageNames.length) {
            agg = agg.sort(function(a, b) {
                return log[b] - log[a];
            });
            cb(agg);
        }
    };

    topPackageNames.forEach(pkg => check(pkg, counter));
}

app.get('/check/:packageName', function (req, res) {
    const packageName = req.params.packageName;
    const response = check(packageName, (err, response) => {
        if (err) {
            console.error("Error while responding to /check/" + packageName, err);
            res.send("could not reply to request");
        } else {
            logPackageCheck(response);
            res.send(response);
        }
    });
});

app.get('/top', function (req, res) {
    const top = getTop((err, top) => {
        if (err) {
            console.error("Error while responding to /top", err);
            res.send("could not reply to request");
        } else {
            res.send(top);
        }
    });
});

app.use(express.static('front-end'));

app.listen(3000, function () {
    console.log('App listening on port 3000!')
});
<|endoftext|>


<commit_before>const check = require("./check");
const express = require('express')
const app = express()

function logPackageCheck(response) {
    console.log(new Date(), response);
    delete response.package;
}

app.get('/:packageName', function (req, res) {
    const packageName = req.params.packageName;
    const response = check(packageName);
    logPackageCheck(response);
    res.send(response);
})

app.listen(3000, function () {
    console.log('Example app listening on port 3000!')
})
<commit_msg>UI end-point<commit_after>const check = require("./check");
const express = require('express')
const app = express()

function logPackageCheck(response) {
    console.log(new Date(), response);
    delete response.package;
}

app.get('/check/:packageName', function (req, res) {
    const packageName = req.params.packageName;
    const response = check(packageName);
    logPackageCheck(response);
    res.send(response);
});

app.get('/', function (req, res) {
    res.send("Here be pretty react file. Oh yeah");
});

app.listen(3000, function () {
    console.log('App listening on port 3000!')
});
<|endoftext|>


<commit_before>Navy.Class('Navy.Notify', {
  _count: null,
  _callback: null,

  initialize: function(count, callback) {
    if (arguments.length === 2) {
      this.set(count, callback);
    }
  },

  pass: function(){
    this._count--;

    if (this._count === 0) {
      this._execCallback();
    }
  },

  set: function(count, callback) {
    this._count = count;
    this._callback = callback;

    if (count === 0) {
      this._execCallback();
    }
  },

  _execCallback: function(){
    setTimeout(this._callback, 0);
  }
});
<commit_msg>コメント追記<commit_after>/**
 * @class Navy.Notify
 */
Navy.Class('Navy.Notify', {
  _count: null,
  _callback: null,

  initialize: function(count, callback) {
    if (arguments.length === 2) {
      this.set(count, callback);
    }
  },

  pass: function(){
    this._count--;

    if (this._count === 0) {
      this._execCallback();
    }
  },

  set: function(count, callback) {
    this._count = count;
    this._callback = callback;

    if (count === 0) {
      this._execCallback();
    }
  },

  _execCallback: function(){
    setTimeout(this._callback, 0);
  }
});
<|endoftext|>


<commit_before>/*global define*/
/**
 * To load this extension, add the following to your custom.js:
 *
 * IPython.load_extensions('nbgrader');
 *
**/

define([
    'require',
    'jquery',
    'base/js/namespace',
    'notebook/js/celltoolbar',

], function (require, $, IPython, celltoolbar) {
    "use strict";

    var CellToolbar = celltoolbar.CellToolbar;

    /**
     * Is the cell a solution cell?
     */
    var is_solution = function (cell) {
        if (cell.metadata.nbgrader === undefined) {
            cell.metadata.nbgrader = {};
            return false;
        } else if (cell.metadata.nbgrader.solution === undefined) {
            return false;
        } else {
            return cell.metadata.nbgrader.solution;
        }
    };

    /**
     * Is the cell a grader cell?
     */
    var is_grader = function (cell) {
        if (cell.metadata.nbgrader === undefined) {
            cell.metadata.nbgrader = {};
            return false;
        } else if (cell.metadata.nbgrader.grade === undefined) {
            return false;
        } else {
            return cell.metadata.nbgrader.grade;
        }
    };

    /**
     * Add a display class to the cell element, depending on the
     * nbgrader cell type.
     */
    var display_cell = function (cell) {
        var grader = is_grader(cell),
            grade_cls = "nbgrader-grade-cell",
            elem = cell.element;

        if (!elem) {
            return;
        }

        if (grader && !elem.hasClass(grade_cls)) {
            elem.addClass(grade_cls);
        } else if (!grader && elem.hasClass(grade_cls)) {
            elem.removeClass(grade_cls);
        }
    };

    /**
     * Create a checkbox to mark whether the cell is a grader cell or
     * not.
     */
    var create_grader_checkbox = function (div, cell, celltoolbar) {
        var chkb = $('<input/>').attr('type', 'checkbox');
        var lbl = $('<label/>').append($('<span/>').text("Grade? "));
        lbl.append(chkb);
        chkb.attr("checked", is_grader(cell));
        chkb.click(function () {
            cell.metadata.nbgrader.grade = !is_grader(cell);
            celltoolbar.rebuild();
            display_cell(cell);
        });
        display_cell(cell);
        $(div).append($('<span/>').append(lbl));
    };

    /**
     * Create a checkbox to mark whether the cell is a solution cell
     * or not.
     */
    var create_solution_checkbox = function (div, cell, celltoolbar) {
        var chkb = $('<input/>').attr('type', 'checkbox');
        var lbl = $('<label/>').append($('<span/>').text("Solution? "));
        lbl.append(chkb);
        chkb.attr("checked", is_solution(cell));
        chkb.click(function () {
            var v = !is_solution(cell);
            cell.metadata.nbgrader.solution = v;
            chkb.attr("checked", v);
        });
        $(div).append($('<span/>').append(lbl));
    };

    /**
     * Create the input text box for the problem or test id.
     */
    var create_id_input = function (div, cell, celltoolbar) {
        if (!is_grader(cell)) {
            return;
        }

        var local_div = $('<div/>');
        var text = $('<input/>').attr('type', 'text');
        var lbl = $('<label/>').append($('<span/>').text('ID: '));
        lbl.append(text);

        text.addClass('nbgrader-id-input');
        text.attr("value", cell.metadata.nbgrader.grader_id);
        text.keyup(function () {
            cell.metadata.nbgrader.grader_id = text.val();
        });

        local_div.addClass('nbgrader-id');
        $(div).append(local_div.append($('<span/>').append(lbl)));

        IPython.keyboard_manager.register_events(text);
    };

    /**
     * Create the input text box for the number of points the problem
     * is worth.
     */
    var create_points_input = function (div, cell, celltoolbar) {
        if (!is_grader(cell)) {
            return;
        }

        var local_div = $('<div/>');
        var text = $('<input/>').attr('type', 'number');
        var lbl = $('<label/>').append($('<span/>').text('Points: '));
        lbl.append(text);

        text.addClass('nbgrader-points-input');
        text.attr("value", cell.metadata.nbgrader.points);
        text.keyup(function () {
            cell.metadata.nbgrader.points = text.val();
        });

        local_div.addClass('nbgrader-points');
        $(div).append(local_div.append($('<span/>').append(lbl)));

        IPython.keyboard_manager.register_events(text);
    };

    /**
     * Load custom css for the nbgrader toolbar.
     */
    var load_css = function () {
        var link = document.createElement('link');
        link.type = 'text/css';
        link.rel = 'stylesheet';
        link.href = require.toUrl('./nbgrader.css');
        console.log(link);
        document.getElementsByTagName('head')[0].appendChild(link);
    };

    /**
     * Load the nbgrader toolbar extension.
     */
    var load_ipython_extension = function () {
        load_css();
        CellToolbar.register_callback('create_assignment.solution_checkbox', create_solution_checkbox);
        CellToolbar.register_callback('create_assignment.grader_checkbox', create_grader_checkbox);
        CellToolbar.register_callback('create_assignment.id_input', create_id_input);
        CellToolbar.register_callback('create_assignment.points_input', create_points_input);

        var preset = [
            'create_assignment.solution_checkbox',
            'create_assignment.grader_checkbox',
            'create_assignment.points_input',
            'create_assignment.id_input'
        ];
        CellToolbar.register_preset('Create Assignment', preset, IPython.notebook);
        console.log('nbgrader extension for metadata editing loaded.');
    };

    return {
        'load_ipython_extension': load_ipython_extension
    };
});
<commit_msg>Use checkbox ui generator for solution checkbox<commit_after>/*global define*/
/**
 * To load this extension, add the following to your custom.js:
 *
 * IPython.load_extensions('nbgrader');
 *
**/

define([
    'require',
    'jquery',
    'base/js/namespace',
    'notebook/js/celltoolbar',

], function (require, $, IPython, celltoolbar) {
    "use strict";

    var CellToolbar = celltoolbar.CellToolbar;

    /**
     * Is the cell a solution cell?
     */
    var is_solution = function (cell) {
        if (cell.metadata.nbgrader === undefined) {
            cell.metadata.nbgrader = {};
            return false;
        } else if (cell.metadata.nbgrader.solution === undefined) {
            return false;
        } else {
            return cell.metadata.nbgrader.solution;
        }
    };

    /**
     * Is the cell a grader cell?
     */
    var is_grader = function (cell) {
        if (cell.metadata.nbgrader === undefined) {
            cell.metadata.nbgrader = {};
            return false;
        } else if (cell.metadata.nbgrader.grade === undefined) {
            return false;
        } else {
            return cell.metadata.nbgrader.grade;
        }
    };

    /**
     * Add a display class to the cell element, depending on the
     * nbgrader cell type.
     */
    var display_cell = function (cell) {
        var grader = is_grader(cell),
            grade_cls = "nbgrader-grade-cell",
            elem = cell.element;

        if (!elem) {
            return;
        }

        if (grader && !elem.hasClass(grade_cls)) {
            elem.addClass(grade_cls);
        } else if (!grader && elem.hasClass(grade_cls)) {
            elem.removeClass(grade_cls);
        }
    };

    /**
     * Create a checkbox to mark whether the cell is a grader cell or
     * not.
     */
    var create_grader_checkbox = function (div, cell, celltoolbar) {
        var chkb = $('<input/>').attr('type', 'checkbox');
        var lbl = $('<label/>').append($('<span/>').text("Grade? "));
        lbl.append(chkb);
        chkb.attr("checked", is_grader(cell));
        chkb.click(function () {
            cell.metadata.nbgrader.grade = !is_grader(cell);
            celltoolbar.rebuild();
            display_cell(cell);
        });
        display_cell(cell);
        $(div).append($('<span/>').append(lbl));
    };

    /**
     * Create a checkbox to mark whether the cell is a solution cell
     * or not.
     */
    var create_solution_checkbox = CellToolbar.utils.checkbox_ui_generator(
        "Solution? ",
        function (cell, val) {
            cell.metadata.nbgrader.solution = val;
        },
        is_solution);

    /**
     * Create the input text box for the problem or test id.
     */
    var create_id_input = function (div, cell, celltoolbar) {
        if (!is_grader(cell)) {
            return;
        }

        var local_div = $('<div/>');
        var text = $('<input/>').attr('type', 'text');
        var lbl = $('<label/>').append($('<span/>').text('ID: '));
        lbl.append(text);

        text.addClass('nbgrader-id-input');
        text.attr("value", cell.metadata.nbgrader.grader_id);
        text.keyup(function () {
            cell.metadata.nbgrader.grader_id = text.val();
        });

        local_div.addClass('nbgrader-id');
        $(div).append(local_div.append($('<span/>').append(lbl)));

        IPython.keyboard_manager.register_events(text);
    };

    /**
     * Create the input text box for the number of points the problem
     * is worth.
     */
    var create_points_input = function (div, cell, celltoolbar) {
        if (!is_grader(cell)) {
            return;
        }

        var local_div = $('<div/>');
        var text = $('<input/>').attr('type', 'number');
        var lbl = $('<label/>').append($('<span/>').text('Points: '));
        lbl.append(text);

        text.addClass('nbgrader-points-input');
        text.attr("value", cell.metadata.nbgrader.points);
        text.keyup(function () {
            cell.metadata.nbgrader.points = text.val();
        });

        local_div.addClass('nbgrader-points');
        $(div).append(local_div.append($('<span/>').append(lbl)));

        IPython.keyboard_manager.register_events(text);
    };

    /**
     * Load custom css for the nbgrader toolbar.
     */
    var load_css = function () {
        var link = document.createElement('link');
        link.type = 'text/css';
        link.rel = 'stylesheet';
        link.href = require.toUrl('./nbgrader.css');
        console.log(link);
        document.getElementsByTagName('head')[0].appendChild(link);
    };

    /**
     * Load the nbgrader toolbar extension.
     */
    var load_ipython_extension = function () {
        load_css();
        CellToolbar.register_callback('create_assignment.solution_checkbox', create_solution_checkbox);
        CellToolbar.register_callback('create_assignment.grader_checkbox', create_grader_checkbox);
        CellToolbar.register_callback('create_assignment.id_input', create_id_input);
        CellToolbar.register_callback('create_assignment.points_input', create_points_input);

        var preset = [
            'create_assignment.solution_checkbox',
            'create_assignment.grader_checkbox',
            'create_assignment.points_input',
            'create_assignment.id_input'
        ];
        CellToolbar.register_preset('Create Assignment', preset, IPython.notebook);
        console.log('nbgrader extension for metadata editing loaded.');
    };

    return {
        'load_ipython_extension': load_ipython_extension
    };
});
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'

import Dimensions from 'react-dimensions'
import _ from 'lodash'
import moment from 'moment'
import classnames from 'classnames'

import Dropdown from 'shared/components/Dropdown'
import {fetchTimeSeriesAsync} from 'shared/actions/timeSeries'

import {Table, Column, Cell} from 'fixed-data-table'

const {arrayOf, bool, func, number, oneOfType, shape, string} = PropTypes

const emptySeries = {columns: [], values: []}

const CustomCell = React.createClass({
  propTypes: {
    data: oneOfType([number, string]),
    columnName: string.isRequired,
  },

  render() {
    const {columnName, data} = this.props

    if (columnName === 'time') {
      const date = moment(new Date(data)).format('MM/DD/YY hh:mm:ssA')

      return (

          {date}

      )
    }

    return (

        {data}

    )
  },
})

const ChronoTable = React.createClass({
  propTypes: {
    query: shape({
      host: arrayOf(string.isRequired).isRequired,
      text: string.isRequired,
      id: string.isRequired,
    }).isRequired,
    containerWidth: number.isRequired,
    height: number,
    editQueryStatus: func.isRequired,
  },

  getInitialState() {
    return {
      series: [emptySeries],
      columnWidths: {},
      activeSeriesIndex: 0,
    }
  },

  getDefaultProps() {
    return {
      height: 500,
    }
  },

  componentDidMount() {
    this.fetchCellData(this.props.query)
  },

  componentWillReceiveProps(nextProps) {
    if (this.props.query.text === nextProps.query.text) {
      return
    }

    this.fetchCellData(nextProps.query)
  },

  async fetchCellData(query) {
    if (!query || !query.text) {
      return
    }

    this.setState({isLoading: true})
    // second param is db, we want to leave this blank
    try {
      const {results} = await fetchTimeSeriesAsync({source: query.host, query})
      this.setState({isLoading: false})

      let series = _.get(results, ['0', 'series'], [])

      if (!series.length) {
        return this.setState({series: []})
      }

      series = series.map(s => (s.values ? s : {...s, values: []}))
      this.setState({series})
    } catch (error) {
      this.setState({
        isLoading: false,
        series: [],
      })
      throw error
    }
  },

  handleColumnResize(newColumnWidth, columnKey) {
    const columnWidths = {
      ...this.state.columnWidths,
      [columnKey]: newColumnWidth,
    }

    this.setState({
      columnWidths,
    })
  },

  handleClickTab(activeSeriesIndex) {
    this.setState({activeSeriesIndex})
  },

  handleClickDropdown(item) {
    this.setState({activeSeriesIndex: item.index})
  },

  render() {
    const {containerWidth, height, query} = this.props
    const {series, columnWidths, isLoading, activeSeriesIndex} = this.state
    const {columns, values} = _.get(
      series,
      [`${activeSeriesIndex}`],
      emptySeries
    )

    const maximumTabsCount = 11
    // adjust height to proper value by subtracting the heights of the UI around it
    // tab height, graph-container vertical padding, graph-heading height, multitable-header height
    const minWidth = 70
    const rowHeight = 34
    const headerHeight = 30
    const stylePixelOffset = 130
    const defaultColumnWidth = 200
    const styleAdjustedHeight = height - stylePixelOffset
    const width =
      columns && columns.length > 1 ? defaultColumnWidth : containerWidth

    if (!query) {
      return
Please add a query below

    }

    if (isLoading) {
      return
Loading...

    }

    return (

        {series.length < maximumTabsCount
          ?

              {series.map(({name}, i) =>
                <TabItem
                  isActive={i === activeSeriesIndex}
                  key={i}
                  name={name}
                  index={i}
                  onClickTab={this.handleClickTab}
                />
              )}

          : <Dropdown
              className="dropdown-160 table--tabs-dropdown"
              items={series.map((s, index) => ({...s, text: s.name, index}))}
              onChoose={this.handleClickDropdown}
              selected={series[activeSeriesIndex].name}
              buttonSize="btn-xs"
            />}

          {(columns && !columns.length) || (values && !values.length)
            ?
This series is empty

            :

                {columns.map((columnName, colIndex) => {
                  return (
                    <Column
                      isResizable={true}
                      key={columnName}
                      columnKey={columnName}
                      header={
                        <Cell>
                          {columnName}
                        </Cell>
                      }
                      cell={({rowIndex}) =>
                        <CustomCell
                          columnName={columnName}
                          data={values[rowIndex][colIndex]}
                        />}
                      width={columnWidths[columnName] || width}
                      minWidth={minWidth}
                    />
                  )
                })}

}

    )
  },
})

const TabItem = ({name, index, onClickTab, isActive}) =>

 onClickTab(index)}
  >
    {name}

TabItem.propTypes = {
  name: string,
  onClickTab: func.isRequired,
  index: number.isRequired,
  isActive: bool,
}

export default Dimensions({elementResize: true})(ChronoTable)
<commit_msg>Pixel perfect<commit_after>import React, {PropTypes} from 'react'

import Dimensions from 'react-dimensions'
import _ from 'lodash'
import moment from 'moment'
import classnames from 'classnames'

import Dropdown from 'shared/components/Dropdown'
import {fetchTimeSeriesAsync} from 'shared/actions/timeSeries'

import {Table, Column, Cell} from 'fixed-data-table'

const {arrayOf, bool, func, number, oneOfType, shape, string} = PropTypes

const emptySeries = {columns: [], values: []}

const CustomCell = React.createClass({
  propTypes: {
    data: oneOfType([number, string]),
    columnName: string.isRequired,
  },

  render() {
    const {columnName, data} = this.props

    if (columnName === 'time') {
      const date = moment(new Date(data)).format('MM/DD/YY hh:mm:ssA')

      return (

          {date}

      )
    }

    return (

        {data}

    )
  },
})

const ChronoTable = React.createClass({
  propTypes: {
    query: shape({
      host: arrayOf(string.isRequired).isRequired,
      text: string.isRequired,
      id: string.isRequired,
    }).isRequired,
    containerWidth: number.isRequired,
    height: number,
    editQueryStatus: func.isRequired,
  },

  getInitialState() {
    return {
      series: [emptySeries],
      columnWidths: {},
      activeSeriesIndex: 0,
    }
  },

  getDefaultProps() {
    return {
      height: 500,
    }
  },

  componentDidMount() {
    this.fetchCellData(this.props.query)
  },

  componentWillReceiveProps(nextProps) {
    if (this.props.query.text === nextProps.query.text) {
      return
    }

    this.fetchCellData(nextProps.query)
  },

  async fetchCellData(query) {
    if (!query || !query.text) {
      return
    }

    this.setState({isLoading: true})
    // second param is db, we want to leave this blank
    try {
      const {results} = await fetchTimeSeriesAsync({source: query.host, query})
      this.setState({isLoading: false})

      let series = _.get(results, ['0', 'series'], [])

      if (!series.length) {
        return this.setState({series: []})
      }

      series = series.map(s => (s.values ? s : {...s, values: []}))
      this.setState({series})
    } catch (error) {
      this.setState({
        isLoading: false,
        series: [],
      })
      throw error
    }
  },

  handleColumnResize(newColumnWidth, columnKey) {
    const columnWidths = {
      ...this.state.columnWidths,
      [columnKey]: newColumnWidth,
    }

    this.setState({
      columnWidths,
    })
  },

  handleClickTab(activeSeriesIndex) {
    this.setState({activeSeriesIndex})
  },

  handleClickDropdown(item) {
    this.setState({activeSeriesIndex: item.index})
  },

  render() {
    const {containerWidth, height, query} = this.props
    const {series, columnWidths, isLoading, activeSeriesIndex} = this.state
    const {columns, values} = _.get(
      series,
      [`${activeSeriesIndex}`],
      emptySeries
    )

    const maximumTabsCount = 11
    // adjust height to proper value by subtracting the heights of the UI around it
    // tab height, graph-container vertical padding, graph-heading height, multitable-header height
    const minWidth = 70
    const rowHeight = 34
    const headerHeight = 30
    const stylePixelOffset = 125
    const defaultColumnWidth = 200
    const styleAdjustedHeight = height - stylePixelOffset
    const width =
      columns && columns.length > 1 ? defaultColumnWidth : containerWidth

    if (!query) {
      return
Please add a query below

    }

    if (isLoading) {
      return
Loading...

    }

    return (

        {series.length < maximumTabsCount
          ?

              {series.map(({name}, i) =>
                <TabItem
                  isActive={i === activeSeriesIndex}
                  key={i}
                  name={name}
                  index={i}
                  onClickTab={this.handleClickTab}
                />
              )}

          : <Dropdown
              className="dropdown-160 table--tabs-dropdown"
              items={series.map((s, index) => ({...s, text: s.name, index}))}
              onChoose={this.handleClickDropdown}
              selected={series[activeSeriesIndex].name}
              buttonSize="btn-xs"
            />}

          {(columns && !columns.length) || (values && !values.length)
            ?
This series is empty

            :

                {columns.map((columnName, colIndex) => {
                  return (
                    <Column
                      isResizable={true}
                      key={columnName}
                      columnKey={columnName}
                      header={
                        <Cell>
                          {columnName}
                        </Cell>
                      }
                      cell={({rowIndex}) =>
                        <CustomCell
                          columnName={columnName}
                          data={values[rowIndex][colIndex]}
                        />}
                      width={columnWidths[columnName] || width}
                      minWidth={minWidth}
                    />
                  )
                })}

}

    )
  },
})

const TabItem = ({name, index, onClickTab, isActive}) =>

 onClickTab(index)}
  >
    {name}

TabItem.propTypes = {
  name: string,
  onClickTab: func.isRequired,
  index: number.isRequired,
  isActive: bool,
}

export default Dimensions({elementResize: true})(ChronoTable)
<|endoftext|>