diff --git a/Gemfile b/Gemfile index 644265209..4f2f47682 100644 --- a/Gemfile +++ b/Gemfile @@ -29,6 +29,8 @@ group :development do gem 'grape-swagger' #gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git' #gem 'puma' + gem 'pry-rails' + gem 'pry-byebug' gem 'better_errors', path: 'lib/better_errors' gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler' end @@ -52,8 +54,8 @@ group :test do #end end - gem 'rspec-rails' , '2.13.1' - gem 'guard-rspec','2.5.0' + # gem 'rspec-rails' , '2.13.1' + # gem 'guard-rspec','2.5.0' # Gems used only for assets and not required # in production environments by default. group :assets do @@ -97,7 +99,7 @@ if File.exist?(database_file) adapters.each do |adapter| case adapter when 'mysql2' - gem "mysql2", "= 0.3.11", :platforms => [:mri, :mingw] + gem "mysql2", "= 0.3.18", :platforms => [:mri, :mingw] gem "activerecord-jdbcmysql-adapter", :platforms => :jruby when 'mysql' gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw] diff --git a/app/api/mobile/apis/auth.rb b/app/api/mobile/apis/auth.rb index 320497e50..fbec9a3b0 100644 --- a/app/api/mobile/apis/auth.rb +++ b/app/api/mobile/apis/auth.rb @@ -40,6 +40,17 @@ module Mobile {status: 0} end + desc "忘记密码" + params do + requires :mail,type: String + end + post 'lost_password' do + us = UsersService.new + message = us.lost_password params + present :message, message + present :status, 0 + end + end end end diff --git a/app/api/mobile/apis/upgrade.rb b/app/api/mobile/apis/upgrade.rb index e6a7916d9..9ce1831f3 100644 --- a/app/api/mobile/apis/upgrade.rb +++ b/app/api/mobile/apis/upgrade.rb @@ -15,7 +15,7 @@ module Mobile if attachment.nil? raise '未发现客户端!' end - url = Setting.host_name + "/attachments/download/" + attachment.id.to_s + "/" + attachment.filename + url = "http://" + Setting.host_name + "/attachments/download/" + attachment.id.to_s + "/" + attachment.filename { version: @current_version.version, url: url, diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index ccab34283..23b080d94 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -20,9 +20,9 @@ class AttachmentsController < ApplicationController before_filter :find_project, :only => [:show, :download, :thumbnail, :destroy, :delete_homework]#, :except => [:upload, :autocomplete] before_filter :file_readable, :read_authorize, :only => [:show, :thumbnail]#Modified by young - before_filter :delete_authorize, :only => :destroy - before_filter :authorize_global, :only => :upload - before_filter :authorize_attachment_download1, :only => :download + before_filter :delete_authorize, :only => [:destroy] + before_filter :authorize_global, :only => [:upload] + before_filter :authorize_attachment_download1, :only => [:download] #before_filter :login_without_softapplication, only: [:download] accept_api_auth :show, :download, :upload require 'iconv' @@ -97,12 +97,10 @@ class AttachmentsController < ApplicationController end if candown || User.current.admin? || User.current.id == @attachment.author_id @attachment.increment_download - if stale?(:etag => @attachment.digest) - # images are sent inline send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename), :type => detect_content_type(@attachment), - :disposition => (@attachment.image? ? 'inline' : 'attachment') + :disposition => 'attachment' #inline can open in browser end else diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index aacb32990..28156ac0c 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -99,6 +99,7 @@ class FilesController < ApplicationController end def index + @flag = params[:flag] || false #sort_init 'filename', 'asc' sort_init 'created_on', 'desc' sort_update 'created_on' => "#{Attachment.table_name}.created_on", @@ -144,11 +145,16 @@ class FilesController < ApplicationController end end - @containers = [ Project.includes(:attachments).reorder(sort).find(@project.id)] - @containers += @project.versions.includes(:attachments).reorder(sort).all + @containers = [ Project.includes(:attachments).find(@project.id)] + @containers += @project.versions.includes(:attachments).all - show_attachments @containers + ids = [] + @containers.each do |c| + ids += c.attachments.pluck(:id) + end + @containers = [Struct.new(:attachments).new(Attachment.where('id in (?)',ids).reorder(sort))] + show_attachments @containers respond_to do |format| format.html diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index ce899eff5..ba312c74a 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -99,7 +99,7 @@ class MembersController < ApplicationController @project.members << members # added by nie @project.project_infos << project_info - @project.user_grades << user_grades + @project.user_grades << user_grades unless user_grades.first.user_id.nil? # end end if members.present? && members.all? { |m| m.valid? } @@ -107,17 +107,28 @@ class MembersController < ApplicationController AppliedProject.deleteappiled(member.user_id, @project.id) end end - respond_to do |format| - format.html { redirect_to_settings_in_projects } - format.js { @members = members; @applied_members = applied_members; } - format.api { - @member = members.first - if @member.valid? - render :action => 'show', :status => :created, :location => membership_url(@member) - else - render_validation_errors(@member) - end - } + if params[:flag] + unless members.present? && members.all? {|m| m.valid? } + flash[:error] = members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ') + else + flash[:notice] = l(:label_invite_success) + end + respond_to do |format| + format.html { redirect_to invite_members_project_url(@project) } + end + else + respond_to do |format| + format.html { redirect_to_settings_in_projects } + format.js { @members = members; @applied_members = applied_members; } + format.api { + @member = members.first + if @member.valid? + render :action => 'show', :status => :created, :location => membership_url(@member) + else + render_validation_errors(@member) + end + } + end end elsif @course course_info = [] @@ -310,6 +321,7 @@ class MembersController < ApplicationController end def autocomplete + @flag = params[:flag] || false respond_to do |format| format.js end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 61d89a553..44e5fd8a3 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -334,30 +334,41 @@ class ProjectsController < ApplicationController end def send_mail_to_member - - if !params[:mail].nil? && User.find_by_mail(params[:mail].to_s).nil? + if !params[:mail].blank? && User.find_by_mail(params[:mail].to_s).nil? email = params[:mail] Mailer.send_invite_in_project(email, @project, User.current).deliver @is_zhuce =false + flash[:notice] = l(:notice_email_sent, :value => email) else @is_zhuce = true end respond_to do |format| - format.js + format.html{redirect_to invite_members_by_mail_project_url(@project)} end end #发送邮件邀请新用户 def invite_members_by_mail - @is_zhuce =false - respond_to do |format| - format.html - format.js + if User.current.member_of?(@project) || User.current.admin? + @is_zhuce = false + respond_to do |format| + format.html + format.js + end + else + render_403 end end # 邀请Trustie注册用户 def invite_members - @member ||= @project.members.new + if User.current.member_of?(@project) || User.current.admin? + @member ||= @project.members.new + respond_to do |format| + format.html + end + else + render_403 + end end def edit diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 290af0068..949ddd643 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -28,7 +28,8 @@ class WelcomeController < ApplicationController # 企业版定制: params[:project]为传过来的参数 unless params[:organization].nil? @organization = Organization.find params[:organization] - @organization_projects = Project.visible.joins(:project_status).joins("LEFT JOIN project_scores ON projects.id = project_scores.project_id").where("projects.organization_id = ?", @organization.id).order("score DESC").limit(10).all + # @organization_projects = Project.joins(:project_status).joins("LEFT JOIN project_scores ON projects.id = project_scores.project_id").where("projects.organization_id = ?", @organization.id).order("score DESC").limit(10).all + @organization_projects = @organization.projects.visible.joins("LEFT JOIN project_scores ON projects.id = project_scores.project_id").order("project_scores.score DESC").limit(10).all @part_projects = @organization_projects.count < 9 ? find_miracle_project( 9 - @organization_projects.count, 3,"score desc") : [] # @cur_projects = Project.find(params[:organization]) # @organization = @cur_projects.enterprise_name diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 30b2e7a21..9629ed437 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -490,6 +490,15 @@ module ApplicationHelper s.html_safe end + #项目成员列表复选框生成 + def project_member_check_box_tags_ex name, principals + s = '' + principals.each do |principal| + s << "
  • #{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id)}
  • \n" + end + s.html_safe + end + #扩展的checkbox生成 def principals_check_box_tags_ex(name, principals) s = '' @@ -1198,6 +1207,17 @@ module ApplicationHelper html_safe end + def wiki_simple_format_without_paragraph(text) + text.to_s. + gsub(/\r\n?/, "\n"). # \r\n and \r -> \n + gsub(/\n\n+/, "

    "). # 2+ newline -> 2 br + gsub(/([^\n]\n)(?=[^\n])/, '\1
    '). # 1 newline -> br + gsub("&nbsp", " "). #gsub(/<\/?.*?>/,""). + gsub(/<\/?.*?>/, ""). + gsub(""", "'"). + html_safe + end + def lang_options_for_select(blank=true) { 'Chinese简体中文 '=> 'zh', :English => :en} end diff --git a/app/helpers/files_helper.rb b/app/helpers/files_helper.rb index aace20e6c..9eff409ff 100644 --- a/app/helpers/files_helper.rb +++ b/app/helpers/files_helper.rb @@ -48,7 +48,7 @@ module FilesHelper def courses_check_box_tags(name,courses,current_course,attachment) s = '' courses.each do |course| - if !(attachment.container_type && attachment.container_id == course.id) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course) + if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course) s << " [#{get_course_term course}]
    " end end diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index 6c11199fb..ed18b7ae4 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -23,15 +23,22 @@ module MembersHelper principal_count = scope.count principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] #by young principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all - s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals') - links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options| link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true } - s + content_tag('div', content_tag('ul', links), :class => 'pagination_new') + end + #获取项目可邀请的成员列表 + def render_project_members project + scope = Principal.active.sorted.not_member_of(project).like(params[:q]) + principals = paginateHelper scope,10 + s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :style => "margin-left: -40px;") + links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options| + link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true + } + s + content_tag('ul', links,:class => 'wlist') end # add by nwb @@ -71,4 +78,18 @@ module MembersHelper s + content_tag('div', content_tag('ul', links), :class => 'applied_new') end + private + def paginateHelper obj, pre_size=20 + @obj_count = obj.count + @obj_pages = Redmine::Pagination::Paginator.new @obj_count, pre_size, params['page'] + if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation + obj.limit(@obj_pages.per_page).offset(@obj_pages.offset) + elsif obj.kind_of? Array + obj[@obj_pages.offset, @obj_pages.per_page] + else + logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}" + raise RuntimeError, 'unknow type, Please input you type into this helper.' + end + end + end diff --git a/app/helpers/watchers_helper.rb b/app/helpers/watchers_helper.rb index 971bf603d..b9e658bb5 100644 --- a/app/helpers/watchers_helper.rb +++ b/app/helpers/watchers_helper.rb @@ -283,6 +283,6 @@ module WatchersHelper def exit_project_link(project) link_to(l(:label_exit_project),exit_cur_project_path(project.id), - :remote => true, :confirm => l(:lable_sure_exit_project), :style => "color: #fff; display:block; padding: 0px 5px;margin-right:10px;height:22px;background:none repeat scroll 0% 0% #64BDD9;TES" ) + :remote => true, :confirm => l(:lable_sure_exit_project), :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 22px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES" ) end end diff --git a/app/models/project.rb b/app/models/project.rb index 313652bf4..07854822e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -41,7 +41,7 @@ class Project < ActiveRecord::Base has_many :principals, :through => :member_principals, :source => :principal has_many :enabled_modules, :dependent => :delete_all has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" - has_many :issues, :dependent => :destroy, :include => [:status, :tracker],:order => "id ASC" + has_many :issues, :dependent => :destroy, :include => [:status, :tracker],:order => "issues.id ASC" has_many :issue_changes, :through => :issues, :source => :journals has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC" has_many :time_entries, :dependent => :delete_all diff --git a/app/services/courses_service.rb b/app/services/courses_service.rb index 09cc5d59d..1ec8a0ef0 100644 --- a/app/services/courses_service.rb +++ b/app/services/courses_service.rb @@ -355,19 +355,19 @@ class CoursesService latest_course_dynamics = [] latest_news = course.news.order("created_on desc").first unless latest_news.nil? - latest_course_dynamics << {:type => 1,:time => latest_news.created_on,:message => '最近更新了通知' }#l(:label_recently_updated_notification,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 1,:time => latest_news.created_on,:message => l(:label_recently_updated_notification,:locale => current_user.language.nil? ? 'zh':current_user.language)} end latest_message = course.journals_for_messages.order("created_on desc").first unless latest_message.nil? - latest_course_dynamics << {:type => 2,:time => latest_message.created_on,:message => '最近更新了留言'}#l(:label_recently_updated_message,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 2,:time => latest_message.created_on,:message => l(:label_recently_updated_message,:locale => current_user.language.nil? ? 'zh':current_user.language)} end latest_attachment = course.attachments.order("created_on desc").first unless latest_attachment.nil? - latest_course_dynamics << {:type => 3,:time => latest_attachment.created_on,:message => '最近更新了课件'}#l(:label_recently_updated_courseware,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 3,:time => latest_attachment.created_on,:message => l(:label_recently_updated_courseware,:locale => current_user.language.nil? ? 'zh':current_user.language)} end latest_bid = course.homeworks.order('updated_on DESC').first unless latest_bid.nil? - latest_course_dynamics << {:type => 4,:time => latest_bid.updated_on,:message => '最近更新了作业'}#l(:label_recently_updated_homework,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 4,:time => latest_bid.updated_on,:message => l(:label_recently_updated_homework,:locale => current_user.language.nil? ? 'zh':current_user.language)} end #每个作业中的最新留言 messages = [] @@ -382,7 +382,7 @@ class CoursesService end latest_bid_message = messages.first unless latest_bid_message.nil? - latest_course_dynamics << {:type => 4,:time => latest_bid_message.created_on,:message => '最近更新了作业'}#l(:label_recently_updated_message,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 4,:time => latest_bid_message.created_on,:message => l(:label_recently_updated_message,:locale => current_user.language.nil? ? 'zh':current_user.language)} end #每个作业中学生最后提交的作业 homeworks = [] @@ -397,7 +397,7 @@ class CoursesService end latest_homework_attach = homeworks.first unless latest_homework_attach.nil? - latest_course_dynamics << {:type => 4,:time => latest_homework_attach.updated_at,:message => '最近更新了作业'}#l(:label_recently_updated_homework,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 4,:time => latest_homework_attach.updated_at,:message => l(:label_recently_updated_homework,:locale => current_user.language.nil? ? 'zh':current_user.language)} end latest_course_dynamics.sort!{|order,newer| newer[:time] <=> order[:time]} latest_course_dynamic = latest_course_dynamics.first diff --git a/app/services/users_service.rb b/app/services/users_service.rb index 8cadf031c..f75a84c5b 100644 --- a/app/services/users_service.rb +++ b/app/services/users_service.rb @@ -80,6 +80,28 @@ class UsersService {:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction} end + #忘记密码 + def lost_password params + user = ::User.find_by_mail(params[:mail].to_s) + # user not found or not active + unless user && user.active? + raise l(:notice_account_unknown_email,:locale => 'zh') + end + # user cannot change its password + unless user.change_password_allowed? + raise l(:notice_can_t_change_password,:locale => user.language) + return + end + # create a new token for password recovery + token = Token.new(:user => user, :action => "recovery") + if token.save + Thread.new do + Mailer.lost_password(token).deliver + end + return l(:notice_account_lost_email_sent,:locale => user.language) + end + end + #编辑用户 #gender 1:female 0:male 其他:male def edit_user params diff --git a/app/views/attachments/_form.html.erb b/app/views/attachments/_form.html.erb index 1d637919c..0949899dd 100644 --- a/app/views/attachments/_form.html.erb +++ b/app/views/attachments/_form.html.erb @@ -1,6 +1,6 @@ <% if defined?(container) && container && container.saved_attachments %> - <% container.attachments.each_with_index do |attachment, i| %> + <% container.saved_attachments.each_with_index do |attachment, i| %> <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%> <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") %> diff --git a/app/views/attachments/_links.html.erb b/app/views/attachments/_links.html.erb index 989ed776d..8913febd0 100644 --- a/app/views/attachments/_links.html.erb +++ b/app/views/attachments/_links.html.erb @@ -34,7 +34,8 @@ <%= link_to image_tag('delete.png'), {:controller => 'attachments', :action => 'delete_homework', :id => attachment.id}, :data => {:confirm => l(:text_are_you_sure)}, :method => :delete, - :class => 'delete', + :class => 'delete delete-homework-icon', + :remote => true, :title => l(:button_delete) %> <% else %> <%= link_to image_tag('delete.png'), attachment_path(attachment), diff --git a/app/views/bids/_bid_homework_show.html.erb b/app/views/bids/_bid_homework_show.html.erb index 1009f405f..6b3f91587 100644 --- a/app/views/bids/_bid_homework_show.html.erb +++ b/app/views/bids/_bid_homework_show.html.erb @@ -172,9 +172,9 @@ - <%= l(:label_create_time) %> + <%= l(:label_end_time) %> :  - <%=format_time bid.created_on %> + <%= bid.deadline %> <% if betweentime(bid.deadline) < 0 %> diff --git a/app/views/files/_project_file.html.erb b/app/views/files/_project_file.html.erb index e204030f1..aa597f3f2 100644 --- a/app/views/files/_project_file.html.erb +++ b/app/views/files/_project_file.html.erb @@ -11,7 +11,7 @@ <%= link_to(l(:label_upload_files), 'javascript:void(0);', :class => 'icon m5p5 button_submit', :onclick => "$('#relation_file_div').slideUp();$('#upload_file_div').slideToggle('slow');") if User.current.allowed_to?(:manage_files, @project) %> <%= link_to(l(:label_relation_files), 'javascript:void(0);', :onclick => "$('#upload_file_div').slideUp();$('#relation_file_div').slideToggle();", :class => 'icon m5p5 button_submit') if User.current.allowed_to?(:manage_files, @project) %>

    -