You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2015/10/27 22:36:27 UTC

[01/47] allura git commit: Remove unused method that would be insecure if used (no user_id check)

Repository: allura
Updated Branches:
  refs/heads/db/7919 64e060da4 -> d21d71d1c (forced update)


Remove unused method that would be insecure if used (no user_id check)


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/f33baf42
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/f33baf42
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/f33baf42

Branch: refs/heads/db/7919
Commit: f33baf423d9c7a11d76d1e860eb720bc2d792379
Parents: bae38ad
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 19 18:53:51 2015 +0000
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Oct 19 18:53:51 2015 +0000

----------------------------------------------------------------------
 Allura/allura/model/oauth.py | 15 ---------------
 1 file changed, 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/f33baf42/Allura/allura/model/oauth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/oauth.py b/Allura/allura/model/oauth.py
index fb395f5..6dc00e5 100644
--- a/Allura/allura/model/oauth.py
+++ b/Allura/allura/model/oauth.py
@@ -20,11 +20,9 @@ import logging
 import oauth2 as oauth
 from pylons import tmpl_context as c, app_globals as g
 
-import pymongo
 from paste.deploy.converters import aslist
 from tg import config
 from ming import schema as S
-from ming.orm import session
 from ming.orm import FieldProperty, RelationProperty, ForeignIdProperty
 from ming.orm.declarative import MappedClass
 
@@ -72,19 +70,6 @@ class OAuthConsumerToken(OAuthToken):
 
     user = RelationProperty('User')
 
-    @classmethod
-    def upsert(cls, name):
-        t = cls.query.get(name=name)
-        if t is not None:
-            return t
-        try:
-            t = cls(name=name)
-            session(t).flush(t)
-        except pymongo.errors.DuplicateKeyError:
-            session(t).expunge(t)
-            t = cls.query.get(name=name)
-        return t
-
     @property
     def description_html(self):
         return g.markdown.cached_convert(self, 'description')


[13/47] allura git commit: [#7919] Add markup to support the NavBar

Posted by br...@apache.org.
[#7919] Add markup to support the NavBar


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/f5275793
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/f5275793
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/f5275793

Branch: refs/heads/db/7919
Commit: f5275793d25abffb70ef3874ec7c56340abdfac2
Parents: 8a855ea
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:10:38 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:09:58 2015 -0400

----------------------------------------------------------------------
 Allura/allura/templates/jinja_master/master.html  | 18 ++++++++++++++++++
 Allura/allura/templates/jinja_master/top_nav.html |  9 +++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/f5275793/Allura/allura/templates/jinja_master/master.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/master.html b/Allura/allura/templates/jinja_master/master.html
index fd5a83e..1a7f11c 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -22,8 +22,14 @@
 {% if g.theme.jinja_macros %}
     {% import g.theme.jinja_macros as theme_macros with context %}
 {% endif %}
+{% set is_admin = c.project and h.has_access(c.project, 'admin')() %}
 {% do g.register_forge_js('js/jquery-base.js', location='head_js') %}
 {% do g.register_forge_js('js/jquery.notify.js') %}
+{% do g.register_forge_js('js/browser-polyfill.js') %}
+{% do g.register_forge_js('js/underscore-min.js') %}
+{% do g.register_forge_js('js/react-with-addons.min.js') %}
+{% do g.register_forge_js("js/react-drag.js") %}
+{% do g.register_forge_js('js/react-reorderable.js') %}
 {% do g.register_forge_js('js/jquery.tooltipster.js') %}
 {% do g.register_forge_js('js/modernizr.js') %}
 {% do g.register_forge_js('js/sylvester.js') %}
@@ -32,6 +38,7 @@
 {% do g.register_forge_js('js/build/transpiled.js') %}
 {% do g.register_forge_css('css/forge/hilite.css') %}
 {% do g.register_forge_css('css/forge/tooltipster.css') %}
+{% if is_admin %}{% do g.register_forge_css('css/navbar.css') %}{% endif %}
 {% do g.register_forge_css('css/font-awesome.min.css', compress=False) %}
 {% do g.theme.require() %}
 {% do g.resource_manager.register_widgets(c) %}
@@ -180,5 +187,16 @@
         });
     })
 </script>
+{% if is_admin %}
+    <script>
+        'use strict';
+        $(document).ready(function () {
+            React.render(React.createElement(Main, {
+                initialData: {{ c.project.json_nav()|safe }}
+            }), document.getElementById("top_nav_admin"));
+        });
+    </script>
+{% endif %}
+{% do g.register_forge_js('/') %}
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/allura/blob/f5275793/Allura/allura/templates/jinja_master/top_nav.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/top_nav.html b/Allura/allura/templates/jinja_master/top_nav.html
index f609bd6..c433991 100644
--- a/Allura/allura/templates/jinja_master/top_nav.html
+++ b/Allura/allura/templates/jinja_master/top_nav.html
@@ -17,10 +17,14 @@
        under the License.
 -#}
 {% if c.project %}
+{% if h.has_access(c.project, 'admin')() %}
+    <div id="top_nav_admin"></div>
+    {#        {{ c.app.admin_modal.display() }}  <-- Currently Does not work on non-admin urls #}
+{% else %}
 <ul class="dropdown">
   {% for s in c.project.grouped_navbar_entries() %}
     <li class="{% if s.matches_url(request) %}selected{% endif %}">
-        <a href="{{s.url}}" class="tool-{{(s.tool_name or 'unknown').lower()}}">
+        <a href="{{s.url}}" class="ui-icon-tool-{{(s.tool_name or 'admin').lower()}}-32">
             {{s.label}}
         </a>
         {% set grouped_tool_count = s.matching_urls|length %}
@@ -34,4 +38,5 @@
     </li>
 	{% endfor %}
 </ul>
-{% endif %}
\ No newline at end of file
+{% endif %}
+{% endif %}


[41/47] allura git commit: [#7919] Add cache for installable tools

Posted by br...@apache.org.
[#7919] Add cache for installable tools


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/827525af
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/827525af
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/827525af

Branch: refs/heads/db/7919
Commit: 827525af3858d5bc337bca0d2280595a2455dd93
Parents: 7621027
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 15 17:56:32 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/navbar.es6.js | 44 +++++++++------------------
 1 file changed, 14 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/827525af/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index 791efd9..ecd0fad 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -315,16 +315,6 @@ var ToggleAddNewTool = React.createClass({
 // Add New Tool //
 //////////////////
 
-var NewToolButton = React.createClass({
-    render: function () {
-        return (
-            <button id='new-tool-btn' onClick={ this.props.handleAddButton } className=''>
-                <i className={ classes }></i>
-            </button>
-        );
-    }
-});
-
 
 /**
  * Menu for adding a new tool.
@@ -384,10 +374,6 @@ var NewToolMenu = React.createClass({
 
 var InstallNewToolForm = React.createClass({
     render: function () {
-        //console.log(this.props.active.name);
-
-        //var default_mount_label = this.props.active.defaults.default_mount_label;
-
         return (
             <form id="add-tool-form">
                 <label htmlFor="mount_label">Label</label>
@@ -401,8 +387,8 @@ var InstallNewToolForm = React.createClass({
                        id="mount_point"
                        onChange={this.props.handleChangeForm}
                        onBlur={this.props.toolFormIsValid}
-                       placeholder={slugify(this.props.formData.mount_label)}
-                       value={this.props.formData.mount_point}/>
+                       value={slugify(this.props.formData.mount_label)}
+                       value={this.props.formData.mount_point.toLowerCase()}/>
                 <span>{this.props.validationErrors.mount_point}</span>
 
                 <p style={{"color": "grey"}}><small>http://hs/p/finna/</small><strong style={{"color": "orange"}}>
@@ -443,6 +429,16 @@ var NewToolInfo = React.createClass({
     }
 });
 
+
+var installableToolsCache = {};
+function loadTools(id, callback) {
+    if(!installableToolsCache[id]) {
+        installableToolsCache[id] = $.get(_getProjectUrl(true) + "/admin/installable_tools/").promise();
+    }
+    installableToolsCache[id].done(callback);
+}
+
+
 var NewToolMain = React.createClass({
     getInitialState: function () {
         let toolPlaceHolder = {
@@ -467,25 +463,15 @@ var NewToolMain = React.createClass({
         };
     },
 
-
     componentDidMount: function () {
-        let _this = this;
-        console.log(_getProjectUrl() + "/admin/installable_tools/");
-        $.get(_getProjectUrl(true) + "/admin/installable_tools/", function (result) {
+        let tools = loadTools('tools', function (result) {
             if (this.isMounted()) {
-                console.log('hit is mounted', result['tools']);
                 this.setState({
                     installableTools: result['tools']
-                });
+                })
             }
         }.bind(this));
     },
-    handleAddButton: function (e) {
-        e.preventDefault();
-        console.log('current active tool', this.state.active);
-        console.log('new_tool', this.state.new_tool);
-
-    },
     handleChangeTool: function (e) {
         console.log(`Changed tool to: ${e.target.textContent}`);
         this._setActiveByName(e.target.textContent);
@@ -569,7 +555,6 @@ var NewToolMain = React.createClass({
 
         let result = $.post(_getProjectUrl() + '/admin/mount_point/', data);
             if (!result.responseJSON) {
-                console.log("ALREADY EXISTS", result);
                 errors.mount_point.push("Mount point already exists.");
             }
 
@@ -578,7 +563,6 @@ var NewToolMain = React.createClass({
     },
 
     render: function () {
-        //var visible =
         return <NewToolMenu
             active={this.state.active}
             tools={this.state.installableTools}


[25/47] allura git commit: [#7920] Fix routing conflict for tools api endpoint

Posted by br...@apache.org.
[#7920] Fix routing conflict for tools api endpoint


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/9c363976
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/9c363976
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/9c363976

Branch: refs/heads/db/7919
Commit: 9c363976d297471dd72dd75974e873efeb772353
Parents: 30d234e
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 12:24:55 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/9c363976/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 676a6fc..c10926a 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -796,14 +796,13 @@ class ProjectAdminRestController(BaseController):
         return {'status': 'ok'}
 
     @expose('json:')
-    def tools(self, **kw):
+    def installable_tools(self, **kw):
         """ List of installable tools
-
         """
         response.content_type = 'application/json'
-        tools_names = [t['name'] for t in AdminApp.installable_tools_for(c.project)]
+        tools = [t['name'] for t in AdminApp.installable_tools_for(c.project)]
 
-        return {'status': 'ok'}
+        return {'tools': tools}
 
     @expose('json:')
     @require_post()


[05/47] allura git commit: [#8004] Remove tool icons from project nav

Posted by br...@apache.org.
[#8004] Remove tool icons from project nav


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/687e3f15
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/687e3f15
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/687e3f15

Branch: refs/heads/db/7919
Commit: 687e3f15232d15dd677bac2f965153e164399781
Parents: 52c8d5c
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Oct 20 17:04:08 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Oct 22 10:55:25 2015 -0400

----------------------------------------------------------------------
 Allura/allura/nf/allura/css/site_style.css      | 150 ++++++-------------
 .../allura/templates/jinja_master/master.html   |   2 +-
 .../allura/templates/jinja_master/top_nav.html  |   4 +-
 3 files changed, 50 insertions(+), 106 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/687e3f15/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index a3fbc09..7bda3ee 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -1201,37 +1201,6 @@ nav .ico {
   text-transform: none;
 }
 
-/* these don't work with sprite images (only if the icons were font-based)
-.x16 {
-  font-size: 16px;
-  width: 16px;
-  height: 16px;
-}
-
-.x24 {
-  font-size: 24px;
-  width: 24px;
-  height: 24px;
-}
-
-.x32 {
-  font-size: 32px;
-  width: 32px;
-  height: 32px;
-}
-
-.x48 {
-  font-size: 48px;
-  width: 48px;
-  height: 48px;
-}
-
-.x64 {
-  font-size: 64px;
-  width: 64px;
-  height: 64px;
-}
-*/
 
 .modal b.close {
   position: absolute;
@@ -1240,32 +1209,6 @@ nav .ico {
   cursor: pointer;
 }
 
-#directory .ico, #search .ico {
-  color: #cccccc;
-}
-
-.icon_social_NN, .icon_facebook_16, .icon_facebook_24, .icon_facebook_32 {
-  display: block;
-}
-
-.icon_facebook_16 {
-  background-position: 0 0;
-  width: 16px;
-  height: 16px;
-}
-
-.icon_facebook_24 {
-  background-position: 0 -26px;
-  width: 24px;
-  height: 24px;
-}
-
-.icon_facebook_32 {
-  background-position: 0 -60px;
-  width: 32px;
-  height: 32px;
-}
-
 /* other media  */
 @media print {
   * {
@@ -1821,10 +1764,10 @@ nav .ico {
 }
 
 /* forge  */
-.base, #content_base {
-  margin: -24px 0 0;
+#content_base {
+  margin: -1px 0 0;
   background: #e5e5e5;
-  border: 1px solid #aaaaaa;
+  border: 1px solid #ccc;
   -moz-border-radius-bottomleft: 4px;
   -webkit-border-bottom-left-radius: 4px;
   -o-border-bottom-left-radius: 4px;
@@ -2228,31 +2171,22 @@ a.sidebar-disabled:focus {
 }
 
 #top_nav {
-  background-color: #e5e5e5;
-  background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, #cccccc));
-  background-image: -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
-  background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
-  border: 1px solid #aaaaaa;
-  -moz-border-radius: 4px;
-  -webkit-border-radius: 4px;
-  -o-border-radius: 4px;
+  background-color: #f8f8f8;
+  background-image: linear-gradient(#ffffff, #f0f0f0);
+  border: 1px solid #ccc;
+  border-bottom: 0;
   -ms-border-radius: 4px;
-  -khtml-border-radius: 4px;
-  border-radius: 4px;
-  display: inline-block;
-  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
-  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
-  -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
-  border: medium none;
-  margin: 0 0 20px 0;
+  border-radius: 4px 4px 0 0;
   overflow: visible;
-  width: 940px;
+  z-index: 99;
+  display: block;
+  margin: 0;
+  padding: 0;
 }
 #top_nav a {
   float: left;
   margin-right: 20px;
-  height: 50px;
+  height: 16px;
   min-width: 35px;
   text-align: center;
   color: #333;
@@ -3105,7 +3039,6 @@ table thead tr th.narrow, table tr td.narrow {
   left: 45%;
 }
 ul.dropdown,
-ul.dropdown li,
 ul.dropdown ul {
     list-style: none;
     margin: 0;
@@ -3113,35 +3046,38 @@ ul.dropdown ul {
 }
 
 ul.dropdown {
-    position: relative;
-    z-index: 597;
-    float: left;
+  border-bottom: 1px solid #ccc;
+  border-bottom-left-radius: 4px;
+  border-bottom-right-radius: 4px;
+  box-shadow: 0 1px 1px #ccc;
+  overflow: hidden;
+  padding: 10px 10px 0;
 }
 
-ul.dropdown li {
+#top_nav ul.dropdown > li {
     float: left;
-    vertical-align: middle;
-    zoom: 1;
-    padding-top: 10px;
+    margin-right: 0;
     padding-bottom: 10px;
 }
 
-ul.dropdown li.hover,
-ul.dropdown li:hover {
-    position: relative;
-    z-index: 599;
-    cursor: default;
+#top_nav ul.dropdown > li > a {
+  border-right: 1px solid #ccc; /* e5e5e5 or #ccc ? */
+  margin-right: 10px;
+  padding-right: 10px;
+}
+
+#top_nav ul.dropdown > li:last-child > a {
+  border-right: 0;
+  margin-right: 0;
 }
 
 ul.dropdown ul {
     visibility: hidden;
     position: absolute;
-    top:70px;
+    top:36px;
     z-index: 598;
+    margin-left: -10px;
     background-color: #ffffff;
-    border-width: 1px;
-    border-style: solid;
-    border-color: #dddddd;
     -moz-border-bottom-left-radius: 5px;
     -webkit-border-bottom-left-radius: 5px;
     -o-border-bottom-left-radius: 5px;
@@ -3176,17 +3112,26 @@ ul.dropdown ul li a {
     height: auto !important;
     font-weight:normal;
     padding: 5px;
-    border-top: 1px solid #eee;
 }
 ul.dropdown ul li:first-child a {
     border-top: 0;
 }
-li.selected,
-ul.dropdown ul li.selected a{
-    font-weight:bold;
+#top_nav ul.dropdown > li ul li {
+    border: 1px solid #e5e5e5;
+    border-bottom: none;
 }
-ul.dropdown ul li a:hover {
-    background-color: #09c;
+#top_nav ul.dropdown > li ul li:first-child {
+    border-top: 0;
+}
+#top_nav ul.dropdown li.selected > a {
+    color: #0077AA;
+}
+#top_nav ul.dropdown li ul li:hover {
+  background-color: #09c;
+  background-image: linear-gradient(#09c, #07a);
+  border-color: #07a;
+}
+#top_nav ul.dropdown ul li a:hover {
     color: white !important;
 }
 #top_nav ul.dropdown ul li,
@@ -3194,7 +3139,6 @@ ul.dropdown ul li a:hover {
     float: none;
     display: block;
     text-align: left;
-    margin-right: 0;
 }
 #project-import-form {
     margin-left: 5px;

http://git-wip-us.apache.org/repos/asf/allura/blob/687e3f15/Allura/allura/templates/jinja_master/master.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/master.html b/Allura/allura/templates/jinja_master/master.html
index 4fde7ab..6f2487d 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -33,7 +33,7 @@
 {% do g.register_forge_css('css/forge/hilite.css') %}
 {% do g.register_forge_css('css/forge/tooltipster.css') %}
 {% do g.register_forge_css('css/font-awesome.min.css', compress=False) %}
-{% do g.register_css('/nf/tool_icon_css?' + g.build_key, compress=False) %}
+{#  {% do g.register_css('/nf/tool_icon_css?' + g.build_key, compress=False) %}   If you need tool icons, use this #}
 {% do g.theme.require() %}
 {% do g.resource_manager.register_widgets(c) %}
 {# paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ #}

http://git-wip-us.apache.org/repos/asf/allura/blob/687e3f15/Allura/allura/templates/jinja_master/top_nav.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/top_nav.html b/Allura/allura/templates/jinja_master/top_nav.html
index 8fdfb34..f609bd6 100644
--- a/Allura/allura/templates/jinja_master/top_nav.html
+++ b/Allura/allura/templates/jinja_master/top_nav.html
@@ -20,7 +20,7 @@
 <ul class="dropdown">
   {% for s in c.project.grouped_navbar_entries() %}
     <li class="{% if s.matches_url(request) %}selected{% endif %}">
-        <a href="{{s.url}}" class="ui-icon-tool-{{(s.tool_name or 'admin').lower()}}-32">
+        <a href="{{s.url}}" class="tool-{{(s.tool_name or 'unknown').lower()}}">
             {{s.label}}
         </a>
         {% set grouped_tool_count = s.matching_urls|length %}
@@ -34,4 +34,4 @@
     </li>
 	{% endfor %}
 </ul>
-{% endif %}
+{% endif %}
\ No newline at end of file


[40/47] allura git commit: [#7919] Merged with Dave's refactor/enhancments

Posted by br...@apache.org.
[#7919] Merged with Dave's refactor/enhancments


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/7621027f
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/7621027f
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/7621027f

Branch: refs/heads/db/7919
Commit: 7621027fc7527a338ef0314c3725c92392657eec
Parents: 7a7a4d0
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 15 15:40:27 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css   | 154 +++++---------------------
 Allura/allura/public/nf/js/navbar.es6.js | 106 +++++++-----------
 2 files changed, 66 insertions(+), 194 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/7621027f/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index 0dec309..f3c3336 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -55,10 +55,6 @@ nav {
     margin: auto;
 }
 
-.nav_admin ul {
-    display: flex;
-}
-
 #top_nav_admin > div.edit-mode > ul {
     display: flex;
     flex-direction: row;
@@ -79,7 +75,6 @@ nav {
     display: flex;
 }
 
-
 #top_nav_admin {
     display: grid;
     flex-direction: row;
@@ -90,8 +85,13 @@ nav {
     -ms-border-radius: 4px;
     -khtml-border-radius: 4px;
     border-radius: 4px;
-    width: 940px;
+    width: 918px;  /* 940px - 32px for toggle-admin-btn */
 }
+
+#top_nav_admin .edit-mode .fa {
+    margin: 0 3px;
+}
+
 .btn-bar {
     display: block;
     clear: both;
@@ -127,51 +127,8 @@ li.tb-item-edit > input {
     width: 2.2rem;
 }
 
-li.tb-item-edit > label > i {
-    padding-right: 0.7rem;
-    color: grey;
-    font-size: larger;
-    cursor: move;
-}
-
-div.edit-mode > ul > div.anchored {
-    background: grey;
-}
-
-div.anchored > li.tb-item-edit > label > i {
-    padding-right: 0.7rem;
-    color: #898c89;
-    font-size: larger;
-    cursor: not-allowed;
-}
-
-.react-reorderable-item-active, .draggable-element {
-    height: 28px;
-    width: 120px;
-    margin-top: 5px;
-}
-
-.draggable-element {
-    background-color: rgb(255, 255, 255);
-    border: 1px dashed #B5AFAF;
-    min-width: 100%;
-    border-radius: 3px;
-    width: 9rem;
-    height: 30px;
-}
-
 .draggable-handle {
-    background-color: rgb(126, 125, 125);
-    width: 15%;
-    height: 80%;
-    border-radius: 4px 0 0 4px;
-    margin-top: -2px;
-    margin-left: -2px;
-    z-index: 10000;
     cursor: move;
-    color: white;
-    padding: 3px 3px 4px;
-    border: 1px solid #575656;
 }
 
 ul.dropdown li {
@@ -188,14 +145,14 @@ ul.dropdown li {
 
 .react-reorderable-item {
     display: inline-flex;
-    margin-right: 2%;
-    /* float: left; */
+    float: left;
 }
 
 .react-reorderable-item-active {
     border: 3px dashed #9e9e9e;
     background: #c9c9c9;
-    width: 9rem;
+    width: 5rem; /* dynamic would be nice */
+    height: 50px;
 }
 
 .react-reorderable-item-active div {
@@ -206,23 +163,8 @@ ul.dropdown li {
     position: absolute;
 }
 
-.react-drag > div > div > div > div > div > a {
-    margin-top: 2px;
-    text-align: center;
-    color: #898989;
-    width: 5rem;
-    /* margin-bottom: 10px; */
-    min-width: 100%;
-    overflow-x: hidden;
-    overflow-wrap: break-word;
-    height: 18px;
-    position: relative;
-}
-
-.react-drag > div > div > div > div > div {
-    width: 100%;
-    position: relative;
-    right: -40px;
+#top_nav_admin .tb-item a {
+    margin: 10px;
 }
 
 .react-drag {
@@ -243,13 +185,6 @@ ul.dropdown ul {
     border-top-width: 0;
 }
 
-ul.dropdown ul li a {
-    float: none;
-    display: block;
-    text-align: left;
-    margin-right: 0;
-}
-
 ul.dropdown .hover, ul.dropdown li:hover {
     position: relative;
     z-index: 599;
@@ -258,10 +193,7 @@ ul.dropdown .hover, ul.dropdown li:hover {
 
 .anchored {
     cursor: not-allowed;
-}
-
-#add_tool_menu{
-    position: relative;
+    color: gray;
 }
 
 .tool-partition {
@@ -271,42 +203,35 @@ ul.dropdown .hover, ul.dropdown li:hover {
 }
 
 .installable-tool-box {
-    /* margin: 0 0 15px 50px; */
     list-style: none;
     display: flex;
     background-color: #FFFEFA;
     flex-wrap: wrap;
-    margin-bottom: 0;
-    margin-left: 0;
     justify-content: space-around;
+    margin-left: 0;
+    margin-bottom: 8px;
+    margin-top: -8px;
 }
 
 .installable-tool-box li {
-    /* margin: 5px 10px 20px 60px; */
-    /* margin-left: 80px; */
-    margin-top: 5px;
-    clear: both;
+    margin-top: 15px;
     height: auto;
     border-radius: 4px;
-    /* vertical-align: middle; */
-    /* padding-bottom:10px; */
     padding: 10px;
     text-align: center;
     font-size: medium;
     list-style: none;
     cursor: pointer;
-        border: 1px solid transparent;
-        -webkit-user-select: none;
+    border: 1px solid transparent;
+    -webkit-user-select: none;
     -moz-user-select: none;
     -ms-user-select: none;
     -o-user-select: none;
     user-select: none;
-
 }
 .selected-tool{
     background: #09C;
     color: white;
-
 }
 
 .installable-tool-box li:hover {
@@ -314,8 +239,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     border: 1px solid #09C;
 }
 
-
-
 .installable-tool-box li.selected-tool:hover {
     background: white;
     color: rgb(85, 85, 85);
@@ -329,14 +252,14 @@ ul.dropdown .hover, ul.dropdown li:hover {
     overflow-y: visible;
     margin-bottom: 50px;
     background: white;
-    right: 22px;
-    top: 94px;
+    right: 161px;
+    top: 83px;
     position: absolute;
     z-index: 1000;
 }
 
 .tool-card::before {
-    content: "▲";/* left point triangle in escaped unicode */
+    content: "▲";
     color: #4E4E4E;
     font-size: xx-large;
     position: absolute;
@@ -344,7 +267,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     top: -14px;
     overflow: visible;
     float: right;
-    /* position: relative; */
     height: 1.5rem;
 }
 
@@ -362,8 +284,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
 
 .tool-info {
     min-height: 15rem;
-    /* padding: 35px 5px 5px 10px; */
-    /* background-color: #40AFD4; */
     display: block;
     clear: both;
 }
@@ -373,12 +293,9 @@ ul.dropdown .hover, ul.dropdown li:hover {
     vertical-align: text-top;
     padding-top: 0;
     left: 0;
-    /* text-shadow: 1px 2px 1px  #444; */
     font-size: large;
     font-weight: 400;
-    margin: 2rem;
-    margin-left: 33px;
-    margin-right: 33px;
+    margin: 2rem 33px;
     color: #CCCBC8;
     padding-bottom: 20px;
 }
@@ -388,7 +305,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     padding-bottom: 0;
     vertical-align: text-top;
     padding-top: 18px;
-    /* text-shadow: 1px 2px 1px #C8C8C8; */
     left: 0;
     font-size: large;
     background-color: #AEF4FF;
@@ -407,7 +323,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     right: -30px;
 }
 
-
 .tool-info-left {
     background: #636363;
     width: 60%;
@@ -427,16 +342,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     top: 0;
 }
 
-.tool-info-right form {
-
-    /* display: grid; */
-    /* position: relative; */
-    /* padding-top: 30px; */
-
-
-
-}
-
 .tool-form {
     display: inline-block;
     width: 100%;
@@ -468,10 +373,7 @@ ul.dropdown .hover, ul.dropdown li:hover {
 
 #add-tool-form{
     padding-top: 20px;
-    /* clear: both; */
     padding-left: 25px;
-    /* width: 20%; */
-    /* display: block; */
     padding-right: 25px;
 }
 
@@ -490,18 +392,13 @@ ul.dropdown .hover, ul.dropdown li:hover {
     background: rgba(255, 255, 255, 0.32);
     clear: both;
     float: right;
-    /* font-size: x-large; */
-    color: #777;
+    color: #B3B3B3;
     font-weight: 900;
-    /* position: absolute; */
-    padding: 3px;
     margin: 1px;
-    padding-top: 5px;
     right: 127px;
     position: absolute;
-    padding-left: 5px;
-    padding-right: 5px;
-    border: 2px dashed #777;
+    padding: 5px 5px 3px;
+    border: 2px dashed #B3B3B3;
     top: 18px;
     width: 5.7rem;
     border-radius: 4px;
@@ -515,5 +412,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
 }
 .add-tool-toggle:hover{
     background: #F4F4F4;
+    color: #777;
 }
 

http://git-wip-us.apache.org/repos/asf/allura/blob/7621027f/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index 8aae568..791efd9 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -24,9 +24,9 @@ function slugify(text)
 }
 
 /**
- * Get a tool label from a NavBarItem node.
+ * Get a mount point from a NavBarItem node.
  * @constructor
- * @param {NavBarItem} node - Return a "rest" version of the url.
+ * @param {NavBarItem} node
  * @returns {string}
  */
 function getMountPoint(node) {
@@ -52,26 +52,6 @@ function ToolsPropType() {
     };
 }
 
-/**
- * A NavBar link, the most basic component of the NavBar.
- * @constructor
- */
-var NavLink = React.createClass({
-    propTypes: {
-        name: React.PropTypes.string.isRequired,
-        url: React.PropTypes.string.isRequired,
-        style: React.PropTypes.object
-    },
-    render: function () {
-        var classes = this.props.subMenu ? ' subMenu' : '';
-        classes += this.props.classes;
-        return (
-            <a href={ this.props.url } key={ `link-${_.uniqueId()}` } className={ classes } style={ this.props.style }>
-                { this.props.name }
-            </a> // jshint ignore:line
-        );
-    }
-});
 
 /**
  * When the number of tools of the same type exceeds the grouping threshold,
@@ -83,7 +63,6 @@ var ToolSubMenu = React.createClass({
         isSubmenu: React.PropTypes.bool,
         tools: ToolsPropType
     },
-    handle: '.draggable-handle',
     mode: 'list',
     render: function () {
         var _this = this;
@@ -92,7 +71,7 @@ var ToolSubMenu = React.createClass({
             return (
                 <div className={ 'draggable-element ' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
                     <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
-                        <NavBarItem data={ item } name={ item.mount_point } url={ item.url } data-id={ i }/>
+                        <NavBarItem data={ item } name={ item.mount_point } url={ item.url }/>
                     </div>
                 </div>
             );
@@ -110,7 +89,7 @@ var ToolSubMenu = React.createClass({
 });
 
 /**
- * A single NavBar item. (A wrapper for NavLink).
+ * A single NavBar item.
  * @constructor
  */
 var NavBarItem = React.createClass({
@@ -118,11 +97,19 @@ var NavBarItem = React.createClass({
         name: React.PropTypes.string.isRequired,
         url: React.PropTypes.string.isRequired,
         isSubmenu: React.PropTypes.bool,
-        children: React.PropTypes.array.isRequired,
+        children: React.PropTypes.array,
         tools: ToolsPropType
     },
-    generateLink: function () {
-        return <NavLink url={ this.props.url } name={ this.props.name } key={ _.uniqueId() }/>;
+    generateItem: function () {
+        var controls = [<i className='config-tool fa fa-cog'></i>];
+        var arrow_classes = 'fa fa-arrows-h'
+        if (this.props.is_anchored) {
+            arrow_classes += ' anchored';
+        } else {
+            arrow_classes += ' draggable-handle';
+        }
+        controls.push(<i className={arrow_classes}></i>);
+        return <a>{ this.props.name }<br/>{ controls }</a>
     },
 
     generateSubmenu: function () {
@@ -130,7 +117,7 @@ var NavBarItem = React.createClass({
     },
 
     generateContent: function () {
-        var content = [this.generateLink()];
+        var content = [this.generateItem()];
         if (this.props.children) {
             content.push(this.generateSubmenu());
         }
@@ -140,10 +127,7 @@ var NavBarItem = React.createClass({
 
     render: function () {
         var content = this.generateContent();
-        var classes = this.props.editMode ? 'tb-item tb-item-edit' : 'tb-item';
-        classes = this.props.is_anchored ? `${classes} anchored` : classes;
-
-
+        var classes = 'tb-item tb-item-edit';
         return (
             <div className={ classes }>
                 { content }
@@ -200,7 +184,6 @@ var GroupingThreshold = React.createClass({
 var NormalNavBar = React.createClass({
     buildMenu: function (item) {
         var classes = ` ui-icon-${item.icon}-32`;
-        classes = item.is_anchored ? `${classes} anchored` : classes;
 
         var subMenu;
         if (item.children) {
@@ -240,7 +223,6 @@ var AdminNav = React.createClass({
         isSubmenu: React.PropTypes.bool,
         tools: ToolsPropType
     },
-    handle: '.draggable-handle',
     mode: 'grid',
     getInitialState: function () {
         return {
@@ -263,24 +245,34 @@ var AdminNav = React.createClass({
     render: function () {
         var _this = this;
         var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
-        var tools = this.props.tools.map(function (item, i) {
-            return (
+        var tools = [], anchored_tools = [], end_tools = [];
+        this.props.tools.forEach(function (item) {
+            var core_item = <NavBarItem onMouseOver={ _this.mouseOver } onMouseOut={ _this.mouseOut } {..._this.props} data={ item }
+                                mount_point={ item.mount_point }
+                                name={ item.name } url={ item.url }
+                                key={ 'tb-item-' + _.uniqueId() } is_anchored={ item.is_anchored || item.mount_point === 'admin'}/>;
+            if (item.mount_point === 'admin') {
+                // force admin to end, just like 'Project.sitemap()' does
+                end_tools.push(core_item);
+            } else if (item.is_anchored) {
+                anchored_tools.push(core_item);
+            } else {
+                tools.push(
                 <div className={ 'draggable-element' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
-                    <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
-                        <NavBarItem onMouseOver={ _this.mouseOver } onMouseOut={ _this.mouseOut } {..._this.props} data={ item }
-                                    name={ item.mount_point } url={ item.url }
-                                    key={ 'tb-item-' + _.uniqueId() } is_anchored={ item.is_anchored } data-id={ i }/>
+                        { core_item }
                     </div>
-                </div>
             );
+            }
         });
 
         return (
             <div className='react-drag edit-mode'>
+                { anchored_tools }
                 <ReactReorderable key={ 'reorder-' + _.uniqueId() } handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart }
                                   onDrop={ this.props.onToolReorder } onChange={ this.onChange }>
                     { tools }
                 </ReactReorderable>
+                { end_tools }
             </div>
         );
     }
@@ -310,15 +302,10 @@ var ToggleAdminButton = React.createClass({
  */
 var ToggleAddNewTool = React.createClass({
     render: function () {
-        var classes = this.props.visible ? 'fa fa-unlock' : 'fa fa-lock';
         return (
             <div>
-                <div onClick={ this.props.handleToggleAddNewTool } className="add-tool-toggle">
-                    + Add new...
-                </div>
-                                {this.props.showMenu &&
-                <NewToolMain />
-                }
+                <div onClick={ this.props.handleToggleAddNewTool } className="add-tool-toggle"> + Add new...</div>
+                {this.props.showMenu && <NewToolMain />}
             </div>
         );
     }
@@ -567,7 +554,6 @@ var NewToolMain = React.createClass({
     toolFormIsValid: function (e) {
         e.preventDefault();
 
-        var isValid = true;
         var errors = {
             mount_point: []
         };
@@ -743,22 +729,14 @@ var Main = React.createClass({
         var navBarSwitch = (showAdmin) => {
             if (showAdmin) {
                 return (
-                    <AdminNav tools={ _this.state.data.children }
-                              data={ _this.state.data }
-                              onToolReorder={ _this.onToolReorder }
-                              onUpdateMountOrder={ _this.onUpdateMountOrder }
-                              editMode={ _this.state.visible }
-                        />
+                    <AdminNav tools={ _this.state.data.children } data={ _this.state.data } onToolReorder={ _this.onToolReorder }
+                              onUpdateMountOrder={ _this.onUpdateMountOrder } editMode={ _this.state.visible } />
                 );
             } else {
                 return (
                     <div>
                         <NormalNavBar items={ _this.state.data.children } key={ `normalNav-${_.uniqueId()}` }/>
-
-                        <ToggleAddNewTool
-                            handleToggleAddNewTool={this.handleToggleAddNewTool}
-                            showMenu={this.state.showAddToolMenu}
-                            />
+                        <ToggleAddNewTool handleToggleAddNewTool={this.handleToggleAddNewTool} showMenu={this.state.showAddToolMenu} />
                     </div>
                 )
             }
@@ -769,14 +747,10 @@ var Main = React.createClass({
             <div ref={ _.uniqueId() } className={ 'nav_admin ' + editMode }>
                 { navBar }
                 <div id='bar-config'>
-                    <GroupingThreshold onUpdateThreshold={ this.onUpdateThreshold } isHidden={ this.state.visible }
-                                       initialValue={ this.state.data.grouping_threshold }/>
+                    <GroupingThreshold onUpdateThreshold={ this.onUpdateThreshold } isHidden={ this.state.visible } initialValue={ this.state.data.grouping_threshold }/>
                 </div>
                 <ToggleAdminButton key={ _.uniqueId() } handleButtonPush={ this.handleToggleAdmin } visible={ this.state.visible }/>
             </div>
         );
     }
 });
-   //
-   //React.render(React.createElement(NewToolMain, {
-   //     }), document.getElementById("add_tool_menu"));
\ No newline at end of file


[34/47] allura git commit: [#7919] Add react for development mode

Posted by br...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/394e8b7b/Allura/allura/public/nf/js/react-with-addons.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/react-with-addons.js b/Allura/allura/public/nf/js/react-with-addons.js
new file mode 100644
index 0000000..c1578b7
--- /dev/null
+++ b/Allura/allura/public/nf/js/react-with-addons.js
@@ -0,0 +1,21642 @@
+/**
+ * React (with addons) v0.13.3
+ */
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactWithAddons
+ */
+
+/**
+ * This module exists purely in the open source project, and is meant as a way
+ * to create a separate standalone build of React. This build has "addons", or
+ * functionality we've built and think might be useful but doesn't have a good
+ * place to live inside React core.
+ */
+
+'use strict';
+
+var LinkedStateMixin = _dereq_(25);
+var React = _dereq_(31);
+var ReactComponentWithPureRenderMixin =
+  _dereq_(42);
+var ReactCSSTransitionGroup = _dereq_(34);
+var ReactFragment = _dereq_(69);
+var ReactTransitionGroup = _dereq_(98);
+var ReactUpdates = _dereq_(100);
+
+var cx = _dereq_(127);
+var cloneWithProps = _dereq_(122);
+var update = _dereq_(170);
+
+React.addons = {
+  CSSTransitionGroup: ReactCSSTransitionGroup,
+  LinkedStateMixin: LinkedStateMixin,
+  PureRenderMixin: ReactComponentWithPureRenderMixin,
+  TransitionGroup: ReactTransitionGroup,
+
+  batchedUpdates: ReactUpdates.batchedUpdates,
+  classSet: cx,
+  cloneWithProps: cloneWithProps,
+  createFragment: ReactFragment.create,
+  update: update
+};
+
+if ("production" !== "development") {
+  React.addons.Perf = _dereq_(61);
+  React.addons.TestUtils = _dereq_(95);
+}
+
+module.exports = React;
+
+},{"100":100,"122":122,"127":127,"170":170,"25":25,"31":31,"34":34,"42":42,"61":61,"69":69,"95":95,"98":98}],2:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule AutoFocusMixin
+ * @typechecks static-only
+ */
+
+'use strict';
+
+var focusNode = _dereq_(134);
+
+var AutoFocusMixin = {
+  componentDidMount: function() {
+    if (this.props.autoFocus) {
+      focusNode(this.getDOMNode());
+    }
+  }
+};
+
+module.exports = AutoFocusMixin;
+
+},{"134":134}],3:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015 Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule BeforeInputEventPlugin
+ * @typechecks static-only
+ */
+
+'use strict';
+
+var EventConstants = _dereq_(16);
+var EventPropagators = _dereq_(21);
+var ExecutionEnvironment = _dereq_(22);
+var FallbackCompositionState = _dereq_(23);
+var SyntheticCompositionEvent = _dereq_(106);
+var SyntheticInputEvent = _dereq_(110);
+
+var keyOf = _dereq_(157);
+
+var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
+var START_KEYCODE = 229;
+
+var canUseCompositionEvent = (
+  ExecutionEnvironment.canUseDOM &&
+  'CompositionEvent' in window
+);
+
+var documentMode = null;
+if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
+  documentMode = document.documentMode;
+}
+
+// Webkit offers a very useful `textInput` event that can be used to
+// directly represent `beforeInput`. The IE `textinput` event is not as
+// useful, so we don't use it.
+var canUseTextInputEvent = (
+  ExecutionEnvironment.canUseDOM &&
+  'TextEvent' in window &&
+  !documentMode &&
+  !isPresto()
+);
+
+// In IE9+, we have access to composition events, but the data supplied
+// by the native compositionend event may be incorrect. Japanese ideographic
+// spaces, for instance (\u3000) are not recorded correctly.
+var useFallbackCompositionData = (
+  ExecutionEnvironment.canUseDOM &&
+  (
+    (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11)
+  )
+);
+
+/**
+ * Opera <= 12 includes TextEvent in window, but does not fire
+ * text input events. Rely on keypress instead.
+ */
+function isPresto() {
+  var opera = window.opera;
+  return (
+    typeof opera === 'object' &&
+    typeof opera.version === 'function' &&
+    parseInt(opera.version(), 10) <= 12
+  );
+}
+
+var SPACEBAR_CODE = 32;
+var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
+
+var topLevelTypes = EventConstants.topLevelTypes;
+
+// Events and their corresponding property names.
+var eventTypes = {
+  beforeInput: {
+    phasedRegistrationNames: {
+      bubbled: keyOf({onBeforeInput: null}),
+      captured: keyOf({onBeforeInputCapture: null})
+    },
+    dependencies: [
+      topLevelTypes.topCompositionEnd,
+      topLevelTypes.topKeyPress,
+      topLevelTypes.topTextInput,
+      topLevelTypes.topPaste
+    ]
+  },
+  compositionEnd: {
+    phasedRegistrationNames: {
+      bubbled: keyOf({onCompositionEnd: null}),
+      captured: keyOf({onCompositionEndCapture: null})
+    },
+    dependencies: [
+      topLevelTypes.topBlur,
+      topLevelTypes.topCompositionEnd,
+      topLevelTypes.topKeyDown,
+      topLevelTypes.topKeyPress,
+      topLevelTypes.topKeyUp,
+      topLevelTypes.topMouseDown
+    ]
+  },
+  compositionStart: {
+    phasedRegistrationNames: {
+      bubbled: keyOf({onCompositionStart: null}),
+      captured: keyOf({onCompositionStartCapture: null})
+    },
+    dependencies: [
+      topLevelTypes.topBlur,
+      topLevelTypes.topCompositionStart,
+      topLevelTypes.topKeyDown,
+      topLevelTypes.topKeyPress,
+      topLevelTypes.topKeyUp,
+      topLevelTypes.topMouseDown
+    ]
+  },
+  compositionUpdate: {
+    phasedRegistrationNames: {
+      bubbled: keyOf({onCompositionUpdate: null}),
+      captured: keyOf({onCompositionUpdateCapture: null})
+    },
+    dependencies: [
+      topLevelTypes.topBlur,
+      topLevelTypes.topCompositionUpdate,
+      topLevelTypes.topKeyDown,
+      topLevelTypes.topKeyPress,
+      topLevelTypes.topKeyUp,
+      topLevelTypes.topMouseDown
+    ]
+  }
+};
+
+// Track whether we've ever handled a keypress on the space key.
+var hasSpaceKeypress = false;
+
+/**
+ * Return whether a native keypress event is assumed to be a command.
+ * This is required because Firefox fires `keypress` events for key commands
+ * (cut, copy, select-all, etc.) even though no character is inserted.
+ */
+function isKeypressCommand(nativeEvent) {
+  return (
+    (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
+    // ctrlKey && altKey is equivalent to AltGr, and is not a command.
+    !(nativeEvent.ctrlKey && nativeEvent.altKey)
+  );
+}
+
+
+/**
+ * Translate native top level events into event types.
+ *
+ * @param {string} topLevelType
+ * @return {object}
+ */
+function getCompositionEventType(topLevelType) {
+  switch (topLevelType) {
+    case topLevelTypes.topCompositionStart:
+      return eventTypes.compositionStart;
+    case topLevelTypes.topCompositionEnd:
+      return eventTypes.compositionEnd;
+    case topLevelTypes.topCompositionUpdate:
+      return eventTypes.compositionUpdate;
+  }
+}
+
+/**
+ * Does our fallback best-guess model think this event signifies that
+ * composition has begun?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionStart(topLevelType, nativeEvent) {
+  return (
+    topLevelType === topLevelTypes.topKeyDown &&
+    nativeEvent.keyCode === START_KEYCODE
+  );
+}
+
+/**
+ * Does our fallback mode think that this event is the end of composition?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionEnd(topLevelType, nativeEvent) {
+  switch (topLevelType) {
+    case topLevelTypes.topKeyUp:
+      // Command keys insert or clear IME input.
+      return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1);
+    case topLevelTypes.topKeyDown:
+      // Expect IME keyCode on each keydown. If we get any other
+      // code we must have exited earlier.
+      return (nativeEvent.keyCode !== START_KEYCODE);
+    case topLevelTypes.topKeyPress:
+    case topLevelTypes.topMouseDown:
+    case topLevelTypes.topBlur:
+      // Events are not possible without cancelling IME.
+      return true;
+    default:
+      return false;
+  }
+}
+
+/**
+ * Google Input Tools provides composition data via a CustomEvent,
+ * with the `data` property populated in the `detail` object. If this
+ * is available on the event object, use it. If not, this is a plain
+ * composition event and we have nothing special to extract.
+ *
+ * @param {object} nativeEvent
+ * @return {?string}
+ */
+function getDataFromCustomEvent(nativeEvent) {
+  var detail = nativeEvent.detail;
+  if (typeof detail === 'object' && 'data' in detail) {
+    return detail.data;
+  }
+  return null;
+}
+
+// Track the current IME composition fallback object, if any.
+var currentComposition = null;
+
+/**
+ * @param {string} topLevelType Record from `EventConstants`.
+ * @param {DOMEventTarget} topLevelTarget The listening component root node.
+ * @param {string} topLevelTargetID ID of `topLevelTarget`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?object} A SyntheticCompositionEvent.
+ */
+function extractCompositionEvent(
+  topLevelType,
+  topLevelTarget,
+  topLevelTargetID,
+  nativeEvent
+) {
+  var eventType;
+  var fallbackData;
+
+  if (canUseCompositionEvent) {
+    eventType = getCompositionEventType(topLevelType);
+  } else if (!currentComposition) {
+    if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
+      eventType = eventTypes.compositionStart;
+    }
+  } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
+    eventType = eventTypes.compositionEnd;
+  }
+
+  if (!eventType) {
+    return null;
+  }
+
+  if (useFallbackCompositionData) {
+    // The current composition is stored statically and must not be
+    // overwritten while composition continues.
+    if (!currentComposition && eventType === eventTypes.compositionStart) {
+      currentComposition = FallbackCompositionState.getPooled(topLevelTarget);
+    } else if (eventType === eventTypes.compositionEnd) {
+      if (currentComposition) {
+        fallbackData = currentComposition.getData();
+      }
+    }
+  }
+
+  var event = SyntheticCompositionEvent.getPooled(
+    eventType,
+    topLevelTargetID,
+    nativeEvent
+  );
+
+  if (fallbackData) {
+    // Inject data generated from fallback path into the synthetic event.
+    // This matches the property of native CompositionEventInterface.
+    event.data = fallbackData;
+  } else {
+    var customData = getDataFromCustomEvent(nativeEvent);
+    if (customData !== null) {
+      event.data = customData;
+    }
+  }
+
+  EventPropagators.accumulateTwoPhaseDispatches(event);
+  return event;
+}
+
+/**
+ * @param {string} topLevelType Record from `EventConstants`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The string corresponding to this `beforeInput` event.
+ */
+function getNativeBeforeInputChars(topLevelType, nativeEvent) {
+  switch (topLevelType) {
+    case topLevelTypes.topCompositionEnd:
+      return getDataFromCustomEvent(nativeEvent);
+    case topLevelTypes.topKeyPress:
+      /**
+       * If native `textInput` events are available, our goal is to make
+       * use of them. However, there is a special case: the spacebar key.
+       * In Webkit, preventing default on a spacebar `textInput` event
+       * cancels character insertion, but it *also* causes the browser
+       * to fall back to its default spacebar behavior of scrolling the
+       * page.
+       *
+       * Tracking at:
+       * https://code.google.com/p/chromium/issues/detail?id=355103
+       *
+       * To avoid this issue, use the keypress event as if no `textInput`
+       * event is available.
+       */
+      var which = nativeEvent.which;
+      if (which !== SPACEBAR_CODE) {
+        return null;
+      }
+
+      hasSpaceKeypress = true;
+      return SPACEBAR_CHAR;
+
+    case topLevelTypes.topTextInput:
+      // Record the characters to be added to the DOM.
+      var chars = nativeEvent.data;
+
+      // If it's a spacebar character, assume that we have already handled
+      // it at the keypress level and bail immediately. Android Chrome
+      // doesn't give us keycodes, so we need to blacklist it.
+      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
+        return null;
+      }
+
+      return chars;
+
+    default:
+      // For other native event types, do nothing.
+      return null;
+  }
+}
+
+/**
+ * For browsers that do not provide the `textInput` event, extract the
+ * appropriate string to use for SyntheticInputEvent.
+ *
+ * @param {string} topLevelType Record from `EventConstants`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The fallback string for this `beforeInput` event.
+ */
+function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
+  // If we are currently composing (IME) and using a fallback to do so,
+  // try to extract the composed characters from the fallback object.
+  if (currentComposition) {
+    if (
+      topLevelType === topLevelTypes.topCompositionEnd ||
+      isFallbackCompositionEnd(topLevelType, nativeEvent)
+    ) {
+      var chars = currentComposition.getData();
+      FallbackCompositionState.release(currentComposition);
+      currentComposition = null;
+      return chars;
+    }
+    return null;
+  }
+
+  switch (topLevelType) {
+    case topLevelTypes.topPaste:
+      // If a paste event occurs after a keypress, throw out the input
+      // chars. Paste events should not lead to BeforeInput events.
+      return null;
+    case topLevelTypes.topKeyPress:
+      /**
+       * As of v27, Firefox may fire keypress events even when no character
+       * will be inserted. A few possibilities:
+       *
+       * - `which` is `0`. Arrow keys, Esc key, etc.
+       *
+       * - `which` is the pressed key code, but no char is available.
+       *   Ex: 'AltGr + d` in Polish. There is no modified character for
+       *   this key combination and no character is inserted into the
+       *   document, but FF fires the keypress for char code `100` anyway.
+       *   No `input` event will occur.
+       *
+       * - `which` is the pressed key code, but a command combination is
+       *   being used. Ex: `Cmd+C`. No character is inserted, and no
+       *   `input` event will occur.
+       */
+      if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
+        return String.fromCharCode(nativeEvent.which);
+      }
+      return null;
+    case topLevelTypes.topCompositionEnd:
+      return useFallbackCompositionData ? null : nativeEvent.data;
+    default:
+      return null;
+  }
+}
+
+/**
+ * Extract a SyntheticInputEvent for `beforeInput`, based on either native
+ * `textInput` or fallback behavior.
+ *
+ * @param {string} topLevelType Record from `EventConstants`.
+ * @param {DOMEventTarget} topLevelTarget The listening component root node.
+ * @param {string} topLevelTargetID ID of `topLevelTarget`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?object} A SyntheticInputEvent.
+ */
+function extractBeforeInputEvent(
+  topLevelType,
+  topLevelTarget,
+  topLevelTargetID,
+  nativeEvent
+) {
+  var chars;
+
+  if (canUseTextInputEvent) {
+    chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
+  } else {
+    chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
+  }
+
+  // If no characters are being inserted, no BeforeInput event should
+  // be fired.
+  if (!chars) {
+    return null;
+  }
+
+  var event = SyntheticInputEvent.getPooled(
+    eventTypes.beforeInput,
+    topLevelTargetID,
+    nativeEvent
+  );
+
+  event.data = chars;
+  EventPropagators.accumulateTwoPhaseDispatches(event);
+  return event;
+}
+
+/**
+ * Create an `onBeforeInput` event to match
+ * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
+ *
+ * This event plugin is based on the native `textInput` event
+ * available in Chrome, Safari, Opera, and IE. This event fires after
+ * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
+ *
+ * `beforeInput` is spec'd but not implemented in any browsers, and
+ * the `input` event does not provide any useful information about what has
+ * actually been added, contrary to the spec. Thus, `textInput` is the best
+ * available event to identify the characters that have actually been inserted
+ * into the target node.
+ *
+ * This plugin is also responsible for emitting `composition` events, thus
+ * allowing us to share composition fallback code for both `beforeInput` and
+ * `composition` event types.
+ */
+var BeforeInputEventPlugin = {
+
+  eventTypes: eventTypes,
+
+  /**
+   * @param {string} topLevelType Record from `EventConstants`.
+   * @param {DOMEventTarget} topLevelTarget The listening component root node.
+   * @param {string} topLevelTargetID ID of `topLevelTarget`.
+   * @param {object} nativeEvent Native browser event.
+   * @return {*} An accumulation of synthetic events.
+   * @see {EventPluginHub.extractEvents}
+   */
+  extractEvents: function(
+    topLevelType,
+    topLevelTarget,
+    topLevelTargetID,
+    nativeEvent
+  ) {
+    return [
+      extractCompositionEvent(
+        topLevelType,
+        topLevelTarget,
+        topLevelTargetID,
+        nativeEvent
+      ),
+      extractBeforeInputEvent(
+        topLevelType,
+        topLevelTarget,
+        topLevelTargetID,
+        nativeEvent
+      )
+    ];
+  }
+};
+
+module.exports = BeforeInputEventPlugin;
+
+},{"106":106,"110":110,"157":157,"16":16,"21":21,"22":22,"23":23}],4:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule CSSCore
+ * @typechecks
+ */
+
+var invariant = _dereq_(150);
+
+/**
+ * The CSSCore module specifies the API (and implements most of the methods)
+ * that should be used when dealing with the display of elements (via their
+ * CSS classes and visibility on screen. It is an API focused on mutating the
+ * display and not reading it as no logical state should be encoded in the
+ * display of elements.
+ */
+
+var CSSCore = {
+
+  /**
+   * Adds the class passed in to the element if it doesn't already have it.
+   *
+   * @param {DOMElement} element the element to set the class on
+   * @param {string} className the CSS className
+   * @return {DOMElement} the element passed in
+   */
+  addClass: function(element, className) {
+    ("production" !== "development" ? invariant(
+      !/\s/.test(className),
+      'CSSCore.addClass takes only a single class name. "%s" contains ' +
+      'multiple classes.', className
+    ) : invariant(!/\s/.test(className)));
+
+    if (className) {
+      if (element.classList) {
+        element.classList.add(className);
+      } else if (!CSSCore.hasClass(element, className)) {
+        element.className = element.className + ' ' + className;
+      }
+    }
+    return element;
+  },
+
+  /**
+   * Removes the class passed in from the element
+   *
+   * @param {DOMElement} element the element to set the class on
+   * @param {string} className the CSS className
+   * @return {DOMElement} the element passed in
+   */
+  removeClass: function(element, className) {
+    ("production" !== "development" ? invariant(
+      !/\s/.test(className),
+      'CSSCore.removeClass takes only a single class name. "%s" contains ' +
+      'multiple classes.', className
+    ) : invariant(!/\s/.test(className)));
+
+    if (className) {
+      if (element.classList) {
+        element.classList.remove(className);
+      } else if (CSSCore.hasClass(element, className)) {
+        element.className = element.className
+          .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1')
+          .replace(/\s+/g, ' ') // multiple spaces to one
+          .replace(/^\s*|\s*$/g, ''); // trim the ends
+      }
+    }
+    return element;
+  },
+
+  /**
+   * Helper to add or remove a class from an element based on a condition.
+   *
+   * @param {DOMElement} element the element to set the class on
+   * @param {string} className the CSS className
+   * @param {*} bool condition to whether to add or remove the class
+   * @return {DOMElement} the element passed in
+   */
+  conditionClass: function(element, className, bool) {
+    return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className);
+  },
+
+  /**
+   * Tests whether the element has the class specified.
+   *
+   * @param {DOMNode|DOMWindow} element the element to set the class on
+   * @param {string} className the CSS className
+   * @return {boolean} true if the element has the class, false if not
+   */
+  hasClass: function(element, className) {
+    ("production" !== "development" ? invariant(
+      !/\s/.test(className),
+      'CSS.hasClass takes only a single class name.'
+    ) : invariant(!/\s/.test(className)));
+    if (element.classList) {
+      return !!className && element.classList.contains(className);
+    }
+    return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1;
+  }
+
+};
+
+module.exports = CSSCore;
+
+},{"150":150}],5:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule CSSProperty
+ */
+
+'use strict';
+
+/**
+ * CSS properties which accept numbers but are not in units of "px".
+ */
+var isUnitlessNumber = {
+  boxFlex: true,
+  boxFlexGroup: true,
+  columnCount: true,
+  flex: true,
+  flexGrow: true,
+  flexPositive: true,
+  flexShrink: true,
+  flexNegative: true,
+  fontWeight: true,
+  lineClamp: true,
+  lineHeight: true,
+  opacity: true,
+  order: true,
+  orphans: true,
+  widows: true,
+  zIndex: true,
+  zoom: true,
+
+  // SVG-related properties
+  fillOpacity: true,
+  strokeDashoffset: true,
+  strokeOpacity: true,
+  strokeWidth: true
+};
+
+/**
+ * @param {string} prefix vendor-specific prefix, eg: Webkit
+ * @param {string} key style name, eg: transitionDuration
+ * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
+ * WebkitTransitionDuration
+ */
+function prefixKey(prefix, key) {
+  return prefix + key.charAt(0).toUpperCase() + key.substring(1);
+}
+
+/**
+ * Support style names that may come passed in prefixed by adding permutations
+ * of vendor prefixes.
+ */
+var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
+
+// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
+// infinite loop, because it iterates over the newly added props too.
+Object.keys(isUnitlessNumber).forEach(function(prop) {
+  prefixes.forEach(function(prefix) {
+    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
+  });
+});
+
+/**
+ * Most style properties can be unset by doing .style[prop] = '' but IE8
+ * doesn't like doing that with shorthand properties so for the properties that
+ * IE8 breaks on, which are listed here, we instead unset each of the
+ * individual properties. See http://bugs.jquery.com/ticket/12385.
+ * The 4-value 'clock' properties like margin, padding, border-width seem to
+ * behave without any problems. Curiously, list-style works too without any
+ * special prodding.
+ */
+var shorthandPropertyExpansions = {
+  background: {
+    backgroundImage: true,
+    backgroundPosition: true,
+    backgroundRepeat: true,
+    backgroundColor: true
+  },
+  border: {
+    borderWidth: true,
+    borderStyle: true,
+    borderColor: true
+  },
+  borderBottom: {
+    borderBottomWidth: true,
+    borderBottomStyle: true,
+    borderBottomColor: true
+  },
+  borderLeft: {
+    borderLeftWidth: true,
+    borderLeftStyle: true,
+    borderLeftColor: true
+  },
+  borderRight: {
+    borderRightWidth: true,
+    borderRightStyle: true,
+    borderRightColor: true
+  },
+  borderTop: {
+    borderTopWidth: true,
+    borderTopStyle: true,
+    borderTopColor: true
+  },
+  font: {
+    fontStyle: true,
+    fontVariant: true,
+    fontWeight: true,
+    fontSize: true,
+    lineHeight: true,
+    fontFamily: true
+  }
+};
+
+var CSSProperty = {
+  isUnitlessNumber: isUnitlessNumber,
+  shorthandPropertyExpansions: shorthandPropertyExpansions
+};
+
+module.exports = CSSProperty;
+
+},{}],6:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule CSSPropertyOperations
+ * @typechecks static-only
+ */
+
+'use strict';
+
+var CSSProperty = _dereq_(5);
+var ExecutionEnvironment = _dereq_(22);
+
+var camelizeStyleName = _dereq_(121);
+var dangerousStyleValue = _dereq_(128);
+var hyphenateStyleName = _dereq_(148);
+var memoizeStringOnly = _dereq_(159);
+var warning = _dereq_(171);
+
+var processStyleName = memoizeStringOnly(function(styleName) {
+  return hyphenateStyleName(styleName);
+});
+
+var styleFloatAccessor = 'cssFloat';
+if (ExecutionEnvironment.canUseDOM) {
+  // IE8 only supports accessing cssFloat (standard) as styleFloat
+  if (document.documentElement.style.cssFloat === undefined) {
+    styleFloatAccessor = 'styleFloat';
+  }
+}
+
+if ("production" !== "development") {
+  // 'msTransform' is correct, but the other prefixes should be capitalized
+  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
+
+  // style values shouldn't contain a semicolon
+  var badStyleValueWithSemicolonPattern = /;\s*$/;
+
+  var warnedStyleNames = {};
+  var warnedStyleValues = {};
+
+  var warnHyphenatedStyleName = function(name) {
+    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
+      return;
+    }
+
+    warnedStyleNames[name] = true;
+    ("production" !== "development" ? warning(
+      false,
+      'Unsupported style property %s. Did you mean %s?',
+      name,
+      camelizeStyleName(name)
+    ) : null);
+  };
+
+  var warnBadVendoredStyleName = function(name) {
+    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
+      return;
+    }
+
+    warnedStyleNames[name] = true;
+    ("production" !== "development" ? warning(
+      false,
+      'Unsupported vendor-prefixed style property %s. Did you mean %s?',
+      name,
+      name.charAt(0).toUpperCase() + name.slice(1)
+    ) : null);
+  };
+
+  var warnStyleValueWithSemicolon = function(name, value) {
+    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
+      return;
+    }
+
+    warnedStyleValues[value] = true;
+    ("production" !== "development" ? warning(
+      false,
+      'Style property values shouldn\'t contain a semicolon. ' +
+      'Try "%s: %s" instead.',
+      name,
+      value.replace(badStyleValueWithSemicolonPattern, '')
+    ) : null);
+  };
+
+  /**
+   * @param {string} name
+   * @param {*} value
+   */
+  var warnValidStyle = function(name, value) {
+    if (name.indexOf('-') > -1) {
+      warnHyphenatedStyleName(name);
+    } else if (badVendoredStyleNamePattern.test(name)) {
+      warnBadVendoredStyleName(name);
+    } else if (badStyleValueWithSemicolonPattern.test(value)) {
+      warnStyleValueWithSemicolon(name, value);
+    }
+  };
+}
+
+/**
+ * Operations for dealing with CSS properties.
+ */
+var CSSPropertyOperations = {
+
+  /**
+   * Serializes a mapping of style properties for use as inline styles:
+   *
+   *   > createMarkupForStyles({width: '200px', height: 0})
+   *   "width:200px;height:0;"
+   *
+   * Undefined values are ignored so that declarative programming is easier.
+   * The result should be HTML-escaped before insertion into the DOM.
+   *
+   * @param {object} styles
+   * @return {?string}
+   */
+  createMarkupForStyles: function(styles) {
+    var serialized = '';
+    for (var styleName in styles) {
+      if (!styles.hasOwnProperty(styleName)) {
+        continue;
+      }
+      var styleValue = styles[styleName];
+      if ("production" !== "development") {
+        warnValidStyle(styleName, styleValue);
+      }
+      if (styleValue != null) {
+        serialized += processStyleName(styleName) + ':';
+        serialized += dangerousStyleValue(styleName, styleValue) + ';';
+      }
+    }
+    return serialized || null;
+  },
+
+  /**
+   * Sets the value for multiple styles on a node.  If a value is specified as
+   * '' (empty string), the corresponding style property will be unset.
+   *
+   * @param {DOMElement} node
+   * @param {object} styles
+   */
+  setValueForStyles: function(node, styles) {
+    var style = node.style;
+    for (var styleName in styles) {
+      if (!styles.hasOwnProperty(styleName)) {
+        continue;
+      }
+      if ("production" !== "development") {
+        warnValidStyle(styleName, styles[styleName]);
+      }
+      var styleValue = dangerousStyleValue(styleName, styles[styleName]);
+      if (styleName === 'float') {
+        styleName = styleFloatAccessor;
+      }
+      if (styleValue) {
+        style[styleName] = styleValue;
+      } else {
+        var expansion = CSSProperty.shorthandPropertyExpansions[styleName];
+        if (expansion) {
+          // Shorthand property that IE8 won't like unsetting, so unset each
+          // component to placate it
+          for (var individualStyleName in expansion) {
+            style[individualStyleName] = '';
+          }
+        } else {
+          style[styleName] = '';
+        }
+      }
+    }
+  }
+
+};
+
+module.exports = CSSPropertyOperations;
+
+},{"121":121,"128":128,"148":148,"159":159,"171":171,"22":22,"5":5}],7:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule CallbackQueue
+ */
+
+'use strict';
+
+var PooledClass = _dereq_(30);
+
+var assign = _dereq_(29);
+var invariant = _dereq_(150);
+
+/**
+ * A specialized pseudo-event module to help keep track of components waiting to
+ * be notified when their DOM representations are available for use.
+ *
+ * This implements `PooledClass`, so you should never need to instantiate this.
+ * Instead, use `CallbackQueue.getPooled()`.
+ *
+ * @class ReactMountReady
+ * @implements PooledClass
+ * @internal
+ */
+function CallbackQueue() {
+  this._callbacks = null;
+  this._contexts = null;
+}
+
+assign(CallbackQueue.prototype, {
+
+  /**
+   * Enqueues a callback to be invoked when `notifyAll` is invoked.
+   *
+   * @param {function} callback Invoked when `notifyAll` is invoked.
+   * @param {?object} context Context to call `callback` with.
+   * @internal
+   */
+  enqueue: function(callback, context) {
+    this._callbacks = this._callbacks || [];
+    this._contexts = this._contexts || [];
+    this._callbacks.push(callback);
+    this._contexts.push(context);
+  },
+
+  /**
+   * Invokes all enqueued callbacks and clears the queue. This is invoked after
+   * the DOM representation of a component has been created or updated.
+   *
+   * @internal
+   */
+  notifyAll: function() {
+    var callbacks = this._callbacks;
+    var contexts = this._contexts;
+    if (callbacks) {
+      ("production" !== "development" ? invariant(
+        callbacks.length === contexts.length,
+        'Mismatched list of contexts in callback queue'
+      ) : invariant(callbacks.length === contexts.length));
+      this._callbacks = null;
+      this._contexts = null;
+      for (var i = 0, l = callbacks.length; i < l; i++) {
+        callbacks[i].call(contexts[i]);
+      }
+      callbacks.length = 0;
+      contexts.length = 0;
+    }
+  },
+
+  /**
+   * Resets the internal queue.
+   *
+   * @internal
+   */
+  reset: function() {
+    this._callbacks = null;
+    this._contexts = null;
+  },
+
+  /**
+   * `PooledClass` looks for this.
+   */
+  destructor: function() {
+    this.reset();
+  }
+
+});
+
+PooledClass.addPoolingTo(CallbackQueue);
+
+module.exports = CallbackQueue;
+
+},{"150":150,"29":29,"30":30}],8:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ChangeEventPlugin
+ */
+
+'use strict';
+
+var EventConstants = _dereq_(16);
+var EventPluginHub = _dereq_(18);
+var EventPropagators = _dereq_(21);
+var ExecutionEnvironment = _dereq_(22);
+var ReactUpdates = _dereq_(100);
+var SyntheticEvent = _dereq_(108);
+
+var isEventSupported = _dereq_(151);
+var isTextInputElement = _dereq_(153);
+var keyOf = _dereq_(157);
+
+var topLevelTypes = EventConstants.topLevelTypes;
+
+var eventTypes = {
+  change: {
+    phasedRegistrationNames: {
+      bubbled: keyOf({onChange: null}),
+      captured: keyOf({onChangeCapture: null})
+    },
+    dependencies: [
+      topLevelTypes.topBlur,
+      topLevelTypes.topChange,
+      topLevelTypes.topClick,
+      topLevelTypes.topFocus,
+      topLevelTypes.topInput,
+      topLevelTypes.topKeyDown,
+      topLevelTypes.topKeyUp,
+      topLevelTypes.topSelectionChange
+    ]
+  }
+};
+
+/**
+ * For IE shims
+ */
+var activeElement = null;
+var activeElementID = null;
+var activeElementValue = null;
+var activeElementValueProp = null;
+
+/**
+ * SECTION: handle `change` event
+ */
+function shouldUseChangeEvent(elem) {
+  return (
+    elem.nodeName === 'SELECT' ||
+    (elem.nodeName === 'INPUT' && elem.type === 'file')
+  );
+}
+
+var doesChangeEventBubble = false;
+if (ExecutionEnvironment.canUseDOM) {
+  // See `handleChange` comment below
+  doesChangeEventBubble = isEventSupported('change') && (
+    (!('documentMode' in document) || document.documentMode > 8)
+  );
+}
+
+function manualDispatchChangeEvent(nativeEvent) {
+  var event = SyntheticEvent.getPooled(
+    eventTypes.change,
+    activeElementID,
+    nativeEvent
+  );
+  EventPropagators.accumulateTwoPhaseDispatches(event);
+
+  // If change and propertychange bubbled, we'd just bind to it like all the
+  // other events and have it go through ReactBrowserEventEmitter. Since it
+  // doesn't, we manually listen for the events and so we have to enqueue and
+  // process the abstract event manually.
+  //
+  // Batching is necessary here in order to ensure that all event handlers run
+  // before the next rerender (including event handlers attached to ancestor
+  // elements instead of directly on the input). Without this, controlled
+  // components don't work properly in conjunction with event bubbling because
+  // the component is rerendered and the value reverted before all the event
+  // handlers can run. See https://github.com/facebook/react/issues/708.
+  ReactUpdates.batchedUpdates(runEventInBatch, event);
+}
+
+function runEventInBatch(event) {
+  EventPluginHub.enqueueEvents(event);
+  EventPluginHub.processEventQueue();
+}
+
+function startWatchingForChangeEventIE8(target, targetID) {
+  activeElement = target;
+  activeElementID = targetID;
+  activeElement.attachEvent('onchange', manualDispatchChangeEvent);
+}
+
+function stopWatchingForChangeEventIE8() {
+  if (!activeElement) {
+    return;
+  }
+  activeElement.detachEvent('onchange', manualDispatchChangeEvent);
+  activeElement = null;
+  activeElementID = null;
+}
+
+function getTargetIDForChangeEvent(
+    topLevelType,
+    topLevelTarget,
+    topLevelTargetID) {
+  if (topLevelType === topLevelTypes.topChange) {
+    return topLevelTargetID;
+  }
+}
+function handleEventsForChangeEventIE8(
+    topLevelType,
+    topLevelTarget,
+    topLevelTargetID) {
+  if (topLevelType === topLevelTypes.topFocus) {
+    // stopWatching() should be a noop here but we call it just in case we
+    // missed a blur event somehow.
+    stopWatchingForChangeEventIE8();
+    startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID);
+  } else if (topLevelType === topLevelTypes.topBlur) {
+    stopWatchingForChangeEventIE8();
+  }
+}
+
+
+/**
+ * SECTION: handle `input` event
+ */
+var isInputEventSupported = false;
+if (ExecutionEnvironment.canUseDOM) {
+  // IE9 claims to support the input event but fails to trigger it when
+  // deleting text, so we ignore its input events
+  isInputEventSupported = isEventSupported('input') && (
+    (!('documentMode' in document) || document.documentMode > 9)
+  );
+}
+
+/**
+ * (For old IE.) Replacement getter/setter for the `value` property that gets
+ * set on the active element.
+ */
+var newValueProp =  {
+  get: function() {
+    return activeElementValueProp.get.call(this);
+  },
+  set: function(val) {
+    // Cast to a string so we can do equality checks.
+    activeElementValue = '' + val;
+    activeElementValueProp.set.call(this, val);
+  }
+};
+
+/**
+ * (For old IE.) Starts tracking propertychange events on the passed-in element
+ * and override the value property so that we can distinguish user events from
+ * value changes in JS.
+ */
+function startWatchingForValueChange(target, targetID) {
+  activeElement = target;
+  activeElementID = targetID;
+  activeElementValue = target.value;
+  activeElementValueProp = Object.getOwnPropertyDescriptor(
+    target.constructor.prototype,
+    'value'
+  );
+
+  Object.defineProperty(activeElement, 'value', newValueProp);
+  activeElement.attachEvent('onpropertychange', handlePropertyChange);
+}
+
+/**
+ * (For old IE.) Removes the event listeners from the currently-tracked element,
+ * if any exists.
+ */
+function stopWatchingForValueChange() {
+  if (!activeElement) {
+    return;
+  }
+
+  // delete restores the original property definition
+  delete activeElement.value;
+  activeElement.detachEvent('onpropertychange', handlePropertyChange);
+
+  activeElement = null;
+  activeElementID = null;
+  activeElementValue = null;
+  activeElementValueProp = null;
+}
+
+/**
+ * (For old IE.) Handles a propertychange event, sending a `change` event if
+ * the value of the active element has changed.
+ */
+function handlePropertyChange(nativeEvent) {
+  if (nativeEvent.propertyName !== 'value') {
+    return;
+  }
+  var value = nativeEvent.srcElement.value;
+  if (value === activeElementValue) {
+    return;
+  }
+  activeElementValue = value;
+
+  manualDispatchChangeEvent(nativeEvent);
+}
+
+/**
+ * If a `change` event should be fired, returns the target's ID.
+ */
+function getTargetIDForInputEvent(
+    topLevelType,
+    topLevelTarget,
+    topLevelTargetID) {
+  if (topLevelType === topLevelTypes.topInput) {
+    // In modern browsers (i.e., not IE8 or IE9), the input event is exactly
+    // what we want so fall through here and trigger an abstract event
+    return topLevelTargetID;
+  }
+}
+
+// For IE8 and IE9.
+function handleEventsForInputEventIE(
+    topLevelType,
+    topLevelTarget,
+    topLevelTargetID) {
+  if (topLevelType === topLevelTypes.topFocus) {
+    // In IE8, we can capture almost all .value changes by adding a
+    // propertychange handler and looking for events with propertyName
+    // equal to 'value'
+    // In IE9, propertychange fires for most input events but is buggy and
+    // doesn't fire when text is deleted, but conveniently, selectionchange
+    // appears to fire in all of the remaining cases so we catch those and
+    // forward the event if the value has changed
+    // In either case, we don't want to call the event handler if the value
+    // is changed from JS so we redefine a setter for `.value` that updates
+    // our activeElementValue variable, allowing us to ignore those changes
+    //
+    // stopWatching() should be a noop here but we call it just in case we
+    // missed a blur event somehow.
+    stopWatchingForValueChange();
+    startWatchingForValueChange(topLevelTarget, topLevelTargetID);
+  } else if (topLevelType === topLevelTypes.topBlur) {
+    stopWatchingForValueChange();
+  }
+}
+
+// For IE8 and IE9.
+function getTargetIDForInputEventIE(
+    topLevelType,
+    topLevelTarget,
+    topLevelTargetID) {
+  if (topLevelType === topLevelTypes.topSelectionChange ||
+      topLevelType === topLevelTypes.topKeyUp ||
+      topLevelType === topLevelTypes.topKeyDown) {
+    // On the selectionchange event, the target is just document which isn't
+    // helpful for us so just check activeElement instead.
+    //
+    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
+    // propertychange on the first input event after setting `value` from a
+    // script and fires only keydown, keypress, keyup. Catching keyup usually
+    // gets it and catching keydown lets us fire an event for the first
+    // keystroke if user does a key repeat (it'll be a little delayed: right
+    // before the second keystroke). Other input methods (e.g., paste) seem to
+    // fire selectionchange normally.
+    if (activeElement && activeElement.value !== activeElementValue) {
+      activeElementValue = activeElement.value;
+      return activeElementID;
+    }
+  }
+}
+
+
+/**
+ * SECTION: handle `click` event
+ */
+function shouldUseClickEvent(elem) {
+  // Use the `click` event to detect changes to checkbox and radio inputs.
+  // This approach works across all browsers, whereas `change` does not fire
+  // until `blur` in IE8.
+  return (
+    elem.nodeName === 'INPUT' &&
+    (elem.type === 'checkbox' || elem.type === 'radio')
+  );
+}
+
+function getTargetIDForClickEvent(
+    topLevelType,
+    topLevelTarget,
+    topLevelTargetID) {
+  if (topLevelType === topLevelTypes.topClick) {
+    return topLevelTargetID;
+  }
+}
+
+/**
+ * This plugin creates an `onChange` event that normalizes change events
+ * across form elements. This event fires at a time when it's possible to
+ * change the element's value without seeing a flicker.
+ *
+ * Supported elements are:
+ * - input (see `isTextInputElement`)
+ * - textarea
+ * - select
+ */
+var ChangeEventPlugin = {
+
+  eventTypes: eventTypes,
+
+  /**
+   * @param {string} topLevelType Record from `EventConstants`.
+   * @param {DOMEventTarget} topLevelTarget The listening component root node.
+   * @param {string} topLevelTargetID ID of `topLevelTarget`.
+   * @param {object} nativeEvent Native browser event.
+   * @return {*} An accumulation of synthetic events.
+   * @see {EventPluginHub.extractEvents}
+   */
+  extractEvents: function(
+      topLevelType,
+      topLevelTarget,
+      topLevelTargetID,
+      nativeEvent) {
+
+    var getTargetIDFunc, handleEventFunc;
+    if (shouldUseChangeEvent(topLevelTarget)) {
+      if (doesChangeEventBubble) {
+        getTargetIDFunc = getTargetIDForChangeEvent;
+      } else {
+        handleEventFunc = handleEventsForChangeEventIE8;
+      }
+    } else if (isTextInputElement(topLevelTarget)) {
+      if (isInputEventSupported) {
+        getTargetIDFunc = getTargetIDForInputEvent;
+      } else {
+        getTargetIDFunc = getTargetIDForInputEventIE;
+        handleEventFunc = handleEventsForInputEventIE;
+      }
+    } else if (shouldUseClickEvent(topLevelTarget)) {
+      getTargetIDFunc = getTargetIDForClickEvent;
+    }
+
+    if (getTargetIDFunc) {
+      var targetID = getTargetIDFunc(
+        topLevelType,
+        topLevelTarget,
+        topLevelTargetID
+      );
+      if (targetID) {
+        var event = SyntheticEvent.getPooled(
+          eventTypes.change,
+          targetID,
+          nativeEvent
+        );
+        EventPropagators.accumulateTwoPhaseDispatches(event);
+        return event;
+      }
+    }
+
+    if (handleEventFunc) {
+      handleEventFunc(
+        topLevelType,
+        topLevelTarget,
+        topLevelTargetID
+      );
+    }
+  }
+
+};
+
+module.exports = ChangeEventPlugin;
+
+},{"100":100,"108":108,"151":151,"153":153,"157":157,"16":16,"18":18,"21":21,"22":22}],9:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ClientReactRootIndex
+ * @typechecks
+ */
+
+'use strict';
+
+var nextReactRootIndex = 0;
+
+var ClientReactRootIndex = {
+  createReactRootIndex: function() {
+    return nextReactRootIndex++;
+  }
+};
+
+module.exports = ClientReactRootIndex;
+
+},{}],10:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DOMChildrenOperations
+ * @typechecks static-only
+ */
+
+'use strict';
+
+var Danger = _dereq_(13);
+var ReactMultiChildUpdateTypes = _dereq_(79);
+
+var setTextContent = _dereq_(165);
+var invariant = _dereq_(150);
+
+/**
+ * Inserts `childNode` as a child of `parentNode` at the `index`.
+ *
+ * @param {DOMElement} parentNode Parent node in which to insert.
+ * @param {DOMElement} childNode Child node to insert.
+ * @param {number} index Index at which to insert the child.
+ * @internal
+ */
+function insertChildAt(parentNode, childNode, index) {
+  // By exploiting arrays returning `undefined` for an undefined index, we can
+  // rely exclusively on `insertBefore(node, null)` instead of also using
+  // `appendChild(node)`. However, using `undefined` is not allowed by all
+  // browsers so we must replace it with `null`.
+  parentNode.insertBefore(
+    childNode,
+    parentNode.childNodes[index] || null
+  );
+}
+
+/**
+ * Operations for updating with DOM children.
+ */
+var DOMChildrenOperations = {
+
+  dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
+
+  updateTextContent: setTextContent,
+
+  /**
+   * Updates a component's children by processing a series of updates. The
+   * update configurations are each expected to have a `parentNode` property.
+   *
+   * @param {array<object>} updates List of update configurations.
+   * @param {array<string>} markupList List of markup strings.
+   * @internal
+   */
+  processUpdates: function(updates, markupList) {
+    var update;
+    // Mapping from parent IDs to initial child orderings.
+    var initialChildren = null;
+    // List of children that will be moved or removed.
+    var updatedChildren = null;
+
+    for (var i = 0; i < updates.length; i++) {
+      update = updates[i];
+      if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING ||
+          update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
+        var updatedIndex = update.fromIndex;
+        var updatedChild = update.parentNode.childNodes[updatedIndex];
+        var parentID = update.parentID;
+
+        ("production" !== "development" ? invariant(
+          updatedChild,
+          'processUpdates(): Unable to find child %s of element. This ' +
+          'probably means the DOM was unexpectedly mutated (e.g., by the ' +
+          'browser), usually due to forgetting a <tbody> when using tables, ' +
+          'nesting tags like <form>, <p>, or <a>, or using non-SVG elements ' +
+          'in an <svg> parent. Try inspecting the child nodes of the element ' +
+          'with React ID `%s`.',
+          updatedIndex,
+          parentID
+        ) : invariant(updatedChild));
+
+        initialChildren = initialChildren || {};
+        initialChildren[parentID] = initialChildren[parentID] || [];
+        initialChildren[parentID][updatedIndex] = updatedChild;
+
+        updatedChildren = updatedChildren || [];
+        updatedChildren.push(updatedChild);
+      }
+    }
+
+    var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList);
+
+    // Remove updated children first so that `toIndex` is consistent.
+    if (updatedChildren) {
+      for (var j = 0; j < updatedChildren.length; j++) {
+        updatedChildren[j].parentNode.removeChild(updatedChildren[j]);
+      }
+    }
+
+    for (var k = 0; k < updates.length; k++) {
+      update = updates[k];
+      switch (update.type) {
+        case ReactMultiChildUpdateTypes.INSERT_MARKUP:
+          insertChildAt(
+            update.parentNode,
+            renderedMarkup[update.markupIndex],
+            update.toIndex
+          );
+          break;
+        case ReactMultiChildUpdateTypes.MOVE_EXISTING:
+          insertChildAt(
+            update.parentNode,
+            initialChildren[update.parentID][update.fromIndex],
+            update.toIndex
+          );
+          break;
+        case ReactMultiChildUpdateTypes.TEXT_CONTENT:
+          setTextContent(
+            update.parentNode,
+            update.textContent
+          );
+          break;
+        case ReactMultiChildUpdateTypes.REMOVE_NODE:
+          // Already removed by the for-loop above.
+          break;
+      }
+    }
+  }
+
+};
+
+module.exports = DOMChildrenOperations;
+
+},{"13":13,"150":150,"165":165,"79":79}],11:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DOMProperty
+ * @typechecks static-only
+ */
+
+/*jslint bitwise: true */
+
+'use strict';
+
+var invariant = _dereq_(150);
+
+function checkMask(value, bitmask) {
+  return (value & bitmask) === bitmask;
+}
+
+var DOMPropertyInjection = {
+  /**
+   * Mapping from normalized, camelcased property names to a configuration that
+   * specifies how the associated DOM property should be accessed or rendered.
+   */
+  MUST_USE_ATTRIBUTE: 0x1,
+  MUST_USE_PROPERTY: 0x2,
+  HAS_SIDE_EFFECTS: 0x4,
+  HAS_BOOLEAN_VALUE: 0x8,
+  HAS_NUMERIC_VALUE: 0x10,
+  HAS_POSITIVE_NUMERIC_VALUE: 0x20 | 0x10,
+  HAS_OVERLOADED_BOOLEAN_VALUE: 0x40,
+
+  /**
+   * Inject some specialized knowledge about the DOM. This takes a config object
+   * with the following properties:
+   *
+   * isCustomAttribute: function that given an attribute name will return true
+   * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*
+   * attributes where it's impossible to enumerate all of the possible
+   * attribute names,
+   *
+   * Properties: object mapping DOM property name to one of the
+   * DOMPropertyInjection constants or null. If your attribute isn't in here,
+   * it won't get written to the DOM.
+   *
+   * DOMAttributeNames: object mapping React attribute name to the DOM
+   * attribute name. Attribute names not specified use the **lowercase**
+   * normalized name.
+   *
+   * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.
+   * Property names not specified use the normalized name.
+   *
+   * DOMMutationMethods: Properties that require special mutation methods. If
+   * `value` is undefined, the mutation method should unset the property.
+   *
+   * @param {object} domPropertyConfig the config as described above.
+   */
+  injectDOMPropertyConfig: function(domPropertyConfig) {
+    var Properties = domPropertyConfig.Properties || {};
+    var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};
+    var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};
+    var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};
+
+    if (domPropertyConfig.isCustomAttribute) {
+      DOMProperty._isCustomAttributeFunctions.push(
+        domPropertyConfig.isCustomAttribute
+      );
+    }
+
+    for (var propName in Properties) {
+      ("production" !== "development" ? invariant(
+        !DOMProperty.isStandardName.hasOwnProperty(propName),
+        'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' +
+        '\'%s\' which has already been injected. You may be accidentally ' +
+        'injecting the same DOM property config twice, or you may be ' +
+        'injecting two configs that have conflicting property names.',
+        propName
+      ) : invariant(!DOMProperty.isStandardName.hasOwnProperty(propName)));
+
+      DOMProperty.isStandardName[propName] = true;
+
+      var lowerCased = propName.toLowerCase();
+      DOMProperty.getPossibleStandardName[lowerCased] = propName;
+
+      if (DOMAttributeNames.hasOwnProperty(propName)) {
+        var attributeName = DOMAttributeNames[propName];
+        DOMProperty.getPossibleStandardName[attributeName] = propName;
+        DOMProperty.getAttributeName[propName] = attributeName;
+      } else {
+        DOMProperty.getAttributeName[propName] = lowerCased;
+      }
+
+      DOMProperty.getPropertyName[propName] =
+        DOMPropertyNames.hasOwnProperty(propName) ?
+          DOMPropertyNames[propName] :
+          propName;
+
+      if (DOMMutationMethods.hasOwnProperty(propName)) {
+        DOMProperty.getMutationMethod[propName] = DOMMutationMethods[propName];
+      } else {
+        DOMProperty.getMutationMethod[propName] = null;
+      }
+
+      var propConfig = Properties[propName];
+      DOMProperty.mustUseAttribute[propName] =
+        checkMask(propConfig, DOMPropertyInjection.MUST_USE_ATTRIBUTE);
+      DOMProperty.mustUseProperty[propName] =
+        checkMask(propConfig, DOMPropertyInjection.MUST_USE_PROPERTY);
+      DOMProperty.hasSideEffects[propName] =
+        checkMask(propConfig, DOMPropertyInjection.HAS_SIDE_EFFECTS);
+      DOMProperty.hasBooleanValue[propName] =
+        checkMask(propConfig, DOMPropertyInjection.HAS_BOOLEAN_VALUE);
+      DOMProperty.hasNumericValue[propName] =
+        checkMask(propConfig, DOMPropertyInjection.HAS_NUMERIC_VALUE);
+      DOMProperty.hasPositiveNumericValue[propName] =
+        checkMask(propConfig, DOMPropertyInjection.HAS_POSITIVE_NUMERIC_VALUE);
+      DOMProperty.hasOverloadedBooleanValue[propName] =
+        checkMask(propConfig, DOMPropertyInjection.HAS_OVERLOADED_BOOLEAN_VALUE);
+
+      ("production" !== "development" ? invariant(
+        !DOMProperty.mustUseAttribute[propName] ||
+          !DOMProperty.mustUseProperty[propName],
+        'DOMProperty: Cannot require using both attribute and property: %s',
+        propName
+      ) : invariant(!DOMProperty.mustUseAttribute[propName] ||
+        !DOMProperty.mustUseProperty[propName]));
+      ("production" !== "development" ? invariant(
+        DOMProperty.mustUseProperty[propName] ||
+          !DOMProperty.hasSideEffects[propName],
+        'DOMProperty: Properties that have side effects must use property: %s',
+        propName
+      ) : invariant(DOMProperty.mustUseProperty[propName] ||
+        !DOMProperty.hasSideEffects[propName]));
+      ("production" !== "development" ? invariant(
+        !!DOMProperty.hasBooleanValue[propName] +
+          !!DOMProperty.hasNumericValue[propName] +
+          !!DOMProperty.hasOverloadedBooleanValue[propName] <= 1,
+        'DOMProperty: Value can be one of boolean, overloaded boolean, or ' +
+        'numeric value, but not a combination: %s',
+        propName
+      ) : invariant(!!DOMProperty.hasBooleanValue[propName] +
+        !!DOMProperty.hasNumericValue[propName] +
+        !!DOMProperty.hasOverloadedBooleanValue[propName] <= 1));
+    }
+  }
+};
+var defaultValueCache = {};
+
+/**
+ * DOMProperty exports lookup objects that can be used like functions:
+ *
+ *   > DOMProperty.isValid['id']
+ *   true
+ *   > DOMProperty.isValid['foobar']
+ *   undefined
+ *
+ * Although this may be confusing, it performs better in general.
+ *
+ * @see http://jsperf.com/key-exists
+ * @see http://jsperf.com/key-missing
+ */
+var DOMProperty = {
+
+  ID_ATTRIBUTE_NAME: 'data-reactid',
+
+  /**
+   * Checks whether a property name is a standard property.
+   * @type {Object}
+   */
+  isStandardName: {},
+
+  /**
+   * Mapping from lowercase property names to the properly cased version, used
+   * to warn in the case of missing properties.
+   * @type {Object}
+   */
+  getPossibleStandardName: {},
+
+  /**
+   * Mapping from normalized names to attribute names that differ. Attribute
+   * names are used when rendering markup or with `*Attribute()`.
+   * @type {Object}
+   */
+  getAttributeName: {},
+
+  /**
+   * Mapping from normalized names to properties on DOM node instances.
+   * (This includes properties that mutate due to external factors.)
+   * @type {Object}
+   */
+  getPropertyName: {},
+
+  /**
+   * Mapping from normalized names to mutation methods. This will only exist if
+   * mutation cannot be set simply by the property or `setAttribute()`.
+   * @type {Object}
+   */
+  getMutationMethod: {},
+
+  /**
+   * Whether the property must be accessed and mutated as an object property.
+   * @type {Object}
+   */
+  mustUseAttribute: {},
+
+  /**
+   * Whether the property must be accessed and mutated using `*Attribute()`.
+   * (This includes anything that fails `<propName> in <element>`.)
+   * @type {Object}
+   */
+  mustUseProperty: {},
+
+  /**
+   * Whether or not setting a value causes side effects such as triggering
+   * resources to be loaded or text selection changes. We must ensure that
+   * the value is only set if it has changed.
+   * @type {Object}
+   */
+  hasSideEffects: {},
+
+  /**
+   * Whether the property should be removed when set to a falsey value.
+   * @type {Object}
+   */
+  hasBooleanValue: {},
+
+  /**
+   * Whether the property must be numeric or parse as a
+   * numeric and should be removed when set to a falsey value.
+   * @type {Object}
+   */
+  hasNumericValue: {},
+
+  /**
+   * Whether the property must be positive numeric or parse as a positive
+   * numeric and should be removed when set to a falsey value.
+   * @type {Object}
+   */
+  hasPositiveNumericValue: {},
+
+  /**
+   * Whether the property can be used as a flag as well as with a value. Removed
+   * when strictly equal to false; present without a value when strictly equal
+   * to true; present with a value otherwise.
+   * @type {Object}
+   */
+  hasOverloadedBooleanValue: {},
+
+  /**
+   * All of the isCustomAttribute() functions that have been injected.
+   */
+  _isCustomAttributeFunctions: [],
+
+  /**
+   * Checks whether a property name is a custom attribute.
+   * @method
+   */
+  isCustomAttribute: function(attributeName) {
+    for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {
+      var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];
+      if (isCustomAttributeFn(attributeName)) {
+        return true;
+      }
+    }
+    return false;
+  },
+
+  /**
+   * Returns the default property value for a DOM property (i.e., not an
+   * attribute). Most default values are '' or false, but not all. Worse yet,
+   * some (in particular, `type`) vary depending on the type of element.
+   *
+   * TODO: Is it better to grab all the possible properties when creating an
+   * element to avoid having to create the same element twice?
+   */
+  getDefaultValueForProperty: function(nodeName, prop) {
+    var nodeDefaults = defaultValueCache[nodeName];
+    var testElement;
+    if (!nodeDefaults) {
+      defaultValueCache[nodeName] = nodeDefaults = {};
+    }
+    if (!(prop in nodeDefaults)) {
+      testElement = document.createElement(nodeName);
+      nodeDefaults[prop] = testElement[prop];
+    }
+    return nodeDefaults[prop];
+  },
+
+  injection: DOMPropertyInjection
+};
+
+module.exports = DOMProperty;
+
+},{"150":150}],12:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DOMPropertyOperations
+ * @typechecks static-only
+ */
+
+'use strict';
+
+var DOMProperty = _dereq_(11);
+
+var quoteAttributeValueForBrowser = _dereq_(163);
+var warning = _dereq_(171);
+
+function shouldIgnoreValue(name, value) {
+  return value == null ||
+    (DOMProperty.hasBooleanValue[name] && !value) ||
+    (DOMProperty.hasNumericValue[name] && isNaN(value)) ||
+    (DOMProperty.hasPositiveNumericValue[name] && (value < 1)) ||
+    (DOMProperty.hasOverloadedBooleanValue[name] && value === false);
+}
+
+if ("production" !== "development") {
+  var reactProps = {
+    children: true,
+    dangerouslySetInnerHTML: true,
+    key: true,
+    ref: true
+  };
+  var warnedProperties = {};
+
+  var warnUnknownProperty = function(name) {
+    if (reactProps.hasOwnProperty(name) && reactProps[name] ||
+        warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
+      return;
+    }
+
+    warnedProperties[name] = true;
+    var lowerCasedName = name.toLowerCase();
+
+    // data-* attributes should be lowercase; suggest the lowercase version
+    var standardName = (
+      DOMProperty.isCustomAttribute(lowerCasedName) ?
+        lowerCasedName :
+      DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ?
+        DOMProperty.getPossibleStandardName[lowerCasedName] :
+        null
+    );
+
+    // For now, only warn when we have a suggested correction. This prevents
+    // logging too much when using transferPropsTo.
+    ("production" !== "development" ? warning(
+      standardName == null,
+      'Unknown DOM property %s. Did you mean %s?',
+      name,
+      standardName
+    ) : null);
+
+  };
+}
+
+/**
+ * Operations for dealing with DOM properties.
+ */
+var DOMPropertyOperations = {
+
+  /**
+   * Creates markup for the ID property.
+   *
+   * @param {string} id Unescaped ID.
+   * @return {string} Markup string.
+   */
+  createMarkupForID: function(id) {
+    return DOMProperty.ID_ATTRIBUTE_NAME + '=' +
+      quoteAttributeValueForBrowser(id);
+  },
+
+  /**
+   * Creates markup for a property.
+   *
+   * @param {string} name
+   * @param {*} value
+   * @return {?string} Markup string, or null if the property was invalid.
+   */
+  createMarkupForProperty: function(name, value) {
+    if (DOMProperty.isStandardName.hasOwnProperty(name) &&
+        DOMProperty.isStandardName[name]) {
+      if (shouldIgnoreValue(name, value)) {
+        return '';
+      }
+      var attributeName = DOMProperty.getAttributeName[name];
+      if (DOMProperty.hasBooleanValue[name] ||
+          (DOMProperty.hasOverloadedBooleanValue[name] && value === true)) {
+        return attributeName;
+      }
+      return attributeName + '=' + quoteAttributeValueForBrowser(value);
+    } else if (DOMProperty.isCustomAttribute(name)) {
+      if (value == null) {
+        return '';
+      }
+      return name + '=' + quoteAttributeValueForBrowser(value);
+    } else if ("production" !== "development") {
+      warnUnknownProperty(name);
+    }
+    return null;
+  },
+
+  /**
+   * Sets the value for a property on a node.
+   *
+   * @param {DOMElement} node
+   * @param {string} name
+   * @param {*} value
+   */
+  setValueForProperty: function(node, name, value) {
+    if (DOMProperty.isStandardName.hasOwnProperty(name) &&
+        DOMProperty.isStandardName[name]) {
+      var mutationMethod = DOMProperty.getMutationMethod[name];
+      if (mutationMethod) {
+        mutationMethod(node, value);
+      } else if (shouldIgnoreValue(name, value)) {
+        this.deleteValueForProperty(node, name);
+      } else if (DOMProperty.mustUseAttribute[name]) {
+        // `setAttribute` with objects becomes only `[object]` in IE8/9,
+        // ('' + value) makes it output the correct toString()-value.
+        node.setAttribute(DOMProperty.getAttributeName[name], '' + value);
+      } else {
+        var propName = DOMProperty.getPropertyName[name];
+        // Must explicitly cast values for HAS_SIDE_EFFECTS-properties to the
+        // property type before comparing; only `value` does and is string.
+        if (!DOMProperty.hasSideEffects[name] ||
+            ('' + node[propName]) !== ('' + value)) {
+          // Contrary to `setAttribute`, object properties are properly
+          // `toString`ed by IE8/9.
+          node[propName] = value;
+        }
+      }
+    } else if (DOMProperty.isCustomAttribute(name)) {
+      if (value == null) {
+        node.removeAttribute(name);
+      } else {
+        node.setAttribute(name, '' + value);
+      }
+    } else if ("production" !== "development") {
+      warnUnknownProperty(name);
+    }
+  },
+
+  /**
+   * Deletes the value for a property on a node.
+   *
+   * @param {DOMElement} node
+   * @param {string} name
+   */
+  deleteValueForProperty: function(node, name) {
+    if (DOMProperty.isStandardName.hasOwnProperty(name) &&
+        DOMProperty.isStandardName[name]) {
+      var mutationMethod = DOMProperty.getMutationMethod[name];
+      if (mutationMethod) {
+        mutationMethod(node, undefined);
+      } else if (DOMProperty.mustUseAttribute[name]) {
+        node.removeAttribute(DOMProperty.getAttributeName[name]);
+      } else {
+        var propName = DOMProperty.getPropertyName[name];
+        var defaultValue = DOMProperty.getDefaultValueForProperty(
+          node.nodeName,
+          propName
+        );
+        if (!DOMProperty.hasSideEffects[name] ||
+            ('' + node[propName]) !== defaultValue) {
+          node[propName] = defaultValue;
+        }
+      }
+    } else if (DOMProperty.isCustomAttribute(name)) {
+      node.removeAttribute(name);
+    } else if ("production" !== "development") {
+      warnUnknownProperty(name);
+    }
+  }
+
+};
+
+module.exports = DOMPropertyOperations;
+
+},{"11":11,"163":163,"171":171}],13:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule Danger
+ * @typechecks static-only
+ */
+
+/*jslint evil: true, sub: true */
+
+'use strict';
+
+var ExecutionEnvironment = _dereq_(22);
+
+var createNodesFromMarkup = _dereq_(126);
+var emptyFunction = _dereq_(129);
+var getMarkupWrap = _dereq_(142);
+var invariant = _dereq_(150);
+
+var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/;
+var RESULT_INDEX_ATTR = 'data-danger-index';
+
+/**
+ * Extracts the `nodeName` from a string of markup.
+ *
+ * NOTE: Extracting the `nodeName` does not require a regular expression match
+ * because we make assumptions about React-generated markup (i.e. there are no
+ * spaces surrounding the opening tag and there is at least one attribute).
+ *
+ * @param {string} markup String of markup.
+ * @return {string} Node name of the supplied markup.
+ * @see http://jsperf.com/extract-nodename
+ */
+function getNodeName(markup) {
+  return markup.substring(1, markup.indexOf(' '));
+}
+
+var Danger = {
+
+  /**
+   * Renders markup into an array of nodes. The markup is expected to render
+   * into a list of root nodes. Also, the length of `resultList` and
+   * `markupList` should be the same.
+   *
+   * @param {array<string>} markupList List of markup strings to render.
+   * @return {array<DOMElement>} List of rendered nodes.
+   * @internal
+   */
+  dangerouslyRenderMarkup: function(markupList) {
+    ("production" !== "development" ? invariant(
+      ExecutionEnvironment.canUseDOM,
+      'dangerouslyRenderMarkup(...): Cannot render markup in a worker ' +
+      'thread. Make sure `window` and `document` are available globally ' +
+      'before requiring React when unit testing or use ' +
+      'React.renderToString for server rendering.'
+    ) : invariant(ExecutionEnvironment.canUseDOM));
+    var nodeName;
+    var markupByNodeName = {};
+    // Group markup by `nodeName` if a wrap is necessary, else by '*'.
+    for (var i = 0; i < markupList.length; i++) {
+      ("production" !== "development" ? invariant(
+        markupList[i],
+        'dangerouslyRenderMarkup(...): Missing markup.'
+      ) : invariant(markupList[i]));
+      nodeName = getNodeName(markupList[i]);
+      nodeName = getMarkupWrap(nodeName) ? nodeName : '*';
+      markupByNodeName[nodeName] = markupByNodeName[nodeName] || [];
+      markupByNodeName[nodeName][i] = markupList[i];
+    }
+    var resultList = [];
+    var resultListAssignmentCount = 0;
+    for (nodeName in markupByNodeName) {
+      if (!markupByNodeName.hasOwnProperty(nodeName)) {
+        continue;
+      }
+      var markupListByNodeName = markupByNodeName[nodeName];
+
+      // This for-in loop skips the holes of the sparse array. The order of
+      // iteration should follow the order of assignment, which happens to match
+      // numerical index order, but we don't rely on that.
+      var resultIndex;
+      for (resultIndex in markupListByNodeName) {
+        if (markupListByNodeName.hasOwnProperty(resultIndex)) {
+          var markup = markupListByNodeName[resultIndex];
+
+          // Push the requested markup with an additional RESULT_INDEX_ATTR
+          // attribute.  If the markup does not start with a < character, it
+          // will be discarded below (with an appropriate console.error).
+          markupListByNodeName[resultIndex] = markup.replace(
+            OPEN_TAG_NAME_EXP,
+            // This index will be parsed back out below.
+            '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" '
+          );
+        }
+      }
+
+      // Render each group of markup with similar wrapping `nodeName`.
+      var renderNodes = createNodesFromMarkup(
+        markupListByNodeName.join(''),
+        emptyFunction // Do nothing special with <script> tags.
+      );
+
+      for (var j = 0; j < renderNodes.length; ++j) {
+        var renderNode = renderNodes[j];
+        if (renderNode.hasAttribute &&
+            renderNode.hasAttribute(RESULT_INDEX_ATTR)) {
+
+          resultIndex = +renderNode.getAttribute(RESULT_INDEX_ATTR);
+          renderNode.removeAttribute(RESULT_INDEX_ATTR);
+
+          ("production" !== "development" ? invariant(
+            !resultList.hasOwnProperty(resultIndex),
+            'Danger: Assigning to an already-occupied result index.'
+          ) : invariant(!resultList.hasOwnProperty(resultIndex)));
+
+          resultList[resultIndex] = renderNode;
+
+          // This should match resultList.length and markupList.length when
+          // we're done.
+          resultListAssignmentCount += 1;
+
+        } else if ("production" !== "development") {
+          console.error(
+            'Danger: Discarding unexpected node:',
+            renderNode
+          );
+        }
+      }
+    }
+
+    // Although resultList was populated out of order, it should now be a dense
+    // array.
+    ("production" !== "development" ? invariant(
+      resultListAssignmentCount === resultList.length,
+      'Danger: Did not assign to every index of resultList.'
+    ) : invariant(resultListAssignmentCount === resultList.length));
+
+    ("production" !== "development" ? invariant(
+      resultList.length === markupList.length,
+      'Danger: Expected markup to render %s nodes, but rendered %s.',
+      markupList.length,
+      resultList.length
+    ) : invariant(resultList.length === markupList.length));
+
+    return resultList;
+  },
+
+  /**
+   * Replaces a node with a string of markup at its current position within its
+   * parent. The markup must render into a single root node.
+   *
+   * @param {DOMElement} oldChild Child node to replace.
+   * @param {string} markup Markup to render in place of the child node.
+   * @internal
+   */
+  dangerouslyReplaceNodeWithMarkup: function(oldChild, markup) {
+    ("production" !== "development" ? invariant(
+      ExecutionEnvironment.canUseDOM,
+      'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' +
+      'worker thread. Make sure `window` and `document` are available ' +
+      'globally before requiring React when unit testing or use ' +
+      'React.renderToString for server rendering.'
+    ) : invariant(ExecutionEnvironment.canUseDOM));
+    ("production" !== "development" ? invariant(markup, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : invariant(markup));
+    ("production" !== "development" ? invariant(
+      oldChild.tagName.toLowerCase() !== 'html',
+      'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' +
+      '<html> node. This is because browser quirks make this unreliable ' +
+      'and/or slow. If you want to render to the root you must use ' +
+      'server rendering. See React.renderToString().'
+    ) : invariant(oldChild.tagName.toLowerCase() !== 'html'));
+
+    var newChild = createNodesFromMarkup(markup, emptyFunction)[0];
+    oldChild.parentNode.replaceChild(newChild, oldChild);
+  }
+
+};
+
+module.exports = Danger;
+
+},{"126":126,"129":129,"142":142,"150":150,"22":22}],14:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DefaultEventPluginOrder
+ */
+
+'use strict';
+
+var keyOf = _dereq_(157);
+
+/**
+ * Module that is injectable into `EventPluginHub`, that specifies a
+ * deterministic ordering of `EventPlugin`s. A convenient way to reason about
+ * plugins, without having to package every one of them. This is better than
+ * having plugins be ordered in the same order that they are injected because
+ * that ordering would be influenced by the packaging order.
+ * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
+ * preventing default on events is convenient in `SimpleEventPlugin` handlers.
+ */
+var DefaultEventPluginOrder = [
+  keyOf({ResponderEventPlugin: null}),
+  keyOf({SimpleEventPlugin: null}),
+  keyOf({TapEventPlugin: null}),
+  keyOf({EnterLeaveEventPlugin: null}),
+  keyOf({ChangeEventPlugin: null}),
+  keyOf({SelectEventPlugin: null}),
+  keyOf({BeforeInputEventPlugin: null}),
+  keyOf({AnalyticsEventPlugin: null}),
+  keyOf({MobileSafariClickEventPlugin: null})
+];
+
+module.exports = DefaultEventPluginOrder;
+
+},{"157":157}],15:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule EnterLeaveEventPlugin
+ * @typechecks static-only
+ */
+
+'use strict';
+
+var EventConstants = _dereq_(16);
+var EventPropagators = _dereq_(21);
+var SyntheticMouseEvent = _dereq_(112);
+
+var ReactMount = _dereq_(77);
+var keyOf = _dereq_(157);
+
+var topLevelTypes = EventConstants.topLevelTypes;
+var getFirstReactDOM = ReactMount.getFirstReactDOM;
+
+var eventTypes = {
+  mouseEnter: {
+    registrationName: keyOf({onMouseEnter: null}),
+    dependencies: [
+      topLevelTypes.topMouseOut,
+      topLevelTypes.topMouseOver
+    ]
+  },
+  mouseLeave: {
+    registrationName: keyOf({onMouseLeave: null}),
+    dependencies: [
+      topLevelTypes.topMouseOut,
+      topLevelTypes.topMouseOver
+    ]
+  }
+};
+
+var extractedEvents = [null, null];
+
+var EnterLeaveEventPlugin = {
+
+  eventTypes: eventTypes,
+
+  /**
+   * For almost every interaction we care about, there will be both a top-level
+   * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
+   * we do not extract duplicate events. However, moving the mouse into the
+   * browser from outside will not fire a `mouseout` event. In this case, we use
+   * the `mouseover` top-level event.
+   *
+   * @param {string} topLevelType Record from `EventConstants`.
+   * @param {DOMEventTarget} topLevelTarget The listening component root node.
+   * @param {string} topLevelTargetID ID of `topLevelTarget`.
+   * @param {object} nativeEvent Native browser event.
+   * @return {*} An accumulation of synthetic events.
+   * @see {EventPluginHub.extractEvents}
+   */
+  extractEvents: function(
+      topLevelType,
+      topLevelTarget,
+      topLevelTargetID,
+      nativeEvent) {
+    if (topLevelType === topLevelTypes.topMouseOver &&
+        (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
+      return null;
+    }
+    if (topLevelType !== topLevelTypes.topMouseOut &&
+        topLevelType !== topLevelTypes.topMouseOver) {
+      // Must not be a mouse in or mouse out - ignoring.
+      return null;
+    }
+
+    var win;
+    if (topLevelTarget.window === topLevelTarget) {
+      // `topLevelTarget` is probably a window object.
+      win = topLevelTarget;
+    } else {
+      // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
+      var doc = topLevelTarget.ownerDocument;
+      if (doc) {
+        win = doc.defaultView || doc.parentWindow;
+      } else {
+        win = window;
+      }
+    }
+
+    var from, to;
+    if (topLevelType === topLevelTypes.topMouseOut) {
+      from = topLevelTarget;
+      to =
+        getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement) ||
+        win;
+    } else {
+      from = win;
+      to = topLevelTarget;
+    }
+
+    if (from === to) {
+      // Nothing pertains to our managed components.
+      return null;
+    }
+
+    var fromID = from ? ReactMount.getID(from) : '';
+    var toID = to ? ReactMount.getID(to) : '';
+
+    var leave = SyntheticMouseEvent.getPooled(
+      eventTypes.mouseLeave,
+      fromID,
+      nativeEvent
+    );
+    leave.type = 'mouseleave';
+    leave.target = from;
+    leave.relatedTarget = to;
+
+    var enter = SyntheticMouseEvent.getPooled(
+      eventTypes.mouseEnter,
+      toID,
+      nativeEvent
+    );
+    enter.type = 'mouseenter';
+    enter.target = to;
+    enter.relatedTarget = from;
+
+    EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID);
+
+    extractedEvents[0] = leave;
+    extractedEvents[1] = enter;
+
+    return extractedEvents;
+  }
+
+};
+
+module.exports = EnterLeaveEventPlugin;
+
+},{"112":112,"157":157,"16":16,"21":21,"77":77}],16:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule EventConstants
+ */
+
+'use strict';
+
+var keyMirror = _dereq_(156);
+
+var PropagationPhases = keyMirror({bubbled: null, captured: null});
+
+/**
+ * Types of raw signals from the browser caught at the top level.
+ */
+var topLevelTypes = keyMirror({
+  topBlur: null,
+  topChange: null,
+  topClick: null,
+  topCompositionEnd: null,
+  topCompositionStart: null,
+  topCompositionUpdate: null,
+  topContextMenu: null,
+  topCopy: null,
+  topCut: null,
+  topDoubleClick: null,
+  topDrag: null,
+  topDragEnd: null,
+  topDragEnter: null,
+  topDragExit: null,
+  topDragLeave: null,
+  topDragOver: null,
+  topDragStart: null,
+  topDrop: null,
+  topError: null,
+  topFocus: null,
+  topInput: null,
+  topKeyDown: null,
+  topKeyPress: null,
+  topKeyUp: null,
+  topLoad: null,
+  topMouseDown: null,
+  topMouseMove: null,
+  topMouseOut: null,
+  topMouseOver: null,
+  topMouseUp: null,
+  topPaste: null,
+  topReset: null,
+  topScroll: null,
+  topSelectionChange: null,
+  topSubmit: null,
+  topTextInput: null,
+  topTouchCancel: null,
+  topTouchEnd: null,
+  topTouchMove: null,
+  topTouchStart: null,
+  topWheel: null
+});
+
+var EventConstants = {
+  topLevelTypes: topLevelTypes,
+  PropagationPhases: PropagationPhases
+};
+
+module.exports = EventConstants;
+
+},{"156":156}],17:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @providesModule EventListener
+ * @typechecks
+ */
+
+var emptyFunction = _dereq_(129);
+
+/**
+ * Upstream version of event listener. Does not take into account specific
+ * nature of platform.
+ */
+var EventListener = {
+  /**
+   * Listen to DOM events during the bubble phase.
+   *
+   * @param {DOMEventTarget} target DOM element to register listener on.
+   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
+   * @param {function} callback Callback function.
+   * @return {object} Object with a `remove` method.
+   */
+  listen: function(target, eventType, callback) {
+    if (target.addEventListener) {
+      target.addEventListener(eventType, callback, false);
+      return {
+        remove: function() {
+          target.removeEventListener(eventType, callback, false);
+        }
+      };
+    } else if (target.attachEvent) {
+      target.attachEvent('on' + eventType, callback);
+      return {
+        remove: function() {
+          target.detachEvent('on' + eventType, callback);
+        }
+      };
+    }
+  },
+
+  /**
+   * Listen to DOM events during the capture phase.
+   *
+   * @param {DOMEventTarget} target DOM element to register listener on.
+   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
+   * @param {function} callback Callback function.
+   * @return {object} Object with a `remove` method.
+   */
+  capture: function(target, eventType, callback) {
+    if (!target.addEventListener) {
+      if ("production" !== "development") {
+        console.error(
+          'Attempted to listen to events during the capture phase on a ' +
+          'browser that does not support the capture phase. Your application ' +
+          'will not receive some events.'
+        );
+      }
+      return {
+        remove: emptyFunction
+      };
+    } else {
+      target.addEventListener(eventType, callback, true);
+      return {
+        remove: function() {
+          target.removeEventListener(eventType, callback, true);
+        }
+      };
+    }
+  },
+
+  registerDefault: function() {}
+};
+
+module.exports = EventListener;
+
+},{"129":129}],18:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule EventPluginHub
+ */
+
+'use strict';
+
+var EventPluginRegistry = _dereq_(19);
+var EventPluginUtils = _dereq_(20);
+
+var accumulateInto = _dereq_(118);
+var forEachAccumulated = _dereq_(135);
+var invariant = _dereq_(150);
+
+/**
+ * Internal store for event listeners
+ */
+var listenerBank = {};
+
+/**
+ * Internal queue of events that have accumulated their dispatches and are
+ * waiting to have their dispatches executed.
+ */
+var eventQueue = null;
+
+/**
+ * Dispatches an event and releases it back into the pool, unless persistent.
+ *
+ * @param {?object} event Synthetic event to be dispatched.
+ * @private
+ */
+var executeDispatchesAndRelease = function(event) {
+  if (event) {
+    var executeDispatch = EventPluginUtils.executeDispatch;
+    // Plugins can provide custom behavior when dispatching events.
+    var PluginModule = EventPluginRegistry.getPluginModuleForEvent(event);
+    if (PluginModule && PluginModule.executeDispatch) {
+      executeDispatch = PluginModule.executeDispatch;
+    }
+    EventPluginUtils.executeDispatchesInOrder(event, executeDispatch);
+
+    if (!event.isPersistent()) {
+      event.constructor.release(event);
+    }
+  }
+};
+
+/**
+ * - `InstanceHandle`: [required] Module that performs logical traversals of DOM
+ *   hierarchy given ids of the logical DOM elements involved.
+ */
+var InstanceHandle = null;
+
+function validateInstanceHandle() {
+  var valid =
+    InstanceHandle &&
+    InstanceHandle.traverseTwoPhase &&
+    InstanceHandle.traverseEnterLeave;
+  ("production" !== "development" ? invariant(
+    valid,
+    'InstanceHandle not injected before use!'
+  ) : invariant(valid));
+}
+
+/**
+ * This is a unified interface for event plugins to be installed and configured.
+ *
+ * Event plugins can implement the following properties:
+ *
+ *   `extractEvents` {function(string, DOMEventTarget, string, object): *}
+ *     Required. When a top-level event is fired, this method is expected to
+ *     extract synthetic events that will in turn be queued and dispatched.
+ *
+ *   `eventTypes` {object}
+ *     Optional, plugins that fire events must publish a mapping of registration
+ *     names that are used to register listeners. Values of this mapping must
+ *     be objects that contain `registrationName` or `phasedRegistrationNames`.
+ *
+ *   `executeDispatch` {function(object, function, string)}
+ *     Optional, allows plugins to override how an event gets dispatched. By
+ *     default, the listener is simply invoked.
+ *
+ * Each plugin that is injected into `EventsPluginHub` is immediately operable.
+ *
+ * @public
+ */
+var EventPluginHub = {
+
+  /**
+   * Methods for injecting dependencies.
+   */
+  injection: {
+
+    /**
+     * @param {object} InjectedMount
+     * @public
+     */
+    injectMount: EventPluginUtils.injection.injectMount,
+
+    /**
+     * @param {object} InjectedInstanceHandle
+     * @public
+     */
+    injectInstanceHandle: function(InjectedInstanceHandle) {
+      InstanceHandle = InjectedInstanceHandle;
+      if ("production" !== "development") {
+        validateInstanceHandle();
+      }
+    },
+
+    getInstanceHandle: function() {
+      if ("production" !== "development") {
+        validateInstanceHandle();
+      }
+      return InstanceHandle;
+    },
+
+    /**
+     * @param {array} InjectedEventPluginOrder
+     * @public
+     */
+    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,
+
+    /**
+     * @param {object} injectedNamesToPlugins Map from names to plugin modules.
+     */
+    injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName
+
+  },
+
+  eventNam

<TRUNCATED>

[11/47] allura git commit: [#7919] Add rest endpoints for NavBar grouping and reordering

Posted by br...@apache.org.
[#7919] Add rest endpoints for NavBar grouping and reordering


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/bcdee466
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/bcdee466
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/bcdee466

Branch: refs/heads/db/7919
Commit: bcdee466532aea41b541aa69acfdff09c4145824
Parents: e419885
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:02:55 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:05:14 2015 -0400

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 45 ++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/bcdee466/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 7affa3c..0fbdaf2 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -762,6 +762,51 @@ class ProjectAdminRestController(BaseController):
 
     @expose('json:')
     @require_post()
+    def mount_order(self, subs=None, tools=None, **kw):
+        if kw:
+            for ordinal, mount_point in kw.iteritems():
+                try:
+                    c.project.app_config(mount_point).options.ordinal = int(ordinal)
+                except AttributeError as e:
+                    # Handle subproject
+                    print("Handle subproject", mount_point)
+                    p = M.Project.query.get(shortname="{}/{}".format(c.project.shortname, mount_point),
+                                            neighborhood_id=c.project.neighborhood_id)
+                    if p:
+                        p.ordinal = int(ordinal)
+        M.AuditLog.log('Updated NavBar mount order for {}'.format(c.project.name))
+        return {'status': 'ok'}
+
+
+    @expose('json:')
+    @require_post()
+    def configure_tool_grouping(self, grouping_threshold='1', **kw):
+        try:
+            grouping_threshold = int(grouping_threshold)
+            if grouping_threshold < 1:
+                raise ValueError('Invalid threshold')
+            c.project.set_tool_data(
+                'allura', grouping_threshold=grouping_threshold)
+        except ValueError:
+            return {
+                'status': 'error',
+                'msg': 'Invalid threshold'
+            }
+        M.AuditLog.log('Updated grouping threshold for {}'.format(c.project.name))
+        return {'status': 'ok'}
+
+    @expose('json:')
+    def tools(self, **kw):
+        """ List of installable tools
+
+        """
+        response.content_type = 'application/json'
+        tools_names = [t['name'] for t in AdminApp.installable_tools_for(c.project)]
+
+        return {'status': 'ok'}
+
+    @expose('json:')
+    @require_post()
     def export(self, tools=None, send_email=False, **kw):
         """
         Initiate a bulk export of the project data.


[44/47] allura git commit: [#7919] Update stylesheet to support new component markup

Posted by br...@apache.org.
[#7919] Update stylesheet to support new component markup


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/6381ecbb
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/6381ecbb
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/6381ecbb

Branch: refs/heads/db/7919
Commit: 6381ecbbc059048eaa44a3c167c8b7e5291e6c17
Parents: a6b6f36
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 22 15:58:32 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:05 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css | 3009 ++++-----------------------
 1 file changed, 398 insertions(+), 2611 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/6381ecbb/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index 2cc8798..6b947d1 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -3,9 +3,11 @@
     width: 350px;
     display: none;
 }
+
 .hidden {
     display: none;
 }
+
 .submenu ul {
     list-style: none;
     display: block;
@@ -21,6 +23,7 @@
     z-index: -1000;
     padding-top: 11px;
 }
+
 #bar-config {
     display: inline-flex;
     position: absolute;
@@ -29,12 +32,14 @@
     align-items: stretch;
     flex: 1 1 auto;
 }
+
 #threshold-config > span > input {
     width: 2rem;
     background-color: #A1A1A1;
     color: white;
     font-weight: bold;
 }
+
 #toggle-admin-btn {
     position: absolute;
     right: -9px;
@@ -42,18 +47,21 @@
     width: 2rem;
     height: 1.8rem;
 }
+
 nav {
     display: flex;
     flex-direction: row;
     justify-content: center;
     margin: auto;
 }
+
 #top_nav_admin > div.edit-mode > ul {
     display: flex;
     flex-direction: row;
     flex-wrap: wrap;
     flex: 1;
 }
+
 #top_nav_admin > div.edit-mode > ul > .tb-item {
     background-color: #F0F0F0;
     margin-top: 0.5rem;
@@ -62,9 +70,11 @@ nav {
     border: 1px dashed gray;
     padding: 0.3rem 0.6rem 0.3rem 0.6rem;
 }
+
 .admin-toolbar {
     display: flex;
 }
+
 #top_nav_admin {
     display: grid;
     flex-direction: row;
@@ -75,17 +85,13 @@ nav {
     -ms-border-radius: 4px;
     -khtml-border-radius: 4px;
     border-radius: 4px;
-    width: 918px;
-    /* 940px - 32px for toggle-admin-btn */
+    width: 918px;  /* 940px - 32px for toggle-admin-btn */
 }
+
 #top_nav_admin .edit-mode .fa {
     margin: 0 3px;
-    margin-left: 0;
-    padding: 2px;
-    padding-left: 1px;
-    /* font-size: large; */
-    color: #595959;
 }
+
 .btn-bar {
     display: block;
     clear: both;
@@ -102,6 +108,7 @@ nav {
     position: relative;
     margin: 0 0 20px;
 }
+
 ul.dropdown li {
     float: left;
     vertical-align: middle;
@@ -109,17 +116,21 @@ ul.dropdown li {
     padding-top: 10px;
     padding-bottom: 10px;
 }
+
 ul.dropdown, ul.dropdown li, ul.dropdown ul {
     list-style: none;
     margin: 0;
     padding: 0;
 }
+
 li.tb-item-edit > input {
     width: 2.2rem;
 }
+
 .draggable-handle {
     cursor: move;
 }
+
 ul.dropdown li {
     float: left;
     vertical-align: middle;
@@ -127,38 +138,35 @@ ul.dropdown li {
     padding-top: 10px;
     padding-bottom: 10px;
 }
+
 #content {
     width: 990px;
 }
+
 .react-reorderable-item {
     display: inline-flex;
     float: left;
-    text-align: left;
 }
+
 .react-reorderable-item-active {
     border: 3px dashed #9e9e9e;
     background: #c9c9c9;
-    width: 5rem;
-    /* dynamic would be nice */
+    width: 5rem; /* dynamic would be nice */
     height: 50px;
 }
+
 .react-reorderable-item-active div {
     display: none;
 }
+
 .react-reorderable-handle {
     position: absolute;
 }
+
 #top_nav_admin .tb-item a {
     margin: 10px;
-    text-align: left;
-    display: inline-block;
-    padding-right: 10px;
-    padding-left: 10px;
-    margin-right: 5px;
-    border: 2px solid #8C8C8C;
-    /* border-right: 2px solid #8C8C8C; */
-    border-radius: 3px;
 }
+
 .react-drag {
     -webkit-user-select: none;
     -moz-user-select: none;
@@ -166,6 +174,7 @@ ul.dropdown li {
     -o-user-select: none;
     user-select: none;
 }
+
 ul.dropdown ul {
     visibility: hidden;
     position: absolute;
@@ -175,2653 +184,431 @@ ul.dropdown ul {
     border: 1px solid #dddddd;
     border-top-width: 0;
 }
+
 ul.dropdown .hover, ul.dropdown li:hover {
     position: relative;
     z-index: 599;
     cursor: default;
 }
+
 .anchored {
     cursor: not-allowed;
     color: gray;
 }
-.nav_admin {
+
+.nav_admin{
     height: auto;
 }
-.nav_admin > div > ul > li {
+
+.nav_admin > div > ul > li{
     height: 1.2rem;
     font-weight: inherit;
 }
+
 .tool-partition {
     height: 0;
     /*padding-top: 5px;*/
-    /* border-top: 3px solid #777; */
+    border-top: 3px solid #777;
 }
+
 .installable-tool-box {
     /* position: relative; */
-    display: inlin-f;
-    min-height: 289px;
-    align-content: center;
-    border-right: 1px solid #9D9D9D;
-    background-color: yellow;
-    background-image:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+    display: flex;
+    background-color: white;
+    background-image: 
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, rgba(204, 204, 204, 0.6)));
+    background-image: 
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
+    background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
+    flex-wrap: wrap;
+    /*justify-content: flex-start;*/
+    justify-content: space-around;
+    /*margin-left: 0;*/
+    flex-direction: row;
+    /* padding-bottom: 5px; */
+    /* padding-top: 4px; */
+    /*display: -webkit-flex;*/
+    /*display: flex;*/
+    /*-webkit-flex-direction: row;*/
+    /*flex-direction: row;*/
+    /*margin-bottom: 8px;*/
+}
 
+.installable-tool-box div {
+    padding-top: 4px;
+    margin-bottom: 0;
+    margin-left: 0;
+    border-radius: 0 0 4px 4px;
+    padding-left: 5px;
+    padding-bottom: 2px;
+    padding-right: 5px;
+    text-align: center;
+    font-size: small;
+    font-weight: 400;
+    list-style: none;
+    cursor: pointer;
+    /*align-items: flex-start;*/
+    min-width: 40px;
+    border: 1px solid transparent;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+}
 
 
+/*.installable-tool-box > div{
+    color:blue;
+    background: rgba(255, 255, 255, 0.8);
+    min-width: 75px;
+    border: 1px dashed orange;
+}*/
 
 
+.selected-tool{
+    background: #09C !important;
+    color: white !important;
+    height: 21px;
+}
 
+.installable-tool-box div:hover {
+    background: white;
+    border: 1px solid #09C;
+}
 
+.installable-tool-box div.selected-tool:hover {
+    background: white;
+    color: rgb(85, 85, 85);
+}
 
+.tool-card {
+    width: 500px;
+    display: block;
+    border: 2px solid #4E4E4E;
+    border-radius: 2px 2px 5px 5px;
+    margin-bottom: 0;
+    background: white;
+    right: 10px;
+    top: 50px;
+    position: absolute;
+    z-index: 1000;
+}
 
+.tool-card::before {
+    content: "▲";
+    color: #4E4E4E;
+    font-size: xx-large;
+    position: absolute;
+    right: 0px;
+    top: -14px;
+    overflow: visible;
+    float: right;
+    height: 1.5rem;
+}
 
+.box-title {
+    z-index: 60;
+    height: auto;
+    font-size: small;
+    text-align: center;
+    padding-bottom: 3px;
+    position: relative;
+    padding-top: 3px;
+    background: #4E4E4E;
+    color: #DEDEDE;
+}
 
+.tool-info {
+    min-height: -15rem;
+    display: block;
+    clear: both;
+}
 
+.tool-info-left p {
+    text-align: center;
+    vertical-align: text-top;
+    padding-top: 0;
+    left: 0;
+    font-size: 11pt;
+    font-weight: 400;
+    margin: 2rem 33px;
+    color: #F9F9F9;
+    padding-bottom: 20px;
+    margin: 20px;
+}
 
+.tool-info-left h1 {
+    text-align: center;
+    padding-bottom: 0;
+    vertical-align: text-top;
+    padding-top: 0;
+    left: 0;
+    font-size: large;
+    background-color: #AEF4FF;
+    color: #5B5B5B;
+    height: 2.4rem;
+    margin: 0;
+}
 
+.add-tool-button {
+    width: 140px;
+    height: auto;
+    min-height: 1.6rem;
+    font-size: small;
+    bottom: 0.7rem;
+    right: -10px;
+}
 
+.tool-info-left {
+    background: #636363;
+    width: 60%;
+    height: 206px;
+    left: 0;
+    float: left;
+    top: 0;
+    color: white;
+}
 
+.tool-info-right {
+    width: 40%;
+    float: right;
+    overflow: hidden;
+    position: relative;
+    display: block;
+    top: 0;
+}
 
+.tool-form {
+    display: inline-block;
+    width: 100%;
+    position: absolute;
+    right: 0;
+    top: 0;
+    padding-top: 1rem;
+    height: auto;
+}
 
+#add-tool-form > label{
+    padding: 0;
+    font-size: 13pt;
+    position: absolute;
+    margin-left: 18px;
+}
 
+#add-tool-form > p{
+    font-size: large;
 
+}
 
+#add-tool-form > input {
+    padding-top: 10px;
+    padding-left: 10px;
+    width: 77%;
+    margin: 23px 60px 11px 19px;
+}
 
+#add-tool-form{
+    padding-top: 20px;
+    padding-left: 25px;
+    padding-right: 25px;
+}
 
+.tool-form-fields{
+    clear: both;
+    position: relative;
+    display: flex;
+    flex-direction: row;
+}
 
+#mount_point :invalid{
+    background: #333;
+}
 
+.add-tool-toggle{
+    background: rgba(255, 255, 255, 0.32);
+    /*clear: both;*/
+    color: #8b8b8b;
+    /*font-weight: bold;*/
+    /*margin: 1px;*/
+    /*position: relative;*/
 
+    /*right: 127px;*/
+    /*position: absolute;*/
+    /*padding: 5px 5px 3px;*/
+    border: 1px dashed #B3B3B3;
+    padding-top: 2px;
+    padding-bottom: 2px;
+    /*top: 18px;*/
+    height: 100%;
+    width: 5.7rem;
+    float: right;
+    border-radius: 4px;
+    /*height: 1.5rem;*/
+    cursor: pointer;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+}
+.add-tool-toggle:hover{
+    background: #F4F4F4;
+    color: #777;
+}
 
+.active-nav-link{
+    font-weight: bolder;
+}
 
+.add-tool-field{
+    width: 50%;
+}
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, #cccccc));
-    background-image:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
-    background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
-    /* flex-wrap: wrap; */
-    flex-direction: column;
-    /* justify-content: flex-start; */
-    justify-content: space-around;
-    padding-bottom: 2.2rem;
-    width: 100%;
-    /* -webkit-flex-direction: row; */
-    /* flex-direction: column; */
-    /*margin-bottom: 8px;*/
-    /* min-height: 280px; */
-}
-.installable-tool-box div {
-    /* margin-top: 0.5rem; */
-    margin-left: 0;
-    /* height: auto; */
-    border-radius: 4px;
-    padding: 10px;
-    text-align: right;
-    font-size: medium;
-    list-style: none;
-    cursor: pointer;
-    /*align-items: flex-start;*/
-    min-width: 10%;
-    border: 1px solid transparent;
-    -webkit-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    -o-user-select: none;
-    user-select: none;
-    border-radius: 0 4px 4px 0;
-}
-
-/*.installable-tool-box > div{
-    color:blue;
-    background: rgba(255, 255, 255, 0.8);
-    min-width: 75px;
-    border: 1px dashed orange;
-}*/
-
-.installable-tool-box div:hover {
-    background: white;
-    border: 1px solid rgb(0, 153, 204);
-    border: 1;
-}
-.selected-tool {
-    background: rgba(0, 153, 243, 0.8) !important;
-    color: white !important;
-    box-shadow: 3px 3px 2px #ABABAB !important;
-    font-weight: bold;
-}
-.installable-tool-box div.selected-tool:hover {
-    background: white;
-    color: rgb(85, 85, 85);
-}
-.tool-card {
-    width: 447px;
-    height: 345px;
-    display: block;
-    border: 2px solid #5B5B5B;
-    box-shadow: 7px 5px 21px rgba(68, 68, 68, 0.58);
-    border-radius: 2px 2px 5px 5px;
-    overflow: inherit;
-    margin-bottom: 50px;
-    background: rgb(255, 255, 255);
-    right: 20px;
-    position: absolute;
-    background-image:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, rgba(233, 233, 233, 0.67)));
-    z-index: 1000;
-    background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
-    -webkit-gradient(
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    linear, 0% 0%, 0% 100%,
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    color-stop(0%, #ffffff),
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    color-stop(100%, #cccccc));
-    background-image:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
-    background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
-}
-.tool-card::before {
-    content: "â–²";
-    color: #4E4E4E;
-    font-size: xx-large;
-    position: absolute;
-    right: 0px;
-    top: -14px;
-    overflow: visible;
-    float: right;
-    height: 1.5rem;
-}
-.box-title {
-    z-index: 60;
-    height: auto;
-    font-size: small;
-    text-align: center;
-    padding-bottom: 3px;
-    position: relative;
-    /* padding-top: 3px; */
-    background: #4E4E4E;
-    color: #DEDEDE;
-    background-image:
-
-
-
-
-
-
-
-
-    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #555), color-stop(100%, #666));
-    background-image:
-
-
-
-
-
-
-
-
-    -moz-linear-gradient(top, #666 0%, #555 100%);
-    background-image: linear-gradient(top, #666 0%, #555 100%);
-}
-.tool-info {
-    min-height: 22rem;
-    /* display: block; */
-    width: 72%;
-    float: right;
-    /* clear: both; */
-}
-.tool-info-left p {
-    text-align: center;
-    vertical-align: text-top;
-    padding-top: 0;
-    left: 0;
-    font-size: small;
-    font-kerning: 81;
-    font-weight: 100;
-    min-height: 70px;
-    margin: 1.5rem 23px;
-    margin-top: 0;
-    color: #FFFFFF;
-    padding-bottom: 0px;
-}
-.tool-info-left h1 {
-    text-align: center;
-    padding-bottom: 0;
-    vertical-align: text-top;
-    padding-top: 8px;
-    left: 0;
-    font-size: large;
-    /* background-color: #AEF4FF; */
-    color: #5B5B5B;
-    height: 2.6rem;
-    box-shadow: 3px 2px 5px rgba(34, 34, 34, 0.56);
-}
-.add-tool-button {
-    width: 109px;
-    height: auto;
-    background: white;
-    min-width: 6rem;
-    position: absolute;
-    min-height: 2.1rem;
-    margin-top: 5px;
-    font-size: large;
-    /* bottom: -2.3rem; */
-    overflow: visible;
-    right: 0px;
-    bottom: -29px;
-}
-.tool-info-left {
-    background: rgb(98, 98, 98);
-    /* width: 75%; */
-    position: relative;
-    /* float: right; */
-    /* display: inline-block; */
-    height: auto;
-    /* box-shadow: 0px 1px 5px darkgray; */
-    /* left: 0; */
-    /* border-left: 1px solid #B3B3B3; */
-    /* float: right; */
-    /* top: 0; */
-    color: white;
-}
-.tool-info-right {
-    /* width: 100%; */
-    /* float: right; */
-    /* overflow: hidden; */
-    /* display: inline-grid; */
-    /* flex-direction: column; */
-    /* float: right; */
-    /* position: relative; */
-    /* left: 50px; */
-    /* display: block; */
-    top: 0;
-    /* align-content: center; */
-    height: auto;
-    position: relative;
-    top: -9px;
-}
-.tool-form {
-    display: inline-block;
-    width: 100%;
-    position: absolute;
-    right: 0;
-    top: 0;
-    padding-top: 1rem;
-    /*height: auto;*/
-}
-#add-tool-form > label {
-    /* padding: 0; */
-    font-size: 8pt;
-    /* position: relative; */
-    /* left: -128px; */
-    /* top: 27px; */
-    /* margin-left: 18px; */
-    color: grey;
-}
-#add-tool-form > p {
-    font-size: large;
-}
-#add-tool-form > input {
-    /* padding-top: 10px; */
-    /* padding-left: 10px; */
-    /* position: relative; */
-    /* width: 60%; */
-    /* display: inline-flex; */
-    float: left;
-    /* flex-wrap: wrap; */
-    width: 100px;
-    margin-left: 4px;
-    margin-right: 20px;
-}
-#add-tool-url-preview {
-    font-size: 10pt;
-    position: relative;
-    right: 143px;
-    top: 43px;
-    height: 20px;
-    padding-bottom: 0;
-    margin-bottom: 0;
-}
-#add-tool-form {
-    padding-top: 0;
-    margin-top: 0;
-    display: flex;
-    flex-direction: row;
-    width: 95%;
-    /* align-items: center; */
-    padding-left: 0;
-    /* padding-right: 25px; */
-    /* height: 80px; */
-    align-content: center;
-    /* float: left; */
-}
-.tool-form-fields {
-    clear: both;
-    position: relative;
-    display: flex;
-    flex-direction: row;
-}
-#mount_point:invalid {
-    /* background: #333; */
-}
-.add-tool-toggle {
-    background: rgba(255, 255, 255, 0.32);
-    /* clear: both; */
-    color: #8b8b8b;
-    /* font-weight: bold; */
-    /* margin: 1px; */
-    /*position: relative;*/
-    /* right: 127px; */
-    /* position: absolute; */
-    /*padding: 5px 5px 3px;*/
-    border: 1px dashed #B3B3B3;
-    padding-top: 2px;
-    padding-bottom: 2px;
-    /* top: 18px; */
-    height: 100%;
-    width: 5.7rem;
-    float: right;
-    border-radius: 4px;
-    /*height: 1.5rem;*/
-    cursor: pointer;
-    -webkit-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    -o-user-select: none;
-    user-select: none;
-}
-.add-tool-toggle:hover {
-    background: #F4F4F4;
-    color: #777;
-}
-.active-nav-link {
-    font-weight: bolder;
-}
-.menu-appear {
-    opacity: 0.01;
-}
-.example-appear.example-appear-active {
-    opacity: 1;
-    transition: opacity .5s ease-in;
-}
-#installable-items {
-    position: initial;
-    left: 0px;
-    float: left;
-    width: 28%;
-}
-
 .error-box{
-    background: rgba(255, 165, 0, 0.54);
+    background: rgba(255, 114, 114, 0.65);
     color: white;
     padding: 4px;
-    font-weight: bold;
-    position: absolute;
-    top: 66px;
-    width: 146px;
+    font-weight: 500;
+    position: fixed;
+    top: 289px;
+    width: 175px;
     box-shadow: 0px 1px 1px #8E8E8E;
-    /* left: 17px; */
+    left: 639px;
     border-radius: 4px;
     font-size: 9pt;
     float: left;
-}
-#add-tool-url-preview{
-    /* float: right; */
-}
-
-#add-tool-url-preview > p > small {
-    color: grey;
-}
-
-#add-tool-url-preview > p > strong {
-    color: orange;
-}
-
-.add-tool-field{
-    width: 50%;
-    min-height: 137px;
-}
+}
\ No newline at end of file


[29/47] allura git commit: [#7919] Add tool_label to installable_tools rest endpoint

Posted by br...@apache.org.
[#7919] Add tool_label to installable_tools rest endpoint


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/7a7a4d01
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/7a7a4d01
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/7a7a4d01

Branch: refs/heads/db/7919
Commit: 7a7a4d019d754999118933c04c9311ae7b992b0c
Parents: 37fad09
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 15 14:59:11 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/7a7a4d01/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 84e698c..2f1e62a 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -806,6 +806,7 @@ class ProjectAdminRestController(BaseController):
                 'name': tool['name'],
                 'description': " ".join(tool['app'].tool_description.split()),
                 'icons': tool['app'].icons,
+                'tool_label': tool['app'].tool_label,
                 'defaults': {
                     'default_options': tool['app'].default_options(),
                     'default_mount_label': tool['app'].default_mount_label,


[14/47] allura git commit: [#7919] Add the "tools" endpoint to the api documentation

Posted by br...@apache.org.
[#7919] Add the "tools" endpoint to the api documentation


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/7544bf02
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/7544bf02
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/7544bf02

Branch: refs/heads/db/7919
Commit: 7544bf0250f6b92a164181bbacd05df4d1522bc4
Parents: f527579
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:12:02 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:01 2015 -0400

----------------------------------------------------------------------
 Allura/docs/api-rest/api.raml | 9 +++++++++
 1 file changed, 9 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/7544bf02/Allura/docs/api-rest/api.raml
----------------------------------------------------------------------
diff --git a/Allura/docs/api-rest/api.raml b/Allura/docs/api-rest/api.raml
index 244c5db..ec83c26 100755
--- a/Allura/docs/api-rest/api.raml
+++ b/Allura/docs/api-rest/api.raml
@@ -667,6 +667,15 @@ documentation:
                     required: false
                     description: |
                       "first", "last", or "alpha_tool" for position with respect to existing tools (or existing tools of the same type for "alpha_tool")
+        /tools:
+          description: |
+            Gets a list of installable tools for a project
+
+            returns dict with two fields:
+            success: False if error is occurred, otherwise True
+            info: success or error message
+          get:
+
 
 /u/{username}:
     description: |


[21/47] allura git commit: [#7919] Add NavBar dependencies

Posted by br...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/db6e6859/Allura/allura/public/nf/js/react-with-addons.min.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/react-with-addons.min.js b/Allura/allura/public/nf/js/react-with-addons.min.js
new file mode 100644
index 0000000..0e20d1c
--- /dev/null
+++ b/Allura/allura/public/nf/js/react-with-addons.min.js
@@ -0,0 +1,18 @@
+/**
+ * React (with addons) v0.13.3
+ *
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.React=e()}}(function(){return function e(t,n,r){function o(a,s){if(!n[a]){if(!t[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var c=n[a]={exports:{}};t[a][0].call(c.exports,function(e){var n=t[a][1][e];return o(n?n:e)},c,c.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(e,t,n){"use strict";var r=e(25),o=e(31),i=e(42),a=e(34),s=e(67),u=e(95),l=e(97),c=e(124),p=e(119),d=e(165);o.addons={CSSTransitionGroup:a,LinkedStateMixin:r,PureRenderMixin:i,TransitionGroup:u,batchedUpdates:l.batchedUpdates,classSet:c,cloneWithProps:p
 ,createFragment:s.create,update:d},t.exports=o},{119:119,124:124,165:165,25:25,31:31,34:34,42:42,67:67,95:95,97:97}],2:[function(e,t,n){"use strict";var r=e(131),o={componentDidMount:function(){this.props.autoFocus&&r(this.getDOMNode())}};t.exports=o},{131:131}],3:[function(e,t,n){"use strict";function r(){var e=window.opera;return"object"==typeof e&&"function"==typeof e.version&&parseInt(e.version(),10)<=12}function o(e){return(e.ctrlKey||e.altKey||e.metaKey)&&!(e.ctrlKey&&e.altKey)}function i(e){switch(e){case P.topCompositionStart:return I.compositionStart;case P.topCompositionEnd:return I.compositionEnd;case P.topCompositionUpdate:return I.compositionUpdate}}function a(e,t){return e===P.topKeyDown&&t.keyCode===b}function s(e,t){switch(e){case P.topKeyUp:return-1!==E.indexOf(t.keyCode);case P.topKeyDown:return t.keyCode!==b;case P.topKeyPress:case P.topMouseDown:case P.topBlur:return!0;default:return!1}}function u(e){var t=e.detail;return"object"==typeof t&&"data"in t?t.data:null
 }function l(e,t,n,r){var o,l;if(_?o=i(e):w?s(e,r)&&(o=I.compositionEnd):a(e,r)&&(o=I.compositionStart),!o)return null;M&&(w||o!==I.compositionStart?o===I.compositionEnd&&w&&(l=w.getData()):w=v.getPooled(t));var c=g.getPooled(o,n,r);if(l)c.data=l;else{var p=u(r);null!==p&&(c.data=p)}return h.accumulateTwoPhaseDispatches(c),c}function c(e,t){switch(e){case P.topCompositionEnd:return u(t);case P.topKeyPress:var n=t.which;return n!==T?null:(R=!0,N);case P.topTextInput:var r=t.data;return r===N&&R?null:r;default:return null}}function p(e,t){if(w){if(e===P.topCompositionEnd||s(e,t)){var n=w.getData();return v.release(w),w=null,n}return null}switch(e){case P.topPaste:return null;case P.topKeyPress:return t.which&&!o(t)?String.fromCharCode(t.which):null;case P.topCompositionEnd:return M?null:t.data;default:return null}}function d(e,t,n,r){var o;if(o=D?c(e,r):p(e,r),!o)return null;var i=y.getPooled(I.beforeInput,n,r);return i.data=o,h.accumulateTwoPhaseDispatches(i),i}var f=e(16),h=e(21),m=e
 (22),v=e(23),g=e(103),y=e(107),C=e(154),E=[9,13,27,32],b=229,_=m.canUseDOM&&"CompositionEvent"in window,x=null;m.canUseDOM&&"documentMode"in document&&(x=document.documentMode);var D=m.canUseDOM&&"TextEvent"in window&&!x&&!r(),M=m.canUseDOM&&(!_||x&&x>8&&11>=x),T=32,N=String.fromCharCode(T),P=f.topLevelTypes,I={beforeInput:{phasedRegistrationNames:{bubbled:C({onBeforeInput:null}),captured:C({onBeforeInputCapture:null})},dependencies:[P.topCompositionEnd,P.topKeyPress,P.topTextInput,P.topPaste]},compositionEnd:{phasedRegistrationNames:{bubbled:C({onCompositionEnd:null}),captured:C({onCompositionEndCapture:null})},dependencies:[P.topBlur,P.topCompositionEnd,P.topKeyDown,P.topKeyPress,P.topKeyUp,P.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:C({onCompositionStart:null}),captured:C({onCompositionStartCapture:null})},dependencies:[P.topBlur,P.topCompositionStart,P.topKeyDown,P.topKeyPress,P.topKeyUp,P.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled
 :C({onCompositionUpdate:null}),captured:C({onCompositionUpdateCapture:null})},dependencies:[P.topBlur,P.topCompositionUpdate,P.topKeyDown,P.topKeyPress,P.topKeyUp,P.topMouseDown]}},R=!1,w=null,O={eventTypes:I,extractEvents:function(e,t,n,r){return[l(e,t,n,r),d(e,t,n,r)]}};t.exports=O},{103:103,107:107,154:154,16:16,21:21,22:22,23:23}],4:[function(e,t,n){var r=e(147),o={addClass:function(e,t){return r(!/\s/.test(t)),t&&(e.classList?e.classList.add(t):o.hasClass(e,t)||(e.className=e.className+" "+t)),e},removeClass:function(e,t){return r(!/\s/.test(t)),t&&(e.classList?e.classList.remove(t):o.hasClass(e,t)&&(e.className=e.className.replace(new RegExp("(^|\\s)"+t+"(?:\\s|$)","g"),"$1").replace(/\s+/g," ").replace(/^\s*|\s*$/g,""))),e},conditionClass:function(e,t,n){return(n?o.addClass:o.removeClass)(e,t)},hasClass:function(e,t){return r(!/\s/.test(t)),e.classList?!!t&&e.classList.contains(t):(" "+e.className+" ").indexOf(" "+t+" ")>-1}};t.exports=o},{147:147}],5:[function(e,t,n){"use st
 rict";function r(e,t){return e+t.charAt(0).toUpperCase()+t.substring(1)}var o={boxFlex:!0,boxFlexGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0},i=["Webkit","ms","Moz","O"];Object.keys(o).forEach(function(e){i.forEach(function(t){o[r(t,e)]=o[e]})});var a={background:{backgroundImage:!0,backgroundPosition:!0,backgroundRepeat:!0,backgroundColor:!0},border:{borderWidth:!0,borderStyle:!0,borderColor:!0},borderBottom:{borderBottomWidth:!0,borderBottomStyle:!0,borderBottomColor:!0},borderLeft:{borderLeftWidth:!0,borderLeftStyle:!0,borderLeftColor:!0},borderRight:{borderRightWidth:!0,borderRightStyle:!0,borderRightColor:!0},borderTop:{borderTopWidth:!0,borderTopStyle:!0,borderTopColor:!0},font:{fontStyle:!0,fontVariant:!0,fontWeight:!0,fontSize:!0,lineHeight:!0,fontFamily:!0}},s={isU
 nitlessNumber:o,shorthandPropertyExpansions:a};t.exports=s},{}],6:[function(e,t,n){"use strict";var r=e(5),o=e(22),i=(e(118),e(125)),a=e(145),s=e(156),u=(e(166),s(function(e){return a(e)})),l="cssFloat";o.canUseDOM&&void 0===document.documentElement.style.cssFloat&&(l="styleFloat");var c={createMarkupForStyles:function(e){var t="";for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];null!=r&&(t+=u(n)+":",t+=i(n,r)+";")}return t||null},setValueForStyles:function(e,t){var n=e.style;for(var o in t)if(t.hasOwnProperty(o)){var a=i(o,t[o]);if("float"===o&&(o=l),a)n[o]=a;else{var s=r.shorthandPropertyExpansions[o];if(s)for(var u in s)n[u]="";else n[o]=""}}}};t.exports=c},{118:118,125:125,145:145,156:156,166:166,22:22,5:5}],7:[function(e,t,n){"use strict";function r(){this._callbacks=null,this._contexts=null}var o=e(30),i=e(29),a=e(147);i(r.prototype,{enqueue:function(e,t){this._callbacks=this._callbacks||[],this._contexts=this._contexts||[],this._callbacks.push(e),this._contexts.push(t)},noti
 fyAll:function(){var e=this._callbacks,t=this._contexts;if(e){a(e.length===t.length),this._callbacks=null,this._contexts=null;for(var n=0,r=e.length;r>n;n++)e[n].call(t[n]);e.length=0,t.length=0}},reset:function(){this._callbacks=null,this._contexts=null},destructor:function(){this.reset()}}),o.addPoolingTo(r),t.exports=r},{147:147,29:29,30:30}],8:[function(e,t,n){"use strict";function r(e){return"SELECT"===e.nodeName||"INPUT"===e.nodeName&&"file"===e.type}function o(e){var t=x.getPooled(P.change,R,e);E.accumulateTwoPhaseDispatches(t),_.batchedUpdates(i,t)}function i(e){C.enqueueEvents(e),C.processEventQueue()}function a(e,t){I=e,R=t,I.attachEvent("onchange",o)}function s(){I&&(I.detachEvent("onchange",o),I=null,R=null)}function u(e,t,n){return e===N.topChange?n:void 0}function l(e,t,n){e===N.topFocus?(s(),a(t,n)):e===N.topBlur&&s()}function c(e,t){I=e,R=t,w=e.value,O=Object.getOwnPropertyDescriptor(e.constructor.prototype,"value"),Object.defineProperty(I,"value",k),I.attachEvent("o
 npropertychange",d)}function p(){I&&(delete I.value,I.detachEvent("onpropertychange",d),I=null,R=null,w=null,O=null)}function d(e){if("value"===e.propertyName){var t=e.srcElement.value;t!==w&&(w=t,o(e))}}function f(e,t,n){return e===N.topInput?n:void 0}function h(e,t,n){e===N.topFocus?(p(),c(t,n)):e===N.topBlur&&p()}function m(e,t,n){return e!==N.topSelectionChange&&e!==N.topKeyUp&&e!==N.topKeyDown||!I||I.value===w?void 0:(w=I.value,R)}function v(e){return"INPUT"===e.nodeName&&("checkbox"===e.type||"radio"===e.type)}function g(e,t,n){return e===N.topClick?n:void 0}var y=e(16),C=e(18),E=e(21),b=e(22),_=e(97),x=e(105),D=e(148),M=e(150),T=e(154),N=y.topLevelTypes,P={change:{phasedRegistrationNames:{bubbled:T({onChange:null}),captured:T({onChangeCapture:null})},dependencies:[N.topBlur,N.topChange,N.topClick,N.topFocus,N.topInput,N.topKeyDown,N.topKeyUp,N.topSelectionChange]}},I=null,R=null,w=null,O=null,S=!1;b.canUseDOM&&(S=D("change")&&(!("documentMode"in document)||document.documentMo
 de>8));var A=!1;b.canUseDOM&&(A=D("input")&&(!("documentMode"in document)||document.documentMode>9));var k={get:function(){return O.get.call(this)},set:function(e){w=""+e,O.set.call(this,e)}},L={eventTypes:P,extractEvents:function(e,t,n,o){var i,a;if(r(t)?S?i=u:a=l:M(t)?A?i=f:(i=m,a=h):v(t)&&(i=g),i){var s=i(e,t,n);if(s){var c=x.getPooled(P.change,s,o);return E.accumulateTwoPhaseDispatches(c),c}}a&&a(e,t,n)}};t.exports=L},{105:105,148:148,150:150,154:154,16:16,18:18,21:21,22:22,97:97}],9:[function(e,t,n){"use strict";var r=0,o={createReactRootIndex:function(){return r++}};t.exports=o},{}],10:[function(e,t,n){"use strict";function r(e,t,n){e.insertBefore(t,e.childNodes[n]||null)}var o=e(13),i=e(77),a=e(160),s=e(147),u={dangerouslyReplaceNodeWithMarkup:o.dangerouslyReplaceNodeWithMarkup,updateTextContent:a,processUpdates:function(e,t){for(var n,u=null,l=null,c=0;c<e.length;c++)if(n=e[c],n.type===i.MOVE_EXISTING||n.type===i.REMOVE_NODE){var p=n.fromIndex,d=n.parentNode.childNodes[p],f=
 n.parentID;s(d),u=u||{},u[f]=u[f]||[],u[f][p]=d,l=l||[],l.push(d)}var h=o.dangerouslyRenderMarkup(t);if(l)for(var m=0;m<l.length;m++)l[m].parentNode.removeChild(l[m]);for(var v=0;v<e.length;v++)switch(n=e[v],n.type){case i.INSERT_MARKUP:r(n.parentNode,h[n.markupIndex],n.toIndex);break;case i.MOVE_EXISTING:r(n.parentNode,u[n.parentID][n.fromIndex],n.toIndex);break;case i.TEXT_CONTENT:a(n.parentNode,n.textContent);break;case i.REMOVE_NODE:}}};t.exports=u},{13:13,147:147,160:160,77:77}],11:[function(e,t,n){"use strict";function r(e,t){return(e&t)===t}var o=e(147),i={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(e){var t=e.Properties||{},n=e.DOMAttributeNames||{},a=e.DOMPropertyNames||{},u=e.DOMMutationMethods||{};e.isCustomAttribute&&s._isCustomAttributeFunctions.push(e.isCustomAttribute);for(var l in t){o(!s.isStandardName.hasOwnProperty
 (l)),s.isStandardName[l]=!0;var c=l.toLowerCase();if(s.getPossibleStandardName[c]=l,n.hasOwnProperty(l)){var p=n[l];s.getPossibleStandardName[p]=l,s.getAttributeName[l]=p}else s.getAttributeName[l]=c;s.getPropertyName[l]=a.hasOwnProperty(l)?a[l]:l,u.hasOwnProperty(l)?s.getMutationMethod[l]=u[l]:s.getMutationMethod[l]=null;var d=t[l];s.mustUseAttribute[l]=r(d,i.MUST_USE_ATTRIBUTE),s.mustUseProperty[l]=r(d,i.MUST_USE_PROPERTY),s.hasSideEffects[l]=r(d,i.HAS_SIDE_EFFECTS),s.hasBooleanValue[l]=r(d,i.HAS_BOOLEAN_VALUE),s.hasNumericValue[l]=r(d,i.HAS_NUMERIC_VALUE),s.hasPositiveNumericValue[l]=r(d,i.HAS_POSITIVE_NUMERIC_VALUE),s.hasOverloadedBooleanValue[l]=r(d,i.HAS_OVERLOADED_BOOLEAN_VALUE),o(!s.mustUseAttribute[l]||!s.mustUseProperty[l]),o(s.mustUseProperty[l]||!s.hasSideEffects[l]),o(!!s.hasBooleanValue[l]+!!s.hasNumericValue[l]+!!s.hasOverloadedBooleanValue[l]<=1)}}},a={},s={ID_ATTRIBUTE_NAME:"data-reactid",isStandardName:{},getPossibleStandardName:{},getAttributeName:{},getPropertyNa
 me:{},getMutationMethod:{},mustUseAttribute:{},mustUseProperty:{},hasSideEffects:{},hasBooleanValue:{},hasNumericValue:{},hasPositiveNumericValue:{},hasOverloadedBooleanValue:{},_isCustomAttributeFunctions:[],isCustomAttribute:function(e){for(var t=0;t<s._isCustomAttributeFunctions.length;t++){var n=s._isCustomAttributeFunctions[t];if(n(e))return!0}return!1},getDefaultValueForProperty:function(e,t){var n,r=a[e];return r||(a[e]=r={}),t in r||(n=document.createElement(e),r[t]=n[t]),r[t]},injection:i};t.exports=s},{147:147}],12:[function(e,t,n){"use strict";function r(e,t){return null==t||o.hasBooleanValue[e]&&!t||o.hasNumericValue[e]&&isNaN(t)||o.hasPositiveNumericValue[e]&&1>t||o.hasOverloadedBooleanValue[e]&&t===!1}var o=e(11),i=e(158),a=(e(166),{createMarkupForID:function(e){return o.ID_ATTRIBUTE_NAME+"="+i(e)},createMarkupForProperty:function(e,t){if(o.isStandardName.hasOwnProperty(e)&&o.isStandardName[e]){if(r(e,t))return"";var n=o.getAttributeName[e];return o.hasBooleanValue[e]|
 |o.hasOverloadedBooleanValue[e]&&t===!0?n:n+"="+i(t)}return o.isCustomAttribute(e)?null==t?"":e+"="+i(t):null},setValueForProperty:function(e,t,n){if(o.isStandardName.hasOwnProperty(t)&&o.isStandardName[t]){var i=o.getMutationMethod[t];if(i)i(e,n);else if(r(t,n))this.deleteValueForProperty(e,t);else if(o.mustUseAttribute[t])e.setAttribute(o.getAttributeName[t],""+n);else{var a=o.getPropertyName[t];o.hasSideEffects[t]&&""+e[a]==""+n||(e[a]=n)}}else o.isCustomAttribute(t)&&(null==n?e.removeAttribute(t):e.setAttribute(t,""+n))},deleteValueForProperty:function(e,t){if(o.isStandardName.hasOwnProperty(t)&&o.isStandardName[t]){var n=o.getMutationMethod[t];if(n)n(e,void 0);else if(o.mustUseAttribute[t])e.removeAttribute(o.getAttributeName[t]);else{var r=o.getPropertyName[t],i=o.getDefaultValueForProperty(e.nodeName,r);o.hasSideEffects[t]&&""+e[r]===i||(e[r]=i)}}else o.isCustomAttribute(t)&&e.removeAttribute(t)}});t.exports=a},{11:11,158:158,166:166}],13:[function(e,t,n){"use strict";functio
 n r(e){return e.substring(1,e.indexOf(" "))}var o=e(22),i=e(123),a=e(126),s=e(139),u=e(147),l=/^(<[^ \/>]+)/,c="data-danger-index",p={dangerouslyRenderMarkup:function(e){u(o.canUseDOM);for(var t,n={},p=0;p<e.length;p++)u(e[p]),t=r(e[p]),t=s(t)?t:"*",n[t]=n[t]||[],n[t][p]=e[p];var d=[],f=0;for(t in n)if(n.hasOwnProperty(t)){var h,m=n[t];for(h in m)if(m.hasOwnProperty(h)){var v=m[h];m[h]=v.replace(l,"$1 "+c+'="'+h+'" ')}for(var g=i(m.join(""),a),y=0;y<g.length;++y){var C=g[y];C.hasAttribute&&C.hasAttribute(c)&&(h=+C.getAttribute(c),C.removeAttribute(c),u(!d.hasOwnProperty(h)),d[h]=C,f+=1)}}return u(f===d.length),u(d.length===e.length),d},dangerouslyReplaceNodeWithMarkup:function(e,t){u(o.canUseDOM),u(t),u("html"!==e.tagName.toLowerCase());var n=i(t,a)[0];e.parentNode.replaceChild(n,e)}};t.exports=p},{123:123,126:126,139:139,147:147,22:22}],14:[function(e,t,n){"use strict";var r=e(154),o=[r({ResponderEventPlugin:null}),r({SimpleEventPlugin:null}),r({TapEventPlugin:null}),r({EnterLeaveE
 ventPlugin:null}),r({ChangeEventPlugin:null}),r({SelectEventPlugin:null}),r({BeforeInputEventPlugin:null}),r({AnalyticsEventPlugin:null}),r({MobileSafariClickEventPlugin:null})];t.exports=o},{154:154}],15:[function(e,t,n){"use strict";var r=e(16),o=e(21),i=e(109),a=e(75),s=e(154),u=r.topLevelTypes,l=a.getFirstReactDOM,c={mouseEnter:{registrationName:s({onMouseEnter:null}),dependencies:[u.topMouseOut,u.topMouseOver]},mouseLeave:{registrationName:s({onMouseLeave:null}),dependencies:[u.topMouseOut,u.topMouseOver]}},p=[null,null],d={eventTypes:c,extractEvents:function(e,t,n,r){if(e===u.topMouseOver&&(r.relatedTarget||r.fromElement))return null;if(e!==u.topMouseOut&&e!==u.topMouseOver)return null;var s;if(t.window===t)s=t;else{var d=t.ownerDocument;s=d?d.defaultView||d.parentWindow:window}var f,h;if(e===u.topMouseOut?(f=t,h=l(r.relatedTarget||r.toElement)||s):(f=s,h=t),f===h)return null;var m=f?a.getID(f):"",v=h?a.getID(h):"",g=i.getPooled(c.mouseLeave,m,r);g.type="mouseleave",g.target=f
 ,g.relatedTarget=h;var y=i.getPooled(c.mouseEnter,v,r);return y.type="mouseenter",y.target=h,y.relatedTarget=f,o.accumulateEnterLeaveDispatches(g,y,m,v),p[0]=g,p[1]=y,p}};t.exports=d},{109:109,154:154,16:16,21:21,75:75}],16:[function(e,t,n){"use strict";var r=e(153),o=r({bubbled:null,captured:null}),i=r({topBlur:null,topChange:null,topClick:null,topCompositionEnd:null,topCompositionStart:null,topCompositionUpdate:null,topContextMenu:null,topCopy:null,topCut:null,topDoubleClick:null,topDrag:null,topDragEnd:null,topDragEnter:null,topDragExit:null,topDragLeave:null,topDragOver:null,topDragStart:null,topDrop:null,topError:null,topFocus:null,topInput:null,topKeyDown:null,topKeyPress:null,topKeyUp:null,topLoad:null,topMouseDown:null,topMouseMove:null,topMouseOut:null,topMouseOver:null,topMouseUp:null,topPaste:null,topReset:null,topScroll:null,topSelectionChange:null,topSubmit:null,topTextInput:null,topTouchCancel:null,topTouchEnd:null,topTouchMove:null,topTouchStart:null,topWheel:null}),a
 ={topLevelTypes:i,PropagationPhases:o};t.exports=a},{153:153}],17:[function(e,t,n){var r=e(126),o={listen:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!1),{remove:function(){e.removeEventListener(t,n,!1)}}):e.attachEvent?(e.attachEvent("on"+t,n),{remove:function(){e.detachEvent("on"+t,n)}}):void 0},capture:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!0),{remove:function(){e.removeEventListener(t,n,!0)}}):{remove:r}},registerDefault:function(){}};t.exports=o},{126:126}],18:[function(e,t,n){"use strict";var r=e(19),o=e(20),i=e(115),a=e(132),s=e(147),u={},l=null,c=function(e){if(e){var t=o.executeDispatch,n=r.getPluginModuleForEvent(e);n&&n.executeDispatch&&(t=n.executeDispatch),o.executeDispatchesInOrder(e,t),e.isPersistent()||e.constructor.release(e)}},p=null,d={injection:{injectMount:o.injection.injectMount,injectInstanceHandle:function(e){p=e},getInstanceHandle:function(){return p},injectEventPluginOrder:r.injectEventPluginOrder,injectEven
 tPluginsByName:r.injectEventPluginsByName},eventNameDispatchConfigs:r.eventNameDispatchConfigs,registrationNameModules:r.registrationNameModules,putListener:function(e,t,n){s(!n||"function"==typeof n);var r=u[t]||(u[t]={});r[e]=n},getListener:function(e,t){var n=u[t];return n&&n[e]},deleteListener:function(e,t){var n=u[t];n&&delete n[e]},deleteAllListeners:function(e){for(var t in u)delete u[t][e]},extractEvents:function(e,t,n,o){for(var a,s=r.plugins,u=0,l=s.length;l>u;u++){var c=s[u];if(c){var p=c.extractEvents(e,t,n,o);p&&(a=i(a,p))}}return a},enqueueEvents:function(e){e&&(l=i(l,e))},processEventQueue:function(){var e=l;l=null,a(e,c),s(!l)},__purge:function(){u={}},__getListenerBank:function(){return u}};t.exports=d},{115:115,132:132,147:147,19:19,20:20}],19:[function(e,t,n){"use strict";function r(){if(s)for(var e in u){var t=u[e],n=s.indexOf(e);if(a(n>-1),!l.plugins[n]){a(t.extractEvents),l.plugins[n]=t;var r=t.eventTypes;for(var i in r)a(o(r[i],t,i))}}}function o(e,t,n){a(!l.e
 ventNameDispatchConfigs.hasOwnProperty(n)),l.eventNameDispatchConfigs[n]=e;var r=e.phasedRegistrationNames;if(r){for(var o in r)if(r.hasOwnProperty(o)){var s=r[o];i(s,t,n)}return!0}return e.registrationName?(i(e.registrationName,t,n),!0):!1}function i(e,t,n){a(!l.registrationNameModules[e]),l.registrationNameModules[e]=t,l.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var a=e(147),s=null,u={},l={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(e){a(!s),s=Array.prototype.slice.call(e),r()},injectEventPluginsByName:function(e){var t=!1;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];u.hasOwnProperty(n)&&u[n]===o||(a(!u[n]),u[n]=o,t=!0)}t&&r()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return l.registrationNameModules[t.registrationName]||null;for(var n in t.phasedRegistrationNames)if(t.phasedRegistrationNames.hasOwnProperty(n)){var r=l.registrationNa
 meModules[t.phasedRegistrationNames[n]];if(r)return r}return null},_resetEventPlugins:function(){s=null;for(var e in u)u.hasOwnProperty(e)&&delete u[e];l.plugins.length=0;var t=l.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=l.registrationNameModules;for(var o in r)r.hasOwnProperty(o)&&delete r[o]}};t.exports=l},{147:147}],20:[function(e,t,n){"use strict";function r(e){return e===v.topMouseUp||e===v.topTouchEnd||e===v.topTouchCancel}function o(e){return e===v.topMouseMove||e===v.topTouchMove}function i(e){return e===v.topMouseDown||e===v.topTouchStart}function a(e,t){var n=e._dispatchListeners,r=e._dispatchIDs;if(Array.isArray(n))for(var o=0;o<n.length&&!e.isPropagationStopped();o++)t(e,n[o],r[o]);else n&&t(e,n,r)}function s(e,t,n){e.currentTarget=m.Mount.getNode(n);var r=t(e,n);return e.currentTarget=null,r}function u(e,t){a(e,t),e._dispatchListeners=null,e._dispatchIDs=null}function l(e){var t=e._dispatchListeners,n=e._dispatchIDs;if(Array.isArray(
 t)){for(var r=0;r<t.length&&!e.isPropagationStopped();r++)if(t[r](e,n[r]))return n[r]}else if(t&&t(e,n))return n;return null}function c(e){var t=l(e);return e._dispatchIDs=null,e._dispatchListeners=null,t}function p(e){var t=e._dispatchListeners,n=e._dispatchIDs;h(!Array.isArray(t));var r=t?t(e,n):null;return e._dispatchListeners=null,e._dispatchIDs=null,r}function d(e){return!!e._dispatchListeners}var f=e(16),h=e(147),m={Mount:null,injectMount:function(e){m.Mount=e}},v=f.topLevelTypes,g={isEndish:r,isMoveish:o,isStartish:i,executeDirectDispatch:p,executeDispatch:s,executeDispatchesInOrder:u,executeDispatchesInOrderStopAtTrue:c,hasDispatches:d,injection:m,useTouchEvents:!1};t.exports=g},{147:147,16:16}],21:[function(e,t,n){"use strict";function r(e,t,n){var r=t.dispatchConfig.phasedRegistrationNames[n];return v(e,r)}function o(e,t,n){var o=t?m.bubbled:m.captured,i=r(e,n,o);i&&(n._dispatchListeners=f(n._dispatchListeners,i),n._dispatchIDs=f(n._dispatchIDs,e))}function i(e){e&&e.dispa
 tchConfig.phasedRegistrationNames&&d.injection.getInstanceHandle().traverseTwoPhase(e.dispatchMarker,o,e)}function a(e,t,n){if(n&&n.dispatchConfig.registrationName){var r=n.dispatchConfig.registrationName,o=v(e,r);o&&(n._dispatchListeners=f(n._dispatchListeners,o),n._dispatchIDs=f(n._dispatchIDs,e))}}function s(e){e&&e.dispatchConfig.registrationName&&a(e.dispatchMarker,null,e)}function u(e){h(e,i)}function l(e,t,n,r){d.injection.getInstanceHandle().traverseEnterLeave(n,r,a,e,t)}function c(e){h(e,s)}var p=e(16),d=e(18),f=e(115),h=e(132),m=p.PropagationPhases,v=d.getListener,g={accumulateTwoPhaseDispatches:u,accumulateDirectDispatches:c,accumulateEnterLeaveDispatches:l};t.exports=g},{115:115,132:132,16:16,18:18}],22:[function(e,t,n){"use strict";var r=!("undefined"==typeof window||!window.document||!window.document.createElement),o={canUseDOM:r,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:r&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:r&&!!window.
 screen,isInWorker:!r};t.exports=o},{}],23:[function(e,t,n){"use strict";function r(e){this._root=e,this._startText=this.getText(),this._fallbackText=null}var o=e(30),i=e(29),a=e(142);i(r.prototype,{getText:function(){return"value"in this._root?this._root.value:this._root[a()]},getData:function(){if(this._fallbackText)return this._fallbackText;var e,t,n=this._startText,r=n.length,o=this.getText(),i=o.length;for(e=0;r>e&&n[e]===o[e];e++);var a=r-e;for(t=1;a>=t&&n[r-t]===o[i-t];t++);var s=t>1?1-t:void 0;return this._fallbackText=o.slice(e,s),this._fallbackText}}),o.addPoolingTo(r),t.exports=r},{142:142,29:29,30:30}],24:[function(e,t,n){"use strict";var r,o=e(11),i=e(22),a=o.injection.MUST_USE_ATTRIBUTE,s=o.injection.MUST_USE_PROPERTY,u=o.injection.HAS_BOOLEAN_VALUE,l=o.injection.HAS_SIDE_EFFECTS,c=o.injection.HAS_NUMERIC_VALUE,p=o.injection.HAS_POSITIVE_NUMERIC_VALUE,d=o.injection.HAS_OVERLOADED_BOOLEAN_VALUE;if(i.canUseDOM){var f=document.implementation;r=f&&f.hasFeature&&f.hasFeature
 ("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}var h={isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),Properties:{accept:null,acceptCharset:null,accessKey:null,action:null,allowFullScreen:a|u,allowTransparency:a,alt:null,async:u,autoComplete:null,autoPlay:u,cellPadding:null,cellSpacing:null,charSet:a,checked:s|u,classID:a,className:r?a:s,cols:a|p,colSpan:null,content:null,contentEditable:null,contextMenu:a,controls:s|u,coords:null,crossOrigin:null,data:null,dateTime:a,defer:u,dir:null,disabled:a|u,download:d,draggable:null,encType:null,form:a,formAction:a,formEncType:a,formMethod:a,formNoValidate:u,formTarget:a,frameBorder:a,headers:null,height:a,hidden:a|u,high:null,href:null,hrefLang:null,htmlFor:null,httpEquiv:null,icon:null,id:s,label:null,lang:null,list:a,loop:s|u,low:null,manifest:a,marginHeight:null,marginWidth:null,max:null,maxLength:a,media:a,mediaGroup:null,method:null,min:null,multiple:s|u,muted:s|u,name:null,noValidate:u,open
 :u,optimum:null,pattern:null,placeholder:null,poster:null,preload:null,radioGroup:null,readOnly:s|u,rel:null,required:u,role:a,rows:a|p,rowSpan:null,sandbox:null,scope:null,scoped:u,scrolling:null,seamless:a|u,selected:s|u,shape:null,size:a|p,sizes:a,span:p,spellCheck:null,src:null,srcDoc:s,srcSet:a,start:c,step:null,style:null,tabIndex:null,target:null,title:null,type:null,useMap:null,value:s|l,width:a,wmode:a,autoCapitalize:null,autoCorrect:null,itemProp:a,itemScope:a|u,itemType:a,itemID:a,itemRef:a,property:null,unselectable:a},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{autoCapitalize:"autocapitalize",autoComplete:"autocomplete",autoCorrect:"autocorrect",autoFocus:"autofocus",autoPlay:"autoplay",encType:"encoding",hrefLang:"hreflang",radioGroup:"radiogroup",spellCheck:"spellcheck",srcDoc:"srcdoc",srcSet:"srcset"}};t.exports=h},{11:11,22:22}],25:[function(e,t,n){"use strict";var r=e(73),o=e(92),i={lin
 kState:function(e){return new r(this.state[e],o.createStateKeySetter(this,e))}};t.exports=i},{73:73,92:92}],26:[function(e,t,n){"use strict";function r(e){l(null==e.props.checkedLink||null==e.props.valueLink)}function o(e){r(e),l(null==e.props.value&&null==e.props.onChange)}function i(e){r(e),l(null==e.props.checked&&null==e.props.onChange)}function a(e){this.props.valueLink.requestChange(e.target.value)}function s(e){this.props.checkedLink.requestChange(e.target.checked)}var u=e(84),l=e(147),c={button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0},p={Mixin:{propTypes:{value:function(e,t,n){return!e[t]||c[e.type]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.")},checked:function(e,t,n){return!e[t]||e.onChange||e.readOnly||e.disabled?null:new Error("You pro
 vided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")},onChange:u.func}},getValue:function(e){return e.props.valueLink?(o(e),e.props.valueLink.value):e.props.value},getChecked:function(e){return e.props.checkedLink?(i(e),e.props.checkedLink.value):e.props.checked},getOnChange:function(e){return e.props.valueLink?(o(e),a):e.props.checkedLink?(i(e),s):e.props.onChange}};t.exports=p},{147:147,84:84}],27:[function(e,t,n){"use strict";function r(e){e.remove()}var o=e(33),i=e(115),a=e(132),s=e(147),u={trapBubbledEvent:function(e,t){s(this.isMounted());var n=this.getDOMNode();s(n);var r=o.trapBubbledEvent(e,t,n);this._localEventListeners=i(this._localEventListeners,r)},componentWillUnmount:function(){this._localEventListeners&&a(this._localEventListeners,r)}};t.exports=u},{115:115,132:132,147:147,33:33}],28:[function(e,t,n){"use strict";
 var r=e(16),o=e(126),i=r.topLevelTypes,a={eventTypes:null,extractEvents:function(e,t,n,r){if(e===i.topTouchStart){var a=r.target;a&&!a.onclick&&(a.onclick=o)}}};t.exports=a},{126:126,16:16}],29:[function(e,t,n){"use strict";function r(e,t){if(null==e)throw new TypeError("Object.assign target cannot be null or undefined");for(var n=Object(e),r=Object.prototype.hasOwnProperty,o=1;o<arguments.length;o++){var i=arguments[o];if(null!=i){var a=Object(i);for(var s in a)r.call(a,s)&&(n[s]=a[s])}}return n}t.exports=r},{}],30:[function(e,t,n){"use strict";var r=e(147),o=function(e){var t=this;if(t.instancePool.length){var n=t.instancePool.pop();return t.call(n,e),n}return new t(e)},i=function(e,t){var n=this;if(n.instancePool.length){var r=n.instancePool.pop();return n.call(r,e,t),r}return new n(e,t)},a=function(e,t,n){var r=this;if(r.instancePool.length){var o=r.instancePool.pop();return r.call(o,e,t,n),o}return new r(e,t,n)},s=function(e,t,n,r,o){var i=this;if(i.instancePool.length){var a=i
 .instancePool.pop();return i.call(a,e,t,n,r,o),a}return new i(e,t,n,r,o)},u=function(e){var t=this;r(e instanceof t),e.destructor&&e.destructor(),t.instancePool.length<t.poolSize&&t.instancePool.push(e)},l=10,c=o,p=function(e,t){var n=e;return n.instancePool=[],n.getPooled=t||c,n.poolSize||(n.poolSize=l),n.release=u,n},d={addPoolingTo:p,oneArgumentPooler:o,twoArgumentPooler:i,threeArgumentPooler:a,fiveArgumentPooler:s};t.exports=d},{147:147}],31:[function(e,t,n){"use strict";var r=e(20),o=e(37),i=e(39),a=e(38),s=e(44),u=e(45),l=e(61),c=(e(62),e(46)),p=e(57),d=e(60),f=e(70),h=e(75),m=e(80),v=e(84),g=e(87),y=e(90),C=e(29),E=e(129),b=e(157);d.inject();var _=l.createElement,x=l.createFactory,D=l.cloneElement,M=m.measure("React","render",h.render),T={Children:{map:o.map,forEach:o.forEach,count:o.count,only:b},Component:i,DOM:c,PropTypes:v,initializeTouchEvents:function(e){r.useTouchEvents=e},createClass:a.createClass,createElement:_,cloneElement:D,createFactory:x,createMixin:function(e){
 return e},constructAndRenderComponent:h.constructAndRenderComponent,constructAndRenderComponentByID:h.constructAndRenderComponentByID,findDOMNode:E,render:M,renderToString:y.renderToString,renderToStaticMarkup:y.renderToStaticMarkup,unmountComponentAtNode:h.unmountComponentAtNode,isValidElement:l.isValidElement,withContext:s.withContext,__spread:C};"undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject&&__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({CurrentOwner:u,InstanceHandles:f,Mount:h,Reconciler:g,TextComponent:p});T.version="0.13.3",t.exports=T},{129:129,157:157,20:20,29:29,37:37,38:38,39:39,44:44,45:45,46:46,57:57,60:60,61:61,62:62,70:70,75:75,80:80,84:84,87:87,90:90}],32:[function(e,t,n){"use strict";var r=e(129),o={getDOMNode:function(){return r(this)}};t.exports=o},{129:129}],33:[function(e,t,n){"use strict";function r(e){return Object.prototype.hasOwnProperty.call(e,m)||(e[m]=f++,p[e[m]]={}),p[e[m]]}var o=e(16),i=e(18),a=e(19)
 ,s=e(65),u=e(114),l=e(29),c=e(148),p={},d=!1,f=0,h={topBlur:"blur",topChange:"change",topClick:"click",topCompositionEnd:"compositionend",topCompositionStart:"compositionstart",topCompositionUpdate:"compositionupdate",topContextMenu:"contextmenu",topCopy:"copy",topCut:"cut",topDoubleClick:"dblclick",topDrag:"drag",topDragEnd:"dragend",topDragEnter:"dragenter",topDragExit:"dragexit",topDragLeave:"dragleave",topDragOver:"dragover",topDragStart:"dragstart",topDrop:"drop",topFocus:"focus",topInput:"input",topKeyDown:"keydown",topKeyPress:"keypress",topKeyUp:"keyup",topMouseDown:"mousedown",topMouseMove:"mousemove",topMouseOut:"mouseout",topMouseOver:"mouseover",topMouseUp:"mouseup",topPaste:"paste",topScroll:"scroll",topSelectionChange:"selectionchange",topTextInput:"textInput",topTouchCancel:"touchcancel",topTouchEnd:"touchend",topTouchMove:"touchmove",topTouchStart:"touchstart",topWheel:"wheel"},m="_reactListenersID"+String(Math.random()).slice(2),v=l({},s,{ReactEventListener:null,inj
 ection:{injectReactEventListener:function(e){e.setHandleTopLevel(v.handleTopLevel),v.ReactEventListener=e;
+
+}},setEnabled:function(e){v.ReactEventListener&&v.ReactEventListener.setEnabled(e)},isEnabled:function(){return!(!v.ReactEventListener||!v.ReactEventListener.isEnabled())},listenTo:function(e,t){for(var n=t,i=r(n),s=a.registrationNameDependencies[e],u=o.topLevelTypes,l=0,p=s.length;p>l;l++){var d=s[l];i.hasOwnProperty(d)&&i[d]||(d===u.topWheel?c("wheel")?v.ReactEventListener.trapBubbledEvent(u.topWheel,"wheel",n):c("mousewheel")?v.ReactEventListener.trapBubbledEvent(u.topWheel,"mousewheel",n):v.ReactEventListener.trapBubbledEvent(u.topWheel,"DOMMouseScroll",n):d===u.topScroll?c("scroll",!0)?v.ReactEventListener.trapCapturedEvent(u.topScroll,"scroll",n):v.ReactEventListener.trapBubbledEvent(u.topScroll,"scroll",v.ReactEventListener.WINDOW_HANDLE):d===u.topFocus||d===u.topBlur?(c("focus",!0)?(v.ReactEventListener.trapCapturedEvent(u.topFocus,"focus",n),v.ReactEventListener.trapCapturedEvent(u.topBlur,"blur",n)):c("focusin")&&(v.ReactEventListener.trapBubbledEvent(u.topFocus,"focusin",
 n),v.ReactEventListener.trapBubbledEvent(u.topBlur,"focusout",n)),i[u.topBlur]=!0,i[u.topFocus]=!0):h.hasOwnProperty(d)&&v.ReactEventListener.trapBubbledEvent(d,h[d],n),i[d]=!0)}},trapBubbledEvent:function(e,t,n){return v.ReactEventListener.trapBubbledEvent(e,t,n)},trapCapturedEvent:function(e,t,n){return v.ReactEventListener.trapCapturedEvent(e,t,n)},ensureScrollValueMonitoring:function(){if(!d){var e=u.refreshScrollValues;v.ReactEventListener.monitorScrollValue(e),d=!0}},eventNameDispatchConfigs:i.eventNameDispatchConfigs,registrationNameModules:i.registrationNameModules,putListener:i.putListener,getListener:i.getListener,deleteListener:i.deleteListener,deleteAllListeners:i.deleteAllListeners});t.exports=v},{114:114,148:148,16:16,18:18,19:19,29:29,65:65}],34:[function(e,t,n){"use strict";var r=e(31),o=e(29),i=r.createFactory(e(95)),a=r.createFactory(e(35)),s=r.createClass({displayName:"ReactCSSTransitionGroup",propTypes:{transitionName:r.PropTypes.string.isRequired,transitionAppea
 r:r.PropTypes.bool,transitionEnter:r.PropTypes.bool,transitionLeave:r.PropTypes.bool},getDefaultProps:function(){return{transitionAppear:!1,transitionEnter:!0,transitionLeave:!0}},_wrapChild:function(e){return a({name:this.props.transitionName,appear:this.props.transitionAppear,enter:this.props.transitionEnter,leave:this.props.transitionLeave},e)},render:function(){return i(o({},this.props,{childFactory:this._wrapChild}))}});t.exports=s},{29:29,31:31,35:35,95:95}],35:[function(e,t,n){"use strict";var r=e(31),o=e(4),i=e(94),a=e(157),s=(e(166),17),u=r.createClass({displayName:"ReactCSSTransitionGroupChild",transition:function(e,t){var n=this.getDOMNode(),r=this.props.name+"-"+e,a=r+"-active",s=function(e){e&&e.target!==n||(o.removeClass(n,r),o.removeClass(n,a),i.removeEndEventListener(n,s),t&&t())};i.addEndEventListener(n,s),o.addClass(n,r),this.queueClass(a)},queueClass:function(e){this.classNameQueue.push(e),this.timeout||(this.timeout=setTimeout(this.flushClassNameQueue,s))},flushC
 lassNameQueue:function(){this.isMounted()&&this.classNameQueue.forEach(o.addClass.bind(o,this.getDOMNode())),this.classNameQueue.length=0,this.timeout=null},componentWillMount:function(){this.classNameQueue=[]},componentWillUnmount:function(){this.timeout&&clearTimeout(this.timeout)},componentWillAppear:function(e){this.props.appear?this.transition("appear",e):e()},componentWillEnter:function(e){this.props.enter?this.transition("enter",e):e()},componentWillLeave:function(e){this.props.leave?this.transition("leave",e):e()},render:function(){return a(this.props.children)}});t.exports=u},{157:157,166:166,31:31,4:4,94:94}],36:[function(e,t,n){"use strict";var r=e(87),o=e(130),i=e(146),a=e(162),s={instantiateChildren:function(e,t,n){var r=o(e);for(var a in r)if(r.hasOwnProperty(a)){var s=r[a],u=i(s,null);r[a]=u}return r},updateChildren:function(e,t,n,s){var u=o(t);if(!u&&!e)return null;var l;for(l in u)if(u.hasOwnProperty(l)){var c=e&&e[l],p=c&&c._currentElement,d=u[l];if(a(p,d))r.receiv
 eComponent(c,d,n,s),u[l]=c;else{c&&r.unmountComponent(c,l);var f=i(d,null);u[l]=f}}for(l in e)!e.hasOwnProperty(l)||u&&u.hasOwnProperty(l)||r.unmountComponent(e[l]);return u},unmountChildren:function(e){for(var t in e){var n=e[t];r.unmountComponent(n)}}};t.exports=s},{130:130,146:146,162:162,87:87}],37:[function(e,t,n){"use strict";function r(e,t){this.forEachFunction=e,this.forEachContext=t}function o(e,t,n,r){var o=e;o.forEachFunction.call(o.forEachContext,t,r)}function i(e,t,n){if(null==e)return e;var i=r.getPooled(t,n);f(e,o,i),r.release(i)}function a(e,t,n){this.mapResult=e,this.mapFunction=t,this.mapContext=n}function s(e,t,n,r){var o=e,i=o.mapResult,a=!i.hasOwnProperty(n);if(a){var s=o.mapFunction.call(o.mapContext,t,r);i[n]=s}}function u(e,t,n){if(null==e)return e;var r={},o=a.getPooled(r,t,n);return f(e,s,o),a.release(o),d.create(r)}function l(e,t,n,r){return null}function c(e,t){return f(e,l,null)}var p=e(30),d=e(67),f=e(164),h=(e(166),p.twoArgumentPooler),m=p.threeArgumen
 tPooler;p.addPoolingTo(r,h),p.addPoolingTo(a,m);var v={forEach:i,map:u,count:c};t.exports=v},{164:164,166:166,30:30,67:67}],38:[function(e,t,n){"use strict";function r(e,t){var n=D.hasOwnProperty(t)?D[t]:null;T.hasOwnProperty(t)&&y(n===_.OVERRIDE_BASE),e.hasOwnProperty(t)&&y(n===_.DEFINE_MANY||n===_.DEFINE_MANY_MERGED)}function o(e,t){if(t){y("function"!=typeof t),y(!d.isValidElement(t));var n=e.prototype;t.hasOwnProperty(b)&&M.mixins(e,t.mixins);for(var o in t)if(t.hasOwnProperty(o)&&o!==b){var i=t[o];if(r(n,o),M.hasOwnProperty(o))M[o](e,i);else{var a=D.hasOwnProperty(o),l=n.hasOwnProperty(o),c=i&&i.__reactDontBind,p="function"==typeof i,f=p&&!a&&!l&&!c;if(f)n.__reactAutoBindMap||(n.__reactAutoBindMap={}),n.__reactAutoBindMap[o]=i,n[o]=i;else if(l){var h=D[o];y(a&&(h===_.DEFINE_MANY_MERGED||h===_.DEFINE_MANY)),h===_.DEFINE_MANY_MERGED?n[o]=s(n[o],i):h===_.DEFINE_MANY&&(n[o]=u(n[o],i))}else n[o]=i}}}}function i(e,t){if(t)for(var n in t){var r=t[n];if(t.hasOwnProperty(n)){var o=n in 
 M;y(!o);var i=n in e;y(!i),e[n]=r}}}function a(e,t){y(e&&t&&"object"==typeof e&&"object"==typeof t);for(var n in t)t.hasOwnProperty(n)&&(y(void 0===e[n]),e[n]=t[n]);return e}function s(e,t){return function(){var n=e.apply(this,arguments),r=t.apply(this,arguments);if(null==n)return r;if(null==r)return n;var o={};return a(o,n),a(o,r),o}}function u(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}function l(e,t){var n=t.bind(e);return n}function c(e){for(var t in e.__reactAutoBindMap)if(e.__reactAutoBindMap.hasOwnProperty(t)){var n=e.__reactAutoBindMap[t];e[t]=l(e,f.guard(n,e.constructor.displayName+"."+t))}}var p=e(39),d=(e(45),e(61)),f=e(64),h=e(71),m=e(72),v=(e(83),e(82),e(96)),g=e(29),y=e(147),C=e(153),E=e(154),b=(e(166),E({mixins:null})),_=C({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),x=[],D={mixins:_.DEFINE_MANY,statics:_.DEFINE_MANY,propTypes:_.DEFINE_MANY,contextTypes:_.DEFINE_MANY,childContextTypes:_.DEFINE_MANY,getDef
 aultProps:_.DEFINE_MANY_MERGED,getInitialState:_.DEFINE_MANY_MERGED,getChildContext:_.DEFINE_MANY_MERGED,render:_.DEFINE_ONCE,componentWillMount:_.DEFINE_MANY,componentDidMount:_.DEFINE_MANY,componentWillReceiveProps:_.DEFINE_MANY,shouldComponentUpdate:_.DEFINE_ONCE,componentWillUpdate:_.DEFINE_MANY,componentDidUpdate:_.DEFINE_MANY,componentWillUnmount:_.DEFINE_MANY,updateComponent:_.OVERRIDE_BASE},M={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n<t.length;n++)o(e,t[n])},childContextTypes:function(e,t){e.childContextTypes=g({},e.childContextTypes,t)},contextTypes:function(e,t){e.contextTypes=g({},e.contextTypes,t)},getDefaultProps:function(e,t){e.getDefaultProps?e.getDefaultProps=s(e.getDefaultProps,t):e.getDefaultProps=t},propTypes:function(e,t){e.propTypes=g({},e.propTypes,t)},statics:function(e,t){i(e,t)}},T={replaceState:function(e,t){v.enqueueReplaceState(this,e),t&&v.enqueueCallback(this,t)},isMounted:function(){var e=h.get(this);return e&&e
 !==m.currentlyMountingInstance},setProps:function(e,t){v.enqueueSetProps(this,e),t&&v.enqueueCallback(this,t)},replaceProps:function(e,t){v.enqueueReplaceProps(this,e),t&&v.enqueueCallback(this,t)}},N=function(){};g(N.prototype,p.prototype,T);var P={createClass:function(e){var t=function(e,t){this.__reactAutoBindMap&&c(this),this.props=e,this.context=t,this.state=null;var n=this.getInitialState?this.getInitialState():null;y("object"==typeof n&&!Array.isArray(n)),this.state=n};t.prototype=new N,t.prototype.constructor=t,x.forEach(o.bind(null,t)),o(t,e),t.getDefaultProps&&(t.defaultProps=t.getDefaultProps()),y(t.prototype.render);for(var n in D)t.prototype[n]||(t.prototype[n]=null);return t.type=t,t},injection:{injectMixin:function(e){x.push(e)}}};t.exports=P},{147:147,153:153,154:154,166:166,29:29,39:39,45:45,61:61,64:64,71:71,72:72,82:82,83:83,96:96}],39:[function(e,t,n){"use strict";function r(e,t){this.props=e,this.context=t}{var o=e(96),i=e(147);e(166)}r.prototype.setState=functi
 on(e,t){i("object"==typeof e||"function"==typeof e||null==e),o.enqueueSetState(this,e),t&&o.enqueueCallback(this,t)},r.prototype.forceUpdate=function(e){o.enqueueForceUpdate(this),e&&o.enqueueCallback(this,e)};t.exports=r},{147:147,166:166,96:96}],40:[function(e,t,n){"use strict";var r=e(50),o=e(75),i={processChildrenUpdates:r.dangerouslyProcessChildrenUpdates,replaceNodeWithMarkupByID:r.dangerouslyReplaceNodeWithMarkupByID,unmountIDFromEnvironment:function(e){o.purgeID(e)}};t.exports=i},{50:50,75:75}],41:[function(e,t,n){"use strict";var r=e(147),o=!1,i={unmountIDFromEnvironment:null,replaceNodeWithMarkupByID:null,processChildrenUpdates:null,injection:{injectEnvironment:function(e){r(!o),i.unmountIDFromEnvironment=e.unmountIDFromEnvironment,i.replaceNodeWithMarkupByID=e.replaceNodeWithMarkupByID,i.processChildrenUpdates=e.processChildrenUpdates,o=!0}}};t.exports=i},{147:147}],42:[function(e,t,n){"use strict";var r=e(161),o={shouldComponentUpdate:function(e,t){return!r(this.props,e)
 ||!r(this.state,t)}};t.exports=o},{161:161}],43:[function(e,t,n){"use strict";function r(e){var t=e._currentElement._owner||null;if(t){var n=t.getName();if(n)return" Check the render method of `"+n+"`."}return""}var o=e(41),i=e(44),a=e(45),s=e(61),u=(e(62),e(71)),l=e(72),c=e(78),p=e(80),d=e(83),f=(e(82),e(87)),h=e(97),m=e(29),v=e(127),g=e(147),y=e(162),C=(e(166),1),E={construct:function(e){this._currentElement=e,this._rootNodeID=null,this._instance=null,this._pendingElement=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._renderedComponent=null,this._context=null,this._mountOrder=0,this._isTopLevel=!1,this._pendingCallbacks=null},mountComponent:function(e,t,n){this._context=n,this._mountOrder=C++,this._rootNodeID=e;var r=this._processProps(this._currentElement.props),o=this._processContext(this._currentElement._context),i=c.getComponentClassForElement(this._currentElement),a=new i(r,o);a.props=r,a.context=o,a.refs=v,this._instance=a,u.
 set(a,this);var s=a.state;void 0===s&&(a.state=s=null),g("object"==typeof s&&!Array.isArray(s)),this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1;var p,d,h=l.currentlyMountingInstance;l.currentlyMountingInstance=this;try{a.componentWillMount&&(a.componentWillMount(),this._pendingStateQueue&&(a.state=this._processPendingState(a.props,a.context))),p=this._getValidatedChildContext(n),d=this._renderValidatedComponent(p)}finally{l.currentlyMountingInstance=h}this._renderedComponent=this._instantiateReactComponent(d,this._currentElement.type);var m=f.mountComponent(this._renderedComponent,e,t,this._mergeChildContext(n,p));return a.componentDidMount&&t.getReactMountReady().enqueue(a.componentDidMount,a),m},unmountComponent:function(){var e=this._instance;if(e.componentWillUnmount){var t=l.currentlyUnmountingInstance;l.currentlyUnmountingInstance=this;try{e.componentWillUnmount()}finally{l.currentlyUnmountingInstance=t}}f.unmountComponent(this._renderedCo
 mponent),this._renderedComponent=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._pendingCallbacks=null,this._pendingElement=null,this._context=null,this._rootNodeID=null,u.remove(e)},_setPropsInternal:function(e,t){var n=this._pendingElement||this._currentElement;this._pendingElement=s.cloneAndReplaceProps(n,m({},n.props,e)),h.enqueueUpdate(this,t)},_maskContext:function(e){var t=null;if("string"==typeof this._currentElement.type)return v;var n=this._currentElement.type.contextTypes;if(!n)return v;t={};for(var r in n)t[r]=e[r];return t},_processContext:function(e){var t=this._maskContext(e);return t},_getValidatedChildContext:function(e){var t=this._instance,n=t.getChildContext&&t.getChildContext();if(n){g("object"==typeof t.constructor.childContextTypes);for(var r in n)g(r in t.constructor.childContextTypes);return n}return null},_mergeChildContext:function(e,t){return t?m({},e,t):e},_processProps:function(e){return e},_checkPropType
 s:function(e,t,n){var o=this.getName();for(var i in e)if(e.hasOwnProperty(i)){var a;try{g("function"==typeof e[i]),a=e[i](t,i,o,n)}catch(s){a=s}a instanceof Error&&(r(this),n===d.prop)}},receiveComponent:function(e,t,n){var r=this._currentElement,o=this._context;this._pendingElement=null,this.updateComponent(t,r,e,o,n)},performUpdateIfNecessary:function(e){null!=this._pendingElement&&f.receiveComponent(this,this._pendingElement||this._currentElement,e,this._context),(null!==this._pendingStateQueue||this._pendingForceUpdate)&&this.updateComponent(e,this._currentElement,this._currentElement,this._context,this._context)},_warnIfContextsDiffer:function(e,t){e=this._maskContext(e),t=this._maskContext(t);for(var n=Object.keys(t).sort(),r=(this.getName()||"ReactCompositeComponent",0);r<n.length;r++)n[r]},updateComponent:function(e,t,n,r,o){var i=this._instance,a=i.context,s=i.props;t!==n&&(a=this._processContext(n._context),s=this._processProps(n.props),i.componentWillReceiveProps&&i.compo
 nentWillReceiveProps(s,a));var u=this._processPendingState(s,a),l=this._pendingForceUpdate||!i.shouldComponentUpdate||i.shouldComponentUpdate(s,u,a);l?(this._pendingForceUpdate=!1,this._performComponentUpdate(n,s,u,a,e,o)):(this._currentElement=n,this._context=o,i.props=s,i.state=u,i.context=a)},_processPendingState:function(e,t){var n=this._instance,r=this._pendingStateQueue,o=this._pendingReplaceState;if(this._pendingReplaceState=!1,this._pendingStateQueue=null,!r)return n.state;if(o&&1===r.length)return r[0];for(var i=m({},o?r[0]:n.state),a=o?1:0;a<r.length;a++){var s=r[a];m(i,"function"==typeof s?s.call(n,i,e,t):s)}return i},_performComponentUpdate:function(e,t,n,r,o,i){var a=this._instance,s=a.props,u=a.state,l=a.context;a.componentWillUpdate&&a.componentWillUpdate(t,n,r),this._currentElement=e,this._context=i,a.props=t,a.state=n,a.context=r,this._updateRenderedComponent(o,i),a.componentDidUpdate&&o.getReactMountReady().enqueue(a.componentDidUpdate.bind(a,s,u,l),a)},_updateRend
 eredComponent:function(e,t){var n=this._renderedComponent,r=n._currentElement,o=this._getValidatedChildContext(),i=this._renderValidatedComponent(o);if(y(r,i))f.receiveComponent(n,i,e,this._mergeChildContext(t,o));else{var a=this._rootNodeID,s=n._rootNodeID;f.unmountComponent(n),this._renderedComponent=this._instantiateReactComponent(i,this._currentElement.type);var u=f.mountComponent(this._renderedComponent,a,e,this._mergeChildContext(t,o));this._replaceNodeWithMarkupByID(s,u)}},_replaceNodeWithMarkupByID:function(e,t){o.replaceNodeWithMarkupByID(e,t)},_renderValidatedComponentWithoutOwnerOrContext:function(){var e=this._instance,t=e.render();return t},_renderValidatedComponent:function(e){var t,n=i.current;i.current=this._mergeChildContext(this._currentElement._context,e),a.current=this;try{t=this._renderValidatedComponentWithoutOwnerOrContext()}finally{i.current=n,a.current=null}return g(null===t||t===!1||s.isValidElement(t)),t},attachRef:function(e,t){var n=this.getPublicInstanc
 e(),r=n.refs===v?n.refs={}:n.refs;r[e]=t.getPublicInstance()},detachRef:function(e){var t=this.getPublicInstance().refs;delete t[e]},getName:function(){var e=this._currentElement.type,t=this._instance&&this._instance.constructor;return e.displayName||t&&t.displayName||e.name||t&&t.name||null},getPublicInstance:function(){return this._instance},_instantiateReactComponent:null};p.measureMethods(E,"ReactCompositeComponent",{mountComponent:"mountComponent",updateComponent:"updateComponent",_renderValidatedComponent:"_renderValidatedComponent"});var b={Mixin:E};t.exports=b},{127:127,147:147,162:162,166:166,29:29,41:41,44:44,45:45,61:61,62:62,71:71,72:72,78:78,80:80,82:82,83:83,87:87,97:97}],44:[function(e,t,n){"use strict";var r=e(29),o=e(127),i=(e(166),{current:o,withContext:function(e,t){var n,o=i.current;i.current=r({},o,e);try{n=t()}finally{i.current=o}return n}});t.exports=i},{127:127,166:166,29:29}],45:[function(e,t,n){"use strict";var r={current:null};t.exports=r},{}],46:[function
 (e,t,n){"use strict";function r(e){return o.createFactory(e)}var o=e(61),i=(e(62),e(155)),a=i({a:"a",abbr:"abbr",address:"address",area:"area",article:"article",aside:"aside",audio:"audio",b:"b",base:"base",bdi:"bdi",bdo:"bdo",big:"big",blockquote:"blockquote",body:"body",br:"br",button:"button",canvas:"canvas",caption:"caption",cite:"cite",code:"code",col:"col",colgroup:"colgroup",data:"data",datalist:"datalist",dd:"dd",del:"del",details:"details",dfn:"dfn",dialog:"dialog",div:"div",dl:"dl",dt:"dt",em:"em",embed:"embed",fieldset:"fieldset",figcaption:"figcaption",figure:"figure",footer:"footer",form:"form",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",h6:"h6",head:"head",header:"header",hr:"hr",html:"html",i:"i",iframe:"iframe",img:"img",input:"input",ins:"ins",kbd:"kbd",keygen:"keygen",label:"label",legend:"legend",li:"li",link:"link",main:"main",map:"map",mark:"mark",menu:"menu",menuitem:"menuitem",meta:"meta",meter:"meter",nav:"nav",noscript:"noscript",object:"object",ol:"ol",optgroup
 :"optgroup",option:"option",output:"output",p:"p",param:"param",picture:"picture",pre:"pre",progress:"progress",q:"q",rp:"rp",rt:"rt",ruby:"ruby",s:"s",samp:"samp",script:"script",section:"section",select:"select",small:"small",source:"source",span:"span",strong:"strong",style:"style",sub:"sub",summary:"summary",sup:"sup",table:"table",tbody:"tbody",td:"td",textarea:"textarea",tfoot:"tfoot",th:"th",thead:"thead",time:"time",title:"title",tr:"tr",track:"track",u:"u",ul:"ul","var":"var",video:"video",wbr:"wbr",circle:"circle",clipPath:"clipPath",defs:"defs",ellipse:"ellipse",g:"g",line:"line",linearGradient:"linearGradient",mask:"mask",path:"path",pattern:"pattern",polygon:"polygon",polyline:"polyline",radialGradient:"radialGradient",rect:"rect",stop:"stop",svg:"svg",text:"text",tspan:"tspan"},r);t.exports=a},{155:155,61:61,62:62}],47:[function(e,t,n){"use strict";var r=e(2),o=e(32),i=e(38),a=e(61),s=e(153),u=a.createFactory("button"),l=s({onClick:!0,onDoubleClick:!0,onMouseDown:!0,on
 MouseMove:!0,onMouseUp:!0,onClickCapture:!0,onDoubleClickCapture:!0,onMouseDownCapture:!0,onMouseMoveCapture:!0,onMouseUpCapture:!0}),c=i.createClass({displayName:"ReactDOMButton",tagName:"BUTTON",mixins:[r,o],render:function(){var e={};for(var t in this.props)!this.props.hasOwnProperty(t)||this.props.disabled&&l[t]||(e[t]=this.props[t]);return u(e,this.props.children)}});t.exports=c},{153:153,2:2,32:32,38:38,61:61}],48:[function(e,t,n){"use strict";function r(e){e&&(null!=e.dangerouslySetInnerHTML&&(g(null==e.children),g("object"==typeof e.dangerouslySetInnerHTML&&"__html"in e.dangerouslySetInnerHTML)),g(null==e.style||"object"==typeof e.style))}function o(e,t,n,r){var o=d.findReactContainerForID(e);if(o){var i=o.nodeType===D?o.ownerDocument:o;E(t,i)}r.getPutListenerQueue().enqueuePutListener(e,t,n)}function i(e){I.call(P,e)||(g(N.test(e)),P[e]=!0)}function a(e){i(e),this._tag=e,this._renderedChildren=null,this._previousStyleCopy=null,this._rootNodeID=null}var s=e(6),u=e(11),l=e(12
 ),c=e(33),p=e(40),d=e(75),f=e(76),h=e(80),m=e(29),v=e(128),g=e(147),y=(e(148),e(154)),C=(e(166),c.deleteListener),E=c.listenTo,b=c.registrationNameModules,_={string:!0,number:!0},x=y({style:null}),D=1,M=null,T={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},N=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,P={},I={}.hasOwnProperty;a.displayName="ReactDOMComponent",a.Mixin={construct:function(e){this._currentElement=e},mountComponent:function(e,t,n){this._rootNodeID=e,r(this._currentElement.props);var o=T[this._tag]?"":"</"+this._tag+">";return this._createOpenTagMarkupAndPutListeners(t)+this._createContentMarkup(t,n)+o},_createOpenTagMarkupAndPutListeners:function(e){var t=this._currentElement.props,n="<"+this._tag;for(var r in t)if(t.hasOwnProperty(r)){var i=t[r];if(null!=i)if(b.hasOwnProperty(r))o(this._rootNodeID,r,i,e);else{r===x&&(i&&(i=this._previousStyleCopy=m({},t.style)),i=s.createMarkupForStyles(i));var a=l.createMar
 kupForProperty(r,i);a&&(n+=" "+a)}}if(e.renderToStaticMarkup)return n+">";var u=l.createMarkupForID(this._rootNodeID);return n+" "+u+">"},_createContentMarkup:function(e,t){var n="";("listing"===this._tag||"pre"===this._tag||"textarea"===this._tag)&&(n="\n");var r=this._currentElement.props,o=r.dangerouslySetInnerHTML;if(null!=o){if(null!=o.__html)return n+o.__html}else{var i=_[typeof r.children]?r.children:null,a=null!=i?null:r.children;if(null!=i)return n+v(i);if(null!=a){var s=this.mountChildren(a,e,t);return n+s.join("")}}return n},receiveComponent:function(e,t,n){var r=this._currentElement;this._currentElement=e,this.updateComponent(t,r,e,n)},updateComponent:function(e,t,n,o){r(this._currentElement.props),this._updateDOMProperties(t.props,e),this._updateDOMChildren(t.props,e,o)},_updateDOMProperties:function(e,t){var n,r,i,a=this._currentElement.props;for(n in e)if(!a.hasOwnProperty(n)&&e.hasOwnProperty(n))if(n===x){var s=this._previousStyleCopy;for(r in s)s.hasOwnProperty(r)&&
 (i=i||{},i[r]="");this._previousStyleCopy=null}else b.hasOwnProperty(n)?C(this._rootNodeID,n):(u.isStandardName[n]||u.isCustomAttribute(n))&&M.deletePropertyByID(this._rootNodeID,n);for(n in a){var l=a[n],c=n===x?this._previousStyleCopy:e[n];if(a.hasOwnProperty(n)&&l!==c)if(n===x)if(l?l=this._previousStyleCopy=m({},l):this._previousStyleCopy=null,c){for(r in c)!c.hasOwnProperty(r)||l&&l.hasOwnProperty(r)||(i=i||{},i[r]="");for(r in l)l.hasOwnProperty(r)&&c[r]!==l[r]&&(i=i||{},i[r]=l[r])}else i=l;else b.hasOwnProperty(n)?o(this._rootNodeID,n,l,t):(u.isStandardName[n]||u.isCustomAttribute(n))&&M.updatePropertyByID(this._rootNodeID,n,l)}i&&M.updateStylesByID(this._rootNodeID,i)},_updateDOMChildren:function(e,t,n){var r=this._currentElement.props,o=_[typeof e.children]?e.children:null,i=_[typeof r.children]?r.children:null,a=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,s=r.dangerouslySetInnerHTML&&r.dangerouslySetInnerHTML.__html,u=null!=o?null:e.children,l=null!=i?null:r
 .children,c=null!=o||null!=a,p=null!=i||null!=s;null!=u&&null==l?this.updateChildren(null,t,n):c&&!p&&this.updateTextContent(""),null!=i?o!==i&&this.updateTextContent(""+i):null!=s?a!==s&&M.updateInnerHTMLByID(this._rootNodeID,s):null!=l&&this.updateChildren(l,t,n)},unmountComponent:function(){this.unmountChildren(),c.deleteAllListeners(this._rootNodeID),p.unmountIDFromEnvironment(this._rootNodeID),this._rootNodeID=null}},h.measureMethods(a,"ReactDOMComponent",{mountComponent:"mountComponent",updateComponent:"updateComponent"}),m(a.prototype,a.Mixin,f.Mixin),a.injection={injectIDOperations:function(e){a.BackendIDOperations=M=e}},t.exports=a},{11:11,12:12,128:128,147:147,148:148,154:154,166:166,29:29,33:33,40:40,6:6,75:75,76:76,80:80}],49:[function(e,t,n){"use strict";var r=e(16),o=e(27),i=e(32),a=e(38),s=e(61),u=s.createFactory("form"),l=a.createClass({displayName:"ReactDOMForm",tagName:"FORM",mixins:[i,o],render:function(){return u(this.props)},componentDidMount:function(){this.tra
 pBubbledEvent(r.topLevelTypes.topReset,"reset"),this.trapBubbledEvent(r.topLevelTypes.topSubmit,"submit")}});t.exports=l},{16:16,27:27,32:32,38:38,61:61}],50:[function(e,t,n){"use strict";var r=e(6),o=e(10),i=e(12),a=e(75),s=e(80),u=e(147),l=e(159),c={dangerouslySetInnerHTML:"`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.",style:"`style` must be set using `updateStylesByID()`."},p={updatePropertyByID:function(e,t,n){var r=a.getNode(e);u(!c.hasOwnProperty(t)),null!=n?i.setValueForProperty(r,t,n):i.deleteValueForProperty(r,t)},deletePropertyByID:function(e,t,n){var r=a.getNode(e);u(!c.hasOwnProperty(t)),i.deleteValueForProperty(r,t,n)},updateStylesByID:function(e,t){var n=a.getNode(e);r.setValueForStyles(n,t)},updateInnerHTMLByID:function(e,t){var n=a.getNode(e);l(n,t)},updateTextContentByID:function(e,t){var n=a.getNode(e);o.updateTextContent(n,t)},dangerouslyReplaceNodeWithMarkupByID:function(e,t){var n=a.getNode(e);o.dangerouslyReplaceNodeWithMarkup(n,t)},dang
 erouslyProcessChildrenUpdates:function(e,t){for(var n=0;n<e.length;n++)e[n].parentNode=a.getNode(e[n].parentID);o.processUpdates(e,t)}};s.measureMethods(p,"ReactDOMIDOperations",{updatePropertyByID:"updatePropertyByID",deletePropertyByID:"deletePropertyByID",updateStylesByID:"updateStylesByID",updateInnerHTMLByID:"updateInnerHTMLByID",updateTextContentByID:"updateTextContentByID",dangerouslyReplaceNodeWithMarkupByID:"dangerouslyReplaceNodeWithMarkupByID",dangerouslyProcessChildrenUpdates:"dangerouslyProcessChildrenUpdates"}),t.exports=p},{10:10,12:12,147:147,159:159,6:6,75:75,80:80}],51:[function(e,t,n){"use strict";var r=e(16),o=e(27),i=e(32),a=e(38),s=e(61),u=s.createFactory("iframe"),l=a.createClass({displayName:"ReactDOMIframe",tagName:"IFRAME",mixins:[i,o],render:function(){return u(this.props)},componentDidMount:function(){this.trapBubbledEvent(r.topLevelTypes.topLoad,"load")}});t.exports=l},{16:16,27:27,32:32,38:38,61:61}],52:[function(e,t,n){"use strict";var r=e(16),o=e(27),
 i=e(32),a=e(38),s=e(61),u=s.createFactory("img"),l=a.createClass({displayName:"ReactDOMImg",tagName:"IMG",mixins:[i,o],render:function(){return u(this.props)},componentDidMount:function(){this.trapBubbledEvent(r.topLevelTypes.topLoad,"load"),this.trapBubbledEvent(r.topLevelTypes.topError,"error")}});t.exports=l},{16:16,27:27,32:32,38:38,61:61}],53:[function(e,t,n){"use strict";function r(){this.isMounted()&&this.forceUpdate()}var o=e(2),i=e(12),a=e(26),s=e(32),u=e(38),l=e(61),c=e(75),p=e(97),d=e(29),f=e(147),h=l.createFactory("input"),m={},v=u.createClass({displayName:"ReactDOMInput",tagName:"INPUT",mixins:[o,a.Mixin,s],getInitialState:function(){var e=this.props.defaultValue;return{initialChecked:this.props.defaultChecked||!1,initialValue:null!=e?e:null}},render:function(){var e=d({},this.props);e.defaultChecked=null,e.defaultValue=null;var t=a.getValue(this);e.value=null!=t?t:this.state.initialValue;var n=a.getChecked(this);return e.checked=null!=n?n:this.state.initialChecked,e.on
 Change=this._handleChange,h(e,this.props.children)},componentDidMount:function(){var e=c.getID(this.getDOMNode());m[e]=this},componentWillUnmount:function(){var e=this.getDOMNode(),t=c.getID(e);delete m[t]},componentDidUpdate:function(e,t,n){var r=this.getDOMNode();null!=this.props.checked&&i.setValueForProperty(r,"checked",this.props.checked||!1);var o=a.getValue(this);null!=o&&i.setValueForProperty(r,"value",""+o)},_handleChange:function(e){var t,n=a.getOnChange(this);n&&(t=n.call(this,e)),p.asap(r,this);var o=this.props.name;if("radio"===this.props.type&&null!=o){for(var i=this.getDOMNode(),s=i;s.parentNode;)s=s.parentNode;for(var u=s.querySelectorAll("input[name="+JSON.stringify(""+o)+'][type="radio"]'),l=0,d=u.length;d>l;l++){var h=u[l];if(h!==i&&h.form===i.form){var v=c.getID(h);f(v);var g=m[v];f(g),p.asap(r,g)}}}return t}});t.exports=v},{12:12,147:147,2:2,26:26,29:29,32:32,38:38,61:61,75:75,97:97}],54:[function(e,t,n){"use strict";var r=e(32),o=e(38),i=e(61),a=(e(166),i.creat
 eFactory("option")),s=o.createClass({displayName:"ReactDOMOption",tagName:"OPTION",mixins:[r],componentWillMount:function(){},render:function(){return a(this.props,this.props.children)}});t.exports=s},{166:166,32:32,38:38,61:61}],55:[function(e,t,n){"use strict";function r(){if(this._pendingUpdate){this._pendingUpdate=!1;var e=s.getValue(this);null!=e&&this.isMounted()&&i(this,e)}}function o(e,t,n){if(null==e[t])return null;if(e.multiple){if(!Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be an array if `multiple` is true.")}else if(Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be a scalar value if `multiple` is false.")}function i(e,t){var n,r,o,i=e.getDOMNode().options;if(e.props.multiple){for(n={},r=0,o=t.length;o>r;r++)n[""+t[r]]=!0;for(r=0,o=i.length;o>r;r++){var a=n.hasOwnProperty(i[r].value);i[r].selected!==a&&(i[r].selected=a)}}else{for(n=""+t,r=0,o=i.length;o>r;r++)if(i[r].value===n)return void(i[r].select
 ed=!0);i.length&&(i[0].selected=!0)}}var a=e(2),s=e(26),u=e(32),l=e(38),c=e(61),p=e(97),d=e(29),f=c.createFactory("select"),h=l.createClass({displayName:"ReactDOMSelect",tagName:"SELECT",mixins:[a,s.Mixin,u],propTypes:{defaultValue:o,value:o},render:function(){var e=d({},this.props);return e.onChange=this._handleChange,e.value=null,f(e,this.props.children)},componentWillMount:function(){this._pendingUpdate=!1},componentDidMount:function(){var e=s.getValue(this);null!=e?i(this,e):null!=this.props.defaultValue&&i(this,this.props.defaultValue)},componentDidUpdate:function(e){var t=s.getValue(this);null!=t?(this._pendingUpdate=!1,i(this,t)):!e.multiple!=!this.props.multiple&&(null!=this.props.defaultValue?i(this,this.props.defaultValue):i(this,this.props.multiple?[]:""))},_handleChange:function(e){var t,n=s.getOnChange(this);return n&&(t=n.call(this,e)),this._pendingUpdate=!0,p.asap(r,this),t}});t.exports=h},{2:2,26:26,29:29,32:32,38:38,61:61,97:97}],56:[function(e,t,n){"use strict";fun
 ction r(e,t,n,r){return e===n&&t===r}function o(e){var t=document.selection,n=t.createRange(),r=n.text.length,o=n.duplicate();o.moveToElementText(e),o.setEndPoint("EndToStart",n);var i=o.text.length,a=i+r;return{start:i,end:a}}function i(e){var t=window.getSelection&&window.getSelection();if(!t||0===t.rangeCount)return null;var n=t.anchorNode,o=t.anchorOffset,i=t.focusNode,a=t.focusOffset,s=t.getRangeAt(0),u=r(t.anchorNode,t.anchorOffset,t.focusNode,t.focusOffset),l=u?0:s.toString().length,c=s.cloneRange();c.selectNodeContents(e),c.setEnd(s.startContainer,s.startOffset);var p=r(c.startContainer,c.startOffset,c.endContainer,c.endOffset),d=p?0:c.toString().length,f=d+l,h=document.createRange();h.setStart(n,o),h.setEnd(i,a);var m=h.collapsed;return{start:m?f:d,end:m?d:f}}function a(e,t){var n,r,o=document.selection.createRange().duplicate();"undefined"==typeof t.end?(n=t.start,r=n):t.start>t.end?(n=t.end,r=t.start):(n=t.start,r=t.end),o.moveToElementText(e),o.moveStart("character",n),o
 .setEndPoint("EndToStart",o),o.moveEnd("character",r-n),o.select()}function s(e,t){if(window.getSelection){var n=window.getSelection(),r=e[c()].length,o=Math.min(t.start,r),i="undefined"==typeof t.end?o:Math.min(t.end,r);if(!n.extend&&o>i){var a=i;i=o,o=a}var s=l(e,o),u=l(e,i);if(s&&u){var p=document.createRange();p.setStart(s.node,s.offset),n.removeAllRanges(),o>i?(n.addRange(p),n.extend(u.node,u.offset)):(p.setEnd(u.node,u.offset),n.addRange(p))}}}var u=e(22),l=e(140),c=e(142),p=u.canUseDOM&&"selection"in document&&!("getSelection"in window),d={getOffsets:p?o:i,setOffsets:p?a:s};t.exports=d},{140:140,142:142,22:22}],57:[function(e,t,n){"use strict";var r=e(12),o=e(40),i=e(48),a=e(29),s=e(128),u=function(e){};a(u.prototype,{construct:function(e){this._currentElement=e,this._stringText=""+e,this._rootNodeID=null,this._mountIndex=0},mountComponent:function(e,t,n){this._rootNodeID=e;var o=s(this._stringText);return t.renderToStaticMarkup?o:"<span "+r.createMarkupForID(e)+">"+o+"</span
 >"},receiveComponent:function(e,t){if(e!==this._currentElement){this._currentElement=e;var n=""+e;
+
+n!==this._stringText&&(this._stringText=n,i.BackendIDOperations.updateTextContentByID(this._rootNodeID,n))}},unmountComponent:function(){o.unmountIDFromEnvironment(this._rootNodeID)}}),t.exports=u},{12:12,128:128,29:29,40:40,48:48}],58:[function(e,t,n){"use strict";function r(){this.isMounted()&&this.forceUpdate()}var o=e(2),i=e(12),a=e(26),s=e(32),u=e(38),l=e(61),c=e(97),p=e(29),d=e(147),f=(e(166),l.createFactory("textarea")),h=u.createClass({displayName:"ReactDOMTextarea",tagName:"TEXTAREA",mixins:[o,a.Mixin,s],getInitialState:function(){var e=this.props.defaultValue,t=this.props.children;null!=t&&(d(null==e),Array.isArray(t)&&(d(t.length<=1),t=t[0]),e=""+t),null==e&&(e="");var n=a.getValue(this);return{initialValue:""+(null!=n?n:e)}},render:function(){var e=p({},this.props);return d(null==e.dangerouslySetInnerHTML),e.defaultValue=null,e.value=null,e.onChange=this._handleChange,f(e,this.state.initialValue)},componentDidUpdate:function(e,t,n){var r=a.getValue(this);if(null!=r){var 
 o=this.getDOMNode();i.setValueForProperty(o,"value",""+r)}},_handleChange:function(e){var t,n=a.getOnChange(this);return n&&(t=n.call(this,e)),c.asap(r,this),t}});t.exports=h},{12:12,147:147,166:166,2:2,26:26,29:29,32:32,38:38,61:61,97:97}],59:[function(e,t,n){"use strict";function r(){this.reinitializeTransaction()}var o=e(97),i=e(113),a=e(29),s=e(126),u={initialize:s,close:function(){d.isBatchingUpdates=!1}},l={initialize:s,close:o.flushBatchedUpdates.bind(o)},c=[l,u];a(r.prototype,i.Mixin,{getTransactionWrappers:function(){return c}});var p=new r,d={isBatchingUpdates:!1,batchedUpdates:function(e,t,n,r,o){var i=d.isBatchingUpdates;d.isBatchingUpdates=!0,i?e(t,n,r,o):p.perform(e,null,t,n,r,o)}};t.exports=d},{113:113,126:126,29:29,97:97}],60:[function(e,t,n){"use strict";function r(e){return h.createClass({tagName:e.toUpperCase(),render:function(){return new P(e,null,null,null,null,this.props)}})}function o(){R.EventEmitter.injectReactEventListener(I),R.EventPluginHub.injectEventPlu
 ginOrder(u),R.EventPluginHub.injectInstanceHandle(w),R.EventPluginHub.injectMount(O),R.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:L,EnterLeaveEventPlugin:l,ChangeEventPlugin:a,MobileSafariClickEventPlugin:d,SelectEventPlugin:A,BeforeInputEventPlugin:i}),R.NativeComponent.injectGenericComponentClass(g),R.NativeComponent.injectTextComponentClass(N),R.NativeComponent.injectAutoWrapper(r),R.Class.injectMixin(f),R.NativeComponent.injectComponentClasses({button:y,form:C,iframe:_,img:E,input:x,option:D,select:M,textarea:T,html:F("html"),head:F("head"),body:F("body")}),R.DOMProperty.injectDOMPropertyConfig(p),R.DOMProperty.injectDOMPropertyConfig(U),R.EmptyComponent.injectEmptyComponent("noscript"),R.Updates.injectReconcileTransaction(S),R.Updates.injectBatchingStrategy(v),R.RootIndex.injectCreateReactRootIndex(c.canUseDOM?s.createReactRootIndex:k.createReactRootIndex),R.Component.injectEnvironment(m),R.DOMComponent.injectIDOperations(b)}var i=e(3),a=e(8),s=e(9),u=e(14),l=e(
 15),c=e(22),p=e(24),d=e(28),f=e(32),h=e(38),m=e(40),v=e(59),g=e(48),y=e(47),C=e(49),E=e(52),b=e(50),_=e(51),x=e(53),D=e(54),M=e(55),T=e(58),N=e(57),P=e(61),I=e(66),R=e(68),w=e(70),O=e(75),S=e(86),A=e(99),k=e(100),L=e(101),U=e(98),F=e(122);t.exports={inject:o}},{100:100,101:101,122:122,14:14,15:15,22:22,24:24,28:28,3:3,32:32,38:38,40:40,47:47,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,57:57,58:58,59:59,61:61,66:66,68:68,70:70,75:75,8:8,86:86,9:9,98:98,99:99}],61:[function(e,t,n){"use strict";var r=e(44),o=e(45),i=e(29),a=(e(166),{key:!0,ref:!0}),s=function(e,t,n,r,o,i){this.type=e,this.key=t,this.ref=n,this._owner=r,this._context=o,this.props=i};s.prototype={_isReactElement:!0},s.createElement=function(e,t,n){var i,u={},l=null,c=null;if(null!=t){c=void 0===t.ref?null:t.ref,l=void 0===t.key?null:""+t.key;for(i in t)t.hasOwnProperty(i)&&!a.hasOwnProperty(i)&&(u[i]=t[i])}var p=arguments.length-2;if(1===p)u.children=n;else if(p>1){for(var d=Array(p),f=0;p>f;f++)d[f]=arguments[f+2];u
 .children=d}if(e&&e.defaultProps){var h=e.defaultProps;for(i in h)"undefined"==typeof u[i]&&(u[i]=h[i])}return new s(e,l,c,o.current,r.current,u)},s.createFactory=function(e){var t=s.createElement.bind(null,e);return t.type=e,t},s.cloneAndReplaceProps=function(e,t){var n=new s(e.type,e.key,e.ref,e._owner,e._context,t);return n},s.cloneElement=function(e,t,n){var r,u=i({},e.props),l=e.key,c=e.ref,p=e._owner;if(null!=t){void 0!==t.ref&&(c=t.ref,p=o.current),void 0!==t.key&&(l=""+t.key);for(r in t)t.hasOwnProperty(r)&&!a.hasOwnProperty(r)&&(u[r]=t[r])}var d=arguments.length-2;if(1===d)u.children=n;else if(d>1){for(var f=Array(d),h=0;d>h;h++)f[h]=arguments[h+2];u.children=f}return new s(e.type,l,c,p,e._context,u)},s.isValidElement=function(e){var t=!(!e||!e._isReactElement);return t},t.exports=s},{166:166,29:29,44:44,45:45}],62:[function(e,t,n){"use strict";function r(){if(y.current){var e=y.current.getName();if(e)return" Check the render method of `"+e+"`."}return""}function o(e){var t
 =e&&e.getPublicInstance();if(!t)return void 0;var n=t.constructor;return n?n.displayName||n.name||void 0:void 0}function i(){var e=y.current;return e&&o(e)||void 0}function a(e,t){e._store.validated||null!=e.key||(e._store.validated=!0,u('Each child in an array or iterator should have a unique "key" prop.',e,t))}function s(e,t,n){D.test(e)&&u("Child objects should have non-numeric keys so ordering is preserved.",t,n)}function u(e,t,n){var r=i(),a="string"==typeof n?n:n.displayName||n.name,s=r||a,u=_[e]||(_[e]={});if(!u.hasOwnProperty(s)){u[s]=!0;var l="";if(t&&t._owner&&t._owner!==y.current){var c=o(t._owner);l=" It was passed a child from "+c+"."}}}function l(e,t){if(Array.isArray(e))for(var n=0;n<e.length;n++){var r=e[n];m.isValidElement(r)&&a(r,t)}else if(m.isValidElement(e))e._store.validated=!0;else if(e){var o=E(e);if(o){if(o!==e.entries)for(var i,u=o.call(e);!(i=u.next()).done;)m.isValidElement(i.value)&&a(i.value,t)}else if("object"==typeof e){var l=v.extractIfFragment(e);fo
 r(var c in l)l.hasOwnProperty(c)&&s(c,l[c],t)}}}function c(e,t,n,o){for(var i in t)if(t.hasOwnProperty(i)){var a;try{b("function"==typeof t[i]),a=t[i](n,i,e,o)}catch(s){a=s}a instanceof Error&&!(a.message in x)&&(x[a.message]=!0,r(this))}}function p(e,t){var n=t.type,r="string"==typeof n?n:n.displayName,o=t._owner?t._owner.getPublicInstance().constructor.displayName:null,i=e+"|"+r+"|"+o;if(!M.hasOwnProperty(i)){M[i]=!0;var a="";r&&(a=" <"+r+" />");var s="";o&&(s=" The element was created by "+o+".")}}function d(e,t){return e!==e?t!==t:0===e&&0===t?1/e===1/t:e===t}function f(e){if(e._store){var t=e._store.originalProps,n=e.props;for(var r in n)n.hasOwnProperty(r)&&(t.hasOwnProperty(r)&&d(t[r],n[r])||(p(r,e),t[r]=n[r]))}}function h(e){if(null!=e.type){var t=C.getComponentClassForElement(e),n=t.displayName||t.name;t.propTypes&&c(n,t.propTypes,e.props,g.prop),"function"==typeof t.getDefaultProps}}var m=e(61),v=e(67),g=e(83),y=(e(82),e(45)),C=e(78),E=e(138),b=e(147),_=(e(166),{}),x={},D=
 /^\d+$/,M={},T={checkAndWarnForMutatedProps:f,createElement:function(e,t,n){var r=m.createElement.apply(this,arguments);if(null==r)return r;for(var o=2;o<arguments.length;o++)l(arguments[o],e);return h(r),r},createFactory:function(e){var t=T.createElement.bind(null,e);return t.type=e,t},cloneElement:function(e,t,n){for(var r=m.cloneElement.apply(this,arguments),o=2;o<arguments.length;o++)l(arguments[o],r.type);return h(r),r}};t.exports=T},{138:138,147:147,166:166,45:45,61:61,67:67,78:78,82:82,83:83}],63:[function(e,t,n){"use strict";function r(e){c[e]=!0}function o(e){delete c[e]}function i(e){return!!c[e]}var a,s=e(61),u=e(71),l=e(147),c={},p={injectEmptyComponent:function(e){a=s.createFactory(e)}},d=function(){};d.prototype.componentDidMount=function(){var e=u.get(this);e&&r(e._rootNodeID)},d.prototype.componentWillUnmount=function(){var e=u.get(this);e&&o(e._rootNodeID)},d.prototype.render=function(){return l(a),a()};var f=s.createElement(d),h={emptyElement:f,injection:p,isNullCo
 mponentID:i};t.exports=h},{147:147,61:61,71:71}],64:[function(e,t,n){"use strict";var r={guard:function(e,t){return e}};t.exports=r},{}],65:[function(e,t,n){"use strict";function r(e){o.enqueueEvents(e),o.processEventQueue()}var o=e(18),i={handleTopLevel:function(e,t,n,i){var a=o.extractEvents(e,t,n,i);r(a)}};t.exports=i},{18:18}],66:[function(e,t,n){"use strict";function r(e){var t=p.getID(e),n=c.getReactRootIDFromNodeID(t),r=p.findReactContainerForID(n),o=p.getFirstReactDOM(r);return o}function o(e,t){this.topLevelType=e,this.nativeEvent=t,this.ancestors=[]}function i(e){for(var t=p.getFirstReactDOM(h(e.nativeEvent))||window,n=t;n;)e.ancestors.push(n),n=r(n);for(var o=0,i=e.ancestors.length;i>o;o++){t=e.ancestors[o];var a=p.getID(t)||"";v._handleTopLevel(e.topLevelType,t,a,e.nativeEvent)}}function a(e){var t=m(window);e(t)}var s=e(17),u=e(22),l=e(30),c=e(70),p=e(75),d=e(97),f=e(29),h=e(137),m=e(143);f(o.prototype,{destructor:function(){this.topLevelType=null,this.nativeEvent=null,
 this.ancestors.length=0}}),l.addPoolingTo(o,l.twoArgumentPooler);var v={_enabled:!0,_handleTopLevel:null,WINDOW_HANDLE:u.canUseDOM?window:null,setHandleTopLevel:function(e){v._handleTopLevel=e},setEnabled:function(e){v._enabled=!!e},isEnabled:function(){return v._enabled},trapBubbledEvent:function(e,t,n){var r=n;return r?s.listen(r,t,v.dispatchEvent.bind(null,e)):null},trapCapturedEvent:function(e,t,n){var r=n;return r?s.capture(r,t,v.dispatchEvent.bind(null,e)):null},monitorScrollValue:function(e){var t=a.bind(null,e);s.listen(window,"scroll",t)},dispatchEvent:function(e,t){if(v._enabled){var n=o.getPooled(e,t);try{d.batchedUpdates(i,n)}finally{o.release(n)}}}};t.exports=v},{137:137,143:143,17:17,22:22,29:29,30:30,70:70,75:75,97:97}],67:[function(e,t,n){"use strict";var r=(e(61),e(166),{create:function(e){return e},extract:function(e){return e},extractIfFragment:function(e){return e}});t.exports=r},{166:166,61:61}],68:[function(e,t,n){"use strict";var r=e(11),o=e(18),i=e(41),a=e(38
 ),s=e(63),u=e(33),l=e(78),c=e(48),p=e(80),d=e(89),f=e(97),h={Component:i.injection,Class:a.injection,DOMComponent:c.injection,DOMProperty:r.injection,EmptyComponent:s.injection,EventPluginHub:o.injection,EventEmitter:u.injection,NativeComponent:l.injection,Perf:p.injection,RootIndex:d.injection,Updates:f.injection};t.exports=h},{11:11,18:18,33:33,38:38,41:41,48:48,63:63,78:78,80:80,89:89,97:97}],69:[function(e,t,n){"use strict";function r(e){return i(document.documentElement,e)}var o=e(56),i=e(120),a=e(131),s=e(133),u={hasSelectionCapabilities:function(e){return e&&("INPUT"===e.nodeName&&"text"===e.type||"TEXTAREA"===e.nodeName||"true"===e.contentEditable)},getSelectionInformation:function(){var e=s();return{focusedElem:e,selectionRange:u.hasSelectionCapabilities(e)?u.getSelection(e):null}},restoreSelection:function(e){var t=s(),n=e.focusedElem,o=e.selectionRange;t!==n&&r(n)&&(u.hasSelectionCapabilities(n)&&u.setSelection(n,o),a(n))},getSelection:function(e){var t;if("selectionStart
 "in e)t={start:e.selectionStart,end:e.selectionEnd};else if(document.selection&&"INPUT"===e.nodeName){var n=document.selection.createRange();n.parentElement()===e&&(t={start:-n.moveStart("character",-e.value.length),end:-n.moveEnd("character",-e.value.length)})}else t=o.getOffsets(e);return t||{start:0,end:0}},setSelection:function(e,t){var n=t.start,r=t.end;if("undefined"==typeof r&&(r=n),"selectionStart"in e)e.selectionStart=n,e.selectionEnd=Math.min(r,e.value.length);else if(document.selection&&"INPUT"===e.nodeName){var i=e.createTextRange();i.collapse(!0),i.moveStart("character",n),i.moveEnd("character",r-n),i.select()}else o.setOffsets(e,t)}};t.exports=u},{120:120,131:131,133:133,56:56}],70:[function(e,t,n){"use strict";function r(e){return f+e.toString(36)}function o(e,t){return e.charAt(t)===f||t===e.length}function i(e){return""===e||e.charAt(0)===f&&e.charAt(e.length-1)!==f}function a(e,t){return 0===t.indexOf(e)&&o(t,e.length)}function s(e){return e?e.substr(0,e.lastIndexO
 f(f)):""}function u(e,t){if(d(i(e)&&i(t)),d(a(e,t)),e===t)return e;var n,r=e.length+h;for(n=r;n<t.length&&!o(t,n);n++);return t.substr(0,n)}function l(e,t){var n=Math.min(e.length,t.length);if(0===n)return"";for(var r=0,a=0;n>=a;a++)if(o(e,a)&&o(t,a))r=a;else if(e.charAt(a)!==t.charAt(a))break;var s=e.substr(0,r);return d(i(s)),s}function c(e,t,n,r,o,i){e=e||"",t=t||"",d(e!==t);var l=a(t,e);d(l||a(e,t));for(var c=0,p=l?s:u,f=e;;f=p(f,t)){var h;if(o&&f===e||i&&f===t||(h=n(f,l,r)),h===!1||f===t)break;d(c++<m)}}var p=e(89),d=e(147),f=".",h=f.length,m=100,v={createReactRootID:function(){return r(p.createReactRootIndex())},createReactID:function(e,t){return e+t},getReactRootIDFromNodeID:function(e){if(e&&e.charAt(0)===f&&e.length>1){var t=e.indexOf(f,1);return t>-1?e.substr(0,t):e}return null},traverseEnterLeave:function(e,t,n,r,o){var i=l(e,t);i!==e&&c(e,i,n,r,!1,!0),i!==t&&c(i,t,n,o,!0,!1)},traverseTwoPhase:function(e,t,n){e&&(c("",e,t,n,!0,!1),c(e,"",t,n,!1,!0))},traverseAncestors:fun
 ction(e,t,n){c("",e,t,n,!0,!1)},_getFirstCommonAncestorID:l,_getNextDescendantID:u,isAncestorIDOf:a,SEPARATOR:f};t.exports=v},{147:147,89:89}],71:[function(e,t,n){"use strict";var r={remove:function(e){e._reactInternalInstance=void 0},get:function(e){return e._reactInternalInstance},has:function(e){return void 0!==e._reactInternalInstance},set:function(e,t){e._reactInternalInstance=t}};t.exports=r},{}],72:[function(e,t,n){"use strict";var r={currentlyMountingInstance:null,currentlyUnmountingInstance:null};t.exports=r},{}],73:[function(e,t,n){"use strict";function r(e,t){this.value=e,this.requestChange=t}function o(e){var t={value:"undefined"==typeof e?i.PropTypes.any.isRequired:e.isRequired,requestChange:i.PropTypes.func.isRequired};return i.PropTypes.shape(t)}var i=e(31);r.PropTypes={link:o},t.exports=r},{31:31}],74:[function(e,t,n){"use strict";var r=e(116),o={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(e){var t=r(e);return e.replace(">"," "+o.CHECKSUM_AT
 TR_NAME+'="'+t+'">')},canReuseMarkup:function(e,t){var n=t.getAttribute(o.CHECKSUM_ATTR_NAME);n=n&&parseInt(n,10);var i=r(e);return i===n}};t.exports=o},{116:116}],75:[function(e,t,n){"use strict";function r(e,t){for(var n=Math.min(e.length,t.length),r=0;n>r;r++)if(e.charAt(r)!==t.charAt(r))return r;return e.length===t.length?-1:n}function o(e){var t=I(e);return t&&K.getID(t)}function i(e){var t=a(e);if(t)if(L.hasOwnProperty(t)){var n=L[t];n!==e&&(w(!c(n,t)),L[t]=e)}else L[t]=e;return t}function a(e){return e&&e.getAttribute&&e.getAttribute(k)||""}function s(e,t){var n=a(e);n!==t&&delete L[n],e.setAttribute(k,t),L[t]=e}function u(e){return L.hasOwnProperty(e)&&c(L[e],e)||(L[e]=K.findReactNodeByID(e)),L[e]}function l(e){var t=b.get(e)._rootNodeID;return C.isNullComponentID(t)?null:(L.hasOwnProperty(t)&&c(L[t],t)||(L[t]=K.findReactNodeByID(t)),L[t])}function c(e,t){if(e){w(a(e)===t);var n=K.findReactContainerForID(t);if(n&&P(n,e))return!0}return!1}function p(e){delete L[e]}function d(
 e){var t=L[e];return t&&c(t,e)?void(W=t):!1}function f(e){W=null,E.traverseAncestors(e,d);var t=W;return W=null,t}function h(e,t,n,r,o){var i=D.mountComponent(e,t,r,N);e._isTopLevel=!0,K._mountImageIntoNode(i,n,o)}function m(e,t,n,r){var o=T.ReactReconcileTransaction.getPooled();o.perform(h,null,e,t,n,o,r),T.ReactReconcileTransaction.release(o)}var v=e(11),g=e(33),y=(e(45),e(61)),C=(e(62),e(63)),E=e(70),b=e(71),_=e(74),x=e(80),D=e(87),M=e(96),T=e(97),N=e(127),P=e(120),I=e(141),R=e(146),w=e(147),O=e(159),S=e(162),A=(e(166),E.SEPARATOR),k=v.ID_ATTRIBUTE_NAME,L={},U=1,F=9,B={},j={},V=[],W=null,K={_instancesByReactRootID:B,scrollMonitor:function(e,t){t()},_updateRootComponent:function(e,t,n,r){return K.scrollMonitor(n,function(){M.enqueueElementInternal(e,t),r&&M.enqueueCallbackInternal(e,r)}),e},_registerComponent:function(e,t){w(t&&(t.nodeType===U||t.nodeType===F)),g.ensureScrollValueMonitoring();var n=K.registerContainer(t);return B[n]=e,n},_renderNewRootComponent:function(e,t,n){var
  r=R(e,null),o=K._registerComponent(r,t);return T.batchedUpdates(m,r,o,t,n),r},render:function(e,t,n){w(y.isValidElement(e));var r=B[o(t)];if(r){var i=r._currentElement;if(S(i,e))return K._updateRootComponent(r,e,t,n).getPublicInstance();K.unmountComponentAtNode(t)}var a=I(t),s=a&&K.isRenderedByReact(a),u=s&&!r,l=K._renderNewRootComponent(e,t,u).getPublicInstance();return n&&n.call(l),l},constructAndRenderComponent:function(e,t,n){var r=y.createElement(e,t);return K.render(r,n)},constructAndRenderComponentByID:function(e,t,n){var r=document.getElementById(n);return w(r),K.constructAndRenderComponent(e,t,r)},registerContainer:function(e){var t=o(e);return t&&(t=E.getReactRootIDFromNodeID(t)),t||(t=E.createReactRootID()),j[t]=e,t},unmountComponentAtNode:function(e){w(e&&(e.nodeType===U||e.nodeType===F));var t=o(e),n=B[t];return n?(K.unmountComponentFromNode(n,e),delete B[t],delete j[t],!0):!1},unmountComponentFromNode:function(e,t){for(D.unmountComponent(e),t.nodeType===F&&(t=t.docume
 ntElement);t.lastChild;)t.removeChild(t.lastChild)},findReactContainerForID:function(e){var t=E.getReactRootIDFromNodeID(e),n=j[t];return n},findReactNodeByID:function(e){var t=K.findReactContainerForID(e);return K.findComponentRoot(t,e)},isRenderedByReact:function(e){if(1!==e.nodeType)return!1;var t=K.getID(e);return t?t.charAt(0)===A:!1},getFirstReactDOM:function(e){for(var t=e;t&&t.parentNode!==t;){if(K.isRenderedByReact(t))return t;t=t.parentNode}return null},findComponentRoot:function(e,t){var n=V,r=0,o=f(t)||e;for(n[0]=o.firstChild,n.length=1;r<n.length;){for(var i,a=n[r++];a;){var s=K.getID(a);s?t===s?i=a:E.isAncestorIDOf(s,t)&&(n.length=r=0,n.push(a.firstChild)):n.push(a.firstChild),a=a.nextSibling}if(i)return n.length=0,i}n.length=0,w(!1)},_mountImageIntoNode:function(e,t,n){if(w(t&&(t.nodeType===U||t.nodeType===F)),n){var o=I(t);if(_.canReuseMarkup(e,o))return;var i=o.getAttribute(_.CHECKSUM_ATTR_NAME);o.removeAttribute(_.CHECKSUM_ATTR_NAME);var a=o.outerHTML;o.setAttribut
 e(_.CHECKSUM_ATTR_NAME,i);var s=r(e,a);" (client) "+e.substring(s-20,s+20)+"\n (server) "+a.substring(s-20,s+20),w(t.nodeType!==F)}w(t.nodeType!==F),O(t,e)},getReactRootID:o,getID:i,setID:s,getNode:u,getNodeFromInstance:l,purgeID:p};x.measureMethods(K,"ReactMount",{_renderNewRootComponent:"_renderNewRootComponent",_mountImageIntoNode:"_mountImageIntoNode"}),t.exports=K},{11:11,120:120,127:127,141:141,146:146,147:147,159:159,162:162,166:166,33:33,45:45,61:61,62:62,63:63,70:70,71:71,74:74,80:80,87:87,96:96,97:97}],76:[function(e,t,n){"use strict";function r(e,t,n){h.push({parentID:e,parentNode:null,type:c.INSERT_MARKUP,markupIndex:m.push(t)-1,textContent:null,fromIndex:null,toIndex:n})}function o(e,t,n){h.push({parentID:e,parentNode:null,type:c.MOVE_EXISTING,markupIndex:null,textContent:null,fromIndex:t,toIndex:n})}function i(e,t){h.push({parentID:e,parentNode:null,type:c.REMOVE_NODE,markupIndex:null,textContent:null,fromIndex:t,toIndex:null})}function a(e,t){h.push({parentID:e,parent
 Node:null,type:c.TEXT_CONTENT,markupIndex:null,textContent:t,fromIndex:null,toIndex:null})}function s(){h.length&&(l.processChildrenUpdates(h,m),u())}function u(){h.length=0,m.length=0}var l=e(41),c=e(77),p=e(87),d=e(36),f=0,h=[],m=[],v={Mixin:{mountChildren:function(e,t,n){var r=d.instantiateChildren(e,t,n);this._renderedChildren=r;var o=[],i=0;for(var a in r)if(r.hasOwnProperty(a)){var s=r[a],u=this._rootNodeID+a,l=p.mountComponent(s,u,t,n);s._mountIndex=i,o.push(l),i++}return o},updateTextContent:function(e){f++;var t=!0;try{var n=this._renderedChildren;d.unmountChildren(n);for(var r in n)n.hasOwnProperty(r)&&this._unmountChildByName(n[r],r);this.setTextContent(e),t=!1}finally{f--,f||(t?u():s())}},updateChildren:function(e,t,n){f++;var r=!0;try{this._updateChildren(e,t,n),r=!1}finally{f--,f||(r?u():s())}},_updateChildren:function(e,t,n){var r=this._renderedChildren,o=d.updateChildren(r,e,t,n);if(this._renderedChildren=o,o||r){var i,a=0,s=0;for(i in o)if(o.hasOwnProperty(i)){var u
 =r&&r[i],l=o[i];u===l?(this.moveChild(u,s,a),a=Math.max(u._mountIndex,a),u._mountIndex=s):(u&&(a=Math.max(u._mountIndex,a),this._unmountChildByName(u,i)),this._mountChildByNameAtIndex(l,i,s,t,n)),s++}for(i in r)!r.hasOwnProperty(i)||o&&o.hasOwnProperty(i)||this._unmountChildByName(r[i],i)}},unmountChildren:function(){var e=this._renderedChildren;d.unmountChildren(e),this._renderedChildren=null},moveChild:function(e,t,n){e._mountIndex<n&&o(this._rootNodeID,e._mountIndex,t)},createChild:function(e,t){r(this._rootNodeID,t,e._mountIndex)},removeChild:function(e){i(this._rootNodeID,e._mountIndex)},setTextContent:function(e){a(this._rootNodeID,e)},_mountChildByNameAtIndex:function(e,t,n,r,o){var i=this._rootNodeID+t,a=p.mountComponent(e,i,r,o);e._mountIndex=n,this.createChild(e,a)},_unmountChildByName:function(e,t){this.removeChild(e),e._mountIndex=null}}};t.exports=v},{36:36,41:41,77:77,87:87}],77:[function(e,t,n){"use strict";var r=e(153),o=r({INSERT_MARKUP:null,MOVE_EXISTING:null,REMOV
 E_NODE:null,TEXT_CONTENT:null});t.exports=o},{153:153}],78:[function(e,t,n){"use strict";function r(e){if("function"==typeof e.type)return e.type;var t=e.type,n=p[t];return null==n&&(p[t]=n=l(t)),n}function o(e){return u(c),new c(e.type,e.props)}function i(e){return new d(e)}function a(e){return e instanceof d}var s=e(29),u=e(147),l=null,c=null,p={},d=null,f={injectGenericComponentClass:function(e){c=e},injectTextComponentClass:function(e){d=e},injectComponentClasses:function(e){s(p,e)},injectAutoWrapper:function(e){l=e}},h={getComponentClassForElement:r,createInternalComponent:o,createInstanceForText:i,isTextComponent:a,injection:f};t.exports=h},{147:147,29:29}],79:[function(e,t,n){"use strict";var r=e(147),o={isValidOwner:function(e){return!(!e||"function"!=typeof e.attachRef||"function"!=typeof e.detachRef)},addComponentAsRefTo:function(e,t,n){r(o.isValidOwner(n)),n.attachRef(t,e)},removeComponentAsRefFrom:function(e,t,n){r(o.isValidOwner(n)),n.getPublicInstance().refs[t]===e.get
 PublicInstance()&&n.detachRef(t)}};t.exports=o},{147:147}],80:[function(e,t,n){"use strict";function r(e,t,n){return n}var o={enableMeasure:!1,storedMeasure:r,measureMethods:function(e,t,n){},measure:function(e,t,n){return n},injection:{injectMeasure:function(e){o.storedMeasure=e}}};t.exports=o},{}],81:[function(e,t,n){"use strict";function r(e){return function(t,n,r){t.hasOwnProperty(n)?t[n]=e(t[n],r):t[n]=r}}function o(e,t){for(var n in t)if(t.hasOwnProperty(n)){var r=l[n];r&&l.hasOwnProperty(n)?r(e,n,t[n]):e.hasOwnProperty(n)||(e[n]=t[n])}return e}var i=e(29),a=e(126),s=e(152),u=r(function(e,t){return i({},t,e)}),l={children:a,className:r(s),style:u},c={mergeProps:function(e,t){return o(i({},e),t)}};t.exports=c},{126:126,152:152,29:29}],82:[function(e,t,n){"use strict";var r={};t.exports=r},{}],83:[function(e,t,n){"use strict";var r=e(153),o=r({prop:null,context:null,childContext:null});t.exports=o},{153:153}],84:[function(e,t,n){"use strict";function r(e){function t(t,n,r,o,i){i
 f(o=o||b,null==n[r]){var a=C[i];return t?new Error("Required "+a+" `"+r+"` was not specified in "+("`"+o+"`.")):null}return e(n,r,o,i)}var n=t.bind(null,!1);return n.isRequired=t.bind(null,!0),n}function o(e){function t(t,n,r,o){var i=t[n],a=m(i);if(a!==e){var s=C[o],u=v(i);return new Error("Invalid "+s+" `"+n+"` of type `"+u+"` "+("supplied to `"+r+"`, expected `"+e+"`."))}return null}return r(t)}function i(){return r(E.thatReturns(null))}function a(e){function t(t,n,r,o){var i=t[n];if(!Array.isArray(i)){var a=C[o],s=m(i);return new Error("Invalid "+a+" `"+n+"` of type "+("`"+s+"` supplied to `"+r+"`, expected an array."))}for(var u=0;u<i.length;u++){var l=e(i,u,r,o);if(l instanceof Error)return l}return null}return r(t)}function s(){function e(e,t,n,r){if(!g.isValidElement(e[t])){var o=C[r];return new Error("Invalid "+o+" `"+t+"` supplied to "+("`"+n+"`, expected a ReactElement."))}return null}return r(e)}function u(e){function t(t,n,r,o){if(!(t[n]instanceof e)){var i=C[o],a=e.nam
 e||b;return new Error("Invalid "+i+" `"+n+"` supplied to "+("`"+r+"`, expected instance of `"+a+"`."))}return null}return r(t)}function l(e){function t(t,n,r,o){for(var i=t[n],a=0;a<e.length;a++)if(i===e[a])return null;var s=C[o],u=JSON.stringify(e);return new Error("Invalid "+s+" `"+n+"` of value `"+i+"` "+("supplied to `"+r+"`, expected one of "+u+"."))}return r(t)}function c(e){function t(t,n,r,o){var i=t[n],a=m(i);if("object"!==a){var s=C[o];return new Error("Invalid "+s+" `"+n+"` of type "+("`"+a+"` supplied to `"+r+"`, expected an object."))}for(var u in i)if(i.hasOwnProperty(u)){var l=e(i,u,r,o);if(l instanceof Error)return l}return null}return r(t)}function p(e){function t(t,n,r,o){for(var i=0;i<e.length;i++){var a=e[i];if(null==a(t,n,r

<TRUNCATED>

[23/47] allura git commit: [#7919] Add NavBar dependencies

Posted by br...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/db6e6859/Allura/allura/public/nf/js/browser-polyfill.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/browser-polyfill.js b/Allura/allura/public/nf/js/browser-polyfill.js
new file mode 100644
index 0000000..0e1bf66
--- /dev/null
+++ b/Allura/allura/public/nf/js/browser-polyfill.js
@@ -0,0 +1,4228 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+    draining = false;
+    if (currentQueue.length) {
+        queue = currentQueue.concat(queue);
+    } else {
+        queueIndex = -1;
+    }
+    if (queue.length) {
+        drainQueue();
+    }
+}
+
+function drainQueue() {
+    if (draining) {
+        return;
+    }
+    var timeout = setTimeout(cleanUpNextTick);
+    draining = true;
+
+    var len = queue.length;
+    while(len) {
+        currentQueue = queue;
+        queue = [];
+        while (++queueIndex < len) {
+            currentQueue[queueIndex].run();
+        }
+        queueIndex = -1;
+        len = queue.length;
+    }
+    currentQueue = null;
+    draining = false;
+    clearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+    var args = new Array(arguments.length - 1);
+    if (arguments.length > 1) {
+        for (var i = 1; i < arguments.length; i++) {
+            args[i - 1] = arguments[i];
+        }
+    }
+    queue.push(new Item(fun, args));
+    if (queue.length === 1 && !draining) {
+        setTimeout(drainQueue, 0);
+    }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+    this.fun = fun;
+    this.array = array;
+}
+Item.prototype.run = function () {
+    this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+    throw new Error('process.binding is not supported');
+};
+
+// TODO(shtylman)
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+    throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],2:[function(require,module,exports){
+(function (global){
+"use strict";
+
+require("core-js/shim");
+
+require("regenerator/runtime");
+
+if (global._babelPolyfill) {
+  throw new Error("only one instance of babel/polyfill is allowed");
+}
+global._babelPolyfill = true;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"core-js/shim":182,"regenerator/runtime":183}],3:[function(require,module,exports){
+module.exports = function(it){
+  if(typeof it != 'function')throw TypeError(it + ' is not a function!');
+  return it;
+};
+},{}],4:[function(require,module,exports){
+var isObject = require('./$.is-object');
+module.exports = function(it){
+  if(!isObject(it))throw TypeError(it + ' is not an object!');
+  return it;
+};
+},{"./$.is-object":34}],5:[function(require,module,exports){
+// false -> Array#indexOf
+// true  -> Array#includes
+var toIObject = require('./$.to-iobject')
+  , toLength  = require('./$.to-length')
+  , toIndex   = require('./$.to-index');
+module.exports = function(IS_INCLUDES){
+  return function($this, el, fromIndex){
+    var O      = toIObject($this)
+      , length = toLength(O.length)
+      , index  = toIndex(fromIndex, length)
+      , value;
+    // Array#includes uses SameValueZero equality algorithm
+    if(IS_INCLUDES && el != el)while(length > index){
+      value = O[index++];
+      if(value != value)return true;
+    // Array#toIndex ignores holes, Array#includes - not
+    } else for(;length > index; index++)if(IS_INCLUDES || index in O){
+      if(O[index] === el)return IS_INCLUDES || index;
+    } return !IS_INCLUDES && -1;
+  };
+};
+},{"./$.to-index":70,"./$.to-iobject":72,"./$.to-length":73}],6:[function(require,module,exports){
+// 0 -> Array#forEach
+// 1 -> Array#map
+// 2 -> Array#filter
+// 3 -> Array#some
+// 4 -> Array#every
+// 5 -> Array#find
+// 6 -> Array#findIndex
+var ctx      = require('./$.ctx')
+  , IObject  = require('./$.iobject')
+  , toObject = require('./$.to-object')
+  , toLength = require('./$.to-length');
+module.exports = function(TYPE){
+  var IS_MAP        = TYPE == 1
+    , IS_FILTER     = TYPE == 2
+    , IS_SOME       = TYPE == 3
+    , IS_EVERY      = TYPE == 4
+    , IS_FIND_INDEX = TYPE == 6
+    , NO_HOLES      = TYPE == 5 || IS_FIND_INDEX;
+  return function($this, callbackfn, that){
+    var O      = toObject($this)
+      , self   = IObject(O)
+      , f      = ctx(callbackfn, that, 3)
+      , length = toLength(self.length)
+      , index  = 0
+      , result = IS_MAP ? Array(length) : IS_FILTER ? [] : undefined
+      , val, res;
+    for(;length > index; index++)if(NO_HOLES || index in self){
+      val = self[index];
+      res = f(val, index, O);
+      if(TYPE){
+        if(IS_MAP)result[index] = res;            // map
+        else if(res)switch(TYPE){
+          case 3: return true;                    // some
+          case 5: return val;                     // find
+          case 6: return index;                   // findIndex
+          case 2: result.push(val);               // filter
+        } else if(IS_EVERY)return false;          // every
+      }
+    }
+    return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
+  };
+};
+},{"./$.ctx":15,"./$.iobject":31,"./$.to-length":73,"./$.to-object":74}],7:[function(require,module,exports){
+// 19.1.2.1 Object.assign(target, source, ...)
+var toObject = require('./$.to-object')
+  , IObject  = require('./$.iobject')
+  , enumKeys = require('./$.enum-keys');
+/* eslint-disable no-unused-vars */
+module.exports = Object.assign || function assign(target, source){
+/* eslint-enable no-unused-vars */
+  var T = toObject(target)
+    , l = arguments.length
+    , i = 1;
+  while(l > i){
+    var S      = IObject(arguments[i++])
+      , keys   = enumKeys(S)
+      , length = keys.length
+      , j      = 0
+      , key;
+    while(length > j)T[key = keys[j++]] = S[key];
+  }
+  return T;
+};
+},{"./$.enum-keys":19,"./$.iobject":31,"./$.to-object":74}],8:[function(require,module,exports){
+// getting tag from 19.1.3.6 Object.prototype.toString()
+var cof = require('./$.cof')
+  , TAG = require('./$.wks')('toStringTag')
+  // ES3 wrong here
+  , ARG = cof(function(){ return arguments; }()) == 'Arguments';
+
+module.exports = function(it){
+  var O, T, B;
+  return it === undefined ? 'Undefined' : it === null ? 'Null'
+    // @@toStringTag case
+    : typeof (T = (O = Object(it))[TAG]) == 'string' ? T
+    // builtinTag case
+    : ARG ? cof(O)
+    // ES3 arguments fallback
+    : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
+};
+},{"./$.cof":9,"./$.wks":77}],9:[function(require,module,exports){
+var toString = {}.toString;
+
+module.exports = function(it){
+  return toString.call(it).slice(8, -1);
+};
+},{}],10:[function(require,module,exports){
+'use strict';
+var $            = require('./$')
+  , hide         = require('./$.hide')
+  , ctx          = require('./$.ctx')
+  , species      = require('./$.species')
+  , strictNew    = require('./$.strict-new')
+  , defined      = require('./$.defined')
+  , forOf        = require('./$.for-of')
+  , step         = require('./$.iter-step')
+  , ID           = require('./$.uid')('id')
+  , $has         = require('./$.has')
+  , isObject     = require('./$.is-object')
+  , isExtensible = Object.isExtensible || isObject
+  , SUPPORT_DESC = require('./$.support-desc')
+  , SIZE         = SUPPORT_DESC ? '_s' : 'size'
+  , id           = 0;
+
+var fastKey = function(it, create){
+  // return primitive with prefix
+  if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
+  if(!$has(it, ID)){
+    // can't set id to frozen object
+    if(!isExtensible(it))return 'F';
+    // not necessary to add id
+    if(!create)return 'E';
+    // add missing object id
+    hide(it, ID, ++id);
+  // return object id with prefix
+  } return 'O' + it[ID];
+};
+
+var getEntry = function(that, key){
+  // fast case
+  var index = fastKey(key), entry;
+  if(index !== 'F')return that._i[index];
+  // frozen object case
+  for(entry = that._f; entry; entry = entry.n){
+    if(entry.k == key)return entry;
+  }
+};
+
+module.exports = {
+  getConstructor: function(wrapper, NAME, IS_MAP, ADDER){
+    var C = wrapper(function(that, iterable){
+      strictNew(that, C, NAME);
+      that._i = $.create(null); // index
+      that._f = undefined;      // first entry
+      that._l = undefined;      // last entry
+      that[SIZE] = 0;           // size
+      if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);
+    });
+    require('./$.mix')(C.prototype, {
+      // 23.1.3.1 Map.prototype.clear()
+      // 23.2.3.2 Set.prototype.clear()
+      clear: function clear(){
+        for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){
+          entry.r = true;
+          if(entry.p)entry.p = entry.p.n = undefined;
+          delete data[entry.i];
+        }
+        that._f = that._l = undefined;
+        that[SIZE] = 0;
+      },
+      // 23.1.3.3 Map.prototype.delete(key)
+      // 23.2.3.4 Set.prototype.delete(value)
+      'delete': function(key){
+        var that  = this
+          , entry = getEntry(that, key);
+        if(entry){
+          var next = entry.n
+            , prev = entry.p;
+          delete that._i[entry.i];
+          entry.r = true;
+          if(prev)prev.n = next;
+          if(next)next.p = prev;
+          if(that._f == entry)that._f = next;
+          if(that._l == entry)that._l = prev;
+          that[SIZE]--;
+        } return !!entry;
+      },
+      // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
+      // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
+      forEach: function forEach(callbackfn /*, that = undefined */){
+        var f = ctx(callbackfn, arguments[1], 3)
+          , entry;
+        while(entry = entry ? entry.n : this._f){
+          f(entry.v, entry.k, this);
+          // revert to the last existing entry
+          while(entry && entry.r)entry = entry.p;
+        }
+      },
+      // 23.1.3.7 Map.prototype.has(key)
+      // 23.2.3.7 Set.prototype.has(value)
+      has: function has(key){
+        return !!getEntry(this, key);
+      }
+    });
+    if(SUPPORT_DESC)$.setDesc(C.prototype, 'size', {
+      get: function(){
+        return defined(this[SIZE]);
+      }
+    });
+    return C;
+  },
+  def: function(that, key, value){
+    var entry = getEntry(that, key)
+      , prev, index;
+    // change existing entry
+    if(entry){
+      entry.v = value;
+    // create new entry
+    } else {
+      that._l = entry = {
+        i: index = fastKey(key, true), // <- index
+        k: key,                        // <- key
+        v: value,                      // <- value
+        p: prev = that._l,             // <- previous entry
+        n: undefined,                  // <- next entry
+        r: false                       // <- removed
+      };
+      if(!that._f)that._f = entry;
+      if(prev)prev.n = entry;
+      that[SIZE]++;
+      // add to index
+      if(index !== 'F')that._i[index] = entry;
+    } return that;
+  },
+  getEntry: getEntry,
+  setStrong: function(C, NAME, IS_MAP){
+    // add .keys, .values, .entries, [@@iterator]
+    // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
+    require('./$.iter-define')(C, NAME, function(iterated, kind){
+      this._t = iterated;  // target
+      this._k = kind;      // kind
+      this._l = undefined; // previous
+    }, function(){
+      var that  = this
+        , kind  = that._k
+        , entry = that._l;
+      // revert to the last existing entry
+      while(entry && entry.r)entry = entry.p;
+      // get next entry
+      if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){
+        // or finish the iteration
+        that._t = undefined;
+        return step(1);
+      }
+      // return step by kind
+      if(kind == 'keys'  )return step(0, entry.k);
+      if(kind == 'values')return step(0, entry.v);
+      return step(0, [entry.k, entry.v]);
+    }, IS_MAP ? 'entries' : 'values' , !IS_MAP, true);
+
+    // add [@@species], 23.1.2.2, 23.2.2.2
+    species(C);
+    species(require('./$.core')[NAME]); // for wrapper
+  }
+};
+},{"./$":42,"./$.core":14,"./$.ctx":15,"./$.defined":17,"./$.for-of":24,"./$.has":27,"./$.hide":28,"./$.is-object":34,"./$.iter-define":38,"./$.iter-step":40,"./$.mix":47,"./$.species":60,"./$.strict-new":61,"./$.support-desc":67,"./$.uid":75}],11:[function(require,module,exports){
+// https://github.com/DavidBruant/Map-Set.prototype.toJSON
+var forOf   = require('./$.for-of')
+  , classof = require('./$.classof');
+module.exports = function(NAME){
+  return function toJSON(){
+    if(classof(this) != NAME)throw TypeError(NAME + "#toJSON isn't generic");
+    var arr = [];
+    forOf(this, false, arr.push, arr);
+    return arr;
+  };
+};
+},{"./$.classof":8,"./$.for-of":24}],12:[function(require,module,exports){
+'use strict';
+var hide         = require('./$.hide')
+  , anObject     = require('./$.an-object')
+  , strictNew    = require('./$.strict-new')
+  , forOf        = require('./$.for-of')
+  , method       = require('./$.array-methods')
+  , WEAK         = require('./$.uid')('weak')
+  , isObject     = require('./$.is-object')
+  , $has         = require('./$.has')
+  , isExtensible = Object.isExtensible || isObject
+  , find         = method(5)
+  , findIndex    = method(6)
+  , id           = 0;
+
+// fallback for frozen keys
+var frozenStore = function(that){
+  return that._l || (that._l = new FrozenStore);
+};
+var FrozenStore = function(){
+  this.a = [];
+};
+var findFrozen = function(store, key){
+  return find(store.a, function(it){
+    return it[0] === key;
+  });
+};
+FrozenStore.prototype = {
+  get: function(key){
+    var entry = findFrozen(this, key);
+    if(entry)return entry[1];
+  },
+  has: function(key){
+    return !!findFrozen(this, key);
+  },
+  set: function(key, value){
+    var entry = findFrozen(this, key);
+    if(entry)entry[1] = value;
+    else this.a.push([key, value]);
+  },
+  'delete': function(key){
+    var index = findIndex(this.a, function(it){
+      return it[0] === key;
+    });
+    if(~index)this.a.splice(index, 1);
+    return !!~index;
+  }
+};
+
+module.exports = {
+  getConstructor: function(wrapper, NAME, IS_MAP, ADDER){
+    var C = wrapper(function(that, iterable){
+      strictNew(that, C, NAME);
+      that._i = id++;      // collection id
+      that._l = undefined; // leak store for frozen objects
+      if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);
+    });
+    require('./$.mix')(C.prototype, {
+      // 23.3.3.2 WeakMap.prototype.delete(key)
+      // 23.4.3.3 WeakSet.prototype.delete(value)
+      'delete': function(key){
+        if(!isObject(key))return false;
+        if(!isExtensible(key))return frozenStore(this)['delete'](key);
+        return $has(key, WEAK) && $has(key[WEAK], this._i) && delete key[WEAK][this._i];
+      },
+      // 23.3.3.4 WeakMap.prototype.has(key)
+      // 23.4.3.4 WeakSet.prototype.has(value)
+      has: function has(key){
+        if(!isObject(key))return false;
+        if(!isExtensible(key))return frozenStore(this).has(key);
+        return $has(key, WEAK) && $has(key[WEAK], this._i);
+      }
+    });
+    return C;
+  },
+  def: function(that, key, value){
+    if(!isExtensible(anObject(key))){
+      frozenStore(that).set(key, value);
+    } else {
+      $has(key, WEAK) || hide(key, WEAK, {});
+      key[WEAK][that._i] = value;
+    } return that;
+  },
+  frozenStore: frozenStore,
+  WEAK: WEAK
+};
+},{"./$.an-object":4,"./$.array-methods":6,"./$.for-of":24,"./$.has":27,"./$.hide":28,"./$.is-object":34,"./$.mix":47,"./$.strict-new":61,"./$.uid":75}],13:[function(require,module,exports){
+'use strict';
+var global     = require('./$.global')
+  , $def       = require('./$.def')
+  , BUGGY      = require('./$.iter-buggy')
+  , forOf      = require('./$.for-of')
+  , strictNew  = require('./$.strict-new');
+
+module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){
+  var Base  = global[NAME]
+    , C     = Base
+    , ADDER = IS_MAP ? 'set' : 'add'
+    , proto = C && C.prototype
+    , O     = {};
+  var fixMethod = function(KEY){
+    var fn = proto[KEY];
+    require('./$.redef')(proto, KEY,
+      KEY == 'delete' ? function(a){ return fn.call(this, a === 0 ? 0 : a); }
+      : KEY == 'has' ? function has(a){ return fn.call(this, a === 0 ? 0 : a); }
+      : KEY == 'get' ? function get(a){ return fn.call(this, a === 0 ? 0 : a); }
+      : KEY == 'add' ? function add(a){ fn.call(this, a === 0 ? 0 : a); return this; }
+      : function set(a, b){ fn.call(this, a === 0 ? 0 : a, b); return this; }
+    );
+  };
+  if(typeof C != 'function' || !(IS_WEAK || !BUGGY && proto.forEach && proto.entries)){
+    // create collection constructor
+    C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
+    require('./$.mix')(C.prototype, methods);
+  } else {
+    var inst  = new C
+      , chain = inst[ADDER](IS_WEAK ? {} : -0, 1)
+      , buggyZero;
+    // wrap for init collections from iterable
+    if(!require('./$.iter-detect')(function(iter){ new C(iter); })){ // eslint-disable-line no-new
+      C = wrapper(function(target, iterable){
+        strictNew(target, C, NAME);
+        var that = new Base;
+        if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);
+        return that;
+      });
+      C.prototype = proto;
+      proto.constructor = C;
+    }
+    IS_WEAK || inst.forEach(function(val, key){
+      buggyZero = 1 / key === -Infinity;
+    });
+    // fix converting -0 key to +0
+    if(buggyZero){
+      fixMethod('delete');
+      fixMethod('has');
+      IS_MAP && fixMethod('get');
+    }
+    // + fix .add & .set for chaining
+    if(buggyZero || chain !== inst)fixMethod(ADDER);
+    // weak collections should not contains .clear method
+    if(IS_WEAK && proto.clear)delete proto.clear;
+  }
+
+  require('./$.tag')(C, NAME);
+
+  O[NAME] = C;
+  $def($def.G + $def.W + $def.F * (C != Base), O);
+
+  if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP);
+
+  return C;
+};
+},{"./$.def":16,"./$.for-of":24,"./$.global":26,"./$.iter-buggy":35,"./$.iter-detect":39,"./$.mix":47,"./$.redef":54,"./$.strict-new":61,"./$.tag":68}],14:[function(require,module,exports){
+var core = module.exports = {};
+if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
+},{}],15:[function(require,module,exports){
+// optional / simple context binding
+var aFunction = require('./$.a-function');
+module.exports = function(fn, that, length){
+  aFunction(fn);
+  if(that === undefined)return fn;
+  switch(length){
+    case 1: return function(a){
+      return fn.call(that, a);
+    };
+    case 2: return function(a, b){
+      return fn.call(that, a, b);
+    };
+    case 3: return function(a, b, c){
+      return fn.call(that, a, b, c);
+    };
+  } return function(/* ...args */){
+      return fn.apply(that, arguments);
+    };
+};
+},{"./$.a-function":3}],16:[function(require,module,exports){
+var global     = require('./$.global')
+  , core       = require('./$.core')
+  , hide       = require('./$.hide')
+  , $redef     = require('./$.redef')
+  , PROTOTYPE  = 'prototype';
+var ctx = function(fn, that){
+  return function(){
+    return fn.apply(that, arguments);
+  };
+};
+var $def = function(type, name, source){
+  var key, own, out, exp
+    , isGlobal = type & $def.G
+    , isProto  = type & $def.P
+    , target   = isGlobal ? global : type & $def.S
+        ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE]
+    , exports  = isGlobal ? core : core[name] || (core[name] = {});
+  if(isGlobal)source = name;
+  for(key in source){
+    // contains in native
+    own = !(type & $def.F) && target && key in target;
+    // export native or passed
+    out = (own ? target : source)[key];
+    // bind timers to global for call from export context
+    if(type & $def.B && own)exp = ctx(out, global);
+    else exp = isProto && typeof out == 'function' ? ctx(Function.call, out) : out;
+    // extend global
+    if(target && !own)$redef(target, key, out);
+    // export
+    if(exports[key] != out)hide(exports, key, exp);
+    if(isProto)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out;
+  }
+};
+global.core = core;
+// type bitmap
+$def.F = 1;  // forced
+$def.G = 2;  // global
+$def.S = 4;  // static
+$def.P = 8;  // proto
+$def.B = 16; // bind
+$def.W = 32; // wrap
+module.exports = $def;
+},{"./$.core":14,"./$.global":26,"./$.hide":28,"./$.redef":54}],17:[function(require,module,exports){
+// 7.2.1 RequireObjectCoercible(argument)
+module.exports = function(it){
+  if(it == undefined)throw TypeError("Can't call method on  " + it);
+  return it;
+};
+},{}],18:[function(require,module,exports){
+var isObject = require('./$.is-object')
+  , document = require('./$.global').document
+  // in old IE typeof document.createElement is 'object'
+  , is = isObject(document) && isObject(document.createElement);
+module.exports = function(it){
+  return is ? document.createElement(it) : {};
+};
+},{"./$.global":26,"./$.is-object":34}],19:[function(require,module,exports){
+// all enumerable object keys, includes symbols
+var $ = require('./$');
+module.exports = function(it){
+  var keys       = $.getKeys(it)
+    , getSymbols = $.getSymbols;
+  if(getSymbols){
+    var symbols = getSymbols(it)
+      , isEnum  = $.isEnum
+      , i       = 0
+      , key;
+    while(symbols.length > i)if(isEnum.call(it, key = symbols[i++]))keys.push(key);
+  }
+  return keys;
+};
+},{"./$":42}],20:[function(require,module,exports){
+// 20.2.2.14 Math.expm1(x)
+module.exports = Math.expm1 || function expm1(x){
+  return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : Math.exp(x) - 1;
+};
+},{}],21:[function(require,module,exports){
+module.exports = function(exec){
+  try {
+    return !!exec();
+  } catch(e){
+    return true;
+  }
+};
+},{}],22:[function(require,module,exports){
+'use strict';
+module.exports = function(KEY, length, exec){
+  var defined  = require('./$.defined')
+    , SYMBOL   = require('./$.wks')(KEY)
+    , original = ''[KEY];
+  if(require('./$.fails')(function(){
+    var O = {};
+    O[SYMBOL] = function(){ return 7; };
+    return ''[KEY](O) != 7;
+  })){
+    require('./$.redef')(String.prototype, KEY, exec(defined, SYMBOL, original));
+    require('./$.hide')(RegExp.prototype, SYMBOL, length == 2
+      // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
+      // 21.2.5.11 RegExp.prototype[@@split](string, limit)
+      ? function(string, arg){ return original.call(string, this, arg); }
+      // 21.2.5.6 RegExp.prototype[@@match](string)
+      // 21.2.5.9 RegExp.prototype[@@search](string)
+      : function(string){ return original.call(string, this); }
+    );
+  }
+};
+},{"./$.defined":17,"./$.fails":21,"./$.hide":28,"./$.redef":54,"./$.wks":77}],23:[function(require,module,exports){
+'use strict';
+// 21.2.5.3 get RegExp.prototype.flags
+var anObject = require('./$.an-object');
+module.exports = function(){
+  var that   = anObject(this)
+    , result = '';
+  if(that.global)result += 'g';
+  if(that.ignoreCase)result += 'i';
+  if(that.multiline)result += 'm';
+  if(that.unicode)result += 'u';
+  if(that.sticky)result += 'y';
+  return result;
+};
+},{"./$.an-object":4}],24:[function(require,module,exports){
+var ctx         = require('./$.ctx')
+  , call        = require('./$.iter-call')
+  , isArrayIter = require('./$.is-array-iter')
+  , anObject    = require('./$.an-object')
+  , toLength    = require('./$.to-length')
+  , getIterFn   = require('./core.get-iterator-method');
+module.exports = function(iterable, entries, fn, that){
+  var iterFn = getIterFn(iterable)
+    , f      = ctx(fn, that, entries ? 2 : 1)
+    , index  = 0
+    , length, step, iterator;
+  if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!');
+  // fast case for arrays with default iterator
+  if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){
+    entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
+  } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){
+    call(iterator, f, step.value, entries);
+  }
+};
+},{"./$.an-object":4,"./$.ctx":15,"./$.is-array-iter":32,"./$.iter-call":36,"./$.to-length":73,"./core.get-iterator-method":78}],25:[function(require,module,exports){
+// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
+var toString  = {}.toString
+  , toIObject = require('./$.to-iobject')
+  , getNames  = require('./$').getNames;
+
+var windowNames = typeof window == 'object' && Object.getOwnPropertyNames
+  ? Object.getOwnPropertyNames(window) : [];
+
+var getWindowNames = function(it){
+  try {
+    return getNames(it);
+  } catch(e){
+    return windowNames.slice();
+  }
+};
+
+module.exports.get = function getOwnPropertyNames(it){
+  if(windowNames && toString.call(it) == '[object Window]')return getWindowNames(it);
+  return getNames(toIObject(it));
+};
+},{"./$":42,"./$.to-iobject":72}],26:[function(require,module,exports){
+var global = typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
+module.exports = global;
+if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
+},{}],27:[function(require,module,exports){
+var hasOwnProperty = {}.hasOwnProperty;
+module.exports = function(it, key){
+  return hasOwnProperty.call(it, key);
+};
+},{}],28:[function(require,module,exports){
+var $          = require('./$')
+  , createDesc = require('./$.property-desc');
+module.exports = require('./$.support-desc') ? function(object, key, value){
+  return $.setDesc(object, key, createDesc(1, value));
+} : function(object, key, value){
+  object[key] = value;
+  return object;
+};
+},{"./$":42,"./$.property-desc":53,"./$.support-desc":67}],29:[function(require,module,exports){
+module.exports = require('./$.global').document && document.documentElement;
+},{"./$.global":26}],30:[function(require,module,exports){
+// fast apply, http://jsperf.lnkit.com/fast-apply/5
+module.exports = function(fn, args, that){
+  var un = that === undefined;
+  switch(args.length){
+    case 0: return un ? fn()
+                      : fn.call(that);
+    case 1: return un ? fn(args[0])
+                      : fn.call(that, args[0]);
+    case 2: return un ? fn(args[0], args[1])
+                      : fn.call(that, args[0], args[1]);
+    case 3: return un ? fn(args[0], args[1], args[2])
+                      : fn.call(that, args[0], args[1], args[2]);
+    case 4: return un ? fn(args[0], args[1], args[2], args[3])
+                      : fn.call(that, args[0], args[1], args[2], args[3]);
+  } return              fn.apply(that, args);
+};
+},{}],31:[function(require,module,exports){
+// indexed object, fallback for non-array-like ES3 strings
+var cof = require('./$.cof');
+module.exports = 0 in Object('z') ? Object : function(it){
+  return cof(it) == 'String' ? it.split('') : Object(it);
+};
+},{"./$.cof":9}],32:[function(require,module,exports){
+// check on default Array iterator
+var Iterators = require('./$.iterators')
+  , ITERATOR  = require('./$.wks')('iterator');
+module.exports = function(it){
+  return (Iterators.Array || Array.prototype[ITERATOR]) === it;
+};
+},{"./$.iterators":41,"./$.wks":77}],33:[function(require,module,exports){
+// 20.1.2.3 Number.isInteger(number)
+var isObject = require('./$.is-object')
+  , floor    = Math.floor;
+module.exports = function isInteger(it){
+  return !isObject(it) && isFinite(it) && floor(it) === it;
+};
+},{"./$.is-object":34}],34:[function(require,module,exports){
+// http://jsperf.com/core-js-isobject
+module.exports = function(it){
+  return it !== null && (typeof it == 'object' || typeof it == 'function');
+};
+},{}],35:[function(require,module,exports){
+// Safari has buggy iterators w/o `next`
+module.exports = 'keys' in [] && !('next' in [].keys());
+},{}],36:[function(require,module,exports){
+// call something on iterator step with safe closing on error
+var anObject = require('./$.an-object');
+module.exports = function(iterator, fn, value, entries){
+  try {
+    return entries ? fn(anObject(value)[0], value[1]) : fn(value);
+  // 7.4.6 IteratorClose(iterator, completion)
+  } catch(e){
+    var ret = iterator['return'];
+    if(ret !== undefined)anObject(ret.call(iterator));
+    throw e;
+  }
+};
+},{"./$.an-object":4}],37:[function(require,module,exports){
+'use strict';
+var $ = require('./$')
+  , IteratorPrototype = {};
+
+// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
+require('./$.hide')(IteratorPrototype, require('./$.wks')('iterator'), function(){ return this; });
+
+module.exports = function(Constructor, NAME, next){
+  Constructor.prototype = $.create(IteratorPrototype, {next: require('./$.property-desc')(1,next)});
+  require('./$.tag')(Constructor, NAME + ' Iterator');
+};
+},{"./$":42,"./$.hide":28,"./$.property-desc":53,"./$.tag":68,"./$.wks":77}],38:[function(require,module,exports){
+'use strict';
+var LIBRARY         = require('./$.library')
+  , $def            = require('./$.def')
+  , $redef          = require('./$.redef')
+  , hide            = require('./$.hide')
+  , has             = require('./$.has')
+  , SYMBOL_ITERATOR = require('./$.wks')('iterator')
+  , Iterators       = require('./$.iterators')
+  , FF_ITERATOR     = '@@iterator'
+  , KEYS            = 'keys'
+  , VALUES          = 'values';
+var returnThis = function(){ return this; };
+module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCE){
+  require('./$.iter-create')(Constructor, NAME, next);
+  var createMethod = function(kind){
+    switch(kind){
+      case KEYS: return function keys(){ return new Constructor(this, kind); };
+      case VALUES: return function values(){ return new Constructor(this, kind); };
+    } return function entries(){ return new Constructor(this, kind); };
+  };
+  var TAG      = NAME + ' Iterator'
+    , proto    = Base.prototype
+    , _native  = proto[SYMBOL_ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]
+    , _default = _native || createMethod(DEFAULT)
+    , methods, key;
+  // Fix native
+  if(_native){
+    var IteratorPrototype = require('./$').getProto(_default.call(new Base));
+    // Set @@toStringTag to native iterators
+    require('./$.tag')(IteratorPrototype, TAG, true);
+    // FF fix
+    if(!LIBRARY && has(proto, FF_ITERATOR))hide(IteratorPrototype, SYMBOL_ITERATOR, returnThis);
+  }
+  // Define iterator
+  if(!LIBRARY || FORCE)hide(proto, SYMBOL_ITERATOR, _default);
+  // Plug for library
+  Iterators[NAME] = _default;
+  Iterators[TAG]  = returnThis;
+  if(DEFAULT){
+    methods = {
+      keys:    IS_SET            ? _default : createMethod(KEYS),
+      values:  DEFAULT == VALUES ? _default : createMethod(VALUES),
+      entries: DEFAULT != VALUES ? _default : createMethod('entries')
+    };
+    if(FORCE)for(key in methods){
+      if(!(key in proto))$redef(proto, key, methods[key]);
+    } else $def($def.P + $def.F * require('./$.iter-buggy'), NAME, methods);
+  }
+};
+},{"./$":42,"./$.def":16,"./$.has":27,"./$.hide":28,"./$.iter-buggy":35,"./$.iter-create":37,"./$.iterators":41,"./$.library":44,"./$.redef":54,"./$.tag":68,"./$.wks":77}],39:[function(require,module,exports){
+var SYMBOL_ITERATOR = require('./$.wks')('iterator')
+  , SAFE_CLOSING    = false;
+try {
+  var riter = [7][SYMBOL_ITERATOR]();
+  riter['return'] = function(){ SAFE_CLOSING = true; };
+  Array.from(riter, function(){ throw 2; });
+} catch(e){ /* empty */ }
+module.exports = function(exec){
+  if(!SAFE_CLOSING)return false;
+  var safe = false;
+  try {
+    var arr  = [7]
+      , iter = arr[SYMBOL_ITERATOR]();
+    iter.next = function(){ safe = true; };
+    arr[SYMBOL_ITERATOR] = function(){ return iter; };
+    exec(arr);
+  } catch(e){ /* empty */ }
+  return safe;
+};
+},{"./$.wks":77}],40:[function(require,module,exports){
+module.exports = function(done, value){
+  return {value: value, done: !!done};
+};
+},{}],41:[function(require,module,exports){
+module.exports = {};
+},{}],42:[function(require,module,exports){
+var $Object = Object;
+module.exports = {
+  create:     $Object.create,
+  getProto:   $Object.getPrototypeOf,
+  isEnum:     {}.propertyIsEnumerable,
+  getDesc:    $Object.getOwnPropertyDescriptor,
+  setDesc:    $Object.defineProperty,
+  setDescs:   $Object.defineProperties,
+  getKeys:    $Object.keys,
+  getNames:   $Object.getOwnPropertyNames,
+  getSymbols: $Object.getOwnPropertySymbols,
+  each:       [].forEach
+};
+},{}],43:[function(require,module,exports){
+var $         = require('./$')
+  , toIObject = require('./$.to-iobject');
+module.exports = function(object, el){
+  var O      = toIObject(object)
+    , keys   = $.getKeys(O)
+    , length = keys.length
+    , index  = 0
+    , key;
+  while(length > index)if(O[key = keys[index++]] === el)return key;
+};
+},{"./$":42,"./$.to-iobject":72}],44:[function(require,module,exports){
+module.exports = false;
+},{}],45:[function(require,module,exports){
+// 20.2.2.20 Math.log1p(x)
+module.exports = Math.log1p || function log1p(x){
+  return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : Math.log(1 + x);
+};
+},{}],46:[function(require,module,exports){
+var global    = require('./$.global')
+  , macrotask = require('./$.task').set
+  , Observer  = global.MutationObserver || global.WebKitMutationObserver
+  , process   = global.process
+  , head, last, notify;
+
+function flush(){
+  while(head){
+    head.fn.call(); // <- currently we use it only for Promise - try / catch not required
+    head = head.next;
+  } last = undefined;
+}
+
+// Node.js
+if(require('./$.cof')(process) == 'process'){
+  notify = function(){
+    process.nextTick(flush);
+  };
+// browsers with MutationObserver
+} else if(Observer){
+  var toggle = 1
+    , node   = document.createTextNode('');
+  new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new
+  notify = function(){
+    node.data = toggle = -toggle;
+  };
+// for other environments - macrotask based on:
+// - setImmediate
+// - MessageChannel
+// - window.postMessag
+// - onreadystatechange
+// - setTimeout
+} else {
+  notify = function(){
+    // strange IE + webpack dev server bug - use .call(global)
+    macrotask.call(global, flush);
+  };
+}
+
+module.exports = function asap(fn){
+  var task = {fn: fn, next: undefined};
+  if(last)last.next = task;
+  if(!head){
+    head = task;
+    notify();
+  } last = task;
+};
+},{"./$.cof":9,"./$.global":26,"./$.task":69}],47:[function(require,module,exports){
+var $redef = require('./$.redef');
+module.exports = function(target, src){
+  for(var key in src)$redef(target, key, src[key]);
+  return target;
+};
+},{"./$.redef":54}],48:[function(require,module,exports){
+// most Object methods by ES6 should accept primitives
+module.exports = function(KEY, exec){
+  var $def = require('./$.def')
+    , fn   = (require('./$.core').Object || {})[KEY] || Object[KEY]
+    , exp  = {};
+  exp[KEY] = exec(fn);
+  $def($def.S + $def.F * require('./$.fails')(function(){ fn(1); }), 'Object', exp);
+};
+},{"./$.core":14,"./$.def":16,"./$.fails":21}],49:[function(require,module,exports){
+var $         = require('./$')
+  , toIObject = require('./$.to-iobject');
+module.exports = function(isEntries){
+  return function(it){
+    var O      = toIObject(it)
+      , keys   = $.getKeys(O)
+      , length = keys.length
+      , i      = 0
+      , result = Array(length)
+      , key;
+    if(isEntries)while(length > i)result[i] = [key = keys[i++], O[key]];
+    else while(length > i)result[i] = O[keys[i++]];
+    return result;
+  };
+};
+},{"./$":42,"./$.to-iobject":72}],50:[function(require,module,exports){
+// all object keys, includes non-enumerable and symbols
+var $        = require('./$')
+  , anObject = require('./$.an-object');
+module.exports = function ownKeys(it){
+  var keys       = $.getNames(anObject(it))
+    , getSymbols = $.getSymbols;
+  return getSymbols ? keys.concat(getSymbols(it)) : keys;
+};
+},{"./$":42,"./$.an-object":4}],51:[function(require,module,exports){
+'use strict';
+var path      = require('./$.path')
+  , invoke    = require('./$.invoke')
+  , aFunction = require('./$.a-function');
+module.exports = function(/* ...pargs */){
+  var fn     = aFunction(this)
+    , length = arguments.length
+    , pargs  = Array(length)
+    , i      = 0
+    , _      = path._
+    , holder = false;
+  while(length > i)if((pargs[i] = arguments[i++]) === _)holder = true;
+  return function(/* ...args */){
+    var that    = this
+      , _length = arguments.length
+      , j = 0, k = 0, args;
+    if(!holder && !_length)return invoke(fn, pargs, that);
+    args = pargs.slice();
+    if(holder)for(;length > j; j++)if(args[j] === _)args[j] = arguments[k++];
+    while(_length > k)args.push(arguments[k++]);
+    return invoke(fn, args, that);
+  };
+};
+},{"./$.a-function":3,"./$.invoke":30,"./$.path":52}],52:[function(require,module,exports){
+module.exports = require('./$.global');
+},{"./$.global":26}],53:[function(require,module,exports){
+module.exports = function(bitmap, value){
+  return {
+    enumerable  : !(bitmap & 1),
+    configurable: !(bitmap & 2),
+    writable    : !(bitmap & 4),
+    value       : value
+  };
+};
+},{}],54:[function(require,module,exports){
+// add fake Function#toString
+// for correct work wrapped methods / constructors with methods like LoDash isNative
+var global    = require('./$.global')
+  , hide      = require('./$.hide')
+  , SRC       = require('./$.uid')('src')
+  , TO_STRING = 'toString'
+  , $toString = Function[TO_STRING]
+  , TPL       = ('' + $toString).split(TO_STRING);
+
+require('./$.core').inspectSource = function(it){
+  return $toString.call(it);
+};
+
+(module.exports = function(O, key, val, safe){
+  if(typeof val == 'function'){
+    hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
+    if(!('name' in val))val.name = key;
+  }
+  if(O === global){
+    O[key] = val;
+  } else {
+    if(!safe)delete O[key];
+    hide(O, key, val);
+  }
+})(Function.prototype, TO_STRING, function toString(){
+  return typeof this == 'function' && this[SRC] || $toString.call(this);
+});
+},{"./$.core":14,"./$.global":26,"./$.hide":28,"./$.uid":75}],55:[function(require,module,exports){
+module.exports = function(regExp, replace){
+  var replacer = replace === Object(replace) ? function(part){
+    return replace[part];
+  } : replace;
+  return function(it){
+    return String(it).replace(regExp, replacer);
+  };
+};
+},{}],56:[function(require,module,exports){
+module.exports = Object.is || function is(x, y){
+  return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
+};
+},{}],57:[function(require,module,exports){
+// Works with __proto__ only. Old v8 can't work with null proto objects.
+/* eslint-disable no-proto */
+var getDesc  = require('./$').getDesc
+  , isObject = require('./$.is-object')
+  , anObject = require('./$.an-object');
+var check = function(O, proto){
+  anObject(O);
+  if(!isObject(proto) && proto !== null)throw TypeError(proto + ": can't set as prototype!");
+};
+module.exports = {
+  set: Object.setPrototypeOf || ('__proto__' in {} // eslint-disable-line
+    ? function(buggy, set){
+        try {
+          set = require('./$.ctx')(Function.call, getDesc(Object.prototype, '__proto__').set, 2);
+          set({}, []);
+        } catch(e){ buggy = true; }
+        return function setPrototypeOf(O, proto){
+          check(O, proto);
+          if(buggy)O.__proto__ = proto;
+          else set(O, proto);
+          return O;
+        };
+      }()
+    : undefined),
+  check: check
+};
+},{"./$":42,"./$.an-object":4,"./$.ctx":15,"./$.is-object":34}],58:[function(require,module,exports){
+var global = require('./$.global')
+  , SHARED = '__core-js_shared__'
+  , store  = global[SHARED] || (global[SHARED] = {});
+module.exports = function(key){
+  return store[key] || (store[key] = {});
+};
+},{"./$.global":26}],59:[function(require,module,exports){
+// 20.2.2.28 Math.sign(x)
+module.exports = Math.sign || function sign(x){
+  return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;
+};
+},{}],60:[function(require,module,exports){
+'use strict';
+var $       = require('./$')
+  , SPECIES = require('./$.wks')('species');
+module.exports = function(C){
+  if(require('./$.support-desc') && !(SPECIES in C))$.setDesc(C, SPECIES, {
+    configurable: true,
+    get: function(){ return this; }
+  });
+};
+},{"./$":42,"./$.support-desc":67,"./$.wks":77}],61:[function(require,module,exports){
+module.exports = function(it, Constructor, name){
+  if(!(it instanceof Constructor))throw TypeError(name + ": use the 'new' operator!");
+  return it;
+};
+},{}],62:[function(require,module,exports){
+// true  -> String#at
+// false -> String#codePointAt
+var toInteger = require('./$.to-integer')
+  , defined   = require('./$.defined');
+module.exports = function(TO_STRING){
+  return function(that, pos){
+    var s = String(defined(that))
+      , i = toInteger(pos)
+      , l = s.length
+      , a, b;
+    if(i < 0 || i >= l)return TO_STRING ? '' : undefined;
+    a = s.charCodeAt(i);
+    return a < 0xd800 || a > 0xdbff || i + 1 === l
+      || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff
+        ? TO_STRING ? s.charAt(i) : a
+        : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
+  };
+};
+},{"./$.defined":17,"./$.to-integer":71}],63:[function(require,module,exports){
+// helper for String#{startsWith, endsWith, includes}
+var defined = require('./$.defined')
+  , cof     = require('./$.cof');
+
+module.exports = function(that, searchString, NAME){
+  if(cof(searchString) == 'RegExp')throw TypeError('String#' + NAME + " doesn't accept regex!");
+  return String(defined(that));
+};
+},{"./$.cof":9,"./$.defined":17}],64:[function(require,module,exports){
+// https://github.com/ljharb/proposal-string-pad-left-right
+var toLength = require('./$.to-length')
+  , repeat   = require('./$.string-repeat')
+  , defined  = require('./$.defined');
+
+module.exports = function(that, maxLength, fillString, left){
+  var S            = String(defined(that))
+    , stringLength = S.length
+    , fillStr      = fillString === undefined ? ' ' : String(fillString)
+    , intMaxLength = toLength(maxLength);
+  if(intMaxLength <= stringLength)return S;
+  if(fillStr == '')fillStr = ' ';
+  var fillLen = intMaxLength - stringLength
+    , stringFiller = repeat.call(fillStr, Math.ceil(fillLen / fillStr.length));
+  if(stringFiller.length > fillLen)stringFiller = left
+    ? stringFiller.slice(stringFiller.length - fillLen)
+    : stringFiller.slice(0, fillLen);
+  return left ? stringFiller + S : S + stringFiller;
+};
+},{"./$.defined":17,"./$.string-repeat":65,"./$.to-length":73}],65:[function(require,module,exports){
+'use strict';
+var toInteger = require('./$.to-integer')
+  , defined   = require('./$.defined');
+
+module.exports = function repeat(count){
+  var str = String(defined(this))
+    , res = ''
+    , n   = toInteger(count);
+  if(n < 0 || n == Infinity)throw RangeError("Count can't be negative");
+  for(;n > 0; (n >>>= 1) && (str += str))if(n & 1)res += str;
+  return res;
+};
+},{"./$.defined":17,"./$.to-integer":71}],66:[function(require,module,exports){
+// 1 -> String#trimLeft
+// 2 -> String#trimRight
+// 3 -> String#trim
+var trim = function(string, TYPE){
+  string = String(defined(string));
+  if(TYPE & 1)string = string.replace(ltrim, '');
+  if(TYPE & 2)string = string.replace(rtrim, '');
+  return string;
+};
+
+var $def    = require('./$.def')
+  , defined = require('./$.defined')
+  , spaces  = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' +
+      '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'
+  , space   = '[' + spaces + ']'
+  , non     = '\u200b\u0085'
+  , ltrim   = RegExp('^' + space + space + '*')
+  , rtrim   = RegExp(space + space + '*$');
+
+module.exports = function(KEY, exec){
+  var exp  = {};
+  exp[KEY] = exec(trim);
+  $def($def.P + $def.F * require('./$.fails')(function(){
+    return !!spaces[KEY]() || non[KEY]() != non;
+  }), 'String', exp);
+};
+},{"./$.def":16,"./$.defined":17,"./$.fails":21}],67:[function(require,module,exports){
+// Thank's IE8 for his funny defineProperty
+module.exports = !require('./$.fails')(function(){
+  return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7;
+});
+},{"./$.fails":21}],68:[function(require,module,exports){
+var has  = require('./$.has')
+  , hide = require('./$.hide')
+  , TAG  = require('./$.wks')('toStringTag');
+
+module.exports = function(it, tag, stat){
+  if(it && !has(it = stat ? it : it.prototype, TAG))hide(it, TAG, tag);
+};
+},{"./$.has":27,"./$.hide":28,"./$.wks":77}],69:[function(require,module,exports){
+'use strict';
+var ctx                = require('./$.ctx')
+  , invoke             = require('./$.invoke')
+  , html               = require('./$.html')
+  , cel                = require('./$.dom-create')
+  , global             = require('./$.global')
+  , process            = global.process
+  , setTask            = global.setImmediate
+  , clearTask          = global.clearImmediate
+  , MessageChannel     = global.MessageChannel
+  , counter            = 0
+  , queue              = {}
+  , ONREADYSTATECHANGE = 'onreadystatechange'
+  , defer, channel, port;
+var run = function(){
+  var id = +this;
+  if(queue.hasOwnProperty(id)){
+    var fn = queue[id];
+    delete queue[id];
+    fn();
+  }
+};
+var listner = function(event){
+  run.call(event.data);
+};
+// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
+if(!setTask || !clearTask){
+  setTask = function setImmediate(fn){
+    var args = [], i = 1;
+    while(arguments.length > i)args.push(arguments[i++]);
+    queue[++counter] = function(){
+      invoke(typeof fn == 'function' ? fn : Function(fn), args);
+    };
+    defer(counter);
+    return counter;
+  };
+  clearTask = function clearImmediate(id){
+    delete queue[id];
+  };
+  // Node.js 0.8-
+  if(require('./$.cof')(process) == 'process'){
+    defer = function(id){
+      process.nextTick(ctx(run, id, 1));
+    };
+  // Browsers with MessageChannel, includes WebWorkers
+  } else if(MessageChannel){
+    channel = new MessageChannel;
+    port    = channel.port2;
+    channel.port1.onmessage = listner;
+    defer = ctx(port.postMessage, port, 1);
+  // Browsers with postMessage, skip WebWorkers
+  // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
+  } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScript){
+    defer = function(id){
+      global.postMessage(id + '', '*');
+    };
+    global.addEventListener('message', listner, false);
+  // IE8-
+  } else if(ONREADYSTATECHANGE in cel('script')){
+    defer = function(id){
+      html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){
+        html.removeChild(this);
+        run.call(id);
+      };
+    };
+  // Rest old browsers
+  } else {
+    defer = function(id){
+      setTimeout(ctx(run, id, 1), 0);
+    };
+  }
+}
+module.exports = {
+  set:   setTask,
+  clear: clearTask
+};
+},{"./$.cof":9,"./$.ctx":15,"./$.dom-create":18,"./$.global":26,"./$.html":29,"./$.invoke":30}],70:[function(require,module,exports){
+var toInteger = require('./$.to-integer')
+  , max       = Math.max
+  , min       = Math.min;
+module.exports = function(index, length){
+  index = toInteger(index);
+  return index < 0 ? max(index + length, 0) : min(index, length);
+};
+},{"./$.to-integer":71}],71:[function(require,module,exports){
+// 7.1.4 ToInteger
+var ceil  = Math.ceil
+  , floor = Math.floor;
+module.exports = function(it){
+  return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
+};
+},{}],72:[function(require,module,exports){
+// to indexed object, toObject with fallback for non-array-like ES3 strings
+var IObject = require('./$.iobject')
+  , defined = require('./$.defined');
+module.exports = function(it){
+  return IObject(defined(it));
+};
+},{"./$.defined":17,"./$.iobject":31}],73:[function(require,module,exports){
+// 7.1.15 ToLength
+var toInteger = require('./$.to-integer')
+  , min       = Math.min;
+module.exports = function(it){
+  return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
+};
+},{"./$.to-integer":71}],74:[function(require,module,exports){
+// 7.1.13 ToObject(argument)
+var defined = require('./$.defined');
+module.exports = function(it){
+  return Object(defined(it));
+};
+},{"./$.defined":17}],75:[function(require,module,exports){
+var id = 0
+  , px = Math.random();
+module.exports = function(key){
+  return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
+};
+},{}],76:[function(require,module,exports){
+// 22.1.3.31 Array.prototype[@@unscopables]
+var UNSCOPABLES = require('./$.wks')('unscopables');
+if(!(UNSCOPABLES in []))require('./$.hide')(Array.prototype, UNSCOPABLES, {});
+module.exports = function(key){
+  [][UNSCOPABLES][key] = true;
+};
+},{"./$.hide":28,"./$.wks":77}],77:[function(require,module,exports){
+var store  = require('./$.shared')('wks')
+  , Symbol = require('./$.global').Symbol;
+module.exports = function(name){
+  return store[name] || (store[name] =
+    Symbol && Symbol[name] || (Symbol || require('./$.uid'))('Symbol.' + name));
+};
+},{"./$.global":26,"./$.shared":58,"./$.uid":75}],78:[function(require,module,exports){
+var classof   = require('./$.classof')
+  , ITERATOR  = require('./$.wks')('iterator')
+  , Iterators = require('./$.iterators');
+module.exports = require('./$.core').getIteratorMethod = function(it){
+  if(it != undefined)return it[ITERATOR] || it['@@iterator'] || Iterators[classof(it)];
+};
+},{"./$.classof":8,"./$.core":14,"./$.iterators":41,"./$.wks":77}],79:[function(require,module,exports){
+'use strict';
+var $                = require('./$')
+  , SUPPORT_DESC     = require('./$.support-desc')
+  , createDesc       = require('./$.property-desc')
+  , html             = require('./$.html')
+  , cel              = require('./$.dom-create')
+  , has              = require('./$.has')
+  , cof              = require('./$.cof')
+  , $def             = require('./$.def')
+  , invoke           = require('./$.invoke')
+  , arrayMethod      = require('./$.array-methods')
+  , IE_PROTO         = require('./$.uid')('__proto__')
+  , isObject         = require('./$.is-object')
+  , anObject         = require('./$.an-object')
+  , aFunction        = require('./$.a-function')
+  , toObject         = require('./$.to-object')
+  , toIObject        = require('./$.to-iobject')
+  , toInteger        = require('./$.to-integer')
+  , toIndex          = require('./$.to-index')
+  , toLength         = require('./$.to-length')
+  , IObject          = require('./$.iobject')
+  , fails            = require('./$.fails')
+  , ObjectProto      = Object.prototype
+  , A                = []
+  , _slice           = A.slice
+  , _join            = A.join
+  , defineProperty   = $.setDesc
+  , getOwnDescriptor = $.getDesc
+  , defineProperties = $.setDescs
+  , $indexOf         = require('./$.array-includes')(false)
+  , factories        = {}
+  , IE8_DOM_DEFINE;
+
+if(!SUPPORT_DESC){
+  IE8_DOM_DEFINE = !fails(function(){
+    return defineProperty(cel('div'), 'a', {get: function(){ return 7; }}).a != 7;
+  });
+  $.setDesc = function(O, P, Attributes){
+    if(IE8_DOM_DEFINE)try {
+      return defineProperty(O, P, Attributes);
+    } catch(e){ /* empty */ }
+    if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!');
+    if('value' in Attributes)anObject(O)[P] = Attributes.value;
+    return O;
+  };
+  $.getDesc = function(O, P){
+    if(IE8_DOM_DEFINE)try {
+      return getOwnDescriptor(O, P);
+    } catch(e){ /* empty */ }
+    if(has(O, P))return createDesc(!ObjectProto.propertyIsEnumerable.call(O, P), O[P]);
+  };
+  $.setDescs = defineProperties = function(O, Properties){
+    anObject(O);
+    var keys   = $.getKeys(Properties)
+      , length = keys.length
+      , i = 0
+      , P;
+    while(length > i)$.setDesc(O, P = keys[i++], Properties[P]);
+    return O;
+  };
+}
+$def($def.S + $def.F * !SUPPORT_DESC, 'Object', {
+  // 19.1.2.6 / 15.2.3.3 Object.getOwnPropertyDescriptor(O, P)
+  getOwnPropertyDescriptor: $.getDesc,
+  // 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes)
+  defineProperty: $.setDesc,
+  // 19.1.2.3 / 15.2.3.7 Object.defineProperties(O, Properties)
+  defineProperties: defineProperties
+});
+
+  // IE 8- don't enum bug keys
+var keys1 = ('constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,' +
+            'toLocaleString,toString,valueOf').split(',')
+  // Additional keys for getOwnPropertyNames
+  , keys2 = keys1.concat('length', 'prototype')
+  , keysLen1 = keys1.length;
+
+// Create object with `null` prototype: use iframe Object with cleared prototype
+var createDict = function(){
+  // Thrash, waste and sodomy: IE GC bug
+  var iframe = cel('iframe')
+    , i      = keysLen1
+    , gt     = '>'
+    , iframeDocument;
+  iframe.style.display = 'none';
+  html.appendChild(iframe);
+  iframe.src = 'javascript:'; // eslint-disable-line no-script-url
+  // createDict = iframe.contentWindow.Object;
+  // html.removeChild(iframe);
+  iframeDocument = iframe.contentWindow.document;
+  iframeDocument.open();
+  iframeDocument.write('<script>document.F=Object</script' + gt);
+  iframeDocument.close();
+  createDict = iframeDocument.F;
+  while(i--)delete createDict.prototype[keys1[i]];
+  return createDict();
+};
+var createGetKeys = function(names, length){
+  return function(object){
+    var O      = toIObject(object)
+      , i      = 0
+      , result = []
+      , key;
+    for(key in O)if(key != IE_PROTO)has(O, key) && result.push(key);
+    // Don't enum bug & hidden keys
+    while(length > i)if(has(O, key = names[i++])){
+      ~$indexOf(result, key) || result.push(key);
+    }
+    return result;
+  };
+};
+var Empty = function(){};
+$def($def.S, 'Object', {
+  // 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)
+  getPrototypeOf: $.getProto = $.getProto || function(O){
+    O = toObject(O);
+    if(has(O, IE_PROTO))return O[IE_PROTO];
+    if(typeof O.constructor == 'function' && O instanceof O.constructor){
+      return O.constructor.prototype;
+    } return O instanceof Object ? ObjectProto : null;
+  },
+  // 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)
+  getOwnPropertyNames: $.getNames = $.getNames || createGetKeys(keys2, keys2.length, true),
+  // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
+  create: $.create = $.create || function(O, /*?*/Properties){
+    var result;
+    if(O !== null){
+      Empty.prototype = anObject(O);
+      result = new Empty();
+      Empty.prototype = null;
+      // add "__proto__" for Object.getPrototypeOf shim
+      result[IE_PROTO] = O;
+    } else result = createDict();
+    return Properties === undefined ? result : defineProperties(result, Properties);
+  },
+  // 19.1.2.14 / 15.2.3.14 Object.keys(O)
+  keys: $.getKeys = $.getKeys || createGetKeys(keys1, keysLen1, false)
+});
+
+var construct = function(F, len, args){
+  if(!(len in factories)){
+    for(var n = [], i = 0; i < len; i++)n[i] = 'a[' + i + ']';
+    factories[len] = Function('F,a', 'return new F(' + n.join(',') + ')');
+  }
+  return factories[len](F, args);
+};
+
+// 19.2.3.2 / 15.3.4.5 Function.prototype.bind(thisArg, args...)
+$def($def.P, 'Function', {
+  bind: function bind(that /*, args... */){
+    var fn       = aFunction(this)
+      , partArgs = _slice.call(arguments, 1);
+    var bound = function(/* args... */){
+      var args = partArgs.concat(_slice.call(arguments));
+      return this instanceof bound ? construct(fn, args.length, args) : invoke(fn, args, that);
+    };
+    if(isObject(fn.prototype))bound.prototype = fn.prototype;
+    return bound;
+  }
+});
+
+// fallback for not array-like ES3 strings and DOM objects
+var buggySlice = fails(function(){
+  if(html)_slice.call(html);
+});
+
+$def($def.P + $def.F * buggySlice, 'Array', {
+  slice: function(begin, end){
+    var len   = toLength(this.length)
+      , klass = cof(this);
+    end = end === undefined ? len : end;
+    if(klass == 'Array')return _slice.call(this, begin, end);
+    var start  = toIndex(begin, len)
+      , upTo   = toIndex(end, len)
+      , size   = toLength(upTo - start)
+      , cloned = Array(size)
+      , i      = 0;
+    for(; i < size; i++)cloned[i] = klass == 'String'
+      ? this.charAt(start + i)
+      : this[start + i];
+    return cloned;
+  }
+});
+$def($def.P + $def.F * (IObject != Object), 'Array', {
+  join: function(){
+    return _join.apply(IObject(this), arguments);
+  }
+});
+
+// 22.1.2.2 / 15.4.3.2 Array.isArray(arg)
+$def($def.S, 'Array', {isArray: function(arg){ return cof(arg) == 'Array'; }});
+
+var createArrayReduce = function(isRight){
+  return function(callbackfn, memo){
+    aFunction(callbackfn);
+    var O      = IObject(this)
+      , length = toLength(O.length)
+      , index  = isRight ? length - 1 : 0
+      , i      = isRight ? -1 : 1;
+    if(arguments.length < 2)for(;;){
+      if(index in O){
+        memo = O[index];
+        index += i;
+        break;
+      }
+      index += i;
+      if(isRight ? index < 0 : length <= index){
+        throw TypeError('Reduce of empty array with no initial value');
+      }
+    }
+    for(;isRight ? index >= 0 : length > index; index += i)if(index in O){
+      memo = callbackfn(memo, O[index], index, this);
+    }
+    return memo;
+  };
+};
+var methodize = function($fn){
+  return function(arg1/*, arg2 = undefined */){
+    return $fn(this, arg1, arguments[1]);
+  };
+};
+$def($def.P, 'Array', {
+  // 22.1.3.10 / 15.4.4.18 Array.prototype.forEach(callbackfn [, thisArg])
+  forEach: $.each = $.each || methodize(arrayMethod(0)),
+  // 22.1.3.15 / 15.4.4.19 Array.prototype.map(callbackfn [, thisArg])
+  map: methodize(arrayMethod(1)),
+  // 22.1.3.7 / 15.4.4.20 Array.prototype.filter(callbackfn [, thisArg])
+  filter: methodize(arrayMethod(2)),
+  // 22.1.3.23 / 15.4.4.17 Array.prototype.some(callbackfn [, thisArg])
+  some: methodize(arrayMethod(3)),
+  // 22.1.3.5 / 15.4.4.16 Array.prototype.every(callbackfn [, thisArg])
+  every: methodize(arrayMethod(4)),
+  // 22.1.3.18 / 15.4.4.21 Array.prototype.reduce(callbackfn [, initialValue])
+  reduce: createArrayReduce(false),
+  // 22.1.3.19 / 15.4.4.22 Array.prototype.reduceRight(callbackfn [, initialValue])
+  reduceRight: createArrayReduce(true),
+  // 22.1.3.11 / 15.4.4.14 Array.prototype.indexOf(searchElement [, fromIndex])
+  indexOf: methodize($indexOf),
+  // 22.1.3.14 / 15.4.4.15 Array.prototype.lastIndexOf(searchElement [, fromIndex])
+  lastIndexOf: function(el, fromIndex /* = @[*-1] */){
+    var O      = toIObject(this)
+      , length = toLength(O.length)
+      , index  = length - 1;
+    if(arguments.length > 1)index = Math.min(index, toInteger(fromIndex));
+    if(index < 0)index = toLength(length + index);
+    for(;index >= 0; index--)if(index in O)if(O[index] === el)return index;
+    return -1;
+  }
+});
+
+// 20.3.3.1 / 15.9.4.4 Date.now()
+$def($def.S, 'Date', {now: function(){ return +new Date; }});
+
+var lz = function(num){
+  return num > 9 ? num : '0' + num;
+};
+
+// 20.3.4.36 / 15.9.5.43 Date.prototype.toISOString()
+// PhantomJS and old webkit had a broken Date implementation.
+var date       = new Date(-5e13 - 1)
+  , brokenDate = !(date.toISOString && date.toISOString() == '0385-07-25T07:06:39.999Z'
+      && fails(function(){ new Date(NaN).toISOString(); }));
+$def($def.P + $def.F * brokenDate, 'Date', {
+  toISOString: function toISOString(){
+    if(!isFinite(this))throw RangeError('Invalid time value');
+    var d = this
+      , y = d.getUTCFullYear()
+      , m = d.getUTCMilliseconds()
+      , s = y < 0 ? '-' : y > 9999 ? '+' : '';
+    return s + ('00000' + Math.abs(y)).slice(s ? -6 : -4) +
+      '-' + lz(d.getUTCMonth() + 1) + '-' + lz(d.getUTCDate()) +
+      'T' + lz(d.getUTCHours()) + ':' + lz(d.getUTCMinutes()) +
+      ':' + lz(d.getUTCSeconds()) + '.' + (m > 99 ? m : '0' + lz(m)) + 'Z';
+  }
+});
+},{"./$":42,"./$.a-function":3,"./$.an-object":4,"./$.array-includes":5,"./$.array-methods":6,"./$.cof":9,"./$.def":16,"./$.dom-create":18,"./$.fails":21,"./$.has":27,"./$.html":29,"./$.invoke":30,"./$.iobject":31,"./$.is-object":34,"./$.property-desc":53,"./$.support-desc":67,"./$.to-index":70,"./$.to-integer":71,"./$.to-iobject":72,"./$.to-length":73,"./$.to-object":74,"./$.uid":75}],80:[function(require,module,exports){
+'use strict';
+var $def     = require('./$.def')
+  , toObject = require('./$.to-object')
+  , toIndex  = require('./$.to-index')
+  , toLength = require('./$.to-length');
+$def($def.P, 'Array', {
+  // 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length)
+  copyWithin: function copyWithin(target/* = 0 */, start /* = 0, end = @length */){
+    var O     = toObject(this)
+      , len   = toLength(O.length)
+      , to    = toIndex(target, len)
+      , from  = toIndex(start, len)
+      , end   = arguments[2]
+      , fin   = end === undefined ? len : toIndex(end, len)
+      , count = Math.min(fin - from, len - to)
+      , inc   = 1;
+    if(from < to && to < from + count){
+      inc  = -1;
+      from = from + count - 1;
+      to   = to   + count - 1;
+    }
+    while(count-- > 0){
+      if(from in O)O[to] = O[from];
+      else delete O[to];
+      to   += inc;
+      from += inc;
+    } return O;
+  }
+});
+require('./$.unscope')('copyWithin');
+},{"./$.def":16,"./$.to-index":70,"./$.to-length":73,"./$.to-object":74,"./$.unscope":76}],81:[function(require,module,exports){
+'use strict';
+var $def     = require('./$.def')
+  , toObject = require('./$.to-object')
+  , toIndex  = require('./$.to-index')
+  , toLength = require('./$.to-length');
+$def($def.P, 'Array', {
+  // 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length)
+  fill: function fill(value /*, start = 0, end = @length */){
+    var O      = toObject(this, true)
+      , length = toLength(O.length)
+      , index  = toIndex(arguments[1], length)
+      , end    = arguments[2]
+      , endPos = end === undefined ? length : toIndex(end, length);
+    while(endPos > index)O[index++] = value;
+    return O;
+  }
+});
+require('./$.unscope')('fill');
+},{"./$.def":16,"./$.to-index":70,"./$.to-length":73,"./$.to-object":74,"./$.unscope":76}],82:[function(require,module,exports){
+'use strict';
+// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined)
+var KEY    = 'findIndex'
+  , $def   = require('./$.def')
+  , forced = true
+  , $find  = require('./$.array-methods')(6);
+// Shouldn't skip holes
+if(KEY in [])Array(1)[KEY](function(){ forced = false; });
+$def($def.P + $def.F * forced, 'Array', {
+  findIndex: function findIndex(callbackfn/*, that = undefined */){
+    return $find(this, callbackfn, arguments[1]);
+  }
+});
+require('./$.unscope')(KEY);
+},{"./$.array-methods":6,"./$.def":16,"./$.unscope":76}],83:[function(require,module,exports){
+'use strict';
+// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined)
+var KEY    = 'find'
+  , $def   = require('./$.def')
+  , forced = true
+  , $find  = require('./$.array-methods')(5);
+// Shouldn't skip holes
+if(KEY in [])Array(1)[KEY](function(){ forced = false; });
+$def($def.P + $def.F * forced, 'Array', {
+  find: function find(callbackfn/*, that = undefined */){
+    return $find(this, callbackfn, arguments[1]);
+  }
+});
+require('./$.unscope')(KEY);
+},{"./$.array-methods":6,"./$.def":16,"./$.unscope":76}],84:[function(require,module,exports){
+'use strict';
+var ctx         = require('./$.ctx')
+  , $def        = require('./$.def')
+  , toObject    = require('./$.to-object')
+  , call        = require('./$.iter-call')
+  , isArrayIter = require('./$.is-array-iter')
+  , toLength    = require('./$.to-length')
+  , getIterFn   = require('./core.get-iterator-method');
+$def($def.S + $def.F * !require('./$.iter-detect')(function(iter){ Array.from(iter); }), 'Array', {
+  // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)
+  from: function from(arrayLike/*, mapfn = undefined, thisArg = undefined*/){
+    var O       = toObject(arrayLike)
+      , C       = typeof this == 'function' ? this : Array
+      , mapfn   = arguments[1]
+      , mapping = mapfn !== undefined
+      , index   = 0
+      , iterFn  = getIterFn(O)
+      , length, result, step, iterator;
+    if(mapping)mapfn = ctx(mapfn, arguments[2], 2);
+    // if object isn't iterable or it's array with default iterator - use simple case
+    if(iterFn != undefined && !(C == Array && isArrayIter(iterFn))){
+      for(iterator = iterFn.call(O), result = new C; !(step = iterator.next()).done; index++){
+        result[index] = mapping ? call(iterator, mapfn, [step.value, index], true) : step.value;
+      }
+    } else {
+      for(result = new C(length = toLength(O.length)); length > index; index++){
+        result[index] = mapping ? mapfn(O[index], index) : O[index];
+      }
+    }
+    result.length = index;
+    return result;
+  }
+});
+},{"./$.ctx":15,"./$.def":16,"./$.is-array-iter":32,"./$.iter-call":36,"./$.iter-detect":39,"./$.to-length":73,"./$.to-object":74,"./core.get-iterator-method":78}],85:[function(require,module,exports){
+'use strict';
+var setUnscope = require('./$.unscope')
+  , step       = require('./$.iter-step')
+  , Iterators  = require('./$.iterators')
+  , toIObject  = require('./$.to-iobject');
+
+// 22.1.3.4 Array.prototype.entries()
+// 22.1.3.13 Array.prototype.keys()
+// 22.1.3.29 Array.prototype.values()
+// 22.1.3.30 Array.prototype[@@iterator]()
+require('./$.iter-define')(Array, 'Array', function(iterated, kind){
+  this._t = toIObject(iterated); // target
+  this._i = 0;                   // next index
+  this._k = kind;                // kind
+// 22.1.5.2.1 %ArrayIteratorPrototype%.next()
+}, function(){
+  var O     = this._t
+    , kind  = this._k
+    , index = this._i++;
+  if(!O || index >= O.length){
+    this._t = undefined;
+    return step(1);
+  }
+  if(kind == 'keys'  )return step(0, index);
+  if(kind == 'values')return step(0, O[index]);
+  return step(0, [index, O[index]]);
+}, 'values');
+
+// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
+Iterators.Arguments = Iterators.Array;
+
+setUnscope('keys');
+setUnscope('values');
+setUnscope('entries');
+},{"./$.iter-define":38,"./$.iter-step":40,"./$.iterators":41,"./$.to-iobject":72,"./$.unscope":76}],86:[function(require,module,exports){
+'use strict';
+var $def = require('./$.def');
+$def($def.S, 'Array', {
+  // 22.1.2.3 Array.of( ...items)
+  of: function of(/* ...args */){
+    var index  = 0
+      , length = arguments.length
+      , result = new (typeof this == 'function' ? this : Array)(length);
+    while(length > index)result[index] = arguments[index++];
+    result.length = length;
+    return result;
+  }
+});
+},{"./$.def":16}],87:[function(require,module,exports){
+require('./$.species')(Array);
+},{"./$.species":60}],88:[function(require,module,exports){
+'use strict';
+var $             = require('./$')
+  , isObject      = require('./$.is-object')
+  , HAS_INSTANCE  = require('./$.wks')('hasInstance')
+  , FunctionProto = Function.prototype;
+// 19.2.3.6 Function.prototype[@@hasInstance](V)
+if(!(HAS_INSTANCE in FunctionProto))$.setDesc(FunctionProto, HAS_INSTANCE, {value: function(O){
+  if(typeof this != 'function' || !isObject(O))return false;
+  if(!isObject(this.prototype))return O instanceof this;
+  // for environment w/o native `@@hasInstance` logic enough `instanceof`, but add this:
+  while(O = $.getProto(O))if(this.prototype === O)return true;
+  return false;
+}});
+},{"./$":42,"./$.is-object":34,"./$.wks":77}],89:[function(require,module,exports){
+var setDesc    = require('./$').setDesc
+  , createDesc = require('./$.property-desc')
+  , has        = require('./$.has')
+  , FProto     = Function.prototype
+  , nameRE     = /^\s*function ([^ (]*)/
+  , NAME       = 'name';
+// 19.2.4.2 name
+NAME in FProto || require('./$.support-desc') && setDesc(FProto, NAME, {
+  configurable: true,
+  get: function(){
+    var match = ('' + this).match(nameRE)
+      , name  = match ? match[1] : '';
+    has(this, NAME) || setDesc(this, NAME, createDesc(5, name));
+    return name;
+  }
+});
+},{"./$":42,"./$.has":27,"./$.property-desc":53,"./$.support-desc":67}],90:[function(require,module,exports){
+'use strict';
+var strong = require('./$.collection-strong');
+
+// 23.1 Map Objects
+require('./$.collection')('Map', function(get){
+  return function Map(){ return get(this, arguments[0]); };
+}, {
+  // 23.1.3.6 Map.prototype.get(key)
+  get: function get(key){
+    var entry = strong.getEntry(this, key);
+    return entry && entry.v;
+  },
+  // 23.1.3.9 Map.prototype.set(key, value)
+  set: function set(key, value){
+    return strong.def(this, key === 0 ? 0 : key, value);
+  }
+}, strong, true);
+},{"./$.collection":13,"./$.collection-strong":10}],91:[function(require,module,exports){
+// 20.2.2.3 Math.acosh(x)
+var $def   = require('./$.def')
+  , log1p  = require('./$.log1p')
+  , sqrt   = Math.sqrt
+  , $acosh = Math.acosh;
+
+// V8 bug https://code.google.com/p/v8/issues/detail?id=3509 
+$def($def.S + $def.F * !($acosh && Math.floor($acosh(Number.MAX_VALUE)) == 710), 'Math', {
+  acosh: function acosh(x){
+    return (x = +x) < 1 ? NaN : x > 94906265.62425156
+      ? Math.log(x) + Math.LN2
+      : log1p(x - 1 + sqrt(x - 1) * sqrt(x + 1));
+  }
+});
+},{"./$.def":16,"./$.log1p":45}],92:[function(require,module,exports){
+// 20.2.2.5 Math.asinh(x)
+var $def = require('./$.def');
+
+function asinh(x){
+  return !isFinite(x = +x) || x == 0 ? x : x < 0 ? -asinh(-x) : Math.log(x + Math.sqrt(x * x + 1));
+}
+
+$def($def.S, 'Math', {asinh: asinh});
+},{"./$.def":16}],93:[function(require,module,exports){
+// 20.2.2.7 Math.atanh(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {
+  atanh: function atanh(x){
+    return (x = +x) == 0 ? x : Math.log((1 + x) / (1 - x)) / 2;
+  }
+});
+},{"./$.def":16}],94:[function(require,module,exports){
+// 20.2.2.9 Math.cbrt(x)
+var $def = require('./$.def')
+  , sign = require('./$.sign');
+
+$def($def.S, 'Math', {
+  cbrt: function cbrt(x){
+    return sign(x = +x) * Math.pow(Math.abs(x), 1 / 3);
+  }
+});
+},{"./$.def":16,"./$.sign":59}],95:[function(require,module,exports){
+// 20.2.2.11 Math.clz32(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {
+  clz32: function clz32(x){
+    return (x >>>= 0) ? 31 - Math.floor(Math.log(x + 0.5) * Math.LOG2E) : 32;
+  }
+});
+},{"./$.def":16}],96:[function(require,module,exports){
+// 20.2.2.12 Math.cosh(x)
+var $def = require('./$.def')
+  , exp  = Math.exp;
+
+$def($def.S, 'Math', {
+  cosh: function cosh(x){
+    return (exp(x = +x) + exp(-x)) / 2;
+  }
+});
+},{"./$.def":16}],97:[function(require,module,exports){
+// 20.2.2.14 Math.expm1(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {expm1: require('./$.expm1')});
+},{"./$.def":16,"./$.expm1":20}],98:[function(require,module,exports){
+// 20.2.2.16 Math.fround(x)
+var $def  = require('./$.def')
+  , sign  = require('./$.sign')
+  , pow   = Math.pow
+  , EPSILON   = pow(2, -52)
+  , EPSILON32 = pow(2, -23)
+  , MAX32     = pow(2, 127) * (2 - EPSILON32)
+  , MIN32     = pow(2, -126);
+
+var roundTiesToEven = function(n){
+  return n + 1 / EPSILON - 1 / EPSILON;
+};
+
+
+$def($def.S, 'Math', {
+  fround: function fround(x){
+    var $abs  = Math.abs(x)
+      , $sign = sign(x)
+      , a, result;
+    if($abs < MIN32)return $sign * roundTiesToEven($abs / MIN32 / EPSILON32) * MIN32 * EPSILON32;
+    a = (1 + EPSILON32 / EPSILON) * $abs;
+    result = a - (a - $abs);
+    if(result > MAX32 || result != result)return $sign * Infinity;
+    return $sign * result;
+  }
+});
+},{"./$.def":16,"./$.sign":59}],99:[function(require,module,exports){
+// 20.2.2.17 Math.hypot([value1[, value2[, … ]]])
+var $def = require('./$.def')
+  , abs  = Math.abs;
+
+$def($def.S, 'Math', {
+  hypot: function hypot(value1, value2){ // eslint-disable-line no-unused-vars
+    var sum  = 0
+      , i    = 0
+      , len  = arguments.length
+      , larg = 0
+      , arg, div;
+    while(i < len){
+      arg = abs(arguments[i++]);
+      if(larg < arg){
+        div  = larg / arg;
+        sum  = sum * div * div + 1;
+        larg = arg;
+      } else if(arg > 0){
+        div  = arg / larg;
+        sum += div * div;
+      } else sum += arg;
+    }
+    return larg === Infinity ? Infinity : larg * Math.sqrt(sum);
+  }
+});
+},{"./$.def":16}],100:[function(require,module,exports){
+// 20.2.2.18 Math.imul(x, y)
+var $def = require('./$.def');
+
+// WebKit fails with big numbers
+$def($def.S + $def.F * require('./$.fails')(function(){
+  return Math.imul(0xffffffff, 5) != -5;
+}), 'Math', {
+  imul: function imul(x, y){
+    var UINT16 = 0xffff
+      , xn = +x
+      , yn = +y
+      , xl = UINT16 & xn
+      , yl = UINT16 & yn;
+    return 0 | xl * yl + ((UINT16 & xn >>> 16) * yl + xl * (UINT16 & yn >>> 16) << 16 >>> 0);
+  }
+});
+},{"./$.def":16,"./$.fails":21}],101:[function(require,module,exports){
+// 20.2.2.21 Math.log10(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {
+  log10: function log10(x){
+    return Math.log(x) / Math.LN10;
+  }
+});
+},{"./$.def":16}],102:[function(require,module,exports){
+// 20.2.2.20 Math.log1p(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {log1p: require('./$.log1p')});
+},{"./$.def":16,"./$.log1p":45}],103:[function(require,module,exports){
+// 20.2.2.22 Math.log2(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {
+  log2: function log2(x){
+    return Math.log(x) / Math.LN2;
+  }
+});
+},{"./$.def":16}],104:[function(require,module,exports){
+// 20.2.2.28 Math.sign(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {sign: require('./$.sign')});
+},{"./$.def":16,"./$.sign":59}],105:[function(require,module,exports){
+// 20.2.2.30 Math.sinh(x)
+var $def  = require('./$.def')
+  , expm1 = require('./$.expm1')
+  , exp   = Math.exp;
+
+$def($def.S, 'Math', {
+  sinh: function sinh(x){
+    return Math.abs(x = +x) < 1
+      ? (expm1(x) - expm1(-x)) / 2
+      : (exp(x - 1) - exp(-x - 1)) * (Math.E / 2);
+  }
+});
+},{"./$.def":16,"./$.expm1":20}],106:[function(require,module,exports){
+// 20.2.2.33 Math.tanh(x)
+var $def  = require('./$.def')
+  , expm1 = require('./$.expm1')
+  , exp   = Math.exp;
+
+$def($def.S, 'Math', {
+  tanh: function tanh(x){
+    var a = expm1(x = +x)
+      , b = expm1(-x);
+    return a == Infinity ? 1 : b == Infinity ? -1 : (a - b) / (exp(x) + exp(-x));
+  }
+});
+},{"./$.def":16,"./$.expm1":20}],107:[function(require,module,exports){
+// 20.2.2.34 Math.trunc(x)
+var $def = require('./$.def');
+
+$def($def.S, 'Math', {
+  trunc: function trunc(it){
+    return (it > 0 ? Math.floor : Math.ceil)(it);
+  }
+});
+},{"./$.def":16}],108:[function(require,module,exports){
+'use strict';
+var $          = require('./$')
+  , global     = require('./$.global')
+  , has        = require('./$.has')
+  , cof        = require('./$.cof')
+  , isObject   = require('./$.is-object')
+  , fails      = require('./$.fails')
+  , NUMBER     = 'Number'
+  , $Number    = global[NUMBER]
+  , Base       = $Number
+  , proto      = $Number.prototype
+  // Opera ~12 has broken Object#toString
+  , BROKEN_COF = cof($.create(proto)) == NUMBER;
+var toPrimitive = function(it){
+  var fn, val;
+  if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val;
+  if(typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val;
+  throw TypeError("Can't convert object to number");
+};
+var toNumber = function(it){
+  if(isObject(it))it = toPrimitive(it);
+  if(typeof it == 'string' && it.length > 2 && it.charCodeAt(0) == 48){
+    var binary = false;
+    switch(it.charCodeAt(1)){
+      case 66 : case 98  : binary = true;
+      case 79 : case 111 : return parseInt(it.slice(2), binary ? 2 : 8);
+    }
+  } return +it;
+};
+if(!($Number('0o1') && $Number('0b1'))){
+  $Number = function Number(it){
+    var that = this;
+    return that instanceof $Number
+      // check on 1..constructor(foo) case
+      && (BROKEN_COF ? fails(function(){ proto.valueOf.call(that); }) : cof(that) != NUMBER)
+        ? new Base(toNumber(it)) : toNumber(it);
+  };
+  $.each.call(require('./$.support-desc') ? $.getNames(Base) : (
+      // ES3:
+      'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
+      // ES6 (in case, if modules with ES6 Number statics required before):
+      'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' +
+      'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger'
+    ).split(','), function(key){
+      if(has(Base, key) && !has($Number, key)){
+        $.setDesc($Number, key, $.getDesc(Base, key));
+      }
+    }
+  );
+  $Number.prototype = proto;
+  proto.constructor = $Number;
+  require('./$.redef')(global, NUMBER, $Number);
+}
+},{"./$":42,"./$.cof":9,"./$.fails":21,"./$.global":26,"./$.has":27,"./$.is-object":34,"./$.redef":54,"./$.support-desc":67}],109:[function(require,module,exports){
+// 20.1.2.1 Number.EPSILON
+var $def = require('./$.def');
+
+$def($def.S, 'Number', {EPSILON: Math.pow(2, -52)});
+},{"./$.def":16}],110:[function(require,module,exports){
+// 20.1.2.2 Number.isFinite(number)
+var $def      = require('./$.def')
+  , _isFinite = require('./$.global').isFinite;
+
+$def($def.S, 'Number', {
+  isFinite: function isFinite(it){
+    return typeof it == 'number' && _isFinite(it);
+  }
+});
+},{"./$.def":16,"./$.global":26}],111:[function(require,module,exports){
+// 20.1.2.3 Number.isInteger(number)
+var $def = require('./$.def');
+
+$def($def.S, 'Number', {isInteger: require('./$.is-integer')});
+},{"./$.def":16,"./$.is-integer":33}],112:[function(require,module,exports){
+// 20.1.2.4 Number.isNaN(number)
+var $def = require('./$.def');
+
+$def($def.S, 'Number', {
+  isNaN: function isNaN(number){
+    return number != number;
+  }
+});
+},{"./$.def":16}],113:[function(require,module,exports){
+// 20.1.2.5 Number.isSafeInteger(number)
+var $def      = require('./$.def')
+  , isInteger = require('./$.is-integer')
+  , abs       = Math.abs;
+
+$def($def.S, 'Number', {
+  isSafeInteger: function isSafeInteger(number){
+    return isInteger(number) && abs(number) <= 0x1fffffffffffff;
+  }
+});
+},{"./$.def":16,"./$.is-integer":33}],114:[function(require,module,exports){
+// 20.1.2.6 Number.MAX_SAFE_INTEGER
+var $def = require('./$.def');
+
+$def($def.S, 'Number', {MAX_SAFE_INTEGER: 0x1fffffffffffff});
+},{"./$.def":16}],115:[function(require,module,exports){
+// 20.1.2.10 Number.MIN_SAFE_INTEGER
+var $def = require('./$.def');
+
+$def($def.S, 'Number', {MIN_SAFE_INTEGER: -0x1fffffffffffff});
+},{"./$.def":16}],116:[function(require,module,exports){
+// 20.1.2.12 Number.parseFloat(string)
+var $def = require('./$.def');
+
+$def($def.S, 'Number', {parseFloat: parseFloat});
+},{"./$.def":16}],117:[function(require,module,exports){
+// 20.1.2.13 Number.parseInt(string, radix)
+var $def = require('./$.def');
+
+$def($def.S, 'Number', {parseInt: parseInt});
+},{"./$.def":16}],118:[function(require,module,exports){
+// 19.1.3.1 Object.assign(target, source)
+var $def = require('./$.def');
+$def($def.S, 'Object', {assign: require('./$.assign')});
+},{"./$.assign":7,"./$.def":16}],119:[function(require,module,exports){
+// 19.1.2.5 Object.freeze(O)
+var isObject = require('./$.is-object');
+
+require('./$.object-sap')('freeze', function($freeze){
+  return function freeze(it){
+    return $freeze && isObject(it) ? $freeze(it) : it;
+  };
+});
+},{"./$.is-object":34,"./$.object-sap":48}],120:[function(require,module,exports){
+// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
+var toIObject = require('./$.to-iobject');
+
+require('./$.object-sap')('getOwnPropertyDescriptor', function($getOwnPropertyDescriptor){
+  return function getOwnPropertyDescriptor(it, key){
+    return $getOwnPropertyDescriptor(toIObject(it), key);
+  };
+});
+},{"./$.object-sap":48,"./$.to-iobject":72}],121:[function(require,module,exports){
+// 19.1.2.7 Object.getOwnPropertyNames(O)
+require('./$.object-sap')('getOwnPropertyNames', function(){
+  return require('./$.get-names').get;
+});
+},{"./$.get-names":25,"./$.object-sap":48}],122:[function(require,module,exports){
+// 19.1.2.9 Object.getPrototypeOf(O)
+var toObject = require('./$.to-object');
+
+require('./$.object-sap')('getPrototypeOf', function($getPrototypeOf){
+  return function getPrototypeOf(it){
+    return $getPrototypeOf(toObject(it));
+  };
+});
+},{"./$.object-sap":48,"./$.to-object":74}],123:[function(require,module,exports){
+// 19.1.2.11 Object.isExtensible(O)
+var isObject = require('./$.is-object');
+
+require('./$.object-sap')('isExtensible', function($isExtensible){
+  return function isExtensible(it){
+    return isObject(it) ? $isExtensible ? $isExtensible(it) : true : false;
+  };
+});
+},{"./$.is-object":34,"./$.object-sap":48}],124:[function(require,module,exports){
+// 19.1.2.12 Object.isFrozen(O)
+var isObject = require('./$.is-object');
+
+require('./$.object-sap')('isFrozen', function($isFrozen){
+  return function isFrozen(it){
+    return isObject(it) ? $isFrozen ? $isFrozen(it) : false : true;
+  };
+});
+},{"./$.is-object":34,"./$.object-sap":48}],125:[function(require,module,exports){
+// 19.1.2.13 Object.isSealed(O)
+var isObject = require('./$.is-object');
+
+require('./$.object-sap')('isSealed', function($isSealed){
+  return function isSealed(it){
+    return isObject(it) ? $isSealed ? $isSealed(it) : false : true;
+  };
+});
+},{"./$.is-object":34,"./$.object-sap":48}],126:[function(require,module,exports){
+// 19.1.3.10 Object.is(value1, value2)
+var $def = require('./$.def');
+$def($def.S, 'Object', {
+  is: require('./$.same')
+});
+},{"./$.def":16,"./$.same":56}],127:[function(require,module,exports){
+// 19.1.2.14 Object.keys(O)
+var toObject = require('./$.to-object');
+
+require('./$.object-sap')('keys', function($keys){
+  return function keys(it){
+    return $keys(toObject(it));
+  };
+});
+},{"./$.object-sap":48,"./$.to-object":74}],128:[function(require,module,exports){
+// 19.1.2.15 Object.preventExtensions(O)
+var isObject = require('./$.is-object');
+
+require('./$.object-sap')('preventExtensions', function($preventExtensions){
+  return function preventExtensions(it){
+    return $preventExtensions && isObject(it) ? $preventExtensions(it) : it;
+  };
+});
+},{"./$.is-object":34,"./$.object-sap":48}],129:[function(require,module,exports){
+// 19.1.2.17 Object.seal(O)
+var isObject = require('./$.is-object');
+
+require('./$.object-sap')('seal', function($seal){
+  return function seal(it){
+    return $seal && isObject(it) ? $seal(it) : it;
+  };
+});
+},{"./$.is-object":34,"./$.object-sap":48}],130:[function(require,module,exports){
+// 19.1.3.19 Object.setPrototypeOf(O, proto)
+var $def = require('./$.def');
+$def($def.S, 'Object', {setPrototypeOf: require('./$.set-proto').set});
+},{"./$.def":16,"./$.set-proto":57}],131:[function(require,module,exports){
+'use strict';
+// 19.1.3.6 Object.prototype.toString()
+var classof = require('./$.classof')
+  , test    = {};
+test[require('./$.wks')('toStringTag')] = 'z';
+if(test + '' != '[object z]'){
+  require('./$.redef')(Object.prototype, 'toString', function toString(){
+    return '[object ' + classof(this) + ']';
+  }, true);
+}
+},{"./$.classof":8,"./$.redef":54,"./$.wks":77}],132:[function(require,module,exports){
+'use strict';
+var $          = require('./$')
+  , LIBRARY    = require('./$.library')
+  , global     = require('./$.global')
+  , ctx        = require('./$.ctx')
+  , classof    = require('./$.classof')
+  , $def       = require('./$.def')
+  , isObject   = require('./$.is-object')
+  , anObject   = require('./$.an-object')
+  , aFunction  = require('./$.a-function')
+  , strictNew  = require('./$.strict-new')
+  , forOf      = require('./$.for-of')
+  , setProto   = require('./$.set-proto').set
+  , same       = require('./$.same')
+  , species    = require('./$.species')
+  , SPECIES    = require('./$.wks')('species')
+  , RECORD     = require('./$.uid')('record')
+  , asap       = require('./$.microtask')
+  , PROMISE    = 'Promise'
+  , process    = global.process
+  , isNode     = classof(process) == 'process'
+  , P          = global[PROMISE]
+  , Wrapper;
+
+var testResolve = function(sub){
+  var test = new P(function(){});
+  if(sub)test.constructor = Object;
+  return P.resolve(test) === test;
+};
+
+var useNative = function(){
+  var works = false;
+  function P2(x){
+    var self = new P(x);
+    setProto(self, P2.prototype);
+    return self;
+  }
+  try {
+    works = P && P.resolve && testResolve();
+    setProto(P2, P);
+    P2.prototype = $.create(P.prototype, {constructor: {value: P2}});
+    // actual Firefox has broken subclass support, test that
+    if(!(P2.resolve(5).then(function(){}) instanceof P2)){
+      works = false;
+    }
+    // actual V8 bug, https://code.google.com/p/v8/issues/detail?id=4162
+    if(works && require('./$.support-desc')){
+      var thenableThenGotten = false;
+      P.resolve($.setDesc({}, 'then', {
+        get: function(){ thenableThenGotten = true; }
+      }));
+      works = thenableThenGotten;
+    }
+  } catch(e){ works = false; }
+  return works;
+}();
+
+// helpers
+var isPromise = function(it){
+  return isObject(it) && (useNative ? classof(it) == 'Promise' : RECORD in it);
+};
+var sameConstructor = function(a, b){
+  // library wrapper special case
+  if(LIBRARY && a === P && b === Wrapper)return true;
+  return same(a, b);
+};
+var getConstructor = function(C){
+  var S = anObject(C)[SPECIES];
+  return S != undefined ? S : C;
+};
+var isThenable = function(it){
+  var then;
+  return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
+};
+var notify = function(record, isReject){
+  if(record.n)return;
+  record.n = true;
+  var chain = record.c;
+  asap(function(){
+    var value = record.v
+      , ok    = record.s == 1
+      , i     = 0;
+    var run = function(react){
+      var cb = ok ? react.ok : react.fail
+        , ret, then;
+      try {
+        if(cb){
+          if(!ok)record.h = true;
+          ret = cb === true ? value : cb(value);
+          if(ret === react.P){
+            react.rej(TypeError('Promise-chain cycle'));
+          } else if(then = isThenable(ret)){
+            then.call(ret, react.res, react.rej);
+          } else react.res(ret);
+        } else react.rej(value);
+      } catch(err){
+        react.rej(err);
+      }
+    };
+    while(chain.length > i)run(chain[i++]); // variable length - can't use forEach
+    chain.length = 0;
+    record.n = false;
+    if(isReject)setTimeout(function(){
+      asap(function(){
+        if(isUnhandled(record.p)){
+          if(isNode){
+            process.emit('unhandledRejection', value, record.p);
+          } else if(global.console && console.error){
+            console.error('Unhandled promise rejection', value);
+          }
+        }
+        record.a = undefined;
+      });
+    }, 1);
+  });
+};
+var isUnhandled = function(promise){
+  var record = promise[RECORD]
+    , chain  = record.a || record.c
+    , i      = 0
+    , react;
+  if(record.h)return false;
+  while(chain.length > i){
+    react = chain[i++];
+    if(react.fail || !isUnhandled(react.P))return false;
+  } return true;
+};
+var $reject = function(value){
+  var record = this;
+  if(record.d)return;
+  record.d = true;
+  record = record.r || record; // unwrap
+  record.v = value;
+  record.s = 2;
+  record.a = record.c.slice();
+  notify(record, true);
+};
+var $resolve = function(

<TRUNCATED>

[15/47] allura git commit: [#7919] Fix endpoint to show installable tools for a given project

Posted by br...@apache.org.
[#7919] Fix endpoint to show installable tools for a given project


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/ed9e5f8e
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/ed9e5f8e
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/ed9e5f8e

Branch: refs/heads/db/7919
Commit: ed9e5f8e882a76de0c9d7f7d2eb96d550dde75de
Parents: 76a901d
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:43:12 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 32 ++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/ed9e5f8e/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index e5d819e..84e698c 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -797,7 +797,7 @@ class ProjectAdminRestController(BaseController):
 
     @expose('json:')
     def installable_tools(self, **kw):
-        """ List of installable tools
+        """ List of installable tools and their default options.
         """
         response.content_type = 'application/json'
         tools = []
@@ -809,7 +809,8 @@ class ProjectAdminRestController(BaseController):
                 'defaults': {
                     'default_options': tool['app'].default_options(),
                     'default_mount_label': tool['app'].default_mount_label,
-                    'default_mount_point': tool['app'].default_mount_point,
+                    'default_mount_point': tool['app'].admin_menu_delete_button,
+                    'modal': tool['app'].admin_modal,
                 }
             })
 
@@ -860,6 +861,32 @@ class ProjectAdminRestController(BaseController):
         }
 
     @expose('json:')
+    @require_post()
+    def mount_point(self, mount_point=None, **kw):
+        """
+        Returns a tool from a given mount point
+        """
+        response.content_type = 'application/json'
+
+        tool = c.project.app_instance(mount_point)
+
+        if tool is None:
+            return {
+                'exists': False,
+                'info': 'Mount point does not exists.',
+            }
+
+        try:
+            info = json.dumps(tool)
+        except TypeError:
+            info = "Could not serialize tool."
+
+        return {
+            'exist': True,
+            'info': info
+        }
+
+    @expose('json:')
     def export_status(self, **kw):
         """
         Check the status of a bulk export.
@@ -900,6 +927,7 @@ class ProjectAdminRestController(BaseController):
 
         """
         controller = ProjectAdminController()
+        ordinal = 0
 
         if not tool or not mount_point or not mount_label:
             return {


[17/47] allura git commit: [#7919] Add the navbar front-end logic

Posted by br...@apache.org.
[#7919] Add the navbar front-end logic


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/ddfd67b4
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/ddfd67b4
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/ddfd67b4

Branch: refs/heads/db/7919
Commit: ddfd67b441ed07caf399ecf37c26ae5209941026
Parents: 7544bf0
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:19:50 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/navbar.es6.js | 431 ++++++++++++++++++++++++++
 1 file changed, 431 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/ddfd67b4/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
new file mode 100644
index 0000000..eac0e91
--- /dev/null
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -0,0 +1,431 @@
+'use strict';
+
+
+/**
+ * Gets the current url.
+ * @constructor
+ * @param {bool} rest - Return a "rest" version of the url.
+ * @returns {string}
+ */
+function _getProjectUrl(rest = true) {
+  var [nbhd, proj] = window.location.pathname.split('/').slice(1, 3);
+  var base = `${window.location.protocol}//${window.location.host}`;
+  return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`;
+}
+
+/**
+ * Get a tool label from a NavBarItem node.
+ * @constructor
+ * @param {NavBarItem} node - Return a "rest" version of the url.
+ * @returns {string}
+ */
+function getLabel(node) {
+  return node.props.children.props.children.props.name;
+}
+
+var ToolsPropType = {
+  name: React.PropTypes.string.isRequired,
+  url: React.PropTypes.string.isRequired,
+  isSubmenu: React.PropTypes.bool,
+  tools: React.PropTypes.arrayOf(
+    React.PropTypes.shape({
+      ordinal: React.PropTypes.number,
+      mount_point: React.PropTypes.string,
+      name: React.PropTypes.string,
+      url: React.PropTypes.string,
+      is_anchored: React.PropTypes.bool,
+      tool_name: React.PropTypes.string,
+      icon: React.PropTypes.string
+    })
+  ).isRequired
+};
+
+/**
+ * A NavBar link, the most basic component of the NavBar.
+ * @constructor
+ */
+var NavLink = React.createClass({
+  propTypes: {
+    name: React.PropTypes.string.isRequired,
+    url: React.PropTypes.string.isRequired,
+    style: React.PropTypes.object
+  },
+  render: function() {
+    var classes = this.props.subMenu ? ' subMenu' : '';
+    classes += this.props.classes;
+    return (
+      <a href={ this.props.url } key={ `link-${_.uniqueId()}` } className={ classes } style={ this.props.style }>
+        { this.props.name }
+      </a>
+      );
+  }
+});
+
+/**
+ * When the number of tools of the same type exceeds the grouping threshold,
+ * they are placed in a group and this submenu is generated.
+ * @constructor
+ */
+var ToolSubMenu = React.createClass({
+  propTypes: {
+    isSubmenu: React.PropTypes.bool,
+    tools: ToolsPropType
+  },
+  handle: '.draggable-handle',
+  mode: 'list',
+  render: function() {
+    var _this = this;
+    var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
+    var tools = this.props.tools.map(function(item, i) {
+      return (
+        <div className={ 'draggable-element ' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
+          <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
+            <NavBarItem {..._this.props} data={ item } name={ item.mount_point } url={ item.url } data-id={ i } />
+          </div>
+        </div>
+        );
+    });
+
+    return (
+      <div className='hidden' style={ {  display: 'none'} }>
+        <ReactReorderable handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart } onDrop={ this.props.onToolReorder } onChange={ this.onChange }>
+          { tools }
+        </ReactReorderable>
+      </div>
+      );
+  }
+});
+
+/**
+ * A single NavBar item. (A wrapper for NavLink).
+ * @constructor
+ */
+var NavBarItem = React.createClass({
+  propTypes: {
+    name: React.PropTypes.string.isRequired,
+    url: React.PropTypes.string.isRequired,
+    isSubmenu: React.PropTypes.bool,
+    tools: ToolsPropType
+  },
+  generateLink: function() {
+    return <NavLink url={ this.props.url } name={ this.props.name } key={ _.uniqueId() } />;
+  },
+
+  generateSubmenu: function() {
+    return <ToolSubMenu {...this.props} tools={ this.props.data.children } key={ `submenu-${_.uniqueId()}` } isSubmenu={ true } />;
+  },
+
+  generateContent: function() {
+    var content = [this.generateLink()];
+    if (this.props.data.children) {
+      content.push(this.generateSubmenu());
+    }
+
+    return content;
+  },
+
+  render: function() {
+    var content = this.generateContent();
+    var classes = this.props.editMode ? 'tb-item tb-item-edit' : 'tb-item';
+    classes = this.props.is_anchored ? `${classes} anchored` : classes;
+
+    return (
+      <div className={ classes }>
+        { content }
+      </div>
+      );
+  }
+});
+
+/**
+ * An input component that updates the NavBar's grouping threshold.
+ * @constructor
+ */
+var GroupingThreshold = React.createClass({
+  propTypes: {
+    initialValue: React.PropTypes.number.isRequired
+  },
+  getInitialState: function() {
+    return {
+      value: this.props.initialValue
+    };
+  },
+
+  handleChange: function(event) {
+    this.setState({
+      value: event.target.value
+    });
+    this.props.onUpdateThreshold(event);
+  },
+
+  render: function() {
+    return (
+      <div>
+        { !!this.props.isHidden &&
+          <div id='threshold-config'>
+            <span>
+              <label htmlFor='threshold-input'>Grouping Threshold</label>
+                <input type='number' name='threshold-input' className='tooltip'
+                       title='Number of tools allowed before grouping.'
+                       value={ this.state.value }
+                       onChange={ this.handleChange }
+                       min='1' max='10'/>
+              </span>
+          </div> }
+      </div>
+      );
+  }
+});
+
+/**
+ * The NavBar when in "Normal" mode.
+ * @constructor
+ */
+var NormalNavBar = React.createClass({
+  buildMenu: function(item) {
+    var classes = ` ui-icon-${item.icon}-32`;
+    classes = item.is_anchored ? `${classes} anchored` : classes;
+
+    var subMenu;
+    if (item.children) {
+      subMenu = item.children.map(this.buildMenu);
+    }
+
+    return (
+      <li>
+        <a href={ item.url } key={ 'link-' + _.uniqueId() } className={ classes }>
+          { item.name }
+        </a>
+        <ul className={ item.children ? 'submenu' : '' }>
+          { subMenu }
+        </ul>
+      </li>
+      );
+  },
+
+  render: function() {
+    var listItems = this.props.items.map(this.buildMenu);
+    var classes = 'dropdown';
+    classes = this.props.isSubmenu ? classes += ' submenu' : classes;
+    return (
+      <ul className={ classes } key={ `toolList-${_.uniqueId()}` }>
+        { listItems }
+      </ul>
+      );
+  }
+});
+
+/**
+ * The NavBar when in "Admin" mode.
+ * @constructor
+ */
+var AdminNav = React.createClass({
+  propTypes: {
+    name: React.PropTypes.string.isRequired,
+    url: React.PropTypes.string.isRequired,
+    isSubmenu: React.PropTypes.bool,
+    tools: ToolsPropType
+  },
+  handle: '.draggable-handle',
+  mode: 'grid',
+  getInitialState: function() {
+    return {
+      hover: false
+    };
+  },
+
+  mouseOver: function() {
+    this.setState({
+      hover: true
+    });
+  },
+
+  mouseOut: function() {
+    this.setState({
+      hover: false
+    });
+  },
+
+  render: function() {
+    var _this = this;
+    var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
+    var tools = this.props.tools.map(function(item, i) {
+      return (
+        <div className={ 'draggable-element' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
+          <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
+            <NavBarItem onMouseOver={ _this.mouseOver } onMouseOut={ _this.mouseOut } {..._this.props} data={ item } name={ item.mount_point } url={ item.url }
+            key={ 'tb-item-' + _.uniqueId() } is_anchored={ item.is_anchored } data-id={ i } />
+          </div>
+        </div>
+        );
+    });
+
+    return (
+      <div className='react-drag edit-mode'>
+        <ReactReorderable key={ 'reorder-' + _.uniqueId() } handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart } onDrop={ this.props.onToolReorder } onChange={ this.onChange }>
+          { tools }
+        </ReactReorderable>
+      </div>
+      );
+  }
+});
+
+/**
+ * The button that toggles NavBar modes.
+ * @constructor
+ */
+var ToggleAdminButton = React.createClass({
+  propTypes: {
+    visible: React.PropTypes.bool
+  },
+  render: function() {
+    var classes = this.props.visible ? 'fa fa-unlock' : 'fa fa-lock';
+    return (
+      <button id='toggle-admin-btn' onClick={ this.props.handleButtonPush } className='admin-toolbar-right'>
+        <i className={ classes }></i>
+      </button>
+      );
+  }
+});
+
+/**
+ * The main "controller view" of the NavBar.
+ * @constructor
+ * @param {object} initialData - Consumes the _nav.json endpoint.
+ */
+var Main = React.createClass({
+  propTypes: {
+    initialData: ToolsPropType
+  },
+  getInitialState: function() {
+    return {
+      data: this.props.initialData,
+      visible: false,
+      _session_id: $.cookie('_session_id')
+    };
+  },
+
+  /**
+  * When invoked, this updates the state with the latest data from the server.
+  */
+  getNavJson: function() {
+    $.get(`${_getProjectUrl(false)}/_nav.json`, function(result) {
+      if (this.isMounted()) {
+        this.setState({
+          data: result
+        });
+      }
+    }.bind(this));
+  },
+
+  /**
+  * Handles the locking and unlocking of the NavBar
+  */
+  handleToggleAdmin: function() {
+    this.setState({
+      visible: !this.state.visible
+    });
+  },
+
+  /**
+   * Handles the changing of the NavBars grouping threshold.
+   * @param {object} event
+   */
+  onUpdateThreshold: function(event) {
+    var _this = this;
+    var thres = event.target.value;
+    var url = `${_getProjectUrl()}/admin/configure_tool_grouping`;
+    var csrf = $.cookie('_session_id');
+    var data = {
+      _session_id: csrf,
+      grouping_threshold: thres
+    };
+    var _data = this.state.data;
+    _data.grouping_threshold = thres;
+    this.setState({
+      data: _data
+    });
+    this.setState({
+      in_progress: true
+    });
+    $.post(url, data, function(resp) {}.bind(this)).always(function() {
+      _this.setState({
+        in_progress: false
+      });
+    });
+
+    _this.getNavJson();
+    return false;
+  },
+
+  /**
+   * Handles the changing of the NavBars grouping threshold.
+   * @param {array} data - Array of tools
+   */
+  onToolReorder: function(data) {
+    var tools = this.state.data;
+    var params = {
+      _session_id: $.cookie('_session_id')
+    };
+
+    data.map(function(tool, i) {
+      var name = getLabel(tool);
+      var index = tools.children.findIndex(
+        x => x.mount_point === name
+      );
+      tools.children[index].ordinal = i;
+      params[i] = name;
+    });
+
+    this.setState({
+      data: tools
+    });
+    var _this = this;
+    var url = _getProjectUrl() + '/admin/mount_order';
+    $.ajax({
+      type: 'POST',
+      url: url,
+      data: params,
+      success: function() {
+        $('#messages').notify('Tool order updated',
+          {
+            status: 'confirm'
+          });
+        _this.getNavJson();
+      },
+
+      error: function() {
+        $('#messages').notify('Error saving tool order.',
+          {
+            status: 'error'
+          });
+      }
+    });
+  },
+
+  render: function() {
+    var editMode = this.state.visible ? 'edit-mode' : '';
+    var _this = this;
+    var navBarSwitch = (showAdmin) => {
+      if (showAdmin) {
+        return (
+          <AdminNav tools={ _this.state.data.children } data={ _this.state.data } onToolReorder={ _this.onToolReorder } onUpdateMountOrder={ _this.onUpdateMountOrder } editMode={ _this.state.visible }
+          />
+          );
+      } else {
+        return <NormalNavBar items={ _this.state.data.children } key={ `normalNav-${_.uniqueId()}` } />;
+      }
+    };
+    var navBar = navBarSwitch(this.state.visible);
+
+    return (
+      <div ref={ _.uniqueId() } className={ 'nav_admin ' + editMode }>
+        { navBar }
+        <div id='bar-config'>
+          <GroupingThreshold onUpdateThreshold={ this.onUpdateThreshold } isHidden={ this.state.visible } initialValue={ this.state.data.grouping_threshold } />
+        </div>
+        <ToggleAdminButton key={ _.uniqueId() } handleButtonPush={ this.handleToggleAdmin } visible={ this.state.visible } />
+      </div>
+      );
+  }
+});


[36/47] allura git commit: [#7919] Remove unneeded components and refactor submenus

Posted by br...@apache.org.
[#7919] Remove unneeded components and refactor submenus


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a6b6f365
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a6b6f365
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a6b6f365

Branch: refs/heads/db/7919
Commit: a6b6f365a6f59e68e52b660f30973c29ca23fcf9
Parents: ce77b8e
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 22 15:57:28 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/navbar.es6.js | 534 +++++++-------------------
 1 file changed, 132 insertions(+), 402 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a6b6f365/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index feb1af8..c547cc8 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -1,8 +1,8 @@
 'use strict';
 
-
 /**
  * Gets the current url.
+
  * @constructor
  * @param {bool} rest - Return a "rest" version of the url.
  * @returns {string}
@@ -13,18 +13,44 @@ function _getProjectUrl(rest = true) {
     return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`;
 }
 
-function slugify(text)
-{
-  return text.toString().toLowerCase()
-    .replace(/\s+/g, '-')           // Replace spaces with -
-    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
-    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
-    .replace(/^-+/, '')             // Trim - from start of text
-    .replace(/-+$/, '');            // Trim - from end of text
+function slugify(text) {
+    return text.toString().toLowerCase()
+        .replace(/\s+/g,/\s+/g,/\s+/g,/\s+/g, '-')           // Replace spaces with -
+        .replace(/[^\w\-]+/g,/[^\w\-]+/g,/[^\w\-]+/g,/[^\w\-]+/g, '')       // Remove all non-word chars
+        .replace(/\-\-+/g,/\-\-+/g,/\-\-+/g,/\-\-+/g, '-')         // Replace multiple - with single -
+        .replace(/^-+/,/^-+/,/^-+/,/^-+/, '')             // Trim - from start of text
+        .replace(/-+$/,/-+$/,/-+$/,/-+$/, '');            // Trim - from end of text
 }
+/**
+ * Get the color for a tool type
 
+ * @constructor
+ * @label string 'The default mount label for a tool.  i.e. git and hg use 'Code' which returns 'blue'.
+ * @return {string}
+ */
+function _getToolColor(defaultLabel='standard') {
+    switch (defaultLabel) {
+    case 'Wiki':
+        return '#DDFFF0';
+    case 'Git':  // Git, svn, hg
+        return '#BBDEFB';
+    case 'Mercurial':  // Git, svn, hg
+        return '#BBDEFB';
+    case 'Tickets':
+        return '#D1C4E9';
+    case 'Discussion':
+        return '#DCEDC8';
+    case 'Blog':
+        return '#FFF9C4';
+    case 'Link':
+        return '#FFCDD2';
+    default:
+        return 'white';
+    }
+}
 /**
  * Get a mount point from a NavBarItem node.
+
  * @constructor
  * @param {NavBarItem} node
  * @returns {string}
@@ -52,85 +78,33 @@ function ToolsPropType() {
     };
 }
 
-
-/**
- * When the number of tools of the same type exceeds the grouping threshold,
- * they are placed in a group and this submenu is generated.
- * @constructor
- */
-var ToolSubMenu = React.createClass({
-    propTypes: {
-        isSubmenu: React.PropTypes.bool,
-        tools: ToolsPropType
-    },
-    mode: 'list',
-    render: function () {
-        var _this = this;
-        var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
-        var tools = this.props.tools.map(function (item, i) {
-            return (
-                <div className={ 'draggable-element ' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
-                    <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
-                        <NavBarItem data={ item } name={ item.mount_point } url={ item.url }/>
-                    </div>
-                </div>
-            );
-        });
-
-        return (
-            <div className='hidden' style={ {  display: 'none'} }>
-                <ReactReorderable handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart } onDrop={ this.props.onToolReorder }
-                                  onChange={ this.onChange }>
-                    { tools }
-                </ReactReorderable>
-            </div>
-        );
-    }
-});
-
 /**
  * A single NavBar item.
+
  * @constructor
  */
 var NavBarItem = React.createClass({
     propTypes: {
         name: React.PropTypes.string.isRequired,
         url: React.PropTypes.string.isRequired,
-        isSubmenu: React.PropTypes.bool,
-        children: React.PropTypes.array,
-        tools: ToolsPropType
     },
-    generateItem: function () {
+
+    isAnchored: function() {
+        return this.props.is_anchored !== null;
+    },
+
+    render: function() {
         var controls = [<i className='config-tool fa fa-cog'></i>];
-        var arrow_classes = 'fa fa-arrows-h'
+        var arrow_classes = 'fa fa-arrows-h';
         if (this.props.is_anchored) {
             arrow_classes += ' anchored';
         } else {
             arrow_classes += ' draggable-handle';
         }
         controls.push(<i className={arrow_classes}></i>);
-        return <a>{ this.props.name }<br/>{ controls }</a>
-    },
-
-    generateSubmenu: function () {
-        return <ToolSubMenu {...this.props} tools={ this.props.children } key={ `submenu-${_.uniqueId()}` } isSubmenu={ true }/>;
-    },
-
-    generateContent: function () {
-        var content = [this.generateItem()];
-        if (this.props.children) {
-            content.push(this.generateSubmenu());
-        }
-
-        return content;
-    },
-
-    render: function () {
-        var content = this.generateContent();
-        var classes = 'tb-item tb-item-edit';
         return (
-            <div className={ classes }>
-                { content }
+            <div className="tb-item tb-item-edit">
+                <a>{this.props.name}<br/>{controls}</a>
             </div>
         );
     }
@@ -138,26 +112,27 @@ var NavBarItem = React.createClass({
 
 /**
  * An input component that updates the NavBar's grouping threshold.
+
  * @constructor
  */
 var GroupingThreshold = React.createClass({
     propTypes: {
         initialValue: React.PropTypes.number.isRequired
     },
-    getInitialState: function () {
+    getInitialState: function() {
         return {
             value: this.props.initialValue
         };
     },
 
-    handleChange: function (event) {
+    handleChange: function(event) {
         this.setState({
             value: event.target.value
         });
         this.props.onUpdateThreshold(event);
     },
 
-    render: function () {
+    render: function() {
         return (
             <div>
                 { !!this.props.isHidden &&
@@ -176,14 +151,14 @@ var GroupingThreshold = React.createClass({
     }
 });
 
-
 /**
  * The NavBar when in "Normal" mode.
+
  * @constructor
  */
 var NormalNavBar = React.createClass({
-    buildMenu: function (item) {
-        var classes = ` ui-icon-${item.icon}-32`;
+    buildMenu: function(item) {
+        let classes = window.location.pathname.startsWith(item.url) ? 'active-nav-link' : '';
 
         var subMenu;
         if (item.children) {
@@ -195,20 +170,26 @@ var NormalNavBar = React.createClass({
                 <a href={ item.url } key={ 'link-' + _.uniqueId() } className={ classes }>
                     { item.name }
                 </a>
-                <ul className={ item.children ? 'submenu' : '' }>
-                    { subMenu }
-                </ul>
+                {subMenu &&
+                    <ul className={ classes + ' submenu'}>
+                        { subMenu }
+                    </ul>
+                }
             </li>
         );
     },
 
-    render: function () {
+    render: function() {
         var listItems = this.props.items.map(this.buildMenu);
         var classes = 'dropdown';
-        classes = this.props.isSubmenu ? classes += ' submenu' : classes;
         return (
-            <ul className={ classes } key={ `toolList-${_.uniqueId()}` }>
+            <ul
+                className={ classes }
+                key={ `toolList-${_.uniqueId()}` }>
                 { listItems }
+                <ToggleAddNewTool
+                    handleToggleAddNewTool={this.props.handleToggleAddNewTool}
+                    showAddToolMenu={this.props.showAddToolMenu} />
             </ul>
         );
     }
@@ -224,33 +205,38 @@ var AdminNav = React.createClass({
         tools: ToolsPropType
     },
     mode: 'grid',
-    getInitialState: function () {
+    getInitialState: function() {
         return {
             hover: false
         };
     },
 
-    mouseOver: function () {
+    mouseOver: function() {
         this.setState({
             hover: true
         });
     },
 
-    mouseOut: function () {
+    mouseOut: function() {
         this.setState({
             hover: false
         });
     },
 
-    render: function () {
+    render: function() {
         var _this = this;
         var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
-        var tools = [], anchored_tools = [], end_tools = [];
-        this.props.tools.forEach(function (item) {
-            var core_item = <NavBarItem onMouseOver={ _this.mouseOver } onMouseOut={ _this.mouseOut } {..._this.props} data={ item }
+        var [tools, anchored_tools, end_tools] = [[], [], [],];
+        this.props.tools.forEach(function(item) {
+            var core_item = <NavBarItem
+                                onMouseOver={ _this.mouseOver }
+                                onMouseOut={ _this.mouseOut } {..._this.props}
+                                data={ item }
                                 mount_point={ item.mount_point }
-                                name={ item.name } url={ item.url }
-                                key={ 'tb-item-' + _.uniqueId() } is_anchored={ item.is_anchored || item.mount_point === 'admin'}/>;
+                                name={ item.name }
+                                url={ item.url }
+                                key={ 'tb-item-' + _.uniqueId() }
+                                is_anchored={ item.is_anchored || item.mount_point === 'admin'}/>;
             if (item.mount_point === 'admin') {
                 // force admin to end, just like 'Project.sitemap()' does
                 end_tools.push(core_item);
@@ -258,7 +244,7 @@ var AdminNav = React.createClass({
                 anchored_tools.push(core_item);
             } else {
                 tools.push(
-                <div className={ 'draggable-element' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
+                    <div className={ 'draggable-element' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
                         { core_item }
                     </div>
             );
@@ -268,8 +254,13 @@ var AdminNav = React.createClass({
         return (
             <div className='react-drag edit-mode'>
                 { anchored_tools }
-                <ReactReorderable key={ 'reorder-' + _.uniqueId() } handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart }
-                                  onDrop={ this.props.onToolReorder } onChange={ this.onChange }>
+                <ReactReorderable
+                    key={ 'reorder-' + _.uniqueId() }
+                    handle='.draggable-handle'
+                    mode='grid'
+                    onDragStart={ this.onDragStart }
+                    onDrop={ this.props.onToolReorder }
+                    onChange={ this.onChange }>
                     { tools }
                 </ReactReorderable>
                 { end_tools }
@@ -280,13 +271,14 @@ var AdminNav = React.createClass({
 
 /**
  * The button that toggles NavBar modes.
+
  * @constructor
  */
 var ToggleAdminButton = React.createClass({
     propTypes: {
         visible: React.PropTypes.bool
     },
-    render: function () {
+    render: function() {
         var classes = this.props.visible ? 'fa fa-unlock' : 'fa fa-lock';
         return (
             <button id='toggle-admin-btn' onClick={ this.props.handleButtonPush } className='admin-toolbar-right'>
@@ -297,290 +289,8 @@ var ToggleAdminButton = React.createClass({
 });
 
 /**
- * Add new tool button.
- * @constructor
- */
-var ToggleAddNewTool = React.createClass({
-    render: function () {
-        return (
-            <div>
-                <div onClick={ this.props.handleToggleAddNewTool } className="add-tool-toggle"> + Add new...</div>
-                {this.props.showMenu && <NewToolMain />}
-            </div>
-        );
-    }
-});
-
-//////////////////
-// Add New Tool //
-//////////////////
-
-
-/**
- * Menu for adding a new tool.
- * @constructor
- */
-var NewToolMenu = React.createClass({
-    propTypes: {
-        tools: React.PropTypes.array,
-        onPushAddButton: React.PropTypes.func,
-        onSetActive: React.PropTypes.func,
-        formData: React.PropTypes.object,
-        visible: React.PropTypes.bool
-    },
-
-    render: function () {
-        var _this = this;
-        var showInfo = this.props.active.name !== "Add a tool";
-
-        var tools = this.props.tools.map(function (tool, i) {
-            var classes;
-            if (_this.props.active && _this.props.active.name === tool.name) {
-                classes = " selected-tool"
-            }
-            else {
-                classes = ""
-            }
-            return (
-                <li className={classes}
-                    id={"add-new-" + tool.name}
-                    key={`new-tool-btn-${i}`}
-                    onClick={_this.props.handleChangeTool}>
-                    {tool.tool_label}
-                </li>
-            )
-        });
-
-        return (
-            <div className="tool-card">
-                <div className="box-title">Add a new ...</div>
-                <div id="installable-items">
-                    <ul className="installable-tool-box">
-                        {tools}
-                    </ul>
-                </div>
-                <div className="tool-partition"></div>
-
-                {showInfo &&
-                <NewToolInfo {...this.props}
-                    name={this.props.active.tool_label}
-                    description={this.props.active.description}
-                    handleAddButton={this.props.handleAddButton}/>
-                }
-            </div>
-        );
-    }
-});
-
-var InstallNewToolForm = React.createClass({
-    render: function () {
-        return (
-            <form id="add-tool-form">
-                <label htmlFor="mount_label">Label</label>
-                <input required
-                       id="mount_label"
-                       onChange={this.props.handleChangeForm}
-                       value={this.props.formData.mount_label} />
-
-                <label htmlFor="mount_point">Url Path</label>
-                <input required
-                       id="mount_point"
-                       onChange={this.props.handleChangeForm}
-                       onBlur={this.props.toolFormIsValid}
-                       value={slugify(this.props.formData.mount_label)}
-                       value={this.props.formData.mount_point.toLowerCase()}/>
-                <span>{this.props.validationErrors.mount_point}</span>
-
-                <p style={{"color": "grey"}}><small>http://hs/p/finna/</small><strong style={{"color": "orange"}}>
-                    {this.props.formData.mount_point}
-                </strong></p>
-
-                <button id="new-tool-submit"
-                        onClick={this.props.handleSubmit}
-                        className="add-tool-button">
-                    Add Tool
-                </button>
-            </form>
-        );
-    }
-});
-
-
-var NewToolInfo = React.createClass({
-    propTypes: {
-        name: React.PropTypes.string,
-        description: React.PropTypes.string,
-        handleAddButton: React.PropTypes.func
-    },
-
-
-    render: function () {
-        return (
-            <div className="tool-info">
-                <div className="tool-info-left">
-                    <h1>{this.props.name}</h1>
-                    <p>{this.props.description}</p>
-                </div>
-                <div className="tool-info-right">
-                    <InstallNewToolForm {...this.props} />
-                </div>
-            </div>
-        );
-    }
-});
-
-
-var installableToolsCache = {};
-function loadTools(id, callback) {
-    if(!installableToolsCache[id]) {
-        installableToolsCache[id] = $.get(_getProjectUrl(true) + "/admin/installable_tools/").promise();
-    }
-    installableToolsCache[id].done(callback);
-}
-
-
-var NewToolMain = React.createClass({
-    getInitialState: function () {
-        let toolPlaceHolder = {
-            name: "Add a tool",
-            tool_label: "Add a tool",
-            description: "click on one of the tools shown above to add it to your project."
-        };
-
-        return {
-            visible: false,
-            installableTools: [toolPlaceHolder],
-            active: toolPlaceHolder,
-            errors: {
-                mount_point: [],
-                mount_label: []
-            },
-            new_tool: {
-                mount_point: "",
-                tool_label: "",
-                mount_label: ""
-            }
-        };
-    },
-
-    componentDidMount: function () {
-        let tools = loadTools('tools', function (result) {
-            if (this.isMounted()) {
-                this.setState({
-                    installableTools: result['tools']
-                })
-            }
-        }.bind(this));
-    },
-    handleChangeTool: function (e) {
-        console.log(`Changed tool to: ${e.target.textContent}`);
-        this._setActiveByName(e.target.textContent);
-
-    },
-    _setActiveByName: function (tool_label) {
-        var index = this.state.installableTools.findIndex(
-            x => x.tool_label === tool_label
-        );
-        var active = this.state.installableTools[index];
-        var _new_tool = this.state.new_tool;
-
-        _new_tool['mount_label'] = active.defaults.default_mount_label;
-        _new_tool['mount_point'] = "";
-
-        this.setState({
-            active: active,
-            new_tool: _new_tool
-        });
-    },
-
-    handleChangeForm: function (e) {
-        console.log(e.target.value);
-        var _new_tool = this.state.new_tool;
-
-        console.log(e.target.id);
-        _new_tool[e.target.id] = e.target.value;
-
-        this.setState({
-            new_tool: _new_tool
-        });
-
-    },
-    handleSubmit: function (e) {
-        e.preventDefault();
-        var data = {
-            _session_id: $.cookie('_session_id'),
-            tool: this.state.active.name,
-            mount_label: this.state.new_tool.mount_label,
-            mount_point: this.state.new_tool.mount_point
-        };
-
-        var url = _getProjectUrl() + "/admin/install_tool/";
-
-         $.ajax({
-            type: 'POST',
-            url: url,
-            data: data,
-            success: function () {
-                $('#messages').notify('Tool created',
-                    {
-                        status: 'confirm'
-                    });
-            },
-
-            error: function () {
-                $('#messages').notify('Error creating tool.',
-                    {
-                        status: 'error'
-                    });
-            }
-        });
-
-    },
-
-    toolFormIsValid: function (e) {
-        e.preventDefault();
-
-        var errors = {
-            mount_point: []
-        };
-
-        if (this.state.new_tool.mount_point.length < 3) {
-            errors.mount_point.push("Mount point must have at least 3 characters.");
-        }
-
-        let data = {
-            'mount_point': e.target.value,
-            '_session_id': $.cookie('_session_id')
-        };
-
-        let result = $.post(_getProjectUrl() + '/admin/mount_point/', data);
-            if (!result.responseJSON) {
-                errors.mount_point.push("Mount point already exists.");
-            }
-
-        this.setState({errors: errors})
-
-    },
-
-    render: function () {
-        return <NewToolMenu
-            active={this.state.active}
-            tools={this.state.installableTools}
-            formData={this.state.new_tool}
-            handleChangeTool={this.handleChangeTool}
-            handleSubmit={this.handleSubmit}
-            handleChangeForm={this.handleChangeForm}
-            toolFormIsValid={this.toolFormIsValid}
-            validationErrors={this.state.errors}
-            handleAddButton={this.handleAddButton}/>;
-    }
-});
-
-
-////////////////////////////////////////////
-
-/**
  * The main "controller view" of the NavBar.
+
  * @constructor
  * @param {object} initialData - Consumes the _nav.json endpoint.
  */
@@ -589,7 +299,7 @@ var Main = React.createClass({
         initialData: ToolsPropType,
         installableTools: React.PropTypes.array
     },
-    getInitialState: function () {
+    getInitialState: function() {
         return {
             data: this.props.initialData,
             visible: false,
@@ -601,8 +311,8 @@ var Main = React.createClass({
     /**
      * When invoked, this updates the state with the latest data from the server.
      */
-    getNavJson: function () {
-        $.get(`${_getProjectUrl(false)}/_nav.json`, function (result) {
+    getNavJson: function() {
+        $.get(`${_getProjectUrl(false)}/_nav.json`, function(result) {
             if (this.isMounted()) {
                 this.setState({
                     data: result
@@ -610,12 +320,10 @@ var Main = React.createClass({
             }
         }.bind(this));
     },
-
-
     /**
      * Handles the locking and unlocking of the NavBar
      */
-    handleToggleAdmin: function () {
+    handleToggleAdmin: function() {
         this.setState({
             visible: !this.state.visible
         });
@@ -624,7 +332,13 @@ var Main = React.createClass({
     /**
      * Handles the the display of the "Add new tool" menu.
      */
-    handleToggleAddNewTool: function () {
+    handleToggleAddNewTool: function() {
+        $('body').click(function(e) { // click the background
+                if (e.target == this) {
+                    $(this).fadeOut();
+                }
+            });
+
         this.setState({
             showAddToolMenu: !this.state.showAddToolMenu
         });
@@ -632,9 +346,10 @@ var Main = React.createClass({
 
     /**
      * Handles the changing of the NavBars grouping threshold.
+
      * @param {object} event
      */
-    onUpdateThreshold: function (event) {
+    onUpdateThreshold: function(event) {
         var _this = this;
         var thres = event.target.value;
         var url = `${_getProjectUrl()}/admin/configure_tool_grouping`;
@@ -651,8 +366,8 @@ var Main = React.createClass({
         this.setState({
             in_progress: true
         });
-        $.post(url, data, function () {
-        }.bind(this)).always(function () {
+        $.post(url, data, function() {
+        }.bind(this)).always(function() {
             _this.setState({
                 in_progress: false
             });
@@ -664,15 +379,16 @@ var Main = React.createClass({
 
     /**
      * Handles the changing of the NavBars grouping threshold.
+
      * @param {array} data - Array of tools
      */
-    onToolReorder: function (data) {
+    onToolReorder: function(data) {
         var tools = this.state.data;
         var params = {
             _session_id: $.cookie('_session_id')
         };
 
-        data.map(function (tool, i) {
+        data.map(function(tool, i) {
             var mount_point = getMountPoint(tool);
             var index = tools.children.findIndex(
                 x => x.mount_point === mount_point
@@ -690,7 +406,7 @@ var Main = React.createClass({
             type: 'POST',
             url: url,
             data: params,
-            success: function () {
+            success: function() {
                 $('#messages').notify('Tool order updated',
                     {
                         status: 'confirm'
@@ -698,7 +414,7 @@ var Main = React.createClass({
                 _this.getNavJson();
             },
 
-            error: function () {
+            error: function() {
                 $('#messages').notify('Error saving tool order.',
                     {
                         status: 'error'
@@ -707,33 +423,47 @@ var Main = React.createClass({
         });
     },
 
-    render: function () {
+    render: function() {
         var editMode = this.state.visible ? 'edit-mode' : '';
         var _this = this;
         var navBarSwitch = (showAdmin) => {
             if (showAdmin) {
                 return (
-                    <AdminNav tools={ _this.state.data.menu } data={ _this.state.data } onToolReorder={ _this.onToolReorder }
-                              onUpdateMountOrder={ _this.onUpdateMountOrder } editMode={ _this.state.visible } />
+                    <AdminNav
+                        tools={ _this.state.data.menu }
+                        data={ _this.state.data }
+                        onToolReorder={ _this.onToolReorder }
+                        onUpdateMountOrder={ _this.onUpdateMountOrder }
+                        editMode={ _this.state.visible } />
                 );
             } else {
                 return (
                     <div>
-                        <NormalNavBar items={ _this.state.data.menu } key={ `normalNav-${_.uniqueId()}` }/>
-                        <ToggleAddNewTool handleToggleAddNewTool={this.handleToggleAddNewTool} showMenu={this.state.showAddToolMenu} />
+                        <NormalNavBar
+                            items={ _this.state.data.menu }
+                            handleToggleAddNewTool={this.handleToggleAddNewTool}
+                            showAddToolMenu={this.state.showAddToolMenu}/>
                     </div>
-                )
+                );
             }
         };
         var navBar = navBarSwitch(this.state.visible);
 
         return (
-            <div ref={ _.uniqueId() } className={ 'nav_admin ' + editMode }>
+            <div
+                ref={ _.uniqueId() }
+                className={ 'nav_admin ' + editMode }>
                 { navBar }
                 <div id='bar-config'>
-                    <GroupingThreshold onUpdateThreshold={ this.onUpdateThreshold } isHidden={ this.state.visible } initialValue={ this.state.data.grouping_threshold }/>
+                    <GroupingThreshold
+                        onUpdateThreshold={ this.onUpdateThreshold }
+                        isHidden={ this.state.visible }
+                        initialValue={ this.state.data.grouping_threshold }/>
                 </div>
-                <ToggleAdminButton key={ _.uniqueId() } handleButtonPush={ this.handleToggleAdmin } visible={ this.state.visible }/>
+                <ToggleAdminButton
+                    key={ _.uniqueId() }
+                    handleButtonPush={ this.handleToggleAdmin }
+                    visible={ this.state.visible }/>
             </div>
         );
     }


[08/47] allura git commit: [#8004] move tool_icon_css usage to a docstring

Posted by br...@apache.org.
[#8004] move tool_icon_css usage to a docstring


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/ddcee91c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/ddcee91c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/ddcee91c

Branch: refs/heads/db/7919
Commit: ddcee91ca82c96574f94cc58cb610f49158b4e02
Parents: 7147ad9
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Oct 23 11:25:15 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Fri Oct 23 11:25:15 2015 -0400

----------------------------------------------------------------------
 Allura/allura/controllers/static.py              | 6 +++++-
 Allura/allura/templates/jinja_master/master.html | 1 -
 2 files changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/ddcee91c/Allura/allura/controllers/static.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/static.py b/Allura/allura/controllers/static.py
index 313a877..89a94ab 100644
--- a/Allura/allura/controllers/static.py
+++ b/Allura/allura/controllers/static.py
@@ -44,7 +44,11 @@ class NewForgeController(object):
 
     @expose()
     def tool_icon_css(self, *args, **kw):
-        """Serve stylesheet containing icon urls for every installed tool.
+        """
+        Serve stylesheet containing icon urls for every installed tool.
+
+        If you want to use this, include it in your theme like:
+            g.register_css('/nf/tool_icon_css?' + g.build_key, compress=False)
 
         """
         css, md5 = g.tool_icon_css

http://git-wip-us.apache.org/repos/asf/allura/blob/ddcee91c/Allura/allura/templates/jinja_master/master.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/master.html b/Allura/allura/templates/jinja_master/master.html
index 6f2487d..fd5a83e 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -33,7 +33,6 @@
 {% do g.register_forge_css('css/forge/hilite.css') %}
 {% do g.register_forge_css('css/forge/tooltipster.css') %}
 {% do g.register_forge_css('css/font-awesome.min.css', compress=False) %}
-{#  {% do g.register_css('/nf/tool_icon_css?' + g.build_key, compress=False) %}   If you need tool icons, use this #}
 {% do g.theme.require() %}
 {% do g.resource_manager.register_widgets(c) %}
 {# paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ #}


[03/47] allura git commit: [#8007] fix paths to avoid double slashes in icon paths, not all webservers allow that sloppiness :)

Posted by br...@apache.org.
[#8007] fix paths to avoid double slashes in icon paths, not all webservers allow that sloppiness :)


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/b2167039
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/b2167039
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/b2167039

Branch: refs/heads/db/7919
Commit: b2167039bdb6ce9cdf700861106c258bd59ef076
Parents: f33baf4
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Oct 20 17:05:45 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Wed Oct 21 14:34:35 2015 +0300

----------------------------------------------------------------------
 .../allura/ext/admin/templates/admin_widgets/metadata_admin.html   | 2 +-
 Allura/allura/ext/user_profile/templates/sections/projects.html    | 2 +-
 Allura/allura/templates/jinja_master/nav_menu.html                 | 2 +-
 Allura/allura/templates/jinja_master/neigh_nav_menu.html           | 2 +-
 Allura/allura/templates/jinja_master/theme_macros.html             | 2 +-
 Allura/allura/templates/widgets/neighborhood_overview_form.html    | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/b2167039/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html b/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
index b313dfc..0b3659c 100644
--- a/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
+++ b/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
@@ -99,7 +99,7 @@
     <div id="project-icon" class="viewing">
       {% if value.icon %}
         <div class="viewer" style="overflow: auto">
-          <img src="{{value.url()}}/icon?{{value.icon._id.generation_time}}" style="float:left; margin-right: 1em;" alt="">
+          <img src="{{value.url()}}icon?{{value.icon._id.generation_time}}" style="float:left; margin-right: 1em;" alt="">
           <a id="edit-icon" href="#" title="Edit" style="display:inline-block;margin-top:15px"><b data-icon="p" class="ico ico-pencil"></b></a>
           <a id="delete-icon" href="#" title="Remove" style="display:inline-block;margin-top:15px"><b data-icon="d" class="ico ico-delete"></b></a>
         </div>

http://git-wip-us.apache.org/repos/asf/allura/blob/b2167039/Allura/allura/ext/user_profile/templates/sections/projects.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/sections/projects.html b/Allura/allura/ext/user_profile/templates/sections/projects.html
index 9e1c632..55483bb 100644
--- a/Allura/allura/ext/user_profile/templates/sections/projects.html
+++ b/Allura/allura/ext/user_profile/templates/sections/projects.html
@@ -35,7 +35,7 @@
     {% for project in projects %}
         <li{% if loop.index > 5 %} class="hidden"{% endif %}>
             {% if project.icon -%}
-                <img src="{{project.url()}}/icon?{{project.icon._id.generation_time}}" alt="Project Logo" width="48" height="48"/>
+                <img src="{{project.url()}}icon?{{project.icon._id.generation_time}}" alt="Project Logo" width="48" height="48"/>
             {%- else -%}
                 <img src="{{g.forge_static('images/project_default.png')}}" alt="Project Logo" width="48" height="48"/>
             {%- endif -%}

http://git-wip-us.apache.org/repos/asf/allura/blob/b2167039/Allura/allura/templates/jinja_master/nav_menu.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/nav_menu.html b/Allura/allura/templates/jinja_master/nav_menu.html
index 520267e..b65d80d 100644
--- a/Allura/allura/templates/jinja_master/nav_menu.html
+++ b/Allura/allura/templates/jinja_master/nav_menu.html
@@ -29,7 +29,7 @@
     {% if c.project.is_user_project %}
       {{lib.gravatar(c.project.user_project_of, size=48, className='project_icon')}}
     {% elif c.project.icon %}
-      <img src="{{c.project.url()}}/icon?{{c.project.icon._id.generation_time}}" class="project_icon" alt="Project Logo">
+      <img src="{{c.project.url()}}icon?{{c.project.icon._id.generation_time}}" class="project_icon" alt="Project Logo">
     {% endif %}
     <h1 class="project_title">
         <a href="{{c.project.url()}}" class="project_link">

http://git-wip-us.apache.org/repos/asf/allura/blob/b2167039/Allura/allura/templates/jinja_master/neigh_nav_menu.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/neigh_nav_menu.html b/Allura/allura/templates/jinja_master/neigh_nav_menu.html
index 687dd2b..907ad5f 100644
--- a/Allura/allura/templates/jinja_master/neigh_nav_menu.html
+++ b/Allura/allura/templates/jinja_master/neigh_nav_menu.html
@@ -20,7 +20,7 @@
   <div id="nav_menu_missing"></div>
 {% else %}
     {% if neighborhood.icon %}
-      <a href="{{neighborhood.url()}}"><img src="{{neighborhood.url()}}/icon" class="project_icon" alt="{{neighborhood.name}} Logo"/></a>
+      <a href="{{neighborhood.url()}}"><img src="{{neighborhood.url()}}icon" class="project_icon" alt="{{neighborhood.name}} Logo"/></a>
     {% endif %}
 	<h1 class="project_title"><a href="{{neighborhood.url()}}">{{neighborhood.name}}</a></h1>
   {% if neighborhood.project_list_url %}

http://git-wip-us.apache.org/repos/asf/allura/blob/b2167039/Allura/allura/templates/jinja_master/theme_macros.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/theme_macros.html b/Allura/allura/templates/jinja_master/theme_macros.html
index fd3f6fb..5581037 100644
--- a/Allura/allura/templates/jinja_master/theme_macros.html
+++ b/Allura/allura/templates/jinja_master/theme_macros.html
@@ -121,7 +121,7 @@ http://stackoverflow.com/questions/26582731/redefining-imported-jinja-macros
 {% if not project_header_right %}
 {%- macro project_header_right(project, app) %}
   {% if project.neighborhood.icon %}
-    <a href="{{project.neighborhood.url()}}"><img src="{{project.neighborhood.url()}}/icon" class="neighborhood_icon"
+    <a href="{{project.neighborhood.url()}}"><img src="{{project.neighborhood.url()}}icon" class="neighborhood_icon"
        alt="Return to {{project.neighborhood.name}}" title="Return to {{project.neighborhood.name}}"></a>
        <div class="neighborhood_title">
          <h1><a href="{{project.neighborhood.url()}}">{{project.neighborhood.name}}</a></h1>

http://git-wip-us.apache.org/repos/asf/allura/blob/b2167039/Allura/allura/templates/widgets/neighborhood_overview_form.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/neighborhood_overview_form.html b/Allura/allura/templates/widgets/neighborhood_overview_form.html
index 0bd3215..c555a4d 100644
--- a/Allura/allura/templates/widgets/neighborhood_overview_form.html
+++ b/Allura/allura/templates/widgets/neighborhood_overview_form.html
@@ -40,7 +40,7 @@
     <label class="grid-4">Icon</label>
     <div class="grid-14">
       {% if neighborhood.icon %}
-        <img src="{{neighborhood.url()}}/icon" style="vertical-align: middle" alt=""/>
+        <img src="{{neighborhood.url()}}icon" style="vertical-align: middle" alt=""/>
       {% endif %}
       {{widget.display_field(widget.fields.icon)}}
     </div>


[06/47] allura git commit: [#8004] remove icons from add_project page

Posted by br...@apache.org.
[#8004] remove icons from add_project page


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/d7ee0573
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d7ee0573
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d7ee0573

Branch: refs/heads/db/7919
Commit: d7ee0573fc6ac3cdce208800167824e707bae58a
Parents: 6abb954
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Oct 21 12:44:49 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Oct 22 10:55:26 2015 -0400

----------------------------------------------------------------------
 Allura/allura/lib/widgets/resources/css/add_project.css      | 8 ++++----
 .../allura/templates/widgets/neighborhood_add_project.html   | 3 +--
 2 files changed, 5 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/d7ee0573/Allura/allura/lib/widgets/resources/css/add_project.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/add_project.css b/Allura/allura/lib/widgets/resources/css/add_project.css
index fc3d6dd..69f36f7 100644
--- a/Allura/allura/lib/widgets/resources/css/add_project.css
+++ b/Allura/allura/lib/widgets/resources/css/add_project.css
@@ -106,12 +106,12 @@ div.welcome div.grid-3{
     border: 1px solid black;
 }
 div.button-row {
-    margin: 40px 0 100px 10px;
+    margin: 30px 0 100px 20px;
 }
 div.tool {
     float: left;
     position: relative;
-    padding: 10px 20px 10px 70px;
+    padding: 10px 20px 10px 10px;
     -moz-border-radius: 4px;
     -webkit-border-radius: 4px;
     -o-border-radius: 4px;
@@ -119,8 +119,8 @@ div.tool {
     -khtml-border-radius: 4px;
     border-radius: 4px;
     border: 1px solid #aaa;
-    width: 360px;
-    margin: 5px;
+    width: 395px;
+    margin: 5px 20px;
     background-color: whiteSmoke;
     height: 74px;
 }

http://git-wip-us.apache.org/repos/asf/allura/blob/d7ee0573/Allura/allura/templates/widgets/neighborhood_add_project.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/neighborhood_add_project.html b/Allura/allura/templates/widgets/neighborhood_add_project.html
index a84f9b5..322d721 100644
--- a/Allura/allura/templates/widgets/neighborhood_add_project.html
+++ b/Allura/allura/templates/widgets/neighborhood_add_project.html
@@ -53,7 +53,6 @@
         {% set _ctx = widget.context_for(widget.fields.tools) %}
         {% if tool.installable %}
         <div class="tool">
-            <img src="{{ g.theme.app_icon_url(tool, 48) }}" alt="{{ opt.label }} icon">
             <input type="checkbox" value="{{ opt.html_value }}"
                    {% if _ctx['value'] and opt.html_value in _ctx['value'] %}checked{% endif %}
                    name="{{ _ctx['rendered_name'] }}"
@@ -66,7 +65,7 @@
     {% endif %}
     {% if h.has_access(neighborhood, 'admin') and not neighborhood.project_template and neighborhood.features['private_projects'] %}
     <div style="margin-top:20px">
-        <div class="grid-16" style="padding-top:4px; padding-left:4px">
+        <div class="grid-16" style="padding-top:10px; padding-left:20px">
           {{widget.display_field(widget.fields.private_project)}}
             <label for="{{ widget.context_for(widget.fields.private_project)['id'] }}">
             Private? Private projects will be unreadable to non-project members and will


[07/47] allura git commit: [#8004] remove tool icons from [[projects]] macro, and display_mode=grid too since it is even less good now

Posted by br...@apache.org.
[#8004] remove tool icons from [[projects]] macro, and display_mode=grid too since it is even less good now


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/7147ad9e
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/7147ad9e
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/7147ad9e

Branch: refs/heads/db/7919
Commit: 7147ad9e23326f9771f28378755119b36a8c4246
Parents: d7ee057
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Oct 22 12:21:23 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Oct 22 12:21:23 2015 -0400

----------------------------------------------------------------------
 Allura/allura/lib/macro.py                      | 25 ++++++------
 Allura/allura/lib/widgets/project_list.py       | 20 +---------
 Allura/allura/nf/allura/css/site_style.css      | 40 --------------------
 Allura/allura/templates/neighborhood_help.html  |  6 +--
 .../templates/widgets/project_list_widget.html  |  4 +-
 .../templates/widgets/project_summary.html      | 24 ------------
 Allura/allura/tests/functional/test_root.py     |  7 ++--
 Allura/allura/tests/test_globals.py             | 12 ------
 8 files changed, 21 insertions(+), 117 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/lib/macro.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index fd0ef58..5aca72d 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -164,10 +164,9 @@ def project_blog_posts(max_number=5, sort='timestamp', summary=False, mount_poin
 
 
 def get_projects_for_macro(
-        category=None, display_mode='grid', sort='last_updated',
+        category=None, sort='last_updated',
         show_total=False, limit=100, labels='', award='', private=False,
         columns=1, show_proj_icon=True, show_download_button=False, show_awards_banner=True,
-        grid_view_tools='',
         initial_q={}):
     from allura.lib.widgets.project_list import ProjectList
     from allura.lib import utils
@@ -250,11 +249,11 @@ def get_projects_for_macro(
 
     pl = ProjectList()
     g.resource_manager.register(pl)
-    response = pl.display(projects=projects, display_mode=display_mode,
+    response = pl.display(projects=projects,
                           columns=columns, show_proj_icon=show_proj_icon,
                           show_download_button=show_download_button,
                           show_awards_banner=show_awards_banner,
-                          grid_view_tools=grid_view_tools)
+                          )
     if show_total:
         if total is None:
             total = 0
@@ -267,24 +266,26 @@ def get_projects_for_macro(
 
 
 @macro('neighborhood-wiki')
-def projects(category=None, display_mode='grid', sort='last_updated',
+def projects(category=None, sort='last_updated',
              show_total=False, limit=100, labels='', award='', private=False,
              columns=1, show_proj_icon=True, show_download_button=False, show_awards_banner=True,
-             grid_view_tools=''):
+             display_mode=None, grid_view_tools='',  # old & unused now
+             ):
     initial_q = dict(neighborhood_id=c.project.neighborhood_id)
     return get_projects_for_macro(
-        category=category, display_mode=display_mode, sort=sort,
+        category=category, sort=sort,
         show_total=show_total, limit=limit, labels=labels, award=award, private=private,
         columns=columns, show_proj_icon=show_proj_icon, show_download_button=show_download_button,
-        show_awards_banner=show_awards_banner, grid_view_tools=grid_view_tools,
+        show_awards_banner=show_awards_banner,
         initial_q=initial_q)
 
 
 @macro('userproject-wiki')
-def my_projects(category=None, display_mode='grid', sort='last_updated',
+def my_projects(category=None, sort='last_updated',
                 show_total=False, limit=100, labels='', award='', private=False,
                 columns=1, show_proj_icon=True, show_download_button=False, show_awards_banner=True,
-                grid_view_tools=''):
+                display_mode=None, grid_view_tools='',  # old & unused now
+                ):
 
     myproj_user = c.project.user_project_of
     if myproj_user is None:
@@ -296,10 +297,10 @@ def my_projects(category=None, display_mode='grid', sort='last_updated',
 
     initial_q = dict(_id={'$in': ids})
     return get_projects_for_macro(
-        category=category, display_mode=display_mode, sort=sort,
+        category=category, sort=sort,
         show_total=show_total, limit=limit, labels=labels, award=award, private=private,
         columns=columns, show_proj_icon=show_proj_icon, show_download_button=show_download_button,
-        show_awards_banner=show_awards_banner, grid_view_tools=grid_view_tools,
+        show_awards_banner=show_awards_banner,
         initial_q=initial_q)
 
 

http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/lib/widgets/project_list.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/project_list.py b/Allura/allura/lib/widgets/project_list.py
index b5aa619..a4e3311 100644
--- a/Allura/allura/lib/widgets/project_list.py
+++ b/Allura/allura/lib/widgets/project_list.py
@@ -29,7 +29,6 @@ class ProjectSummary(ew_core.Widget):
     template = 'jinja:allura:templates/widgets/project_summary.html'
     defaults = dict(
         ew_core.Widget.defaults,
-        sitemap=None,
         icon=None,
         value=None,
         icon_url=None,
@@ -38,22 +37,11 @@ class ProjectSummary(ew_core.Widget):
         show_proj_icon=True,
         show_download_button=True,
         show_awards_banner=True,
-        grid_view_tools='')
+        )
 
     def prepare_context(self, context):
         response = super(ProjectSummary, self).prepare_context(context)
         value = response['value']
-        if response['sitemap'] is None:
-            response['sitemap'] = [s for s in value.sitemap() if s.url]
-
-        if response['grid_view_tools'] != '':
-            view_tools_list = response['grid_view_tools'].split(',')
-            icon_tool_list = ["tool-%s" % vt.lower() for vt in view_tools_list]
-            old_sitemap = response['sitemap']
-            response['sitemap'] = []
-            for sm in old_sitemap:
-                if sm.ui_icon is not None and sm.ui_icon.lower() in icon_tool_list:
-                    response['sitemap'].append(sm)
 
         if response['icon_url'] is None:
             if value.icon:
@@ -90,15 +78,13 @@ class ProjectList(ew_core.Widget):
         ew_core.Widget.defaults,
         projects=[],
         project_summary=ProjectSummary(),
-        display_mode='list',
-        sitemaps=None,
         icon_urls=None,
         accolades_index=None,
         columns=1,
         show_proj_icon=True,
         show_download_button=True,
         show_awards_banner=True,
-        grid_view_tools='')
+        )
 
     def prepare_context(self, context):
         response = super(ProjectList, self).prepare_context(context)
@@ -110,8 +96,6 @@ class ProjectList(ew_core.Widget):
         for opt in ['show_proj_icon', 'show_download_button', 'show_awards_banner']:
             response[opt] = asbool(response[opt])
 
-        if response['sitemaps'] is None and response['display_mode'] != 'list':
-            response['sitemaps'] = M.Project.menus(projects)
         if response['icon_urls'] is None and response['show_proj_icon']:
             response['icon_urls'] = M.Project.icon_urls(projects)
         if response['accolades_index'] is None and response['show_awards_banner']:

http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index 7bda3ee..d702ca9 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -2286,17 +2286,6 @@ div.attachment_thumb .file_type span {
   margin-top: 10px;
 }
 
-.border {
-  -moz-border-radius: 5px;
-  -webkit-border-radius: 5px;
-  -o-border-radius: 5px;
-  -ms-border-radius: 5px;
-  -khtml-border-radius: 5px;
-  border-radius: 5px;
-  padding: 5px 10px;
-  border-bottom: 1px solid #fff;
-}
-
 .card {
   position: relative;
   -moz-border-radius: 4px;
@@ -2351,23 +2340,6 @@ div.attachment_thumb .file_type span {
 .card .desc {
   margin: 5px 0 0;
 }
-.card .quik {
-  position: absolute;
-  bottom: 10px;
-  left: 10px;
-}
-.card .quik a {
-  margin: 0;
-  color: #000;
-  text-shadow: #fff 0 1px;
-  border: none;
-  width: 24px;
-  height: 24px;
-  display: inline-block;
-}
-.card .quik a span {
-  display: none;
-}
 .card .feature {
   position: absolute;
   top: -1px;
@@ -2393,18 +2365,6 @@ div.attachment_thumb .file_type span {
   background-image: -webkit-gradient(linear, 50% 100%, 100% 0%, color-stop(0.9, white), color-stop(0.9, #555555));
   background-image: -moz-linear-gradient(100% 25% 230deg, #555555, white, white 1%);
 }
-.card hr {
-  visibility: hidden;
-}
-.card.sm {
-  height: 46px;
-  width: 34px;
-}
-.card.sm .box {
-  height: 48px;
-  margin: 0 0 0 -7px;
-  padding: 0;
-}
 .list.card {
   width: 740px;
   display: inline;

http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/templates/neighborhood_help.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/neighborhood_help.html b/Allura/allura/templates/neighborhood_help.html
index 5c5d27a..18f2568 100644
--- a/Allura/allura/templates/neighborhood_help.html
+++ b/Allura/allura/templates/neighborhood_help.html
@@ -38,18 +38,16 @@
   to list all the projects in your neighborhood.
   </p>
   <p>
-  Example: <code>[[projects display_mode=list columns=2 show_download_button=no limit=50]]</code>
+  Example: <code>[[projects columns=2 show_download_button=no limit=50]]</code>
   </p>
   <p>Display options:</p>
   <ul>
-    <li><code>display_mode</code> = grid/list.  Default is 'grid'</li>
     <li><code>show_proj_icon</code> = yes/no.  Default 'yes'</li>
-    <li><code>grid_view_tools</code> = git,hg,svn,tickets,wiki... Limit the tools shown in project list. Multivalue option (example grid_view_tools=git,wiki).  Default ''</li>
     <li><code>show_download_button</code> = yes/no.  Default 'no'</li>
 	<li><code>show_awards_banner</code> = yes/no.  Default 'yes'</li>
     <li><code>sort</code> = last_updated/alpha/random/last_registered.  Default 'last_updated'</li>
     <li><code>show_total</code> = yes/no.  Adds a sentence with a total count of how many projects are listed. Default 'no'</li>
-    <li><code>columns</code> = 1, 2, or 3.  Works with 'list' display_mode.  Default 1</li>
+    <li><code>columns</code> = 1, 2, or 3.  Default 1</li>
   </ul>
   <p>Filter options:</p>
   <ul>

http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/templates/widgets/project_list_widget.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/project_list_widget.html b/Allura/allura/templates/widgets/project_list_widget.html
index 13fccca..3f3ae4e 100644
--- a/Allura/allura/templates/widgets/project_list_widget.html
+++ b/Allura/allura/templates/widgets/project_list_widget.html
@@ -29,13 +29,11 @@
             value=project, 
             icon_url=icon_urls[project._id], 
             accolades=accolades_index[project._id],
-            sitemap=sitemaps[project._id],
-            display_mode=display_mode,
             columns=columns,
             show_proj_icon=show_proj_icon,
             show_download_button=show_download_button,
             show_awards_banner=show_awards_banner,
-            grid_view_tools=grid_view_tools)}}
+            )}}
       {% endif %}
     {% endfor %}
     {% do g.set_project(old_project) %}

http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/templates/widgets/project_summary.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/project_summary.html b/Allura/allura/templates/widgets/project_summary.html
index 72c96a6..bc69f2f 100644
--- a/Allura/allura/templates/widgets/project_summary.html
+++ b/Allura/allura/templates/widgets/project_summary.html
@@ -16,7 +16,6 @@
        specific language governing permissions and limitations
        under the License.
 -#}
-{% if display_mode == 'list' %}
 <div class="list card{% if show_proj_icon%} proj_icon{% endif %}"
 	{%- if columns == 2 %} style="width: 330px"{% elif columns == 3 %} style="width: 220px"{% endif %}>
   {% if accolades %}
@@ -35,26 +34,3 @@
   <p class="desc">{% if value.summary %}{{value.summary}}{% else %}{{h.text.truncate(value.short_description, 50)}}{% endif %}</p>
   {% if show_download_button %}{{g.markdown_wiki.convert('[[download_button]]')}}{% endif %}
 </div>
-{% else %}
-  <div class="border card">
-    {% if accolades %}
-      <div class="box notch sponsor">
-        <div class="feature">
-          <a href="{{accolades[0].award_url}}" title="{{accolades[0].comment}}">{{accolades[0].award.short}}</a>
-        </div>
-        {% if icon_url %}<img src="{{icon_url}}" alt="{{value.name}} Logo"/>{% endif %}
-      </div>
-    {% elif icon_url %}
-      <div class="box">
-        <img src="{{icon_url}}" alt="{{value.name}} Logo"/>
-      </div>
-    {% endif %}
-    <h2><a href="{{value.url()}}">{{value.name}}</a></h2>
-    <p class="desc">{% if value.summary %}{{value.summary}}{% else %}{{h.text.truncate(value.short_description, 50)}}{% endif %}</p>
-    <div class="quik">
-      {% for s in sitemap %}
-      <a href="{{s.url}}" class="ui-icon-{{(s.ui_icon or 'admin').lower()}}-24" title="{{s.label}}"><span>{{s.label}}</span></a>
-      {% endfor %}
-    </div>
-  </div>
-{% endif %}

http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_root.py b/Allura/allura/tests/functional/test_root.py
index bc54d65..5aae3e5 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -112,10 +112,9 @@ class TestRootController(TestController):
             p.install_app('home', 'home', 'Home', ordinal=0)
 
         response = self.app.get('/adobe/')
-        projects = response.html.findAll('div', {'class': 'border card'})
-        assert len(projects) == 2
-        cat_links = response.html.find(
-            'div', {'id': 'sidebar'}).findAll('ul')[1].findAll('li')
+        projects = response.html.findAll('div', {'class': 'list card proj_icon'})
+        assert_equal(len(projects), 2)
+        cat_links = response.html.find('div', {'id': 'sidebar'}).findAll('ul')[1].findAll('li')
         assert len(cat_links) == 3, cat_links
         assert cat_links[0].find('a').get('href') == '/adobe/browse/clustering'
         assert cat_links[0].find('a').find('span').string == 'Clustering'

http://git-wip-us.apache.org/repos/asf/allura/blob/7147ad9e/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index bb5d80e..139250e 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -585,18 +585,6 @@ def test_projects_macro():
         assert two_column_style not in r
 
 
-@td.with_wiki
-def test_limit_tools_macro():
-    p_nbhd = M.Neighborhood.query.get(name='Adobe')
-    with h.push_context(p_nbhd.neighborhood_project._id, 'wiki'):
-        r = g.markdown_wiki.convert('[[projects]]')
-        assert '<span>Admin</span>' in r
-        r = g.markdown_wiki.convert('[[projects grid_view_tools=wiki]]')
-        assert '<span>Admin</span>' not in r
-        r = g.markdown_wiki.convert('[[projects grid_view_tools=wiki,admin]]')
-        assert '<span>Admin</span>' in r
-
-
 @td.with_user_project('test-admin')
 @td.with_user_project('test-user-1')
 def test_myprojects_macro():


[10/47] allura git commit: [#7919] Extend json_nav to include additional navbar attributes

Posted by br...@apache.org.
[#7919] Extend json_nav to include additional navbar attributes


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/8a855eae
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/8a855eae
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/8a855eae

Branch: refs/heads/db/7919
Commit: 8a855eaee6e1a313c4025ba1b9a52f4eee67daa1
Parents: bcdee46
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:05:47 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:05:14 2015 -0400

----------------------------------------------------------------------
 Allura/allura/model/project.py | 48 +++++++++++++++++++++++++++++++------
 1 file changed, 41 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/8a855eae/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index cef25bc..550f95c 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -28,6 +28,7 @@ from pylons import tmpl_context as c, app_globals as g
 from pylons import request
 from paste.deploy.converters import asbool
 import formencode as fe
+import json
 
 from ming import schema as S
 from ming.utils import LazyProperty
@@ -601,6 +602,39 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                 i += 1
         return new_tools
 
+    def json_nav(self):
+        grouping_threshold = self.get_tool_data('allura', 'grouping_threshold', 1)
+        anchored_tools = self.neighborhood.get_anchored_tools()
+        children = []
+        i = 0
+        for s in self.grouped_navbar_entries():
+            _offset = -2 if s.url.endswith("/") else -1
+            mount_point = s.url.split('/')[_offset]
+            entry = dict(name=s.label,
+                         url=s.url,
+                         icon=s.ui_icon or 'tool-admin',
+                         tool_name=s.tool_name or 'sub',
+                         mount_point=mount_point,
+                         is_anchored=s.tool_name in anchored_tools.keys(),
+                         ordinal=i)
+            i += 1
+            if s.children:
+                entry['child_count'] = len(s.children)
+                entry['children'] = [dict(name=child.label,
+                                          url=child.url,
+                                          icon=child.ui_icon or 'tool-admin',
+                                          mount_point=child.url.split('/')[-2],
+                                          tool_name=child.tool_name or 'sub',
+                                          is_anchored=child.tool_name in anchored_tools.keys(),
+                                          ordinal=x + i)
+                                     for x, child in enumerate(s.children)]
+                i += len(s.children)
+            children.append(entry)
+
+        return json.dumps(dict(grouping_threshold=grouping_threshold,
+                               children=children,
+                               child_count=i))
+
     def grouped_navbar_entries(self):
         """Return a :class:`~allura.app.SitemapEntry` list suitable for rendering
         the project navbar with tools grouped together by tool type.
@@ -801,7 +835,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
 
         for sub in self.direct_subprojects:
             result.append(
-                {'ordinal': int(sub.ordinal + i), 'sub': sub, 'rank': 1})
+                {'ordinal': int(sub.ordinal + i), 'sub': sub})
         for ac in self.app_configs:
             App = g.entry_points['tool'].get(ac.tool_name)
             if include_hidden or App and not App.hidden:
@@ -809,11 +843,9 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                     ordinal = anchored_tools.keys().index(ac.tool_name.lower())
                 else:
                     ordinal = int(ac.options.get('ordinal', 0)) + i
-                rank = 0 if ac.options.get(
-                    'mount_point', None) == 'home' else 1
-                result.append(
-                    {'ordinal': int(ordinal), 'ac': ac, 'rank': rank})
-        return sorted(result, key=lambda e: (e['ordinal'], e['rank']))
+                result.append({'ordinal': int(ordinal), 'ac': ac})
+
+        return sorted(result, key=lambda e: (e['ordinal']))
 
     def first_mount_visible(self, user):
         mounts = self.ordered_mounts()
@@ -1271,8 +1303,10 @@ class AppConfig(MappedClass, ActivityObject):
             (self.options.mount_point, self.url())]
 
     def __json__(self):
+        options = self.options._deinstrument()
+        options['url'] = self.project.url() + self.options.mount_point + '/'
         return dict(
             _id=self._id,
             # strip away the ming instrumentation
-            options=self.options._deinstrument(),
+            options=options,
         )


[33/47] allura git commit: [#7919] Add "Add new tool" feature

Posted by br...@apache.org.
[#7919] Add "Add new tool" feature


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/7ca68755
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/7ca68755
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/7ca68755

Branch: refs/heads/db/7919
Commit: 7ca68755dbfe10f75313ffa40e8fdb69b9ce5c73
Parents: 437f465
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:59:23 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/navbar.es6.js | 250 +++++++++++++++++++++++++-
 1 file changed, 248 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/7ca68755/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index 9cdb907..5d62002 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -10,7 +10,7 @@
 function _getProjectUrl(rest = true) {
     var [nbhd, proj] = window.location.pathname.split('/').slice(1, 3);
     var base = `${window.location.protocol}//${window.location.host}`;
-    return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`;
+    return rest ? `${base}/rest/${nbhd}/${proj}/` : `${base}/${nbhd}/${proj}/`;
 }
 
 /**
@@ -292,6 +292,246 @@ var ToggleAdminButton = React.createClass({
     }
 });
 
+//////////////////
+// Add New Tool //
+//////////////////
+
+var NewToolButton = React.createClass({
+    render: function () {
+        return (
+            <button id='new-tool-btn' onClick={ this.props.handleAddButton } className=''>
+                <i className={ classes }></i>
+            </button>
+        );
+    }
+});
+
+
+/**
+ * Menu for adding a new tool.
+ * @constructor
+ */
+var NewToolMenu = React.createClass({
+    propTypes: {
+        tools: React.PropTypes.array,
+        onPushAddButton: React.PropTypes.func,
+        onSetActive: React.PropTypes.func,
+        formData: React.PropTypes.object,
+        visible: React.PropTypes.bool
+    },
+
+    render: function () {
+        var _this = this;
+
+        var tools = this.props.tools.map(function (tool, i) {
+            var classes;
+            if (_this.props.active && _this.props.active.name === tool.name) {
+                classes = " selected-tool"
+            }
+            else {
+                classes = ""
+            }
+            return (
+                <li className={classes}
+                    id={"add-new-" + tool.name}
+                    key={`new-tool-btn-${i}`}
+                    onClick={_this.props.handleChangeTool}>
+                    {tool.name}
+                </li>
+            )
+        });
+
+        return (
+            <div className="tool-card">
+                <div className="box-title">Add a new tool
+                </div>
+                <div id="installable-items">
+                    <ul className="installable-tool-box">
+                        {tools}
+                    </ul>
+                </div>
+                <div className="tool-partition"></div>
+                <NewToolInfo {...this.props}
+                    name={this.props.active.name}
+                    description={this.props.active.description}
+                    handleAddButton={this.props.handleAddButton}/>
+            </div>
+        );
+    }
+});
+
+var InstallNewToolForm = React.createClass({
+    render: function () {
+        console.log(this.props.active.name);
+        if (this.props.active.name === "Add a tool"){
+
+            return(<div></div>);
+        }
+        var default_mount_point = this.props.active.defaults.default_mount_point;
+        var default_mount_label = this.props.active.defaults.default_mount_label;
+
+        return (
+            <form id="add-tool-form">
+                <label htmlFor="mount_label">Label</label>
+                <input id="mount_label" onChange={this.props.handleChangeForm} value={default_mount_label} />
+
+                <label htmlFor="mount_point">Url Path</label>
+                <input id="mount_point"
+                       onChange={this.props.handleChangeForm}
+                       onBlur={this.props.validateMountPoint}
+                       value={this.props.formData.mount_point}/>
+
+                <p style={{"color": "grey"}}><small>http://hs/p/finna/</small><strong style={{"color": "orange"}}>
+                    {this.props.formData.mount_point}
+                </strong></p>
+
+                <button id="new-tool-submit"
+                        onClick={this.props.handleAddButton}
+                        className="add-tool-button">
+                    Add Tool
+                </button>
+            </form>
+        );
+    }
+});
+
+
+var NewToolInfo = React.createClass({
+    propTypes: {
+        name: React.PropTypes.string,
+        description: React.PropTypes.description,
+        handleAddButton: React.PropTypes.func
+    },
+
+
+    render: function () {
+        return (
+            <div className="tool-info">
+                <div className="tool-info-left">
+                    <h1>{this.props.name}</h1>
+                    <p>{this.props.description}</p>
+                </div>
+                <div className="tool-info-right">
+                    <InstallNewToolForm {...this.props} />
+                </div>
+            </div>
+        );
+    }
+});
+
+var NewToolMain = React.createClass({
+    getInitialState: function () {
+        let toolPlaceHolder = {
+            name: "Add a tool",
+            description: "click on one of the tools shown above to add it to your project."
+        };
+
+        return {
+            installableTools: [toolPlaceHolder],
+            active: toolPlaceHolder,
+            new_tool: {
+                mount_point: "",
+                mount_label: ""
+            }
+        };
+    },
+
+
+    componentDidMount: function () {
+        let _this = this;
+        $.get(_getProjectUrl(true) + "/admin/installable_tools/", function (result) {
+            if (this.isMounted()) {
+                console.log('hit is mounted', result['tools']);
+                this.setState({
+                    installableTools: result['tools']
+                });
+            }
+        }.bind(this));
+    },
+    handleAddButton: function (e) {
+        e.preventDefault();
+        console.log('Add new too button pushed');
+        console.log('e.target.name', e);
+        console.log(e.target.textContent);
+
+    },
+    handleChangeTool: function (e) {
+        console.log(`Changed tool to: ${e.target.textContent}`);
+        this._setActiveByName(e.target.textContent);
+
+    },
+    _setActiveByName: function (name) {
+        var index = this.state.installableTools.findIndex(
+            x => x.name === name
+        );
+        this.setState({
+            active: this.state.installableTools[index]
+        });
+    },
+
+    handleChangeForm: function (e) {
+        console.log(e.target.value);
+        var _new_tool = this.state.new_tool;
+
+        console.log(e.target.id);
+        _new_tool[e.target.id] = e.target.value;
+
+        this.setState({
+            new_tool: _new_tool
+        });
+
+    },
+    handleSubmit: function (e) {
+        e.preventDefault();
+        var nextItems = this.state.items.concat([this.state.text]);
+        var nextText = '';
+        this.setState({items: nextItems, text: nextText});
+    },
+
+    validateMountPoint: function (e) {
+        e.preventDefault();
+        let url = _getProjectUrl(true) + '/admin/mount_point/';
+
+        let data = {
+            'mount_point': e.target.value,
+            '_session_id': $.cookie('_session_id')
+        };
+
+        let d = $.post(url, data).done(function (result) {
+            console.log(result);
+        });
+
+        if(d.responseJSON.exists){
+            alert('exists');
+        }else{
+            alert('does not exist');
+        }
+
+    },
+
+    render: function () {
+        return <NewToolMenu
+            active={this.state.active}
+            tools={this.state.installableTools}
+            formData={this.state.new_tool}
+            handleChangeTool={this.handleChangeTool}
+            handleChangeForm={this.handleChangeForm}
+            validateMountPoint={this.validateMountPoint}
+            handleAddButton={this.handleAddButton}/>;
+    }
+});
+
+
+
+
+
+
+
+
+
+
+////////////////////////////////////////////
+
 /**
  * The main "controller view" of the NavBar.
  * @constructor
@@ -299,7 +539,8 @@ var ToggleAdminButton = React.createClass({
  */
 var Main = React.createClass({
     propTypes: {
-        initialData: ToolsPropType
+        initialData: ToolsPropType,
+        installableTools: React.PropTypes.array
     },
     getInitialState: function () {
         return {
@@ -322,6 +563,7 @@ var Main = React.createClass({
         }.bind(this));
     },
 
+
     /**
      * Handles the locking and unlocking of the NavBar
      */
@@ -436,3 +678,7 @@ var Main = React.createClass({
         );
     }
 });
+
+
+   React.render(React.createElement(NewToolMain, {
+        }), document.getElementById("add_tool_menu"));
\ No newline at end of file


[16/47] allura git commit: [#7920] Fix import error

Posted by br...@apache.org.
[#7920] Fix import error


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/30d234e9
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/30d234e9
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/30d234e9

Branch: refs/heads/db/7919
Commit: 30d234e9a7100bafe9020e7c256fe0de92cd0381
Parents: d2c26d5
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 12:19:14 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/30d234e9/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 0fbdaf2..676a6fc 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -21,7 +21,7 @@ from urlparse import urlparse
 import json
 from operator import itemgetter
 import pkg_resources
-from pylons import tmpl_context as c, app_globals as g
+from pylons import tmpl_context as c, app_globals as g, response
 from pylons import request
 from paste.deploy.converters import asbool, aslist
 from tg import expose, redirect, flash, validate, config, jsonify


[45/47] allura git commit: [#7919] first step in better injecting of the react nav bar

Posted by br...@apache.org.
[#7919] first step in better injecting of the react nav bar

* remove unneeded child_count
* move JS to run only on top nav template
* still render regular HTML menu for admins, then replace it when ready
  this avoids any flash
* use h.escape_json instead of just 'safe', to ensure no subtle security issues


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a666e08a
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a666e08a
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a666e08a

Branch: refs/heads/db/7919
Commit: a666e08a978b80bf20a7e26c722ae4bf5807ca73
Parents: 6381ecb
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Oct 16 17:53:11 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:36:08 2015 -0400

----------------------------------------------------------------------
 Allura/allura/controllers/project.py            |   2 +-
 Allura/allura/model/project.py                  |   9 +-
 Allura/allura/public/nf/css/navbar.css          | 187 ++-----------------
 .../allura/templates/jinja_master/master.html   |  11 --
 .../allura/templates/jinja_master/top_nav.html  |  16 +-
 5 files changed, 37 insertions(+), 188 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a666e08a/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 869d326..dbd1652 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -381,7 +381,7 @@ class ProjectController(FeedController):
 
     @expose('json:')
     def _nav(self):
-        return c.project.json_nav()
+        return c.project.nav_data()
 
     @expose()
     def _lookup(self, name, *remainder):

http://git-wip-us.apache.org/repos/asf/allura/blob/a666e08a/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index e40f1a5..1609057 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -602,7 +602,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                 i += 1
         return new_tools
 
-    def json_nav(self):
+    def nav_data(self):
         grouping_threshold = self.get_tool_data('allura', 'grouping_threshold', 1)
         anchored_tools = self.neighborhood.get_anchored_tools()
         children = []
@@ -619,7 +619,6 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                          ordinal=i)
             i += 1
             if s.children:
-                entry['child_count'] = len(s.children)
                 entry['children'] = [dict(name=child.label,
                                           url=child.url,
                                           icon=child.ui_icon or 'tool-admin',
@@ -631,9 +630,9 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                 i += len(s.children)
             children.append(entry)
 
-        return json.dumps(dict(grouping_threshold=grouping_threshold,
-                               menu=children,
-                               child_count=i))
+        return dict(grouping_threshold=grouping_threshold,
+                    menu=children,
+                    )
 
     def grouped_navbar_entries(self):
         """Return a :class:`~allura.app.SitemapEntry` list suitable for rendering

http://git-wip-us.apache.org/repos/asf/allura/blob/a666e08a/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index 6b947d1..d27b727 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -4,9 +4,9 @@
     display: none;
 }
 
-.hidden {
-    display: none;
-}
+/*.hidden {*/
+/*display: none;*/
+/*}*/
 
 .submenu ul {
     list-style: none;
@@ -85,7 +85,7 @@ nav {
     -ms-border-radius: 4px;
     -khtml-border-radius: 4px;
     border-radius: 4px;
-    width: 918px;  /* 940px - 32px for toggle-admin-btn */
+    width: 918px; /* 940px - 32px for toggle-admin-btn */
 }
 
 #top_nav_admin .edit-mode .fa {
@@ -196,174 +196,29 @@ ul.dropdown .hover, ul.dropdown li:hover {
     color: gray;
 }
 
-.nav_admin{
+.nav_admin {
     height: auto;
 }
 
-.nav_admin > div > ul > li{
+.nav_admin > div > ul > li {
     height: 1.2rem;
     font-weight: inherit;
 }
 
 .tool-partition {
     height: 0;
-    /*padding-top: 5px;*/
     border-top: 3px solid #777;
 }
 
 .installable-tool-box {
-    /* position: relative; */
     display: flex;
     background-color: white;
-    background-image: 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, rgba(204, 204, 204, 0.6)));
-    background-image: 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
+    background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, rgba(204, 204, 204, 0.6)));
+    background-image: -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
     background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
     flex-wrap: wrap;
-    /*justify-content: flex-start;*/
     justify-content: space-around;
-    /*margin-left: 0;*/
     flex-direction: row;
-    /* padding-bottom: 5px; */
-    /* padding-top: 4px; */
-    /*display: -webkit-flex;*/
-    /*display: flex;*/
-    /*-webkit-flex-direction: row;*/
-    /*flex-direction: row;*/
-    /*margin-bottom: 8px;*/
 }
 
 .installable-tool-box div {
@@ -389,7 +244,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     user-select: none;
 }
 
-
 /*.installable-tool-box > div{
     color:blue;
     background: rgba(255, 255, 255, 0.8);
@@ -397,8 +251,7 @@ ul.dropdown .hover, ul.dropdown li:hover {
     border: 1px dashed orange;
 }*/
 
-
-.selected-tool{
+.selected-tool {
     background: #09C !important;
     color: white !important;
     height: 21px;
@@ -521,14 +374,14 @@ ul.dropdown .hover, ul.dropdown li:hover {
     height: auto;
 }
 
-#add-tool-form > label{
+#add-tool-form > label {
     padding: 0;
     font-size: 13pt;
     position: absolute;
     margin-left: 18px;
 }
 
-#add-tool-form > p{
+#add-tool-form > p {
     font-size: large;
 
 }
@@ -540,24 +393,24 @@ ul.dropdown .hover, ul.dropdown li:hover {
     margin: 23px 60px 11px 19px;
 }
 
-#add-tool-form{
+#add-tool-form {
     padding-top: 20px;
     padding-left: 25px;
     padding-right: 25px;
 }
 
-.tool-form-fields{
+.tool-form-fields {
     clear: both;
     position: relative;
     display: flex;
     flex-direction: row;
 }
 
-#mount_point :invalid{
+#mount_point :invalid {
     background: #333;
 }
 
-.add-tool-toggle{
+.add-tool-toggle {
     background: rgba(255, 255, 255, 0.32);
     /*clear: both;*/
     color: #8b8b8b;
@@ -584,21 +437,21 @@ ul.dropdown .hover, ul.dropdown li:hover {
     -o-user-select: none;
     user-select: none;
 }
-.add-tool-toggle:hover{
+
+.add-tool-toggle:hover {
     background: #F4F4F4;
     color: #777;
 }
 
-.active-nav-link{
+.active-nav-link {
     font-weight: bolder;
 }
 
-.add-tool-field{
+.add-tool-field {
     width: 50%;
 }
 
-
-.error-box{
+.error-box {
     background: rgba(255, 114, 114, 0.65);
     color: white;
     padding: 4px;

http://git-wip-us.apache.org/repos/asf/allura/blob/a666e08a/Allura/allura/templates/jinja_master/master.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/master.html b/Allura/allura/templates/jinja_master/master.html
index be6515e..3017c51 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -188,16 +188,5 @@
         });
     })
 </script>
-{% if is_admin %}
-    <script>
-        'use strict';
-        $(document).ready(function () {
-            React.render(React.createElement(Main, {
-                initialData: {{ c.project.json_nav()|safe }}
-            }), document.getElementById("top_nav_admin"));
-        });
-    </script>
-{% endif %}
-{% do g.register_forge_js('/') %}
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/allura/blob/a666e08a/Allura/allura/templates/jinja_master/top_nav.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/top_nav.html b/Allura/allura/templates/jinja_master/top_nav.html
index c433991..88d7904 100644
--- a/Allura/allura/templates/jinja_master/top_nav.html
+++ b/Allura/allura/templates/jinja_master/top_nav.html
@@ -17,10 +17,7 @@
        under the License.
 -#}
 {% if c.project %}
-{% if h.has_access(c.project, 'admin')() %}
-    <div id="top_nav_admin"></div>
-    {#        {{ c.app.admin_modal.display() }}  <-- Currently Does not work on non-admin urls #}
-{% else %}
+<div id="top_nav_admin">
 <ul class="dropdown">
   {% for s in c.project.grouped_navbar_entries() %}
     <li class="{% if s.matches_url(request) %}selected{% endif %}">
@@ -38,5 +35,16 @@
     </li>
 	{% endfor %}
 </ul>
+</div>
+{% if h.has_access(c.project, 'admin')() %}
+    {#        {{ c.app.admin_modal.display() }}  <-- Currently Does not work on non-admin urls #}
+    <script>
+        'use strict';
+        $(document).ready(function () {
+            React.render(React.createElement(Main, {
+                initialData: {{ h.escape_json(c.project.nav_data())|safe }}
+            }), document.getElementById("top_nav_admin"));
+        });
+    </script>
 {% endif %}
 {% endif %}


[37/47] allura git commit: [#7919] Update stylesheet to support new component markup

Posted by br...@apache.org.
[#7919] Update stylesheet to support new component markup


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/dca91692
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/dca91692
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/dca91692

Branch: refs/heads/db/7919
Commit: dca91692ba6c66ca2fcc1ea02df121732da31aa9
Parents: a6d5339
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 22 15:53:35 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css | 2856 ++++++++++++++++++++++++---
 1 file changed, 2633 insertions(+), 223 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/dca91692/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index f3c3336..2cc8798 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -3,11 +3,9 @@
     width: 350px;
     display: none;
 }
-
 .hidden {
     display: none;
 }
-
 .submenu ul {
     list-style: none;
     display: block;
@@ -23,7 +21,6 @@
     z-index: -1000;
     padding-top: 11px;
 }
-
 #bar-config {
     display: inline-flex;
     position: absolute;
@@ -32,14 +29,12 @@
     align-items: stretch;
     flex: 1 1 auto;
 }
-
 #threshold-config > span > input {
     width: 2rem;
     background-color: #A1A1A1;
     color: white;
     font-weight: bold;
 }
-
 #toggle-admin-btn {
     position: absolute;
     right: -9px;
@@ -47,21 +42,18 @@
     width: 2rem;
     height: 1.8rem;
 }
-
 nav {
     display: flex;
     flex-direction: row;
     justify-content: center;
     margin: auto;
 }
-
 #top_nav_admin > div.edit-mode > ul {
     display: flex;
     flex-direction: row;
     flex-wrap: wrap;
     flex: 1;
 }
-
 #top_nav_admin > div.edit-mode > ul > .tb-item {
     background-color: #F0F0F0;
     margin-top: 0.5rem;
@@ -70,11 +62,9 @@ nav {
     border: 1px dashed gray;
     padding: 0.3rem 0.6rem 0.3rem 0.6rem;
 }
-
 .admin-toolbar {
     display: flex;
 }
-
 #top_nav_admin {
     display: grid;
     flex-direction: row;
@@ -85,13 +75,17 @@ nav {
     -ms-border-radius: 4px;
     -khtml-border-radius: 4px;
     border-radius: 4px;
-    width: 918px;  /* 940px - 32px for toggle-admin-btn */
+    width: 918px;
+    /* 940px - 32px for toggle-admin-btn */
 }
-
 #top_nav_admin .edit-mode .fa {
     margin: 0 3px;
+    margin-left: 0;
+    padding: 2px;
+    padding-left: 1px;
+    /* font-size: large; */
+    color: #595959;
 }
-
 .btn-bar {
     display: block;
     clear: both;
@@ -108,7 +102,6 @@ nav {
     position: relative;
     margin: 0 0 20px;
 }
-
 ul.dropdown li {
     float: left;
     vertical-align: middle;
@@ -116,21 +109,17 @@ ul.dropdown li {
     padding-top: 10px;
     padding-bottom: 10px;
 }
-
 ul.dropdown, ul.dropdown li, ul.dropdown ul {
     list-style: none;
     margin: 0;
     padding: 0;
 }
-
 li.tb-item-edit > input {
     width: 2.2rem;
 }
-
 .draggable-handle {
     cursor: move;
 }
-
 ul.dropdown li {
     float: left;
     vertical-align: middle;
@@ -138,35 +127,38 @@ ul.dropdown li {
     padding-top: 10px;
     padding-bottom: 10px;
 }
-
 #content {
     width: 990px;
 }
-
 .react-reorderable-item {
     display: inline-flex;
     float: left;
+    text-align: left;
 }
-
 .react-reorderable-item-active {
     border: 3px dashed #9e9e9e;
     background: #c9c9c9;
-    width: 5rem; /* dynamic would be nice */
+    width: 5rem;
+    /* dynamic would be nice */
     height: 50px;
 }
-
 .react-reorderable-item-active div {
     display: none;
 }
-
 .react-reorderable-handle {
     position: absolute;
 }
-
 #top_nav_admin .tb-item a {
     margin: 10px;
+    text-align: left;
+    display: inline-block;
+    padding-right: 10px;
+    padding-left: 10px;
+    margin-right: 5px;
+    border: 2px solid #8C8C8C;
+    /* border-right: 2px solid #8C8C8C; */
+    border-radius: 3px;
 }
-
 .react-drag {
     -webkit-user-select: none;
     -moz-user-select: none;
@@ -174,7 +166,6 @@ ul.dropdown li {
     -o-user-select: none;
     user-select: none;
 }
-
 ul.dropdown ul {
     visibility: hidden;
     position: absolute;
@@ -184,234 +175,2653 @@ ul.dropdown ul {
     border: 1px solid #dddddd;
     border-top-width: 0;
 }
-
 ul.dropdown .hover, ul.dropdown li:hover {
     position: relative;
     z-index: 599;
     cursor: default;
 }
-
 .anchored {
     cursor: not-allowed;
     color: gray;
 }
-
+.nav_admin {
+    height: auto;
+}
+.nav_admin > div > ul > li {
+    height: 1.2rem;
+    font-weight: inherit;
+}
 .tool-partition {
     height: 0;
-    margin-top: 5px;
-    border-top: 3px solid #777;
+    /*padding-top: 5px;*/
+    /* border-top: 3px solid #777; */
 }
-
 .installable-tool-box {
-    list-style: none;
-    display: flex;
-    background-color: #FFFEFA;
-    flex-wrap: wrap;
-    justify-content: space-around;
-    margin-left: 0;
-    margin-bottom: 8px;
-    margin-top: -8px;
-}
+    /* position: relative; */
+    display: inlin-f;
+    min-height: 289px;
+    align-content: center;
+    border-right: 1px solid #9D9D9D;
+    background-color: yellow;
+    background-image:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
-.installable-tool-box li {
-    margin-top: 15px;
-    height: auto;
-    border-radius: 4px;
-    padding: 10px;
-    text-align: center;
-    font-size: medium;
-    list-style: none;
-    cursor: pointer;
-    border: 1px solid transparent;
-    -webkit-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    -o-user-select: none;
-    user-select: none;
-}
-.selected-tool{
-    background: #09C;
-    color: white;
-}
 
-.installable-tool-box li:hover {
-    background: white;
-    border: 1px solid #09C;
-}
 
-.installable-tool-box li.selected-tool:hover {
-    background: white;
-    color: rgb(85, 85, 85);
-}
 
-.tool-card {
-    width: 600px;
-    display: block;
-    border: 2px solid #4E4E4E;
-    border-radius: 2px 2px 5px 5px;
-    overflow-y: visible;
-    margin-bottom: 50px;
-    background: white;
-    right: 161px;
-    top: 83px;
-    position: absolute;
-    z-index: 1000;
-}
 
-.tool-card::before {
-    content: "▲";
-    color: #4E4E4E;
-    font-size: xx-large;
-    position: absolute;
-    right: 0px;
-    top: -14px;
-    overflow: visible;
-    float: right;
-    height: 1.5rem;
-}
 
-.box-title {
-    z-index: 60;
-    height: auto;
-    font-size: small;
-    text-align: center;
-    padding-bottom: 3px;
-    position: relative;
-    padding-top: 3px;
-    background: #4E4E4E;
-    color: #DEDEDE;
-}
 
-.tool-info {
-    min-height: 15rem;
-    display: block;
-    clear: both;
-}
 
-.tool-info-left p {
-    text-align: center;
-    vertical-align: text-top;
-    padding-top: 0;
-    left: 0;
-    font-size: large;
-    font-weight: 400;
-    margin: 2rem 33px;
-    color: #CCCBC8;
-    padding-bottom: 20px;
-}
 
-.tool-info-left h1 {
-    text-align: center;
-    padding-bottom: 0;
-    vertical-align: text-top;
-    padding-top: 18px;
-    left: 0;
-    font-size: large;
-    background-color: #AEF4FF;
-    color: #5B5B5B;
-    height: 3rem;
-}
 
-.add-tool-button {
-    width: 140px;
-    height: auto;
-    background: white;
-    min-width: 6rem;
-    min-height: 2.6rem;
-    font-size: large;
-    bottom: -0.3rem;
-    right: -30px;
-}
 
-.tool-info-left {
-    background: #636363;
-    width: 60%;
-    height: 260px;
-    left: 0;
-    float: left;
-    top: 0;
-    color: white;
-}
 
-.tool-info-right {
-    width: 40%;
-    float: right;
-    overflow: hidden;
-    position: relative;
-    display: block;
-    top: 0;
-}
 
-.tool-form {
-    display: inline-block;
-    width: 100%;
-    position: absolute;
-    right: 0;
-    top: 0;
-    padding-top: 1rem;
-    height: auto;
-}
 
-#add-tool-form > label{
-    padding: 0;
-    font-size: 13pt;
-    position: absolute;
-    margin-left: 18px;
-}
 
-#add-tool-form > p{
-    font-size: large;
 
-}
 
-#add-tool-form > input {
-    padding-top: 10px;
-    padding-left: 10px;
-    width: 77%;
-    margin: 23px 60px 11px 19px;
-}
 
-#add-tool-form{
-    padding-top: 20px;
-    padding-left: 25px;
-    padding-right: 25px;
-}
 
-.tool-form-fields{
-    clear: both;
-    position: relative;
-    display: flex;
-    flex-direction: row;
-}
 
-#mount_point :invalid{
-    background: #333;
-}
 
-.add-tool-toggle{
-    background: rgba(255, 255, 255, 0.32);
-    clear: both;
-    float: right;
-    color: #B3B3B3;
-    font-weight: 900;
-    margin: 1px;
-    right: 127px;
-    position: absolute;
-    padding: 5px 5px 3px;
-    border: 2px dashed #B3B3B3;
-    top: 18px;
-    width: 5.7rem;
-    border-radius: 4px;
-    height: 1.5rem;
-    cursor: pointer;
-    -webkit-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    -o-user-select: none;
-    user-select: none;
-}
-.add-tool-toggle:hover{
-    background: #F4F4F4;
-    color: #777;
-}
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, #cccccc));
+    background-image:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
+    background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
+    /* flex-wrap: wrap; */
+    flex-direction: column;
+    /* justify-content: flex-start; */
+    justify-content: space-around;
+    padding-bottom: 2.2rem;
+    width: 100%;
+    /* -webkit-flex-direction: row; */
+    /* flex-direction: column; */
+    /*margin-bottom: 8px;*/
+    /* min-height: 280px; */
+}
+.installable-tool-box div {
+    /* margin-top: 0.5rem; */
+    margin-left: 0;
+    /* height: auto; */
+    border-radius: 4px;
+    padding: 10px;
+    text-align: right;
+    font-size: medium;
+    list-style: none;
+    cursor: pointer;
+    /*align-items: flex-start;*/
+    min-width: 10%;
+    border: 1px solid transparent;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+    border-radius: 0 4px 4px 0;
+}
+
+/*.installable-tool-box > div{
+    color:blue;
+    background: rgba(255, 255, 255, 0.8);
+    min-width: 75px;
+    border: 1px dashed orange;
+}*/
+
+.installable-tool-box div:hover {
+    background: white;
+    border: 1px solid rgb(0, 153, 204);
+    border: 1;
+}
+.selected-tool {
+    background: rgba(0, 153, 243, 0.8) !important;
+    color: white !important;
+    box-shadow: 3px 3px 2px #ABABAB !important;
+    font-weight: bold;
+}
+.installable-tool-box div.selected-tool:hover {
+    background: white;
+    color: rgb(85, 85, 85);
+}
+.tool-card {
+    width: 447px;
+    height: 345px;
+    display: block;
+    border: 2px solid #5B5B5B;
+    box-shadow: 7px 5px 21px rgba(68, 68, 68, 0.58);
+    border-radius: 2px 2px 5px 5px;
+    overflow: inherit;
+    margin-bottom: 50px;
+    background: rgb(255, 255, 255);
+    right: 20px;
+    position: absolute;
+    background-image:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #ffffff), color-stop(100%, rgba(233, 233, 233, 0.67)));
+    z-index: 1000;
+    background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
+    -webkit-gradient(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    linear, 0% 0%, 0% 100%,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    color-stop(0%, #ffffff),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    color-stop(100%, #cccccc));
+    background-image:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    -moz-linear-gradient(top, #ffffff 0%, #cccccc 100%);
+    background-image: linear-gradient(top, #ffffff 0%, #cccccc 100%);
+}
+.tool-card::before {
+    content: "â–²";
+    color: #4E4E4E;
+    font-size: xx-large;
+    position: absolute;
+    right: 0px;
+    top: -14px;
+    overflow: visible;
+    float: right;
+    height: 1.5rem;
+}
+.box-title {
+    z-index: 60;
+    height: auto;
+    font-size: small;
+    text-align: center;
+    padding-bottom: 3px;
+    position: relative;
+    /* padding-top: 3px; */
+    background: #4E4E4E;
+    color: #DEDEDE;
+    background-image:
+
+
+
+
+
+
+
+
+    -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #555), color-stop(100%, #666));
+    background-image:
+
+
+
+
+
+
+
+
+    -moz-linear-gradient(top, #666 0%, #555 100%);
+    background-image: linear-gradient(top, #666 0%, #555 100%);
+}
+.tool-info {
+    min-height: 22rem;
+    /* display: block; */
+    width: 72%;
+    float: right;
+    /* clear: both; */
+}
+.tool-info-left p {
+    text-align: center;
+    vertical-align: text-top;
+    padding-top: 0;
+    left: 0;
+    font-size: small;
+    font-kerning: 81;
+    font-weight: 100;
+    min-height: 70px;
+    margin: 1.5rem 23px;
+    margin-top: 0;
+    color: #FFFFFF;
+    padding-bottom: 0px;
+}
+.tool-info-left h1 {
+    text-align: center;
+    padding-bottom: 0;
+    vertical-align: text-top;
+    padding-top: 8px;
+    left: 0;
+    font-size: large;
+    /* background-color: #AEF4FF; */
+    color: #5B5B5B;
+    height: 2.6rem;
+    box-shadow: 3px 2px 5px rgba(34, 34, 34, 0.56);
+}
+.add-tool-button {
+    width: 109px;
+    height: auto;
+    background: white;
+    min-width: 6rem;
+    position: absolute;
+    min-height: 2.1rem;
+    margin-top: 5px;
+    font-size: large;
+    /* bottom: -2.3rem; */
+    overflow: visible;
+    right: 0px;
+    bottom: -29px;
+}
+.tool-info-left {
+    background: rgb(98, 98, 98);
+    /* width: 75%; */
+    position: relative;
+    /* float: right; */
+    /* display: inline-block; */
+    height: auto;
+    /* box-shadow: 0px 1px 5px darkgray; */
+    /* left: 0; */
+    /* border-left: 1px solid #B3B3B3; */
+    /* float: right; */
+    /* top: 0; */
+    color: white;
+}
+.tool-info-right {
+    /* width: 100%; */
+    /* float: right; */
+    /* overflow: hidden; */
+    /* display: inline-grid; */
+    /* flex-direction: column; */
+    /* float: right; */
+    /* position: relative; */
+    /* left: 50px; */
+    /* display: block; */
+    top: 0;
+    /* align-content: center; */
+    height: auto;
+    position: relative;
+    top: -9px;
+}
+.tool-form {
+    display: inline-block;
+    width: 100%;
+    position: absolute;
+    right: 0;
+    top: 0;
+    padding-top: 1rem;
+    /*height: auto;*/
+}
+#add-tool-form > label {
+    /* padding: 0; */
+    font-size: 8pt;
+    /* position: relative; */
+    /* left: -128px; */
+    /* top: 27px; */
+    /* margin-left: 18px; */
+    color: grey;
+}
+#add-tool-form > p {
+    font-size: large;
+}
+#add-tool-form > input {
+    /* padding-top: 10px; */
+    /* padding-left: 10px; */
+    /* position: relative; */
+    /* width: 60%; */
+    /* display: inline-flex; */
+    float: left;
+    /* flex-wrap: wrap; */
+    width: 100px;
+    margin-left: 4px;
+    margin-right: 20px;
+}
+#add-tool-url-preview {
+    font-size: 10pt;
+    position: relative;
+    right: 143px;
+    top: 43px;
+    height: 20px;
+    padding-bottom: 0;
+    margin-bottom: 0;
+}
+#add-tool-form {
+    padding-top: 0;
+    margin-top: 0;
+    display: flex;
+    flex-direction: row;
+    width: 95%;
+    /* align-items: center; */
+    padding-left: 0;
+    /* padding-right: 25px; */
+    /* height: 80px; */
+    align-content: center;
+    /* float: left; */
+}
+.tool-form-fields {
+    clear: both;
+    position: relative;
+    display: flex;
+    flex-direction: row;
+}
+#mount_point:invalid {
+    /* background: #333; */
+}
+.add-tool-toggle {
+    background: rgba(255, 255, 255, 0.32);
+    /* clear: both; */
+    color: #8b8b8b;
+    /* font-weight: bold; */
+    /* margin: 1px; */
+    /*position: relative;*/
+    /* right: 127px; */
+    /* position: absolute; */
+    /*padding: 5px 5px 3px;*/
+    border: 1px dashed #B3B3B3;
+    padding-top: 2px;
+    padding-bottom: 2px;
+    /* top: 18px; */
+    height: 100%;
+    width: 5.7rem;
+    float: right;
+    border-radius: 4px;
+    /*height: 1.5rem;*/
+    cursor: pointer;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+}
+.add-tool-toggle:hover {
+    background: #F4F4F4;
+    color: #777;
+}
+.active-nav-link {
+    font-weight: bolder;
+}
+.menu-appear {
+    opacity: 0.01;
+}
+.example-appear.example-appear-active {
+    opacity: 1;
+    transition: opacity .5s ease-in;
+}
+#installable-items {
+    position: initial;
+    left: 0px;
+    float: left;
+    width: 28%;
+}
+
+.error-box{
+    background: rgba(255, 165, 0, 0.54);
+    color: white;
+    padding: 4px;
+    font-weight: bold;
+    position: absolute;
+    top: 66px;
+    width: 146px;
+    box-shadow: 0px 1px 1px #8E8E8E;
+    /* left: 17px; */
+    border-radius: 4px;
+    font-size: 9pt;
+    float: left;
+}
+#add-tool-url-preview{
+    /* float: right; */
+}
+
+#add-tool-url-preview > p > small {
+    color: grey;
+}
+
+#add-tool-url-preview > p > strong {
+    color: orange;
+}
+
+.add-tool-field{
+    width: 50%;
+    min-height: 137px;
+}


[46/47] allura git commit: [#7919] Refactor and reduce toolbar css

Posted by br...@apache.org.
[#7919] Refactor and reduce toolbar css


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/6075d973
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/6075d973
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/6075d973

Branch: refs/heads/db/7919
Commit: 6075d97352cbf41a62a21512c9a77c795bda2f67
Parents: a666e08
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 26 12:57:23 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Mon Oct 26 12:57:23 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css         | 319 ++++----------------
 Allura/allura/public/nf/js/add-new-tool.es6.js |   2 +-
 Allura/allura/public/nf/js/navbar.es6.js       |   6 +-
 3 files changed, 70 insertions(+), 257 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/6075d973/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index d27b727..097c163 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -1,146 +1,58 @@
-.submenu ul {
-    list-style: none;
-    width: 350px;
-    display: none;
-}
-
-/*.hidden {*/
-/*display: none;*/
-/*}*/
-
-.submenu ul {
-    list-style: none;
-    display: block;
-    position: relative;
-    background-color: rgb(237, 237, 237);
-    border: solid darkgray 1px;
-    border-radius: 0 0 5px 5px;
-    margin-top: -13px;
-    margin-left: 341px;
-    left: -25px;
-    padding-left: 0;
-    box-shadow: 3px 0 3px #d7d7d7;
-    z-index: -1000;
-    padding-top: 11px;
-}
-
 #bar-config {
-    display: inline-flex;
     position: absolute;
     right: 0;
     top: -30px;
-    align-items: stretch;
-    flex: 1 1 auto;
-}
-
-#threshold-config > span > input {
-    width: 2rem;
-    background-color: #A1A1A1;
-    color: white;
-    font-weight: bold;
 }
 
 #toggle-admin-btn {
     position: absolute;
-    right: -9px;
-    top: 0;
-    width: 2rem;
+    right: -11px;
+    top: -1px;
+    width: 1.8rem;
     height: 1.8rem;
 }
 
-nav {
-    display: flex;
-    flex-direction: row;
-    justify-content: center;
-    margin: auto;
-}
-
-#top_nav_admin > div.edit-mode > ul {
-    display: flex;
-    flex-direction: row;
-    flex-wrap: wrap;
-    flex: 1;
-}
-
-#top_nav_admin > div.edit-mode > ul > .tb-item {
-    background-color: #F0F0F0;
-    margin-top: 0.5rem;
-    display: inline-grid;
-    margin-left: .5rem;
-    border: 1px dashed gray;
-    padding: 0.3rem 0.6rem 0.3rem 0.6rem;
-}
-
-.admin-toolbar {
-    display: flex;
+#threshold-config > span > input {
+    width: 2rem;
+    background-color: #F2F2F2;
+    color: #333;
+    font-weight: bold;
 }
 
 #top_nav_admin {
-    display: grid;
-    flex-direction: row;
-    flex-wrap: wrap;
-    -moz-border-radius: 4px;
-    -webkit-border-radius: 4px;
-    -o-border-radius: 4px;
-    -ms-border-radius: 4px;
-    -khtml-border-radius: 4px;
-    border-radius: 4px;
+    overflow: hidden;
+    min-height: 42px;
     width: 918px; /* 940px - 32px for toggle-admin-btn */
 }
 
-#top_nav_admin .edit-mode .fa {
-    margin: 0 3px;
+#admin-toolbar-list{
+    border-bottom: 1px solid transparent;
 }
 
-.btn-bar {
-    display: block;
-    clear: both;
-    padding: 0 10px 0 10px;
-    -moz-border-radius: 4px;
-    -webkit-border-radius: 4px;
-    -o-border-radius: 4px;
-    -ms-border-radius: 4px;
-    -khtml-border-radius: 4px;
-    border-radius: 4px;
-    text-decoration: none;
-    min-width: 1em;
-    text-align: center;
-    position: relative;
-    margin: 0 0 20px;
-}
-
-ul.dropdown li {
-    float: left;
-    vertical-align: middle;
-    zoom: 1;
-    padding-top: 10px;
-    padding-bottom: 10px;
-}
-
-ul.dropdown, ul.dropdown li, ul.dropdown ul {
-    list-style: none;
-    margin: 0;
-    padding: 0;
-}
-
-li.tb-item-edit > input {
-    width: 2.2rem;
+.anchored {
+    cursor: not-allowed;
+    color: gray;
 }
 
 .draggable-handle {
+    margin-left: 2px;
     cursor: move;
 }
 
-ul.dropdown li {
+.react-reorderable-item {
+    display: inline-flex;
     float: left;
-    vertical-align: middle;
-    zoom: 1;
-    padding-top: 10px;
-    padding-bottom: 10px;
 }
 
-#content {
-    width: 990px;
+.react-reorderable-item-active {
+    border: 3px dashed #9e9e9e;
+    background: #c9c9c9;
+    width: 5rem; /* dynamic would be nice */
+    height: 50px;
+}
+
+.react-reorderable-item-active div {
+    display: none;
 }
 
 .react-reorderable-item {
@@ -164,7 +76,9 @@ ul.dropdown li {
 }
 
 #top_nav_admin .tb-item a {
-    margin: 10px;
+    margin: 10px 10px 10px 0;
+    border-right: 1px solid #ccc;
+    padding-right: 10px;
 }
 
 .react-drag {
@@ -175,39 +89,20 @@ ul.dropdown li {
     user-select: none;
 }
 
-ul.dropdown ul {
-    visibility: hidden;
-    position: absolute;
-    top: 70px;
-    z-index: 598;
-    background-color: #ffffff;
-    border: 1px solid #dddddd;
-    border-top-width: 0;
-}
-
-ul.dropdown .hover, ul.dropdown li:hover {
+.btn-bar {
+    display: block;
+    padding: 0 10px 0 10px;
+    -moz-border-radius: 4px;
+    -webkit-border-radius: 4px;
+    -o-border-radius: 4px;
+    -ms-border-radius: 4px;
+    -khtml-border-radius: 4px;
+    border-radius: 4px;
+    text-decoration: none;
+    min-width: 1em;
+    text-align: center;
     position: relative;
-    z-index: 599;
-    cursor: default;
-}
-
-.anchored {
-    cursor: not-allowed;
-    color: gray;
-}
-
-.nav_admin {
-    height: auto;
-}
-
-.nav_admin > div > ul > li {
-    height: 1.2rem;
-    font-weight: inherit;
-}
-
-.tool-partition {
-    height: 0;
-    border-top: 3px solid #777;
+    margin: 0 0 20px;
 }
 
 .installable-tool-box {
@@ -222,19 +117,15 @@ ul.dropdown .hover, ul.dropdown li:hover {
 }
 
 .installable-tool-box div {
-    padding-top: 4px;
     margin-bottom: 0;
     margin-left: 0;
     border-radius: 0 0 4px 4px;
-    padding-left: 5px;
-    padding-bottom: 2px;
-    padding-right: 5px;
+    padding: 4px 5px 2px;
     text-align: center;
     font-size: small;
     font-weight: 400;
     list-style: none;
     cursor: pointer;
-    /*align-items: flex-start;*/
     min-width: 40px;
     border: 1px solid transparent;
     -webkit-user-select: none;
@@ -244,14 +135,7 @@ ul.dropdown .hover, ul.dropdown li:hover {
     user-select: none;
 }
 
-/*.installable-tool-box > div{
-    color:blue;
-    background: rgba(255, 255, 255, 0.8);
-    min-width: 75px;
-    border: 1px dashed orange;
-}*/
-
-.selected-tool {
+.tool-card .selected-tool {
     background: #09C !important;
     color: white !important;
     height: 21px;
@@ -285,7 +169,7 @@ ul.dropdown .hover, ul.dropdown li:hover {
     color: #4E4E4E;
     font-size: xx-large;
     position: absolute;
-    right: 0px;
+    right: 0;
     top: -14px;
     overflow: visible;
     float: right;
@@ -305,9 +189,17 @@ ul.dropdown .hover, ul.dropdown li:hover {
 }
 
 .tool-info {
-    min-height: -15rem;
     display: block;
-    clear: both;
+}
+
+.tool-info-left {
+    background: #636363;
+    width: 60%;
+    height: 206px;
+    left: 0;
+    float: left;
+    top: 0;
+    color: white;
 }
 
 .tool-info-left p {
@@ -317,7 +209,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     left: 0;
     font-size: 11pt;
     font-weight: 400;
-    margin: 2rem 33px;
     color: #F9F9F9;
     padding-bottom: 20px;
     margin: 20px;
@@ -336,74 +227,26 @@ ul.dropdown .hover, ul.dropdown li:hover {
     margin: 0;
 }
 
-.add-tool-button {
-    width: 140px;
-    height: auto;
-    min-height: 1.6rem;
-    font-size: small;
-    bottom: 0.7rem;
-    right: -10px;
-}
-
-.tool-info-left {
-    background: #636363;
-    width: 60%;
-    height: 206px;
-    left: 0;
-    float: left;
-    top: 0;
-    color: white;
-}
-
 .tool-info-right {
     width: 40%;
     float: right;
-    overflow: hidden;
     position: relative;
-    display: block;
     top: 0;
 }
 
-.tool-form {
-    display: inline-block;
-    width: 100%;
-    position: absolute;
-    right: 0;
-    top: 0;
-    padding-top: 1rem;
-    height: auto;
-}
-
-#add-tool-form > label {
-    padding: 0;
-    font-size: 13pt;
-    position: absolute;
-    margin-left: 18px;
-}
-
-#add-tool-form > p {
-    font-size: large;
-
-}
-
-#add-tool-form > input {
-    padding-top: 10px;
-    padding-left: 10px;
-    width: 77%;
-    margin: 23px 60px 11px 19px;
-}
-
 #add-tool-form {
     padding-top: 20px;
     padding-left: 25px;
     padding-right: 25px;
 }
 
-.tool-form-fields {
-    clear: both;
-    position: relative;
-    display: flex;
-    flex-direction: row;
+.add-tool-button {
+    width: 140px;
+    height: auto;
+    min-height: 1.6rem;
+    font-size: small;
+    bottom: 0.7rem;
+    right: -10px;
 }
 
 #mount_point :invalid {
@@ -411,25 +254,12 @@ ul.dropdown .hover, ul.dropdown li:hover {
 }
 
 .add-tool-toggle {
-    background: rgba(255, 255, 255, 0.32);
-    /*clear: both;*/
-    color: #8b8b8b;
-    /*font-weight: bold;*/
-    /*margin: 1px;*/
-    /*position: relative;*/
-
-    /*right: 127px;*/
-    /*position: absolute;*/
-    /*padding: 5px 5px 3px;*/
     border: 1px dashed #B3B3B3;
-    padding-top: 2px;
-    padding-bottom: 2px;
-    /*top: 18px;*/
+    padding: 1px;
     height: 100%;
-    width: 5.7rem;
+    width: 5.1rem;
     float: right;
     border-radius: 4px;
-    /*height: 1.5rem;*/
     cursor: pointer;
     -webkit-user-select: none;
     -moz-user-select: none;
@@ -443,25 +273,6 @@ ul.dropdown .hover, ul.dropdown li:hover {
     color: #777;
 }
 
-.active-nav-link {
-    font-weight: bolder;
-}
-
 .add-tool-field {
     width: 50%;
 }
-
-.error-box {
-    background: rgba(255, 114, 114, 0.65);
-    color: white;
-    padding: 4px;
-    font-weight: 500;
-    position: fixed;
-    top: 289px;
-    width: 175px;
-    box-shadow: 0px 1px 1px #8E8E8E;
-    left: 639px;
-    border-radius: 4px;
-    font-size: 9pt;
-    float: left;
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/6075d973/Allura/allura/public/nf/js/add-new-tool.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/add-new-tool.es6.js b/Allura/allura/public/nf/js/add-new-tool.es6.js
index c9820e9..c5593e8 100644
--- a/Allura/allura/public/nf/js/add-new-tool.es6.js
+++ b/Allura/allura/public/nf/js/add-new-tool.es6.js
@@ -111,7 +111,7 @@ var FormField = React.createClass({
         });
         console.log('result', result);
         return (
-            <div className="error-box">
+            <div className="add-tool-error-box">
                 {result}
             </div>
         );

http://git-wip-us.apache.org/repos/asf/allura/blob/6075d973/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index c547cc8..e860597 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -101,10 +101,11 @@ var NavBarItem = React.createClass({
         } else {
             arrow_classes += ' draggable-handle';
         }
-        controls.push(<i className={arrow_classes}></i>);
+//controls.push(<i className={arrow_classes}></i>);
         return (
             <div className="tb-item tb-item-edit">
-                <a>{this.props.name}<br/>{controls}</a>
+                <a>{controls}
+                    <span className="draggable-handle">{this.props.name}</span></a>
             </div>
         );
     }
@@ -184,6 +185,7 @@ var NormalNavBar = React.createClass({
         var classes = 'dropdown';
         return (
             <ul
+                id="admin-toolbar-list"
                 className={ classes }
                 key={ `toolList-${_.uniqueId()}` }>
                 { listItems }


[26/47] allura git commit: [#7919] Add additional fields to the rest api

Posted by br...@apache.org.
[#7919] Add additional fields to the rest api


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/76a901d1
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/76a901d1
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/76a901d1

Branch: refs/heads/db/7919
Commit: 76a901d1f88d716f9e342305c8110a754c07c3e8
Parents: 9c36397
Author: Heith Seewald <hs...@hsmb.local>
Authored: Wed Oct 7 14:38:40 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 Allura/allura/app.py                  | 24 +++++++++++++++++++++---
 Allura/allura/ext/admin/admin_main.py | 13 ++++++++++++-
 2 files changed, 33 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/76a901d1/Allura/allura/app.py
----------------------------------------------------------------------
diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index 4cc47b1..3096e79 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -190,6 +190,18 @@ class SitemapEntry(object):
         return self.url in request.upath_info or any([
             url in request.upath_info for url in self.matching_urls])
 
+    def __json__(self):
+        return dict(
+            label=self.label,
+            className=self.className,
+            url=self.url,
+            small=self.small,
+            ui_icon=self.ui_icon,
+            children=self.children,
+            tool_name=self.tool_name,
+            matching_urls=self.matching_urls,
+            extra_html_attrs=self.extra_html_attrs,
+        )
 
 class Application(object):
 
@@ -757,9 +769,15 @@ class Application(object):
 
         Returns dict that will be included in project's API under tools key.
         """
-        return {'name': self.config.tool_name,
-                'mount_point': self.config.options.mount_point,
-                'label': self.config.options.mount_label}
+        return {
+            'name': self.config.tool_name,
+            'mount_point': self.config.options.mount_point,
+            'url': self.config.url(),
+            'icons': self.icons,
+            'installable': self.installable,
+            'tool_label': self.tool_label,
+            'mount_label': self.config.options.mount_label
+        }
 
 
 class AdminControllerMixin(object):

http://git-wip-us.apache.org/repos/asf/allura/blob/76a901d1/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index c10926a..e5d819e 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -800,7 +800,18 @@ class ProjectAdminRestController(BaseController):
         """ List of installable tools
         """
         response.content_type = 'application/json'
-        tools = [t['name'] for t in AdminApp.installable_tools_for(c.project)]
+        tools = []
+        for tool in AdminApp.installable_tools_for(c.project):
+            tools.append({
+                'name': tool['name'],
+                'description': " ".join(tool['app'].tool_description.split()),
+                'icons': tool['app'].icons,
+                'defaults': {
+                    'default_options': tool['app'].default_options(),
+                    'default_mount_label': tool['app'].default_mount_label,
+                    'default_mount_point': tool['app'].default_mount_point,
+                }
+            })
 
         return {'tools': tools}
 


[38/47] allura git commit: [#7919] improve the tool descriptions, set missing ones

Posted by br...@apache.org.
[#7919] improve the tool descriptions, set missing ones


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/df770b9a
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/df770b9a
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/df770b9a

Branch: refs/heads/db/7919
Commit: df770b9ad92c6dc1fb7d73c849bd6e3cc2d1d26e
Parents: 827525a
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Oct 16 13:03:20 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 ForgeChat/forgechat/main.py                   | 1 +
 ForgeDiscussion/forgediscussion/forum_main.py | 3 ++-
 ForgeGit/forgegit/git_main.py                 | 5 ++---
 ForgeLink/forgelink/link_main.py              | 4 ++++
 ForgeSVN/forgesvn/svn_main.py                 | 3 ++-
 ForgeTracker/forgetracker/tracker_main.py     | 4 ++--
 6 files changed, 13 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/df770b9a/ForgeChat/forgechat/main.py
----------------------------------------------------------------------
diff --git a/ForgeChat/forgechat/main.py b/ForgeChat/forgechat/main.py
index bdd373a..d8cd841 100644
--- a/ForgeChat/forgechat/main.py
+++ b/ForgeChat/forgechat/main.py
@@ -47,6 +47,7 @@ log = logging.getLogger(__name__)
 class ForgeChatApp(Application):
     __version__ = version.__version__
     tool_label = 'Chat'
+    tool_description = 'IRC chat integration'
     status = 'alpha'
     default_mount_label = 'Chat'
     default_mount_point = 'chat'

http://git-wip-us.apache.org/repos/asf/allura/blob/df770b9a/ForgeDiscussion/forgediscussion/forum_main.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py
index 542b3f0..44885c9 100644
--- a/ForgeDiscussion/forgediscussion/forum_main.py
+++ b/ForgeDiscussion/forgediscussion/forum_main.py
@@ -72,7 +72,8 @@ class ForgeDiscussionApp(Application):
     exportable = True
     tool_label = 'Discussion'
     tool_description = """
-        Collaborate with your community in your forum.
+        Discussion forums are a place to talk about any topics related to your project.
+        You may set up multiple forums within the Discussion tool.
     """
     default_mount_label = 'Discussion'
     default_mount_point = 'discussion'

http://git-wip-us.apache.org/repos/asf/allura/blob/df770b9a/ForgeGit/forgegit/git_main.py
----------------------------------------------------------------------
diff --git a/ForgeGit/forgegit/git_main.py b/ForgeGit/forgegit/git_main.py
index 62fc0f7..050addb 100644
--- a/ForgeGit/forgegit/git_main.py
+++ b/ForgeGit/forgegit/git_main.py
@@ -47,9 +47,8 @@ class ForgeGitApp(RepositoryApp):
     __version__ = version.__version__
     tool_label = 'Git'
     tool_description = """
-        Git is a distributed version control system designed to
-        handle everything from small to very large projects with speed
-        and efficiency.
+        Git is a popular distributed version control system with broad functionality.
+        It is known for its speed, flexibility, and data integrity.
     """
     ordinal = 2
     forkable = True

http://git-wip-us.apache.org/repos/asf/allura/blob/df770b9a/ForgeLink/forgelink/link_main.py
----------------------------------------------------------------------
diff --git a/ForgeLink/forgelink/link_main.py b/ForgeLink/forgelink/link_main.py
index dde7a02..8dc69a2 100644
--- a/ForgeLink/forgelink/link_main.py
+++ b/ForgeLink/forgelink/link_main.py
@@ -44,6 +44,10 @@ class ForgeLinkApp(Application):
 
     '''This is the Link app for PyForge'''
     __version__ = version.__version__
+    tool_description = """
+        A link to a URL of your choice, either on this site or somewhere else.
+        It will appear in your project menu alongside the other project tools.
+    """
     permissions = ['configure', 'read']
     permissions_desc = {
         'read': 'View link.',

http://git-wip-us.apache.org/repos/asf/allura/blob/df770b9a/ForgeSVN/forgesvn/svn_main.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/svn_main.py b/ForgeSVN/forgesvn/svn_main.py
index e87d106..771f930 100644
--- a/ForgeSVN/forgesvn/svn_main.py
+++ b/ForgeSVN/forgesvn/svn_main.py
@@ -61,7 +61,8 @@ class ForgeSVNApp(RepositoryApp):
     })
     tool_label = 'SVN'
     tool_description = """
-        Enterprise-class centralized version control for the masses.
+        Subversion ("svn") is a centralized version control system.  In general, SVN is simpler to use
+        but not as powerful as distributed systems like Git and Mercurial.
     """
     ordinal = 4
     forkable = False

http://git-wip-us.apache.org/repos/asf/allura/blob/df770b9a/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index ad63b74..75dbf13 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -253,8 +253,8 @@ class ForgeTrackerApp(Application):
     searchable = True
     tool_label = 'Tickets'
     tool_description = """
-        Bugs, enhancements, tasks, etc., will help you plan and
-        manage your development.
+        Organize your project's bugs, enhancements, tasks, etc. with a ticket system.
+        You can track and search by status, assignee, milestone, labels, and custom fields.
     """
     default_mount_label = 'Tickets'
     default_mount_point = 'tickets'


[19/47] allura git commit: [#7920] Add configured jshint and jscs

Posted by br...@apache.org.
[#7920] Add configured jshint and jscs


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/832cc30c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/832cc30c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/832cc30c

Branch: refs/heads/db/7919
Commit: 832cc30c8625769c344e799eec2b522727ac6d9b
Parents: db6e685
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:28:03 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 .jscsrc   |  9 +++++++++
 .jshintrc | 14 ++++++++++++++
 2 files changed, 23 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/832cc30c/.jscsrc
----------------------------------------------------------------------
diff --git a/.jscsrc b/.jscsrc
new file mode 100644
index 0000000..0568d39
--- /dev/null
+++ b/.jscsrc
@@ -0,0 +1,9 @@
+{
+  "preset": "airbnb",
+  "requireCamelCaseOrUpperCaseIdentifiers": false,
+  "requireTrailingComma": false,
+  "esprima": "esprima-fb",
+  "fileExtensions": [
+    "es6.js"
+  ]
+}

http://git-wip-us.apache.org/repos/asf/allura/blob/832cc30c/.jshintrc
----------------------------------------------------------------------
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..f4ea9d1
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,14 @@
+{
+    "esnext": true,
+    "globalstrict": true,
+    "latedef": true,
+    "supernew": true,
+    "jquery": true,
+    "globals": {
+        "React": true,
+        "$": true,
+        "window": true,
+        "_": true,
+        "ReactReorderable": true
+    }
+}


[35/47] allura git commit: [#7919] Add react for development mode

Posted by br...@apache.org.
[#7919] Add react for development mode


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/394e8b7b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/394e8b7b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/394e8b7b

Branch: refs/heads/db/7919
Commit: 394e8b7b0303104b04c6a663f575ddf6a831df53
Parents: 7ca6875
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 14:26:41 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/react-with-addons.js | 21642 +++++++++++++++++
 1 file changed, 21642 insertions(+)
----------------------------------------------------------------------



[47/47] allura git commit: [#7919] dedicated broccoli build for navbar.js

Posted by br...@apache.org.
[#7919] dedicated broccoli build for navbar.js


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/d21d71d1
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d21d71d1
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d21d71d1

Branch: refs/heads/db/7919
Commit: d21d71d1c1b95af7b4537acb6e615a82e515850e
Parents: 6075d97
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 26 17:28:55 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Oct 27 17:36:01 2015 -0400

----------------------------------------------------------------------
 Brocfile.js  | 32 +++++++++++++++++++++++++++-----
 package.json |  1 +
 2 files changed, 28 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/d21d71d1/Brocfile.js
----------------------------------------------------------------------
diff --git a/Brocfile.js b/Brocfile.js
index 71a8f90..78731fc 100644
--- a/Brocfile.js
+++ b/Brocfile.js
@@ -20,9 +20,11 @@ var babelTranspiler = require("broccoli-babel-transpiler");
 var sourceMapConcat = require('broccoli-sourcemap-concat');
 var funnel = require('broccoli-funnel');
 var uglifyJavaScript = require('broccoli-uglify-js');
+var mergeTrees = require('broccoli-merge-trees');
 
+/* main output tree */
 var tree = funnel('Allura/allura/public/nf/js', {
-  include: ['*.es6.js'],
+    include: ['*.es6.js'],
 });
 tree = babelTranspiler(tree, {
     browserPolyfill: true,
@@ -30,11 +32,31 @@ tree = babelTranspiler(tree, {
     sourceMaps: 'inline',  // external doesn't work, have to use extract below
     comments: false,
 });
+
+/* exactly what's needed for the navbar, so separate apps may use it too */
+var navbar_deps = funnel('Allura/allura/public/nf/js', {
+    include: ['underscore-min.js',
+              'react-with-addons.js',
+              'react-drag.js',
+              'react-reorderable.js',
+    ],
+});
+navbar = mergeTrees([navbar_deps, tree]);
+navbar = sourceMapConcat(navbar, {
+    // headerFiles & footerFiles used to specify some that must come before or after others
+    headerFiles: ['react-with-addons.js'],
+    inputFiles: ['*.js'],
+    footerFiles: ['add-new-tool.es6.js','navbar.es6.js',],
+    outputFile: '/navbar.js',
+});
+
 tree = sourceMapConcat(tree, {
-  inputFiles: ['**/*'],
-  outputFile: '/transpiled.js'
+    inputFiles: ['**/*'],
+    outputFile: '/transpiled.js'
 });
 
+var output = mergeTrees([tree, navbar]);
+
 if (process.env.BROCCOLI_ENV === 'production') {
     /* can't use this for dev mode, since it drops the sourcemap comment even if we set  output: {comments: true}
      https://github.com/mishoo/UglifyJS2/issues/653
@@ -42,10 +64,10 @@ if (process.env.BROCCOLI_ENV === 'production') {
      https://github.com/mishoo/UglifyJS2/issues/780
      https://github.com/mishoo/UglifyJS2/issues/520
      */
-    tree = uglifyJavaScript(tree, {
+    output = uglifyJavaScript(output, {
         mangle: false,
         compress: false
     });
 }
 
-module.exports = tree;
+module.exports = output;

http://git-wip-us.apache.org/repos/asf/allura/blob/d21d71d1/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index f850f00..47d384e 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
     "broccoli": "^0.16.8",
     "broccoli-babel-transpiler": "^5.4.5",
     "broccoli-funnel": "^0.2.8",
+    "broccoli-merge-trees": "^0.2.3",
     "broccoli-sourcemap-concat": "^2.0.1",
     "broccoli-uglify-js": "^0.1.3"
   }


[09/47] allura git commit: [#7919] Add stylesheet for the admin navbar

Posted by br...@apache.org.
[#7919] Add stylesheet for the admin navbar


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/5486f49b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/5486f49b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/5486f49b

Branch: refs/heads/db/7919
Commit: 5486f49b2682a6a0d112c272ef0d582f5a12dc2d
Parents: ddcee91
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 02:57:13 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:05:13 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css | 228 ++++++++++++++++++++++++++++
 1 file changed, 228 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/5486f49b/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
new file mode 100644
index 0000000..7ddbdac
--- /dev/null
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -0,0 +1,228 @@
+.submenu ul {
+  list-style: none;
+  width: 350px;
+  display: none;
+}
+.hidden {
+  display: none;
+}
+.submenu ul {
+  list-style: none;
+  display: block;
+  position: relative;
+  background-color: rgb(237, 237, 237);
+  border: solid darkgray 1px;
+  border-radius: 0 0 5px 5px;
+  margin-top: -13px;
+  margin-left: 341px;
+  left: -25px;
+  padding-left: 0;
+  box-shadow: 3px 0 3px #d7d7d7;
+  z-index: -1000;
+  padding-top: 11px;
+}
+#bar-config {
+  display: inline-flex;
+  position: absolute;
+  right: 0;
+  top: -30px;
+  align-items: stretch;
+  flex: 1 1 auto;
+}
+#threshold-config > span > input {
+  width: 2rem;
+  background-color: #A1A1A1;
+  color: white;
+  font-weight: bold;
+}
+#toggle-admin-btn {
+  position: absolute;
+  right: -9px;
+  top: 0;
+  width: 2rem;
+  height: 1.8rem;
+}
+nav {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  margin: auto;
+}
+.nav_admin ul {
+  display: flex;
+}
+#top_nav_admin > div.edit-mode > ul {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  flex: 1;
+}
+#top_nav_admin > div.edit-mode > ul > .tb-item {
+  background-color: #F0F0F0;
+  margin-top: 0.5rem;
+  display: inline-grid;
+  margin-left: .5rem;
+  border: 1px dashed gray;
+  padding: 0.3rem 0.6rem 0.3rem 0.6rem;
+}
+.admin-toolbar {
+  display: flex;
+}
+#top_nav_admin {
+  display: grid;
+  flex-direction: row;
+  flex-wrap: wrap;
+  -moz-border-radius: 4px;
+  -webkit-border-radius: 4px;
+  -o-border-radius: 4px;
+  -ms-border-radius: 4px;
+  -khtml-border-radius: 4px;
+  border-radius: 4px;
+  width: 940px;
+}
+.btn-bar {
+  display: block;
+  clear: both;
+  padding: 0 10px 0 10px;
+  -moz-border-radius: 4px;
+  -webkit-border-radius: 4px;
+  -o-border-radius: 4px;
+  -ms-border-radius: 4px;
+  -khtml-border-radius: 4px;
+  border-radius: 4px;
+  text-decoration: none;
+  min-width: 1em;
+  text-align: center;
+  position: relative;
+  margin: 0 0 20px;
+}
+ul.dropdown li {
+  float: left;
+  vertical-align: middle;
+  zoom: 1;
+  padding-top: 10px;
+  padding-bottom: 10px;
+}
+ul.dropdown, ul.dropdown li, ul.dropdown ul {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+li.tb-item-edit > input {
+  width: 2.2rem;
+}
+li.tb-item-edit > label > i {
+  padding-right: 0.7rem;
+  color: grey;
+  font-size: larger;
+  cursor: move;
+}
+div.edit-mode > ul > div.anchored {
+  background: grey;
+}
+div.anchored > li.tb-item-edit > label > i {
+  padding-right: 0.7rem;
+  color: #898c89;
+  font-size: larger;
+  cursor: not-allowed;
+}
+
+.react-reorderable-item-active, .draggable-element {
+  height: 28px;
+  width: 120px;
+  margin-top: 5px;
+}
+.draggable-element {
+  background-color: rgb(255, 255, 255);
+  border: 1px dashed #B5AFAF;
+  min-width: 100%;
+  border-radius: 3px;
+  width: 9rem;
+  height: 30px;
+}
+.draggable-handle {
+  background-color: rgb(126, 125, 125);
+  width: 15%;
+  height: 80%;
+  border-radius: 4px 0 0 4px;
+  margin-top: -2px;
+  margin-left: -2px;
+  z-index: 10000;
+  cursor: move;
+  color: white;
+  padding: 3px 3px 4px;
+  border: 1px solid #575656;
+}
+ul.dropdown li {
+  float: left;
+  vertical-align: middle;
+  zoom: 1;
+  padding-top: 10px;
+  padding-bottom: 10px;
+}
+#content {
+  width: 990px;
+}
+.react-reorderable-item {
+  display: inline-flex;
+  margin-right: 2%;
+  /* float: left; */
+}
+.react-reorderable-item-active {
+  border: 3px dashed #9e9e9e;
+  background: #c9c9c9;
+  width: 9rem;
+}
+.react-reorderable-item-active div {
+  display: none;
+}
+.react-reorderable-handle {
+  position: absolute;
+}
+.react-drag > div > div > div > div > div > a {
+  margin-top: 2px;
+  text-align: center;
+  color: #898989;
+  width: 5rem;
+  /* margin-bottom: 10px; */
+  min-width: 100%;
+  overflow-x: hidden;
+  overflow-wrap: break-word;
+  height: 18px;
+  position: relative;
+}
+.react-drag > div > div > div > div > div {
+  width: 100%;
+  position: relative;
+  right: -40px;
+}
+.react-drag {
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+}
+ul.dropdown ul {
+  visibility: hidden;
+  position: absolute;
+  top: 70px;
+  z-index: 598;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+  border-top-width: 0;
+}
+ul.dropdown ul li a {
+  float: none;
+  display: block;
+  text-align: left;
+  margin-right: 0;
+}
+ul.dropdown .hover, ul.dropdown li:hover {
+  position: relative;
+  z-index: 599;
+  cursor: default;
+}
+.anchored {
+  cursor: not-allowed;
+}


[39/47] allura git commit: [#7919] Split the "add new tool" components into another file

Posted by br...@apache.org.
[#7919] Split the "add new tool" components into another file


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/ce77b8e1
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/ce77b8e1
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/ce77b8e1

Branch: refs/heads/db/7919
Commit: ce77b8e1ffdae4bf5d448b425db0b793d0321589
Parents: dca9169
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 22 15:54:59 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/add-new-tool.es6.js | 347 ++++++++++++++++++++
 1 file changed, 347 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/ce77b8e1/Allura/allura/public/nf/js/add-new-tool.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/add-new-tool.es6.js b/Allura/allura/public/nf/js/add-new-tool.es6.js
new file mode 100644
index 0000000..c9820e9
--- /dev/null
+++ b/Allura/allura/public/nf/js/add-new-tool.es6.js
@@ -0,0 +1,347 @@
+'use strict';
+
+///////////////////////////////////////////////////
+// Components for adding a new tool to a project //
+///////////////////////////////////////////////////
+
+/**
+ * Add new tool button.
+ * @constructor
+ */
+var ToggleAddNewTool = React.createClass({
+    render: function() {
+        let _this = this;
+
+        var content = (() => {
+            if (_this.props.showAddToolMenu) {
+                return (
+                    <div>
+                        <span onClick={ _this.props.handleToggleAddNewTool }
+                              className='add-tool-toggle'> + Add new...</span>
+                        <NewToolMain />
+                    </div>
+                );
+            } else {
+                return (
+                    <span onClick={ _this.props.handleToggleAddNewTool }
+                          className='add-tool-toggle'> + Add new...</span>
+                );
+            }
+        })();
+
+        return (<li>
+                {content}
+            </li>
+        );
+    }
+});
+
+/**
+ * Menu for adding a new tool.
+ * @constructor
+ */
+var NewToolMenu = React.createClass({
+    propTypes: {
+        tools: React.PropTypes.array,
+        onPushAddButton: React.PropTypes.func,
+        onSetActive: React.PropTypes.func,
+        formData: React.PropTypes.object,
+        visible: React.PropTypes.bool
+    },
+
+    render: function() {
+        var _this = this;
+        var showInfo = this.props.active.name !== 'Add a tool';
+        var tools = this.props.tools.map(function(tool, i) {
+            var classes;
+            if (_this.props.active && _this.props.active.tool_label === tool.tool_label) {
+                classes = ' selected-tool';
+            }else {
+                classes = ' ';
+            }
+            return (
+                <div className={classes}
+                    id={'add-new-' + tool.name}
+                    key={`new-tool-btn-${i}`}
+                    onClick={_this.props.handleChangeTool}>
+                    {tool.tool_label}
+                </div>
+            );
+        });
+
+        return (
+            <div className='tool-card'>
+                <div className='box-title'>Add a new ...</div>
+                <div id='installable-items'>
+                    <div className='installable-tool-box'>
+                        {tools}
+                    </div>
+                </div>
+                {showInfo &&
+                <NewToolInfo {...this.props}
+                    name={this.props.active.name}
+                    toolLabel={this.props.active.tool_label}
+                    description={this.props.active.description}
+                    handleAddButton={this.props.handleAddButton}/>
+                }
+            </div>
+        );
+    }
+});
+
+var FormField = React.createClass({
+    propTypes: {
+        id: React.PropTypes.string,
+        handleOnChange: React.PropTypes.func,
+        value: React.PropTypes.func,
+        errors: React.PropTypes.array
+    },
+
+    getErrors: function() {
+        if (!this.props.errors.hasOwnProperty(this.props.id) || this.props.errors[this.props.id].length === 0) {
+            return;
+        }
+
+        let errorList = [].concat(this.props.errors[this.props.id]);
+
+        var result = errorList.map(function(e) {
+            console.log('eeeee', e);
+            console.dir(e);
+            return <span>{e}</span>;
+        });
+        console.log('result', result);
+        return (
+            <div className="error-box">
+                {result}
+            </div>
+        );
+    },
+    render: function () {
+        let errors = this.getErrors();
+        console.log('val e', errors);
+        return (
+            <div className="add-tool-field">
+                <label htmlFor={this.props.id}>{this.props.label}</label>
+                <input required
+                       id={this.props.id}
+                       onBlur={this.props.handleOnBlur}
+                       onChange={this.props.handleOnChange}
+                       value={this.props.value}/>
+
+                {errors}
+            </div>
+
+        );
+    }
+});
+
+var InstallNewToolForm = React.createClass({
+    render: function() {
+        return (
+            <form id='add-tool-form'>
+                <FormField
+                    id="mount_label"
+                    handleOnChange={this.props.handleChangeForm}
+                    handleOnBlur={this.props.toolFormIsValid}
+                    value={this.props.formData.mount_label}
+                    label="Label"
+                    errors={this.props.validationErrors}
+                    />
+
+                <FormField
+                    id="mount_point"
+                    handleOnChange={this.props.handleChangeForm}
+                    handleOnBlur={this.props.toolFormIsValid}
+                    value={this.props.formData.mount_point}
+                    label="Url Path"
+                    errors={this.props.validationErrors}
+                />
+
+                <div id={'add-tool-url-preview'}>
+                    <p>
+                        <small>{_getProjectUrl(false)}/</small>
+                        <strong>{this.props.formData.mount_point}</strong>
+                    </p>
+                </div>
+                <div>
+                <button id='new-tool-submit'
+                        onClick={this.props.handleSubmit}
+                        className='add-tool-button'>
+                    Add Tool
+                </button>
+                </div>
+            </form>
+        );
+    }
+});
+
+var NewToolInfo = React.createClass({
+    propTypes: {
+        name: React.PropTypes.string,
+        description: React.PropTypes.string,
+        handleAddButton: React.PropTypes.func
+    },
+
+    render: function() {
+        var titleStyle = {background: _getToolColor(this.props.toolLabel)};
+        return (
+            <div className='tool-info'>
+                <div className='tool-info-left'>
+                    <h1 style={titleStyle}>{this.props.toolLabel}</h1>
+                    <p>{this.props.description}</p>
+                </div>
+                <div className='tool-info-right'>
+                    <InstallNewToolForm {...this.props} />
+                </div>
+            </div>
+        );
+    }
+});
+
+var installableToolsCache = {};
+function loadTools(id, callback) {
+    if (!installableToolsCache[id]) {
+        installableToolsCache[id] = $.get(_getProjectUrl(true) + '/admin/installable_tools/').promise();
+    }
+    installableToolsCache[id].done(callback);
+}
+
+var NewToolMain = React.createClass({
+    getInitialState: function() {
+        let toolPlaceHolder = {
+            name: 'Add a tool',
+            tool_label: 'Add a tool',
+            description: 'click on one of the tools shown above to add it to your project.'
+        };
+
+        return {
+            visible: false,
+            installableTools: [toolPlaceHolder],
+            active: toolPlaceHolder,
+            errors: {
+                mount_point: [],
+                mount_label: []
+            },
+            new_tool: {
+                mount_point: '',
+                tool_label: '',
+                mount_label: ''
+            }
+        };
+    },
+
+    componentDidMount: function() {
+        let tools = loadTools('tools', function(result) {
+            if (this.isMounted()) {
+                this.setState({
+                    installableTools: result.tools
+                });
+            }
+        }.bind(this));
+    },
+    handleChangeTool: function(e) {
+        console.log("HANDLE CHANGE -->", e.target.textContent);
+        this._setActiveByLabel(e.target.textContent);
+    },
+    _setActiveByLabel: function(tool_label) {
+        var index = this.state.installableTools.findIndex(
+            x => x.tool_label === tool_label
+        );
+        console.log('index for tool_label: ', index);
+        var active = this.state.installableTools[index];
+
+        console.log('new active: ', active);
+
+        var _new_tool = this.state.new_tool;
+        console.log('new _new_tool: ', _new_tool);
+
+        _new_tool.mount_label = active.defaults.default_mount_label;
+        _new_tool.mount_point = '';
+
+        this.setState({
+            active: active,
+            new_tool: _new_tool
+        });
+    },
+
+    handleChangeForm: function(e) {
+            var _new_tool = this.state.new_tool;
+            _new_tool[e.target.id] = e.target.value;
+
+            this.setState({
+                new_tool: _new_tool
+            });
+
+        },
+
+    handleSubmit: function(e) {
+        e.preventDefault();
+        var data = {
+            _session_id: $.cookie('_session_id'),
+            tool: this.state.active.name,
+            mount_label: this.state.new_tool.mount_label,
+            mount_point: this.state.new_tool.mount_point
+        };
+
+        $.ajax({
+            type: 'POST',
+            url: _getProjectUrl() + '/admin/install_tool/',
+            data: data,
+            success: function() {
+                $('#messages')
+                    .notify('Tool created', {
+                        status: 'confirm'
+                    });
+            },
+
+            error: function() {
+                $('#messages')
+                    .notify('Error creating tool.', {
+                        status: 'error'
+                    });
+            }
+        });
+    },
+    toolFormIsValid: function(e) {
+        e.preventDefault();
+        var errors = {
+            mount_point: []
+        };
+
+        if (this.state.new_tool.mount_point.length < 3) {
+            errors.mount_point.push('Mount point must have at least 3 characters.');
+        }
+        let data = {
+            'mount_point': e.target.value,
+            '_session_id': $.cookie('_session_id')
+        };
+
+        let result = $.post(_getProjectUrl() + '/admin/mount_point/', data);
+        if (!result.responseJSON) {
+            errors.mount_point.push('Mount point already exists.');
+        }
+
+        this.setState({errors: errors});
+
+    },
+
+    render: function() {
+        return (
+            <React.addons.CSSTransitionGroup
+                transitionName="menu"
+                transitionEnterTimeout={500}
+                transitionLeaveTimeout={300} >
+                    <NewToolMenu
+                        active={this.state.active}
+                        tools={this.state.installableTools}
+                        formData={this.state.new_tool}
+                        handleChangeTool={this.handleChangeTool}
+                        handleSubmit={this.handleSubmit}
+                        handleChangeForm={this.handleChangeForm}
+                        toolFormIsValid={this.toolFormIsValid}
+                        validationErrors={this.state.errors}
+                        handleAddButton={this.handleAddButton}/>
+            </React.addons.CSSTransitionGroup>
+    );
+    }
+});


[43/47] allura git commit: [#7919] Make _nav.json's keys backwards compatible

Posted by br...@apache.org.
[#7919] Make _nav.json's keys backwards compatible


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a6d53393
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a6d53393
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a6d53393

Branch: refs/heads/db/7919
Commit: a6d53393f71dd2208ec172e46810d9456882d101
Parents: 9497a73
Author: Heith Seewald <hs...@hsmb.local>
Authored: Fri Oct 16 13:28:28 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 Allura/allura/model/project.py           | 2 +-
 Allura/allura/public/nf/js/navbar.es6.js | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a6d53393/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 550f95c..e40f1a5 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -632,7 +632,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             children.append(entry)
 
         return json.dumps(dict(grouping_threshold=grouping_threshold,
-                               children=children,
+                               menu=children,
                                child_count=i))
 
     def grouped_navbar_entries(self):

http://git-wip-us.apache.org/repos/asf/allura/blob/a6d53393/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index ecd0fad..feb1af8 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -713,13 +713,13 @@ var Main = React.createClass({
         var navBarSwitch = (showAdmin) => {
             if (showAdmin) {
                 return (
-                    <AdminNav tools={ _this.state.data.children } data={ _this.state.data } onToolReorder={ _this.onToolReorder }
+                    <AdminNav tools={ _this.state.data.menu } data={ _this.state.data } onToolReorder={ _this.onToolReorder }
                               onUpdateMountOrder={ _this.onUpdateMountOrder } editMode={ _this.state.visible } />
                 );
             } else {
                 return (
                     <div>
-                        <NormalNavBar items={ _this.state.data.children } key={ `normalNav-${_.uniqueId()}` }/>
+                        <NormalNavBar items={ _this.state.data.menu } key={ `normalNav-${_.uniqueId()}` }/>
                         <ToggleAddNewTool handleToggleAddNewTool={this.handleToggleAddNewTool} showMenu={this.state.showAddToolMenu} />
                     </div>
                 )


[28/47] allura git commit: [#7919] Integrate 'Add new tool' menu with admin toolbar

Posted by br...@apache.org.
[#7919] Integrate 'Add new tool' menu with admin toolbar


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/37fad09f
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/37fad09f
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/37fad09f

Branch: refs/heads/db/7919
Commit: 37fad09f067e7904e4a2373996ee41da62926b11
Parents: 29e7bad
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 15 14:56:38 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css   | 195 ++++++++++++++++++--------
 Allura/allura/public/nf/js/navbar.es6.js | 184 ++++++++++++++++++------
 2 files changed, 279 insertions(+), 100 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/37fad09f/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index 8c28509..0dec309 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -79,6 +79,7 @@ nav {
     display: flex;
 }
 
+
 #top_nav_admin {
     display: grid;
     flex-direction: row;
@@ -91,7 +92,6 @@ nav {
     border-radius: 4px;
     width: 940px;
 }
-
 .btn-bar {
     display: block;
     clear: both;
@@ -260,6 +260,10 @@ ul.dropdown .hover, ul.dropdown li:hover {
     cursor: not-allowed;
 }
 
+#add_tool_menu{
+    position: relative;
+}
+
 .tool-partition {
     height: 0;
     margin-top: 5px;
@@ -267,88 +271,116 @@ ul.dropdown .hover, ul.dropdown li:hover {
 }
 
 .installable-tool-box {
+    /* margin: 0 0 15px 50px; */
     list-style: none;
     display: flex;
     background-color: #FFFEFA;
     flex-wrap: wrap;
+    margin-bottom: 0;
+    margin-left: 0;
     justify-content: space-around;
 }
 
 .installable-tool-box li {
-    margin-top: 15px;
-
+    /* margin: 5px 10px 20px 60px; */
+    /* margin-left: 80px; */
+    margin-top: 5px;
+    clear: both;
     height: auto;
     border-radius: 4px;
+    /* vertical-align: middle; */
+    /* padding-bottom:10px; */
     padding: 10px;
     text-align: center;
-    font-size: x-large;
+    font-size: medium;
     list-style: none;
     cursor: pointer;
-}
+        border: 1px solid transparent;
+        -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
 
-.installable-tool-box li:hover {
+}
+.selected-tool{
     background: #09C;
     color: white;
+
 }
 
-.selected-tool {
+.installable-tool-box li:hover {
     background: white;
     border: 1px solid #09C;
 }
 
+
+
 .installable-tool-box li.selected-tool:hover {
     background: white;
     color: rgb(85, 85, 85);
 }
 
-#add_tool_menu{
-    position: relative;
-    z-index: 1000;
-}
-
 .tool-card {
-    width: 800px;
-    /* margin-left: 25px; */
-    background-color: #CB6666;
+    width: 600px;
     display: block;
-    border: 1px solid #777;
+    border: 2px solid #4E4E4E;
     border-radius: 2px 2px 5px 5px;
-    height: auto;
+    overflow-y: visible;
+    margin-bottom: 50px;
+    background: white;
+    right: 22px;
+    top: 94px;
     position: absolute;
-    overflow: auto;
-    right: 0;
-    min-height: 21rem;
-    z-index: inherit;
+    z-index: 1000;
+}
+
+.tool-card::before {
+    content: "▲";/* left point triangle in escaped unicode */
+    color: #4E4E4E;
+    font-size: xx-large;
+    position: absolute;
+    right: 0px;
+    top: -14px;
+    overflow: visible;
+    float: right;
+    /* position: relative; */
+    height: 1.5rem;
 }
 
 .box-title {
-    width: 800px;
+    z-index: 60;
     height: auto;
-    font-size: large;
+    font-size: small;
     text-align: center;
-    padding-bottom: 10px;
-    padding-top: 10px;
-    background: #606060;
-    color: white;
+    padding-bottom: 3px;
+    position: relative;
+    padding-top: 3px;
+    background: #4E4E4E;
+    color: #DEDEDE;
 }
 
 .tool-info {
-    min-height: 12rem;
-    padding: 35px 5px 5px 10px;
+    min-height: 15rem;
+    /* padding: 35px 5px 5px 10px; */
+    /* background-color: #40AFD4; */
     display: block;
+    clear: both;
 }
 
 .tool-info-left p {
     text-align: center;
-    padding-bottom: 0;
     vertical-align: text-top;
-    padding-top: 18px;
-    position: relative;
+    padding-top: 0;
     left: 0;
+    /* text-shadow: 1px 2px 1px  #444; */
     font-size: large;
     font-weight: 400;
-    margin: 2rem 80px 100px 90px;
+    margin: 2rem;
+    margin-left: 33px;
+    margin-right: 33px;
     color: #CCCBC8;
+    padding-bottom: 20px;
 }
 
 .tool-info-left h1 {
@@ -356,46 +388,53 @@ ul.dropdown .hover, ul.dropdown li:hover {
     padding-bottom: 0;
     vertical-align: text-top;
     padding-top: 18px;
-    position: relative;
+    /* text-shadow: 1px 2px 1px #C8C8C8; */
     left: 0;
-    font-size: xx-large;
-    background-color: #E7E7E7;
+    font-size: large;
+    background-color: #AEF4FF;
     color: #5B5B5B;
     height: 3rem;
 }
 
 .add-tool-button {
-    width: auto;
+    width: 140px;
     height: auto;
     background: white;
     min-width: 6rem;
     min-height: 2.6rem;
     font-size: large;
-    clear: both;
-    position: relative;
-    right: -4.8rem;
-    bottom: 0.1rem;
+    bottom: -0.3rem;
+    right: -30px;
 }
 
+
 .tool-info-left {
-    background: #727170;
+    background: #636363;
     width: 60%;
-    height: auto;
+    height: 260px;
     left: 0;
+    float: left;
     top: 0;
     color: white;
-    position: absolute;
 }
 
 .tool-info-right {
-    background: rgba(239, 239, 239, 1);
     width: 40%;
-    height: 100%;
-    right: 0;
+    float: right;
+    overflow: hidden;
+    position: relative;
     display: block;
-    clear: both;
     top: 0;
-    position: absolute;
+}
+
+.tool-info-right form {
+
+    /* display: grid; */
+    /* position: relative; */
+    /* padding-top: 30px; */
+
+
+
 }
 
 .tool-form {
@@ -408,14 +447,14 @@ ul.dropdown .hover, ul.dropdown li:hover {
     height: auto;
 }
 
-#add-tool-form > label {
+#add-tool-form > label{
     padding: 0;
     font-size: 13pt;
     position: absolute;
-    margin-left: 42px;
+    margin-left: 18px;
 }
 
-#add-tool-form > p {
+#add-tool-form > p{
     font-size: large;
 
 }
@@ -423,22 +462,58 @@ ul.dropdown .hover, ul.dropdown li:hover {
 #add-tool-form > input {
     padding-top: 10px;
     padding-left: 10px;
-    width: 63%;
-    margin: 22px 62px 10px 40px;
+    width: 77%;
+    margin: 23px 60px 11px 19px;
 }
 
-#add-tool-form {
-    position: absolute;
-    left: auto;
+#add-tool-form{
     padding-top: 20px;
+    /* clear: both; */
     padding-left: 25px;
-    display: block;
+    /* width: 20%; */
+    /* display: block; */
     padding-right: 25px;
 }
 
-.tool-form-fields {
+.tool-form-fields{
     clear: both;
     position: relative;
     display: flex;
     flex-direction: row;
-}
\ No newline at end of file
+}
+
+#mount_point :invalid{
+    background: #333;
+}
+
+.add-tool-toggle{
+    background: rgba(255, 255, 255, 0.32);
+    clear: both;
+    float: right;
+    /* font-size: x-large; */
+    color: #777;
+    font-weight: 900;
+    /* position: absolute; */
+    padding: 3px;
+    margin: 1px;
+    padding-top: 5px;
+    right: 127px;
+    position: absolute;
+    padding-left: 5px;
+    padding-right: 5px;
+    border: 2px dashed #777;
+    top: 18px;
+    width: 5.7rem;
+    border-radius: 4px;
+    height: 1.5rem;
+    cursor: pointer;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+}
+.add-tool-toggle:hover{
+    background: #F4F4F4;
+}
+

http://git-wip-us.apache.org/repos/asf/allura/blob/37fad09f/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index a5ece5b..8aae568 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -13,6 +13,16 @@ function _getProjectUrl(rest = true) {
     return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`;
 }
 
+function slugify(text)
+{
+  return text.toString().toLowerCase()
+    .replace(/\s+/g, '-')           // Replace spaces with -
+    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
+    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
+    .replace(/^-+/, '')             // Trim - from start of text
+    .replace(/-+$/, '');            // Trim - from end of text
+}
+
 /**
  * Get a tool label from a NavBarItem node.
  * @constructor
@@ -294,6 +304,26 @@ var ToggleAdminButton = React.createClass({
     }
 });
 
+/**
+ * Add new tool button.
+ * @constructor
+ */
+var ToggleAddNewTool = React.createClass({
+    render: function () {
+        var classes = this.props.visible ? 'fa fa-unlock' : 'fa fa-lock';
+        return (
+            <div>
+                <div onClick={ this.props.handleToggleAddNewTool } className="add-tool-toggle">
+                    + Add new...
+                </div>
+                                {this.props.showMenu &&
+                <NewToolMain />
+                }
+            </div>
+        );
+    }
+});
+
 //////////////////
 // Add New Tool //
 //////////////////
@@ -324,6 +354,7 @@ var NewToolMenu = React.createClass({
 
     render: function () {
         var _this = this;
+        var showInfo = this.props.active.name !== "Add a tool";
 
         var tools = this.props.tools.map(function (tool, i) {
             var classes;
@@ -338,25 +369,27 @@ var NewToolMenu = React.createClass({
                     id={"add-new-" + tool.name}
                     key={`new-tool-btn-${i}`}
                     onClick={_this.props.handleChangeTool}>
-                    {tool.name}
+                    {tool.tool_label}
                 </li>
             )
         });
 
         return (
             <div className="tool-card">
-                <div className="box-title">Add a new tool
-                </div>
+                <div className="box-title">Add a new ...</div>
                 <div id="installable-items">
                     <ul className="installable-tool-box">
                         {tools}
                     </ul>
                 </div>
                 <div className="tool-partition"></div>
+
+                {showInfo &&
                 <NewToolInfo {...this.props}
-                    name={this.props.active.name}
+                    name={this.props.active.tool_label}
                     description={this.props.active.description}
                     handleAddButton={this.props.handleAddButton}/>
+                }
             </div>
         );
     }
@@ -364,31 +397,33 @@ var NewToolMenu = React.createClass({
 
 var InstallNewToolForm = React.createClass({
     render: function () {
-        console.log(this.props.active.name);
-        if (this.props.active.name === "Add a tool"){
+        //console.log(this.props.active.name);
 
-            return(<div></div>);
-        }
-        var default_mount_point = this.props.active.defaults.default_mount_point;
-        var default_mount_label = this.props.active.defaults.default_mount_label;
+        //var default_mount_label = this.props.active.defaults.default_mount_label;
 
         return (
             <form id="add-tool-form">
                 <label htmlFor="mount_label">Label</label>
-                <input id="mount_label" onChange={this.props.handleChangeForm} value={default_mount_label} />
+                <input required
+                       id="mount_label"
+                       onChange={this.props.handleChangeForm}
+                       value={this.props.formData.mount_label} />
 
                 <label htmlFor="mount_point">Url Path</label>
-                <input id="mount_point"
+                <input required
+                       id="mount_point"
                        onChange={this.props.handleChangeForm}
-                       onBlur={this.props.validateMountPoint}
+                       onBlur={this.props.toolFormIsValid}
+                       placeholder={slugify(this.props.formData.mount_label)}
                        value={this.props.formData.mount_point}/>
+                <span>{this.props.validationErrors.mount_point}</span>
 
                 <p style={{"color": "grey"}}><small>http://hs/p/finna/</small><strong style={{"color": "orange"}}>
                     {this.props.formData.mount_point}
                 </strong></p>
 
                 <button id="new-tool-submit"
-                        onClick={this.props.handleAddButton}
+                        onClick={this.props.handleSubmit}
                         className="add-tool-button">
                     Add Tool
                 </button>
@@ -425,14 +460,21 @@ var NewToolMain = React.createClass({
     getInitialState: function () {
         let toolPlaceHolder = {
             name: "Add a tool",
+            tool_label: "Add a tool",
             description: "click on one of the tools shown above to add it to your project."
         };
 
         return {
+            visible: false,
             installableTools: [toolPlaceHolder],
             active: toolPlaceHolder,
+            errors: {
+                mount_point: [],
+                mount_label: []
+            },
             new_tool: {
                 mount_point: "",
+                tool_label: "",
                 mount_label: ""
             }
         };
@@ -453,9 +495,8 @@ var NewToolMain = React.createClass({
     },
     handleAddButton: function (e) {
         e.preventDefault();
-        console.log('Add new too button pushed');
-        console.log('e.target.name', e);
-        console.log(e.target.textContent);
+        console.log('current active tool', this.state.active);
+        console.log('new_tool', this.state.new_tool);
 
     },
     handleChangeTool: function (e) {
@@ -463,12 +504,19 @@ var NewToolMain = React.createClass({
         this._setActiveByName(e.target.textContent);
 
     },
-    _setActiveByName: function (name) {
+    _setActiveByName: function (tool_label) {
         var index = this.state.installableTools.findIndex(
-            x => x.name === name
+            x => x.tool_label === tool_label
         );
+        var active = this.state.installableTools[index];
+        var _new_tool = this.state.new_tool;
+
+        _new_tool['mount_label'] = active.defaults.default_mount_label;
+        _new_tool['mount_point'] = "";
+
         this.setState({
-            active: this.state.installableTools[index]
+            active: active,
+            new_tool: _new_tool
         });
     },
 
@@ -486,40 +534,74 @@ var NewToolMain = React.createClass({
     },
     handleSubmit: function (e) {
         e.preventDefault();
-        var nextItems = this.state.items.concat([this.state.text]);
-        var nextText = '';
-        this.setState({items: nextItems, text: nextText});
+        var data = {
+            _session_id: $.cookie('_session_id'),
+            tool: this.state.active.name,
+            mount_label: this.state.new_tool.mount_label,
+            mount_point: this.state.new_tool.mount_point
+        };
+
+        var url = _getProjectUrl() + "/admin/install_tool/";
+
+         $.ajax({
+            type: 'POST',
+            url: url,
+            data: data,
+            success: function () {
+                $('#messages').notify('Tool created',
+                    {
+                        status: 'confirm'
+                    });
+            },
+
+            error: function () {
+                $('#messages').notify('Error creating tool.',
+                    {
+                        status: 'error'
+                    });
+            }
+        });
+
     },
 
-    validateMountPoint: function (e) {
+    toolFormIsValid: function (e) {
         e.preventDefault();
-        let url = _getProjectUrl(true) + '/admin/mount_point/';
+
+        var isValid = true;
+        var errors = {
+            mount_point: []
+        };
+
+        if (this.state.new_tool.mount_point.length < 3) {
+            errors.mount_point.push("Mount point must have at least 3 characters.");
+        }
 
         let data = {
             'mount_point': e.target.value,
             '_session_id': $.cookie('_session_id')
         };
 
-        let d = $.post(url, data).done(function (result) {
-            console.log(result);
-        });
+        let result = $.post(_getProjectUrl() + '/admin/mount_point/', data);
+            if (!result.responseJSON) {
+                console.log("ALREADY EXISTS", result);
+                errors.mount_point.push("Mount point already exists.");
+            }
 
-        if(d.responseJSON.exists){
-            alert('exists');
-        }else{
-            alert('does not exist');
-        }
+        this.setState({errors: errors})
 
     },
 
     render: function () {
+        //var visible =
         return <NewToolMenu
             active={this.state.active}
             tools={this.state.installableTools}
             formData={this.state.new_tool}
             handleChangeTool={this.handleChangeTool}
+            handleSubmit={this.handleSubmit}
             handleChangeForm={this.handleChangeForm}
-            validateMountPoint={this.validateMountPoint}
+            toolFormIsValid={this.toolFormIsValid}
+            validationErrors={this.state.errors}
             handleAddButton={this.handleAddButton}/>;
     }
 });
@@ -541,6 +623,7 @@ var Main = React.createClass({
         return {
             data: this.props.initialData,
             visible: false,
+            showAddToolMenu: false,
             _session_id: $.cookie('_session_id')
         };
     },
@@ -569,6 +652,15 @@ var Main = React.createClass({
     },
 
     /**
+     * Handles the the display of the "Add new tool" menu.
+     */
+    handleToggleAddNewTool: function () {
+        this.setState({
+            showAddToolMenu: !this.state.showAddToolMenu
+        });
+    },
+
+    /**
      * Handles the changing of the NavBars grouping threshold.
      * @param {object} event
      */
@@ -651,12 +743,24 @@ var Main = React.createClass({
         var navBarSwitch = (showAdmin) => {
             if (showAdmin) {
                 return (
-                    <AdminNav tools={ _this.state.data.children } data={ _this.state.data } onToolReorder={ _this.onToolReorder }
-                              onUpdateMountOrder={ _this.onUpdateMountOrder } editMode={ _this.state.visible }
+                    <AdminNav tools={ _this.state.data.children }
+                              data={ _this.state.data }
+                              onToolReorder={ _this.onToolReorder }
+                              onUpdateMountOrder={ _this.onUpdateMountOrder }
+                              editMode={ _this.state.visible }
                         />
                 );
             } else {
-                return <NormalNavBar items={ _this.state.data.children } key={ `normalNav-${_.uniqueId()}` }/>;
+                return (
+                    <div>
+                        <NormalNavBar items={ _this.state.data.children } key={ `normalNav-${_.uniqueId()}` }/>
+
+                        <ToggleAddNewTool
+                            handleToggleAddNewTool={this.handleToggleAddNewTool}
+                            showMenu={this.state.showAddToolMenu}
+                            />
+                    </div>
+                )
             }
         };
         var navBar = navBarSwitch(this.state.visible);
@@ -673,6 +777,6 @@ var Main = React.createClass({
         );
     }
 });
-
-   React.render(React.createElement(NewToolMain, {
-        }), document.getElementById("add_tool_menu"));
\ No newline at end of file
+   //
+   //React.render(React.createElement(NewToolMain, {
+   //     }), document.getElementById("add_tool_menu"));
\ No newline at end of file


[24/47] allura git commit: [#7919] Add NavBar dependencies

Posted by br...@apache.org.
[#7919] Add NavBar dependencies


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/db6e6859
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/db6e6859
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/db6e6859

Branch: refs/heads/db/7919
Commit: db6e685998a1f6da7be88498c4817c3c26cc4404
Parents: ddfd67b
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:23:08 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/browser-polyfill.js  | 4228 ++++++++++++++++++
 Allura/allura/public/nf/js/react-drag.js        |  557 +++
 Allura/allura/public/nf/js/react-reorderable.js |  316 ++
 .../public/nf/js/react-with-addons.min.js       |   18 +
 Allura/allura/public/nf/js/underscore-min.js    |    6 +
 5 files changed, 5125 insertions(+)
----------------------------------------------------------------------



[32/47] allura git commit: [#7919] Add styles for the "add new tool" menu

Posted by br...@apache.org.
[#7919] Add styles for the "add new tool" menu


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/437f4655
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/437f4655
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/437f4655

Branch: refs/heads/db/7919
Commit: 437f4655e376bb7b8d8e4f549f5219c98102e474
Parents: 77421ff
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:45:43 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css | 524 +++++++++++++++++++---------
 1 file changed, 367 insertions(+), 157 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/437f4655/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index 7ddbdac..a5d24bc 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -1,228 +1,438 @@
 .submenu ul {
-  list-style: none;
-  width: 350px;
-  display: none;
+    list-style: none;
+    width: 350px;
+    display: none;
 }
+
 .hidden {
-  display: none;
+    display: none;
 }
+
 .submenu ul {
-  list-style: none;
-  display: block;
-  position: relative;
-  background-color: rgb(237, 237, 237);
-  border: solid darkgray 1px;
-  border-radius: 0 0 5px 5px;
-  margin-top: -13px;
-  margin-left: 341px;
-  left: -25px;
-  padding-left: 0;
-  box-shadow: 3px 0 3px #d7d7d7;
-  z-index: -1000;
-  padding-top: 11px;
+    list-style: none;
+    display: block;
+    position: relative;
+    background-color: rgb(237, 237, 237);
+    border: solid darkgray 1px;
+    border-radius: 0 0 5px 5px;
+    margin-top: -13px;
+    margin-left: 341px;
+    left: -25px;
+    padding-left: 0;
+    box-shadow: 3px 0 3px #d7d7d7;
+    z-index: -1000;
+    padding-top: 11px;
 }
+
 #bar-config {
-  display: inline-flex;
-  position: absolute;
-  right: 0;
-  top: -30px;
-  align-items: stretch;
-  flex: 1 1 auto;
+    display: inline-flex;
+    position: absolute;
+    right: 0;
+    top: -30px;
+    align-items: stretch;
+    flex: 1 1 auto;
 }
+
 #threshold-config > span > input {
-  width: 2rem;
-  background-color: #A1A1A1;
-  color: white;
-  font-weight: bold;
+    width: 2rem;
+    background-color: #A1A1A1;
+    color: white;
+    font-weight: bold;
 }
+
 #toggle-admin-btn {
-  position: absolute;
-  right: -9px;
-  top: 0;
-  width: 2rem;
-  height: 1.8rem;
+    position: absolute;
+    right: -9px;
+    top: 0;
+    width: 2rem;
+    height: 1.8rem;
 }
+
 nav {
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  margin: auto;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    margin: auto;
 }
+
 .nav_admin ul {
-  display: flex;
+    display: flex;
 }
+
 #top_nav_admin > div.edit-mode > ul {
-  display: flex;
-  flex-direction: row;
-  flex-wrap: wrap;
-  flex: 1;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    flex: 1;
 }
+
 #top_nav_admin > div.edit-mode > ul > .tb-item {
-  background-color: #F0F0F0;
-  margin-top: 0.5rem;
-  display: inline-grid;
-  margin-left: .5rem;
-  border: 1px dashed gray;
-  padding: 0.3rem 0.6rem 0.3rem 0.6rem;
+    background-color: #F0F0F0;
+    margin-top: 0.5rem;
+    display: inline-grid;
+    margin-left: .5rem;
+    border: 1px dashed gray;
+    padding: 0.3rem 0.6rem 0.3rem 0.6rem;
 }
+
 .admin-toolbar {
-  display: flex;
+    display: flex;
 }
+
 #top_nav_admin {
-  display: grid;
-  flex-direction: row;
-  flex-wrap: wrap;
-  -moz-border-radius: 4px;
-  -webkit-border-radius: 4px;
-  -o-border-radius: 4px;
-  -ms-border-radius: 4px;
-  -khtml-border-radius: 4px;
-  border-radius: 4px;
-  width: 940px;
+    display: grid;
+    flex-direction: row;
+    flex-wrap: wrap;
+    -moz-border-radius: 4px;
+    -webkit-border-radius: 4px;
+    -o-border-radius: 4px;
+    -ms-border-radius: 4px;
+    -khtml-border-radius: 4px;
+    border-radius: 4px;
+    width: 940px;
 }
+
 .btn-bar {
-  display: block;
-  clear: both;
-  padding: 0 10px 0 10px;
-  -moz-border-radius: 4px;
-  -webkit-border-radius: 4px;
-  -o-border-radius: 4px;
-  -ms-border-radius: 4px;
-  -khtml-border-radius: 4px;
-  border-radius: 4px;
-  text-decoration: none;
-  min-width: 1em;
-  text-align: center;
-  position: relative;
-  margin: 0 0 20px;
+    display: block;
+    clear: both;
+    padding: 0 10px 0 10px;
+    -moz-border-radius: 4px;
+    -webkit-border-radius: 4px;
+    -o-border-radius: 4px;
+    -ms-border-radius: 4px;
+    -khtml-border-radius: 4px;
+    border-radius: 4px;
+    text-decoration: none;
+    min-width: 1em;
+    text-align: center;
+    position: relative;
+    margin: 0 0 20px;
 }
+
 ul.dropdown li {
-  float: left;
-  vertical-align: middle;
-  zoom: 1;
-  padding-top: 10px;
-  padding-bottom: 10px;
+    float: left;
+    vertical-align: middle;
+    zoom: 1;
+    padding-top: 10px;
+    padding-bottom: 10px;
 }
+
 ul.dropdown, ul.dropdown li, ul.dropdown ul {
-  list-style: none;
-  margin: 0;
-  padding: 0;
+    list-style: none;
+    margin: 0;
+    padding: 0;
 }
+
 li.tb-item-edit > input {
-  width: 2.2rem;
+    width: 2.2rem;
 }
+
 li.tb-item-edit > label > i {
-  padding-right: 0.7rem;
-  color: grey;
-  font-size: larger;
-  cursor: move;
+    padding-right: 0.7rem;
+    color: grey;
+    font-size: larger;
+    cursor: move;
 }
+
 div.edit-mode > ul > div.anchored {
-  background: grey;
+    background: grey;
 }
+
 div.anchored > li.tb-item-edit > label > i {
-  padding-right: 0.7rem;
-  color: #898c89;
-  font-size: larger;
-  cursor: not-allowed;
+    padding-right: 0.7rem;
+    color: #898c89;
+    font-size: larger;
+    cursor: not-allowed;
 }
 
 .react-reorderable-item-active, .draggable-element {
-  height: 28px;
-  width: 120px;
-  margin-top: 5px;
+    height: 28px;
+    width: 120px;
+    margin-top: 5px;
 }
+
 .draggable-element {
-  background-color: rgb(255, 255, 255);
-  border: 1px dashed #B5AFAF;
-  min-width: 100%;
-  border-radius: 3px;
-  width: 9rem;
-  height: 30px;
+    background-color: rgb(255, 255, 255);
+    border: 1px dashed #B5AFAF;
+    min-width: 100%;
+    border-radius: 3px;
+    width: 9rem;
+    height: 30px;
 }
+
 .draggable-handle {
-  background-color: rgb(126, 125, 125);
-  width: 15%;
-  height: 80%;
-  border-radius: 4px 0 0 4px;
-  margin-top: -2px;
-  margin-left: -2px;
-  z-index: 10000;
-  cursor: move;
-  color: white;
-  padding: 3px 3px 4px;
-  border: 1px solid #575656;
+    background-color: rgb(126, 125, 125);
+    width: 15%;
+    height: 80%;
+    border-radius: 4px 0 0 4px;
+    margin-top: -2px;
+    margin-left: -2px;
+    z-index: 10000;
+    cursor: move;
+    color: white;
+    padding: 3px 3px 4px;
+    border: 1px solid #575656;
 }
+
 ul.dropdown li {
-  float: left;
-  vertical-align: middle;
-  zoom: 1;
-  padding-top: 10px;
-  padding-bottom: 10px;
+    float: left;
+    vertical-align: middle;
+    zoom: 1;
+    padding-top: 10px;
+    padding-bottom: 10px;
 }
+
 #content {
-  width: 990px;
+    width: 990px;
 }
+
 .react-reorderable-item {
-  display: inline-flex;
-  margin-right: 2%;
-  /* float: left; */
+    display: inline-flex;
+    margin-right: 2%;
+    /* float: left; */
 }
+
 .react-reorderable-item-active {
-  border: 3px dashed #9e9e9e;
-  background: #c9c9c9;
-  width: 9rem;
+    border: 3px dashed #9e9e9e;
+    background: #c9c9c9;
+    width: 9rem;
 }
+
 .react-reorderable-item-active div {
-  display: none;
+    display: none;
 }
+
 .react-reorderable-handle {
-  position: absolute;
+    position: absolute;
 }
+
 .react-drag > div > div > div > div > div > a {
-  margin-top: 2px;
-  text-align: center;
-  color: #898989;
-  width: 5rem;
-  /* margin-bottom: 10px; */
-  min-width: 100%;
-  overflow-x: hidden;
-  overflow-wrap: break-word;
-  height: 18px;
-  position: relative;
+    margin-top: 2px;
+    text-align: center;
+    color: #898989;
+    width: 5rem;
+    /* margin-bottom: 10px; */
+    min-width: 100%;
+    overflow-x: hidden;
+    overflow-wrap: break-word;
+    height: 18px;
+    position: relative;
 }
+
 .react-drag > div > div > div > div > div {
-  width: 100%;
-  position: relative;
-  right: -40px;
+    width: 100%;
+    position: relative;
+    right: -40px;
 }
+
 .react-drag {
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  -o-user-select: none;
-  user-select: none;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
 }
+
 ul.dropdown ul {
-  visibility: hidden;
-  position: absolute;
-  top: 70px;
-  z-index: 598;
-  background-color: #ffffff;
-  border: 1px solid #dddddd;
-  border-top-width: 0;
+    visibility: hidden;
+    position: absolute;
+    top: 70px;
+    z-index: 598;
+    background-color: #ffffff;
+    border: 1px solid #dddddd;
+    border-top-width: 0;
 }
+
 ul.dropdown ul li a {
-  float: none;
-  display: block;
-  text-align: left;
-  margin-right: 0;
+    float: none;
+    display: block;
+    text-align: left;
+    margin-right: 0;
 }
+
 ul.dropdown .hover, ul.dropdown li:hover {
-  position: relative;
-  z-index: 599;
-  cursor: default;
+    position: relative;
+    z-index: 599;
+    cursor: default;
 }
+
 .anchored {
-  cursor: not-allowed;
+    cursor: not-allowed;
+}
+
+.tool-partition {
+    height: 0;
+    margin-top: 5px;
+    border-top: 3px solid #777;
+}
+
+.installable-tool-box {
+    list-style: none;
+    display: flex;
+    background-color: #FFFEFA;
+    flex-wrap: wrap;
+    justify-content: space-around;
 }
+
+.installable-tool-box li {
+    margin-top: 15px;
+
+    height: auto;
+    border-radius: 4px;
+    padding: 10px;
+    text-align: center;
+    font-size: x-large;
+    list-style: none;
+    cursor: pointer;
+}
+
+.installable-tool-box li:hover {
+    background: #09C;
+    color: white;
+}
+
+.selected-tool {
+    background: white;
+    border: 1px solid #09C;
+}
+
+.installable-tool-box li.selected-tool:hover {
+    background: white;
+    color: rgb(85, 85, 85);
+}
+
+.tool-card {
+    width: 800px;
+    margin-left: 25px;
+    background-color: white;
+    display: block;
+    border: 1px solid #777;
+    border-radius: 2px 2px 5px 5px;
+    height: auto;
+    position: absolute;
+    overflow: auto;
+    right: 0;
+    min-height: 21rem;
+}
+
+.box-title {
+    width: 800px;
+    height: auto;
+    font-size: large;
+    text-align: center;
+    padding-bottom: 10px;
+    padding-top: 10px;
+    background: #606060;
+    color: white;
+}
+
+.tool-info {
+    min-height: 12rem;
+    padding: 35px 5px 5px 10px;
+    display: block;
+}
+
+.tool-info-left p {
+    text-align: center;
+    padding-bottom: 0;
+    vertical-align: text-top;
+    padding-top: 18px;
+    position: relative;
+    left: 0;
+    font-size: large;
+    font-weight: 400;
+    margin: 2rem 80px 100px 90px;
+    color: #CCCBC8;
+}
+
+.tool-info-left h1 {
+    text-align: center;
+    padding-bottom: 0;
+    vertical-align: text-top;
+    padding-top: 18px;
+    position: relative;
+    left: 0;
+    font-size: xx-large;
+    background-color: #E7E7E7;
+    color: #5B5B5B;
+    height: 3rem;
+}
+
+.add-tool-button {
+    width: auto;
+    height: auto;
+    background: white;
+    min-width: 6rem;
+    min-height: 2.6rem;
+    font-size: large;
+    clear: both;
+    position: relative;
+    right: -4.8rem;
+    bottom: 0.1rem;
+}
+
+.tool-info-left {
+    background: #727170;
+    width: 60%;
+    height: auto;
+    left: 0;
+    top: 0;
+    color: white;
+    position: absolute;
+}
+
+.tool-info-right {
+    background: rgba(239, 239, 239, .7);
+    width: 40%;
+    height: 100%;
+    right: 0;
+    display: block;
+    clear: both;
+    top: 0;
+    position: absolute;
+}
+
+.tool-form {
+    display: inline-block;
+    width: 100%;
+    position: absolute;
+    right: 0;
+    top: 0;
+    padding-top: 1rem;
+    height: auto;
+}
+
+#add-tool-form > label {
+    padding: 0;
+    font-size: 13pt;
+    position: absolute;
+    margin-left: 42px;
+}
+
+#add-tool-form > p {
+    font-size: large;
+
+}
+
+#add-tool-form > input {
+    padding-top: 10px;
+    padding-left: 10px;
+    width: 63%;
+    margin: 22px 62px 10px 40px;
+}
+
+#add-tool-form {
+    position: absolute;
+    left: auto;
+    padding-top: 20px;
+    padding-left: 25px;
+    display: block;
+    padding-right: 25px;
+}
+
+.tool-form-fields {
+    clear: both;
+    position: relative;
+    display: flex;
+    flex-direction: row;
+}
\ No newline at end of file


[18/47] allura git commit: [#7920] Format navbar to pass eslint inspection

Posted by br...@apache.org.
[#7920] Format navbar to pass eslint inspection


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/d2c26d53
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d2c26d53
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d2c26d53

Branch: refs/heads/db/7919
Commit: d2c26d53e2301f6833b461df8c370be32b35141f
Parents: 832cc30
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 12:10:25 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:02 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/navbar.es6.js | 673 +++++++++++++-------------
 1 file changed, 340 insertions(+), 333 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/d2c26d53/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index eac0e91..9cdb907 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -8,9 +8,9 @@
  * @returns {string}
  */
 function _getProjectUrl(rest = true) {
-  var [nbhd, proj] = window.location.pathname.split('/').slice(1, 3);
-  var base = `${window.location.protocol}//${window.location.host}`;
-  return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`;
+    var [nbhd, proj] = window.location.pathname.split('/').slice(1, 3);
+    var base = `${window.location.protocol}//${window.location.host}`;
+    return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`;
 }
 
 /**
@@ -20,24 +20,24 @@ function _getProjectUrl(rest = true) {
  * @returns {string}
  */
 function getLabel(node) {
-  return node.props.children.props.children.props.name;
+    return node.props.children.props.children.props.name;
 }
 
 var ToolsPropType = {
-  name: React.PropTypes.string.isRequired,
-  url: React.PropTypes.string.isRequired,
-  isSubmenu: React.PropTypes.bool,
-  tools: React.PropTypes.arrayOf(
-    React.PropTypes.shape({
-      ordinal: React.PropTypes.number,
-      mount_point: React.PropTypes.string,
-      name: React.PropTypes.string,
-      url: React.PropTypes.string,
-      is_anchored: React.PropTypes.bool,
-      tool_name: React.PropTypes.string,
-      icon: React.PropTypes.string
-    })
-  ).isRequired
+    name: React.PropTypes.string.isRequired,
+    url: React.PropTypes.string.isRequired,
+    isSubmenu: React.PropTypes.bool,
+    tools: React.PropTypes.arrayOf(
+        React.PropTypes.shape({
+            ordinal: React.PropTypes.number,
+            mount_point: React.PropTypes.string,
+            name: React.PropTypes.string,
+            url: React.PropTypes.string,
+            is_anchored: React.PropTypes.bool,
+            tool_name: React.PropTypes.string,
+            icon: React.PropTypes.string
+        })
+    ).isRequired
 };
 
 /**
@@ -45,20 +45,20 @@ var ToolsPropType = {
  * @constructor
  */
 var NavLink = React.createClass({
-  propTypes: {
-    name: React.PropTypes.string.isRequired,
-    url: React.PropTypes.string.isRequired,
-    style: React.PropTypes.object
-  },
-  render: function() {
-    var classes = this.props.subMenu ? ' subMenu' : '';
-    classes += this.props.classes;
-    return (
-      <a href={ this.props.url } key={ `link-${_.uniqueId()}` } className={ classes } style={ this.props.style }>
-        { this.props.name }
-      </a>
-      );
-  }
+    propTypes: {
+        name: React.PropTypes.string.isRequired,
+        url: React.PropTypes.string.isRequired,
+        style: React.PropTypes.object
+    },
+    render: function () {
+        var classes = this.props.subMenu ? ' subMenu' : '';
+        classes += this.props.classes;
+        return (
+            <a href={ this.props.url } key={ `link-${_.uniqueId()}` } className={ classes } style={ this.props.style }>
+                { this.props.name }
+            </a> // jshint ignore:line
+        );
+    }
 });
 
 /**
@@ -67,33 +67,34 @@ var NavLink = React.createClass({
  * @constructor
  */
 var ToolSubMenu = React.createClass({
-  propTypes: {
-    isSubmenu: React.PropTypes.bool,
-    tools: ToolsPropType
-  },
-  handle: '.draggable-handle',
-  mode: 'list',
-  render: function() {
-    var _this = this;
-    var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
-    var tools = this.props.tools.map(function(item, i) {
-      return (
-        <div className={ 'draggable-element ' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
-          <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
-            <NavBarItem {..._this.props} data={ item } name={ item.mount_point } url={ item.url } data-id={ i } />
-          </div>
-        </div>
+    propTypes: {
+        isSubmenu: React.PropTypes.bool,
+        tools: ToolsPropType
+    },
+    handle: '.draggable-handle',
+    mode: 'list',
+    render: function () {
+        var _this = this;
+        var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
+        var tools = this.props.tools.map(function (item, i) {
+            return (
+                <div className={ 'draggable-element ' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
+                    <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
+                        <NavBarItem {..._this.props} data={ item } name={ item.mount_point } url={ item.url } data-id={ i }/>
+                    </div>
+                </div>
+            );
+        });
+
+        return (
+            <div className='hidden' style={ {  display: 'none'} }>
+                <ReactReorderable handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart } onDrop={ this.props.onToolReorder }
+                                  onChange={ this.onChange }>
+                    { tools }
+                </ReactReorderable>
+            </div>
         );
-    });
-
-    return (
-      <div className='hidden' style={ {  display: 'none'} }>
-        <ReactReorderable handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart } onDrop={ this.props.onToolReorder } onChange={ this.onChange }>
-          { tools }
-        </ReactReorderable>
-      </div>
-      );
-  }
+    }
 });
 
 /**
@@ -101,40 +102,40 @@ var ToolSubMenu = React.createClass({
  * @constructor
  */
 var NavBarItem = React.createClass({
-  propTypes: {
-    name: React.PropTypes.string.isRequired,
-    url: React.PropTypes.string.isRequired,
-    isSubmenu: React.PropTypes.bool,
-    tools: ToolsPropType
-  },
-  generateLink: function() {
-    return <NavLink url={ this.props.url } name={ this.props.name } key={ _.uniqueId() } />;
-  },
-
-  generateSubmenu: function() {
-    return <ToolSubMenu {...this.props} tools={ this.props.data.children } key={ `submenu-${_.uniqueId()}` } isSubmenu={ true } />;
-  },
-
-  generateContent: function() {
-    var content = [this.generateLink()];
-    if (this.props.data.children) {
-      content.push(this.generateSubmenu());
-    }
+    propTypes: {
+        name: React.PropTypes.string.isRequired,
+        url: React.PropTypes.string.isRequired,
+        isSubmenu: React.PropTypes.bool,
+        tools: ToolsPropType
+    },
+    generateLink: function () {
+        return <NavLink url={ this.props.url } name={ this.props.name } key={ _.uniqueId() }/>;
+    },
+
+    generateSubmenu: function () {
+        return <ToolSubMenu {...this.props} tools={ this.props.data.children } key={ `submenu-${_.uniqueId()}` } isSubmenu={ true }/>;
+    },
+
+    generateContent: function () {
+        var content = [this.generateLink()];
+        if (this.props.data.children) {
+            content.push(this.generateSubmenu());
+        }
+
+        return content;
+    },
+
+    render: function () {
+        var content = this.generateContent();
+        var classes = this.props.editMode ? 'tb-item tb-item-edit' : 'tb-item';
+        classes = this.props.is_anchored ? `${classes} anchored` : classes;
 
-    return content;
-  },
-
-  render: function() {
-    var content = this.generateContent();
-    var classes = this.props.editMode ? 'tb-item tb-item-edit' : 'tb-item';
-    classes = this.props.is_anchored ? `${classes} anchored` : classes;
-
-    return (
-      <div className={ classes }>
-        { content }
-      </div>
-      );
-  }
+        return (
+            <div className={ classes }>
+                { content }
+            </div>
+        );
+    }
 });
 
 /**
@@ -142,27 +143,27 @@ var NavBarItem = React.createClass({
  * @constructor
  */
 var GroupingThreshold = React.createClass({
-  propTypes: {
-    initialValue: React.PropTypes.number.isRequired
-  },
-  getInitialState: function() {
-    return {
-      value: this.props.initialValue
-    };
-  },
-
-  handleChange: function(event) {
-    this.setState({
-      value: event.target.value
-    });
-    this.props.onUpdateThreshold(event);
-  },
-
-  render: function() {
-    return (
-      <div>
-        { !!this.props.isHidden &&
-          <div id='threshold-config'>
+    propTypes: {
+        initialValue: React.PropTypes.number.isRequired
+    },
+    getInitialState: function () {
+        return {
+            value: this.props.initialValue
+        };
+    },
+
+    handleChange: function (event) {
+        this.setState({
+            value: event.target.value
+        });
+        this.props.onUpdateThreshold(event);
+    },
+
+    render: function () {
+        return (
+            <div>
+                { !!this.props.isHidden &&
+                <div id='threshold-config'>
             <span>
               <label htmlFor='threshold-input'>Grouping Threshold</label>
                 <input type='number' name='threshold-input' className='tooltip'
@@ -171,48 +172,49 @@ var GroupingThreshold = React.createClass({
                        onChange={ this.handleChange }
                        min='1' max='10'/>
               </span>
-          </div> }
-      </div>
-      );
-  }
+                </div> }
+            </div>
+        );
+    }
 });
 
+
 /**
  * The NavBar when in "Normal" mode.
  * @constructor
  */
 var NormalNavBar = React.createClass({
-  buildMenu: function(item) {
-    var classes = ` ui-icon-${item.icon}-32`;
-    classes = item.is_anchored ? `${classes} anchored` : classes;
+    buildMenu: function (item) {
+        var classes = ` ui-icon-${item.icon}-32`;
+        classes = item.is_anchored ? `${classes} anchored` : classes;
 
-    var subMenu;
-    if (item.children) {
-      subMenu = item.children.map(this.buildMenu);
-    }
+        var subMenu;
+        if (item.children) {
+            subMenu = item.children.map(this.buildMenu);
+        }
+
+        return (
+            <li>
+                <a href={ item.url } key={ 'link-' + _.uniqueId() } className={ classes }>
+                    { item.name }
+                </a>
+                <ul className={ item.children ? 'submenu' : '' }>
+                    { subMenu }
+                </ul>
+            </li>
+        );
+    },
 
-    return (
-      <li>
-        <a href={ item.url } key={ 'link-' + _.uniqueId() } className={ classes }>
-          { item.name }
-        </a>
-        <ul className={ item.children ? 'submenu' : '' }>
-          { subMenu }
-        </ul>
-      </li>
-      );
-  },
-
-  render: function() {
-    var listItems = this.props.items.map(this.buildMenu);
-    var classes = 'dropdown';
-    classes = this.props.isSubmenu ? classes += ' submenu' : classes;
-    return (
-      <ul className={ classes } key={ `toolList-${_.uniqueId()}` }>
-        { listItems }
-      </ul>
-      );
-  }
+    render: function () {
+        var listItems = this.props.items.map(this.buildMenu);
+        var classes = 'dropdown';
+        classes = this.props.isSubmenu ? classes += ' submenu' : classes;
+        return (
+            <ul className={ classes } key={ `toolList-${_.uniqueId()}` }>
+                { listItems }
+            </ul>
+        );
+    }
 });
 
 /**
@@ -220,54 +222,56 @@ var NormalNavBar = React.createClass({
  * @constructor
  */
 var AdminNav = React.createClass({
-  propTypes: {
-    name: React.PropTypes.string.isRequired,
-    url: React.PropTypes.string.isRequired,
-    isSubmenu: React.PropTypes.bool,
-    tools: ToolsPropType
-  },
-  handle: '.draggable-handle',
-  mode: 'grid',
-  getInitialState: function() {
-    return {
-      hover: false
-    };
-  },
-
-  mouseOver: function() {
-    this.setState({
-      hover: true
-    });
-  },
-
-  mouseOut: function() {
-    this.setState({
-      hover: false
-    });
-  },
-
-  render: function() {
-    var _this = this;
-    var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
-    var tools = this.props.tools.map(function(item, i) {
-      return (
-        <div className={ 'draggable-element' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
-          <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
-            <NavBarItem onMouseOver={ _this.mouseOver } onMouseOut={ _this.mouseOut } {..._this.props} data={ item } name={ item.mount_point } url={ item.url }
-            key={ 'tb-item-' + _.uniqueId() } is_anchored={ item.is_anchored } data-id={ i } />
-          </div>
-        </div>
+    propTypes: {
+        name: React.PropTypes.string.isRequired,
+        url: React.PropTypes.string.isRequired,
+        isSubmenu: React.PropTypes.bool,
+        tools: ToolsPropType
+    },
+    handle: '.draggable-handle',
+    mode: 'grid',
+    getInitialState: function () {
+        return {
+            hover: false
+        };
+    },
+
+    mouseOver: function () {
+        this.setState({
+            hover: true
+        });
+    },
+
+    mouseOut: function () {
+        this.setState({
+            hover: false
+        });
+    },
+
+    render: function () {
+        var _this = this;
+        var subMenuClass = this.props.isSubmenu ? ' submenu ' : '';
+        var tools = this.props.tools.map(function (item, i) {
+            return (
+                <div className={ 'draggable-element' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
+                    <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
+                        <NavBarItem onMouseOver={ _this.mouseOver } onMouseOut={ _this.mouseOut } {..._this.props} data={ item }
+                                    name={ item.mount_point } url={ item.url }
+                                    key={ 'tb-item-' + _.uniqueId() } is_anchored={ item.is_anchored } data-id={ i }/>
+                    </div>
+                </div>
+            );
+        });
+
+        return (
+            <div className='react-drag edit-mode'>
+                <ReactReorderable key={ 'reorder-' + _.uniqueId() } handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart }
+                                  onDrop={ this.props.onToolReorder } onChange={ this.onChange }>
+                    { tools }
+                </ReactReorderable>
+            </div>
         );
-    });
-
-    return (
-      <div className='react-drag edit-mode'>
-        <ReactReorderable key={ 'reorder-' + _.uniqueId() } handle='.draggable-handle' mode='grid' onDragStart={ this.onDragStart } onDrop={ this.props.onToolReorder } onChange={ this.onChange }>
-          { tools }
-        </ReactReorderable>
-      </div>
-      );
-  }
+    }
 });
 
 /**
@@ -275,17 +279,17 @@ var AdminNav = React.createClass({
  * @constructor
  */
 var ToggleAdminButton = React.createClass({
-  propTypes: {
-    visible: React.PropTypes.bool
-  },
-  render: function() {
-    var classes = this.props.visible ? 'fa fa-unlock' : 'fa fa-lock';
-    return (
-      <button id='toggle-admin-btn' onClick={ this.props.handleButtonPush } className='admin-toolbar-right'>
-        <i className={ classes }></i>
-      </button>
-      );
-  }
+    propTypes: {
+        visible: React.PropTypes.bool
+    },
+    render: function () {
+        var classes = this.props.visible ? 'fa fa-unlock' : 'fa fa-lock';
+        return (
+            <button id='toggle-admin-btn' onClick={ this.props.handleButtonPush } className='admin-toolbar-right'>
+                <i className={ classes }></i>
+            </button>
+        );
+    }
 });
 
 /**
@@ -294,138 +298,141 @@ var ToggleAdminButton = React.createClass({
  * @param {object} initialData - Consumes the _nav.json endpoint.
  */
 var Main = React.createClass({
-  propTypes: {
-    initialData: ToolsPropType
-  },
-  getInitialState: function() {
-    return {
-      data: this.props.initialData,
-      visible: false,
-      _session_id: $.cookie('_session_id')
-    };
-  },
-
-  /**
-  * When invoked, this updates the state with the latest data from the server.
-  */
-  getNavJson: function() {
-    $.get(`${_getProjectUrl(false)}/_nav.json`, function(result) {
-      if (this.isMounted()) {
+    propTypes: {
+        initialData: ToolsPropType
+    },
+    getInitialState: function () {
+        return {
+            data: this.props.initialData,
+            visible: false,
+            _session_id: $.cookie('_session_id')
+        };
+    },
+
+    /**
+     * When invoked, this updates the state with the latest data from the server.
+     */
+    getNavJson: function () {
+        $.get(`${_getProjectUrl(false)}/_nav.json`, function (result) {
+            if (this.isMounted()) {
+                this.setState({
+                    data: result
+                });
+            }
+        }.bind(this));
+    },
+
+    /**
+     * Handles the locking and unlocking of the NavBar
+     */
+    handleToggleAdmin: function () {
+        this.setState({
+            visible: !this.state.visible
+        });
+    },
+
+    /**
+     * Handles the changing of the NavBars grouping threshold.
+     * @param {object} event
+     */
+    onUpdateThreshold: function (event) {
+        var _this = this;
+        var thres = event.target.value;
+        var url = `${_getProjectUrl()}/admin/configure_tool_grouping`;
+        var csrf = $.cookie('_session_id');
+        var data = {
+            _session_id: csrf,
+            grouping_threshold: thres
+        };
+        var _data = this.state.data;
+        _data.grouping_threshold = thres;
         this.setState({
-          data: result
+            data: _data
         });
-      }
-    }.bind(this));
-  },
-
-  /**
-  * Handles the locking and unlocking of the NavBar
-  */
-  handleToggleAdmin: function() {
-    this.setState({
-      visible: !this.state.visible
-    });
-  },
-
-  /**
-   * Handles the changing of the NavBars grouping threshold.
-   * @param {object} event
-   */
-  onUpdateThreshold: function(event) {
-    var _this = this;
-    var thres = event.target.value;
-    var url = `${_getProjectUrl()}/admin/configure_tool_grouping`;
-    var csrf = $.cookie('_session_id');
-    var data = {
-      _session_id: csrf,
-      grouping_threshold: thres
-    };
-    var _data = this.state.data;
-    _data.grouping_threshold = thres;
-    this.setState({
-      data: _data
-    });
-    this.setState({
-      in_progress: true
-    });
-    $.post(url, data, function(resp) {}.bind(this)).always(function() {
-      _this.setState({
-        in_progress: false
-      });
-    });
-
-    _this.getNavJson();
-    return false;
-  },
-
-  /**
-   * Handles the changing of the NavBars grouping threshold.
-   * @param {array} data - Array of tools
-   */
-  onToolReorder: function(data) {
-    var tools = this.state.data;
-    var params = {
-      _session_id: $.cookie('_session_id')
-    };
-
-    data.map(function(tool, i) {
-      var name = getLabel(tool);
-      var index = tools.children.findIndex(
-        x => x.mount_point === name
-      );
-      tools.children[index].ordinal = i;
-      params[i] = name;
-    });
-
-    this.setState({
-      data: tools
-    });
-    var _this = this;
-    var url = _getProjectUrl() + '/admin/mount_order';
-    $.ajax({
-      type: 'POST',
-      url: url,
-      data: params,
-      success: function() {
-        $('#messages').notify('Tool order updated',
-          {
-            status: 'confirm'
-          });
+        this.setState({
+            in_progress: true
+        });
+        $.post(url, data, function () {
+        }.bind(this)).always(function () {
+            _this.setState({
+                in_progress: false
+            });
+        });
+
         _this.getNavJson();
-      },
-
-      error: function() {
-        $('#messages').notify('Error saving tool order.',
-          {
-            status: 'error'
-          });
-      }
-    });
-  },
-
-  render: function() {
-    var editMode = this.state.visible ? 'edit-mode' : '';
-    var _this = this;
-    var navBarSwitch = (showAdmin) => {
-      if (showAdmin) {
+        return false;
+    },
+
+    /**
+     * Handles the changing of the NavBars grouping threshold.
+     * @param {array} data - Array of tools
+     */
+    onToolReorder: function (data) {
+        var tools = this.state.data;
+        var params = {
+            _session_id: $.cookie('_session_id')
+        };
+
+        data.map(function (tool, i) {
+            var name = getLabel(tool);
+            var index = tools.children.findIndex(
+                    x => x.mount_point === name
+            );
+            tools.children[index].ordinal = i;
+            params[i] = name;
+        });
+
+        this.setState({
+            data: tools
+        });
+        var _this = this;
+        var url = _getProjectUrl() + '/admin/mount_order';
+        $.ajax({
+            type: 'POST',
+            url: url,
+            data: params,
+            success: function () {
+                $('#messages').notify('Tool order updated',
+                    {
+                        status: 'confirm'
+                    });
+                _this.getNavJson();
+            },
+
+            error: function () {
+                $('#messages').notify('Error saving tool order.',
+                    {
+                        status: 'error'
+                    });
+            }
+        });
+    },
+
+    render: function () {
+        var editMode = this.state.visible ? 'edit-mode' : '';
+        var _this = this;
+        var navBarSwitch = (showAdmin) => {
+            if (showAdmin) {
+                return (
+                    <AdminNav tools={ _this.state.data.children } data={ _this.state.data } onToolReorder={ _this.onToolReorder }
+                              onUpdateMountOrder={ _this.onUpdateMountOrder } editMode={ _this.state.visible }
+                        />
+                );
+            } else {
+                return <NormalNavBar items={ _this.state.data.children } key={ `normalNav-${_.uniqueId()}` }/>;
+            }
+        };
+        var navBar = navBarSwitch(this.state.visible);
+
         return (
-          <AdminNav tools={ _this.state.data.children } data={ _this.state.data } onToolReorder={ _this.onToolReorder } onUpdateMountOrder={ _this.onUpdateMountOrder } editMode={ _this.state.visible }
-          />
-          );
-      } else {
-        return <NormalNavBar items={ _this.state.data.children } key={ `normalNav-${_.uniqueId()}` } />;
-      }
-    };
-    var navBar = navBarSwitch(this.state.visible);
-
-    return (
-      <div ref={ _.uniqueId() } className={ 'nav_admin ' + editMode }>
-        { navBar }
-        <div id='bar-config'>
-          <GroupingThreshold onUpdateThreshold={ this.onUpdateThreshold } isHidden={ this.state.visible } initialValue={ this.state.data.grouping_threshold } />
-        </div>
-        <ToggleAdminButton key={ _.uniqueId() } handleButtonPush={ this.handleToggleAdmin } visible={ this.state.visible } />
-      </div>
-      );
-  }
+            <div ref={ _.uniqueId() } className={ 'nav_admin ' + editMode }>
+                { navBar }
+                <div id='bar-config'>
+                    <GroupingThreshold onUpdateThreshold={ this.onUpdateThreshold } isHidden={ this.state.visible }
+                                       initialValue={ this.state.data.grouping_threshold }/>
+                </div>
+                <ToggleAdminButton key={ _.uniqueId() } handleButtonPush={ this.handleToggleAdmin } visible={ this.state.visible }/>
+            </div>
+        );
+    }
 });


[12/47] allura git commit: [#7919] Refactor _nav endpoint to use json_nav on the project model

Posted by br...@apache.org.
[#7919] Refactor _nav endpoint to use json_nav on the project model


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e4198857
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e4198857
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e4198857

Branch: refs/heads/db/7919
Commit: e4198857ded3c9b13d21e18ea94553d2b4018a18
Parents: 5486f49
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:01:25 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:05:14 2015 -0400

----------------------------------------------------------------------
 Allura/allura/controllers/project.py | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e4198857/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 20d9f63..869d326 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -380,16 +380,8 @@ class ProjectController(FeedController):
         self._list = ToolListController()
 
     @expose('json:')
-    def _nav(self, **kw):
-        menu = []
-        for s in c.project.grouped_navbar_entries():
-            entry = dict(name=s.label, url=s.url,
-                         icon=s.ui_icon, tool_name=s.tool_name)
-            if s.children:
-                entry['children'] = [dict(name=child.label, url=child.url, icon=child.ui_icon, tool_name=child.tool_name)
-                                     for child in s.children]
-            menu.append(entry)
-        return dict(menu=menu)
+    def _nav(self):
+        return c.project.json_nav()
 
     @expose()
     def _lookup(self, name, *remainder):


[22/47] allura git commit: [#7919] Add NavBar dependencies

Posted by br...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/db6e6859/Allura/allura/public/nf/js/react-drag.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/react-drag.js b/Allura/allura/public/nf/js/react-drag.js
new file mode 100644
index 0000000..c52ac50
--- /dev/null
+++ b/Allura/allura/public/nf/js/react-drag.js
@@ -0,0 +1,557 @@
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['React'], factory);
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('react/addons'));
+    } else {
+        root.ReactDrag = factory(root.React);
+    }
+}(this, function (React) {
+    /* global React */
+    /* exported ReactDrag */
+    'use strict';
+
+    function classNames() {
+        var classes = '';
+        for (var i = 0; i < arguments.length; i++) {
+            var arg = arguments[i];
+            if (!arg) continue;
+            var argType = typeof arg;
+            if ('string' === argType || 'number' === argType) {
+                classes += ' ' + arg;
+            } else if (Array.isArray(arg)) {
+                classes += ' ' + classNames.apply(null, arg);
+            } else if ('object' === argType) {
+                for (var key in arg) {
+                    if (arg.hasOwnProperty(key) && arg[key]) {
+                        classes += ' ' + key;
+                    }
+                }
+            }
+        }
+        return classes.substr(1);
+    }
+
+    var emptyFunction = function () {
+    };
+    var CX = classNames;
+
+    function createUIEvent(draggable) {
+        return {
+            position: {
+                top: draggable.state.pageY,
+                left: draggable.state.pageX
+            }
+        };
+    }
+
+    function canDragY(draggable) {
+        return draggable.props.axis === 'both' ||
+            draggable.props.axis === 'y';
+    }
+
+    function canDragX(draggable) {
+        return draggable.props.axis === 'both' ||
+            draggable.props.axis === 'x';
+    }
+
+    function isFunction(func) {
+        return typeof func === 'function' ||
+            Object.prototype.toString.call(func) === '[object Function]';
+    }
+
+// @credits https://gist.github.com/rogozhnikoff/a43cfed27c41e4e68cdc
+    function findInArray(array, callback) {
+        for (var i = 0, length = array.length, element = null; i < length; i += 1) {
+            element = array[i];
+            if (callback.apply(callback, [element, i, array])) {
+                return element;
+            }
+        }
+    }
+
+    function matchesSelector(el, selector) {
+        var method = findInArray([
+            'matches',
+            'webkitMatchesSelector',
+            'mozMatchesSelector',
+            'msMatchesSelector',
+            'oMatchesSelector'
+        ], function (method) {
+            return isFunction(el[method]);
+        });
+
+        return el[method].call(el, selector);
+    }
+
+// @credits:
+// http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript/4819886#4819886
+    /* Conditional to fix node server side rendering of component */
+    if (typeof window === 'undefined') {
+        // Do Node Stuff
+        var isTouchDevice = false;
+    } else {
+        // Do Browser Stuff
+        var isTouchDevice = 'ontouchstart' in window // works on most browsers
+            || 'onmsgesturechange' in window; // works on ie10 on ms surface
+        // Check for IE11
+        try {
+            document.createEvent('TouchEvent');
+        } catch (e) {
+            isTouchDevice = false;
+        }
+
+    }
+
+// look ::handleDragStart
+//function isMultiTouch(e) {
+//  return e.touches && Array.isArray(e.touches) && e.touches.length > 1
+//}
+
+    /**
+     * simple abstraction for dragging events names
+     * */
+    var dragEventFor = (function () {
+        var eventsFor = {
+            touch: {
+                start: 'touchstart',
+                move: 'touchmove',
+                end: 'touchend'
+            },
+            mouse: {
+                start: 'mousedown',
+                move: 'mousemove',
+                end: 'mouseup'
+            }
+        };
+        return eventsFor[isTouchDevice ? 'touch' : 'mouse'];
+    })();
+
+    /**
+     * get {pageX, pageY} positions of control
+     * */
+    function getControlPosition(e) {
+        var position = (e.touches && e.touches[0]) || e;
+        return {
+            pageX: position.pageX,
+            pageY: position.pageY
+        };
+    }
+
+    function getBoundPosition(pageX, pageY, bound, target) {
+        if (bound) {
+            if ((typeof bound !== 'string' && bound.toLowerCase() !== 'parent') &&
+                (typeof bound !== 'object')) {
+                console.warn('Bound should either "parent" or an object');
+            }
+            var par = target.parentNode;
+            var topLimit = bound.top || 0;
+            var leftLimit = bound.left || 0;
+            var rightLimit = bound.right || par.offsetWidth;
+            var bottomLimit = bound.bottom || par.offsetHeight;
+            pageX = Math.min(pageX, rightLimit - target.offsetWidth);
+            pageY = Math.min(pageY, bottomLimit - target.offsetHeight);
+            pageX = Math.max(leftLimit, pageX);
+            pageY = Math.max(topLimit, pageY);
+        }
+        return {
+            pageX: pageX,
+            pageY: pageY
+        };
+    }
+
+    function addEvent(el, event, handler) {
+        if (!el) {
+            return;
+        }
+        if (el.attachEvent) {
+            el.attachEvent('on' + event, handler);
+        } else if (el.addEventListener) {
+            el.addEventListener(event, handler, true);
+        } else {
+            el['on' + event] = handler;
+        }
+    }
+
+    function removeEvent(el, event, handler) {
+        if (!el) {
+            return;
+        }
+        if (el.detachEvent) {
+            el.detachEvent('on' + event, handler);
+        } else if (el.removeEventListener) {
+            el.removeEventListener(event, handler, true);
+        } else {
+            el['on' + event] = null;
+        }
+    }
+
+    var ReactDrag = React.createClass({
+        displayName: 'Draggable',
+
+        propTypes: {
+            /**
+             * `axis` determines which axis the draggable can move.
+             *
+             * 'both' allows movement horizontally and vertically.
+             * 'x' limits movement to horizontal axis.
+             * 'y' limits movement to vertical axis.
+             *
+             * Defaults to 'both'.
+             */
+            axis: React.PropTypes.oneOf(['both', 'x', 'y']),
+
+            /**
+             * `handle` specifies a selector to be used as the handle
+             * that initiates drag.
+             *
+             * Example:
+             *
+             * ```jsx
+             *   var App = React.createClass({
+     *       render: function () {
+     *         return (
+     *            <Draggable handle=".handle">
+     *              <div>
+     *                  <div className="handle">Click me to drag</div>
+     *                  <div>This is some other content</div>
+     *              </div>
+     *           </Draggable>
+     *         );
+     *       }
+     *   });
+             * ```
+             */
+            handle: React.PropTypes.string,
+
+            /**
+             * `cancel` specifies a selector to be used to prevent drag initialization.
+             *
+             * Example:
+             *
+             * ```jsx
+             *   var App = React.createClass({
+     *       render: function () {
+     *           return(
+     *               <Draggable cancel=".cancel">
+     *                   <div>
+     *             <div className="cancel">You can't drag from here</div>
+     *            <div>Dragging here works fine</div>
+     *                   </div>
+     *               </Draggable>
+     *           );
+     *       }
+     *   });
+             * ```
+             */
+            cancel: React.PropTypes.string,
+
+            /**
+             * `grid` specifies the x and y that dragging should snap to.
+             *
+             * Example:
+             *
+             * ```jsx
+             *   var App = React.createClass({
+     *       render: function () {
+     *           return (
+     *               <Draggable grid={[25, 25]}>
+     *                   <div>I snap to a 25 x 25 grid</div>
+     *               </Draggable>
+     *           );
+     *       }
+     *   });
+             * ```
+             */
+            grid: React.PropTypes.arrayOf(React.PropTypes.number),
+
+            /**
+             * `start` specifies the x and y that the dragged item should start at
+             *
+             * Example:
+             *
+             * ```jsx
+             *   var App = React.createClass({
+     *       render: function () {
+     *           return (
+     *               <Draggable start={{x: 25, y: 25}}>
+     *                   <div>I start with left: 25px; top: 25px;</div>
+     *               </Draggable>
+     *           );
+     *       }
+     *   });
+             * ```
+             */
+            start: React.PropTypes.object,
+
+            /**
+             * Called when dragging starts.
+             *
+             * Example:
+             *
+             * ```js
+             *  function (event, ui) {}
+             * ```
+             *
+             * `event` is the Event that was triggered.
+             * `ui` is an object:
+             *
+             * ```js
+             *  {
+     *    position: {top: 0, left: 0}
+     *  }
+             * ```
+             */
+            onStart: React.PropTypes.func,
+
+            /**
+             * Called while dragging.
+             *
+             * Example:
+             *
+             * ```js
+             *  function (event, ui) {}
+             * ```
+             *
+             * `event` is the Event that was triggered.
+             * `ui` is an object:
+             *
+             * ```js
+             *  {
+     *    position: {top: 0, left: 0}
+     *  }
+             * ```
+             */
+            onDrag: React.PropTypes.func,
+
+            /**
+             * Called when dragging stops.
+             *
+             * Example:
+             *
+             * ```js
+             *  function (event, ui) {}
+             * ```
+             *
+             * `event` is the Event that was triggered.
+             * `ui` is an object:
+             *
+             * ```js
+             *  {
+     *    position: {top: 0, left: 0}
+     *  }
+             * ```
+             */
+            onStop: React.PropTypes.func,
+
+            /**
+             * A workaround option which can be passed if
+             * onMouseDown needs to be accessed,
+             * since it'll always be blocked (due to that
+             * there's internal use of onMouseDown)
+             *
+             */
+            onMouseDown: React.PropTypes.func,
+
+            /**
+             * Defines the bounderies around the element
+             * could be dragged. This property could be
+             * object or a string. If used as object
+             * the bounderies should be defined as:
+             *
+             * {
+     *   left: LEFT_BOUND,
+     *   right: RIGHT_BOUND,
+     *   top: TOP_BOUND,
+     *   bottom: BOTTOM_BOUND
+     * }
+             *
+             * The only acceptable string
+             * property is: "parent".
+             */
+            bound: React.PropTypes.any
+        },
+
+        componentWillUnmount: function () {
+            // Remove any leftover event handlers
+            removeEvent(window, dragEventFor.move, this.handleDrag);
+            removeEvent(window, dragEventFor.end, this.handleDragEnd);
+        },
+
+        getDefaultProps: function () {
+            return {
+                axis: 'both',
+                handle: null,
+                cancel: null,
+                grid: null,
+                bound: false,
+                start: {
+                    x: 0,
+                    y: 0
+                },
+                onStart: emptyFunction,
+                onDrag: emptyFunction,
+                onStop: emptyFunction,
+                onMouseDown: emptyFunction
+            };
+        },
+
+        getInitialState: function () {
+            return {
+                // Whether or not currently dragging
+                dragging: false,
+
+                // Start top/left of this.getDOMNode()
+                startX: 0,
+                startY: 0,
+
+                // Offset between start top/left and mouse top/left
+                offsetX: 0,
+                offsetY: 0,
+
+                // Current top/left of this.getDOMNode()
+                pageX: this.props.start.x,
+                pageY: this.props.start.y
+            };
+        },
+
+        handleDragStart: function (e) {
+            // todo: write right implementation to prevent multitouch drag
+            // prevent multi-touch events
+            // if (isMultiTouch(e)) {
+            //     this.handleDragEnd.apply(e, arguments);
+            //     return
+            // }
+
+            // Make it possible to attach event handlers on top of this one
+            this.props.onMouseDown(e);
+
+            var node = this.getDOMNode();
+
+            // Short circuit if handle or cancel prop was provided
+            // and selector doesn't match
+            if ((this.props.handle && !matchesSelector(e.target, this.props.handle)) ||
+                (this.props.cancel && matchesSelector(e.target, this.props.cancel))) {
+                return;
+            }
+
+            var dragPoint = getControlPosition(e);
+
+            // Initiate dragging
+            this.setState({
+                dragging: true,
+                offsetX: parseInt(dragPoint.pageX, 10),
+                offsetY: parseInt(dragPoint.pageY, 10),
+                startX: parseInt(node.style.left, 10) || 0,
+                startY: parseInt(node.style.top, 10) || 0
+            });
+
+            // Call event handler
+            this.props.onStart(e, createUIEvent(this));
+
+            // Add event handlers
+            addEvent(window, dragEventFor.move, this.handleDrag);
+            addEvent(window, dragEventFor.end, this.handleDragEnd);
+        },
+
+        handleDragEnd: function (e) {
+            // Short circuit if not currently dragging
+            if (!this.state.dragging) {
+                return;
+            }
+
+            // Turn off dragging
+            this.setState({
+                dragging: false
+            });
+
+            // Call event handler
+            this.props.onStop(e, createUIEvent(this));
+
+            // Remove event handlers
+            removeEvent(window, dragEventFor.move, this.handleDrag);
+            removeEvent(window, dragEventFor.end, this.handleDragEnd);
+        },
+
+        handleDrag: function (e) {
+            var dragPoint = getControlPosition(e);
+
+            // Calculate top and left
+            var pageX = (this.state.startX +
+            (dragPoint.pageX - this.state.offsetX));
+            var pageY = (this.state.startY +
+            (dragPoint.pageY - this.state.offsetY));
+            var pos =
+                getBoundPosition(pageX, pageY, this.props.bound, this.getDOMNode());
+            pageX = pos.pageX;
+            pageY = pos.pageY;
+
+            // Snap to grid if prop has been provided
+            if (Array.isArray(this.props.grid)) {
+                var directionX = pageX < parseInt(this.state.pageX, 10) ? -1 : 1;
+                var directionY = pageY < parseInt(this.state.pageY, 10) ? -1 : 1;
+
+                pageX = Math.abs(pageX - parseInt(this.state.pageX, 10)) >=
+                this.props.grid[0]
+                    ? (parseInt(this.state.pageX, 10) +
+                (this.props.grid[0] * directionX))
+                    : this.state.pageX;
+
+                pageY = Math.abs(pageY - parseInt(this.state.pageY, 10)) >=
+                this.props.grid[1]
+                    ? (parseInt(this.state.pageY, 10) +
+                (this.props.grid[1] * directionY))
+                    : this.state.pageY;
+            }
+
+            // Update top and left
+            this.setState({
+                pageX: pageX,
+                pageY: pageY
+            });
+
+            // Call event handler
+            this.props.onDrag(e, createUIEvent(this));
+
+            // Prevent the default behavior
+            e.preventDefault();
+        },
+
+        render: function () {
+            var style = {
+                // Set top if vertical drag is enabled
+                top: canDragY(this)
+                    ? this.state.pageY
+                    : this.state.startY,
+
+                // Set left if horizontal drag is enabled
+                left: canDragX(this)
+                    ? this.state.pageX
+                    : this.state.startX
+            };
+
+            var className = CX({
+                'react-drag': true,
+                'react-drag-dragging': this.state.dragging
+            });
+            // Reuse the child provided
+            // This makes it flexible to use whatever element is wanted (div, ul, etc)
+            return React.addons.cloneWithProps(
+                React.Children.only(this.props.children), {
+                    style: style,
+                    className: className,
+
+                    onMouseDown: this.handleDragStart,
+                    onTouchStart: function (ev) {
+                        ev.preventDefault(); // prevent for scroll
+                        return this.handleDragStart.apply(this, arguments);
+                    }.bind(this),
+
+                    onMouseUp: this.handleDragEnd,
+                    onTouchEnd: this.handleDragEnd
+                });
+        }
+    });
+
+    return ReactDrag;
+}));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/db6e6859/Allura/allura/public/nf/js/react-reorderable.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/react-reorderable.js b/Allura/allura/public/nf/js/react-reorderable.js
new file mode 100755
index 0000000..401d6a5
--- /dev/null
+++ b/Allura/allura/public/nf/js/react-reorderable.js
@@ -0,0 +1,316 @@
+(function(root, factory) {
+  if (typeof define === 'function' && define.amd) {
+    define(['React', 'ReactDrag'], factory);
+  } else if (typeof exports === 'object') {
+    module.exports = factory(require('react/addons'), require('react-drag'));
+  } else {
+    root.ReactReorderable = factory(root.React, root.ReactDrag);
+  }
+}(this, function(React, ReactDrag) {
+'use strict';
+
+function getClosestReorderable(el) {
+  while (el) {
+    if (el.className &&
+        el.className.indexOf('react-reorderable-item') >= 0) {
+      return el;
+    }
+    el = el.parentNode;
+  }
+  return null;
+}
+
+var SIBLING_TYPES = {
+  NONE: 0,
+  NEXT: 1,
+  PREVIOUS: 2
+};
+
+function getControlPosition(e) {
+  var position = (e.touches && e.touches[0]) || e;
+  return {
+    clientX: position.clientX,
+    clientY: position.clientY
+  };
+}
+
+function getHorizontalSiblingType(e, node) {
+  var rect = node.getBoundingClientRect();
+  var nodeTop = rect.top;
+  var nodeLeft = rect.left;
+  var width = rect.width;
+  var height = rect.height;
+  var position = getControlPosition(e);
+
+  if (position.clientY < nodeTop || position.clientY > nodeTop + height) {
+    return SIBLING_TYPES.NONE;
+  }
+  if (position.clientX > nodeLeft && position.clientX < nodeLeft + 1 / 2 * width) {
+    return SIBLING_TYPES.NEXT;
+  }
+  if (position.clientX > nodeLeft + 1 / 2 * width && position.clientX < nodeLeft + width) {
+    return SIBLING_TYPES.PREVIOUS;
+  }
+  return SIBLING_TYPES.NONE;
+}
+
+function getVerticalSiblingType(e, node) {
+  var rect = node.getBoundingClientRect();
+  var nodeTop = rect.top;
+  var nodeLeft = rect.left;
+  var width = rect.width;
+  var height = rect.height;
+  var position = getControlPosition(e);
+
+  if (position.clientX < nodeLeft || position.clientX > nodeLeft + width) {
+    return SIBLING_TYPES.NONE;
+  }
+  if (position.clientY > nodeTop && position.clientY < nodeTop + 1 / 2 * height) {
+    return SIBLING_TYPES.NEXT;
+  }
+  if (position.clientY > nodeTop + 1 / 2 * height && position.clientY < nodeTop + height) {
+    return SIBLING_TYPES.PREVIOUS;
+  }
+  return SIBLING_TYPES.NONE;
+}
+
+function getSiblingNode(e, node, mode) {
+  var p = node.parentNode;
+  var siblings = p.children;
+  var current;
+  var done = false;
+  var result = {};
+  mode = mode || 'list';
+  for (var i = 0; i < siblings.length && !done; i += 1) {
+    current = siblings[i];
+    if (current.getAttribute('data-reorderable-key') !==
+        node.getAttribute('data-reorderable-key')) {
+      // The cursor should be around the middle of the item
+      var siblingType;
+      if (mode === 'list') {
+        siblingType = getVerticalSiblingType(e, current);
+      } else {
+        siblingType = getHorizontalSiblingType(e, current);
+      }
+      if (siblingType !== SIBLING_TYPES.NONE) {
+        result.node = current;
+        result.type = siblingType;
+        return result;
+      }
+    }
+  }
+  return result;
+}
+
+function indexChildren(children) {
+  var prefix = 'node-';
+  var map = {};
+  var ids = [];
+  var id;
+  for (var i = 0; i < children.length; i += 1) {
+    var id = prefix + (i + 1);
+    ids.push(id);
+    children[i] = React.createElement("div", {className: "react-reorderable-item", 
+         key: id, "data-reorderable-key": id}, 
+        children[i]
+      );
+    map[id] = children[i];
+  }
+  return { map: map, ids: ids };
+}
+
+function is(elem, selector) {
+  var matches = elem.parentNode.querySelectorAll(selector);
+  for (var i = 0; i < matches.length; i += 1) {
+    if (elem === matches[i]) {
+      return true;
+    }
+  }
+  return false;
+}
+
+function getNodesOrder(current, sibling, order) {
+  var currentKey = current.getAttribute('data-reorderable-key');
+  var currentPos = order.indexOf(currentKey);
+  order.splice(currentPos, 1);
+  var siblingKey = sibling.node.getAttribute('data-reorderable-key');
+  var siblingKeyPos = order.indexOf(siblingKey);
+  if (sibling.type === SIBLING_TYPES.PREVIOUS) {
+    order.splice(siblingKeyPos + 1, 0, currentKey);
+  } else {
+    order.splice(siblingKeyPos, 0, currentKey);
+  }
+  return order;
+}
+
+
+var ReactReorderable = React.createClass({displayName: "ReactReorderable",
+  componentWillMount: function () {
+    window.addEventListener('mouseup', this._mouseupHandler = function () {
+      this.setState({
+        mouseDownPosition: null
+      });
+    }.bind(this));
+  },
+  componentWillUnmount: function () {
+    window.removeEventListener('mouseup', this._mouseupHandler);
+  },
+  componentWillReceiveProps: function (nextProps) {
+    if (nextProps.children) {
+      var res = indexChildren(nextProps.children);
+      this.setState({
+        order: res.ids,
+        reorderableMap: res.map
+      });
+    }
+  },
+  getInitialState: function () {
+    var res = indexChildren(this.props.children);
+    return {
+      order: res.ids,
+      startPosition: null,
+      activeItem: null,
+      reorderableMap: res.map
+    };
+  },
+  onDragStop: function (e) {
+    this.setState({
+      activeItem: null,
+      startPosition: null
+    });
+    this.props.onDrop(this.state.order.map(function (id) {
+      return this.state.reorderableMap[id].props.children;
+    }, this));
+  },
+  onDrag: function (e) {
+    var handle = this.refs.handle.getDOMNode();
+    var sibling = getSiblingNode(e, handle, this.props.mode);
+
+    if (sibling && sibling.node) {
+      var oldOrder = this.state.order.slice();
+      var order = getNodesOrder(getClosestReorderable(handle), sibling, this.state.order);
+      var changed = false;
+      for (var i = 0; i < order.length && !changed; i += 1) {
+        if (order[i] !== oldOrder[i]) {
+          changed = true;
+        }
+      }
+      if (changed) {
+        this.props.onChange(this.state.order.map(function (id) {
+          return this.state.reorderableMap[id].props.children;
+        }, this));
+      }
+      this.setState({
+        order: order
+      });
+    }
+  },
+  onMouseDown: function (e) {
+    var position;
+
+    if (!this.props.handle || is(e.target, this.props.handle)) {
+      position = getControlPosition(e);
+
+      this.setState({
+        mouseDownPosition: {
+          x: position.clientX,
+          y: position.clientY
+        }
+      });
+    }
+  },
+  onTouchStart: function(e) {
+    e.preventDefault(); // prevent scrolling
+    this.onMouseDown(e);
+  },
+  onMouseMove: function (e) {
+    var position;
+
+    if (!this.state.activeItem) {
+      var initial = this.state.mouseDownPosition;
+      // Still not clicked
+      if (!initial) {
+        return;
+      }
+
+      position = getControlPosition(e);
+
+      if (Math.abs(position.clientX - initial.x) >= 5 ||
+          Math.abs(position.clientY - initial.y) >= 5) {
+        var node = getClosestReorderable(e.target);
+        var nativeEvent = e.nativeEvent;
+        var id = node.getAttribute('data-reorderable-key');
+        // React resets the event's properties
+        this.props.onDragStart(this.state.reorderableMap[id]);
+        this.activeItem = node;
+        var parentNode = node.parentNode && node.parentNode.parentNode;
+        this.setState({
+          mouseDownPosition: null,
+          activeItem: id,
+          startPosition: {
+            x: node.offsetLeft - (parentNode && parentNode.scrollLeft || 0),
+            y: node.offsetTop - (parentNode && parentNode.scrollTop || 0)
+          }
+        }, function () {
+          this.refs.handle.handleDragStart(nativeEvent);
+        }.bind(this));
+      }
+    }
+  },
+  render: function () {
+    var children = this.state.order.map(function (id) {
+      var className = (this.state.activeItem) ? 'noselect ' : '';
+      if (this.state.activeItem === id) {
+        className += 'react-reorderable-item-active';
+      }
+      return React.addons.cloneWithProps(
+        this.state.reorderableMap[id], {
+          key: 'reaorderable-' + id,
+          ref: 'active',
+          onMouseDown: this.onMouseDown,
+          onMouseMove: this.onMouseMove,
+          onTouchStart: this.onTouchStart,
+          onTouchMove: this.onMouseMove,
+          className: className
+      });
+    }, this);
+    var handle;
+    if (this.state.activeItem) {
+      var pos = this.state.startPosition;
+      handle = React.addons.cloneWithProps(
+        this.state.reorderableMap[this.state.activeItem], {
+          className: 'react-reorderable-handle'
+      });
+      handle =
+        React.createElement(ReactDrag, {onStop: this.onDragStop, 
+          onDrag: this.onDrag, 
+          ref: "handle", 
+          start: { x: pos.x, y: pos.y}}, 
+          handle
+        );
+    }
+    return (
+      React.createElement("div", {ref: "wrapper"}, 
+        children, 
+        handle
+      )
+    );
+  }
+});
+
+ReactReorderable.propTypes = {
+  onDragStart: React.PropTypes.func,
+  onDrag: React.PropTypes.func,
+  onDrop: React.PropTypes.func,
+  onChange: React.PropTypes.func
+};
+
+ReactReorderable.defaultProps = {
+  onDragStart: function () {},
+  onDrag: function () {},
+  onDrop: function () {},
+  onChange: function () {}
+};
+
+return ReactReorderable;
+}));
\ No newline at end of file


[27/47] allura git commit: [#7919] separate mount point vs name (aka label). Fix warnings

Posted by br...@apache.org.
[#7919] separate mount point vs name (aka label). Fix warnings


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/29e7badf
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/29e7badf
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/29e7badf

Branch: refs/heads/db/7919
Commit: 29e7badf057b2622e2fdbd3da648412e4a53ab02
Parents: e1f41c4
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 12 14:58:14 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/js/navbar.es6.js | 56 ++++++++++++++-------------
 1 file changed, 29 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/29e7badf/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index 7d64b08..a5ece5b 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -10,7 +10,7 @@
 function _getProjectUrl(rest = true) {
     var [nbhd, proj] = window.location.pathname.split('/').slice(1, 3);
     var base = `${window.location.protocol}//${window.location.host}`;
-    return rest ? `${base}/rest/${nbhd}/${proj}/` : `${base}/${nbhd}/${proj}/`;
+    return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`;
 }
 
 /**
@@ -19,26 +19,28 @@ function _getProjectUrl(rest = true) {
  * @param {NavBarItem} node - Return a "rest" version of the url.
  * @returns {string}
  */
-function getLabel(node) {
-    return node.props.children.props.children.props.name;
+function getMountPoint(node) {
+    return node.props.children.props.children.props.mount_point;
 }
 
-var ToolsPropType = {
-    name: React.PropTypes.string.isRequired,
-    url: React.PropTypes.string.isRequired,
-    isSubmenu: React.PropTypes.bool,
-    tools: React.PropTypes.arrayOf(
-        React.PropTypes.shape({
-            ordinal: React.PropTypes.number,
-            mount_point: React.PropTypes.string,
-            name: React.PropTypes.string,
-            url: React.PropTypes.string,
-            is_anchored: React.PropTypes.bool,
-            tool_name: React.PropTypes.string,
-            icon: React.PropTypes.string
-        })
-    ).isRequired
-};
+function ToolsPropType() {
+    return {
+        name: React.PropTypes.string.isRequired,
+        url: React.PropTypes.string.isRequired,
+        isSubmenu: React.PropTypes.bool,
+        tools: React.PropTypes.arrayOf(
+            React.PropTypes.shape({
+                ordinal: React.PropTypes.number,
+                mount_point: React.PropTypes.string,
+                name: React.PropTypes.string,
+                url: React.PropTypes.string,
+                is_anchored: React.PropTypes.bool,
+                tool_name: React.PropTypes.string,
+                icon: React.PropTypes.string
+            })
+        ).isRequired
+    };
+}
 
 /**
  * A NavBar link, the most basic component of the NavBar.
@@ -80,7 +82,7 @@ var ToolSubMenu = React.createClass({
             return (
                 <div className={ 'draggable-element ' + subMenuClass } key={ 'draggable-' + _.uniqueId() }>
                     <div className='draggable-handle' key={ 'handleId-' + _.uniqueId() }>
-                        <NavBarItem {..._this.props} data={ item } name={ item.mount_point } url={ item.url } data-id={ i }/>
+                        <NavBarItem data={ item } name={ item.mount_point } url={ item.url } data-id={ i }/>
                     </div>
                 </div>
             );
@@ -106,6 +108,7 @@ var NavBarItem = React.createClass({
         name: React.PropTypes.string.isRequired,
         url: React.PropTypes.string.isRequired,
         isSubmenu: React.PropTypes.bool,
+        children: React.PropTypes.array.isRequired,
         tools: ToolsPropType
     },
     generateLink: function () {
@@ -113,12 +116,12 @@ var NavBarItem = React.createClass({
     },
 
     generateSubmenu: function () {
-        return <ToolSubMenu {...this.props} tools={ this.props.data.children } key={ `submenu-${_.uniqueId()}` } isSubmenu={ true }/>;
+        return <ToolSubMenu {...this.props} tools={ this.props.children } key={ `submenu-${_.uniqueId()}` } isSubmenu={ true }/>;
     },
 
     generateContent: function () {
         var content = [this.generateLink()];
-        if (this.props.data.children) {
+        if (this.props.children) {
             content.push(this.generateSubmenu());
         }
 
@@ -130,6 +133,7 @@ var NavBarItem = React.createClass({
         var classes = this.props.editMode ? 'tb-item tb-item-edit' : 'tb-item';
         classes = this.props.is_anchored ? `${classes} anchored` : classes;
 
+
         return (
             <div className={ classes }>
                 { content }
@@ -223,8 +227,6 @@ var NormalNavBar = React.createClass({
  */
 var AdminNav = React.createClass({
     propTypes: {
-        name: React.PropTypes.string.isRequired,
-        url: React.PropTypes.string.isRequired,
         isSubmenu: React.PropTypes.bool,
         tools: ToolsPropType
     },
@@ -609,12 +611,12 @@ var Main = React.createClass({
         };
 
         data.map(function (tool, i) {
-            var name = getLabel(tool);
+            var mount_point = getMountPoint(tool);
             var index = tools.children.findIndex(
-                    x => x.mount_point === name
+                x => x.mount_point === mount_point
             );
             tools.children[index].ordinal = i;
-            params[i] = name;
+            params[i] = mount_point;
         });
 
         this.setState({


[04/47] allura git commit: [#8004] remove icons from project admin landing page

Posted by br...@apache.org.
[#8004] remove icons from project admin landing page


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/6abb9542
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/6abb9542
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/6abb9542

Branch: refs/heads/db/7919
Commit: 6abb9542c913a9015d308e65cd505d6d6a47204d
Parents: 687e3f1
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Oct 21 12:31:24 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Oct 22 10:55:25 2015 -0400

----------------------------------------------------------------------
 .../ext/admin/templates/project_admin.html      | 32 +++++++++++++-------
 1 file changed, 21 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/6abb9542/Allura/allura/ext/admin/templates/project_admin.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/templates/project_admin.html b/Allura/allura/ext/admin/templates/project_admin.html
index 3c9b4f5..6920236 100644
--- a/Allura/allura/ext/admin/templates/project_admin.html
+++ b/Allura/allura/ext/admin/templates/project_admin.html
@@ -28,8 +28,8 @@
 {% block content %}
   <p>{{config.site_name}} projects come with a number of Tools, which can be configured and adjusted to your needs.</p>
 
-  <div class="grid-2">
-    <img src="{{g.forge_static('images/project_default.png')}}" alt="">
+  <div class="grid-1">
+    &nbsp;
   </div>
   <div class="grid-13">
     <h3>Project Setup</h3>
@@ -40,8 +40,8 @@
   </div>
   <div style="clear:both"></div>
 
-  <div class="grid-2">
-    <img src="{{ g.theme.app_icon_url('Wiki', 48) }}" alt="">
+  <div class="grid-1">
+    &nbsp;
   </div>
   <div class="grid-13">
     <h3>Wikis</h3>
@@ -59,9 +59,9 @@
   <div style="clear:both"></div>
   {% if scm_tools %}
     {% set tool = scm_tools[0] %}
-    <div class="grid-2">
-        <img src="{{ g.theme.app_icon_url('Git', 48) }}" alt="">
-    </div>
+      <div class="grid-1">
+        &nbsp;
+      </div>
     <div class="grid-13">
       <h3>Code</h3>
       <p>Source Control Management will help you keep track of code changes over time. A repository has already been created, checkout, add files and upload code.</p>
@@ -73,8 +73,8 @@
   {% endif %}
   <div style="clear:both"></div>
 
-  <div class="grid-2">
-    <img src="{{ g.theme.app_icon_url('Tickets', 48) }}" alt="">
+  <div class="grid-1">
+    &nbsp;
   </div>
   <div class="grid-13">
   <h3>Tickets</h3>
@@ -92,8 +92,8 @@
   </div>
   <div style="clear:both"></div>
 
-  <div class="grid-2">
-    <img src="{{ g.theme.app_icon_url('Discussion', 48) }}" alt="">
+  <div class="grid-1">
+    &nbsp;
   </div>
   <div class="grid-13">
     <h3>Forums</h3>
@@ -109,3 +109,13 @@
     {% endfor %}
   </div>
 {% endblock %}
+
+{% block extra_css %}
+<style>
+    .grid-20.pad .grid-1,
+    .grid-20.pad .grid-13,
+    .grid-20.pad .grid-4 {
+        margin-top: 2em;
+    }
+</style>
+{% endblock %}
\ No newline at end of file


[02/47] allura git commit: [#8007] Fix forum icon path

Posted by br...@apache.org.
[#8007] Fix forum icon path


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/52c8d5cf
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/52c8d5cf
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/52c8d5cf

Branch: refs/heads/db/7919
Commit: 52c8d5cf89fac05ae736c157b757818b62b39d78
Parents: b216703
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Oct 21 14:27:38 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Wed Oct 21 14:34:35 2015 +0300

----------------------------------------------------------------------
 .../forgediscussion/templates/discussionforums/admin_forums.html   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/52c8d5cf/ForgeDiscussion/forgediscussion/templates/discussionforums/admin_forums.html
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/templates/discussionforums/admin_forums.html b/ForgeDiscussion/forgediscussion/templates/discussionforums/admin_forums.html
index 9b6b3e0..4d31933 100644
--- a/ForgeDiscussion/forgediscussion/templates/discussionforums/admin_forums.html
+++ b/ForgeDiscussion/forgediscussion/templates/discussionforums/admin_forums.html
@@ -40,7 +40,7 @@
           <div class="editable viewing">
             <span class="viewer">
               {% if forum.icon %}
-                <img src="{{forum.url()}}/icon" alt="Forum icon"/>
+                <img src="{{forum.url()}}icon" alt="Forum icon"/>
               {% else %}
                 <img src="{{g.forge_static('images/project_default.png')}}" alt="Forum icon"/>
               {% endif %}


[42/47] allura git commit: [#7919] use minified react in non-development situations

Posted by br...@apache.org.
[#7919] use minified react in non-development situations


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/9497a730
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/9497a730
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/9497a730

Branch: refs/heads/db/7919
Commit: 9497a7300e5a75fcec05f865911ae45ef3badbfe
Parents: df770b9
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Oct 16 13:06:45 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:04 2015 -0400

----------------------------------------------------------------------
 Allura/allura/templates/jinja_master/master.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/9497a730/Allura/allura/templates/jinja_master/master.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/master.html b/Allura/allura/templates/jinja_master/master.html
index 0032b74..be6515e 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -27,7 +27,7 @@
 {% do g.register_forge_js('js/jquery.notify.js') %}
 {% do g.register_forge_js('js/browser-polyfill.js') %}
 {% do g.register_forge_js('js/underscore-min.js') %}
-{% do g.register_forge_js('js/react-with-addons.js') %}
+{% do g.register_forge_js('js/react-with-addons' + ('' if h.asbool(config.get('debug')) else '.min') + '.js') %}
 {% do g.register_forge_js("js/react-drag.js") %}
 {% do g.register_forge_js('js/react-reorderable.js') %}
 {% do g.register_forge_js('js/jquery.tooltipster.js') %}


[31/47] allura git commit: [#7919] Add div to attach the "Add new tool" menu

Posted by br...@apache.org.
[#7919] Add div to attach the "Add new tool" menu


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/77421ffa
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/77421ffa
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/77421ffa

Branch: refs/heads/db/7919
Commit: 77421ffad9dd3f93de9ec206127ae996c69a3a4b
Parents: ed9e5f8
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:44:49 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/templates/jinja_master/master.html | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/77421ffa/Allura/allura/templates/jinja_master/master.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/master.html b/Allura/allura/templates/jinja_master/master.html
index 1a7f11c..bb03bf1 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -103,6 +103,7 @@
             {% include g.theme.top_nav %}
         {% endblock %}
     </div>
+<div id="add_tool_menu"></div>
     <div id="content_base">
         {% block content_base %}
             {% if not hide_left_bar %}


[30/47] allura git commit: [#7919] Fix style issues with "Add New Tool" menu

Posted by br...@apache.org.
[#7919] Fix style issues with "Add New Tool" menu


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e1f41c46
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e1f41c46
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e1f41c46

Branch: refs/heads/db/7919
Commit: e1f41c4616ef1e9133df487b9d4121bb3d355e10
Parents: 394e8b7
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 15:02:24 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 23 13:10:03 2015 -0400

----------------------------------------------------------------------
 Allura/allura/public/nf/css/navbar.css           | 12 +++++++++---
 Allura/allura/public/nf/js/navbar.es6.js         | 12 ++----------
 Allura/allura/templates/jinja_master/master.html |  2 +-
 3 files changed, 12 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e1f41c46/Allura/allura/public/nf/css/navbar.css
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/css/navbar.css b/Allura/allura/public/nf/css/navbar.css
index a5d24bc..8c28509 100644
--- a/Allura/allura/public/nf/css/navbar.css
+++ b/Allura/allura/public/nf/css/navbar.css
@@ -301,10 +301,15 @@ ul.dropdown .hover, ul.dropdown li:hover {
     color: rgb(85, 85, 85);
 }
 
+#add_tool_menu{
+    position: relative;
+    z-index: 1000;
+}
+
 .tool-card {
     width: 800px;
-    margin-left: 25px;
-    background-color: white;
+    /* margin-left: 25px; */
+    background-color: #CB6666;
     display: block;
     border: 1px solid #777;
     border-radius: 2px 2px 5px 5px;
@@ -313,6 +318,7 @@ ul.dropdown .hover, ul.dropdown li:hover {
     overflow: auto;
     right: 0;
     min-height: 21rem;
+    z-index: inherit;
 }
 
 .box-title {
@@ -382,7 +388,7 @@ ul.dropdown .hover, ul.dropdown li:hover {
 }
 
 .tool-info-right {
-    background: rgba(239, 239, 239, .7);
+    background: rgba(239, 239, 239, 1);
     width: 40%;
     height: 100%;
     right: 0;

http://git-wip-us.apache.org/repos/asf/allura/blob/e1f41c46/Allura/allura/public/nf/js/navbar.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js
index 5d62002..7d64b08 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -399,7 +399,7 @@ var InstallNewToolForm = React.createClass({
 var NewToolInfo = React.createClass({
     propTypes: {
         name: React.PropTypes.string,
-        description: React.PropTypes.description,
+        description: React.PropTypes.string,
         handleAddButton: React.PropTypes.func
     },
 
@@ -439,6 +439,7 @@ var NewToolMain = React.createClass({
 
     componentDidMount: function () {
         let _this = this;
+        console.log(_getProjectUrl() + "/admin/installable_tools/");
         $.get(_getProjectUrl(true) + "/admin/installable_tools/", function (result) {
             if (this.isMounted()) {
                 console.log('hit is mounted', result['tools']);
@@ -522,14 +523,6 @@ var NewToolMain = React.createClass({
 });
 
 
-
-
-
-
-
-
-
-
 ////////////////////////////////////////////
 
 /**
@@ -679,6 +672,5 @@ var Main = React.createClass({
     }
 });
 
-
    React.render(React.createElement(NewToolMain, {
         }), document.getElementById("add_tool_menu"));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/e1f41c46/Allura/allura/templates/jinja_master/master.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/master.html b/Allura/allura/templates/jinja_master/master.html
index bb03bf1..0032b74 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -27,7 +27,7 @@
 {% do g.register_forge_js('js/jquery.notify.js') %}
 {% do g.register_forge_js('js/browser-polyfill.js') %}
 {% do g.register_forge_js('js/underscore-min.js') %}
-{% do g.register_forge_js('js/react-with-addons.min.js') %}
+{% do g.register_forge_js('js/react-with-addons.js') %}
 {% do g.register_forge_js("js/react-drag.js") %}
 {% do g.register_forge_js('js/react-reorderable.js') %}
 {% do g.register_forge_js('js/jquery.tooltipster.js') %}


[20/47] allura git commit: [#7919] Add NavBar dependencies

Posted by br...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/db6e6859/Allura/allura/public/nf/js/underscore-min.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/underscore-min.js b/Allura/allura/public/nf/js/underscore-min.js
new file mode 100644
index 0000000..f01025b
--- /dev/null
+++ b/Allura/allura/public/nf/js/underscore-min.js
@@ -0,0 +1,6 @@
+//     Underscore.js 1.8.3
+//     http://underscorejs.org
+//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+//     Underscore may be freely distributed under the MIT license.
+(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.h
 asOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}}
 ,j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)
 &&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var
  a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.c
 all(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,
 r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.i
 ndexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.
 memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return func
 tion(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e
 ,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=
 function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t)
 ,i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))}
 ,m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n)
 .join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i
 ="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=f
 unction(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this);
+//# sourceMappingURL=underscore-min.map
\ No newline at end of file