<commit_before>
(function($) {
    $.fn.barReporter = function(options) {
        options = $.extend({
            "data": [],
            "color": "green",
            "type": "stacked",
            "scale": undefined,
        }, options);

        //find the bar element or initialize & add to container
        var get_or_create_row = function(parent, id) {
            var el = $(parent).find("#brRow" + id);
            if( !el.length ) {
                el = $("
" +
                    "

" +
                    "

");
                $(parent).append( el );
            }
            return el;
        }

        //find or add a new bar
        var get_or_create_bar = function(parent, index) {
            var el = $(parent).find(".brBars #brBar" + index);
            if( !el.length ) {
                el = $("

");
                $(parent).find(".brBars").append( el );
            }
            return el;
        }

        //calculates the scale to present items out of
        var get_scale = function() {
            if( options.scale ) {
                return options.scale
            }

            var scale = 0;

            for( var index in options.data ) {
                var data = options.data[index][0];
                var total = 0;

                //if row does not have array of data, row's total is simply the value
                if( !$.isArray(data) ) {
                    total = data;

                //if row has array of data, row is either sum of values or highest value (depends on report type)
                } else {
                    $(data).each(function(i,value) {
                        if( options.type == "stacked" ) {
                            total += value;
                        } else if( (options.type == "multi") && (value > total) ) {
                            total = value;
                        }
                    });
                }

                if( total > scale ) {
                    scale = total;
                }
            }

            return scale;
        }

        //Remove any rows that no longer exist
        if( $(this).find(".brRow").length >= options.data.length ) {
            $(this).find(".brRow").each(function(index) {
                if( index > options.data.length - 1 ) {
                    $(this).remove();
                }
            });
        }

        //loop through rows and render them
        $(options.data).each($.proxy(function(index, row_data) {

            //get or create row
            var row_el = get_or_create_row(this, index);

            var data = $.isArray( row_data[0] ) ? row_data[0] : [ row_data[0] ];
            var label = row_data[1];

            //Remove any bars that no longer exist
            if( row_el.find(".brBar").length >= data.length ) {
                row_el.find(".brBar").each(function(index) {
                    if( index > data.length - 1 ) {
                        $(this).remove();
                    }
                });
            }

            //Update bar data
            $(data).each( function(index, value) {
                var el = get_or_create_bar( row_el, index );
                var width = value / get_scale() * 100;
                $(el).css("width", width + "%");
            });

            //Update label
            $(row_el).find(".brLabel").text( label );

        }, this));
    }

})(jQuery);

//        Reporting.draw_status_bars({
//            render_fn: function(id, title, height, color) {
//                var entry = $(ed.templates.render('reporting_bar', {
//                    id: id,
//                    title: title,
//                    height: height,
//                    color: color,
//                    drawbuttons: report_options["draw_correct_answer_buttons"]
//                }));
//            },
//            update_fn: function(el, id, value, label) {
//                if( !id ) { return false; }
//                $(el).find("#" + id.valueOf() + " #bar").css("width", value + "%");
//                $(el).find("#" + id.valueOf() + " .chart_percent").text(value + "%");
//                $(el).find("#" + id.valueOf() + " .extra_label").text(label);
//            },
//
//        });
//
//
//
//
//
//
//draw_status_bars: function(options) {
//    var options = $.extend({ //        el: "body",
//        title: "",
//        title_position: "vertical", //may be vertical or horizontal
//        data: [],
//        height: 25,
//        get_fn: this._get_status_bars,
//        render_fn: this._draw_status_bar,
//        update_fn: this._update_status_bar,
//        inline_bars: false, //defines if multiple bars should be rendered in one line, or in multiple rows
//        remove_unreferenced_bars: true //if the status bar el contains a status bar that is not defined in 'data', specify if remove
//    }, options);
//
//    //el: element to put the status bars in
//    //data: [{id: '--', title:'---', value: 0-100, label: '(opn)', color: '(opn)'}, ...]
//
//    //cannot use table because when tables are not visible, jqplot does not work
//    //create a container if it doesn't exist of the status bars
//    var $status_bar_div_container = $(options.el).find(".status_bar_container");
//
//    //if nothing present, initialize
//    if ($status_bar_div_container.length == 0) {
//        if( options.title_position == "horizontal" ) {
//            $status_bar_div_container = $("

");
//            if (options.drawbuttons && (options.module_item.get('type') != 'na')) {
//                $status_bar_div_container.append("
	Correct
");
//            }
//
//        } else {
//            $status_bar_div_container = $("

" + options.title + "

");
//        }
//        $(options.el).prepend($status_bar_div_container);
//    }
//
//    //check against previous data to see if any changes are required; return immediately if not
//    var prev_data = $status_bar_div_container.data("status_bars_data");
//    if( prev_data && (_.isEqual(prev_data, options.data)) ) { return true; }
//    $status_bar_div_container.data("status_bars_data", options.data);
//
//    var bar_ids = _.map(options.data, function(item) { return item.id; });
//    var bar_el_ids = _.map(options.get_fn($status_bar_div_container), function(el) { return $(el).attr("id"); });
//
//    //boolean true/false value, triggered if a bar is added or removed from the chart
//    //when bars are added or removed, we must resize them
//    var bars_changed = false;
//
//    if( options.remove_unreferenced_bars ) {
//        //remove any bars that are present in the el, but not in the data
//        _.each(bar_el_ids, function(bar_id) {
//            if( _.indexOf(bar_ids, bar_id) == -1 ) {
//                options.get_fn($status_bar_div_container).filter(function() { return $(this).attr("id") == bar_id; }).remove();
//                bars_changed = true;
//            }
//        });
//    }
//
//
//    //add any bars that are present in the data, but not in the el
//    _.each(bar_ids, function(bar_id) {
//        if( _.indexOf(bar_el_ids, bar_id) == -1 ) {
//            var bar_data = _.detect(options.data, function(item) { return item.id == bar_id});
//            if( !bar_data.height ) { bar_data.height = options.height; }
//            if( !bar_data.color ) { bar_data.color = color; }
//            $status_bar_div_container.append(options.render_fn(bar_data.id, bar_data.title, bar_data.height, bar_data.color));
//            bars_changed = true;
//        }
//    });
//
//    //update bars
//    for( i in options.data ) {
//        var bar_data = options.data[i];
//        options.update_fn($status_bar_div_container, bar_data.id, bar_data.value, bar_data.label);
//    }
//
//    if( bars_changed ) {
//        var $status_bars = $status_bar_div_container.find(".status_bar");
//        if( options.inline_bars ) {
//            $status_bars.css("width", (100 / $status_bars.length) + "%");
//        } else {
//            $status_bars.css("width", "100%");
//        }
//    }
//},
//    _get_status_bars: function(el) {
//        return $(el).find(".status_bar");
//    },
//    _draw_status_bar: function(id, title, height, color, label) {
//        //value = 0-100
//        var html = "
" +
//            "
" +
//            "" +
//            "

" +
//            "
" +
//            (title ? "
" + title + "
" : "") +
//            "
";
//        return html;
//    },
//    _update_status_bar: function(el, id, value, label) {
//        if( !id ) { return false; }
//        $(el).find("#" + id.valueOf() + " #bar").css("width", value + "%");
//        $(el).find("#" + id.valueOf() + " .chart_percent").text(label);
//    },
//
//
//
<commit_msg>Optimizations<commit_after>
(function($) {
    $.fn.barReporter = function(options) {
        options = $.extend({
            "data": [],
            "color": "green",
            "type": "stacked",
            "scale": undefined,
        }, options);

        //determine graph scale
        var scale = $.fn.barReporter.calculate_scale(options);

        //Remove any rows that no longer exist
        if( $(this).find(".brRow").length >= options.data.length ) {
            $(this).find(".brRow").each(function(index) {
                if( index > options.data.length - 1 ) {
                    $(this).remove();
                }
            });
        }

        //loop through rows and render them
        $(options.data).each($.proxy(function(index, row_data) {

            //get or create row
            var row_el = $.fn.barReporter.get_or_create_row(this, index);

            var data = $.isArray( row_data[0] ) ? row_data[0] : [ row_data[0] ];
            var label = row_data[1];

            //Remove any bars that no longer exist
            if( row_el.find(".brBar").length >= data.length ) {
                row_el.find(".brBar").each(function(index) {
                    if( index > data.length - 1 ) {
                        $(this).remove();
                    }
                });
            }

            //Update bar data
            $(data).each( function(index, value) {
                var el = $.fn.barReporter.get_or_create_bar( row_el, index );
                var width = value / scale * 100;
                $(el).css("width", width + "%");
            });

            //Update label
            $(row_el).find(".brLabel").text( label );

        }, this));
    };

    //find the bar element or initialize & add to container
    $.fn.barReporter.get_or_create_row = function(parent, id) {
        var el = $(parent).find("#brRow" + id);
        if( !el.length ) {
            el = $("
" +
                "

" +
                "

");
            $(parent).append( el );
        }
        return el;
    }

    //find or add a new bar
    $.fn.barReporter.get_or_create_bar = function(parent, index) {
        var el = $(parent).find(".brBars #brBar" + index);
        if( !el.length ) {
            el = $("

");
            $(parent).find(".brBars").append( el );
        }
        return el;
    }

    //calculates the scale to present items out of
    $.fn.barReporter.calculate_scale = function(options) {
        if( options.scale ) {
            return options.scale
        }

        var scale = 0;

        for( var index in options.data ) {
            var data = options.data[index][0];
            var total = 0;

            //if row does not have array of data, row's total is simply the value
            if( !$.isArray(data) ) {
                total = data;

            //if row has array of data, row is either sum of values or highest value (depends on report type)
            } else {
                $(data).each(function(i,value) {
                    if( options.type == "stacked" ) {
                        total += value;
                    } else if( (options.type == "multi") && (value > total) ) {
                        total = value;
                    }
                });
            }

            if( total > scale ) {
                scale = total;
            }
        }

        return scale;
    }

})(jQuery);

//        Reporting.draw_status_bars({
//            render_fn: function(id, title, height, color) {
//                var entry = $(ed.templates.render('reporting_bar', {
//                    id: id,
//                    title: title,
//                    height: height,
//                    color: color,
//                    drawbuttons: report_options["draw_correct_answer_buttons"]
//                }));
//            },
//            update_fn: function(el, id, value, label) {
//                if( !id ) { return false; }
//                $(el).find("#" + id.valueOf() + " #bar").css("width", value + "%");
//                $(el).find("#" + id.valueOf() + " .chart_percent").text(value + "%");
//                $(el).find("#" + id.valueOf() + " .extra_label").text(label);
//            },
//
//        });
//
//
//
//
//
//
//draw_status_bars: function(options) {
//    var options = $.extend({ //        el: "body",
//        title: "",
//        title_position: "vertical", //may be vertical or horizontal
//        data: [],
//        height: 25,
//        get_fn: this._get_status_bars,
//        render_fn: this._draw_status_bar,
//        update_fn: this._update_status_bar,
//        inline_bars: false, //defines if multiple bars should be rendered in one line, or in multiple rows
//        remove_unreferenced_bars: true //if the status bar el contains a status bar that is not defined in 'data', specify if remove
//    }, options);
//
//    //el: element to put the status bars in
//    //data: [{id: '--', title:'---', value: 0-100, label: '(opn)', color: '(opn)'}, ...]
//
//    //cannot use table because when tables are not visible, jqplot does not work
//    //create a container if it doesn't exist of the status bars
//    var $status_bar_div_container = $(options.el).find(".status_bar_container");
//
//    //if nothing present, initialize
//    if ($status_bar_div_container.length == 0) {
//        if( options.title_position == "horizontal" ) {
//            $status_bar_div_container = $("

");
//            if (options.drawbuttons && (options.module_item.get('type') != 'na')) {
//                $status_bar_div_container.append("
	Correct
");
//            }
//
//        } else {
//            $status_bar_div_container = $("

" + options.title + "

");
//        }
//        $(options.el).prepend($status_bar_div_container);
//    }
//
//    //check against previous data to see if any changes are required; return immediately if not
//    var prev_data = $status_bar_div_container.data("status_bars_data");
//    if( prev_data && (_.isEqual(prev_data, options.data)) ) { return true; }
//    $status_bar_div_container.data("status_bars_data", options.data);
//
//    var bar_ids = _.map(options.data, function(item) { return item.id; });
//    var bar_el_ids = _.map(options.get_fn($status_bar_div_container), function(el) { return $(el).attr("id"); });
//
//    //boolean true/false value, triggered if a bar is added or removed from the chart
//    //when bars are added or removed, we must resize them
//    var bars_changed = false;
//
//    if( options.remove_unreferenced_bars ) {
//        //remove any bars that are present in the el, but not in the data
//        _.each(bar_el_ids, function(bar_id) {
//            if( _.indexOf(bar_ids, bar_id) == -1 ) {
//                options.get_fn($status_bar_div_container).filter(function() { return $(this).attr("id") == bar_id; }).remove();
//                bars_changed = true;
//            }
//        });
//    }
//
//
//    //add any bars that are present in the data, but not in the el
//    _.each(bar_ids, function(bar_id) {
//        if( _.indexOf(bar_el_ids, bar_id) == -1 ) {
//            var bar_data = _.detect(options.data, function(item) { return item.id == bar_id});
//            if( !bar_data.height ) { bar_data.height = options.height; }
//            if( !bar_data.color ) { bar_data.color = color; }
//            $status_bar_div_container.append(options.render_fn(bar_data.id, bar_data.title, bar_data.height, bar_data.color));
//            bars_changed = true;
//        }
//    });
//
//    //update bars
//    for( i in options.data ) {
//        var bar_data = options.data[i];
//        options.update_fn($status_bar_div_container, bar_data.id, bar_data.value, bar_data.label);
//    }
//
//    if( bars_changed ) {
//        var $status_bars = $status_bar_div_container.find(".status_bar");
//        if( options.inline_bars ) {
//            $status_bars.css("width", (100 / $status_bars.length) + "%");
//        } else {
//            $status_bars.css("width", "100%");
//        }
//    }
//},
//    _get_status_bars: function(el) {
//        return $(el).find(".status_bar");
//    },
//    _draw_status_bar: function(id, title, height, color, label) {
//        //value = 0-100
//        var html = "
" +
//            "
" +
//            "" +
//            "

" +
//            "
" +
//            (title ? "
" + title + "
" : "") +
//            "
";
//        return html;
//    },
//    _update_status_bar: function(el, id, value, label) {
//        if( !id ) { return false; }
//        $(el).find("#" + id.valueOf() + " #bar").css("width", value + "%");
//        $(el).find("#" + id.valueOf() + " .chart_percent").text(label);
//    },
//
//
//
<|endoftext|>


<commit_before>
openerp.hr_timesheet_sheet = function(instance) {
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    instance.hr_timesheet_sheet.WeeklyTimesheet = instance.web.form.FormWidget.extend(instance.web.form.ReinitializeWidgetMixin, {
        events: {
            "click .oe_timesheet_weekly_account a": "go_to",
        },
        init: function() {
            this._super.apply(this, arguments);
            this.set({
                sheets: [],
                date_to: false,
                date_from: false,
            });
            this.field_manager.on("field_changed:timesheet_ids", this, this.query_sheets);
            this.field_manager.on("field_changed:date_from", this, function() {
                this.set({"date_from": instance.web.str_to_date(this.field_manager.get_field_value("date_from"))});
            });
            this.field_manager.on("field_changed:date_to", this, function() {
                this.set({"date_to": instance.web.str_to_date(this.field_manager.get_field_value("date_to"))});
            });
            this.field_manager.on("field_changed:user_id", this, function() {
                this.set({"user_id": this.field_manager.get_field_value("user_id")});
            });
            this.on("change:sheets", this, this.update_sheets);
            this.res_o2m_drop = new instance.web.DropMisordered();
            this.render_drop = new instance.web.DropMisordered();
            this.description_line = _t("/");
        },
        go_to: function(event) {
            var id = JSON.parse($(event.target).data("id"));
            this.do_action({
                type: 'ir.actions.act_window',
                res_model: "account.analytic.account",
                res_id: id,
                views: [[false, 'form']],
                target: 'current'
            });
        },
        query_sheets: function() {
            var self = this;
            if (self.updating)
                return;
            var commands = this.field_manager.get_field_value("timesheet_ids");
            this.res_o2m_drop.add(new instance.web.Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [],
                    new instance.web.CompoundContext()]))
                .done(function(result) {
                self.querying = true;
                self.set({sheets: result});
                self.querying = false;
            });
        },
        update_sheets: function() {
            var self = this;
            if (self.querying)
                return;
            self.updating = true;
            self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() {
                self.updating = false;
            });
        },
        initialize_field: function() {
            instance.web.form.ReinitializeWidgetMixin.initialize_field.call(this);
            var self = this;
            self.on("change:sheets", self, self.initialize_content);
            self.on("change:date_to", self, self.initialize_content);
            self.on("change:date_from", self, self.initialize_content);
            self.on("change:user_id", self, self.initialize_content);
        },
        initialize_content: function() {
            var self = this;
            if (self.setting)
                return;
            // don't render anything until we have date_to and date_from
            if (!self.get("date_to") || !self.get("date_from"))
                return;
            this.destroy_content();

            // it's important to use those vars to avoid race conditions
            var dates;
            var accounts;
            var account_names;
            var default_get;
            return this.render_drop.add(new instance.web.Model("hr.analytic.timesheet").call("default_get", [
                ['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'],
                new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) {
                default_get = result;
                // calculating dates
                dates = [];
                var start = self.get("date_from");
                var end = self.get("date_to");
                while (start <= end) {
                    dates.push(start);
                    start = start.clone().addDays(1);
                }
                // group by account
                accounts = _(self.get("sheets")).chain()
                .map(function(el) {
                    // much simpler to use only the id in all cases
                    if (typeof(el.account_id) === "object")
                        el.account_id = el.account_id[0];
                    return el;
                })
                .groupBy("account_id").value();

                var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el) });

                return new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids,
                    new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) {
                    accounts = _(accounts).chain().map(function(lines, account_id) {
                        account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {});
                        // group by days
                        account_id = account_id === "false" ? false :  Number(account_id);
                        var index = _.groupBy(lines, "date");
                        var days = _.map(dates, function(date) {
                            var day = {day: date, lines: index[instance.web.date_to_str(date)] || []};
                            // add line where we will insert/remove hours
                            var to_add = _.find(day.lines, function(line) { return line.name === self.description_line });
                            if (to_add) {
                                day.lines = _.without(day.lines, to_add);
                                day.lines.unshift(to_add);
                            } else {
                                day.lines.unshift(_.extend(_.clone(account_defaults), {
                                    name: self.description_line,
                                    unit_amount: 0,
                                    date: instance.web.date_to_str(date),
                                    account_id: account_id,
                                }));
                            }
                            return day;
                        });
                        return {account: account_id, days: days, account_defaults: account_defaults};
                    }).value();

                    // we need the name_get of the analytic accounts
                    return new instance.web.Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"),
                        new instance.web.CompoundContext()]).then(function(result) {
                        account_names = {};
                        _.each(result, function(el) {
                            account_names[el[0]] = el[1];
                        });
                        accounts = _.sortBy(accounts, function(el) {
                            return account_names[el.account];
                        });
                    });;
                });
            })).then(function(result) {
                // we put all the gathered data in self, then we render
                self.dates = dates;
                self.accounts = accounts;
                self.account_names = account_names;
                self.default_get = default_get;
                //real rendering
                self.display_data();
            });
        },
        destroy_content: function() {
            if (this.dfm) {
                this.dfm.destroy();
                this.dfm = undefined;
            }
        },
        display_data: function() {
            var self = this;
            self.$el.html(QWeb.render("hr_timesheet_sheet.WeeklyTimesheet", {widget: self}));
            _.each(self.accounts, function(account) {
                _.each(_.range(account.days.length), function(day_count) {
                    if (!self.get('effective_readonly')) {
                        self.get_box(account, day_count).val(self.sum_box(account, day_count)).change(function() {
                            var num = Number($(this).val());
                            if (isNaN(num)) {
                                $(this).val(self.sum_box(account, day_count));
                            } else {
                                account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
                                self.display_totals();
                                self.sync();
                            }
                        });
                    } else {
                        self.get_box(account, day_count).html(self.sum_box(account, day_count));
                    }
                });
            });
            self.display_totals();
            self.$(".oe_timesheet_weekly_adding button").click(_.bind(this.init_add_account, this));
        },
        init_add_account: function() {
            var self = this;
            if (self.dfm)
                return;
            self.$(".oe_timesheet_weekly_add_row").show();
            self.dfm = new instance.web.form.DefaultFieldManager(self);
            self.dfm.extend_field_desc({
                account: {
                    relation: "account.analytic.account",
                },
            });
            self.account_m2o = new instance.web.form.FieldMany2One(self.dfm, {
                attrs: {
                    name: "account",
                    type: "many2one",
                    domain: [
                        ['type','in',['normal', 'contract']],
                        ['state', '<>', 'close'],
                        ['use_timesheets','=',1],
                        ['id', 'not in', _.pluck(self.accounts, "account")],
                    ],
                    context: {
                        default_use_timesheets: 1,
                        default_type: "contract",
                    },
                    modifiers: '{"required": true}',
                },
            });
            self.account_m2o.prependTo(self.$(".oe_timesheet_weekly_add_row td"));
            self.$(".oe_timesheet_weekly_add_row button").click(function() {
                var id = self.account_m2o.get_value();
                if (id === false) {
                    self.dfm.set({display_invalid_fields: true});
                    return;
                }
                var ops = self.generate_o2m_value();
                new instance.web.Model("hr.analytic.timesheet").call("on_change_account_id", [[], id]).then(function(res) {
                    var def = _.extend({}, self.default_get, res.value, {
                        name: self.description_line,
                        unit_amount: 0,
                        date: instance.web.date_to_str(self.dates[0]),
                        account_id: id,
                    });
                    ops.push(def);
                    self.set({"sheets": ops});
                });
            });
        },
        get_box: function(account, day_count) {
            return this.$('[data-account="' + account.account + '"][data-day-count="' + day_count + '"]');
        },
        get_total: function(account) {
            return this.$('[data-account-total="' + account.account + '"]');
        },
        get_day_total: function(day_count) {
            return this.$('[data-day-total="' + day_count + '"]');
        },
        get_super_total: function() {
            return this.$('.oe_timesheet_weekly_supertotal');
        },
        sum_box: function(account, day_count) {
            var line_total = 0;
            _.each(account.days[day_count].lines, function(line) {
                line_total += line.unit_amount;
            });
            return line_total;
        },
        display_totals: function() {
            var self = this;
            var day_tots = _.map(_.range(self.dates.length), function() { return 0 });
            var super_tot = 0;
            _.each(self.accounts, function(account) {
                var acc_tot = 0;
                _.each(_.range(self.dates.length), function(day_count) {
                    var sum = self.sum_box(account, day_count);
                    acc_tot += sum;
                    day_tots[day_count] += sum;
                    super_tot += sum;
                });
                self.get_total(account).html(acc_tot);
            });
            _.each(_.range(self.dates.length), function(day_count) {
                self.get_day_total(day_count).html(day_tots[day_count]);
            });
            self.get_super_total().html(super_tot);
        },
        sync: function() {
            var self = this;
            self.setting = true;
            self.set({sheets: this.generate_o2m_value()});
            self.setting = false;
        },
        generate_o2m_value: function() {
            var self = this;
            var ops = [];

            _.each(self.accounts, function(account) {
                var auth_keys = _.extend(_.clone(account.account_defaults), {
                    name: true, unit_amount: true, date: true, account_id:true,
                });
                _.each(account.days, function(day) {
                    _.each(day.lines, function(line) {
                        if (line.unit_amount !== 0) {
                            var tmp = _.clone(line);
                            tmp.id = undefined;
                            _.each(line, function(v, k) {
                                if (v instanceof Array) {
                                    tmp[k] = v[0];
                                }
                            });
                            // we have to remove some keys, because analytic lines are shitty
                            _.each(_.keys(tmp), function(key) {
                                if (auth_keys[key] === undefined) {
                                    tmp[key] = undefined;
                                }
                            });
                            ops.push(tmp);
                        }
                    });
                });
            });
            return ops;
        },
    });

    instance.web.form.custom_widgets.add('weekly_timesheet', 'instance.hr_timesheet_sheet.WeeklyTimesheet');

};
<commit_msg>[FIX] stop multiple rpc call of default_get on loading<commit_after>
openerp.hr_timesheet_sheet = function(instance) {
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    instance.hr_timesheet_sheet.WeeklyTimesheet = instance.web.form.FormWidget.extend(instance.web.form.ReinitializeWidgetMixin, {
        events: {
            "click .oe_timesheet_weekly_account a": "go_to",
        },
        init: function() {
            this._super.apply(this, arguments);
            this.set({
                sheets: [],
                date_to: false,
                date_from: false,
            });
            this.updating = true;
            this.field_manager.on("field_changed:timesheet_ids", this, this.query_sheets);
            this.field_manager.on("field_changed:date_from", this, function() {
                this.set({"date_from": instance.web.str_to_date(this.field_manager.get_field_value("date_from"))});
            });
            this.field_manager.on("field_changed:date_to", this, function() {
                this.set({"date_to": instance.web.str_to_date(this.field_manager.get_field_value("date_to"))});
            });
            this.field_manager.on("field_changed:user_id", this, function() {
                this.set({"user_id": this.field_manager.get_field_value("user_id")});
            });
            this.on("change:sheets", this, this.update_sheets);
            this.res_o2m_drop = new instance.web.DropMisordered();
            this.render_drop = new instance.web.DropMisordered();
            this.description_line = _t("/");
        },
        go_to: function(event) {
            var id = JSON.parse($(event.target).data("id"));
            this.do_action({
                type: 'ir.actions.act_window',
                res_model: "account.analytic.account",
                res_id: id,
                views: [[false, 'form']],
                target: 'current'
            });
        },
        query_sheets: function() {
            var self = this;
            if (self.updating)
                return;
            var commands = this.field_manager.get_field_value("timesheet_ids");
            this.res_o2m_drop.add(new instance.web.Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [],
                    new instance.web.CompoundContext()]))
                .done(function(result) {
                self.querying = true;
                self.set({sheets: result});
                self.querying = false;
            });
        },
        update_sheets: function() {
            var self = this;
            if (self.querying)
                return;
            self.updating = true;
            self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() {
                self.updating = false;
            });
        },
        initialize_field: function() {
            instance.web.form.ReinitializeWidgetMixin.initialize_field.call(this);
            var self = this;
            self.on("change:sheets", self, self.initialize_content);
            self.on("change:date_to", self, self.initialize_content);
            self.on("change:date_from", self, self.initialize_content);
            self.on("change:user_id", self, self.initialize_content);
        },
        initialize_content: function() {
            var self = this;
            if (self.setting)
                return;
            // don't render anything until we have date_to and date_from
            if (!self.get("date_to") || !self.get("date_from"))
                return;
            this.destroy_content();

            // it's important to use those vars to avoid race conditions
            var dates;
            var accounts;
            var account_names;
            var default_get;
            return this.render_drop.add(new instance.web.Model("hr.analytic.timesheet").call("default_get", [
                ['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'],
                new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) {
                default_get = result;
                // calculating dates
                dates = [];
                var start = self.get("date_from");
                var end = self.get("date_to");
                while (start <= end) {
                    dates.push(start);
                    start = start.clone().addDays(1);
                }
                // group by account
                accounts = _(self.get("sheets")).chain()
                .map(function(el) {
                    // much simpler to use only the id in all cases
                    if (typeof(el.account_id) === "object")
                        el.account_id = el.account_id[0];
                    return el;
                })
                .groupBy("account_id").value();

                var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el) });

                return new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids,
                    new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) {
                    accounts = _(accounts).chain().map(function(lines, account_id) {
                        account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {});
                        // group by days
                        account_id = account_id === "false" ? false :  Number(account_id);
                        var index = _.groupBy(lines, "date");
                        var days = _.map(dates, function(date) {
                            var day = {day: date, lines: index[instance.web.date_to_str(date)] || []};
                            // add line where we will insert/remove hours
                            var to_add = _.find(day.lines, function(line) { return line.name === self.description_line });
                            if (to_add) {
                                day.lines = _.without(day.lines, to_add);
                                day.lines.unshift(to_add);
                            } else {
                                day.lines.unshift(_.extend(_.clone(account_defaults), {
                                    name: self.description_line,
                                    unit_amount: 0,
                                    date: instance.web.date_to_str(date),
                                    account_id: account_id,
                                }));
                            }
                            return day;
                        });
                        return {account: account_id, days: days, account_defaults: account_defaults};
                    }).value();

                    // we need the name_get of the analytic accounts
                    return new instance.web.Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"),
                        new instance.web.CompoundContext()]).then(function(result) {
                        account_names = {};
                        _.each(result, function(el) {
                            account_names[el[0]] = el[1];
                        });
                        accounts = _.sortBy(accounts, function(el) {
                            return account_names[el.account];
                        });
                    });;
                });
            })).then(function(result) {
                // we put all the gathered data in self, then we render
                self.dates = dates;
                self.accounts = accounts;
                self.account_names = account_names;
                self.default_get = default_get;
                //real rendering
                self.display_data();
            });
        },
        destroy_content: function() {
            if (this.dfm) {
                this.dfm.destroy();
                this.dfm = undefined;
            }
        },
        display_data: function() {
            var self = this;
            self.$el.html(QWeb.render("hr_timesheet_sheet.WeeklyTimesheet", {widget: self}));
            _.each(self.accounts, function(account) {
                _.each(_.range(account.days.length), function(day_count) {
                    if (!self.get('effective_readonly')) {
                        self.get_box(account, day_count).val(self.sum_box(account, day_count)).change(function() {
                            var num = Number($(this).val());
                            if (isNaN(num)) {
                                $(this).val(self.sum_box(account, day_count));
                            } else {
                                account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
                                self.display_totals();
                                self.sync();
                            }
                        });
                    } else {
                        self.get_box(account, day_count).html(self.sum_box(account, day_count));
                    }
                });
            });
            self.display_totals();
            self.$(".oe_timesheet_weekly_adding button").click(_.bind(this.init_add_account, this));
        },
        init_add_account: function() {
            var self = this;
            if (self.dfm)
                return;
            self.$(".oe_timesheet_weekly_add_row").show();
            self.dfm = new instance.web.form.DefaultFieldManager(self);
            self.dfm.extend_field_desc({
                account: {
                    relation: "account.analytic.account",
                },
            });
            self.account_m2o = new instance.web.form.FieldMany2One(self.dfm, {
                attrs: {
                    name: "account",
                    type: "many2one",
                    domain: [
                        ['type','in',['normal', 'contract']],
                        ['state', '<>', 'close'],
                        ['use_timesheets','=',1],
                        ['id', 'not in', _.pluck(self.accounts, "account")],
                    ],
                    context: {
                        default_use_timesheets: 1,
                        default_type: "contract",
                    },
                    modifiers: '{"required": true}',
                },
            });
            self.account_m2o.prependTo(self.$(".oe_timesheet_weekly_add_row td"));
            self.$(".oe_timesheet_weekly_add_row button").click(function() {
                var id = self.account_m2o.get_value();
                if (id === false) {
                    self.dfm.set({display_invalid_fields: true});
                    return;
                }
                var ops = self.generate_o2m_value();
                new instance.web.Model("hr.analytic.timesheet").call("on_change_account_id", [[], id]).then(function(res) {
                    var def = _.extend({}, self.default_get, res.value, {
                        name: self.description_line,
                        unit_amount: 0,
                        date: instance.web.date_to_str(self.dates[0]),
                        account_id: id,
                    });
                    ops.push(def);
                    self.set({"sheets": ops});
                });
            });
        },
        get_box: function(account, day_count) {
            return this.$('[data-account="' + account.account + '"][data-day-count="' + day_count + '"]');
        },
        get_total: function(account) {
            return this.$('[data-account-total="' + account.account + '"]');
        },
        get_day_total: function(day_count) {
            return this.$('[data-day-total="' + day_count + '"]');
        },
        get_super_total: function() {
            return this.$('.oe_timesheet_weekly_supertotal');
        },
        sum_box: function(account, day_count) {
            var line_total = 0;
            _.each(account.days[day_count].lines, function(line) {
                line_total += line.unit_amount;
            });
            return line_total;
        },
        display_totals: function() {
            var self = this;
            var day_tots = _.map(_.range(self.dates.length), function() { return 0 });
            var super_tot = 0;
            _.each(self.accounts, function(account) {
                var acc_tot = 0;
                _.each(_.range(self.dates.length), function(day_count) {
                    var sum = self.sum_box(account, day_count);
                    acc_tot += sum;
                    day_tots[day_count] += sum;
                    super_tot += sum;
                });
                self.get_total(account).html(acc_tot);
            });
            _.each(_.range(self.dates.length), function(day_count) {
                self.get_day_total(day_count).html(day_tots[day_count]);
            });
            self.get_super_total().html(super_tot);
        },
        sync: function() {
            var self = this;
            self.setting = true;
            self.set({sheets: this.generate_o2m_value()});
            self.setting = false;
        },
        generate_o2m_value: function() {
            var self = this;
            var ops = [];

            _.each(self.accounts, function(account) {
                var auth_keys = _.extend(_.clone(account.account_defaults), {
                    name: true, unit_amount: true, date: true, account_id:true,
                });
                _.each(account.days, function(day) {
                    _.each(day.lines, function(line) {
                        if (line.unit_amount !== 0) {
                            var tmp = _.clone(line);
                            tmp.id = undefined;
                            _.each(line, function(v, k) {
                                if (v instanceof Array) {
                                    tmp[k] = v[0];
                                }
                            });
                            // we have to remove some keys, because analytic lines are shitty
                            _.each(_.keys(tmp), function(key) {
                                if (auth_keys[key] === undefined) {
                                    tmp[key] = undefined;
                                }
                            });
                            ops.push(tmp);
                        }
                    });
                });
            });
            return ops;
        },
    });

    instance.web.form.custom_widgets.add('weekly_timesheet', 'instance.hr_timesheet_sheet.WeeklyTimesheet');

};
<|endoftext|>


