<commit_before>module.exports = function(RED) {
    'use strict';

    const Promise = require('bluebird');
    const Redmine = require('node-redmine');
    const _ = require('lodash');

    function IssuesNode(config) {
        RED.nodes.createNode(this,config);
        var node = this;
        var server = RED.nodes.getNode(config.server);

        var redmine = new Redmine(server.url, {apiKey: server.key});
        redmine = Promise.promisifyAll(redmine, {suffix:"_async"});

        // Issue ID
        function retrieveIssueId(msg, path) {
            return new Promise((resolve, reject) => {
                var issueIdStr = _.get(msg, path);
                if (!_.isNumber(issueIdStr) && !_.isString(issueIdStr)) {
                    reject(new Error(`msg.${path} must be a number`));
                } else {
                    var issueId = Number(issueIdStr);
                    if (issueId > 0) {
                        resolve(issueId);
                    } else {
                        reject(new Error("Invalid issue ID: " + issueIdStr));
                    }
                }
            });
        }

        // Parameters
        function retrieveParameters(msg, path) {
            return new Promise((resolve, reject) => {
                var params = _.get(msg, path);
                if (!_.isObject(params)) {
                    reject(new Error(`msg.${path} must be an object`));
                } else {
                    resolve(params);
                }
            });
        }

        // Include
        function retrieveIncludes(config) {
            return new Promise((resolve, reject) => {
                var result = null;
                const flags = {
                    includeChildren: "children",
                    includeAttachments: "attachments",
                    includeRelations: "relations",
                    includeChangesets: "changesets",
                    includeJournals: "journals",
                    includeWatchers: "watchers"
                };
                for (var p in flags) {
                    if (config[p]) {
                        if (result) {
                            result += ',' + flags[p];
                        } else {
                            result = flags[p];
                        }
                    }
                }
                resolve({include:result});
            });
        }

        const modes = {
            // Listing issues
            "list": function listIssues(msg) {
                node.status({fill:"blue", shape:"ring", text:"listing"});
                var allIssues = config.allIssues;
                return retrieveParameters(msg, config.paramsProperty)
                    .then(Promise.coroutine(function* (params) {
                        var issues = [],
                            total_count = 0;
                        do {
                            if (allIssues) {
                                params.limit = 100;
                                params.offset = issues.length;
                            }
                            let data = yield redmine.issues_async(params);
                            if (data && _.isArray(data.issues) && _.isNumber(data.total_count)) {
                                if (total_count == data.total_count || total_count === 0) {
                                    issues = _.concat(issues, data.issues);
                                    total_count = data.total_count;
                                } else {
                                    // Issues were added/deleted while fetching. Retry
                                    issues = [];
                                    total_count = 0;
                                }
                            }
                        } while (allIssues && issues.length < total_count);

                        msg.payload = issues;
                        msg.total_count = total_count;
                        return msg;
                    }));
            },

            // Showing an issue
            "get": function getIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"getting"});
                return Promise.all([
                    retrieveIssueId(msg, config.issueIdProperty),
                    retrieveIncludes(config)
                ])
                    .then((results) => redmine.get_issue_by_id_async(results[0], results[1]))
                    .then((data) => {
                        msg.payload = data.issue;
                        return msg;
                    });
            },

            // Creating an issue
            "create": function createIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"creating"});
                return retrieveParameters(msg, config.paramsProperty)
                    .then((params) => redmine.create_issue_async({issue:params}))
                    .then((data) => {
                        msg.payload = data.issue;
                        return msg;
                    });
            },

            // Updating an issue
            "update": function updateIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"updating"});
                return Promise.all([
                    retrieveIssueId(msg, config.issueIdProperty),
                    retrieveParameters(msg, config.paramsProperty)
                ])
                    .then((results) => redmine.update_issue_async(results[0], results[1]))
                    .then((data) => {
                        return msg;
                    });
            },

            // Deleting an issue
            "delete": function deleteIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"deleting"});
                return retrieveIssueId(msg, config.issueIdProperty)
                    .then((issueId) => redmine.delete_issue_async(issueId))
                    .then((data) => {
                        return msg;
                    });
            },

            // Adding a watcher
            "addWatcher": function addWatcher(msg) {
                node.status({fill:"blue", shape:"ring", text:"adding a watcher"});
                return retrieveIssueId(msg, config.issueIdProperty)
                    .then((issueId) => redmine.add_watcher_async(issueId, msg.payload))
                    .then((data) => {
                        return msg;
                    });
            },

            // Removing a watcher
            "removeWatcher": function removeWatcher(msg) {
                node.status({fill:"blue", shape:"ring", text:"removing a watcher"});
                return retrieveIssueId(msg, config.issueIdProperty)
                    .then((issueId) => redmine.remove_watcher_async(issueId, msg.user_id))
                    .then((data) => {
                        return msg;
                    });
            }
        };

        node.on('input', function(msg) {
            var func = modes[config.mode];
            if (!func) {
                return node.error(new Error("Illgal mode: " + config.mode), msg);
            }
            func(msg)
            .then(function (msg){
                node.send(msg);
                node.status({});
            })
            .catch(function (err) {
                node.error(err, msg);
                node.status({fill:"red", shape:"ring", text:"failed"});
            });
        });
    }
    RED.nodes.registerType("issues",IssuesNode);
}
<commit_msg>add impersonation functionarity<commit_after>module.exports = function(RED) {
    'use strict';

    const Promise = require('bluebird');
    const Redmine = require('node-redmine');
    const _ = require('lodash');

    function IssuesNode(config) {
        RED.nodes.createNode(this,config);
        var node = this;

        function createClient(config, msg) {
            var server = RED.nodes.getNode(config.server);
            var redmine = new Redmine(server.url, {
                apiKey: server.key,
                impersonate: _.get(msg, server.impersonate)
            });
            if (!_.hasIn(redmine, 'impersonate')) {
                Object.defineProperty(redmine, 'impersonate', {
                    get: function() {
                        return this.config.impersonate;
                    },
                    set: function(username) {
                        this.config.impersonate = username;
                    }
                });
            }
            return redmine;
        }

        // Issue ID
        function retrieveIssueId(msg, path) {
            return new Promise((resolve, reject) => {
                var issueIdStr = _.get(msg, path);
                if (!_.isNumber(issueIdStr) && !_.isString(issueIdStr)) {
                    reject(new Error(`msg.${path} must be a number`));
                } else {
                    var issueId = Number(issueIdStr);
                    if (issueId > 0) {
                        resolve(issueId);
                    } else {
                        reject(new Error("Invalid issue ID: " + issueIdStr));
                    }
                }
            });
        }

        // Parameters
        function retrieveParameters(msg, path) {
            return new Promise((resolve, reject) => {
                var params = _.get(msg, path);
                if (!_.isObject(params)) {
                    reject(new Error(`msg.${path} must be an object`));
                } else {
                    resolve(params);
                }
            });
        }

        // Include
        function retrieveIncludes(config) {
            return new Promise((resolve, reject) => {
                var result = null;
                const flags = {
                    includeChildren: "children",
                    includeAttachments: "attachments",
                    includeRelations: "relations",
                    includeChangesets: "changesets",
                    includeJournals: "journals",
                    includeWatchers: "watchers"
                };
                for (var p in flags) {
                    if (config[p]) {
                        if (result) {
                            result += ',' + flags[p];
                        } else {
                            result = flags[p];
                        }
                    }
                }
                resolve({include:result});
            });
        }

        const modes = {
            // Listing issues
            "list": function listIssues(msg) {
                node.status({fill:"blue", shape:"ring", text:"listing"});
                var allIssues = config.allIssues;
                return retrieveParameters(msg, config.paramsProperty)
                    .then(Promise.coroutine(function* (params) {
                        var redmine = createClient(config, msg),
                            issues = [],
                            total_count = 0;
                        if (allIssues) {
                            params.limit = 100;
                            params.offset = issues.length;
                        }
                        do {
                            let data = yield Promise.promisify(redmine.issues, {context: redmine})(params);
                            if (data && _.isArray(data.issues) && _.isNumber(data.total_count)) {
                                if (total_count == data.total_count || total_count === 0) {
                                    issues = _.concat(issues, data.issues);
                                    total_count = data.total_count;
                                } else {
                                    // Issues were added/deleted while fetching. Retry
                                    issues = [];
                                    total_count = 0;
                                }
                            }
                        } while (allIssues && issues.length < total_count);

                        msg.payload = issues;
                        msg.total_count = total_count;
                        return msg;
                    }));
            },

            // Showing an issue
            "get": function getIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"getting"});
                return Promise.all([
                    retrieveIssueId(msg, config.issueIdProperty),
                    retrieveIncludes(config)
                ])
                .then((results) => {
                    var redmine = createClient(config, msg);
                    return Promise.promisify(redmine.get_issue_by_id, {context: redmine})(results[0], results[1]);
                })
                .then((data) => {
                    msg.payload = data.issue;
                    return msg;
                });
            },

            // Creating an issue
            "create": function createIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"creating"});
                return retrieveParameters(msg, config.paramsProperty)
                    .then((params) => {
                        var redmine = createClient(config, msg);
                        return Promise.promisify(redmine.create_issue, {context: redmine})({issue:params});
                    })
                    .then((data) => {
                        msg.payload = data.issue;
                        return msg;
                    });
            },

            // Updating an issue
            "update": function updateIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"updating"});
                return Promise.all([
                    retrieveIssueId(msg, config.issueIdProperty),
                    retrieveParameters(msg, config.paramsProperty)
                ])
                .then((results) => {
                    var redmine = createClient(config, msg);
                    return Promise.promisify(redmine.update_issue, {context: redmine})(results[0], results[1]);
                })
                .then((data) => {
                    return msg;
                });
            },

            // Deleting an issue
            "delete": function deleteIssue(msg) {
                node.status({fill:"blue", shape:"ring", text:"deleting"});
                return retrieveIssueId(msg, config.issueIdProperty)
                    .then((issueId) => {
                        var redmine = createClient(config, msg);
                        return Promise.promisify(redmine.delete_issue, {context: redmine})(issueId);
                    })
                    .then((data) => {
                        return msg;
                    });
            },

            // Adding a watcher
            "addWatcher": function addWatcher(msg) {
                node.status({fill:"blue", shape:"ring", text:"adding a watcher"});
                return retrieveIssueId(msg, config.issueIdProperty)
                    .then((issueId) => {
                        var redmine = createClient(config, msg);
                        return Promise.promisify(redmine.add_watcher, {context: redmine})(issueId, msg.payload);
                    })
                    .then((data) => {
                        return msg;
                    });
            },

            // Removing a watcher
            "removeWatcher": function removeWatcher(msg) {
                node.status({fill:"blue", shape:"ring", text:"removing a watcher"});
                return retrieveIssueId(msg, config.issueIdProperty)
                    .then((issueId) => {
                        var redmine = createClient(config, msg);
                        return Promise.promisify(redmine.remove_watcher, {context: redmine})(issueId, msg.user_id);
                    })
                    .then((data) => {
                        return msg;
                    });
            }
        };

        node.on('input', function(msg) {
            var func = modes[config.mode];
            if (!func) {
                return node.error(new Error("Illgal mode: " + config.mode), msg);
            }
            func(msg)
            .then(function (msg){
                node.send(msg);
                node.status({});
            })
            .catch(function (err) {
                node.error(err, msg);
                node.status({fill:"red", shape:"ring", text:"failed"});
            });
        });
    }
    RED.nodes.registerType("issues",IssuesNode);
}
<|endoftext|>


