AMBARI-19735.Create new Navigation Bar for 3.0.0.(xiwang)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9a706402 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9a706402 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9a706402 Branch: refs/heads/side-navigation-feature-branch Commit: 9a706402c71c2a9c948a3d675b892e93156d66a7 Parents: eba6388 Author: Xi Wang <xiw...@apache.org> Authored: Tue Jan 17 16:20:52 2017 -0800 Committer: Xi Wang <xiw...@apache.org> Committed: Fri Feb 3 15:51:20 2017 -0800 ---------------------------------------------------------------------- .../main/resources/ui/admin-web/app/index.html | 2 +- ambari-web/app/assets/img/ambari-Logo.png | Bin 0 -> 2779 bytes ambari-web/app/assets/img/logo-white.png | Bin 4538 -> 0 bytes ambari-web/app/config.js | 6 +- ambari-web/app/styles/application.less | 2 + ambari-web/app/styles/common.less | 7 +- ambari-web/app/styles/side_navigation.less | 33 +++ .../app/styles/theme/bootstrap-ambari.css | 285 ++++++++++++++++++- ambari-web/app/styles/top-nav.less | 178 ++---------- ambari-web/app/templates/application.hbs | 178 +++++++----- ambari-web/app/templates/main/menu.hbs | 23 -- ambari-web/app/templates/main/menu_item.hbs | 50 ---- .../app/templates/main/side-menu-item.hbs | 47 +++ ambari-web/app/views/application.js | 34 +++ ambari-web/app/views/main/menu.js | 150 ++++++++-- ambari-web/app/views/main/service/menu.js | 104 +------ ambari-web/test/views/main/menu_test.js | 2 +- 17 files changed, 660 insertions(+), 441 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-admin/src/main/resources/ui/admin-web/app/index.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/index.html b/ambari-admin/src/main/resources/ui/admin-web/app/index.html index ba16103..d17ec53 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/index.html +++ b/ambari-admin/src/main/resources/ui/admin-web/app/index.html @@ -48,7 +48,7 @@ <header class="navbar navbar-static-top navbar-inverse"> <div class="navbar-inner"> <div class="container"> - <a href="{{fromSiteRoot('/#/main/dashboard')}}" class="logo"><img src="/img/logo-white.png" alt="{{'common.apacheAmbari' | translate}}" title="{{'common.apacheAmbari' | translate}}"></a> + <a href="{{fromSiteRoot('/#/main/dashboard')}}" class="logo"><img src="/img/ambari-logo.png" alt="{{'common.apacheAmbari' | translate}}" title="{{'common.apacheAmbari' | translate}}"></a> <a href="{{fromSiteRoot('/#/main/dashboard')}}" class="brand" title="{{'common.apacheAmbari' | translate}}">{{'common.ambari' | translate}}</a> <ul class="nav navbar-nav navbar-right"> <li> http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/assets/img/ambari-Logo.png ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/img/ambari-Logo.png b/ambari-web/app/assets/img/ambari-Logo.png new file mode 100644 index 0000000..07d31ee Binary files /dev/null and b/ambari-web/app/assets/img/ambari-Logo.png differ http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/assets/img/logo-white.png ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/img/logo-white.png b/ambari-web/app/assets/img/logo-white.png deleted file mode 100644 index a562ba7..0000000 Binary files a/ambari-web/app/assets/img/logo-white.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/config.js b/ambari-web/app/config.js index c7b41e6..6afa810 100644 --- a/ambari-web/app/config.js +++ b/ambari-web/app/config.js @@ -55,9 +55,9 @@ App.healthIconClassOrange = 'glyphicon glyphicon-minus-sign'; // bootstrap icon App.healthIconClassYellow = 'glyphicon glyphicon-question-sign'; // bootstrap icon class for heartbeat lost service/host/host-component App.isManagedMySQLForHiveEnabled = false; App.isStormMetricsSupported = true; -App.healthStatusRed = '#ff0000'; -App.healthStatusGreen = '#5AB400'; -App.healthStatusOrange = '#FF8E00'; +App.healthStatusRed = '#EF6162'; +App.healthStatusGreen = '#1EB475'; +App.healthStatusOrange = '#E98A41'; App.inactivityRemainTime = 60; // in seconds App.enableLogger = true; App.stackVersionsAvailable = true; http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index 612c09c..7a5b18e 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -69,6 +69,7 @@ ul.typeahead.dropdown-menu { overflow: visible; padding-bottom: @footer-height; min-width: 980px; + margin-left: @side-navigation-width; .clock-view { top: 10px; @@ -89,6 +90,7 @@ footer { color: #666; margin-top: -1 * @footer-height - 1; height: @footer-height - 60px; + margin-left: @side-navigation-width; } .editable-list-container { http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/styles/common.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/common.less b/ambari-web/app/styles/common.less index 29bb49d..94a5cd3 100644 --- a/ambari-web/app/styles/common.less +++ b/ambari-web/app/styles/common.less @@ -37,9 +37,9 @@ ***********************************************************************/ @health-status-red: #EF6162; @health-status-blue: #0000ff; -@health-status-green: #3FAE2A; +@health-status-green: #1EB475; @health-status-yellow: #FFD13D; -@health-status-orange: #E98A41; +@health-status-orange: #e98a41; @maintenance-black: #000; /************************************************************************ * Health status(service/host/host component health)icon colors ends @@ -60,7 +60,7 @@ @top-nav-bg-color-from: #555; @top-nav-bg-color-to: #333; -@top-nav-brand-color: #fff; +@top-nav-brand-color: #999; @top-nav-ops-count-color: #fff; @top-nav-ops-count-bg-color: #c3c3c3; @top-nav-menu-active-text-color: #333; @@ -184,6 +184,7 @@ } @footer-height: 100px; +@side-navigation-width: 190px; @default-font-size: 14px; @smaller-font-size: 12px; http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/styles/side_navigation.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/side_navigation.less b/ambari-web/app/styles/side_navigation.less new file mode 100644 index 0000000..5e188ac --- /dev/null +++ b/ambari-web/app/styles/side_navigation.less @@ -0,0 +1,33 @@ +/** + * 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. + */ + +@import 'common.less'; + +#side-nav { + position: fixed; + top: 0px; + bottom: auto; + z-index: 2079; + padding-bottom: 9999px; + margin-bottom: -9999px; + + .side-nav-footer { + position: fixed; + bottom: 0px; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/styles/theme/bootstrap-ambari.css ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/theme/bootstrap-ambari.css b/ambari-web/app/styles/theme/bootstrap-ambari.css index cd5179a..c3998a5 100644 --- a/ambari-web/app/styles/theme/bootstrap-ambari.css +++ b/ambari-web/app/styles/theme/bootstrap-ambari.css @@ -536,8 +536,8 @@ h2.table-title { font-style: normal; line-height: 1; color: #333; - line-height: 1.4; font-size: 14px; + line-height: 1.4; color: #999; } .wizard .wizard-body .wizard-content .panel.panel-default { @@ -584,12 +584,13 @@ h2.table-title { font-weight: normal; font-style: normal; line-height: 1; - margin-left: 30px; + color: #333; font-size: 14px; color: #999; + margin-left: 30px; } .wizard .wizard-body .wizard-nav .nav li .step-index { - line-height: 16px; + line-height: 18px; } .wizard .wizard-body .wizard-nav .nav li .step-description { font-family: 'Roboto', sans-serif; @@ -699,9 +700,6 @@ input[type="radio"].disabled + label:hover:before { background-color: #b2b8c1; border-color: #b2b8c1; } -input[type="checkbox"] + label { - margin-top: -2px; -} input[type="checkbox"] + label:before { content: ''; position: absolute; @@ -722,14 +720,13 @@ input[type="checkbox"]:checked + label:after { top: 2px; left: 2px; font-size: 9px; - line-height: 1.42; } input[type="radio"] + label:before, input.radio + label:before { content: ''; position: absolute; left: 0; - top: 2px; + top: 0; width: 12px; height: 12px; box-sizing: border-box; @@ -743,12 +740,282 @@ input.radio:checked + label:after { content: ''; background-color: #FFF; position: absolute; - top: 5px; + top: 3px; left: 3px; width: 6px; height: 6px; border-radius: 6px; } +.navigation-bar-container { + height: auto; + width: 190px; + background-color: #323544; + padding: 0px 0px; + overflow: hidden; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header { + background: #313d54; + padding: 15px 5px 15px 25px; + min-height: 50px; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header > a.ambari-logo { + padding: 0px; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header > a.ambari-logo > img { + height: 25px; + float: left; + margin-top: -2px; + margin-left: -3px; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header > a.ambari-header { + font-family: 'Roboto', sans-serif; + font-weight: normal; + font-style: normal; + line-height: 1; + color: #333; + font-size: 20px; + width: 55px; + display: inline; + color: #fff; + padding: 0px 8px; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header span.toggle-icon { + margin-bottom: 5px; + font-size: 13px; + cursor: pointer; + display: inline-block; + vertical-align: middle; + color: #b8bec4; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header ul.dropdown-menu { + min-width: 190px; + max-width: 190px; + width: 190px; + right: -43px; + left: auto; + top: 30px; + background: #323543; + border: none; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header ul.dropdown-menu li { + border: none; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header ul.dropdown-menu li > a { + font-family: 'Roboto', sans-serif; + font-weight: normal; + font-style: normal; + line-height: 1; + color: #333; + font-size: 13px; + color: #999; + padding: 15px 10px; + height: auto; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.navigation-bar-container ul.nav.side-nav-header li.navigation-header ul.dropdown-menu li > a:hover { + background: #404351; + color: #fff; +} +.navigation-bar-container ul.nav.side-nav-menu li, +.navigation-bar-container ul.nav.side-nav-footer li { + padding: 0px; + margin: 0px; +} +.navigation-bar-container ul.nav.side-nav-menu li a, +.navigation-bar-container ul.nav.side-nav-footer li a { + padding: 15px 5px 15px 25px; + display: table-cell; + vertical-align: middle; + width: 190px; + border-radius: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; +} +.navigation-bar-container ul.nav.side-nav-menu li a .navigation-menu-item, +.navigation-bar-container ul.nav.side-nav-footer li a .navigation-menu-item { + font-family: 'Roboto', sans-serif; + font-weight: normal; + font-style: normal; + line-height: 1; + color: #333; + font-size: 16px; + color: #b8bec4; + padding-left: 8px; +} +.navigation-bar-container ul.nav.side-nav-menu li a .navigation-icon, +.navigation-bar-container ul.nav.side-nav-footer li a .navigation-icon { + line-height: 18px; + font-size: 18px; + color: #b8bec4; +} +.navigation-bar-container ul.nav.side-nav-menu li a .toggle-icon, +.navigation-bar-container ul.nav.side-nav-footer li a .toggle-icon { + line-height: 14px; + font-size: 14px; + color: #b8bec4; + padding: 3px 5px 3px 10px; +} +.navigation-bar-container ul.nav.side-nav-menu li.navigation-footer, +.navigation-bar-container ul.nav.side-nav-footer li.navigation-footer { + background: #313d54; +} +.navigation-bar-container ul.nav.side-nav-menu li.navigation-footer a .navigation-icon, +.navigation-bar-container ul.nav.side-nav-footer li.navigation-footer a .navigation-icon { + color: #3fae2a; + font-size: 20px; + position: relative; + padding: 0px 15px; + left: calc(30%); +} +.navigation-bar-container ul.nav.side-nav-menu li.navigation-footer a .navigation-icon:hover, +.navigation-bar-container ul.nav.side-nav-footer li.navigation-footer a .navigation-icon:hover { + color: #fff; +} +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li { + background-color: #323544; +} +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li a, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li a { + font-family: 'Roboto', sans-serif; + font-weight: normal; + font-style: normal; + line-height: 1; + color: #333; + font-size: 13px; + color: #999; +} +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li a .submenu-icon, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li a .submenu-icon { + line-height: 14px; + font-size: 14px; +} +.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li > a:hover, +.navigation-bar-container ul.nav.side-nav-footer li.mainmenu-li > a:hover, +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li > a:hover, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li > a:hover { + background: #404351; + cursor: pointer; + color: #fff; +} +.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li > a:hover .navigation-menu-item, +.navigation-bar-container ul.nav.side-nav-footer li.mainmenu-li > a:hover .navigation-menu-item, +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li > a:hover .navigation-menu-item, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li > a:hover .navigation-menu-item, +.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li > a:hover .navigation-icon, +.navigation-bar-container ul.nav.side-nav-footer li.mainmenu-li > a:hover .navigation-icon, +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li > a:hover .navigation-icon, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li > a:hover .navigation-icon, +.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li > a:hover .toggle-icon, +.navigation-bar-container ul.nav.side-nav-footer li.mainmenu-li > a:hover .toggle-icon, +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li > a:hover .toggle-icon, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li > a:hover .toggle-icon, +.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li > a:hover .submenu-item, +.navigation-bar-container ul.nav.side-nav-footer li.mainmenu-li > a:hover .submenu-item, +.navigation-bar-container ul.nav.side-nav-menu li.submenu-li > a:hover .submenu-item, +.navigation-bar-container ul.nav.side-nav-footer li.submenu-li > a:hover .submenu-item { + color: #fff; +} +.navigation-bar-container ul.nav.side-nav-menu li.active:not(.no-active-effect), +.navigation-bar-container ul.nav.side-nav-footer li.active:not(.no-active-effect) { + background: #404351; + cursor: pointer; +} +.navigation-bar-container ul.nav.side-nav-menu li.active:not(.no-active-effect) > a, +.navigation-bar-container ul.nav.side-nav-footer li.active:not(.no-active-effect) > a { + border-left: 6px solid #3fae2a; + padding-left: 19px; + color: #fff; +} +.navigation-bar-container ul.nav.side-nav-menu li.active:not(.no-active-effect) > a .navigation-menu-item, +.navigation-bar-container ul.nav.side-nav-footer li.active:not(.no-active-effect) > a .navigation-menu-item, +.navigation-bar-container ul.nav.side-nav-menu li.active:not(.no-active-effect) > a .submenu-item, +.navigation-bar-container ul.nav.side-nav-footer li.active:not(.no-active-effect) > a .submenu-item, +.navigation-bar-container ul.nav.side-nav-menu li.active:not(.no-active-effect) > a .navigation-icon, +.navigation-bar-container ul.nav.side-nav-footer li.active:not(.no-active-effect) > a .navigation-icon, +.navigation-bar-container ul.nav.side-nav-menu li.active:not(.no-active-effect) > a .toggle-icon, +.navigation-bar-container ul.nav.side-nav-footer li.active:not(.no-active-effect) > a .toggle-icon { + color: #fff; +} +.navigation-bar-container .nav-pills > li.active > a, +.navigation-bar-container .nav-pills > li.active > a:focus, +.navigation-bar-container .nav-pills > li.active > a:hover, +.navigation-bar-container .nav > li > a:focus, +.navigation-bar-container .nav > li > a:hover { + background-color: inherit; +} +.navigation-bar-container.collapsed { + width: 50px; + overflow: visible; +} +.navigation-bar-container.collapsed ul.nav.side-nav-header li.navigation-header { + padding: 15px 0px 15px 17px; +} +.navigation-bar-container.collapsed ul.nav.side-nav-header li.navigation-header a.ambari-header, +.navigation-bar-container.collapsed ul.nav.side-nav-header li.navigation-header span.toggle-icon, +.navigation-bar-container.collapsed ul.nav.side-nav-header li.navigation-header .dropdown-menu { + display: none; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li a, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li a { + padding: 15px 0px 15px 17px; + width: 50px; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li a .navigation-menu-item, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li a .navigation-menu-item, +.navigation-bar-container.collapsed ul.nav.side-nav-menu li a .toggle-icon, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li a .toggle-icon { + display: none; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.navigation-footer a .navigation-icon, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.navigation-footer a .navigation-icon { + padding: 0px 5px; + left: 0px; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li ul.sub-menu, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li ul.sub-menu { + display: none; + width: 190px; + position: absolute; + left: 50px; + top: 0px; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li:hover ul.sub-menu, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li:hover ul.sub-menu { + display: block; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.submenu-li > a, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.submenu-li > a { + padding: 15px 5px 15px 25px; + width: 190px; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.active, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.active { + background: #404351; + cursor: pointer; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.active > a, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.active > a { + border-left: 6px solid #3fae2a; + padding-left: 12px; + color: #fff; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.active > a .navigation-menu-item, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.active > a .navigation-menu-item, +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.active > a .submenu-item, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.active > a .submenu-item, +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.active > a .navigation-icon, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.active > a .navigation-icon, +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.active > a .toggle-icon, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.active > a .toggle-icon { + color: #fff; +} +.navigation-bar-container.collapsed ul.nav.side-nav-menu li.submenu-li.active > a, +.navigation-bar-container.collapsed ul.nav.side-nav-footer li.submenu-li.active > a { + padding-left: 19px; +} h1, h2, h3, http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/styles/top-nav.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/top-nav.less b/ambari-web/app/styles/top-nav.less index 3dcd298..747caab 100644 --- a/ambari-web/app/styles/top-nav.less +++ b/ambari-web/app/styles/top-nav.less @@ -19,33 +19,37 @@ @import 'common.less'; #top-nav { - .navbar.navbar-static-top { - background-image: -moz-linear-gradient(top, @top-nav-bg-color-from, @top-nav-bg-color-to); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@top-nav-bg-color-from), to(@top-nav-bg-color-to)); - background-image: -webkit-linear-gradient(top, @top-nav-bg-color-from, @top-nav-bg-color-to); - background-image: -o-linear-gradient(top, @top-nav-bg-color-from, @top-nav-bg-color-to); - background-image: linear-gradient(to bottom, @top-nav-bg-color-from, @top-nav-bg-color-to); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr= @top-nav-bg-color-from, endColorstr=@top-nav-bg-color-to); //for IE9- - box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1); + background: #fff; + border-top: 1px solid #e3e3e3; + border-bottom: 1px solid #e3e3e3; .navbar-text.brand-wrapper { color: @top-nav-brand-color; font-size: 16px; font-weight: normal; - text-shadow: 0 1px 0 #555; a, a:hover, a:active, a:visited { color: @top-nav-brand-color; text-decoration: none; + line-height: 20px; + vertical-align: middle; + position: relative; } - .ambari-link { - margin-left: 25px; - } - .label { + + .numberCircle { + border-radius: 50%; + width: 20px; + height: 20px; + padding: 0px 0px; color: @top-nav-ops-count-color; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: @top-nav-ops-count-bg-color; + text-align: center; + font-size: 12px; + display: inline-block; + position: relative; + top: -2px; + &.operations-count { .infoPulse(); } @@ -59,10 +63,13 @@ cursor: default; } } - .icon-caret-left { - color: @top-nav-ops-count-bg-color; - margin-right: -1px; - text-shadow: none; + .cluster-name, .bg-label, .alerts-label { + margin: 0px 15px 0px 5px; + .glyphicon { + font-size: 20px; + top: 4px; + left: 2px; + } } .ops-count { margin-right: -1px; @@ -73,140 +80,9 @@ a:hover { text-decoration: none; } - - .logo { - img { - height: 32px; - width: 32px; - position: absolute; - top: 8px; - } - } - - .alerts-label { - margin-left: 5px; - display: inline-block; - } - - .icon-caret-left { - color: @top-nav-ops-count-bg-color; - margin-right: -1px; - text-shadow: none; - } - - .cluster-name { - margin-left: 20px; - } - - .top-nav-menu.nav { - padding-right: 20px; - li > a { - text-shadow: none; - color: @top-nav-menu-text-color; - text-align: center; - white-space: nowrap; - } - .active > a, .active > a:hover, .active > a:focus { - color: @top-nav-menu-active-text-color; - background-color: @top-nav-menu-active-bg-color; - box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - } - li > a:focus, li > a:hover { - color: @top-nav-menu-text-hover-color; - text-decoration: none; - background-color: transparent; - } - .glyphicon-th { - font-size: 1.1em; - } - - li.top-nav-dropdown { - position: relative; - } - .top-nav-dropdown:hover .top-nav-dropdown-menu { - display: block; - } - .top-nav-dropdown-menu { - display: none; - position: absolute; - top: 95%; - left: 0; - z-index: 1000; - float: left; - min-width: 220px; - width: 220px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - background-color: @top-nav-menu-dropdown-bg-color; - border: 3px solid @top-nav-menu-dropdown-border-color; - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; - .alerts-count { - margin-right: 5px; - } - } - .top-nav-dropdown-menu > li{ - position: relative; - } - .top-nav-dropdown-menu > li > a { - text-decoration: none; - text-align: left; - display: block; - padding: 3px 0 3px 5px; - color: @top-nav-menu-dropdown-text-color; - white-space: nowrap; - .glyphicon-health-block > span:before { - line-height: 20px; - } - } - .top-nav-dropdown-menu > li.active > a{ - background-color: #e5e5e5; - } - .top-nav-dropdown-menu > li > a:hover { - color: #fff; - background-color: #666; - background-image: linear-gradient(to bottom, #666, #555); - background-repeat: repeat-x; - } - .top-nav-dropdown-menu > li.disabled > a { - color: #a9a9a9; - cursor: default; - } - .top-nav-dropdown-menu > li.disabled > a:hover { - color: #a9a9a9; - background-color: @top-nav-menu-dropdown-bg-color; - background-image: none; - } - } - } - - .navbar .nav .top-nav-user .active > a, - .navbar .nav .top-nav-user .active > a:hover { - color: #fff; - text-decoration: none; - } - - .navbar .nav .top-nav-user > li > a { - border-radius: 8px; - font-size: 13px; - font-weight: bold; - margin: 1px 10px 2px 0; - padding: 7px 14px; - text-decoration: none; - text-shadow: none; } - .navbar .nav .top-nav-user > li > a:hover { - background-color: transparent; - color: #999; - text-decoration: none; + .top-nav-user { + margin-top: 2px; } - - .navbar .nav .top-nav-user > li.right { - float: right; - } - } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/templates/application.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/application.hbs b/ambari-web/app/templates/application.hbs index cf3e561..b2210b7 100644 --- a/ambari-web/app/templates/application.hbs +++ b/ambari-web/app/templates/application.hbs @@ -20,34 +20,118 @@ {{view App.ClockView}} {{/if}} +<div id="side-nav" class="navigation-bar-container"> + <ul class="side-nav-header nav nav-pills nav-stacked"> + <li class="navigation-header"> + {{#if enableLinks}} + <a {{translateAttr href="topnav.logo.href"}} class="ambari-logo"> + <img src="/img/ambari-logo.png" alt="Apache Ambari" title="Apache Ambari"> + </a> + <a {{translateAttr href="topnav.logo.href"}} class="ambari-header" title="Apache Ambari">{{t app.name}}</a> + {{else}} + <a class="ambari-logo"> + <img src="/img/ambari-logo.png" alt="Apache Ambari" title="Apache Ambari"> + </a> + <a class="ambari-header" title="Apache Ambari">{{t app.name}}</a> + {{/if}} + + <div class="btn-group"> + <span class="dropdown-toggle toggle-icon glyphicon glyphicon-triangle-bottom" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> + <ul class="dropdown-menu"> + {{#if view.views.length}} + {{#each item in view.views}} + <li><a class="" href="#" {{action "setView" item target="App.router.mainViewsController"}}>{{item.label}}</a></li> + {{/each}} + {{else}} + <li class="disabled"><a href="javascript:void(null);">{{t menu.item.views.noViews}}</a></li> + {{/if}} + </ul> + </div> + </li> + </ul> + {{view App.MainSideMenuView}} + <ul class="side-nav-footer nav nav-pills nav-stacked"> + <li class="navigation-footer"> + <a> + <span class="navigation-icon icon-double-angle-left" data-toggle="collapseSideNav"></span> + </a> + </li> + </ul> +</div> + <div id="main"> <div id="top-nav"> <nav class="navbar navbar-default navbar-static-top"> <div class="container main-container"> <div class="navbar-header navbar-nav"> - {{#if enableLinks}} - <a {{translateAttr href="topnav.logo.href"}} class="navbar-brand logo"> - <img src="/img/logo-white.png" alt="Apache Ambari" title="Apache Ambari"> - </a> - {{else}} - <a class="logo"><img src="/img/logo-white.png" alt="Apache Ambari" title="Apache Ambari"></a> - {{/if}} </div> - <p class="navbar-text navbar-nav brand-wrapper"> + + {{! right offset. don't delete me! }} + <ul class="nav navbar-nav navbar-right"></ul> + + {{! user dropdown }} + {{#if App.router.loggedIn}} + <div class="top-nav-user navbar-right btn-group"> + <button class="dropdown-toggle navbar-btn btn btn-default" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> + <i class="glyphicon glyphicon-user"></i> {{App.router.displayLoginName}} <span class="caret"></span> + </button> + <ul class="dropdown-menu"> + + {{! about }} + <li><a href="#" id="about" {{action showAboutPopup target="controller"}}>{{t app.aboutAmbari}}</a></li> + {{! about end }} + + {{! manage ambari }} + {{#if showManageAmbari}} + {{#isAuthorized "AMBARI.ADD_DELETE_CLUSTERS, AMBARI.ASSIGN_ROLES, AMBARI.EDIT_STACK_REPOS, AMBARI.MANAGE_GROUPS, AMBARI.MANAGE_STACK_VERSIONS, AMBARI.MANAGE_USERS, AMBARI.MANAGE_VIEWS, AMBARI.RENAME_CLUSTER, AMBARI.MANAGE_USERS"}} + <li> + <a href="#" id="manage-ambari" {{action goToAdminView target="controller"}}> + {{t app.manageAmbari}} + </a> + </li> + {{/isAuthorized}} + {{/if}} + {{! manage ambari end }} + + {{! user settings }} + {{#if isExistingClusterDataLoaded}} + {{#isAuthorized "AMBARI.MANAGE_SETTINGS"}} + <li> + <a href="#" {{action showSettingsPopup target="App.router.userSettingsController"}}> + {{t app.settings}} + </a> + </li> + {{/isAuthorized}} + {{/if}} + {{! user settings end }} + + {{! sign out }} + {{#if showExitLink}} + <li role="separator" class="divider"></li> + <li><a href="" id="sign-out" {{action logoff}}>{{t app.signout}}</a></li> + {{/if}} + {{! sign out end }} + </ul> + </div> + {{/if}} + {{! user dropdown end }} + + <div class="navbar-nav navbar-text navbar-right brand-wrapper"> {{#if enableLinks}} - <a {{translateAttr href="topnav.logo.href"}} class="ambari-link" title="Apache Ambari">{{t app.name}}</a> + {{! cluster name }} <a href="#" {{bindAttr title="clusterName"}} {{action "showPopup" target="App.router.backgroundOperationsController"}} class="cluster-name"> {{#unless App.isClusterUser}} - <span>{{clusterDisplayName}} </span> + <span>{{clusterDisplayName}}</span> {{/unless}} </a> {{! cluster name end }} {{! bg label }} <a href="#" class="bg-label" {{action "showPopup" target="App.router.backgroundOperationsController"}}> {{#with App.router.backgroundOperationsController}} - <i {{bindAttr class="allOperationsCount:ops-count :icon-caret-left"}}></i><span id="span-bg-operation-count" {{bindAttr class="allOperationsCount:operations-count :label"}}> - {{allOperationsCount}} {{pluralize allOperationsCount singular="t:op" plural="t:ops"}} + <span class="glyphicon glyphicon-cog"></span> + <span id="span-bg-operation-count" {{bindAttr class="allOperationsCount:operations-count :numberCircle"}}> + {{allOperationsCount}} </span> {{/with}} </a> @@ -56,78 +140,22 @@ {{#if App.router.clusterController.isAlertsLoaded}} <a href="#" class="alerts-label" {{action "showPopup" target="App.router.mainAlertInstancesController"}}> {{#if App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} + <span class="glyphicon glyphicon-bell"></span> {{! alerts exist }} - <span {{bindAttr class=":label App.router.mainAlertDefinitionsController.isCriticalAlerts:alert-crit-count:alert-warn-count"}}> - {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} {{pluralize App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount singular="alert" plural="alerts"}} + <span {{bindAttr class=":numberCircle App.router.mainAlertDefinitionsController.isCriticalAlerts:alert-crit-count:alert-warn-count"}}> + {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} </span> {{else}} {{! no alerts }} - <span {{translateAttr title="titlebar.alerts.noAlerts"}} class="label alerts-none-count"> - {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} {{pluralize App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount singular="alert" plural="alerts"}} + <span {{translateAttr title="titlebar.alerts.noAlerts"}} class="numberCircle alerts-none-count"> + {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} </span> {{/if}} </a> {{/if}} {{! alerts label end }} - {{else}} - <a title="Apache Ambari" class="ambari-link">{{t app.name}}</a> {{/if}} - </p> - - {{! right offset. don't delete me! }} - <ul class="nav navbar-nav navbar-right"></ul> - - {{! user dropdown }} - {{#if App.router.loggedIn}} - <ul class="nav navbar-nav top-nav-user navbar-right"> - <li class="dropdown"> - <button class="dropdown-toggle navbar-btn btn btn-default" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> - <i class="glyphicon glyphicon-user"></i> {{App.router.displayLoginName}} <span class="caret"></span> - </button> - <ul class="dropdown-menu"> - - {{! about }} - <li><a href="#" id="about" {{action showAboutPopup target="controller"}}>{{t app.aboutAmbari}}</a></li> - {{! about end }} - - {{! manage ambari }} - {{#if showManageAmbari}} - {{#isAuthorized "AMBARI.ADD_DELETE_CLUSTERS, AMBARI.ASSIGN_ROLES, AMBARI.EDIT_STACK_REPOS, AMBARI.MANAGE_GROUPS, AMBARI.MANAGE_STACK_VERSIONS, AMBARI.MANAGE_USERS, AMBARI.MANAGE_VIEWS, AMBARI.RENAME_CLUSTER, AMBARI.MANAGE_USERS"}} - <li> - <a href="#" id="manage-ambari" {{action goToAdminView target="controller"}}> - {{t app.manageAmbari}} - </a> - </li> - {{/isAuthorized}} - {{/if}} - {{! manage ambari end }} - - {{! user settings }} - {{#if isExistingClusterDataLoaded}} - {{#isAuthorized "AMBARI.MANAGE_SETTINGS"}} - <li> - <a href="#" {{action showSettingsPopup target="App.router.userSettingsController"}}> - {{t app.settings}} - </a> - </li> - {{/isAuthorized}} - {{/if}} - {{! user settings end }} - - {{! sign out }} - {{#if showExitLink}} - <li role="separator" class="divider"></li> - <li><a href="" id="sign-out" {{action logoff}}>{{t app.signout}}</a></li> - {{/if}} - {{! sign out end }} - - </ul> - </li> - </ul> - {{/if}} - {{! user dropdown end }} - - {{view App.MainMenuView}} + </div> </div> </nav> @@ -164,4 +192,4 @@ {{outlet}} </div> </div> -</div> \ No newline at end of file +</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/templates/main/menu.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/main/menu.hbs b/ambari-web/app/templates/main/menu.hbs deleted file mode 100644 index 0b943ec..0000000 --- a/ambari-web/app/templates/main/menu.hbs +++ /dev/null @@ -1,23 +0,0 @@ -{{! -* 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. -}} - -<ul class="nav nav-tabs"> - {{#each view.items}} - <li {{bindAttr class="active"}} ><a {{action navigate routing }} href="#">{{unbound label}}</a></li> - {{/each}} -</ul> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/templates/main/menu_item.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/main/menu_item.hbs b/ambari-web/app/templates/main/menu_item.hbs deleted file mode 100644 index 0021445..0000000 --- a/ambari-web/app/templates/main/menu_item.hbs +++ /dev/null @@ -1,50 +0,0 @@ -{{! -* 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. -}} - - -<a href="#" {{action goToSection view.content.routing target="view"}} {{bindAttr class="view.content.isView:views-button-container"}}> - {{{unbound view.content.label}}} -</a> - -<!--dropdown menu for the items had dropdowns--> -{{#if view.isServicesItem}} - {{view App.TopNavServiceMenuView}} -{{/if}} -{{#if view.isAdminItem}} - <ul class="top-nav-dropdown-menu dropdown-menu"> - {{#each category in view.dropdownCategories}} - {{#view view.AdminDropdownItemView itemBinding="category.name"}} - <a href="#" {{action "goToCategory" category.url target="view"}}>{{category.label}}</a> - {{/view}} - {{/each}} - </ul> -{{/if}} -{{#if view.isViewsItem}} - <ul class="top-nav-dropdown-menu dropdown-menu"> - {{#if view.content.views.length}} - {{#each category in view.content.views}} - <li><a href="#" {{action "setView" category target="App.router.mainViewsController"}}>{{category.label}}</a></li> - {{/each}} - {{else}} - <li class="disabled"><a href="javascript:void(null);">{{t menu.item.views.noViews}}</a></li> - {{/if}} - </ul> -{{/if}} - - - http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/templates/main/side-menu-item.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/main/side-menu-item.hbs b/ambari-web/app/templates/main/side-menu-item.hbs new file mode 100644 index 0000000..ca10a73 --- /dev/null +++ b/ambari-web/app/templates/main/side-menu-item.hbs @@ -0,0 +1,47 @@ +{{! +* 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. +}} + + +<a {{action goToSection view.content.routing target="view"}} {{bindAttr class="view.content.isView:views-button-container"}}> + <span {{bindAttr class=":navigation-icon view.content.iconClass"}}></span> + <span class="navigation-menu-item">{{{unbound view.content.label}}}</span> + {{#if view.isServicesItem}} + <span class="toggle-icon glyphicon glyphicon-menu-down" data-toggle="collapseSubMenu"></span> + {{/if}} + {{#if view.isAdminItem}} + <span class="toggle-icon glyphicon glyphicon-menu-down" data-toggle="collapseSubMenu"></span> + {{/if}} +</a> + +<!--dropdown menu for the items had dropdowns--> +{{#if view.isServicesItem}} + {{view App.SideNavServiceMenuView}} +{{/if}} +{{#if view.isAdminItem}} + <ul class="sub-menu nav nav-pills nav-stacked"> + {{#each category in view.dropdownCategories}} + {{#view view.AdminDropdownItemView itemBinding="category.name"}} + <a href="#" {{action "goToCategory" category.url target="view"}}>{{category.label}}</a> + {{/view}} + {{/each}} + </ul> +{{/if}} + + + + http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/views/application.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/application.js b/ambari-web/app/views/application.js index 38ca3b5..c9cffb1 100644 --- a/ambari-web/app/views/application.js +++ b/ambari-web/app/views/application.js @@ -22,6 +22,13 @@ var App = require('app'); App.ApplicationView = Em.View.extend({ templateName: require('templates/application'), + views: function () {⨠+ if (App.router.get('loggedIn')) {⨠+ return App.router.get('mainViewsController.ambariViews').filterProperty('visible');⨠+ } else {⨠+ return [];⨠+ }â¨}.property('App.router.mainViewsController.ambariViews.length', 'App.router.loggedIn'), + didInsertElement: function () { // on 'Enter' pressed, trigger modal window primary button if primary button is enabled(green) // on 'Esc' pressed, close the modal @@ -37,5 +44,32 @@ App.ApplicationView = Em.View.extend({ } return true; }); + + $('[data-toggle=collapseSideNav]').click(function() { + $('.navigation-bar-container').toggleClass('collapsed').promise().done(function(){ + + if ($('.navigation-bar-container').hasClass('collapsed')) { + // set submenu invisible when collapsed + $('.navigation-bar-container.collapsed ul.sub-menu').hide(); + // set the hover effect when collapsed, should show sub-menu on hovering + $(".navigation-bar-container.collapsed .side-nav-menu>li").hover(function() { + $(this).children("ul.sub-menu").show(); + }, function() { + $(this).children("ul.sub-menu").hide(); + }); + } else { + // keep showing all submenu + $('.navigation-bar-container ul.sub-menu').show(); + $(".navigation-bar-container .side-nav-menu>li").unbind('mouseenter mouseleave'); + $('[data-toggle=collapseSubMenu]').removeClass('glyphicon-menu-right'); + $('[data-toggle=collapseSubMenu]').addClass('glyphicon-menu-down'); + } + + //set main content left margin based on the width of side-nav + $('#main').css('margin-left', $('.navigation-bar-container').width()); + $('footer').css('margin-left', $('.navigation-bar-container').width()); + }); + $('[data-toggle=collapseSideNav]').toggleClass('icon-double-angle-right');//, 100, "easeOutSine"); + }); } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/views/main/menu.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/menu.js b/ambari-web/app/views/main/menu.js index bb27388..45eb2b9 100644 --- a/ambari-web/app/views/main/menu.js +++ b/ambari-web/app/views/main/menu.js @@ -18,13 +18,9 @@ var App = require('app'); -/** - * this menu extended by other with modifying content and itemViewClass.template - * @type {*} - */ -App.MainMenuView = Em.CollectionView.extend({ +App.MainSideMenuView = Em.CollectionView.extend({ tagName: 'ul', - classNames: ['nav', 'top-nav-menu', 'navbar-nav', 'navbar-right'], + classNames: ['nav', 'side-nav-menu', 'nav-pills', 'nav-stacked'], views: function () { return App.router.get('mainViewsController.ambariViews'); @@ -37,33 +33,40 @@ App.MainMenuView = Em.CollectionView.extend({ if (App.router.get('clusterController.isLoaded') && App.get('router.clusterInstallCompleted')) { if (!App.get('isOnlyViewUser')) { result.push( - {label: Em.I18n.t('menu.item.dashboard'), routing: 'dashboard', active: 'active'}, - {label: Em.I18n.t('menu.item.services'), routing: 'services'}, - {label: Em.I18n.t('menu.item.hosts'), routing: 'hosts'}, - {label: Em.I18n.t('menu.item.alerts'), routing: 'alerts'} + {label: Em.I18n.t('menu.item.dashboard'), iconClass: 'glyphicon glyphicon-home', routing: 'dashboard', active: 'active'}, + {label: Em.I18n.t('menu.item.services'), iconClass: 'glyphicon glyphicon-briefcase', routing: 'services'}, + {label: Em.I18n.t('menu.item.hosts'), iconClass: 'icon-tasks', routing: 'hosts'}, + {label: Em.I18n.t('menu.item.alerts'), iconClass: 'glyphicon glyphicon-bell', routing: 'alerts'} ); } if (App.isAuthorized('CLUSTER.TOGGLE_KERBEROS, CLUSTER.MODIFY_CONFIGS, SERVICE.START_STOP, SERVICE.SET_SERVICE_USERS_GROUPS, CLUSTER.UPGRADE_DOWNGRADE_STACK, CLUSTER.VIEW_STACK_DETAILS') - || (App.get('upgradeInProgress') || App.get('upgradeHolding'))) { - result.push({ label: Em.I18n.t('menu.item.admin'), routing: 'admin'}); + || (App.get('upgradeInProgress') || App.get('upgradeHolding'))) { + result.push({ label: Em.I18n.t('menu.item.admin'), iconClass: 'glyphicon glyphicon-wrench', routing: 'admin'}); } } - result.push({ label: Em.I18n.t('menu.item.views'), routing: 'views.index', isView: true, views: this.get('views').filterProperty('visible')}); } return result; }.property( - 'App.router.loggedIn', - 'views.length', - 'App.router.clusterController.isLoaded', - 'App.router.clusterInstallCompleted', - 'App.router.wizardWatcherController.isWizardRunning' + 'App.router.loggedIn', + 'views.length', + 'App.router.clusterController.isLoaded', + 'App.router.clusterInstallCompleted', + 'App.router.wizardWatcherController.isWizardRunning' ), itemViewClass: Em.View.extend({ - classNameBindings: ['active', 'dropdownMenu:dropdown'], + classNameBindings: ['active', 'dropdownMenu:dropdown', 'dropdownMenu:no-active-effect'], - classNames: ['top-nav-dropdown'], + classNames: ['mainmenu-li'], + + didInsertElement: function () { + $('[data-toggle=collapseSubMenu]').off('click').on('click', function(event){ + $(this).parent().siblings('.sub-menu').slideToggle(600); + $(this).toggleClass('glyphicon-menu-right glyphicon-menu-down'); + event.stopPropagation(); + }); + }, active: function () { if (App.get('clusterName') && App.router.get('clusterController.isLoaded')) { @@ -79,9 +82,9 @@ App.MainMenuView = Em.CollectionView.extend({ return ''; }.property('App.router.location.lastSetURL', 'App.router.clusterController.isLoaded'), - templateName: require('templates/main/menu_item'), + templateName: require('templates/main/side-menu-item'), - dropdownMenu: Em.computed.existsIn('content.routing', ['services', 'admin', 'views']), + dropdownMenu: Em.computed.existsIn('content.routing', ['services', 'admin']), isAdminItem: Em.computed.equal('content.routing', 'admin'), isServicesItem: Em.computed.equal('content.routing', 'services'), isViewsItem: function () { @@ -146,6 +149,7 @@ App.MainMenuView = Em.CollectionView.extend({ AdminDropdownItemView: Ember.View.extend({ tagName: 'li', classNameBindings: ['isActive:active', 'isDisabled:disabled'], + classNames: ['submenu-li'], isActive: Em.computed.equalProperties('item', 'parentView.selectedAdminItem'), isDisabled: function () { return !!this.get('parentView.dropdownCategories').findProperty('name', this.get('item')).disabled; @@ -161,3 +165,105 @@ App.MainMenuView = Em.CollectionView.extend({ }) }) }); + +App.SideNavServiceMenuView = Em.CollectionView.extend({ + disabledServices: [], + + content: function () { + return App.router.get('mainServiceController.content').filter(function (item) { + return !this.get('disabledServices').contains(item.get('id')); + }, this); + }.property('App.router.mainServiceController.content', 'App.router.mainServiceController.content.length'), + + didInsertElement:function () { + App.router.location.addObserver('lastSetURL', this, 'renderOnRoute'); + this.renderOnRoute(); + App.tooltip(this.$(".restart-required-service"), {html:true, placement:"right"}); + }, + + willDestroyElement: function() { + App.router.location.removeObserver('lastSetURL', this, 'renderOnRoute'); + this.$(".restart-required-service").tooltip('destroy'); + }, + + activeServiceId:null, + /** + * Syncs navigation menu with requested URL + */ + renderOnRoute:function () { + var last_url = App.router.location.lastSetURL || location.href.replace(/^[^#]*#/, ''); + if (last_url.substr(1, 4) !== 'main' || !this._childViews) { + return; + } + var reg = /^\/main\/services\/(\S+)\//g; + var sub_url = reg.exec(last_url); + var service_id = (null != sub_url) ? sub_url[1] : 1; + this.set('activeServiceId', service_id); + }, + + tagName:'ul', + classNames:[ 'sub-menu', 'nav', 'nav-pills', 'nav-stacked'], + + itemViewClass:Em.View.extend({ + + classNameBindings:["active", "clients"], + classNames: ["submenu-li"], + templateName:require('templates/main/service/menu_item'), + restartRequiredMessage: null, + + shouldBeRestarted: Em.computed.someBy('content.hostComponents', 'staleConfigs', true), + + active:function () { + return this.get('content.id') == this.get('parentView.activeServiceId') ? 'active' : ''; + }.property('parentView.activeServiceId'), + + alertsCount: function () { + return this.get('content.alertsCount') > 99 ? "99+" : this.get('content.alertsCount') ; + }.property('content.alertsCount'), + + hasCriticalAlerts: Em.computed.alias('content.hasCriticalAlerts'), + + isConfigurable: function () { + return !App.get('services.noConfigTypes').contains(this.get('content.serviceName')); + }.property('App.services.noConfigTypes','content.serviceName'), + + link: function() { + var stateName = (['summary','configs'].contains(App.router.get('currentState.name'))) + ? this.get('isConfigurable') ? App.router.get('currentState.name') : 'summary' + : 'summary'; + return "#/main/services/" + this.get('content.id') + "/" + stateName; + }.property('App.router.currentState.name', 'parentView.activeServiceId','isConfigurable'), + + goToConfigs: function () { + App.router.set('mainServiceItemController.routeToConfigs', true); + App.router.transitionTo('services.service.configs', this.get('content')); + App.router.set('mainServiceItemController.routeToConfigs', false); + }, + + refreshRestartRequiredMessage: function() { + var restarted, componentsCount, hostsCount, message, tHosts, tComponents; + restarted = this.get('content.restartRequiredHostsAndComponents'); + componentsCount = 0; + hostsCount = 0; + message = ""; + for (var host in restarted) { + hostsCount++; + componentsCount += restarted[host].length; + } + if (hostsCount > 1) { + tHosts = Em.I18n.t('common.hosts'); + } else { + tHosts = Em.I18n.t('common.host'); + } + if (componentsCount > 1) { + tComponents = Em.I18n.t('common.components'); + } else { + tComponents = Em.I18n.t('common.component'); + } + message += componentsCount + ' ' + tComponents + ' ' + Em.I18n.t('on') + ' ' + + hostsCount + ' ' + tHosts + ' ' + Em.I18n.t('services.service.config.restartService.needToRestartEnd'); + this.set('restartRequiredMessage', message); + }.observes('content.restartRequiredHostsAndComponents') + }) + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/app/views/main/service/menu.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/service/menu.js b/ambari-web/app/views/main/service/menu.js index aad718d..650cbbf 100644 --- a/ambari-web/app/views/main/service/menu.js +++ b/ambari-web/app/views/main/service/menu.js @@ -115,106 +115,4 @@ App.MainServiceMenuView = Em.CollectionView.extend({ this.set('restartRequiredMessage', message); }.observes('content.restartRequiredHostsAndComponents') }) - -}); - -App.TopNavServiceMenuView = Em.CollectionView.extend({ - disabledServices: [], - - content: function () { - return App.router.get('mainServiceController.content').filter(function (item) { - return !this.get('disabledServices').contains(item.get('id')); - }, this); - }.property('App.router.mainServiceController.content', 'App.router.mainServiceController.content.length'), - - didInsertElement:function () { - App.router.location.addObserver('lastSetURL', this, 'renderOnRoute'); - this.renderOnRoute(); - App.tooltip(this.$(".restart-required-service"), {html:true, placement:"right"}); - }, - - willDestroyElement: function() { - App.router.location.removeObserver('lastSetURL', this, 'renderOnRoute'); - this.$(".restart-required-service").tooltip('destroy'); - }, - - activeServiceId:null, - /** - * Syncs navigation menu with requested URL - */ - renderOnRoute:function () { - var last_url = App.router.location.lastSetURL || location.href.replace(/^[^#]*#/, ''); - if (last_url.substr(1, 4) !== 'main' || !this._childViews) { - return; - } - var reg = /^\/main\/services\/(\S+)\//g; - var sub_url = reg.exec(last_url); - var service_id = (null != sub_url) ? sub_url[1] : 1; - this.set('activeServiceId', service_id); - }, - - tagName:'ul', - classNames:[ "top-nav-dropdown-menu"], - - itemViewClass:Em.View.extend({ - - classNameBindings:["active", "clients"], - templateName:require('templates/main/service/menu_item'), - restartRequiredMessage: null, - - shouldBeRestarted: Em.computed.someBy('content.hostComponents', 'staleConfigs', true), - - active:function () { - return this.get('content.id') == this.get('parentView.activeServiceId') ? 'active' : ''; - }.property('parentView.activeServiceId'), - - alertsCount: function () { - return this.get('content.alertsCount') > 99 ? "99+" : this.get('content.alertsCount') ; - }.property('content.alertsCount'), - - hasCriticalAlerts: Em.computed.alias('content.hasCriticalAlerts'), - - isConfigurable: function () { - return !App.get('services.noConfigTypes').contains(this.get('content.serviceName')); - }.property('App.services.noConfigTypes','content.serviceName'), - - link: function() { - var stateName = (['summary','configs'].contains(App.router.get('currentState.name'))) - ? this.get('isConfigurable') ? App.router.get('currentState.name') : 'summary' - : 'summary'; - return "#/main/services/" + this.get('content.id') + "/" + stateName; - }.property('App.router.currentState.name', 'parentView.activeServiceId','isConfigurable'), - - goToConfigs: function () { - App.router.set('mainServiceItemController.routeToConfigs', true); - App.router.transitionTo('services.service.configs', this.get('content')); - App.router.set('mainServiceItemController.routeToConfigs', false); - }, - - refreshRestartRequiredMessage: function() { - var restarted, componentsCount, hostsCount, message, tHosts, tComponents; - restarted = this.get('content.restartRequiredHostsAndComponents'); - componentsCount = 0; - hostsCount = 0; - message = ""; - for (var host in restarted) { - hostsCount++; - componentsCount += restarted[host].length; - } - if (hostsCount > 1) { - tHosts = Em.I18n.t('common.hosts'); - } else { - tHosts = Em.I18n.t('common.host'); - } - if (componentsCount > 1) { - tComponents = Em.I18n.t('common.components'); - } else { - tComponents = Em.I18n.t('common.component'); - } - message += componentsCount + ' ' + tComponents + ' ' + Em.I18n.t('on') + ' ' + - hostsCount + ' ' + tHosts + ' ' + Em.I18n.t('services.service.config.restartService.needToRestartEnd'); - this.set('restartRequiredMessage', message); - }.observes('content.restartRequiredHostsAndComponents') - }) - -}); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/9a706402/ambari-web/test/views/main/menu_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/menu_test.js b/ambari-web/test/views/main/menu_test.js index ecc4516..658984c 100644 --- a/ambari-web/test/views/main/menu_test.js +++ b/ambari-web/test/views/main/menu_test.js @@ -24,7 +24,7 @@ describe('App.MainMenuView', function () { var view; beforeEach(function () { - view = App.MainMenuView.create() + view = App.MainSideMenuView.create() }); describe("#views", function () {