# encoding: utf-8 # # Redmine - project management software # Copyright (C) 2006-2013 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'forwardable' require 'cgi' module ApplicationHelper include Redmine::WikiFormatting::Macros::Definitions include Redmine::I18n include GravatarHelper::PublicMethods include Redmine::Pagination::Helper include AvatarHelper ## added by william include PraiseTreadHelper include CoursesHelper extend Forwardable def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter # def user_blogs_path(resource,parameters={}) # super # end # 超出1w后用k+形式显示 def switch_integer_into_k number number > 10000 ? (number.to_f / 1000).round.to_s + "k" : number end # 隐藏项目以外的信息 # return: true 显示,false 不显示 def hidden_unproject_infos hidden_info = Setting.find_by_name("hidden_non_project") (hidden_info && hidden_info.value == "1") ? true : false end # 获取当前用户的fork数量 def get_fork_from_project forked_from_project_id Project.find(forked_from_project_id) end # 通过系统外部邮箱查找用户,如果用户不存在则用邮箱替换 def get_user_by_mail mail user = User.find_by_mail(mail) user.nil? ? User.find(2) : user end # 通过系统外部用户名查找用户,如果用户不存在则用邮箱替换 def get_user_by_login_and login user = User.find_by_login(login) user.nil? ? User.find(2) : user end # 重置user_path,目的是将id转换成用户名 # def user_path(resource, parameters = {}) # if Fixnum === resource # resource = User.find(resource) # end # super # end # 历史数据(老版本库数据)处理完则可以修改该放放 def get_rep_identifier_by_project project identifier = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) result = identifier.nil? ? Repository.where(:project_id => project.id).first.try(:identifier) : identifier result end # 项目版本库导出Excel功能 def export_rep_xls(gpid, options = {}) g = Gitlab.client cycle = params[:cycle] rev = params[:rev] if cycle == "week" statics = g.rep_stats_week(gpid, :rev => rev) elsif cycle == "month" statics = g.rep_stats_month(gpid, :rev => rev) end xls_report = StringIO.new book = Spreadsheet::Workbook.new sheet1 = book.create_worksheet :name => l(:project_module_repository) blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 sheet1.row(0).default_format = blue sheet1.row(0).concat([l(:rep_branch),l(:rep_author),l(:rep_changeset),l(:rep_code_add),l(:rep_code_delete),l(:rep_code_modified),l(:rep_sode_time),l(:rep_sode_cycle),l(:rep_author_mail)]) count_row = 1 statics.each do |static| user = User.where(:mail => static.email).first sheet1[count_row,0] = rev sheet1[count_row,1] = user.nil? ? static.uname : user.show_name sheet1[count_row,2] = static.commits_num sheet1[count_row,3] = static.add sheet1[count_row,4] = static.del sheet1[count_row,5] = static.changes sheet1[count_row,6] = Time.now.strftime('%Y-%m-%d %H:%M:%S') sheet1[count_row,7] = cycle == "week" ? "最近1周" : "最近一月" sheet1[count_row,8] = static.email count_row += 1 end book.write xls_report xls_report.string end # 项目issue列表导出Excel功能 def issue_list_xls issues xls_report = StringIO.new book = Spreadsheet::Workbook.new sheet1 = book.create_worksheet :name => "issues" blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 sheet1.row(0).default_format = blue sheet1.row(0).concat([l(:issue_xls_id),l(:issue_xls_tracker_id),l(:issue_xls_title),l(:issue_xls_description),l(:issue_xls_status),l(:issue_xls_assign),l(:issue_xls_priority),l(:issue_xls_author),l(:issue_xls_created_at),l(:milestone),l(:issue_xls_start),l(:issue_xls_due),l(:issue_xls_ratio)]) count_row = 1 issues.each do |issue| sheet1[count_row,0] = issue.id sheet1[count_row,1] = issue_tracker_change(issue.tracker_id) sheet1[count_row,2] = issue.subject sheet1[count_row,3] = (issue.description.gsub(/<\/?.*?>/,"")).html_safe sheet1[count_row,4] = issue_status_change(issue.status_id) sheet1[count_row,5] = issue.assigned_to.try(:show_name) sheet1[count_row,6] = issue_priority_change(issue.priority_id) sheet1[count_row,7] = issue.author.show_name sheet1[count_row,8] = issue.created_on.nil? ? issue.created_on : issue.created_on.strftime('%Y-%m-%d %H:%M:%S') sheet1[count_row,9] = issue.fixed_version.try(:name) sheet1[count_row,10] = issue.start_date.nil? ? issue.start_date : issue.start_date.strftime('%Y-%m-%d') sheet1[count_row,11] = issue.due_date.nil? ? issue.due_date : issue.due_date.strftime('%Y-%m-%d') sheet1[count_row,12] = issue_ratio_change(issue.done_ratio, issue.status_id) count_row += 1 end book.write xls_report xls_report.string end # 获取用户单位 # 优先获取高校信息,如果改信息不存在则获取occupation def get_occupation_from_user user School.where("id=?",user.user_extensions.school_id).first.try(:name).nil? ? user.user_extensions.try(:occupation) : School.where("id=?",user.user_extensions.school_id).first.try(:name) end def update_visiti_count container container.update_column(:visits, container.visits + 1) end def if_hidden_subdomain field domains = field.sub_domains.select{|domain| domain.hide.to_i == 0} result = domains.length > 0 ? true : false return result end # 判断某个资源是否可以申请 def attach_show_allow attach_id attachment = Attachment.find(attach_id) case attachment.container_type when "Project" User.current.member_of?(attachment.container) ? true : false when "Course" User.current.member_of_course?(attachment.container) ? true : false when "OrgSubfield" User.current.member_of_org?(attachment.container.organization) ? true : false when "Principal" User.current.id == attachment.author_id ? true : false end end # 判断某个私有资源是否可以发送下载权限 # 结果为true不能下载,false可以下载 def private_attachment_allow attachment_id attach = Attachment.find(attachment_id) # 条件取否,result结果为true则不能下载 result = attach.is_public == 0 && attach.author != User.current && !attach.get_apply_resource_status(attach.id, User.current.id) && !attach_show_allow(attach) end # Time 2015-03-24 15:27:29 # Author lizanle # Description 从硬盘上删除对应的资源文件 def delete_kindeditor_assets_from_disk owner_id,owner_type assets = Kindeditor::Asset.where(["owner_id = ? and owner_type = ?",owner_id,owner_type]) if !assets.nil? && !assets.blank? assets.all.each do |asset| next if asset.nil? filepath = File.join(Rails.root,"public","files","uploads", asset[:created_at].to_s.gsub("+0800","").to_datetime.strftime("%Y%m").to_s, asset[:asset].to_s) File.delete(filepath) if File.exist?filepath end end end def link_to_user_version(version, options = {}) return '' unless version && version.is_a?(Version) link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => "linkBlue" end # 判断课程是否为精品课程 def is_excellent_course course (course.is_excellent? or course.excellent_option?) ? true : false end # 判断课程对成员是否可见 def visible_course?(course) (course.is_delete? or (!course.is_public? && !User.current.member_of_course?(course))) ? false : true end # 获取项目/课程总分 # 发布缺陷 4分 回复缺陷 1分 提交一次 4分 讨论帖子 2分 回复帖子 1分 发布新闻 1分 def static_project_score obj score = obj.issue_num * 4 + obj.issue_journal_num + (obj.changeset_num||0) * 4 + obj.board_num * 2 + obj.board_message_num + obj.news_num + obj.attach_num * 5 end # 获取组织成员中文名字 def get_org_member_role_name member unless member.roles[0].nil? case member.roles[0].name when 'orgManager' '管理人员' when 'orgMember' '组织成员' end end end # 判断组织左侧展开或者隐藏 def is_hide_org_left obj if obj.nil? return true else if obj.hide == 0 return true else return false end end end # Time 2015-03-24 16:38:05 # Author lizanle # Description after save后需要进行资源记录的更新 # owner_type = 1 对应的是 memo # owner_type = 2 对应的是forum # owner_type = 3 对应的是message # owner_type = 4 对应的是news # owner_type = 5 对应的是comment def update_kindeditor_assets_owner ids,owner_id,owner_type ids.each do |id| asset = Kindeditor::Asset.find(id.to_i) asset.owner_id = owner_id asset.owner_type = owner_type asset.save end end # 更新课程活跃度得分 def course_member_score(course_id,user_id,type) course_contributor_score = CourseContributorScore.where("course_id =? and user_id =?", course_id, user_id).first case type when "HomeworkCommon" if course_contributor_score.nil? CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :homework_journal_num => 1) else score = course_contributor_score.homework_journal_num.to_i + 1 course_contributor_score.update_column(:homework_journal_num, score) end # 课程留言 when "Course" if course_contributor_score.nil? CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :journal_num => 1) else score = course_contributor_score.journal_num.to_i + 1 course_contributor_score.update_column(:journal_num, score) end when "Message" if course_contributor_score.nil? CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :message_num => 1) else score = course_contributor_score.message_num.to_i + 1 course_contributor_score.update_column(:message_num, score) end when "MessageReply" if course_contributor_score.nil? CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :message_reply_num => 1) else score = course_contributor_score.message_reply_num.to_i + 1 course_contributor_score.update_column(:message_reply_num, score) end when "NewReply" if course_contributor_score.nil? CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :news_reply_num => 1) else score = course_contributor_score.news_reply_num.to_i + 1 course_contributor_score.update_column(:news_reply_num, score) end when "News" if course_contributor_score.nil? CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :news_num => 1) else score = course_contributor_score.news_num.to_i + 1 course_contributor_score.update_column(:news_num, score) end when "Attachment" if course_contributor_score.nil? CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :resource_num => 1) else score = course_contributor_score.resource_num.to_i + 1 course_contributor_score.update_column(:resource_num, score) end end end # 删除某条记录相应减少课程统计数 def down_course_score_num (course_id,user_id,type) course_contributor_score = CourseContributorScore.where("course_id =? and user_id =?", course_id, user_id).first case type when "HomeworkCommon" unless course_contributor_score.nil? score = course_contributor_score.homework_journal_num.to_i - 1 course_contributor_score.update_column(:homework_journal_num, score < 0 ? 0 : score) end # 课程留言 when "Course" unless course_contributor_score.nil? score = course_contributor_score.journal_num.to_i - 1 course_contributor_score.update_column(:journal_num, score < 0 ? 0 : score) end when "Message" unless course_contributor_score.nil? score = course_contributor_score.message_num.to_i - 1 course_contributor_score.update_column(:message_num, score < 0 ? 0 : score) end when "MessageReply" unless course_contributor_score.nil? score = course_contributor_score.message_reply_num.to_i - 1 course_contributor_score.update_column(:message_reply_num, score < 0 ? 0 : score) end when "NewReply" unless course_contributor_score.nil? score = course_contributor_score.news_reply_num.to_i - 1 course_contributor_score.update_column(:news_reply_num, score < 0 ? 0 : score) end when "News" unless course_contributor_score.nil? score = course_contributor_score.news_num.to_i - 1 course_contributor_score.update_column(:news_num, score < 0 ? 0 : score) end when "Attachment" unless course_contributor_score.nil? score = course_contributor_score.resource_num.to_i - 1 course_contributor_score.update_column(:resource_num, score < 0 ? 0 : score) end end end # Added by young # Define the course menu's link class # 不是数组的转化成数组,然后判断当前menu_item是否在给定的列表 # REVIEW: 目测menu的机制,貌似不是很需要转换,再说 def link_class(label) labels = label.is_a?(Array) ? label : ([] << label) #a = current_menu_item labels.include?(current_menu_item) ? 'selected' : '' end #Ended by young # Return true if user is authorized for controller/action, otherwise false def authorize_for(controller, action) User.current.allowed_to?({:controller => controller, :action => action}, @project) end # add by nwb def authorize_for_course(controller, action) User.current.allowed_to?({:controller => controller, :action => action}, @course) end def authorize_for_contest(controller, action) User.current.allowed_to?({:controller => controller, :action => action}, @contest) end # Display a link if user is authorized # # @param [String] name Anchor text (passed to link_to) # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized # @param [optional, Hash] html_options Options passed to link_to # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action]) end def link_to_if_authorized_course(name, options = {}, html_options = nil, *parameters_for_method_reference) link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for_course(options[:controller] || params[:controller], options[:action]) end def link_to_if_authorized_contest(name, options = {}, html_options = nil, *parameters_for_method_reference) link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for_contest(options[:controller] || params[:controller], options[:action]) end # Displays a link to user's account page if active def link_to_user(user, canShowRealName = false, options={}) if user.is_a?(User) if canShowRealName name = h(user.realname(options[:format])) else name = h(user.name(options[:format])) end #if user.active? || (User.current.admin? && user.logged?) # link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => user.css_classes #else # name #end link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => user.css_classes else h(user.to_s) end end def link_to_isuue_user(user, options={}) if user.is_a?(User) if options[:format] name = h(user.name(options[:format])) else name = h(user.show_name) end link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => "pro_info_p" else h(user.to_s) end end def link_to_settings_user(user, options={}) if user.is_a?(User) name = h(user.name(options[:format])) link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => "w90 c_orange fl" else h(user.to_s) end end #重载上面方法,增加样式显示 def link_to_user_header user,canShowRealName=false,options={} if user.is_a?(User) if canShowRealName name = user.show_name name = user.login if name == "" else name = user.login end link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => options[:class] else h(user.to_s) end end # Displays a link to +issue+ with its subject. # Examples: # # link_to_issue(issue) # => Defect #6: This is the subject # link_to_issue(issue, :truncate => 6) # => Defect #6: This i... # link_to_issue(issue, :subject => false) # => Defect #6 # link_to_issue(issue, :project => true) # => Foo - Defect #6 # link_to_issue(issue, :subject => false, :tracker => false) # => #6 # def link_to_issue(issue, options={}) title = nil subject = nil text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}" if options[:subject] == false title = truncate(issue.subject, :length => 60) else subject = issue.subject if options[:truncate] subject = truncate(subject, :length => options[:truncate]) end end s = link_to text, issue_path(issue), :class => issue.css_classes, :title => title s << h(": #{subject}") if subject s = h("#{issue.project} - ") + s if options[:project] s end def link_to_issue_version(issue, options={}) title = nil subject = nil text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}" if options[:subject] == false title = truncate(issue.subject, :length => 60) else subject = issue.subject if options[:truncate] subject = truncate(subject, :length => 60) end end # status_id:3、已解决 5、已关闭 if issue.status_id == 3 s = link_to text, issue_path(issue), :class => "text_line_s fl", :title => title elsif issue.status_id == 5 s = link_to text, issue_path(issue), :class => "text_line_s del_line fl", :title => title else s = link_to text, issue_path(issue), :class => "c_blue fl", :title => title end s << h("".html_safe) if subject s = h("#{issue.project} - ") + s if options[:project] s end # Generates a link to an attachment. # Options: # * :text - Link text (default to attachment filename) # * :download - Force download (default: false) def link_to_short_attachment(attachment, options={}) length = options[:length] ? options[:length]:23 text = h(truncate(options.delete(:text) || attachment.filename, length: length, omission: '...')) route_method = options.delete(:download) ? :download_named_attachment_url_without_domain : :named_attachment_url_without_domain html_options = options.slice!(:only_path) url = send(route_method, attachment, attachment.filename, options) link_to text, url, html_options end # Generates a link to an attachment. # Options: # * :text - Link text (default to attachment filename) # * :download - Force download (default: false) def link_to_attachment(attachment, options={}) token = options[:token] if options[:token] text = options.delete(:text) || attachment.filename route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path html_options = options.slice!(:only_path) url = send(route_method, attachment, attachment.filename, options) url << "?token=#{token}" unless token.nil? link_to text, url, html_options end def link_to_attachment_img(attachment, options={}) text = options.delete(:text) || attachment.filename route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path html_options = options.slice!(:only_path) url = send(route_method, attachment, attachment.filename, options) image_tag url, html_options end # Generates a link to a SCM revision # Options: # * :text - Link text (default to the formatted revision) def link_to_revision(revision, repository, options={}) if repository.is_a?(Project) repository = repository.repository end text = options.delete(:text) || format_revision(revision) rev = revision.respond_to?(:identifier) ? revision.identifier : revision link_to( h(text), {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev}, :title => l(:label_revision_id, format_revision(revision)) ) end # Generates a link to a message def link_to_message(message, options={}, html_options = nil) link_to( truncate(message.subject, :length => 60), board_message_path(message.board_id, message.parent_id || message.id, { :r => (message.parent_id && message.id), :anchor => (message.parent_id ? "message-#{message.id}" : nil) }.merge(options)), html_options ) end # Generates a link to a project if active # Examples: # # link_to_project(project) # => link to the specified project overview # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) # def link_to_project(project, options={}, html_options = nil) if project.archived? h(project.name) elsif options.key?(:action) ActiveSupport::Deprecation.warn "#link_to_project with :action option is deprecated and will be removed in Redmine 3.0." url = {:controller => 'projects', :action => 'show', :id => project}.merge(options) link_to project.name, url, html_options else link_to project.name, project_path(project, options), html_options end end def link_to_course(course, options={}, html_options = nil) if course.archived? h(course.name) elsif options.key?(:action) ActiveSupport::Deprecation.warn "#link_to_course with :action option is deprecated and will be removed in Redmine 3.0." url = {:controller => 'courses', :action => 'show', :id => project}.merge(options) link_to course.name, url, html_options else link_to course.name, course_path(course, options), html_options end end # Generates a link to a project settings if active def link_to_project_settings(project, options={}, html_options=nil) if project.active? link_to project.name, settings_project_path(project, options), html_options elsif project.archived? h(project.name) else link_to project.name, project_path(project, options), html_options end end def wiki_page_path(page, options={}) url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) end def thumbnail_tag(attachment) link_to image_tag(thumbnail_path(attachment)), named_attachment_path(attachment, attachment.filename), :title => attachment.filename end def thumbnail_issue_tag(attachment) imagesize = attachment.thumbnail(:size => "200*200") imagepath = named_attachment_path(attachment, attachment.filename) if imagesize link_to image_tag(thumbnail_path(attachment), height: '73', width: '100', class: 'issue_attachment_picture'), imagepath, :title => attachment.filename else link_to image_tag(imagepath , height: '73', width: '100', class: 'issue_attachment_picture'), imagepath, :title => attachment.filename end end # 图片缩略图链接 def thumbnail_small_tag(attachment) imagesize = attachment.thumbnail(:size => "200*200") imagepath = named_attachment_path(attachment, attachment.filename) if imagesize link_to image_tag(imagesize), imagepath, :title => attachment.filename else link_to image_tag(imagepath , height: '200', width: '250'), imagepath, :title => attachment.filename end end def toggle_link(name, id, options={}) onclick = "$('##{id}').slideToggle(); " onclick << (options[:focus] ? "$('##{options[:focus]}').focus(); " : "this.blur(); ") onclick << "return false;" link_to(name, "javascript:void(0)", :onclick => onclick,:class => options[:class]) end def image_to_function(name, function, html_options = {}) html_options.symbolize_keys! tag(:input, html_options.merge({ :type => "image", :src => image_path(name), :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" })) end def format_activity_title(text) h(truncate_single_line(text, :length => 100)) end def format_activity_day(date) date == User.current.today ? l(:label_today).titleize : format_date(date) end def format_activity_description(text) h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "
").html_safe #h(truncate(text.to_s, :length => 120).gsub(/<\/?.*?>/,"")).html_safe end def format_version_name(version) if version.project == @project h(truncate(version.name,:length=>20)) else h("#{version.project} - #{truncate(version.name,:length=>20)}") end end def due_date_distance_in_words(date) if date l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) end end # Renders a tree of projects as a nested set of unordered lists # The given collection may be a subset of the whole project tree # (eg. some intermediate nodes are private and can not be seen) #Modified by nie. def render_project_nested_lists(projects) s = '' if projects.any? ancestors = [] original_project = @project #modified by nie projects.each do |project| # set the project environment to please macros. @project = project if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) # s << "\n" * ancestors.size) @project = original_project end s.html_safe end def render_course_nested_lists(courses) s = '' if courses.any? ancestors = [] original_course = @course #modified by nie courses.each do |course| # set the project environment to please macros. @course = course if (ancestors.empty? )#|| course.is_descendant_of?(ancestors.last)) s << "\n" end end classes = (ancestors.empty? ? 'root' : 'child') s << "
  • " s << (render :partial => 'courses/course', :locals => {:course => course}).to_s s << "
    \n" ancestors << course end s << ("
  • \n" * ancestors.size) @course = original_course end s.html_safe end #added by young def render_project_nested_lists_new(projects) s = '' if projects.any? ancestors = [] original_project = @project projects.sort_by(&:lft).each do |project| # set the project environment to please macros. @project = project if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) # s << "\n" * ancestors.size) @project = original_project end s.html_safe end #end def render_page_hierarchy(pages, node=nil, options={}) content = '' if pages[node] content << "\n" end content.html_safe end # Renders flash messages def render_flash_messages s = '' flash.each do |k,v| s << content_tag('div', v.html_safe, :class => "flash #{k}", :id => "flash_#{k}") end s.html_safe end # Renders tabs and their content def render_tabs(tabs) if tabs.any? render :partial => 'common/tabs', :locals => {:tabs => tabs} else content_tag 'p', l(:label_no_data), :class => "nodata" end end def render_project_settings_tabs(tabs) if tabs.any? render :partial => 'common/project_tab', :locals => {:tabs => tabs} else content_tag 'p', l(:label_no_data), :class => "nodata" end end # Renders the project quick-jump box def render_project_jump_box return unless User.current.logged? projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq if projects.any? options = ("" + '').html_safe options << project_tree_options_for_select(projects, :selected => @project) do |p| { :value => project_path(:id => p, :jump => current_menu_item) } end select_tag('project_quick_jump_box', options, :onchange => 'if (this.value != \'\') { window.location = this.value; }') end end def project_tree_options_for_select(projects, options = {}) s = '' project_tree(projects) do |project, level| name_prefix = (level > 0 ? ' ' * 2 * level + '» ' : '').html_safe tag_options = {:value => project.id} tag_options[:title] = project.name if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project)) tag_options[:selected] = 'selected' else tag_options[:selected] = nil end tag_options.merge!(yield(project)) if block_given? s << content_tag('option', name_prefix + h(project), tag_options) end s.html_safe end # Yields the given block for each project with its level in the tree # # Wrapper for Project#project_tree def project_tree(projects, &block) Project.project_tree(projects, &block) end # 项目版本库可见权限判断: # modules中设置可见 # 版本库存在 # 版本库设置了隐藏则仅仅项目成员或超级管理员可见(hidden_repo:1 隐藏版本库) # return -> true 可见 def visible_repository?(project) repository = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first if project.enabled_modules.where("name = 'repository'").empty? || repository.nil? result = false else result = (project.hidden_repo && !User.current.admin && !User.current.member_of?(project)) ? false : true end end def show_attachment_tip container_id, container_type atts = Attachment.where(:container_id => container_id, :container_type => container_type, :is_public => 0) atts.count > 0 ? true :false end # 必须是项目成员,项目必须提交过代码 def allow_pull_request project return 0 if project.gpid.nil? g = Gitlab.client count = g.user_static(project.gpid, :rev => "master").count count end # 判断版本库是否初始为gitlab def rep_is_gitlab?(project) rep = project.repositories.where("type =?", "Repository::Gitlab") return rep.blank? ? true :false end # 获取Gitlab版本库提交总数 def commit_count(project, branch) g = Gitlab.client #add by hx if g.commits(project.gpid, :ref_name => @rev , :page=>200).count > 0 count = 4020 elsif g.commits(project.gpid , :page=>25, :ref_name => branch).count==0 count = count_commits(project.gpid , 0 , 25) elsif g.commits(project.gpid , :page=>50, :ref_name => branch).count ==0 count = count_commits(project.gpid , 25 , 50)+ 25 * 20 elsif g.commits(project.gpid , :page=>75, :ref_name => branch).count ==0 count = count_commits(project.gpid , 50 , 75)+ 50 * 20 elsif g.commits(project.gpid , :page=>100, :ref_name => branch).count== 0 count = count_commits(project.gpid , 75 , 100) + 75 * 20 elsif g.commits(project.gpid , :page=>125, :ref_name => branch).count==0 count = count_commits(project.gpid , 100 , 125) + 100 * 20 elsif g.commits(project.gpid , :page=>150, :ref_name => branch).count==0 count = count_commits(project.gpid , 125 , 150) + 125 * 20 else count = count_commits(project.gpid , 150 ,200) + 150 * 20 end end #add by hx def count_commits(project_id , left , right) count = 0 (left..right).each do |page| if $g.commits(project_id,:page => page).count == 0 break else count = count + $g.commits(project_id, :ref_name => @rev, :page => page).count end end return count end # 获取单一gitlab项目 def gitlab_repository(project) rep = Repository.where("project_id =? and type =?", project.id,"Repository::Gitlab" ).first end # 判断当前用户是否为项目管理员 def is_project_manager?(user_id, project_id) @result = false mem = Member.where("user_id = ? and project_id = ?",user_id, project_id) unless mem.blank? @result = mem.first.roles.to_s.include?("Manager") ? true : false end return @result end # 公开项目资源可以引用,admin和管理员和资源上传者拥有设置公开私有权限 def authority_pubilic_for_files(project, file) @result = false if (is_project_manager?(User.current.id, @project.id) && User.current.allowed_to?(:manage_files, project)) || file.author_id == User.current.id || User.current.admin && project_contains_attachment?(project,file) && file.container_id == project.id && file.container_type == "Project" @result = true end return @result end def principals_check_box_tags(name, principals) s = '' principals.each do |principal| s << "\n" end s.html_safe end # 判断模块是否可见 def project_modules_allow project @project.enabled_modules.where("name = 'issue_tracking'").empty? end # 计算Pull Request的请求数目 def pull_request_count project g = Gitlab.client g.merge_requests(project.gpid).count 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_url_in_org( principal.id)}
  • \n" end s.html_safe end #缺陷追踪者列表复选框生成 def issue_watcher_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 = '' principals.each do |principal| s << "\n" end s.html_safe end # li标签checkbos扩展 def principals_check_box_tags_li(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_radio_box_tags_ex(name, principals) s = '' principals.each do |principal| s << "\n" end s.html_safe end # Returns a string for users/groups option tags def principals_options_for_select(collection, selected=nil) s = '' if collection.include?(User.current) s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) end groups = '' collection.sort.each do |element| selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) (element.is_a?(Group) ? groups : s) << %() end unless groups.empty? s << %(#{groups}) end s.html_safe end def assigned_options_for_select(collection, selected=nil) s = '' s << content_tag('option', "#{l(:label_assiged_tip)}", :value => 0) if collection.include?(User.current) s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) end groups = '' collection.sort.each do |element| selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) (element.is_a?(Group) ? groups : s) << %() end unless groups.empty? s << %(#{groups}) end s.html_safe end # Options for the new membership projects combo-box def options_for_membership_project_select(principal, projects) options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") options << project_tree_options_for_select(projects) do |p| {:disabled => principal.projects.to_a.include?(p)} end options end # Truncates and returns the string as a single line def truncate_single_line(string, *args) truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') end # Truncates at line break after 250 characters or options[:length] def truncate_lines(string, options={}) length = options[:length] || 250 if string.to_s =~ /\A(.{#{length}}.*?)$/m "#{$1}..." else string end end def anchor(text) text.to_s.gsub(' ', '_') end def html_hours(text) text.gsub(%r{(\d+)\.(\d+)}, '\1.\2').html_safe end def authoring(created, author, options={}) l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)).html_safe end def added_time(created) l(:label_added_time, :age => time_tag(created)).html_safe end def user_url_and_time(user_name, user_url, created) unless user_name.nil? || user_name == '' l(:label_added_time_by, :author => link_to(user_name, user_url), :age => time_tag(created)).html_safe else l(:label_added_time, :age => time_tag(created)).html_safe end end #huang def betweentime(enddate) ss=(DateTime.parse("#{enddate.to_date}")-DateTime.parse("#{DateTime.now.to_date}")).to_i return ss end def time_tag(time, *args) options = args.extract_options! text = distance_of_time_in_words(Time.now, time) if @project content_tag('acronym', text, options.reverse_merge(:title => format_time(time))) # link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => User.current.time_to_date(time)},options.reverse_merge(:title => format_time(time))) else content_tag('acronym', text, options.reverse_merge(:title => format_time(time))) end end def syntax_highlight_lines(name, content) lines = [] syntax_highlight(name, content).each_line { |line| lines << line } lines end def syntax_highlight(name, content) Redmine::SyntaxHighlighting.highlight_by_filename(content, name) end def to_path_param(path) str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") str.blank? ? nil : str end def reorder_links(name, url, method = :post) link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => method, :title => l(:label_sort_highest)) + link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => method, :title => l(:label_sort_higher)) + link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => method, :title => l(:label_sort_lower)) + link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => method, :title => l(:label_sort_lowest)) end def breadcrumb(*args) elements = args.flatten elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'wiki_con_tit"') : nil end def other_formats_links(&block) concat('

    '.html_safe + l(:label_export_to)) yield Redmine::Views::OtherFormatsBuilder.new(self) concat('

    '.html_safe) end def page_header_title if @project.nil? || @project.new_record? h(Setting.app_title) else b = [] ancestors = (@project.root? ? [] : @project.ancestors.visible.all) if ancestors.any? root = ancestors.shift b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') if ancestors.size > 2 b << "\xe2\x80\xa6" ancestors = ancestors[-2, 2] end b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') } end b << h(@project) b.join(" \xc2\xbb ").html_safe end end def html_title(*args) #點擊項目版本庫 多觸發一次 字符串為"/" #暫時解決方法 直接判斷 if(args == ["/"]) args = [] end first_page = FirstPage.find_by_page_type('project') if args.empty? title = @html_title || [] if @project title << @project.name elsif @course title << @course.name elsif @organization title << @organization.name elsif @user title << @user.try(:realname) elsif @syllabus title << @syllabus.title else title << (User.current.id == 2 ? "未登录" : User.current.try(:realname)) end if first_page.nil? || first_page.web_title.nil? title << Setting.app_title unless Setting.app_title == title.last else title << first_page.web_title unless first_page.web_title == title.last end title.select {|t| !t.blank? }.join(' - ') else @html_title ||= [] @html_title += args end end # Returns the theme, controller name, and action as css classes for the # HTML body. def body_css_classes css = [] if theme = Redmine::Themes.theme(Setting.ui_theme) css << 'theme-' + theme.name end css << 'controller-' + controller_name css << 'action-' + action_name css.join(' ') end def accesskey(s) @used_accesskeys ||= [] key = Redmine::AccessKeys.key_for(s) return nil if @used_accesskeys.include?(key) @used_accesskeys << key key end # Formats text according to system settings. # 2 ways to call this method: # * with a String: textilizable(text, options) # * with an object and one of its attribute: textilizable(issue, :description, options) def textilizable(*args) options = args.last.is_a?(Hash) ? args.pop : {} case args.size when 1 obj = options[:object] text = args.shift when 2 obj = args.shift attr = args.shift text = obj.send(attr).to_s else raise ArgumentError, 'invalid arguments to textilizable' end return '' if text.blank? project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) only_path = options.delete(:only_path) == false ? false : true text = text.dup macros = catch_macros(text) text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) @parsed_headings = [] @heading_anchors = {} @current_section = 0 if options[:edit_section_links] parse_sections(text, project, obj, attr, only_path, options) text = parse_non_pre_blocks(text, obj, macros) do |text| [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name| send method_name, text, project, obj, attr, only_path, options end end parse_headings(text, project, obj, attr, only_path, options) if @parsed_headings.any? replace_toc(text, @parsed_headings) end text.html_safe end # #格式化字符串,不转义html代码 def textAreailizable(*args) options = args.last.is_a?(Hash) ? args.pop : {} case args.size when 1 obj = options[:object] text = args.shift when 2 obj = args.shift attr = args.shift text = obj.send(attr).to_s else raise ArgumentError, 'invalid arguments to textilizable' end return '' if text.blank? project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) only_path = options.delete(:only_path) == false ? false : true text = text.dup macros = catch_macros(text) #text = Redmine::WikiFormatting.to_html("CKEditor", text, :object => obj, :attribute => attr) @parsed_headings = [] @heading_anchors = {} @current_section = 0 if options[:edit_section_links] parse_sections(text, project, obj, attr, only_path, options) text = parse_non_pre_blocks(text, obj, macros) do |text| [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name| send method_name, text, project, obj, attr, only_path, options end end parse_headings(text, project, obj, attr, only_path, options) if @parsed_headings.any? replace_toc(text, @parsed_headings) end text.html_safe end def parse_non_pre_blocks(text, obj, macros) s = StringScanner.new(text) tags = [] parsed = '' while !s.eos? s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im) text, full_tag, closing, tag = s[1], s[2], s[3], s[4] if tags.empty? yield text inject_macros(text, obj, macros) if macros.any? else inject_macros(text, obj, macros, false) if macros.any? end parsed << text if tag if closing if tags.last == tag.downcase tags.pop end else tags << tag.downcase end parsed << full_tag end end # Close any non closing tags while tag = tags.pop parsed << "" end parsed end def parse_inline_attachments(text, project, obj, attr, only_path, options) # when using an image link, try to use an attachment, if possible attachments = options[:attachments] || [] attachments += obj.attachments if obj.respond_to?(:attachments) if attachments.present? text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| filename, ext, alt, alttext = $1.downcase, $2, $3, $4 # search for the picture in attachments if found = Attachment.latest_attach(attachments, filename) image_url = download_named_attachment_path(found, found.filename, :only_path => only_path) desc = found.description.to_s.gsub('"', '') if !desc.blank? && alttext.blank? alt = " title=\"#{desc}\" alt=\"#{desc}\"" end "src=\"#{image_url}\"#{alt}" else m end end end end # 判断课程、项目、组织是否有权限删除历史资源 # 项目管理员或者附件的作者可以删除 # (is_project_manager?(User.current.id, @project.id) || User.current.id == history.author_id) def allow_to_delete_attachment history attachment = history.attachment case attachment.try(:container_type) when "Project" result = is_project_manager?(User.current.id, attachment.container_id) || User.current.id == history.author_id || User.current.admin? when "Course" result = User.current.allowed_to?(:as_teacher, attachment.container) || User.current.id == history.author_id || User.current.admin? when "OrgSubfield" result = User.current.id == history.author_id || User.current.admin_of_org?(attachment.container) || User.current.admin? end end # Wiki links # # Examples: # [[mypage]] # [[mypage|mytext]] # wiki links can refer other project wikis, using project name or identifier: # [[project:]] -> wiki starting page # [[project:|mytext]] # [[project:mypage]] # [[project:mypage|mytext]] def parse_wiki_links(text, project, obj, attr, only_path, options) text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| link_project = project esc, all, page, title = $1, $2, $3, $5 if esc.nil? if page =~ /^([^\:]+)\:(.*)$/ identifier, page = $1, $2 link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier) title ||= identifier if page.blank? end if link_project && link_project.wiki # extract anchor anchor = nil if page =~ /^(.+?)\#(.+)$/ page, anchor = $1, $2 end anchor = sanitize_anchor_name(anchor) if anchor.present? # check if page exists wiki_page = link_project.wiki.find_page(page) url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page "##{anchor}" else case options[:wiki_links] when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export else wiki_page_id = page.present? ? Wiki.titleize(page) : nil parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent) end end link_to(title.present? ? title.html_safe : h(page), User.current.logged? ? url : signin_url_without_domain, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) else # project or wiki doesn't exist all end else all end end end def select_option_helper option tmp = Hash.new tmp={"" => ""} if option.nil? else option.each do |project| tmp[project.name] = project.id end end tmp end # Redmine links # # Examples: # Issues: # #52 -> Link to issue #52 # Changesets: # r52 -> Link to revision 52 # commit:a85130f -> Link to scmid starting with a85130f # Documents: # document#17 -> Link to document with id 17 # document:Greetings -> Link to the document with title "Greetings" # document:"Some document" -> Link to the document with title "Some document" # Versions: # version#3 -> Link to version with id 3 # version:1.0.0 -> Link to version named "1.0.0" # version:"1.0 beta 2" -> Link to version named "1.0 beta 2" # Attachments: # attachment:file.zip -> Link to the attachment of the current object named file.zip # Source files: # source:some/file -> Link to the file located at /some/file in the project's repository # source:some/file@52 -> Link to the file's revision 52 # source:some/file#L120 -> Link to line 120 of the file # source:some/file@52#L120 -> Link to line 120 of the file's revision 52 # export:some/file -> Force the download of the file # Forum messages: # message#1218 -> Link to message with id 1218 # # Links can refer other objects from other projects, using project identifier: # identifier:r52 # identifier:document:"Some document" # identifier:version:1.0.0 # identifier:source:some/file def parse_redmine_links(text, default_project, obj, attr, only_path, options) text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m| leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $2, $3, $4, $5, $10, $11, $8 || $12 || $18, $14 || $19, $15, $17 link = nil project = default_project if project_identifier project = Project.visible.find_by_identifier(project_identifier) end if esc.nil? if prefix.nil? && sep == 'r' if project repository = nil if repo_identifier repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} else repository = project.repository end # project.changesets.visible raises an SQL error because of a double join on repositories if repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(repository.id, identifier)) link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.revision}, :class => 'changeset', :title => truncate_single_line(changeset.comments, :length => 100)) end end elsif sep == '#' oid = identifier.to_i case prefix when nil if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status) anchor = comment_id ? "note-#{comment_id}" : nil link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor}, :class => issue.css_classes, :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") end when 'document' if document = Document.visible.find_by_id(oid) link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, :class => 'document' end when 'version' if version = Version.visible.find_by_id(oid) link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, :class => 'version' end when 'message' if message = Message.visible.find_by_id(oid, :include => :parent) link = link_to_message(message, {:only_path => only_path}, :class => 'message') end when 'forum' if board = Board.visible.find_by_id(oid) link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, :class => 'board' end when 'news' if news = News.visible.find_by_id(oid) link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, :class => 'news' end when 'project' if p = Project.visible.find_by_id(oid) link = link_to_project(p, {:only_path => only_path}, :class => 'project') end end elsif sep == ':' # removes the double quotes if any name = identifier.gsub(%r{^"(.*)"$}, "\\1") case prefix when 'document' if project && document = project.documents.visible.find_by_title(name) link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, :class => 'document' end when 'version' if project && version = project.versions.visible.find_by_name(name) link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, :class => 'version' end when 'forum' if project && board = project.boards.visible.find_by_name(name) link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, :class => 'board' end when 'news' if project && news = project.news.visible.find_by_title(name) link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, :class => 'news' end when 'commit', 'source', 'export' if project repository = nil if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$} repo_prefix, repo_identifier, name = $1, $2, $3 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} else repository = project.repository end if prefix == 'commit' if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, :class => 'changeset', :title => truncate_single_line(changeset.comments, :length => 100) end else if repository && User.current.allowed_to?(:browse_repository, project) name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} path, rev, anchor = $1, $3, $5 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, :path => to_path_param(path), :rev => rev, :anchor => anchor}, :class => (prefix == 'export' ? 'source download' : 'source') end end repo_prefix = nil end when 'attachment' attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) if attachments && attachment = Attachment.latest_attach(attachments, name) link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') end when 'project' if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first link = link_to_project(p, {:only_path => only_path}, :class => 'project') end end end end (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}")) end end HEADING_RE = /(]+)?>(.+?)<\/h(\d)>)/i unless const_defined?(:HEADING_RE) def parse_sections(text, project, obj, attr, only_path, options) return unless options[:edit_section_links] text.gsub!(HEADING_RE) do heading = $1 @current_section += 1 if @current_section > 1 content_tag('div', link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)), :class => 'contextual', :title => l(:button_edit_section)) + heading.html_safe else heading end end end # Headings and TOC # Adds ids and links to headings unless options[:headings] is set to false def parse_headings(text, project, obj, attr, only_path, options) return if options[:headings] == false text.gsub!(HEADING_RE) do level, attrs, content = $2.to_i, $3, $4 item = strip_tags(content).strip anchor = sanitize_anchor_name(item) # used for single-file wiki export anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) @heading_anchors[anchor] ||= 0 idx = (@heading_anchors[anchor] += 1) if idx > 1 anchor = "#{anchor}-#{idx}" end @parsed_headings << [level, anchor, item] "\n#{content}" end end MACROS_RE = /( (!)? # escaping ( \{\{ # opening tag ([\w]+) # macro name (\(([^\n\r]*?)\))? # optional arguments ([\n\r].*?[\n\r])? # optional block of text \}\} # closing tag ) )/mx unless const_defined?(:MACROS_RE) MACRO_SUB_RE = /( \{\{ macro\((\d+)\) \}\} )/x unless const_defined?(:MACRO_SUB_RE) # Extracts macros from text def catch_macros(text) macros = {} text.gsub!(MACROS_RE) do all, macro = $1, $4.downcase if macro_exists?(macro) || all =~ MACRO_SUB_RE index = macros.size macros[index] = all "{{macro(#{index})}}" else all end end macros end # Executes and replaces macros in text def inject_macros(text, obj, macros, execute=true) text.gsub!(MACRO_SUB_RE) do all, index = $1, $2.to_i orig = macros.delete(index) if execute && orig && orig =~ MACROS_RE esc, all, macro, args, block = $2, $3, $4.downcase, $6.to_s, $7.try(:strip) if esc.nil? h(exec_macro(macro, obj, args, block) || all) else h(all) end elsif orig h(orig) else h(all) end end end TOC_RE = /

    \{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) # Renders the TOC with given headings def replace_toc(text, headings) text.gsub!(TOC_RE) do # Keep only the 4 first levels headings = headings.select{|level, anchor, item| level <= 4} if headings.empty? '' else div_class = 'toc' div_class << ' right' if $1 == '>' div_class << ' left' if $1 == '<' out = "

    ' * (current - root) out << '' end end end # Same as Rails' simple_format helper without using paragraphs def 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 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 def label_tag_for(name, option_tags = nil, options = {}) label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "") content_tag("label", label_text) end def labelled_form_for(*args, &proc) args << {} unless args.last.is_a?(Hash) options = args.last if args.first.is_a?(Symbol) options.merge!(:as => args.shift) end options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) form_for(*args, &proc) end def labelled_fields_for(*args, &proc) args << {} unless args.last.is_a?(Hash) options = args.last options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) fields_for(*args, &proc) end def labelled_remote_form_for(*args, &proc) ActiveSupport::Deprecation.warn "ApplicationHelper#labelled_remote_form_for is deprecated and will be removed in Redmine 2.2." args << {} unless args.last.is_a?(Hash) options = args.last options.merge!({:builder => Redmine::Views::LabelledFormBuilder, :remote => true}) form_for(*args, &proc) end def error_messages_for(*objects) html = "" # modified by fq if objects.first.is_a?(Array) objects = objects.first end # end if objects != nil objects = objects.map {|o| o.is_a?(String) ? instance_variable_get("@#{o}") : o}.compact errors = objects.map {|o| o.errors.full_messages}.flatten if errors.any? html << "
    \n" end end html.html_safe end def delete_link(url, options={}) options = { :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del' }.merge(options) link_to l(:button_delete), url, options end def delete_version_link(url, options={}) options = { :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del' }.merge(options) link_to "", url, options end def delete_link_version(url, options={}) options = { :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'c_purple' }.merge(options) link_to l(:button_delete), url, options end def delete_new_link(url, options={}) options = { :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => "c_purple" }.merge(options) link_to l(:button_delete), url, options end def preview_link(url, form, target='preview', options={}) content_tag 'a', l(:label_preview), { :href => "#", :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|, :accesskey => accesskey(:preview) }.merge(options) end def link_to_function(name, function, html_options={}) content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:class => "BlueCirBtnMini ml10",:style => "display:inline-block; height:20px; line-height:20px;")) end def link_to_function_none(name, function, html_options={}) content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:style => "display:inline-block; height:20px; line-height:20px;")) end # Helper to render JSON in views def raw_json(arg) arg.to_json.to_s.gsub('/', '\/').html_safe end def back_url url = params[:back_url] if url.nil? && referer = request.env['HTTP_REFERER'] url = CGI.unescape(referer.to_s) end url end def back_url_hidden_field_tag url = back_url hidden_field_tag('back_url', url, :id => nil) unless url.blank? end def check_all_links(form_name) link_to_function_none(l(:button_check_all), "checkAll('#{form_name}', true)") + " ".html_safe + " | "+ " ".html_safe + link_to_function_none(l(:button_uncheck_all), "checkAll('#{form_name}', false)") end # 本次修改,修改为只显示关闭的所占%比 def progress_bar(pcts, options={}) pcts = [pcts] unless pcts.is_a?(Array) pcts = pcts.collect(&:round) # pcts[1] = pcts[1] + pcts[0] pcts << (100 - pcts[0]) width = options[:width] || '100px;' legend = options[:legend] || '' content_tag('span', content_tag('tr', (pcts[0] > 0 ? content_tag('span', '', :style => "width: #{pcts[0]}%;", :class => 'roadmap_progressbar_inner', :title => "已关闭:#{pcts[0]}%") : ''.html_safe) #+ # (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done', :title => "开发中:#{pcts[1]}%") : ''.html_safe) + #(pcts[1] > 0 ? content_tag('span', '', :style => "width: #{pcts[1]}%;", :class => 'roadmap_progressbar ml5', :title => "未完成:#{pcts[1]}%") : ''.html_safe), :style => "width: #{width}" ), :class => 'roadmap_progressbar ml5').html_safe # + content_tag('p', legend, :class => 'percent').html_safe end def checked_image(checked=true) if checked image_tag 'toggle_check.png' end end def context_menu(url) unless @context_menu_included content_for :header_tags do javascript_include_tag('context_menu') + stylesheet_link_tag('context_menu') end if l(:direction) == 'rtl' content_for :header_tags do stylesheet_link_tag('context_menu_rtl') end end @context_menu_included = true end javascript_tag "contextMenuInit('#{ url_for(url) }')" end def calendar_for(field_id,start_day=nil) include_calendar_headers_tags(start_day) javascript_tag("$(function() { $('##{field_id}').datepicker(datepickerOptions); });") end def include_calendar_headers_tags(start_day=nil) if start_day.nil? unless @calendar_headers_tags_included @calendar_headers_tags_included = true content_for :header_tags do start_of_week = Setting.start_of_week start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? # Redmine uses 1..7 (monday..sunday) in settings and locales # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 start_of_week = start_of_week.to_i % 7 tags = javascript_tag( "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + "showOn: 'button', buttonImageOnly: true, buttonImage: '" + path_to_image('/images/public_icon.png') + "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};") jquery_locale = l('jquery.locale', :default => current_language.to_s) unless jquery_locale == 'en' tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") end tags end end else unless @calendar_headers_tags_included @calendar_headers_tags_included = true content_for :header_tags do start_of_week = Setting.start_of_week start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? # Redmine uses 1..7 (monday..sunday) in settings and locales # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 start_of_week = start_of_week.to_i % 7 tags = javascript_tag( "var datepickerOptions={dateFormat: 'yy-mm-dd',minDate: new Date(), firstDay: #{start_of_week}, " + "showOn: 'button', buttonImageOnly: true, buttonImage: '" + path_to_image('/images/public_icon.png') + "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true, onClose: function(dateText, inst) {TimeClose(dateText,inst);}, beforeShow : function(input){TimeBeforeShow(input);} };") jquery_locale = l('jquery.locale', :default => current_language.to_s) unless jquery_locale == 'en' tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") end tags end end end end # Overrides Rails' stylesheet_link_tag with themes and plugins support. # Examples: # stylesheet_link_tag('styles') # => picks styles.css from the current theme or defaults # stylesheet_link_tag('styles', :plugin => 'foo) # => picks styles.css from plugin's assets # def stylesheet_link_tag(*sources) options = sources.last.is_a?(Hash) ? sources.pop : {} plugin = options.delete(:plugin) sources = sources.map do |source| if plugin "/plugin_assets/#{plugin}/stylesheets/#{source}" elsif current_theme && current_theme.stylesheets.include?(source) current_theme.stylesheet_path(source) else source end end super sources, options end # Overrides Rails' image_tag with themes and plugins support. # Examples: # image_tag('image.png') # => picks image.png from the current theme or defaults # image_tag('image.png', :plugin => 'foo) # => picks image.png from plugin's assets # def image_tag(source, options={}) if plugin = options.delete(:plugin) source = "/plugin_assets/#{plugin}/images/#{source}" elsif current_theme && current_theme.images.include?(source) source = current_theme.image_path(source) end super source, options end # Overrides Rails' javascript_include_tag with plugins support # Examples: # javascript_include_tag('scripts') # => picks scripts.js from defaults # javascript_include_tag('scripts', :plugin => 'foo) # => picks scripts.js from plugin's assets # def javascript_include_tag(*sources) options = sources.last.is_a?(Hash) ? sources.pop : {} @sources ||= [] sources = sources.delete_if do|source| @sources.include?(source) end @sources += sources if plugin = options.delete(:plugin) sources = sources.map do |source| if plugin "/plugin_assets/#{plugin}/javascripts/#{source}" else source end end end if sources && !sources.empty? super(sources, options) else '' end end def content_for(name, content = nil, &block) @has_content ||= {} @has_content[name] = true super(name, content, &block) end def has_content?(name) (@has_content && @has_content[name]) || false end def sidebar_content? has_content?(:sidebar) || view_layouts_base_sidebar_hook_response.present? end def view_layouts_base_sidebar_hook_response @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar) end def email_delivery_enabled? !!ActionMailer::Base.perform_deliveries end # Returns the avatar image tag for the given +user+ if avatars are enabled # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe ') def avatar(user, options = { }) if Setting.gravatar_enabled? options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default}) email = nil if user.respond_to?(:mail) email = user.mail elsif user.to_s =~ %r{<(.+?)>} email = $1 end return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil #options ={"class" => ["avatar2"],"width" =>["80px"],"height" =>["80px"]} #return image_tag url_to_avatar(user), options else '' end end def sanitize_anchor_name(anchor) if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-') else # TODO: remove when ruby1.8 is no longer supported anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') end end # Returns the javascript tags that are included in the html layout head def javascript_heads tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'application', 'jquery.colorbox-min') unless User.current.pref.warn_on_leaving_unsaved == '0' tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") end tags end def hubspot_head tags = javascript_include_tag('hubspot/messenger.min', 'hubspot/messenger-theme-future') tags << stylesheet_link_tag('hubspot/messenger', 'hubspot/messenger-theme-future', 'hubspot/messenger-theme-flat') end def bootstrap_head tags = stylesheet_link_tag('bootstrap/bootstrap.min', 'bootstrap/bootstrap-theme.min') tags << javascript_include_tag('bootstrap/affix') tags << javascript_include_tag('bootstrap/alert') tags << javascript_include_tag('bootstrap/button') tags << javascript_include_tag('bootstrap/carousel') tags << javascript_include_tag('bootstrap/collapse') tags << javascript_include_tag('bootstrap/dropdown') tags << javascript_include_tag('bootstrap/modal') tags << javascript_include_tag('bootstrap/popover') tags << javascript_include_tag('bootstrap/scrollspy') tags << javascript_include_tag('bootstrap/tab') tags << javascript_include_tag('bootstrap/tooltip') tags << javascript_include_tag('bootstrap/transition') tags end def favicon "".html_safe end def robot_exclusion_tag ''.html_safe end # Returns true if arg is expected in the API response def include_in_api_response?(arg) unless @included_in_api_response param = params[:include] @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',') @included_in_api_response.collect!(&:strip) end @included_in_api_response.include?(arg.to_s) end # Returns options or nil if nometa param or X-Redmine-Nometa header # was set in the request def api_meta(options) if params[:nometa].present? || request.headers['X-Redmine-Nometa'] # compatibility mode for activeresource clients that raise # an error when unserializing an array with attributes nil else options end end # Add by Tao def url_to_avatar(source) source = nil if source.kind_of?(String) get_avatar(source) end # Endof Tao's code def date_format_local(time) date = time.strftime("%Y年%m月%d日") end #当TAG数量过多时,更多链接 #1代表是user类型 2代表是project类型 3代表是issue类型 4代表需求 9代表课程 def more_tags id,object_flag a= 1 case object_flag when "1" s = link_to l(:label_more_tags),:controller => "users", :action => "show", :id => id when "2" s = link_to l(:label_more_tags),:controller => "projects", :action => "show", :id => id when "3" s = link_to l(:label_more_tags),:controller => "issues", :action => "show", :id => id when "4" s = link_to l(:label_more_tags),:controller => "bids", :action => "show", :id => id when "9" s = link_to l(:label_more_tags),:controller => "courses", :action => "show", :id => id end s end def get_user_identity identity s = "" case identity when 0 s = '教师' when 1 s = '学生' when 2 s = '组织' when 3 s= '开发者' else s = '学生' end s end # 获取issue类型 def get_issue_type_new tracker_id case tracker_id when 1 "缺陷" when 2 "功能" when 3 "支持" when 4 "任务" when 5 "周报" end end def get_memo @new_memo = Memo.new @public_forum = Forum.find(1) rescue ActiveRecord::RecordNotFound end #获取用户未过期的课程 def get_user_course user courses_doing = [] user.courses.select("courses.*,(SELECT MAX(created_at) FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a").order("a desc").each do |course| if !course_endTime_timeout?(course) courses_doing.push course end end courses_doing end def attachment_history_candown attachment_history if attachment_history.container_type == "Course" course = Course.find(attachment_history.container_id) candown = User.current.member_of_course?(course) || (course.is_public && attachment_history.is_public == 1) elsif attachment_history.container_type == "Project" project = Project.find(attachment_history.container_id) candown = User.current.member_of?(project) || (project.is_public && attachment_history.is_public == 1) elsif attachment_history.container_type == "OrgSubfield" org = OrgSubfield.find(attachment_history.container_id).organization candown = User.current.member_of_org?(org) || (org.organization.is_public && attachment_history.is_public == 1 && (User.current.logged? || org.organization.allow_guest_download?)) end end def attachment_candown attachment candown = false if attachment.container if attachment.container.class.to_s=="PhoneAppVersion" candown = true elsif attachment.container.class.to_s != "HomeworkAttach" && attachment.container.class.to_s != "StudentWork" && (attachment.container.has_attribute?(:project) || attachment.container.has_attribute?(:project_id)) && attachment.container.project project = attachment.container.project candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) elsif attachment.container.is_a?(Project) project = attachment.container candown = User.current.member_of?(project) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && attachment.container.board.project project = attachment.container.board.project candown = User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) elsif (attachment.container.has_attribute?(:course) ||attachment.container.has_attribute?(:course_id) ) && attachment.container.course course = attachment.container.course candown = User.current.member_of_course?(course) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 elsif attachment.container.is_a?(Course) course = attachment.container candown= User.current.member_of_course?(course) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 elsif attachment.container.is_a?(OrgSubfield) org = attachment.container.organization candown = User.current.member_of_org?(org) || ((attachment.is_public == 1 || attachment.get_status_by_attach(User.current.id) == 2) && org.allow_guest_download == true) elsif attachment.container.is_a?(OrgDocumentComment) org = attachment.container.organization candown = org.allow_guest_download || User.current.member_of_org?(org) || (org.is_public && attachment.is_public == 1) elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && attachment.container.board.course course = attachment.container.board.course candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1) elsif attachment.container.class.to_s=="Organization" candown = true elsif attachment.container.class.to_s=="HomeworkAttach" candown = true elsif attachment.container.class.to_s=="StudentWorksScore" candown = true elsif attachment.container.class.to_s=="StudentWork" candown = true elsif attachment.container.class.to_s=="BlogComment" #博客资源允许下载 candown = true elsif attachment.container.class.to_s=="Memo" #论坛资源允许下载 candown = true elsif attachment.container.class.to_s=="Syllabus" #论坛资源允许下载 candown = true elsif attachment.container.class.to_s == "User" candown = (attachment.is_public == 1 || attachment.is_public == true || attachment.author_id == User.current.id) elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses course = attachment.container.courses.first candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1) else candown = (attachment.is_public == 1 || attachment.is_public == true) end end candown end def project_type_link(text, value) if value == 1 link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" elsif value == 2 link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" else link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" end end #如果学生作品被打分后修改,应该给老师提示 def send_message_to_teacher student_work if StudentWork === student_work if student_work.student_works_scores.any? course = student_work.homework_common.course course.members.map(&:user_id).uniq.each do|user_id| if User.find(user_id).allowed_to?(:as_teacher, course) student_work.course_messages << CourseMessage.new(:user_id => user_id, :course_id => course.id, :viewed => false, :status => 1) end end end end end private def wiki_helper helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) extend helper return self end def link_to_content_update(text, url_params = {}, html_options = {}) link_to(text, url_params, html_options) end #added by nie # Display watcher picture def show_more_watchers?(obj) if User.watched_by(obj.id).count > 6 return true else return false end end def show_watcher_profile(obj) count = 0 html = '' if User.watched_by(obj.id).count == 0 html << (content_tag "span", l(:label_no_current_watchers)) end for user in User.watched_by(obj.id) html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}") count = count + 1 if count >= 12 break end end html.html_safe end #display bid project def show_more_bid_project?(bid) if bid.projects.where('is_public = 1').count > 12 return true else return false end end def show_bid_project(bid) html = '' if bid.projects.where('is_public = 1').count == 0 html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") else bid.projects.where('is_public = 1').take(12).each do |project| html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") end end html.html_safe end def show_bid_fans_picture(obj) html = '' if obj.watcher_users.count == 0 html << (content_tag "span", l(:label_project_no_follow)) else obj.watcher_users.take(12).each do |user| html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) end end html.html_safe end #display contest project def show_more_contest_project?(contest) if contest.projects.where('is_public = 1').count > 12 return true else return false end end def show_more_contest_softapplication?(contest) if contest.softapplications.where('is_public = 1').count > 12 return true else return false end end def show_contest_project(bid) html = '' if contest.projects.where('is_public = 1').count == 0 html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") else contest.projects.where('is_public = 1').take(12).each do |project| html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") end end html.html_safe end def show_contest_project(contest) html = '' if contest.projects.where('is_public = 1').count == 0 html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") else contest.projects.where('is_public = 1').take(12).each do |project| html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") end end html.html_safe end def show_contest_softapplication(contest) html = '' if contest.softapplications.where('is_public = 1').count == 0 html << (content_tag "p", l(:label_no_contest_softapplication), :class => "font_lighter") else contest.softapplications.where('is_public = 1').take(12).each do |softapplication| html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") end end html.html_safe end def show_contest_fans_picture(obj) html = '' if obj.watcher_users.count == 0 html << (content_tag "span", l(:label_project_no_follow)) else obj.watcher_users.take(12).each do |user| html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) end end html.html_safe end #display fans picture def show_more_fans?(obj) if obj.watcher_users.count > 12 return true else return false end end def show_fans_picture(obj) html = '' if obj.watcher_users.count == 0 html << (content_tag "span", l(:label_no_current_fans)) else obj.watcher_users.take(12).each do |user| html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) end end html.html_safe end # added by bai def show_more_participate?(obj) if obj.join_in_contests.count > 12 return true else return false end end def show_participate_picture(obj) html = '' count = 0 if obj.join_in_contests.count == 0 html << (content_tag "span", l(:label_no_current_participate)) end for temp in obj.join_in_contests html << (link_to image_tag(url_to_avatar(temp.user), :class => "avatar"), user_path(temp.user), :class => "avatar", :title => "#{temp.user.name}") count = count + 1 if count >= 12 break end end html.html_safe end #end # add by huang def show_watcher_list(user) html = '' count = 0 for user in User.watched_by(user.id) html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}") count = count + 1 if count >= 12 break end end html.html_safe end # end #added by william def get_fans_num(user) user.watcher_users.count end #end def hadcommittedhomework(cur,curb) bid = Bid.find_by_id(curb) return true if bid.nil? case bid.homework_type when Bid::HomeworkFile attaches = HomeworkAttach.where(bid_id: curb) attaches.map(&:user_id).include? cur when Bid::HomeworkProject attaches = BidingProject.where(user_id: User.current, bid_id: bid) attaches.count > 0 # > 0 则有提交记录 else true end end def render_dynamic_nav home_link = link_to l(:field_homepage), {:controller => 'welcome', :action => 'index'} home_link = "
  • " << home_link << "
  • " # bootstrap_render_dynamic_nav content_tag :ul, (home_link.html_safe+bootstrap_render_dynamic_nav) end def bootstrap_render_dynamic_nav hidden_non_project = Setting.find_by_name("hidden_non_project") visiable = !(hidden_non_project && hidden_non_project.value == "0") main_course_link = link_to l(:label_course_practice), {:controller => 'welcome', :action => 'index', :host => Setting.host_course} main_project_link = link_to l(:label_project_deposit), {:controller => 'welcome', :action => 'index', :host => Setting.host_name} main_contest_link = link_to l(:label_contest_innovate), {:controller => 'welcome', :action => 'index', :host => Setting.host_contest} # course_all_course_link = link_to l(:label_course_all), {:controller => 'courses', :action => 'index'} course_teacher_all_link = link_to l(:label_teacher_all), {:controller => 'users', :action => 'index', :role => 'teacher', :host => Setting.host_course} # courses_link = link_to l(:label_course_practice), {:controller => 'courses', :action => 'index'} #users_link = link_to l(:label_software_user), {:controller => 'users', :action => 'index', :host => Setting.host_user} # contest_link = link_to l(:label_contest_innovate), {:controller => 'contests', :action => 'index'} # bids_link = link_to l(:label_requirement_enterprise), {:controller => 'bids', :action => 'index'} forum_link = link_to l(:label_forum_all), {:controller => "forums", :action => "index"} stores_link = link_to l(:label_stores_index), {:controller => 'stores', :action=> 'index'} school_all_school_link = link_to l(:label_school_all), {:controller => 'school', :action => 'index'} project_new_link = link_to l(:label_project_new), {:controller => 'projects', :action => 'new', :host => Setting.host_name} # project_mine_link = link_to l(:label_my_project), {:controller => 'users', :action => 'user_projects', :host => Setting.host_name} #@nav_dispaly_project_label nav_list = Array.new nav_list.push(school_all_school_link) if @nav_dispaly_course_all_label && @show_course == 1 && visiable # nav_list.push(course_all_course_link) if @nav_dispaly_course_all_label && @show_course == 1 nav_list.push(course_teacher_all_link) if @nav_dispaly_teacher_all_label && @show_course == 1 && visiable nav_list.push(main_project_link) if @nav_dispaly_main_project_label nav_list.push(main_course_link) if @nav_dispaly_main_course_label && @show_course == 1 && visiable nav_list.push(main_contest_link) if @nav_dispaly_main_contest_label && @show_contest == 1 && visiable nav_list.push(courses_link) if @nav_dispaly_course_label && @show_course == 1 && visiable nav_list.push(project_new_link) if @nav_dispaly_project_label # nav_list.push(project_mine_link) if @nav_dispaly_main_project_label # nav_list.push(projects_link) if @nav_dispaly_project_label #nav_list.push(users_link) if @nav_dispaly_user_label # nav_list.push(contest_link) if @nav_dispaly_contest_label && @show_contest == 1 nav_list.push(bids_link) if @nav_dispaly_bid_label && visiable nav_list.push(forum_link) if @nav_dispaly_forum_label && visiable nav_list.push(stores_link) if @nav_dispaly_store_all_label && visiable content_li = '' nav_list.collect do |nav_item| content_li << content_tag(:li, nav_item, :class => 'topnav_a fl') end content_li.html_safe end def current_user User.current end # def hadcommittedforcontest(curu) # message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ") # message.each do |createmessage| # if createmessage.user_id == curu # return true # end # end # end def footer_logo(ul_class=nil, li_class=nil) logos = [] logos.push(link_to image_tag('/images/footer_logo/nudt.png',:alt=>"nudt"),"http://www.nudt.edu.cn/special.asp?classid=12" ) logos.push(link_to image_tag('/images/footer_logo/peking_eecs.png', :alt=>"peking_eecs"), "http://www.sei.pku.edu.cn/" ) logos.push(link_to image_tag('/images/footer_logo/buaa_scse.png', :alt=>"buaa_scse"), "http://scse.buaa.edu.cn/" ) logos.push(link_to image_tag('/images/footer_logo/iscas.png', :alt=>"iscas"), "http://www.iscas.ac.cn" ) logos.push(link_to image_tag('/images/footer_logo/inforbus.png', :alt=>"inforbus"), "http://www.inforbus.com" ) logos.collect! { |logo| content_tag(:li, logo.html_safe, :class => li_class.to_s) } content_tag(:ul, logos.join("").html_safe, :class => ul_class.to_s).html_safe end def sort_homework_path(bid, sort, direction) case self.action_name when 'show_courseEx' get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc') when 'get_not_batch_homework' get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) when 'get_batch_homeworks' get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) when 'get_homeworks' get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) else '#' end end def anonymous_comment_link(bid, course) link = case bid.comment_status when 0 confirm_info = "开启匿评后学生将不能对作品进行提交、修改、删除等操作\n" confirm_info += anonymous_comment_notice(bid,course) confirm_info += '是否确定开启匿评?' link_to '启动匿评', start_anonymous_comment_bid_path(bid), id: "#{bid.id}_start_anonymous_comment", remote: true, :confirm => confirm_info, disable_with: '加载中...' when 1 confirm_info = "关闭匿评后所有同学将不能继续进行匿评,且将公开已提交作品列表\n" confirm_info += anonymous_comment_notice(bid,course) confirm_info += '是否确定关闭匿评?' link_to '关闭匿评', stop_anonymous_comment_bid_path(bid), id: "#{bid.id}_stop_anonymous_comment", remote: true, :confirm => confirm_info when 2 '匿评结束' end content_tag('span', link, id: "#{bid.id}_anonymous_comment") end def anonymous_comment_notice(bid, course) case bid.comment_status when 0 @student_size ||= searchStudent(course).size @homework_size = bid.homeworks.size percent = @homework_size.to_f / (@student_size == 0 ? 1 : @student_size) confirm_info = "目前#{@student_size}个学生,总共提交了#{@homework_size}份作品,占#{number_to_percentage(percent * 100, precision: 1)}\n" when 1 @homework_evaluations = 0 bid.homeworks.map { |homework| @homework_evaluations += homework.homework_evaluations.count} teachers = "(" teacher_members = searchTeacherAndAssistant(course) teacher_members.each do |member| if member == teacher_members.last teachers += member.user_id.to_s + ")" else teachers += member.user_id.to_s + "," end end @has_evaluations = 0 bid.homeworks.map { |homework| @has_evaluations += homework.rates(:quality).where("seems_rateable_rates.rater_id not in #{teachers}").count} percent = @has_evaluations.to_f / (@homework_evaluations == 0 ? 1 : @homework_evaluations) confirm_info = "目前总共分配了#{@homework_evaluations}份匿评作品,已评价#{@has_evaluations}份作品,占#{number_to_percentage(percent * 100, precision: 1)}\n" end confirm_info end def get_technical_title user if user.user_extensions.technical_title == "Professor" || user.user_extensions.technical_title == "教授" technical_title = l(:label_technicl_title_professor) elsif user.user_extensions.technical_title == "Associate professor" || user.user_extensions.technical_title == "副教授" technical_title = l(:label_technicl_title_associate_professor) elsif user.user_extensions.technical_title == "Lecturer" || user.user_extensions.technical_title == "讲师" technical_title = l(:label_technicl_title_lecturer) elsif user.user_extensions.technical_title == "Teaching assistant" || user.user_extensions.technical_title == "助教" technical_title = l(:label_technicl_title_teaching_assistant) end technical_title end def get_user_roll user technical_title = "" case user.user_extensions.identity.to_s when "0" technical_title = get_technical_title user when "1" technical_title = l(:label_account_identity_student) when "2" technical_title = l(:label_account_identity_enterprise) when "3" technical_title = l(:label_account_identity_developer) end technical_title end def ie8? request.env["HTTP_USER_AGENT"] =~ /MSIE 8.0/ end #获取指定资源列表的TAG的集合以及每个TAG的数量,降序排序 def attachment_tag_list attachments tag_list = Hash.new attachments.each do |attachment| attachment.tag_list.map{|tag| tag_list.has_key?(tag) ? tag_list[tag] = tag_list[tag] + 1 : tag_list[tag] = 1} end tag_list.sort {|a,b| b[1]<=>a[1]} end #获取课程资源的TAG云 def get_course_tag_list course all_attachments = course.attachments.select{|attachment| attachment.is_public? || (attachment.container_type == "Course" && User.current.member_of_course?(course))|| attachment.author_id == User.current.id } tag_list = attachment_tag_list all_attachments tag_list end # 获取项目资源的Tag云 def get_project_tag_list project all_attachments = project.attachments.select{|attachment| attachment.is_public? || (attachment.container_type == "Project" && User.current.member_of?(project))|| attachment.author_id == User.current.id } tag_list = attachment_tag_list all_attachments tag_list end def get_org_subfield_tag_list org_subfield all_attachments = org_subfield.attachments.select{|attachment| attachment.is_public? || (attachment.container_type == "OrgSubfield" && User.current.member_of_org?(org_subfield.organization))|| attachment.author_id == User.current.id } tag_list = attachment_tag_list all_attachments tag_list end #获取匿评相关连接代码 def homework_anonymous_comment (homework, hw_status, user_activity_id = -1) if homework.homework_detail_manual.comment_status == 0 ||Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") link = link_to "启动匿评","javascript:void(0)", :class => "postOptionLink", :title => "作业截止日期之前不可以启动匿评" elsif homework.student_works.has_committed.count >= 2 && homework.homework_detail_manual#作业份数大于2 case homework.homework_detail_manual.comment_status when 1 link = link_to '启动匿评', Setting.protocol + "://" + Setting.host_name + "/homework_common/" + homework.id.to_s + "/alert_anonymous_comment?hw_status=" + hw_status.to_s + "&user_activity_id=" + user_activity_id.to_s, id: "#{homework.id}_start_anonymous_comment", remote: true, disable_with: '加载中...',:class => 'postOptionLink' when 2 link = link_to '关闭匿评', Setting.protocol + "://" + Setting.host_name + "/homework_common/" + homework.id.to_s + "/alert_anonymous_comment?hw_status=" + hw_status.to_s + "&user_activity_id=" + user_activity_id.to_s, id: "#{homework.id}_stop_anonymous_comment", remote: true,:class => 'postOptionLink' when 3 # link = link_to "匿评结束","javascript:void(0)", :class => "postOptionLink", :title => "匿评结束" end else link = link_to "启动匿评","javascript:void(0)", :class => "postOptionLink", :title => "学生提交作业数大于等于2时才可以启动匿评" end link end #学生根据传入作业确定显示为编辑作品还是新建作品 def student_new_homework homework work = cur_user_works_for_homework homework if work.nil? link_to "提交作品", new_student_work_path(:homework => homework.id),:class => 'fr mr10 work_edit' else if homework.homework_type == 1 && homework.homework_detail_manual && homework.homework_detail_manual.comment_status != 1 #匿评作业,且作业状态不是在开启匿评之前 link_to "作品已交", "javascript:void(0);", :class => 'fr mr10 pr_join_span c_white', :title => "开启匿评后不可修改作品" elsif homework.homework_type == 2 #编程作业修改作品 if homework.homework_detail_manual && homework.homework_detail_manual.comment_status != 1 link_to "作品已交", "javascript:void(0);", :class => 'fr mr10 pr_join_span c_white', :title => "开启匿评后不可修改作品" else link_to "修改作品", new_student_work_path(:homework => homework.id),:class => 'fr mr10 work_edit' end else link_to "修改作品", edit_student_work_path(work.id),:class => 'fr mr10 work_edit' end end end #动态列表中,确定学生是该提交还是进列表 def student_work_activity_submit_status(opt={}) default_opt = {class: 'c_blue'}.merge(opt) is_teacher = User.current.user_extensions && User.current.user_extensions.identity == 0 && User.current.allowed_to?(:add_course, nil, :global => true) homework = default_opt[:homework] work = cur_user_works_for_homework homework if work.nil? && !is_teacher link_to "提交("+homework.student_works.count.to_s+")", new_student_work_path(:homework => homework.id,:host=> Setting.host_course), :class=> default_opt[:class] else link_to "提交("+homework.student_works.count.to_s+")", student_work_index_path(:homework => homework.id,:host=> Setting.host_course), :class=> default_opt[:class] end end #根据传入作业确定显示为编辑作品还是新建作品,或者显示作品数量 def user_for_homework_common homework,is_teacher count = homework.student_works.has_committed.count if User.current.member_of_course?(homework.course) if is_teacher #老师显示作品数量 link_to "作品(#{count})", student_work_index_url_in_org(homework.id, 2), :class => "c_blue" else #学生显示提交作品、修改作品等按钮 work = cur_user_works_for_homework homework project = cur_user_projects_for_homework homework if work.nil? && Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 link_to "提交作品(#{count})","javascript:void(0)", :class => 'c_grey',:style=>"cursor:not-allowed",:title => '请先关联项目再提交作品' else link_to "提交作品(#{count})", new_student_work_url_without_domain(homework.id),:class => 'c_blue' end elsif work.nil? && Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") < Time.now.strftime("%Y-%m-%d") if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 link_to "补交作品(#{count})","javascript:void(0)", :class => 'c_grey',:style=>"cursor:not-allowed",:title => '请先关联项目再补交作品' else link_to "补交作品(#{count})", new_student_work_url_without_domain(homework.id),:class => 'c_red' end else if homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 2 && StudentWorksEvaluationDistribution.where("student_work_id = #{work.id}").count > 0 #匿评作业,且作业状态不是在开启匿评之前 if homework.homework_type != 3 link_to "作品匿评", student_work_index_url_in_org(homework.id, 2), :class => 'c_blue', :title => "开启匿评后不可修改作品" else work_ids = "(" + homework.student_works.has_committed.map(&:id).join(",") + ")" if User.current.student_works_evaluation_distributions.where("student_work_id IN #{work_ids}").count > 0 link_to "作品匿评", student_work_index_url_in_org(homework.id, 2), :class => 'c_blue', :title => "开启匿评后不可修改作品" else link_to "查看作品(#{count})",student_work_index_url_in_org(homework.id, 2), :class => 'c_blue', :title => "匿评开启后提交的作品不参与匿评" end end elsif homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 3 link_to "查看作品(#{count})",student_work_index_url_in_org(homework.id, 2), :class => 'c_blue', :title => "匿评已结束" elsif homework.homework_type == 2 && Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d")#编程作业不能修改作品 link_to "修改作品(#{count})", new_student_work_url_without_domain(homework.id),:class => 'c_blue' elsif Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") && work.user_id == User.current.id link_to "修改作品(#{count})", edit_student_work_url_without_domain(work.id),:class => 'c_blue' else link_to "查看作品(#{count})", student_work_index_url_in_org(homework.id, 2), :class => 'c_blue', :title => "作业截止后不可修改作品" end end end else link_to "作品(#{count})",student_work_index_url_in_org(homework.id, 2),:class => "c_blue" end end #根据传入作业确定显示为提交作品、补交作品、查看作品等 def student_for_homework_common homework if User.current.member_of_course?(homework.course) work = cur_user_works_for_homework homework project = cur_user_projects_for_homework homework if work.nil? && Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 link_to "查看详情", homework_common_index_path(:course_id => homework.course_id), :class => 'hw_btn_green2 fr mt5',:title => '查看分组作业详情', :target => '_blank' else link_to "提交作品", new_student_work_url_without_domain(homework.id),:class => 'hw_btn_green2 fr mt5', :target => '_blank' end elsif work.nil? && Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") < Time.now.strftime("%Y-%m-%d") if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 link_to "查看详情", homework_common_index_path(:course_id => homework.course_id), :class => 'hw_btn_green2 fr mt5',:title => '查看分组作业详情', :target => '_blank' else link_to "补交作品", new_student_work_url_without_domain(homework.id),:class => 'btn_orange_big fr mt5', :target => '_blank' end else if homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 2 #匿评作业,且作业状态不是在开启匿评之前 link_to "作品匿评", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green2 fr mt5', :title => "开启匿评后不可修改作品", :target => '_blank' elsif homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 3 link_to "查看作品",student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green2 fr mt5', :title => "匿评已结束", :target => '_blank' elsif homework.homework_type == 2 && Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d")#编程作业不能修改作品 link_to "修改作品", new_student_work_url_without_domain(homework.id),:class => 'hw_btn_green2 fr mt5', :target => '_blank' elsif Time.parse(homework.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") && work.user_id == User.current.id link_to "修改作品", edit_student_work_url_without_domain(work.id),:class => 'hw_btn_green2 fr mt5', :target => '_blank' else link_to "查看作品", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green2 fr mt5', :title => "作业截止后不可修改作品", :target => '_blank' end end end end def relate_project homework,is_teacher,is_in_course,user_activity_id,course_activity if User.current.member_of_course?(homework.course) if is_teacher #link_to "已关联(#{homework.student_work_projects.count})",student_work_index_path(:homework => homework.id),:class => "c_blue" else projects = cur_user_projects_for_homework homework works = cur_user_works_for_homework homework if works.nil? && projects.nil? link_to "关联项目",new_student_work_project_student_work_index_path(:homework => homework.id,:is_in_course=>is_in_course,:user_activity_id=>user_activity_id,:course_activity=>course_activity),remote: true,:class=> 'c_blue', :title=> '请选择分组作业关联的项目' elsif works.nil? link_to "取消关联",cancel_relate_project_student_work_index_path(:homework => homework.id,:is_in_course=>is_in_course,:user_activity_id=>user_activity_id,:course_activity=>course_activity), :confirm => "您确定要取消关联吗?", remote: true,:class => "c_blue", :title=> '取消关联项目' else #link_to "已关联(#{homework.student_work_projects.count})",student_work_index_path(:homework => homework.id),:class => "c_blue" end end end end def student_anonymous_comment homework if homework.homework_detail_manual case homework.homework_detail_manual.comment_status when 1 "未开启匿评".html_safe when 2 "正在匿评中".html_safe when 3 "匿评已结束".html_safe end end end #获取当前用户在指定作业下提交的作业的集合 def cur_user_works_for_homework homework work = homework.student_works.where("user_id = ? && work_status != 0",User.current).first if homework.homework_type == 3 pro = homework.student_work_projects.where("user_id = #{User.current.id}").first if pro.nil? || pro.student_work_id == "" || pro.student_work_id.nil? work = nil else work = StudentWork.find pro.student_work_id end end work end #获取当前用户在指定作业下关联的项目的集合 def cur_user_projects_for_homework homework homework.student_work_projects.where("user_id = ?",User.current).first end #获取当前作业的提交截止时间/互评截止时间 def cur_homework_end_time homework str = "" if homework.anonymous_comment == 0 && homework.end_time && homework.end_time < Date.today && homework.homework_detail_manual str = "互评截止:#{format_date homework.homework_detail_manual.evaluation_end}" else str = "提交截止:#{homework.end_time ? (format_date homework.end_time) : '       --       '}" end str end def file_preview_tag(file, html_options={}) if %w(pdf pptx doc docx xls xlsx).any?{|x| file.filename.downcase.end_with?(x)} link_to '预览', download_named_attachment_path(file.id, file.filename, preview: true),html_options end end def file_preview_eye(file, html_options={}) if %w(pdf pptx doc docx xls xlsx).any?{|x| file.filename.downcase.end_with?(x)} link_to '', User.current.logged? ? download_named_attachment_path(file.id, file.filename, preview: true) : signin_url_without_domain, html_options end end #将文本内的/n转换为
    def text_format text text.gsub("&","&").gsub("<","<").gsub(">",">").gsub("\n","
    ").html_safe end #评分规则显示 def scoring_rules late_penalty,homework_id,is_teacher,absence_penalty=nil if absence_penalty if late_penalty.to_i == 0 && absence_penalty.to_i == 0 notice = "尚未设置评分规则" if is_teacher notice += ",请 " + link_to("设置",edit_homework_common_path(homework_id),:class => "c_green") end elsif late_penalty.to_i != 0 && absence_penalty.to_i == 0 notice = "迟交扣#{late_penalty}分,缺评扣分未设置" elsif late_penalty.to_i == 0 && absence_penalty.to_i != 0 notice = "迟交扣分未设置,缺评一个作品扣#{absence_penalty}分" elsif late_penalty.to_i != 0 && absence_penalty.to_i != 0 notice = "迟交扣#{late_penalty}分,缺评一个作品扣#{absence_penalty}分" end else if late_penalty.to_i == 0 notice = "尚未设置评分规则" if is_teacher notice += ",请 " + link_to("设置",edit_homework_common_path(homework_id),:class => "c_green") end else notice = "迟交扣#{late_penalty}分" end end notice.html_safe end #老师C语言的标准代码 def c_stantard_code_teacher "// 老师您好!这是一个C语言的样例程序 // 程序功能:输入两个整数,输出两者之和 // 测试集合:老师可以给出多组测试集,例如: // 输入1和2,输出3 // 输入3和4,输出7 // ... ... // 系统将根据您给出的测试集对学生代码进行自动评分 // 特别提醒:程序采用命令行传参方式,输入通过argv传入 // 否则您的作业标准代码将不能通过测试 #include //引用必须头文件 int main(int argc, char** argv) { int a = atoi(argv[1]); //将第一个输入转成整型 int b = atoi(argv[2]); //将第二个输入转换为整型 printf(\"%d\",a+b); //输出a+b return 0; }".html_safe end #老师C++语言的标准代码 def c_stantard_code_teacher_ "// 老师您好!这是一个C++语言的样例程序 // 程序功能:输入两个整数,输出两者之和 // 测试集合:老师可以给出多组测试集,例如: // 输入1和2,输出3 // 输入3和4,输出7 // ... ... // 系统将根据您给出的测试集对学生代码进行自动评分 // 特别提醒:程序采用命令行传参方式,输入通过argv传入 // 否则您的作业标准代码将不能通过测试 #include //引用必须头文件 #include using namespace std; int main(int argc, char** argv){ int a = atoi(argv[1]); //将第一个输入转成整型 int b = atoi(argv[2]); //将第二个输入转换为整型 cout< //引用必须头文件 int main(int argc, char** argv) { int a = atoi(argv[1]); //将第一个输入转成整型 int b = atoi(argv[2]); //将第二个输入转换为整型 printf(\"%d\",a+b); //输出a+b return 0; }".html_safe end #学生C++语言的标准代码 def c_stantard_code_student_ "// 同学好!这是一个C++语言的样例程序 // 程序功能:输入两个整数,输出两者之和 // 测试集合:老师可以给出多组测试集,例如: // 输入1和2,输出3 // 输入3和4,输出7 // ... ... // 系统将根据您给出的测试集对学生代码进行自动评分 // 特别提醒:程序采用命令行传参方式,输入通过argv传入 // 否则您的作业标准代码将不能通过测试 #include //引用必须头文件 #include using namespace std; int main(int argc, char** argv){ int a = atoi(argv[1]); //将第一个输入转成整型 int b = atoi(argv[2]); //将第二个输入转换为整型 cout< a.created_on } elsif jour.respond_to?(:created_at) result.sort! { |a,b| b.created_at <=> a.created_at } end result end #获取该节点所在的帖子 def get_root_parent comment while comment.parent comment = comment.parent end comment end #将有置顶属性的提到数组前面 def sort_by_sticky topics tmpTopics = [] tmpIndex = 0 topics.each do |topic| if topic.sticky == 1 tmpTopics[tmpIndex] = topic tmpIndex = tmpIndex + 1 end end topics.each do |topic| if topic.sticky == 0 tmpTopics[tmpIndex] = topic tmpIndex = tmpIndex + 1 end end return tmpTopics end #按人气排序的时候 相同的人气必须按某种时间顺序排序 有置顶属性 def sortby_time_countcommon_hassticky topics,sortstr tmpTopics = [] tmpTopics = topics tStart = -1 tEnd = -1 tmpTopics_1 = [] tmpIndex = 0 tmpTopics.each_with_index do |topic,index| if topic.sticky == 0 if tStart == -1 if (index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]) tStart = index end else if ((topic[:infocount] == tmpTopics[index-1][:infocount]) && ((index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]))) tEnd = index else if (topic[:infocount] == tmpTopics[index-1][:infocount]) tEnd = index end if tEnd > tStart for i in tStart..tEnd tmpTopics_1[tmpIndex] = tmpTopics[i] tmpIndex = tmpIndex + 1 end if sortstr == "created_at" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_at].to_i <=> x[:created_at].to_i } elsif sortstr == "created_on" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_on].to_i <=> x[:created_on].to_i } elsif sortstr == "updated_at" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_at].to_i <=> x[:updated_at].to_i } elsif sortstr == "updated_on" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_on].to_i <=> x[:updated_on].to_i } end tmpIndex = 0 for i in tStart..tEnd tmpTopics[i] = tmpTopics_1[tmpIndex] tmpIndex = tmpIndex + 1 end end tStart = -1 tEnd = -1 tmpTopics_1 = [] tmpIndex = 0 end end end end return tmpTopics end #按人气排序的时候 相同的人气必须按某种时间顺序排序 无置顶属性 def sortby_time_countcommon_nosticky topics,sortstr tmpTopics = [] tmpTopics = topics tStart = -1 tEnd = -1 tmpTopics_1 = [] tmpIndex = 0 tmpTopics.each_with_index do |topic,index| if tStart == -1 if (index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]) tStart = index end else if ((topic[:infocount] == tmpTopics[index-1][:infocount]) && ((index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]))) tEnd = index else if (topic[:infocount] == tmpTopics[index-1][:infocount]) tEnd = index end if tEnd > tStart for i in tStart..tEnd tmpTopics_1[tmpIndex] = tmpTopics[i] tmpIndex = tmpIndex + 1 end if sortstr == "created_at" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_at].to_i <=> x[:created_at].to_i } elsif sortstr == "created_on" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_on].to_i <=> x[:created_on].to_i } elsif sortstr == "updated_at" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_at].to_i <=> x[:updated_at].to_i } elsif sortstr == "updated_on" tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_on].to_i <=> x[:updated_on].to_i } end tmpIndex = 0 for i in tStart..tEnd tmpTopics[i] = tmpTopics_1[tmpIndex] tmpIndex = tmpIndex + 1 end end tStart = -1 tEnd = -1 tmpTopics_1 = [] tmpIndex = 0 end end end return tmpTopics end def strip_html(text,len=0,endss="...") ss = "" if !text.nil? && text.length>0 ss=text.gsub(/<\/?.*?>/, '').strip ss = ss.gsub(/ */, ' ') if len > 0 && ss.length > len ss = ss[0, len] + endss elsif len > 0 && ss.length <= len ss = ss #ss = truncate(ss, :length => len) end end return ss end def message_content content content = (strip_html content).strip content = content.gsub(/\s+/, " ") if content.gsub(" ", "") == "" content = "[非文本消息]" end content end def get_hw_index(hw,is_teacher) if is_teacher homeworks = hw.course.homework_commons.order("created_at asc") else homeworks = hw.course.homework_commons.where("publish_time <= '#{Date.today}'").order("created_at asc") end hw_ids = homeworks.map{|hw| hw.id} if !homeworks.empty? index = hw_ids.index(hw.id) return index end def get_hw_status homework_common str = "" if homework_common.homework_detail_manual if homework_common.homework_detail_manual.comment_status == 0 && homework_common.publish_time.nil? str += '挂起' elsif homework_common.homework_detail_manual.comment_status == 0 str += '未发布' elsif homework_common.homework_detail_manual.comment_status == 1 if homework_common.anonymous_comment == 0 str += '未开启匿评' else str += '匿评已禁用' end if Time.parse(homework_common.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") str += '作品提交中' elsif Time.parse(homework_common.end_time.to_s).strftime("%Y-%m-%d") < Time.now.strftime("%Y-%m-%d") str += '作品补交中' end elsif homework_common.homework_detail_manual.comment_status == 2 if homework_common.anonymous_comment == 0 str += '匿评中' else str += '匿评已禁用' end str += '教师评阅中' elsif homework_common.homework_detail_manual.comment_status == 3 if homework_common.anonymous_comment == 0 str += '匿评已结束' else str += '匿评已禁用' end str += '教师评阅中' end end str end def get_group_member_names work result = "" unless work.nil? work.student_work_projects.each do |member| user = User.where(:id => member.user_id).first unless user.nil? if result != "" result += "、#{user.show_name}" else result += user.show_name end end end end result end def course_syllabus_option user = User.current syllabus_members = SyllabusMember.where("user_id = #{user.id}") syllabus_ids = syllabus_members.empty? ? "(-1)" : "(" + syllabus_members.map{|mem| mem.syllabus_id}.join(',') + ")" syllabuses = Syllabus.where("id in #{syllabus_ids}") type = [] option1 = [] option1 << "请选择课程" option1 << 0 type << option1 unless syllabuses.empty? syllabuses.each do |syllabus| option = [] option << syllabus.title option << syllabus.id type << option end end type end def create_works_list homework unless homework.course.nil? students = homework.course.student if !students.empty? && homework.student_works.empty? name = homework.name name_str = name + "的作品提交" str = "" students.each do |student| if str != "" str += "," end str += "('#{name_str}',#{homework.id},#{student.student_id}, '#{format_time(Time.now)}', '#{format_time(Time.now)}')" end sql = "insert into student_works (name, homework_common_id,user_id, created_at, updated_at) values" + str ActiveRecord::Base.connection.execute sql end end end # 获取项目动态更新时间 def get_forge_act_message(act, type) forge_act = ForgeActivity.where(:forge_act_id => act.id, :forge_act_type => type).first format_time(forge_act.nil? ? act.created_on : forge_act.try(:updated_at)) end #作业类型 def homework_type_option type = [] option1 = [] option1 << "普通作业" option1 << 1 option2 = [] option2 << "编程作业" option2 << 2 option3 = [] option3 << "分组作业" option3 << 3 type << option1 type << option2 type << option3 type end