<commit_before>var post_top_url = "/api/v1/post/?limit=5&offset=40";
var post_bottom_url = "/api/v1/post/";
var comment_offsets = new Object();
var isBottominit = 0;

function writeComment() {
    $('#form_comment').submit(function(event) {
        var feedback_api = "/api/v1/comment/";
        var data = JSON.stringify({
            "comment": $("input[name=comment]").val(),
            "post_key": $("input[name=post_key]").val()
        });
        console.log(data);
        $.ajax({
            url: feedback_api,
            type: "POST",
            contentType: "application/json",
            data: data,
            dataType: "json",
            statusCode: {
                201: function(data) {
                    console.log("post submit response");
                    console.log(data);
                }
            }
        });
        return false;
    });
};

function focusComment(){
    $(".p_commentList").waypoint(function(){
        var tagid = $(this).attr("id");
        console.log(tagid);
        var postid = tagid.replace("commentList", "");
        (function poll() {
            console.log(postid);
            setTimeout(function(){$.ajax({complete:poll()});pollComment(postid);}, 5000);
        })();
    }, { offset: "bottom-in-view"});
}

function pollComment(post_id) {
    if(!post_id)
        return;

    get_uri = "/api/v1/comment/?post=" + post_id; // api inner parameter ?limit=20&offset=0"

    if(comment_offsets[post_id]){
        console.log("use offset in comment polling  " + comment_offsets[post_id]);
        get_uri = "/api/v1/comment/?limit=5&offset=" + comment_offsets[post_id];
    }
    $.ajax({
        url: get_uri,
        type: "GET",
        dataType: "json",
        success: function(data) {
            console.log("polling comment");
            console.log(data);
            if(data.objects.length != 0)
            {
                $("#comment_template").tmpl(data.objects).appendTo("#commentList"+post_id);
                comment_offsets[post_id] = data.meta.offset + data.objects.length;
                console.log("오프셋"+comment_offsets[post_id]);
                console.log("comment polling done "+comment_offsets[post_id]);
            }
        }
        });
}
$("#form_post").submit(function(event) {
    alert("@");
    var feedback_api = "/api/v1/post/";
    var data = JSON.stringify({
        "post": $("input[name=post]").val()
    });
    console.log(data);
    $.ajax({
        url: feedback_api,
        type: "POST",
        contentType: "application/json",
        data: data,
        dataType: "json",
        statusCode: {
            201: function(data) {
                /*post로 생성 후 생성한 json response*/
                console.log("post submit response");
                console.log(data);
//                $('#post_public_template').tmpl(data).prependTo('#timeline');
            }
        }
    });
    return false;
});

function timelineRefresh() {
    $.ajax({
        url: post_top_url,
        type: "GET",
        dataType: "json",
        success: function(data) {
            console.log("TTTTTTTTTTTT polling post" + post_top_url);
            console.log(data)
            if(data.objects.length != 0)
            {
                $("#post_public_template").tmpl(data.objects.reverse()).prependTo("#timeline");
                $.waypoints('refresh');
                writeComment();
                $(".p_responses").click(function(){
                    $(this).parent().children("section").toggle();
                    $(this).toggleClass("opened");
                    return false;
                });
                post_top_url = data.meta.next;
                if(!post_top_url)
                    post_top_url = "api/v1/post/?limit=20&offset=" + (data.meta.offset+data.objects.length);
                if(isBottominit==0) {
                    post_bottom_url = data.meta.previous;
                    console.log(post_bottom_url);
                    isBottominit = 1;
                }
                focusComment();
            }
        }
        });
}

/* post polling */
$(document).ready(function() {
  timelineRefresh();
  (function poll() {
    setTimeout(function(){$.ajax({complete:poll()});timelineRefresh();}, 5000);
  })();
  $("#p_timeline").waypoint(function(){console.log("start bottom   "+post_bottom_url);postBottom();}, { offset: 'bottom-in-view' });

});

function postBottom() {
    if(!post_bottom_url)
        return;
    $.ajax({
        url: post_bottom_url,
        type: "GET",
        dataType: "json",
        success: function(data) {
            if(data.objects.length != 0)
            {
                $("#post_public_template").tmpl(data.objects.reverse()).appendTo("#timeline");
                $(".p_responses").click(function(){
                    $(this).parent().children("section").toggle();
                    $(this).toggleClass("opened");
                    return false;
                });
                writeComment();
                post_bottom_url = data.meta.previous;
                console.log("BBBBBBBBBB polling post" + post_bottom_url);
            }
        }
        });
}

<commit_msg>js 정리 - comment polling 정지<commit_after>var post_top_url = "/api/v1/friendposts/?limit=5&offset=40";
var post_bottom_url = "/api/v1/friendposts/";
var comment_offsets = new Object();
var isBottominit = 0;

// post create
$("#form_post").submit(function(event) {
    alert("@");
    var feedback_api = "/api/v1/post/";
    var data = JSON.stringify({
        "post": $("input[name=post]").val()
    });
    console.log(data);
    $.ajax({
        url: feedback_api,
        type: "POST",
        contentType: "application/json",
        data: data,
        dataType: "json",
        statusCode: {
            201: function(data) {
                /*post로 생성 후 생성한 json response*/
                console.log("post submit response");
                console.log(data);
            }
        }
    });
    return false;
});

// comment create
$(document).on("submit", "#form_comment",function(event) {
        var feedback_api = "/api/v1/comment/";
        var data = JSON.stringify({
            "comment": $("input[name=comment]").val(),
            "post_key": $("input[name=post_key]").val()
        });
        console.log(data);
        $.ajax({
            url: feedback_api,
            type: "POST",
            contentType: "application/json",
            data: data,
            dataType: "json",
            statusCode: {
                201: function(data) {
                    console.log("post submit response");
                    console.log(data);
                    pollComment($("input[name=post_key]").val());
                }
            }
        });
        return false;
});

// polling post
function PostTopPolling() {
    $.ajax({
        url: post_top_url,
        type: "GET",
        dataType: "json",
        success: function(data) {
            console.log("TOP POLL POST  url:" + post_top_url);
            console.log(data)
            if(data.objects.length != 0)
            {
                $("#post_public_template").tmpl(data.objects.reverse()).prependTo("#timeline");
                $.waypoints('refresh');
                post_top_url = data.meta.next;
                if(!post_top_url)
                    post_top_url = "api/v1/post/?limit=20&offset=" + (data.meta.offset+data.objects.length);
                if(isBottominit==0) {
                    post_bottom_url = data.meta.previous;
                    console.log("previous url init "+post_bottom_url);
                    isBottominit = 1;
                }
//                focusComment();
            }
        }
        });
}

// when screen on top, call PostTopPolling
$(document).ready(function() {
  PostTopPolling();
  $("#p_timeline").waypoint(function(){postBottom();}, { offset: 'bottom-in-view' });
  $("#p_timeline").waypoint(function(){
  (function poll() {
    setTimeout(function(){PostTopPolling();$.ajax({complete:poll()});}, 5000);
  })()}, { offset: '0' })
});

function postBottom() {
    if(!post_bottom_url)
        return;
    $.ajax({
        url: post_bottom_url,
        type: "GET",
        dataType: "json",
        success: function(data) {
            if(data.objects.length != 0)
            {
                $("#post_public_template").tmpl(data.objects.reverse()).appendTo("#timeline");
                post_bottom_url = data.meta.previous;
                console.log("BOTTOM POLL POST   url:" + post_bottom_url);
            }
        }
        });
}

// when on post, call pollComment
function focusComment(){
    $(".p_commentList").waypoint(function(){
        var tagid = $(this).attr("id");
        if (!tagid)
            return false;
        var postid = tagid.replace("commentList", "");
        pollComment(postid);
        (function poll() {
            console.log(postid);
            setTimeout(function(){$.ajax({complete:poll()});pollComment(postid);}, 60000);
        })();
    }, { offset: "bottom-in-view"});
}

$(document).on("waypoint", { offset: "bottom-in-view"}, ".p_commentList", function(){
    var tagid = $(this).attr("id");
        if (!tagid)
            return false;
        var postid = tagid.replace("commentList", "");
        pollComment(postid);
        (function poll() {
            console.log(postid);
            setTimeout(function(){$.ajax({complete:poll()});pollComment(postid);}, 60000);
        })();
})

// polling comment
function pollComment(post_id) {
    if(!post_id)
        return;

    get_uri = "/api/v1/comment/?post=" + post_id; // api inner parameter ?limit=20&offset=0"

    if(comment_offsets[post_id]){
        get_uri = "/api/v1/comment/?limit=30&offset=" + comment_offsets[post_id];
    }
    $.ajax({
        url: get_uri,
        type: "GET",
        dataType: "json",
        success: function(data) {
            if(data.objects.length != 0)
            {
                $("#comment_template").tmpl(data.objects).appendTo("#commentList"+post_id);
                comment_offsets[post_id] = data.meta.offset + data.objects.length;
                console.log("댓글 폴링한 마지막 오프셋 :"+comment_offsets[post_id]);
            }
        }
        });
}

// comment toggle
$(document).on("click", ".p_responses", function(){
                    $(this).parent().children("section").toggle();
                    $(this).toggleClass("opened");
                    return false;
                });<|endoftext|>


