增加项目和用户的排序功能

This commit is contained in:
nieguanghui 2013-08-28 09:34:54 +08:00
parent cce0b299b7
commit fa27d3bf32
12 changed files with 338 additions and 82 deletions

View File

@ -282,6 +282,7 @@ class AccountController < ApplicationController
def register_by_email_activation(user, &block) def register_by_email_activation(user, &block)
token = Token.new(:user => user, :action => "register") token = Token.new(:user => user, :action => "register")
if user.save and token.save if user.save and token.save
UserStatus.create(:user_id => user.id)
Mailer.register(token).deliver Mailer.register(token).deliver
flash[:notice] = l(:notice_account_register_done) flash[:notice] = l(:notice_account_register_done)
redirect_to signin_path redirect_to signin_path
@ -298,6 +299,7 @@ class AccountController < ApplicationController
user.activate user.activate
user.last_login_on = Time.now user.last_login_on = Time.now
if user.save if user.save
UserStatus.create(:user_id => user.id)
self.logged_user = user self.logged_user = user
flash[:notice] = l(:notice_account_activated) flash[:notice] = l(:notice_account_activated)
redirect_to my_account_path redirect_to my_account_path
@ -311,6 +313,7 @@ class AccountController < ApplicationController
# Pass a block for behavior when a user fails to save # Pass a block for behavior when a user fails to save
def register_manually_by_administrator(user, &block) def register_manually_by_administrator(user, &block)
if user.save if user.save
UserStatus.create(:user_id => user.id)
# Sends an email to the administrators # Sends an email to the administrators
Mailer.account_activation_request(user).deliver Mailer.account_activation_request(user).deliver
account_pending account_pending

View File

