You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by he...@apache.org on 2015/10/15 21:00:48 UTC

[01/42] allura git commit: Fix JS issue with subscriptions. Blog post subscribe action to say "post".

Repository: allura
Updated Branches:
  refs/heads/hs/7919 cc3ccae9f -> a5ab3d942 (forced update)


Fix JS issue with subscriptions. Blog post subscribe action to say "post".

Don't include subscriptions.js which needs react.js, when logged out. The
subscription widget only is meant for logged-in users.  And the template
which includes react.js is only included when logged in already.


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

Branch: refs/heads/hs/7919
Commit: bcf93e117a175c2fde54175df38defabee23fe2a
Parents: aa6e158
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Sep 28 17:52:00 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Sep 28 17:52:00 2015 -0400

----------------------------------------------------------------------
 Allura/allura/lib/widgets/subscriptions.py   | 4 +++-
 ForgeBlog/forgeblog/main.py                  | 2 +-
 ForgeBlog/forgeblog/templates/blog/post.html | 4 +++-
 3 files changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/bcf93e11/Allura/allura/lib/widgets/subscriptions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/subscriptions.py b/Allura/allura/lib/widgets/subscriptions.py
index c8d3dcd..4e3324a 100644
--- a/Allura/allura/lib/widgets/subscriptions.py
+++ b/Allura/allura/lib/widgets/subscriptions.py
@@ -17,6 +17,7 @@
 
 import ew as ew_core
 import ew.jinja2_ew as ew
+from pylons import tmpl_context as c
 
 from allura.lib import validators as V
 from allura.lib.widgets import form_fields as ffw
@@ -90,4 +91,5 @@ class SubscribeForm(ew.SimpleForm):
     def resources(self):
         for r in super(SubscribeForm, self).resources():
             yield r
-        yield ew.JSLink('js/subscriptions.js')
+        if not c.user.is_anonymous():
+            yield ew.JSLink('js/subscriptions.js')

http://git-wip-us.apache.org/repos/asf/allura/blob/bcf93e11/ForgeBlog/forgeblog/main.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index b4f4641..a3483cf 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -70,7 +70,7 @@ class W:
     attachment_add = ffw.AttachmentAdd()
     attachment_list = ffw.AttachmentList()
     preview_post_form = widgets.PreviewPostForm()
-    subscribe_form = SubscribeForm()
+    subscribe_form = SubscribeForm(thing='post')
     search_results = SearchResults()
     help_modal = SearchHelp()
 

http://git-wip-us.apache.org/repos/asf/allura/blob/bcf93e11/ForgeBlog/forgeblog/templates/blog/post.html
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/templates/blog/post.html b/ForgeBlog/forgeblog/templates/blog/post.html
index c0caad3..d0a3434 100644
--- a/ForgeBlog/forgeblog/templates/blog/post.html
+++ b/ForgeBlog/forgeblog/templates/blog/post.html
@@ -27,7 +27,9 @@
     <a href="edit" title="Edit"><b data-icon="{{g.icons['pencil'].char}}" class="ico {{g.icons['pencil'].css}}"></b></a>
   {% endif %}
   <a href="history" title="History"><b data-icon="{{g.icons['history'].char}}" class="ico {{g.icons['history'].css}}"></b></a>
-  {{c.subscribe_form.display(value=subscribed, action='subscribe', style='icon')}}
+  {% if c.user and c.user != c.user.anonymous() %}
+    {{c.subscribe_form.display(value=subscribed, action='subscribe', style='icon')}}
+  {% endif %}
   <a href="feed" title="RSS"><b data-icon="{{g.icons['feed'].char}}" class="ico {{g.icons['feed'].css}}"></b></a>
 {% endblock %}
 


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

Posted by he...@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/147f0592
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/147f0592
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/147f0592

Branch: refs/heads/hs/7919
Commit: 147f05920a880e6ba39fced17fa56aff9b5d7f55
Parents: 38a245a
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 12 14:58:14 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:19 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/147f0592/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({


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

Posted by he...@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/df5c88c2
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/df5c88c2
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/df5c88c2

Branch: refs/heads/hs/7919
Commit: df5c88c2e0631006c5ed0dd2280bd4cbb98c3df2
Parents: 967324b
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:44:49 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:18 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/df5c88c2/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 ac87d77..3d94d9c 100644
--- a/Allura/allura/templates/jinja_master/master.html
+++ b/Allura/allura/templates/jinja_master/master.html
@@ -104,6 +104,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 %}


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

Posted by he...@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/99d2ea94
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/99d2ea94
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/99d2ea94

Branch: refs/heads/hs/7919
Commit: 99d2ea943eb213f5f5409c4f218393edcb553e54
Parents: 147f059
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 15 14:56:38 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:19 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/99d2ea94/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/99d2ea94/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


[40/42] allura git commit: [#7919] Add react for development mode

Posted by he...@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/40dd7391
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/40dd7391
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/40dd7391

Branch: refs/heads/hs/7919
Commit: 40dd739189c1b918566310afa2b01a3adb2ac6e0
Parents: d21e238
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 14:26:41 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:19 2015 -0400

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



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

Posted by he...@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/3bb27f6b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/3bb27f6b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/3bb27f6b

Branch: refs/heads/hs/7919
Commit: 3bb27f6b028e46b9a541cd763c3e061b55bcf410
Parents: 0d8b355
Author: Heith Seewald <hs...@hsmb.local>
Authored: Wed Oct 7 14:38:40 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:18 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/3bb27f6b/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/3bb27f6b/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}
 


[22/42] allura git commit: [#7919] Add markup to support the NavBar

Posted by he...@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/d7823062
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d7823062
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d7823062

Branch: refs/heads/hs/7919
Commit: d7823062a217bf2e89080e6c100fa72af985edc1
Parents: 9475ba9
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:10:38 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:16 2015 -0400

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


http://git-wip-us.apache.org/repos/asf/allura/blob/d7823062/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..ac87d77 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.register_css('/nf/tool_icon_css?' + g.build_key, compress=False) %}
 {% do g.theme.require() %}
@@ -181,5 +188,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/d7823062/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..c433991 100644
--- a/Allura/allura/templates/jinja_master/top_nav.html
+++ b/Allura/allura/templates/jinja_master/top_nav.html
@@ -17,6 +17,10 @@
        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 %}">
@@ -35,3 +39,4 @@
 	{% endfor %}
 </ul>
 {% endif %}
+{% endif %}


[08/42] allura git commit: [#7980] don't time a removed and unused function

Posted by he...@apache.org.
[#7980] don't time a removed and unused function


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

Branch: refs/heads/hs/7919
Commit: 2bdcb95a3d8138cf6e917e78ec7ca069ce03b713
Parents: e5023ae
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Oct 1 10:33:34 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Oct 6 10:34:04 2015 +0000

----------------------------------------------------------------------
 Allura/allura/lib/custom_middleware.py | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/2bdcb95a/Allura/allura/lib/custom_middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 1938e51..fce19e5 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -322,7 +322,6 @@ class AlluraTimerMiddleware(TimerMiddleware):
             Timer('urlopen', urllib2, 'urlopen'),
             Timer('base_repo_tool.{method_name}',
                   allura.model.repository.RepositoryImplementation, 'last_commit_ids'),
-            Timer('unified_diff', allura.model.repository, 'unified_diff'),
         ] + [Timer('sidebar', ep.load(), 'sidebar_menu') for ep in tool_entry_points]
 
         try:


[27/42] allura git commit: [#7919] Add NavBar dependencies

Posted by he...@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/c456344c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/c456344c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/c456344c

Branch: refs/heads/hs/7919
Commit: c456344c37cbed070a541fc645ec8ece6218ac8a
Parents: 4a4984f
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:23:08 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:17 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(+)
----------------------------------------------------------------------



[16/42] allura git commit: [#7919] Add stylesheet for the admin navbar

Posted by he...@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/280fd2bd
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/280fd2bd
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/280fd2bd

Branch: refs/heads/hs/7919
Commit: 280fd2bd5097c655c3e70eb3ef1e0e30a802b738
Parents: bae38ad
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 02:57:13 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:15 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/280fd2bd/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;
+}


[38/42] allura git commit: [#7919] Add "Add new tool" feature

Posted by he...@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/d21e238e
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d21e238e
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d21e238e

Branch: refs/heads/hs/7919
Commit: d21e238ec42acc57bc275d0a8125e5687a70c95c
Parents: 788a8f4
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:59:23 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:19 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/d21e238e/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


[06/42] allura git commit: [#7980] Fix many pep8 / pyflakes and related issues

Posted by he...@apache.org.
[#7980] Fix many pep8 / pyflakes and related issues

* line length
* legit uses of has_key
* unused vars
* unused imports
* etc


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

Branch: refs/heads/hs/7919
Commit: 9d39b9a74cd64da27ec80f26fee992d6d763a07f
Parents: b79b854
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Sep 30 09:48:31 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Oct 6 10:34:02 2015 +0000

----------------------------------------------------------------------
 Allura/allura/command/__init__.py               |   5 +
 .../allura/command/create_trove_categories.py   |  66 ++++-----
 Allura/allura/controllers/__init__.py           |   8 +-
 Allura/allura/controllers/auth.py               |  12 +-
 Allura/allura/lib/helpers.py                    |  53 +++----
 Allura/allura/lib/widgets/__init__.py           |   4 +
 Allura/allura/lib/widgets/forms.py              |  40 +++--
 Allura/allura/model/__init__.py                 |  15 +-
 Allura/allura/model/repo.py                     |   5 +
 Allura/allura/model/repository.py               |  34 +++--
 Allura/allura/tests/functional/test_auth.py     | 105 +++++++------
 Allura/allura/tests/functional/test_discuss.py  |  30 ++--
 .../tests/functional/test_neighborhood.py       |  55 +++----
 Allura/allura/tests/functional/test_rest.py     |   6 +-
 .../tests/functional/test_user_profile.py       |   6 +-
 Allura/allura/tests/test_globals.py             |  34 +++--
 Allura/allura/tests/test_utils.py               |  22 +--
 Allura/allura/websetup/bootstrap.py             |  38 ++---
 Allura/setup.cfg                                |   6 +
 .../forgeactivity/tests/functional/test_rest.py |   6 +-
 .../forgeblog/tests/functional/test_rest.py     |   6 +-
 .../tests/functional/test_forum.py              |  92 ++++++------
 .../tests/functional/test_forum_admin.py        |  23 ++-
 .../tests/functional/test_rest.py               |  11 +-
 .../forgediscussion/widgets/__init__.py         |   4 +
 .../tests/functional/test_controllers.py        | 148 ++++++++-----------
 .../tests/google/test_extractor.py              |  23 ++-
 .../forgelink/tests/functional/test_rest.py     |   6 +-
 .../forgetracker/tests/functional/test_rest.py  |   6 +-
 .../forgetracker/tests/functional/test_root.py  |  77 +++++-----
 .../forgewiki/tests/functional/test_rest.py     |   6 +-
 .../forgewiki/tests/functional/test_root.py     |  23 ++-
 scripts/teamforge-import.py                     |  20 +--
 33 files changed, 499 insertions(+), 496 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/command/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/__init__.py b/Allura/allura/command/__init__.py
index 24254aa..0221b7b 100644
--- a/Allura/allura/command/__init__.py
+++ b/Allura/allura/command/__init__.py
@@ -22,3 +22,8 @@ from smtp_server import SMTPServerCommand
 from create_neighborhood import CreateNeighborhoodCommand, UpdateNeighborhoodCommand
 from create_trove_categories import CreateTroveCategoriesCommand
 from set_neighborhood_features import SetNeighborhoodFeaturesCommand
+
+__all__ = [
+    'Command', 'ShowModelsCommand', 'ReindexCommand', 'EnsureIndexCommand', 'ScriptCommand', 'SetToolAccessCommand',
+    'SMTPServerCommand', 'CreateNeighborhoodCommand', 'UpdateNeighborhoodCommand', 'CreateTroveCategoriesCommand',
+    'SetNeighborhoodFeaturesCommand']

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/command/create_trove_categories.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/create_trove_categories.py b/Allura/allura/command/create_trove_categories.py
index eba9244..288117c 100644
--- a/Allura/allura/command/create_trove_categories.py
+++ b/Allura/allura/command/create_trove_categories.py
@@ -233,7 +233,7 @@ class CreateTroveCategoriesCommand(base.Command):
                                "User Interface :: Toolkits/Libraries :: ClanLib", True))
         self.create_trove_cat(
             (516, 500, "db_group_objmap", "Project is a relational object mapper",
-             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a relational object mapper",
+             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a relational object mapper",  # nopep8
              True))
         self.create_trove_cat(
             (487, 458, "ui_ggi", "GGI", "User Interface :: Toolkits/Libraries :: GGI", True))
@@ -245,7 +245,7 @@ class CreateTroveCategoriesCommand(base.Command):
                                "User Interface :: Toolkits/Libraries :: wxWidgets", True))
         self.create_trove_cat(
             (511, 500, "db_group_mgmt", "Project is a database management tool",
-             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a database management tool",
+             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a database management tool",  # nopep8
              True))
         self.create_trove_cat(
             (479, 458, "ui_qt", "Qt", "User Interface :: Toolkits/Libraries :: Qt", True))
@@ -253,7 +253,7 @@ class CreateTroveCategoriesCommand(base.Command):
             (477, 458, "ui_gtk", "GTK+", "User Interface :: Toolkits/Libraries :: GTK+", True))
         self.create_trove_cat(
             (513, 500, "db_group_netdbms", "Project is a network-based DBMS (database system)",
-             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a network-based DBMS (database system)",
+             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a network-based DBMS (database system)",  # nopep8
              True))
         self.create_trove_cat(
             (228, 458, "newt", "Newt", "User Interface :: Toolkits/Libraries :: Newt", True))
@@ -261,7 +261,7 @@ class CreateTroveCategoriesCommand(base.Command):
                                "User Interface :: Toolkits/Libraries :: Curses/Ncurses", True))
         self.create_trove_cat(
             (515, 500, "db_group_conv", "Project is a database conversion tool",
-             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a database conversion tool",
+             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a database conversion tool",  # nopep8
              True))
         self.create_trove_cat(
             (478, 458, "ui_tk", "Tk", "User Interface :: Toolkits/Libraries :: Tk", True))
@@ -271,7 +271,7 @@ class CreateTroveCategoriesCommand(base.Command):
                                "Topic :: Communications :: Email :: Post-Office", True))
         self.create_trove_cat(
             (514, 500, "db_group_propfmt", "Project is a tool for a proprietary database file format",
-             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a tool for a proprietary database file format",
+             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a tool for a proprietary database file format",  # nopep8
              True))
         self.create_trove_cat(
             (482, 458, "ui_aalib", "AAlib", "User Interface :: Toolkits/Libraries :: AAlib", True))
@@ -279,7 +279,7 @@ class CreateTroveCategoriesCommand(base.Command):
             (484, 458, "ui_fltk", "FLTK", "User Interface :: Toolkits/Libraries :: FLTK", True))
         self.create_trove_cat(
             (512, 500, "db_group_filedbms", "Project is a file-based DBMS (database system)",
-             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a file-based DBMS (database system)",
+             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a file-based DBMS (database system)",  # nopep8
              True))
         self.create_trove_cat(
             (486, 458, "ui_plib", "Plib", "User Interface :: Toolkits/Libraries :: Plib", True))
@@ -287,7 +287,7 @@ class CreateTroveCategoriesCommand(base.Command):
             (488, 458, "ui_glide", "Glide", "User Interface :: Toolkits/Libraries :: Glide", True))
         self.create_trove_cat(
             (510, 500, "db_group_api", "Project is a database abstraction layer (API)",
-             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a database abstraction layer (API)",
+             "Database Environment :: Grouping and Descriptive Categories (DB) :: Project is a database abstraction layer (API)",  # nopep8
              True))
         self.create_trove_cat(
             (490, 458, "ui_glut", "GLUT", "User Interface :: Toolkits/Libraries :: GLUT", True))
@@ -828,14 +828,14 @@ class CreateTroveCategoriesCommand(base.Command):
             (441, 315, "ecos", "eCos", "Operating System :: Handheld/Embedded Operating Systems :: eCos", True))
         self.create_trove_cat(
             (
-            443, 315, "vxworks", "VxWorks", "Operating System :: Handheld/Embedded Operating Systems :: VxWorks", True))
+            443, 315, "vxworks", "VxWorks", "Operating System :: Handheld/Embedded Operating Systems :: VxWorks", True))  # nopep8
         self.create_trove_cat((444, 315, "symbianos", "SymbianOS",
                                "Operating System :: Handheld/Embedded Operating Systems :: SymbianOS", True))
         self.create_trove_cat(
             (442, 315, "qnx", "QNX", "Operating System :: Handheld/Embedded Operating Systems :: QNX", True))
         self.create_trove_cat(
             (
-            440, 315, "uclinux", "uClinux", "Operating System :: Handheld/Embedded Operating Systems :: uClinux", True))
+            440, 315, "uclinux", "uClinux", "Operating System :: Handheld/Embedded Operating Systems :: uClinux", True))  # nopep8
         self.create_trove_cat(
             (418, 199, "modern_oses", "Modern (Vendor-Supported) Desktop Operating Systems",
              "Operating System :: Modern (Vendor-Supported) Desktop Operating Systems", True))
@@ -871,13 +871,13 @@ class CreateTroveCategoriesCommand(base.Command):
             (634, 236, "console-platforms", "Console-based Platforms",
              "Operating System :: Other Operating Systems :: Console-based Platforms", True))
         self.create_trove_cat((637, 634, "sega-dreamcast", "Sega Dreamcast",
-                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Sega Dreamcast",
+                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Sega Dreamcast",  # nopep8
                                True))
         self.create_trove_cat((635, 634, "xbox", "Microsoft Xbox",
-                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Microsoft Xbox",
+                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Microsoft Xbox",  # nopep8
                                True))
         self.create_trove_cat((636, 634, "sony-ps2", "Sony Playstation 2",
-                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Sony Playstation 2",
+                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Sony Playstation 2",  # nopep8
                                True))
         self.create_trove_cat(
             (422, 236, "mswin_98", "Win98", "Operating System :: Other Operating Systems :: Win98", True))
@@ -923,11 +923,11 @@ class CreateTroveCategoriesCommand(base.Command):
              "Operating System :: Grouping and Descriptive Categories :: Project is OS Distribution-Specific", True))
         self.create_trove_cat(
             (449, 432, "eightbit_oses", "Classic 8-bit Operating Systems (Apple, Atari, Commodore, etc.)",
-             "Operating System :: Grouping and Descriptive Categories :: Classic 8-bit Operating Systems (Apple, Atari, Commodore, etc.)",
+             "Operating System :: Grouping and Descriptive Categories :: Classic 8-bit Operating Systems (Apple, Atari, Commodore, etc.)",  # nopep8
              True))
         self.create_trove_cat(
             (436, 432, "os_portable", "OS Portable (Source code to work with many OS platforms)",
-             "Operating System :: Grouping and Descriptive Categories :: OS Portable (Source code to work with many OS platforms)",
+             "Operating System :: Grouping and Descriptive Categories :: OS Portable (Source code to work with many OS platforms)",  # nopep8
              True))
         self.create_trove_cat(
             (438, 432, "os_projectdistro", "Project is an Operating System Distribution",
@@ -935,7 +935,7 @@ class CreateTroveCategoriesCommand(base.Command):
              True))
         self.create_trove_cat(
             (235, 432, "independent", "OS Independent (Written in an interpreted language)",
-             "Operating System :: Grouping and Descriptive Categories :: OS Independent (Written in an interpreted language)",
+             "Operating System :: Grouping and Descriptive Categories :: OS Independent (Written in an interpreted language)",  # nopep8
              True))
         self.create_trove_cat(
             (200, 432, "posix", "All POSIX (Linux/BSD/UNIX-like OSes)",
@@ -945,7 +945,7 @@ class CreateTroveCategoriesCommand(base.Command):
              "Operating System :: Grouping and Descriptive Categories :: 32-bit MS Windows (NT/2000/XP)", True))
         self.create_trove_cat(
             (202, 432, "bsd", "All BSD Platforms (FreeBSD/NetBSD/OpenBSD/Apple Mac OS X)",
-             "Operating System :: Grouping and Descriptive Categories :: All BSD Platforms (FreeBSD/NetBSD/OpenBSD/Apple Mac OS X)",
+             "Operating System :: Grouping and Descriptive Categories :: All BSD Platforms (FreeBSD/NetBSD/OpenBSD/Apple Mac OS X)",  # nopep8
              True))
         self.create_trove_cat(
             (435, 432, "mswin_all32bit", "All 32-bit MS Windows (95/98/NT/2000/XP)",
@@ -1107,7 +1107,7 @@ class CreateTroveCategoriesCommand(base.Command):
         self.create_trove_cat((57, 55, "kde", "K Desktop Environment (KDE)",
                                "Topic :: Desktop Environment :: K Desktop Environment (KDE)", True))
         self.create_trove_cat(
-            (61, 57, "themes", "Themes", "Topic :: Desktop Environment :: K Desktop Environment (KDE) :: Themes", True))
+            (61, 57, "themes", "Themes", "Topic :: Desktop Environment :: K Desktop Environment (KDE) :: Themes", True))  # nopep8
         self.create_trove_cat(
             (58, 55, "gnome", "Gnome", "Topic :: Desktop Environment :: Gnome", True))
         self.create_trove_cat((62, 55, "screensavers", "Screen Savers",
@@ -1473,7 +1473,7 @@ class CreateTroveCategoriesCommand(base.Command):
              "Operating System :: Modern (Vendor-Supported) Desktop Operating Systems :: Windows 7", True))
         self.create_trove_cat(
             (
-            728, 315, "android", "Android", "Operating System :: Handheld/Embedded Operating Systems :: Android", True))
+            728, 315, "android", "Android", "Operating System :: Handheld/Embedded Operating Systems :: Android", True))  # nopep8
         self.create_trove_cat((780, 315, "ios", "Apple iPhone",
                                "Operating System :: Handheld/Embedded Operating Systems :: Apple iPhone", True))
         self.create_trove_cat((863, 534, "architects", "Architects",
@@ -1564,7 +1564,7 @@ class CreateTroveCategoriesCommand(base.Command):
         self.create_trove_cat((673, 576, "bsm", "Business Service Management",
                                "Topic :: Office/Business :: Enterprise :: Business Service Management"))
         self.create_trove_cat((674, 673, "servicesupport", "Service Support",
-                               "Topic :: Office/Business :: Enterprise :: Business Service Management :: Service Support"))
+                               "Topic :: Office/Business :: Enterprise :: Business Service Management :: Service Support"))  # nopep8
         self.create_trove_cat(
             (675, 673, "serviceassurance", "Service Assurance",
              "Topic :: Office/Business :: Enterprise :: Business Service Management :: Service Assurance"))