<commit_before>app.controller('pairView', function(pair, readyForUpload, $scope, $state, $stateParams, $location, $window, pairService, $rootScope) {
	$window.scrollTo(0, 0);
	$scope.pair = pair;
	$scope.sharingConfig = {};

	var actor = pair.get('actor');
	var scenario = pair.get('scenario');
	$scope.actorId = actor.id;
	$scope.scenarioId = scenario.id;

	//set meta title
	$state.current.title = [actor.get('text'),
	                        scenario.get('text')].join(' ');
	$scope.title = $state.current.title;

	// set meta description
	$state.current.description = ['"',
	                              $state.current.title,
	                              '" ',
	                              'is a pair of cards that might be added to God Hates Charades.'].join('');

	$scope.sharingConfig.title = $state.current.title;

	$scope.uploadTitle = ['Watch me act like "',
	                      $state.current.title,
	                      '"'].join('');
	$scope.uploadDescription = ['I just acted out a scene from God Hates Charades: The Game that makes your friends funny! I\'m acting as "',
	                            $state.current.title,
	                            '"\n',
	                            'Check out the game on Kickstarter right now! http://bit.ly/godhatescharades \n',
	                            'Vote on cards or record your own vide on godhatescharades.com',].join('');
	$scope.uploadKeywords = [pair.id,
	                         '"God Hates Charades"',
	                         '"Party Game"',
	                         'Acting',
	                         'Actor',
	                         'Scenario'];

	// DISQUS
	$scope.disqus = {
		shortname: 'godhatescharades',
		id: $stateParams.pairId,
		url: 'http://godhatescharades.com' + $location.url()
	};
});<commit_msg>fixed the url in the video description<commit_after>app.controller('pairView', function(pair, readyForUpload, $scope, $state, $stateParams, $location, $window, pairService, $rootScope) {
	$window.scrollTo(0, 0);
	$scope.pair = pair;
	$scope.sharingConfig = {};

	var actor = pair.get('actor');
	var scenario = pair.get('scenario');
	$scope.actorId = actor.id;
	$scope.scenarioId = scenario.id;

	//set meta title
	$state.current.title = [actor.get('text'),
	                        scenario.get('text')].join(' ');
	$scope.title = $state.current.title;

	// set meta description
	$state.current.description = ['"',
	                              $state.current.title,
	                              '" ',
	                              'is a pair of cards that might be added to God Hates Charades.'].join('');

	$scope.sharingConfig.title = $state.current.title;

	$scope.uploadTitle = ['Watch me act like "',
	                      $state.current.title,
	                      '"'].join('');
	$scope.uploadDescription = ['I just acted out a scene from God Hates Charades: The Game that makes your friends funny! I\'m acting as "',
	                            $state.current.title,
	                            '"\n\n',
	                            'Check out the game on Kickstarter right now! http://bit.ly/godhatescharades \n\n',
	                            'Vote on cards or record your own vide on http://godhatescharades.com',].join('');
	$scope.uploadKeywords = [pair.id,
	                         '"God Hates Charades"',
	                         '"Party Game"',
	                         'Acting',
	                         'Actor',
	                         'Scenario'];

	// DISQUS
	$scope.disqus = {
		shortname: 'godhatescharades',
		id: $stateParams.pairId,
		url: 'http://godhatescharades.com' + $location.url()
	};
});<|endoftext|>


<commit_before>timelineModel = {
    currentDate: ko.observable(new Date(0))
};

function setSyncDate() {
    window.first_date = timelineModel.currentDate();
    window.nextSync = window.first_date;
    window.nextSync.setMonth(window.nextSync.getMonth() + 1);
    window.nextSync.setDate(1);
    window.nextSyncStr = window.nextSync.getFullYear() + '-' + (window.nextSync.getMonth() + 1) + '-' + window.nextSync.getDate();
    window.id_elem = 'plen';
}

function check_events() {
    var tmp_events_calendar = window.calendar;
    $(tmp_events_calendar).each(function (i) {
        var conv_date = new Date(tmp_events_calendar[i].date);
        if (conv_date - timelineModel.currentDate() === 0) {
            $('#pause').click();
            tmp_event = tmp_events_calendar[i].events
            $(tmp_event).each(function (j) {
                //alert("Event #"+tmp_event[j].incdt_id+" happend!");
                display_event(tmp_event[j].incdt_id, tmp_event[j].cost);
                submit_event(str_date);
            })
            $('.incident_page').click();

        }

    })

}

function submit_event(date) {
    var request = $.ajax({
        url: "/api/chronos/event",
        type: "POST",
        data: JSON.stringify({date: date}),
        success: function (response) {
            console.log("success: " + response.messages[0]);
        },
        error: function (response) {
            console.log("fail: " + response.messages[0]);
        }
    });
}

function submit_change() { // need different event handling, to capture any change
    var msg = {
        date: $.datepicker.formatDate($.datepicker.ISO_8601, timelineModel.currentDate),
        policyUpdate: []
    };
    if (policyUpdate.length > 0) {
        msg.policyUpdate = policyUpdate;
        //msg.newCosts = calculate_cost_from_calendar();
    }
    msg.initPolicy = true;
    console.log(msg);
    statusUpdating();
    var request = $.ajax({
        url: "/api/chronos/update",
        type: "POST",
        data: JSON.stringify(msg),
        success: update_policy,
        error: function (response) {
            console.log("fail: " + response.responseText);
        }
    });
    return false;
}

function resume() {
    statusUpdating();
    var request = $.ajax({
        url: "/api/chronos/resume",
        type: "GET",
        success: function (policy) {
            policyUpdate = [];
            statusReady();
            $('#pause').click();
            timelineModel.currentDate($.datepicker.parseDate($.datepicker.ISO_8601, policy['date']))
            window.calendar = policy['calendar'];
            setSyncDate();
            display_contextualized_policy(policy['policy'][0]);
        },
        error: function (response) {
            console.log("fail: " + response.responseText);
        }
    });
    return false;
}

startTimer = function (interval) {
    console.log("timer started");
    if (window.timer1 != null) pauseInterval();
    window.timer1 = setInterval(function () {
        var tmp = timelineModel.currentDate();
        var addHours = 24;
        var addDays = 1;

        //tmp.setDate(tmp.getDate()+addDays);
        tmp.setHours(tmp.getHours() + addHours);

        timelineModel.currentDate(tmp);

        check_events();
        if ($.datepicker.formatDate($.datepicker.ISO_8601, tmp) == window.nextSyncStr) {
            toastr['success']("Changes submitted");
            $('#pause').click();
            window.first_date = tmp;
            window.nextSync = window.first_date;
            window.nextSync.setMonth(window.nextSync.getMonth() + 2);
            window.nextSync.setDate(1);
            window.nextSyncStr = window.nextSync.getFullYear() + '-' + window.nextSync.getMonth() + '-' + window.nextSync.getDate();
            submit_change();
        }
        //script for interactive characters
        UpdateCharacters($.datepicker.formatDate($.datepicker.ISO_8601, timelineModel.currentDate())); //specified in characters.js

    }, interval);
    return false;
}

pauseInterval = function () {
    clearInterval(window.timer1);
}

$(function () {
    ko.applyBindings(timelineModel, document.getElementById('timeline'));

    timelineModel.currentDate.subscribe(function () {
        if (timelineModel.currentDate - new Date('2014-2-1') < 0) {
            //console.log('less than 1 month passed. Score is not yet calculated, hide button');
            $(".score_page").css("display", "none");
        } else {
            //console.log('>=1 month passed. Score is calculated, show button.');
            $(".score_page").css("display", "block");
        }
        $(".incident_page").css("display", "none");
    })

})

function format_date(date) {
    return $.datepicker.formatDate($.datepicker.RFC_1123, date)
}<commit_msg>Fixed major bug with dates<commit_after>timelineModel = {
    currentDate: ko.observable(new Date(0))
};

function setSyncDate() {
    window.nextSync = new Date(timelineModel.currentDate());
    window.nextSync.setMonth(window.nextSync.getMonth() + 1);
    window.nextSync.setDate(1);
    window.id_elem = 'plen';
}

function check_events() {
    var tmp_events_calendar = window.calendar;
    $(tmp_events_calendar).each(function (i) {
        var conv_date = new Date(tmp_events_calendar[i].date);
        if (conv_date - timelineModel.currentDate() === 0) {
            $('#pause').click();
            tmp_event = tmp_events_calendar[i].events
            $(tmp_event).each(function (j) {
                display_event(tmp_event[j].incdt_id, tmp_event[j].cost);
                submit_event(str_date);
            })
            $('.incident_page').click();

        }
    })
}

function submit_event(date) {
    $.ajax({
        url: "/api/chronos/event",
        type: "POST",
        data: JSON.stringify({date: date}),
        success: function (response) {
            console.log("success: " + response.messages[0]);
        },
        error: function (response) {
            console.log("fail: " + response.messages[0]);
        }
    });
}

function submit_change() { // need different event handling, to capture any change
    var msg = {
        date: $.datepicker.formatDate($.datepicker.ISO_8601, timelineModel.currentDate()),
        policyUpdate: []
    };
    if (policyUpdate.length > 0) {
        msg.policyUpdate = policyUpdate;
        //msg.newCosts = calculate_cost_from_calendar();
    }
    msg.initPolicy = true;
    console.log(msg);
    statusUpdating();
    var request = $.ajax({
        url: "/api/chronos/update",
        type: "POST",
        data: JSON.stringify(msg),
        success: update_policy,
        error: function (response) {
            console.log("fail: " + response.responseText);
        }
    });
    return false;
}

function resume() {
    statusUpdating();
    var request = $.ajax({
        url: "/api/chronos/resume",
        type: "GET",
        success: function (policy) {
            policyUpdate = [];
            statusReady();
            $('#pause').click();
            timelineModel.currentDate($.datepicker.parseDate($.datepicker.ISO_8601, policy['date']))
            window.calendar = policy['calendar'];
            setSyncDate();
            display_contextualized_policy(policy['policy'][0]);
        },
        error: function (response) {
            console.log("fail: " + response.responseText);
        }
    });
    return false;
}

