mirror of
https://github.com/meineerde/redmine.git
synced 2025-12-27 02:41:15 +00:00
Replaces project jump select with custom dropdown (#23310).
git-svn-id: http://svn.redmine.org/redmine/trunk@15994 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
bac3ac738a
commit
62823442d3
@ -45,6 +45,13 @@ class ProjectsController < ApplicationController
|
||||
end
|
||||
@projects = scope.to_a
|
||||
}
|
||||
format.js {
|
||||
if params[:q].present?
|
||||
@projects = Project.visible.like(params[:q]).to_a
|
||||
else
|
||||
@projects = User.current.projects.to_a
|
||||
end
|
||||
}
|
||||
format.api {
|
||||
@offset, @limit = api_offset_and_limit
|
||||
@project_count = scope.count
|
||||
|
||||
@ -330,22 +330,40 @@ module ApplicationHelper
|
||||
content_tag 'p', l(:label_no_data), :class => "nodata"
|
||||
end
|
||||
end
|
||||
|
||||
# Returns an array of projects that are displayed in the quick-jump box
|
||||
def projects_for_jump_box(user=User.current)
|
||||
if user.logged?
|
||||
user.projects.active.select(:id, :name, :identifier, :lft, :rgt).to_a
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def render_projects_for_jump_box(projects, selected=nil)
|
||||
s = ''.html_safe
|
||||
project_tree(projects) do |project, level|
|
||||
padding = level * 16
|
||||
text = content_tag('span', project.name, :style => "padding-left:#{padding}px;")
|
||||
s << link_to(text, project_path(project, :jump => current_menu_item), :title => project.name, :class => (project == selected ? 'selected' : nil))
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
# Renders the project quick-jump box
|
||||
def render_project_jump_box
|
||||
return unless User.current.logged?
|
||||
projects = User.current.projects.active.select(:id, :name, :identifier, :lft, :rgt).to_a
|
||||
projects = projects_for_jump_box(User.current)
|
||||
if projects.any?
|
||||
options =
|
||||
("<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
|
||||
'<option value="" disabled="disabled">---</option>').html_safe
|
||||
text = @project.try(:name) || l(:label_jump_to_a_project)
|
||||
trigger = content_tag('span', text, :class => 'drdn-trigger')
|
||||
q = text_field_tag('q', '', :id => 'projects-quick-search', :class => 'autocomplete', :data => {:automcomplete_url => projects_path(:format => 'js')})
|
||||
content = content_tag('div',
|
||||
content_tag('div', q, :class => 'quick-search') +
|
||||
content_tag('div', render_projects_for_jump_box(projects, @project), :class => 'drdn-items selection'),
|
||||
:class => 'drdn-content'
|
||||
)
|
||||
|
||||
options << project_tree_options_for_select(projects, :selected => @project) do |p|
|
||||
{ :value => project_path(:id => p, :jump => current_menu_item) }
|
||||
end
|
||||
|
||||
content_tag( :span, nil, :class => 'jump-box-arrow') +
|
||||
select_tag('project_quick_jump_box', options, :onchange => 'if (this.value != \'\') { window.location = this.value; }')
|
||||
content_tag('span', trigger + content, :id => "project-jump", :class => "drdn")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
2
app/views/projects/index.js.erb
Normal file
2
app/views/projects/index.js.erb
Normal file
@ -0,0 +1,2 @@
|
||||
<% s = @projects.any? ? render_projects_for_jump_box(@projects) : content_tag('span', l(:label_no_data)) %>
|
||||
$('#project-jump .drdn-items').html('<%= escape_javascript s %>');
|
||||
@ -1,11 +1,13 @@
|
||||
<div class="contextual">
|
||||
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
|
||||
<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %>
|
||||
<% end %>
|
||||
<% if @editable && @content.current_version? %>
|
||||
<%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
|
||||
<% end %>
|
||||
<%= watcher_link(@page, User.current) %>
|
||||
<span class="drdn">
|
||||
<span class="drdn-trigger">Hello</span>
|
||||
<div class="drdn-content drdn-items">
|
||||
<% if @editable %>
|
||||
<% if @content.current_version? %>
|
||||
<%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
|
||||
<%= watcher_link(@page, User.current) %>
|
||||
<%= link_to_if_authorized(l(:button_lock), {:action => 'protect', :id => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.protected? %>
|
||||
<%= link_to_if_authorized(l(:button_unlock), {:action => 'protect', :id => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? %>
|
||||
<%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :id => @page.title}, :class => 'icon icon-move') %>
|
||||
@ -15,6 +17,11 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
<%= link_to_if_authorized(l(:label_history), {:action => 'history', :id => @page.title}, :class => 'icon icon-history') %>
|
||||
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
|
||||
<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %>
|
||||
<% end %>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<%= wiki_page_breadcrumb(@page) %>
|
||||
|
||||
@ -572,6 +572,69 @@ function observeSearchfield(fieldId, targetId, url) {
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$(".drdn .autocomplete").val('');
|
||||
|
||||
$(".drdn-trigger").click(function(e){
|
||||
var drdn = $(this).closest(".drdn");
|
||||
if (drdn.hasClass("expanded")) {
|
||||
drdn.removeClass("expanded");
|
||||
} else {
|
||||
$(".drdn").removeClass("expanded");
|
||||
drdn.addClass("expanded");
|
||||
if (!isMobile()) {
|
||||
drdn.find(".autocomplete").focus();
|
||||
}
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
$(document).click(function(e){
|
||||
if ($(e.target).closest(".drdn").length < 1) {
|
||||
$(".drdn.expanded").removeClass("expanded");
|
||||
}
|
||||
});
|
||||
|
||||
observeSearchfield('projects-quick-search', null, $('#projects-quick-search').data('automcomplete-url'));
|
||||
|
||||
$(".drdn-content").keydown(function(event){
|
||||
var items = $(this).find(".drdn-items");
|
||||
var focused = items.find("a:focus");
|
||||
switch (event.which) {
|
||||
case 40: //down
|
||||
if (focused.length > 0) {
|
||||
focused.nextAll("a").first().focus();;
|
||||
} else {
|
||||
items.find("a").first().focus();;
|
||||
}
|
||||
event.preventDefault();
|
||||
break;
|
||||
case 38: //up
|
||||
if (focused.length > 0) {
|
||||
var prev = focused.prevAll("a");
|
||||
if (prev.length > 0) {
|
||||
prev.first().focus();
|
||||
} else {
|
||||
$(this).find(".autocomplete").focus();
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
case 35: //end
|
||||
if (focused.length > 0) {
|
||||
focused.nextAll("a").last().focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
case 36: //home
|
||||
if (focused.length > 0) {
|
||||
focused.prevAll("a").last().focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function beforeShowDatePicker(input, inst) {
|
||||
var default_date = null;
|
||||
switch ($(input).attr("id")) {
|
||||
|
||||
@ -30,7 +30,9 @@ pre, code {font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace;}
|
||||
#header a {color:#f8f8f8;}
|
||||
#header h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
#header h1 .breadcrumbs { display:block; font-size: .5em; font-weight: normal; }
|
||||
|
||||
#quick-search {float:right;}
|
||||
#quick-search #q {width:130px; height:24px; box-sizing:border-box; vertical-align:middle; border:1px solid #ccc; border-radius:3px;}
|
||||
|
||||
#main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px; width: 100%;}
|
||||
#main-menu ul {margin: 0; padding: 0; width: 100%; white-space: nowrap;}
|
||||
@ -140,6 +142,79 @@ a#toggle-completed-versions {color:#999;}
|
||||
|
||||
a.toggle-checkboxes { margin-left: 5px; padding-left: 12px; background: url(../images/toggle_check.png) no-repeat 0% 50%; }
|
||||
|
||||
/***** Dropdown *****/
|
||||
.drdn {position:relative;}
|
||||
.drdn-trigger {
|
||||
width:100%;
|
||||
height:24px;
|
||||
box-sizing:border-box;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap;
|
||||
padding:3px 18px 3px 6px;
|
||||
background:#fff url(../images/sort_desc.png) no-repeat 97% 50%;
|
||||
cursor:pointer;
|
||||
user-select:none;
|
||||
-moz-user-select:none;
|
||||
-webkit-user-select:none;
|
||||
}
|
||||
.drdn-content {
|
||||
display:none;
|
||||
position:absolute;
|
||||
right:0px;
|
||||
top:25px;
|
||||
min-width:100px;
|
||||
background-color:#fff;
|
||||
border:1px solid #ccc;
|
||||
border-radius:4px;
|
||||
color:#555;
|
||||
z-index:99;
|
||||
}
|
||||
.drdn.expanded .drdn-trigger {background-image:url(../images/sort_asc.png);}
|
||||
.drdn.expanded .drdn-content {display:block;}
|
||||
|
||||
.drdn-content .quick-search {margin:8px;}
|
||||
.drdn-content .autocomplete {box-sizing: border-box; width:100% !important; height:28px;}
|
||||
.drdn-content .autocomplete:focus {border-color:#5ad;}
|
||||
.drdn-items {max-height:400px; overflow:auto;}
|
||||
.quick-search + .drdn-items {border-top:1px solid #ccc;}
|
||||
.drdn-items>* {
|
||||
display:block;
|
||||
border:1px solid #fff;
|
||||
color:#555 !important;
|
||||
overflow:hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space:nowrap;
|
||||
padding:4px 8px;
|
||||
}
|
||||
.drdn-items>a:hover {text-decoration:none; background-color:#759FCF; color:#fff !important;}
|
||||
.drdn-items>*:focus {border:1px dotted #bbb;}
|
||||
|
||||
.drdn-items.selection>*:before {
|
||||
content:' ';
|
||||
display:inline-block;
|
||||
line-height:1em;
|
||||
width:1em;
|
||||
height:1em;
|
||||
margin-right:4px;
|
||||
font-weight:bold;
|
||||
}
|
||||
.drdn-items.selection>*.selected:before {
|
||||
content:"\2713 ";
|
||||
}
|
||||
.drdn-items>span {color:#999;}
|
||||
|
||||
#project-jump.drdn {width:200px;display:inline-block;}
|
||||
#project-jump .drdn-trigger {
|
||||
display:inline-block;
|
||||
border-radius:3px;
|
||||
border:1px solid #ccc;
|
||||
margin:0 !important;
|
||||
vertical-align:middle;
|
||||
color:#555;
|
||||
}
|
||||
#project-jump .drdn-content {width:280px;}
|
||||
|
||||
/***** Tables *****/
|
||||
table.list, .table-list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
|
||||
table.list th, .table-list-header { background-color:#EEEEEE; padding: 4px; white-space:nowrap; font-weight:bold; }
|
||||
|
||||
@ -125,18 +125,40 @@
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
/* this represents the dropdown arrow to left of the mobile project menu */
|
||||
#header .jump-box-arrow:before {
|
||||
/* styles for combobox within quick-search (#project_quick_jump_box) */
|
||||
#project-jump.drdn {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 2em;
|
||||
height: 64px;
|
||||
padding: 5px;
|
||||
padding-right: 72px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
#project-jump .drdn-trigger {
|
||||
font-size:1.5em;
|
||||
font-weight:bold;
|
||||
display:block;
|
||||
width:100%;
|
||||
color:#fff;
|
||||
padding-left:24px;
|
||||
background:transparent;
|
||||
height:50px;
|
||||
line-height:40px;
|
||||
border:0;
|
||||
}
|
||||
#project-jump .drdn-trigger:before {
|
||||
/* set a font-size in order to achive same result in different themes */
|
||||
font-family: Verdana, sans-serif;
|
||||
font-size: 2em;
|
||||
line-height: 64px;
|
||||
font-size: 1.5em;
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
||||
width: 2em;
|
||||
padding: 0 .5em;
|
||||
padding: 0 8px;
|
||||
/* achieve dropdwon arrow by scaling a caret character */
|
||||
content: '^';
|
||||
-webkit-transform: scale(1,-.8);
|
||||
@ -147,39 +169,27 @@
|
||||
|
||||
opacity: .6;
|
||||
}
|
||||
#project-jump.expanded .drdn-trigger:before {
|
||||
-webkit-transform: scale(1,.8);
|
||||
-ms-transform: scale(1,.8);
|
||||
transform: scale(1,.8);
|
||||
padding-top:8px;
|
||||
}
|
||||
|
||||
/* styles for combobox within quick-search (#project_quick_jump_box) */
|
||||
#header #quick-search select {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
line-height: 1.2;
|
||||
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 0;
|
||||
|
||||
float: left;
|
||||
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 2em;
|
||||
height: 35px;
|
||||
padding: 5px;
|
||||
padding-right: 72px;
|
||||
padding-left: 50px;
|
||||
|
||||
text-indent: .01px;
|
||||
|
||||
color: inherit;
|
||||
border: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
/* hide default browser arrow */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
#project-jump .drdn-content {
|
||||
position:absolute;
|
||||
left:0px;
|
||||
top:64px;
|
||||
width:100%;
|
||||
font-size:15px;
|
||||
font-weight:normal;
|
||||
}
|
||||
#project-jump .drdn-content .autocomplete {
|
||||
height:40px;
|
||||
font-size:20px;
|
||||
}
|
||||
#project-jump .drdn-content a {
|
||||
padding:8px;
|
||||
}
|
||||
|
||||
#header #quick-search form {
|
||||
|
||||
@ -52,6 +52,12 @@ class ProjectsControllerTest < Redmine::ControllerTest
|
||||
assert_select 'feed>entry', :count => Project.visible(User.current).count
|
||||
end
|
||||
|
||||
def test_index_js
|
||||
xhr :get, :index, :format => 'js', :q => 'coo'
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
test "#index by non-admin user with view_time_entries permission should show overall spent time link" do
|
||||
@request.session[:user_id] = 3
|
||||
get :index
|
||||
|
||||
@ -138,8 +138,8 @@ class WelcomeControllerTest < Redmine::ControllerTest
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_select "#header select" do
|
||||
assert_select "option", :text => 'Foo & Bar'
|
||||
assert_select "#header #project-jump" do
|
||||
assert_select "a", :text => 'Foo & Bar'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user