@@ -1593,14 +1593,14 @@ class CreateTroveCategoriesCommand(base.Command):
              "License :: OSI-Approved Open Source :: Simple Public License 2.0"))
         self.create_trove_cat(
             (687, 673, "cmdb", "Configuration Management Database (CMDB)",
-             "Topic :: Office/Business :: Enterprise :: Business Service Management :: Configuration Management Database (CMDB)"))
+             "Topic :: Office/Business :: Enterprise :: Business Service Management :: Configuration Management Database (CMDB)"))  # nopep8
         self.create_trove_cat(
             (688, 18, "mobileapps", "Mobile", "Topic :: Mobile"))
         self.create_trove_cat((689, 315, "winmobile", "Windows Mobile",
                                "Operating System :: Handheld/Embedded Operating Systems :: Windows Mobile"))
         self.create_trove_cat(
             (690, 315, "brew", "BREW (Binary Runtime Environment for Wireless)",
-             "Operating System :: Handheld/Embedded Operating Systems :: BREW (Binary Runtime Environment for Wireless)"))
+             "Operating System :: Handheld/Embedded Operating Systems :: BREW (Binary Runtime Environment for Wireless)"))  # nopep8
         self.create_trove_cat(
             (691, 315, "j2me", "J2ME (Java Platform, Micro Edition)",
              "Operating System :: Handheld/Embedded Operating Systems :: J2ME (Java Platform, Micro Edition)"))
@@ -1658,16 +1658,16 @@ class CreateTroveCategoriesCommand(base.Command):
             (717, 160, "proglangmeta", "Project is a programming language",
              "Programming Language :: Project is a programming language"))
         self.create_trove_cat((718, 634, "msxb360", "Microsoft Xbox 360",
-                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Microsoft Xbox 360"))
+                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Microsoft Xbox 360"))  # nopep8
         self.create_trove_cat((719, 634, "nintendogc", "Nintendo GameCube",
-                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Nintendo GameCube"))
+                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Nintendo GameCube"))  # nopep8
         self.create_trove_cat((720, 634, "nintendowii", "Nintendo Wii",
-                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Nintendo Wii"))
+                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Nintendo Wii"))  # nopep8
         self.create_trove_cat((721, 634, "sonyps3", "Sony PlayStation 3",
-                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Sony PlayStation 3"))
+                               "Operating System :: Other Operating Systems :: Console-based Platforms :: Sony PlayStation 3"))  # nopep8
         self.create_trove_cat(
             (722, 634, "sonypsp", "Sony PlayStation Portable (PSP)",
-             "Operating System :: Other Operating Systems :: Console-based Platforms :: Sony PlayStation Portable (PSP)"))
+             "Operating System :: Other Operating Systems :: Console-based Platforms :: Sony PlayStation Portable (PSP)"))  # nopep8
         self.create_trove_cat(
             (723, 160, "scilab", "Scilab", "Programming Language :: Scilab"))
         self.create_trove_cat(
@@ -1685,10 +1685,10 @@ class CreateTroveCategoriesCommand(base.Command):
             (730, 274, "basque", "Basque (Euskara)", "Translations :: Basque (Euskara)"))
         self.create_trove_cat(
             (731, 14, "classpath", "GNU General Public License with Classpath exception (Classpath::License)",
-             "License :: OSI-Approved Open Source :: GNU General Public License with Classpath exception (Classpath::License)"))
+             "License :: OSI-Approved Open Source :: GNU General Public License with Classpath exception (Classpath::License)"))  # nopep8
         self.create_trove_cat(
             (732, 727, "caddcam", "Computer-aided technologies (CADD/CAM/CAE)",
-             "Topic :: Scientific/Engineering :: Mechanical and Civil Engineering :: Computer-aided technologies (CADD/CAM/CAE)"))
+             "Topic :: Scientific/Engineering :: Mechanical and Civil Engineering :: Computer-aided technologies (CADD/CAM/CAE)"))  # nopep8
         self.create_trove_cat((733, 576, "humanresources", "Human Resources",
                                "Topic :: Office/Business :: Enterprise :: Human Resources"))
         self.create_trove_cat(
@@ -1983,7 +1983,7 @@ class CreateTroveCategoriesCommand(base.Command):
         self.update_trove_cat(
             16, dict(
                 fullname="GNU Library or Lesser General Public License version 2.0 (LGPLv2)",
-                fullpath="License :: OSI-Approved Open Source :: GNU Library or Lesser General Public License version 2.0 (LGPLv2)"))
+                fullpath="License :: OSI-Approved Open Source :: GNU Library or Lesser General Public License version 2.0 (LGPLv2)"))  # nopep8
         self.update_trove_cat(
             15, dict(fullname="GNU General Public License version 2.0 (GPLv2)",
                      fullpath="License :: OSI-Approved Open Source :: GNU General Public License version 2.0 (GPLv2)"))
@@ -1995,16 +1995,16 @@ class CreateTroveCategoriesCommand(base.Command):
              "License :: Creative Commons Attribution License"))
         self.create_trove_cat(
             (869, 868, "ccaslv2", "Creative Commons Attribution ShareAlike License V2.0",
-             "License :: Creative Commons Attribution License :: Creative Commons Attribution ShareAlike License V2.0"))
+             "License :: Creative Commons Attribution License :: Creative Commons Attribution ShareAlike License V2.0"))  # nopep8
         self.create_trove_cat(
             (870, 868, "ccaslv3", "Creative Commons Attribution ShareAlike License V3.0",
-             "License :: Creative Commons Attribution License :: Creative Commons Attribution ShareAlike License V3.0"))
+             "License :: Creative Commons Attribution License :: Creative Commons Attribution ShareAlike License V3.0"))  # nopep8
         self.create_trove_cat(
             (871, 868, "ccanclv2", "Creative Commons Attribution Non-Commercial License V2.0",
-             "License :: Creative Commons Attribution License :: Creative Commons Attribution Non-Commercial License V2.0"))
+             "License :: Creative Commons Attribution License :: Creative Commons Attribution Non-Commercial License V2.0"))  # nopep8
         self.create_trove_cat(
             (680, 14, "lgplv3", "GNU Library or Lesser General Public License version 3.0 (LGPLv3)",
-             "License :: OSI-Approved Open Source :: GNU Library or Lesser General Public License version 3.0 (LGPLv3)"))
+             "License :: OSI-Approved Open Source :: GNU Library or Lesser General Public License version 3.0 (LGPLv3)"))  # nopep8
         self.create_trove_cat(
             (679, 14, "gplv3", "GNU General Public License version 3.0 (GPLv3)",
              "License :: OSI-Approved Open Source :: GNU General Public License version 3.0 (GPLv3)"))

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/controllers/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/__init__.py b/Allura/allura/controllers/__init__.py
index a69bafb..417b8ad 100644
--- a/Allura/allura/controllers/__init__.py
+++ b/Allura/allura/controllers/__init__.py
@@ -18,6 +18,10 @@
 #       under the License.
 
 """Controllers for the allura application."""
-from .discuss import DiscussionController, AppDiscussionController, ThreadController, PostController, ModerationController
-from .discuss import AppDiscussionRestController
+from .discuss import DiscussionController, AppDiscussionController, ThreadController, PostController
+from .discuss import ModerationController, AppDiscussionRestController
 from .base import BaseController, DispatchIndex
+
+__all__ = [
+    'DiscussionController', 'AppDiscussionController', 'ThreadController', 'PostController', 'ModerationController',
+    'AppDiscussionRestController', 'BaseController', 'DispatchIndex']

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index f4f03c9..e3c4d38 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -51,6 +51,7 @@ from allura.controllers import BaseController
 
 log = logging.getLogger(__name__)
 
+
 class F(object):
     login_form = LoginForm()
     password_change_form = forms.PasswordChangeForm(action='/auth/preferences/change_password')
@@ -183,20 +184,19 @@ class AuthController(BaseController):
         user_record = M.User.by_email_address(email)
         allow_non_primary_email_reset = asbool(config.get('auth.allow_non_primary_email_password_reset', True))
 
-
         if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
             flash('Enter email in correct format!','error')
             redirect('/auth/forgotten_password')
 
         if not allow_non_primary_email_reset:
-            message = 'If the given email address is on record, a password reset email has been sent to the account\'s primary email address.'
+            message = 'If the given email address is on record, '\
+                      'a password reset email has been sent to the account\'s primary email address.'
             email_record = M.EmailAddress.get(email=provider.get_primary_email_address(user_record=user_record),
                                                     confirmed=True)
         else:
             message = 'A password reset email has been sent, if the given email address is on record in our system.'
             email_record = M.EmailAddress.get(email=email, confirmed=True)
 
-
         if user_record and email_record and email_record.confirmed:
             hash = h.nonce(42)
             user_record.set_tool_data('AuthPasswordReset',
@@ -459,10 +459,8 @@ class PreferencesController(BaseController):
         # not using **kw in method signature, to ensure 'admin' can't be passed in via a form submit
         kw = form_params
         addr = kw.pop('addr', None)
-        new_addr= kw.pop('new_addr', None)
+        new_addr = kw.pop('new_addr', None)
         primary_addr = kw.pop('primary_addr', None)
-        oid = kw.pop('oid', None)
-        new_oid = kw.pop('new_oid', None)
         provider = plugin.AuthenticationProvider.get(request)
         for i, (old_a, data) in enumerate(zip(user.email_addresses, addr or [])):
             obj = user.address_object(old_a)
@@ -1011,7 +1009,7 @@ class OAuthController(BaseController):
             validation_pin=h.nonce(20),
             is_bearer=True,
         )