<commit_before>import React from 'react';
import { Route, IndexRoute } from 'react-router';

import { App } from './App';
import {
    Counter,
    JoinLogin,
    JoinLoginEmail,
    List,
  } from './containers';

export default function routes(store) {
  const requireLogin = (nextState, replaceState, cb) => {
    function checkAuth() {
      const { auth: { user }} = store.getState();
      if (!user) {
        // oops, not logged in, so can't be here!
        replaceState(null, '/login');
      }
      cb();
    }

    if (!isAuthLoaded(store.getState())) {
      store.dispatch(loadAuth()).then(checkAuth);
    } else {
      checkAuth();
    }
  };

  /**
   * Please keep routes in alphabetical order
   */
  return (
    <Route path="/" component={App}>
      <IndexRoute component={List} />
      <Route path="counter" component={Counter} increment={1} color="darkred" />
      <Route path="join-login" component={JoinLogin}>
        <IndexRoute component={JoinLoginEmail} />
      </Route>
    </Route>
  );
}
<commit_msg>comment out stuff for now<commit_after>import React from 'react';
import { IndexRoute, Route } from 'react-router';

import {
    App,
    Counter,
    JoinLogin,
    JoinLoginEmail,
    List,
  } from './containers';

export default function routes(store) {
  // const requireLogin = (nextState, replaceState, cb) => {
  //   function checkAuth() {
  //     const { auth: { user }} = store.getState();
  //     if (!user) {
  //       // oops, not logged in, so can't be here!
  //       replaceState(null, '/login');
  //     }
  //     cb();
  //   }
  //
  //   if (!isAuthLoaded(store.getState())) {
  //     store.dispatch(loadAuth()).then(checkAuth);
  //   } else {
  //     checkAuth();
  //   }
  // };

  /**
   * Please keep routes in alphabetical order
   */
  return (
    <Route path="/" component={App}>
      <IndexRoute component={List} />
      <Route path="counter" component={Counter} increment={1} color="darkred" />
      <Route path="join-login" component={JoinLogin}>
        <IndexRoute component={JoinLoginEmail} />
      </Route>
    </Route>
  );
}
<|endoftext|>