startTimer = function (interval) {
    console.log("timer started");
    if (window.timer1 != null) pauseInterval();
    window.timer1 = setInterval(function () {
        var tmp = timelineModel.currentDate();

        tmp.setDate(tmp.getDate()+1);

        timelineModel.currentDate(tmp);

        check_events();
        if (timelineModel.currentDate() - window.nextSync === 0) {
            toastr['success']("Changes submitted");
            $('#pause').click();
            window.nextSync = new Date(timelineModel.currentDate());
            window.nextSync.setMonth(window.nextSync.getMonth() + 2);
            window.nextSync.setDate(1);

            submit_change();
        }
        //script for interactive characters
        UpdateCharacters($.datepicker.formatDate($.datepicker.ISO_8601, timelineModel.currentDate())); //specified in characters.js

    }, interval);
    return false;
}

pauseInterval = function () {
    clearInterval(window.timer1);
}

$(function () {
    ko.applyBindings(timelineModel, document.getElementById('timeline'));

    timelineModel.currentDate.subscribe(function () {
        if (timelineModel.currentDate - new Date('2014-2-1') < 0) {
            //console.log('less than 1 month passed. Score is not yet calculated, hide button');
            $(".score_page").css("display", "none");
        } else {
            //console.log('>=1 month passed. Score is calculated, show button.');
            $(".score_page").css("display", "block");
        }
        $(".incident_page").css("display", "none");
    })

})

function format_date(date) {
    return $.datepicker.formatDate($.datepicker.RFC_1123, date)
}<|endoftext|>


<commit_before>'use strict';
var request = require('request');
var fs = require('fs');
var Job = require('../../lib/models/job');
var _ = require('underscore');
var location = __dirname;

module.exports = {
  config: {},
  routes: function (app, context) {
    app.get('/report', function (req, res) {
      var org = req.params.org;
      var repo = req.params.repo;
      var branch = req.query.branch;
      var protocol = req.protocol;
      var hostName = req.get('Host');
      var project = org + '/' + repo;
      var jobsEndpoint = protocol + '://' + hostName + '/' + org + '/' + repo + '/jobs';
      var options = {
        limit: 1,
        sort: [['finished', 'desc']]
      };
      Job.find({ project: project, archived: null}, options, function(err, docs){
        var id = docs[0]._id;
        var home = process.env.HOME;
        var coverageLocation = home + '/.strider/data/'+ org + '-' + repo + '-' + branch + '/job-' + id +'/coverage';
        fs.readdir(coverageLocation, function (err, file) {
          var promises = [];
          var valid = [];
          _.each(file, function (item) {
            var index = item.indexOf('.');
            if (index !== -1) {
              var extension = item.substr(index, item.length);
              valid.push(extension);

              // if (extension === 'js' || extension === 'html' || extension === 'css') {
              //   valid.push(item);
              // }
            }
          });
          res.send(valid);
        });
        //   _.each(valid, function (item) {
        //     var temp = (function (src) {
        //       return new Promise(function (resolve, reject) {
        //         fs.readFile(src, function (err, data) {
        //           var returnData = '';
        //           switch(extension){
        //             case 'js':
        //               returnData = '<script>' + data + '</script>';
        //               break;
        //             case 'css':
        //               returnData = '<style>' + data + '</style>';
        //               break;
        //             default:
        //               returnData = data;
        //           }
        //           resolve(returnData);
        //         });
        //       });
        //     })(item);
        //     promises.push(temp);
        //   });
        //   Promise.all(promises).then(function(finalStrings){
        //     var fileStrings = '';
        //     _.each(finalStrings, function (item) {
        //       fileStrings += item;
        //     });
        //     res.send(fileStrings);
        //   });
        // });
      });
      // request({url: jobsEndpoint}, function (er, response, body) {
      //   var myCookie = request.cookie(response.headers['set-cookie'][0]);
      //   var cookieJar = request.jar();
      //   cookieJar.setCookie(myCookie, jobsEndpoint);
      //   request({url: jobsEndpoint, jar: cookieJar}, function(err, response, body){
      //     res.send(body);
      //   });
      // });

      // res.json({user: req.session});

      // res.json({yes: app});
      // var jobsEndpoint = protocol + '://' + hostName + '/' + org + '/' + repo + '/jobs';
      // console.log('BODY', body);
      // var latestJobId = JSON.parse(body)[0];
    });
  },
  globalRoutes: function (app, context) {
    app.get('/report', function (req, res) {
      res.json({context: context});
    });
  }
};
<commit_msg>reports endpoint<commit_after>'use strict';
var request = require('request');
var fs = require('fs');
var Job = require('../../lib/models/job');
var _ = require('underscore');
var location = __dirname;

module.exports = {
  config: {},
  routes: function (app, context) {
    app.get('/report', function (req, res) {
      var org = req.params.org;
      var repo = req.params.repo;
      var branch = req.query.branch;
      var protocol = req.protocol;
      var hostName = req.get('Host');
      var project = org + '/' + repo;
      var jobsEndpoint = protocol + '://' + hostName + '/' + org + '/' + repo + '/jobs';
      var options = {
        limit: 1,
        sort: [['finished', 'desc']]
      };
      Job.find({ project: project, archived: null}, options, function(err, docs){
        var id = docs[0]._id;
        var home = process.env.HOME;
        var coverageLocation = home + '/.strider/data/'+ org + '-' + repo + '-' + branch + '/job-' + id +'/coverage';
        fs.readdir(coverageLocation, function (err, file) {
          var promises = [];
          var valid = [];
          _.each(file, function (item) {
            var index = item.indexOf('.');
            if (index !== -1) {
              var extension = item.substr(index, item.length);
              if (extension === '.js' || extension === '.html' || extension === '.css') {
                valid.push(item);
              }
            }
          });
          res.send(valid);
        });
        //   _.each(valid, function (item) {
        //     var temp = (function (src) {
        //       return new Promise(function (resolve, reject) {
        //         fs.readFile(src, function (err, data) {
        //           var returnData = '';
        //           switch(extension){
        //             case 'js':
        //               returnData = '<script>' + data + '</script>';
        //               break;
        //             case 'css':
        //               returnData = '<style>' + data + '</style>';
        //               break;
        //             default:
        //               returnData = data;
        //           }
        //           resolve(returnData);
        //         });
        //       });
        //     })(item);
        //     promises.push(temp);
        //   });
        //   Promise.all(promises).then(function(finalStrings){
        //     var fileStrings = '';
        //     _.each(finalStrings, function (item) {
        //       fileStrings += item;
        //     });
        //     res.send(fileStrings);
        //   });
        // });
      });
      // request({url: jobsEndpoint}, function (er, response, body) {
      //   var myCookie = request.cookie(response.headers['set-cookie'][0]);
      //   var cookieJar = request.jar();
      //   cookieJar.setCookie(myCookie, jobsEndpoint);
      //   request({url: jobsEndpoint, jar: cookieJar}, function(err, response, body){
      //     res.send(body);
      //   });
      // });

      // res.json({user: req.session});

      // res.json({yes: app});
      // var jobsEndpoint = protocol + '://' + hostName + '/' + org + '/' + repo + '/jobs';
      // console.log('BODY', body);
      // var latestJobId = JSON.parse(body)[0];
    });
  },
  globalRoutes: function (app, context) {
    app.get('/report', function (req, res) {
      res.json({context: context});
    });
  }
};
<|endoftext|>


<commit_before>
var browserify = require('browserify');
console.log('browserify=',browserify);

var Writable = require('stream').Writable;

process.stdout = new Writable();
process.stderr = new Writable();

process.stdout.write = function() {
  console.log('STDOUT', arguments);
};
process.stderr.write = function() {
  console.log('STDERR', arguments);
};

process.binding = function() {
  return {fs: ''}
};

process.argv = ['npm'];

var npm = require('npm');
console.log('npm=',npm);

npm.load();
npm.commands.install();
<commit_msg>stderr to console.warn, stdout to console.log<commit_after>
var browserify = require('browserify');
console.log('browserify=',browserify);

var Writable = require('stream').Writable;

process.stdout = new Writable();
process.stderr = new Writable();

process.stdout.write = function() {
  console.log.apply(console, arguments);
};
process.stderr.write = function() {
  console.warn.apply(console, arguments);
};

process.binding = function() {
  return {fs: ''}
};

process.argv = ['npm'];

var npm = require('npm');
console.log('npm=',npm);

npm.load();
npm.commands.install();
<|endoftext|>


<commit_before>/**
 * fsLocal.js -- Ares FileSystem (fs) provider, using local files.
 *
 * This FileSystemProvider is both the simplest possible one
 * and a working sample for other implementations.
 */

// modules requirements

var fs = require("fs");
var path = require("path");
var express = require("express");
var util  = require('util');

// command-line arguments

