<commit_before>define(function (require) {
    "use strict";

    // Brackets modules
    var _               = brackets.getModule("thirdparty/lodash"),
        DefaultDialogs  = brackets.getModule("widgets/DefaultDialogs"),
        Dialogs         = brackets.getModule("widgets/Dialogs"),
        StringUtils     = brackets.getModule("utils/StringUtils");

    // Local modules
    var ErrorHandler    = require("src/ErrorHandler"),
        Events          = require("src/Events"),
        EventEmitter    = require("src/EventEmitter"),
        Git             = require("src/git/Git"),
        Preferences     = require("src/Preferences"),
        ProgressDialog  = require("src/dialogs/Progress"),
        Promise         = require("bluebird"),
        PullDialog      = require("src/dialogs/Pull"),
        PushDialog      = require("src/dialogs/Push"),
        Strings         = require("strings"),
        Utils           = require("src/Utils");

    // Templates
    var gitRemotesPickerTemplate = require("text!templates/git-remotes-picker.html");

    // Module variables
    var $selectedRemote  = null,
        $remotesDropdown = null,
        $gitPanel = null,
        $gitPush = null;

    function initVariables() {
        $gitPanel = $("#git-panel");
        $selectedRemote = $gitPanel.find(".git-selected-remote");
        $remotesDropdown = $gitPanel.find(".git-remotes-dropdown");
        $gitPush = $gitPanel.find(".git-push");
    }

    // Implementation

    function getDefaultRemote(allRemotes) {
        var defaultRemotes = Preferences.get("defaultRemotes") || {},
            candidate = defaultRemotes[Preferences.get("currentGitRoot")];

        var exists = _.find(allRemotes, function (remote) {
            return remote.name === candidate;
        });
        if (!exists) {
            candidate = null;
            if (allRemotes.length > 0) {
                candidate = _.first(allRemotes).name;
            }
        }

        return candidate;
    }

    function setDefaultRemote(remoteName) {
        var defaultRemotes = Preferences.get("defaultRemotes") || {};
        defaultRemotes[Preferences.get("currentGitRoot")] = remoteName;
        Preferences.persist("defaultRemotes", defaultRemotes);
    }

    function clearRemotePicker() {
        $selectedRemote
            .html("—")
            .data("remote", null);
    }

    function selectRemote(remoteName, type) {
        if (!remoteName) {
            return clearRemotePicker();
        }

        // Set as default remote only if is a normal git remote
        if (type === "git") { setDefaultRemote(remoteName); }

        // Disable pull if it is not a normal git remote
        $gitPanel.find(".git-pull").prop("disabled", type !== "git");

        // Enable push and set selected-remote-type to Git push button by type of remote
        $gitPush
            .prop("disabled", false)
            .attr("x-selected-remote-type", type);

        // Update remote name of $selectedRemote
        $selectedRemote
            .text(remoteName)
            .attr("data-type", type) // use attr to apply CSS styles
            .data("remote", remoteName);
    }

    function refreshRemotesPicker() {
        Git.getRemotes().then(function (remotes) {
            // Set default remote name and cache the remotes dropdown menu
            var defaultRemoteName = getDefaultRemote(remotes);

            // Disable Git-push and Git-pull if there are not remotes defined
            $gitPanel
                .find(".git-pull, .git-push, .git-fetch")
                .prop("disabled", remotes.length === 0);

            // Add options to change remote
            remotes.forEach(function (remote) {
                remote.deletable = remote.name !== "origin";
            });

            // Pass to Mustache the needed data
            var compiledTemplate = Mustache.render(gitRemotesPickerTemplate, {
                Strings: Strings,
                remotes: remotes
            });

            // Inject the rendered template inside the $remotesDropdown
            $remotesDropdown.html(compiledTemplate);

            // Notify others that they may add more stuff to this dropdown
            EventEmitter.emit(Events.REMOTES_REFRESH_PICKER);
            // TODO: is it possible to wait for listeners to finish?

            // TODO: if there're no remotes but there are some ftp remotes
            // we need to adjust that something other may be put as default
            // low priority
            if (remotes.length > 0) {
                selectRemote(defaultRemoteName, "git");
            } else {
                clearRemotePicker();
            }
        }).catch(function (err) {
            ErrorHandler.showError(err, "Getting remotes failed!");
        });
    }

    function handleRemoteCreation() {
        return Utils.askQuestion(Strings.CREATE_NEW_REMOTE, Strings.ENTER_REMOTE_NAME)
            .then(function (name) {
                return Utils.askQuestion(Strings.CREATE_NEW_REMOTE, Strings.ENTER_REMOTE_URL).then(function (url) {
                    return [name, url];
                });
            })
            .spread(function (name, url) {
                return Git.createRemote(name, url).then(function () {
                    return refreshRemotesPicker();
                });
            })
            .catch(function (err) {
                if (!ErrorHandler.equals(err, Strings.USER_ABORTED)) {
                    ErrorHandler.showError(err, "Remote creation failed");
                }
            });
    }

    function deleteRemote(remoteName) {
        return Utils.askQuestion(Strings.DELETE_REMOTE, StringUtils.format(Strings.DELETE_REMOTE_NAME, remoteName), { booleanResponse: true })
            .then(function (response) {
                if (response === true) {
                    return Git.deleteRemote(remoteName).then(function () {
                        return refreshRemotesPicker();
                    });
                }
            })
            .catch(function (err) {
                ErrorHandler.logError(err);
            });
    }

    function showPushResult(result) {
        if (typeof result.remoteUrl === "string") {
            result.remoteUrl = Utils.encodeSensitiveInformation(result.remoteUrl);
        }

        var template = [
            "
{{flagDescription}}
",
            "Info:",
            "Remote url - {{remoteUrl}}",
            "Local branch - {{from}}",
            "Remote branch - {{to}}",
            "Summary - {{summary}}",
            "
Status - {{status}}
"
        ].join("
");

        Dialogs.showModalDialog(
            DefaultDialogs.DIALOG_ID_INFO,
            Strings.GIT_PUSH_RESPONSE, // title
            Mustache.render(template, result) // message
        );
    }

    function pushToRemote(remote) {
        if (!remote) { return ErrorHandler.showError("No remote has been selected for push!"); }

        var pushConfig = {
            remote: remote
        };

        PushDialog.show(pushConfig)
            .then(function (pushConfig) {
                var q = Promise.resolve(),
                    additionalArgs = [];

                if (pushConfig.tags) {
                    additionalArgs.push("--tags");
                }

                // set a new tracking branch if desired
                if (pushConfig.branch && pushConfig.setBranchAsTracking) {
                    q = q.then(function () {
                        return Git.setUpstreamBranch(pushConfig.remote, pushConfig.branch);
                    });
                }
                // put username and password into remote url
                if (pushConfig.remoteUrlNew) {
                    q = q.then(function () {
                        return Git.setRemoteUrl(pushConfig.remote, pushConfig.remoteUrlNew);
                    });
                }
                // do the pull itself (we are not using pull command)
                q = q.then(function () {
                    var op;

                    if (pushConfig.pushToNew) {
                        op = Git.pushToNewUpstream(pushConfig.remote, pushConfig.branch);
                    } else if (pushConfig.strategy === "DEFAULT") {
                        op = Git.push(pushConfig.remote, pushConfig.branch, additionalArgs);
                    } else if (pushConfig.strategy === "FORCED") {
                        op = Git.pushForced(pushConfig.remote, pushConfig.branch);
                    } else if (pushConfig.strategy === "DELETE_BRANCH") {
                        op = Git.deleteRemoteBranch(pushConfig.remote, pushConfig.branch);
                    }
                    return ProgressDialog.show(op)
                        .then(function (result) {
                            return ProgressDialog.waitForClose().then(function () {
                                showPushResult(result);
                            });
                        })
                        .catch(function (err) {
                            ErrorHandler.showError(err, "Pushing to remote failed");
                        });
                });
                // restore original url if desired
                if (pushConfig.remoteUrlRestore) {
                    q = q.finally(function () {
                        return Git.setRemoteUrl(pushConfig.remote, pushConfig.remoteUrlRestore);
                    });
                }

                return q.finally(function () {
                    EventEmitter.emit(Events.REFRESH_ALL);
                });
            })
            .catch(function (err) {
                // when dialog is cancelled, there's no error
                if (err) { ErrorHandler.showError(err, "Pushing operation failed"); }
            });
    }

    function pullFromRemote(remote) {
        if (!remote) { return ErrorHandler.showError("No remote has been selected for pull!"); }

        var pullConfig = {
            remote: remote
        };

        PullDialog.show(pullConfig)
            .then(function (pullConfig) {
                var q = Promise.resolve();

                // set a new tracking branch if desired
                if (pullConfig.branch && pullConfig.setBranchAsTracking) {
                    q = q.then(function () {
                        return Git.setUpstreamBranch(pullConfig.remote, pullConfig.branch);
                    });
                }
                // put username and password into remote url
                if (pullConfig.remoteUrlNew) {
                    q = q.then(function () {
                        return Git.setRemoteUrl(pullConfig.remote, pullConfig.remoteUrlNew);
                    });
                }
                // do the pull itself (we are not using pull command)
                q = q.then(function () {
                    // fetch the remote first
                    return ProgressDialog.show(Git.fetchRemote(pullConfig.remote))
                        .then(function () {
                            if (pullConfig.strategy === "DEFAULT") {
                                return Git.mergeRemote(pullConfig.remote, pullConfig.branch);
                            } else if (pullConfig.strategy === "AVOID_MERGING") {
                                return Git.mergeRemote(pullConfig.remote, pullConfig.branch, true);
                            } else if (pullConfig.strategy === "MERGE_NOCOMMIT") {
                                return Git.mergeRemote(pullConfig.remote, pullConfig.branch, false, true);
                            } else if (pullConfig.strategy === "REBASE") {
                                return Git.rebaseRemote(pullConfig.remote, pullConfig.branch);
                            } else if (pullConfig.strategy === "RESET") {
                                return Git.resetRemote(pullConfig.remote, pullConfig.branch);
                            }
                        })
                        .then(function (result) {
                            return ProgressDialog.waitForClose().then(function () {
                                return Utils.showOutput(result, Strings.GIT_PULL_RESPONSE);
                            });
                        })
                        .catch(function (err) {
                            ErrorHandler.showError(err, "Pulling from remote failed");
                        });
                });
                // restore original url if desired
                if (pullConfig.remoteUrlRestore) {
                    q = q.finally(function () {
                        return Git.setRemoteUrl(pullConfig.remote, pullConfig.remoteUrlRestore);
                    });
                }

                return q.finally(function () {
                    EventEmitter.emit(Events.REFRESH_ALL);
                });
            })
            .catch(function (err) {
                // when dialog is cancelled, there's no error
                if (err) { ErrorHandler.showError(err, "Pulling operation failed"); }
            });
    }

    function handleFetch(silent) {
        var q = Promise.resolve();

        // Define the fetch action promise to use
        var action = Git.fetchAllRemotes;

        // Tell the rest of the plugin that the fetch has started
        EventEmitter.emit(Events.FETCH_STARTED);

        if (!silent) {
            // If it's not a silent fetch show a progress window
            q = q.then(function () {
                return ProgressDialog.show(action());
            })
            .catch(function (err) {
                ErrorHandler.showError(err);
            })
            .then(ProgressDialog.waitForClose);
        } else {
            // Else fetch in the background
            q = action()
            .catch(function (err) {
                ErrorHandler.logError(err);
            });
        }

        // Tell the rest of the plugin that the fetch has completed
        return q.finally(function () {
            EventEmitter.emit(Events.FETCH_COMPLETE);
        });
    }

    // Event subscriptions
    EventEmitter.on(Events.GIT_ENABLED, function () {
        initVariables();
        refreshRemotesPicker();
    });
    EventEmitter.on(Events.HANDLE_REMOTE_PICK, function (event) {
        var $remote     = $(event.target).closest(".remote-name"),
            remoteName  = $remote.data("remote-name"),
            type        = $remote.data("type");
        selectRemote(remoteName, type);
        EventEmitter.emit(Events.REFRESH_ALL);
    });
    EventEmitter.on(Events.HANDLE_REMOTE_CREATE, function () {
        handleRemoteCreation();
    });
    EventEmitter.on(Events.HANDLE_REMOTE_DELETE, function (event) {
        var remoteName = $(event.target).closest(".remote-name").data("remote-name");
        deleteRemote(remoteName);
    });
    EventEmitter.on(Events.HANDLE_PULL, function () {
        var remoteName = $selectedRemote.data("remote");
        pullFromRemote(remoteName);
    });
    EventEmitter.on(Events.HANDLE_PUSH, function () {
        var remoteName = $selectedRemote.data("remote");
        pushToRemote(remoteName);
    });
    EventEmitter.on(Events.HANDLE_FETCH, function () {
        handleFetch();
    });

});
<commit_msg>Code cleanup for fetch button<commit_after>define(function (require) {
    "use strict";

    // Brackets modules
    var _               = brackets.getModule("thirdparty/lodash"),
        DefaultDialogs  = brackets.getModule("widgets/DefaultDialogs"),
        Dialogs         = brackets.getModule("widgets/Dialogs"),
        StringUtils     = brackets.getModule("utils/StringUtils");

    // Local modules
    var ErrorHandler    = require("src/ErrorHandler"),
        Events          = require("src/Events"),
        EventEmitter    = require("src/EventEmitter"),
        Git             = require("src/git/Git"),
        Preferences     = require("src/Preferences"),
        ProgressDialog  = require("src/dialogs/Progress"),
        Promise         = require("bluebird"),
        PullDialog      = require("src/dialogs/Pull"),
        PushDialog      = require("src/dialogs/Push"),
        Strings         = require("strings"),
        Utils           = require("src/Utils");

    // Templates
    var gitRemotesPickerTemplate = require("text!templates/git-remotes-picker.html");

    // Module variables
    var $selectedRemote  = null,
        $remotesDropdown = null,
        $gitPanel = null,
        $gitPush = null;

    function initVariables() {
        $gitPanel = $("#git-panel");
        $selectedRemote = $gitPanel.find(".git-selected-remote");
        $remotesDropdown = $gitPanel.find(".git-remotes-dropdown");
        $gitPush = $gitPanel.find(".git-push");
    }

    // Implementation

    function getDefaultRemote(allRemotes) {
        var defaultRemotes = Preferences.get("defaultRemotes") || {},
            candidate = defaultRemotes[Preferences.get("currentGitRoot")];

        var exists = _.find(allRemotes, function (remote) {
            return remote.name === candidate;
        });
        if (!exists) {
            candidate = null;
            if (allRemotes.length > 0) {
                candidate = _.first(allRemotes).name;
            }
        }

        return candidate;
    }

    function setDefaultRemote(remoteName) {
        var defaultRemotes = Preferences.get("defaultRemotes") || {};
        defaultRemotes[Preferences.get("currentGitRoot")] = remoteName;
        Preferences.persist("defaultRemotes", defaultRemotes);
    }

    function clearRemotePicker() {
        $selectedRemote
            .html("—")
            .data("remote", null);
    }

    function selectRemote(remoteName, type) {
        if (!remoteName) {
            return clearRemotePicker();
        }

        // Set as default remote only if is a normal git remote
        if (type === "git") { setDefaultRemote(remoteName); }

        // Disable pull if it is not a normal git remote
        $gitPanel.find(".git-pull").prop("disabled", type !== "git");

        // Enable push and set selected-remote-type to Git push button by type of remote
        $gitPush
            .prop("disabled", false)
            .attr("x-selected-remote-type", type);

        // Update remote name of $selectedRemote
        $selectedRemote
            .text(remoteName)
            .attr("data-type", type) // use attr to apply CSS styles
            .data("remote", remoteName);
    }

    function refreshRemotesPicker() {
        Git.getRemotes().then(function (remotes) {
            // Set default remote name and cache the remotes dropdown menu
            var defaultRemoteName = getDefaultRemote(remotes);

            // Disable Git-push and Git-pull if there are not remotes defined
            $gitPanel
                .find(".git-pull, .git-push, .git-fetch")
                .prop("disabled", remotes.length === 0);

            // Add options to change remote
            remotes.forEach(function (remote) {
                remote.deletable = remote.name !== "origin";
            });

            // Pass to Mustache the needed data
            var compiledTemplate = Mustache.render(gitRemotesPickerTemplate, {
                Strings: Strings,
                remotes: remotes
            });

            // Inject the rendered template inside the $remotesDropdown
            $remotesDropdown.html(compiledTemplate);

            // Notify others that they may add more stuff to this dropdown
            EventEmitter.emit(Events.REMOTES_REFRESH_PICKER);
            // TODO: is it possible to wait for listeners to finish?

            // TODO: if there're no remotes but there are some ftp remotes
            // we need to adjust that something other may be put as default
            // low priority
            if (remotes.length > 0) {
                selectRemote(defaultRemoteName, "git");
            } else {
                clearRemotePicker();
            }
        }).catch(function (err) {
            ErrorHandler.showError(err, "Getting remotes failed!");
        });
    }

    function handleRemoteCreation() {
        return Utils.askQuestion(Strings.CREATE_NEW_REMOTE, Strings.ENTER_REMOTE_NAME)
            .then(function (name) {
                return Utils.askQuestion(Strings.CREATE_NEW_REMOTE, Strings.ENTER_REMOTE_URL).then(function (url) {
                    return [name, url];
                });
            })
            .spread(function (name, url) {
                return Git.createRemote(name, url).then(function () {
                    return refreshRemotesPicker();
                });
            })
            .catch(function (err) {
                if (!ErrorHandler.equals(err, Strings.USER_ABORTED)) {
                    ErrorHandler.showError(err, "Remote creation failed");
                }
            });
    }

    function deleteRemote(remoteName) {
        return Utils.askQuestion(Strings.DELETE_REMOTE, StringUtils.format(Strings.DELETE_REMOTE_NAME, remoteName), { booleanResponse: true })
            .then(function (response) {
                if (response === true) {
                    return Git.deleteRemote(remoteName).then(function () {
                        return refreshRemotesPicker();
                    });
                }
            })
            .catch(function (err) {
                ErrorHandler.logError(err);
            });
    }

    function showPushResult(result) {
        if (typeof result.remoteUrl === "string") {
            result.remoteUrl = Utils.encodeSensitiveInformation(result.remoteUrl);
        }

        var template = [
            "
{{flagDescription}}
",
            "Info:",
            "Remote url - {{remoteUrl}}",
            "Local branch - {{from}}",
            "Remote branch - {{to}}",
            "Summary - {{summary}}",
            "
Status - {{status}}
"
        ].join("
");

        Dialogs.showModalDialog(
            DefaultDialogs.DIALOG_ID_INFO,
            Strings.GIT_PUSH_RESPONSE, // title
            Mustache.render(template, result) // message
        );
    }

    function pushToRemote(remote) {
        if (!remote) { return ErrorHandler.showError("No remote has been selected for push!"); }

        var pushConfig = {
            remote: remote
        };

        PushDialog.show(pushConfig)
            .then(function (pushConfig) {
                var q = Promise.resolve(),
                    additionalArgs = [];

                if (pushConfig.tags) {
                    additionalArgs.push("--tags");
                }

                // set a new tracking branch if desired
                if (pushConfig.branch && pushConfig.setBranchAsTracking) {
                    q = q.then(function () {
                        return Git.setUpstreamBranch(pushConfig.remote, pushConfig.branch);
                    });
                }
                // put username and password into remote url
                if (pushConfig.remoteUrlNew) {
                    q = q.then(function () {
                        return Git.setRemoteUrl(pushConfig.remote, pushConfig.remoteUrlNew);
                    });
                }
                // do the pull itself (we are not using pull command)
                q = q.then(function () {
                    var op;

                    if (pushConfig.pushToNew) {
                        op = Git.pushToNewUpstream(pushConfig.remote, pushConfig.branch);
                    } else if (pushConfig.strategy === "DEFAULT") {
                        op = Git.push(pushConfig.remote, pushConfig.branch, additionalArgs);
                    } else if (pushConfig.strategy === "FORCED") {
                        op = Git.pushForced(pushConfig.remote, pushConfig.branch);
                    } else if (pushConfig.strategy === "DELETE_BRANCH") {
                        op = Git.deleteRemoteBranch(pushConfig.remote, pushConfig.branch);
                    }
                    return ProgressDialog.show(op)
                        .then(function (result) {
                            return ProgressDialog.waitForClose().then(function () {
                                showPushResult(result);
                            });
                        })
                        .catch(function (err) {
                            ErrorHandler.showError(err, "Pushing to remote failed");
                        });
                });
                // restore original url if desired
                if (pushConfig.remoteUrlRestore) {
                    q = q.finally(function () {
                        return Git.setRemoteUrl(pushConfig.remote, pushConfig.remoteUrlRestore);
                    });
                }

                return q.finally(function () {
                    EventEmitter.emit(Events.REFRESH_ALL);
                });
            })
            .catch(function (err) {
                // when dialog is cancelled, there's no error
                if (err) { ErrorHandler.showError(err, "Pushing operation failed"); }
            });
    }

    function pullFromRemote(remote) {
        if (!remote) { return ErrorHandler.showError("No remote has been selected for pull!"); }

        var pullConfig = {
            remote: remote
        };

        PullDialog.show(pullConfig)
            .then(function (pullConfig) {
                var q = Promise.resolve();

                // set a new tracking branch if desired
                if (pullConfig.branch && pullConfig.setBranchAsTracking) {
                    q = q.then(function () {
                        return Git.setUpstreamBranch(pullConfig.remote, pullConfig.branch);
                    });
                }
                // put username and password into remote url
                if (pullConfig.remoteUrlNew) {
                    q = q.then(function () {
                        return Git.setRemoteUrl(pullConfig.remote, pullConfig.remoteUrlNew);
                    });
                }
                // do the pull itself (we are not using pull command)
                q = q.then(function () {
                    // fetch the remote first
                    return ProgressDialog.show(Git.fetchRemote(pullConfig.remote))
                        .then(function () {
                            if (pullConfig.strategy === "DEFAULT") {
                                return Git.mergeRemote(pullConfig.remote, pullConfig.branch);
                            } else if (pullConfig.strategy === "AVOID_MERGING") {
                                return Git.mergeRemote(pullConfig.remote, pullConfig.branch, true);
                            } else if (pullConfig.strategy === "MERGE_NOCOMMIT") {
                                return Git.mergeRemote(pullConfig.remote, pullConfig.branch, false, true);
                            } else if (pullConfig.strategy === "REBASE") {
                                return Git.rebaseRemote(pullConfig.remote, pullConfig.branch);
                            } else if (pullConfig.strategy === "RESET") {
                                return Git.resetRemote(pullConfig.remote, pullConfig.branch);
                            }
                        })
                        .then(function (result) {
                            return ProgressDialog.waitForClose().then(function () {
                                return Utils.showOutput(result, Strings.GIT_PULL_RESPONSE);
                            });
                        })
                        .catch(function (err) {
                            ErrorHandler.showError(err, "Pulling from remote failed");
                        });
                });
                // restore original url if desired
                if (pullConfig.remoteUrlRestore) {
                    q = q.finally(function () {
                        return Git.setRemoteUrl(pullConfig.remote, pullConfig.remoteUrlRestore);
                    });
                }

                return q.finally(function () {
                    EventEmitter.emit(Events.REFRESH_ALL);
                });
            })
            .catch(function (err) {
                // when dialog is cancelled, there's no error
                if (err) { ErrorHandler.showError(err, "Pulling operation failed"); }
            });
    }

    function handleFetch(silent) {
        var q = Promise.resolve();

        // Tell the rest of the plugin that the fetch has started
        EventEmitter.emit(Events.FETCH_STARTED);

        if (!silent) {
            // If it's not a silent fetch show a progress window
            q = q.then(ProgressDialog.show(Git.fetchAllRemotes()))
            .catch(function (err) {
                ErrorHandler.showError(err);
            })
            .then(ProgressDialog.waitForClose);
        } else {
            // Else fetch in the background
            q = Git.fetchAllRemotes()
            .catch(function (err) {
                ErrorHandler.logError(err);
            });
        }

        // Tell the rest of the plugin that the fetch has completed
        return q.finally(function () {
            EventEmitter.emit(Events.FETCH_COMPLETE);
        });
    }

    // Event subscriptions
    EventEmitter.on(Events.GIT_ENABLED, function () {
        initVariables();
        refreshRemotesPicker();
    });
    EventEmitter.on(Events.HANDLE_REMOTE_PICK, function (event) {
        var $remote     = $(event.target).closest(".remote-name"),
            remoteName  = $remote.data("remote-name"),
            type        = $remote.data("type");
        selectRemote(remoteName, type);
        EventEmitter.emit(Events.REFRESH_ALL);
    });
    EventEmitter.on(Events.HANDLE_REMOTE_CREATE, function () {
        handleRemoteCreation();
    });
    EventEmitter.on(Events.HANDLE_REMOTE_DELETE, function (event) {
        var remoteName = $(event.target).closest(".remote-name").data("remote-name");
        deleteRemote(remoteName);
    });
    EventEmitter.on(Events.HANDLE_PULL, function () {
        var remoteName = $selectedRemote.data("remote");
        pullFromRemote(remoteName);
    });
    EventEmitter.on(Events.HANDLE_PUSH, function () {
        var remoteName = $selectedRemote.data("remote");
        pushToRemote(remoteName);
    });
    EventEmitter.on(Events.HANDLE_FETCH, function () {
        handleFetch();
    });

});
<|endoftext|>


<commit_before>// DecentCMS (c) 2014 Bertrand Le Roy, under MIT. See LICENSE.txt for licensing details.
'use strict';

/**
 * The shape part handler creates shapes from raw content parts without the need
 * for a specific handler.
 */
var ShapePart = {
  feature: 'core-parts',
  service: 'shape-handler',
  /**
   * Adds a shape to `context.shape.temp.shapes` for each part that has a 'shape'
   * property.
   * The specific type of shape to transform the part object into is specified
   * by the `meta.shape` property of the part.
   * @param {object} context The context object.
   * @param {object} context.shape
   * The shape to handle. Its `meta.shape` property is the name of the shape
   * to create. If not found, the shape is looked for on the type.
   * @param {object} context.scope The scope.
   * @param {Function} done The callback.
   */
  handle: function handleShapePart(context, done) {
    var content = context.shape;
    if (!content.meta
      || content.meta.type !== 'content'
      || !content.temp) return done();
    var temp = content.temp;
    var item = temp.item;
    var scope = context.scope;
    var shapeHelper = scope.require('shape');
    var contentManager = scope.require('content-manager');
    var type = contentManager.getType(item);
    Object.getOwnPropertyNames(item).forEach(function(partName) {
      if (partName === 'meta' || partName === 'temp') return;
      var part = item[partName];
      var shapeName = (part.meta ? part.meta.shape : null)
        || (type && type.parts[partName] ? type.parts[partName].shape : null)
        || null;
      if (shapeName) {
        var meta = shapeHelper.meta(part);
        delete meta.shape;
        meta.type = shapeName;
        meta.name = partName;
        meta.alternates = [shapeName + '-' + partName];
        meta.item = item;
        shapeHelper.temp(part).displayType = temp.displayType;
        temp.shapes.push(part);
      }
    });
    done();
  }
};

module.exports = ShapePart;<commit_msg>Make shape part more resilient to null parts.<commit_after>// DecentCMS (c) 2014 Bertrand Le Roy, under MIT. See LICENSE.txt for licensing details.
'use strict';

/**
 * The shape part handler creates shapes from raw content parts without the need
 * for a specific handler.
 */
var ShapePart = {
  feature: 'core-parts',
  service: 'shape-handler',
  /**
   * Adds a shape to `context.shape.temp.shapes` for each part that has a 'shape'
   * property.
   * The specific type of shape to transform the part object into is specified
   * by the `meta.shape` property of the part.
   * @param {object} context The context object.
   * @param {object} context.shape
   * The shape to handle. Its `meta.shape` property is the name of the shape
   * to create. If not found, the shape is looked for on the type.
   * @param {object} context.scope The scope.
   * @param {Function} done The callback.
   */
  handle: function handleShapePart(context, done) {
    var content = context.shape;
    if (!content.meta
      || content.meta.type !== 'content'
      || !content.temp) return done();
    var temp = content.temp;
    var item = temp.item;
    var scope = context.scope;
    var shapeHelper = scope.require('shape');
    var contentManager = scope.require('content-manager');
    var type = contentManager.getType(item);
    Object.getOwnPropertyNames(item).forEach(function(partName) {
      if (partName === 'meta' || partName === 'temp') return;
      var part = item[partName];
      if (!part) return;
      var shapeName = (part.meta ? part.meta.shape : null)
        || (type && type.parts[partName] ? type.parts[partName].shape : null)
        || null;
      if (shapeName) {
        var meta = shapeHelper.meta(part);
        delete meta.shape;
        meta.type = shapeName;
        meta.name = partName;
        meta.alternates = [shapeName + '-' + partName];
        meta.item = item;
        shapeHelper.temp(part).displayType = temp.displayType;
        temp.shapes.push(part);
      }
    });
    done();
  }
};

module.exports = ShapePart;<|endoftext|>


<commit_before>import knex from 'knex';
import KRedis from 'kredis';
import {merge, isString} from 'lodash';

import isUsableObject from './isUsableObject';
import Table from './Table';
import migrator from './migrator';
import Util from './util/Util';

export default class Orm {
  constructor(config={}) {
    if ('db' in config) {
      this.knex = knex(config.db);
    } else {
      throw new Error(`no 'db' config found`);
    }

    if ('redis' in config) {
      this.cache = new KRedis(config.redis);
    }

    // tables definitions
    this.tableClasses = new Map();

    // tables instances
    this.tables = new Map();

    // tableColumns cache
    this.tableColumns = new Map();

    // migrator
    this.migrator = migrator(this);

    // util
    this.util = new Util(this);

    // exports which can be exported in place of orm instance
    this.exports = {
      orm: this,
      table: this.table.bind(this),
      trx: this.trx.bind(this),
      raw: this.raw.bind(this),
      migrator: this.migrator,
      cache: this.cache,
      knex: this.knex,
      isUsableObject
    };
  }

  // raw expr helper
  raw(expr) {
    return knex.raw(expr);
  }

  // transaction helper
  transaction(promiseFn) {
    return this.knex.transaction(promiseFn);
  }

  // transaction shorthand
  // usage:
  // return orm.trx((t) => {
  //   return orm('users', t).save([{}, {}, {}]);
  // }).then((users) => {
  //    ...
  // });
  trx(promiseFn) {
    let outerResult;

    return this.transaction((t) => {
      return promiseFn(t).then((result) => {
        return t.commit().then(() => {
          outerResult = result;
          return result;
        });
      }).catch((e) => {
        t.rollback();
        throw e;
      });
    }).then(() => outerResult);
  }

  // method to close the database
  close() {
    const promises = [this.knex.destroy()];

    if (this.cache) {
      promises.push(this.cache.disconnect());
    }

    return Promise.all(promises);
  }

  // here, we load the columns of all the tables that have been
  // defined via the orm, and return a promise on completion
  // cos, if people wanna do that before starting the server
  // let em do that. we also call ioredis.connect if its available
  load() {
    const promises = Array.from(this.tables.keys).map((name) => this.table(name).load());

    if (this.cache) {
      promises.push(this.cache.connect());
    }

    return Promise.all(promises);
  }

  // get a tableClass
  tableClass(tableName) {
    return this.tableClasses.get(tableName);
  }

  // get a table object
  table(tableName, trx=null) {
    if (! this.tables.has(tableName)) {
      throw new Error(`trying to access invalid table ${tableName}`);
    }

    const tbl = this.tables.get(tableName).fork();

    if (trx !== null) {
      tbl.transacting(trx);
    }

    return tbl;
  }

  // shorthand for table
  tbl(tableName, trx=null) {
    return this.table(tableName, trx);
  }

  defineTable(params={}) {
    const tableName = params.name;

    if (! isString(tableName)) {
      throw new Error(`Invalid table-name: ${tableName} supplied via key 'name'`);
    }

    if (this.tableClasses.has(tableName)) {
      throw new Error(`Table '${tableName}' already defined`);
    }

    this.tableClasses.set(tableName, this.newTableClass(params));
    this.instantitateTable(tableName, params);
    return this;
  }

  extendTable(tableName, {scopes={}, joints={}, relations={}, methods={}}) {
    if (! this.tableClasses.has(tableName)) {
      throw new Error(`Table '${tableName}' not defined yet`);
    }

    const TableClass = this.tableClass(tableName);
    const ExtendedTableClass = class extends TableClass {};

    this.attachScopesToTableClass(ExtendedTableClass, scopes);
    this.attachJointsToTableClass(ExtendedTableClass, joints);
    this.attachRelationsToTableClass(ExtendedTableClass, relations);
    this.attachMethodsToTableClass(ExtendedTableClass, methods);

    this.tableClasses.set(tableName, ExtendedTableClass);
    this.instantitateTable(tableName);
    return this;
  }

  instantitateTable(tableName) {
    const TableClass = this.tableClasses.get(tableName);

    return this.tables.set(tableName, new TableClass(this));
  }

  newTableClass(params) {
    return this.extendTableClass(Table, params);
  }

  extendTableClass(TableClass, params) {
    const {name, props, processors, scopes, joints, relations, methods} = merge(
      // the defaults
      {
        // the table's name, is required
        name: null,

        // table properties
        props: {
          key: 'id',
          // default key column, can be ['user_id', 'post_id'] for composite keys
          autoId: false,
          // by default we don't assume that you use an auto generated db id
          perPage: 25,
          // standard batch size per page used by `forPage` method
          // forPage method uses offset
          // avoid that and use a keyset in prod (http://use-the-index-luke.com/no-offset)
          timestamps: false
          // set to `true` if you want auto timestamps or
          // timestamps: ['created_at', 'updated_at'] (these are defaults when `true`)
          // will be assigned in this order only
        },

        // used to process model and collection results fetched from the db
        // override as you need to
        processors: {
          model(row) { return row; },
          collection(rows) { return rows; }
        },

        // predefined scopes on the table
        scopes: {},
        // predefined joints on the table
        joints: {},
        // relations definitions for the table
        relations: {},
        // table methods defintions
        methods: {}
      },
      // supplied params which will override the defaults
      params
    );

    // the extended table class whose objects will behave as needed
    const ExtendedTableClass = class extends TableClass {};

    // assign name to the table class
    ExtendedTableClass.prototype.name = name;

    // assign props to the table class
    ExtendedTableClass.prototype.props = props;

    // assign processors to the table class
    ExtendedTableClass.prototype.processors = processors;

    // store names of defined scopes, joints, relations, and methods
    ExtendedTableClass.prototype.definedScopes = new Set();
    ExtendedTableClass.prototype.definedJoints = new Set();
    ExtendedTableClass.prototype.definedRelations = new Set();
    ExtendedTableClass.prototype.definedMethods = new Set();

    // attach scopes, joints, relations and methods to tables
    // these are the only ones extendable after creation
    this.attachScopesToTableClass(ExtendedTableClass, scopes);
    this.attachJointsToTableClass(ExtendedTableClass, joints);
    this.attachRelationsToTableClass(ExtendedTableClass, relations);
    this.attachMethodsToTableClass(ExtendedTableClass, methods);

    // return the extended table class
    return ExtendedTableClass;
  }

  attachScopesToTableClass(TableClass, scopes) {
    // keep a record of defined scopes
    Object.keys(scopes).forEach((name) => {
      TableClass.prototype.definedScopes.add(name);
    });

    // process and merge scopes with table class
    merge(
      TableClass.prototype,
      Object.keys(scopes).reduce((processed, name) => {
        return merge(processed, {
          [name](...args) {
            scopes[name].apply(this, args);
            // set the label of the last pushed scope
            this.scopeTrack.relabelLastScope(name);
            return this;
          }
        });
      }, {})
    );
  }

  attachJointsToTableClass(TableClass, joints) {
    // keep a record of defined joints
    Object.keys(joints).forEach((name) => {
      TableClass.prototype.definedJoints.add(name);
    });

    // process and merge joints with table class
    merge(
      TableClass.prototype,
      Object.keys(joints).reduce((processed, name) => {
        // predefined joints never take arguments
        return merge(processed, {
          [name]() {
            if (this.scopeTrack.hasJoint(name)) {
              return this;
            } else {
              joints[name].call(this);
              // set the label of the last pushed scope
              this.scopeTrack.relabelLastScope(name);
              // ensure that the last scope is a joint
              this.scopeTrack.convertLastScopeToJoint();
              return this;
            }
          }
        });
      }, {})
    );
  }

  attachRelationsToTableClass(TableClass, relations) {
    // keep a record of defined relations
    Object.keys(relations).forEach((name) => {
      TableClass.prototype.definedRelations.add(name);
    });

    // process and merge relations with table class
    merge(
      TableClass.prototype,
      Object.keys(relations).reduce((processed, name) => {
        // const relation = relations[name];
        return merge(processed, {
          [name](model) {
            if (model) {
              return relations[name].bind(this)().setName(name).forModel(model);
            } else {
              return relations[name].bind(this)().setName(name);
            }
          }
        });
      }, {})
    );
  }

  attachMethodsToTableClass(TableClass, methods) {
    // keep a record of defined methods
    Object.keys(methods).forEach((name) => {
      TableClass.prototype.definedMethods.add(name);
    });

    // process and merge relations with table class
    merge(
      TableClass.prototype,
      Object.keys(methods).reduce((processed, name) => {
        return merge(processed, {[name]: methods[name]});
      }, {})
    );
  }
}
<commit_msg>some changes to trx<commit_after>import knex from 'knex';
import KRedis from 'kredis';
import {merge, isString} from 'lodash';

import isUsableObject from './isUsableObject';
import Table from './Table';
import migrator from './migrator';
import Util from './util/Util';

export default class Orm {
  constructor(config={}) {
    if ('db' in config) {
      this.knex = knex(config.db);
    } else {
      throw new Error(`no 'db' config found`);
    }

    if ('redis' in config) {
      this.cache = new KRedis(config.redis);
    }

    // tables definitions
    this.tableClasses = new Map();

    // tables instances
    this.tables = new Map();

    // tableColumns cache
    this.tableColumns = new Map();

    // migrator
    this.migrator = migrator(this);

    // util
    this.util = new Util(this);

    // exports which can be exported in place of orm instance
    this.exports = {
      orm: this,
      table: this.table.bind(this),
      trx: this.trx.bind(this),
      raw: this.raw.bind(this),
      migrator: this.migrator,
      cache: this.cache,
      knex: this.knex,
      isUsableObject
    };
  }

  // raw expr helper
  raw(expr) {
    return knex.raw(expr);
  }

  // transaction helper
  transaction(promiseFn) {
    return this.knex.transaction(promiseFn);
  }

  // transaction shorthand
  // usage:
  // return orm.trx((t) => {
  //   return orm('users', t).save([{}, {}, {}]);
  // }).then((users) => {
  //    ...
  // });
  trx(promiseFn) {
    let outerResult;

    return this.transaction((t) => {
      return promiseFn(t).then((result) => {
        return t.commit().then(() => {
          outerResult = result;
          return result;
        });
      }).catch((e) => {
        t.rollback().then(() => {
          throw e;
        });
      });
    }).then(() => outerResult);
  }

  // method to close the database
  close() {
    const promises = [this.knex.destroy()];

    if (this.cache) {
      promises.push(this.cache.disconnect());
    }

    return Promise.all(promises);
  }

  // here, we load the columns of all the tables that have been
  // defined via the orm, and return a promise on completion
  // cos, if people wanna do that before starting the server
  // let em do that. we also call ioredis.connect if its available
  load() {
    const promises = Array.from(this.tables.keys).map((name) => this.table(name).load());

    if (this.cache) {
      promises.push(this.cache.connect());
    }

    return Promise.all(promises);
  }

  // get a tableClass
  tableClass(tableName) {
    return this.tableClasses.get(tableName);
  }

  // get a table object
  table(tableName, trx=null) {
    if (! this.tables.has(tableName)) {
      throw new Error(`trying to access invalid table ${tableName}`);
    }

    const tbl = this.tables.get(tableName).fork();

    if (trx !== null) {
      tbl.transacting(trx);
    }

    return tbl;
  }

  // shorthand for table
  tbl(tableName, trx=null) {
    return this.table(tableName, trx);
  }

  defineTable(params={}) {
    const tableName = params.name;

    if (! isString(tableName)) {
      throw new Error(`Invalid table-name: ${tableName} supplied via key 'name'`);
    }

    if (this.tableClasses.has(tableName)) {
      throw new Error(`Table '${tableName}' already defined`);
    }

    this.tableClasses.set(tableName, this.newTableClass(params));
    this.instantitateTable(tableName, params);
    return this;
  }

  extendTable(tableName, {scopes={}, joints={}, relations={}, methods={}}) {
    if (! this.tableClasses.has(tableName)) {
      throw new Error(`Table '${tableName}' not defined yet`);
    }

    const TableClass = this.tableClass(tableName);
    const ExtendedTableClass = class extends TableClass {};

    this.attachScopesToTableClass(ExtendedTableClass, scopes);
    this.attachJointsToTableClass(ExtendedTableClass, joints);
    this.attachRelationsToTableClass(ExtendedTableClass, relations);
    this.attachMethodsToTableClass(ExtendedTableClass, methods);

    this.tableClasses.set(tableName, ExtendedTableClass);
    this.instantitateTable(tableName);
    return this;
  }

  instantitateTable(tableName) {
    const TableClass = this.tableClasses.get(tableName);

    return this.tables.set(tableName, new TableClass(this));
  }

  newTableClass(params) {
    return this.extendTableClass(Table, params);
  }

  extendTableClass(TableClass, params) {
    const {name, props, processors, scopes, joints, relations, methods} = merge(
      // the defaults
      {
        // the table's name, is required
        name: null,

        // table properties
        props: {
          key: 'id',
          // default key column, can be ['user_id', 'post_id'] for composite keys
          autoId: false,
          // by default we don't assume that you use an auto generated db id
          perPage: 25,
          // standard batch size per page used by `forPage` method
          // forPage method uses offset
          // avoid that and use a keyset in prod (http://use-the-index-luke.com/no-offset)
          timestamps: false
          // set to `true` if you want auto timestamps or
          // timestamps: ['created_at', 'updated_at'] (these are defaults when `true`)
          // will be assigned in this order only
        },

        // used to process model and collection results fetched from the db
        // override as you need to
        processors: {
          model(row) { return row; },
          collection(rows) { return rows; }
        },

        // predefined scopes on the table
        scopes: {},
        // predefined joints on the table
        joints: {},
        // relations definitions for the table
        relations: {},
        // table methods defintions
        methods: {}
      },
      // supplied params which will override the defaults
      params
    );

    // the extended table class whose objects will behave as needed
    const ExtendedTableClass = class extends TableClass {};

    // assign name to the table class
    ExtendedTableClass.prototype.name = name;

    // assign props to the table class
    ExtendedTableClass.prototype.props = props;

    // assign processors to the table class
    ExtendedTableClass.prototype.processors = processors;

    // store names of defined scopes, joints, relations, and methods
    ExtendedTableClass.prototype.definedScopes = new Set();
    ExtendedTableClass.prototype.definedJoints = new Set();
    ExtendedTableClass.prototype.definedRelations = new Set();
    ExtendedTableClass.prototype.definedMethods = new Set();

    // attach scopes, joints, relations and methods to tables
    // these are the only ones extendable after creation
    this.attachScopesToTableClass(ExtendedTableClass, scopes);
    this.attachJointsToTableClass(ExtendedTableClass, joints);
    this.attachRelationsToTableClass(ExtendedTableClass, relations);
    this.attachMethodsToTableClass(ExtendedTableClass, methods);

    // return the extended table class
    return ExtendedTableClass;
  }

  attachScopesToTableClass(TableClass, scopes) {
    // keep a record of defined scopes
    Object.keys(scopes).forEach((name) => {
      TableClass.prototype.definedScopes.add(name);
    });

    // process and merge scopes with table class
    merge(
      TableClass.prototype,
      Object.keys(scopes).reduce((processed, name) => {
        return merge(processed, {
          [name](...args) {
            scopes[name].apply(this, args);
            // set the label of the last pushed scope
            this.scopeTrack.relabelLastScope(name);
            return this;
          }
        });
      }, {})
    );
  }

  attachJointsToTableClass(TableClass, joints) {
    // keep a record of defined joints
    Object.keys(joints).forEach((name) => {
      TableClass.prototype.definedJoints.add(name);
    });

    // process and merge joints with table class
    merge(
      TableClass.prototype,
      Object.keys(joints).reduce((processed, name) => {
        // predefined joints never take arguments
        return merge(processed, {
          [name]() {
            if (this.scopeTrack.hasJoint(name)) {
              return this;
            } else {
              joints[name].call(this);
              // set the label of the last pushed scope
              this.scopeTrack.relabelLastScope(name);
              // ensure that the last scope is a joint
              this.scopeTrack.convertLastScopeToJoint();
              return this;
            }
          }
        });
      }, {})
    );
  }

  attachRelationsToTableClass(TableClass, relations) {
    // keep a record of defined relations
    Object.keys(relations).forEach((name) => {
      TableClass.prototype.definedRelations.add(name);
    });

    // process and merge relations with table class
    merge(
      TableClass.prototype,
      Object.keys(relations).reduce((processed, name) => {
        // const relation = relations[name];
        return merge(processed, {
          [name](model) {
            if (model) {
              return relations[name].bind(this)().setName(name).forModel(model);
            } else {
              return relations[name].bind(this)().setName(name);
            }
          }
        });
      }, {})
    );
  }

  attachMethodsToTableClass(TableClass, methods) {
    // keep a record of defined methods
    Object.keys(methods).forEach((name) => {
      TableClass.prototype.definedMethods.add(name);
    });

    // process and merge relations with table class
    merge(
      TableClass.prototype,
      Object.keys(methods).reduce((processed, name) => {
        return merge(processed, {[name]: methods[name]});
      }, {})
    );
  }
}
<|endoftext|>


<commit_before>'use strict';

const co = require('co');
const broccoliTestHelper = require('broccoli-test-helper');
const expect = require('chai').expect;

const MockProject = require('../../helpers/mock-project');
const Builder = require('../../../lib/models/builder');

const { createTempDir, fromBuilder } = broccoliTestHelper;
const ROOT = process.cwd();

describe('Builder - broccoli tests', function() {
  let projectRoot, builderOutputPath, output, project, builder;

  beforeEach(co.wrap(function *() {
    projectRoot = yield createTempDir();
    builderOutputPath = yield createTempDir();

    project = new MockProject({ root: projectRoot.path() });
  }));

  afterEach(co.wrap(function *() {
    yield projectRoot.dispose();
    yield builderOutputPath.dispose();
    yield output.dispose();

    // this is needed because lib/utilities/find-build-file.js does a
    // `process.chdir` when it looks for the `ember-cli-build.js`
    process.chdir(ROOT);
  }));

  it('falls back to broccoli-builder@0.18 when legacy plugins exist in build', co.wrap(function *() {
    projectRoot.write({
      'ember-cli-build.js': `
        const fs = require('fs');
        const os = require('os');
        const crypto = require('crypto');

        function randomString() {
          return crypto
            .randomBytes(20)
            .toString('base64')
            .replace('+', '0')
            .replace('/', '0');
        }

        function LegacyPlugin (inputTree) {
          this.inputTree = inputTree;
          this.tmpDestDir = os.tmpdir() + '/' + randomString();
        }

        LegacyPlugin.prototype.read = function(readTree) {
          fs.mkdirSync(this.tmpDestDir); // doesn't handle rebuilds, yolo

          return readTree(this.inputTree).then(inputDir => {
            let sourceFile = inputDir + '/hello.txt';
            let destFile = this.tmpDestDir + '/hello.txt';
            let sourceContent = fs.readFileSync(sourceFile, 'utf-8');

            fs.writeFileSync(destFile, sourceContent);

            return this.tmpDestDir;
          });
        }

        module.exports = function () {
          return new LegacyPlugin(__dirname + '/app');
        }
      `,
      app: {
        'hello.txt': '// hello!',
      },
    });

    builder = new Builder({
      project,
      ui: project.ui,
      onProcessInterrupt: {
        addHandler() {},
        removeHandler() {},
      },
      outputPath: builderOutputPath.path(),
    });

    output = fromBuilder(builder);
    yield output.build();

    expect(output.read()).to.deep.equal({
      'hello.txt': '// hello!',
    });
    expect(builder.broccoliBuilderFallback).to.be.true;
    expect(builder.ui.output).to.include('WARNING: Invalid Broccoli2 node detected, falling back to broccoli-builder. Broccoli error:');
    expect(builder.ui.output).to.include("LegacyPlugin: The .read/.rebuild API is no longer supported as of Broccoli 1.0. Plugins must now derive from broccoli-plugin. https://github.com/broccolijs/broccoli/blob/master/docs/broccoli-1-0-plugin-api.md");
  }));
});
<commit_msg>Only assert on fallback messaging when BROCCOLI_2 enabled.<commit_after>'use strict';

const co = require('co');
const broccoliTestHelper = require('broccoli-test-helper');
const expect = require('chai').expect;

const MockProject = require('../../helpers/mock-project');
const Builder = require('../../../lib/models/builder');
const { isExperimentEnabled } = require('../../../lib/experiments');

const { createTempDir, fromBuilder } = broccoliTestHelper;
const ROOT = process.cwd();

describe('Builder - broccoli tests', function() {
  let projectRoot, builderOutputPath, output, project, builder;

  beforeEach(co.wrap(function *() {
    projectRoot = yield createTempDir();
    builderOutputPath = yield createTempDir();

    project = new MockProject({ root: projectRoot.path() });
  }));

  afterEach(co.wrap(function *() {
    yield projectRoot.dispose();
    yield builderOutputPath.dispose();
    yield output.dispose();

    // this is needed because lib/utilities/find-build-file.js does a
    // `process.chdir` when it looks for the `ember-cli-build.js`
    process.chdir(ROOT);
  }));

  it('falls back to broccoli-builder@0.18 when legacy plugins exist in build', co.wrap(function *() {
    projectRoot.write({
      'ember-cli-build.js': `
        const fs = require('fs');
        const os = require('os');
        const crypto = require('crypto');

        function randomString() {
          return crypto
            .randomBytes(20)
            .toString('base64')
            .replace('+', '0')
            .replace('/', '0');
        }

        function LegacyPlugin (inputTree) {
          this.inputTree = inputTree;
          this.tmpDestDir = os.tmpdir() + '/' + randomString();
        }

        LegacyPlugin.prototype.read = function(readTree) {
          fs.mkdirSync(this.tmpDestDir); // doesn't handle rebuilds, yolo

          return readTree(this.inputTree).then(inputDir => {
            let sourceFile = inputDir + '/hello.txt';
            let destFile = this.tmpDestDir + '/hello.txt';
            let sourceContent = fs.readFileSync(sourceFile, 'utf-8');

            fs.writeFileSync(destFile, sourceContent);

            return this.tmpDestDir;
          });
        }

        module.exports = function () {
          return new LegacyPlugin(__dirname + '/app');
        }
      `,
      app: {
        'hello.txt': '// hello!',
      },
    });

    builder = new Builder({
      project,
      ui: project.ui,
      onProcessInterrupt: {
        addHandler() {},
        removeHandler() {},
      },
      outputPath: builderOutputPath.path(),
    });

    output = fromBuilder(builder);
    yield output.build();

    expect(output.read()).to.deep.equal({
      'hello.txt': '// hello!',
    });

    if (isExperimentEnabled('BROCCOLI_2')) {
      expect(builder.broccoliBuilderFallback).to.be.true;
      expect(builder.ui.output).to.include('WARNING: Invalid Broccoli2 node detected, falling back to broccoli-builder. Broccoli error:');
      expect(builder.ui.output).to.include("LegacyPlugin: The .read/.rebuild API is no longer supported as of Broccoli 1.0. Plugins must now derive from broccoli-plugin. https://github.com/broccolijs/broccoli/blob/master/docs/broccoli-1-0-plugin-api.md");
    }
  }));
});
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var page = require('page')
  , domify = require('domify')
  , delegates = require('delegates')
  , classes = require('classes')
  , request = require('superagent')
  , options = require('./options')
  , closest = require('closest')
  , autocomplete = require('autocomplete')
  , Enumerable = require('enumerable')
  , Chart = require('Chart.js')
  , log = require('debug')('proposal-options');

/**
 * Expose ProposalOptions.
 */

module.exports = ProposalOptions;

var buttonsBox = delegationBox = null;

/**
 * Proposal Options view
 *
 * @param {Array} proposals list of proposals
 * @param {Object} selected proposal object
 * @return {ProposalOptions} `ProposalOptions` instance.
 * @api public
 */

function ProposalOptions (proposal, citizen) {
  if (!(this instanceof ProposalOptions)) {
    return new ProposalOptions(proposals);
  }

  this.proposal = proposal;
  this.citizen = citizen;
  this.options = domify(options({ proposal: proposal, citizen: citizen }));
  this.events = delegates(this.options, this);
  // this.events.bind('click a.change-vote small', 'showvote');
  this.events.bind('click .vote-box .direct-vote .vote-option span', 'vote');
  this.events.bind('click .vote-box .proxy-vote .vote-option span', 'proxy');
  this.events.bind('click .vote-box .meta-data a.change-vote small', 'changevote');

  this.buttonsBox = this.options.querySelector('.vote-box .vote-options');
  this.delegationBox = this.options.querySelector('.vote-box .delegation-box');

  this.delegationInput = this.options.querySelector('.vote-box .delegation-box .delegation-input');
  this.initializeAutocomplete(this.delegationInput);
}

/**
 * Toggle voting buttons
 *
 * @param {Object} toggle element whose visibility is to be toggled
 * @return {ProposalOptions} instance of `ProposalOptions`
 * @api public
 */

ProposalOptions.prototype.toggleVisibility = function(el) {

  classes(el).toggle('hide');
}

/**
 * Vote for option
 *
 * @param {Object} ev event
 * @api private
 */

ProposalOptions.prototype.vote = function(ev) {
  ev.preventDefault();

  var target = closest(ev.target, '.vote-option')
    , id = target.getAttribute('data-proposal')
    , value;

  if (classes(target).has('vote-no')) {
    value = 'negative';
  } else if (classes(target).has('vote-yes')) {
    value = 'positive';
  } else if (classes(target).has('vote-abstain')) {
    value = 'neutral';
  }

  this.post(
    '/api/proposal/:id/vote'.replace(':id', id),
    {value:value},
    function(res) { page(window.location.pathname) }
  );
}

/**
 * Event handler for clicking the delegation button
 * @param  {Object} ev event
 * @return {ProposalOptions}    instance of `ProposalOptions`
 * @api private
 */
ProposalOptions.prototype.proxy = function(ev) {
  ev.preventDefault();

  this.toggleVisibility(this.buttonsBox);
  this.toggleVisibility(this.delegationBox);
}

ProposalOptions.prototype.delegate = function(ev) {
  ev.preventDefault();

  //CONTINUE HERE - gvilarino
  // var target = closest
  //get stuff from event

  this.post(
    '/api/delegation/create',
    { tag: 'tag', tid: 'trusteeId' },
    function(res) { page(windows.location.pathname) }
  );
}

/**
 * Change vote
 *
 * @param {Object} ev event
 * @api private
 */

ProposalOptions.prototype.changevote = function(ev) {
  ev.preventDefault();

  classes(this.buttonsBox).toggle('hide', false);
};

ProposalOptions.prototype.post = function(path, payload, onSucces, onBodyError, onError) {
  request
  .post(path)
  .set('Accept', 'application/json')
  .send(payload)
  .end(function (err, res) {
    if (err) {
      log(err);
      if (onError) {
        return onError(err);
      }
      else return;
    };

    if (res.body.error) {
      log(res.body.error);
      if (onBodyError) {
        return onBodyError();
      } else if (res.body.action && res.body.action.redirect) {
        return window.location.replace(res.body.action.redirect);
      };
    }

    if (onSucces) {
      return onSucces(res);
    }
    else return;
  });
};

/**
 * Render options
 *
 * @return {NodeElement} proposals options
 * @api public
 */

ProposalOptions.prototype.render = function() {
  // this.renderChart(); UNDONE: from previous layout; was breaking rendering
  return this.options;
}

ProposalOptions.prototype.initializeAutocomplete = function(input) {
  var me = this.citizen;

  autocomplete(input, '/api/citizen/search?q=:q')
  .label('fullName')
  .value('id')
  .parse(function(data){
    return Enumerable(data).reject('id == "' + me.id + '"').value();
  })
  .format(function(label, q) {
    //Format results displayed in select-box
    var r = new RegExp('(?:' + q + ')', 'i');
    return label.replace(r, '$&');
  })
  .on('select', function(id) {
    console.log(id);
  })
};

/**
 * Render chart into options block
 *
 * @return {ProposalOptions} `ProposalOptions` instance.
 * @api public
 */

ProposalOptions.prototype.renderChart = function() {
  var container = this.options.querySelector('#vote-chart');
  var vote = this.proposal.vote;
  var data = [];

  if (vote.census.length) {
    data.push({
      value: vote.positive.length,
      color: "#a4cb53",
      label: "YES",
      labelColor: "white",
      labelAlign: "center"
    });
    data.push({
      value: vote.negative.length,
      color: "#d95e59",
      label: "NO",
      labelColor: "white",
      labelAlign: "center"
    });

    new Chart(container.getContext('2d')).Pie(data);
  } else {
    var p = document.createElement('p');
    p.classList.add('alert');
    p.classList.add('alert-info');
    p.innerHTML = "No voting yet."
    container.parentNode.insertBefore(p, container);
  }
}<commit_msg>[proposal-options] - Change voting route to `/api/law/:id/vote`<commit_after>/**
 * Module dependencies.
 */

var page = require('page')
  , domify = require('domify')
  , delegates = require('delegates')
  , classes = require('classes')
  , request = require('superagent')
  , options = require('./options')
  , closest = require('closest')
  , autocomplete = require('autocomplete')
  , Enumerable = require('enumerable')
  , Chart = require('Chart.js')
  , log = require('debug')('proposal-options');

/**
 * Expose ProposalOptions.
 */

module.exports = ProposalOptions;

var buttonsBox = delegationBox = null;

/**
 * Proposal Options view
 *
 * @param {Array} proposals list of proposals
 * @param {Object} selected proposal object
 * @return {ProposalOptions} `ProposalOptions` instance.
 * @api public
 */

function ProposalOptions (proposal, citizen) {
  if (!(this instanceof ProposalOptions)) {
    return new ProposalOptions(proposals);
  }

  this.proposal = proposal;
  this.citizen = citizen;
  this.options = domify(options({ proposal: proposal, citizen: citizen }));
  this.events = delegates(this.options, this);
  // this.events.bind('click a.change-vote small', 'showvote');
  this.events.bind('click .vote-box .direct-vote .vote-option span', 'vote');
  this.events.bind('click .vote-box .proxy-vote .vote-option span', 'proxy');
  this.events.bind('click .vote-box .meta-data a.change-vote small', 'changevote');

  this.buttonsBox = this.options.querySelector('.vote-box .vote-options');
  this.delegationBox = this.options.querySelector('.vote-box .delegation-box');

  this.delegationInput = this.options.querySelector('.vote-box .delegation-box .delegation-input');
  this.initializeAutocomplete(this.delegationInput);
}

/**
 * Toggle voting buttons
 *
 * @param {Object} toggle element whose visibility is to be toggled
 * @return {ProposalOptions} instance of `ProposalOptions`
 * @api public
 */

ProposalOptions.prototype.toggleVisibility = function(el) {

  classes(el).toggle('hide');
}

/**
 * Vote for option
 *
 * @param {Object} ev event
 * @api private
 */

ProposalOptions.prototype.vote = function(ev) {
  ev.preventDefault();

  var target = closest(ev.target, '.vote-option')
    , id = target.getAttribute('data-proposal')
    , value;

  if (classes(target).has('vote-no')) {
    value = 'negative';
  } else if (classes(target).has('vote-yes')) {
    value = 'positive';
  } else if (classes(target).has('vote-abstain')) {
    value = 'neutral';
  }

  this.post(
    '/api/law/:id/vote'.replace(':id', id),
    {value:value},
    function(res) { page(window.location.pathname) }
  );
}

/**
 * Event handler for clicking the delegation button
 * @param  {Object} ev event
 * @return {ProposalOptions}    instance of `ProposalOptions`
 * @api private
 */
ProposalOptions.prototype.proxy = function(ev) {
  ev.preventDefault();

  this.toggleVisibility(this.buttonsBox);
  this.toggleVisibility(this.delegationBox);
}

ProposalOptions.prototype.delegate = function(ev) {
  ev.preventDefault();

  //CONTINUE HERE - gvilarino
  // var target = closest
  //get stuff from event

  this.post(
    '/api/delegation/create',
    { tag: 'tag', tid: 'trusteeId' },
    function(res) { page(windows.location.pathname) }
  );
}

/**
 * Change vote
 *
 * @param {Object} ev event
 * @api private
 */

ProposalOptions.prototype.changevote = function(ev) {
  ev.preventDefault();

  classes(this.buttonsBox).toggle('hide', false);
};

ProposalOptions.prototype.post = function(path, payload, onSucces, onBodyError, onError) {
  request
  .post(path)
  .set('Accept', 'application/json')
  .send(payload)
  .end(function (err, res) {
    if (err) {
      log(err);
      if (onError) {
        return onError(err);
      }
      else return;
    };

    if (res.body.error) {
      log(res.body.error);
      if (onBodyError) {
        return onBodyError();
      } else if (res.body.action && res.body.action.redirect) {
        return window.location.replace(res.body.action.redirect);
      };
    }

    if (onSucces) {
      return onSucces(res);
    }
    else return;
  });
};

/**
 * Render options
 *
 * @return {NodeElement} proposals options
 * @api public
 */

ProposalOptions.prototype.render = function() {
  // this.renderChart(); UNDONE: from previous layout; was breaking rendering
  return this.options;
}

ProposalOptions.prototype.initializeAutocomplete = function(input) {
  var me = this.citizen;

  autocomplete(input, '/api/citizen/search?q=:q')
  .label('fullName')
  .value('id')
  .parse(function(data){
    return Enumerable(data).reject('id == "' + me.id + '"').value();
  })
  .format(function(label, q) {
    //Format results displayed in select-box
    var r = new RegExp('(?:' + q + ')', 'i');
    return label.replace(r, '$&');
  })
  .on('select', function(id) {
    console.log(id);
  })
};

/**
 * Render chart into options block
 *
 * @return {ProposalOptions} `ProposalOptions` instance.
 * @api public
 */

ProposalOptions.prototype.renderChart = function() {
  var container = this.options.querySelector('#vote-chart');
  var vote = this.proposal.vote;
  var data = [];

  if (vote.census.length) {
    data.push({
      value: vote.positive.length,
      color: "#a4cb53",
      label: "YES",
      labelColor: "white",
      labelAlign: "center"
    });
    data.push({
      value: vote.negative.length,
      color: "#d95e59",
      label: "NO",
      labelColor: "white",
      labelAlign: "center"
    });

    new Chart(container.getContext('2d')).Pie(data);
  } else {
    var p = document.createElement('p');
    p.classList.add('alert');
    p.classList.add('alert-info');
    p.innerHTML = "No voting yet."
    container.parentNode.insertBefore(p, container);
  }
}<|endoftext|>


<commit_before>/**
 * Created by tushar.mathur on 18/06/16.
 */

'use strict'

import {Observable as O} from 'rx'
import {mux} from 'muxer'
import R from 'ramda'

export const ev = R.curry((event, message) => message.event === event)

export const RequestParams = R.curry((request, params) => {
  return O.create((observer) => request(params)
    .on('data', (message) => observer.onNext({event: 'data', message}))
    .on('response', (message) => observer.onNext({event: 'response', message}))
    .on('complete', () => observer.onCompleted())
    .on('error', (error) => observer.onError(error))
  )
})

export const Request = R.curry((request, requestParams$) => {
  const response$ = requestParams$.flatMap(RequestParams(request))
  return mux({
    response$: response$.filter(ev('response')),
    data$: response$.filter(ev('data'))
  })
})
<commit_msg>refactor(Request): use request as params instead of a stream<commit_after>/**
 * Created by tushar.mathur on 18/06/16.
 */

'use strict'

import {Observable as O} from 'rx'
import {mux} from 'muxer'
import R from 'ramda'

export const ev = R.curry(($, event) => $.filter(R.whereEq({event})).pluck('message'))

export const RequestParams = R.curry((request, params) => {
  return O.create((observer) => request(params)
    .on('data', (message) => observer.onNext({event: 'data', message}))
    .on('response', (message) => observer.onNext({event: 'response', message}))
    .on('complete', () => observer.onCompleted())
    .on('error', (error) => observer.onError(error))
  )
})

export const Request = R.curry((request, params) => {
  const Response$ = ev(RequestParams(params))
  return mux({
    response$: Response$('response'),
    data$: Response$('data')
  })
})
<|endoftext|>


<commit_before>import React, { Component } from "react";
import { Button, Progress } from "reactstrap";
import { Link } from "react-router-dom";

import config from "./config";
import ControlsModal from "./ControlsModal";
import Emulator from "./Emulator";

import "./RunPage.css";

function loadBinary(path, callback, handleProgress) {
  var req = new XMLHttpRequest();
  req.open("GET", path);
  req.overrideMimeType("text/plain; charset=x-user-defined");
  req.onload = function() {
    if (this.status === 200) {
      if (req.responseText.match(/^<!doctype html>/i)) {
        // Got HTML back, so it is probably falling back to index.html due to 404
        return callback(new Error("Page not found"));
      }

      callback(null, this.responseText);
    } else if (this.status === 0) {
      // Aborted, so ignore error
    } else {
      callback(new Error(req.statusText));
    }
  };
  req.onerror = function() {
    callback(new Error(req.statusText));
  };
  req.onprogress = handleProgress;
  req.send();
  return req;
}

/*
 * The UI for the emulator. Also responsible for loading ROM from URL or file.
 */
class RunPage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      rom: null,
      romData: null,
      running: false,
      paused: false,
      controlsModalOpen: false,
      loading: true,
      loadedPercent: 3,
      error: null
    };
  }

  render() {
    return (

         {
            this.navbar = el;
          }}
        >

              <Link to="/" className="nav-link">
                ‹ Back
              </Link>

                {this.state.rom && this.state.rom.description}

              <Button
                outline
                color="primary"
                onClick={this.toggleControlsModal}
                className="mr-3"
              >
                Controls
              </Button>
              <Button
                outline
                color="primary"
                onClick={this.handlePauseResume}
                disabled={!this.state.running}
              >
                {this.state.paused ? "Resume" : "Pause"}
              </Button>

        {this.state.error ? (
          this.state.error
        ) : (

 {
              this.screenContainer = el;
            }}
          >
            {this.state.loading ? (
              <Progress
                value={this.state.loadedPercent}
                style={{
                  position: "absolute",
                  width: "70%",
                  left: "15%",
                  top: "48%"
                }}
              />
            ) : this.state.romData ? (
              <Emulator
                romData={this.state.romData}
                paused={this.state.paused}
                ref={emulator => {
                  this.emulator = emulator;
                }}
              />
            ) : null}

            {/* TODO: lift keyboard and gamepad state up */}
            {this.state.controlsModalOpen && (
              <ControlsModal
                isOpen={this.state.controlsModalOpen}
                toggle={this.toggleControlsModal}
                keys={this.emulator.keyboardController.keys}
                setKeys={this.emulator.keyboardController.setKeys}
                promptButton={this.emulator.gamepadController.promptButton}
                gamepadConfig={this.emulator.gamepadController.gamepadConfig}
                setGamepadConfig={
                  this.emulator.gamepadController.setGamepadConfig
                }
              />
            )}

        )}

    );
  }

  componentDidMount() {
    window.addEventListener("resize", this.layout);
    this.layout();
    this.load();
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.layout);
    if (this.currentRequest) {
      this.currentRequest.abort();
    }
  }

  load = () => {
    if (this.props.match.params.slug) {
      const slug = this.props.match.params.slug;
      const isLocalROM = /^local-/.test(slug);
      const savedString = localStorage.getItem("blob-" + slug.split("-")[1]);
      const rom = isLocalROM ? savedString : config.ROMS[slug];
      if (!rom) {
        this.setState({ error: `No such ROM: ${slug}` });
        return;
      }
      this.setState({ rom: rom });
      if (isLocalROM) {
        this.handleLoaded(rom);
      } else {
        this.currentRequest = loadBinary(
          rom.url,
          (err, data) => {
            if (err) {
              this.setState({ error: `Error loading ROM: ${err.message}` });
            } else {
              this.handleLoaded(data);
            }
          },
          this.handleProgress
        );
      }
    } else if (this.props.location.state && this.props.location.state.file) {
      let reader = new FileReader();
      reader.readAsBinaryString(this.props.location.state.file);
      reader.onload = e => {
        this.currentRequest = null;
        this.handleLoaded(reader.result);
      };
    } else {
      this.setState({ error: "No ROM provided" });
    }
  };

  handleProgress = e => {
    if (e.lengthComputable) {
      this.setState({ loadedPercent: (e.loaded / e.total) * 100 });
    }
  };

  handleLoaded = data => {
    this.setState({ running: true, loading: false, romData: data });
  };

  handlePauseResume = () => {
    this.setState({ paused: !this.state.paused });
  };

  layout = () => {
    let navbarHeight = parseFloat(window.getComputedStyle(this.navbar).height);
    this.screenContainer.style.height = `${window.innerHeight -
      navbarHeight}px`;
    if (this.emulator) {
      this.emulator.fitInParent();
    }
  };

  toggleControlsModal = () => {
    this.setState({ controlsModalOpen: !this.state.controlsModalOpen });
  };
}

export default RunPage;
<commit_msg>Refactor: Use "romInfo" instead of "rom" so metadata is not confused with ROM data in code<commit_after>import React, { Component } from "react";
import { Button, Progress } from "reactstrap";
import { Link } from "react-router-dom";

import config from "./config";
import ControlsModal from "./ControlsModal";
import Emulator from "./Emulator";

import "./RunPage.css";

function loadBinary(path, callback, handleProgress) {
  var req = new XMLHttpRequest();
  req.open("GET", path);
  req.overrideMimeType("text/plain; charset=x-user-defined");
  req.onload = function() {
    if (this.status === 200) {
      if (req.responseText.match(/^<!doctype html>/i)) {
        // Got HTML back, so it is probably falling back to index.html due to 404
        return callback(new Error("Page not found"));
      }

      callback(null, this.responseText);
    } else if (this.status === 0) {
      // Aborted, so ignore error
    } else {
      callback(new Error(req.statusText));
    }
  };
  req.onerror = function() {
    callback(new Error(req.statusText));
  };
  req.onprogress = handleProgress;
  req.send();
  return req;
}

/*
 * The UI for the emulator. Also responsible for loading ROM from URL or file.
 */
class RunPage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      romName: null,
      romData: null,
      running: false,
      paused: false,
      controlsModalOpen: false,
      loading: true,
      loadedPercent: 3,
      error: null
    };
  }

  render() {
    return (

         {
            this.navbar = el;
          }}
        >

              <Link to="/" className="nav-link">
                ‹ Back
              </Link>

                {this.state.romName}

              <Button
                outline
                color="primary"
                onClick={this.toggleControlsModal}
                className="mr-3"
              >
                Controls
              </Button>
              <Button
                outline
                color="primary"
                onClick={this.handlePauseResume}
                disabled={!this.state.running}
              >
                {this.state.paused ? "Resume" : "Pause"}
              </Button>

        {this.state.error ? (
          this.state.error
        ) : (

 {
              this.screenContainer = el;
            }}
          >
            {this.state.loading ? (
              <Progress
                value={this.state.loadedPercent}
                style={{
                  position: "absolute",
                  width: "70%",
                  left: "15%",
                  top: "48%"
                }}
              />
            ) : this.state.romData ? (
              <Emulator
                romData={this.state.romData}
                paused={this.state.paused}
                ref={emulator => {
                  this.emulator = emulator;
                }}
              />
            ) : null}

            {/* TODO: lift keyboard and gamepad state up */}
            {this.state.controlsModalOpen && (
              <ControlsModal
                isOpen={this.state.controlsModalOpen}
                toggle={this.toggleControlsModal}
                keys={this.emulator.keyboardController.keys}
                setKeys={this.emulator.keyboardController.setKeys}
                promptButton={this.emulator.gamepadController.promptButton}
                gamepadConfig={this.emulator.gamepadController.gamepadConfig}
                setGamepadConfig={
                  this.emulator.gamepadController.setGamepadConfig
                }
              />
            )}

        )}

    );
  }

  componentDidMount() {
    window.addEventListener("resize", this.layout);
    this.layout();
    this.load();
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.layout);
    if (this.currentRequest) {
      this.currentRequest.abort();
    }
  }

  load = () => {
    if (this.props.match.params.slug) {
      const slug = this.props.match.params.slug;
      const isLocalROM = /^local-/.test(slug);
      const romInfo = config.ROMS[slug]
      if (!isLocalROM && !romInfo) {
        this.setState({ error: `No such ROM: ${slug}` });
        return;
      }
      if (isLocalROM) {
        const localROMData = localStorage.getItem("blob-" + slug.split("-")[1]);
        this.handleLoaded(localROMData);
      } else {
        this.setState({ romName: romInfo.name });
        this.currentRequest = loadBinary(
          romInfo.url,
          (err, data) => {
            if (err) {
              this.setState({ error: `Error loading ROM: ${err.message}` });
            } else {
              this.handleLoaded(data);
            }
          },
          this.handleProgress
        );
      }
    } else if (this.props.location.state && this.props.location.state.file) {
      let reader = new FileReader();
      reader.readAsBinaryString(this.props.location.state.file);
      reader.onload = e => {
        this.currentRequest = null;
        this.handleLoaded(reader.result);
      };
    } else {
      this.setState({ error: "No ROM provided" });
    }
  };

  handleProgress = e => {
    if (e.lengthComputable) {
      this.setState({ loadedPercent: (e.loaded / e.total) * 100 });
    }
  };

  handleLoaded = data => {
    this.setState({ running: true, loading: false, romData: data });
  };

  handlePauseResume = () => {
    this.setState({ paused: !this.state.paused });
  };

  layout = () => {
    let navbarHeight = parseFloat(window.getComputedStyle(this.navbar).height);
    this.screenContainer.style.height = `${window.innerHeight -
      navbarHeight}px`;
    if (this.emulator) {
      this.emulator.fitInParent();
    }
  };

  toggleControlsModal = () => {
    this.setState({ controlsModalOpen: !this.state.controlsModalOpen });
  };
}

