Commit ac9b5bc0 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch '7-2-dev' into 'master'

Explore area

Fixes #1426

See merge request !987
parents 326fb383 001096ca
.explore-title {
text-align: center;
h3 {
font-weight: normal;
font-size: 30px;
}
}
class Explore::GroupsController < ApplicationController
skip_before_filter :authenticate_user!,
:reject_blocked, :set_current_user_for_observers,
:add_abilities
layout "explore"
def index
@groups = GroupsFinder.new.execute(current_user)
@groups = @groups.search(params[:search]) if params[:search].present?
@groups = @groups.sort(@sort = params[:sort])
@groups = @groups.page(params[:page]).per(20)
end
end
class Public::ProjectsController < ApplicationController class Explore::ProjectsController < ApplicationController
skip_before_filter :authenticate_user!, skip_before_filter :authenticate_user!,
:reject_blocked, :set_current_user_for_observers, :reject_blocked,
:add_abilities :add_abilities
layout 'public' layout 'explore'
def index def index
@projects = Project.publicish(current_user) @projects = ProjectsFinder.new.execute(current_user)
@projects = @projects.search(params[:search]) if params[:search].present? @projects = @projects.search(params[:search]) if params[:search].present?
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace).page(params[:page]).per(20) @projects = @projects.includes(:namespace).page(params[:page]).per(20)
end end
def trending
@trending_projects = TrendingProjectsFinder.new.execute(current_user)
@trending_projects = @trending_projects.page(params[:page]).per(10)
end
end end
class TrendingProjectsFinder
def execute(current_user, start_date = nil)
start_date ||= Date.today - 1.month
projects = projects_for(current_user)
# Determine trending projects based on comments count
# for period of time - ex. month
projects.joins(:notes).where('notes.created_at > ?', start_date).
select("projects.*, count(notes.id) as ncount").
group("projects.id").order("ncount DESC")
end
private
def projects_for(current_user)
ProjectsFinder.new.execute(current_user)
end
end
...@@ -73,4 +73,20 @@ class Group < Namespace ...@@ -73,4 +73,20 @@ class Group < Namespace
def public_profile? def public_profile?
projects.public_only.any? projects.public_only.any?
end end
class << self
def search(query)
where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%")
end
def sort(method)
case method.to_s
when "newest" then reorder("namespaces.created_at DESC")
when "oldest" then reorder("namespaces.created_at ASC")
when "recently_updated" then reorder("namespaces.updated_at DESC")
when "last_updated" then reorder("namespaces.updated_at ASC")
else reorder("namespaces.path, namespaces.name ASC")
end
end
end
end end
...@@ -46,5 +46,5 @@ ...@@ -46,5 +46,5 @@
%br %br
Public projects are an easy way to allow everyone to have read-only access. Public projects are an easy way to allow everyone to have read-only access.
.link_holder .link_holder
= link_to public_projects_path, class: "btn btn-new" do = link_to explore_projects_path, class: "btn btn-new" do
Browse public projects » Browse public projects »
.clearfix
.pull-left
= form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f|
.form-group
= search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input input-mn-300", id: "groups_search"
.form-group
= submit_tag 'Search', class: "btn btn-primary wide"
.pull-right
.dropdown.inline
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%span.light sort:
- if @sort.present?
= @sort.humanize
- else
Name
%b.caret
%ul.dropdown-menu
%li
= link_to explore_groups_path(sort: nil) do
Name
= link_to explore_groups_path(sort: 'newest') do
Newest
= link_to explore_groups_path(sort: 'oldest') do
Oldest
= link_to explore_groups_path(sort: 'recently_updated') do
Recently updated
= link_to explore_groups_path(sort: 'last_updated') do
Last updated
%hr
%ul.bordered-list
- @groups.each do |group|
%li
.clearfix
%h4
= link_to group_path(id: group.path) do
%i.icon-group
= group.name
.clearfix
%p
= truncate group.description, length: 150
.clearfix
%p.light
#{pluralize(group.members.size, 'member')}, #{pluralize(group.projects.count, 'project')}
- unless @groups.present?
.nothing-here-block No public groups
= paginate @groups, theme: "gitlab"
%li
%h4.project-title
.project-access-icon
= visibility_level_icon(project.visibility_level)
= link_to project.name_with_namespace, project
- if project.description.present?
%p.project-description.str-truncated
= project.description
.repo-info
- unless project.empty_repo?
= link_to pluralize(project.repository.round_commit_count, 'commit'), project_commits_path(project, project.default_branch)
&middot;
= link_to pluralize(project.repository.branch_names.count, 'branch'), project_branches_path(project)
&middot;
= link_to pluralize(project.repository.tag_names.count, 'tag'), project_tags_path(project)
- else
%i.icon-warning-sign
Empty repository
%h3.page-title
Projects (#{@projects.total_count})
.light
You can browse public projects in read-only mode until signed in.
%hr
.clearfix .clearfix
.pull-left .pull-left
= form_tag public_projects_path, method: :get, class: 'form-inline form-tiny' do |f| = form_tag explore_projects_path, method: :get, class: 'form-inline form-tiny' do |f|
.form-group .form-group
= search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input input-mn-300", id: "projects_search" = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input input-mn-300", id: "projects_search"
.form-group .form-group
...@@ -22,46 +17,21 @@ ...@@ -22,46 +17,21 @@
%b.caret %b.caret
%ul.dropdown-menu %ul.dropdown-menu
%li %li
= link_to public_projects_path(sort: nil) do = link_to explore_projects_path(sort: nil) do
Name Name
= link_to public_projects_path(sort: 'newest') do = link_to explore_projects_path(sort: 'newest') do
Newest Newest
= link_to public_projects_path(sort: 'oldest') do = link_to explore_projects_path(sort: 'oldest') do
Oldest Oldest
= link_to public_projects_path(sort: 'recently_updated') do = link_to explore_projects_path(sort: 'recently_updated') do
Recently updated Recently updated
= link_to public_projects_path(sort: 'last_updated') do = link_to explore_projects_path(sort: 'last_updated') do
Last updated Last updated
%hr %hr
.public-projects .public-projects
%ul.bordered-list.top-list %ul.bordered-list.top-list
- @projects.each do |project| = render @projects
%li
%h4
= link_to project_path(project) do
= project.name_with_namespace
- if project.internal?
%small.access-icon
= internal_icon
Internal
.pull-right.hidden-sm.hidden-xs
%pre.public-clone git clone #{project.http_url_to_repo}
- if project.description.present?
%p
= project.description
.repo-info
- unless project.empty_repo?
= link_to pluralize(project.repository.round_commit_count, 'commit'), project_commits_path(project, project.default_branch)
&middot;
= link_to pluralize(project.repository.branch_names.count, 'branch'), project_branches_path(project)
&middot;
= link_to pluralize(project.repository.tag_names.count, 'tag'), project_tags_path(project)
- else
%i.icon-warning-sign
Empty repository
- unless @projects.present? - unless @projects.present?
.nothing-here-block No public projects .nothing-here-block No public projects
......
.explore-trending-block
%p.lead
%i.icon-comments-alt
See most discussed projects for last month
%hr
.public-projects
%ul.bordered-list
= render @trending_projects
.center
= link_to 'Show all projects', explore_projects_path, class: 'btn btn-primary'
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
'data-original-title' => 'Help' do 'data-original-title' => 'Help' do
%i.icon-question-sign %i.icon-question-sign
%li %li
= link_to public_root_path, title: "Public area", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do = link_to explore_root_path, title: "Explore", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do
%i.icon-globe %i.icon-globe
%li %li
= link_to user_snippets_path(current_user), title: "My snippets", class: 'has_bottom_tooltip', 'data-original-title' => 'My snippets' do = link_to user_snippets_path(current_user), title: "My snippets", class: 'has_bottom_tooltip', 'data-original-title' => 'My snippets' do
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
.container .container
%div.app_logo %div.app_logo
%span.separator %span.separator
= link_to public_root_path, class: "home" do = link_to explore_root_path, class: "home" do
%h1 GITLAB %h1 GITLAB
%span.separator %span.separator
%h1.title= title %h1.title= title
......
...@@ -33,6 +33,6 @@ ...@@ -33,6 +33,6 @@
%hr %hr
.container .container
.footer-links .footer-links
= link_to "Explore public projects", public_projects_path = link_to "Explore", explore_root_path
= link_to "Documentation", "http://doc.gitlab.com/" = link_to "Documentation", "http://doc.gitlab.com/"
= link_to "About GitLab", "https://about.gitlab.com/" = link_to "About GitLab", "https://about.gitlab.com/"
- page_title = 'Explore'
!!! 5
%html{ lang: "en"}
= render "layouts/head", title: page_title
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
= render "layouts/broadcast"
- if current_user
= render "layouts/head_panel", title: page_title
- else
= render "layouts/public_head_panel", title: page_title
.container.navless-container
.content
.explore-title
%h3
Explore GitLab
%p.lead
Discover projects and groups. Share your projects with others
%ul.nav.nav-tabs
= nav_link(path: 'projects#trending') do
= link_to 'Trending Projects', explore_root_path
= nav_link(path: 'projects#index') do
= link_to 'All Projects', explore_projects_path
= nav_link(controller: :groups) do
= link_to 'All Groups', explore_groups_path
= yield
!!! 5
%html{ lang: "en"}
= render "layouts/head", title: "Public Projects"
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
= render "layouts/broadcast"
- if current_user
= render "layouts/head_panel", title: "Public Projects"
- else
= render "layouts/public_head_panel", title: "Public Projects"
.container.navless-container
.content= yield
...@@ -47,13 +47,23 @@ Gitlab::Application.routes.draw do ...@@ -47,13 +47,23 @@ Gitlab::Application.routes.draw do
get "/s/:username" => "snippets#user_index", as: :user_snippets, constraints: { username: /.*/ } get "/s/:username" => "snippets#user_index", as: :user_snippets, constraints: { username: /.*/ }
# #
# Public namespace # Explroe area
# #
namespace :public do namespace :explore do
resources :projects, only: [:index] resources :projects, only: [:index] do
root to: "projects#index" collection do
get :trending
end
end
resources :groups, only: [:index]
root to: "projects#trending"
end end
# Compatibility with old routing
get 'public' => "explore/projects#index"
get 'public/projects' => "explore/projects#index"
# #
# Attachments serving # Attachments serving
# #
......
@public @public
Feature: Public Projects Feature Feature: Explore Projects Feature
Background: Background:
Given public project "Community" Given public project "Community"
And internal project "Internal" And internal project "Internal"
......
@public @public
Feature: Public Projects Feature Feature: Explore Groups Feature
Background: Background:
Given group "TestGroup" has private project "Enterprise" Given group "TestGroup" has private project "Enterprise"
...@@ -117,3 +117,35 @@ Feature: Public Projects Feature ...@@ -117,3 +117,35 @@ Feature: Public Projects Feature
And I visit group "TestGroup" members page And I visit group "TestGroup" members page
Then I should see group member "John Doe" Then I should see group member "John Doe"
And I should not see member roles And I should not see member roles
Scenario: I should see group with public project in public groups area
Given group "TestGroup" has public project "Community"
When I visit the public groups area
Then I should see group "TestGroup"
Scenario: I should not see group with internal project in public groups area
Given group "TestGroup" has internal project "Internal"
When I visit the public groups area
Then I should not see group "TestGroup"
Scenario: I should not see group with private project in public groups area
When I visit the public groups area
Then I should not see group "TestGroup"
Scenario: I should see group with public project in public groups area as user
Given group "TestGroup" has public project "Community"
When I sign in as a user
And I visit the public groups area
Then I should see group "TestGroup"
Scenario: I should see group with internal project in public groups area as user
Given group "TestGroup" has internal project "Internal"
When I sign in as a user
And I visit the public groups area
Then I should see group "TestGroup"
Scenario: I should not see group with private project in public groups area as user
When I sign in as a user
And I visit the public groups area
Then I should not see group "TestGroup"
Feature: Public Projects
Background:
Given I sign in as a user
Scenario: I should see the list of public projects
When I visit the public projects area
Then I should see the list of public projects
class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps class Spinach::Features::ExploreGroupsFeature < Spinach::FeatureSteps
include SharedAuthentication include SharedAuthentication
include SharedPaths include SharedPaths
include SharedGroup include SharedGroup
...@@ -15,7 +15,7 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps ...@@ -15,7 +15,7 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
step 'group "TestGroup" has public project "Community"' do step 'group "TestGroup" has public project "Community"' do
group_has_project("TestGroup", "Community", Gitlab::VisibilityLevel::PUBLIC) group_has_project("TestGroup", "Community", Gitlab::VisibilityLevel::PUBLIC)
end end
step '"John Doe" is owner of group "TestGroup"' do step '"John Doe" is owner of group "TestGroup"' do
group = Group.find_by(name: "TestGroup") || create(:group, name: "TestGroup") group = Group.find_by(name: "TestGroup") || create(:group, name: "TestGroup")
user = create(:user, name: "John Doe") user = create(:user, name: "John Doe")
...@@ -37,31 +37,31 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps ...@@ -37,31 +37,31 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
step 'I visit group "TestGroup" members page' do step 'I visit group "TestGroup" members page' do
visit members_group_path(Group.find_by(name: "TestGroup")) visit members_group_path(Group.find_by(name: "TestGroup"))
end end
step 'I should not see project "Enterprise" items' do step 'I should not see project "Enterprise" items' do
page.should_not have_content "Enterprise" page.should_not have_content "Enterprise"
end end
step 'I should see project "Internal" items' do step 'I should see project "Internal" items' do
page.should have_content "Internal" page.should have_content "Internal"
end end
step 'I should not see project "Internal" items' do step 'I should not see project "Internal" items' do
page.should_not have_content "Internal" page.should_not have_content "Internal"
end end
step 'I should see project "Community" items' do step 'I should see project "Community" items' do
page.should have_content "Community" page.should have_content "Community"
end end
step 'I change filter to Everyone\'s' do step 'I change filter to Everyone\'s' do
click_link "Everyone's" click_link "Everyone's"
end end
step 'I should see group member "John Doe"' do step 'I should see group member "John Doe"' do
page.should have_content "John Doe" page.should have_content "John Doe"
end end
step 'I should not see member roles' do step 'I should not see member roles' do
page.body.should_not match(%r{owner|developer|reporter|guest}i) page.body.should_not match(%r{owner|developer|reporter|guest}i)
end end
......
class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps class Spinach::Features::ExploreProjectsFeature < Spinach::FeatureSteps
include SharedAuthentication include SharedAuthentication
include SharedPaths include SharedPaths
include SharedProject include SharedProject
......
class PublicProjects < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedPaths
Then 'I should see the list of public projects' do
page.should have_content "Public Projects"
end
end
...@@ -21,6 +21,14 @@ module SharedGroup ...@@ -21,6 +21,14 @@ module SharedGroup
is_member_of("Mary Jane", "Guest", Gitlab::Access::GUEST) is_member_of("Mary Jane", "Guest", Gitlab::Access::GUEST)
end end
step 'I should see group "TestGroup"' do
page.should have_content "TestGroup"
end
step 'I should not see group "TestGroup"' do
page.should_not have_content "TestGroup"
end
protected protected
def is_member_of(username, groupname, role) def is_member_of(username, groupname, role)
......
...@@ -324,13 +324,21 @@ module SharedPaths ...@@ -324,13 +324,21 @@ module SharedPaths
# ---------------------------------------- # ----------------------------------------
step 'I visit the public projects area' do step 'I visit the public projects area' do
visit public_root_path visit explore_projects_path
end end
step 'I visit public page for "Community" project' do step 'I visit public page for "Community" project' do
visit public_project_path(Project.find_by(name: "Community")) visit public_project_path(Project.find_by(name: "Community"))
end end
# ----------------------------------------
# Public Groups
# ----------------------------------------
step 'I visit the public groups area' do
visit explore_groups_path
end
# ---------------------------------------- # ----------------------------------------
# Snippets # Snippets
# ---------------------------------------- # ----------------------------------------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment