allura-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brond...@apache.org
Subject [01/50] [abbrv] allura git commit: [#7919] Make add-new-tool menu use ContextMenu component
Date Thu, 17 Dec 2015 19:21:48 GMT
Repository: allura
Updated Branches:
  refs/heads/db/8034 [created] 65f06ddf0


[#7919]  Make add-new-tool menu use ContextMenu component


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

Branch: refs/heads/db/8034
Commit: 8c9b371a1d3de959662815d5021bd1dfd01898a0
Parents: 2fe6809
Author: Heith Seewald <heiths@gmail.com>
Authored: Thu Dec 3 10:53:46 2015 -0500
Committer: Heith Seewald <heiths@gmail.com>
Committed: Wed Dec 16 13:54:29 2015 -0600

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py           |   1 -
 Allura/allura/model/project.py                  |   9 +-
 Allura/allura/public/nf/js/context-menu.es6.js  |  80 +++++++++
 Allura/allura/public/nf/js/navbar.es6.js        | 166 +++++++++----------
 .../allura/templates/jinja_master/top_nav.html  |  12 +-
 5 files changed, 175 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/8c9b371a/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 35fc77a..d2d5854 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -798,7 +798,6 @@ class ProjectAdminRestController(BaseController):
     def installable_tools(self, **kw):
         """ List of installable tools and their default options.
         """
-        response.content_type = 'application/json'
         tools = []
         for tool in AdminApp.installable_tools_for(c.project):
             tools.append({

http://git-wip-us.apache.org/repos/asf/allura/blob/8c9b371a/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 2391690..c07ac13 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -640,9 +640,12 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                 entry['children'] = [make_entry(child, mount_point=child.url.split('/')[-2])
for child in s.children]
             children.append(entry)
 
-        return dict(grouping_threshold=grouping_threshold,
-                    menu=children,
-                    )
+        response = dict(grouping_threshold=grouping_threshold, menu=children)
+        if admin_options:
+            response['installable_tools'] =[dict(text=t['tool_label'], href='#', tooltip=t['description'])
+                                             for t in ProjectAdminRestController().installable_tools()['tools']]
+
+        return response
 
     def grouped_navbar_entries(self):
         """Return a :class:`~allura.app.SitemapEntry` list suitable for rendering

http://git-wip-us.apache.org/repos/asf/allura/blob/8c9b371a/Allura/allura/public/nf/js/context-menu.es6.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/context-menu.es6.js b/Allura/allura/public/nf/js/context-menu.es6.js
new file mode 100644
index 0000000..66f2fc6
--- /dev/null
+++ b/Allura/allura/public/nf/js/context-menu.es6.js
@@ -0,0 +1,80 @@
+/*
+ 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.
+ */
+'use strict';
+
+
+class ContextMenu extends React.Component {
+    constructor(props) {
+        super(props);
+    }
+
+    static propTypes = {
+        classes: React.PropTypes.array,
+        items: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
+        onOptionClick: React.PropTypes.func.isRequired
+    };
+
+    static defaultOptions = {
+        classes: []
+    };
+
+    componentWillMount() {
+        let _this = this;
+        var mount_point;
+        $('body').on('click.contextMenu', function (evt) {
+            /* the :not filter should've worked as a 2nd param to .on() instead of this,
+             but clicks in the page gutter were being delayed for some reason */
+            if ($(evt.target).is(':not(.contextMenu)')) {
+
+                /* if clicking directly onto another gear, set it directly.
+                 this is necessary since sometimes our jquery events seem to interfere with
the react event
+                 that is supposed to handle this kind of thing */
+                if ($(evt.target).is('.config-tool')) {
+                    mount_point = $(evt.target).next().data('mount-point');
+                } else {
+                    // no current option menu
+                    mount_point = "";
+                }
+                _this.props.onOptionClick(mount_point);
+            }
+        });
+    }
+
+    componentWillUnmount() {
+        $("body").off('click.contextMenu');  // de-register our specific click handler
+    }
+
+    render() {
+        return (
+            <div className="contextMenu">
+                <ul>{
+                    this.props.items.map(function (o, i) {
+                        return (<li key={i}>
+                            <ToolTipLink
+                                href={o.href}
+                                classes={['context-link']}
+                                toolTip={o.tooltip}
+                                text={o.text}/>
+                        </li>)
+                    })}
+                </ul>
+            </div>
+        )
+    }
+}

http://git-wip-us.apache.org/repos/asf/allura/blob/8c9b371a/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 90c3998..e59d6c0 100644
--- a/Allura/allura/public/nf/js/navbar.es6.js
+++ b/Allura/allura/public/nf/js/navbar.es6.js
@@ -50,35 +50,7 @@ function slugify(text) {
         .replace(/^-+/,/^-+/,/^-+/,/^-+/, '')             // Trim - from start of text
         .replace(/-+$/,/-+$/,/-+$/,/-+$/, '');            // Trim - from end of text
 }
-/**
- * Get the color for a tool type
 
- * @constructor
- * @label string 'The default mount label for a tool.  i.e. git and hg use 'Code' which returns
'blue'.
- * @return {string}
- */
-
-function _getToolColor(defaultLabel='standard') {
-    // Replace with css... (if we even want to keep the color)
-    switch (defaultLabel) {
-    case 'Wiki':
-        return '#DDFFF0';
-    case 'Git':  // Git, svn, hg
-        return '#BBDEFB';
-    case 'Mercurial':  // Git, svn, hg
-        return '#BBDEFB';
-    case 'Tickets':
-        return '#D1C4E9';
-    case 'Discussion':
-        return '#DCEDC8';
-    case 'Blog':
-        return '#FFF9C4';
-    case 'Link':
-        return '#FFCDD2';
-    default:
-        return 'white';
-    }
-}
 /**
  * Get a mount point from a NavBarItem node.
 
@@ -157,9 +129,9 @@ var NavBarItem = React.createClass({
                     </span>
                 </a>
                 {this.props.currentOptionMenu.tool && this.props.currentOptionMenu.tool
=== this.props.mount_point &&
-                    <OptionsMenu
+                    <ContextMenu
                         {...this.props}
-                        options={this.props.options}
+                        items={this.props.options}
                         onOptionClick={this.props.onOptionClick}
                     />}
             </div>
@@ -171,55 +143,55 @@ var NavBarItem = React.createClass({
     }
 });
 
-/**
- * Options "context" menu
-
- * @constructor
- */
-var OptionsMenu = React.createClass({
-    propTypes: {
-        options: React.PropTypes.array.isRequired,
-        onOptionClick: React.PropTypes.func.isRequired
-    },
-
-    componentWillMount: function() {
-        var _this = this;
-        var mount_point;
-        $('body').on('click.optionMenu', function(evt) {
-            /* the :not filter should've worked as a 2nd param to .on() instead of this,
-               but clicks in the page gutter were being delayed for some reason */
-            if ($(evt.target).is(':not(.optionMenu)')) {
-
-                /* if clicking directly onto another gear, set it directly.
-                   this is necessary since sometimes our jquery events seem to interfere
with the react event
-                   that is supposed to handle this kind of thing */
-                if ($(evt.target).is('.config-tool')) {
-                    mount_point = $(evt.target).next().data('mount-point');
-                } else {
-                    // no current option menu
-                    mount_point = "";
-                }
-                _this.props.onOptionClick(mount_point);
-            }
-        });
-    },
-
-    componentWillUnmount: function() {
-        $("body").off('click.optionMenu');  // de-register our specific click handler
-    },
-
-    render: function() {
-        return (<div className="optionMenu">
-            <ul>
-               {this.props.options.map((o, i) =>
-                    <li key={i}>
-                        <ToolTipLink href={o.href} classes={['context-link']} toolTip={this.props.toolTip}
text={o.text}/>
-                    </li>
-                )}
-            </ul>
-        </div>)
-    }
-});
+///**
+// * Options "context" menu
+//
+// * @constructor
+// */
+//var OptionsMenu = React.createClass({
+//    propTypes: {
+//        options: React.PropTypes.array.isRequired,
+//        onOptionClick: React.PropTypes.func.isRequired
+//    },
+//
+//    componentWillMount: function() {
+//        var _this = this;
+//        var mount_point;
+//        $('body').on('click.optionMenu', function(evt) {
+//            /* the :not filter should've worked as a 2nd param to .on() instead of this,
+//               but clicks in the page gutter were being delayed for some reason */
+//            if ($(evt.target).is(':not(.optionMenu)')) {
+//
+//                /* if clicking directly onto another gear, set it directly.
+//                   this is necessary since sometimes our jquery events seem to interfere
with the react event
+//                   that is supposed to handle this kind of thing */
+//                if ($(evt.target).is('.config-tool')) {
+//                    mount_point = $(evt.target).next().data('mount-point');
+//                } else {
+//                    // no current option menu
+//                    mount_point = "";
+//                }
+//                _this.props.onOptionClick(mount_point);
+//            }
+//        });
+//    },
+//
+//    componentWillUnmount: function() {
+//        $("body").off('click.optionMenu');  // de-register our specific click handler
+//    },
+//
+//    render: function() {
+//        return (<div className="optionMenu">
+//            <ul>
+//               {this.props.options.map((o, i) =>
+//                    <li key={i}>
+//                        <ToolTipLink href={o.href} classes={['context-link']} toolTip={this.props.toolTip}
text={o.text}/>
+//                    </li>
+//                )}
+//            </ul>
+//        </div>)
+//    }
+//});
 
 /**
  * An input component that updates the NavBar's grouping threshold.
@@ -299,11 +271,24 @@ var ToggleAddNewTool = React.createClass({
             visible: !this.state.visible
         });
     },
-    render: function() {
-        return <AddNewToolButton
-            {...this.props}
-            showAddToolMenu={this.state.visible}
-            handleToggleAddNewTool={this.handleToggle} />;
+
+    onOptionClick: function(e) {
+        console.log("e", e);
+    },
+    render: function () {
+        return (
+            <div>
+                <a onClick={ this.handleToggle } className="add-tool-toggle">
+                    Add New...
+                </a>
+                {this.state.visible &&
+                <ContextMenu
+                    {...this.props}
+                    onOptionClick={this.onOptionClick}
+                    items={this.props.installableTools} />
+                }
+            </div>
+        )
     }
 });
 
@@ -329,6 +314,9 @@ var NormalNavBar = React.createClass({
         );
     },
 
+    onOptionClick: function(e){
+        console.log(e);
+    },
     render: function() {
         var listItems = this.props.items.map(this.buildMenu);
 
@@ -348,7 +336,12 @@ var NormalNavBar = React.createClass({
                 id="normal-nav-bar"
                 className="dropdown">
                 { listItems }
-                <li id="add-tool-container"><ToggleAddNewTool existingMounts={mount_points}
/></li>
+                <li id="add-tool-container">
+                    <ToggleAddNewTool
+                        {...this.props}
+                        items={this.props.installableTools}
+                        onOptionClick={this.onOptionClick} />
+                </li>
             </ul>
         );
     }
@@ -491,6 +484,7 @@ var Main = React.createClass({
     propTypes: {
         initialData: React.PropTypes.shape({
             menu: React.PropTypes.arrayOf(ToolsPropType),
+            installableTools: React.PropTypes.array,
             grouping_threshold: React.PropTypes.number.isRequired
         }),
         installableTools: React.PropTypes.array
@@ -622,6 +616,7 @@ var Main = React.createClass({
                 return (
                     <AdminNav
                         tools={ _this.state.data.menu }
+                        installableTools={ _this.state.data.installable_tools }
                         data={ _this.state.data }
                         onToolReorder={ _this.onToolReorder }
                         onToolDragStart={ _this.onToolDragStart }
@@ -636,6 +631,7 @@ var Main = React.createClass({
                     <div>
                         <NormalNavBar
                             items={ _this.state.data.menu }
+                            installableTools={ _this.state.data.installable_tools }
                             />
                     </div>
                 );

http://git-wip-us.apache.org/repos/asf/allura/blob/8c9b371a/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 a49e8c0..3dee011 100644
--- a/Allura/allura/templates/jinja_master/top_nav.html
+++ b/Allura/allura/templates/jinja_master/top_nav.html
@@ -48,15 +48,19 @@
     {% do g.register_forge_js('js/react-reorderable.min.js') %}
     {% do g.register_forge_js('js/build/transpiled.js') %} {# if we do more es6, we'll need
to register this in other places, or maybe even global #}
     <script>
+    'use strict';
+    let _data = {{ h.escape_json(c.project.nav_data(admin_options=True))|safe  }};
         $(document).ready(function () {
-            $('#toggle-admin-btn').click(function() {
+            console.table({{_data }});
+            $('#toggle-admin-btn').click(function () {
                 ReactDOM.render(React.createElement(Main, {
-                    initialData: {{ h.escape_json(c.project.nav_data(admin_options=True))|safe
}}
+                    initialData: _data
                 }), document.getElementById("top_nav_admin"));
             });
 
-            ReactDOM.render(React.createElement(ToggleAddNewTool),
-                            document.getElementById('add-tool-container'));
+            ReactDOM.render(React.createElement(ToggleAddNewTool, {
+                        installableTools: _data.installable_tools
+                    }), document.getElementById('add-tool-container'));
         });
     </script>
 {% endif %}


Mime
View raw message