function FsLocal(config, next) {

	/**
	 * Express server instance
	 *
	 * @private
	 */
	var app = express.createServer();

	app.use(express.logger('dev'));

	// Security
	app.use(cors);
	//app.use(express.cookieParser());
	app.use(function(req, res, next) {
		debugger;
		console.log("authenticating...");
		if (req.connection.remoteAddress !== "127.0.0.1") {
			fail(res, "Access denied from IP address "+req.connection.remoteAddress);
		} else {
			next()
		}
	});

	app.use(function(req, res, next) {
		debugger;
		console.log("originalMethod/method = "+req.originalMethod+"/"+req.method);
		req.originalMethod = req.method;
		if (req.query._method) {
			req.method = req.query._method.toUpperCase();
		}
		console.log("originalMethod/method = "+req.originalMethod+"/"+req.method);
		if (!verbs[req.originalMethod] ||
		    !verbs[req.originalMethod][req.method]) {
			next("unknown originalMethod/method = "+req.originalMethod+"/"+req.method);
		} else {
			next();
		}
	});

	//app.use(express.bodyParser()); // parses json, x-www-form-urlencoded, and multipart/form-data
	//app.enable('strict routing'); // XXX what for?

	app.all(config.urlPrefix, function(req, res) {
		res.redirect(config.urlPrefix +
			     '/' + encodeFileId('/') +
			    "?_method=PROPFIND");
	});
	app.all(config.urlPrefix + '/:id', function(req, res, next) {
		debugger;
		console.log("parsing parameters...");
		req.params.root = config.root;
		req.params.id = req.params.id || encodeFileId('/');
		req.params.path = decodeFileId(req.params.id);
		req.params.localPath = path.resolve(path.join(req.params.root, req.params.path));
		req.params.depth = parseInt(req.param('depth'), 10) || 0;
		console.log("req.params=");
		console.dir(req.params);
		verbs[req.originalMethod][req.method](req, res, respond.bind(this, res));
	});

	// start the filesystem (fs) server & notify the IDE server
	// (parent) where to find it

	app.listen(config.port, "127.0.0.1", null /*backlog*/, function() {
		// Send back the URL to the IDE server, when port is
		// actually bound
		var service = {
			url: "http://127.0.0.1:"+app.address().port.toString()+config.urlPrefix
		};
		return next(null, service);
	});

	/**
	 * Terminates express server
	 */
	this.quit = function() {
		app.close();
	};

	// utilities library

	function cors(req, res, next) {
		res.header('Access-Control-Allow-Origin', "*");
		res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
		res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
		if ('OPTIONS' == req.method) {
			res.send(200);
		}
		else {
			next();
		}
	}

	function encodeFileId(relPath) {
		if (relPath) {
			return encodeURIComponent(relPath);
		} else {
			return undefined;
		}
	}

	function decodeFileId(id) {
		if (id) {
			return decodeURIComponent(id);
		} else {
			return undefined;
		}
	}

	function respond(res, err, data) {
		if (err) {
			return fail(res, err);
		} else {
			return success(res, data);
		}
	}

	function success(res, data) {
		if (data) {
			res.status(200).send(data);
		} else {
			res.status(200);
			res.end();
		}
	}

	function fail(res, err, code) {
		if (err instanceof Error) {
			console.error(err.stack);
			res.send(err.stack, code ? code : 500);
		} else {
			console.error(err);
			res.send(JSON.stringify({error: err}), code ? code: 403);
		}
	}

	// Served files

	var _mimeTypes = {
		"html": "text/html",
		"jpeg": "image/jpeg",
		"jpg": "image/jpeg",
		"png": "image/png",
		"js": "text/javascript",
		"css": "text/css"
	};

	// File-System (fs) verbs

	var verbs = {
		GET: {}, 	// verbs that are transmitted over an HTTP GET method
		POST: {} 	// verbs that are transmitted over an HTTP POST method
	};

	verbs.GET.PROPFIND = function(req, res, next) {
		return _propfind(req.params.localPath, req.params.path,
				 req.params.depth, next);
	};

	var _propfind = function(localPath, relPath, depth, next) {
		if (path.basename(relPath).charAt(0) ===".") {
			// Skip hidden files & folders (using UNIX
			// convention: XXX do it for Windows too)
			return next(null);
		}

		fs.stat(localPath, function(err, stat) {
			if (err) {
				return next(err);
			}

			// minimum common set of properties
			var node = {
				path: relPath,
				name: path.basename(relPath),
				id: encodeFileId(relPath),
				isDir: stat.isDirectory()
			};

			console.dir(node);

			if (stat.isFile() || !depth) {
				return next(null, node);
			} else if (node.isDir) {
				node.contents = [];
				fs.readdir(localPath, function(err, files) {
					if (err) {
						return next(err); // XXX or skip this directory...
					}
					if (!files.length) {
						return next(null, node);
					}
					var count = files.length;
					files.forEach(function(name) {
						_propfind(path.join(localPath, name), path.join(relPath, name), depth-1, function(err, subNode){
							if (err) {
								return next(err);
							}
							node.contents.push(subNode);
							if (--count === 0) {
								// return to upper layer only if
								// every nodes of this layer
								// were successfully parsed
								return next(null, node);
							}
						});
					});
				});
			} else {
				// skip special files
				return next(null);
			}
		});
	};

	verbs.GET.GET = function(req, res, next) {
		fs.stat(req.params.localPath, function(err, stat) {
			if (err) {
				return next(err); // XXX be smarter about error codes
			}
			if (stat.isFile()) {
				// XXX use the below when we upload using express.bodyParser()
				/*
				var mimeType = _mimeTypes[path.extname(req.params.localPath).split(".")[1]];
				res.writeHead(200, {'Content-Type': mimeType} );
				var fileStream = fs.createReadStream(req.params.localPath);
				fileStream.pipe(res);
				return success(res);
				 */
				return fs.readFile(req.params.localPath, function(err, buffer) {
					return next(err, {content: buffer.toString('base64')});
				});
			} else {
				return next("Not a file"); // XXX be smarter about error codes
			}
		});
	};

	verbs.POST.PUT = function (req, res, next) {
		// XXX replace application/json body by direct upload using multipart/form-data + express.bodyParser()
		var body = JSON.parse(req.body); // req.param('content') || ''
		var buffer = new Buffer(body.content, 'base64');
		fs.writeFile(req.params.localPath, buffer, function(err){
			// XXX success should return 201 (Created) if file did not exists before
			next(err, {id: req.params.id, path: req.params.path});
		});
	};

	verbs.POST.MKCOL = function(req, res, next) {
		fs.mkdir(req.params.localPath, function(err) {
			var error;
			if (!err) {
				next(null, {id: req.params.id, path: req.params.path});
			} else if (err.code === 'EEXIST') {
				error = new Error(err.path + ": already exists");
				error.http_code = 405; // Method Not Allowed
				next(error);
			} else {
				error = new Error(err.path + ": " + err.code);
				error.http_code = 500; // Internal Server Error
				next(error);
			}
		});
	};

	verbs.POST.DELETE = function(req, res, next) {
		_rmrf(req.params.localPath, next);
	};

	function _rmrf(dir, next) {
		// from <https://gist.github.com/1526919>
		fs.stat(dir, function(err, stats) {
			if (err) {
				return next(err);
			}

			if (!stats.isDirectory()) {
				return fs.unlink(dir, next); // XXX success should return 204 (No Content)
			}

			var count = 0;
			fs.readdir(dir, function(err, files) {
				if (err) {
					return next(err);
				}

				if (files.length < 1) {
					return fs.rmdir(dir, next); // XXX success should return 204 (No Content)
				}

				files.forEach(function(file) {
					var sub = path.join(dir, file);

					_rmrf(sub, function(err) {
						if (err) {
							return next(err);
						}

						if (++count == files.length) {
							return fs.rmdir(dir, next);
						}
					});
				});
			});
		});
	}

	verbs.POST.MOVE = function(req, res, next) {
		// XXX improve status codes (see RFC4918, section 9.9.4)
		_changeNode(req, res, fs.rename, next);
	};

	verbs.POST.COPY = function(req, res, next) {
		// XXX improve status codes (see RFC4918, section 9.9.4)
		_changeNode(req, res, _cpr, next);
	};

	function _changeNode(req, res, op, next) {
		var newPath;
		if (req.param('name')) {
			// rename file within the same collection (folder)
			newPath = path.resolve(path.join(path.dirname(req.params.localPath),
							 path.basename(req.param('name'))));
		} else if (req.param('path')) {
			// move at a new location
			newPath = path.resolve(path.join(req.params.root, req.param('path')));
		} else {
			return next(new Error("missing parameter: name or path"));
		}
		return op(req.params.localPath, newPath, next);
	}

	function _cpr(srcPath, dstPath, next) {
		function _copyFile(srcPath, dstPath, next) {
			var is, os;
				is = fs.createReadStream(srcPath);
				os = fs.createWriteStream(dstPath);
				util.pump(is, os, next); // XXX success should return 201 (Created)
		}
		function _copyDir(srcPath, dstPath, next) {
			var count = 0;
			fs.readdir(srcPath, function(err, files) {
				if (err) {
					return next(err);
				}
				fs.mkdir(dstPath, function(err) {
					if (err) {
						return next(err);
					}
					if (files.length >= 1) {
						files.forEach(function(file) {
							var sub = path.join(dstPath, file);

							_cpr(path.join(srcPath, file), path.join(dstPath, file), function(err) {
								if (err) {
									return next(err);
								}

								if (++count == files.length) {
									return next(null);
								}
							});
						});
					}
				});
			});
		}
		fs.stat(srcPath, function(err, stats) {
			if (err) {
				return next(err);
			}
			if (stats.isDirectory()) {
				_copyDir(srcPath, dstPath, next);
			} else if (stats.isFile()){
				_copyFile(srcPath, dstPath, next);
			}
		});
	}
}

debugger;			// webkit breakpoint

if (path.basename(process.argv[1]) === "fsLocal.js") {
	// We are main.js: create & run the object...

	var version = process.version.match(/[0-9]+.[0-9]+/)[0];
	if (version <= 0.7) {
		process.exit("Only supported on Node.js version 0.8 and above");
	}

	var fsLocal = new FsLocal({
		// urlPrefix (M) can be '/', '/res/files/' ...etc
		urlPrefix:	process.argv[2],
		// root (m) local filesystem access root absolute path
		root:		path.resolve(process.argv[3]),
		// port (o) local IP port of the express server (default: 9009, 0: dynamic)
		port: parseInt(process.argv[4] || "9009", 10)
	}, function(err, service){
		if (err) {
			process.exit(err);
		}
		console.log("fsLocal['"+process.argv[3]+"'] available at "+service.url);
		if (process.send) {
			// only possible/available if parent-process is node
			process.send(service);
		}
	});

} else {

	// ... otherwise hook into commonJS module systems
	module.exports = FsLocal;
}
<commit_msg>ENYO-1000: WebDAV-like first implementation.  GET/PROPFIND & POST/MKCOL<commit_after>/**
 * fsLocal.js -- Ares FileSystem (fs) provider, using local files.
 *
 * This FileSystemProvider is both the simplest possible one
 * and a working sample for other implementations.
 */

// modules requirements

var fs = require("fs");
var path = require("path");
var express = require("express");
var util  = require("util");
var querystring = require("querystring");

