Feature #31353 » 0001-wip.patch
| app/views/layouts/base.html.erb | ||
|---|---|---|
| 60 | 60 | |
| 61 | 61 |
<div id="wrapper2"> |
| 62 | 62 |
<div id="wrapper3"> |
| 63 |
<div id="top-menu"> |
|
| 64 |
<div id="account"> |
|
| 65 |
<%= render_menu :account_menu -%> |
|
| 66 |
</div> |
|
| 67 |
<%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}".html_safe, :id => 'loggedas') if User.current.logged? %>
|
|
| 63 |
<nav id="top-menu"> |
|
| 64 |
<nav class="general-menu"> |
|
| 68 | 65 |
<%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%> |
| 69 |
</div> |
|
| 66 |
</nav> |
|
| 67 |
<nav class="profile-menu"> |
|
| 68 |
<ul class="nav-list"> |
|
| 69 |
<% if User.current.logged? || !Setting.login_required? %> |
|
| 70 |
<li class="nav-item"> |
|
| 71 |
<div id="quick-search"> |
|
| 72 |
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
|
| 73 |
<%= hidden_field_tag 'scope', default_search_project_scope, :id => nil %> |
|
| 74 |
<%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %> |
|
| 75 |
<label for='q'> |
|
| 76 |
<%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project, :scope => default_search_project_scope}, :accesskey => accesskey(:search) %>:
|
|
| 77 |
</label> |
|
| 78 |
<%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search), |
|
| 79 |
:data => {
|
|
| 80 |
:auto_complete => true, |
|
| 81 |
:issues_url => auto_complete_issues_path(:q => '') |
|
| 82 |
} %> |
|
| 83 |
<% end %> |
|
| 84 |
</div> |
|
| 85 |
</li> |
|
| 86 |
<li class="nav-item"> |
|
| 87 |
<%= render_project_jump_box %> |
|
| 88 |
</li> |
|
| 89 |
<% end %> |
|
| 90 |
<% if User.current.logged? %> |
|
| 91 |
<li class="nav-item avatar-menu drdn"> |
|
| 92 |
<a href="#" class="drdn-trigger" onclick="toggleNewObjectDropdown(); return false;"> |
|
| 93 |
<%= Setting.gravatar_enabled? ? avatar(User.current, :size => '22') : User.current.login.to_s %> |
|
| 94 |
<span class="icon-only icon-expended" ></span> |
|
| 95 |
</a> |
|
| 96 |
<div class="drdn-content"> |
|
| 97 |
<div class="drdn-items"> |
|
| 98 |
<ul id="loggedas"><li> |
|
| 99 |
<span class="name"><%= User.current.name %></span> |
|
| 100 |
<%= link_to("@" + User.current.login, user_url(User.current)) %>
|
|
| 101 |
</li></ul> |
|
| 102 |
<span class="divider"></span> |
|
| 103 |
<%= render_menu(:account_menu, nil, :class => 'account-menu') -%> |
|
| 104 |
</div> |
|
| 105 |
</div> |
|
| 106 |
</li> |
|
| 107 |
<% else %> |
|
| 108 |
<li class="nav-item"> |
|
| 109 |
<div id="account"> |
|
| 110 |
<%= render_menu :account_menu -%> |
|
| 111 |
</div> |
|
| 112 |
</li |
|
| 113 |
<% end %> |
|
| 114 |
</ul> |
|
| 115 |
</nav> |
|
| 116 |
</nav> |
|
| 70 | 117 | |
| 71 | 118 |
<div id="header"> |
| 72 | 119 | |
| 73 | 120 |
<a href="#" class="mobile-toggle-button js-flyout-menu-toggle-button"></a> |
| 74 | 121 | |
| 75 |
<% if User.current.logged? || !Setting.login_required? %> |
|
| 76 |
<div id="quick-search"> |
|
| 77 |
<%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
|
|
| 78 |
<%= hidden_field_tag 'scope', default_search_project_scope, :id => nil %> |
|
| 79 |
<%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %> |
|
| 80 |
<label for='q'> |
|
| 81 |
<%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project, :scope => default_search_project_scope}, :accesskey => accesskey(:search) %>:
|
|
| 82 |
</label> |
|
| 83 |
<%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search), |
|
| 84 |
:data => {
|
|
| 85 |
:auto_complete => true, |
|
| 86 |
:issues_url => auto_complete_issues_path(:q => '') |
|
| 87 |
} %> |
|
| 88 |
<% end %> |
|
| 89 |
<%= render_project_jump_box %> |
|
| 90 |
</div> |
|
| 91 |
<% end %> |
|
| 92 | ||
| 93 | 122 |
<h1><%= page_header_title %></h1> |
| 94 | 123 | |
| 95 | 124 |
<% if display_main_menu?(@project) %> |
| 96 |
<div id="main-menu" class="tabs">
|
|
| 125 |
<nav id="main-menu" class="tabs">
|
|
| 97 | 126 |
<%= render_main_menu(@project) %> |
| 98 | 127 |
<div class="tabs-buttons" style="display:none;"> |
| 99 | 128 |
<button class="tab-left" onclick="moveTabLeft(this); return false;"></button> |
| 100 | 129 |
<button class="tab-right" onclick="moveTabRight(this); return false;"></button> |
| 101 | 130 |
</div> |
| 102 |
</div>
|
|
| 131 |
</nav>
|
|
| 103 | 132 |
<% end %> |
| 104 | 133 |
</div> |
| 105 | 134 | |
| lib/redmine/menu_manager.rb | ||
|---|---|---|
| 110 | 110 |
menu_name.present? && Redmine::MenuManager.items(menu_name).children.present? |
| 111 | 111 |
end |
| 112 | 112 | |
| 113 |
def render_menu(menu, project=nil) |
|
| 113 |
def render_menu(menu, project=nil, options={})
|
|
| 114 | 114 |
links = [] |
| 115 | 115 |
menu_items_for(menu, project) do |node| |
| 116 | 116 |
links << render_menu_node(node, project) |
| 117 | 117 |
end |
| 118 |
links.empty? ? nil : content_tag('ul', links.join.html_safe)
|
|
| 118 |
default_options = {:class => 'nav-list'}
|
|
| 119 |
options = default_options.merge(options) |
|
| 120 |
links.empty? ? nil : content_tag('ul', links.join.html_safe, options)
|
|
| 119 | 121 |
end |
| 120 | 122 | |
| 121 | 123 |
def render_menu_node(node, project=nil) |
| ... | ... | |
| 124 | 126 |
else |
| 125 | 127 |
caption, url, selected = extract_node_details(node, project) |
| 126 | 128 |
return content_tag('li',
|
| 127 |
render_single_menu_node(node, caption, url, selected)) |
|
| 129 |
render_single_menu_node(node, caption, url, selected), :class => 'nav-item')
|
|
| 128 | 130 |
end |
| 129 | 131 |
end |
| 130 | 132 | |
| ... | ... | |
| 132 | 134 |
caption, url, selected = extract_node_details(node, project) |
| 133 | 135 | |
| 134 | 136 |
html = [].tap do |html| |
| 135 |
html << '<li>' |
|
| 137 |
html << '<li class="nav-item">'
|
|
| 136 | 138 |
# Parent |
| 137 | 139 |
html << render_single_menu_node(node, caption, url, selected) |
| 138 | 140 | |
| public/javascripts/application.js | ||
|---|---|---|
| 892 | 892 |
$('input[data-disables], input[data-enables], input[data-shows]').each(toggleDisabledOnChange);
|
| 893 | 893 |
} |
| 894 | 894 | |
| 895 |
function toggleNewObjectDropdown() {
|
|
| 896 |
var dropdown = $('#new-object + ul.menu-children');
|
|
| 895 |
function toggleNewObjectDropdown(element) {
|
|
| 896 |
var dropdown = $(element).next('.menu-children');
|
|
| 897 | 897 |
if(dropdown.hasClass('visible')){
|
| 898 | 898 |
dropdown.removeClass('visible');
|
| 899 | 899 |
}else{
|
| public/stylesheets/application.css | ||
|---|---|---|
| 15 | 15 |
#wrapper {background: white;overflow: hidden;}
|
| 16 | 16 |
#wrapper3 { display: flex; flex-direction: column; }
|
| 17 | 17 | |
| 18 |
#top-menu {background: #3E5B76; color: #fff; height:1.8em; font-size: 0.8em; padding: 2px 2px 0px 6px;}
|
|
| 19 |
#top-menu ul {margin: 0; padding: 0;}
|
|
| 20 |
#top-menu li {
|
|
| 21 |
float:left; |
|
| 22 |
list-style-type:none; |
|
| 23 |
margin: 0px 0px 0px 0px; |
|
| 24 |
padding: 0px 0px 0px 0px; |
|
| 25 |
white-space:nowrap; |
|
| 18 |
#top-menu *, *::before, *::after {
|
|
| 19 |
box-sizing: border-box; |
|
| 26 | 20 |
} |
| 27 |
#top-menu a {color: #fff; margin-right: 8px; font-weight: bold;}
|
|
| 28 |
#top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; }
|
|
| 29 | ||
| 30 |
#account {float:right;}
|
|
| 31 | ||
| 32 |
#header {min-height:5.3em;margin:0;background-color:#628DB6;color:#f8f8f8; padding: 4px 8px 20px 6px; position:relative;}
|
|
| 21 |
#top-menu {background: #3E5B76; padding: 2px 6px 0px 6px; display: flex;}
|
|
| 22 |
#top-menu > nav {
|
|
| 23 |
line-height: 24px; |
|
| 24 |
padding: 6px 0 6px 0; |
|
| 25 |
} |
|
| 26 |
#top-menu .general-menu {
|
|
| 27 |
align-items: stretch; |
|
| 28 |
flex: 1 1 auto; |
|
| 29 |
} |
|
| 30 |
#top-menu .profile-menu {
|
|
| 31 |
flex: 0 0 auto; |
|
| 32 |
border-top: 0; |
|
| 33 |
} |
|
| 34 |
#top-menu ul.nav-list > li.nav-item {
|
|
| 35 |
margin-right: 8px; |
|
| 36 |
} |
|
| 37 |
#top-menu ul.nav-list > li.nav-item:last-child {
|
|
| 38 |
margin-right: 0; |
|
| 39 |
} |
|
| 40 |
#top-menu ul.nav-list li.nav-item > a {
|
|
| 41 |
font-size: 0.9em; |
|
| 42 |
color: #fff; |
|
| 43 |
} |
|
| 44 |
#top-menu .profile-menu li.avatar-menu .drdn-content {
|
|
| 45 |
padding-top: 5px; |
|
| 46 |
padding-bottom: 5px; |
|
| 47 |
} |
|
| 48 |
#top-menu .profile-menu li.avatar-menu li {
|
|
| 49 |
flex-direction: column; |
|
| 50 |
} |
|
| 51 |
#top-menu .profile-menu li.avatar-menu li a {
|
|
| 52 |
width: 100%; |
|
| 53 |
display: block; |
|
| 54 |
padding: 4px; |
|
| 55 |
} |
|
| 56 |
#top-menu .profile-menu li.avatar-menu:hover > a {
|
|
| 57 |
text-decoration: none; |
|
| 58 |
} |
|
| 59 |
#top-menu .profile-menu li.avatar-menu img.gravatar {
|
|
| 60 |
border: 1px solid #dfdfdf; |
|
| 61 |
margin-right: 4px; |
|
| 62 |
} |
|
| 63 |
#top-menu .profile-menu li.avatar-menu:hover img.gravatar {
|
|
| 64 |
border: 1px solid #fff; |
|
| 65 |
} |
|
| 66 |
#top-menu .profile-menu li.avatar-menu ul {
|
|
| 67 |
padding: 0; |
|
| 68 |
min-width: 200px; |
|
| 69 |
} |
|
| 70 |
#loggedas span.name {
|
|
| 71 |
font-weight: 600; |
|
| 72 |
padding: 4px; |
|
| 73 |
} |
|
| 74 |
#loggedas span.login {
|
|
| 75 |
display: block; |
|
| 76 |
} |
|
| 77 |
#header {min-height:5.3em;margin:0;background-color:#628DB6;color:#f8f8f8; padding: 4px 8px 0 6px;}
|
|
| 33 | 78 |
#header a {color:#f8f8f8;}
|
| 34 | 79 |
#header h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
| 35 | 80 |
#header h1 .breadcrumbs { display:block; font-size: .5em; font-weight: normal; }
|
| 36 | 81 | |
| 37 |
#quick-search {float:right;}
|
|
| 38 |
#quick-search #q {width:130px; height:24px; box-sizing:border-box; vertical-align:middle; border:1px solid #ccc; border-radius:3px;}
|
|
| 82 |
#quick-search label, #quick-search label a {color: #fff;}
|
|
| 83 |
#quick-search #q {width:130px; height:24px;}
|
|
| 39 | 84 | |
| 40 |
#main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px; width: 100%;}
|
|
| 41 |
#main-menu ul {margin: 0; padding: 0; width: 100%; white-space: nowrap;}
|
|
| 42 |
#main-menu li {
|
|
| 43 |
float:none; |
|
| 44 |
list-style-type:none; |
|
| 45 |
margin: 0px 2px 0px 0px; |
|
| 46 |
padding: 0px 0px 0px 0px; |
|
| 47 |
white-space:nowrap; |
|
| 48 |
display:inline-block; |
|
| 49 |
} |
|
| 50 |
#main-menu li a {
|
|
| 51 |
display: block; |
|
| 85 |
#main-menu {margin-right: -500px; width: 100%;}
|
|
| 86 |
#main-menu li.nav-item a {
|
|
| 52 | 87 |
color: #fff; |
| 53 | 88 |
text-decoration: none; |
| 54 | 89 |
font-weight: bold; |
| 55 |
margin: 0;
|
|
| 90 |
display: block;
|
|
| 56 | 91 |
padding: 4px 10px 4px 10px; |
| 57 | 92 |
border-top-left-radius: 3px; |
| 58 | 93 |
border-top-right-radius: 3px; |
| ... | ... | |
| 149 | 184 | |
| 150 | 185 |
a#toggle-completed-versions {color:#999;}
|
| 151 | 186 | |
| 187 |
/***** Navigation *****/ |
|
| 188 |
nav ul.nav-list {
|
|
| 189 |
margin: 0; |
|
| 190 |
padding: 0; |
|
| 191 |
width: 100%; |
|
| 192 |
white-space: nowrap; |
|
| 193 |
display: flex; |
|
| 194 |
flex-direction: row; |
|
| 195 |
} |
|
| 196 |
nav ul.nav-list li.nav-item {
|
|
| 197 |
list-style-type: none; |
|
| 198 |
margin: 0; |
|
| 199 |
padding: 0; |
|
| 200 |
white-space: nowrap; |
|
| 201 |
} |
|
| 202 |
nav ul.nav-list li.nav-item > a {
|
|
| 203 |
padding: 4px; |
|
| 204 |
} |
|
| 152 | 205 |
/***** Dropdown *****/ |
| 153 | 206 |
.drdn {position:relative;}
|
| 154 | 207 |
.drdn-trigger {
|
| ... | ... | |
| 165 | 218 |
display:none; |
| 166 | 219 |
position:absolute; |
| 167 | 220 |
right:0px; |
| 168 |
top:25px;
|
|
| 221 |
top:28px;
|
|
| 169 | 222 |
min-width:100px; |
| 170 | 223 |
background-color:#fff; |
| 171 | 224 |
border:1px solid #ccc; |
| ... | ... | |
| 173 | 226 |
color:#555; |
| 174 | 227 |
z-index:99; |
| 175 | 228 |
} |
| 229 |
.drdn-content .divider {
|
|
| 230 |
height: 1px; |
|
| 231 |
background-color: #ccc; |
|
| 232 |
padding: 0; |
|
| 233 |
margin: 0; |
|
| 234 |
border: 0; |
|
| 235 |
} |
|
| 176 | 236 |
.drdn.expanded .drdn-content {display:block;}
|
| 177 | 237 | |
| 178 | 238 |
.drdn-content .quick-search {margin:8px;}
|
| ... | ... | |
| 207 | 267 |
border: none; |
| 208 | 268 |
} |
| 209 | 269 |
.drdn-items>span {color:#999;}
|
| 210 | ||
| 211 | 270 |
.contextual .drdn-content {top:18px;}
|
| 212 | 271 |
.contextual .drdn-items {padding:2px;}
|
| 213 | 272 |
.contextual .drdn-items>a:hover {color:#2A5685; border:1px solid #628db6; background-color:#eef5fd; border-radius:3px;}
|
| ... | ... | |
| 216 | 275 |
#project-jump .drdn-trigger {
|
| 217 | 276 |
width:100%; |
| 218 | 277 |
height:24px; |
| 278 |
line-height: 16px; |
|
| 219 | 279 |
display:inline-block; |
| 220 | 280 |
padding:3px 18px 3px 6px; |
| 221 | 281 |
border-radius:3px; |
| 222 | 282 |
border:1px solid #ccc; |
| 223 |
margin:0 !important; |
|
| 224 | 283 |
vertical-align:middle; |
| 225 | 284 |
color:#555; |
| 226 | 285 |
background:#fff url(../images/arrow_down.png) no-repeat 97% 50%; |
| 227 | 286 |
} |
| 228 | 287 |
#project-jump .drdn.expanded .drdn-trigger {background-image:url(../images/arrow_up.png);}
|
| 229 | 288 |
#project-jump .drdn-content {width:280px;}
|
| 230 |
#project-jump .drdn-items>* {color:#555 !important;}
|
|
| 231 |
#project-jump .drdn-items>a:hover {background-color:#759FCF; color:#fff !important;}
|
|
| 289 |
#project-jump .drdn-items>*, .avatar-menu .drdn-items * {color:#555 !important;}
|
|
| 290 |
#project-jump .drdn-items>a:hover, .avatar-menu .drdn-items a:hover {background-color:#759FCF; color:#fff !important; text-decoration: none;}
|
|
| 232 | 291 | |
| 233 | 292 |
/***** Tables *****/ |
| 234 | 293 |
table.list, .table-list { border: 1px solid #e4e4e4; width: 100%; margin-bottom: 4px; border-radius: 3px; border-spacing: 0; overflow: hidden;}
|