<commit_before>DrNicTest.Unit.Runner = function(testcases) {
  var argumentOptions = arguments[1] || {};
  var options = this.options = {};
  options.testLog = ('testLog' in argumentOptions) ? argumentOptions.testLog : 'testlog';
  options.resultsURL = this.queryParams.resultsURL;
  options.testLog = DrNicTest.$(options.testLog);

  this.tests = this.getTests(testcases);
  this.currentTest = 0;
  this.logger = new DrNicTest.Unit.Logger(options.testLog);

  // TODO replace Event.observer(window, "load")
  Event.observe(window, "load", function() {
    this.runTests.bind(this).delay(0.1);
  }.bind(this));
};

DrNicTest.Unit.Runner.prototype.queryParams = window.location.search.parseQuery();

DrNicTest.Unit.Runner.prototype.getTests = function(testcases) {
  var tests = [], options = this.options;
  if (this.queryParams.tests) tests = this.queryParams.tests.split(',');
  else if (options.tests) tests = options.tests;
  else if (options.test) tests = [option.test];
  else {
    for (testname in testcases) {
      if (/^test/.match(testname)) tests.push(testname);
    }
  }
  var results = [];
  for (var i=0; i < tests.length; i++) {
    var test = tests[i];
    if (testcases[test])
      results.push(
        new DrNicTest.Unit.Testcase(test, testcases[test], testcases.setup, testcases.teardown)
      );
  };
  return results;
};

