Merge branch 'api-default-order' into 'master'
Sorting refactoring * refactor sorting logic for web UI * refactor and document ordering for API: project, issues, merge requests * explicitly define ordering in models using default_scope See merge request !1476
This commit is contained in:
commit
dd8dd92e50
56 changed files with 411 additions and 215 deletions
|
@ -1,7 +1,7 @@
|
|||
class Admin::DashboardController < Admin::ApplicationController
|
||||
def index
|
||||
@projects = Project.order("created_at DESC").limit(10)
|
||||
@users = User.order("created_at DESC").limit(10)
|
||||
@groups = Group.order("created_at DESC").limit(10)
|
||||
@projects = Project.limit(10)
|
||||
@users = User.limit(10)
|
||||
@groups = Group.limit(10)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,8 @@ class Admin::GroupsController < Admin::ApplicationController
|
|||
before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :project_teams_update]
|
||||
|
||||
def index
|
||||
@groups = Group.order('name ASC')
|
||||
@groups = Group.all
|
||||
@groups = @groups.sort(@sort = params[:sort])
|
||||
@groups = @groups.search(params[:name]) if params[:name].present?
|
||||
@groups = @groups.page(params[:page]).per(20)
|
||||
end
|
||||
|
|
|
@ -2,16 +2,16 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
before_filter :user, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
@users = User.filter(params[:filter])
|
||||
@users = User.order_name_asc.filter(params[:filter])
|
||||
@users = @users.search(params[:name]) if params[:name].present?
|
||||
@users = @users.sort(@sort = params[:sort])
|
||||
@users = @users.alphabetically.page(params[:page])
|
||||
@users = @users.page(params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
@personal_projects = user.personal_projects
|
||||
@joined_projects = user.projects.joined(@user)
|
||||
@keys = user.keys.order('id DESC')
|
||||
@keys = user.keys
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -254,7 +254,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def set_filters_params
|
||||
params[:sort] ||= 'newest'
|
||||
params[:sort] ||= 'created_desc'
|
||||
params[:scope] = 'all' if params[:scope].blank?
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
|
||||
|
@ -280,7 +280,7 @@ class ApplicationController < ActionController::Base
|
|||
author_id = @filter_params[:author_id]
|
||||
milestone_id = @filter_params[:milestone_id]
|
||||
|
||||
@sort = @filter_params[:sort].try(:humanize)
|
||||
@sort = @filter_params[:sort]
|
||||
@assignees = User.where(id: collection.pluck(:assignee_id))
|
||||
@authors = User.where(id: collection.pluck(:author_id))
|
||||
@milestones = Milestone.where(id: collection.pluck(:milestone_id))
|
||||
|
|
|
@ -9,7 +9,7 @@ class DashboardController < ApplicationController
|
|||
# If user needs more - point to Dashboard#projects page
|
||||
@projects_limit = 30
|
||||
|
||||
@groups = current_user.authorized_groups.sort_by(&:human_name)
|
||||
@groups = current_user.authorized_groups.order_name_asc
|
||||
@has_authorized_projects = @projects.count > 0
|
||||
@projects_count = @projects.count
|
||||
@projects = @projects.limit(@projects_limit)
|
||||
|
|
|
@ -3,7 +3,7 @@ class Profiles::KeysController < ApplicationController
|
|||
skip_before_filter :authenticate_user!, only: [:get_keys]
|
||||
|
||||
def index
|
||||
@keys = current_user.keys.order('id DESC')
|
||||
@keys = current_user.keys
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -13,7 +13,7 @@ class Projects::CommitsController < Projects::ApplicationController
|
|||
|
||||
@commits = @repo.commits(@ref, @path, @limit, @offset)
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
group(:commit_id).count
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
|
|
@ -7,7 +7,7 @@ class Projects::LabelsController < Projects::ApplicationController
|
|||
respond_to :js, :html
|
||||
|
||||
def index
|
||||
@labels = @project.labels.order_by_name.page(params[:page]).per(20)
|
||||
@labels = @project.labels.page(params[:page]).per(20)
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -23,7 +23,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
|
||||
def show
|
||||
@note_counts = Note.where(commit_id: @merge_request.commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
group(:commit_id).count
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
|
|
@ -22,6 +22,7 @@ class NotesFinder
|
|||
end
|
||||
|
||||
# Use overlapping intervals to avoid worrying about race conditions
|
||||
notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP)
|
||||
notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP).
|
||||
order(created_at: :asc, id: :asc)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,19 @@
|
|||
module SortingHelper
|
||||
def sort_options_hash
|
||||
{
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_recently_updated => sort_title_recently_updated,
|
||||
sort_value_oldest_updated => sort_title_oldest_updated,
|
||||
sort_value_recently_created => sort_title_recently_created,
|
||||
sort_value_oldest_created => sort_title_oldest_created,
|
||||
sort_value_milestone_soon => sort_title_milestone_soon,
|
||||
sort_value_milestone_later => sort_title_milestone_later,
|
||||
sort_value_largest_repo => sort_title_largest_repo,
|
||||
sort_value_recently_signin => sort_title_recently_signin,
|
||||
sort_value_oldest_signin => sort_title_oldest_signin,
|
||||
}
|
||||
end
|
||||
|
||||
def sort_title_oldest_updated
|
||||
'Oldest updated'
|
||||
end
|
||||
|
@ -14,4 +29,68 @@ module SortingHelper
|
|||
def sort_title_recently_created
|
||||
'Recently created'
|
||||
end
|
||||
|
||||
def sort_title_milestone_soon
|
||||
'Milestone due soon'
|
||||
end
|
||||
|
||||
def sort_title_milestone_later
|
||||
'Milestone due later'
|
||||
end
|
||||
|
||||
def sort_title_name
|
||||
'Name'
|
||||
end
|
||||
|
||||
def sort_title_largest_repo
|
||||
'Largest repository'
|
||||
end
|
||||
|
||||
def sort_title_recently_signin
|
||||
'Recent sign in'
|
||||
end
|
||||
|
||||
def sort_title_oldest_signin
|
||||
'Oldest sign in'
|
||||
end
|
||||
|
||||
def sort_value_oldest_updated
|
||||
'updated_asc'
|
||||
end
|
||||
|
||||
def sort_value_recently_updated
|
||||
'updated_desc'
|
||||
end
|
||||
|
||||
def sort_value_oldest_created
|
||||
'created_asc'
|
||||
end
|
||||
|
||||
def sort_value_recently_created
|
||||
'created_desc'
|
||||
end
|
||||
|
||||
def sort_value_milestone_soon
|
||||
'milestone_due_asc'
|
||||
end
|
||||
|
||||
def sort_value_milestone_later
|
||||
'milestone_due_desc'
|
||||
end
|
||||
|
||||
def sort_value_name
|
||||
'name_asc'
|
||||
end
|
||||
|
||||
def sort_value_largest_repo
|
||||
'repository_size_desc'
|
||||
end
|
||||
|
||||
def sort_value_recently_signin
|
||||
'recent_sign_in'
|
||||
end
|
||||
|
||||
def sort_value_oldest_signin
|
||||
'oldest_sign_in'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#
|
||||
|
||||
class BroadcastMessage < ActiveRecord::Base
|
||||
include Sortable
|
||||
|
||||
validates :message, presence: true
|
||||
validates :starts_at, presence: true
|
||||
validates :ends_at, presence: true
|
||||
|
|
|
@ -29,6 +29,8 @@ module Issuable
|
|||
scope :only_opened, -> { with_state(:opened) }
|
||||
scope :only_reopened, -> { with_state(:reopened) }
|
||||
scope :closed, -> { with_state(:closed) }
|
||||
scope :order_milestone_due_desc, -> { joins(:milestone).reorder('milestones.due_date DESC, milestones.id DESC') }
|
||||
scope :order_milestone_due_asc, -> { joins(:milestone).reorder('milestones.due_date ASC, milestones.id ASC') }
|
||||
|
||||
delegate :name,
|
||||
:email,
|
||||
|
@ -55,13 +57,10 @@ module Issuable
|
|||
|
||||
def sort(method)
|
||||
case method.to_s
|
||||
when 'newest' then reorder("#{table_name}.created_at DESC")
|
||||
when 'oldest' then reorder("#{table_name}.created_at ASC")
|
||||
when 'recently_updated' then reorder("#{table_name}.updated_at DESC")
|
||||
when 'last_updated' then reorder("#{table_name}.updated_at ASC")
|
||||
when 'milestone_due_soon' then joins(:milestone).reorder("milestones.due_date ASC")
|
||||
when 'milestone_due_later' then joins(:milestone).reorder("milestones.due_date DESC")
|
||||
else reorder("#{table_name}.created_at DESC")
|
||||
when 'milestone_due_asc' then order_milestone_due_asc
|
||||
when 'milestone_due_desc' then order_milestone_due_desc
|
||||
else
|
||||
order_by(method)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
38
app/models/concerns/sortable.rb
Normal file
38
app/models/concerns/sortable.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
# == Sortable concern
|
||||
#
|
||||
# Set default scope for ordering objects
|
||||
#
|
||||
module Sortable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# By default all models should be ordered
|
||||
# by created_at field starting from newest
|
||||
default_scope { order(created_at: :desc, id: :desc) }
|
||||
|
||||
scope :order_created_desc, -> { reorder(created_at: :desc, id: :desc) }
|
||||
scope :order_created_asc, -> { reorder(created_at: :asc, id: :asc) }
|
||||
scope :order_updated_desc, -> { reorder(updated_at: :desc, id: :desc) }
|
||||
scope :order_updated_asc, -> { reorder(updated_at: :asc, id: :asc) }
|
||||
|
||||
if column_names.include?('name')
|
||||
scope :order_name_asc, -> { reorder(name: :asc) }
|
||||
scope :order_name_desc, -> { reorder(name: :desc) }
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def order_by(method)
|
||||
case method.to_s
|
||||
when 'name_asc' then order_name_asc
|
||||
when 'name_desc' then order_name_desc
|
||||
when 'updated_asc' then order_updated_asc
|
||||
when 'updated_desc' then order_updated_desc
|
||||
when 'created_asc' then order_created_asc
|
||||
when 'created_desc' then order_created_desc
|
||||
else
|
||||
all
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -10,6 +10,8 @@
|
|||
#
|
||||
|
||||
class Email < ActiveRecord::Base
|
||||
include Sortable
|
||||
|
||||
belongs_to :user
|
||||
|
||||
validates :user_id, presence: true
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#
|
||||
|
||||
class Event < ActiveRecord::Base
|
||||
include Sortable
|
||||
default_scope { where.not(author_id: nil) }
|
||||
|
||||
CREATED = 1
|
||||
|
|
|
@ -28,6 +28,16 @@ class Group < Namespace
|
|||
after_create :post_create_hook
|
||||
after_destroy :post_destroy_hook
|
||||
|
||||
class << self
|
||||
def search(query)
|
||||
where("LOWER(namespaces.name) LIKE :query or LOWER(namespaces.path) LIKE :query", query: "%#{query.downcase}%")
|
||||
end
|
||||
|
||||
def sort(method)
|
||||
order_by(method)
|
||||
end
|
||||
end
|
||||
|
||||
def human_name
|
||||
name
|
||||
end
|
||||
|
@ -88,20 +98,4 @@ class Group < Namespace
|
|||
def system_hook_service
|
||||
SystemHooksService.new
|
||||
end
|
||||
|
||||
class << self
|
||||
def search(query)
|
||||
where("LOWER(namespaces.name) LIKE :query or LOWER(namespaces.path) 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
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#
|
||||
|
||||
class WebHook < ActiveRecord::Base
|
||||
include Sortable
|
||||
include HTTParty
|
||||
|
||||
default_value_for :push_events, true
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#
|
||||
|
||||
class Identity < ActiveRecord::Base
|
||||
include Sortable
|
||||
belongs_to :user
|
||||
|
||||
validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
|
||||
|
|
|
@ -24,6 +24,7 @@ class Issue < ActiveRecord::Base
|
|||
include Issuable
|
||||
include InternalId
|
||||
include Taskable
|
||||
include Sortable
|
||||
|
||||
ActsAsTaggableOn.strict_case_match = true
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
require 'digest/md5'
|
||||
|
||||
class Key < ActiveRecord::Base
|
||||
include Sortable
|
||||
include Gitlab::Popen
|
||||
|
||||
belongs_to :user
|
||||
|
|
|
@ -28,7 +28,7 @@ class Label < ActiveRecord::Base
|
|||
format: { with: /\A[^&\?,&]+\z/ },
|
||||
uniqueness: { scope: :project_id }
|
||||
|
||||
scope :order_by_name, -> { reorder("labels.title ASC") }
|
||||
default_scope { order(title: :asc) }
|
||||
|
||||
alias_attribute :name, :title
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#
|
||||
|
||||
class Member < ActiveRecord::Base
|
||||
include Sortable
|
||||
include Notifiable
|
||||
include Gitlab::Access
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ class MergeRequest < ActiveRecord::Base
|
|||
include Issuable
|
||||
include Taskable
|
||||
include InternalId
|
||||
include Sortable
|
||||
|
||||
belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
|
||||
belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
require Rails.root.join("app/models/commit")
|
||||
|
||||
class MergeRequestDiff < ActiveRecord::Base
|
||||
include Sortable
|
||||
|
||||
# Prevent store of diff
|
||||
# if commits amount more then 200
|
||||
COMMITS_SAFE_SIZE = 200
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
class Milestone < ActiveRecord::Base
|
||||
include InternalId
|
||||
include Sortable
|
||||
|
||||
belongs_to :project
|
||||
has_many :issues
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#
|
||||
|
||||
class Namespace < ActiveRecord::Base
|
||||
include Sortable
|
||||
include Gitlab::ShellAdapter
|
||||
|
||||
has_many :projects, dependent: :destroy
|
||||
|
|
|
@ -33,6 +33,7 @@ require 'carrierwave/orm/activerecord'
|
|||
require 'file_size_validator'
|
||||
|
||||
class Project < ActiveRecord::Base
|
||||
include Sortable
|
||||
include Gitlab::ShellAdapter
|
||||
include Gitlab::VisibilityLevel
|
||||
include Gitlab::ConfigHelper
|
||||
|
@ -53,7 +54,7 @@ class Project < ActiveRecord::Base
|
|||
attr_accessor :new_default_branch
|
||||
|
||||
# Relations
|
||||
belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
|
||||
belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
|
||||
belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id'
|
||||
belongs_to :namespace
|
||||
|
||||
|
@ -86,7 +87,7 @@ class Project < ActiveRecord::Base
|
|||
has_many :merge_requests, dependent: :destroy, foreign_key: 'target_project_id'
|
||||
# Merge requests from source project should be kept when source project was removed
|
||||
has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: MergeRequest
|
||||
has_many :issues, -> { order 'issues.state DESC, issues.created_at DESC' }, dependent: :destroy
|
||||
has_many :issues, dependent: :destroy
|
||||
has_many :labels, dependent: :destroy
|
||||
has_many :services, dependent: :destroy
|
||||
has_many :events, dependent: :destroy
|
||||
|
@ -139,14 +140,16 @@ class Project < ActiveRecord::Base
|
|||
mount_uploader :avatar, AttachmentUploader
|
||||
|
||||
# Scopes
|
||||
scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) }
|
||||
scope :sorted_by_stars, -> { reorder('projects.star_count DESC') }
|
||||
scope :sorted_by_names, -> { joins(:namespace).reorder('namespaces.name ASC, projects.name ASC') }
|
||||
|
||||
scope :without_user, ->(user) { where('projects.id NOT IN (:ids)', ids: user.authorized_projects.map(&:id) ) }
|
||||
scope :without_team, ->(team) { team.projects.present? ? where('projects.id NOT IN (:ids)', ids: team.projects.map(&:id)) : scoped }
|
||||
scope :not_in_group, ->(group) { where('projects.id NOT IN (:ids)', ids: group.project_ids ) }
|
||||
scope :in_team, ->(team) { where('projects.id IN (:ids)', ids: team.projects.map(&:id)) }
|
||||
scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
|
||||
scope :in_group_namespace, -> { joins(:group) }
|
||||
scope :sorted_by_activity, -> { reorder('projects.last_activity_at DESC') }
|
||||
scope :sorted_by_stars, -> { reorder('projects.star_count DESC') }
|
||||
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
|
||||
scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
|
||||
scope :public_only, -> { where(visibility_level: Project::PUBLIC) }
|
||||
|
@ -228,13 +231,10 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def sort(method)
|
||||
case method.to_s
|
||||
when 'newest' then reorder('projects.created_at DESC')
|
||||
when 'oldest' then reorder('projects.created_at ASC')
|
||||
when 'recently_updated' then reorder('projects.updated_at DESC')
|
||||
when 'last_updated' then reorder('projects.updated_at ASC')
|
||||
when 'largest_repository' then reorder('projects.repository_size DESC')
|
||||
else reorder('namespaces.path, projects.name ASC')
|
||||
if method == 'repository_size_desc'
|
||||
reorder(repository_size: :desc, id: :desc)
|
||||
else
|
||||
order_by(method)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# To add new service you should build a class inherited from Service
|
||||
# and implement a set of methods
|
||||
class Service < ActiveRecord::Base
|
||||
include Sortable
|
||||
serialize :properties, JSON
|
||||
|
||||
default_value_for :active, false
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#
|
||||
|
||||
class Snippet < ActiveRecord::Base
|
||||
include Sortable
|
||||
include Linguist::BlobHelper
|
||||
include Gitlab::VisibilityLevel
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ require 'carrierwave/orm/activerecord'
|
|||
require 'file_size_validator'
|
||||
|
||||
class User < ActiveRecord::Base
|
||||
include Sortable
|
||||
include Gitlab::ConfigHelper
|
||||
include TokenAuthenticatable
|
||||
extend Gitlab::ConfigHelper
|
||||
|
@ -176,7 +177,6 @@ class User < ActiveRecord::Base
|
|||
scope :admins, -> { where(admin: true) }
|
||||
scope :blocked, -> { with_state(:blocked) }
|
||||
scope :active, -> { with_state(:active) }
|
||||
scope :alphabetically, -> { order('name ASC') }
|
||||
scope :in_team, ->(team){ where(id: team.member_ids) }
|
||||
scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
|
||||
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
|
||||
|
@ -199,11 +199,10 @@ class User < ActiveRecord::Base
|
|||
|
||||
def sort(method)
|
||||
case method.to_s
|
||||
when 'recent_sign_in' then reorder('users.last_sign_in_at DESC')
|
||||
when 'oldest_sign_in' then reorder('users.last_sign_in_at ASC')
|
||||
when 'recently_created' then reorder('users.created_at DESC')
|
||||
when 'late_created' then reorder('users.created_at ASC')
|
||||
else reorder("users.name ASC")
|
||||
when 'recent_sign_in' then reorder(last_sign_in_at: :desc)
|
||||
when 'oldest_sign_in' then reorder(last_sign_in_at: :asc)
|
||||
else
|
||||
order_by(method)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -290,7 +289,7 @@ class User < ActiveRecord::Base
|
|||
def authorized_groups
|
||||
@authorized_groups ||= begin
|
||||
group_ids = (groups.pluck(:id) + authorized_projects.pluck(:namespace_id))
|
||||
Group.where(id: group_ids).order('namespaces.name ASC')
|
||||
Group.where(id: group_ids)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -301,7 +300,7 @@ class User < ActiveRecord::Base
|
|||
project_ids = personal_projects.pluck(:id)
|
||||
project_ids.push(*groups_projects.pluck(:id))
|
||||
project_ids.push(*projects.pluck(:id).uniq)
|
||||
Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC')
|
||||
Project.where(id: project_ids)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,10 +8,31 @@
|
|||
|
||||
%hr
|
||||
= form_tag admin_groups_path, method: :get, class: 'form-inline' do
|
||||
= hidden_field_tag :sort, @sort
|
||||
.form-group
|
||||
= text_field_tag :name, params[:name], class: "form-control input-mn-300"
|
||||
= button_tag "Search", class: "btn submit btn-primary"
|
||||
|
||||
.pull-right
|
||||
.dropdown.inline
|
||||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light sort:
|
||||
- if @sort.present?
|
||||
= sort_options_hash[@sort]
|
||||
- else
|
||||
= sort_title_recently_created
|
||||
%b.caret
|
||||
%ul.dropdown-menu
|
||||
%li
|
||||
= link_to admin_groups_path(sort: sort_value_recently_created) do
|
||||
= sort_title_recently_created
|
||||
= link_to admin_groups_path(sort: sort_value_oldest_created) do
|
||||
= sort_title_oldest_created
|
||||
= link_to admin_groups_path(sort: sort_value_recently_updated) do
|
||||
= sort_title_recently_updated
|
||||
= link_to admin_groups_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
|
||||
%hr
|
||||
|
||||
%ul.bordered-list
|
||||
|
|
|
@ -47,24 +47,22 @@
|
|||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light sort:
|
||||
- if @sort.present?
|
||||
= @sort.humanize
|
||||
= sort_options_hash[@sort]
|
||||
- else
|
||||
Name
|
||||
= sort_title_recently_created
|
||||
%b.caret
|
||||
%ul.dropdown-menu
|
||||
%li
|
||||
= link_to admin_projects_path(sort: nil) do
|
||||
Name
|
||||
= link_to admin_projects_path(sort: 'newest') do
|
||||
= link_to admin_projects_path(sort: sort_value_recently_created) do
|
||||
= sort_title_recently_created
|
||||
= link_to admin_projects_path(sort: 'oldest') do
|
||||
= link_to admin_projects_path(sort: sort_value_oldest_created) do
|
||||
= sort_title_oldest_created
|
||||
= link_to admin_projects_path(sort: 'recently_updated') do
|
||||
= link_to admin_projects_path(sort: sort_value_recently_updated) do
|
||||
= sort_title_recently_updated
|
||||
= link_to admin_projects_path(sort: 'last_updated') do
|
||||
= link_to admin_projects_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
= link_to admin_projects_path(sort: 'largest_repository') do
|
||||
Largest repository
|
||||
= link_to admin_projects_path(sort: sort_value_largest_repo) do
|
||||
= sort_title_largest_repo
|
||||
= link_to 'New Project', new_project_path, class: "btn btn-new"
|
||||
%ul.well-list
|
||||
- @projects.each do |project|
|
||||
|
|
|
@ -36,22 +36,26 @@
|
|||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light sort:
|
||||
- if @sort.present?
|
||||
= @sort.humanize
|
||||
= sort_options_hash[@sort]
|
||||
- else
|
||||
Name
|
||||
= sort_title_name
|
||||
%b.caret
|
||||
%ul.dropdown-menu
|
||||
%li
|
||||
= link_to admin_users_path(sort: nil) do
|
||||
Name
|
||||
= link_to admin_users_path(sort: 'recent_sign_in') do
|
||||
Recent sign in
|
||||
= link_to admin_users_path(sort: 'oldest_sign_in') do
|
||||
Oldest sign in
|
||||
= link_to admin_users_path(sort: 'recently_created') do
|
||||
= link_to admin_users_path(sort: sort_value_name) do
|
||||
= sort_title_name
|
||||
= link_to admin_users_path(sort: sort_value_recently_signin) do
|
||||
= sort_title_recently_signin
|
||||
= link_to admin_users_path(sort: sort_value_oldest_signin) do
|
||||
= sort_title_oldest_signin
|
||||
= link_to admin_users_path(sort: sort_value_recently_created) do
|
||||
= sort_title_recently_created
|
||||
= link_to admin_users_path(sort: 'late_created') do
|
||||
= link_to admin_users_path(sort: sort_value_oldest_created) do
|
||||
= sort_title_oldest_created
|
||||
= link_to admin_users_path(sort: sort_value_recently_updated) do
|
||||
= sort_title_recently_updated
|
||||
= link_to admin_users_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
|
||||
= link_to 'New User', new_admin_user_path, class: "btn btn-new"
|
||||
%ul.well-list
|
||||
|
|
|
@ -82,19 +82,19 @@
|
|||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light sort:
|
||||
- if @sort.present?
|
||||
= @sort.humanize
|
||||
= sort_options_hash[@sort]
|
||||
- else
|
||||
Name
|
||||
= sort_title_recently_created
|
||||
%b.caret
|
||||
%ul.dropdown-menu
|
||||
%li
|
||||
= link_to projects_dashboard_filter_path(sort: nil) do
|
||||
Name
|
||||
= link_to projects_dashboard_filter_path(sort: 'newest') do
|
||||
= link_to projects_dashboard_filter_path(sort: sort_value_recently_created) do
|
||||
= sort_title_recently_created
|
||||
= link_to projects_dashboard_filter_path(sort: 'oldest') do
|
||||
= link_to projects_dashboard_filter_path(sort: sort_value_oldest_created) do
|
||||
= sort_title_oldest_created
|
||||
= link_to projects_dashboard_filter_path(sort: 'recently_updated') do
|
||||
= link_to projects_dashboard_filter_path(sort: sort_value_recently_updated) do
|
||||
= sort_title_recently_updated
|
||||
= link_to projects_dashboard_filter_path(sort: 'last_updated') do
|
||||
= link_to projects_dashboard_filter_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
= link_to projects_dashboard_filter_path(sort: sort_value_name) do
|
||||
= sort_title_name
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
.clearfix
|
||||
.pull-left
|
||||
= form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f|
|
||||
= hidden_field_tag :sort, @sort
|
||||
.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
|
||||
|
@ -11,21 +12,19 @@
|
|||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light sort:
|
||||
- if @sort.present?
|
||||
= @sort.humanize
|
||||
= sort_options_hash[@sort]
|
||||
- else
|
||||
Name
|
||||
= sort_title_recently_created
|
||||
%b.caret
|
||||
%ul.dropdown-menu
|
||||
%li
|
||||
= link_to explore_groups_path(sort: nil) do
|
||||
Name
|
||||
= link_to explore_groups_path(sort: 'newest') do
|
||||
= link_to explore_groups_path(sort: sort_value_recently_created) do
|
||||
= sort_title_recently_created
|
||||
= link_to explore_groups_path(sort: 'oldest') do
|
||||
= link_to explore_groups_path(sort: sort_value_oldest_created) do
|
||||
= sort_title_oldest_created
|
||||
= link_to explore_groups_path(sort: 'recently_updated') do
|
||||
= link_to explore_groups_path(sort: sort_value_recently_updated) do
|
||||
= sort_title_recently_updated
|
||||
= link_to explore_groups_path(sort: 'last_updated') do
|
||||
= link_to explore_groups_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
|
||||
%hr
|
||||
|
|
|
@ -11,21 +11,19 @@
|
|||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light sort:
|
||||
- if @sort.present?
|
||||
= @sort.humanize
|
||||
= sort_options_hash[@sort]
|
||||
- else
|
||||
Name
|
||||
= sort_title_recently_created
|
||||
%b.caret
|
||||
%ul.dropdown-menu
|
||||
%li
|
||||
= link_to explore_projects_path(sort: nil) do
|
||||
Name
|
||||
= link_to explore_projects_path(sort: 'newest') do
|
||||
= link_to explore_projects_path(sort: sort_value_recently_created) do
|
||||
= sort_title_recently_created
|
||||
= link_to explore_projects_path(sort: 'oldest') do
|
||||
= link_to explore_projects_path(sort: sort_value_oldest_created) do
|
||||
= sort_title_oldest_created
|
||||
= link_to explore_projects_path(sort: 'recently_updated') do
|
||||
= link_to explore_projects_path(sort: sort_value_recently_updated) do
|
||||
= sort_title_recently_updated
|
||||
= link_to explore_projects_path(sort: 'last_updated') do
|
||||
= link_to explore_projects_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
|
||||
%hr
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
= link_to page_filter_path(label_name: nil) do
|
||||
Any
|
||||
- if @project.labels.any?
|
||||
- @project.labels.order_by_name.each do |label|
|
||||
- @project.labels.each do |label|
|
||||
%li
|
||||
= link_to page_filter_path(label_name: label.name) do
|
||||
= render_colored_label(label)
|
||||
|
|
|
@ -2,21 +2,21 @@
|
|||
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
|
||||
%span.light sort:
|
||||
- if @sort.present?
|
||||
= @sort
|
||||
= sort_options_hash[@sort]
|
||||
- else
|
||||
Newest
|
||||
= sort_title_recently_created
|
||||
%b.caret
|
||||
%ul.dropdown-menu.dropdown-menu-align-right
|
||||
%li
|
||||
= link_to page_filter_path(sort: 'newest') do
|
||||
= link_to page_filter_path(sort: sort_value_recently_created) do
|
||||
= sort_title_recently_created
|
||||
= link_to page_filter_path(sort: 'oldest') do
|
||||
= link_to page_filter_path(sort: sort_value_oldest_created) do
|
||||
= sort_title_oldest_created
|
||||
= link_to page_filter_path(sort: 'recently_updated') do
|
||||
= link_to page_filter_path(sort: sort_value_recently_updated) do
|
||||
= sort_title_recently_updated
|
||||
= link_to page_filter_path(sort: 'last_updated') do
|
||||
= link_to page_filter_path(sort: sort_value_oldest_updated) do
|
||||
= sort_title_oldest_updated
|
||||
= link_to page_filter_path(sort: 'milestone_due_soon') do
|
||||
Milestone due soon
|
||||
= link_to page_filter_path(sort: 'milestone_due_later') do
|
||||
Milestone due later
|
||||
= link_to page_filter_path(sort: sort_value_milestone_soon) do
|
||||
= sort_title_milestone_soon
|
||||
= link_to page_filter_path(sort: sort_value_milestone_later) do
|
||||
= sort_title_milestone_later
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddTimestampsToIdentities < ActiveRecord::Migration
|
||||
def change
|
||||
add_timestamps(:identities)
|
||||
end
|
||||
end
|
14
db/schema.rb
14
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20150125163100) do
|
||||
ActiveRecord::Schema.define(version: 20150205211843) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -87,9 +87,11 @@ ActiveRecord::Schema.define(version: 20150125163100) do
|
|||
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
|
||||
|
||||
create_table "identities", force: true do |t|
|
||||
t.string "extern_uid"
|
||||
t.string "provider"
|
||||
t.integer "user_id"
|
||||
t.string "extern_uid"
|
||||
t.string "provider"
|
||||
t.integer "user_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree
|
||||
|
@ -323,12 +325,12 @@ ActiveRecord::Schema.define(version: 20150125163100) do
|
|||
t.string "import_url"
|
||||
t.integer "visibility_level", default: 0, null: false
|
||||
t.boolean "archived", default: false, null: false
|
||||
t.string "avatar"
|
||||
t.string "import_status"
|
||||
t.float "repository_size", default: 0.0
|
||||
t.integer "star_count", default: 0, null: false
|
||||
t.string "import_type"
|
||||
t.string "import_source"
|
||||
t.string "avatar"
|
||||
end
|
||||
|
||||
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
|
||||
|
@ -426,7 +428,6 @@ ActiveRecord::Schema.define(version: 20150125163100) do
|
|||
t.integer "notification_level", default: 1, null: false
|
||||
t.datetime "password_expires_at"
|
||||
t.integer "created_by_id"
|
||||
t.datetime "last_credential_check_at"
|
||||
t.string "avatar"
|
||||
t.string "confirmation_token"
|
||||
t.datetime "confirmed_at"
|
||||
|
@ -434,6 +435,7 @@ ActiveRecord::Schema.define(version: 20150125163100) do
|
|||
t.string "unconfirmed_email"
|
||||
t.boolean "hide_no_ssh_key", default: false
|
||||
t.string "website_url", default: "", null: false
|
||||
t.datetime "last_credential_check_at"
|
||||
t.string "github_access_token"
|
||||
t.string "gitlab_access_token"
|
||||
end
|
||||
|
|
|
@ -18,6 +18,8 @@ Parameters:
|
|||
|
||||
- `state` (optional) - Return `all` issues or just those that are `opened` or `closed`
|
||||
- `labels` (optional) - Comma-separated list of label names
|
||||
- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
|
||||
```json
|
||||
[
|
||||
|
@ -105,6 +107,8 @@ Parameters:
|
|||
- `state` (optional) - Return `all` issues or just those that are `opened` or `closed`
|
||||
- `labels` (optional) - Comma-separated list of label names
|
||||
- `milestone` (optional) - Milestone title
|
||||
- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
|
||||
## Single issue
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
## List merge requests
|
||||
|
||||
Get all merge requests for this project. The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`). The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests.
|
||||
Get all merge requests for this project.
|
||||
The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`).
|
||||
The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests.
|
||||
|
||||
```
|
||||
GET /projects/:id/merge_requests
|
||||
|
@ -14,8 +16,8 @@ Parameters:
|
|||
|
||||
- `id` (required) - The ID of a project
|
||||
- `state` (optional) - Return `all` requests or just those that are `merged`, `opened` or `closed`
|
||||
- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order
|
||||
- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
|
||||
```json
|
||||
[
|
||||
|
|
|
@ -11,8 +11,8 @@ GET /projects
|
|||
Parameters:
|
||||
|
||||
- `archived` (optional) - if passed, limit by archived status
|
||||
- `order_by` (optional) - Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order
|
||||
- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
- `search` (optional) - Return list of authorized projects according to a search criteria
|
||||
|
||||
```json
|
||||
|
@ -98,6 +98,13 @@ Get a list of projects which are owned by the authenticated user.
|
|||
GET /projects/owned
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `archived` (optional) - if passed, limit by archived status
|
||||
- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
- `search` (optional) - Return list of authorized projects according to a search criteria
|
||||
|
||||
### List ALL projects
|
||||
|
||||
Get a list of all GitLab projects (admin only).
|
||||
|
@ -106,6 +113,13 @@ Get a list of all GitLab projects (admin only).
|
|||
GET /projects/all
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `archived` (optional) - if passed, limit by archived status
|
||||
- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
|
||||
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
- `search` (optional) - Return list of authorized projects according to a search criteria
|
||||
|
||||
### Get single project
|
||||
|
||||
Get a specific project, identified by project ID or NAMESPACE/PROJECT_NAME, which is owned by the authenticated user.
|
||||
|
|
|
@ -33,7 +33,7 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
|
|||
end
|
||||
|
||||
step 'I should be redirected to group page' do
|
||||
current_path.should == admin_group_path(Group.last)
|
||||
current_path.should == admin_group_path(Group.find_by(path: 'gitlab'))
|
||||
end
|
||||
|
||||
When 'I select user "John Doe" from user list as "Reporter"' do
|
||||
|
|
|
@ -83,7 +83,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
|
|||
end
|
||||
|
||||
step 'I should be redirected to group "Samurai" page' do
|
||||
current_path.should == group_path(Group.last)
|
||||
current_path.should == group_path(Group.find_by(name: 'Samurai'))
|
||||
end
|
||||
|
||||
step 'I should see newly created group "Samurai"' do
|
||||
|
|
|
@ -70,8 +70,8 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
|
|||
find("#merge_request_source_branch").value.should have_content "new_design"
|
||||
find("#merge_request_target_branch").value.should have_content "master"
|
||||
find("#merge_request_title").value.should == "New Design"
|
||||
verify_commit_link(".mr_target_commit",@project)
|
||||
verify_commit_link(".mr_source_commit",@forked_project)
|
||||
verify_commit_link(".mr_target_commit", @project)
|
||||
verify_commit_link(".mr_source_commit", @forked_project)
|
||||
end
|
||||
|
||||
step 'I update the merge request title' do
|
||||
|
@ -114,7 +114,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
|
|||
step 'I fill out an invalid "Merge Request On Forked Project" merge request' do
|
||||
select "Select branch", from: "merge_request_target_branch"
|
||||
find(:select, "merge_request_source_project_id", {}).value.should == @forked_project.id.to_s
|
||||
find(:select, "merge_request_target_project_id", {}).value.should == project.id.to_s
|
||||
find(:select, "merge_request_target_project_id", {}).value.should == @project.id.to_s
|
||||
find(:select, "merge_request_source_branch", {}).value.should == ""
|
||||
find(:select, "merge_request_target_branch", {}).value.should == ""
|
||||
click_button "Compare branches"
|
||||
|
@ -125,7 +125,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
|
|||
end
|
||||
|
||||
step 'the target repository should be the original repository' do
|
||||
page.should have_select("merge_request_target_project_id", selected: project.path_with_namespace)
|
||||
page.should have_select("merge_request_target_project_id", selected: @project.path_with_namespace)
|
||||
end
|
||||
|
||||
# Verify a link is generated against the correct project
|
||||
|
|
|
@ -174,7 +174,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
|
|||
click_link 'add a file'
|
||||
|
||||
# Remove pre-receive hook so we can push without auth
|
||||
FileUtils.rm(File.join(Project.last.repository.path, 'hooks', 'pre-receive'))
|
||||
FileUtils.rm(File.join(@project.repository.path, 'hooks', 'pre-receive'))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -154,6 +154,22 @@ module API
|
|||
Gitlab::Access.options_with_owner.values.include? level.to_i
|
||||
end
|
||||
|
||||
def issuable_order_by
|
||||
if params["order_by"] == 'updated_at'
|
||||
'updated_at'
|
||||
else
|
||||
'created_at'
|
||||
end
|
||||
end
|
||||
|
||||
def issuable_sort
|
||||
if params["sort"] == 'asc'
|
||||
:asc
|
||||
else
|
||||
:desc
|
||||
end
|
||||
end
|
||||
|
||||
# error helpers
|
||||
|
||||
def forbidden!(reason = nil)
|
||||
|
|
|
@ -27,7 +27,9 @@ module API
|
|||
# Parameters:
|
||||
# state (optional) - Return "opened" or "closed" issues
|
||||
# labels (optional) - Comma-separated list of label names
|
||||
|
||||
# order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
|
||||
# sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
#
|
||||
# Example Requests:
|
||||
# GET /issues
|
||||
# GET /issues?state=opened
|
||||
|
@ -39,8 +41,7 @@ module API
|
|||
issues = current_user.issues
|
||||
issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
|
||||
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
|
||||
issues = issues.order('issues.id DESC')
|
||||
|
||||
issues.reorder(issuable_order_by => issuable_sort)
|
||||
present paginate(issues), with: Entities::Issue
|
||||
end
|
||||
end
|
||||
|
@ -53,6 +54,8 @@ module API
|
|||
# state (optional) - Return "opened" or "closed" issues
|
||||
# labels (optional) - Comma-separated list of label names
|
||||
# milestone (optional) - Milestone title
|
||||
# order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
|
||||
# sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
#
|
||||
# Example Requests:
|
||||
# GET /projects/:id/issues
|
||||
|
@ -67,11 +70,12 @@ module API
|
|||
issues = user_project.issues
|
||||
issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
|
||||
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
|
||||
|
||||
unless params[:milestone].nil?
|
||||
issues = filter_issues_milestone(issues, params[:milestone])
|
||||
end
|
||||
issues = issues.order('issues.id DESC')
|
||||
|
||||
issues.reorder(issuable_order_by => issuable_sort)
|
||||
present paginate(issues), with: Entities::Issue
|
||||
end
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ module API
|
|||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# state (optional) - Return requests "merged", "opened" or "closed"
|
||||
# order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
|
||||
# sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
|
||||
#
|
||||
# Example:
|
||||
# GET /projects/:id/merge_requests
|
||||
|
@ -37,25 +39,18 @@ module API
|
|||
#
|
||||
get ":id/merge_requests" do
|
||||
authorize! :read_merge_request, user_project
|
||||
merge_requests = user_project.merge_requests
|
||||
|
||||
mrs = case params["state"]
|
||||
when "opened" then user_project.merge_requests.opened
|
||||
when "closed" then user_project.merge_requests.closed
|
||||
when "merged" then user_project.merge_requests.merged
|
||||
else user_project.merge_requests
|
||||
end
|
||||
merge_requests =
|
||||
case params["state"]
|
||||
when "opened" then merge_requests.opened
|
||||
when "closed" then merge_requests.closed
|
||||
when "merged" then merge_requests.merged
|
||||
else merge_requests
|
||||
end
|
||||
|
||||
sort = case params["sort"]
|
||||
when 'desc' then 'DESC'
|
||||
else 'ASC'
|
||||
end
|
||||
|
||||
mrs = case params["order_by"]
|
||||
when 'updated_at' then mrs.order("updated_at #{sort}")
|
||||
else mrs.order("created_at #{sort}")
|
||||
end
|
||||
|
||||
present paginate(mrs), with: Entities::MergeRequest
|
||||
merge_requests.reorder(issuable_order_by => issuable_sort)
|
||||
present paginate(merge_requests), with: Entities::MergeRequest
|
||||
end
|
||||
|
||||
# Show MR
|
||||
|
|
|
@ -11,6 +11,37 @@ module API
|
|||
attrs[:visibility_level] = Gitlab::VisibilityLevel::PUBLIC if !attrs[:visibility_level].present? && publik == true
|
||||
attrs
|
||||
end
|
||||
|
||||
def filter_projects(projects)
|
||||
# If the archived parameter is passed, limit results accordingly
|
||||
if params[:archived].present?
|
||||
projects = projects.where(archived: parse_boolean(params[:archived]))
|
||||
end
|
||||
|
||||
if params[:search].present?
|
||||
projects = projects.search(params[:search])
|
||||
end
|
||||
|
||||
projects.reorder(project_order_by => project_sort)
|
||||
end
|
||||
|
||||
def project_order_by
|
||||
order_fields = %w(id name path created_at updated_at last_activity_at)
|
||||
|
||||
if order_fields.include?(params['order_by'])
|
||||
params['order_by']
|
||||
else
|
||||
'created_at'
|
||||
end
|
||||
end
|
||||
|
||||
def project_sort
|
||||
if params["sort"] == 'asc'
|
||||
:asc
|
||||
else
|
||||
:desc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Get a projects list for authenticated user
|
||||
|
@ -19,25 +50,7 @@ module API
|
|||
# GET /projects
|
||||
get do
|
||||
@projects = current_user.authorized_projects
|
||||
sort = params[:sort] == 'desc' ? 'desc' : 'asc'
|
||||
|
||||
@projects = case params["order_by"]
|
||||
when 'id' then @projects.reorder("id #{sort}")
|
||||
when 'name' then @projects.reorder("name #{sort}")
|
||||
when 'created_at' then @projects.reorder("created_at #{sort}")
|
||||
when 'last_activity_at' then @projects.reorder("last_activity_at #{sort}")
|
||||
else @projects
|
||||
end
|
||||
|
||||
# If the archived parameter is passed, limit results accordingly
|
||||
if params[:archived].present?
|
||||
@projects = @projects.where(archived: parse_boolean(params[:archived]))
|
||||
end
|
||||
|
||||
if params[:search].present?
|
||||
@projects = @projects.search(params[:search])
|
||||
end
|
||||
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = paginate @projects
|
||||
present @projects, with: Entities::Project
|
||||
end
|
||||
|
@ -47,16 +60,8 @@ module API
|
|||
# Example Request:
|
||||
# GET /projects/owned
|
||||
get '/owned' do
|
||||
sort = params[:sort] == 'desc' ? 'desc' : 'asc'
|
||||
@projects = current_user.owned_projects
|
||||
@projects = case params["order_by"]
|
||||
when 'id' then @projects.reorder("id #{sort}")
|
||||
when 'name' then @projects.reorder("name #{sort}")
|
||||
when 'created_at' then @projects.reorder("created_at #{sort}")
|
||||
when 'last_activity_at' then @projects.reorder("last_activity_at #{sort}")
|
||||
else @projects
|
||||
end
|
||||
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = paginate @projects
|
||||
present @projects, with: Entities::Project
|
||||
end
|
||||
|
@ -67,16 +72,8 @@ module API
|
|||
# GET /projects/all
|
||||
get '/all' do
|
||||
authenticated_as_admin!
|
||||
sort = params[:sort] == 'desc' ? 'desc' : 'asc'
|
||||
|
||||
@projects = case params["order_by"]
|
||||
when 'id' then Project.order("id #{sort}")
|
||||
when 'name' then Project.order("name #{sort}")
|
||||
when 'created_at' then Project.order("created_at #{sort}")
|
||||
when 'last_activity_at' then Project.order("last_activity_at #{sort}")
|
||||
else Project
|
||||
end
|
||||
|
||||
@projects = Project.all
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = paginate @projects
|
||||
present @projects, with: Entities::Project
|
||||
end
|
||||
|
|
|
@ -32,14 +32,14 @@ describe "Admin::Users", feature: true do
|
|||
|
||||
it "should apply defaults to user" do
|
||||
click_button "Create user"
|
||||
user = User.last
|
||||
user = User.find_by(username: 'bang')
|
||||
user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
|
||||
user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
|
||||
end
|
||||
|
||||
it "should create user with valid data" do
|
||||
click_button "Create user"
|
||||
user = User.last
|
||||
user = User.find_by(username: 'bang')
|
||||
user.name.should == "Big Bang"
|
||||
user.email.should == "bigbang@mail.com"
|
||||
end
|
||||
|
@ -52,7 +52,7 @@ describe "Admin::Users", feature: true do
|
|||
|
||||
it "should send valid email to user with email & password" do
|
||||
click_button "Create user"
|
||||
user = User.last
|
||||
user = User.find_by(username: 'bang')
|
||||
email = ActionMailer::Base.deliveries.last
|
||||
email.subject.should have_content("Account was created")
|
||||
email.text_part.body.should have_content(user.email)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Issues", feature: true do
|
||||
include SortingHelper
|
||||
|
||||
let(:project) { create(:project) }
|
||||
|
||||
before do
|
||||
|
@ -80,7 +82,7 @@ describe "Issues", feature: true do
|
|||
title: title)
|
||||
end
|
||||
|
||||
@issue = Issue.first # with title 'foobar'
|
||||
@issue = Issue.find_by(title: 'foobar')
|
||||
@issue.milestone = create(:milestone, project: project)
|
||||
@issue.assignee = nil
|
||||
@issue.save
|
||||
|
@ -130,14 +132,14 @@ describe "Issues", feature: true do
|
|||
let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') }
|
||||
|
||||
it 'sorts by newest' do
|
||||
visit project_issues_path(project, sort: 'newest')
|
||||
visit project_issues_path(project, sort: sort_value_recently_created)
|
||||
|
||||
first_issue.should include("foo")
|
||||
last_issue.should include("baz")
|
||||
end
|
||||
|
||||
it 'sorts by oldest' do
|
||||
visit project_issues_path(project, sort: 'oldest')
|
||||
visit project_issues_path(project, sort: sort_value_oldest_created)
|
||||
|
||||
first_issue.should include("baz")
|
||||
last_issue.should include("foo")
|
||||
|
@ -146,7 +148,7 @@ describe "Issues", feature: true do
|
|||
it 'sorts by most recently updated' do
|
||||
baz.updated_at = Time.now + 100
|
||||
baz.save
|
||||
visit project_issues_path(project, sort: 'recently_updated')
|
||||
visit project_issues_path(project, sort: sort_value_recently_updated)
|
||||
|
||||
first_issue.should include("baz")
|
||||
end
|
||||
|
@ -154,7 +156,7 @@ describe "Issues", feature: true do
|
|||
it 'sorts by least recently updated' do
|
||||
baz.updated_at = Time.now - 100
|
||||
baz.save
|
||||
visit project_issues_path(project, sort: 'last_updated')
|
||||
visit project_issues_path(project, sort: sort_value_oldest_updated)
|
||||
|
||||
first_issue.should include("baz")
|
||||
end
|
||||
|
@ -168,13 +170,13 @@ describe "Issues", feature: true do
|
|||
end
|
||||
|
||||
it 'sorts by recently due milestone' do
|
||||
visit project_issues_path(project, sort: 'milestone_due_soon')
|
||||
visit project_issues_path(project, sort: sort_value_milestone_soon)
|
||||
|
||||
first_issue.should include("foo")
|
||||
end
|
||||
|
||||
it 'sorts by least recently due milestone' do
|
||||
visit project_issues_path(project, sort: 'milestone_due_later')
|
||||
visit project_issues_path(project, sort: sort_value_milestone_later)
|
||||
|
||||
first_issue.should include("bar")
|
||||
end
|
||||
|
@ -191,7 +193,7 @@ describe "Issues", feature: true do
|
|||
end
|
||||
|
||||
it 'sorts with a filter applied' do
|
||||
visit project_issues_path(project, sort: 'oldest', assignee_id: user2.id)
|
||||
visit project_issues_path(project, sort: sort_value_oldest_created, assignee_id: user2.id)
|
||||
|
||||
first_issue.should include("bar")
|
||||
last_issue.should include("foo")
|
||||
|
|
|
@ -474,7 +474,7 @@ describe User do
|
|||
@user = create :user, created_at: Date.today, last_sign_in_at: Date.today, name: 'Alpha'
|
||||
@user1 = create :user, created_at: Date.today - 1, last_sign_in_at: Date.today - 1, name: 'Omega'
|
||||
end
|
||||
|
||||
|
||||
it "sorts users as recently_signed_in" do
|
||||
User.sort('recent_sign_in').first.should == @user
|
||||
end
|
||||
|
@ -484,11 +484,11 @@ describe User do
|
|||
end
|
||||
|
||||
it "sorts users as recently_created" do
|
||||
User.sort('recently_created').first.should == @user
|
||||
User.sort('created_desc').first.should == @user
|
||||
end
|
||||
|
||||
it "sorts users as late_created" do
|
||||
User.sort('late_created').first.should == @user1
|
||||
User.sort('created_asc').first.should == @user1
|
||||
end
|
||||
|
||||
it "sorts users by name when nil is passed" do
|
||||
|
|
|
@ -26,30 +26,34 @@ describe API::API, api: true do
|
|||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.length.should == 3
|
||||
json_response.first['title'].should == merge_request.title
|
||||
json_response.last['title'].should == merge_request.title
|
||||
end
|
||||
|
||||
it "should return an array of all merge_requests" do
|
||||
get api("/projects/#{project.id}/merge_requests?state", user)
|
||||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.length.should == 3
|
||||
json_response.first['title'].should == merge_request.title
|
||||
json_response.last['title'].should == merge_request.title
|
||||
end
|
||||
|
||||
it "should return an array of open merge_requests" do
|
||||
get api("/projects/#{project.id}/merge_requests?state=opened", user)
|
||||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.length.should == 1
|
||||
json_response.first['title'].should == merge_request.title
|
||||
json_response.last['title'].should == merge_request.title
|
||||
end
|
||||
|
||||
it "should return an array of closed merge_requests" do
|
||||
get api("/projects/#{project.id}/merge_requests?state=closed", user)
|
||||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.length.should == 2
|
||||
json_response.first['title'].should == merge_request_closed.title
|
||||
json_response.second['title'].should == merge_request_merged.title
|
||||
json_response.second['title'].should == merge_request_closed.title
|
||||
json_response.first['title'].should == merge_request_merged.title
|
||||
end
|
||||
|
||||
it "should return an array of merged merge_requests" do
|
||||
get api("/projects/#{project.id}/merge_requests?state=merged", user)
|
||||
response.status.should == 200
|
||||
|
@ -69,9 +73,10 @@ describe API::API, api: true do
|
|||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.length.should == 3
|
||||
json_response.first['id'].should == @mr_earlier.id
|
||||
json_response.last['id'].should == @mr_later.id
|
||||
json_response.last['id'].should == @mr_earlier.id
|
||||
json_response.first['id'].should == @mr_later.id
|
||||
end
|
||||
|
||||
it "should return an array of merge_requests in descending order" do
|
||||
get api("/projects/#{project.id}/merge_requests?sort=desc", user)
|
||||
response.status.should == 200
|
||||
|
@ -80,21 +85,23 @@ describe API::API, api: true do
|
|||
json_response.first['id'].should == @mr_later.id
|
||||
json_response.last['id'].should == @mr_earlier.id
|
||||
end
|
||||
|
||||
it "should return an array of merge_requests ordered by updated_at" do
|
||||
get api("/projects/#{project.id}/merge_requests?order_by=updated_at", user)
|
||||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.length.should == 3
|
||||
json_response.first['id'].should == @mr_earlier.id
|
||||
json_response.last['id'].should == @mr_later.id
|
||||
json_response.last['id'].should == @mr_earlier.id
|
||||
json_response.first['id'].should == @mr_later.id
|
||||
end
|
||||
|
||||
it "should return an array of merge_requests ordered by created_at" do
|
||||
get api("/projects/#{project.id}/merge_requests?sort=created_at", user)
|
||||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.length.should == 3
|
||||
json_response.first['id'].should == @mr_earlier.id
|
||||
json_response.last['id'].should == @mr_later.id
|
||||
json_response.last['id'].should == @mr_earlier.id
|
||||
json_response.first['id'].should == @mr_later.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue