<commit_before>var Sidebar = React.createClass({
    componentDidMount: function() {
        /* Look up categories in semantic search.
         * For some reason they can't run locally,
         * but we'll use them with our API to
         * seperate users, problems, and blog posts.
         * For the moment though, they're together.
         */

        var dummySearchContent = [
            {
              title: 'Traveling Salesman Problem',
              description: 'Find the optimal route through a set of 500 points in 3D space.'
            },
            {
              title: 'Tron: A Postmortem',
              description: 'by Jake Sanders'
            },
            {
              title: 'Joshua Gruenstein',
              description: 'Horace Mann'
            }
        ];

        $('.ui.search').search({
            source: dummySearchContent
        });
    },
    gameList: function(games, active) {
        var season = -1;
        return games.map(function(game) {
            if (game.season != season) {
                season = game.season;
                return (

                            {"Season " + game.season}

                        {game.name}

                );
            } else return (
                {game.name}
            );
        });
    },
    render: function() {
        return (

                            <input className="prompt" type="text" placeholder="Search..." />

Games

                        { this.gameList(this.props.games, this.props.active) }

                    Users

                    Blog

About

NYCSL is an inter-mural programming competition for highschool students in the New York area.  Each month-ish a new problem is posted, and participants are challenged to create the optimal solution.  Challenges can be games, algorithmic problems, or something else entirely.  The top ranked students for each challenge receive prizes, and are invited to attend the NYCSL Championship at Horace Mann in the summer.

        );
    }
});

var NavBar = React.createClass({
    componentDidMount: function() {
        $("#loginBtn").click(function(e) {
            e.preventDefault();
            $('.ui.modal').modal('show');
            return false;
        });

        $('#accountBtn').popup({
            popup: '.special.popup',
            hoverable: true,
            position : 'bottom center'
        });
    },
    openMenu: function() {
        $('.ui.sidebar').sidebar('toggle');
    },
    signInModal: function() {
        return (

                    Login with Github

Click the button below to login with Github.

If you don't already have an account linked to your Github profile, that's ok. We@apos;ll automatically detect it and help you get things set up.

                    <button className="ui button fluid">

                        Connect to Github
                    </button>

        );
    },
    signUpModal: function() {
        return (

                    Signup with Github

                            School
                            <select className="ui fluid search dropdown selection">
                                <option value="">Select School</option>
                                <option value="HM">Horace Mann School</option>
                                <option value="DA">Dalton School</option>
                                <option value="ST">Stuyvesant</option>
                            </select>

                    <button className="ui button fluid">
                        Create Account
                    </button>

        );
    },
    loggedInMenu: function(githubID) {
        return (

                    Submit

                        Profile

                        Logout

        );
    },
    loggedOutMenu: function() {
        return (

                    Login with Github

        );
    },
    render: function() {
        return (

                    NYCSL

                     Menu

                { this.props.logState ? this.loggedInMenu(this.props.githubID) : this.loggedOutMenu() }

        );
    }
});

var games = [
    { id:"ST", name:"Steiner Tree", season:0 },
    { id:"TR", name:"Tron", season:0 },
    { id:"RM", name:"Roommate", season:0 },
    { id:"TS", name:"Traveling Salesman", season:0 }
];

ReactDOM.render(
    <Sidebar games={games} active="ST" />,
    document.getElementById('sidebarBox')
);

ReactDOM.render(
    <NavBar githubID="7736334" logState={true} />,
    document.getElementById('navbarBox')
);
<commit_msg>react-ify login modal<commit_after>var Sidebar = React.createClass({
    componentDidMount: function() {
        /* Look up categories in semantic search.
         * For some reason they can't run locally,
         * but we'll use them with our API to
         * seperate users, problems, and blog posts.
         * For the moment though, they're together.
         */

        var dummySearchContent = [
            { title: 'Traveling Salesman Problem', description: 'Find the optimal route through a set of 500 points in 3D space.' },
            { title: 'Tron: A Postmortem', description: 'by Jake Sanders' },
            { title: 'Joshua Gruenstein', description: 'Horace Mann' }
        ];

        $('.ui.search').search({
            source: dummySearchContent
        });
    },
    gameList: function(games, active) {
        var season = -1;
        return games.map(function(game) {
            if (game.season != season) {
                season = game.season;
                return (

                            {"Season " + game.season}

                        {game.name}

                );
            } else return (
                {game.name}
            );
        });
    },
    render: function() {
        return (

                            <input className="prompt" type="text" placeholder="Search..." />

Games

                        { this.gameList(this.props.games, this.props.active) }

                    Users

                    Blog

About

NYCSL is an inter-mural programming competition for highschool students in the New York area.  Each month-ish a new problem is posted, and participants are challenged to create the optimal solution.  Challenges can be games, algorithmic problems, or something else entirely.  The top ranked students for each challenge receive prizes, and are invited to attend the NYCSL Championship at Horace Mann in the summer.

        );
    }
});

var NavBar = React.createClass({
    componentDidMount: function() {
        $('#accountBtn').popup({
            popup: '.special.popup',
            hoverable: true,
            position : 'bottom center'
        });
    },
    openMenu: function() {
        $('.ui.sidebar').sidebar('toggle');
    },
    openLoginModal: function() {
        $('.ui.modal').modal('show');
    },
    signInModal: function() {
        return (

                    Login with Github

Click the button below to login with Github.

If you don't already have an account linked to your Github profile, that's ok. We'll automatically detect it and help you get things set up.

                    <button className="ui button fluid">

                        Connect to Github
                    </button>

        );
    },
    signUpModal: function() {
        return (

                    Signup with Github

                            School
                            <select className="ui fluid search dropdown selection">
                                <option value="">Select School</option>
                                <option value="HM">Horace Mann School</option>
                                <option value="DA">Dalton School</option>
                                <option value="ST">Stuyvesant</option>
                            </select>

                    <button className="ui button fluid">
                        Create Account
                    </button>

        );
    },
    loggedInMenu: function(githubID) {
        return (

                    Submit

                        Profile

                        Logout

        );
    },
    loggedOutMenu: function() {
        return (

                    Login with Github

                { this.signInModal() }

        );
    },
    render: function() {
        return (

                    NYCSL

                     Menu

                { this.props.logState ? this.loggedInMenu(this.props.githubID) : this.loggedOutMenu() }

        );
    }
});

var games = [
    { id:"ST", name:"Steiner Tree", season:0 },
    { id:"TR", name:"Tron", season:0 },
    { id:"RM", name:"Roommate", season:0 },
    { id:"TS", name:"Traveling Salesman", season:0 }
];

ReactDOM.render(
    <Sidebar games={games} active="ST" />,
    document.getElementById('sidebarBox')
);

ReactDOM.render(
    <NavBar githubID="7736334" logState={false} />,
    document.getElementById('navbarBox')
);
<|endoftext|>