DrNicTest.Unit.Runner.prototype.getResult = function() {
  var results = {
    tests: this.tests.length,
    assertions: 0,
    failures: 0,
    errors: 0
  };

  return this.tests.inject(results, function(results, test) {
    results.assertions += test.assertions;
    results.failures   += test.failures;
    results.errors     += test.errors;
    return results;
  });
};

DrNicTest.Unit.Runner.prototype.postResults = function() {
  if (this.options.resultsURL) {
    // TODO replace prototype's Ajax.Request
    new Ajax.Request(this.options.resultsURL,
      { method: 'get', parameters: this.getResult(), asynchronous: false });
  }
};

DrNicTest.Unit.Runner.prototype.runTests = function() {
  var test = this.tests[this.currentTest], actions;

  if (!test) return this.finish();
  if (!test.isWaiting) this.logger.start(test.name);
  test.run();
  if(test.isWaiting) {
    this.logger.message("Waiting for " + test.timeToWait + "ms");
    // setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
    setTimeout(function() {
      this.runTests();
    }, test.timeToWait || 1000);
    return;
  }

  this.logger.finish(test.status(), test.summary());
  if (actions = test.actions) this.logger.appendActionButtons(actions);
  this.currentTest++;
  // tail recursive, hopefully the browser will skip the stackframe
  this.runTests();
};

DrNicTest.Unit.Runner.prototype.finish = function() {
  this.postResults();
  this.logger.summary(this.summary());
};

DrNicTest.Unit.Runner.prototype.summary = function() {
  return new DrNicTest.Template('#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors').evaluate(this.getResult());
};
<commit_msg>attempt to ignore queryParams if test run without resultsUrl<commit_after>DrNicTest.Unit.Runner = function(testcases) {
  var argumentOptions = arguments[1] || {};
  var options = this.options = {};
  options.testLog = ('testLog' in argumentOptions) ? argumentOptions.testLog : 'testlog';
  options.resultsURL = this.queryParams.resultsURL;
  options.testLog = DrNicTest.$(options.testLog);

  this.tests = this.getTests(testcases);
  this.currentTest = 0;
  this.logger = new DrNicTest.Unit.Logger(options.testLog);

  // TODO replace Event.observer(window, "load")
  Event.observe(window, "load", function() {
    this.runTests.bind(this).delay(0.1);
  }.bind(this));
};

DrNicTest.Unit.Runner.prototype.queryParams = function() {
  if (window.location.search.length > 0) {
    return window.location.search.parseQuery();
  }
  return "";
}();

DrNicTest.Unit.Runner.prototype.getTests = function(testcases) {
  var tests = [], options = this.options;
  if (this.queryParams.tests) tests = this.queryParams.tests.split(',');
  else if (options.tests) tests = options.tests;
  else if (options.test) tests = [option.test];
  else {
    for (testname in testcases) {
      if (/^test/.match(testname)) tests.push(testname);
    }
  }
  var results = [];
  for (var i=0; i < tests.length; i++) {
    var test = tests[i];
    if (testcases[test])
      results.push(
        new DrNicTest.Unit.Testcase(test, testcases[test], testcases.setup, testcases.teardown)
      );
  };
  return results;
};

DrNicTest.Unit.Runner.prototype.getResult = function() {
  var results = {
    tests: this.tests.length,
    assertions: 0,
    failures: 0,
    errors: 0
  };

  return this.tests.inject(results, function(results, test) {
    results.assertions += test.assertions;
    results.failures   += test.failures;
    results.errors     += test.errors;
    return results;
  });
};

DrNicTest.Unit.Runner.prototype.postResults = function() {
  if (this.options.resultsURL) {
    // TODO replace prototype's Ajax.Request
    new Ajax.Request(this.options.resultsURL,
      { method: 'get', parameters: this.getResult(), asynchronous: false });
  }
};

DrNicTest.Unit.Runner.prototype.runTests = function() {
  var test = this.tests[this.currentTest], actions;

  if (!test) return this.finish();
  if (!test.isWaiting) this.logger.start(test.name);
  test.run();
  if(test.isWaiting) {
    this.logger.message("Waiting for " + test.timeToWait + "ms");
    // setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
    setTimeout(function() {
      this.runTests();
    }, test.timeToWait || 1000);
    return;
  }

  this.logger.finish(test.status(), test.summary());
  if (actions = test.actions) this.logger.appendActionButtons(actions);
  this.currentTest++;
  // tail recursive, hopefully the browser will skip the stackframe
  this.runTests();
};

DrNicTest.Unit.Runner.prototype.finish = function() {
  this.postResults();
  this.logger.summary(this.summary());
};

DrNicTest.Unit.Runner.prototype.summary = function() {
  return new DrNicTest.Template('#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors').evaluate(this.getResult());
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

/**
 * Builds app binaries for OS X, Linux, and Windows.
 */

var config = require('../config')
var cp = require('child_process')
var electronPackager = require('electron-packager')
var fs = require('fs')
var path = require('path')
var pkg = require('../package.json')
var rimraf = require('rimraf')

var BUILD_NAME = config.APP_NAME + '-v' + config.APP_VERSION

function build () {
  var platform = process.argv[2]
  var packageType = process.argv.length > 3 ? process.argv[3] : 'all'
  if (platform === 'darwin') {
    buildDarwin(printDone)
  } else if (platform === 'win32') {
    buildWin32(printDone)
  } else if (platform === 'linux') {
    buildLinux(packageType, printDone)
  } else {
    buildDarwin(function (err, buildPath) {
      printDone(err, buildPath)
      buildWin32(function (err, buildPath) {
        printDone(err, buildPath)
        buildLinux(packageType, printDone)
      })
    })
  }
}

var all = {
  // Build 64 bit binaries only.
  arch: 'x64',

  // The human-readable copyright line for the app.
  'app-copyright': config.APP_COPYRIGHT,

  // The release version of the application. Maps to the `ProductVersion` metadata
  // property on Windows, and `CFBundleShortVersionString` on OS X.
  'app-version': pkg.version,

  // Package the application's source code into an archive, using Electron's archive
  // format. Mitigates issues around long path names on Windows and slightly speeds up
  // require().
  asar: true,

  // A glob expression, that unpacks the files with matching names to the
  // "app.asar.unpacked" directory.
  'asar-unpack': 'WebTorrent*',

  // The build version of the application. Maps to the FileVersion metadata property on
  // Windows, and CFBundleVersion on OS X. We're using the short git hash (e.g. 'e7d837e')
  // Windows requires the build version to start with a number :/ so we stick on a prefix
  'build-version': '0-' + cp.execSync('git rev-parse --short HEAD').toString().replace('\n', ''),

  // The application source directory.
  dir: config.ROOT_PATH,

  // Pattern which specifies which files to ignore when copying files to create the
  // package(s).
  ignore: /^\/dist|\/(appveyor.yml|.appveyor.yml|appdmg|AUTHORS|CONTRIBUTORS|bench|benchmark|benchmark\.js|bin|bower\.json|component\.json|coverage|doc|docs|docs\.mli|dragdrop\.min\.js|example|examples|example\.html|example\.js|externs|ipaddr\.min\.js|Makefile|min|minimist|perf|rusha|simplepeer\.min\.js|simplewebsocket\.min\.js|static\/screenshot\.png|test|tests|test\.js|tests\.js|webtorrent\.min\.js|\.[^\/]*|.*\.md|.*\.markdown)$/,

  // The application name.
  name: config.APP_NAME,

  // The base directory where the finished package(s) are created.
  out: path.join(config.ROOT_PATH, 'dist'),

  // Replace an already existing output directory.
  overwrite: true,

  // Runs `npm prune --production` which remove the packages specified in
  // "devDependencies" before starting to package the app.
  prune: true,

  // The Electron version with which the app is built (without the leading 'v')
  version: pkg.dependencies['electron-prebuilt']
}

var darwin = {
  platform: 'darwin',

  // The bundle identifier to use in the application's plist (OS X only).
  'app-bundle-id': 'io.webtorrent.webtorrent',

  // The application category type, as shown in the Finder via "View" -> "Arrange by
  // Application Category" when viewing the Applications directory (OS X only).
  'app-category-type': 'public.app-category.utilities',

  // The bundle identifier to use in the application helper's plist (OS X only).
  'helper-bundle-id': 'io.webtorrent.webtorrent-helper',

  // Application icon.
  icon: config.APP_ICON + '.icns'
}

var win32 = {
  platform: 'win32',

  // Object hash of application metadata to embed into the executable (Windows only)
  'version-string': {

    // Company that produced the file.
    CompanyName: config.APP_NAME,

    // Name of the program, displayed to users
    FileDescription: config.APP_NAME,

    // Original name of the file, not including a path. This information enables an
    // application to determine whether a file has been renamed by a user. The format of
    // the name depends on the file system for which the file was created.
    OriginalFilename: 'WebTorrent.exe',

    // Name of the product with which the file is distributed.
    ProductName: config.APP_NAME,

    // Internal name of the file, if one exists, for example, a module name if the file
    // is a dynamic-link library. If the file has no internal name, this string should be
    // the original filename, without extension. This string is required.
    InternalName: config.APP_NAME
  },

  // Application icon.
  icon: config.APP_ICON + '.ico'
}

var linux = {
  platform: 'linux'

  // Note: Application icon for Linux is specified via the BrowserWindow `icon` option.
}

build()

function buildDarwin (cb) {
  var plist = require('plist')

  electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
    if (err) return cb(err)

    var appPath = path.join(buildPath[0], config.APP_NAME + '.app')
    var contentsPath = path.join(appPath, 'Contents')
    var resourcesPath = path.join(contentsPath, 'Resources')
    var infoPlistPath = path.join(contentsPath, 'Info.plist')
    var infoPlist = plist.parse(fs.readFileSync(infoPlistPath, 'utf8'))

    // TODO: Use new `extend-info` and `extra-resource` opts to electron-packager,
    // available as of v6.
    infoPlist.CFBundleDocumentTypes = [
      {
        CFBundleTypeExtensions: [ 'torrent' ],
        CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleTypeName: 'BitTorrent Document',
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSItemContentTypes: [ 'org.bittorrent.torrent' ]
      },
      {
        CFBundleTypeName: 'Any',
        CFBundleTypeOSTypes: [ '****' ],
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSTypeIsPackage: false
      }
    ]

    infoPlist.CFBundleURLTypes = [
      {
        CFBundleTypeRole: 'Editor',
        CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleURLName: 'BitTorrent Magnet URL',
        CFBundleURLSchemes: [ 'magnet' ]
      }
    ]

    fs.writeFileSync(infoPlistPath, plist.build(infoPlist))

    // Copy torrent file icon into app bundle
    cp.execSync(`cp ${config.APP_FILE_ICON + '.icns'} ${resourcesPath}`)

    if (process.platform === 'darwin') {
      var appDmg = require('appdmg')
      var sign = require('electron-osx-sign')

      /*
       * Sign the app with Apple Developer ID certificate. We sign the app for 2 reasons:
       *   - So the auto-updater (Squirrrel.Mac) can check that app updates are signed by
       *     the same author as the current version.
       *   - So users will not a see a warning about the app coming from an "Unidentified
       *     Developer" when they open it for the first time (OS X Gatekeeper).
       *
       * To sign an OS X app for distribution outside the App Store, the following are
       * required:
       *   - Xcode
       *   - Xcode Command Line Tools (xcode-select --install)
       *   - Membership in the Apple Developer Program
       */
      var signOpts = {
        app: appPath,
        platform: 'darwin',
        verbose: true
      }

      sign(signOpts, function (err) {
        if (err) return cb(err)

        // Create .zip file (used by the auto-updater)
        var zipPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.zip')
        cp.execSync(`cd ${buildPath[0]} && zip -r -y ${zipPath} ${config.APP_NAME + '.app'}`)
        console.log('Created OS X .zip file.')

        var targetPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.dmg')
        rimraf.sync(targetPath)

        // Create a .dmg (OS X disk image) file, for easy user installation.
        var dmgOpts = {
          basepath: config.ROOT_PATH,
          target: targetPath,
          specification: {
            title: config.APP_NAME,
            icon: config.APP_ICON + '.icns',
            background: path.join(config.STATIC_PATH, 'appdmg.png'),
            'icon-size': 128,
            contents: [
              { x: 122, y: 240, type: 'file', path: appPath },
              { x: 380, y: 240, type: 'link', path: '/Applications' },
              // Hide hidden icons out of view, for users who have hidden files shown.
              // https://github.com/LinusU/node-appdmg/issues/45#issuecomment-153924954
              { x: 50, y: 500, type: 'position', path: '.background' },
              { x: 100, y: 500, type: 'position', path: '.DS_Store' },
              { x: 150, y: 500, type: 'position', path: '.Trashes' },
              { x: 200, y: 500, type: 'position', path: '.VolumeIcon.icns' }
            ]
          }
        }

        var dmg = appDmg(dmgOpts)
        dmg.on('error', cb)
        dmg.on('progress', function (info) {
          if (info.type === 'step-begin') console.log(info.title + '...')
        })
        dmg.on('finish', function (info) {
          console.log('Created OS X disk image (.dmg) file.')
          cb(null, buildPath)
        })
      })
    }
  })
}

function buildWin32 (cb) {
  var installer = require('electron-winstaller')

  electronPackager(Object.assign({}, all, win32), function (err, buildPath) {
    if (err) return cb(err)

    console.log('Creating Windows installer...')
    installer.createWindowsInstaller({
      appDirectory: buildPath[0],
      authors: config.APP_TEAM,
      // certificateFile: '', // TODO
      description: config.APP_NAME,
      exe: config.APP_NAME + '.exe',
      iconUrl: config.APP_ICON + '.ico',
      loadingGif: path.join(config.STATIC_PATH, 'loading.gif'),
      name: config.APP_NAME,
      outputDirectory: path.join(config.ROOT_PATH, 'dist'),
      productName: config.APP_NAME,
      setupExe: BUILD_NAME + '.exe',
      setupIcon: config.APP_ICON + '.ico',
      title: config.APP_NAME,
      usePackageJson: false,
      version: pkg.version
    }).then(function () {
      console.log('Created Windows installer.')
      cb(null, buildPath)
    }).catch(cb)
  })
}

function buildLinux (packageType, cb) {
  electronPackager(Object.assign({}, all, linux), function (err, buildPath) {
    if (err) return cb(err)

    var distPath = path.join(config.ROOT_PATH, 'dist')
    var filesPath = buildPath[0]

    if (packageType === 'deb' || packageType === 'all') {
      // Create .deb file for debian based platforms
      var deb = require('nobin-debian-installer')()
      var destPath = path.join('/opt', pkg.name)

      deb.pack({
        package: pkg,
        info: {
          arch: 'amd64',
          targetDir: distPath,
          scripts: {
            postinst: path.join(config.STATIC_PATH, 'linux', 'postinst'),
            postrm: path.join(config.STATIC_PATH, 'linux', 'postrm')
          }
        }
      }, [{
        src: ['./**'],
        dest: destPath,
        expand: true,
        cwd: filesPath
      }], function (err, done) {
        if (err) return console.error(err.message || err)
        console.log('Created Linux .deb file.')
      })
    }

    if (packageType === 'zip' || packageType === 'all') {
      // Create .zip file for Linux
      var zipPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '-linux.zip')
      var appFolderName = path.basename(filesPath)
      cp.execSync(`cd ${distPath} && zip -r -y ${zipPath} ${appFolderName}`)
      console.log('Created Linux .zip file.')
    }
  })
}

