Return-Path: X-Original-To: apmail-allura-commits-archive@www.apache.org Delivered-To: apmail-allura-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2F295107BD for ; Fri, 23 Oct 2015 17:37:29 +0000 (UTC) Received: (qmail 11430 invoked by uid 500); 23 Oct 2015 17:37:29 -0000 Delivered-To: apmail-allura-commits-archive@allura.apache.org Received: (qmail 11379 invoked by uid 500); 23 Oct 2015 17:37:29 -0000 Mailing-List: contact commits-help@allura.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@allura.apache.org Delivered-To: mailing list commits@allura.apache.org Received: (qmail 10916 invoked by uid 99); 23 Oct 2015 17:37:28 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 23 Oct 2015 17:37:28 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B87D1E027F; Fri, 23 Oct 2015 17:37:28 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: heiths@apache.org To: commits@allura.apache.org Date: Fri, 23 Oct 2015 17:38:09 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [43/45] allura git commit: [#7919] Remove unneeded components and refactor submenus [#7919] Remove unneeded components and refactor submenus Project: http://git-wip-us.apache.org/repos/asf/allura/repo Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a6b6f365 Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a6b6f365 Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a6b6f365 Branch: refs/heads/hs/7919 Commit: a6b6f365a6f59e68e52b660f30973c29ca23fcf9 Parents: ce77b8e Author: Heith Seewald Authored: Thu Oct 22 15:57:28 2015 -0400 Committer: Heith Seewald Committed: Fri Oct 23 13:10:04 2015 -0400 ---------------------------------------------------------------------- Allura/allura/public/nf/js/navbar.es6.js | 534 +++++++------------------- 1 file changed, 132 insertions(+), 402 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/allura/blob/a6b6f365/Allura/allura/public/nf/js/navbar.es6.js ---------------------------------------------------------------------- diff --git a/Allura/allura/public/nf/js/navbar.es6.js b/Allura/allura/public/nf/js/navbar.es6.js index feb1af8..c547cc8 100644 --- a/Allura/allura/public/nf/js/navbar.es6.js +++ b/Allura/allura/public/nf/js/navbar.es6.js @@ -1,8 +1,8 @@ 'use strict'; - /** * Gets the current url. + * @constructor * @param {bool} rest - Return a "rest" version of the url. * @returns {string} @@ -13,18 +13,44 @@ function _getProjectUrl(rest = true) { return rest ? `${base}/rest/${nbhd}/${proj}` : `${base}/${nbhd}/${proj}`; } -function slugify(text) -{ - return text.toString().toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(/[^\w\-]+/g, '') // Remove all non-word chars - .replace(/\-\-+/g, '-') // Replace multiple - with single - - .replace(/^-+/, '') // Trim - from start of text - .replace(/-+$/, ''); // Trim - from end of text +function slugify(text) { + return text.toString().toLowerCase() + .replace(/\s+/g,/\s+/g,/\s+/g,/\s+/g, '-') // Replace spaces with - + .replace(/[^\w\-]+/g,/[^\w\-]+/g,/[^\w\-]+/g,/[^\w\-]+/g, '') // Remove all non-word chars + .replace(/\-\-+/g,/\-\-+/g,/\-\-+/g,/\-\-+/g, '-') // Replace multiple - with single - + .replace(/^-+/,/^-+/,/^-+/,/^-+/, '') // Trim - from start of text + .replace(/-+$/,/-+$/,/-+$/,/-+$/, ''); // Trim - from end of text } +/** + * Get the color for a tool type + * @constructor + * @label string 'The default mount label for a tool. i.e. git and hg use 'Code' which returns 'blue'. + * @return {string} + */ +function _getToolColor(defaultLabel='standard') { + switch (defaultLabel) { + case 'Wiki': + return '#DDFFF0'; + case 'Git': // Git, svn, hg + return '#BBDEFB'; + case 'Mercurial': // Git, svn, hg + return '#BBDEFB'; + case 'Tickets': + return '#D1C4E9'; + case 'Discussion': + return '#DCEDC8'; + case 'Blog': + return '#FFF9C4'; + case 'Link': + return '#FFCDD2'; + default: + return 'white'; + } +} /** * Get a mount point from a NavBarItem node. + * @constructor * @param {NavBarItem} node * @returns {string} @@ -52,85 +78,33 @@ function ToolsPropType() { }; } - -/** - * When the number of tools of the same type exceeds the grouping threshold, - * they are placed in a group and this submenu is generated. - * @constructor - */ -var ToolSubMenu = React.createClass({ - propTypes: { - isSubmenu: React.PropTypes.bool, - tools: ToolsPropType - }, - mode: 'list', - render: function () { - var _this = this; - var subMenuClass = this.props.isSubmenu ? ' submenu ' : ''; - var tools = this.props.tools.map(function (item, i) { - return ( -
-
- -
-
- ); - }); - - return ( -
- - { tools } - -
- ); - } -}); - /** * A single NavBar item. + * @constructor */ var NavBarItem = React.createClass({ propTypes: { name: React.PropTypes.string.isRequired, url: React.PropTypes.string.isRequired, - isSubmenu: React.PropTypes.bool, - children: React.PropTypes.array, - tools: ToolsPropType }, - generateItem: function () { + + isAnchored: function() { + return this.props.is_anchored !== null; + }, + + render: function() { var controls = []; - var arrow_classes = 'fa fa-arrows-h' + var arrow_classes = 'fa fa-arrows-h'; if (this.props.is_anchored) { arrow_classes += ' anchored'; } else { arrow_classes += ' draggable-handle'; } controls.push(); - return { this.props.name }
{ controls }
- }, - - generateSubmenu: function () { - return ; - }, - - generateContent: function () { - var content = [this.generateItem()]; - if (this.props.children) { - content.push(this.generateSubmenu()); - } - - return content; - }, - - render: function () { - var content = this.generateContent(); - var classes = 'tb-item tb-item-edit'; return ( -
- { content } + ); } @@ -138,26 +112,27 @@ var NavBarItem = React.createClass({ /** * An input component that updates the NavBar's grouping threshold. + * @constructor */ var GroupingThreshold = React.createClass({ propTypes: { initialValue: React.PropTypes.number.isRequired }, - getInitialState: function () { + getInitialState: function() { return { value: this.props.initialValue }; }, - handleChange: function (event) { + handleChange: function(event) { this.setState({ value: event.target.value }); this.props.onUpdateThreshold(event); }, - render: function () { + render: function() { return (
{ !!this.props.isHidden && @@ -176,14 +151,14 @@ var GroupingThreshold = React.createClass({ } }); - /** * The NavBar when in "Normal" mode. + * @constructor */ var NormalNavBar = React.createClass({ - buildMenu: function (item) { - var classes = ` ui-icon-${item.icon}-32`; + buildMenu: function(item) { + let classes = window.location.pathname.startsWith(item.url) ? 'active-nav-link' : ''; var subMenu; if (item.children) { @@ -195,20 +170,26 @@ var NormalNavBar = React.createClass({ { item.name } -
    - { subMenu } -
+ {subMenu && +
    + { subMenu } +
+ } ); }, - render: function () { + render: function() { var listItems = this.props.items.map(this.buildMenu); var classes = 'dropdown'; - classes = this.props.isSubmenu ? classes += ' submenu' : classes; return ( -
    +
      { listItems } +
    ); } @@ -224,33 +205,38 @@ var AdminNav = React.createClass({ tools: ToolsPropType }, mode: 'grid', - getInitialState: function () { + getInitialState: function() { return { hover: false }; }, - mouseOver: function () { + mouseOver: function() { this.setState({ hover: true }); }, - mouseOut: function () { + mouseOut: function() { this.setState({ hover: false }); }, - render: function () { + render: function() { var _this = this; var subMenuClass = this.props.isSubmenu ? ' submenu ' : ''; - var tools = [], anchored_tools = [], end_tools = []; - this.props.tools.forEach(function (item) { - var core_item = ; + name={ item.name } + url={ item.url } + key={ 'tb-item-' + _.uniqueId() } + is_anchored={ item.is_anchored || item.mount_point === 'admin'}/>; if (item.mount_point === 'admin') { // force admin to end, just like 'Project.sitemap()' does end_tools.push(core_item); @@ -258,7 +244,7 @@ var AdminNav = React.createClass({ anchored_tools.push(core_item); } else { tools.push( -
    +
    { core_item }
    ); @@ -268,8 +254,13 @@ var AdminNav = React.createClass({ return (
    { anchored_tools } - + { tools } { end_tools } @@ -280,13 +271,14 @@ var AdminNav = React.createClass({ /** * The button that toggles NavBar modes. + * @constructor */ var ToggleAdminButton = React.createClass({ propTypes: { visible: React.PropTypes.bool }, - render: function () { + render: function() { var classes = this.props.visible ? 'fa fa-unlock' : 'fa fa-lock'; return ( - - ); - } -}); - - -var NewToolInfo = React.createClass({ - propTypes: { - name: React.PropTypes.string, - description: React.PropTypes.string, - handleAddButton: React.PropTypes.func - }, - - - render: function () { - return ( -
    -
    -

    {this.props.name}

    -

    {this.props.description}

    -
    -
    - -
    -
    - ); - } -}); - - -var installableToolsCache = {}; -function loadTools(id, callback) { - if(!installableToolsCache[id]) { - installableToolsCache[id] = $.get(_getProjectUrl(true) + "/admin/installable_tools/").promise(); - } - installableToolsCache[id].done(callback); -} - - -var NewToolMain = React.createClass({ - getInitialState: function () { - let toolPlaceHolder = { - name: "Add a tool", - tool_label: "Add a tool", - description: "click on one of the tools shown above to add it to your project." - }; - - return { - visible: false, - installableTools: [toolPlaceHolder], - active: toolPlaceHolder, - errors: { - mount_point: [], - mount_label: [] - }, - new_tool: { - mount_point: "", - tool_label: "", - mount_label: "" - } - }; - }, - - componentDidMount: function () { - let tools = loadTools('tools', function (result) { - if (this.isMounted()) { - this.setState({ - installableTools: result['tools'] - }) - } - }.bind(this)); - }, - handleChangeTool: function (e) { - console.log(`Changed tool to: ${e.target.textContent}`); - this._setActiveByName(e.target.textContent); - - }, - _setActiveByName: function (tool_label) { - var index = this.state.installableTools.findIndex( - x => x.tool_label === tool_label - ); - var active = this.state.installableTools[index]; - var _new_tool = this.state.new_tool; - - _new_tool['mount_label'] = active.defaults.default_mount_label; - _new_tool['mount_point'] = ""; - - this.setState({ - active: active, - new_tool: _new_tool - }); - }, - - handleChangeForm: function (e) { - console.log(e.target.value); - var _new_tool = this.state.new_tool; - - console.log(e.target.id); - _new_tool[e.target.id] = e.target.value; - - this.setState({ - new_tool: _new_tool - }); - - }, - handleSubmit: function (e) { - e.preventDefault(); - var data = { - _session_id: $.cookie('_session_id'), - tool: this.state.active.name, - mount_label: this.state.new_tool.mount_label, - mount_point: this.state.new_tool.mount_point - }; - - var url = _getProjectUrl() + "/admin/install_tool/"; - - $.ajax({ - type: 'POST', - url: url, - data: data, - success: function () { - $('#messages').notify('Tool created', - { - status: 'confirm' - }); - }, - - error: function () { - $('#messages').notify('Error creating tool.', - { - status: 'error' - }); - } - }); - - }, - - toolFormIsValid: function (e) { - e.preventDefault(); - - var errors = { - mount_point: [] - }; - - if (this.state.new_tool.mount_point.length < 3) { - errors.mount_point.push("Mount point must have at least 3 characters."); - } - - let data = { - 'mount_point': e.target.value, - '_session_id': $.cookie('_session_id') - }; - - let result = $.post(_getProjectUrl() + '/admin/mount_point/', data); - if (!result.responseJSON) { - errors.mount_point.push("Mount point already exists."); - } - - this.setState({errors: errors}) - - }, - - render: function () { - return ; - } -}); - - -//////////////////////////////////////////// - -/** * The main "controller view" of the NavBar. + * @constructor * @param {object} initialData - Consumes the _nav.json endpoint. */ @@ -589,7 +299,7 @@ var Main = React.createClass({ initialData: ToolsPropType, installableTools: React.PropTypes.array }, - getInitialState: function () { + getInitialState: function() { return { data: this.props.initialData, visible: false, @@ -601,8 +311,8 @@ var Main = React.createClass({ /** * When invoked, this updates the state with the latest data from the server. */ - getNavJson: function () { - $.get(`${_getProjectUrl(false)}/_nav.json`, function (result) { + getNavJson: function() { + $.get(`${_getProjectUrl(false)}/_nav.json`, function(result) { if (this.isMounted()) { this.setState({ data: result @@ -610,12 +320,10 @@ var Main = React.createClass({ } }.bind(this)); }, - - /** * Handles the locking and unlocking of the NavBar */ - handleToggleAdmin: function () { + handleToggleAdmin: function() { this.setState({ visible: !this.state.visible }); @@ -624,7 +332,13 @@ var Main = React.createClass({ /** * Handles the the display of the "Add new tool" menu. */ - handleToggleAddNewTool: function () { + handleToggleAddNewTool: function() { + $('body').click(function(e) { // click the background + if (e.target == this) { + $(this).fadeOut(); + } + }); + this.setState({ showAddToolMenu: !this.state.showAddToolMenu }); @@ -632,9 +346,10 @@ var Main = React.createClass({ /** * Handles the changing of the NavBars grouping threshold. + * @param {object} event */ - onUpdateThreshold: function (event) { + onUpdateThreshold: function(event) { var _this = this; var thres = event.target.value; var url = `${_getProjectUrl()}/admin/configure_tool_grouping`; @@ -651,8 +366,8 @@ var Main = React.createClass({ this.setState({ in_progress: true }); - $.post(url, data, function () { - }.bind(this)).always(function () { + $.post(url, data, function() { + }.bind(this)).always(function() { _this.setState({ in_progress: false }); @@ -664,15 +379,16 @@ var Main = React.createClass({ /** * Handles the changing of the NavBars grouping threshold. + * @param {array} data - Array of tools */ - onToolReorder: function (data) { + onToolReorder: function(data) { var tools = this.state.data; var params = { _session_id: $.cookie('_session_id') }; - data.map(function (tool, i) { + data.map(function(tool, i) { var mount_point = getMountPoint(tool); var index = tools.children.findIndex( x => x.mount_point === mount_point @@ -690,7 +406,7 @@ var Main = React.createClass({ type: 'POST', url: url, data: params, - success: function () { + success: function() { $('#messages').notify('Tool order updated', { status: 'confirm' @@ -698,7 +414,7 @@ var Main = React.createClass({ _this.getNavJson(); }, - error: function () { + error: function() { $('#messages').notify('Error saving tool order.', { status: 'error' @@ -707,33 +423,47 @@ var Main = React.createClass({ }); }, - render: function () { + render: function() { var editMode = this.state.visible ? 'edit-mode' : ''; var _this = this; var navBarSwitch = (showAdmin) => { if (showAdmin) { return ( - + ); } else { return (
    - - +
    - ) + ); } }; var navBar = navBarSwitch(this.state.visible); return ( -
    +
    { navBar }
    - +
    - +
    ); }