diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index b3142feb494..85fb8e785ac 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -11,6 +11,7 @@ //= require jquery.tagify //= require jquery.cookie //= require jquery.endless-scroll +//= require jquery.highlight //= require bootstrap-modal //= require modernizr //= require chosen diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index a0f522c1e41..9609733c93c 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -947,3 +947,7 @@ p.time { padding: 4px; margin: 2px; } + +.highlight_word { + background:#EEDC94; +} diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb new file mode 100644 index 00000000000..8a452fe0914 --- /dev/null +++ b/app/controllers/search_controller.rb @@ -0,0 +1,12 @@ +class SearchController < ApplicationController + def show + query = params[:search] + if query.blank? + @projects = [] + @merge_requests = [] + else + @projects = Project.search(query).limit(10) + @merge_requests = MergeRequest.search(query).limit(10) + end + end +end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index da74baa208a..8f5c2f27f39 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -37,6 +37,10 @@ class MergeRequest < ActiveRecord::Base scope :closed, where(:closed => true) scope :assigned, lambda { |u| where(:assignee_id => u.id)} + def self.search query + where("title like :query", :query => "%#{query}%") + end + def validate_branches if target_branch == source_branch errors.add :base, "You can not use same branch for source and target branches" diff --git a/app/models/project.rb b/app/models/project.rb index 08a12d7d8b5..9391ba9cc3a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -54,6 +54,10 @@ class Project < ActiveRecord::Base UsersProject.access_roles end + def self.search query + where("name like :query or code like :query or path like :query", :query => "%#{query}%") + end + def to_param code end diff --git a/app/views/dashboard/_projects_feed.html.haml b/app/views/dashboard/_projects_feed.html.haml index c1abe556a88..5f146d49817 100644 --- a/app/views/dashboard/_projects_feed.html.haml +++ b/app/views/dashboard/_projects_feed.html.haml @@ -1,4 +1,4 @@ -- @active_projects.first(5).each do |project| +- projects.first(5).each do |project| .wll = link_to project do %h4 diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/index.html.haml index d3946f5b327..5dde57e8a22 100644 --- a/app/views/dashboard/index.html.haml +++ b/app/views/dashboard/index.html.haml @@ -20,7 +20,7 @@ .row .dashboard_block .row - .span10= render "dashboard/projects_feed" + .span10= render "dashboard/projects_feed", :projects => @active_projects .span4.right - if current_user.can_create_project? .alert-message.block-message.warning diff --git a/app/views/layouts/_app_menu.html.haml b/app/views/layouts/_app_menu.html.haml index 27d9b458bc9..60ff4854843 100644 --- a/app/views/layouts/_app_menu.html.haml +++ b/app/views/layouts/_app_menu.html.haml @@ -1,6 +1,7 @@ %nav.main_menu = render "layouts/const_menu_links" = link_to "Projects", projects_path, :class => "#{"current" if current_page?(projects_path)}" + = link_to "Search", search_path, :class => "#{"current" if current_page?(search_path)}" = link_to "Issues", dashboard_issues_path, :class => "#{"current" if current_page?(dashboard_issues_path)}", :id => "issues_slide" = link_to "Requests", dashboard_merge_requests_path, :class => "#{"current" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide" = link_to "Help", help_path, :class => "#{"current" if controller.controller_name == "help"}" diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 221bca559a9..88429a4857e 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -7,7 +7,9 @@ %h1 GITLAB %h1.project_name= title - .search= text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" + .search + = form_tag search_path, :method => :get do |f| + = text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" - if current_user.is_admin? = link_to admin_projects_path, :class => "admin_link", :title => "Admin area" do = image_tag "admin.PNG", :width => 16 diff --git a/app/views/search/_result.html.haml b/app/views/search/_result.html.haml new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/app/views/search/_result.html.haml @@ -0,0 +1 @@ + diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml new file mode 100644 index 00000000000..a524b7b4013 --- /dev/null +++ b/app/views/search/show.html.haml @@ -0,0 +1,41 @@ += form_tag search_path, :method => :get do |f| + .padded + = label_tag :search, "Looking for" + .input + = text_field_tag :search, params[:search],:placeholder => "issue 143", :class => "xxlarge" + = submit_tag 'Search', :class => "btn primary" +- if params[:search].present? + %br + %h3 Search results + %hr + .search_results + - if @projects.empty? && @merge_requests.empty? + %h3 + %small Nothing here + - else + - if @projects.any? + - @projects.each do |project| + = link_to project do + %h4 + %span.ico.project + = project.name + %small + last activity at + = project.last_activity_date.stamp("Aug 25, 2011") + - if @merge_requests.any? + - @merge_requests.each do |merge_request| + = link_to [merge_request.project, merge_request] do + %h5 + Merge Request # + = merge_request.id + – + = truncate merge_request.title, :length => 50 + %small + updated at + = merge_request.updated_at.stamp("Aug 25, 2011") + %strong + %span.label= merge_request.project.name + :javascript + $(function() { + $(".search_results").highlight("#{params[:search]}"); + }) diff --git a/config/routes.rb b/config/routes.rb index 4cc3a4ff77b..be559282ae6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Gitlab::Application.routes.draw do - + get 'search' => "search#show" # Optionally, enable Resque here require 'resque/server' diff --git a/vendor/assets/javascripts/jquery.highlight.js b/vendor/assets/javascripts/jquery.highlight.js new file mode 100644 index 00000000000..7a67cf99844 --- /dev/null +++ b/vendor/assets/javascripts/jquery.highlight.js @@ -0,0 +1,53 @@ +/* + +highlight v3 + +Highlights arbitrary terms. + + + +MIT license. + +Johann Burkard + + + +*/ + +jQuery.fn.highlight = function(pat) { + function innerHighlight(node, pat) { + var skip = 0; + if (node.nodeType == 3) { + var pos = node.data.toUpperCase().indexOf(pat); + if (pos >= 0) { + var spannode = document.createElement('span'); + spannode.className = 'highlight_word'; + var middlebit = node.splitText(pos); + var endbit = middlebit.splitText(pat.length); + var middleclone = middlebit.cloneNode(true); + spannode.appendChild(middleclone); + middlebit.parentNode.replaceChild(spannode, middlebit); + skip = 1; + } + } + else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) { + for (var i = 0; i < node.childNodes.length; ++i) { + i += innerHighlight(node.childNodes[i], pat); + } + } + return skip; + } + return this.each(function() { + innerHighlight(this, pat.toUpperCase()); + }); +}; + +jQuery.fn.removeHighlight = function() { + return this.find("span.highlight").each(function() { + this.parentNode.firstChild.nodeName; + with (this.parentNode) { + replaceChild(this.firstChild, this); + normalize(); + } + }).end(); +};