function printDone (err, buildPath) {
  if (err) console.error(err.message || err)
  else console.log('Built ' + buildPath[0])
}
<commit_msg>Windows: don't generate .msi<commit_after>#!/usr/bin/env node

/**
 * Builds app binaries for OS X, Linux, and Windows.
 */

var config = require('../config')
var cp = require('child_process')
var electronPackager = require('electron-packager')
var fs = require('fs')
var path = require('path')
var pkg = require('../package.json')
var rimraf = require('rimraf')

var BUILD_NAME = config.APP_NAME + '-v' + config.APP_VERSION

function build () {
  var platform = process.argv[2]
  var packageType = process.argv.length > 3 ? process.argv[3] : 'all'
  if (platform === 'darwin') {
    buildDarwin(printDone)
  } else if (platform === 'win32') {
    buildWin32(printDone)
  } else if (platform === 'linux') {
    buildLinux(packageType, printDone)
  } else {
    buildDarwin(function (err, buildPath) {
      printDone(err, buildPath)
      buildWin32(function (err, buildPath) {
        printDone(err, buildPath)
        buildLinux(packageType, printDone)
      })
    })
  }
}

var all = {
  // Build 64 bit binaries only.
  arch: 'x64',

  // The human-readable copyright line for the app.
  'app-copyright': config.APP_COPYRIGHT,

  // The release version of the application. Maps to the `ProductVersion` metadata
  // property on Windows, and `CFBundleShortVersionString` on OS X.
  'app-version': pkg.version,

  // Package the application's source code into an archive, using Electron's archive
  // format. Mitigates issues around long path names on Windows and slightly speeds up
  // require().
  asar: true,

  // A glob expression, that unpacks the files with matching names to the
  // "app.asar.unpacked" directory.
  'asar-unpack': 'WebTorrent*',

  // The build version of the application. Maps to the FileVersion metadata property on
  // Windows, and CFBundleVersion on OS X. We're using the short git hash (e.g. 'e7d837e')
  // Windows requires the build version to start with a number :/ so we stick on a prefix
  'build-version': '0-' + cp.execSync('git rev-parse --short HEAD').toString().replace('\n', ''),

  // The application source directory.
  dir: config.ROOT_PATH,

  // Pattern which specifies which files to ignore when copying files to create the
  // package(s).
  ignore: /^\/dist|\/(appveyor.yml|.appveyor.yml|appdmg|AUTHORS|CONTRIBUTORS|bench|benchmark|benchmark\.js|bin|bower\.json|component\.json|coverage|doc|docs|docs\.mli|dragdrop\.min\.js|example|examples|example\.html|example\.js|externs|ipaddr\.min\.js|Makefile|min|minimist|perf|rusha|simplepeer\.min\.js|simplewebsocket\.min\.js|static\/screenshot\.png|test|tests|test\.js|tests\.js|webtorrent\.min\.js|\.[^\/]*|.*\.md|.*\.markdown)$/,

  // The application name.
  name: config.APP_NAME,

  // The base directory where the finished package(s) are created.
  out: path.join(config.ROOT_PATH, 'dist'),

  // Replace an already existing output directory.
  overwrite: true,

  // Runs `npm prune --production` which remove the packages specified in
  // "devDependencies" before starting to package the app.
  prune: true,

  // The Electron version with which the app is built (without the leading 'v')
  version: pkg.dependencies['electron-prebuilt']
}

var darwin = {
  platform: 'darwin',

  // The bundle identifier to use in the application's plist (OS X only).
  'app-bundle-id': 'io.webtorrent.webtorrent',

  // The application category type, as shown in the Finder via "View" -> "Arrange by
  // Application Category" when viewing the Applications directory (OS X only).
  'app-category-type': 'public.app-category.utilities',

  // The bundle identifier to use in the application helper's plist (OS X only).
  'helper-bundle-id': 'io.webtorrent.webtorrent-helper',

  // Application icon.
  icon: config.APP_ICON + '.icns'
}

var win32 = {
  platform: 'win32',

  // Object hash of application metadata to embed into the executable (Windows only)
  'version-string': {

    // Company that produced the file.
    CompanyName: config.APP_NAME,

    // Name of the program, displayed to users
    FileDescription: config.APP_NAME,

    // Original name of the file, not including a path. This information enables an
    // application to determine whether a file has been renamed by a user. The format of
    // the name depends on the file system for which the file was created.
    OriginalFilename: 'WebTorrent.exe',

    // Name of the product with which the file is distributed.
    ProductName: config.APP_NAME,

    // Internal name of the file, if one exists, for example, a module name if the file
    // is a dynamic-link library. If the file has no internal name, this string should be
    // the original filename, without extension. This string is required.
    InternalName: config.APP_NAME
  },

  // Application icon.
  icon: config.APP_ICON + '.ico'
}

var linux = {
  platform: 'linux'

  // Note: Application icon for Linux is specified via the BrowserWindow `icon` option.
}

build()

function buildDarwin (cb) {
  var plist = require('plist')

  electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
    if (err) return cb(err)

    var appPath = path.join(buildPath[0], config.APP_NAME + '.app')
    var contentsPath = path.join(appPath, 'Contents')
    var resourcesPath = path.join(contentsPath, 'Resources')
    var infoPlistPath = path.join(contentsPath, 'Info.plist')
    var infoPlist = plist.parse(fs.readFileSync(infoPlistPath, 'utf8'))

    // TODO: Use new `extend-info` and `extra-resource` opts to electron-packager,
    // available as of v6.
    infoPlist.CFBundleDocumentTypes = [
      {
        CFBundleTypeExtensions: [ 'torrent' ],
        CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleTypeName: 'BitTorrent Document',
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSItemContentTypes: [ 'org.bittorrent.torrent' ]
      },
      {
        CFBundleTypeName: 'Any',
        CFBundleTypeOSTypes: [ '****' ],
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSTypeIsPackage: false
      }
    ]

    infoPlist.CFBundleURLTypes = [
      {
        CFBundleTypeRole: 'Editor',
        CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleURLName: 'BitTorrent Magnet URL',
        CFBundleURLSchemes: [ 'magnet' ]
      }
    ]

    fs.writeFileSync(infoPlistPath, plist.build(infoPlist))

    // Copy torrent file icon into app bundle
    cp.execSync(`cp ${config.APP_FILE_ICON + '.icns'} ${resourcesPath}`)

    if (process.platform === 'darwin') {
      var appDmg = require('appdmg')
      var sign = require('electron-osx-sign')

      /*
       * Sign the app with Apple Developer ID certificate. We sign the app for 2 reasons:
       *   - So the auto-updater (Squirrrel.Mac) can check that app updates are signed by
       *     the same author as the current version.
       *   - So users will not a see a warning about the app coming from an "Unidentified
       *     Developer" when they open it for the first time (OS X Gatekeeper).
       *
       * To sign an OS X app for distribution outside the App Store, the following are
       * required:
       *   - Xcode
       *   - Xcode Command Line Tools (xcode-select --install)
       *   - Membership in the Apple Developer Program
       */
      var signOpts = {
        app: appPath,
        platform: 'darwin',
        verbose: true
      }

      sign(signOpts, function (err) {
        if (err) return cb(err)

        // Create .zip file (used by the auto-updater)
        var zipPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.zip')
        cp.execSync(`cd ${buildPath[0]} && zip -r -y ${zipPath} ${config.APP_NAME + '.app'}`)
        console.log('Created OS X .zip file.')

        var targetPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.dmg')
        rimraf.sync(targetPath)

        // Create a .dmg (OS X disk image) file, for easy user installation.
        var dmgOpts = {
          basepath: config.ROOT_PATH,
          target: targetPath,
          specification: {
            title: config.APP_NAME,
            icon: config.APP_ICON + '.icns',
            background: path.join(config.STATIC_PATH, 'appdmg.png'),
            'icon-size': 128,
            contents: [
              { x: 122, y: 240, type: 'file', path: appPath },
              { x: 380, y: 240, type: 'link', path: '/Applications' },
              // Hide hidden icons out of view, for users who have hidden files shown.
              // https://github.com/LinusU/node-appdmg/issues/45#issuecomment-153924954
              { x: 50, y: 500, type: 'position', path: '.background' },
              { x: 100, y: 500, type: 'position', path: '.DS_Store' },
              { x: 150, y: 500, type: 'position', path: '.Trashes' },
              { x: 200, y: 500, type: 'position', path: '.VolumeIcon.icns' }
            ]
          }
        }

        var dmg = appDmg(dmgOpts)
        dmg.on('error', cb)
        dmg.on('progress', function (info) {
          if (info.type === 'step-begin') console.log(info.title + '...')
        })
        dmg.on('finish', function (info) {
          console.log('Created OS X disk image (.dmg) file.')
          cb(null, buildPath)
        })
      })
    }
  })
}

function buildWin32 (cb) {
  var installer = require('electron-winstaller')

  electronPackager(Object.assign({}, all, win32), function (err, buildPath) {
    if (err) return cb(err)

    console.log('Creating Windows installer...')
    installer.createWindowsInstaller({
      appDirectory: buildPath[0],
      authors: config.APP_TEAM,
      // certificateFile: '', // TODO
      description: config.APP_NAME,
      exe: config.APP_NAME + '.exe',
      iconUrl: config.APP_ICON + '.ico',
      loadingGif: path.join(config.STATIC_PATH, 'loading.gif'),
      name: config.APP_NAME,
      noMsi: true,
      outputDirectory: path.join(config.ROOT_PATH, 'dist'),
      productName: config.APP_NAME,
      setupExe: BUILD_NAME + '.exe',
      setupIcon: config.APP_ICON + '.ico',
      title: config.APP_NAME,
      usePackageJson: false,
      version: pkg.version
    }).then(function () {
      console.log('Created Windows installer.')
      cb(null, buildPath)
    }).catch(cb)
  })
}

function buildLinux (packageType, cb) {
  electronPackager(Object.assign({}, all, linux), function (err, buildPath) {
    if (err) return cb(err)

    var distPath = path.join(config.ROOT_PATH, 'dist')
    var filesPath = buildPath[0]

    if (packageType === 'deb' || packageType === 'all') {
      // Create .deb file for debian based platforms
      var deb = require('nobin-debian-installer')()
      var destPath = path.join('/opt', pkg.name)

      deb.pack({
        package: pkg,
        info: {
          arch: 'amd64',
          targetDir: distPath,
          scripts: {
            postinst: path.join(config.STATIC_PATH, 'linux', 'postinst'),
            postrm: path.join(config.STATIC_PATH, 'linux', 'postrm')
          }
        }
      }, [{
        src: ['./**'],
        dest: destPath,
        expand: true,
        cwd: filesPath
      }], function (err, done) {
        if (err) return console.error(err.message || err)
        console.log('Created Linux .deb file.')
      })
    }

    if (packageType === 'zip' || packageType === 'all') {
      // Create .zip file for Linux
      var zipPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '-linux.zip')
      var appFolderName = path.basename(filesPath)
      cp.execSync(`cd ${distPath} && zip -r -y ${zipPath} ${appFolderName}`)
      console.log('Created Linux .zip file.')
    }
  })
}

function printDone (err, buildPath) {
  if (err) console.error(err.message || err)
  else console.log('Built ' + buildPath[0])
}
<|endoftext|>


<commit_before>angular.module('citizen-engagement').controller('MapCtrl', function(IssueService, $http, apiUrl, mapboxSecret, geolocation, $log, $scope, $state, leafletData) {
  var mapCtrl = this;

  //geolocation: get position of the user
  geolocation.getLocation().then(function(data){
    mapCtrl.center.lat = data.coords.latitude;
    mapCtrl.center.lng = data.coords.longitude;
  }).catch(function(err) {
    $log.error('Could not get location because: ' + err.message);
  });

  //map
  var mapboxMapId = 'mapbox.satellite';  // Use your favorite tileset here
  // Build the tile layer URL
  var mapboxTileLayerUrl = 'http://api.tiles.mapbox.com/v4/' + mapboxMapId;
  mapboxTileLayerUrl = mapboxTileLayerUrl + '/{z}/{x}/{y}.png';
  mapboxTileLayerUrl = mapboxTileLayerUrl + '?access_token=' + mapboxSecret;

  mapCtrl.defaults = {
      tileLayer: mapboxTileLayerUrl
    };
  mapCtrl.markers = [];
  mapCtrl.center = {
    lat: 51.48,
    lng: 0,
    zoom: 13
  };

  IssueService.getIssues().then(function(issues) {
    console.log(issues);
    //issueCtrl.issues = issues;
    createMarkers(issues);
  })

  //get all issues from user's location
  /*
  $http({
  method: 'GET', //post
  url: apiUrl + '/issues',
  params: {pageSize: 50}
}).then(function(result) {
//console.log(result);
createMarkers(result.data);
//console.log(mapCtrl.locations);
});

*/

leafletData.getMap().then(function(map) {
  map.on('click', function(e) {
    console.log("Latitude : " + e.latlng.lat + " Longitude :  "+ e.latlng.lng);
  });
});

  function createMarkers (issues) {
    console.log(issues);
    for(var i=0; i<issues.length; i++){
      mapCtrl.markers.push({
        lat: issues[i].location.coordinates[1],
        lng: issues[i].location.coordinates[0],
        issue: issues[i]
      });
    }
  }

  $scope.$on('leafletDirectiveMap.dragend', function(event, map){
    $http({
      method: 'POST',
      url: apiUrl + '/issues/searches',
      data: {
        "location": {
          "$geoWithin": {
            "$centerSphere" : [
              [ 6.622009 , 46.766129 ],
              0.1
            ]
          }
        }
      }
    }).then(function(result) {
      //console.log(result);
      createMarkers(result.data);
      console.log(mapCtrl.locations);
    });
  });

  //Redirect to issueDetails
  $scope.$on('leafletDirectiveMarker.click', function(event, marker) {
    console.log(marker.model.issue);
    $state.go('tab.issueDetailsMap', {issueId: marker.model.issue.id});
  });

});
<commit_msg>center the map on load event<commit_after>angular.module('citizen-engagement').controller('MapCtrl', function(IssueService, $http, apiUrl, mapboxSecret, geolocation, $log, $scope, $state, leafletData) {
  var mapCtrl = this;

  //geolocation: get position of the user
  geolocation.getLocation().then(function(data){
    mapCtrl.center.lat = data.coords.latitude;
    mapCtrl.center.lng = data.coords.longitude;
  }).catch(function(err) {
    $log.error('Could not get location because: ' + err.message);
  });

  //map
  var mapboxMapId = 'mapbox.satellite';  // Use your favorite tileset here
  // Build the tile layer URL
  var mapboxTileLayerUrl = 'http://api.tiles.mapbox.com/v4/' + mapboxMapId;
  mapboxTileLayerUrl = mapboxTileLayerUrl + '/{z}/{x}/{y}.png';
  mapboxTileLayerUrl = mapboxTileLayerUrl + '?access_token=' + mapboxSecret;

  mapCtrl.defaults = {
      tileLayer: mapboxTileLayerUrl
    };
  mapCtrl.markers = [];
  mapCtrl.center = {
    lat: 51.48,
    lng: 0,
    zoom: 15
  };

  IssueService.getIssues().then(function(issues) {
    console.log(issues);
    //issueCtrl.issues = issues;
    createMarkers(issues);
  })

leafletData.getMap().then(function(map) {
  map.on('load', function(e) {
    console.log('woplaaaaaaa');
    mapCtrl.center = {
      lat: e.latlng.lat,
      lng: e.latlng.lng,
      zoom: 15
    };
  });
});

  function createMarkers (issues) {
    console.log(issues);
    for(var i=0; i<issues.length; i++){
      mapCtrl.markers.push({
        lat: issues[i].location.coordinates[1],
        lng: issues[i].location.coordinates[0],
        issue: issues[i]
      });
    }
  }

  $scope.$on('leafletDirectiveMap.dragend', function(event, map){
    $http({
      method: 'POST',
      url: apiUrl + '/issues/searches',
      data: {
        "location": {
          "$geoWithin": {
            "$centerSphere" : [
              [ 6.622009 , 46.766129 ],
              0.1
            ]
          }
        }
      }
    }).then(function(result) {
      //console.log(result);
      createMarkers(result.data);
      console.log(mapCtrl.locations);
    });
  });

  //Redirect to issueDetails
  $scope.$on('leafletDirectiveMarker.click', function(event, marker) {
    console.log(marker.model.issue);
    $state.go('tab.issueDetailsMap', {issueId: marker.model.issue.id});
  });

});
<|endoftext|>


<commit_before>#!/usr/bin/env node
/*
** r2frida main commandline program
** --pancake 2015
*/

var spawnSync = require('child_process').spawnSync;
var colors = require ('colors');
var fs = require ('fs');

/* actions */

const helpmsg = 'Usage: r2frida [-h|-v] [-f adb|ip] [-n|-s] [-l|-L|procname|pid]';

const Option = {
  showLongHelp: function() {
    die ([helpmsg,
    ' -l            list processes',
    ' -L            list applications',
    ' -f [adb|ip]   forward port to frida-server',
    ' -v            show version information',
    ' -n            batch mode no prompt',
    ' -s            enter the r2node shell'].join('\n'));
  },
  showHelp: function() {
    die (helpmsg, 0);
  },
  showVersion: function() {
    const package_json = '' + fs.readFileSync('../package.json');
    const version = JSON.parse (package_json).version;
    die (version, 0);
  },
  enterShell: function(target) {
    target && exec (process.execPath, ['main.js', target]);
    die ('Missing target', 1);
  },
  enterBatchShell: function(target) {
    target && exec (process.execPath, ['main.js', '-n', target]);
    die ('Missing target', 1);
  },
  forwardPort: function(target) {
    target || die ('Missing target', 1);
    if (target == 'adb') {
      exec ('adb', ['forward', 'tcp:27042', 'tcp:27042']);
    } else {
      exec ('ssh', ['-L', '27042:localhost:27042', 'root@'+target]);
    }
    exec ('r2', ['r2pipe://node r2io-frida.js ' + target]);
  },
  startR2: function(target) {
    exec ('r2', ['r2pipe://node r2io-frida.js ' + target]);
  },
  listProcesses: function() {
    var frida = require ('frida');
    frida.getRemoteDevice().then(function(device) {
      device.enumerateProcesses().then (function(procs) {
        for (var i in procs.reverse()) {
          var p = procs[i];
          console.log(p.pid + '\t' + p.name);
        }
      })
    });
  },
  listApplications: function() {
    var frida = require ('frida');
    frida.getRemoteDevice().then(function(device) {
      device.enumerateApplications().then (function(procs) {
        for (var i in procs.reverse()) {
          var p = procs[i];
          console.log(p.pid + '\t' + p.name);
        }
      })
    });
  }
}

/* main */

Main (process.argv.slice(2), {
  '-h': Option.showLongHelp,
  '-v': Option.showVersion,
  '-s': Option.enterShell,
  '-n': Option.enterBatchShell,
  '-f': Option.forwardPort,
  '-l': Option.listProcesses,
  '-L': Option.listApplications
});

function Main(argv, options) {
  var target = undefined;
  process.chdir (__dirname + '/../src');
  for (var i in argv) {
    var opt = options [argv[+i]];
    if (opt) {
      return opt (argv[+i + 1]);
    }
    if (target) {
      die ("Invalid parameter: '" + argv[+i] + "'", 1);
    }
    target = argv[+i];
  }
  target && Option.startR2(target);
  Option.showHelp ();
}

/* utils */

function die(msg, ret) {
  var println = ret ? console.error : console.log;
  var color = ret ? colors.red : colors.yellow;
  println (color (msg));
  process.exit (ret);
}

function exec(cmd, args) {
  var res = spawnSync (cmd, args, {
    stdio: [0, 1, 2]
  });
  process.exit (res.status);
}
<commit_msg>Fix r2frida -L appname/appid<commit_after>#!/usr/bin/env node
/*
** r2frida main commandline program
** --pancake 2015
*/

var spawnSync = require('child_process').spawnSync;
var colors = require ('colors');
var fs = require ('fs');

/* actions */

const helpmsg = 'Usage: r2frida [-h|-v] [-f adb|ip] [-n|-s] [-l|-L|procname|pid]';

function alignColumn(arr, col) {
  var str = arr[0];
  for (var i = 1; i<arr.length ; i++) {
    var word = ''+ (arr[i-1] || '');
    var curlen = word.length;
    var curcol = col * i + curlen;
    var curnex = col * (i+1) ;
    var left = curnex>curcol? curnex - curcol: 1;
    str += new Array(left).join(' ');
    str += arr[i];
  }
  return str;
}