export default RunPage;
<|endoftext|>


<commit_before>TC.control = TC.control || {};

if (!TC.Control) {
    TC.syncLoadJS(TC.apiLocation + 'TC/Control');
}

TC.control.NavBar = function () {
    TC.Control.apply(this, arguments);
};

TC.inherit(TC.control.NavBar, TC.Control);

(function () {
    var ctlProto = TC.control.NavBar.prototype;

    ctlProto.CLASS = 'tc-ctl-nav';

    ctlProto.render = function () {
        var self = this;
        if (!self.wrap) {
            self.wrap = new TC.wrap.control.NavBar(self);
        }
    };

    ctlProto.register = function (map) {
        var self = this;
        TC.Control.prototype.register.call(self, map);
        self.wrap.register(map);

        //esta chama es para que la primera vez se ajuste la barrita de escala (debido a otra chama con el maxResolution, que es culpa de OL)
        map.loaded(function () {
            self.wrap.refresh();
        });

        map.on(TC.Consts.event.PROJECTIONCHANGE, function (e) {
            var bottomLeft = TC.Util.reproject([map.options.initialExtent[0], map.options.initialExtent[1]], map.options.crs, e.crs);
            var topRight = TC.Util.reproject([map.options.initialExtent[2], map.options.initialExtent[3]], map.options.crs, e.crs);
            self.wrap.setInitialExtent([bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]);
        });
    };

})();<commit_msg>Change register in NavBar to return a promise<commit_after>TC.control = TC.control || {};