-        access_token = M.OAuthAccessToken(
+        M.OAuthAccessToken(
             consumer_token_id=consumer_token._id,
             request_token_id=c.user._id,
             user_id=request_token.user_id,

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 68330ba..bf5a580 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -133,9 +133,11 @@ def make_safe_path_portion(ustr, relaxed=True):
     s = s.replace('--', '-')
     return s
 
+
 def escape_json(data):
     return json.dumps(data).replace('<', '\u003C')
 
+
 def monkeypatch(*objs):
     def patchem(func):
         for obj in objs:
@@ -695,9 +697,9 @@ def paging_sanitizer(limit, page, total_count, zero_based_pages=True):
     return limit, page
 
 
-def _add_inline_line_numbers_to_text(text):
+def _add_inline_line_numbers_to_text(txt):
     markup_text = '<div class="codehilite"><pre>'
-    for line_num, line in enumerate(text.splitlines(), 1):
+    for line_num, line in enumerate(txt.splitlines(), 1):
         markup_text = markup_text + \
             '<span id="l%s" class="code_block"><span class="lineno">%s</span> %s</span>' % (
                 line_num, line_num, line)
@@ -705,7 +707,7 @@ def _add_inline_line_numbers_to_text(text):
     return markup_text
 
 
-def _add_table_line_numbers_to_text(text):
+def _add_table_line_numbers_to_text(txt):
     def _prepend_whitespaces(num, max_num):
         num, max_num = str(num), str(max_num)
         diff = len(max_num) - len(num)
@@ -715,7 +717,7 @@ def _add_table_line_numbers_to_text(text):
         max_num = l + start
         return '\n'.join(map(_prepend_whitespaces, range(start, max_num), [max_num] * l))
 
-    lines = text.splitlines(True)
+    lines = txt.splitlines(True)
     linenumbers = '<td class="linenos"><div class="linenodiv"><pre>' + \
         _len_to_str_column(len(lines)) + '</pre></div></td>'
     markup_text = '<table class="codehilitetable"><tbody><tr>' + \
@@ -731,28 +733,28 @@ INLINE = 'inline'
 TABLE = 'table'
 
 
-def render_any_markup(name, text, code_mode=False, linenumbers_style=TABLE):
+def render_any_markup(name, txt, code_mode=False, linenumbers_style=TABLE):
     """
     renders markdown using allura enhacements if file is in markdown format
     renders any other markup format using the pypeline
     Returns jinja-safe text
     """
-    if text == '':
-        text = '<p><em>Empty File</em></p>'
+    if txt == '':
+        txt = '<p><em>Empty File</em></p>'
     else:
         fmt = g.pypeline_markup.can_render(name)
         if fmt == 'markdown':
-            text = g.markdown.convert(text)
+            txt = g.markdown.convert(txt)
         else:
-            text = g.pypeline_markup.render(name, text)
+            txt = g.pypeline_markup.render(name, txt)
         if not fmt:
             if code_mode and linenumbers_style == INLINE:
-                text = _add_inline_line_numbers_to_text(text)
+                txt = _add_inline_line_numbers_to_text(txt)
             elif code_mode and linenumbers_style == TABLE:
-                text = _add_table_line_numbers_to_text(text)
+                txt = _add_table_line_numbers_to_text(txt)
             else:
-                text = '<pre>%s</pre>' % text
-    return Markup(text)
+                txt = '<pre>%s</pre>' % txt
+    return Markup(txt)
 
 # copied from jinja2 dev
 # latest release, 2.6, implements this incorrectly
@@ -1053,28 +1055,28 @@ def urlopen(url, retries=3, codes=(408, 500, 502, 503, 504), timeout=None):
                 raise e
 
 
-def plain2markdown(text, preserve_multiple_spaces=False, has_html_entities=False):
+def plain2markdown(txt, preserve_multiple_spaces=False, has_html_entities=False):
     if not has_html_entities:
         # prevent &foo; and &#123; from becoming HTML entities
-        text = re_amp.sub('&amp;', text)
+        txt = re_amp.sub('&amp;', txt)
     # avoid accidental 4-space indentations creating code blocks
     if preserve_multiple_spaces:
-        text = text.replace('\t', ' ' * 4)
-        text = re_preserve_spaces.sub('&nbsp;', text)
+        txt = txt.replace('\t', ' ' * 4)
+        txt = re_preserve_spaces.sub('&nbsp;', txt)
     else:
-        text = re_leading_spaces.sub('', text)
+        txt = re_leading_spaces.sub('', txt)
     try:
         # try to use html2text for most of the escaping
         import html2text
         html2text.BODY_WIDTH = 0
-        text = html2text.escape_md_section(text, snob=True)
+        txt = html2text.escape_md_section(txt, snob=True)
     except ImportError:
         # fall back to just escaping any MD-special chars
-        text = md_chars_matcher_all.sub(r"\\\1", text)
+        txt = md_chars_matcher_all.sub(r"\\\1", txt)
     # prevent < and > from becoming tags
-    text = re_angle_bracket_open.sub('&lt;', text)
-    text = re_angle_bracket_close.sub('&gt;', text)
-    return text
+    txt = re_angle_bracket_open.sub('&lt;', txt)
+    txt = re_angle_bracket_close.sub('&gt;', txt)
+    return txt
 
 
 def iter_entry_points(group, *a, **kw):
@@ -1166,7 +1168,7 @@ def login_overlay(exceptions=None):
     """
     try:
         yield
-    except HTTPUnauthorized as e:
+    except HTTPUnauthorized:
         if exceptions:
             for exception in exceptions:
                 if request.path.rstrip('/').endswith('/%s' % exception):
@@ -1251,7 +1253,6 @@ def rate_limit(cfg_opt, artifact_count, start_date, exception=None):
     now = datetime.utcnow()
     for rate, count in rate_limits.items():
         age = now - start_date
-        age = (age.microseconds +
-                (age.seconds + age.days * 24 * 3600) * 10 ** 6) / 10 ** 6
+        age = (age.microseconds + (age.seconds + age.days * 24 * 3600) * 10 ** 6) / 10 ** 6
         if age < int(rate) and artifact_count >= count:
             raise exception()

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/lib/widgets/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/__init__.py b/Allura/allura/lib/widgets/__init__.py
index 6e13a39..9d21e37 100644
--- a/Allura/allura/lib/widgets/__init__.py
+++ b/Allura/allura/lib/widgets/__init__.py
@@ -20,3 +20,7 @@ from .subscriptions import SubscriptionForm
 from .oauth_widgets import OAuthApplicationForm, OAuthRevocationForm
 from .auth_widgets import LoginForm, ForgottenPasswordForm, DisableAccountForm
 from .vote import VoteForm
+
+__all__ = [
+    'Post', 'Thread', 'Discussion', 'SubscriptionForm', 'OAuthApplicationForm', 'OAuthRevocationForm', 'LoginForm',
+    'ForgottenPasswordForm', 'DisableAccountForm', 'VoteForm']

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/lib/widgets/forms.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index cfbad2c..5d35788 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -18,7 +18,6 @@
 import logging
 import warnings
 
-from collections import defaultdict
 from pylons import app_globals as g, tmpl_context as c
 from formencode import validators as fev
 import formencode
@@ -686,13 +685,12 @@ class SelectSubCategoryForm(ForgeForm):
     def display(self, **kw):
         categories = kw.get('categories')
 
-        self.fields['selected_category'].options = \
-            [ew.Option(py_value=el.trove_cat_id, label=el.fullname)
-             for el in categories]
-        self.fields['selected_category'].validator = \
-            validator = formencode.All(
-                V.OneOfValidator(categories),
-                fev.UnicodeString(not_empty=True))
+        self.fields['selected_category'].options = [
+            ew.Option(py_value=el.trove_cat_id, label=el.fullname) for el in categories
+        ]
+        self.fields['selected_category'].validator = formencode.All(
+            V.OneOfValidator(categories),
+            fev.UnicodeString(not_empty=True))
         return super(ForgeForm, self).display(**kw)
 
 
@@ -830,18 +828,19 @@ class NeighborhoodOverviewForm(ForgeForm):
                 empty_val = False
                 if inp['value'] is None or inp['value'] == '':
                     empty_val = True
-                display += '<tr><td class="left"><label>%(label)s</label></td>'\
-                           '<td><input type="checkbox" name="%(ctx_name)s-%(inp_name)s-def" %(def_checked)s>default</td>'\
-                           '<td class="right"><div class="%(ctx_name)s-%(inp_name)s-inp"><table class="input_inner">'\
-                           '<tr><td><input type="text" class="%(inp_type)s" name="%(ctx_name)s-%(inp_name)s" '\
-                           'value="%(inp_value)s"></td><td>%(inp_additional)s</td></tr></table></div></td></tr>\n' % {'ctx_id': ctx['id'],
-                                                                                                                      'ctx_name': ctx['name'],
-                                                                                                                      'inp_name': inp['name'],
-                                                                                                                      'inp_value': inp['value'],
-                                                                                                                      'label': inp['label'],
-                                                                                                                      'inp_type': inp['type'],
-                                                                                                                      'def_checked': 'checked="checked"' if empty_val else '',
-                                                                                                                      'inp_additional': additional_inputs}
+                display += '<tr><td class="left"><label>%(label)s</label></td>' \
+                           '<td><input type="checkbox" name="%(ctx_name)s-%(inp_name)s-def" %(def_checked)s>default</td>' \
+                           '<td class="right"><div class="%(ctx_name)s-%(inp_name)s-inp"><table class="input_inner">' \
+                           '<tr><td><input type="text" class="%(inp_type)s" name="%(ctx_name)s-%(inp_name)s" ' \
+                           'value="%(inp_value)s"></td><td>%(inp_additional)s</td></tr></table></div></td></tr>\n' % {
+                               'ctx_id': ctx['id'],
+                               'ctx_name': ctx['name'],
+                               'inp_name': inp['name'],
+                               'inp_value': inp['value'],
+                               'label': inp['label'],
+                               'inp_type': inp['type'],
+                               'def_checked': 'checked="checked"' if empty_val else '',
+                               'inp_additional': additional_inputs}
             display += '</table>'
 
             if ctx['errors'] and field.show_errors and not ignore_errors:
@@ -1105,7 +1104,6 @@ class AwardGrantForm(ForgeForm):
         self._project_select_url = kw.pop('project_select_url', '')
         super(AwardGrantForm, self).__init__(*args, **kw)
 
-
     def award_options(self):
         return [ew.Option(py_value=a.short, label=a.short) for a in self._awards]
 

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/model/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/__init__.py b/Allura/allura/model/__init__.py
index 784d1af..cb817b4 100644
--- a/Allura/allura/model/__init__.py
+++ b/Allura/allura/model/__init__.py
@@ -22,7 +22,8 @@
 from .neighborhood import Neighborhood, NeighborhoodFile
 from .project import Project, ProjectCategory, TroveCategory, ProjectFile, AppConfig
 from .index import ArtifactReference, Shortlink
-from .artifact import Artifact, MovedArtifact, Message, VersionedArtifact, Snapshot, Feed, AwardFile, Award, AwardGrant, VotableArtifact
+from .artifact import Artifact, MovedArtifact, Message, VersionedArtifact, Snapshot, Feed, AwardFile, Award, AwardGrant
+from .artifact import VotableArtifact
 from .discuss import Discussion, Thread, PostHistory, Post, DiscussionAttachment
 from .attachments import BaseAttachment
 from .auth import AuthGlobals, User, ProjectRole, EmailAddress, OldProjectRole
@@ -48,3 +49,15 @@ from . import repo_refresh
 
 from ming.orm import Mapper
 Mapper.compile_all()
+
+__all__ = [
+    'Neighborhood', 'NeighborhoodFile', 'Project', 'ProjectCategory', 'TroveCategory', 'ProjectFile', 'AppConfig',
+    'ArtifactReference', 'Shortlink', 'Artifact', 'MovedArtifact', 'Message', 'VersionedArtifact', 'Snapshot', 'Feed',
+    'AwardFile', 'Award', 'AwardGrant', 'VotableArtifact', 'Discussion', 'Thread', 'PostHistory', 'Post',
+    'DiscussionAttachment', 'BaseAttachment', 'AuthGlobals', 'User', 'ProjectRole', 'EmailAddress', 'OldProjectRole',
+    'AuditLog', 'audit_log', 'AlluraUserProperty', 'File', 'Notification', 'Mailbox', 'Repository',
+    'RepositoryImplementation', 'MergeRequest', 'GitLikeTree', 'Stats', 'OAuthToken', 'OAuthConsumerToken',
+    'OAuthRequestToken', 'OAuthAccessToken', 'MonQTask', 'Webhook', 'ACE', 'ACL', 'EVERYONE', 'ALL_PERMISSIONS',
+    'DENY_ALL', 'MarkdownCache', 'main_doc_session', 'main_orm_session', 'project_doc_session', 'project_orm_session',
+    'artifact_orm_session', 'repository_orm_session', 'task_orm_session', 'ArtifactSessionExtension', 'repository',
+    'repo_refresh', ]

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/model/repo.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/repo.py b/Allura/allura/model/repo.py
index f041116..6ba6633 100644
--- a/Allura/allura/model/repo.py
+++ b/Allura/allura/model/repo.py
@@ -24,3 +24,8 @@ from .repository import QSIZE, README_RE, VIEWABLE_EXTENSIONS, PYPELINE_EXTENSIO
 from .repository import CommitDoc, TreeDoc, LastCommitDoc, TreesDoc, CommitRunDoc
 from .repository import RepoObject, Commit, Tree, Blob, LastCommit
 from .repository import ModelCache
+
+__all__ = [
+    'SUser', 'SObjType', 'QSIZE', 'README_RE', 'VIEWABLE_EXTENSIONS', 'PYPELINE_EXTENSIONS',
+    'DIFF_SIMILARITY_THRESHOLD', 'CommitDoc', 'TreeDoc', 'LastCommitDoc', 'TreesDoc', 'CommitRunDoc', 'RepoObject',
+    'Commit', 'Tree', 'Blob', 'LastCommit', 'ModelCache']

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/model/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 77c3fc4..75ed2dc 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -30,7 +30,7 @@ from urlparse import urljoin
 from threading import Thread
 from Queue import Queue
 from itertools import chain
-from difflib import SequenceMatcher, unified_diff
+from difflib import SequenceMatcher
 
 import tg
 from paste.deploy.converters import asint, asbool
@@ -56,7 +56,7 @@ from .timeline import ActivityObject
 from .monq_model import MonQTask
 from .project import AppConfig
 from .session import main_doc_session
-from .session import repository_orm_session, artifact_orm_session
+from .session import repository_orm_session
 
 
 log = logging.getLogger(__name__)
@@ -78,18 +78,20 @@ SObjType = S.OneOf('blob', 'tree', 'submodule')
 # Used for when we're going to batch queries using $in
 QSIZE = 100
 BINARY_EXTENSIONS = frozenset([
-    ".3ds", ".3g2", ".3gp", ".7z", ".a", ".aac", ".adp", ".ai", ".aif", ".apk", ".ar", ".asf", ".au", ".avi",
-    ".bak", ".bin", ".bk", ".bmp", ".btif", ".bz2", ".cab", ".caf", ".cgm", ".cmx", ".cpio", ".cr2", ".dat", ".deb", ".djvu", ".dll",
-    ".dmg", ".dng", ".doc", ".docx", ".dra", ".DS_Store", ".dsk", ".dts", ".dtshd", ".dvb", ".dwg", ".dxf", ".ecelp4800",
-    ".ecelp7470", ".ecelp9600", ".egg", ".eol", ".eot", ".epub", ".exe", ".f4v", ".fbs", ".fh", ".fla", ".flac", ".fli", ".flv",
-    ".fpx", ".fst", ".fvt", ".g3", ".gif", ".gz", ".h261", ".h263", ".h264", ".ico", ".ief", ".img", ".ipa", ".iso", ".jar", ".jpeg",
-    ".jpg", ".jpgv", ".jpm", ".jxr", ".ktx", ".lvp", ".lz", ".lzma", ".lzo", ".m3u", ".m4a", ".m4v", ".mar", ".mdi", ".mid", ".mj2",
-    ".mka", ".mkv", ".mmr", ".mng", ".mov", ".movie", ".mp3", ".mp4", ".mp4a", ".mpeg", ".mpg", ".mpga", ".mxu", ".nef", ".npx", ".o",
-    ".oga", ".ogg", ".ogv", ".otf", ".pbm", ".pcx", ".pdf", ".pea", ".pgm", ".pic", ".png", ".pnm", ".ppm", ".psd", ".pya", ".pyc",
-    ".pyo", ".pyv", ".qt", ".rar", ".ras", ".raw", ".rgb", ".rip", ".rlc", ".rz", ".s3m", ".s7z", ".scpt", ".sgi", ".shar", ".sil",
-    ".smv", ".so", ".sub", ".swf", ".tar", ".tbz2", ".tga", ".tgz", ".tif", ".tiff", ".tlz", ".ts", ".ttf", ".uvh", ".uvi", ".uvm",
-    ".uvp", ".uvs", ".uvu", ".viv", ".vob", ".war", ".wav", ".wax", ".wbmp", ".wdp", ".weba", ".webm", ".webp", ".whl", ".wm", ".wma",
-    ".wmv", ".wmx", ".woff", ".woff2", ".wvx", ".xbm", ".xif", ".xm", ".xpi", ".xpm", ".xwd", ".xz", ".z", ".zip", ".zipx"
+    ".3ds", ".3g2", ".3gp", ".7z", ".a", ".aac", ".adp", ".ai", ".aif", ".apk", ".ar", ".asf", ".au", ".avi", ".bak",
+    ".bin", ".bk", ".bmp", ".btif", ".bz2", ".cab", ".caf", ".cgm", ".cmx", ".cpio", ".cr2", ".dat", ".deb", ".djvu",
+    ".dll", ".dmg", ".dng", ".doc", ".docx", ".dra", ".DS_Store", ".dsk", ".dts", ".dtshd", ".dvb", ".dwg", ".dxf",
+    ".ecelp4800", ".ecelp7470", ".ecelp9600", ".egg", ".eol", ".eot", ".epub", ".exe", ".f4v", ".fbs", ".fh", ".fla",
+    ".flac", ".fli", ".flv", ".fpx", ".fst", ".fvt", ".g3", ".gif", ".gz", ".h261", ".h263", ".h264", ".ico", ".ief",
+    ".img", ".ipa", ".iso", ".jar", ".jpeg", ".jpg", ".jpgv", ".jpm", ".jxr", ".ktx", ".lvp", ".lz", ".lzma", ".lzo",
+    ".m3u", ".m4a", ".m4v", ".mar", ".mdi", ".mid", ".mj2", ".mka", ".mkv", ".mmr", ".mng", ".mov", ".movie", ".mp3",
+    ".mp4", ".mp4a", ".mpeg", ".mpg", ".mpga", ".mxu", ".nef", ".npx", ".o", ".oga", ".ogg", ".ogv", ".otf", ".pbm",
+    ".pcx", ".pdf", ".pea", ".pgm", ".pic", ".png", ".pnm", ".ppm", ".psd", ".pya", ".pyc", ".pyo", ".pyv", ".qt",
+    ".rar", ".ras", ".raw", ".rgb", ".rip", ".rlc", ".rz", ".s3m", ".s7z", ".scpt", ".sgi", ".shar", ".sil", ".smv",
+    ".so", ".sub", ".swf", ".tar", ".tbz2", ".tga", ".tgz", ".tif", ".tiff", ".tlz", ".ts", ".ttf", ".uvh", ".uvi",
+    ".uvm", ".uvp", ".uvs", ".uvu", ".viv", ".vob", ".war", ".wav", ".wax", ".wbmp", ".wdp", ".weba", ".webm", ".webp",
+    ".whl", ".wm", ".wma", ".wmv", ".wmx", ".woff", ".woff2", ".wvx", ".xbm", ".xif", ".xm", ".xpi", ".xpm", ".xwd",
+    ".xz", ".z", ".zip", ".zipx"
 ])
 
 PYPELINE_EXTENSIONS = frozenset(utils.MARKDOWN_EXTENSIONS + ['.rst'])
@@ -895,7 +897,7 @@ class MergeRequest(VersionedArtifact, ActivityObject):
             'state': {'$in': ['busy', 'complete', 'error', 'ready']},  # needed to use index
             'task_name': 'allura.tasks.repo_tasks.merge',
             'args': [self._id],
-            'time_queue': {'$gt': datetime.utcnow() - timedelta(days=1)}, # constrain on index further
+            'time_queue': {'$gt': datetime.utcnow() - timedelta(days=1)},  # constrain on index further
         }).sort('_id', -1).limit(1).first()
         if task:
             return task.state
@@ -906,7 +908,7 @@ class MergeRequest(VersionedArtifact, ActivityObject):
             'state': {'$in': ['busy', 'complete', 'error', 'ready']},  # needed to use index
             'task_name': 'allura.tasks.repo_tasks.can_merge',
             'args': [self._id],
-            'time_queue': {'$gt': datetime.utcnow() - timedelta(days=1)}, # constrain on index further
+            'time_queue': {'$gt': datetime.utcnow() - timedelta(days=1)},  # constrain on index further
         }).sort('_id', -1).limit(1).first()
         if task:
             return task.state

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 388be1a..5ad86ea 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -1063,7 +1063,7 @@ class TestPreferences(TestController):
                               weekday=weekday2,
                               starttime=starttime2.strftime('%H:%M'),
                               endtime=endtime2.strftime('%H:%M'),
-                            _session_id=self.app.cookies['_session_id'],
+                              _session_id=self.app.cookies['_session_id'],
                           ))
         user = M.User.query.get(username='test-admin')
         timeslot2dict = dict(week_day=weekday2,
@@ -1159,14 +1159,14 @@ class TestPreferences(TestController):
         skill_cat = M.TroveCategory.query.get(show_as_skill=True)
         level = 'low'
         comment = 'test comment'
-        result = self.app.get('/auth/user_info/skills/')
-        r = self.app.post('/auth/user_info/skills/save_skill',
-                          params=dict(
-                              level=level,
-                              comment=comment,
-                              selected_skill=str(skill_cat.trove_cat_id),
-                              _session_id=self.app.cookies['_session_id'],
-                          ))
+        self.app.get('/auth/user_info/skills/')
+        self.app.post('/auth/user_info/skills/save_skill',
+                      params=dict(
+                          level=level,
+                          comment=comment,
+                          selected_skill=str(skill_cat.trove_cat_id),
+                          _session_id=self.app.cookies['_session_id'],
+                      ))
         user = M.User.query.get(username='test-admin')
         skilldict = dict(category_id=skill_cat._id,
                          comment=comment, level=level)
@@ -1175,14 +1175,14 @@ class TestPreferences(TestController):
         # Add again the same skill
         level = 'medium'
         comment = 'test comment 2'
-        result = self.app.get('/auth/user_info/skills/')
-        r = self.app.post('/auth/user_info/skills/save_skill',
-                          params=dict(
-                              level=level,
-                              comment=comment,
-                              selected_skill=str(skill_cat.trove_cat_id),
-                              _session_id=self.app.cookies['_session_id'],
-                          ))
+        self.app.get('/auth/user_info/skills/')
+        self.app.post('/auth/user_info/skills/save_skill',
+                      params=dict(
+                          level=level,
+                          comment=comment,
+                          selected_skill=str(skill_cat.trove_cat_id),
+                          _session_id=self.app.cookies['_session_id'],
+                      ))
         user = M.User.query.get(username='test-admin')
         skilldict = dict(category_id=skill_cat._id,
                          comment=comment, level=level)
@@ -1191,13 +1191,13 @@ class TestPreferences(TestController):
         # Add an invalid skill
         level2 = 'not a level'
         comment2 = 'test comment 2'
-        r = self.app.post('/auth/user_info/skills/save_skill',
-                          params=dict(
-                              level=level2,
-                              comment=comment2,
-                              selected_skill=str(skill_cat.trove_cat_id),
-                              _session_id=self.app.cookies['_session_id'],
-                          ))
+        self.app.post('/auth/user_info/skills/save_skill',
+                      params=dict(
+                          level=level2,
+                          comment=comment2,
+                          selected_skill=str(skill_cat.trove_cat_id),
+                          _session_id=self.app.cookies['_session_id'],
+                      ))
         user = M.User.query.get(username='test-admin')
         # Check that everything is as it was before
         assert len(user.skills) == 1 and skilldict in user.skills
@@ -1450,13 +1450,13 @@ class TestOAuth(TestController):
     def test_interactive(self, Request, Server):
         M.OAuthConsumerToken.consumer = mock.Mock()
         user = M.User.by_username('test-admin')
-        consumer_token = M.OAuthConsumerToken(
+        M.OAuthConsumerToken(
             api_key='api_key',
             user_id=user._id,
             description='ctok_desc',
         )
         ThreadLocalORMSession.flush_all()
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key',
             'oauth_callback': 'http://my.domain.com/callback',
         }
@@ -1467,7 +1467,7 @@ class TestOAuth(TestController):
         r = r.forms[0].submit('yes')
         assert r.location.startswith('http://my.domain.com/callback')
         pin = parse_qs(urlparse(r.location).query)['oauth_verifier'][0]
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key',
             'oauth_token': rtok,
             'oauth_verifier': pin,
@@ -1502,10 +1502,10 @@ class TestOAuth(TestController):
     @mock.patch('allura.controllers.rest.oauth.Server')
     @mock.patch('allura.controllers.rest.oauth.Request')
     def test_request_token_no_consumer_token(self, Request, Server):
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key'}
-        r = self.app.post('/rest/oauth/request_token',
-                          params={'key': 'value'}, status=403)
+        self.app.post('/rest/oauth/request_token',
+                      params={'key': 'value'}, status=403)
 
     @mock.patch('allura.controllers.rest.oauth.Server')
     @mock.patch('allura.controllers.rest.oauth.Request')
@@ -1513,12 +1513,12 @@ class TestOAuth(TestController):
         Server().verify_request.side_effect = ValueError
         M.OAuthConsumerToken.consumer = mock.Mock()
         user = M.User.by_username('test-user')
-        consumer_token = M.OAuthConsumerToken(
+        M.OAuthConsumerToken(
             api_key='api_key',
             user_id=user._id,
         )
         ThreadLocalORMSession.flush_all()
-        req = Request.from_request.return_value = {'oauth_consumer_key': 'api_key'}
+        Request.from_request.return_value = {'oauth_consumer_key': 'api_key'}
         self.app.post('/rest/oauth/request_token', params={'key': 'value'}, status=403)
 
     def test_authorize_ok(self):
@@ -1528,7 +1528,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='oob',
@@ -1549,7 +1549,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='oob',
@@ -1567,7 +1567,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='oob',
@@ -1584,7 +1584,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='http://my.domain.com/callback',
@@ -1601,7 +1601,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='http://my.domain.com/callback?myparam=foo',
@@ -1613,7 +1613,7 @@ class TestOAuth(TestController):
 
     @mock.patch('allura.controllers.rest.oauth.Request')
     def test_access_token_no_consumer(self, Request):
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key',
             'oauth_token': 'api_key',
             'oauth_verifier': 'good',
@@ -1622,13 +1622,13 @@ class TestOAuth(TestController):
 
     @mock.patch('allura.controllers.rest.oauth.Request')
     def test_access_token_no_request(self, Request):
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key',
             'oauth_token': 'api_key',
             'oauth_verifier': 'good',
         }
         user = M.User.by_username('test-admin')
-        ctok = M.OAuthConsumerToken(
+        M.OAuthConsumerToken(
             api_key='api_key',
             user_id=user._id,
             description='ctok_desc',
@@ -1638,7 +1638,7 @@ class TestOAuth(TestController):
 
     @mock.patch('allura.controllers.rest.oauth.Request')
     def test_access_token_bad_pin(self, Request):
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key',
             'oauth_token': 'api_key',
             'oauth_verifier': 'bad',
@@ -1649,7 +1649,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='http://my.domain.com/callback?myparam=foo',
@@ -1662,7 +1662,7 @@ class TestOAuth(TestController):
     @mock.patch('allura.controllers.rest.oauth.Server')
     @mock.patch('allura.controllers.rest.oauth.Request')
     def test_access_token_bad_sig(self, Request, Server):
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key',
             'oauth_token': 'api_key',
             'oauth_verifier': 'good',
@@ -1673,7 +1673,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='http://my.domain.com/callback?myparam=foo',
@@ -1687,7 +1687,7 @@ class TestOAuth(TestController):
     @mock.patch('allura.controllers.rest.oauth.Server')
     @mock.patch('allura.controllers.rest.oauth.Request')
     def test_access_token_ok(self, Request, Server):
-        req = Request.from_request.return_value = {
+        Request.from_request.return_value = {
             'oauth_consumer_key': 'api_key',
             'oauth_token': 'api_key',
             'oauth_verifier': 'good',
@@ -1698,7 +1698,7 @@ class TestOAuth(TestController):
             user_id=user._id,
             description='ctok_desc',
         )
-        rtok = M.OAuthRequestToken(
+        M.OAuthRequestToken(
             api_key='api_key',
             consumer_token_id=ctok._id,
             callback='http://my.domain.com/callback?myparam=foo',
@@ -1735,8 +1735,8 @@ class TestDisableAccount(TestController):
 
     def test_bad_password(self):
         self.app.get('/')  # establish session
-        r = self.app.post('/auth/disable/do_disable',{'password': 'bad',
-                                                      '_session_id': self.app.cookies['_session_id'],})
+        r = self.app.post('/auth/disable/do_disable', {'password': 'bad',
+                                                       '_session_id': self.app.cookies['_session_id'], })
         assert_in('Invalid password', r)
         user = M.User.by_username('test-admin')
         assert_equal(user.disabled, False)
@@ -1744,7 +1744,7 @@ class TestDisableAccount(TestController):
     def test_disable(self):
         self.app.get('/')  # establish session
         r = self.app.post('/auth/disable/do_disable', {'password': 'foo',
-                                                       '_session_id': self.app.cookies['_session_id'],})
+                                                       '_session_id': self.app.cookies['_session_id'], })
         assert_equal(r.status_int, 302)
         assert_equal(r.location, 'http://localhost/')
         flash = json.loads(self.webflash(r))
@@ -1866,8 +1866,8 @@ class TestPasswordExpire(TestController):
             self.assert_redirects()
             user = M.User.by_username('test-user')
             user.set_tool_data('AuthPasswordReset',
-                          hash="generated_hash_value",
-                          hash_expiry="04-08-2020")
+                               hash="generated_hash_value",
+                               hash_expiry="04-08-2020")
             hash = user.get_tool_data('AuthPasswordReset', 'hash')
             hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
             assert_equal(hash, 'generated_hash_value')
@@ -1890,7 +1890,6 @@ class TestPasswordExpire(TestController):
             assert_equal(hash, '')
             assert_equal(hash_expiry, '')
 
-
     def check_validation(self, oldpw, pw, pw2):
         user = M.User.by_username('test-user')
         old_update_time = user.last_password_updated
@@ -1950,7 +1949,6 @@ class TestPasswordExpire(TestController):
 
 
 class TestCSRFProtection(TestController):
-
     def test_blocks_invalid(self):
         # so test-admin isn't automatically logged in for all requests
         self.app.extra_environ = {'disable_auth_magic': 'True'}
@@ -1980,4 +1978,3 @@ class TestCSRFProtection(TestController):
     def test_token_present_on_first_request(self):
         r = self.app.get('/auth/')
         assert_true(r.form['_session_id'].value)
-

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/tests/functional/test_discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 21b5d3b..f5e5b05 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -69,9 +69,8 @@ class TestDiscuss(TestDiscussBase):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = text
         r = self.app.post(f['action'].encode('utf-8'), params=params,
                           headers={'Referer': thread_link.encode("utf-8")},
@@ -92,9 +91,8 @@ class TestDiscuss(TestDiscussBase):
         params = dict()
         inputs = post_form.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[post_form.find('textarea')['name']] = 'This is a new post'
         r = self.app.post(post_link,
                           params=params,
@@ -107,9 +105,8 @@ class TestDiscuss(TestDiscussBase):
         params = dict()
         inputs = post_form.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[post_form.find('textarea')['name']] = 'Tis a reply'
         r = self.app.post(post_link + 'reply',
                           params=params,
@@ -214,9 +211,8 @@ class TestDiscuss(TestDiscussBase):
         params = dict()
         inputs = reply_form.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[reply_form.find('textarea')['name']] = 'zzz'
         self.app.post(post_link, params)
         assert create_activity.call_count == 1, create_activity.call_count
@@ -252,9 +248,8 @@ class TestAttachment(TestDiscussBase):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'Test Post'
         r = self.app.post(f['action'].encode('utf-8'), params=params,
                           headers={'Referer': self.thread_link.encode('utf-8')})
@@ -292,9 +287,8 @@ class TestAttachment(TestDiscussBase):
         inputs = post_form.findAll('input')
 
         for field in inputs:
-            if field.has_key('name') and (field['name'] != 'file_info'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name') and field['name'] != 'file_info':  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[post_form.find('textarea')['name']] = 'Reply'
         r = self.app.post(self.post_link + 'reply',
                           params=params,

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/tests/functional/test_neighborhood.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 9b8b215..13c2808 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -38,7 +38,6 @@ from alluratest.controller import setup_trove_categories
 
 
 class TestNeighborhood(TestController):
-
     def test_home_project(self):
         r = self.app.get('/adobe/wiki/')
         assert r.location.endswith('/adobe/wiki/Home/')
@@ -120,9 +119,9 @@ class TestNeighborhood(TestController):
 
     def test_prohibited_tools(self):
         self.app.post('/p/_admin/update',
-                          params=dict(name='Projects',
-                          prohibited_tools='wiki, tickets'),
-                          extra_environ=dict(username='root'))
+                      params=dict(name='Projects',
+                                  prohibited_tools='wiki, tickets'),
+                      extra_environ=dict(username='root'))
 
         r = self.app.get('/p/_admin/overview', extra_environ=dict(username='root'))
         assert 'wiki, tickets' in r
@@ -133,7 +132,7 @@ class TestNeighborhood(TestController):
 
         r = self.app.post('/p/_admin/update',
                           params=dict(name='Projects',
-                          prohibited_tools='wiki, test'),
+                                      prohibited_tools='wiki, test'),
                           extra_environ=dict(username='root'))
         assert 'error' in self.webflash(r), self.webflash(r)
 
@@ -361,8 +360,8 @@ class TestNeighborhood(TestController):
         assert '/*projecttitlecolor*/.project_title{color:green;}' in neighborhood.css
         assert '/*barontop*/.pad h2.colored {background-color:#555555; background-image: none;}' in neighborhood.css
         assert '/*titlebarbackground*/.pad h2.title{background-color:#333; background-image: none;}' in neighborhood.css
-        assert "/*titlebarcolor*/.pad h2.title, .pad h2.title small a {color:#444;} "\
-               ".pad h2.dark small b.ico {background-image: "\
+        assert "/*titlebarcolor*/.pad h2.title, .pad h2.title small a {color:#444;} " \
+               ".pad h2.dark small b.ico {background-image: " \
                "url('/nf/_ew_/theme/allura/images/neo-icon-set-ffffff-256x350.png');}" in neighborhood.css
 
     def test_max_projects(self):
@@ -647,8 +646,8 @@ class TestNeighborhood(TestController):
     def test_project_template(self):
         setup_trove_categories()
         icon_url = 'file://' + \
-            os.path.join(allura.__path__[0], 'nf', 'allura',
-                         'images', 'neo-icon-set-454545-256x350.png')
+                   os.path.join(allura.__path__[0], 'nf', 'allura',
+                                'images', 'neo-icon-set-454545-256x350.png')
         test_groups = [{
             "name": "Viewer",  # group will be created, all params are valid
             "permissions": ["read"],
@@ -670,7 +669,9 @@ class TestNeighborhood(TestController):
             "permissions": ["admin"]
         }]
         r = self.app.post('/adobe/_admin/update', params=dict(name='Mozq1',
-                                                              css='', homepage='# MozQ1!\n[Root]', project_template="""{
+                                                              css='',
+                                                              homepage='# MozQ1!\n[Root]',
+                                                              project_template="""{
                 "private":true,
                 "icon":{
                     "url":"%s",
@@ -717,22 +718,14 @@ class TestNeighborhood(TestController):
         p = M.Project.query.get(shortname='testtemp')
         # make sure the correct tools got installed in the right order
         top_nav = r.html.find('div', {'id': 'top_nav'})
-        assert top_nav.contents[1].contents[1].contents[
-            1]['href'] == '/adobe/testtemp/wiki/'
-        assert 'Wiki' in top_nav.contents[
-            1].contents[1].contents[1].contents[0]
-        assert top_nav.contents[1].contents[3].contents[
-            1]['href'] == '/adobe/testtemp/discussion/'
-        assert 'Discussion' in top_nav.contents[
-            1].contents[3].contents[1].contents[0]
-        assert top_nav.contents[1].contents[5].contents[
-            1]['href'] == '/adobe/testtemp/news/'
-        assert 'News' in top_nav.contents[
-            1].contents[5].contents[1].contents[0]
-        assert top_nav.contents[1].contents[7].contents[
-            1]['href'] == '/adobe/testtemp/admin/'
-        assert 'Admin' in top_nav.contents[
-            1].contents[7].contents[1].contents[0]
+        assert top_nav.contents[1].contents[1].contents[1]['href'] == '/adobe/testtemp/wiki/'
+        assert 'Wiki' in top_nav.contents[1].contents[1].contents[1].contents[0]
+        assert top_nav.contents[1].contents[3].contents[1]['href'] == '/adobe/testtemp/discussion/'
+        assert 'Discussion' in top_nav.contents[1].contents[3].contents[1].contents[0]
+        assert top_nav.contents[1].contents[5].contents[1]['href'] == '/adobe/testtemp/news/'
+        assert 'News' in top_nav.contents[1].contents[5].contents[1].contents[0]
+        assert top_nav.contents[1].contents[7].contents[1]['href'] == '/adobe/testtemp/admin/'
+        assert 'Admin' in top_nav.contents[1].contents[7].contents[1].contents[0]
         # make sure project is private
         r = self.app.get(
             '/adobe/testtemp/wiki/',
@@ -804,7 +797,7 @@ class TestNeighborhood(TestController):
                 },
                 "tool_order":["wiki","admin"],
 
-                }""" ),
+                }"""),
                           extra_environ=dict(username='root'))
         neighborhood = M.Neighborhood.query.get(name='Adobe')
         neighborhood.anchored_tools = 'wiki:Wiki'
@@ -835,7 +828,8 @@ class TestNeighborhood(TestController):
             r = self.app.get(
                 '/p/check_names?neighborhood=Projects&project_unixname=%s' % name)
             assert_equal(
-                r.json, {'project_unixname': 'Please use only small letters, numbers, and dashes 3-15 characters long.'})
+                r.json,
+                {'project_unixname': 'Please use only small letters, numbers, and dashes 3-15 characters long.'})
         r = self.app.get(
             '/p/check_names?neighborhood=Projects&project_unixname=mymoz')
         assert_equal(r.json, {})
@@ -895,8 +889,8 @@ class TestNeighborhood(TestController):
         image = PIL.Image.open(StringIO(r.body))
         assert image.size == (48, 48)
         self.app.post('/adobe/_admin/awards/grant',
-                params=dict(grant='FOO', recipient='adobe-1',
-                            url='http://award.org', comment='Winner!'),
+                      params=dict(grant='FOO', recipient='adobe-1',
+                                  url='http://award.org', comment='Winner!'),
                       extra_environ=dict(username='root'))
         r = self.app.get('/adobe/_admin/accolades',
                          extra_environ=dict(username='root'))
@@ -960,7 +954,6 @@ class TestNeighborhood(TestController):
 
 
 class TestPhoneVerificationOnProjectRegistration(TestController):
-
     def test_phone_verification_fragment_renders(self):
         self.app.get('/p/phone_verification_fragment', status=200)
         self.app.get('/adobe/phone_verification_fragment', status=200)

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index 903cda7..1a2006d 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -249,9 +249,9 @@ class TestRestHome(TestRestApiBase):
         assert_equal(r.json['result'], False)
 
     def test_project_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/has_access', status=404)
-        r = self.api_get('/rest/p/test/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/has_access', status=404)
+        self.api_get('/rest/p/test/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/has_access?perm=read', status=404)
 
     def test_project_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/tests/functional/test_user_profile.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_user_profile.py b/Allura/allura/tests/functional/test_user_profile.py
index 4425ace..14c28bf 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -194,9 +194,9 @@ class TestUserProfileHasAccessAPI(TestRestApiBase):
 
     @td.with_user_project('test-admin')
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/u/test-admin/profile/has_access', status=404)
-        r = self.api_get('/rest/u/test-admin/profile/has_access?user=root', status=404)
-        r = self.api_get('/rest/u/test-admin/profile/has_access?perm=read', status=404)
+        self.api_get('/rest/u/test-admin/profile/has_access', status=404)
+        self.api_get('/rest/u/test-admin/profile/has_access?user=root', status=404)
+        self.api_get('/rest/u/test-admin/profile/has_access?perm=read', status=404)
 
     @td.with_user_project('test-admin')
     def test_has_access_unknown_params(self):

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 0203969..bb5d80e 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -48,6 +48,7 @@ from allura.tests import decorators as td
 from forgewiki import model as WM
 from forgeblog import model as BM
 
+
 def squish_spaces(text):
     return re.sub(r'\s+', ' ', text)
 
@@ -171,7 +172,9 @@ def test_macro_gittip_button():
     with h.push_config(c, project=p_test):
         r = g.markdown_wiki.convert('[[gittip_button username=test]]')
     assert_equal(
-        r, u'<div class="markdown_content"><p><iframe height="22pt" src="https://www.gittip.com/test/widget.html" style="border: 0; margin: 0; padding: 0;" width="48pt"></iframe>\n</p></div>')
+        r,
+        u'<div class="markdown_content"><p><iframe height="22pt" src="https://www.gittip.com/test/widget.html" '
+        u'style="border: 0; margin: 0; padding: 0;" width="48pt"></iframe>\n</p></div>')
 
 
 def test_macro_neighborhood_feeds():
@@ -213,7 +216,7 @@ def test_macro_members():
     p_test.add_user(M.User.by_username('test-user'), ['Developer'])
     p_test.add_user(M.User.by_username('test-user-0'), ['Member'])
     ThreadLocalORMSession.flush_all()
-    r = g.markdown_wiki.convert('[[members limit=2]]').replace('\t','').replace('\n','')
+    r = g.markdown_wiki.convert('[[members limit=2]]').replace('\t', '').replace('\n', '')
     assert_equal(r,
                  '<div class="markdown_content"><h6>Project Members:</h6>'
                  '<ul class="md-users-list">'
@@ -258,7 +261,7 @@ def test_macro_project_admins_one_br():
     with h.push_config(c, project=p_test):
         r = g.markdown_wiki.convert('[[project_admins]]\n[[download_button]]')
 
-    assert not '</a><br/><br/><a href=' in r, r
+    assert '</a><br/><br/><a href=' not in r, r
     assert '</a></li><li><a href=' in r, r
 
 
@@ -293,6 +296,7 @@ def test_macro_include_no_extra_br():
 <p></p></div>'''
     assert_equal(squish_spaces(html), squish_spaces(expected_html))
 
+
 @with_setup(setUp, tearDown)
 @td.with_wiki
 @td.with_tool('test', 'Wiki', 'wiki2')
@@ -330,11 +334,13 @@ def test_macro_include_permissions():
 @patch('oembed.OEmbedEndpoint.fetch')
 def test_macro_embed(oembed_fetch):
     oembed_fetch.return_value = {
-        "html": '<iframe width="480" height="270" src="http://www.youtube.com/embed/kOLpSPEA72U?feature=oembed" frameborder="0" allowfullscreen></iframe>)',
+        "html": '<iframe width="480" height="270" src="http://www.youtube.com/embed/kOLpSPEA72U?feature=oembed" '
+                'frameborder="0" allowfullscreen></iframe>)',
         "title": "Nature's 3D Printer: MIND BLOWING Cocoon in Rainforest - Smarter Every Day 94",
     }
     r = g.markdown_wiki.convert('[[embed url=http://www.youtube.com/watch?v=kOLpSPEA72U]]')
-    assert_in('<div class="grid-20"><iframe height="270" src="https://www.youtube.com/embed/kOLpSPEA72U?feature=oembed" width="480"></iframe></div>',
+    assert_in('<div class="grid-20"><iframe height="270" '
+              'src="https://www.youtube.com/embed/kOLpSPEA72U?feature=oembed" width="480"></iframe></div>',
               r.replace('\n', ''))
 
 
@@ -484,13 +490,20 @@ def test_markdown_invalid_tagslash():
     r = g.markdown.convert('<div/onload><img src=x onerror=alert(document.cookie)>')
     assert_not_in('onerror', r)
 
+
 def test_markdown_invalid_script_in_link():
     r = g.markdown.convert('[xss](http://"><a onmouseover=prompt(document.domain)>xss</a>)')
-    assert_equal('''<div class="markdown_content"><p><a class="" href='http://"&gt;&lt;a%20onmouseover=prompt(document.domain)&gt;xss&lt;/a&gt;' rel="nofollow">xss</a></p></div>''', r)
+    assert_equal('<div class="markdown_content"><p><a class="" '
+                 '''href='http://"&gt;&lt;a%20onmouseover=prompt(document.domain)&gt;xss&lt;/a&gt;' '''
+                 'rel="nofollow">xss</a></p></div>', r)
+
 
 def test_markdown_invalid_script_in_link2():
     r = g.markdown.convert('[xss](http://"><img src=x onerror=alert(document.cookie)>)')
-    assert_equal('''<div class="markdown_content"><p><a class="" href='http://"&gt;&lt;img%20src=x%20onerror=alert(document.cookie)&gt;' rel="nofollow">xss</a></p></div>''', r)
+    assert_equal('<div class="markdown_content"><p><a class="" '
+                 '''href='http://"&gt;&lt;img%20src=x%20onerror=alert(document.cookie)&gt;' '''
+                 'rel="nofollow">xss</a></p></div>', r)
+
 
 @td.with_wiki
 def test_macro_include():
@@ -629,7 +642,8 @@ def test_hideawards_macro():
 
     with h.push_context(p_nbhd.neighborhood_project._id):
         r = g.markdown_wiki.convert('[[projects]]')
-        assert_in('<div class="feature"> <a href="http://award.org" rel="nofollow" title="Winner!">Award short</a> </div>',
+        assert_in('<div class="feature"> <a href="http://award.org" rel="nofollow" title="Winner!">'
+                  'Award short</a> </div>',
                   squish_spaces(r))
 
         r = g.markdown_wiki.convert('[[projects show_awards_banner=False]]')
@@ -642,7 +656,7 @@ def get_project_names(r):
     """
     # projects short names are in h2 elements without any attributes
     # there is one more h2 element, but it has `class` attribute
-    #re_proj_names = re.compile('<h2><a[^>]>(.+)<\/a><\/h2>')
+    # re_proj_names = re.compile('<h2><a[^>]>(.+)<\/a><\/h2>')
     re_proj_names = re.compile('<h2><a[^>]+>(.+)<\/a><\/h2>')
     return [e for e in re_proj_names.findall(r)]
 
@@ -754,8 +768,10 @@ class TestHandlePaging(unittest.TestCase):
     def setUp(self):
         prefs = {}
         c.user = Mock()
+
         def get_pref(name):
             return prefs.get(name)
+
         def set_pref(name, value):
             prefs[name] = value
         c.user.get_pref = get_pref

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/tests/test_utils.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index dd67ded..413165a 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -22,7 +22,6 @@ import time
 import unittest
 import datetime as dt
 from ming.odm import session
-import model as M
 from os import path
 
 from webob import Request
@@ -169,12 +168,12 @@ class TestTruthyCallable(unittest.TestCase):
             return utils.TruthyCallable(predicate)
         true_predicate = wrapper_func(True)
         false_predicate = wrapper_func(False)
-        assert true_predicate(True) == True
-        assert false_predicate(False) == False
-        assert true_predicate() == True
-        assert false_predicate() == False
-        assert bool(true_predicate) == True
-        assert bool(false_predicate) == False
+        assert true_predicate(True) is True
+        assert false_predicate(False) is False
+        assert true_predicate() is True
+        assert false_predicate() is False
+        assert bool(true_predicate) is True
+        assert bool(false_predicate) is False
 
 
 class TestCaseInsensitiveDict(unittest.TestCase):
@@ -260,7 +259,8 @@ class TestHTMLSanitizer(unittest.TestCase):
         assert_equal(self.simple_tag_list(p), ['div', 'div'])
 
     def test_html_sanitizer_youtube_iframe(self):
-        p = utils.ForgeHTMLSanitizer('<div><iframe src="https://www.youtube.com/embed/kOLpSPEA72U?feature=oembed"></iframe></div>')
+        p = utils.ForgeHTMLSanitizer(
+            '<div><iframe src="https://www.youtube.com/embed/kOLpSPEA72U?feature=oembed"></iframe></div>')
         assert_equal(
             self.simple_tag_list(p), ['div', 'iframe', 'div'])
 
@@ -272,6 +272,7 @@ def test_ip_address():
     assert_equal(utils.ip_address(req),
                  '1.2.3.4')
 
+
 def test_ip_address_header():
     req = Mock()
     req.remote_addr = '1.2.3.4'
@@ -280,6 +281,7 @@ def test_ip_address_header():
         assert_equal(utils.ip_address(req),
                      '5.6.7.8')
 
+
 def test_ip_address_header_not_set():
     req = Mock()
     req.remote_addr = '1.2.3.4'
@@ -329,5 +331,5 @@ def test_phone_number_hash():
 
 def test_skip_mod_date():
     with utils.skip_mod_date(M.Artifact):
-        assert getattr(session(M.Artifact)._get(), 'skip_mod_date', None) == True
-    assert getattr(session(M.Artifact)._get(), 'skip_mod_date', None) == False
\ No newline at end of file
+        assert getattr(session(M.Artifact)._get(), 'skip_mod_date', None) is True
+    assert getattr(session(M.Artifact)._get(), 'skip_mod_date', None) is False

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/allura/websetup/bootstrap.py
----------------------------------------------------------------------
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 33a3f3c..8bc04fe 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -22,7 +22,6 @@ import os
 import sys
 import logging
 import shutil
-from collections import defaultdict
 from textwrap import dedent
 
 import tg
@@ -110,7 +109,7 @@ def bootstrap(command, conf, vars):
     log.info('Initializing search')
 
     log.info('Registering root user & default neighborhoods')
-    anonymous = M.User(
+    M.User(
         _id=None,
         username='*anonymous',
         display_name='Anonymous')
@@ -172,7 +171,8 @@ def bootstrap(command, conf, vars):
         [[projects show_total=yes]]
         '''))
     set_nbhd_wiki_content(p_users, dedent('''
-        This is the "Users" neighborhood.  All users automatically get a user-project created for them, using their username.
+        This is the "Users" neighborhood.
+        All users automatically get a user-project created for them, using their username.
 
         [Neighborhood administration](/u/admin)
 
@@ -208,19 +208,19 @@ def bootstrap(command, conf, vars):
             make_user('Test User %d' % unum)
 
     log.info('Creating basic project categories')
-    cat1 = M.ProjectCategory(name='clustering', label='Clustering')
+    M.ProjectCategory(name='clustering', label='Clustering')
     cat2 = M.ProjectCategory(name='communications', label='Communications')
-    cat2_1 = M.ProjectCategory(
+    M.ProjectCategory(
         name='synchronization', label='Synchronization', parent_id=cat2._id)
-    cat2_2 = M.ProjectCategory(
+    M.ProjectCategory(
         name='streaming', label='Streaming', parent_id=cat2._id)
-    cat2_3 = M.ProjectCategory(name='fax', label='Fax', parent_id=cat2._id)
-    cat2_4 = M.ProjectCategory(name='bbs', label='BBS', parent_id=cat2._id)
+    M.ProjectCategory(name='fax', label='Fax', parent_id=cat2._id)
+    M.ProjectCategory(name='bbs', label='BBS', parent_id=cat2._id)
 
     cat3 = M.ProjectCategory(name='database', label='Database')
-    cat3_1 = M.ProjectCategory(
+    M.ProjectCategory(
         name='front_ends', label='Front-Ends', parent_id=cat3._id)
-    cat3_2 = M.ProjectCategory(
+    M.ProjectCategory(
         name='engines_servers', label='Engines/Servers', parent_id=cat3._id)
 
     if create_test_data:
@@ -244,12 +244,12 @@ def bootstrap(command, conf, vars):
             p_projects.add_user(u_admin, ['Admin'])
             p_users.add_user(u_admin, ['Admin'])
 
-            p_allura = n_projects.register_project('allura', u_admin, 'Allura')
-        u1 = make_user('Test User')
-        p_adobe1 = n_adobe.register_project('adobe-1', u_admin, 'Adobe project 1')
+            n_projects.register_project('allura', u_admin, 'Allura')
+        make_user('Test User')
+        n_adobe.register_project('adobe-1', u_admin, 'Adobe project 1')
         p_adobe.add_user(u_admin, ['Admin'])
         p0 = n_projects.register_project('test', u_admin, 'Test Project')
-        p1 = n_projects.register_project('test2', u_admin, 'Test 2')
+        n_projects.register_project('test2', u_admin, 'Test 2')
         p0._extra_tool_status = ['alpha', 'beta']
 
     sess = session(M.Neighborhood)  # all the sessions are the same
@@ -279,11 +279,11 @@ def bootstrap(command, conf, vars):
             log.info('Registering initial apps')
             with h.push_config(c, user=u_admin):
                 p0.install_apps([{'ep_name': ep_name}
-                    for ep_name, app in g.entry_points['tool'].iteritems()
-                    if app._installable(tool_name=ep_name,
-                                        nbhd=n_projects,
-                                        project_tools=[])
-                ])
+                                 for ep_name, app in g.entry_points['tool'].iteritems()
+                                 if app._installable(tool_name=ep_name,
+                                                     nbhd=n_projects,
+                                                     project_tools=[])
+                                 ])
 
     ThreadLocalORMSession.flush_all()
     ThreadLocalORMSession.close_all()


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

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/c456344c/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>

[13/42] allura git commit: [#7984] force location of user subscriptions form elements

Posted by he...@apache.org.
[#7984] force location of user subscriptions form elements


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

Branch: refs/heads/hs/7919
Commit: 151c63b630a7373669cbd20ea8f8b37d7fed0439
Parents: 00110b1
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 12 10:27:55 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Oct 13 16:19:05 2015 -0400

----------------------------------------------------------------------
 Allura/allura/lib/widgets/subscriptions.py      | 24 +++++---
 .../templates/widgets/user_subs_form.html       | 61 ++++++++++++++++++++
 2 files changed, 76 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/151c63b6/Allura/allura/lib/widgets/subscriptions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/subscriptions.py b/Allura/allura/lib/widgets/subscriptions.py
index 4e3324a..5d1ebea 100644
--- a/Allura/allura/lib/widgets/subscriptions.py
+++ b/Allura/allura/lib/widgets/subscriptions.py
@@ -58,17 +58,23 @@ class _SubscriptionTable(ew.TableField):
 class SubscriptionForm(CsrfForm):
     defaults = dict(
         ew.SimpleForm.defaults,
+        id='user-subs-form',
         submit_text='Save')
 
-    class fields(ew_core.NameList):
-        subscriptions = _SubscriptionTable()
-        email_format = ew.SingleSelectField(
-            name='email_format',
-            label='Email Format',
-            options=[
-                ew.Option(py_value='plain', label='Plain Text'),
-                ew.Option(py_value='html', label='HTML'),
-                ew.Option(py_value='both', label='Combined')])
+    template = 'jinja:allura:templates/widgets/user_subs_form.html'
+
+    @property
+    def fields(self):
+        return [
+            _SubscriptionTable(name='subscriptions'),
+            ew.SingleSelectField(
+                name='email_format',
+                show_label=False,
+                options=[
+                    ew.Option(py_value='plain', label='Plain Text'),
+                    ew.Option(py_value='html', label='HTML'),
+                    ew.Option(py_value='both', label='Combined')]),
+        ]
 
 
 class SubscribeForm(ew.SimpleForm):

http://git-wip-us.apache.org/repos/asf/allura/blob/151c63b6/Allura/allura/templates/widgets/user_subs_form.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/user_subs_form.html b/Allura/allura/templates/widgets/user_subs_form.html
new file mode 100644
index 0000000..39aecbc
--- /dev/null
+++ b/Allura/allura/templates/widgets/user_subs_form.html
@@ -0,0 +1,61 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.
+-#}
+
+<form {{widget.j2_attrs(dict(
+      name=rendered_name,
+      id=id,
+      method=method,
+      action=action,
+      enctype=enctype), attrs)}}>
+
+    {% set subs_table = widget.fields[0] %}
+    {{ subs_table.display(**widget.context_for(subs_table)) }}
+
+    {# use a table so it matches width and placement of big table above #}
+    <table class="user_subs_opts">
+    <tr><td>
+        <div class="user_sub_email_format">
+        Email Format:
+        {% set email_format = widget.fields[1] %}
+        {{ email_format.display(**widget.context_for(email_format)) }}
+        </div>
+        {% for hf in widget.hidden_fields %}
+            {{ hf.display(**widget.context_for(hf)) }}
+        {% endfor %}
+        {% for b in buttons %}
+            {{ b.display() }}
+        {% endfor %}
+    </td></tr>
+    </table>
+</form>
+
+<style type="text/css">
+    #user-subs-form table:first-child {
+        margin-bottom: 10px;
+    }
+    #user-subs-form table.user_subs_opts td {
+        border-bottom: none;
+    }
+    .user_sub_email_format {
+        float: left;
+    }
+    .user_subs_opts input[type=submit] {
+        float: right;
+    }
+</style>
\ No newline at end of file


[03/42] allura git commit: [#7991] limit phone number usage to once

Posted by he...@apache.org.
[#7991] limit phone number usage to once


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

Branch: refs/heads/hs/7919
Commit: b79b854693f1aadebe408e7f95bad2a747cbf047
Parents: c8300e1
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 5 15:19:55 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Oct 5 15:38:26 2015 -0400

----------------------------------------------------------------------
 Allura/allura/lib/plugin.py                         |  7 ++++++-
 Allura/allura/tests/functional/test_neighborhood.py | 16 +++++++++++++++-
 2 files changed, 21 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/b79b8546/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 2270dcb..46cd3e8 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -726,11 +726,16 @@ class ProjectRegistrationProvider(object):
             return True
         return bool(user.get_tool_data('phone_verification', 'number_hash'))
 
-    def verify_phone(self, user, number):
+    def verify_phone(self, user, number, allow_reuse=False):
+        from allura import model as M
         ok = {'status': 'ok'}
         if not asbool(config.get('project.verify_phone')):
             return ok
         number = utils.clean_phone_number(number)
+        number_hash = utils.phone_number_hash(number)
+        if not allow_reuse and M.User.query.find({'tool_data.phone_verification.number_hash': number_hash}).count():
+            return {'status': 'error',
+                    'error': 'That phone number has already been used.'}
         return g.phone_service.verify(number)
 
     def check_phone_verification(self, user, request_id, pin, number_hash):

http://git-wip-us.apache.org/repos/asf/allura/blob/b79b8546/Allura/allura/tests/functional/test_neighborhood.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 8b6a74f..9b8b215 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -24,7 +24,7 @@ import PIL
 from mock import patch
 from tg import config
 from nose.tools import assert_equal, assert_in, assert_not_equal
-from ming.orm.ormsession import ThreadLocalORMSession
+from ming.orm.ormsession import ThreadLocalORMSession, session
 from paste.httpexceptions import HTTPFound
 from pylons import app_globals as g
 
@@ -33,6 +33,7 @@ from allura import model as M
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura.lib import helpers as h
+from allura.lib import utils
 from alluratest.controller import setup_trove_categories
 
 
@@ -1006,6 +1007,19 @@ class TestPhoneVerificationOnProjectRegistration(TestController):
         }
         assert_equal(r.json, expected)
 
+    @patch.object(g, 'phone_service', autospec=True)
+    def test_verify_phone_already_used(self, phone_service):
+        with h.push_config(config, **{'project.verify_phone': 'true'}):
+            u = M.User.register(dict(username='existing-user'), make_project=False)
+            u.set_tool_data('phone_verification', number_hash=utils.phone_number_hash('1-555-444-9999'))
+            session(u).flush(u)
+            phone_service.verify.return_value = {'request_id': 'request-id', 'status': 'ok'}
+            r = self.app.get('/p/verify_phone', {'number': '1-555-444-9999'})
+            assert_equal(r.json, {
+                'status': 'error',
+                'error': u'That phone number has already been used.'
+            })
+
     def test_check_phone_verification_no_params(self):
         with h.push_config(config, **{'project.verify_phone': 'true'}):
             self.app.get('/p/check_phone_verification', status=404)


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

Posted by he...@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/a38ab24b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a38ab24b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a38ab24b

Branch: refs/heads/hs/7919
Commit: a38ab24b5b9651c831f745d7988b3c8e8ba2936a
Parents: 4328524
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:02:55 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:16 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/a38ab24b/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.


[14/42] allura git commit: [#7984] skip tools that never have notications; better text within the table

Posted by he...@apache.org.
[#7984] skip tools that never have notications; better text within the table


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

Branch: refs/heads/hs/7919
Commit: e97c5ffe587b5e49a63fbee3800265df1db96a94
Parents: 68786d3
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Oct 13 16:52:08 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Oct 14 10:01:15 2015 -0400

----------------------------------------------------------------------
 Allura/allura/app.py                        |  3 +++
 Allura/allura/controllers/auth.py           | 17 ++++++++++++-----
 Allura/allura/ext/admin/admin_main.py       |  1 +
 Allura/allura/ext/search/search_main.py     |  1 +
 Allura/allura/ext/user_profile/user_main.py |  1 +
 Allura/allura/lib/widgets/subscriptions.py  |  4 ++--
 Allura/allura/tests/functional/test_auth.py | 12 ++++++------
 ForgeActivity/forgeactivity/main.py         |  1 +
 ForgeChat/forgechat/main.py                 |  1 +
 ForgeLink/forgelink/link_main.py            |  1 +
 ForgeUserStats/forgeuserstats/main.py       |  1 +
 11 files changed, 30 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/Allura/allura/app.py
----------------------------------------------------------------------
diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index bd6f36b..4cc47b1 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -216,6 +216,8 @@ class Application(object):
         can not be added to the project by the user. Default value is float("inf").
     :cvar bool hidden: Default is False, Application is not hidden from the
         list of a project's installed tools.
+    :cvar bool has_notifications: Default is True, if set to False then application will not
+        be listed on user subscriptions table.
     :cvar str tool_description: Text description of this Application.
     :cvar bool relaxed_mount_points: Set to True to relax the default mount point
         naming restrictions for this Application. Default is False. See
@@ -272,6 +274,7 @@ class Application(object):
     relaxed_mount_points = False
     ordinal = 0
     hidden = False
+    has_notifications = True
     icons = {
         24: 'images/admin_24.png',
         32: 'images/admin_32.png',

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index e3c4d38..f2043af 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -868,15 +868,19 @@ class SubscriptionsController(BaseController):
                 continue
             if app_config is None:
                 continue
+            app = app_config.load()
+            if not app.has_notifications:
+                continue
 
             subscriptions.append(dict(
                 subscription_id=mb._id,
                 project_id=project._id,
                 app_config_id=mb.app_config_id,
                 project_name=project.name,
-                mount_point=app_config.options['mount_point'],
+                tool=app_config.options['mount_label'],
                 artifact_title=dict(
-                    text=mb.artifact_title, href=mb.artifact_url),
+                    text='Everything' if mb.artifact_title == 'All artifacts' else mb.artifact_title,
+                    href=mb.artifact_url),
                 topic=mb.topic,
                 type=mb.type,
                 frequency=mb.frequency.unit,
@@ -902,20 +906,23 @@ class SubscriptionsController(BaseController):
         for tool in my_tools:
             if tool['_id'] in my_tools_subscriptions:
                 continue  # We have already subscribed to this tool.
+            app = tool.load()
+            if not app.has_notifications:
+                continue
 
             subscriptions.append(
                 dict(tool_id=tool._id,
                      user_id=c.user._id,
                      project_id=tool.project_id,
                      project_name=my_projects[tool.project_id].name,
-                     mount_point=tool.options['mount_point'],
-                     artifact_title='No subscription',
+                     tool=tool.options['mount_label'],
+                     artifact_title='Everything',
                      topic=None,
                      type=None,
                      frequency=None,
                      artifact=None))
 
-        subscriptions.sort(key=lambda d: (d['project_name'], d['mount_point']))
+        subscriptions.sort(key=lambda d: (d['project_name'], d['tool']))
         provider = plugin.AuthenticationProvider.get(request)
         menu = provider.account_navigation()
         return dict(

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/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 dcda9be..7affa3c 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -86,6 +86,7 @@ class AdminApp(Application):
         48: 'images/admin_48.png'
     }
     exportable = True
+    has_notifications = False
 
     def __init__(self, project, config):
         Application.__init__(self, project, config)

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/Allura/allura/ext/search/search_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/search/search_main.py b/Allura/allura/ext/search/search_main.py
index 99c5dfc..9f8a92b 100644
--- a/Allura/allura/ext/search/search_main.py
+++ b/Allura/allura/ext/search/search_main.py
@@ -40,6 +40,7 @@ class SearchApp(Application):
     __version__ = version.__version__
     max_instances = 0
     hidden = True
+    has_notifications = False
     sitemap = []
 
     def __init__(self, project, config):

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/Allura/allura/ext/user_profile/user_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index f676bed..9be9276 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -59,6 +59,7 @@ class UserProfileApp(Application):
     __version__ = version.__version__
     tool_label = 'Profile'
     max_instances = 0
+    has_notifications = False
     icons = {
         24: 'images/home_24.png',
         32: 'images/home_32.png',

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/Allura/allura/lib/widgets/subscriptions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/subscriptions.py b/Allura/allura/lib/widgets/subscriptions.py
index db6c51d..909a506 100644
--- a/Allura/allura/lib/widgets/subscriptions.py
+++ b/Allura/allura/lib/widgets/subscriptions.py
@@ -41,10 +41,10 @@ class _SubscriptionTable(ew.TableField):
     class fields(ew_core.NameList):
         project_name = ffw.DisplayOnlyField(
             label='Project', show_label=True, with_hidden_input=False)
-        mount_point = ffw.DisplayOnlyField(
+        tool = ffw.DisplayOnlyField(
             label='Tool', show_label=True, with_hidden_input=False)
         artifact_title = ew.LinkField(
-            label='Artifact', show_label=True, plaintext_if_no_href=True)
+            label='Item(s)', show_label=True, plaintext_if_no_href=True)
         # unsubscribe = SubmitButton()
         subscribed = ew.Checkbox(suppress_label=True)
 

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 5ad86ea..d74ebf0 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -582,20 +582,20 @@ class TestAuth(TestController):
         subscriptions = M.Mailbox.query.find(dict(
             user_id=c.user._id, is_flash=False)).all()
         # make sure page actually lists all the user's subscriptions
-        assert len(
-            subscriptions) > 0, 'Test user has no subscriptions, cannot verify that they are shown'
+        assert len(subscriptions) > 0, 'Test user has no subscriptions, cannot verify that they are shown'
         for m in subscriptions:
             assert m._id in r, "Page doesn't list subscription for Mailbox._id = %s" % m._id
 
         # make sure page lists all tools which user can subscribe
         user = M.User.query.get(username='test-admin')
-        tools = []
         for p in user.my_projects():
             for ac in p.app_configs:
                 if not M.Mailbox.subscribed(project_id=p._id, app_config_id=ac._id):
-                    tools.append(ac._id)
-        for tool_id in tools:
-            assert tool_id in r, "Page doesn't list tool with app_config_id = %s" % tool_id
+                    if ac.tool_name in ('activity', 'admin', 'search', 'userstats', 'profile'):
+                        # these have has_notifications=False
+                        assert ac._id not in r, "Page lists tool %s but it should not" % ac.tool_name
+                    else:
+                        assert ac._id in r, "Page doesn't list tool %s" % ac.tool_name
 
     def _find_subscriptions_form(self, r):
         form = None

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/ForgeActivity/forgeactivity/main.py
----------------------------------------------------------------------
diff --git a/ForgeActivity/forgeactivity/main.py b/ForgeActivity/forgeactivity/main.py
index 9bb6029..845eb9e 100644
--- a/ForgeActivity/forgeactivity/main.py
+++ b/ForgeActivity/forgeactivity/main.py
@@ -52,6 +52,7 @@ class ForgeActivityApp(Application):
     default_mount_point = 'activity'
     max_instances = 0
     searchable = False
+    has_notifications = False
 
     def __init__(self, project, config):
         Application.__init__(self, project, config)

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/ForgeChat/forgechat/main.py
----------------------------------------------------------------------
diff --git a/ForgeChat/forgechat/main.py b/ForgeChat/forgechat/main.py
index 39a6807..bdd373a 100644
--- a/ForgeChat/forgechat/main.py
+++ b/ForgeChat/forgechat/main.py
@@ -59,6 +59,7 @@ class ForgeChatApp(Application):
     config_options = Application.config_options + [
         ConfigOption('channel', str, ''),
     ]
+    has_notifications = False
     icons = {
         24: 'images/chat_24.png',
         32: 'images/chat_32.png',

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/ForgeLink/forgelink/link_main.py
----------------------------------------------------------------------
diff --git a/ForgeLink/forgelink/link_main.py b/ForgeLink/forgelink/link_main.py
index 735816d..dde7a02 100644
--- a/ForgeLink/forgelink/link_main.py
+++ b/ForgeLink/forgelink/link_main.py
@@ -59,6 +59,7 @@ class ForgeLinkApp(Application):
     config_on_install = ['url']
     searchable = True
     exportable = True
+    has_notifications = False
     tool_label = 'External Link'
     default_mount_label = 'Link name'
     default_mount_point = 'link'

http://git-wip-us.apache.org/repos/asf/allura/blob/e97c5ffe/ForgeUserStats/forgeuserstats/main.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/main.py b/ForgeUserStats/forgeuserstats/main.py
index eb25140..daa19ef 100644
--- a/ForgeUserStats/forgeuserstats/main.py
+++ b/ForgeUserStats/forgeuserstats/main.py
@@ -97,6 +97,7 @@ class ForgeUserStatsApp(Application):
         'admin': 'Toggle stats visibility.',
     }
     max_instances = 0
+    has_notifications = False
     ordinal = 15
     config_options = Application.config_options
     default_external_feeds = []


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

Posted by he...@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/9475ba9f
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/9475ba9f
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/9475ba9f

Branch: refs/heads/hs/7919
Commit: 9475ba9f43c1f7a0ce6542952379bc5348b01e1b
Parents: a38ab24
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:05:47 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:16 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/9475ba9f/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,
         )


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

Posted by he...@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/38a245ab
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/38a245ab
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/38a245ab

Branch: refs/heads/hs/7919
Commit: 38a245abb049a1bc8c9a5e92d0861f8f0a377ba2
Parents: 40dd739
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 15:02:24 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:19 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/38a245ab/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/38a245ab/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/38a245ab/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 3d94d9c..68a6741 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') %}


[02/42] allura git commit: Docker & doc fixes for node, pwd, etc

Posted by he...@apache.org.
Docker & doc fixes for node, pwd, etc

Revert changes to WORKDIR in Allura/Dockerfile from recent broccoli/jsx setup
commits.  Its needed to have the 'web' container start in the root folder, so
`pip` command etc works.

Update docs to take advantage of the 'taskd' container starting in Allura
subdir so paster commands can run without "bash -c 'cd ...'" stuff.

Use newest version of node/npm to avoid symlink errors when installing
npm packages within a VM shared mount.

Add instructions for running administrative commands within docker.  Add
success logging at end of create-neighborhood so that some thread widget
errors don't make people think that command failed.


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

Branch: refs/heads/hs/7919
Commit: a1aab2208a37d3a32ed6639650eedcd5325dccaf
Parents: 0323078
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 5 13:38:39 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Oct 5 13:38:39 2015 -0400

----------------------------------------------------------------------
 Allura/allura/command/create_neighborhood.py   |  5 +++++
 Allura/docs/getting_started/administration.rst |  4 ++++
 Allura/docs/getting_started/installation.rst   | 20 +++++++++++++-------
 Dockerfile                                     | 13 +++++++++----
 docker-compose.yml                             |  8 ++++----
 5 files changed, 35 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a1aab220/Allura/allura/command/create_neighborhood.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/create_neighborhood.py b/Allura/allura/command/create_neighborhood.py
index db79bb0..d099c46 100644
--- a/Allura/allura/command/create_neighborhood.py
+++ b/Allura/allura/command/create_neighborhood.py
@@ -15,6 +15,8 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+import logging
+
 from . import base
 
 from ming.orm import session
@@ -23,6 +25,8 @@ from bson import ObjectId
 from allura import model as M
 from allura.lib import plugin, exceptions
 
+log = logging.getLogger(__name__)
+
 
 class CreateNeighborhoodCommand(base.Command):
     min_args = 3
@@ -44,6 +48,7 @@ class CreateNeighborhoodCommand(base.Command):
                           google_analytics=False))
         project_reg = plugin.ProjectRegistrationProvider.get()
         project_reg.register_neighborhood_project(n, admins)
+        log.info('Successfully created neighborhood "{}"'.format(shortname))
 
 
 class UpdateNeighborhoodCommand(base.Command):

http://git-wip-us.apache.org/repos/asf/allura/blob/a1aab220/Allura/docs/getting_started/administration.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/administration.rst b/Allura/docs/getting_started/administration.rst
index 1571cb6..8673840 100644
--- a/Allura/docs/getting_started/administration.rst
+++ b/Allura/docs/getting_started/administration.rst
@@ -76,6 +76,10 @@ Scripts are in the `scripts/` directory and run slightly differently, via `paste
 
      paster script development.ini ../scripts/create-allura-sitemap.py -- -u 100
 
+To run these when using docker, prefix with :code:`docker-compose run web` and use :code:`docker-dev.ini` like::
+
+    docker-compose run taskd paster create-neighborhood docker-dev.ini myneighborhood myuser ...
+
 Tasks can be run via the web interface at http://MYSITE/nf/admin/task_manager  You must know
 the full task name, e.g. :code:`allura.tasks.admin_tasks.install_app`  You can
 optionally provide a username and project and app which will get set on the

http://git-wip-us.apache.org/repos/asf/allura/blob/a1aab220/Allura/docs/getting_started/installation.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/getting_started/installation.rst b/Allura/docs/getting_started/installation.rst
index 026da99..e180ac3 100644
--- a/Allura/docs/getting_started/installation.rst
+++ b/Allura/docs/getting_started/installation.rst
@@ -182,12 +182,12 @@ Allura uses a background task service called "taskd" to do async tasks like send
 A few more steps, if using git
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If you're using a released version of Allura, these are already done for you.  This transpiles JS into a version all browsers support:
+If you're using a released version of Allura, these are already done for you.  This transpiles JS into a version all browsers support.
+For non-Ubuntu installations see https://nodejs.org/en/download/package-manager/ for other options to replace the first line here:
 
 .. code-block:: bash
 
-    (env-allura)~$ sudo aptitude install nodejs npm
-    (env-allura)~$ sudo ln -s /usr/bin/nodejs /usr/bin/node
+    (env-allura)~$ curl --silent --location https://deb.nodesource.com/setup_4.x | sudo bash -
     (env-allura)~$ cd ~/src/allura
     (env-allura)~$ npm install -g broccoli-cli
     (env-allura)~$ npm install
@@ -256,7 +256,7 @@ Build/fetch all required images (run these in allura source directory):
 
     docker-compose build
 
-Install requirements:
+Install requirements (and first containers started):
 
 .. code-block:: bash
 
@@ -272,11 +272,11 @@ Initialize database with test data:
 
 .. code-block:: bash
 
-    docker-compose run web bash -c 'cd Allura && paster setup-app docker-dev.ini'
+    docker-compose run taskd paster setup-app docker-dev.ini
 
 .. note::
 
-   If you want to skip test data creation you can instead run: :code:`docker-compose run web bash -c 'cd Allura && ALLURA_TEST_DATA=False paster setup-app docker-dev.ini'`
+   If you want to skip test data creation you can instead run: :code:`docker-compose run -e ALLURA_TEST_DATA=False taskd paster setup-app docker-dev.ini`
 
 Start containers in the background:
 
@@ -284,9 +284,15 @@ Start containers in the background:
 
     docker-compose up -d
 
-You're up and running!  Visit localhost:8080 or on a Mac or Windows, whatever IP address Docker Toolbox is using.  Then
+You're up and running!  Visit localhost:8080, or on a Mac or Windows whatever IP address Docker Toolbox is using.  Then
 see our :ref:`post-setup-instructions` and read more below about the Docker environment for Allura.
 
+.. note::
+
+   If running from git source, it will take a few minutes during the first time running "up", to set up JS build tools
+   before the webapp is actually running on port 8080.  Watch the progress with :code:`docker-compose logs web`.
+
+
 Containers
 ^^^^^^^^^^
 

http://git-wip-us.apache.org/repos/asf/allura/blob/a1aab220/Dockerfile
----------------------------------------------------------------------
diff --git a/Dockerfile b/Dockerfile
index f125d55..f91dd98 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -30,8 +30,13 @@ RUN apt-get update && apt-get install -y \
     zip \
     subversion \
     python-svn \
-    npm
-RUN ln -s /usr/bin/nodejs /usr/bin/node
+    curl
+
+# up-to-date version of node & npm
+RUN curl --silent --location https://deb.nodesource.com/setup_4.x | sudo bash - && \
+    apt-get install --yes nodejs
+
+# only do the global installation here.  All local packages are installed in the docker-compose.yml command, since they need the shared mount
 RUN npm install -g broccoli-cli
 
 # Snapshot generation for SVN (and maybe other SCMs) might fail without this
@@ -42,5 +47,5 @@ ENV LANG en_US.UTF-8
 # tests). If this is not set, it uses os.getlogin, which fails inside docker.
 ENV USER root
 
-WORKDIR /allura/Allura
-CMD gunicorn --paste docker-dev.ini --reload
+WORKDIR /allura
+CMD gunicorn --paste Allura/docker-dev.ini --reload

http://git-wip-us.apache.org/repos/asf/allura/blob/a1aab220/docker-compose.yml
----------------------------------------------------------------------
diff --git a/docker-compose.yml b/docker-compose.yml
index faac4a4..5eaaf4c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -17,16 +17,16 @@
 
 web:
   build: .
-  working_dir: /allura
-  # specialized command (and working_dir) to run broccoli
+  # specialized command to run broccoli
   # since it depends on files from the shared volume, it can't be run as part of the Dockerfile build :(
+  # and --no-bin-links necessary when Virtualbox is used since shared mount can't handle symlinks
   command: >
     sh -c '
     if [ ! -e Allura/allura/public/nf/js/build/transpiled.js ]; then
-      npm install &&
+      npm install --no-bin-links --loglevel http &&
       npm run build;
     fi;
-    gunicorn --paste Allura/docker-dev.ini --reload
+    gunicorn --paste Allura/docker-dev.ini --reload;
     '
   ports:
     - "8080:8080"


[05/42] allura git commit: [#7980] Fix many pep8 / pyflakes and related issues

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/Allura/setup.cfg
----------------------------------------------------------------------
diff --git a/Allura/setup.cfg b/Allura/setup.cfg
index a835b71..0298938 100644
--- a/Allura/setup.cfg
+++ b/Allura/setup.cfg
@@ -15,6 +15,12 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0
 

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeActivity/forgeactivity/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_rest.py b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
index f85639a..8c9e0f5 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_rest.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
@@ -33,9 +33,9 @@ class TestActivityHasAccessAPI(TestRestApiBase):
         config['activitystream.enabled'] = self._enabled
 
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/activity/has_access', status=404)
-        r = self.api_get('/rest/p/test/activity/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/activity/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/activity/has_access', status=404)
+        self.api_get('/rest/p/test/activity/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/activity/has_access?perm=read', status=404)
 
     def test_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeBlog/forgeblog/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/tests/functional/test_rest.py b/ForgeBlog/forgeblog/tests/functional/test_rest.py
index 3df73da..e7a9d7b 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_rest.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_rest.py
@@ -214,9 +214,9 @@ class TestBlogApi(TestRestApiBase):
         assert_equal(r.json['page'], 2)
 
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/blog/has_access', status=404)
-        r = self.api_get('/rest/p/test/blog/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/blog/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/blog/has_access', status=404)
+        self.api_get('/rest/p/test/blog/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/blog/has_access?perm=read', status=404)
 
     def test_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index caad619..c66d5f8 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -26,7 +26,7 @@ from email.mime.multipart import MIMEMultipart
 
 import pkg_resources
 from pylons import tmpl_context as c
-from nose.tools import assert_equal, assert_in, assert_not_in
+from nose.tools import assert_equal, assert_in, assert_not_in, assert_true, assert_false
 import feedparser
 
 from allura import model as M
@@ -147,9 +147,8 @@ class TestForumAsync(TestController):
         self.user = M.User.query.get(username='root')
 
     def test_has_access(self):
-        assert False == c.app.has_access(M.User.anonymous(), 'testforum')
-        assert True == c.app.has_access(
-            M.User.query.get(username='root'), 'testforum')
+        assert_false(c.app.has_access(M.User.anonymous(), 'testforum'))
+        assert_true(c.app.has_access(M.User.query.get(username='root'), 'testforum'))
 
     def test_post(self):
         self._post('testforum', 'Test Thread', 'Nothing here')
@@ -209,9 +208,8 @@ class TestForumAsync(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params['subject'] = 'New Subject'
         params['text'] = 'Asdf'
         r = self.app.post(url, params=params)
@@ -221,9 +219,8 @@ class TestForumAsync(TestController):
         params = dict()
         inputs = post_form.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[post_form.find('textarea')['name']] = 'text'
         r = self.app.post(url + 'reply', params=params)
         self._post('testforum', 'Test Reply', 'Nothing here, either',
@@ -317,7 +314,6 @@ class TestForum(TestController):
                 form[field.name] = 'Test_Description'
         return form
 
-
     def test_unicode_name(self):
         r = self.app.get('/admin/discussion/forums')
         form = r.forms[3]
@@ -375,9 +371,8 @@ class TestForum(TestController):
             params = dict()
             inputs = f.findAll('input')
             for field in inputs:
-                if field.has_key('name'):
-                    params[field['name']] = field.has_key(
-                        'value') and field['value'] or ''
+                if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                    params[field['name']] = field.get('value') or ''
             params[f.find('textarea')['name']] = '1st post in Zero Posts thread'
             params[f.find('select')['name']] = 'testforum'
             params[f.find('input', {'style': 'width: 90%'})['name']] = 'Test Zero Posts'
@@ -419,8 +414,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'This is a *test thread*'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'Test Thread'
@@ -443,8 +438,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'Post text'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = "this is <h2> o'clock"
@@ -477,8 +472,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'Post content'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'Test Thread'
@@ -503,8 +498,7 @@ class TestForum(TestController):
         assert 'Post content' in r
         r = self.app.get('/discussion/testforum/moderate/')
         post = FM.ForumPost.query.get(text='Post content')
-        link = '<a href="%s">[%s]</a>' % (post.thread.url()
-                                          + '?limit=25#' + post.slug, post.shorthand_id())
+        link = '<a href="%s">[%s]</a>' % (post.thread.url() + '?limit=25#' + post.slug, post.shorthand_id())
         assert link in r, link
 
     def test_thread(self):
@@ -514,8 +508,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'aaa'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'AAA'
@@ -528,8 +522,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'bbb'
         thread = self.app.post(str(rep_url), params=params)
         thread = self.app.get(url)
@@ -550,8 +544,8 @@ class TestForum(TestController):
         params = dict()
         inputs = reply_form.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[reply_form.find('textarea')['name']] = 'zzz'
         self.app.post(post_link, params)
         r = self.app.get(thread_url)
@@ -565,8 +559,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'Post text'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'Post subject'
@@ -579,8 +573,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name') and 'subscription' not in field['name']:
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         self.app.post(str(subscribe_url), params=params)
         self.app.post('/discussion/general/subscribe_to_forum', {'subscribe': True})
         f = thread.html.find('div', {'class': 'row reply_post_form'}).find('form')
@@ -588,8 +582,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'Reply 2'
         self.app.post(str(rep_url), params=params)
         assert M.Notification.query.find(
@@ -613,8 +607,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'aaa aaa'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'AAAA'
@@ -666,8 +660,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'aaa aaa'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'topic1'
@@ -680,8 +674,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'aaa aaa'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'topic2'
@@ -731,8 +725,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'aaa aaa'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'topic1'
@@ -746,8 +740,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'bbb'
         thread = self.app.post(str(rep_url), params=params)
         thread = self.app.get(url)
@@ -779,8 +773,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'aaa'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'AAA'
@@ -803,8 +797,8 @@ class TestForum(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'aaa'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'AAA'
@@ -847,7 +841,7 @@ class TestForum(TestController):
         timestamp_before = M.Project.query.get(shortname='test').last_updated
 
         # View the thread and make sure project last_updated is not updated
-        thread = self.app.get(url)
+        self.app.get(url)
         timestamp_after = M.Project.query.get(shortname='test').last_updated
         assert_equal(timestamp_before, timestamp_after)
 

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
index 4597017..3e7f0d4 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
@@ -188,9 +188,8 @@ class TestForumAdmin(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'secret text'
         params[f.find('select')['name']] = 'secret'
         params[f.find('input', {'style': 'width: 90%'})
@@ -243,9 +242,8 @@ class TestForumAdmin(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'post text'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'post topic'
@@ -269,9 +267,8 @@ class TestForumAdmin(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'post text'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'post topic'
@@ -299,9 +296,8 @@ class TestForumAdmin(TestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'post text'
         params[f.find('select')['name']] = 'testforum'
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'post topic'
@@ -309,7 +305,8 @@ class TestForumAdmin(TestController):
         M.MonQTask.run_ready()
         email_tasks = M.MonQTask.query.find(
             dict(task_name='allura.tasks.mail_tasks.sendsimplemail')).all()
-        assert 'Sent from localhost because email@monitoring.com is subscribed to http://localhost/p/test/discussion/testforum/' in email_tasks[
+        assert 'Sent from localhost because email@monitoring.com is subscribed '\
+               'to http://localhost/p/test/discussion/testforum/' in email_tasks[
             0].kwargs['text'], email_tasks[0].kwargs['text']
         assert 'a project admin can change settings at http://localhost/p/test/admin/discussion/forums' in email_tasks[
             0].kwargs['text']

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
index c7624a4..bf677e9 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
@@ -55,9 +55,8 @@ class TestDiscussionApiBase(TestRestApiBase):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key(
-                    'value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = text
         params[f.find('select')['name']] = forum
         params[f.find('input', {'style': 'width: 90%'})['name']] = subject
@@ -250,9 +249,9 @@ class TestRootRestController(TestDiscussionApiBase):
         assert_equal(r.json['forums'][0]['shortname'], 'general')
 
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/discussion/has_access', status=404)
-        r = self.api_get('/rest/p/test/discussion/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/discussion/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/discussion/has_access', status=404)
+        self.api_get('/rest/p/test/discussion/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/discussion/has_access?perm=read', status=404)
 
     def test_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeDiscussion/forgediscussion/widgets/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/widgets/__init__.py b/ForgeDiscussion/forgediscussion/widgets/__init__.py
index f733ddb..53322a7 100644
--- a/ForgeDiscussion/forgediscussion/widgets/__init__.py
+++ b/ForgeDiscussion/forgediscussion/widgets/__init__.py
@@ -18,3 +18,7 @@
 from forum_widgets import ForumSubscriptionForm, ThreadSubscriptionForm, AnnouncementsTable
 from forum_widgets import ModerateThread, ForumHeader, ThreadHeader
 from forum_widgets import Post, Thread, Forum
+
+__all__ = [
+    'ForumSubscriptionForm', 'ThreadSubscriptionForm', 'AnnouncementsTable', 'ModerateThread', 'ForumHeader',
+    'ThreadHeader', 'Post', 'Thread', 'Forum']

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeGit/forgegit/tests/functional/test_controllers.py
----------------------------------------------------------------------
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index cdff7c8..0e0928d 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -42,7 +42,6 @@ from forgegit import model as GM
 
 
 class _TestCase(TestController):
-
     def setUp(self):
         super(_TestCase, self).setUp()
         self.setup_with_tools()
@@ -50,8 +49,7 @@ class _TestCase(TestController):
     @with_git
     def setup_with_tools(self):
         h.set_context('test', 'src-git', neighborhood='Projects')
-        repo_dir = pkg_resources.resource_filename(
-            'forgegit', 'tests/data')
+        repo_dir = pkg_resources.resource_filename('forgegit', 'tests/data')
         c.app.repo.fs_path = repo_dir
         c.app.repo.status = 'ready'
         c.app.repo.name = 'testgit.git'
@@ -67,8 +65,7 @@ class _TestCase(TestController):
     @with_tool('test', 'Git', 'testgit-index', 'Git', type='git')
     def setup_testgit_index_repo(self):
         h.set_context('test', 'testgit-index', neighborhood='Projects')
-        repo_dir = pkg_resources.resource_filename(
-            'forgegit', 'tests/data')
+        repo_dir = pkg_resources.resource_filename('forgegit', 'tests/data')
         c.app.repo.fs_path = repo_dir
         c.app.repo.status = 'ready'
         c.app.repo.name = 'testgit_index.git'
@@ -79,13 +76,10 @@ class _TestCase(TestController):
 
 
 class TestRootController(_TestCase):
-
-
     @with_tool('test', 'Git', 'weird-chars', 'WeirdChars', type='git')
     def _setup_weird_chars_repo(self):
         h.set_context('test', 'weird-chars', neighborhood='Projects')
-        repo_dir = pkg_resources.resource_filename(
-            'forgegit', 'tests/data')
+        repo_dir = pkg_resources.resource_filename('forgegit', 'tests/data')
         c.app.repo.fs_path = repo_dir
         c.app.repo.status = 'ready'
         c.app.repo.name = 'weird-chars.git'
@@ -135,41 +129,34 @@ class TestRootController(_TestCase):
              u'message': u'Add README', u'row': 2})
 
     def test_log(self):
-        resp = self.app.get(
-            '/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/')
+        resp = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/')
         assert 'Initial commit' in resp
         assert '<div class="markdown_content"><p>Change README</div>' in resp
         assert 'tree/README?format=raw">Download</a>' not in resp
-        assert 'Tree' in resp.html.findAll(
-            'td')[2].text, resp.html.findAll('td')[2].text
+        assert 'Tree' in resp.html.findAll('td')[2].text, resp.html.findAll('td')[2].text
         assert 'byRick Copeland' in resp.html.findAll('td')[0].text, resp.html.findAll('td')[0].text
-        resp = self.app.get(
-            '/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/README')
+        resp = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/README')
         assert 'View' in resp.html.findAll('td')[2].text
         assert 'Change README' in resp
         assert 'tree/README?format=raw">Download</a>' in resp
         assert 'Add README' in resp
         assert "Initial commit " not in resp
-        resp = self.app.get(
-            '/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/a/b/c/')
+        resp = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/a/b/c/')
         assert 'Remove file' in resp
         assert 'Initial commit' in resp
         assert 'Add README' not in resp
         assert 'Change README' not in resp
-        resp = self.app.get(
-            '/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/not/exist')
+        resp = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/not/exist')
         assert 'No (more) commits' in resp
 
     def test_diff_ui(self):
-        r = self.app.get(
-            '/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/README')
+        r = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/README')
         assert '<div class="grid-19"><input type="button" value="Compare" class="compare_revision"></div>' in r
         assert '<input type="checkbox" class="revision"' in r
         assert 'revision="1e146e67985dcd71c74de79613719bef7bddca4a"' in r
         assert 'url_commit="/p/test/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/">' in r
 
-        r = self.app.get(
-            '/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/')
+        r = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/')
         assert '<div class="grid-19"><input type="button" value="Compare" class="compare_revision"></div>' not in r
         assert '<input type="checkbox" class="revision"' not in r
         assert 'revision="1e146e67985dcd71c74de79613719bef7bddca4a"' not in r
@@ -247,10 +234,8 @@ class TestRootController(_TestCase):
     def test_file(self):
         ci = self._get_ci()
         resp = self.app.get(ci + 'tree/README')
-        assert 'README' in resp.html.find(
-            'h2', {'class': 'dark title'}).contents[2]
-        content = str(
-            resp.html.find('div', {'class': 'clip grid-19 codebrowser'}))
+        assert 'README' in resp.html.find('h2', {'class': 'dark title'}).contents[2]
+        content = str(resp.html.find('div', {'class': 'clip grid-19 codebrowser'}))
         assert 'This is readme' in content, content
         assert '<span id="l1" class="code_block">' in resp
         assert 'var hash = window.location.hash.substring(1);' in resp
@@ -261,16 +246,14 @@ class TestRootController(_TestCase):
         url = ci + 'tree/' + h.urlquote(u'привіт.txt') + '?format=raw'
         resp = self.app.get(url)
         assert_in(u'Привіт!\nWhich means Hello!', resp.body.decode('utf-8'))
-        assert_equal(
-            resp.headers.get('Content-Disposition').decode('utf-8'),
-            u'attachment;filename="привіт.txt"')
+        assert_equal(resp.headers.get('Content-Disposition').decode('utf-8'),
+                     u'attachment;filename="привіт.txt"')
 
         url = ci + 'tree/' + h.urlquote(u'with space.txt') + '?format=raw'
         resp = self.app.get(url)
         assert_in(u'with space', resp.body.decode('utf-8'))
-        assert_equal(
-            resp.headers.get('Content-Disposition').decode('utf-8'),
-            u'attachment;filename="with space.txt"')
+        assert_equal(resp.headers.get('Content-Disposition').decode('utf-8'),
+                     u'attachment;filename="with space.txt"')
 
     def test_invalid_file(self):
         ci = self._get_ci()
@@ -278,8 +261,7 @@ class TestRootController(_TestCase):
 
     def test_diff(self):
         ci = self._get_ci()
-        resp = self.app.get(
-            ci + 'tree/README?diff=df30427c488aeab84b2352bdf88a3b19223f9d7a')
+        resp = self.app.get(ci + 'tree/README?diff=df30427c488aeab84b2352bdf88a3b19223f9d7a')
         assert 'readme' in resp, resp.showbrowser()
         assert '+++' in resp, resp.showbrowser()
 
@@ -287,8 +269,7 @@ class TestRootController(_TestCase):
         ci = self._get_ci()
         fn = 'tree/README?diff=df30427c488aeab84b2352bdf88a3b19223f9d7a'
         r = self.app.get(ci + fn + '&diformat=regular')
-        assert fn + \
-            '&amp;diformat=sidebyside">Switch to side-by-side view</a>' in r
+        assert fn + '&amp;diformat=sidebyside">Switch to side-by-side view</a>' in r
 
         r = self.app.get(ci + fn + '&diformat=sidebyside')
         assert fn + '&amp;diformat=regular">Switch to unified view</a>' in r
@@ -297,8 +278,7 @@ class TestRootController(_TestCase):
     def test_refresh(self):
         notification = M.Notification.query.find({'subject': '[test:src-git] 5 new commits to Git'}).first()
         assert notification
-        domain = '.'.join(
-            reversed(c.app.url[1:-1].split('/'))).replace('_', '-')
+        domain = '.'.join(reversed(c.app.url[1:-1].split('/'))).replace('_', '-')
         common_suffix = tg.config['forgemail.domain']
         email = 'noreply@%s%s' % (domain, common_suffix)
         assert_in(email, notification['reply_to_address'])
@@ -306,8 +286,7 @@ class TestRootController(_TestCase):
     def test_file_force_display(self):
         ci = self._get_ci()
         resp = self.app.get(ci + 'tree/README?force=True')
-        content = str(
-            resp.html.find('div', {'class': 'clip grid-19 codebrowser'}))
+        content = str(resp.html.find('div', {'class': 'clip grid-19 codebrowser'}))
         assert re.search(r'<pre>.*This is readme', content), content
         assert '</pre>' in content, content
 
@@ -320,8 +299,7 @@ class TestRootController(_TestCase):
         r = self.app.get(ci + 'tree/index.html')
         header = r.html.find('h2', {'class': 'dark title'}).contents[2]
         assert 'index.html' in header, header
-        content = str(
-            r.html.find('div', {'class': 'clip grid-19 codebrowser'}))
+        content = str(r.html.find('div', {'class': 'clip grid-19 codebrowser'}))
         assert ('<span class="nt">&lt;h1&gt;</span>'
                 'index.html'
                 '<span class="nt">&lt;/h1&gt;</span>') in content, content
@@ -335,8 +313,7 @@ class TestRootController(_TestCase):
         header = r.html.find('h2', {'class': 'dark title'})
         assert 'index' in header.contents[3], header.contents[3]
         assert 'index.htm' in header.contents[4], header.contents[4]
-        content = str(
-            r.html.find('div', {'class': 'clip grid-19 codebrowser'}))
+        content = str(r.html.find('div', {'class': 'clip grid-19 codebrowser'}))
         assert ('<span class="nt">&lt;h1&gt;</span>'
                 'index/index.htm'
                 '<span class="nt">&lt;/h1&gt;</span>') in content, content
@@ -387,9 +364,7 @@ class TestRootController(_TestCase):
         assert not '<div id="access_urls"' in r
         r = self.app.get('/src-git/fork')
         assert not '<div id="access_urls"' in r
-        r = self.app.get(
-            ci +
-            'tree/README?diff=df30427c488aeab84b2352bdf88a3b19223f9d7a')
+        r = self.app.get(ci + 'tree/README?diff=df30427c488aeab84b2352bdf88a3b19223f9d7a')
         assert not '<div id="access_urls"' in r
         r = self.app.get(ci + 'tree/README')
         assert not '<div id="access_urls"' in r
@@ -419,8 +394,7 @@ class TestRootController(_TestCase):
         self.setup_testgit_index_repo()
         r = self.app.get('/p/test/testgit-index/ci/master/tree/index/')
         form = r.html.find('form', 'tarball')
-        assert_equal(
-            form.get('action'), '/p/test/testgit-index/ci/master/tarball')
+        assert_equal(form.get('action'), '/p/test/testgit-index/ci/master/tarball')
         assert_equal(form.input.get('value'), '/index')
 
     def test_default_branch(self):
@@ -466,7 +440,6 @@ class TestRootController(_TestCase):
 
 
 class TestRestController(_TestCase):
-
     def test_index(self):
         self.app.get('/rest/p/test/src-git/', status=200)
 
@@ -475,7 +448,6 @@ class TestRestController(_TestCase):
 
 
 class TestHasAccessAPI(TestRestApiBase):
-
     def setUp(self):
         super(TestHasAccessAPI, self).setUp()
         self.setup_with_tools()
@@ -485,9 +457,9 @@ class TestHasAccessAPI(TestRestApiBase):
         pass
 
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/src-git/has_access', status=404)
-        r = self.api_get('/rest/p/test/src-git/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/src-git/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/src-git/has_access', status=404)
+        self.api_get('/rest/p/test/src-git/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/src-git/has_access?perm=read', status=404)
 
     def test_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""
@@ -526,7 +498,6 @@ class TestHasAccessAPI(TestRestApiBase):
 
 
 class TestFork(_TestCase):
-
     def setUp(self):
         super(TestFork, self).setUp()
         to_project = M.Project.query.get(
@@ -575,7 +546,8 @@ class TestFork(_TestCase):
         return r
 
     def _find_request_merge_form(self, resp):
-        cond = lambda f: f.action == 'do_request_merge'
+        def cond(f):
+            return f.action == 'do_request_merge'
         return self.find_form(resp, cond)
 
     def _request_merge(self, **kw):
@@ -684,8 +656,7 @@ class TestFork(_TestCase):
         assert 'Merge Request #%s:  (rejected)' % mr_num in r, r
 
     def test_merge_request_default_branches(self):
-        _select_val = lambda r, n: r.html.find(
-            'select', {'name': n}).find(selected=True).string
+        _select_val = lambda r, n: r.html.find('select', {'name': n}).find(selected=True).string
         r = self.app.get('/p/test2/code/request_merge')
         assert_equal(_select_val(r, 'source_branch'), 'master')
         assert_equal(_select_val(r, 'target_branch'), 'master')
@@ -719,11 +690,12 @@ class TestFork(_TestCase):
 
     def test_merge_request_edit(self):
         r = self.app.post('/p/test2/code/do_request_merge',
-            params={
-                'source_branch': 'zz',
-                'target_branch': 'master',
-                'summary': 'summary',
-                'description': 'description'}).follow()
+                          params={
+                              'source_branch': 'zz',
+                              'target_branch': 'master',
+                              'summary': 'summary',
+                              'description': 'description',
+                          }).follow()
         assert '<a href="edit" title="Edit"><b data-icon="p" class="ico ico-pencil" title="Edit"></b></a>' in r
         r = self.app.get('/p/test/src-git/merge-requests/1/edit')
         assert 'value="summary"' in r
@@ -732,20 +704,24 @@ class TestFork(_TestCase):
         assert md_edit is not None, 'MarkdownEdit widget not found'
 
         r = self.app.post('/p/test/src-git/merge-requests/1/do_request_merge_edit',
-            params={
-                'source_branch': 'zz',
-                'target_branch': 'master',
-                'summary': 'changed summary',
-                'description': 'changed description'},
-                extra_environ=dict(username='*anonymous'), status=302).follow()
+                          params={
+                              'source_branch': 'zz',
+                              'target_branch': 'master',
+                              'summary': 'changed summary',
+                              'description': 'changed description'
+                          },
+                          extra_environ=dict(username='*anonymous'),
+                          status=302,
+                          ).follow()
         assert 'Login' in r
 
         r = self.app.post('/p/test/src-git/merge-requests/1/do_request_merge_edit',
-            params={
-                'source_branch': 'master',
-                'target_branch': 'master',
-                'summary': 'changed summary',
-                'description': 'changed description'}).follow()
+                          params={
+                              'source_branch': 'master',
+                              'target_branch': 'master',
+                              'summary': 'changed summary',
+                              'description': 'changed description',
+                          }).follow()
 
         assert '[5c4724]' not in r
         assert '<p>changed description</p' in r
@@ -786,7 +762,6 @@ class TestFork(_TestCase):
 
 
 class TestDiff(TestController):
-
     def setUp(self):
         super(TestDiff, self).setUp()
         self.setup_with_tools()
@@ -794,8 +769,7 @@ class TestDiff(TestController):
     @with_git
     def setup_with_tools(self):
         h.set_context('test', 'src-git', neighborhood='Projects')
-        repo_dir = pkg_resources.resource_filename(
-            'forgegit', 'tests/data')
+        repo_dir = pkg_resources.resource_filename('forgegit', 'tests/data')
         c.app.repo.fs_path = repo_dir
         c.app.repo.status = 'ready'
         c.app.repo.name = 'testmime.git'
@@ -805,19 +779,18 @@ class TestDiff(TestController):
         ThreadLocalORMSession.flush_all()
 
     def test_diff(self):
-        r = self.app.get(
-            '/src-git/ci/d961abbbf10341ee18a668c975842c35cfc0bef2/tree/1.png?barediff=2ce83a24e52c21e8d2146b1a04a20717c0bb08d7')
+        r = self.app.get('/src-git/ci/d961abbbf10341ee18a668c975842c35cfc0bef2/tree/1.png'
+                         '?barediff=2ce83a24e52c21e8d2146b1a04a20717c0bb08d7')
         assert 'alt="2ce83a2..."' in r
         assert 'alt="d961abb..."' in r
 
-        r = self.app.get(
-            '/src-git/ci/d961abbbf10341ee18a668c975842c35cfc0bef2/tree/1.png?diff=2ce83a24e52c21e8d2146b1a04a20717c0bb08d7')
+        r = self.app.get('/src-git/ci/d961abbbf10341ee18a668c975842c35cfc0bef2/tree/1.png'
+                         '?diff=2ce83a24e52c21e8d2146b1a04a20717c0bb08d7')
         assert 'alt="2ce83a2..."' in r
         assert 'alt="d961abb..."' in r
 
 
 class TestGitRename(TestController):
-
     def setUp(self):
         super(TestGitRename, self).setUp()
         self.setup_with_tools()
@@ -862,8 +835,9 @@ class TestGitRename(TestController):
 
         # the diff portion of the output
         resp_no_ws = re.sub(r'\s+', '', str(resp))
-        assert '<a href="/p/test/src-git/ci/fbb0644603bb6ecee3ebb62efe8c86efc9b84ee6/tree/f.txt">f.txt</a>to<a href="/p/test/src-git/ci/b120505a61225e6c14bee3e5b5862db81628c35c/tree/f2.txt">f2.txt</a>'.replace(' ','') \
-               in resp_no_ws
+        assert_in('<a href="/p/test/src-git/ci/fbb0644603bb6ecee3ebb62efe8c86efc9b84ee6/tree/f.txt">f.txt</a>'
+                  'to<a href="/p/test/src-git/ci/b120505a61225e6c14bee3e5b5862db81628c35c/tree/f2.txt">f2.txt</a>'
+                  .replace(' ', ''), resp_no_ws)
         assert '<span class="empty-diff">File was renamed.</span>' in resp
 
 
@@ -875,8 +849,7 @@ class TestGitBranch(TestController):
     @with_git
     def setup_with_tools(self):
         h.set_context('test', 'src-git', neighborhood='Projects')
-        repo_dir = pkg_resources.resource_filename(
-            'forgegit', 'tests/data')
+        repo_dir = pkg_resources.resource_filename('forgegit', 'tests/data')
         c.app.repo.fs_path = repo_dir
         c.app.repo.status = 'ready'
         c.app.repo.name = 'test_branch.git'
@@ -892,7 +865,6 @@ class TestGitBranch(TestController):
 
 
 class TestIncludeMacro(_TestCase):
-
     def setUp(self):
         super(TestIncludeMacro, self).setUp()
         setup_global_objects()

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeImporters/forgeimporters/tests/google/test_extractor.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/google/test_extractor.py b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
index fe74f9c..72a7d6c 100644
--- a/ForgeImporters/forgeimporters/tests/google/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
@@ -182,7 +182,8 @@ class TestGoogleCodeProjectExtractor(TestCase):
 
     @without_module('html2text')
     def test_get_issue_basic_fields(self):
-        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
+        test_issue = open(pkg_resources.resource_filename(
+            'forgeimporters', 'tests/data/google/test-issue.html')).read()
         gpe = self._make_extractor(test_issue)
 
         self.assertEqual(gpe.get_issue_creator().name, 'john...@gmail.com')
@@ -222,7 +223,8 @@ class TestGoogleCodeProjectExtractor(TestCase):
 
     @skipif(module_not_available('html2text'))
     def test_get_issue_basic_fields_html2text(self):
-        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
+        test_issue = open(pkg_resources.resource_filename(
+            'forgeimporters', 'tests/data/google/test-issue.html')).read()
         gpe = self._make_extractor(test_issue)
         self.assertEqual(gpe.get_issue_creator().name, 'john...@gmail.com')
         self.assertEqual(gpe.get_issue_creator().url,
@@ -303,8 +305,9 @@ class TestGoogleCodeProjectExtractor(TestCase):
         attachments = gpe.get_issue_attachments()
         self.assertEqual(len(attachments), 1)
         self.assertEqual(attachments[0].filename, 'at1.txt')
-        self.assertEqual(
-            attachments[0].url, 'http://allura-google-importer.googlecode.com/issues/attachment?aid=70000000&name=at1.txt&token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255')
+        self.assertEqual(attachments[0].url,
+                         'http://allura-google-importer.googlecode.com/issues/attachment?aid=70000000&name=at1.txt'
+                         '&token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255')
         self.assertEqual(attachments[0].type, 'text/plain')
 
     def test_get_issue_ids(self):
@@ -367,8 +370,10 @@ class TestWithSetupForComments(TestCase):
     # These tests use iter_comments and 2 HTML pages of comments.
 
     def _create_extractor(self):
-        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue-first-page.html')).read()
-        test_issue_older = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue-prev-page.html')).read()
+        test_issue = open(pkg_resources.resource_filename(
+            'forgeimporters', 'tests/data/google/test-issue-first-page.html')).read()
+        test_issue_older = open(pkg_resources.resource_filename(
+            'forgeimporters', 'tests/data/google/test-issue-prev-page.html')).read()
 
         class LocalTestExtractor(google.GoogleCodeProjectExtractor):
             def urlopen(self, url, **kw):
@@ -442,7 +447,8 @@ class TestWithSetupForComments(TestCase):
                 'author.name': 'john...@gmail.com',
                 'author.url': 'http://code.google.com/u/101557263855536553789/',
                 'created_date': 'Thu Aug  8 15:36:57 2013',
-                'body': 'Oh, I forgot one \\(with an inter\\-project reference to [issue other\\-project:1](https://code.google.com/p/other-project/issues/detail?id=1)\\)',
+                'body': 'Oh, I forgot one \\(with an inter\\-project reference to '
+                        '[issue other\\-project:1](https://code.google.com/p/other-project/issues/detail?id=1)\\)',
                 'updates': {'Labels:': 'OpSys-OSX'},
                 'attachments': [],
             },
@@ -511,7 +517,8 @@ class TestWithSetupForComments(TestCase):
                 'author.name': 'john...@gmail.com',
                 'author.url': 'http://code.google.com/u/101557263855536553789/',
                 'created_date': 'Thu Aug  8 15:36:57 2013',
-                'body': 'Oh, I forgot one \\(with an inter-project reference to [issue other-project:1](https://code.google.com/p/other-project/issues/detail?id=1)\\)',
+                'body': 'Oh, I forgot one \\(with an inter-project reference to '
+                        '[issue other-project:1](https://code.google.com/p/other-project/issues/detail?id=1)\\)',
                 'updates': {'Labels:': 'OpSys-OSX'},
                 'attachments': [],
             },

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeLink/forgelink/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeLink/forgelink/tests/functional/test_rest.py b/ForgeLink/forgelink/tests/functional/test_rest.py
index 7fd6485..b2ac3b3 100644
--- a/ForgeLink/forgelink/tests/functional/test_rest.py
+++ b/ForgeLink/forgelink/tests/functional/test_rest.py
@@ -91,9 +91,9 @@ class TestLinkHasAccess(TestRestApiBase):
         h.set_context('test', 'link', neighborhood='Projects')
 
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/link/has_access', status=404)
-        r = self.api_get('/rest/p/test/link/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/link/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/link/has_access', status=404)
+        self.api_get('/rest/p/test/link/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/link/has_access?perm=read', status=404)
 
     def test_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeTracker/forgetracker/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_rest.py b/ForgeTracker/forgetracker/tests/functional/test_rest.py
index d2f42bf..a45477e 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_rest.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_rest.py
@@ -249,9 +249,9 @@ class TestRestSearch(TestTrackerApiBase):
 class TestRestHasAccess(TestTrackerApiBase):
 
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/bugs/has_access', status=404)
-        r = self.api_get('/rest/p/test/bugs/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/bugs/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/bugs/has_access', status=404)
+        self.api_get('/rest/p/test/bugs/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/bugs/has_access?perm=read', status=404)
 
     def test_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index efcc59d..73ef421 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -67,11 +67,13 @@ class TrackerTestController(TestController):
         pass
 
     def _find_new_ticket_form(self, resp):
-        cond = lambda f: f.action.endswith('/save_ticket')
+        def cond(f):
+            return f.action.endswith('/save_ticket')
         return self.find_form(resp, cond)
 
     def _find_update_ticket_form(self, resp):
-        cond = lambda f: f.action.endswith('/update_ticket_from_widget')
+        def cond(f):
+            return f.action.endswith('/update_ticket_from_widget')
         return self.find_form(resp, cond)
 
     def new_ticket(self, mount_point='/bugs/', extra_environ=None, **kw):
@@ -363,8 +365,8 @@ class TestFunctionalController(TrackerTestController):
         assert 'test new ticket form description' in response
 
     def test_mass_edit(self):
-        ticket_view = self.new_ticket(summary='First Ticket').follow()
-        ticket_view = self.new_ticket(summary='Second Ticket').follow()
+        self.new_ticket(summary='First Ticket').follow()
+        self.new_ticket(summary='Second Ticket').follow()
         M.MonQTask.run_ready()
         first_ticket = tm.Ticket.query.find({'summary': 'First Ticket'}).first()
         second_ticket = tm.Ticket.query.find({'summary': 'Second Ticket'}).first()
@@ -627,7 +629,7 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/feed.atom', extra_environ=env)
         assert 'Private Ticket' not in r
         # ... or in the API ...
-        r = self.app.get('/rest/p/test/bugs/2/', extra_environ=env, status=401)
+        self.app.get('/rest/p/test/bugs/2/', extra_environ=env, status=401)
         r = self.app.get('/rest/p/test/bugs/', extra_environ=env)
         assert 'Private Ticket' not in r
 
@@ -870,8 +872,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'test comment'
         self.app.post(f['action'].encode('utf-8'), params=params,
                       headers={'Referer': '/bugs/1/'.encode("utf-8")})
@@ -881,7 +883,7 @@ class TestFunctionalController(TrackerTestController):
                       upload_files=[('file_info', 'test.txt', 'HiThere!')])
         r = self.app.get('/bugs/1/', dict(page=1))
         assert '<input class="submit delete_attachment file" type="submit" value="X"/>' in r
-        form = r.forms[5].submit()
+        r.forms[5].submit()
         r = self.app.get('/bugs/1/', dict(page=1))
         assert '<input class="submit delete_attachment" type="submit" value="X"/>' not in r
 
@@ -917,7 +919,7 @@ class TestFunctionalController(TrackerTestController):
         file_data = file(file_path).read()
         upload = ('attachment', file_name, file_data)
         self.new_ticket(summary='test new attachment')
-        ticket_editor = self.app.post('/bugs/1/update_ticket', {
+        self.app.post('/bugs/1/update_ticket', {
             'summary': 'zzz'
         }, upload_files=[upload]).follow()
         ticket = tm.Ticket.query.find({'ticket_num': 1}).first()
@@ -1116,8 +1118,8 @@ class TestFunctionalController(TrackerTestController):
             open_status_names='aa bb',
             closed_status_names='cc',
         )
-        r = self.app.post('/admin/bugs/set_custom_fields',
-                          params=variable_encode(params))
+        self.app.post('/admin/bugs/set_custom_fields',
+                      params=variable_encode(params))
         kw = {'custom_fields._number': ''}
         ticket_view = self.new_ticket(summary='test custom fields', **kw).follow()
         assert '<strong>Number</strong>:  --&gt;' not in ticket_view
@@ -1191,7 +1193,7 @@ class TestFunctionalController(TrackerTestController):
         assert 'Milestone' in ticket_view
         assert '1.0' in ticket_view
         assert 'zzzé' not in ticket_view
-        r = self.app.post('/bugs/update_milestones', {
+        self.app.post('/bugs/update_milestones', {
             'field_name': '_milestone',
             'milestones-0.old_name': '1.0',
             'milestones-0.new_name': 'zzzé',
@@ -1357,7 +1359,7 @@ class TestFunctionalController(TrackerTestController):
         self.new_ticket(summary='test first ticket')
         self.new_ticket(summary='test second ticket')
         p = M.Project.query.get(shortname='test')
-        tracker = p.app_instance('bugs')
+        p.app_instance('bugs')
         t = tm.Ticket.query.get(summary='test first ticket')
         t.reported_by_id = M.User.by_username('test-user-0')._id
         t = tm.Ticket.query.get(summary='test second ticket')
@@ -1422,8 +1424,8 @@ class TestFunctionalController(TrackerTestController):
             'sort': ''}).follow()
         r = self.app.get('/bugs/')
         assert sidebar_contains(r, 'This is not too long.')
-        r = self.app.post('/admin/bugs/bins/save_bin', {
-            'summary': 'This will be truncated because it is too long to show in the sidebar without being ridiculous.',
+        self.app.post('/admin/bugs/bins/save_bin', {
+            'summary': 'This will be truncated because it is too long to show in the sidebar without being ridiculous',
             'terms': 'aaa',
             'old_summary': '',
             'sort': ''}).follow()
@@ -1457,8 +1459,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = post_content
         r = self.app.post(f['action'].encode('utf-8'), params=params,
                           headers={'Referer': '/bugs/1/'.encode("utf-8")})
@@ -1473,8 +1475,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params['ticket_form.summary'] = new_summary
         r = self.app.post(f['action'].encode('utf-8'), params=params,
                           headers={'Referer': '/bugs/1/'.encode("utf-8")})
@@ -1492,8 +1494,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = post_content
         r = self.app.post(f['action'].encode('utf-8'), params=params,
                           headers={'Referer': '/bugs/1/'.encode("utf-8")})
@@ -1520,8 +1522,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = post_content
         self.app.post(f['action'].encode('utf-8'), params=params,
                       headers={'Referer': '/bugs/1/'.encode("utf-8")})
@@ -1534,8 +1536,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = post_form.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[post_form.find('textarea')['name']] = 'Tis a reply'
         r = self.app.post(post_link + 'reply',
                           params=params,
@@ -1559,7 +1561,8 @@ class TestFunctionalController(TrackerTestController):
         assert_in('test first ticket', str(ticket_rows))
         assert_in('test second ticket', str(ticket_rows))
         edit_link = response.html.find('a', {'title': 'Bulk Edit'})
-        expected_link = "/p/test/bugs/edit/?q=%21status%3Awont-fix+%26%26+%21status%3Aclosed&sort=snippet_s+asc&limit=25&filter=&page=0"
+        expected_link = "/p/test/bugs/edit/?q=%21status%3Awont-fix+%26%26+%21status%3Aclosed"\
+                        "&sort=snippet_s+asc&limit=25&filter=&page=0"
         assert_equal(expected_link, edit_link['href'])
         response = self.app.get(edit_link['href'])
         ticket_rows = response.html.find('tbody', {'class': 'ticket-list'})
@@ -2139,8 +2142,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = post_content
         r = self.app.post(f['action'].encode('utf-8'), params=params,
                           headers={'Referer': '/p/test2/bugs2/1/'.encode("utf-8")})
@@ -2317,7 +2320,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_tags(self):
         p = M.Project.query.get(shortname='test')
-        tracker = p.app_instance('bugs')
+        p.app_instance('bugs')
         self.new_ticket(summary='a', labels='tag1,tag2')
         self.new_ticket(summary='b', labels='tag2')
         self.new_ticket(summary='c', labels='42cc,test')
@@ -2336,8 +2339,8 @@ class TestFunctionalController(TrackerTestController):
         params = dict()
         inputs = f.findAll('input')
         for field in inputs:
-            if field.has_key('name'):
-                params[field['name']] = field.has_key('value') and field['value'] or ''
+            if field.has_key('name'):  # nopep8 - beautifulsoup3 actually uses has_key
+                params[field['name']] = field.get('value') or ''
         params[f.find('textarea')['name']] = 'test comment'
         self.app.post(f['action'].encode('utf-8'), params=params,
                       headers={'Referer': '/bugs/1/'.encode("utf-8")})
@@ -2392,7 +2395,9 @@ class TestFunctionalController(TrackerTestController):
             return_path, rcpts, body = _client.sendmail.call_args[0]
             body = body.split('\n')
             assert 'Subject: [test:bugs] #1 test <h2> ticket' in body
-            assert_in('<p><strong> <a class="alink" href="http://localhost:8080/p/test/bugs/1/">[bugs:#1]</a> test &lt;h2&gt; ticket</strong></p>', body)
+            assert_in('<p><strong> <a class="alink" href="http://localhost:8080/p/test/bugs/1/">[bugs:#1]</a>'
+                      ' test &lt;h2&gt; ticket</strong></p>',
+                      body)
 
     @patch('forgetracker.search.query_filter_choices')
     def test_multiselect(self, query_filter_choices):
@@ -2623,7 +2628,7 @@ class TestEmailMonitoring(TrackerTestController):
             if (('thread' in f['action']) and ('post' in f['action'])):
                 params = {i['name']: i.get('value', '')
                           for i in f.findAll('input')
-                          if i.has_key('name')}
+                          if i.has_key('name')}  # nopep8 - beautifulsoup3 actually uses has_key
                 params[f.find('textarea')['name']] = 'foobar'
                 self.app.post(str(f['action']), params)
                 break  # Do it only once if many forms met
@@ -2869,7 +2874,7 @@ class TestBulkMove(TrackerTestController):
         original_p = M.Project.query.get(shortname='test')
         tracker = p.app_instance('bugs')
         original_tracker = original_p.app_instance('bugs')
-        r = self.app.post('/p/test/bugs/move_tickets', {
+        self.app.post('/p/test/bugs/move_tickets', {
             'tracker': str(tracker.config._id),
             '__ticket_ids': [t._id for t in tickets],
             '__search': '',
@@ -2907,7 +2912,7 @@ class TestBulkMove(TrackerTestController):
         tickets[0].subscribe(user=first_user)
         tickets[1].subscribe(user=second_user)
         M.MonQTask.query.remove()
-        r = self.app.post('/p/test/bugs/move_tickets', {
+        self.app.post('/p/test/bugs/move_tickets', {
             'tracker': str(tracker.config._id),
             '__ticket_ids': [t._id for t in tickets],
             '__search': '',
@@ -2970,7 +2975,7 @@ class TestBulkMove(TrackerTestController):
         p = M.Project.query.get(shortname='test2')
         tracker = p.app_instance('bugs2')
         M.MonQTask.query.remove()
-        r = self.app.post('/p/test/bugs/move_tickets', {
+        self.app.post('/p/test/bugs/move_tickets', {
             'tracker': str(tracker.config._id),
             '__ticket_ids': [t._id for t in tickets],
             '__search': '',

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeWiki/forgewiki/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index 3bc61bb..4aba7f1 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -131,9 +131,9 @@ class TestWikiHasAccess(TestRestApiBase):
         h.set_context('test', 'wiki', neighborhood='Projects')
 
     def test_has_access_no_params(self):
-        r = self.api_get('/rest/p/test/wiki/has_access', status=404)
-        r = self.api_get('/rest/p/test/wiki/has_access?user=root', status=404)
-        r = self.api_get('/rest/p/test/wiki/has_access?perm=read', status=404)
+        self.api_get('/rest/p/test/wiki/has_access', status=404)
+        self.api_get('/rest/p/test/wiki/has_access?user=root', status=404)
+        self.api_get('/rest/p/test/wiki/has_access?perm=read', status=404)
 
     def test_has_access_unknown_params(self):
         """Unknown user and/or permission always False for has_access API"""

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/ForgeWiki/forgewiki/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index b716877..635e2b6 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -35,14 +35,6 @@ from alluratest.controller import TestController
 
 from forgewiki import model
 
-#---------x---------x---------x---------x---------x---------x---------x
-# RootController methods exposed:
-#     index, new_page, search
-# PageController methods exposed:
-#     index, edit, history, diff, raw, revert, update
-# CommentController methods exposed:
-#     reply, delete
-
 
 class TestRootController(TestController):
 
@@ -184,7 +176,8 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': 'test label',
                 'viewable_by-0.id': 'all'}).follow()
-        assert '''<a href="/p/test/wiki/search/?q=labels_t:%22test label%22&parser=standard">test label (1)</a>''' in response
+        assert_in('<a href="/p/test/wiki/search/?q=labels_t:%22test label%22&parser=standard">test label (1)</a>',
+                  response)
 
     def test_title_slashes(self):
         # forward slash not allowed in wiki page title - converted to dash
@@ -335,9 +328,13 @@ class TestRootController(TestController):
                                             **Note:** The logo shown in the sidebar is no longer stored as an object in the wiki (as it was in the Hosted App installation). Rather save it as a regular file, then edit LocalSettings.php, adding""")
         self.app.post('/wiki/testdiff/update', params=d)
         response = self.app.get('/wiki/testdiff/diff?v1=1&v2=2')
-        assert '# Now fix <del> permissons. </del> <ins> permissions. </ins> Wrong permissions may cause <ins> a </ins> massive slowdown!' in response
+        assert_in('# Now fix <del> permissons. </del> <ins> permissions. </ins> '
+                  'Wrong permissions may cause <ins> a </ins> massive slowdown!',
+                  response)
         response = self.app.get('/wiki/testdiff/diff?v1=2&v2=1')
-        assert '# Now fix <del> permissions. </del> <ins> permissons. </ins> Wrong permissions may cause <del> a </del> massive slowdown!' in response
+        assert_in('# Now fix <del> permissions. </del> <ins> permissons. </ins> '
+                  'Wrong permissions may cause <del> a </del> massive slowdown!',
+                  response)
 
     def test_page_raw(self):
         self.app.post(
@@ -763,7 +760,7 @@ class TestRootController(TestController):
         assert inp is not None
         # subscribe
         self.app.post('/p/test/wiki/subscribe', {'subscribe': True},
-                     extra_environ={'username': str(user.username)}).follow()
+                      extra_environ={'username': str(user.username)}).follow()
         # user is subscribed
         assert M.Mailbox.subscribed(user_id=user._id)
         r = self.app.get('/p/test/wiki/Home/', extra_environ={'username': str(user.username)})
@@ -771,7 +768,7 @@ class TestRootController(TestController):
         assert inp is not None
         # unsubscribe
         self.app.post('/p/test/wiki/subscribe', {'unsubscribe': True},
-                     extra_environ={'username': str(user.username)}).follow()
+                      extra_environ={'username': str(user.username)}).follow()
         # user is not subscribed
         assert not M.Mailbox.subscribed(user_id=user._id)
         r = self.app.get('/p/test/wiki/Home/', extra_environ={'username': str(user.username)})

http://git-wip-us.apache.org/repos/asf/allura/blob/9d39b9a7/scripts/teamforge-import.py
----------------------------------------------------------------------
diff --git a/scripts/teamforge-import.py b/scripts/teamforge-import.py
index 9f601a0..b668128 100644
--- a/scripts/teamforge-import.py
+++ b/scripts/teamforge-import.py
@@ -305,18 +305,7 @@ def convert_project_shortname(teamforge_path):
 
 # FIXME hardcoded
 skip_perms_usernames = set([
-    'faisal_saeed', 'dsarkisian', 'debonairamit', 'nishanthiremath', 'Bhuvnesh', 'bluetooth', 'cnkurzke', 'makow2', 'jannes1', 'Joel_Hegberg', 'Farroc', 'brian_chen', 'eirikur',
-    'dmitry_flyorov', 'bipingm', 'MornayJo', 'ibv', 'b_weisshaar', 'k9srb', 'johnmmills', 'a_gomolitsky', 'filim', 'kapoor', 'ljzegers', 'jrukes', 'dwilson9', 'jlin', 'quickie',
-    'johnbell', 'nnikolenko', 'Gaetan', 'Giannetta', 'Katia', 'jackhan', 'jacobwangus', 'adwankar', 'dinobrusco', 'qbarnes', 'ilmojung', 'clifford_chan', 'nbaig', 'fhutchi1',
-    'rinofarina', 'baiyanbin', 'muralidhar', 'duanyiruo', 'bredding', 'mkolkey', 'manvith', 'nanduk', 'engyihan', 'deepsie', 'dabon', 'dino_jiang', 'mattrose', 'peter_j_wilhelm',
-    'emx2500', 'jmcguire', 'lfilimowski', 'guruppandit', 'abhilashisme', 'edwinhm', 'rabbi', 'ferrans', 'guna', 'kevin_robinson', 'adathiruthi', 'kochen', 'onehap', 'kalanithi',
-    'jamesn', 'obu001', 'chetanv', 'Avinash', 'HugoBoss', 'Han_Wei', 'mhooper', 'g16872', 'mfcarignano', 'jim_burke', 'kevin', 'arunkarra', 'adam_feng', 'pavan_scm', 'kostya_katz',
-    'ppazderka', 'eileenzhuang', 'pyammine', 'judyho', 'ashoykh', 'rdemento', 'ibrahim', 'min_wang', 'arvind_setlur', 'moorthy_karthik', 'daniel_nelson', 'dms', 'esnmurthy',
-    'rasa_bonyadlou', 'prashantjoshi', 'edkeating', 'billsaez', 'cambalindo', 'jims', 'bozkoyun', 'andry_deltsov', 'bpowers', 'manuel_milli', 'maryparsons', 'spriporov', 'yutianli',
-    'xiebin', 'tnemeth1', 'udayaps', 'zzzzuser', 'timberger', 'sbarve1', 'zarman', 'rwallace67', 'thangavelu_arum', 'yuhuaixie', 'tingup', 'sekchai', 'sasanplus', 'rupal', 'sebastien_hertz',
-    'sab8123', 'rony_lim', 'slava_kirillin', 'smwest', 'wendydu_yq', 'sco002', 'RonFred', 'spatnala', 'vd', 'Sunny', 'tthompson', 'sunijams', 'slaw', 'rodovich', 'zhangqingqi82', 'venki',
-    'yuntaom', 'xiaojin', 'walterciocosta', 'straus', 'Thomas', 'stupka', 'wangyu', 'yaowang', 'wisekb', 'tyler_louie', 'smartgarfield', 'shekar_mahalingam',
-    'venkata_akella', 'v_yellapragada', 'vavasthi', 'rpatel', 'zhengfang', 'sweetybala', 'vap', 'sergey', 'ymhuang', 'spatel78745'
+    'username1', 'username2', 'username3'
 ])
 
 
@@ -583,9 +572,9 @@ def import_discussion(project, pid, frs_mapping, sf_project_shortname, nbhd):
                                 parent=p.parent, timestamp=create_date)
                             p.slug = slug
                             p.full_slug = full_slug
-                            if oldest_post == None or oldest_post.timestamp > create_date:
+                            if oldest_post is None or oldest_post.timestamp > create_date:
                                 oldest_post = p
-                            if newest_post == None or newest_post.timestamp < create_date:
+                            if newest_post is None or newest_post.timestamp < create_date:
                                 newest_post = p
                             ThreadLocalORMSession.flush_all()
                     to.num_replies = to_num_replies
@@ -901,7 +890,8 @@ def _dir_sql(created_on, project, dir_name, rel_path):
       AND pfs_type = 'd'
       AND pfs_name = '%s'
       AND parent_directory = %s;
-    """ % (created_on, convert_project_shortname(project.path), options.neighborhood_shortname, dir_name, parent_directory)
+    """ % (created_on, convert_project_shortname(project.path), options.neighborhood_shortname,
+           dir_name, parent_directory)
     return sql
 
 


[07/42] allura git commit: [#7980] set default line length settings for pep8 & flake8

Posted by he...@apache.org.
[#7980] set default line length settings for pep8 & flake8


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

Branch: refs/heads/hs/7919
Commit: e5023ae108f85207176e64c47b1dff3784dbe222
Parents: 9d39b9a
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Sep 30 10:53:49 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Oct 6 10:34:03 2015 +0000

----------------------------------------------------------------------
 ForgeActivity/setup.cfg   |  6 ++++++
 ForgeBlog/setup.cfg       |  6 ++++++
 ForgeChat/setup.cfg       |  6 ++++++
 ForgeDiscussion/setup.cfg |  6 ++++++
 ForgeGit/setup.cfg        |  6 ++++++
 ForgeLink/setup.cfg       |  6 ++++++
 ForgeSVN/setup.cfg        |  6 ++++++
 ForgeTracker/setup.cfg    |  6 ++++++
 ForgeWiki/setup.cfg       |  6 ++++++
 setup.cfg                 | 22 ++++++++++++++++++++++
 10 files changed, 76 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeActivity/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeActivity/setup.cfg b/ForgeActivity/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeActivity/setup.cfg
+++ b/ForgeActivity/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeBlog/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeBlog/setup.cfg b/ForgeBlog/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeBlog/setup.cfg
+++ b/ForgeBlog/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeChat/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeChat/setup.cfg b/ForgeChat/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeChat/setup.cfg
+++ b/ForgeChat/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeDiscussion/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/setup.cfg b/ForgeDiscussion/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeDiscussion/setup.cfg
+++ b/ForgeDiscussion/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeGit/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeGit/setup.cfg b/ForgeGit/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeGit/setup.cfg
+++ b/ForgeGit/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeLink/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeLink/setup.cfg b/ForgeLink/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeLink/setup.cfg
+++ b/ForgeLink/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeSVN/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeSVN/setup.cfg b/ForgeSVN/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeSVN/setup.cfg
+++ b/ForgeSVN/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeTracker/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeTracker/setup.cfg b/ForgeTracker/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeTracker/setup.cfg
+++ b/ForgeTracker/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/ForgeWiki/setup.cfg
----------------------------------------------------------------------
diff --git a/ForgeWiki/setup.cfg b/ForgeWiki/setup.cfg
index 2637327..f054a10 100644
--- a/ForgeWiki/setup.cfg
+++ b/ForgeWiki/setup.cfg
@@ -1,2 +1,8 @@
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119
+
 [egg_info]
 tag_build = dev0

http://git-wip-us.apache.org/repos/asf/allura/blob/e5023ae1/setup.cfg
----------------------------------------------------------------------
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..1ba576a
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,22 @@
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you 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.
+
+[pep8]
+max-line-length = 119
+
+[flake8]
+max-line-length = 119


[25/42] allura git commit: [#7919] Add NavBar dependencies

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/c456344c/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/c456344c/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


[04/42] allura git commit: [#7991] Add sparse index for phone_verification.number_hash

Posted by he...@apache.org.
[#7991] Add sparse index for phone_verification.number_hash


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

Branch: refs/heads/hs/7919
Commit: c8300e128dd3b6c936ce9dacbe88da10b04c05d6
Parents: 0323078
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Oct 5 12:05:40 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Oct 5 15:38:26 2015 -0400

----------------------------------------------------------------------
 Allura/allura/command/show_models.py | 10 ++++------
 Allura/allura/model/auth.py          |  3 +++
 Allura/allura/tests/test_commands.py | 13 ++++++++-----
 3 files changed, 15 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/c8300e12/Allura/allura/command/show_models.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/show_models.py b/Allura/allura/command/show_models.py
index 89a2a88..d651383 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -282,24 +282,22 @@ class EnsureIndexCommand(base.Command):
             base.log.info('...... ensure %s:%s', collection.name, idx)
             while True:
                 try:
-                    collection.ensure_index(idx.index_spec, unique=True)
+                    collection.ensure_index(idx.index_spec, **idx.index_options)
                     break
                 except DuplicateKeyError, err:
                     base.log.info('Found dupe key(%s), eliminating dupes', err)
                     self._remove_dupes(collection, idx.index_spec)
         for keys, idx in indexes.iteritems():
             base.log.info('...... ensure %s:%s', collection.name, idx)
-            collection.ensure_index(idx.index_spec, background=True)
+            collection.ensure_index(idx.index_spec, background=True, **idx.index_options)
         # Drop obsolete indexes
         for iname, keys in prev_indexes.iteritems():
             if keys not in indexes:
-                base.log.info('...... drop index %s:%s',
-                              collection.name, iname)
+                base.log.info('...... drop index %s:%s', collection.name, iname)
                 collection.drop_index(iname)
         for iname, keys in prev_uindexes.iteritems():
             if keys not in uindexes:
-                base.log.info('...... drop index %s:%s',
-                              collection.name, iname)
+                base.log.info('...... drop index %s:%s', collection.name, iname)
                 collection.drop_index(iname)
 
     def _recreate_index(self, collection, iname, keys, **creation_options):

http://git-wip-us.apache.org/repos/asf/allura/blob/c8300e12/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 163d5de..955c952 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -272,6 +272,9 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
         session = main_orm_session
         indexes = ['tool_data.sfx.userid', 'tool_data.AuthPasswordReset.hash']
         unique_indexes = ['username']
+        custom_indexes = [
+            dict(fields=('tool_data.phone_verification.number_hash',), sparse=True),
+        ]
 
     type_s = 'User'
 

http://git-wip-us.apache.org/repos/asf/allura/blob/c8300e12/Allura/allura/tests/test_commands.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_commands.py b/Allura/allura/tests/test_commands.py
index f6800b7..fb5fb03 100644
--- a/Allura/allura/tests/test_commands.py
+++ b/Allura/allura/tests/test_commands.py
@@ -187,7 +187,8 @@ class TestEnsureIndexCommand(object):
             '_foo_bar': {'key': [('foo', 1), ('bar', 1)]},
         }
         indexes = [
-            Mock(unique=False, index_spec=[('foo', 1)]),
+            Mock(unique=False, index_spec=[('foo', 1)],
+                 index_options={'unique': False, 'sparse': False}),
         ]
         cmd = show_models.EnsureIndexCommand('ensure_index')
         cmd._update_indexes(collection, indexes)
@@ -216,8 +217,10 @@ class TestEnsureIndexCommand(object):
             '_foo_baz': {'key': [('foo', 1), ('baz', 1)]},
         }
         indexes = [
-            Mock(index_spec=[('foo', 1), ('bar', 1)], unique=False, ),
-            Mock(index_spec=[('foo', 1), ('baz', 1)], unique=True, ),
+            Mock(index_spec=[('foo', 1), ('bar', 1)], unique=False,
+                 index_options={'unique': False, 'sparse': False}),
+            Mock(index_spec=[('foo', 1), ('baz', 1)], unique=True,
+                 index_options={'unique': True, 'sparse': False}),
         ]
 
         cmd = show_models.EnsureIndexCommand('ensure_index')
@@ -235,8 +238,8 @@ class TestEnsureIndexCommand(object):
             call.drop_index('_foo_baz'),
             call.ensure_index([('foo', 1), ('baz', 1)], unique=True),
             call.drop_index('_foo_baz_temporary_extra_field_for_indexing'),
-            call.ensure_index([('foo', 1), ('baz', 1)], unique=True),
-            call.ensure_index([('foo', 1), ('bar', 1)], background=True)
+            call.ensure_index([('foo', 1), ('baz', 1)], unique=True, sparse=False),
+            call.ensure_index([('foo', 1), ('bar', 1)], unique=False, sparse=False, background=True)
         ])
 
 


[29/42] allura git commit: [#7920] Format navbar to pass eslint inspection

Posted by he...@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/1529c03d
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/1529c03d
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/1529c03d

Branch: refs/heads/hs/7919
Commit: 1529c03d52c259cba66dc4824d2a61db907e5116
Parents: cad9245
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 12:10:25 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:17 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/1529c03d/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>
+        );
+    }
 });


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

Posted by he...@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/788a8f44
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/788a8f44
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/788a8f44

Branch: refs/heads/hs/7919
Commit: 788a8f44b994bb6a34a7f68d204ec50595239d62
Parents: df5c88c
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:45:43 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:18 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/788a8f44/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


[09/42] allura git commit: Allow token auth over http when in debug mode

Posted by he...@apache.org.
Allow token auth over http when in debug mode


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

Branch: refs/heads/hs/7919
Commit: 93be151997c74d269fd4ed0cd1081a1eb48e2b0a
Parents: 2bdcb95
Author: Heith Seewald <hs...@hsmb.local>
Authored: Fri Oct 9 12:25:38 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Fri Oct 9 12:25:38 2015 -0400

----------------------------------------------------------------------
 Allura/allura/controllers/rest.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/93be1519/Allura/allura/controllers/rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index 2578fa2..30d28d9 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -21,8 +21,9 @@
 import logging
 
 import oauth2 as oauth
+from paste.util.converters import asbool
 from webob import exc
-from tg import expose, flash, redirect
+from tg import expose, flash, redirect, config
 from pylons import tmpl_context as c, app_globals as g
 from pylons import request, response
 
@@ -117,7 +118,8 @@ class OAuthNegotiator(object):
             # handle bearer tokens
             # skip https check if auth invoked from tests
             testing = request.environ.get('paste.testing', False)
-            if not testing and request.scheme != 'https':
+            debug = asbool(config.get('debug', False))
+            if not testing and request.scheme != 'https' and not debug:
                 request.environ['pylons.status_code_redirect'] = True
                 raise exc.HTTPForbidden
             access_token = M.OAuthAccessToken.query.get(api_key=access_token)


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

Posted by he...@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/967324b6
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/967324b6
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/967324b6

Branch: refs/heads/hs/7919
Commit: 967324b6f9c60ad64cc9634b487db3a91f3d5721
Parents: 3bb27f6
Author: Heith Seewald <hs...@hsmb.local>
Authored: Mon Oct 12 13:43:12 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:18 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/967324b6/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 {


[10/42] allura git commit: Merge remote-tracking branch 'dave/fix_subscribe_errors'

Posted by he...@apache.org.
Merge remote-tracking branch 'dave/fix_subscribe_errors'


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

Branch: refs/heads/hs/7919
Commit: 77c45dacd1096fcc679d9d5693ca629e689a1e81
Parents: 93be151 bcf93e1
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 13 14:47:56 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Tue Oct 13 14:47:56 2015 -0400

----------------------------------------------------------------------
 Allura/allura/lib/widgets/subscriptions.py   | 4 +++-
 ForgeBlog/forgeblog/main.py                  | 2 +-
 ForgeBlog/forgeblog/templates/blog/post.html | 4 +++-
 3 files changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------



[28/42] allura git commit: [#7920] Add configured jshint and jscs

Posted by he...@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/cad92456
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/cad92456
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/cad92456

Branch: refs/heads/hs/7919
Commit: cad9245650609f4bc663e389a4e4a2adf894594d
Parents: c456344
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:28:03 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:17 2015 -0400

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


http://git-wip-us.apache.org/repos/asf/allura/blob/cad92456/.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/cad92456/.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
+    }
+}


[12/42] allura git commit: [#7984] remove unused columns

Posted by he...@apache.org.
[#7984] remove unused columns


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

Branch: refs/heads/hs/7919
Commit: 68786d38cdf01b5138fbf30ee5ae65932733c88a
Parents: 151c63b
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Oct 13 16:14:54 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Oct 13 16:19:05 2015 -0400

----------------------------------------------------------------------
 Allura/allura/lib/widgets/subscriptions.py | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/68786d38/Allura/allura/lib/widgets/subscriptions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/subscriptions.py b/Allura/allura/lib/widgets/subscriptions.py
index 5d1ebea..db6c51d 100644
--- a/Allura/allura/lib/widgets/subscriptions.py
+++ b/Allura/allura/lib/widgets/subscriptions.py
@@ -42,13 +42,7 @@ class _SubscriptionTable(ew.TableField):
         project_name = ffw.DisplayOnlyField(
             label='Project', show_label=True, with_hidden_input=False)
         mount_point = ffw.DisplayOnlyField(
-            label='App', show_label=True, with_hidden_input=False)
-        topic = ffw.DisplayOnlyField(
-            label='Topic', show_label=True, with_hidden_input=False)
-        type = ffw.DisplayOnlyField(
-            label='Type', show_label=True, with_hidden_input=False)
-        frequency = ffw.DisplayOnlyField(
-            label='Frequency', show_label=True, with_hidden_input=False)
+            label='Tool', show_label=True, with_hidden_input=False)
         artifact_title = ew.LinkField(
             label='Artifact', show_label=True, plaintext_if_no_href=True)
         # unsubscribe = SubmitButton()


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

Posted by he...@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/4a4984f3
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/4a4984f3
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/4a4984f3

Branch: refs/heads/hs/7919
Commit: 4a4984f3539add5d8179cd6839b06d6e07d0b449
Parents: 6c51ac7
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:19:50 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:16 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/4a4984f3/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>
+      );
+  }
+});


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

Posted by he...@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/6c51ac77
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/6c51ac77
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/6c51ac77

Branch: refs/heads/hs/7919
Commit: 6c51ac77796b9e1101b1ac0b83b7d70ece268f4b
Parents: d782306
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:12:02 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:16 2015 -0400

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


http://git-wip-us.apache.org/repos/asf/allura/blob/6c51ac77/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: |


[39/42] allura git commit: [#7919] Add react for development mode

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/40dd7391/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>

[15/42] allura git commit: Update Ming and pymongo to latest version (pymongo >= 3 not yet supported by Ming)

Posted by he...@apache.org.
Update Ming and pymongo to latest version (pymongo >= 3 not yet supported by Ming)


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

Branch: refs/heads/hs/7919
Commit: bae38ad961ed4126d2c67f91573099660a2a37e2
Parents: e97c5ff
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Wed Oct 14 21:38:29 2015 +0000
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Thu Oct 15 13:00:22 2015 +0000

----------------------------------------------------------------------
 requirements.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/bae38ad9/requirements.txt
----------------------------------------------------------------------
diff --git a/requirements.txt b/requirements.txt
index b2b6ea5..324fa33 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -21,7 +21,7 @@ httplib2==0.7.4
 iso8601==0.1.4
 Jinja2==2.6
 Markdown==2.2.0
-Ming==0.4.7
+Ming==0.5.2
 oauth2==1.5.170
 # tg2 dep PasteDeploy must specified before TurboGears2, to avoid a version/allow-hosts problem
 Paste==1.7.5.1
@@ -30,7 +30,7 @@ PasteScript==1.7.4.2
 Pillow==2.9.0
 poster==0.8.1
 Pygments==2.0.2
-pymongo==2.4.2
+pymongo==2.8.1
 Pypeline==0.2
 pysolr==2.1.0-beta
 python-dateutil==1.5


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

Posted by he...@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/a5ab3d94
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a5ab3d94
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a5ab3d94

Branch: refs/heads/hs/7919
Commit: a5ab3d94251e0f8697bb0f87b238c147e338617b
Parents: 99d2ea9
Author: Heith Seewald <hs...@hsmb.local>
Authored: Thu Oct 15 14:59:11 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:20 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/a5ab3d94/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,


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

Posted by he...@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/0d8b3550
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/0d8b3550
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/0d8b3550

Branch: refs/heads/hs/7919
Commit: 0d8b355005bd37f051d2a19247233bfe3157febc
Parents: 675dfc6
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 12:24:55 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:18 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/0d8b3550/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()


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

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/c456344c/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


[11/42] allura git commit: Merge remote-tracking branch 'dave/docker_npm_pwd'

Posted by he...@apache.org.
Merge remote-tracking branch 'dave/docker_npm_pwd'


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

Branch: refs/heads/hs/7919
Commit: 00110b12ed58a44a95104d8579721bb6461bdada
Parents: 77c45da a1aab22
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 13 14:52:11 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Tue Oct 13 14:52:11 2015 -0400

----------------------------------------------------------------------
 Allura/allura/command/create_neighborhood.py   |  5 +++++
 Allura/docs/getting_started/administration.rst |  4 ++++
 Allura/docs/getting_started/installation.rst   | 20 +++++++++++++-------
 Dockerfile                                     | 13 +++++++++----
 docker-compose.yml                             |  8 ++++----
 5 files changed, 35 insertions(+), 15 deletions(-)
----------------------------------------------------------------------



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

Posted by he...@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/43285241
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/43285241
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/43285241

Branch: refs/heads/hs/7919
Commit: 432852417801d5479a58bf0281d6654225fb4df6
Parents: 280fd2b
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 03:01:25 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:16 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/43285241/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):


[30/42] allura git commit: [#7920] Fix import error

Posted by he...@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/675dfc6b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/675dfc6b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/675dfc6b

Branch: refs/heads/hs/7919
Commit: 675dfc6b5fb41e5b8b9b34c5f8ce68c613b54207
Parents: 1529c03
Author: Heith Seewald <hs...@hsmb.local>
Authored: Tue Oct 6 12:19:14 2015 -0400
Committer: Heith Seewald <hs...@hsmb.local>
Committed: Thu Oct 15 15:00:17 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/675dfc6b/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


[26/42] allura git commit: [#7919] Add NavBar dependencies

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/c456344c/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>