@ -14,7 +14,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ProjectsController < ApplicationController class ProjectsController < ApplicationController
layout 'base_projects'# by young layout 'base_projects'# by young
menu_item :overview menu_item :overview
@ -51,32 +50,32 @@ class ProjectsController < ApplicationController
helper :activities helper :activities
helper :documents helper :documents
helper :watchers helper :watchers
# helper :watcherlist # helper :watcherlist
### added by william ### added by william
include ActsAsTaggableOn::TagsHelper include ActsAsTaggableOn::TagsHelper
# Lists visible projects # Lists visible projects
# def index # def index
# respond_to do |format| # respond_to do |format|
# format.html { # format.html {
# scope = Project # scope = Project
# unless params[:closed] # unless params[:closed]
# scope = scope.active # scope = scope.active
# end # end
# @projects = scope.visible.order('lft').all # @projects = scope.visible.order('lft').all
# } # }
# format.api { # format.api {
# @offset, @limit = api_offset_and_limit # @offset, @limit = api_offset_and_limit
# @project_count = Project.visible.count # @project_count = Project.visible.count
# @projects = Project.visible.offset(@offset).limit(@limit).order('lft').all # @projects = Project.visible.offset(@offset).limit(@limit).order('lft').all
# } # }
# format.atom { # format.atom {
# projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all # projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all
# render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}") # render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}")
# } # }
# end # end
# end # end
def index def index
#Modified by nie #Modified by nie
@ -89,33 +88,79 @@ class ProjectsController < ApplicationController
@offset, @limit = api_offset_and_limit({:limit => 10}) @offset, @limit = api_offset_and_limit({:limit => 10})
@projects = Project.visible @projects = Project.visible
# @projects.each do |project| # @projects.each do |project|
# @admin = project.users_by_role[Role.find(3)] # @admin = project.users_by_role[Role.find(3)]
# unless @admin.nil? # unless @admin.nil?
# @admin.each do |user| # @admin.each do |user|
# ProjectInfo.create(:user_id => user.id, :project_id => project.id) # ProjectInfo.create(:user_id => user.id, :project_id => project.id)
# end # end
# #
# end # end
# end
# @projects.each do |project|
# ProjectStatus.create(:changesets_count => project.changesets.count, :project_id => project.id, :watchers_count => project.watcher_users.count)
# end # end
@projects = Project.visible.like(params[:name]) if params[:name].present? @projects = Project.visible.like(params[:name]) if params[:name].present?
@project_count = @projects.count @project_count = @projects.count
@project_pages = Paginator.new @project_count, @limit, params['page'] @project_pages = Paginator.new @project_count, @limit, params['page']
@offset ||= @project_pages.offset
@projects = @projects.offset(@offset).limit(@limit).order('created_on DESC').all @offset ||= @project_pages.reverse_offset
#@projects = @projects.offset(@offset).limit(@limit).order('created_on DESC').all
if params[:project_sort_type].present?
case params[:project_sort_type]
when '0'
@offset ||= @project_pages.reverse_offset
unless @offset == 0
@projects = @projects.offset(@offset).limit(@limit).all.reverse
else
limit = @project_count % @limit
@projects = @projects.offset(@offset).limit(limit).all.reverse
end
# @projects = @projects.sort {|x,y| y.created_on <=> x.created_on }
# @projects = @projects[@offset, @limit]
when '1'
@offset ||= @project_pages.reverse_offset
unless @offset == 0
@projects = @projects.includes(:project_status).reorder('project_statuses.changesets_count').offset(@offset).limit(@limit).all.reverse
else
limit = @project_count % @limit
@projects = @projects.includes(:project_status).reorder('project_statuses.changesets_count').offset(@offset).limit(limit).all.reverse
end
#@projects = @projects[@offset, @limit]
when '2'
@offset ||= @project_pages.reverse_offset
unless @offset == 0
@projects = @projects.includes(:project_status).reorder('project_statuses.watchers_count').offset(@offset).limit(@limit).all.reverse
else
limit = @project_count % @limit
@projects = @projects.includes(:project_status).reorder('project_statuses.watchers_count').offset(@offset).limit(limit).all.reverse
end
end
else
@offset ||= @project_pages.reverse_offset
unless @offset == 0
@projects = @projects.offset(@offset).limit(@limit).all.reverse
else
limit = @project_count % @limit
@projects = @projects.offset(@offset).limit(limit).all.reverse
end
# @projects = @projects.sort {|x,y| y.created_on <=> x.created_on }
# @projects = @projects[@offset, @limit]
end
#end #end
respond_to do |format| respond_to do |format|
format.html { format.html {
render :layout => 'base' render :layout => 'base'
scope = Project scope = Project
unless params[:closed] unless params[:closed]
scope = scope.active scope = scope.active
end end
@projects = scope.visible.offset(@offset).limit(@limit).order('created_on DESC').all
} }
format.api { format.api {
# @offset, @limit = api_offset_and_limit # @offset, @limit = api_offset_and_limit
# @project_count = Project.visible.count # @project_count = Project.visible.count
# @projects = Project.visible.offset(@offset).limit(@limit).order('lft').all # @projects = Project.visible.offset(@offset).limit(@limit).order('lft').all
} }
format.atom { format.atom {
projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all
@ -155,8 +200,9 @@ class ProjectsController < ApplicationController
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => User.current, :roles => [r]) m = Member.new(:user => User.current, :roles => [r])
project = ProjectInfo.new(:user_id => User.current.id, :project_id => @project.id) project = ProjectInfo.new(:user_id => User.current.id, :project_id => @project.id)
@project.members << m project_status = ProjectStatus.create(:project_id => @project.id)
@project.project_infos << project @project.members << m
@project.project_infos << project
end end
respond_to do |format| respond_to do |format|
format.html { format.html {
@ -203,15 +249,15 @@ class ProjectsController < ApplicationController
end end
end end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
# source_project not found # source_project not found
render_404 render_404
end end
# Show @project # Show @project
def show def show
# try to redirect to the requested menu item # try to redirect to the requested menu item
if params[:jump] && redirect_to_project_menu_item(@project, params[:jump]) if params[:jump] && redirect_to_project_menu_item(@project, params[:jump])
return return
end end
@users_by_role = @project.users_by_role @users_by_role = @project.users_by_role
@ -229,7 +275,7 @@ class ProjectsController < ApplicationController
end end
@key = User.current.rss_key @key = User.current.rss_key
#新增内容 #新增内容
@days = Setting.activity_days_default.to_i @days = Setting.activity_days_default.to_i
if params[:from] if params[:from]
@ -246,12 +292,12 @@ class ProjectsController < ApplicationController
@date_from = @date_to - @days @date_from = @date_to - @days
@with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
@author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id])) @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id]))
# 决定显示所用用户或单个用户活动 # 决定显示所用用户或单个用户活动
@activity = Redmine::Activity::Fetcher.new(User.current, :project => @project, @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
:with_subprojects => @with_subprojects, :with_subprojects => @with_subprojects,
:author => @author) :author => @author)
@activity.scope_select {|t| !has["show_#{t}"].nil?} @activity.scope_select {|t| !has["show_#{t}"].nil?}
# @activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty? # @activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty?
#Added by young #Added by young
events = @activity.events(@date_from, @date_to) events = @activity.events(@date_from, @date_to)
@ -262,8 +308,8 @@ class ProjectsController < ApplicationController
events = events.slice(@offset,@limit) events = events.slice(@offset,@limit)
#Ended by young #Ended by young
@events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)} @events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)}
# documents # documents
@sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category' @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
documents = @project.documents.includes(:attachments, :category).all documents = @project.documents.includes(:attachments, :category).all
case @sort_by case @sort_by
when 'date' when 'date'
@ -273,17 +319,16 @@ class ProjectsController < ApplicationController
when 'author' when 'author'
@grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author} @grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
else else
@grouped = documents.group_by(&:category) @grouped = documents.group_by(&:category)
end end
@document = @project.documents.build @document = @project.documents.build
# #
respond_to do |format| respond_to do |format|
format.html format.html
format.api format.api
end end
end end
def settings def settings
@issue_custom_fields = IssueCustomField.sorted.all @issue_custom_fields = IssueCustomField.sorted.all
@issue_category ||= IssueCategory.new @issue_category ||= IssueCategory.new
@ -299,7 +344,6 @@ class ProjectsController < ApplicationController
def member def member
end end
def file def file
end end
@ -369,9 +413,9 @@ class ProjectsController < ApplicationController
format.html { redirect_to admin_projects_path } format.html { redirect_to admin_projects_path }
format.api { render_api_ok } format.api { render_api_ok }
end end
else else
render :layout => "base" render :layout => "base"
end end
# hide project in layout # hide project in layout
@project = nil @project = nil
end end
@ -387,18 +431,17 @@ class ProjectsController < ApplicationController
parent = parent_id.blank? ? nil : Project.find_by_id(parent_id.to_i) parent = parent_id.blank? ? nil : Project.find_by_id(parent_id.to_i)
unless @project.allowed_parents.include?(parent) unless @project.allowed_parents.include?(parent)
@project.errors.add :parent_id, :invalid @project.errors.add :parent_id, :invalid
return false return false
end end
end end
true true
end end
end
# added by huang # added by huang
def watcherlist
def watcherlist
if @watched if @watched
@users -= watched.watcher_users @users -= watched.watcher_users
end end
end
end end
# end