if (!TC.Control) {
    TC.syncLoadJS(TC.apiLocation + 'TC/Control');
}

TC.control.NavBar = function () {
    TC.Control.apply(this, arguments);
};

TC.inherit(TC.control.NavBar, TC.Control);

(function () {
    var ctlProto = TC.control.NavBar.prototype;

    ctlProto.CLASS = 'tc-ctl-nav';

    ctlProto.render = function () {
        var self = this;
        if (!self.wrap) {
            self.wrap = new TC.wrap.control.NavBar(self);
        }
    };

    ctlProto.register = function (map) {
        const self = this;
        const result = TC.Control.prototype.register.call(self, map);
        self.wrap.register(map);

        //esta chama es para que la primera vez se ajuste la barrita de escala (debido a otra chama con el maxResolution, que es culpa de OL)
        map.loaded(function () {
            self.wrap.refresh();
        });

        map.on(TC.Consts.event.PROJECTIONCHANGE, function (e) {
            var bottomLeft = TC.Util.reproject([map.options.initialExtent[0], map.options.initialExtent[1]], map.options.crs, e.crs);
            var topRight = TC.Util.reproject([map.options.initialExtent[2], map.options.initialExtent[3]], map.options.crs, e.crs);
            self.wrap.setInitialExtent([bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]);
        });

        return result;
    };

})();<|endoftext|>