function FsLocal(config, next) {

	config.root = path.resolve(config.root);

	/**
	 * Express server instance
	 *
	 * @private
	 */
	var app = express.createServer();

	app.use(express.logger('dev'));

	// CORS -- Cros-Origin Resources Sharing
	app.use(function(req, res, next) {
		res.header('Access-Control-Allow-Origin', "*"); // XXX be safer than '*'
		res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
		res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
		if ('OPTIONS' == req.method) {
			res.status(200).end();
		}
		else {
			next();
		}
	});

	// Authentication
	app.use(express.cookieParser());
	app.use(function(req, res, next) {
		if (req.connection.remoteAddress !== "127.0.0.1") {
			next("Access denied from IP address "+req.connection.remoteAddress);
		} else {
			next();
		}
	});

	// HTTP method overloading
	app.use(function(req, res, next) {
		//debugger;
		req.originalMethod = req.method;
		if (req.query._method) {
			req.method = req.query._method.toUpperCase();
		}
		if (!verbs[req.originalMethod] ||
		    !verbs[req.originalMethod][req.method]) {
			next("unknown originalMethod/method = "+req.originalMethod+"/"+req.method);
		} else {
			next();
		}
	});

	// Error handler (4 parameters)
	app.use(function(err, req, res, next){
		respond(res, err);
	});

	// Success
	function respond(res, err, response) {
		var error;
		var errMsg;
		if (err) {
			console.log("err=");
			console.dir(err);
			if (err.code && err.path) {
				// fs.xxx error
				if (err.code === 'EEXIST') {
					errMsg = err.path + ": already exists";
					error.http_code = 405; // Method Not Allowed
				} else {
					error = new Error(err.path + ": " + err.code);
					error.http_code = 500; // Internal Server Error
				}
			} else if (typeof err === 'string') {
				error = new Error(err);
				error.http_code = 500; // Internal Server Error
			} else if (err instanceof Error) {
				error = err;
			}
			console.log("error=");
			console.error(err.stack);
			res.send(err.stack, err.http_code ? err.http_code : 500);
		} else {
			console.log("response=");
			console.dir(response);
			var code = response.code || 200;
			var body = response.body;
			if (body) {
				res.status(code).send(body);
			} else {
				res.status(code).end();
			}
		}
	}

	//app.use(express.bodyParser()); // parses json, x-www-form-urlencoded, and multipart/form-data
	//app.enable('strict routing'); // XXX what for?

	app.all(path.normalize(config.urlPrefix), function(req, res) {
		res.redirect('/id/' + encodeFileId('/') +
			     res.query ? "?" +
			     querystring.stringify(req.query) : '');
	});
	app.all(path.join(config.urlPrefix, '/id/:id'), function(req, res, next) {
		console.log("req.query=");
		console.dir(req.query);
		req.params.id = req.params.id || encodeFileId('/');
		req.params.path = decodeFileId(req.params.id);
		// 'infinity' is '-1', 'undefined' is '0'
		req.params.depth = req.query.depth ? (req.query.depth === 'infinity' ? -1 : parseInt(req.query.depth, 10)) : 0;
		console.log("req.params=");
		console.dir(req.params);
		verbs[req.originalMethod][req.method](req, res, respond.bind(this, res));
	});
	console.log("route="+path.join(config.urlPrefix, ':id'));

	// start the filesystem (fs) server & notify the IDE server
	// (parent) where to find it

	app.listen(config.port, "127.0.0.1", null /*backlog*/, function() {
		// Send back the URL to the IDE server, when port is
		// actually bound
		var service = {
			url: "http://127.0.0.1:"+app.address().port.toString()+config.urlPrefix
		};
		return next(null, service);
	});

	/**
	 * Terminates express server
	 */
	this.quit = function() {
		app.close();
	};

	// utilities library

	function encodeFileId(relPath) {
		if (relPath) {
			return encodeURIComponent(relPath);
		} else {
			return undefined;
		}
	}

	function decodeFileId(id) {
		if (id) {
			return decodeURIComponent(id);
		} else {
			return undefined;
		}
	}

	// Served files

	var _mimeTypes = {
		"html": "text/html",
		"jpeg": "image/jpeg",
		"jpg": "image/jpeg",
		"png": "image/png",
		"js": "text/javascript",
		"css": "text/css"
	};

	// File-System (fs) verbs

	var verbs = {
		GET: {}, 	// verbs that are transmitted over an HTTP GET method
		POST: {} 	// verbs that are transmitted over an HTTP POST method
	};

	verbs.GET.PROPFIND = function(req, res, next) {
		_propfind(req.params.path, req.params.depth, function(err, content){
			next(err, {code: 200, body: content});
		});
	};

	var _propfind = function(relPath, depth, next) {
		var localPath = path.join(config.root, relPath);
		if (path.basename(relPath).charAt(0) ===".") {
			// Skip hidden files & folders (using UNIX
			// convention: XXX do it for Windows too)
			return next(null);
		}

		fs.stat(localPath, function(err, stat) {
			if (err) {
				return next(err);
			}

			// minimum common set of properties
			var node = {
				path: relPath,
				name: path.basename(relPath),
				id: encodeFileId(relPath),
				isDir: stat.isDirectory()
			};

			console.log("depth="+depth+", node=");
			console.dir(node);

			if (stat.isFile() || !depth) {
				return next(null, node);
			} else if (node.isDir) {
				node.contents = [];
				fs.readdir(localPath, function(err, files) {
					if (err) {
						return next(err); // XXX or skip this directory...
					}
					if (!files.length) {
						return next(null, node);
					}
					var count = files.length;
					files.forEach(function(name) {
						_propfind(path.join(relPath, name), depth-1, function(err, subNode){
							if (err) {
								return next(err);
							}
							if (subNode) {
								node.contents.push(subNode);
							}
							if (--count === 0) {
								// return to upper layer only if
								// every nodes of this layer
								// were successfully parsed
								return next(null, node);
							}
						});
					});
				});
			} else {
				// skip special files
				return next(null);
			}
		});
	};

	verbs.GET.GET = function(req, res, next) {
		var localPath = path.join(config.root, req.params.path);
		fs.stat(req.params.localPath, function(err, stat) {
			if (err) {
				return next(err); // XXX be smarter about error codes
			}
			if (stat.isFile()) {
				// XXX use the below when we upload using express.bodyParser()
				/*
				 var mimeType = _mimeTypes[path.extname(req.params.path).split(".")[1]];
				 res.writeHead(200, {'Content-Type': mimeType} );
				 var fileStream = fs.createReadStream(localPath);
				 fileStream.pipe(res);
				 next();
				 */
				return fs.readFile(req.params.localPath, function(err, buffer) {
					return next(err, {content: buffer.toString('base64')});
				});
			} else {
				return next("Not a file"); // XXX be smarter about error codes
			}
		});
	};

	verbs.POST.PUT = function (req, res, next) {
		var newPath, newId;
		if (!req.query.name) {
			next("missing 'name' query parameter");
			return;
		}
		newPath = path.join(req.params.path, path.basename(req.query.name));
		newId = encodeFileId(newPath);

		// XXX replace application/json body by direct upload using multipart/form-data + express.bodyParser()
		var body = JSON.parse(req.body); // req.param('content') || ''
		var buffer = new Buffer(body.content, 'base64');
		fs.writeFile(path.join(config.root, newPath), buffer, function(err){
			next(err, {
				code: 201, // Created
				body: {id: req.params.id, path: req.params.path}
			});
		});
	};

	verbs.POST.MKCOL = function(req, res, next) {
		var newPath, newId;
		if (!req.query.name) {
			next("missing 'name' query parameter");
			return;
		}
		newPath = path.join(req.params.path, path.basename(req.query.name));
		newId = encodeFileId(newPath);

		fs.mkdir(path.join(config.root, newPath), function(err) {
			next(err, {
				code: 201, // Created
				body: {id: newId, path: newPath}
			});
		});
	};

	verbs.POST.DELETE = function(req, res, next) {
		_rmrf(req.params.localPath, next);
	};

	function _rmrf(dir, next) {
		// from <https://gist.github.com/1526919>
		fs.stat(dir, function(err, stats) {
			if (err) {
				return next(err);
			}

			if (!stats.isDirectory()) {
				return fs.unlink(dir, next); // XXX should return 204 (No Content) on success
			}

			var count = 0;
			fs.readdir(dir, function(err, files) {
				if (err) {
					return next(err);
				}

				if (files.length < 1) {
					return fs.rmdir(dir, next); // XXX should return 204 (No Content) on success
				}

				files.forEach(function(file) {
					var sub = path.join(dir, file);

					_rmrf(sub, function(err) {
						if (err) {
							return next(err);
						}

						if (++count == files.length) {
							return fs.rmdir(dir, next);
						}
					});
				});
			});
		});
	}

	verbs.POST.MOVE = function(req, res, next) {
		// XXX improve status codes (see RFC4918, section 9.9.4)
		_changeNode(req, res, fs.rename, next);
	};

	verbs.POST.COPY = function(req, res, next) {
		// XXX improve status codes (see RFC4918, section 9.9.4)
		_changeNode(req, res, _cpr, next);
	};

	function _changeNode(req, res, op, next) {
		var newPath;
		if (req.query.name) {
			// rename file within the same collection (folder)
			newPath = path.join(config.root, req.params.path,
					    path.basename(req.query.name));
		} else if (req.query.path) {
			// move at a new location
			newPath = path.join(config.root, req.param('path'));
		} else {
			return next(new Error("missing parameter: name or path"));
		}
		return op(path.join(config.root, req.params.path), newPath, next);
	}

	function _cpr(srcPath, dstPath, next) {
		function _copyFile(srcPath, dstPath, next) {
			var is, os;
			is = fs.createReadStream(srcPath);
			os = fs.createWriteStream(dstPath);
			util.pump(is, os, next); // XXX should return 201 (Created) on success
		}
		function _copyDir(srcPath, dstPath, next) {
			var count = 0;
			fs.readdir(srcPath, function(err, files) {
				if (err) {
					return next(err);
				}
				fs.mkdir(dstPath, function(err) {
					if (err) {
						return next(err);
					}
					if (files.length >= 1) {
						files.forEach(function(file) {
							var sub = path.join(dstPath, file);

							_cpr(path.join(srcPath, file), path.join(dstPath, file), function(err) {
								if (err) {
									return next(err);
								}

								if (++count == files.length) {
									return next(null);
								}
							});
						});
					}
				});
			});
		}
		fs.stat(srcPath, function(err, stats) {
			if (err) {
				return next(err);
			}
			if (stats.isDirectory()) {
				_copyDir(srcPath, dstPath, next);
			} else if (stats.isFile()){
				_copyFile(srcPath, dstPath, next);
			}
		});
	}
}

//debugger;