View File

@ -138,7 +138,7 @@ class UsersController < ApplicationController
end end
#end #end
def index def index
sort_init 'login', 'asc' sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on) sort_update %w(login firstname lastname mail admin created_on last_login_on)
@ -158,12 +158,57 @@ class UsersController < ApplicationController
scope = User.logged.status(@status) scope = User.logged.status(@status)
scope = scope.like(params[:name]) if params[:name].present? scope = scope.like(params[:name]) if params[:name].present?
scope = scope.in_group(params[:group_id]) if params[:group_id].present? scope = scope.in_group(params[:group_id]) if params[:group_id].present?
# scope.each do |user|
# UserStatus.create(:changesets_count => user.changesets.count, :watchers_count => user.watcher_users.count, :user_id => user.id)
# end
@user_count = scope.count @user_count = scope.count
@user_pages = Paginator.new @user_count, @limit, params['page'] @user_pages = Paginator.new @user_count, @limit, params['page']
@offset ||= @user_pages.offset #@offset ||= @user_pages.offset
@users = scope.order(sort_clause).limit(@limit).offset(@offset).all #@users = scope.order(sort_clause).limit(@limit).offset(@offset).all
@user_base_tag = params[:id]?'base_users':'base' @user_base_tag = params[:id]?'base_users':'base'
if params[:user_sort_type].present?
case params[:user_sort_type]
when '0'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users = scope.offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
@users = scope.offset(@offset).limit(limit).all.reverse
end
# @projects = @projects.sort {|x,y| y.created_on <=> x.created_on }
# @projects = @projects[@offset, @limit]
when '1'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users = scope.includes(:user_status).reorder('user_statuses.changesets_count').offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
@users = scope.includes(:user_status).reorder('user_statuses.changesets_count').offset(@offset).limit(limit).all.reverse
end
#sort {|x,y| y.user_status.changesets_count <=> x.user_status.changesets_count}
#@users = @users[@offset, @limit]
when '2'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users = scope.includes(:user_status).reorder('user_statuses.watchers_count').offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
@users = scope.includes(:user_status).reorder('user_statuses.watchers_count').offset(@offset).limit(limit).all.reverse
end
#@users = @users[@offset, @limit]
end
else
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users = scope.offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
@users = scope.offset(@offset).limit(limit).all.reverse
end
# @projects = @projects.sort {|x,y| y.created_on <=> x.created_on }
# @projects = @projects[@offset, @limit]
end
respond_to do |format| respond_to do |format|
format.html { format.html {
@groups = Group.all.sort @groups = Group.all.sort

View File

@ -23,6 +23,11 @@ class Changeset < ActiveRecord::Base
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
# end # end
#Added by nie
has_one :project_status, :dependent => :destroy
has_one :users_status
#end
has_and_belongs_to_many :issues has_and_belongs_to_many :issues
has_and_belongs_to_many :parents, has_and_belongs_to_many :parents,
:class_name => "Changeset", :class_name => "Changeset",

View File

@ -57,7 +57,6 @@ class Project < ActiveRecord::Base
#ADDED BY NIE #ADDED BY NIE
has_many :project_infos, :dependent => :destroy has_many :project_infos, :dependent => :destroy
has_one :project_status, :class_name => "ProjectStatus", :dependent => :destroy has_one :project_status, :class_name => "ProjectStatus", :dependent => :destroy
#end #end
has_one :wiki, :dependent => :destroy has_one :wiki, :dependent => :destroy
# Custom field for the project issues # Custom field for the project issues

View File

@ -18,6 +18,10 @@
class Watcher < ActiveRecord::Base class Watcher < ActiveRecord::Base
belongs_to :watchable, :polymorphic => true belongs_to :watchable, :polymorphic => true
belongs_to :user belongs_to :user
#Added by nie
has_one :project_status
has_one :users_status
#end
validates_presence_of :user validates_presence_of :user
validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id] validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id]

