<commit_before>/**
 * Copyright 2014 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function(RED) {
    "use strict";
    var fs = require('fs');
    var minimatch = require("minimatch");

    function AmazonS3InNode(n) {
        RED.nodes.createNode(this,n);
        this.awsConfig = RED.nodes.getNode(n.aws);
        this.region = n.region;
        this.bucket = n.bucket;
        this.filepattern = n.filepattern || "";
        var node = this;
        var AWS = this.awsConfig ? this.awsConfig.AWS : null;
        if (!AWS) {
            node.warn("Missing AWS credentials");
            return;
        }
        var s3 = new AWS.S3();
        node.status({fill:"blue",shape:"dot",text:"initializing"});
        s3.listObjects({ Bucket: node.bucket }, function(err, data) {
            if (err) {
                node.error("failed to fetch S3 state: " + err);
                node.status({fill:"red",shape:"ring",text:"error"});
                return;
            }
            node.state = data.Contents.filter(function (e) {
                return !node.filepattern || minimatch(e, node.filepattern);
            }).map(function (e) {
                return e.Key;
            });
            node.status({});
            node.on("input", function(msg) {
                node.status({fill:"blue",shape:"dot",text:"checking for changes"});
                s3.listObjects({ Bucket: node.bucket }, function(err, data) {
                    if (err) {
                        node.warn("failed to fetch S3 state: " + err);
                        node.status({});
                        return;
                    }
                    node.status({});
                    var newState = data.Contents.filter(function (e) {
                        return !node.filepattern ||
                            minimatch(e, node.filepattern);
                    }).map(function (e) {
                        return e.Key;
                    });
                    var seen = {};
                    var i;
                    for (i = 0; i < node.state.length; i++) {
                        seen[node.state[i]] = true;
                    }
                    for (i = 0; i < newState.length; i++) {
                        if (seen[newState[i]]) {
                            delete seen[newState[i]];
                        } else {
                            msg.payload = newState[i];
                            msg.file = newState[i].substring(newState[i].lastIndexOf('/') + 1);
                            msg.event = 'add';
                            node.send(msg);
                        }
                    }
                    for (var k in seen) {
                        if (seen.hasOwnProperty(k)) {
                            msg.payload = k;
                            msg.file = k.substring(k.lastIndexOf('/') + 1);
                            msg.event = 'delete';
                            node.send(msg);
                        }
                    }
                    node.state = newState;
                });
            });
            var interval = setInterval(function() {
                node.emit("input", {});
            }, 900000); // 15 minutes
            node.on("close", function() {
                if (interval !== null) {
                    clearInterval(interval);
                }
            });
        });
    }
    RED.nodes.registerType("amazon s3 in", AmazonS3InNode);

    function AmazonS3QueryNode(n) {
        RED.nodes.createNode(this,n);
        this.awsConfig = RED.nodes.getNode(n.aws);
        this.region = n.region;
        this.bucket = n.bucket;
        this.filename = n.filename || "";
        var node = this;
        var AWS = this.awsConfig ? this.awsConfig.AWS : null;
        if (!AWS) {
            node.warn("Missing AWS credentials");
            return;
        }
        var s3 = new AWS.S3();
        node.on("input", function(msg) {
            var bucket = node.bucket || msg.bucket;
            if (bucket === "") {
                node.warn("No bucket specified");
                return;
            }
            var filename = node.filename || msg.filename;
            if (filename === "") {
                node.warn("No filename specified");
                return;
            }
            msg.bucket = bucket;
            msg.filename = filename;
            node.status({fill:"blue",shape:"dot",text:"downloading"});
            s3.getObject({
                Bucket: bucket,
                Key: filename,
            }, function(err, data) {
                if (err) {
                    node.warn("download failed " + err.toString());
                    delete msg.payload;
                    msg.error = err;
                } else {
                    msg.payload = data.Body;
                    delete msg.error;
                }
                node.status({});
                node.send(msg);
            });
        });
    }
    RED.nodes.registerType("amazon s3", AmazonS3QueryNode);

    function AmazonS3OutNode(n) {
        RED.nodes.createNode(this,n);
        this.awsConfig = RED.nodes.getNode(n.aws);
        this.region = n.region;
        this.bucket = n.bucket;
        this.filename = n.filename || "";
        this.localFilename = n.localFilename || "";
        var node = this;
        var AWS = this.awsConfig ? this.awsConfig.AWS : null;
        if (!AWS) {
            node.warn("Missing AWS credentials");
            return;
        }
        if (AWS) {
            var s3 = new AWS.S3();
            node.status({fill:"blue",shape:"dot",text:"checking credentials"});
            s3.listObjects({ Bucket: node.bucket }, function(err) {
                if (err) {
                    node.error("AWS S3 error: " + err);
                    node.status({fill:"red",shape:"ring",text:"error"});
                    return;
                }
                node.status({});
                node.on("input", function(msg) {
                    var bucket = node.bucket || msg.bucket;
                    if (bucket === "") {
                        node.warn("No bucket specified");
                        return;
                    }
                    var filename = node.filename || msg.filename;
                    if (filename === "") {
                        node.warn("No filename specified");
                        return;
                    }
                    var localFilename = node.localFilename || msg.localFilename;
                    if (localFilename) {
                        // TODO: use chunked upload for large files
                        node.status({fill:"blue",shape:"dot",text:"uploading"});
                        var stream = fs.createReadStream(localFilename);
                        s3.putObject({
                            Bucket: bucket,
                            Body: stream,
                            Key: filename,
                        }, function(err) {
                            if (err) {
                                node.error(err.toString());
                                node.status({fill:"red",shape:"ring",text:"failed"});
                                return;
                            }
                            node.status({});
                        });
                    } else if (typeof msg.payload !== "undefined") {
                        node.status({fill:"blue",shape:"dot",text:"uploading"});
                        s3.putObject({
                            Bucket: bucket,
                            Body: RED.util.ensureBuffer(msg.payload),
                            Key: filename,
                        }, function(err) {
                            if (err) {
                                node.error(err.toString());
                                node.status({fill:"red",shape:"ring",text:"failed"});
                                return;
                            }
                            node.status({});
                        });
                    }
                });
            });
        }
    }
    RED.nodes.registerType("amazon s3 out",AmazonS3OutNode);
};
<commit_msg>Add bucket name to watch node messages for consistency with other s3 nodes.<commit_after>/**
 * Copyright 2014 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function(RED) {
    "use strict";
    var fs = require('fs');
    var minimatch = require("minimatch");

    function AmazonS3InNode(n) {
        RED.nodes.createNode(this,n);
        this.awsConfig = RED.nodes.getNode(n.aws);
        this.region = n.region;
        this.bucket = n.bucket;
        this.filepattern = n.filepattern || "";
        var node = this;
        var AWS = this.awsConfig ? this.awsConfig.AWS : null;
        if (!AWS) {
            node.warn("Missing AWS credentials");
            return;
        }
        var s3 = new AWS.S3();
        node.status({fill:"blue",shape:"dot",text:"initializing"});
        s3.listObjects({ Bucket: node.bucket }, function(err, data) {
            if (err) {
                node.error("failed to fetch S3 state: " + err);
                node.status({fill:"red",shape:"ring",text:"error"});
                return;
            }
            node.state = data.Contents.filter(function (e) {
                return !node.filepattern || minimatch(e, node.filepattern);
            }).map(function (e) {
                return e.Key;
            });
            node.status({});
            node.on("input", function(msg) {
                node.status({fill:"blue",shape:"dot",text:"checking for changes"});
                s3.listObjects({ Bucket: node.bucket }, function(err, data) {
                    if (err) {
                        node.warn("failed to fetch S3 state: " + err);
                        node.status({});
                        return;
                    }
                    node.status({});
                    var newState = data.Contents.filter(function (e) {
                        return !node.filepattern ||
                            minimatch(e, node.filepattern);
                    }).map(function (e) {
                        return e.Key;
                    });
                    var seen = {};
                    var i;
                    msg.bucket = node.bucket;
                    for (i = 0; i < node.state.length; i++) {
                        seen[node.state[i]] = true;
                    }
                    for (i = 0; i < newState.length; i++) {
                        if (seen[newState[i]]) {
                            delete seen[newState[i]];
                        } else {
                            msg.payload = newState[i];
                            msg.file = newState[i].substring(newState[i].lastIndexOf('/') + 1);
                            msg.event = 'add';
                            node.send(msg);
                        }
                    }
                    for (var k in seen) {
                        if (seen.hasOwnProperty(k)) {
                            msg.payload = k;
                            msg.file = k.substring(k.lastIndexOf('/') + 1);
                            msg.event = 'delete';
                            node.send(msg);
                        }
                    }
                    node.state = newState;
                });
            });
            var interval = setInterval(function() {
                node.emit("input", {});
            }, 900000); // 15 minutes
            node.on("close", function() {
                if (interval !== null) {
                    clearInterval(interval);
                }
            });
        });
    }
    RED.nodes.registerType("amazon s3 in", AmazonS3InNode);

    function AmazonS3QueryNode(n) {
        RED.nodes.createNode(this,n);
        this.awsConfig = RED.nodes.getNode(n.aws);
        this.region = n.region;
        this.bucket = n.bucket;
        this.filename = n.filename || "";
        var node = this;
        var AWS = this.awsConfig ? this.awsConfig.AWS : null;
        if (!AWS) {
            node.warn("Missing AWS credentials");
            return;
        }
        var s3 = new AWS.S3();
        node.on("input", function(msg) {
            var bucket = node.bucket || msg.bucket;
            if (bucket === "") {
                node.warn("No bucket specified");
                return;
            }
            var filename = node.filename || msg.filename;
            if (filename === "") {
                node.warn("No filename specified");
                return;
            }
            msg.bucket = bucket;
            msg.filename = filename;
            node.status({fill:"blue",shape:"dot",text:"downloading"});
            s3.getObject({
                Bucket: bucket,
                Key: filename,
            }, function(err, data) {
                if (err) {
                    node.warn("download failed " + err.toString());
                    delete msg.payload;
                    msg.error = err;
                } else {
                    msg.payload = data.Body;
                    delete msg.error;
                }
                node.status({});
                node.send(msg);
            });
        });
    }
    RED.nodes.registerType("amazon s3", AmazonS3QueryNode);

    function AmazonS3OutNode(n) {
        RED.nodes.createNode(this,n);
        this.awsConfig = RED.nodes.getNode(n.aws);
        this.region = n.region;
        this.bucket = n.bucket;
        this.filename = n.filename || "";
        this.localFilename = n.localFilename || "";
        var node = this;
        var AWS = this.awsConfig ? this.awsConfig.AWS : null;
        if (!AWS) {
            node.warn("Missing AWS credentials");
            return;
        }
        if (AWS) {
            var s3 = new AWS.S3();
            node.status({fill:"blue",shape:"dot",text:"checking credentials"});
            s3.listObjects({ Bucket: node.bucket }, function(err) {
                if (err) {
                    node.error("AWS S3 error: " + err);
                    node.status({fill:"red",shape:"ring",text:"error"});
                    return;
                }
                node.status({});
                node.on("input", function(msg) {
                    var bucket = node.bucket || msg.bucket;
                    if (bucket === "") {
                        node.warn("No bucket specified");
                        return;
                    }
                    var filename = node.filename || msg.filename;
                    if (filename === "") {
                        node.warn("No filename specified");
                        return;
                    }
                    var localFilename = node.localFilename || msg.localFilename;
                    if (localFilename) {
                        // TODO: use chunked upload for large files
                        node.status({fill:"blue",shape:"dot",text:"uploading"});
                        var stream = fs.createReadStream(localFilename);
                        s3.putObject({
                            Bucket: bucket,
                            Body: stream,
                            Key: filename,
                        }, function(err) {
                            if (err) {
                                node.error(err.toString());
                                node.status({fill:"red",shape:"ring",text:"failed"});
                                return;
                            }
                            node.status({});
                        });
                    } else if (typeof msg.payload !== "undefined") {
                        node.status({fill:"blue",shape:"dot",text:"uploading"});
                        s3.putObject({
                            Bucket: bucket,
                            Body: RED.util.ensureBuffer(msg.payload),
                            Key: filename,
                        }, function(err) {
                            if (err) {
                                node.error(err.toString());
                                node.status({fill:"red",shape:"ring",text:"failed"});
                                return;
                            }
                            node.status({});
                        });
                    }
                });
            });
        }
    }
    RED.nodes.registerType("amazon s3 out",AmazonS3OutNode);
};
<|endoftext|>


<commit_before>
openerp.web_im = function(instance) {

    var USERS_LIMIT = 20;
    var ERROR_DELAY = 5000;

    var _t = instance.web._t,
       _lt = instance.web._lt;
    var QWeb = instance.web.qweb;

    instance.web.UserMenu.include({
        do_update: function(){
            var self = this;
            this.update_promise.then(function() {
                var im = new instance.web_im.InstantMessaging(self);
                im.appendTo(instance.client.$el);
                var button = new instance.web_im.ImTopButton(this);
                button.on("clicked", im, im.switch_display);
                button.appendTo(instance.webclient.$el.find('.oe_systray'));
            });
            return this._super.apply(this, arguments);
        },
    });

    instance.web_im.ImTopButton = instance.web.Widget.extend({
        template:'ImTopButton',
        events: {
            "click": "clicked",
        },
        clicked: function() {
            this.trigger("clicked");
        },
    });

    instance.web_im.InstantMessaging = instance.web.Widget.extend({
        template: "InstantMessaging",
        events: {
            "keydown .oe_im_searchbox": "input_change",
            "keyup .oe_im_searchbox": "input_change",
            "change .oe_im_searchbox": "input_change",
        },
        init: function(parent) {
            this._super(parent);
            this.shown = false;
            this.set("right_offset", 0);
            this.set("current_search", "");
            this.last = null;
            this.users = [];
            this.activated = false;
            this.c_manager = new instance.web_im.ConversationManager(this);
            this.on("change:right_offset", this.c_manager, _.bind(function() {
                this.c_manager.set("right_offset", this.get("right_offset"));
            }, this));
            this.user_search_dm = new instance.web.DropMisordered();
            this.users_cache = {};
        },
        start: function() {
            this.$el.css("right", -this.$el.outerWidth());
            $(window).scroll(_.bind(this.calc_box, this));
            $(window).resize(_.bind(this.calc_box, this));
            this.calc_box();

            this.on("change:current_search", this, this.search_changed);
            this.search_changed();

            var self = this;

            return this.ensure_users([instance.session.uid]).then(function() {
                self.c_manager.set_me(self.get_user(instance.session.uid));
                return new instance.web.Model("im.message").call("activated", [], {context: new instance.web.CompoundContext()}).then(function(activated) {
                    if (activated) {
                        self.activated = true;
                        self.poll();
                    }
                });
            });
        },
        calc_box: function() {
            var $topbar = instance.client.$(".oe_topbar");
            var top = $topbar.offset().top + $topbar.height();
            top = Math.max(top - $(window).scrollTop(), 0);
            this.$el.css("top", top);
            this.$el.css("bottom", 0);
        },
        input_change: function() {
            this.set("current_search", this.$(".oe_im_searchbox").val());
        },
        search_changed: function(e) {
            var users = new instance.web.Model("res.users");
            var self = this;
            return this.user_search_dm.add(users.query(["name"])
                    .filter([["name", "ilike", this.get("current_search")]])
                    .limit(USERS_LIMIT).all()).then(function(result) {
                self.add_to_user_cache(result);
                self.$(".oe_im_input").val("");
                var old_users = self.users;
                self.users = [];
                _.each(result, function(user) {
                    var widget = new instance.web_im.UserWidget(self, self.get_user(user.id));
                    widget.appendTo(self.$(".oe_im_users"));
                    widget.on("activate_user", self, self.activate_user);
                    self.users.push(widget);
                });
                _.each(old_users, function(user) {
                    user.destroy();
                });
            });
        },
        ensure_users: function(user_ids) {
            var no_cache = {};
            _.each(user_ids, function(el) {
                if (! this.users_cache[el])
                    no_cache[el] = el;
            }, this);
            var self = this;
            if (_.size(no_cache) === 0)
                return $.when();
            else
                return new instance.web.Model("res.users").call("read", [_.values(no_cache), ["name"]],
                        {context: new instance.web.CompoundContext()}).then(function(users) {
                    self.add_to_user_cache(users);
                });
        },
        add_to_user_cache: function(user_recs) {
            _.each(user_recs, function(user_rec) {
                if (! this.users_cache[user_rec.id]) {
                    var user = new instance.web_im.ImUser(this, user_rec);
                    this.users_cache[user_rec.id] = user;
                    user.on("destroyed", this, function() {
                        delete this.users_cache[user_rec.id];
                    });
                }
            }, this);
        },
        get_user: function(user_id) {
            return this.users_cache[user_id];
        },
        switch_display: function() {
            var fct =  _.bind(function(place) {
                this.set("right_offset", place + this.$el.outerWidth());
            }, this);
            var opt = {
                step: fct,
            };
            if (this.shown) {
                this.$el.animate({
                    right: -this.$el.outerWidth(),
                }, opt);
            } else {
                if (! this.activated) {
                    this.do_warn("Instant Messaging is not activated on this server.", "");
                    return;
                }
                this.$el.animate({
                    right: 0,
                }, opt);
            }
            this.shown = ! this.shown;
        },
        poll: function() {
            var self = this;
            this.rpc("/im/poll", {
                last: this.last,
                context: instance.web.pyeval.eval('context', {}),
            }, {shadow: true}).then(function(result) {
                self.last = result.last;
                var user_ids = _.pluck(_.pluck(result.res, "from"), 0);
                self.ensure_users(user_ids).then(function() {
                    _.each(result.res, function(mes) {
                        var user = self.get_user(mes.from[0]);
                        self.c_manager.received_message(mes, user);
                    });
                    self.poll();
                });
            }, function(unused, e) {
                e.preventDefault();
                setTimeout(_.bind(self.poll, self), ERROR_DELAY);
            });
        },
        activate_user: function(user) {
            this.c_manager.activate_user(user);
        },
    });

    instance.web_im.UserWidget = instance.web.Widget.extend({
        "template": "UserWidget",
        events: {
            "click": "activate_user",
        },
        init: function(parent, user) {
            this._super(parent);
            this.user = user;
            this.user.add_watcher();
        },
        activate_user: function() {
            this.trigger("activate_user", this.user);
        },
        destroy: function() {
            this.user.remove_watcher();
            this._super();
        },
    });

    instance.web_im.ImUser = instance.web.Class.extend(instance.web.PropertiesMixin, {
        init: function(parent, user_rec) {
            instance.web.PropertiesMixin.init.call(this, parent);
            user_rec.image_url = instance.session.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.id});
            this.set(user_rec);
            this.set("watcher_count", 0);
            this.on("change:watcher_count", this, function() {
                if (this.get("watcher_count") === 0)
                    this.destroy();
            });
        },
        destroy: function() {
            this.trigger("destroyed");
            instance.web.PropertiesMixin.destroy.call(this);
        },
        add_watcher: function() {
            this.set("watcher_count", this.get("watcher_count") + 1);
        },
        remove_watcher: function() {
            this.set("watcher_count", this.get("watcher_count") - 1);
        },
    });

    instance.web_im.ConversationManager = instance.web.Controller.extend({
        init: function(parent) {
            this._super(parent);
            this.set("right_offset", 0);
            this.conversations = [];
            this.users = {};
            this.on("change:right_offset", this, this.calc_positions);
        },
        set_me: function(me) {
            this.me = me;
        },
        activate_user: function(user) {
            if (this.users[user.get('id')]) {
                return this.users[user.get('id')];
            }
            var conv = new instance.web_im.Conversation(this, user, this.me);
            conv.appendTo(instance.client.$el);
            conv.on("destroyed", this, function() {
                this.conversations = _.without(this.conversations, conv);
                delete this.users[conv.user.get('id')];
                this.calc_positions();
            });
            this.conversations.push(conv);
            this.users[user.get('id')] = conv;
            this.calc_positions();
            return conv;
        },
        received_message: function(message, user) {
            var conv = this.activate_user(user);
            conv.received_message(message);
        },
        calc_positions: function() {
            var current = this.get("right_offset");
            _.each(_.range(this.conversations.length), function(i) {
                this.conversations[i].set("right_position", current);
                current += this.conversations[i].$el.outerWidth(true);
            }, this);
        },
    });

    instance.web_im.Conversation = instance.web.Widget.extend({
        "template": "Conversation",
        events: {
            "keydown input": "send_message",
            "click .oe_im_chatview_close": "destroy",
        },
        init: function(parent, user, me) {
            this._super(parent);
            this.me = me;
            this.user = user;
            this.user.add_watcher();
            this.set("right_position", 0);
        },
        start: function() {
            this.on("change:right_position", this, this.calc_pos);
            this.calc_pos();
        },
        calc_pos: function() {
            this.$el.css("right", this.get("right_position"));
        },
        received_message: function(message) {
            this._add_bubble(this.user, [message.message], message.date);
        },
        send_message: function(e) {
            if(e && e.which !== 13) {
                return;
            }
            var mes = this.$("input").val();
            this.$("input").val("");
            this._add_bubble(this.me, [mes], instance.web.datetime_to_str(new Date()));
            var model = new instance.web.Model("im.message");
            model.call("post", [mes, this.user.get('id')], {context: new instance.web.CompoundContext()});
        },
        _add_bubble: function(user, items, date) {
            date = instance.web.str_to_datetime(date);
            date = date.toString(Date.CultureInfo.formatPatterns.shortDate + " " + Date.CultureInfo.formatPatterns.shortTime);
            var bubble = QWeb.render("Conversation.bubble", {"items": items, "user": user, "time": date});
            $(this.$(".oe_im_chatview_content").children()[0]).append($(bubble));
            this.$(".oe_im_chatview_content").scrollTop($(this.$(".oe_im_chatview_content").children()[0]).height());
        },
        destroy: function() {
            this.user.remove_watcher();
            this.trigger("destroyed");
            return this._super();
        },
    });

}<commit_msg>Added multi bubble<commit_after>
openerp.web_im = function(instance) {

    var USERS_LIMIT = 20;
    var ERROR_DELAY = 5000;

    var _t = instance.web._t,
       _lt = instance.web._lt;
    var QWeb = instance.web.qweb;

    instance.web.UserMenu.include({
        do_update: function(){
            var self = this;
            this.update_promise.then(function() {
                var im = new instance.web_im.InstantMessaging(self);
                im.appendTo(instance.client.$el);
                var button = new instance.web_im.ImTopButton(this);
                button.on("clicked", im, im.switch_display);
                button.appendTo(instance.webclient.$el.find('.oe_systray'));
            });
            return this._super.apply(this, arguments);
        },
    });

    instance.web_im.ImTopButton = instance.web.Widget.extend({
        template:'ImTopButton',
        events: {
            "click": "clicked",
        },
        clicked: function() {
            this.trigger("clicked");
        },
    });

    instance.web_im.InstantMessaging = instance.web.Widget.extend({
        template: "InstantMessaging",
        events: {
            "keydown .oe_im_searchbox": "input_change",
            "keyup .oe_im_searchbox": "input_change",
            "change .oe_im_searchbox": "input_change",
        },
        init: function(parent) {
            this._super(parent);
            this.shown = false;
            this.set("right_offset", 0);
            this.set("current_search", "");
            this.last = null;
            this.users = [];
            this.activated = false;
            this.c_manager = new instance.web_im.ConversationManager(this);
            this.on("change:right_offset", this.c_manager, _.bind(function() {
                this.c_manager.set("right_offset", this.get("right_offset"));
            }, this));
            this.user_search_dm = new instance.web.DropMisordered();
            this.users_cache = {};
        },
        start: function() {
            this.$el.css("right", -this.$el.outerWidth());
            $(window).scroll(_.bind(this.calc_box, this));
            $(window).resize(_.bind(this.calc_box, this));
            this.calc_box();

            this.on("change:current_search", this, this.search_changed);
            this.search_changed();

            var self = this;

            return this.ensure_users([instance.session.uid]).then(function() {
                self.c_manager.set_me(self.get_user(instance.session.uid));
                return new instance.web.Model("im.message").call("activated", [], {context: new instance.web.CompoundContext()}).then(function(activated) {
                    if (activated) {
                        self.activated = true;
                        self.poll();
                    }
                });
            });
        },
        calc_box: function() {
            var $topbar = instance.client.$(".oe_topbar");
            var top = $topbar.offset().top + $topbar.height();
            top = Math.max(top - $(window).scrollTop(), 0);
            this.$el.css("top", top);
            this.$el.css("bottom", 0);
        },
        input_change: function() {
            this.set("current_search", this.$(".oe_im_searchbox").val());
        },
        search_changed: function(e) {
            var users = new instance.web.Model("res.users");
            var self = this;
            return this.user_search_dm.add(users.query(["name"])
                    .filter([["name", "ilike", this.get("current_search")]])
                    .limit(USERS_LIMIT).all()).then(function(result) {
                self.add_to_user_cache(result);
                self.$(".oe_im_input").val("");
                var old_users = self.users;
                self.users = [];
                _.each(result, function(user) {
                    var widget = new instance.web_im.UserWidget(self, self.get_user(user.id));
                    widget.appendTo(self.$(".oe_im_users"));
                    widget.on("activate_user", self, self.activate_user);
                    self.users.push(widget);
                });
                _.each(old_users, function(user) {
                    user.destroy();
                });
            });
        },
        ensure_users: function(user_ids) {
            var no_cache = {};
            _.each(user_ids, function(el) {
                if (! this.users_cache[el])
                    no_cache[el] = el;
            }, this);
            var self = this;
            if (_.size(no_cache) === 0)
                return $.when();
            else
                return new instance.web.Model("res.users").call("read", [_.values(no_cache), ["name"]],
                        {context: new instance.web.CompoundContext()}).then(function(users) {
                    self.add_to_user_cache(users);
                });
        },
        add_to_user_cache: function(user_recs) {
            _.each(user_recs, function(user_rec) {
                if (! this.users_cache[user_rec.id]) {
                    var user = new instance.web_im.ImUser(this, user_rec);
                    this.users_cache[user_rec.id] = user;
                    user.on("destroyed", this, function() {
                        delete this.users_cache[user_rec.id];
                    });
                }
            }, this);
        },
        get_user: function(user_id) {
            return this.users_cache[user_id];
        },
        switch_display: function() {
            var fct =  _.bind(function(place) {
                this.set("right_offset", place + this.$el.outerWidth());
            }, this);
            var opt = {
                step: fct,
            };
            if (this.shown) {
                this.$el.animate({
                    right: -this.$el.outerWidth(),
                }, opt);
            } else {
                if (! this.activated) {
                    this.do_warn("Instant Messaging is not activated on this server.", "");
                    return;
                }
                this.$el.animate({
                    right: 0,
                }, opt);
            }
            this.shown = ! this.shown;
        },
        poll: function() {
            var self = this;
            this.rpc("/im/poll", {
                last: this.last,
                context: instance.web.pyeval.eval('context', {}),
            }, {shadow: true}).then(function(result) {
                self.last = result.last;
                var user_ids = _.pluck(_.pluck(result.res, "from"), 0);
                self.ensure_users(user_ids).then(function() {
                    _.each(result.res, function(mes) {
                        var user = self.get_user(mes.from[0]);
                        self.c_manager.received_message(mes, user);
                    });
                    self.poll();
                });
            }, function(unused, e) {
                e.preventDefault();
                setTimeout(_.bind(self.poll, self), ERROR_DELAY);
            });
        },
        activate_user: function(user) {
            this.c_manager.activate_user(user);
        },
    });

    instance.web_im.UserWidget = instance.web.Widget.extend({
        "template": "UserWidget",
        events: {
            "click": "activate_user",
        },
        init: function(parent, user) {
            this._super(parent);
            this.user = user;
            this.user.add_watcher();
        },
        activate_user: function() {
            this.trigger("activate_user", this.user);
        },
        destroy: function() {
            this.user.remove_watcher();
            this._super();
        },
    });

    instance.web_im.ImUser = instance.web.Class.extend(instance.web.PropertiesMixin, {
        init: function(parent, user_rec) {
            instance.web.PropertiesMixin.init.call(this, parent);
            user_rec.image_url = instance.session.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.id});
            this.set(user_rec);
            this.set("watcher_count", 0);
            this.on("change:watcher_count", this, function() {
                if (this.get("watcher_count") === 0)
                    this.destroy();
            });
        },
        destroy: function() {
            this.trigger("destroyed");
            instance.web.PropertiesMixin.destroy.call(this);
        },
        add_watcher: function() {
            this.set("watcher_count", this.get("watcher_count") + 1);
        },
        remove_watcher: function() {
            this.set("watcher_count", this.get("watcher_count") - 1);
        },
    });

    instance.web_im.ConversationManager = instance.web.Controller.extend({
        init: function(parent) {
            this._super(parent);
            this.set("right_offset", 0);
            this.conversations = [];
            this.users = {};
            this.on("change:right_offset", this, this.calc_positions);
        },
        set_me: function(me) {
            this.me = me;
        },
        activate_user: function(user) {
            if (this.users[user.get('id')]) {
                return this.users[user.get('id')];
            }
            var conv = new instance.web_im.Conversation(this, user, this.me);
            conv.appendTo(instance.client.$el);
            conv.on("destroyed", this, function() {
                this.conversations = _.without(this.conversations, conv);
                delete this.users[conv.user.get('id')];
                this.calc_positions();
            });
            this.conversations.push(conv);
            this.users[user.get('id')] = conv;
            this.calc_positions();
            return conv;
        },
        received_message: function(message, user) {
            var conv = this.activate_user(user);
            conv.received_message(message);
        },
        calc_positions: function() {
            var current = this.get("right_offset");
            _.each(_.range(this.conversations.length), function(i) {
                this.conversations[i].set("right_position", current);
                current += this.conversations[i].$el.outerWidth(true);
            }, this);
        },
    });

    instance.web_im.Conversation = instance.web.Widget.extend({
        "template": "Conversation",
        events: {
            "keydown input": "send_message",
            "click .oe_im_chatview_close": "destroy",
        },
        init: function(parent, user, me) {
            this._super(parent);
            this.me = me;
            this.user = user;
            this.user.add_watcher();
            this.set("right_position", 0);
        },
        start: function() {
            this.on("change:right_position", this, this.calc_pos);
            this.calc_pos();
        },
        calc_pos: function() {
            this.$el.css("right", this.get("right_position"));
        },
        received_message: function(message) {
            this._add_bubble(this.user, message.message, message.date);
        },
        send_message: function(e) {
            if(e && e.which !== 13) {
                return;
            }
            var mes = this.$("input").val();
            this.$("input").val("");
            this._add_bubble(this.me, mes, instance.web.datetime_to_str(new Date()));
            var model = new instance.web.Model("im.message");
            model.call("post", [mes, this.user.get('id')], {context: new instance.web.CompoundContext()});
        },
        _add_bubble: function(user, item, date) {
            var items = [item];
            if (user === this.last_user) {
                this.last_bubble.remove();
                items = this.last_items.concat(items);
            }
            this.last_user = user;
            this.last_items = items;
            date = instance.web.str_to_datetime(date);
            date = date.toString(Date.CultureInfo.formatPatterns.shortDate + " " + Date.CultureInfo.formatPatterns.shortTime);
            this.last_bubble = $(QWeb.render("Conversation.bubble", {"items": items, "user": user, "time": date}));
            $(this.$(".oe_im_chatview_content").children()[0]).append(this.last_bubble);
            this.$(".oe_im_chatview_content").scrollTop($(this.$(".oe_im_chatview_content").children()[0]).height());
        },
        destroy: function() {
            this.user.remove_watcher();
            this.trigger("destroyed");
            return this._super();
        },
    });

}<|endoftext|>


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

var prify = require('es6-promisify')
var path = require('path')
var mkdirp = prify(require('mkdirp'))

var rollup = require('rollup')
var nodeResolve = require('rollup-plugin-node-resolve')
var babel = require('rollup-plugin-babel')
var commonjs = require('rollup-plugin-commonjs')
var json = require('rollup-plugin-json')

if (process.argv.length !== 4) {
  throw Error('Usage: target outFile')
}
var tgt = process.argv[2]
var tgtPkg = require(path.resolve('packages', tgt, 'package.json'))
var entry = path.resolve('packages', tgt, tgtPkg.main)

var global = tgtPkg.controller.global

mkdirp(path.dirname(path.resolve(process.argv[3])))
  .then(function () {
    return rollup.rollup({
      entry,
      plugins: [
        nodeResolve({
          extensions: ['.js', '.json'],
          main: true,
          modulesOnly: false, // required for rollup-plugin-commonjs
          // for valid values see https://github.com/substack/node-resolve
          customResolveOptions: {
            paths: [ path.resolve('packages', tgt, 'node_modules') ]
          }
        }),
        json(),
        babel({
          exclude: 'node_modules/**'
        }),
        commonjs()
      ]
    })
  })
  .then(function (bundle) {
    return bundle.write({
      format: 'iife',
      moduleName: global,
      dest: path.resolve(process.argv[3])
    })
  })
  .catch(function (err) {
    console.error(err)
    process.exit(1)
  })
<commit_msg>obviously I forgot the important part<commit_after>#!/usr/bin/env node

var prify = require('es6-promisify')
var path = require('path')
var mkdirp = prify(require('mkdirp'))
var fs = require('fs')

var rollup = require('rollup')
var nodeResolve = require('rollup-plugin-node-resolve')
var babel = require('rollup-plugin-babel')
var commonjs = require('rollup-plugin-commonjs')
var json = require('rollup-plugin-json')
var writeFile = prify(fs.writeFile)
var readFile = prify(fs.readFile)

if (process.argv.length > 5 || (process.argv.length === 5 && process.argv[4] !== "watch")) {
  throw Error('Usage: target outFile [watch]')
}

var watch = process.argv.length === 5

var watcher = null

var tgt = process.argv[2]
var tgtPkg = require(path.resolve('packages', tgt, 'package.json'))
var entry = path.resolve('packages', tgt, tgtPkg.main)

var global = tgtPkg.controller.global

var config =
mkdirp(path.dirname(path.resolve(process.argv[3])))
  .then(() => readFile('tmp/cache.json'))
  .then((cache) => JSON.parse(cache))
  .catch((err) => null)
  .then((cache) => {
    return rollup.rollup({
      cache,
      entry,
      plugins: [
        nodeResolve({
          extensions: ['.js', '.json'],
          main: true,
          modulesOnly: false, // required for rollup-plugin-commonjs
          // for valid values see https://github.com/substack/node-resolve
          customResolveOptions: {
            paths: [ path.resolve('packages', tgt, 'node_modules') ]
          }}),
        json(),
        babel({
          exclude: 'node_modules/**'}),
        commonjs()]})
  })
  .then((bundle) => {
    const cache = JSON.stringify(bundle)
    return mkdirp('tmp')
      .then(() => writeFile('tmp/cache.json', cache))
      .then(() => bundle.write({
        format: 'iife',
        moduleName: global,
        dest: path.resolve(process.argv[3])
      }))
  })
  .catch(function (err) {
    console.error(err)
    process.exit(1)
  })

process.on('SIGINT', () => {
  if (watcher) {
    watcher.close()
    watcher = null
  }
  process.exit(125)
})
<|endoftext|>


<commit_before>/* This file is part of Indico.
 * Copyright (C) 2002 - 2018 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

import {camelizeKeys} from 'indico/utils/case';

/* eslint-disable import/unambiguous */
(function(global) {
    global.setupEventCreationDialog = function setupEventCreationDialog(options) {
        options = $.extend({
            categoryField: null,
            protectionModeFields: null,
            initialCategory: null,
            checkAvailability: false,
            rbExcludedCategories: null,
            serverDefaultTimezone: null
        }, options);

        const messages = $($.parseHTML($('#event-creation-protection-messages').html()));
        const protectionMessage = $('<div>', {class: 'form-group', css: {marginTop: '5px'}});

        const $createBooking = $('#event-creation-create_booking');
        const $availableMessage = $('#room-available');
        const $availablePrebookMessage = $('#room-available-prebook');
        const $conflictBookingMessage = $('#room-conflict-booking');
        const $conflictPrebookingMessage = $('#room-conflict-prebooking');
        const $conflictPrebookingPrebookMessage = $('#room-conflict-prebooking-prebook');
        const $userBookingMessage = $('#room-user-booking');
        const $userPrebookingMessage = $('#room-user-prebooking');
        const $unbookableMessage = $('#room-unbookable');
        const $cannotBookMessage = $('#room-cannot-book');
        const $bookingSwitch = $('#create-booking');
        const $prebookingSwitch = $('#create-prebooking');
        const $bookingSwitchPrebooking = $('#create-booking-over-prebooking');
        const $prebookingSwitchPrebooking = $('#create-prebooking-over-prebooking');
        const calendarUrl = Indico.Urls.RoomBooking.calendar;

        let currentCategory = null;
        let previousRoomId, $currentMessage, startDt, endDt, category, roomData, timezone;
        let multipleOccurrences = false;

        protectionMessage.appendTo(options.protectionModeFields.closest('.form-field'));

        function updateProtectionMessage() {
            let mode = options.protectionModeFields.filter(':checked').val();
            if (mode === 'inheriting') {
                mode = currentCategory.is_protected ? 'inheriting-protected' : 'inheriting-public';
            }
            const elem = messages.filter('.{0}-protection-message'.format(mode));
            elem.find('.js-category-title').text(currentCategory.title);
            protectionMessage.html(elem);
        }

        options.categoryField.on('indico:categorySelected', (evt, cat) => {
            if (!currentCategory) {
                options.protectionModeFields.prop('disabled', false);
                options.protectionModeFields.filter('[value=inheriting]').prop('checked', true);
            }
            currentCategory = cat;
            updateProtectionMessage();
        });

        options.protectionModeFields.on('change', function() {
            updateProtectionMessage();
        });

        if (options.initialCategory) {
            options.categoryField.trigger('indico:categorySelected', [options.initialCategory]);
        } else {
            options.protectionModeFields.prop('disabled', true);
        }

        function setLectureTimes(occurrence) {
            startDt = moment(`${occurrence['date']} ${occurrence['time']}`, 'YYYY-MM-DD HH:mm');
            endDt = moment(startDt).add(occurrence['duration'], 'minutes');
        }

        function initAvailabilityValues() {
            const startDate = $('#event-creation-start_dt-date').val();
            const startTime = $('#event-creation-start_dt-time').val();
            const endDate = $('#event-creation-end_dt-date').val();
            const endTime = $('#event-creation-end_dt-time').val();
            const occurrencesVal = $('#event-creation-occurrences').val();
            const occurrences = occurrencesVal ? JSON.parse(occurrencesVal) : null;

            roomData = JSON.parse($('#event-creation-location_data').val());
            timezone = $('#event-creation-timezone').val();
            category = JSON.parse($('#event-creation-category').val());

            if (occurrences && occurrences.length === 1) {
                setLectureTimes(occurrences[0]);
            } else {
                startDt = moment(`${startDate} ${startTime}`, 'DD/MM/YYYY HH:mm');
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
            }
        }

        function isCategoryExcluded(categoryId) {
            return options.rbExcludedCategories.some((excludedCategory) => {
                return (parseInt(excludedCategory.id, 10) === categoryId);
            });
        }

        function addCalendarLink($message) {
            const params = {
                date: startDt.format('YYYY-MM-DD'),
                text: roomData['room_name']
            };
            const url = build_url(calendarUrl, params);
            $message.find('a').prop('href', url);
        }

        function hideAvailability(resetCheckbox) {
            if ($currentMessage) {
                if (resetCheckbox) {
                    $('#availability-messages').find("input[id^='create']").prop('checked', false);
                    $createBooking.val('false');
                }
                $currentMessage.hide();
            }
        }

        function updateAvailability(resetCheckbox = false) {
            hideAvailability(resetCheckbox);

            if (!('room_id' in roomData) ||
                !startDt.isValid() ||
                !endDt.isValid() ||
                !startDt.isSame(endDt, 'day') ||
                startDt.isSameOrAfter(endDt) ||
                isCategoryExcluded(category['id']) ||
                timezone !== options.serverDefaultTimezone ||
                multipleOccurrences) {
                $createBooking.val('false');
                return;
            }

            const requestParams = {
                room_id: roomData['room_id'],
                start_dt: startDt.format(moment.HTML5_FMT.DATETIME_LOCAL),
                end_dt: endDt.format(moment.HTML5_FMT.DATETIME_LOCAL)
            };

            $.ajax({
                url: build_url(Indico.Urls.RoomBooking.room.check_available, requestParams),
                method: 'GET',
                dataType: 'json',
                contentType: 'application/json',
                error: handleAjaxError,
                success(data) {
                    data = camelizeKeys(data);
                    if (data.userBooking) {
                        $createBooking.val('false');
                        $currentMessage = $userBookingMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.userPrebooking) {
                        $createBooking.val('false');
                        $currentMessage = $userPrebookingMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.conflictBooking) {
                        $createBooking.val('false');
                        $currentMessage = $conflictBookingMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.unbookable) {
                        $createBooking.val('false');
                        $currentMessage = $unbookableMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.conflictPrebooking) {
                        if (data.canBook) {
                            $createBooking.val(String($bookingSwitchPrebooking[0].checked));
                            $currentMessage = $conflictPrebookingMessage;
                            addCalendarLink($currentMessage);
                        } else if (data.canPrebook) {
                            $createBooking.val(String($prebookingSwitchPrebooking[0].checked));
                            $currentMessage = $conflictPrebookingPrebookMessage;
                            addCalendarLink($currentMessage);
                        } else {
                            $createBooking.val('false');
                            $currentMessage = $cannotBookMessage;
                        }
                    } else if (data.canBook) {
                        $createBooking.val(String($bookingSwitch[0].checked));
                        $currentMessage = $availableMessage;
                    } else if (data.canPrebook) {
                        $createBooking.val(String($prebookingSwitch[0].checked));
                        $currentMessage = $availablePrebookMessage;
                    } else {
                        $createBooking.val('false');
                        $currentMessage = $cannotBookMessage;
                    }
                    $currentMessage.show();
                }
            });
        }

        if (options.checkAvailability) {
            initAvailabilityValues();

            $('#event-creation-location_data').on('change', function() {
                roomData = JSON.parse($(this).val());
                if (previousRoomId !== roomData['room_id']) {
                    previousRoomId = roomData['room_id'];
                    updateAvailability(true);
                }
            });

            $('#event-creation-start_dt-date').on('change', function() {
                const startDate = $(this).val();
                const startTime = $('#event-creation-start_dt-time').val();
                const endDate = $('#event-creation-end_dt-date').val();
                const endTime = $('#event-creation-end_dt-time').val();
                startDt = moment(`${startDate} ${startTime}`, 'DD/MM/YYYY HH:mm');
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                // workaround for automatic end date update if start date is after end date
                if (endDt.isBefore(startDt)) {
                    endDt = moment(`${startDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                }
                updateAvailability();
            });

            $('#event-creation-start_dt-time').on('change', function() {
                const startDate = $('#event-creation-start_dt-date').val();
                const startTime = $('#event-creation-start_dt-time').val();
                startDt = moment(`${startDate} ${startTime}`, 'DD/MM/YYYY HH:mm');
                updateAvailability();
            });

            $('#event-creation-end_dt-date').on('change', function() {
                const endDate = $(this).val();
                const endTime = $('#event-creation-end_dt-time').val();
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                updateAvailability();
            });

            $('#event-creation-end_dt-time').on('change', function() {
                const endDate = $('#event-creation-end_dt-date').val();
                const endTime = $(this).val();
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                updateAvailability();
            });

            $('#event-creation-occurrences').on('change', function() {
                const occurrences = JSON.parse($(this).val());
                if (occurrences.length === 1) {
                    setLectureTimes(occurrences[0]);
                    multipleOccurrences = false;
                } else {
                    multipleOccurrences = true;
                }
                updateAvailability();
            });

            $('#event-creation-timezone').on('change', function() {
                timezone = ($(this).val());
                updateAvailability();
            });

            $('#event-creation-category').on('change', function() {
                category = JSON.parse($(this).val());
                updateAvailability();
            });

            $bookingSwitch.add($prebookingSwitch).add($bookingSwitchPrebooking).add($prebookingSwitchPrebooking).on('change', function() {
                $createBooking.val(String(this.checked));
            });
        }
    };
})(window);
<commit_msg>Fix errors in event creation dialog<commit_after>/* This file is part of Indico.
 * Copyright (C) 2002 - 2018 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

import rbURL from 'indico-url:rooms_new.roombooking';
import checkRoomAvailabilityURL from 'indico-url:rooms_new.check_room_available';

import {camelizeKeys} from 'indico/utils/case';

/* eslint-disable import/unambiguous */
(function(global) {
    global.setupEventCreationDialog = function setupEventCreationDialog(options) {
        options = $.extend({
            categoryField: null,
            protectionModeFields: null,
            initialCategory: null,
            checkAvailability: false,
            rbExcludedCategories: null,
            serverDefaultTimezone: null
        }, options);

        const messages = $($.parseHTML($('#event-creation-protection-messages').html()));
        const protectionMessage = $('<div>', {class: 'form-group', css: {marginTop: '5px'}});

        const $createBooking = $('#event-creation-create_booking');
        const $availableMessage = $('#room-available');
        const $availablePrebookMessage = $('#room-available-prebook');
        const $conflictBookingMessage = $('#room-conflict-booking');
        const $conflictPrebookingMessage = $('#room-conflict-prebooking');
        const $conflictPrebookingPrebookMessage = $('#room-conflict-prebooking-prebook');
        const $userBookingMessage = $('#room-user-booking');
        const $userPrebookingMessage = $('#room-user-prebooking');
        const $unbookableMessage = $('#room-unbookable');
        const $cannotBookMessage = $('#room-cannot-book');
        const $bookingSwitch = $('#create-booking');
        const $prebookingSwitch = $('#create-prebooking');
        const $bookingSwitchPrebooking = $('#create-booking-over-prebooking');
        const $prebookingSwitchPrebooking = $('#create-prebooking-over-prebooking');

        let currentCategory = null;
        let previousRoomId, $currentMessage, startDt, endDt, category, roomData, timezone;
        let multipleOccurrences = false;

        protectionMessage.appendTo(options.protectionModeFields.closest('.form-field'));

        function updateProtectionMessage() {
            let mode = options.protectionModeFields.filter(':checked').val();
            if (mode === 'inheriting') {
                mode = currentCategory.is_protected ? 'inheriting-protected' : 'inheriting-public';
            }
            const elem = messages.filter('.{0}-protection-message'.format(mode));
            elem.find('.js-category-title').text(currentCategory.title);
            protectionMessage.html(elem);
        }

        options.categoryField.on('indico:categorySelected', (evt, cat) => {
            if (!currentCategory) {
                options.protectionModeFields.prop('disabled', false);
                options.protectionModeFields.filter('[value=inheriting]').prop('checked', true);
            }
            currentCategory = cat;
            updateProtectionMessage();
        });

        options.protectionModeFields.on('change', function() {
            updateProtectionMessage();
        });

        if (options.initialCategory) {
            options.categoryField.trigger('indico:categorySelected', [options.initialCategory]);
        } else {
            options.protectionModeFields.prop('disabled', true);
        }

        function setLectureTimes(occurrence) {
            startDt = moment(`${occurrence['date']} ${occurrence['time']}`, 'YYYY-MM-DD HH:mm');
            endDt = moment(startDt).add(occurrence['duration'], 'minutes');
        }

        function initAvailabilityValues() {
            const startDate = $('#event-creation-start_dt-date').val();
            const startTime = $('#event-creation-start_dt-time').val();
            const endDate = $('#event-creation-end_dt-date').val();
            const endTime = $('#event-creation-end_dt-time').val();
            const occurrencesVal = $('#event-creation-occurrences').val();
            const occurrences = occurrencesVal ? JSON.parse(occurrencesVal) : null;

            roomData = JSON.parse($('#event-creation-location_data').val());
            timezone = $('#event-creation-timezone').val();
            category = JSON.parse($('#event-creation-category').val());

            if (occurrences && occurrences.length === 1) {
                setLectureTimes(occurrences[0]);
            } else {
                startDt = moment(`${startDate} ${startTime}`, 'DD/MM/YYYY HH:mm');
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
            }
        }

        function isCategoryExcluded(categoryId) {
            return options.rbExcludedCategories.some((excludedCategory) => {
                return (parseInt(excludedCategory.id, 10) === categoryId);
            });
        }

        function addCalendarLink($message) {
            const params = {
                path: 'calendar',
                date: startDt.format('YYYY-MM-DD'),
                text: roomData['room_name']
            };
            const url = rbURL(params);
            $message.find('a').prop('href', url);
        }

        function hideAvailability(resetCheckbox) {
            if ($currentMessage) {
                if (resetCheckbox) {
                    $('#availability-messages').find("input[id^='create']").prop('checked', false);
                    $createBooking.val('false');
                }
                $currentMessage.hide();
            }
        }

        function updateAvailability(resetCheckbox = false) {
            hideAvailability(resetCheckbox);

            if (!('room_id' in roomData) ||
                !startDt.isValid() ||
                !endDt.isValid() ||
                !startDt.isSame(endDt, 'day') ||
                startDt.isSameOrAfter(endDt) ||
                isCategoryExcluded(category['id']) ||
                timezone !== options.serverDefaultTimezone ||
                multipleOccurrences) {
                $createBooking.val('false');
                return;
            }

            const requestParams = {
                room_id: roomData['room_id'],
                start_dt: startDt.format(moment.HTML5_FMT.DATETIME_LOCAL),
                end_dt: endDt.format(moment.HTML5_FMT.DATETIME_LOCAL)
            };

            $.ajax({
                url: checkRoomAvailabilityURL(requestParams),
                method: 'GET',
                dataType: 'json',
                contentType: 'application/json',
                error: handleAjaxError,
                success(data) {
                    data = camelizeKeys(data);
                    if (data.userBooking) {
                        $createBooking.val('false');
                        $currentMessage = $userBookingMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.userPrebooking) {
                        $createBooking.val('false');
                        $currentMessage = $userPrebookingMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.conflictBooking) {
                        $createBooking.val('false');
                        $currentMessage = $conflictBookingMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.unbookable) {
                        $createBooking.val('false');
                        $currentMessage = $unbookableMessage;
                        addCalendarLink($currentMessage);
                    } else if (data.conflictPrebooking) {
                        if (data.canBook) {
                            $createBooking.val(String($bookingSwitchPrebooking[0].checked));
                            $currentMessage = $conflictPrebookingMessage;
                            addCalendarLink($currentMessage);
                        } else if (data.canPrebook) {
                            $createBooking.val(String($prebookingSwitchPrebooking[0].checked));
                            $currentMessage = $conflictPrebookingPrebookMessage;
                            addCalendarLink($currentMessage);
                        } else {
                            $createBooking.val('false');
                            $currentMessage = $cannotBookMessage;
                        }
                    } else if (data.canBook) {
                        $createBooking.val(String($bookingSwitch[0].checked));
                        $currentMessage = $availableMessage;
                    } else if (data.canPrebook) {
                        $createBooking.val(String($prebookingSwitch[0].checked));
                        $currentMessage = $availablePrebookMessage;
                    } else {
                        $createBooking.val('false');
                        $currentMessage = $cannotBookMessage;
                    }
                    $currentMessage.show();
                }
            });
        }

        if (options.checkAvailability) {
            initAvailabilityValues();

            $('#event-creation-location_data').on('change', function() {
                roomData = JSON.parse($(this).val());
                if (previousRoomId !== roomData['room_id']) {
                    previousRoomId = roomData['room_id'];
                    updateAvailability(true);
                }
            });

            $('#event-creation-start_dt-date').on('change', function() {
                const startDate = $(this).val();
                const startTime = $('#event-creation-start_dt-time').val();
                const endDate = $('#event-creation-end_dt-date').val();
                const endTime = $('#event-creation-end_dt-time').val();
                startDt = moment(`${startDate} ${startTime}`, 'DD/MM/YYYY HH:mm');
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                // workaround for automatic end date update if start date is after end date
                if (endDt.isBefore(startDt)) {
                    endDt = moment(`${startDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                }
                updateAvailability();
            });

            $('#event-creation-start_dt-time').on('change', function() {
                const startDate = $('#event-creation-start_dt-date').val();
                const startTime = $('#event-creation-start_dt-time').val();
                startDt = moment(`${startDate} ${startTime}`, 'DD/MM/YYYY HH:mm');
                updateAvailability();
            });

            $('#event-creation-end_dt-date').on('change', function() {
                const endDate = $(this).val();
                const endTime = $('#event-creation-end_dt-time').val();
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                updateAvailability();
            });

            $('#event-creation-end_dt-time').on('change', function() {
                const endDate = $('#event-creation-end_dt-date').val();
                const endTime = $(this).val();
                endDt = moment(`${endDate} ${endTime}`, 'DD/MM/YYYY HH:mm');
                updateAvailability();
            });

            $('#event-creation-occurrences').on('change', function() {
                const occurrences = JSON.parse($(this).val());
                if (occurrences.length === 1) {
                    setLectureTimes(occurrences[0]);
                    multipleOccurrences = false;
                } else {
                    multipleOccurrences = true;
                }
                updateAvailability();
            });

            $('#event-creation-timezone').on('change', function() {
                timezone = ($(this).val());
                updateAvailability();
            });

            $('#event-creation-category').on('change', function() {
                category = JSON.parse($(this).val());
                updateAvailability();
            });

            $bookingSwitch.add($prebookingSwitch).add($bookingSwitchPrebooking).add($prebookingSwitchPrebooking).on('change', function() {
                $createBooking.val(String(this.checked));
            });
        }
    };
})(window);
<|endoftext|>


<commit_before>/**
 * Created by uetsujitomoya on 2017/08/17.
 */

import　{find_verb_from_csv} from "find_verb.js"

let first_japanese_row_num_in_sentence = 3 ;
let starting_kihonku_row_num_in_sentence = 2 ;
let starting_bunsetsu_row_num_in_sentence = 1 ;

let reconstruct_KNP = (raw_2d_array,KNP_character_array) => {
    let KNP_sentence_array=[]
    let temp_sentence_2d_array=[]
    let temp_rowNo=0;
    raw_2d_array.forEach((row_array)=>{
        if(row_array[0]!="EOS"){
            temp_sentence_2d_array.push(row_array)
        }else{
            KNP_sentence_array.push(new KNP_sentence(temp_rowNo,temp_sentence_2d_array,KNP_character_array))
            temp_sentence_2d_array=[]
        }
        temp_rowNo++
    })
}

let count_bunsetsu=(input_2d_array)=>{
    let cnt=0
    input_2d_array.forEach((row_array)=>{
        if(row_array[0]=="*"){
            cnt++
        }
    })
    return cnt
}

let count_kihonku=(input_2d_array)=>{
    let cnt=0
    input_2d_array.forEach((row_array)=>{
        if(row_array[0]=="+"){
            cnt++
        }
    })
    return cnt
}

//文節取得
/*EODまでが一個の文
 アスタリスクが1個の文節 phtase_no
 プラスが1個の基本句　basic_phrase_no
 *2次元配列を4次元配列に組み替える
 * */

class KNP_sentence{
    constructor(raw_rowNo,sentence_2d_array,KNP_character_array) {
        //console.log("raw_rowNo %d",raw_rowNo)
        //console.log(sentence_2d_array)
        if(sentence_2d_array.length==1){
            return 0
        }//空白センテンス処理

        //動詞判定・登場人物判定と組み合わせる

        //PARAがかかる先は？

        //PARAの探索（3列目にPを含む文字列があればPARAがそこにあると判定し、文節配列と基本句配列にPARAを挿入）
        //そのためには、始めに文節配列・基本句配列のlengthだけ決めてしまったほうが良い

        //this.csv_raw_array=[]
        this.rowNo=raw_rowNo
        this.bunsetsu_array=[]
        this.bunsetsu_array.length=count_bunsetsu(sentence_2d_array)

        this.kihonku_array=[]
        this.kihonku_array.length=count_kihonku(sentence_2d_array)

        this.surface_form = "null"
        //this.basic_form = row_array[2]

        let temp_2d_array_for_bunsetsu=[]
        let temp_2d_array_for_kihonku=[]

        temp_2d_array_for_bunsetsu.push(sentence_2d_array[starting_bunsetsu_row_num_in_sentence])//0文節目　開始宣言をプッシュ

        temp_2d_array_for_bunsetsu.push(sentence_2d_array[starting_kihonku_row_num_in_sentence])//0基本句目　開始宣言をプッシュ
        temp_2d_array_for_kihonku.push(sentence_2d_array[starting_kihonku_row_num_in_sentence])//0基本句目　開始宣言をプッシュ

        let bunsetsu_num_in_sentence=0
        let kihonku_num_in_sentence=0

        for( let temp_rowNo = first_japanese_row_num_in_sentence ; temp_rowNo < sentence_2d_array.length ; temp_rowNo++ ){
            let temp_surface_form=sentence_2d_array[temp_rowNo][0];
            if(temp_surface_form=="+" && sentence_2d_array[temp_rowNo-1][0]!="*"){//文節内 2こ目以降の基本句
                //console.info(temp_2d_array_for_kihonku)
                this.kihonku_array[kihonku_num_in_sentence] = new KNP_kihonku_in_sentence(kihonku_num_in_sentence,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
                temp_2d_array_for_kihonku=[]
                kihonku_num_in_sentence++
            }else if( temp_surface_form == "*" ){
                //console.info(temp_2d_array_for_kihonku)
                this.kihonku_array[kihonku_num_in_sentence] = new KNP_kihonku_in_sentence(kihonku_num_in_sentence,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
                temp_2d_array_for_kihonku=[]
                kihonku_num_in_sentence++

                //console.info(temp_2d_array_for_bunsetsu)
                this.bunsetsu_array[bunsetsu_num_in_sentence] = new KNP_bunsetsu(bunsetsu_num_in_sentence,temp_2d_array_for_bunsetsu,KNP_character_array)//文の中の通し番号での文節array
                temp_2d_array_for_bunsetsu=[]
                bunsetsu_num_in_sentence++
            }
            temp_2d_array_for_bunsetsu.push(sentence_2d_array[temp_rowNo])
            temp_2d_array_for_kihonku.push(sentence_2d_array[temp_rowNo])
        }

        //console.log("bunsetsu_num_in_sentence %d",bunsetsu_num_in_sentence)
        //console.log(temp_2d_array_for_bunsetsu)
        this.bunsetsu_array[bunsetsu_num_in_sentence] = new KNP_bunsetsu(bunsetsu_num_in_sentence,temp_2d_array_for_bunsetsu,KNP_character_array)
        this.kihonku_array[kihonku_num_in_sentence] = new KNP_kihonku_in_sentence(kihonku_num_in_sentence,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
        /*
        raw_2d_array.forEach((row_array)=>{

        })
        */

        //最後に、掛かり先を探索して埋める
        this.input_each_kakarareru_bunsetsu_id();
        this.input_each_kakarareru_kihonku_id();
        console.log(raw_rowNo)
        console.log(this.bunsetsu_array)
    }

    input_each_kakarareru_bunsetsu_id () {
        //動詞なら、その動詞にかかるのを探していく
        this.bunsetsu_array.forEach((kakaru_bunsetsu)=>{
            for(let kakarareru_bunsetsu_num = 0 ; kakarareru_bunsetsu_num < this.bunsetsu_array.length ; kakarareru_bunsetsu_num++){

                //console.log(this.bunsetsu_array[kakarareru_bunsetsu_num])
                if(kakaru_bunsetsu.kakaru_bunsetsu_id == this.bunsetsu_array[kakarareru_bunsetsu_num].id){
                    this.bunsetsu_array[kakarareru_bunsetsu_num].kakarareru_bunsetsu_id_array.push(kakaru_bunsetsu.id)
                    //console.log(this.bunsetsu_array[kakarareru_bunsetsu_num])
                    break;
                }
            }
        })
    }

    input_each_kakarareru_kihonku_id(){
        this.kihonku_array.forEach((kakaru_kihonku)=>{
            //console.log(this.kihonku_array)
            for(let kakarareru_kihonku_num = 0 ; kakarareru_kihonku_num < this.kihonku_array.length ; kakarareru_kihonku_num++){
                //console.log(this.kihonku_array[kakarareru_kihonku_num])
                if(kakaru_kihonku.kakatu_kihonku_id == this.kihonku_array[kakarareru_kihonku_num].id){
                    this.kihonku_array[kakarareru_kihonku_num].kakarareru_kihonku_id_array.push(kakaru_kihonku.id)
                    //console.log(this.kihonku_array[kakarareru_kihonku_num])
                    break;
                }
            }
        })
    }
}

class KNP_bunsetsu {
    constructor(num,input_2d_array,KNP_character_array) {
        //console.log(input_2d_array)

        this.csv_raw_array=input_2d_array
        //this.rowNo=rowNo
        this.id = num+"D"

        this.kihonku_array=[]
        this.kihonku_array.length=count_kihonku(input_2d_array)

        this.word_array=[]

        /*
        if(this.word_array[0][3]=="動詞"){
            this.verb_data={}
        }
        */
        this.kakaru_bunsetsu_id = input_2d_array[0][1]
        this.kakarareru_bunsetsu_id_array = []
        this.surface_form = ""
        input_2d_array.forEach((row_array)=>{
            this.surface_form += row_array[0]
            this.word_array.push( new KNP_word(row_array) )
        })

        this.existsSubject=false
        this.existsObject=false
        this.isVerb=false

        this.make_kihonku_array_in_bunsetsu( input_2d_array )

        existsSubject(this,KNP_character_array)
        if(!this.existsSubject){
            existsObject(this,KNP_character_array)
            if(!this.existsSubject){
                find_verb(this)
            }
        }
    }

    make_kihonku_array_in_bunsetsu( bunsetsu_raw_2d_array ){
        let kihonku_num_in_bunsetsu = 0
        let temp_2d_array_for_kihonku=[]
        for( let temp_rowNo = 1 ; temp_rowNo < bunsetsu_raw_2d_array.length ; temp_rowNo++ ){
            if(temp_surface_form=="+"){//文節内 2こ目以降の基本句
                //console.info(temp_2d_array_for_kihonku)
                this.kihonku_array[kihonku_num_in_bunsetsu] = new KNP_kihonku_in_bunsetsu(kihonku_num_in_bunsetsu,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
                temp_2d_array_for_kihonku=[]
                kihonku_num_in_bunsetsu++
            }
            temp_2d_array_for_kihonku.push(bunsetsu_raw_2d_array[temp_rowNo])
        }
        this.kihonku_array[kihonku_num_in_bunsetsu] = new KNP_kihonku_in_bunsetsu(kihonku_num_in_bunsetsu,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
    }
}

class KNP_kihonku_in_sentence {
    constructor(num,input_2d_array) {
        //console.log(input_2d_array)

        this.csv_raw_array=input_2d_array
        //this.rowNo=rowNo
        this.id = num+"D"
        this.word_array=[]
        /*
        if(this.word_array[0][3]=="動詞"){
            this.verb_data={}
        }
        */
        this.kakaru_kihonku_id = input_2d_array[0][1]
        this.kakarareru_kihonku_id_array = []
        this.surface_form = ""
        input_2d_array.forEach((row_array)=>{
            this.surface_form += row_array[0]
        })
    }
}

class KNP_kihonku_in_bunsetsu {
    constructor(rowNo,row_array,upper_row_array) {

        this.csv_raw_array=[]
        this.rowNo=rowNo
        this.num = num+"D"
        this.word_array=[]
        if(this.word_array[0][3]=="動詞"){
            this.verb_data={}
        }

        this.subject = "null"
        this.object = "null"
        this.kakarareruNo = upper_row_array[1]
        this.kakaruNo = "null"
        this.surface_form = row_array[0]
    }
}

class KNP_word {
    constructor(row_array) {

        this.csv_raw_array=[]
        this.rowNo=rowNo
        this.hinshi=row_array[3]

    }
}

let existsSubject=(bunsetsu,KNP_character_array)=>{

    const bunsetsu_info_row = bunsetsu.csv_raw_array[0]
    const temp_character_name=bunsetsu.csv_raw_array[1][0]
    for(var col_num=0;col_num<bunsetsu_info_row.length;col_num++){
        if ( bunsetsu_info_row[col_num].match("ガ格")&&isCharacter(KNP_character_array,temp_character_name)) {
            bunsetsu.isSubject=true
            bunsetsu.subject=temp_character_name
            break;
        }
    }
}

let existsObject=(bunsetsu,KNP_character_array)=>{

    const bunsetsu_info_row = bunsetsu.csv_raw_array[0]
    const temp_character_name=bunsetsu.csv_raw_array[1][0]
    for(let col_num=0;col_num<bunsetsu_info_row.length;col_num++){
        if ( ( bunsetsu_info_row[col_num].match("ヲ格") || bunsetsu_info_row[col_num].match("ニ格") ) && isCharacter(KNP_character_array,temp_character_name) ) {
            bunsetsu.isObject=true
            bunsetsu.object=temp_character_name
            break;
        }
    }
}

let isCharacter=(KNP_character_array,temp_character_name)=>{
    KNP_character_array.forEach((character)=>{
        if(temp_character_name==character.name){
            return true
        }
    })
    return false
}

export {reconstruct_KNP}<commit_msg>add : maybe get hinshi<commit_after>/**
 * Created by uetsujitomoya on 2017/08/17.
 */

import　{find_verb_from_csv} from "find_verb.js"

let first_japanese_row_num_in_sentence = 3 ;
let starting_kihonku_row_num_in_sentence = 2 ;
let starting_bunsetsu_row_num_in_sentence = 1 ;

let reconstruct_KNP = (raw_2d_array,KNP_character_array) => {
    let KNP_sentence_array=[]
    let temp_sentence_2d_array=[]
    let temp_rowNo=0;
    raw_2d_array.forEach((row_array)=>{
        if(row_array[0]!="EOS"){
            temp_sentence_2d_array.push(row_array)
        }else{
            KNP_sentence_array.push(new KNP_sentence(temp_rowNo,temp_sentence_2d_array,KNP_character_array))
            temp_sentence_2d_array=[]
        }
        temp_rowNo++
    })
}

let count_bunsetsu=(input_2d_array)=>{
    let cnt=0
    input_2d_array.forEach((row_array)=>{
        if(row_array[0]=="*"){
            cnt++
        }
    })
    return cnt
}

let count_kihonku=(input_2d_array)=>{
    let cnt=0
    input_2d_array.forEach((row_array)=>{
        if(row_array[0]=="+"){
            cnt++
        }
    })
    return cnt
}

//文節取得
/*EODまでが一個の文
 アスタリスクが1個の文節 phtase_no
 プラスが1個の基本句　basic_phrase_no
 *2次元配列を4次元配列に組み替える
 * */

class KNP_sentence{
    constructor(raw_rowNo,sentence_2d_array,KNP_character_array) {
        //console.log("raw_rowNo %d",raw_rowNo)
        //console.log(sentence_2d_array)
        if(sentence_2d_array.length==1){
            return 0
        }//空白センテンス処理

        //動詞判定・登場人物判定と組み合わせる

        //PARAがかかる先は？

        //PARAの探索（3列目にPを含む文字列があればPARAがそこにあると判定し、文節配列と基本句配列にPARAを挿入）
        //そのためには、始めに文節配列・基本句配列のlengthだけ決めてしまったほうが良い

        //this.csv_raw_array=[]
        this.rowNo=raw_rowNo
        this.bunsetsu_array=[]
        this.bunsetsu_array.length=count_bunsetsu(sentence_2d_array)

        this.kihonku_array=[]
        this.kihonku_array.length=count_kihonku(sentence_2d_array)

        this.surface_form = "null"
        //this.basic_form = row_array[2]

        let temp_2d_array_for_bunsetsu=[]
        let temp_2d_array_for_kihonku=[]

        temp_2d_array_for_bunsetsu.push(sentence_2d_array[starting_bunsetsu_row_num_in_sentence])//0文節目　開始宣言をプッシュ

        temp_2d_array_for_bunsetsu.push(sentence_2d_array[starting_kihonku_row_num_in_sentence])//0基本句目　開始宣言をプッシュ
        temp_2d_array_for_kihonku.push(sentence_2d_array[starting_kihonku_row_num_in_sentence])//0基本句目　開始宣言をプッシュ

        let bunsetsu_num_in_sentence=0
        let kihonku_num_in_sentence=0

        for( let temp_rowNo = first_japanese_row_num_in_sentence ; temp_rowNo < sentence_2d_array.length ; temp_rowNo++ ){
            let temp_surface_form=sentence_2d_array[temp_rowNo][0];
            if(temp_surface_form=="+" && sentence_2d_array[temp_rowNo-1][0]!="*"){//文節内 2こ目以降の基本句
                //console.info(temp_2d_array_for_kihonku)
                this.kihonku_array[kihonku_num_in_sentence] = new KNP_kihonku_in_sentence(kihonku_num_in_sentence,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
                temp_2d_array_for_kihonku=[]
                kihonku_num_in_sentence++
            }else if( temp_surface_form == "*" ){
                //console.info(temp_2d_array_for_kihonku)
                this.kihonku_array[kihonku_num_in_sentence] = new KNP_kihonku_in_sentence(kihonku_num_in_sentence,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
                temp_2d_array_for_kihonku=[]
                kihonku_num_in_sentence++

                //console.info(temp_2d_array_for_bunsetsu)
                this.bunsetsu_array[bunsetsu_num_in_sentence] = new KNP_bunsetsu(bunsetsu_num_in_sentence,temp_2d_array_for_bunsetsu,KNP_character_array)//文の中の通し番号での文節array
                temp_2d_array_for_bunsetsu=[]
                bunsetsu_num_in_sentence++
            }
            temp_2d_array_for_bunsetsu.push(sentence_2d_array[temp_rowNo])
            temp_2d_array_for_kihonku.push(sentence_2d_array[temp_rowNo])
        }

        //console.log("bunsetsu_num_in_sentence %d",bunsetsu_num_in_sentence)
        //console.log(temp_2d_array_for_bunsetsu)
        this.bunsetsu_array[bunsetsu_num_in_sentence] = new KNP_bunsetsu(bunsetsu_num_in_sentence,temp_2d_array_for_bunsetsu,KNP_character_array)
        this.kihonku_array[kihonku_num_in_sentence] = new KNP_kihonku_in_sentence(kihonku_num_in_sentence,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
        /*
        raw_2d_array.forEach((row_array)=>{

        })
        */

        //最後に、掛かり先を探索して埋める
        this.input_each_kakarareru_bunsetsu_id();
        this.input_each_kakarareru_kihonku_id();
        console.log(raw_rowNo)
        console.log(this.bunsetsu_array)
    }

    input_each_kakarareru_bunsetsu_id () {
        //動詞なら、その動詞にかかるのを探していく
        this.bunsetsu_array.forEach((kakaru_bunsetsu)=>{
            for(let kakarareru_bunsetsu_num = 0 ; kakarareru_bunsetsu_num < this.bunsetsu_array.length ; kakarareru_bunsetsu_num++){

                //console.log(this.bunsetsu_array[kakarareru_bunsetsu_num])
                if(kakaru_bunsetsu.kakaru_bunsetsu_id == this.bunsetsu_array[kakarareru_bunsetsu_num].id){
                    this.bunsetsu_array[kakarareru_bunsetsu_num].kakarareru_bunsetsu_id_array.push(kakaru_bunsetsu.id)
                    //console.log(this.bunsetsu_array[kakarareru_bunsetsu_num])
                    break;
                }
            }
        })
    }

    input_each_kakarareru_kihonku_id(){
        this.kihonku_array.forEach((kakaru_kihonku)=>{
            //console.log(this.kihonku_array)
            for(let kakarareru_kihonku_num = 0 ; kakarareru_kihonku_num < this.kihonku_array.length ; kakarareru_kihonku_num++){
                //console.log(this.kihonku_array[kakarareru_kihonku_num])
                if(kakaru_kihonku.kakatu_kihonku_id == this.kihonku_array[kakarareru_kihonku_num].id){
                    this.kihonku_array[kakarareru_kihonku_num].kakarareru_kihonku_id_array.push(kakaru_kihonku.id)
                    //console.log(this.kihonku_array[kakarareru_kihonku_num])
                    break;
                }
            }
        })
    }
}

class KNP_bunsetsu {
    constructor(num,input_2d_array,KNP_character_array) {
        //console.log(input_2d_array)

        this.csv_raw_array=input_2d_array
        //this.rowNo=rowNo
        this.id = num+"D"

        this.kihonku_array=[]
        this.kihonku_array.length=count_kihonku(input_2d_array)

        this.word_array=[]

        /*
        if(this.word_array[0][3]=="動詞"){
            this.verb_data={}
        }
        */
        this.kakaru_bunsetsu_id = input_2d_array[0][1]
        this.kakarareru_bunsetsu_id_array = []
        this.surface_form = ""
        input_2d_array.forEach((row_array)=>{
            this.surface_form += row_array[0]
            this.word_array.push( new KNP_word(row_array) )
        })

        this.existsSubject=false
        this.existsObject=false
        this.isVerb=false

        this.make_kihonku_array_in_bunsetsu( input_2d_array )

        existsSubject(this,KNP_character_array)
        if(!this.existsSubject){
            existsObject(this,KNP_character_array)
            if(!this.existsSubject){
                find_verb(this)
            }
        }
    }

    make_kihonku_array_in_bunsetsu( bunsetsu_raw_2d_array ){
        let kihonku_num_in_bunsetsu = 0
        let temp_2d_array_for_kihonku=[]
        for( let temp_rowNo = 1 ; temp_rowNo < bunsetsu_raw_2d_array.length ; temp_rowNo++ ){
            if(temp_surface_form=="+"){//文節内 2こ目以降の基本句
                //console.info(temp_2d_array_for_kihonku)
                this.kihonku_array[kihonku_num_in_bunsetsu] = new KNP_kihonku_in_bunsetsu(kihonku_num_in_bunsetsu,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
                temp_2d_array_for_kihonku=[]
                kihonku_num_in_bunsetsu++
            }
            temp_2d_array_for_kihonku.push(bunsetsu_raw_2d_array[temp_rowNo])
        }
        this.kihonku_array[kihonku_num_in_bunsetsu] = new KNP_kihonku_in_bunsetsu(kihonku_num_in_bunsetsu,temp_2d_array_for_kihonku)//文の中の通し番号での基本句array
    }
}

class KNP_kihonku_in_sentence {
    constructor(num,input_2d_array) {
        //console.log(input_2d_array)

        this.csv_raw_array=input_2d_array
        //this.rowNo=rowNo
        this.id = num+"D"

        this.word_array=[]
        for(let rowNo =1;rowNo<row_array.length;rowNo++){
            this.word_array.push(new KNP_word(input_2d_array[rowNo]))
        }
        /*
        if(this.word_array[0][3]=="動詞"){
            this.verb_data={}
        }
        */
        this.kakaru_kihonku_id = input_2d_array[0][1]
        this.kakarareru_kihonku_id_array = []
        this.surface_form = ""
        input_2d_array.forEach((row_array)=>{
            this.surface_form += row_array[0]
        })
    }
}

class KNP_kihonku_in_bunsetsu {
    constructor(rowNo,row_array) {

        this.csv_raw_array=[]
        this.rowNo=rowNo
        //this.num = num+"D"
        this.word_array=[]
        for(let rowNo =1;rowNo<row_array.length;rowNo++){

        }
        if(this.word_array[0][3]=="動詞"){
            this.verb_data={}
        }

        this.subject = "null"
        this.object = "null"
        this.kakarareruNo = upper_row_array[1]
        this.kakaruNo = "null"
        this.surface_form = row_array[0]
    }
}

class KNP_word {
    constructor(row_array) {

        this.csv_raw_array=[]
        //this.rowNo=rowNo
        this.hinshi=row_array[3]

    }
}

let existsSubject=(bunsetsu,KNP_character_array)=>{

    const bunsetsu_info_row = bunsetsu.csv_raw_array[0]
    const temp_character_name=bunsetsu.csv_raw_array[1][0]
    for(var col_num=0;col_num<bunsetsu_info_row.length;col_num++){
        if ( bunsetsu_info_row[col_num].match("ガ格")&&isCharacter(KNP_character_array,temp_character_name)) {
            bunsetsu.isSubject=true
            bunsetsu.subject=temp_character_name
            break;
        }
    }
}

let existsObject=(bunsetsu,KNP_character_array)=>{

    const bunsetsu_info_row = bunsetsu.csv_raw_array[0]
    const temp_character_name=bunsetsu.csv_raw_array[1][0]
    for(let col_num=0;col_num<bunsetsu_info_row.length;col_num++){
        if ( ( bunsetsu_info_row[col_num].match("ヲ格") || bunsetsu_info_row[col_num].match("ニ格") ) && isCharacter(KNP_character_array,temp_character_name) ) {
            bunsetsu.isObject=true
            bunsetsu.object=temp_character_name
            break;
        }
    }
}

let isCharacter=(KNP_character_array,temp_character_name)=>{
    KNP_character_array.forEach((character)=>{
        if(temp_character_name==character.name){
            return true
        }
    })
    return false
}

export {reconstruct_KNP}<|endoftext|>