<commit_before>var Zen = (function($) {
	'use strict';

	function each(array, fn) {
		for (var i = 0, len = array.length; i < len; i++) {
			if (fn.call(array[i], i) === false) return;
		}
	}
	function includes(haystack, needle) {
		var isIncluded = false;
		each(haystack, function () {
			return !(isIncluded = this.name === needle);
		});
		return isIncluded;
	}

	function getName(properties) {
		if (properties._name) return properties._name;

		switch (properties.parent._name) {
		case 'ol':
		case 'ul':
			return 'li';
		case 'table':
			return 'tr';
		case 'tr':
			return 'td';
		case 'select':
			return 'option';
		case 'nav':
			return 'ul';
		case 'form':
			var isInput = includes(properties._attributes, 'type');
			return isInput ? 'input' : 'div';
		case 'head':
			var isMeta = includes(properties._attributes, 'content');
			return isMeta ? 'meta' : 'div';
		default:
			return 'div';
		}
	}

	function replaceDollar(value, dataSource, counter){
		var key = value.match(/\$:([a-z]+)/i)[1],
		    replacement = dataSource(key, counter - 1);
		return value.replace('$:' + key, replacement);
	}

	function interpolate(value, dataSource, counter) {
		var result = value;

		if (value.indexOf('$') < 0) return value;

		// this is the RegExp you want /^|[^\\]$:[a-z]+/i

		if((result == "$:content") || (/\-\$:[a-z]+/i.test(value) && dataSource)){
		  return replaceDollar(value, dataSource, counter);
		}

		if (/\$:[a-z]+/i.test(value) && dataSource) {
		  var key = result.match(/\$:([a-z]+)\s/g);
		  for (var i = 0; i < key.length; i++) {
		    var replacement = key[i].substring(2, key[i].length);
			result = result.replace(key[i], replacement);
		  }
			return result;
		}

		if (value.indexOf('$') && value.indexOf("$:") == -1 && value.indexOf("-$") == -1) {
		  return value.replace(/\$/, '$');
		}

		return value.replace('$', counter);
	}

	function buildNode(properties, dataSource) {
		var name = getName(properties);
		var node = document.createElement(name);

		if (properties._text) {
			// RADAR look out for IE issues
			node.textContent = interpolate(properties._text, dataSource, properties.counter);
		}

		each(properties._attributes, function () {
			this.value = interpolate(this.value, dataSource, properties.counter);
			node.setAttribute(this.name, this.value);
		});

		// be recursive
		return node;
	}

	function traverseTree(base, context, dataSource){
		var node = buildNode(base, dataSource);
		context.appendChild(node);
		each(base.children, function() {
			traverseTree(this, node, dataSource);
		});
	}

	var parser = emmet.require('abbreviationParser');

	function getterFor(data) {
		return function(key, index) {
			var value = data[key];
			return (typeof(value) === 'object') ? value[index] : value;
		};
	}

	function Zen(expression, dataSource) {
		if (typeof(dataSource) === 'object') dataSource = getterFor(dataSource);

		var fragment = document.createDocumentFragment();
		var nodes = parser.parse(expression).children;
		each(nodes, function () {
			traverseTree(this, fragment, dataSource);
		});
		return fragment;
	};

	if ($) {
		$.zen = function(expression, dataSource) {
			var fragment = Zen(expression, dataSource);
			return $(fragment);
		}
		$.fn.zen = function(expression, dataSource) {
			var fragment = Zen(expression, dataSource);
			return this.each(function() {
				var clone = fragment.cloneNode(true);
				this.innerHTML = '';
				this.appendChild(clone);
			});
		};
	}

	return Zen;

})(window.jQuery);
<commit_msg>Build default getter only if we do not get a function as a second argument.<commit_after>var Zen = (function($) {
	'use strict';

	function each(array, fn) {
		for (var i = 0, len = array.length; i < len; i++) {
			if (fn.call(array[i], i) === false) return;
		}
	}
	function includes(haystack, needle) {
		var isIncluded = false;
		each(haystack, function () {
			return !(isIncluded = this.name === needle);
		});
		return isIncluded;
	}

	function getName(properties) {
		if (properties._name) return properties._name;

		switch (properties.parent._name) {
		case 'ol':
		case 'ul':
			return 'li';
		case 'table':
			return 'tr';
		case 'tr':
			return 'td';
		case 'select':
			return 'option';
		case 'nav':
			return 'ul';
		case 'form':
			var isInput = includes(properties._attributes, 'type');
			return isInput ? 'input' : 'div';
		case 'head':
			var isMeta = includes(properties._attributes, 'content');
			return isMeta ? 'meta' : 'div';
		default:
			return 'div';
		}
	}

	function replaceDollar(value, dataSource, counter){
		var key = value.match(/\$:([a-z]+)/i)[1],
		    replacement = dataSource(key, counter - 1);
		return value.replace('$:' + key, replacement);
	}

	function interpolate(value, dataSource, counter) {
		var result = value;

		if (value.indexOf('$') < 0) return value;

		// this is the RegExp you want /^|[^\\]$:[a-z]+/i

		if((result == "$:content") || (/\-\$:[a-z]+/i.test(value) && dataSource)){
		  return replaceDollar(value, dataSource, counter);
		}

		if (/\$:[a-z]+/i.test(value) && dataSource) {
		  var key = result.match(/\$:([a-z]+)\s/g);
		  for (var i = 0; i < key.length; i++) {
		    var replacement = key[i].substring(2, key[i].length);
			result = result.replace(key[i], replacement);
		  }
			return result;
		}

		if (value.indexOf('$') && value.indexOf("$:") == -1 && value.indexOf("-$") == -1) {
		  return value.replace(/\$/, '$');
		}

		return value.replace('$', counter);
	}

	function buildNode(properties, dataSource) {
		var name = getName(properties);
		var node = document.createElement(name);

		if (properties._text) {
			// RADAR look out for IE issues
			node.textContent = interpolate(properties._text, dataSource, properties.counter);
		}

		each(properties._attributes, function () {
			this.value = interpolate(this.value, dataSource, properties.counter);
			node.setAttribute(this.name, this.value);
		});

		// be recursive
		return node;
	}

	function traverseTree(base, context, dataSource){
		var node = buildNode(base, dataSource);
		context.appendChild(node);
		each(base.children, function() {
			traverseTree(this, node, dataSource);
		});
	}

	var parser = emmet.require('abbreviationParser');

	function getterFor(data) {
		return function(key, index) {
			var value = data[key];
			return (typeof(value) === 'object') ? value[index] : value;
		};
	}

	function Zen(expression, dataSource) {
		if (typeof(dataSource) !== 'function') dataSource = getterFor(dataSource);

		var fragment = document.createDocumentFragment();
		var nodes = parser.parse(expression).children;
		each(nodes, function () {
			traverseTree(this, fragment, dataSource);
		});
		return fragment;
	};

	if ($) {
		$.zen = function(expression, dataSource) {
			var fragment = Zen(expression, dataSource);
			return $(fragment);
		}
		$.fn.zen = function(expression, dataSource) {
			var fragment = Zen(expression, dataSource);
			return this.each(function() {
				var clone = fragment.cloneNode(true);
				this.innerHTML = '';
				this.appendChild(clone);
			});
		};
	}

	return Zen;

})(window.jQuery);
<|endoftext|>