View File

@ -19,6 +19,21 @@
</div> </div>
<%end%> <%end%>
<div class="pagination" style="border-bottom: 1px solid rgb(223,223,223); width: 95%; margin-left: 2%; margin-top: 15px" >
<ul style="margin-right:0px">
<li>
<%= link_to l(:label_sort_by_time), projects_path(:project_sort_type => '0') %>
</li>
<li>
<%= link_to l(:label_sort_by_active), projects_path(:project_sort_type => '1') %>
</li>
<li>
<%= link_to l(:label_sort_by_influence), projects_path(:project_sort_type => '2') %>
</li>
</ul>
</div>
<div id="projects-index"> <div id="projects-index">
<%= render_project_hierarchy(@projects)%> <%= render_project_hierarchy(@projects)%>
</div> </div>

View File

@ -86,6 +86,21 @@
</div> </div>
&nbsp; &nbsp;
<div class="pagination" style="border-bottom: 1px solid rgb(223,223,223); width: 95%; margin-left: 2%; margin-top: 0px">
<ul style="margin-right:0px">
<li>
<%= link_to l(:label_sort_by_time), users_path(:user_sort_type => '0') %>
</li>
<li>
<%= link_to l(:label_sort_by_active), users_path(:user_sort_type => '1') %>
</li>
<li>
<%= link_to l(:label_sort_by_influence), users_path(:user_sort_type => '2') %>
</li>
</ul>
</div>
<div class="autoscroll"> <div class="autoscroll">
<% for user in @users -%> <% for user in @users -%>
<% unless user.id == 1%> <% unless user.id == 1%>

View File

@ -0,0 +1,9 @@
class CreateProjectStatuses < ActiveRecord::Migration
def change
create_table :project_statuses do |t|
t.integer :changesets_count
t.integer :watchers_count
t.integer :project_id
end
end
end

View File

@ -0,0 +1,11 @@
class CreateUserStatuses < ActiveRecord::Migration
def change
create_table :user_statuses do |t|
t.integer :changesets_count
t.integer :watchers_count
t.integer :user_id
t.timestamps
end
end
end

View File

@ -0,0 +1,76 @@
class StoredStatusProcedure < ActiveRecord::Migration
def up
#sql = <<- END_OF_SQL_CODE
execute "
create procedure `sp_user_status_cursor`()
begin
declare v_uid bigint(22);
declare v int(10);
declare _done TINYINT(1) default 0;
declare cur_user cursor for select user_id, count(*) from changesets where user_id != '' group by user_id;
declare continue handler for not found set _done = 1;
open cur_user;
loop_xxx:loop
fetch cur_user into v_uid,v;
if _done=1 then
leave loop_xxx;
end if;
begin
update user_statuses set changesets_count = v where user_id = v_uid;
commit;
end;
end loop;
end;
"
execute "
create event if not exists e_test
on schedule every 1 day starts'2013_08_27 01:50:00'
on completion preserve
do call `sp_user_status_cursor`();
"
execute "
create procedure `sp_project_status_cursor`()
begin
declare v_uid bigint(22);
declare v int(10);
declare _done TINYINT(1) default 0;
declare cur_user cursor for select project_id,count(*) from (select project_id,repositories.id from repositories inner join changesets where repositories.id = changesets.repository_id)t group by project_id;
declare continue handler for not found set _done = 1;
open cur_user;
loop_xxx:loop
fetch cur_user into v_uid,v;
if _done=1 then
leave loop_xxx;
end if;
begin
update project_statuses set changesets_count = v where project_id = v_uid;
commit;
end;
end loop;
end;
"
execute "
create event if not exists e_project_status_test
on schedule every 1 day starts'2013_08_27 01:50:00'
on completion preserve
do call `sp_project_status_cursor`();
"
execute "
set global event_scheduler = on;
"
end
def down
execute " drop procedure if exists `sp_user_status_cursor`;
"
execute "
drop event if exists e_test;
"
execute "
drop procedure if exists `sp_project_status_cursor`;
"
execute "
drop event if exists e_project_status_test;
"
end
end

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130819020004) do ActiveRecord::Schema.define(:version => 20130828004955) do
create_table "a_user_watchers", :force => true do |t| create_table "a_user_watchers", :force => true do |t|
t.string "name" t.string "name"
@ -445,6 +445,23 @@ ActiveRecord::Schema.define(:version => 20130819020004) do
t.string "salt", :null => false t.string "salt", :null => false
end end
create_table "permissions", :force => true do |t|
t.string "controller", :limit => 30, :default => "", :null => false
t.string "action", :limit => 30, :default => "", :null => false
t.string "description", :limit => 60, :default => "", :null => false
t.boolean "is_public", :default => false, :null => false
t.integer "sort", :default => 0, :null => false
t.boolean "mail_option", :default => false, :null => false
t.boolean "mail_enabled", :default => false, :null => false
end
create_table "permissions_roles", :id => false, :force => true do |t|
t.integer "permission_id", :default => 0, :null => false
t.integer "role_id", :default => 0, :null => false
end
add_index "permissions_roles", ["role_id"], :name => "permissions_roles_role_id"
create_table "praise_tread_caches", :force => true do |t| create_table "praise_tread_caches", :force => true do |t|
t.integer "object_id", :null => false t.integer "object_id", :null => false
t.string "object_type" t.string "object_type"
@ -470,6 +487,12 @@ ActiveRecord::Schema.define(:version => 20130819020004) do
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
end end
create_table "project_statuses", :force => true do |t|
t.integer "changesets_count"
t.integer "watchers_count"
t.integer "project_id"
end
create_table "project_tags", :force => true do |t| create_table "project_tags", :force => true do |t|
t.integer "project_id" t.integer "project_id"
t.integer "tag_id" t.integer "tag_id"
@ -648,6 +671,14 @@ ActiveRecord::Schema.define(:version => 20130819020004) do
add_index "user_preferences", ["user_id"], :name => "index_user_preferences_on_user_id" add_index "user_preferences", ["user_id"], :name => "index_user_preferences_on_user_id"
create_table "user_statuses", :force => true do |t|
t.integer "changesets_count"
t.integer "watchers_count"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "user_tags", :force => true do |t| create_table "user_tags", :force => true do |t|
t.integer "user_id" t.integer "user_id"
t.integer "tag_id" t.integer "tag_id"