const Option = {
  showLongHelp: function() {
    die ([helpmsg,
    ' -l            list processes',
    ' -L            list applications',
    ' -f [adb|ip]   forward port to frida-server',
    ' -v            show version information',
    ' -n            batch mode no prompt',
    ' -s            enter the r2node shell'].join('\n'));
  },
  showHelp: function() {
    die (helpmsg, 0);
  },
  showVersion: function() {
    const package_json = '' + fs.readFileSync('../package.json');
    const version = JSON.parse (package_json).version;
    die (version, 0);
  },
  enterShell: function(target) {
    target && exec (process.execPath, ['main.js', target]);
    die ('Missing target', 1);
  },
  enterBatchShell: function(target) {
    target && exec (process.execPath, ['main.js', '-n', target]);
    die ('Missing target', 1);
  },
  forwardPort: function(target) {
    target || die ('Missing target', 1);
    if (target == 'adb') {
      exec ('adb', ['forward', 'tcp:27042', 'tcp:27042']);
    } else {
      exec ('ssh', ['-L', '27042:localhost:27042', 'root@'+target]);
    }
    exec ('r2', ['r2pipe://node r2io-frida.js ' + target]);
  },
  startR2: function(target) {
    exec ('r2', ['r2pipe://node r2io-frida.js ' + target]);
  },
  listProcesses: function() {
    var frida = require ('frida');
    frida.getRemoteDevice().then(function(device) {
      device.enumerateProcesses().then (function(procs) {
        for (var i in procs.reverse()) {
          var p = procs[i];
          console.log(alignColumn ([p.pid, p.name], 16));
        }
      })
    });
  },
  listApplications: function() {
    var frida = require ('frida');
    frida.getRemoteDevice().then(function(device) {
      device.enumerateApplications().then (function(procs) {
        for (var i in procs.reverse()) {
          var p = procs[i];
          console.log(alignColumn([p.name,p.identifier], 16));
        }
      })
    });
  }
}

/* main */

Main (process.argv.slice(2), {
  '-h': Option.showLongHelp,
  '-v': Option.showVersion,
  '-s': Option.enterShell,
  '-n': Option.enterBatchShell,
  '-f': Option.forwardPort,
  '-l': Option.listProcesses,
  '-L': Option.listApplications
});

function Main(argv, options) {
  var target = undefined;
  process.chdir (__dirname + '/../src');
  for (var i in argv) {
    var opt = options [argv[+i]];
    if (opt) {
      return opt (argv[+i + 1]);
    }
    if (target) {
      die ("Invalid parameter: '" + argv[+i] + "'", 1);
    }
    target = argv[+i];
  }
  target && Option.startR2(target);
  Option.showHelp ();
}

/* utils */

function die(msg, ret) {
  var println = ret ? console.error : console.log;
  var color = ret ? colors.red : colors.yellow;
  println (color (msg));
  process.exit (ret);
}

function exec(cmd, args) {
  var res = spawnSync (cmd, args, {
    stdio: [0, 1, 2]
  });
  process.exit (res.status);
}
<|endoftext|>


<commit_before>$( document ).ready(function () {
  var socket = null;
  var ui = {
    moveLeft: $('#left[name="move"]'),
    moveForward: $('#forward[name="move"]'),
    moveReverse: $('#reverse[name="move"]'),
    moveRight: $('#right[name="move"]'),

    cameraLeft: $('#left[name="camera"]'),
    cameraUp: $('#up[name="camera"]'),
    cameraCenter: $('#center[name="camera"]'),
    cameraDown: $('#down[name="camera"]'),
    cameraRight: $('#right[name="camera"]'),

    allButtons: $('.button'),

    containerStream: $('#container-stream')
  };
  var activeClass = 'is-active';
  var isPressed = false;
  //var streamUrl = "http://" + document.location.hostname + "/?action=stream";
  var streamUrl = "http://192.168.1.51:9000/?action=stream";

  /* Initialise socket.io */
  try {
    socket = io.connect();
  } catch (e) {
    socket = null;
  }

  function socketSend(action) {
    if (socket && action) {
      socket.emit(action);
    }
  }

  function socketSendData(action, data) {
    if (socket && action) {
      socket.emit(action, data);
    }
  }

  function botMove(action) {
    switch(action){
      case 'forward':
        socketSendData('move', 'forward');
        ui.moveForward.addClass(activeClass);
        break;
      case 'reverse':
        socketSendData('move', 'reverse');
        ui.moveReverse.addClass(activeClass);
        break;
      case 'left':
        socketSendData('move', 'left');
        ui.moveLeft.addClass(activeClass);
        break;
      case 'right':
        socketSendData('move', 'right');
        ui.moveRight.addClass(activeClass);
        break;
    }
  }

  function cameraMove(action) {
    switch(action){
      case 'left':
        socketSendData('camera', 'left');
        ui.cameraLeft.addClass(activeClass);
        break;
      case 'up':
        socketSendData('camera', 'up');
        ui.cameraUp.addClass(activeClass);
        break;
      case 'center':
        socketSendData('camera', 'center');
        ui.cameraCenter.addClass(activeClass);
        break;
      case 'down':
        socketSendData('camera', 'down');
        ui.cameraDown.addClass(activeClass);
        break;
      case 'right':
        socketSendData('camera', 'right');
        ui.cameraRight.addClass(activeClass);
        break;
    }
  }

  //  Listener for key presses
  $(document).keydown(function(e){
    if(isPressed) return;

    isPressed = true;
    switch(e.which){
      /* Bot moves */
      case 65: // A
        botMove('left');
        break;
      case 87:  // W
        botMove('forward');
        break;
      case 83:  // S
        botMove('reverse');
        break;
      case 68: // D
        botMove('right');
        break;

      /* Camera orientation */
      case 52: case 100: // 4
        cameraMove('left');
        break;
      case 56: case 104: // 8
        cameraMove('up');
        break;
      case 53: case 101: // 5
        cameraMove('center');
        break;
      case 50: case 98: // 2
        cameraMove('down');
        break;
      case 54: case 102: // 6
        cameraMove('right');
        break;
    }
  });

  $(document).keyup(function(e){
    ui.allButtons.removeClass(activeClass);
    socketSend('stop');
    isPressed = false;
  });

  $('.button').on("mousedown vmousedown", function(e) {
    if(isPressed) return;

    isPressed = true;
    var target = e.target;

    if (target && $(target).attr('name') && $(target).attr('id')) {
      var name = $(target).attr('name');
      var id = $(target).attr('id');

      if (name === 'move') {
        botMove(id);
      } else if (name === 'camera') {
        cameraMove(id);
      }
    }
  });

  $('.button').on("mouseup vmouseup", function() {
    ui.allButtons.removeClass(activeClass);
    socketSend('stop');
    isPressed = false;
  });

  setTimeout(function(){
    ui.containerStream.html('');
    $('#stream').error(function() {
      ui.containerStream.html('

Sreaming error.

');
    });
  }, 2000);
});
<commit_msg>Fixed stream path in<commit_after>$( document ).ready(function () {
  var socket = null;
  var ui = {
    moveLeft: $('#left[name="move"]'),
    moveForward: $('#forward[name="move"]'),
    moveReverse: $('#reverse[name="move"]'),
    moveRight: $('#right[name="move"]'),

    cameraLeft: $('#left[name="camera"]'),
    cameraUp: $('#up[name="camera"]'),
    cameraCenter: $('#center[name="camera"]'),
    cameraDown: $('#down[name="camera"]'),
    cameraRight: $('#right[name="camera"]'),

    allButtons: $('.button'),

    containerStream: $('#container-stream')
  };
  var activeClass = 'is-active';
  var isPressed = false;
  var streamUrl = "http://" + document.location.hostname + "/?action=stream";
  //var streamUrl = "http://192.168.1.51:9000/?action=stream";

  /* Initialise socket.io */
  try {
    socket = io.connect();
  } catch (e) {
    socket = null;
  }

  function socketSend(action) {
    if (socket && action) {
      socket.emit(action);
    }
  }

  function socketSendData(action, data) {
    if (socket && action) {
      socket.emit(action, data);
    }
  }

  function botMove(action) {
    switch(action){
      case 'forward':
        socketSendData('move', 'forward');
        ui.moveForward.addClass(activeClass);
        break;
      case 'reverse':
        socketSendData('move', 'reverse');
        ui.moveReverse.addClass(activeClass);
        break;
      case 'left':
        socketSendData('move', 'left');
        ui.moveLeft.addClass(activeClass);
        break;
      case 'right':
        socketSendData('move', 'right');
        ui.moveRight.addClass(activeClass);
        break;
    }
  }

  function cameraMove(action) {
    switch(action){
      case 'left':
        socketSendData('camera', 'left');
        ui.cameraLeft.addClass(activeClass);
        break;
      case 'up':
        socketSendData('camera', 'up');
        ui.cameraUp.addClass(activeClass);
        break;
      case 'center':
        socketSendData('camera', 'center');
        ui.cameraCenter.addClass(activeClass);
        break;
      case 'down':
        socketSendData('camera', 'down');
        ui.cameraDown.addClass(activeClass);
        break;
      case 'right':
        socketSendData('camera', 'right');
        ui.cameraRight.addClass(activeClass);
        break;
    }
  }

  //  Listener for key presses
  $(document).keydown(function(e){
    if(isPressed) return;

    isPressed = true;
    switch(e.which){
      /* Bot moves */
      case 65: // A
        botMove('left');
        break;
      case 87:  // W
        botMove('forward');
        break;
      case 83:  // S
        botMove('reverse');
        break;
      case 68: // D
        botMove('right');
        break;

      /* Camera orientation */
      case 52: case 100: // 4
        cameraMove('left');
        break;
      case 56: case 104: // 8
        cameraMove('up');
        break;
      case 53: case 101: // 5
        cameraMove('center');
        break;
      case 50: case 98: // 2
        cameraMove('down');
        break;
      case 54: case 102: // 6
        cameraMove('right');
        break;
    }
  });

  $(document).keyup(function(e){
    ui.allButtons.removeClass(activeClass);
    socketSend('stop');
    isPressed = false;
  });

  $('.button').on("mousedown vmousedown", function(e) {
    if(isPressed) return;

    isPressed = true;
    var target = e.target;

    if (target && $(target).attr('name') && $(target).attr('id')) {
      var name = $(target).attr('name');
      var id = $(target).attr('id');

      if (name === 'move') {
        botMove(id);
      } else if (name === 'camera') {
        cameraMove(id);
      }
    }
  });

  $('.button').on("mouseup vmouseup", function() {
    ui.allButtons.removeClass(activeClass);
    socketSend('stop');
    isPressed = false;
  });

  setTimeout(function(){
    ui.containerStream.html('');
    $('#stream').error(function() {
      ui.containerStream.html('

Sreaming error.

');
    });
  }, 2000);
});
<|endoftext|>