<commit_before>(function($) {
  var config = {
    selectors: { // according to query selector standards
      project: '.project',
      project_id: 'data-id',
      environment: '.environment',
      story_column: '.story',
      github_link: '.GitHubDiffURL',
      refresh_button: '.refresh',
    },
    github: {
      url_compare_regexp: /.*\/(.*)\/compare/
    },
    urls: {
      pivotal: {
        base: 'https://www.pivotaltracker.com',
        story: '/story/show',
        api: '/services/v5',
      }
    }
  };

  /**
   * removeDupesFromArray returns an array without dupes
   * @param  {Array} arr Any array
   * @return {Array}     Array without dups
   */
  function removeDupesFromArray(arr) {
    return arr.filter(function(elem, i) {
      return arr.indexOf(elem) == i;
    });
  }

  /**
   * mapStatusLabelClass returns label class type (as of Twitter Bootstrap 3)
   * @param  {string} status Pivotal story status
   * @return {string}        Bootstrap class name
   */
  function mapStatusLabelClass(status) {
    switch(status) {
      case 'rejected':
        return 'danger';
      case 'accepted':
        return 'success';
      case 'delivered':
        return 'warning';
      case 'finished':
        return 'primary';
      case 'started':
        return 'info';
      default:
        return 'default';
    }
  }

  /**
   * getProjectDiffs return an Object, project name as the key and github diff URLs
   * as the value
   * @return {Object} {project_name: diff_url}
   */
  function getProjectDiffs() {
    var diffURLs = {};

    $(config.selectors.project).each(function() {
      var $this = $(this);
      var project = $this.data('id');
      var url = $this.find(config.selectors.github_link).attr('href');

      if (url) {
        diffURLs[project] = url;
      }
    });

    return diffURLs;
  }

  /**
   * getLinkDiv return an HTML string of story link and status
   * @param  {Object} pt_info Pivotal story object
   * @return {String}         HTML string
   */
  function getLinkDiv(pt_info) {
    var links = [];

    for (f in pt_info) {
      var story = pt_info[f];
      var status = ''+ story.status +'';
      var dep = ''+ story.dependencies.length +'';

      links.push('#'+ story.id +''+ status + dep +'
');
    }

    return links.join('');
  }

  function injectPivotalStatus(project_id, pt_info) {
    var project_selector = config.selectors.project + '[' + config.selectors.project_id + '="' + project_id + '"]';
    var $project = $(project_selector).find(config.selectors.story_column);
    $project.append(getLinkDiv(pt_info));
    $project.find('[data-toggle="popover"]').popover({
      html: true,
      trigger: 'hover',
      placement: 'top'
    });
  }

  /**
   * getGithubCommits returns Github commits for a given repository
   * @param  {String}   github_token Github token
   * @param  {String}   repo         Github repository name
   * @param  {String}   sha1         Current commit hash
   * @param  {String}   sha2         Latest commit hash
   * @param  {Function} callback
   */
  function getGithubCommits(github_token, repo, sha1, sha2, callback) {
    $.ajax({
      url: 'https://api.github.com/repos/gengo/'+ repo +'/compare/'+ sha1 +'...'+ sha2,
      type: 'GET',
      headers: {
        'Authorization': 'token '+ github_token
      },
      success: function(data) {
        callback(data.commits);
      },
      error: function(err) {
        console.error(err);
      }
    });
  }

  /**
   * getPivotalStoryIDs return an array of Pivotal story IDs from array of messages
   * @param  {Array} msgs Array of string messages
   * @return {Array}      Array of pivotal IDs
   */
  function getPivotalStoryIDs(msgs) {
    var storyIDs = msgs.map(function(str) {
      return parseInt(str.match(/\[#(\d+)\]/)[1], 10);
    });

    return removeDupesFromArray(storyIDs);
  }

  /**
   * getPivotalStoryInfo return pivotal story data
   * @param  {string}   pt_token Pivotal token
   * @param  {number}   story_id Story id
   * @param  {Function} callback
   */
  function getPivotalStoryInfo(pt_token, story_id, callback) {
    $.ajax({
      url: config.urls.pivotal.base + config.urls.pivotal.api + '/stories/' + story_id,
      type: 'GET',
      headers: {
        'X-TrackerToken': pt_token
      },
      success: function(data) {
        getRepoDependencies(pt_token, data.project_id, story_id, function(list) {
          callback({
            id: story_id,
            url: data.url,
            status: data.current_state,
            dependencies: list
          });
        });
      }
    });
  }

  /**
   * getRepoDependencies return a list of dependencies for stroy in a project
   * @param  {String}   pt_token   Pivotal token
   * @param  {number}   project_id Project ID
   * @param  {number}   story_id   Story ID
   * @param  {Function} callback   Returns Pivotal story ID list
   */
  function getRepoDependencies(pt_token, project_id, story_id, callback) {
    $.ajax({
      url: config.urls.pivotal.base + config.urls.pivotal.api +'/projects/'+ project_id +'/stories/'+ story_id +'/comments',
      type: 'GET',
      headers: {
        'X-TrackerToken': pt_token
      },
      success: function(data) {
        // Find all git commit messages
        var list = data.filter(function(obj) {
          return obj.commit_type ? true : false;
        });
        // Find repo name from comment body text
        list = list.map(function(item) {
          return item.text.split('https://github.com/gengo/')[1].split('/commit/')[0];
        });

        callback(removeDupesFromArray(list));
      }
    });
  }

  /**
   * showNoStoriesMessage
   * @param  {jQuery} $target jQuery button object
   */
  function showNoStoriesMessage($target) {
    $target.closest(config.selectors.story_column).text('No stories found.');
  }

  $(document).ready(function() {
    // add button to story columns
    var button = '<button class="btn btn-default getStories">Get stories</button>Loading...';
    $(config.selectors.story_column).each(function() {
      $(this).html(button);
    });

    // When reset button clecked add Get stories button
    $(config.selectors.refresh_button).click(function() {
      $(this).closest(config.selectors.project).find(config.selectors.story_column).html(button);
    });

    $('.project').on('click', '.getStories', function(e) {
      e.preventDefault();

      var $this_button = $(e.currentTarget);
      var project = $this_button.parents(config.selectors.project).data('id');
      var diffs = getProjectDiffs();

      $this_button.hide(); // do not show button

      if (project in diffs) {
        // great! we found diffs for this project; load the pivotal stories
        $this_button.siblings('.loading').show();

        (function(project) {
          var url = diffs[project];
          // hashes: currentCommit...latestCommit
          var commitHashes = (url.substr(url.lastIndexOf('/') + 1)).split('...');
          var repositoryName = url.match(config.github.url_compare_regexp)[1];

          getGithubCommits(GITHUB_TOKEN, repositoryName, commitHashes[0], commitHashes[1], function(commits) {
            // Array of comitt messages
            var messages = commits.map(function(obj) {
              return obj.commit.message;
            });
            // Array of pivotal story IDs
            var pivotal_ids = getPivotalStoryIDs(messages);
            if (!pivotal_ids) {
              showNoStoriesMessage($this_button);
              return;
            };

            $this_button.siblings('.loading').hide();

            var display_message = [];
            for (pt_id in pivotal_ids) {
              var id = pivotal_ids[pt_id];

              getPivotalStoryInfo(PIVOTAL_TOKEN, id, function(info) {
                display_message[id] = info;
                injectPivotalStatus(project, display_message);
              });
            }
          });
        })(project);
      }
      else {
        showNoStoriesMessage($this_button);
      }
    });

  });
}(jQuery));
<commit_msg>fexes on feedback<commit_after>(function($) {
  var config = {
    selectors: { // according to query selector standards
      project: '.project',
      project_id: 'data-id',
      environment: '.environment',
      story_column: '.story',
      github_link: '.GitHubDiffURL',
      refresh_button: '.refresh',
    },
    github: {
      url_compare_regexp: /.*\/(.*)\/compare/
    },
    urls: {
      pivotal: {
        base: 'https://www.pivotaltracker.com',
        story: '/story/show',
        api: '/services/v5',
      }
    }
  };

  /**
   * removeDupesFromArray returns an array without dupes
   * @param  {Array} arr Any array
   * @return {Array}     Array without dups
   */
  function removeDupesFromArray(arr) {
    return arr.filter(function(elem, i) {
      return arr.indexOf(elem) == i;
    });
  }

  /**
   * mapStatusLabelClass returns label class type (as of Twitter Bootstrap 3)
   * @param  {string} status Pivotal story status
   * @return {string}        Bootstrap class name
   */
  function mapStatusLabelClass(status) {
    switch(status) {
      case 'rejected':
        return 'danger';
      case 'accepted':
        return 'success';
      case 'delivered':
        return 'warning';
      case 'finished':
        return 'primary';
      case 'started':
        return 'info';
      default:
        return 'default';
    }
  }

  /**
   * getProjectDiffs return an Object, project name as the key and github diff URLs
   * as the value
   * @return {Object} {project_name: diff_url}
   */
  function getProjectDiffs() {
    var diffURLs = {};

    $(config.selectors.project).each(function() {
      var $this = $(this);
      var project = $this.data('id');
      var url = $this.find(config.selectors.github_link).attr('href');

      if (url) {
        diffURLs[project] = url;
      }
    });

    return diffURLs;
  }

  /**
   * getLinkDiv return an HTML string of story link and status
   * @param  {Object} pt_info Pivotal story object
   * @return {String}         HTML string
   */
  function getLinkDiv(pt_info) {
    var links = [];

    for (f in pt_info) {
      var story = pt_info[f];
      var status = ''+ story.status +'';
      var dep = ''+ story.dependencies.length +'';

      links.push('#'+ story.id +''+ status + dep +'
');
    }

    return links.join('');
  }

  function injectPivotalStatus(project_id, pt_info) {
    var project_selector = config.selectors.project + '[' + config.selectors.project_id + '="' + project_id + '"]';
    var $project = $(project_selector).find(config.selectors.story_column);
    $project.append(getLinkDiv(pt_info));
    $project.find('[data-toggle="popover"]').popover({
      html: true,
      trigger: 'hover',
      placement: 'top'
    });
  }

  /**
   * getGithubCommits returns Github commits for a given repository
   * @param  {String}   github_token Github token
   * @param  {String}   repo         Github repository name
   * @param  {String}   sha1         Current commit hash
   * @param  {String}   sha2         Latest commit hash
   * @param  {Function} callback
   */
  function getGithubCommits(github_token, repo, sha1, sha2, callback) {
    $.ajax({
      url: 'https://api.github.com/repos/gengo/'+ repo +'/compare/'+ sha1 +'...'+ sha2,
      type: 'GET',
      headers: {
        'Authorization': 'token '+ github_token
      },
      success: function(data) {
        callback(data.commits);
      },
      error: function(err) {
        console.error(err);
      }
    });
  }

  /**
   * getPivotalStoryIDs return an array of Pivotal story IDs from array of messages
   * @param  {Array} msgs Array of string messages
   * @return {Array}      Array of pivotal IDs
   */
  function getPivotalStoryIDs(msgs) {
    var storyIDs = msgs.map(function(str) {
      return parseInt(str.match(/\[#(\d+)\]/)[1], 10);
    });

    return removeDupesFromArray(storyIDs);
  }

  /**
   * getPivotalStoryInfo return pivotal story data
   * @param  {string}   pt_token Pivotal token
   * @param  {number}   story_id Story id
   * @param  {Function} callback
   */
  function getPivotalStoryInfo(pt_token, story_id, callback) {
    $.ajax({
      url: config.urls.pivotal.base + config.urls.pivotal.api + '/stories/' + story_id,
      type: 'GET',
      headers: {
        'X-TrackerToken': pt_token
      },
      success: function(data) {
        getRepoDependencies(pt_token, data.project_id, story_id, function(list) {
          callback({
            id: story_id,
            url: data.url,
            status: data.current_state,
            dependencies: list
          });
        });
      }
    });
  }

  /**
   * getRepoDependencies return a list of dependencies for stroy in a project
   * @param  {String}   pt_token   Pivotal token
   * @param  {number}   project_id Project ID
   * @param  {number}   story_id   Story ID
   * @param  {Function} callback   Returns Pivotal story ID list
   */
  function getRepoDependencies(pt_token, project_id, story_id, callback) {
    $.ajax({
      url: config.urls.pivotal.base + config.urls.pivotal.api +'/projects/'+ project_id +'/stories/'+ story_id +'/comments',
      type: 'GET',
      headers: {
        'X-TrackerToken': pt_token
      },
      success: function(data) {
        // Find all git commit messages
        var list = data.filter(function(obj) {
          return obj.commit_type;
        });
        // Find repo name from comment body text
        list = list.map(function(item) {
          return item.text.split('https://github.com/gengo/')[1].split('/commit/')[0];
        });

        callback(removeDupesFromArray(list));
      }
    });
  }

  /**
   * showNoStoriesMessage
   * @param  {jQuery} $target jQuery button object
   */
  function showNoStoriesMessage($target) {
    $target.closest(config.selectors.story_column).text('No stories found.');
  }

  $(document).ready(function() {
    // add button to story columns
    var button = '<button class="btn btn-default getStories">Get stories</button>Loading...';
    $(config.selectors.story_column).each(function() {
      $(this).html(button);
    });

    // When reset button clicked add Get stories button
    $(config.selectors.refresh_button).click(function() {
      $(this).closest(config.selectors.project).find(config.selectors.story_column).html(button);
    });

    $('.project').on('click', '.getStories', function(e) {
      e.preventDefault();

      var $this_button = $(e.currentTarget);
      var project = $this_button.parents(config.selectors.project).data('id');
      var diffs = getProjectDiffs();

      $this_button.hide(); // do not show button

      if (project in diffs) {
        // great! we found diffs for this project; load the pivotal stories
        $this_button.siblings('.loading').show();

        (function(project) {
          var url = diffs[project];
          // hashes: currentCommit...latestCommit
          var commitHashes = (url.substr(url.lastIndexOf('/') + 1)).split('...');
          var repositoryName = url.match(config.github.url_compare_regexp)[1];

          getGithubCommits(GITHUB_TOKEN, repositoryName, commitHashes[0], commitHashes[1], function(commits) {
            // Array of comitt messages
            var messages = commits.map(function(obj) {
              return obj.commit.message;
            });
            // Array of pivotal story IDs
            var pivotal_ids = getPivotalStoryIDs(messages);
            if (!pivotal_ids) {
              showNoStoriesMessage($this_button);
              return;
            };

            $this_button.siblings('.loading').hide();

            var display_message = [];
            for (pt_id in pivotal_ids) {
              var id = pivotal_ids[pt_id];

              getPivotalStoryInfo(PIVOTAL_TOKEN, id, function(info) {
                display_message[id] = info;
                injectPivotalStatus(project, display_message);
              });
            }
          });
        })(project);
      }
      else {
        showNoStoriesMessage($this_button);
      }
    });

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


<commit_before>var npm = require("npm/lib/npm.js");
var readInstalled = require("./read-installed.js");
var path = require("path");
var async = require("async");
var fs = require("fs");
var tsort = require("./tsort");
var _ = require("underscore");
var shared = require("ep_carabiner/static/js/shared");
shared(exports);
var hooks = require("ep_carabiner/static/js/hooks");
hooks.plugins = exports;

exports.prefix = 'ep_';
exports.loaded = false;
exports.packages = {};
exports.plugin_packages = {};
exports.plugins = {};
exports.parts = [];
exports.hooks = {};

exports.reload = function (cb) {
  npm.load({}, function(er) {
    exports.loadPluginPackages(function (er) {
      exports.update(cb);
    });
  });
};

exports.callInit = function (cb) {
  async.mapSeries(
    Object.keys(exports.plugins),
    function (plugin_name, cb) {
      var plugin = exports.plugins[plugin_name];
      fs.stat(path.normalize(path.join(plugin.package.path, ".ep_initialized")), function (err, stats) {
        if (err) {
          async.waterfall([
            function (cb) { fs.writeFile(path.normalize(path.join(plugin.package.path, ".ep_initialized")), 'done', cb); },
            function (cb) { hooks.aCallAll("init_" + plugin_name, {}, cb); },
            cb,
          ]);
        } else {
          cb();
        }
      });
    },
    function () { cb(); }
  );
}

exports.update = function (cb) {
  exports.loadPlugins(function () {
    exports.loadHooks(exports.hooks, function (err) {
      exports.loadHooks(exports.client_hooks, function (err) {
        exports.loaded = true;
        exports.callInit(cb);
      });
    });
  });
};

exports.loadPlugins = function (cb) {
  var partsToParentChildList = function(parts) {
    var res = [];
    _.chain(parts).keys().forEach(function (name) {
      _.each(parts[name].post || [], function (child_name)  {
        res.push([name, child_name]);
      });
      _.each(parts[name].pre || [], function (parent_name)  {
        res.push([parent_name, name]);
      });
      if (!parts[name].pre && !parts[name].post) {
        res.push([name, ":" + name]); // Include apps with no dependency info
      }
    });
    return res;
  }

  var sortParts = function(parts) {
    return tsort(
      partsToParentChildList(parts)
    ).filter(
      function (name) { return parts[name] !== undefined; }
    ).map(
      function (name) { return parts[name]; }
    );
  }

  exports.loadPluginPackages(function (er) {
    var parts = [];
    var plugins = {};
    // Load plugin metadata ep.json
    async.forEach(
      Object.keys(exports.plugin_packages),
      function (plugin_name, cb) {
        loadPlugin(exports.plugin_packages, plugin_name, plugins, parts, cb);
      },
      function (err) {
        if (err) cb(err);
        exports.plugins = plugins;
        exports.parts = sortParts(parts);
        exports.hooks = exports.extractHooks(exports.parts, "hooks");
        // Extract client side hooks here too, so we don't have to call it from formatHooks (which is synchronous)
        exports.client_hooks = exports.extractHooks(exports.parts, "client_hooks");

        cb();
      }
    );
  });
};

exports.loadPluginPackages = function (cb) {
  // Filters the result of getPackages() to only packages with the right prefix
  exports.loadPackages(function (err) {
    if (err) {
      cb(err);
    } else {
      var res = {};
      for (var name in exports.packages) {
        if (name.indexOf(exports.prefix) === 0) {
          res[name] = exports.packages[name];
        }
      }
      exports.plugin_packages = res;
      cb(null);
    }
  });
}

exports.loadPackages = function (cb) {
  // Loads a list of installed NPM packages and flattens them to a list
  var dir = path.resolve(npm.dir, '..');
  readInstalled(dir, function (er, data) {
    if (er) cb(er, null);
    var packages = {};
    function flatten(deps) {
      _.chain(deps).keys().each(function (name) {
        if (name.indexOf(exports.prefix) === 0) {
          packages[name] = _.clone(deps[name]);
          // Delete anything that creates loops so that the plugin
          // list can be sent as JSON to the web client
          delete packages[name].dependencies;
          delete packages[name].parent;
        }

        if (deps[name].dependencies !== undefined) flatten(deps[name].dependencies);
      });
    }

    var tmp = {};
    tmp[data.name] = data;
    flatten(tmp);
    exports.packages = packages;
    cb();
  });
};

function loadPlugin(packages, plugin_name, plugins, parts, cb) {
  var plugin_path = path.resolve(packages[plugin_name].path, "ep.json");
  fs.readFile(
    plugin_path,
    function (er, data) {
      if (er) {
        console.error("Unable to load plugin definition file " + plugin_path);
        return cb();
      }
      try {
        var plugin = JSON.parse(data);
        plugin['package'] = packages[plugin_name];
        plugins[plugin_name] = plugin;
        _.each(plugin.parts, function (part) {
          part.plugin = plugin_name;
          part.full_name = plugin_name + "/" + part.name;
          parts[part.full_name] = part;
        });
      } catch (ex) {
        console.error("Unable to parse plugin definition file " + plugin_path + ": " + ex.toString());
      }
      cb();
    }
  );
}
<commit_msg>Bugfix for package prefixes<commit_after>var npm = require("npm/lib/npm.js");
var readInstalled = require("./read-installed.js");
var path = require("path");
var async = require("async");
var fs = require("fs");
var tsort = require("./tsort");
var _ = require("underscore");
var shared = require("ep_carabiner/static/js/shared");
shared(exports);
var hooks = require("ep_carabiner/static/js/hooks");
hooks.plugins = exports;

exports.prefix = 'ep_';
exports.loaded = false;
exports.packages = {};
exports.plugin_packages = {};
exports.plugins = {};
exports.parts = [];
exports.hooks = {};

exports.reload = function (cb) {
  npm.load({}, function(er) {
    exports.loadPluginPackages(function (er) {
      exports.update(cb);
    });
  });
};

exports.callInit = function (cb) {
  async.mapSeries(
    Object.keys(exports.plugins),
    function (plugin_name, cb) {
      var plugin = exports.plugins[plugin_name];
      fs.stat(path.normalize(path.join(plugin.package.path, ".ep_initialized")), function (err, stats) {
        if (err) {
          async.waterfall([
            function (cb) { fs.writeFile(path.normalize(path.join(plugin.package.path, ".ep_initialized")), 'done', cb); },
            function (cb) { hooks.aCallAll("init_" + plugin_name, {}, cb); },
            cb,
          ]);
        } else {
          cb();
        }
      });
    },
    function () { cb(); }
  );
}

exports.update = function (cb) {
  exports.loadPlugins(function () {
    exports.loadHooks(exports.hooks, function (err) {
      exports.loadHooks(exports.client_hooks, function (err) {
        exports.loaded = true;
        exports.callInit(cb);
      });
    });
  });
};

exports.loadPlugins = function (cb) {
  var partsToParentChildList = function(parts) {
    var res = [];
    _.chain(parts).keys().forEach(function (name) {
      _.each(parts[name].post || [], function (child_name)  {
        res.push([name, child_name]);
      });
      _.each(parts[name].pre || [], function (parent_name)  {
        res.push([parent_name, name]);
      });
      if (!parts[name].pre && !parts[name].post) {
        res.push([name, ":" + name]); // Include apps with no dependency info
      }
    });
    return res;
  }

  var sortParts = function(parts) {
    return tsort(
      partsToParentChildList(parts)
    ).filter(
      function (name) { return parts[name] !== undefined; }
    ).map(
      function (name) { return parts[name]; }
    );
  }

  exports.loadPluginPackages(function (er) {
    var parts = [];
    var plugins = {};
    // Load plugin metadata ep.json
    async.forEach(
      Object.keys(exports.plugin_packages),
      function (plugin_name, cb) {
        loadPlugin(exports.plugin_packages, plugin_name, plugins, parts, cb);
      },
      function (err) {
        if (err) cb(err);
        exports.plugins = plugins;
        exports.parts = sortParts(parts);
        exports.hooks = exports.extractHooks(exports.parts, "hooks");
        // Extract client side hooks here too, so we don't have to call it from formatHooks (which is synchronous)
        exports.client_hooks = exports.extractHooks(exports.parts, "client_hooks");

        cb();
      }
    );
  });
};

exports.loadPluginPackages = function (cb) {
  // Filters the result of getPackages() to only packages with the right prefix
  exports.loadPackages(function (err) {
    if (err) {
      cb(err);
    } else {
      var res = {};
      for (var name in exports.packages) {
        if (name.indexOf(exports.prefix) === 0) {
          res[name] = exports.packages[name];
        }
      }
      exports.plugin_packages = res;
      cb(null);
    }
  });
}

exports.loadPackages = function (cb) {
  // Loads a list of installed NPM packages and flattens them to a list
  var dir = path.resolve(npm.dir, '..');
  readInstalled(dir, function (er, data) {
    if (er) cb(er, null);
    var packages = {};
    function flatten(deps) {
      _.chain(deps).keys().each(function (name) {
        packages[name] = _.clone(deps[name]);
        // Delete anything that creates loops so that the plugin
        // list can be sent as JSON to the web client
        delete packages[name].dependencies;
        delete packages[name].parent;
        if (deps[name].dependencies !== undefined) flatten(deps[name].dependencies);
      });
    }

    var tmp = {};
    tmp[data.name] = data;
    flatten(tmp);
    exports.packages = packages;
    cb();
  });
};

function loadPlugin(packages, plugin_name, plugins, parts, cb) {
  var plugin_path = path.resolve(packages[plugin_name].path, "ep.json");
  fs.readFile(
    plugin_path,
    function (er, data) {
      if (er) {
        console.error("Unable to load plugin definition file " + plugin_path);
        return cb();
      }
      try {
        var plugin = JSON.parse(data);
        plugin['package'] = packages[plugin_name];
        plugins[plugin_name] = plugin;
        _.each(plugin.parts, function (part) {
          part.plugin = plugin_name;
          part.full_name = plugin_name + "/" + part.name;
          parts[part.full_name] = part;
        });
      } catch (ex) {
        console.error("Unable to parse plugin definition file " + plugin_path + ": " + ex.toString());
      }
      cb();
    }
  );
}
<|endoftext|>


<commit_before>import $ from "jquery";

import * as narrow_state from "./narrow_state";
import * as people from "./people";
import * as pm_list_data from "./pm_list_data";
import * as pm_list_dom from "./pm_list_dom";
import * as stream_popover from "./stream_popover";
import * as ui from "./ui";
import * as ui_util from "./ui_util";
import * as vdom from "./vdom";

let prior_dom;
let private_messages_open = false;

// This module manages the "Private messages" section in the upper
// left corner of the app.  This was split out from stream_list.js.

function get_filter_li() {
    return $(".top_left_private_messages .private_messages_header");
}

function set_count(count) {
    ui_util.update_unread_count_in_dom(get_filter_li(), count);
}

function remove_expanded_private_messages() {
    stream_popover.hide_topic_popover();
    ui.get_content_element($("#private-container")).empty();
}

export function close() {
    private_messages_open = false;
    prior_dom = undefined;
    remove_expanded_private_messages();
}

export function _build_private_messages_list() {
    const conversations = pm_list_data.get_conversations();
    const dom_ast = pm_list_dom.pm_ul(conversations);
    return dom_ast;
}

export function update_private_messages() {
    if (!narrow_state.active()) {
        return;
    }

    if (private_messages_open) {
        const $container = ui.get_content_element($("#private-container"));
        const new_dom = _build_private_messages_list();

        function replace_content(html) {
            $container.html(html);
        }

        function find() {
            return $container.find("ul");
        }

        vdom.update(replace_content, find, new_dom, prior_dom);
        prior_dom = new_dom;
    }
}

export function expand() {
    private_messages_open = true;
    stream_popover.hide_topic_popover();
    update_private_messages();
    if (pm_list_data.is_all_privates()) {
        $(".top_left_private_messages").addClass("active-filter");
    }
}

export function update_dom_with_unread_counts(counts) {
    update_private_messages();
    set_count(counts.private_message_count);
}

function should_expand_pm_list(filter) {
    const op_is = filter.operands("is");

    if (op_is.length >= 1 && op_is.includes("private")) {
        return true;
    }

    const op_pm = filter.operands("pm-with");

    if (op_pm.length !== 1) {
        return false;
    }

    const emails_strings = op_pm[0];
    const emails = emails_strings.split(",");

    const has_valid_emails = people.is_valid_bulk_emails_for_compose(emails);

    return has_valid_emails;
}

export function handle_narrow_activated(filter) {
    if (should_expand_pm_list(filter)) {
        expand();
    } else {
        close();
    }
}

export function handle_narrow_deactivated() {
    close();
}
<commit_msg>pm_list: Remove unnecessary topic popover calls.<commit_after>import $ from "jquery";

import * as narrow_state from "./narrow_state";
import * as people from "./people";
import * as pm_list_data from "./pm_list_data";
import * as pm_list_dom from "./pm_list_dom";
import * as ui from "./ui";
import * as ui_util from "./ui_util";
import * as vdom from "./vdom";

let prior_dom;
let private_messages_open = false;

// This module manages the "Private messages" section in the upper
// left corner of the app.  This was split out from stream_list.js.

function get_filter_li() {
    return $(".top_left_private_messages .private_messages_header");
}

function set_count(count) {
    ui_util.update_unread_count_in_dom(get_filter_li(), count);
}

function remove_expanded_private_messages() {
    ui.get_content_element($("#private-container")).empty();
}

export function close() {
    private_messages_open = false;
    prior_dom = undefined;
    remove_expanded_private_messages();
}

export function _build_private_messages_list() {
    const conversations = pm_list_data.get_conversations();
    const dom_ast = pm_list_dom.pm_ul(conversations);
    return dom_ast;
}

export function update_private_messages() {
    if (!narrow_state.active()) {
        return;
    }

    if (private_messages_open) {
        const $container = ui.get_content_element($("#private-container"));
        const new_dom = _build_private_messages_list();

        function replace_content(html) {
            $container.html(html);
        }

        function find() {
            return $container.find("ul");
        }

        vdom.update(replace_content, find, new_dom, prior_dom);
        prior_dom = new_dom;
    }
}

export function expand() {
    private_messages_open = true;
    update_private_messages();
    if (pm_list_data.is_all_privates()) {
        $(".top_left_private_messages").addClass("active-filter");
    }
}

export function update_dom_with_unread_counts(counts) {
    update_private_messages();
    set_count(counts.private_message_count);
}

function should_expand_pm_list(filter) {
    const op_is = filter.operands("is");

    if (op_is.length >= 1 && op_is.includes("private")) {
        return true;
    }

    const op_pm = filter.operands("pm-with");

    if (op_pm.length !== 1) {
        return false;
    }

    const emails_strings = op_pm[0];
    const emails = emails_strings.split(",");

    const has_valid_emails = people.is_valid_bulk_emails_for_compose(emails);

    return has_valid_emails;
}

export function handle_narrow_activated(filter) {
    if (should_expand_pm_list(filter)) {
        expand();
    } else {
        close();
    }
}

export function handle_narrow_deactivated() {
    close();
}
<|endoftext|>


<commit_before>$("#frm").validate({
    errorLabelContainer: $("div.growlUI"),
    errorClass: "ipt-error",
    submitHandler: function(){
        $("#frm").ajaxSubmit({
            dataType: "json",
            beforeSubmit:function(){
                $(".videoinfo-cont").fadeOut();
                $.blockUI({
                    message: "Please wait...",
                    fadeIn: 900,
                    fadeOut: 700,
                    showOverlay: true,
                    css: {
                        border: 'none',
                        backgroundColor: '#52C5B1',
                        opacity: 1.0,
                        color: '#fff',
                        'z-index': 9999999999,
                        'box-shadow': '0 0 10px #444444',
                        'border-radius': '10px'
                    }
                });
            },
            success: function(data, status){
                if(data.sucesso){
//                    console.log(data.video.streams);
                    $(".videoinfo .video-img")
                        .attr("src", "")
                        .attr('src', data.video.thumbnail);

                    $(".videoinfo .video-url")
                        .attr("href", "")
                        .attr('href', data.video.url)
                        .attr("download", "")
                        .attr('download', data.video.url);

                    $(".videoinfo .video-title")
                        .empty()
                        .html(data.video.title);

                    $(".videoinfo .clearfix")
                        .empty()
                        .append("
Author: " + data.video.author + "
")
                        .append("
 Duration: " + data.video.duration + "
");

                    for(i=0; i < data.video.streams.length; i++){
                        $(".videoinfo .clearfix").append('' + data.video.streams[i][0] + '(' + data.video.streams[i][1] +') | ');
                    }

                    $(".videoinfo-cont").fadeIn();

                    console.log(data.video.thumbnail);
                    $.unblockUI();
                } else {
                    $.blockUI({
                        message: data.error,
                        fadeIn: 500,
                        fadeOut: 700,
                        timeout: 4000,
                        showOverlay: false,
                        css: {
                            border: 'none',
                            backgroundColor: '#52C5B1',
                            opacity: 1.0,
                            color: '#fff',
                            'z-index': 9999999999,
                            'box-shadow': '0 0 10px #444444',
                            'border-radius': '10px'
                        }
                    });

                }

            }

        });

    },

    invalidHandler: function(form, validator) {
        $('#frm input[name=videoUrl]')
            .popover({trigger: "manual", placement:"top", content:"Enter a valid link youtube video"})
            .popover('show');
        setTimeout(function(){
            $('#frm input[name=videoUrl]').popover('hide');
        }, 3000)
    },

    rules: {
        videoUrl: {
            required: true
        }
    }
});
<commit_msg>Attr Download<commit_after>$("#frm").validate({
    errorLabelContainer: $("div.growlUI"),
    errorClass: "ipt-error",
    submitHandler: function(){
        $("#frm").ajaxSubmit({
            dataType: "json",
            beforeSubmit:function(){
                $(".videoinfo-cont").fadeOut();
                $.blockUI({
                    message: "Please wait...",
                    fadeIn: 900,
                    fadeOut: 700,
                    showOverlay: true,
                    css: {
                        border: 'none',
                        backgroundColor: '#52C5B1',
                        opacity: 1.0,
                        color: '#fff',
                        'z-index': 9999999999,
                        'box-shadow': '0 0 10px #444444',
                        'border-radius': '10px'
                    }
                });
            },
            success: function(data, status){
                if(data.sucesso){
//                    console.log(data.video.streams);
                    $(".videoinfo .video-img")
                        .attr("src", "")
                        .attr('src', data.video.thumbnail);

                    $(".videoinfo .video-url")
                        .attr("href", "")
                        .attr('href', data.video.url);

                    $(".videoinfo .video-title")
                        .empty()
                        .html(data.video.title);

                    $(".videoinfo .clearfix")
                        .empty()
                        .append("
Author: " + data.video.author + "
")
                        .append("
 Duration: " + data.video.duration + "
");

                    for(i=0; i < data.video.streams.length; i++){
                        $(".videoinfo .clearfix").append('' + data.video.streams[i][0] + '(' + data.video.streams[i][1] +') | ');
                    }

                    $(".videoinfo-cont").fadeIn();

                    console.log(data.video.thumbnail);
                    $.unblockUI();
                } else {
                    $.blockUI({
                        message: data.error,
                        fadeIn: 500,
                        fadeOut: 700,
                        timeout: 4000,
                        showOverlay: false,
                        css: {
                            border: 'none',
                            backgroundColor: '#52C5B1',
                            opacity: 1.0,
                            color: '#fff',
                            'z-index': 9999999999,
                            'box-shadow': '0 0 10px #444444',
                            'border-radius': '10px'
                        }
                    });

                }

            }

        });

    },

    invalidHandler: function(form, validator) {
        $('#frm input[name=videoUrl]')
            .popover({trigger: "manual", placement:"top", content:"Enter a valid link youtube video"})
            .popover('show');
        setTimeout(function(){
            $('#frm input[name=videoUrl]').popover('hide');
        }, 3000)
    },

    rules: {
        videoUrl: {
            required: true
        }
    }
});
<|endoftext|>


<commit_before>import $ from "jquery";

// Add functions to this that have no non-trivial
// dependencies other than jQuery.

export function change_tab_to(tabname) {
    $(`#gear-menu a[href="${CSS.escape(tabname)}"]`).tab("show");
}

// https://stackoverflow.com/questions/4233265/contenteditable-set-caret-at-the-end-of-the-text-cross-browser
export function place_caret_at_end(el) {
    el.focus();

    if (window.getSelection !== undefined && document.createRange !== undefined) {
        const range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        const sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (document.body.createTextRange !== undefined) {
        const textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
}

export function blur_active_element() {
    // this blurs anything that may perhaps be actively focused on.
    document.activeElement.blur();
}

export function convert_enter_to_click(e) {
    const key = e.which;
    if (key === 13) {
        // Enter
        $(e.currentTarget).trigger("click");
    }
}

export function update_unread_count_in_dom(unread_count_elem, count) {
    // This function is used to update unread count in top left corner
    // elements.
    const unread_count_span = unread_count_elem.find(".unread_count");

    if (count === 0) {
        unread_count_span.hide();
        unread_count_span.text("");
        return;
    }

    unread_count_span.show();
    unread_count_span.text(count);
}
<commit_msg>ui_util: Stop propagation enter keypress when it is already handled.<commit_after>import $ from "jquery";

// Add functions to this that have no non-trivial
// dependencies other than jQuery.

export function change_tab_to(tabname) {
    $(`#gear-menu a[href="${CSS.escape(tabname)}"]`).tab("show");
}

// https://stackoverflow.com/questions/4233265/contenteditable-set-caret-at-the-end-of-the-text-cross-browser
export function place_caret_at_end(el) {
    el.focus();

    if (window.getSelection !== undefined && document.createRange !== undefined) {
        const range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        const sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (document.body.createTextRange !== undefined) {
        const textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
}

export function blur_active_element() {
    // this blurs anything that may perhaps be actively focused on.
    document.activeElement.blur();
}

export function convert_enter_to_click(e) {
    const key = e.which;
    if (key === 13) {
        // Enter
        e.preventDefault();
        e.stopPropagation();
        $(e.currentTarget).trigger("click");
    }
}

export function update_unread_count_in_dom(unread_count_elem, count) {
    // This function is used to update unread count in top left corner
    // elements.
    const unread_count_span = unread_count_elem.find(".unread_count");

    if (count === 0) {
        unread_count_span.hide();
        unread_count_span.text("");
        return;
    }

    unread_count_span.show();
    unread_count_span.text(count);
}
<|endoftext|>


<commit_before>var whiteboard_id = 'unknown';
var socket = undefined;
var tool_heads = [null, null, null, null, null]; // support up to five fingers! not.
var tools_by_name = {};
var context_picture = document.getElementById('canvas1').getContext('2d'); // bottom layer
var context_preview = document.getElementById('canvas2').getContext('2d'); // top layer
var active_tool = null;
var global_colour = '#000000';

function setWhiteboardId(wid) {
	whiteboard_id = wid;
}

// Functions for drawing things on canvases

function drawClear(context) {
	context.clearRect(0, 0, context.canvas.width, context.canvas.height);
}

function drawSegment(start, end, context, colour, thickness) {
	context.lineJoin = "round";
	context.strokeStyle = colour;
	context.lineWidth = thickness;
	context.beginPath();
	context.moveTo(start.x, start.y);
	context.lineTo(end.x, end.y);
	context.closePath();
	context.stroke();
}

function drawLine(points, context, colour, thickness) {
	if (points.length > 1) {
		for (var i = 1; i < points.length; i++) {
			drawSegment(points[i - 1], points[i], context, colour, thickness);
		}
	}
}

function drawLineTimed(points, context, colour, thickness, interval) {
	// This seems extremely inefficient...
	if (points.length > 1) {
		var i = 1;
		function func() {
			if (i < points.length) {
				drawSegment(points[i - 1], points[i], context, colour, thickness);
				i += 1;
				window.setTimeout(func, interval);
			}
		}
		func();
	}
}

function drawText(position, text, colour, font, context) {
	context.textBaseline = 'top';
	context.font = font;
	context.fillStyle = colour;
	context.fillText(text, position.x, position.y);
}

// A tool head for drawing like a pencil. This can also be used to function as an eraser.

function PencilHead(tool_name, colour, thickness) {
	this.tool_name = tool_name;
	this.points = Array();
	this.colour = colour;
	this.thickness = thickness;
	this.distance = 0;
}

PencilHead.prototype.pushData = function() {
	if (this.points.length > 1) {
		var last_point = this.points[this.points.length - 1];
		sendPaintEvent(this.tool_name, cleanupLine(this.points));
		this.points = [last_point];
	}
}

PencilHead.prototype.onMove = function(new_point) {
	if (new_point) {
		this.points.push(new_point);
		var l = this.points.length;
		if (l > 1) {
			drawSegment(this.points[l - 2], new_point, context_preview, this.colour, this.thickness);
			this.distance += distance(this.points[l - 2], new_point);
		}
		if (this.distance > 2000 && l > 200) {
			this.pushData()
			this.distance = 0;
		}
	}
}

PencilHead.prototype.onRelease = function() {
	this.pushData();
	drawClear(context_preview);
}

var tool_pencil = {
	name: 'pencil',
	buttonImage: 'pencil.png',
	buttonImageSelected: 'pencil_select.png',
	onButtonClick: function() {
		console.log('Selected Pencil');
		return true;
	},
	makeToolHead: function() {
		return new PencilHead('pencil', global_colour, 2);
	},
	drawFull: function(points) {
		drawLine(points, context_picture, global_colour, 2);
	}
};

var tool_eraser = {
	name: 'eraser',
	buttonImage: 'eraser.png',
	buttonImageSelected: 'eraser_select.png',
	onButtonClick: function() {
		console.log('Selected Eraser');
		return true;
	},
	makeToolHead: function() {
		return new PencilHead('eraser', '#dddddd', 30);
	},
	drawFull: function(points) {
		drawLine(points, context_picture, '#ffffff', 30);
	}
};

var tool_clear = {
	name: 'clear',
	buttonImage: 'clear.png',
	onButtonClick: function() {
		sendPaintEvent('clear', []);
		// This is just a button.
		return false;
	},
	drawFull: function(data) {
		drawClear(context_picture);
	}
};

function TextHead() {
	this.text = 'Type here!';
	$('#text_input_pane').show();
	$('#text_input_text').text('Enter Text');
}

jQuery.fn.selectText = function() {
	var range, selection;
	return this.each(function() {
		if (document.body.createTextRange) {
			range = document.body.createTextRange();
			range.moveToElementText(this);
			range.select();
		} else if (window.getSelection) {
			selection = window.getSelection();
			range = document.createRange();
			range.selectNodeContents(this);
			selection.removeAllRanges();
			selection.addRange(range);
		}
	});
};

TextHead.prototype.onMove = function(a) {
	// Move text and display
	var point = new Point(a.x, a.y);
	window.setTimeout(function () {
		var e = $('#text_input_text');
		e.css('left', point.x);
		e.css('top', point.y);
		e.selectText();
		e.focus();
	}, 10);
	// Setup callbacks
	function textInputKeyHandle(event) {
		var commit = (event.keyCode == 13 && !event.shiftKey);
		if (commit) {
			console.log('Committing text paint...');
			sendPaintEvent('text', {
				position: point,
				text: $('#text_input_text').text(),
			});
		}
		if (commit || event.keyCode == 27) {
			$('#text_input_pane').hide();
		}
	}
	$('#text_input_text').off('keydown');
	$('#text_input_pane').off('keydown');
	$('#text_input_text').keydown(textInputKeyHandle);
	$('#text_input_pane').keydown(textInputKeyHandle);
}

TextHead.prototype.onRelease = function() {
	// do nothing...
}

// When we press enter, we've finished.
var tool_text = {
	name: 'text',
	buttonImage: 'text.png',
	buttonImageSelected: 'text_select.png',
	onButtonClick: function() {
		console.log('Selected Text');
		return true;
	},
	makeToolHead: function() {
		return new TextHead();
	},
	drawFull: function(data) {
		console.log('tool_text.drawFull', data);
		var pos = data.position;
		var text = data.text;
		var colour = '#000000';
		var font = '30px Helvetica';
		drawText(pos, text, colour, font, context_picture);
	}
};

var tools = {
	pencil: tool_pencil,
	eraser: tool_eraser,
	text: tool_text,
	clear: tool_clear
};

function sendPaintEvent(the_tool, the_points) {
	// console.log('sendPaintEvent', the_tool, the_points);
	socket.emit('paint',
		{
			data: {
				'tool': the_tool,
				'points': the_points,
				'board_id': whiteboard_id
			}
		}
	);
	drawCommand(the_tool, the_points);
}

// Perform events

function eventToolDown(n, p) {
	tool_heads[n] = active_tool.makeToolHead();
	tool_heads[n].onMove(p);
}

function eventToolMove(n, p) {
	if (tool_heads[n]) {
		tool_heads[n].onMove(p);
	}
}

function eventToolUp(n) {
	if (tool_heads[n]) {
		tool_heads[n].onRelease();
		tool_heads[n] = null;
	}
}

// Interperet events

function mouseDown(e) {
	eventToolDown(0, new Point(e.pageX, e.pageY));
}

function mouseMove(e) {
	eventToolMove(0, new Point(e.pageX, e.pageY));
}

function mouseUp(e) {
	eventToolUp(0);
}

function touchDown(e) {
	mouseDown(e.touches[0]);
}

function touchMove(e) {
	mouseMove(e.touches[0]);
	e.preventDefault();
}

function drawCommand(the_tool, the_points) {
	if (the_tool in tools) {
		tools[the_tool].drawFull(the_points);
	}
}

$('#canvas2').mousedown(mouseDown);
$('#canvas2').mousemove(mouseMove);
$('#canvas2').mouseup(mouseUp);
document.addEventListener('touchstart', touchDown, false);
document.addEventListener('touchmove', touchMove, false);
document.addEventListener('touchend', mouseUp, false);
document.addEventListener('touchcancel', mouseUp, false);

// Tool buttons

function trigerToolButton(t) {
	console.log('Triggering...', t);
	// Tigger the click event
	var n = tools[t].name;
	var p = tools[t].buttonImageSelected;
	if (tools[t].onButtonClick()) {
		active_tool = tools[t];
		// Change button images
		for (i in tools) {
			var n2 = tools[i].name;
			var p2 = tools[i].buttonImage;
			console.log(i);
			document.getElementById('button_' + n2).src = '/static/' + p2;
			console.log('done');
		}
		console.log(n);
		document.getElementById('button_' + n).src = '/static/' + p;
		console.log('done');
	}
}

for (i in tools) {
	// Clojures because javascript is strange...
	function clojure() {
		var name = tools[i].name;
		$('#button_' + name).click(function(e) {trigerToolButton(name);});
	}
	clojure();
}

// Colours

var colours = {
	black: '#000000',
	blue: '#484fc0',
	red: '#df4b26'
}

function triggerColourButton(col) {
	console.log('Colour: ', col, colours[col]);
	global_colour = colours[col];
	for (i in colours) {
		$("#colour_" + i).attr('src', '/static/col_' + i + '.png');
	}
	$('#colour_' + col).attr('src', '/static/col_s_' + col + '.png');
}

for (i in colours) {
	console.log(i, 'is a colour');
	function clojure() {
		var x = i;
		$('#colour_' + x).click(function(e) {triggerColourButton(x);});
	}
	clojure();
}

// Data transfer

$(document).ready(function() {

	active_tool = tool_pencil;

	console.log('Board ID:', whiteboard_id);

	socket = io.connect('http://' + document.domain + ':' + location.port + '/');
	socket.emit('full image', {data:{'board_id': whiteboard_id}});

	socket.on('paint', function(msg) {
		// console.log('paint', msg);
		if (msg.data.board_id == whiteboard_id) {
			actions = msg.data.actions;
			for (i in actions) {
				// console.log(actions[i].tool, actions[i].points);
				drawCommand(actions[i].tool, actions[i].points);
			}
		}
	});

});<commit_msg>Colour value is transmitted<commit_after>var whiteboard_id = 'unknown';
var socket = undefined;
var tool_heads = [null, null, null, null, null]; // support up to five fingers! not.
var tools_by_name = {};
var context_picture = document.getElementById('canvas1').getContext('2d'); // bottom layer
var context_preview = document.getElementById('canvas2').getContext('2d'); // top layer
var active_tool = null;
var global_colour = '#000000';

function setWhiteboardId(wid) {
	whiteboard_id = wid;
}

// Functions for drawing things on canvases

function drawClear(context) {
	context.clearRect(0, 0, context.canvas.width, context.canvas.height);
}

function drawSegment(start, end, context, colour, thickness) {
	context.lineJoin = "round";
	context.strokeStyle = colour;
	context.lineWidth = thickness;
	context.beginPath();
	context.moveTo(start.x, start.y);
	context.lineTo(end.x, end.y);
	context.closePath();
	context.stroke();
}

function drawLine(points, context, colour, thickness) {
	if (points.length > 1) {
		for (var i = 1; i < points.length; i++) {
			drawSegment(points[i - 1], points[i], context, colour, thickness);
		}
	}
}

function drawLineTimed(points, context, colour, thickness, interval) {
	// This seems extremely inefficient...
	if (points.length > 1) {
		var i = 1;
		function func() {
			if (i < points.length) {
				drawSegment(points[i - 1], points[i], context, colour, thickness);
				i += 1;
				window.setTimeout(func, interval);
			}
		}
		func();
	}
}

function drawText(position, text, colour, font, context) {
	context.textBaseline = 'top';
	context.font = font;
	context.fillStyle = colour;
	context.fillText(text, position.x, position.y);
}

// A tool head for drawing like a pencil. This can also be used to function as an eraser.

function PencilHead(tool_name, colour, thickness) {
	this.tool_name = tool_name;
	this.points = Array();
	this.colour = colour;
	this.thickness = thickness;
	this.distance = 0;
}

PencilHead.prototype.pushData = function() {
	if (this.points.length > 1) {
		var last_point = this.points[this.points.length - 1];
		var action_data = {
			points: cleanupLine(this.points),
			colour: this.colour,
			thickness: this.thickness
		}
		sendPaintEvent(this.tool_name, action_data);
		this.points = [last_point];
	}
	drawClear(context_preview);
}

PencilHead.prototype.onMove = function(new_point) {
	if (new_point) {
		this.points.push(new_point);
		var l = this.points.length;
		if (l > 1) {
			drawSegment(this.points[l - 2], new_point, context_preview, this.colour, this.thickness);
			this.distance += distance(this.points[l - 2], new_point);
		}
		if (this.distance > 2000 && l > 200) {
			this.pushData()
			this.distance = 0;
		}
	}
}

PencilHead.prototype.onRelease = function() {
	this.pushData();
}

var tool_pencil = {
	name: 'pencil',
	buttonImage: 'pencil.png',
	buttonImageSelected: 'pencil_select.png',
	onButtonClick: function() {
		console.log('Selected Pencil');
		return true;
	},
	makeToolHead: function() {
		return new PencilHead('pencil', global_colour, 2);
	},
	drawFull: function(data) {
		drawLine(data.points, context_picture, data.colour, 2);
	}
};

var tool_eraser = {
	name: 'eraser',
	buttonImage: 'eraser.png',
	buttonImageSelected: 'eraser_select.png',
	onButtonClick: function() {
		console.log('Selected Eraser');
		return true;
	},
	makeToolHead: function() {
		return new PencilHead('eraser', '#dddddd', 30);
	},
	drawFull: function(data) {
		drawLine(data.points, context_picture, '#ffffff', 30);
	}
};

var tool_clear = {
	name: 'clear',
	buttonImage: 'clear.png',
	onButtonClick: function() {
		sendPaintEvent('clear', []);
		// This is just a button.
		return false;
	},
	drawFull: function(data) {
		drawClear(context_picture);
	}
};

function TextHead() {
	this.text = 'Type here!';
	$('#text_input_pane').show();
	$('#text_input_text').text('Enter Text');
}

jQuery.fn.selectText = function() {
	var range, selection;
	return this.each(function() {
		if (document.body.createTextRange) {
			range = document.body.createTextRange();
			range.moveToElementText(this);
			range.select();
		} else if (window.getSelection) {
			selection = window.getSelection();
			range = document.createRange();
			range.selectNodeContents(this);
			selection.removeAllRanges();
			selection.addRange(range);
		}
	});
};

TextHead.prototype.onMove = function(a) {
	// Move text and display
	var point = new Point(a.x, a.y);
	window.setTimeout(function () {
		var e = $('#text_input_text');
		e.css('left', point.x);
		e.css('top', point.y);
		e.selectText();
		e.focus();
	}, 10);
	// Setup callbacks
	function textInputKeyHandle(event) {
		var commit = (event.keyCode == 13 && !event.shiftKey);
		if (commit) {
			console.log('Committing text paint...');
			sendPaintEvent('text', {
				position: point,
				text: $('#text_input_text').text(),
			});
		}
		if (commit || event.keyCode == 27) {
			$('#text_input_pane').hide();
		}
	}
	$('#text_input_text').off('keydown');
	$('#text_input_pane').off('keydown');
	$('#text_input_text').keydown(textInputKeyHandle);
	$('#text_input_pane').keydown(textInputKeyHandle);
}

TextHead.prototype.onRelease = function() {
	// do nothing...
}

// When we press enter, we've finished.
var tool_text = {
	name: 'text',
	buttonImage: 'text.png',
	buttonImageSelected: 'text_select.png',
	onButtonClick: function() {
		console.log('Selected Text');
		return true;
	},
	makeToolHead: function() {
		return new TextHead();
	},
	drawFull: function(data) {
		console.log('tool_text.drawFull', data);
		var pos = data.position;
		var text = data.text;
		var colour = '#000000';
		var font = '30px Helvetica';
		drawText(pos, text, colour, font, context_picture);
	}
};

var tools = {
	pencil: tool_pencil,
	eraser: tool_eraser,
	text: tool_text,
	clear: tool_clear
};

function sendPaintEvent(tool_name, action_data) {
	// console.log('sendPaintEvent', tool_name, the_points);
	socket.emit('paint',
		{
			data: {
				'tool': tool_name,
				'data': action_data,
				'board_id': whiteboard_id
			}
		}
	);
	drawCommand(tool_name, action_data);
}

// Perform events

function eventToolDown(n, p) {
	tool_heads[n] = active_tool.makeToolHead();
	tool_heads[n].onMove(p);
}

function eventToolMove(n, p) {
	if (tool_heads[n]) {
		tool_heads[n].onMove(p);
	}
}

function eventToolUp(n) {
	if (tool_heads[n]) {
		tool_heads[n].onRelease();
		tool_heads[n] = null;
	}
}

// Interperet events

function mouseDown(e) {
	eventToolDown(0, new Point(e.pageX, e.pageY));
}

function mouseMove(e) {
	eventToolMove(0, new Point(e.pageX, e.pageY));
}

function mouseUp(e) {
	eventToolUp(0);
}

function touchDown(e) {
	mouseDown(e.touches[0]);
}

function touchMove(e) {
	mouseMove(e.touches[0]);
	e.preventDefault();
}

function drawCommand(the_tool, the_data) {
	if (the_tool in tools) {
		tools[the_tool].drawFull(the_data);
	}
}

$('#canvas2').mousedown(mouseDown);
$('#canvas2').mousemove(mouseMove);
$('#canvas2').mouseup(mouseUp);
document.addEventListener('touchstart', touchDown, false);
document.addEventListener('touchmove', touchMove, false);
document.addEventListener('touchend', mouseUp, false);
document.addEventListener('touchcancel', mouseUp, false);

// Tool buttons

function trigerToolButton(t) {
	console.log('Triggering...', t);
	// Tigger the click event
	var n = tools[t].name;
	var p = tools[t].buttonImageSelected;
	if (tools[t].onButtonClick()) {
		active_tool = tools[t];
		// Change button images
		for (i in tools) {
			var n2 = tools[i].name;
			var p2 = tools[i].buttonImage;
			console.log(i);
			document.getElementById('button_' + n2).src = '/static/' + p2;
			console.log('done');
		}
		console.log(n);
		document.getElementById('button_' + n).src = '/static/' + p;
		console.log('done');
	}
}

for (i in tools) {
	// Clojures because javascript is strange...
	function clojure() {
		var name = tools[i].name;
		$('#button_' + name).click(function(e) {trigerToolButton(name);});
	}
	clojure();
}

// Colours

var colours = {
	black: '#000000',
	blue: '#484fc0',
	red: '#df4b26'
}

function triggerColourButton(col) {
	console.log('Colour: ', col, colours[col]);
	global_colour = colours[col];
	for (i in colours) {
		$("#colour_" + i).attr('src', '/static/col_' + i + '.png');
	}
	$('#colour_' + col).attr('src', '/static/col_s_' + col + '.png');
}

for (i in colours) {
	console.log(i, 'is a colour');
	function clojure() {
		var x = i;
		$('#colour_' + x).click(function(e) {triggerColourButton(x);});
	}
	clojure();
}

// Data transfer

$(document).ready(function() {

	active_tool = tool_pencil;

	console.log('Board ID:', whiteboard_id);

	socket = io.connect('http://' + document.domain + ':' + location.port + '/');
	socket.emit('full image', {data:{'board_id': whiteboard_id}});

	socket.on('paint', function(msg) {
		// console.log('paint', msg);
		if (msg.data.board_id == whiteboard_id) {
			actions = msg.data.actions;
			for (i in actions) {
				// console.log(actions[i].tool, actions[i].points);
				drawCommand(actions[i].tool, actions[i].data);
			}
		}
	});

});<|endoftext|>


<commit_before>var Twit = require('twit'),
    ShortIdGenerator = require('./ShortIdGenerator');

module.exports = {
    T: null,
    stream: null,
    ME: null,
    PINAuth: null,
    vorpal: null,
    cache: null,
    login: function(ckey, csecret, akey, asecret, vorpal, cache) {
        this.vorpal = vorpal;
        this.cache = cache;
        this.T = new Twit({
            consumer_key:        ckey,
            consumer_secret:     csecret,
            access_token:        akey,
            access_token_secret: asecret
        });

        this.loadMyself();
    },
    startStream: function() {
        const self = this;
        this.stream = this.T.stream('user');

        this.stream.on('tweet', function(tweet) {
            self.displayStatus(tweet);
        });
    },
    loadMyself: function() {
        const self = this;
        this.T.get('account/verify_credentials', { skip_status: true })
            .catch(function(err) {
                self.vorpal.log('Error GET account/verify_credentials: ' + err);
            })
            .then(function(result) {
                self.vorpal.log("Logged in as " + result.data.screen_name);
                self.ME = result.data;

                self.loadHome();
            });
    },

    loadHome: function() {
        const self = this;
        this.T.get('statuses/home_timeline', { count: 20 })
            .catch(function(err) {
                self.vorpal.log('Error GET statuses/home_timeline: ' + err);
            })
            .then(function(result) {
                result.data.reverse().forEach(function(tweet) {
                    self.displayStatus(tweet);
                });
            });
    },

    loadReplies: function() {
        const self = this;
        this.T.get('statuses/mentions_timeline')
            .catch(function(err) {
                self.vorpal.log('Error GET statuses/mentions_timeline: ' + err);
            })
            .then(function(result) {
                result.data.reverse().forEach(function(tweet) {
                    self.displayStatus(tweet);
                });
            });
    },

    update: function(tweet) {
        const self = this;
        this.T.post('statuses/update', { status: tweet })
            .catch(function(err) {
                if (err) self.vorpal.log(err);
            });
    },

    delete: function(id) {
        const self = this;
        this.T.post('statuses/destroy/:id', { id: id })
            .catch(function(err) {
                self.vorpal.log('Error POST statuses/destroy: ' + err);
            })
            .then(function(result) {
                self.vorpal.log(('Deleted tweet with status ' + result.data.id_str).yellow);
            });
    },

    isMention: function(status) {
        for (var m in status.entities.user_mentions) {
            var mention = status.entities.user_mentions[m];
            if (mention.id == this.ME.id) return true;
        }
        return false;
    },

    displayStatus: function(status) {
        var id = ShortIdGenerator.generate();

        var doc = {
            id: id,
            status: status
        };
        this.cache.update({ id: id }, doc, { upsert: true });

        var text = status.text;

        this.vorpal.log(status.entities.urls);
        for (var u in status.entities.urls) {
            var url = status.entities.urls[u];
            var _text = text.substring(0, url.indices[0]);
            _text += url.display_url;
            _text += text.substring(url.indices[1]);
            text = _text;
        }

        for (var m in status.entities.user_mentions) {
            var mention = status.entities.user_mentions[m];
            text = text.replace(
                '@' + mention.screen_name,
                ('@' + mention.screen_name).bold
            );
        }

        var line = id + "> ";
        line += "<@";
        line += status.user.screen_name == this.ME.screen_name
            ? status.user.screen_name.underline.yellow
            : status.user.screen_name.underline.blue;
        line += ">: ";
        line += this.isMention(status) ? text.red : text;
        line += '\n';
        this.vorpal.log(line);
    }
};
<commit_msg>improve retweet handling<commit_after>var Twit = require('twit'),
    ShortIdGenerator = require('./ShortIdGenerator');

module.exports = {
    T: null,
    stream: null,
    ME: null,
    PINAuth: null,
    vorpal: null,
    cache: null,
    login: function(ckey, csecret, akey, asecret, vorpal, cache) {
        this.vorpal = vorpal;
        this.cache = cache;
        this.T = new Twit({
            consumer_key:        ckey,
            consumer_secret:     csecret,
            access_token:        akey,
            access_token_secret: asecret
        });

        this.loadMyself();
    },
    startStream: function() {
        const self = this;
        this.stream = this.T.stream('user');

        this.stream.on('tweet', function(tweet) {
            self.displayStatus(tweet);
        });
    },
    loadMyself: function() {
        const self = this;
        this.T.get('account/verify_credentials', { skip_status: true })
            .catch(function(err) {
                self.vorpal.log('Error GET account/verify_credentials: ' + err);
            })
            .then(function(result) {
                self.vorpal.log("Logged in as " + result.data.screen_name);
                self.ME = result.data;

                self.loadHome();
            });
    },

    loadHome: function() {
        const self = this;
        this.T.get('statuses/home_timeline', { count: 20 })
            .catch(function(err) {
                self.vorpal.log('Error GET statuses/home_timeline: ' + err);
            })
            .then(function(result) {
                result.data.reverse().forEach(function(tweet) {
                    self.displayStatus(tweet);
                });
            });
    },

    loadReplies: function() {
        const self = this;
        this.T.get('statuses/mentions_timeline')
            .catch(function(err) {
                self.vorpal.log('Error GET statuses/mentions_timeline: ' + err);
            })
            .then(function(result) {
                result.data.reverse().forEach(function(tweet) {
                    self.displayStatus(tweet);
                });
            });
    },

    update: function(tweet) {
        const self = this;
        this.T.post('statuses/update', { status: tweet })
            .catch(function(err) {
                if (err) self.vorpal.log(err);
            });
    },

    delete: function(id) {
        const self = this;
        this.T.post('statuses/destroy/:id', { id: id })
            .catch(function(err) {
                self.vorpal.log('Error POST statuses/destroy: ' + err);
            })
            .then(function(result) {
                self.vorpal.log(('Deleted tweet with status ' + result.data.id_str).yellow);
            });
    },

    isMention: function(status) {
        for (var m in status.entities.user_mentions) {
            var mention = status.entities.user_mentions[m];
            if (mention.id == this.ME.id) return true;
        }
        return false;
    },

    displayStatus: function(status) {
        var id = ShortIdGenerator.generate();

        var doc = {
            id: id,
            status: status
        };
        this.cache.update({ id: id }, doc, { upsert: true });

        var isRetweet = status.retweeted_status ? true : false;

        var text = isRetweet ? status.retweeted_status.text : status.text;
        var entities = isRetweet ? status.retweeted_status.entities : status.entities;

        for (var u in entities.urls) {
            var url = entities.urls[u];
            var _text = text.substring(0, url.indices[0]);
            _text += url.expanded_url;
            _text += text.substring(url.indices[1]);
            text = _text;
        }

        for (var m in entities.user_mentions) {
            var mention = entities.user_mentions[m];
            text = text.replace(
                '@' + mention.screen_name,
                ('@' + mention.screen_name).bold
            );
        }

        if (isRetweet) {
            text = "RT " + ("@" + status.retweeted_status.user.screen_name + ": ").bold + text;
        }

        var line = id + "> ";
        line += "<@";
        line += status.user.screen_name == this.ME.screen_name
            ? status.user.screen_name.underline.yellow
            : status.user.screen_name.underline.blue;
        line += ">: ";
        line += this.isMention(status) ? text.red : text;
        line += '\n';
        this.vorpal.log(line);
    }
};
<|endoftext|>


<commit_before>/**
 * Github FileBrowser configuration module.
 */
var m = require('mithril');

var Fangorn = require('fangorn');
var waterbutler = require('waterbutler');

function _uploadUrl(item, file) {
    return waterbutler.buildTreeBeardUpload(item, file, {branch: item.data.branch});
}

// Define Fangorn Button Actions
function _fangornActionColumn (item, col){
    var self = this;
    var buttons = [];

    function _removeEvent (event, item, col) {
        try {
            event.stopPropagation();
        } catch (e) {
            window.event.cancelBubble = true;
        }
        var tb = this;

        function cancelDelete () {
            this.modal.dismiss();
        }
        function runDelete () {
            var tb = this;
            $('.tb-modal-footer .btn-success').html(' Deleting...').attr('disabled', 'disabled');
            // delete from server, if successful delete from view
            $.ajax({
                url: waterbutler.buildTreeBeardDelete(item, {branch: item.data.branch, sha: item.data.extra.fileSha}),
                type : 'DELETE'
            })
            .done(function(data) {
                // delete view
                tb.deleteNode(item.parentID, item.id);
                window.console.log('Delete success: ', data);
                tb.modal.dismiss();
            })
            .fail(function(data){
                tb.modal.dismiss();
                window.console.log('Delete failed: ', data);
                item.notify.update('Delete failed.', 'danger', undefined, 3000);
            });
        }
        if (item.data.permissions.edit) {
            var mithrilContent = m('div', [
                    m('h3', 'Delete "' + item.data.name+ '"?'),
                    m('p', 'This action is irreversable.')
                ]);
            var mithrilButtons = m('div', [
                    m('button', { 'class' : 'btn btn-default m-r-md', onclick : function() { cancelDelete.call(tb); } }, 'Cancel'),
                    m('button', { 'class' : 'btn btn-success', onclick : function() { runDelete.call(tb); }  }, 'OK')
                ]);
            tb.modal.update(mithrilContent, mithrilButtons);
        } else {
            item.notify.update('You don\'t have permission to delete this file.', 'info', undefined, 3000);
        }
    }

    function _downloadEvent (event, item, col) {
        event.stopPropagation();
        console.log('Download Event triggered', this, event, item, col);
        window.location = waterbutler.buildTreeBeardDownload(item, {ref: item.data.extra.fileSha});
    }

    // Download Zip File
    if (item.kind === 'folder') {
        if (item.data.permissions.edit) {
            buttons.push({
                'name' : '',
                'icon' : 'icon-upload-alt',
                'css' : 'fangorn-clickable btn btn-default btn-xs',
                'onclick' : Fangorn.ButtonEvents._uploadEvent
            });
        }

        if (item.data.addonFullname) {
            buttons.push(
                {
                    'name' : '',
                    'icon' : 'icon-download-alt',
                    'css' : 'fangorn-clickable btn btn-info btn-xs',
                    'onclick' : function(){window.location = item.data.urls.zip;}
                },
                {
                    'name' : '',
                    'icon' : 'icon-external-link',
                    'css' : 'btn btn-primary btn-xs',
                    'onclick' : function(){window.location = item.data.urls.repo;}//GO TO EXTERNAL PAGE
                }
            );
        }
    } else if (item.kind === 'file') {
        buttons.push({
            'name' : '',
            'icon' : 'icon-download-alt',
            'css' : 'btn btn-info btn-xs',
            'onclick' : _downloadEvent
        });

        if (item.data.permissions.edit) {
            buttons.push({
                'name' : '',
                'icon' : 'icon-remove',
                'css' : 'm-l-lg text-danger fg-hover-hide',
                'style' : 'display:none',
                'onclick' : _removeEvent
            });
        }
    }

    return buttons.map(function(btn){
        return m('span', { 'data-col' : item.id }, [
            m('i', {
                'class' : btn.css,
                style : btn.style,
                'onclick' : function(event){ btn.onclick.call(self, event, item, col); }
            }, [ m('span', { 'class' : btn.icon}, btn.name) ])
        ]);
    });
}

function changeBranch(item, ref){
    item.data.branch = ref;
    this.updateFolder(null, item);
}

function _resolveLazyLoad(item) {
    return waterbutler.buildTreeBeardMetadata(item, {ref: item.data.branch});
}

function _fangornLazyLoadOnLoad (tree) {
    tree.children.forEach(function(item) {
        Fangorn.Utils.inheritFromParent(item, tree, ['branch']);
    });
}

function _fangornGithubTitle(item, col)  {
    var tb = this;
    var branchArray = [];
    if (item.data.branches) {
        item.data.branch = item.data.branch || item.data.defaultBranch;
        for (var i = 0; i < item.data.branches.length; i++) {
            var selected = item.data.branches[i] === item.data.defaultBranch ? 'selected' : '';
            branchArray.push(m('option', {selected : selected, value:item.data.branches[i]}, item.data.branches[i]));
        }
    }

    if (item.data.addonFullname) {
        return m('span',[
            m('github-name', item.data.name + ' '),
            m('span',[
                m('select[name=branch-selector]', { onchange: function(ev) { changeBranch.call(tb, item, ev.target.value ) } }, branchArray)
            ])
        ]);
    } else {
        return m('span',[
            m('github-name', {
                onclick: function() {
                    var params = $.param(
                        $.extend(
                          {
                              provider: item.data.provider,
                              path: item.data.path.substring(1),
                              branch: item.data.branch
                          },
                          item.data.extra || {}
                        )
                    );
                    window.location = item.data.nodeApiUrl + 'waterbutler/files/?' + params;
                }}, item.data.name)
        ]);
    }

}

function _fangornColumns (item) {
    var columns = [];
    columns.push({
        data : 'name',
        folderIcons : true,
        filter: true,
        custom : _fangornGithubTitle
    });

    if(this.options.placement === 'project-files') {
        columns.push(
            {
            css : 'action-col',
            filter : false,
            custom : _fangornActionColumn
        },
        {
            data  : 'downloads',
            filter : false,
            css : ''
        });
    }
    return columns;
}

function _fangornFolderIcons(item){
    if(item.data.iconUrl){
        return m('img',{src:item.data.iconUrl, style:{width:'16px', height:'auto'}}, ' ');
    }
    return undefined;
}

function _fangornUploadComplete(item){
    console.log('upload complete', this, item);
    var index = this.returnIndex(item.id);
}

function _fangornUploadSuccess(file, item, response) {
    if (response) {
        response.branch = item.parent().data.branch;
    }
}

// Register configuration
Fangorn.config.github = {
    // Handle changing the branch select
    uploadUrl: _uploadUrl,
    lazyload: _resolveLazyLoad,
    resolveRows: _fangornColumns,
    folderIcon: _fangornFolderIcons,
    onUploadComplete: _fangornUploadComplete,
    lazyLoadOnLoad: _fangornLazyLoadOnLoad,
    uploadSuccess: _fangornUploadSuccess
};
<commit_msg>Fix typo in file deletion dialog box<commit_after>/**
 * Github FileBrowser configuration module.
 */
var m = require('mithril');

var Fangorn = require('fangorn');
var waterbutler = require('waterbutler');

function _uploadUrl(item, file) {
    return waterbutler.buildTreeBeardUpload(item, file, {branch: item.data.branch});
}

// Define Fangorn Button Actions
function _fangornActionColumn (item, col){
    var self = this;
    var buttons = [];

    function _removeEvent (event, item, col) {
        try {
            event.stopPropagation();
        } catch (e) {
            window.event.cancelBubble = true;
        }
        var tb = this;

        function cancelDelete () {
            this.modal.dismiss();
        }
        function runDelete () {
            var tb = this;
            $('.tb-modal-footer .btn-success').html(' Deleting...').attr('disabled', 'disabled');
            // delete from server, if successful delete from view
            $.ajax({
                url: waterbutler.buildTreeBeardDelete(item, {branch: item.data.branch, sha: item.data.extra.fileSha}),
                type : 'DELETE'
            })
            .done(function(data) {
                // delete view
                tb.deleteNode(item.parentID, item.id);
                window.console.log('Delete success: ', data);
                tb.modal.dismiss();
            })
            .fail(function(data){
                tb.modal.dismiss();
                window.console.log('Delete failed: ', data);
                item.notify.update('Delete failed.', 'danger', undefined, 3000);
            });
        }
        if (item.data.permissions.edit) {
            var mithrilContent = m('div', [
                    m('h3', 'Delete "' + item.data.name+ '"?'),
                    m('p', 'This action is irreversible.')
                ]);
            var mithrilButtons = m('div', [
                    m('button', { 'class' : 'btn btn-default m-r-md', onclick : function() { cancelDelete.call(tb); } }, 'Cancel'),
                    m('button', { 'class' : 'btn btn-success', onclick : function() { runDelete.call(tb); }  }, 'OK')
                ]);
            tb.modal.update(mithrilContent, mithrilButtons);
        } else {
            item.notify.update('You don\'t have permission to delete this file.', 'info', undefined, 3000);
        }
    }

    function _downloadEvent (event, item, col) {
        event.stopPropagation();
        console.log('Download Event triggered', this, event, item, col);
        window.location = waterbutler.buildTreeBeardDownload(item, {ref: item.data.extra.fileSha});
    }

    // Download Zip File
    if (item.kind === 'folder') {
        if (item.data.permissions.edit) {
            buttons.push({
                'name' : '',
                'icon' : 'icon-upload-alt',
                'css' : 'fangorn-clickable btn btn-default btn-xs',
                'onclick' : Fangorn.ButtonEvents._uploadEvent
            });
        }

        if (item.data.addonFullname) {
            buttons.push(
                {
                    'name' : '',
                    'icon' : 'icon-download-alt',
                    'css' : 'fangorn-clickable btn btn-info btn-xs',
                    'onclick' : function(){window.location = item.data.urls.zip;}
                },
                {
                    'name' : '',
                    'icon' : 'icon-external-link',
                    'css' : 'btn btn-primary btn-xs',
                    'onclick' : function(){window.location = item.data.urls.repo;}//GO TO EXTERNAL PAGE
                }
            );
        }
    } else if (item.kind === 'file') {
        buttons.push({
            'name' : '',
            'icon' : 'icon-download-alt',
            'css' : 'btn btn-info btn-xs',
            'onclick' : _downloadEvent
        });

        if (item.data.permissions.edit) {
            buttons.push({
                'name' : '',
                'icon' : 'icon-remove',
                'css' : 'm-l-lg text-danger fg-hover-hide',
                'style' : 'display:none',
                'onclick' : _removeEvent
            });
        }
    }

    return buttons.map(function(btn){
        return m('span', { 'data-col' : item.id }, [
            m('i', {
                'class' : btn.css,
                style : btn.style,
                'onclick' : function(event){ btn.onclick.call(self, event, item, col); }
            }, [ m('span', { 'class' : btn.icon}, btn.name) ])
        ]);
    });
}

function changeBranch(item, ref){
    item.data.branch = ref;
    this.updateFolder(null, item);
}

function _resolveLazyLoad(item) {
    return waterbutler.buildTreeBeardMetadata(item, {ref: item.data.branch});
}

function _fangornLazyLoadOnLoad (tree) {
    tree.children.forEach(function(item) {
        Fangorn.Utils.inheritFromParent(item, tree, ['branch']);
    });
}

function _fangornGithubTitle(item, col)  {
    var tb = this;
    var branchArray = [];
    if (item.data.branches) {
        item.data.branch = item.data.branch || item.data.defaultBranch;
        for (var i = 0; i < item.data.branches.length; i++) {
            var selected = item.data.branches[i] === item.data.defaultBranch ? 'selected' : '';
            branchArray.push(m('option', {selected : selected, value:item.data.branches[i]}, item.data.branches[i]));
        }
    }

    if (item.data.addonFullname) {
        return m('span',[
            m('github-name', item.data.name + ' '),
            m('span',[
                m('select[name=branch-selector]', { onchange: function(ev) { changeBranch.call(tb, item, ev.target.value ) } }, branchArray)
            ])
        ]);
    } else {
        return m('span',[
            m('github-name', {
                onclick: function() {
                    var params = $.param(
                        $.extend(
                          {
                              provider: item.data.provider,
                              path: item.data.path.substring(1),
                              branch: item.data.branch
                          },
                          item.data.extra || {}
                        )
                    );
                    window.location = item.data.nodeApiUrl + 'waterbutler/files/?' + params;
                }}, item.data.name)
        ]);
    }

}

function _fangornColumns (item) {
    var columns = [];
    columns.push({
        data : 'name',
        folderIcons : true,
        filter: true,
        custom : _fangornGithubTitle
    });

    if(this.options.placement === 'project-files') {
        columns.push(
            {
            css : 'action-col',
            filter : false,
            custom : _fangornActionColumn
        },
        {
            data  : 'downloads',
            filter : false,
            css : ''
        });
    }
    return columns;
}

function _fangornFolderIcons(item){
    if(item.data.iconUrl){
        return m('img',{src:item.data.iconUrl, style:{width:'16px', height:'auto'}}, ' ');
    }
    return undefined;
}

function _fangornUploadComplete(item){
    console.log('upload complete', this, item);
    var index = this.returnIndex(item.id);
}

function _fangornUploadSuccess(file, item, response) {
    if (response) {
        response.branch = item.parent().data.branch;
    }
}

// Register configuration
Fangorn.config.github = {
    // Handle changing the branch select
    uploadUrl: _uploadUrl,
    lazyload: _resolveLazyLoad,
    resolveRows: _fangornColumns,
    folderIcon: _fangornFolderIcons,
    onUploadComplete: _fangornUploadComplete,
    lazyLoadOnLoad: _fangornLazyLoadOnLoad,
    uploadSuccess: _fangornUploadSuccess
};
<|endoftext|>


<commit_before>'use strict';

angular.module('yomadApp')
  .service('messageDescriptionService', ['$q', function messageDescriptionService($q) {

    return {
      getDescriptionForMessage(message) {
        if(message.priority > 5){
          var pMsg = "!! ";
        }
        else{
          var pMsg = "";
        }

        if(message.isBurst && message.type === "map") {
          return pMsg + message.user + ": " + message.locationDesc;
        } else if(message.isBurst && message.type == "land" {
          return pMsg + message.user + ": " + message.name + " at " + message.locationDesc;
        } else if(message.isBurst) {
          return message.locationDesc;
        } else {
          return message.address1;
        }
      }
    }
  }]);
<commit_msg>fixes<commit_after>'use strict';

angular.module('yomadApp')
  .service('messageDescriptionService', ['$q', function messageDescriptionService($q) {

    return {
      getDescriptionForMessage(message) {
        if(message.priority > 5){
          var pMsg = "!! ";
        }
        else{
          var pMsg = "";
        }

        if(message.isBurst && message.type === "map") {
          return pMsg + message.user + ": " + message.locationDesc;
        } else if(message.isBurst && message.type === "land") {
          return pMsg + message.user + ": " + message.name + " at " + message.locationDesc;
        } else if(message.isBurst) {
          return message.locationDesc;
        } else {
          return message.address1;
        }
      }
    }
  }]);
<|endoftext|>