if (path.basename(process.argv[1]) === "fsLocal.js") {
	// We are main.js: create & run the object...

	var version = process.version.match(/[0-9]+.[0-9]+/)[0];
	if (version <= 0.7) {
		process.exit("Only supported on Node.js version 0.8 and above");
	}

	var fsLocal = new FsLocal({
		// urlPrefix (M) can be '/', '/res/files/' ...etc
		urlPrefix:	process.argv[2],
		// root (m) local filesystem access root absolute path
		root:		path.resolve(process.argv[3]),
		// port (o) local IP port of the express server (default: 9009, 0: dynamic)
		port: parseInt(process.argv[4] || "9009", 10)
	}, function(err, service){
		if (err) {
			process.exit(err);
		}
		console.log("fsLocal['"+process.argv[3]+"'] available at "+service.url);
		if (process.send) {
			// only possible/available if parent-process is node
			process.send(service);
		}
	});

} else {

	// ... otherwise hook into commonJS module systems
	module.exports = FsLocal;
}
<|endoftext|>


<commit_before>var async = require("async");
const template = require("./template");

exports.notifyContacts = function (gh, pr, status, mailer, emailConfig, store, log, cb) {
    log.info("Attempting to notify error on " + pr.fullName);
    var staff = gh.getRepoContacts(pr.fullName, function(err, emails) {
        var actualEmails;
        if (err || !emails) {
            log.error(err);
            actualEmails = emailConfig.fallback;
        }
        else {
            actualEmails = emails.filter(function(e) { return e !== null;});
            if (!actualEmails || !actualEmails.length) {
                log.error("Could not retrieve email addresses from repo contacts for " + pr.fullName);
                actualEmails = emailConfig.fallback;
            }
        }
        mailer.sendMail({
            from: emailConfig.from,
            to: actualEmails.join(","),
            cc: [...emailConfig.cc].join(","),
            subject: "IPR check failed for PR #" + pr.num+ " on " + pr.fullName,
            text: status.payload.description + "\n\n See " + status.payload.target_url
        }, function(err) {
            if (err) {
                log.error(err);
                return cb();
            }
            // send mail to unaffiliated users
            async.each(pr.unaffiliatedUsers, function(u, userCB) {
                store.getUser(u, function(err, user) {
                    if (err) return userCB(err);
                    if (user.emails.length) {
                        const mailData = {
                            displayName: user.displayName ? user.displayName : user.login,
                            prnum: pr.num,
                            repo: pr.fullName,
                            contacts: actualEmails.join(",")
                        }
                        mailer.sendMail({
                            from: emailConfig.from,
                            to: user.emails[0].value,
                            cc: [...actualEmails, ...emailConfig.cc].join(","),
                            subject: "Information needed for your PR #" + pr.num+ " on " + pr.fullName,
                            text: template('affiliation-mail.txt', mailData)
                        }, userCB);
                    } else {
                        // TODO: comment on pull request directly?
                        return userCB();
                    }
                })
            }, function(err) {
                if (err)  log.error(err);
                return cb();
            });
        });
    });
};
<commit_msg>Simplify code in mailer<commit_after>var async = require("async");
const template = require("./template");

exports.notifyContacts = function (gh, pr, status, mailer, emailConfig, store, log, cb) {
    log.info("Attempting to notify error on " + pr.fullName);
    var staff = gh.getRepoContacts(pr.fullName, function(err, emails) {
        var actualEmails;
        if (err || !emails) {
            log.error(err);
            actualEmails = emailConfig.fallback;
        }
        else {
            actualEmails = emails.filter(function(e) { return e !== null;});
            if (!actualEmails || !actualEmails.length) {
                log.error("Could not retrieve email addresses from repo contacts for " + pr.fullName);
                actualEmails = emailConfig.fallback;
            }
        }
        mailer.sendMail({
            from: emailConfig.from,
            to: actualEmails.join(","),
            cc: emailConfig.cc.join(","),
            subject: "IPR check failed for PR #" + pr.num+ " on " + pr.fullName,
            text: status.payload.description + "\n\n See " + status.payload.target_url
        }, function(err) {
            if (err) {
                log.error(err);
                return cb();
            }
            // send mail to unaffiliated users
            async.each(pr.unaffiliatedUsers, function(u, userCB) {
                store.getUser(u, function(err, user) {
                    if (err) return userCB(err);
                    if (user.emails.length) {
                        const mailData = {
                            displayName: user.displayName ? user.displayName : user.login,
                            prnum: pr.num,
                            repo: pr.fullName,
                            contacts: actualEmails.join(",")
                        }
                        mailer.sendMail({
                            from: emailConfig.from,
                            to: user.emails[0].value,
                            cc: [...actualEmails, ...emailConfig.cc].join(","),
                            subject: "Information needed for your PR #" + pr.num+ " on " + pr.fullName,
                            text: template('affiliation-mail.txt', mailData)
                        }, userCB);
                    } else {
                        // TODO: comment on pull request directly?
                        return userCB();
                    }
                })
            }, function(err) {
                if (err)  log.error(err);
                return cb();
            });
        });
    });
};
<|endoftext|>


<commit_before>// @flow

import * as React from 'react'
import {WebView} from 'react-native'
import type {PlayState, HtmlAudioError} from './types'

const kstoEmbed = 'https://www.stolaf.edu/multimedia/play/embed/ksto.html'

type Props = {
  playState: PlayState,
  onWaiting?: () => any,
  onEnded?: () => any,
  onStalled?: () => any,
  onPlay?: () => any,
  onPause?: () => any,
  onError?: HtmlAudioError => any,
  style: any,
}

type HtmlAudioState =
  | 'waiting'
  | 'ended'
  | 'stalled'
  | 'playing'
  | 'play'
  | 'pause'

type HtmlAudioEvent =
  | {type: HtmlAudioState}
  | {type: 'error', error: HtmlAudioError}

export class StreamPlayer extends React.PureComponent<Props> {
  _webview: WebView

  componentWillReceiveProps(nextProps: Props) {
    this.dispatchEvent(nextProps.playState)
  }

  componentWillUnmount() {
    this.pause()
  }

  dispatchEvent = (nextPlayState: PlayState) => {
    // console.log('<StreamPlayer> state changed to', nextPlayState)

    switch (nextPlayState) {
      case 'paused':
        return this.pause()

      case 'loading':
      case 'checking':
      case 'playing':
        return this.play()

      default:
        return
    }
  }

  handleMessage = (event: any) => {
    const data: HtmlAudioEvent = JSON.parse(event.nativeEvent.data)

    // console.log('<audio> dispatched event', data.type)

    switch (data.type) {
      case 'waiting':
        return this.props.onWaiting && this.props.onWaiting()

      case 'ended':
        return this.props.onEnded && this.props.onEnded()

      case 'stalled':
        return this.props.onStalled && this.props.onStalled()

      case 'pause':
        return this.props.onPause && this.props.onPause()

      case 'playing':
      case 'play':
        return this.props.onPlay && this.props.onPlay()

      case 'error':
        return this.props.onError && this.props.onError(data.error)

      default:
        return
    }
  }

  pause = () => {
    // console.log('sent "pause" message to <audio>')
    this._webview.postMessage('pause')
  }

  play = () => {
    // console.log('sent "play" message to <audio>')
    this._webview.postMessage('play')
  }

  setRef = (ref: WebView) => (this._webview = ref)

  js = `
    function ready(fn) {
      if (document.readyState !== 'loading') {
        fn();
      } else if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', fn);
      } else {
        document.attachEvent('onreadystatechange', function () {
          if (document.readyState !== 'loading') {
            fn();
          }
        });
      }
    };

    ready(function () {
      var player = document.querySelector('audio');

      /*******
       *******/

      document.addEventListener('message', function (event) {
        switch (event.data) {
          case 'play':
            player.muted = false;
            player.play().catch(error);
            break;

          case 'pause':
            player.pause();
            break;
        }
      });

      /*******
       *******/

      function message(data) {
        window.postMessage(JSON.stringify(data));
      }

      function send(event) {
        message({type: event.type});
      }

      function error(event) {
        message({
          type: event.type,
          error: 'error',
        });
      }

      /*******
       *******/

      /* "waiting" is fired when playback has stopped because of a temporary
       * lack of data. */
      player.addEventListener('waiting', send);

      /* "ended" is fired when playback or streaming has stopped because the
       * end of the media was reached or because no further data is
       * available. */
      player.addEventListener('ended', send);

      /* "stalled" is fired when the user agent is trying to fetch media data,
       * but data is unexpectedly not forthcoming. */
      player.addEventListener('stalled', send);

      /* "playing" is fired when playback is ready to start after having been
       * paused or delayed due to lack of data. */
      player.addEventListener('playing', send);

      /* "pause" is fired when playback has been paused. */
      player.addEventListener('pause', send);

      /* "play" is fired when playback has begun. */
      player.addEventListener('play', send);

      /* "error" is fired when an error occurs. */
      player.addEventListener('error', error);
    });
  `

  render() {
    return (
      <WebView
        ref={this.setRef}
        allowsInlineMediaPlayback={true}
        mediaPlaybackRequiresUserAction={false}
        onMessage={this.handleMessage}
        source={{uri: kstoEmbed}}
        style={this.props.style}
        injectedJavaScript={this.js}
      />
    )
  }
}
<commit_msg>sort props<commit_after>// @flow

import * as React from 'react'
import {WebView} from 'react-native'
import type {PlayState, HtmlAudioError} from './types'

const kstoEmbed = 'https://www.stolaf.edu/multimedia/play/embed/ksto.html'

type Props = {
  playState: PlayState,
  onWaiting?: () => any,
  onEnded?: () => any,
  onStalled?: () => any,
  onPlay?: () => any,
  onPause?: () => any,
  onError?: HtmlAudioError => any,
  style: any,
}

type HtmlAudioState =
  | 'waiting'
  | 'ended'
  | 'stalled'
  | 'playing'
  | 'play'
  | 'pause'

type HtmlAudioEvent =
  | {type: HtmlAudioState}
  | {type: 'error', error: HtmlAudioError}

export class StreamPlayer extends React.PureComponent<Props> {
  _webview: WebView

  componentWillReceiveProps(nextProps: Props) {
    this.dispatchEvent(nextProps.playState)
  }

  componentWillUnmount() {
    this.pause()
  }

  dispatchEvent = (nextPlayState: PlayState) => {
    // console.log('<StreamPlayer> state changed to', nextPlayState)

    switch (nextPlayState) {
      case 'paused':
        return this.pause()

      case 'loading':
      case 'checking':
      case 'playing':
        return this.play()

      default:
        return
    }
  }

  handleMessage = (event: any) => {
    const data: HtmlAudioEvent = JSON.parse(event.nativeEvent.data)

    // console.log('<audio> dispatched event', data.type)

    switch (data.type) {
      case 'waiting':
        return this.props.onWaiting && this.props.onWaiting()

      case 'ended':
        return this.props.onEnded && this.props.onEnded()

      case 'stalled':
        return this.props.onStalled && this.props.onStalled()

      case 'pause':
        return this.props.onPause && this.props.onPause()

      case 'playing':
      case 'play':
        return this.props.onPlay && this.props.onPlay()

      case 'error':
        return this.props.onError && this.props.onError(data.error)

      default:
        return
    }
  }

  pause = () => {
    // console.log('sent "pause" message to <audio>')
    this._webview.postMessage('pause')
  }

  play = () => {
    // console.log('sent "play" message to <audio>')
    this._webview.postMessage('play')
  }

  setRef = (ref: WebView) => (this._webview = ref)

  js = `
    function ready(fn) {
      if (document.readyState !== 'loading') {
        fn();
      } else if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', fn);
      } else {
        document.attachEvent('onreadystatechange', function () {
          if (document.readyState !== 'loading') {
            fn();
          }
        });
      }
    };

    ready(function () {
      var player = document.querySelector('audio');

      /*******
       *******/

      document.addEventListener('message', function (event) {
        switch (event.data) {
          case 'play':
            player.muted = false;
            player.play().catch(error);
            break;

          case 'pause':
            player.pause();
            break;
        }
      });

      /*******
       *******/

      function message(data) {
        window.postMessage(JSON.stringify(data));
      }

      function send(event) {
        message({type: event.type});
      }

      function error(event) {
        message({
          type: event.type,
          error: 'error',
        });
      }

      /*******
       *******/

      /* "waiting" is fired when playback has stopped because of a temporary
       * lack of data. */
      player.addEventListener('waiting', send);

      /* "ended" is fired when playback or streaming has stopped because the
       * end of the media was reached or because no further data is
       * available. */
      player.addEventListener('ended', send);

      /* "stalled" is fired when the user agent is trying to fetch media data,
       * but data is unexpectedly not forthcoming. */
      player.addEventListener('stalled', send);

      /* "playing" is fired when playback is ready to start after having been
       * paused or delayed due to lack of data. */
      player.addEventListener('playing', send);

      /* "pause" is fired when playback has been paused. */
      player.addEventListener('pause', send);

      /* "play" is fired when playback has begun. */
      player.addEventListener('play', send);

      /* "error" is fired when an error occurs. */
      player.addEventListener('error', error);
    });
  `

  render() {
    return (
      <WebView
        ref={this.setRef}
        allowsInlineMediaPlayback={true}
        injectedJavaScript={this.js}
        mediaPlaybackRequiresUserAction={false}
        onMessage={this.handleMessage}
        source={{uri: kstoEmbed}}
        style={this.props.style}
      />
    )
  }
}
<|endoftext|>


<commit_before>describe('Popover', function () {
  'use strict';

  beforeEach(function(done) {
    var self = this;
    requirejs([
      'jquery',
      'Popover'
    ],
    function (
      $,
      Popover
    ) {
      self.$html = $(window.__html__['spec/javascripts/fixtures/Popover.html']).appendTo('body');
      self.$fixture = $('body').find('[data-dough-component="Popover"]');
      self.$trigger = self.$html.filter('[data-dough-collapsable-trigger]');
      self.$trigger.css({
        background: 'blue',
        height: '100px',
        width: '200px'
      });
      self.$target = self.$html.filter('[data-dough-collapsable-target]');
      self.$target.css({
        background: 'red',
        height: '100px',
        width: '200px'
      });
      self.Popover = Popover;
      $('body').css({height: '1000px', width: '1000px', margin: 0, padding: 0});
      done();
    }, done);
  });

  afterEach(function() {
    this.$html.remove();
  });

  function getElementCenterFromViewport(component, $el, direction) {
    return Math.floor(component.getElementBoundaries($el)[direction === 'horizontal'? 'left' : 'top'] + component.getElementCenterPosition($el)[direction]);
  }

  describe('Position left', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'left'
        });
        this.component.init();
        done();
      });

      it('should position itself to the left of the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(this.component.getElementBoundaries($target).right).to.be.below($('body').width());
      });
    });

    describe('With vertical alignment enabled', function () {
      beforeEach(function (done) {
        this.$fixture.css({
          margin: 'auto'
        });
        this.component = new this.Popover(this.$fixture, {
          direction: 'left',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should vertically centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'vertical'))
          .to.equal(getElementCenterFromViewport(this.component, $target, 'vertical'));
      });
    });
  });

  describe('Position right', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'right'
        });
        this.component.init();
        done();
      });

      it('should position itself to the right of the trigger', function() {
        var $trigger = this.component.$trigger,
            $target = this.component.$target;

        $trigger.click();
        expect(this.component.getElementBoundaries($target).left)
          .to.be.equal(this.component.getElementBoundaries($trigger).right - this.component.getBodyOffset().left);
      });
    });

    describe('With vertical alignment enabled', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'right',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should vertically centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'vertical'))
          .to.equal(getElementCenterFromViewport(this.component, $target, 'vertical'));
      });
    });
  });

  describe('Position Top', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'top'
        });
        this.component.init();
        done();
      });

      it('should position itself above the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(this.component.getElementBoundaries($target).bottom)
          .to.be.equal(this.component.getElementBoundaries($target).bottom);
      });
    });

    describe('With horizontal alignment enabled', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'top',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should horizontally centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        this.$trigger.css({
          margin: '100px auto 0'
        });

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'horizontal') - this.component.getBodyOffset().left)
          .to.equal(getElementCenterFromViewport(this.component, $target, 'horizontal'));
      });
    });
  });

  describe('Position Bottom', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'bottom'
        });
        this.component.init();
        done();
      });

      it('should position itself below the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.css({
          display : 'block'
        });
        $trigger.click();
        expect($target.offset().top).to.be.above($trigger.offset().top);
        expect(this.component.getElementBoundaries($target).bottom).to.be.below($('body').height());
      });
    });

    describe('With horizontal alignment enabled', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'bottom',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should horizontally centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        this.component.$el.css({
          margin: '0 auto'
        });

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'horizontal') - this.component.getBodyOffset().left)
          .to.equal(getElementCenterFromViewport(this.component, $target, 'horizontal'));
      });
    });
  });

});
<commit_msg>Remove offset declaration from test<commit_after>describe('Popover', function () {
  'use strict';

  beforeEach(function(done) {
    var self = this;
    requirejs([
      'jquery',
      'Popover'
    ],
    function (
      $,
      Popover
    ) {
      self.$html = $(window.__html__['spec/javascripts/fixtures/Popover.html']).appendTo('body');
      self.$fixture = $('body').find('[data-dough-component="Popover"]');
      self.$trigger = self.$html.filter('[data-dough-collapsable-trigger]');
      self.$trigger.css({
        background: 'blue',
        height: '100px',
        width: '200px'
      });
      self.$target = self.$html.filter('[data-dough-collapsable-target]');
      self.$target.css({
        background: 'red',
        height: '100px',
        width: '200px'
      });
      self.Popover = Popover;
      $('body').css({height: '1000px', width: '1000px', margin: 0, padding: 0});
      done();
    }, done);
  });

  afterEach(function() {
    this.$html.remove();
  });

  function getElementCenterFromViewport(component, $el, direction) {
    return Math.floor(component.getElementBoundaries($el)[direction === 'horizontal'? 'left' : 'top'] + component.getElementCenterPosition($el)[direction]);
  }

  describe('Position left', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'left'
        });
        this.component.init();
        done();
      });

      it('should position itself to the left of the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(this.component.getElementBoundaries($target).right).to.be.below($('body').width());
      });
    });

    describe('With vertical alignment enabled', function () {
      beforeEach(function (done) {
        this.$fixture.css({
          margin: 'auto'
        });
        this.component = new this.Popover(this.$fixture, {
          direction: 'left',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should vertically centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'vertical'))
          .to.equal(getElementCenterFromViewport(this.component, $target, 'vertical'));
      });
    });
  });

  describe('Position right', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'right'
        });
        this.component.init();
        done();
      });

      it('should position itself to the right of the trigger', function() {
        var $trigger = this.component.$trigger,
            $target = this.component.$target;

        $trigger.click();
        expect(this.component.getElementBoundaries($target).left)
          .to.be.equal(this.component.getElementBoundaries($trigger).right);
      });
    });

    describe('With vertical alignment enabled', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'right',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should vertically centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'vertical'))
          .to.equal(getElementCenterFromViewport(this.component, $target, 'vertical'));
      });
    });
  });

  describe('Position Top', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'top'
        });
        this.component.init();
        done();
      });

      it('should position itself above the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.click();
        expect(this.component.getElementBoundaries($target).bottom)
          .to.be.equal(this.component.getElementBoundaries($target).bottom);
      });
    });

    describe('With horizontal alignment enabled', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'top',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should horizontally centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        this.$trigger.css({
          margin: '100px auto 0'
        });

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'horizontal'))
          .to.equal(getElementCenterFromViewport(this.component, $target, 'horizontal'));
      });
    });
  });

  describe('Position Bottom', function () {
    describe('Default', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'bottom'
        });
        this.component.init();
        done();
      });

      it('should position itself below the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        $trigger.css({
          display : 'block'
        });
        $trigger.click();
        expect($target.offset().top).to.be.above($trigger.offset().top);
        expect(this.component.getElementBoundaries($target).bottom).to.be.below($('body').height());
      });
    });

    describe('With horizontal alignment enabled', function () {
      beforeEach(function (done) {
        this.component = new this.Popover(this.$fixture, {
          direction: 'bottom',
          centerAlign: true
        });
        this.component.init();
        done();
      });

      it('should horizontally centre itself to the trigger', function() {
        var $target = this.component.$target,
            $trigger = this.component.$trigger;

        this.component.$el.css({
          margin: '0 auto'
        });

        $trigger.click();
        expect(getElementCenterFromViewport(this.component, $trigger, 'horizontal'))
          .to.equal(getElementCenterFromViewport(this.component, $target, 'horizontal'));
      });
    });
  });

});
<|endoftext|>