diff --git a/app/api/mobile/entities/course_dynamic.rb b/app/api/mobile/entities/course_dynamic.rb index fe31668ff..6077a8722 100644 --- a/app/api/mobile/entities/course_dynamic.rb +++ b/app/api/mobile/entities/course_dynamic.rb @@ -4,56 +4,50 @@ module Mobile include Redmine::I18n def self.course_dynamic_expose(field) expose field do |c,opt| - if field == :update_time - (format_time(c[field]) if (c.is_a?(Hash) && c.key?(field))) - elsif field == :news_count - obj = nil - c[:dynamics].each do |d| - if d[:type] == 1 - obj = d[:count] - end - end - obj - elsif field == :document_count - obj = nil - c[:dynamics].each do |d| - if d[:type] == 3 - obj = d[:count] - end - end - obj - elsif field == :topic_count - obj = nil - c[:dynamics].each do |d| - if d[:type] == 2 - obj = d[:count] - end - end - obj - elsif field == :homework_count - obj = nil - c[:dynamics].each do |d| - if d[:type] == 4 - obj = d[:count] - end - end - obj - else + # if field == :news_count + # obj = nil + # c[:dynamics].each do |d| + # if d[:type] == 1 + # obj = d[:count] + # end + # end + # obj + # elsif field == :document_count + # obj = nil + # c[:dynamics].each do |d| + # if d[:type] == 3 + # obj = d[:count] + # end + # end + # obj + # elsif field == :topic_count + # obj = nil + # c[:dynamics].each do |d| + # if d[:type] == 2 + # obj = d[:count] + # end + # end + # obj + # elsif field == :homework_count + # obj = nil + # c[:dynamics].each do |d| + # if d[:type] == 4 + # obj = d[:count] + # end + # end + # obj + # else c[field] if (c.is_a?(Hash) && c.key?(field)) - end + # end end end - course_dynamic_expose :type - course_dynamic_expose :count course_dynamic_expose :course_name course_dynamic_expose :course_term course_dynamic_expose :course_time course_dynamic_expose :course_id course_dynamic_expose :course_img_url course_dynamic_expose :message - course_dynamic_expose :update_time - course_dynamic_expose :count course_dynamic_expose :news_count course_dynamic_expose :document_count course_dynamic_expose :topic_count @@ -63,62 +57,32 @@ module Mobile course_dynamic_expose :current_user_is_member course_dynamic_expose :current_user_is_teacher - expose :documents,using:Mobile::Entities::Attachment do |f,opt| - obj = nil - f[:dynamics].each do |d| - if d[:type] == 3 - obj = d[:documents] - end - end - obj - end + # expose :documents,using:Mobile::Entities::Attachment do |f,opt| + # obj = nil + # f[:dynamics].each do |d| + # if d[:type] == 3 + # obj = d[:documents] + # end + # end + # obj + # end expose :topics,using:Mobile::Entities::Message do |f,opt| - obj = nil - f[:dynamics].each do |d| - if d[:type] == 2 - obj = d[:topics] - end - end - obj + f[:topics] end expose :homeworks,using:Mobile::Entities::Homework do |f,opt| - obj = nil - f[:dynamics].each do |d| - if d[:type] == 4 - obj = d[:homeworks] - end - end - obj + f[:homeworks] end expose :news,using:Mobile::Entities::News do |f,opt| - obj = nil - f[:dynamics].each do |d| - if d[:type] == 1 - obj = d[:news] - end - end - obj + f[:news] end expose :better_students,using:Mobile::Entities::User do |f,opt| - obj = nil - f[:dynamics].each do |d| - if d[:type] == 6 - obj = d[:better_students] - end - end - obj + f[:better_students] end expose :active_students,using:Mobile::Entities::User do |f,opt| - obj = nil - f[:dynamics].each do |d| - if d[:type] == 7 - obj = d[:active_students] - end - end - obj + f[:active_students] end end diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 086ecfb7f..1624008f2 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -337,6 +337,19 @@ class AdminController < ApplicationController format.html end end + + #学校列表 + def schools + @school_name = params[:school_name] + if @school_name + @schools = School.where("name like '%#{@school_name}%'") + else + @schools = School.all + end + respond_to do |format| + format.html + end + end #移动端版本管理 def mobile_version @versions = PhoneAppVersion.reorder('created_at desc') @@ -382,4 +395,78 @@ class AdminController < ApplicationController end + #留言列表 + def leave_messages + @jour = JournalsForMessage.find_by_sql("SELECT * FROM journals_for_messages AS j1 + WHERE j1.jour_type IN ('Course','Principal') AND (j1.m_parent_id IS NULL OR (j1.m_parent_id IN (SELECT id FROM journals_for_messages WHERE jour_type IN ('Course','Principal')))) order by created_on desc") + @jour = paginateHelper @jour,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end + + #帖子 + def messages_list + @memo = Memo.reorder("created_at desc") + @memo = paginateHelper @memo,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end + + #课程讨论区的帖子 + def course_messages + @course_ms=Message.joins("join boards on messages.board_id=boards.id where boards.course_id is not NULL").reorder('created_on desc') + @course_ms = paginateHelper @course_ms,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end + + #项目讨论区的帖子 + def project_messages + @project_ms=Message.joins("join boards on messages.board_id=boards.id where boards.project_id != -1").reorder('created_on desc') + @project_ms = paginateHelper @project_ms,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end + + #通知 + def notices + @news = News.where('course_id is not NULL').order('created_on desc') + @news = paginateHelper @news,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end + + #最近登录用户列表 + def latest_login_users + scope = User.order('last_login_on desc') + scope = scope.where("last_login_on>= '#{params[:startdate]} 00:00:00'") if params[:startdate].present? + scope =scope.where("last_login_on <= '#{params[:enddate]} 23:59:59'") if params[:enddate].present? + @user = scope + @user = paginateHelper @user,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end + + #作业 + def homework + @homework = HomeworkCommon.order('end_time desc') + @homework = paginateHelper @homework,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end + end diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index a301a1e6c..ee953e913 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -514,6 +514,8 @@ private end def has_login - render_403 unless User.current.logged? + unless @attachment && @attachment.container_type == "PhoneAppVersion" + render_403 unless User.current.logged? + end end end diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index a0a61786c..29f2e00f4 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -20,11 +20,10 @@ class CoursesController < ApplicationController menu_item l(:label_sort_by_influence), :only => :index before_filter :can_show_course, :except => [] - before_filter :logged_user_by_apptoken,:only => [:show,:new_homework,:feedback] - before_filter :find_course, :except => [ :index, :search,:list, :new,:join,:unjoin, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise,:view_homework_attaches,:join_private_courses] - before_filter :authorize_course, :only => [:show, :settings, :edit, :update, :modules, :close, :reopen, :view_homework_attaches, :course] - before_filter :authorize_course_global, :only => [:view_homework_attaches, :new,:create] - before_filter :require_admin, :only => [:copy, :archive, :unarchive, :destroy, :calendar] + before_filter :logged_user_by_apptoken,:only => [:show,:feedback] + before_filter :find_course, :except => [ :index, :search, :new,:join,:unjoin, :create, :new_join, :course,:join_private_courses] + before_filter :authorize_course, :only => [:show, :settings, :update, :course] + before_filter :authorize_course_global, :only => [:new,:create] before_filter :toggleCourse, :only => [:finishcourse, :restartcourse] before_filter :require_login, :only => [:join, :unjoin] @@ -40,9 +39,14 @@ class CoursesController < ApplicationController else @state = 5 #未登录 end - respond_to do |format| - format.js { render :partial => 'set_join', :locals => {:user => user, :course => course, :object_id => params[:object_id]} } - end + # if @state == 1 || @state == 3 + # respond_to course_path(course.id) + # else + respond_to do |format| + format.js { render :partial => 'set_join', :locals => {:user => user, :course => course, :object_id => params[:object_id]} } + end + #end + rescue Exception => e @state = 4 #已经加入了课程 respond_to do |format| @@ -102,74 +106,17 @@ class CoursesController < ApplicationController # 课程搜索 # add by nwb def search - courses_all = Course.all_course - name = params[:name] - if name.blank? - @courses = [] - @courses_all = [] - @course_count = 0 - @course_pages = Paginator.new @course_count, per_page_option, params['page'] + if params[:name].empty? + courses = Course.visible + @courses = paginateHelper courses,10 else - @courses = courses_all.visible - if params[:name].present? - @courses_all = @courses.like(params[:name]) - else - @courses_all = @courses; - end - @course_count = @courses_all.count - @course_pages = Paginator.new @course_count, per_page_option, params['page'] - - # 课程的动态数 - @course_activity_count=Hash.new - @courses_all.each do |course| - @course_activity_count[course.id]=0 - end - - case params[:course_sort_type] - when '0' - @courses = @courses_all.order("created_at desc") - @s_type = 0 - @courses = @courses.offset(@course_pages.offset).limit(@course_pages.per_page) - - @course_activity_count=get_course_activity @courses,@course_activity_count - - when '1' - @courses = @courses_all.order("course_ac_para desc") - @s_type = 1 - @courses = @courses.offset(@course_pages.offset).limit(@course_pages.per_page) - - @course_activity_count=get_course_activity @courses,@course_activity_count - - when '2' - @courses = @courses_all.order("watchers_count desc") - @s_type = 2 - @courses = @courses.offset(@course_pages.offset).limit(@course_pages.per_page) - - @course_activity_count=get_course_activity @courses,@course_activity_count - - when '3' - @course_activity_count=get_course_activity @courses_all,@course_activity_count_array - @courses=handle_course @courses_all,@course_activity_count - @s_type = 3 - @courses = @courses[@course_pages.offset, @course_pages.per_page] - - else - @s_type = 0 - @courses = @courses_all.order("created_at desc") - @courses = @courses.offset(@course_pages.offset).limit(@course_pages.per_page) - - @course_activity_count=get_course_activity @courses,@course_activity_count - - end + courses = Course.visible.where("LOWER(name) like '%#{params[:name].to_s.downcase}%'") + @courses = paginateHelper courses,10 end respond_to do |format| format.html { render :layout => 'course_base' - scope = Course - unless params[:closed] - scope = scope.active - end } format.atom { courses = Course.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all @@ -605,7 +552,7 @@ class CoursesController < ApplicationController def toggleCourse @course_prefs = Course.find_by_extra(@course.extra) - unless (@course_prefs.teacher == User.current || User.current.admin?) + unless (User.current.allowed_to?(:as_teacher,@course_prefs) || User.current.admin?) render_403 end end @@ -659,92 +606,9 @@ class CoursesController < ApplicationController end def show - if params[:jump] && redirect_to_course_menu_item(@course, params[:jump]) - return - end - @users_by_role = @course.users_by_role - if(User.find_by_id(CourseInfos.find_by_course_id(@course.id).try(:user_id))) - @user = User.find_by_id(CourseInfos.find_by_course_id(@course.id).user_id) - end - @key = User.current.rss_key - #新增内容 - @days = Setting.activity_days_default.to_i - if params[:from] - begin; @date_to = params[:from].to_date + 1; rescue; end - end - has = { - "show_course_files" => true, - "show_course_news" => true, - "show_course_messages" => true, - #"show_course_journals_for_messages" => true, - # "show_bids" => true, - # "show_homeworks" => true, - "show_polls" => true - } - @date_to ||= Date.today + 1 - @date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date - @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id])) - if @author.nil? - # 显示老师和助教的活动 - # @authors = searchTeacherAndAssistant(@course) - @authors = course_all_member(@course) - events = [] - key = "course_events_#{@course.id}".to_sym - if Rails.env.production? && Setting.course_cahce_enabled? - events = Rails.cache.read(key) || [] - end - if events.empty? - @authors.each do |author| - @activity = Redmine::Activity::Fetcher.new(User.current, :course => @course, - :with_subprojects => false, - :author => author.user) - - @activity.scope_select {|t| has["show_#{t}"]} - # modify by nwb - # 添加私密性判断 - if User.current.member_of_course?(@course)|| User.current.admin? - events += @activity.events(@days, @course.created_at) - else - events += @activity.events(@days, @course.created_at, :is_public => 1) - end - end - Rails.cache.write(key, events) if Rails.env.production? && Setting.course_cahce_enabled? - end - else - # @author = @course.teacher - @activity = Redmine::Activity::Fetcher.new(User.current, :course => @course, - :with_subprojects => false, - :author => @author) - - @activity.scope_select {|t| has["show_#{t}"]} - # modify by nwb - # 添加私密性判断 - if User.current.member_of_course?(@course)|| User.current.admin? - events = @activity.events(@days, @course.created_at) - else - events = @activity.events(@days, @course.created_at, :is_public => 1) - end - end - - # 无新动态时,显示老动态 - if events.count == 0 - if User.current.member_of_course?(@course)|| User.current.admin? - events = @activity.events - else - events = @activity.events(:is_public => 1) - end - end - @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category' - if(User.find_by_id(CourseInfos.find_by_course_id(@course.id).try(:user_id))) - @user = User.find_by_id(CourseInfos.find_by_course_id(@course.id).user_id) - end - - sorted_events = sort_activity_events_course(events) - events = paginateHelper sorted_events,10 - @events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)} - # documents - - + course_activities = @course.course_activities.order("created_at desc") + @canShowRealName = User.current.member_of_course? @course + @course_activities = paginateHelper course_activities,10 respond_to do |format| format.html{render :layout => 'base_courses'} format.api @@ -809,6 +673,12 @@ class CoursesController < ApplicationController end end + #删除课程 + #删除课程只是将课程的is_delete状态改为false,is_delete为false状态的课程只有管理员可以看到 + def destroy + + end + private def allow_join course if course_endTime_timeout? course diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index 19c1214e2..7b81d12db 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -177,11 +177,11 @@ class FilesController < ApplicationController def index @flag = params[:flag] || false #sort_init 'filename', 'asc' - sort_init 'created_on', 'desc' - sort_update 'created_on' => "#{Attachment.table_name}.created_on", - 'filename' => "#{Attachment.table_name}.filename", - 'size' => "#{Attachment.table_name}.filesize", - 'downloads' => "#{Attachment.table_name}.downloads" + # sort_init 'created_on', 'desc' + # sort_update 'created_on' => "#{Attachment.table_name}.created_on", + # 'filename' => "#{Attachment.table_name}.filename", + # 'size' => "#{Attachment.table_name}.filesize", + # 'downloads' => "#{Attachment.table_name}.downloads" sort = "" @sort = "" @order = "" diff --git a/app/controllers/homework_common_controller.rb b/app/controllers/homework_common_controller.rb index 6e6fa7d20..87c1e288b 100644 --- a/app/controllers/homework_common_controller.rb +++ b/app/controllers/homework_common_controller.rb @@ -1,6 +1,7 @@ class HomeworkCommonController < ApplicationController require 'net/http' require 'json' + require "base64" layout "base_courses" before_filter :find_course, :only => [:index,:new,:create,:next_step] before_filter :find_homework, :only => [:edit,:update,:alert_anonymous_comment,:start_anonymous_comment,:stop_anonymous_comment,:destroy] @@ -18,6 +19,28 @@ class HomeworkCommonController < ApplicationController end def new + @homework_type = "1" + + @homework = HomeworkCommon.new + @homework.safe_attributes = params[:homework_common] + @homework.late_penalty = 2 + @homework.end_time = (Time.now + 3600 * 24).strftime('%Y-%m-%d') + @homework.publish_time = Time.now.strftime('%Y-%m-%d') + + if @homework_type == "1" + #匿评作业相关属性 + @homework_detail_manual = HomeworkDetailManual.new + @homework_detail_manual.ta_proportion = 0.6 + @homework_detail_manual.absence_penalty = 2 + @homework_detail_manual.evaluation_num = 3 + @homework_detail_manual.evaluation_start = Time.now.strftime('%Y-%m-%d') + @homework_detail_manual.evaluation_end = (Time.now + 3600 * 24).strftime('%Y-%m-%d') + @homework.homework_detail_manual = @homework_detail_manual + elsif @homework_type == "2" + #编程作业相关属性 + @homework_detail_programing = HomeworkDetailPrograming.new + @homework.homework_detail_programing = @homework_detail_programing + end respond_to do |format| format.html end @@ -29,7 +52,7 @@ class HomeworkCommonController < ApplicationController @homework = HomeworkCommon.new @homework.safe_attributes = params[:homework_common] - @homework.late_penalty = 0 + @homework.late_penalty = 2 @homework.end_time = (Time.now + 3600 * 24).strftime('%Y-%m-%d') @homework.publish_time = Time.now.strftime('%Y-%m-%d') @@ -37,7 +60,7 @@ class HomeworkCommonController < ApplicationController #匿评作业相关属性 @homework_detail_manual = HomeworkDetailManual.new @homework_detail_manual.ta_proportion = 0.6 - @homework_detail_manual.absence_penalty = 0 + @homework_detail_manual.absence_penalty = 2 @homework_detail_manual.evaluation_num = 3 @homework_detail_manual.evaluation_start = Time.now.strftime('%Y-%m-%d') @homework_detail_manual.evaluation_end = (Time.now + 3600 * 24).strftime('%Y-%m-%d') @@ -71,18 +94,20 @@ class HomeworkCommonController < ApplicationController if homework.homework_type == 2 homework_detail_programing = HomeworkDetailPrograming.new - homework_detail_programing.language = "C++" + homework_detail_programing.language = params[:language] homework_detail_programing.standard_code = params[:standard_code] - + homework_detail_programing.ta_proportion = params[:ta_proportion] || 0.6 question = {title:homework.name,content:homework.description} question[:input] = [] question[:output] = [] - if params[:input] && params[:output] + if params[:input] && params[:output] && params[:result] params[:input].each do |k,v| if params[:output].include? k homework_test = HomeworkTest.new homework_test.input = v homework_test.output = params[:output][k] + homework_test.result = params[:result][k] + homework_test.error_msg = params[:error_msg] homework.homework_tests << homework_test question[:input] << homework_test.input question[:output] << homework_test.output @@ -122,6 +147,8 @@ class HomeworkCommonController < ApplicationController end if homework.save + homework_detail_programing.save if homework_detail_programing + homework_detail_manual.save if homework_detail_manual respond_to do |format| format.html { flash[:notice] = l(:notice_successful_create) @@ -187,8 +214,9 @@ class HomeworkCommonController < ApplicationController end if @homework.homework_type == 2 && @homework_detail_programing #编程作业 - @homework_detail_programing.language = "C++" + @homework_detail_programing.language = params[:language] @homework_detail_programing.standard_code = params[:standard_code] + @homework_detail_programing.ta_proportion = params[:ta_proportion] || 0.6 homework_tests = @homework.homework_tests #需要删除的测试 ids = homework_tests.map(&:id) - params[:input].keys.map(&:to_i) @@ -196,23 +224,45 @@ class HomeworkCommonController < ApplicationController homework_test = HomeworkTest.find id homework_test.destroy if homework_test end - if params[:input] && params[:output] + if params[:input] && params[:output] && params[:result] params[:input].each do |k,v| if params[:output].include? k homework_test = HomeworkTest.find_by_id k if homework_test #已存在的测试,修改 homework_test.input = v homework_test.output = params[:output][k] + homework_test.result = params[:result][k] + homework_test.error_msg = params[:error_msg] else #不存在的测试,增加 homework_test = HomeworkTest.new homework_test.input = v homework_test.output = params[:output][k] + homework_test.result = params[:result][k] + homework_test.error_msg = params[:error_msg] homework_test.homework_common = @homework end homework_test.save end end end + + #发送修改作业的请求 + question = {title:@homework.name,content:@homework.description} + question[:input] = [] + question[:output] = [] + @homework.homework_tests.each do |test| + question[:input] << test.input + question[:output] << test.output + end + uri = URI("http://192.168.80.21:8080/api/questions/#{@homework_detail_programing.question_id}.json") + body = question.to_json + res = Net::HTTP.new(uri.host, uri.port).start do |client| + request = Net::HTTP::Put.new(uri.path) + request.body = body + request["Content-Type"] = "application/json" + client.request(request) + end + result = JSON.parse(res.body) end @homework.save_attachments(params[:attachments]) @@ -308,6 +358,24 @@ class HomeworkCommonController < ApplicationController end end + def programing_test + test = {language:params[:language],src:Base64.encode64(params[:src]),input:[params[:input]],output:[params[:output]]} + @index = params[:index] + uri = URI('http://192.168.80.21:8080/api/realtime.json') + body = test.to_json + res = Net::HTTP.new(uri.host, uri.port).start do |client| + request = Net::HTTP::Post.new(uri.path) + request.body = body + request["Content-Type"] = "application/json" + client.request(request) + end + result = JSON.parse(res.body) + @err_msg = result["compile_error_msg"] + result["results"].each do |re| + @result = re["status"] + end + end + private #获取课程 def find_course diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 539d84e65..0995d1304 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -112,7 +112,19 @@ class IssuesController < ApplicationController end def show - + # 当前用户查看指派给他的缺陷消息,则设置消息为已读 + query = @issue.forge_messages + if User.current.id == @issue.assigned_to_id + query.update_all(:viewed => true) + end + # 缺陷状态更新 + query_journals = @issue.journals + if User.current.id == @issue.author_id + query_journals.each do |query_journal| + query_journal.forge_messages.update_all(:viewed => true) + end + end + # @journals = @issue.journals.includes(:user, :details).reorder("#{Journal.table_name}.id ASC").all @journals.each_with_index {|j,i| j.indice = i+1} @journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project) diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb index 56b4a30fc..1a8e75b54 100644 --- a/app/controllers/news_controller.rb +++ b/app/controllers/news_controller.rb @@ -71,10 +71,15 @@ class NewsController < ApplicationController scope = @course ? @course.news.course_visible : News.course_visible @news_count = scope.count - #@news_pages = Paginator.new @news_count, @limit, params['page'] - #@offset ||= scope_page.offset - scope_order = scope.all(:include => [:author, :course], - :order => "#{News.table_name}.created_on DESC") + @q = params[:subject] + if params[:subject].nil? || params[:subject].blank? + scope_order = scope.all(:include => [:author, :course], + :order => "#{News.table_name}.created_on DESC") + else + scope_order = scope.where("#{News.table_name}.title like '#{'%' << params[:subject].to_s << '%'}'").all(:include => [:author, :course], + :order => "#{News.table_name}.created_on DESC") + end + # :offset => @offset, # :limit => @limit) @newss = paginateHelper scope_order,10 @@ -83,6 +88,7 @@ class NewsController < ApplicationController @news = News.new render :layout => 'base_courses' } + format.js format.api format.atom { render_feed(@newss, :title => (@course ? @course.name : Setting.app_title) + ": #{l(:label_news_plural)}") } end @@ -141,7 +147,7 @@ class NewsController < ApplicationController ids = params[:asset_id].split(',') update_kindeditor_assets_owner ids,@news.id,OwnerTypeHelper::NEWS end - # ض̬ļ¼add start + # ������ض�̬�ļ�¼add start teachers = searchTeacherAndAssistant(@course) for teacher in teachers if(teacher.user_id != User.current.id) @@ -155,7 +161,7 @@ class NewsController < ApplicationController notify.save() end end - # ض̬ļ¼add end + # ������ض�̬�ļ�¼add end render_attachment_warning_if_needed(@news) flash[:notice] = l(:notice_successful_create) redirect_to course_news_index_url(@course) diff --git a/app/controllers/poll_controller.rb b/app/controllers/poll_controller.rb index 758747e02..edf8c2259 100644 --- a/app/controllers/poll_controller.rb +++ b/app/controllers/poll_controller.rb @@ -1,3 +1,4 @@ +#encoding utf-8 class PollController < ApplicationController before_filter :find_poll_and_course, :only => [:edit,:update,:destroy,:show,:statistics_result,:create_poll_question,:commit_poll,:commit_answer,:publish_poll,:republish_poll,:poll_result,:close_poll,:export_poll] before_filter :find_container, :only => [:new,:create, :index] @@ -137,11 +138,19 @@ class PollController < ApplicationController @poll_questions.poll_answers.new question_option end end - if @poll_questions.save - respond_to do |format| - format.js - end + # 如果是插入的话,那么从插入的这个id以后的question_num都将要+1 + if params[:quest_id] + @is_insert = true + @poll.poll_questions.where("question_number > #{params[:quest_num].to_i}").update_all(" question_number = question_number + 1") + @poll_question_num = params[:quest_num].to_i + @poll_questions.question_number = params[:quest_num].to_i + 1 end + if @poll_questions.save + respond_to do |format| + format.js + end + end + end #修改题目 @@ -328,6 +337,37 @@ class PollController < ApplicationController end end + + def import_poll + @poll = Poll.find(params[:to_id]) + question_num = @poll.poll_questions.select("max(question_number) question_number").first.question_number + import_poll = Poll.find(params[:import_id]) + import_poll.poll_questions.each_with_index do |question,index| + option = { + :is_necessary => question.is_necessary, + :question_title => question.question_title, + :question_type => question.question_type, + :question_number => question_num + index+1 + } + poll_questions = @poll.poll_questions.new option + for i in 1..question.poll_answers.count + answer = question.poll_answers[i-1][:answer_text] + question_option = { + :answer_position => i, + :answer_text => answer + } + poll_questions.poll_answers.new question_option + end + @poll.poll_questions << poll_questions + end + if @poll.save + @poll = Poll.find(params[:to_id]) + respond_to do |format| + format.js + end + end + end + #重新发布问卷 def republish_poll @poll.poll_questions.each do |poll_question| @@ -371,6 +411,70 @@ class PollController < ApplicationController end end + # 将其他地方的问卷导出来 + def other_poll + # 查作者是我,或者作者是当前课程的老师,且不在当前课程内的问卷 进行导入 + tea_ids = '(' + tea_ids << Course.find(params[:polls_group_id]).tea_id.to_s << ','<< User.current.id.to_s << ')' + @polls = Poll.where("user_id in #{tea_ids} and polls_type = 'course' and polls_group_id != #{params[:polls_group_id]}") + @polls_group_id = params[:polls_group_id] + respond_to do |format| + format.js + end + end + + # 将问卷导入本课程 + def import_other_poll + course_id = params[:course_id] + @course = Course.find(course_id) + params[:polls].each_with_index do |p,i| + poll = Poll.find(p) + option = { + :polls_name => poll.polls_name || l(:label_poll_new), + :polls_type => 'Course', + :polls_group_id => course_id, + :polls_status => 1, + :user_id => User.current.id, + :published_at => Time.now, + :closed_at => Time.now, + :show_result => 1, + :polls_description => poll.polls_description + } + @poll = Poll.create option + + poll.poll_questions.each do | q| + #question_title = params[:poll_questions_title].nil? || params[:poll_questions_title].empty? ? l(:label_enter_single_title) : params[:poll_questions_title] + option = { + :is_necessary => q[:is_necessary], + :question_title => q[:question_title], + :question_type => q[:question_type] || 1, + :question_number => q[:question_number] + } + @poll_questions = @poll.poll_questions.new option + + for i in 1..q.poll_answers.count + answer = q.poll_answers[i-1].nil? ? l(:label_new_answer) : q.poll_answers[i-1][:answer_text] + question_option = { + :answer_position => i, + :answer_text => answer + } + @poll_questions.poll_answers.new question_option + end + end + @poll.save + end + @is_teacher = User.current.allowed_to?(:as_teacher,@course) + if @is_teacher + polls = Poll.where("polls_type = 'Course' and polls_group_id = #{@course.id}") + else + polls = Poll.where("polls_type = 'Course' and polls_group_id = #{@course.id} and polls_status = 2") + end + @polls = paginateHelper polls,20 #分页 + respond_to do |format| + format.js + end + end + private def find_poll_and_course @poll = Poll.find params[:id] diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e194c32ab..f042bba50 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -86,8 +86,14 @@ class ProjectsController < ApplicationController @project_pages = Project.project_entities.visible.like(params[:name]).page(params[:page]).per(10) else @project_pages = Project.project_entities.visible.page(params[:page] ).per(10) + @project_pages = Project.project_entities.visible.page(params[:page] ).per(10) end @projects = @project_pages.order("created_on desc") + @limit = 10#per_page_option + + @project_count = Project.project_entities.visible.like(params[:name]).page(params[:page]).count + @project_pages = Paginator.new @project_count, @limit, params['page'] + respond_to do |format| format.html { render :layout => 'base' @@ -150,11 +156,15 @@ class ProjectsController < ApplicationController end def new - @issue_custom_fields = IssueCustomField.sorted.all - @trackers = Tracker.sorted.all - @project = Project.new - @project.safe_attributes = params[:project] - render :layout => 'base' + if User.current.login? + @issue_custom_fields = IssueCustomField.sorted.all + @trackers = Tracker.sorted.all + @project = Project.new + @project.safe_attributes = params[:project] + render :layout => 'base' + else + redirect_to signin_url + end end def share @@ -167,6 +177,10 @@ class ProjectsController < ApplicationController end def create + unless User.current.login? + redirect_to signin_url + return + end @issue_custom_fields = IssueCustomField.sorted.all @trackers = Tracker.sorted.all @project = Project.new @@ -280,11 +294,11 @@ class ProjectsController < ApplicationController # 根据私密性,取出符合条件的所有数据 if User.current.member_of?(@project) || User.current.admin? - @events_pages = ForgeActivity.where("project_id = ?",@project).order("created_at desc").page(params['page'|| 1]).per(20); + @events_pages = ForgeActivity.where("project_id = ? and forge_act_type != ?",@project, "Document" ).order("created_at desc").page(params['page'|| 1]).per(20); #events = @activity.events(@date_from, @date_to) else @events_pages = ForgeActivity.includes(:project).where("forge_activities.project_id = ? and projects.is_public - = ?",@project,1).order("created_at desc") + = ? and forge_act_type != ? ",@project,1, "Document").order("created_at desc") .page(params['page'|| 1]).per(10); # @events = @activity.events(@date_from, @date_to, :is_public => 1) end @@ -361,12 +375,6 @@ class ProjectsController < ApplicationController end end - # dts测试工具 - def dts_rep - render_403 unless User.current.admin? - @dts = Dts.all - end - #发送邮件邀请新用户 def invite_members_by_mail if User.current.member_of?(@project) || User.current.admin? diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index b335e1830..e0aea0c2e 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -449,6 +449,8 @@ update def stats @project_id = params[:id] @repository_id = @repository.identifier + # 提交次数统计 + @status_commit_count = Changeset.count(:conditions => ["#{Changeset.table_name}.repository_id = ?", @repository.id]) render :layout => 'base_projects' end @@ -459,6 +461,12 @@ update data = graph_commits_per_month(@repository) when "commits_per_author" data = graph_commits_per_author(@repository) + when "author_commits_per_month" + data = graph_author_commits_per_month(@repository) + when "author_commits_six_month" + data = author_commits_six_month(@repository) + when "author_code_six_months" + data = author_code_six_month(@repository) end if data headers["Content-Type"] = "image/svg+xml" @@ -484,7 +492,18 @@ update if params[:repository_id].present? @repository = @project.repositories.find_by_identifier_param(params[:repository_id]) else - @repository = @project.repository + # 多版本库,如果一个版本库为空则去下一个 + rep_count = @project.repositories.count + if @project.repository.nil? + for i in 0..rep_count + unless @project.repositories[i].nil? + @repository = @project.repositories[i] + break + end + end + else + @repository = @project.repository + end end (render_404; return false) unless @repository @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s @@ -606,6 +625,123 @@ update ) graph.burn end + + # 用户最近一年的提交次数 + def graph_author_commits_per_month(repository) + @date_to = Date.today + @date_from = @date_to << 12 + @date_from = Date.civil(@date_from.year, @date_from.month, @date_from.day) + commits_by_author = Changeset.count(:all, :group => :committer, + :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to]) + commits_by_author = commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}.last(25) + + fields = commits_by_author.collect {|r| r.first} + commits_data = commits_by_author.collect {|r| r.last} + + fields = fields + [""]*(10 - fields.length) if fields.length<10 + commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10 + + # Remove email adress in usernames + fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') } + + graph = SVG::Graph::BarHorizontal.new( + :height => 400, + :width => 600, + :fields => fields, + :stack => :side, + :scale_integers => true, + :show_data_values => true, + :rotate_y_labels => false, + :graph_title => l(:label_author_commits_year), + :show_graph_title => true, + :no_css => true + ) + graph.add_data( + :data => commits_data, + :title => l(:label_revision_commit_count) + ) + graph.burn + end + + # 用户最近六个月的提交次数 + def author_commits_six_month(repository) + @date_to = Date.today + @date_from = @date_to << 6 + @date_from = Date.civil(@date_from.year, @date_from.month, @date_from.day) + commits_by_author = Changeset.count(:all, :group => :committer, + :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to]) + commits_by_author = commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}.last(25) + + fields = commits_by_author.collect {|r| r.first} + commits_data = commits_by_author.collect {|r| r.last} + + fields = fields + [""]*(10 - fields.length) if fields.length<10 + commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10 + + # Remove email adress in usernames + fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') } + + graph = SVG::Graph::BarHorizontal.new( + :height => 400, + :width => 600, + :fields => fields, + :stack => :side, + :scale_integers => true, + :show_data_values => true, + :rotate_y_labels => false, + :graph_title => l(:label_author_commits_six_month), + :show_graph_title => true + ) + graph.add_data( + :data => commits_data, + :title => l(:label_revision_commit_count) + ) + graph.burn + end + + # 最近六个月代码量统计 + def author_code_six_month(repository) + @date_to = Date.today + @date_from = @date_to << 6 + @date_from = Date.civil(@date_from.year, @date_from.month, @date_from.day) + commits_by_author = Changeset.count(:group => :committer, :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to]) + commits_by_author = commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}.last(40) + all_author = [] + commits_by_author.each do |cba| + all_author << cba.first + end + # all_author = all_author.collect {|c| c.gsub(%r{/ /<.+@.+>}, '') } + all_author = all_author.collect {|c| c.split.first } + commits_by_author = repository.commits(all_author, "#{@date_from}", "#{@date_to}", repository.id == 150 ? "szzh" : 'master') + + fields = commits_by_author.collect {|r| r.first} + commits_data = commits_by_author.collect {|r| r.last} + + fields = fields + [""]*(10 - fields.length) if fields.length<10 + commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10 + + # Remove email adress in usernames + fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') } + + graph = SVG::Graph::BarHorizontal.new( + :height => 400, + :width => 600, + :fields => fields, + :stack => :side, + :scale_integers => true, + :show_data_values => true, + :rotate_y_labels => false, + :graph_title => l(:label_author_code_six_month), + :show_graph_title => true + ) + graph.add_data( + :data => commits_data, + :title => l(:lable_revision_code_count) + ) + graph.burn + end + + def check_hidden_repo project = Project.find(params[:id]) if !User.current.member_of?(project) diff --git a/app/controllers/school_controller.rb b/app/controllers/school_controller.rb index 008fe00fc..3e0c280ac 100644 --- a/app/controllers/school_controller.rb +++ b/app/controllers/school_controller.rb @@ -4,28 +4,21 @@ class SchoolController < ApplicationController def upload uploaded_io = params[:logo] - school_id = 0 - schools = School.where("name = ?", params[:school]) - - schools.each do |s| - school_id = s.id - end - + school_id ||= params[:id] unless uploaded_io.nil? File.open(Rails.root.join('public', 'images', 'school', school_id.to_s+'.png'), 'wb') do |file| file.write(uploaded_io.read) end - s1 = School.find(school_id) s1.logo_link = '/images/school/'+school_id.to_s+'.png' s1.save - - - end + end + redirect_to admin_schools_url(:school_name => params[:school_name]) end def upload_logo - + @school = School.find params[:id] + @school_name = params[:school_name] end #获取制定学校开设的课程数 diff --git a/app/controllers/student_work_controller.rb b/app/controllers/student_work_controller.rb index dae0bcab6..01f858442 100644 --- a/app/controllers/student_work_controller.rb +++ b/app/controllers/student_work_controller.rb @@ -128,7 +128,7 @@ class StudentWorkController < ApplicationController solutions = { student_work_id:stundet_work.id, src:Base64.encode64(stundet_work.description), - language:1 + language:@homework.homework_detail_programing.language } uri = URI(url) body = solutions.to_json @@ -157,7 +157,7 @@ class StudentWorkController < ApplicationController end def edit - if @homework.homework_type == 2 #编程作业不能修改作业 + if !User.current.admin? && @homework.homework_type == 2 #编程作业不能修改作业 render_403 else respond_to do |format| @@ -387,8 +387,8 @@ class StudentWorkController < ApplicationController if stundet_work && params[:results] && params[:results].class.to_s == "Array" homework_common = stundet_work.homework_common params[:results].each do |result| - homework_test = homework_common.homework_tests.where("input = '#{result[:input]}' AND output = '#{result[:output]}'").first - if homework_test + homework_tests = homework_common.homework_tests.where("input = '#{result[:input]}' AND output = '#{result[:output]}'") + homework_tests.each do |homework_test| student_work_test = StudentWorkTest.new student_work_test.student_work = stundet_work student_work_test.homework_test = homework_test @@ -396,6 +396,7 @@ class StudentWorkController < ApplicationController if student_work_test.result == 0 student_score_count += 1 end + student_work_test.error_msg = params[:compile_error_msg] student_work_test.save! end end @@ -444,7 +445,7 @@ class StudentWorkController < ApplicationController #判断是不是当前作品的提交者 #提交者 && (非匿评作业 || 未开启匿评) 可以编辑作品 def author_of_work - render_403 unless (User.current.id == @work.user_id || User.current.admin?) && (@homework.homework_type != 1 || @homework.homework_detail_manual.comment_status == 1 ) + render_403 unless User.current.admin? || (User.current.id == @work.user_id && @homework.homework_type != 1 || @homework.homework_detail_manual.comment_status == 1 ) end def teacher_of_course @@ -467,22 +468,60 @@ class StudentWorkController < ApplicationController sheet1 = book.create_worksheet :name => "homework" blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 sheet1.row(0).default_format = blue - sheet1.row(0).concat([l(:excel_user_id),l(:excel_user_name),l(:excel_nickname),l(:excel_student_id),l(:excel_mail),l(:excel_homework_name), - l(:excel_t_score),l(:excel_ta_score),l(:excel_n_score),l(:excel_f_score),l(:excel_commit_time)]) - count_row = 1 - items.each do |homework| - sheet1[count_row,0]=homework.user.id - sheet1[count_row,1] = homework.user.lastname.to_s + homework.user.firstname.to_s - sheet1[count_row,2] = homework.user.login - sheet1[count_row,3] = homework.user.user_extensions.student_id - sheet1[count_row,4] = homework.user.mail - sheet1[count_row,5] = homework.name - sheet1[count_row,6] = homework.teacher_score.nil? ? l(:label_without_score) : format("%.2f",homework.teacher_score) - sheet1[count_row,7] = homework.teaching_asistant_score.nil? ? l(:label_without_score) : format("%.2f",homework.teaching_asistant_score) - sheet1[count_row,8] = homework.student_score.nil? ? l(:label_without_score) : format("%.2f",homework.student_score) - sheet1[count_row,9] = homework.respond_to?("score") ? homework.score.nil? ? l(:label_without_score) : format("%.2f",homework.score) : l(:label_without_score) - sheet1[count_row,10] = format_time(homework.created_at) - count_row += 1 + if @homework.homework_type == 0 #普通作业 + sheet1.row(0).concat([l(:excel_user_id),l(:excel_user_name),l(:excel_nickname),l(:excel_student_id),l(:excel_mail),l(:excel_homework_name), + l(:excel_t_score),l(:excel_ta_score),l(:excel_f_score),l(:excel_commit_time)]) + count_row = 1 + items.each do |homework| + sheet1[count_row,0]=homework.user.id + sheet1[count_row,1] = homework.user.lastname.to_s + homework.user.firstname.to_s + sheet1[count_row,2] = homework.user.login + sheet1[count_row,3] = homework.user.user_extensions.student_id + sheet1[count_row,4] = homework.user.mail + sheet1[count_row,5] = homework.name + sheet1[count_row,6] = homework.teacher_score.nil? ? l(:label_without_score) : format("%.2f",homework.teacher_score) + sheet1[count_row,7] = homework.teaching_asistant_score.nil? ? l(:label_without_score) : format("%.2f",homework.teaching_asistant_score) + # sheet1[count_row,8] = homework.student_score.nil? ? l(:label_without_score) : format("%.2f",homework.student_score) + sheet1[count_row,8] = homework.respond_to?("score") ? homework.score.nil? ? l(:label_without_score) : format("%.2f",homework.score) : l(:label_without_score) + sheet1[count_row,9] = format_time(homework.created_at) + count_row += 1 + end + elsif @homework.homework_type == 1 #匿评作业 + sheet1.row(0).concat([l(:excel_user_id),l(:excel_user_name),l(:excel_nickname),l(:excel_student_id),l(:excel_mail),l(:excel_homework_name), + l(:excel_t_score),l(:excel_ta_score), l(:excel_n_score),l(:excel_f_score),l(:excel_commit_time)]) + count_row = 1 + items.each do |homework| + sheet1[count_row,0]=homework.user.id + sheet1[count_row,1] = homework.user.lastname.to_s + homework.user.firstname.to_s + sheet1[count_row,2] = homework.user.login + sheet1[count_row,3] = homework.user.user_extensions.student_id + sheet1[count_row,4] = homework.user.mail + sheet1[count_row,5] = homework.name + sheet1[count_row,6] = homework.teacher_score.nil? ? l(:label_without_score) : format("%.2f",homework.teacher_score) + sheet1[count_row,7] = homework.teaching_asistant_score.nil? ? l(:label_without_score) : format("%.2f",homework.teaching_asistant_score) + sheet1[count_row,8] = homework.student_score.nil? ? l(:label_without_score) : format("%.2f",homework.student_score) + sheet1[count_row,9] = homework.respond_to?("score") ? homework.score.nil? ? l(:label_without_score) : format("%.2f",homework.score) : l(:label_without_score) + sheet1[count_row,10] = format_time(homework.created_at) + count_row += 1 + end + elsif @homework.homework_type == 2 #编程作业 + sheet1.row(0).concat([l(:excel_user_id),l(:excel_user_name),l(:excel_nickname),l(:excel_student_id),l(:excel_mail),l(:excel_homework_name), + l(:excel_t_score),l(:excel_ta_score), l(:excel_s_score),l(:excel_f_score),l(:excel_commit_time)]) + count_row = 1 + items.each do |homework| + sheet1[count_row,0]=homework.user.id + sheet1[count_row,1] = homework.user.lastname.to_s + homework.user.firstname.to_s + sheet1[count_row,2] = homework.user.login + sheet1[count_row,3] = homework.user.user_extensions.student_id + sheet1[count_row,4] = homework.user.mail + sheet1[count_row,5] = homework.name + sheet1[count_row,6] = homework.teacher_score.nil? ? l(:label_without_score) : format("%.2f",homework.teacher_score) + sheet1[count_row,7] = homework.teaching_asistant_score.nil? ? l(:label_without_score) : format("%.2f",homework.teaching_asistant_score) + sheet1[count_row,8] = homework.student_score.nil? ? l(:label_without_score) : format("%.2f",homework.student_score) + sheet1[count_row,9] = homework.respond_to?("score") ? homework.score.nil? ? l(:label_without_score) : format("%.2f",homework.score) : l(:label_without_score) + sheet1[count_row,10] = format_time(homework.created_at) + count_row += 1 + end end book.write xls_report xls_report.string diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d6597f3da..1aa8de526 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,3 +1,4 @@ +#encoding: utf-8 # Redmine - project management software # Copyright (C) 2006-2013 Jean-Philippe Lang # @@ -14,6 +15,7 @@ # 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. + class UsersController < ApplicationController layout :setting_layout @@ -28,6 +30,7 @@ class UsersController < ApplicationController # menu_item :requirement_focus, :only => :watch_bids menu_item :requirement_focus, :only => :watch_contests menu_item :user_newfeedback, :only => :user_newfeedback + menu_item :user_messages, :only => :user_messages #Ended by young @@ -40,14 +43,16 @@ class UsersController < ApplicationController :user_watchlist, :user_fanslist,:update, :user_courses, :user_homeworks, :watch_projects, :show_score, :topic_score_index, :project_score_index, :activity_score_index, :influence_score_index, :score_index,:show_new_score, :topic_new_score_index, :project_new_score_index, :activity_new_score_index, :influence_new_score_index, :score_new_index,:update_score,:user_activities,:user_projects_index, - :user_courses4show,:user_projects4show,:user_course_activities,:user_project_activities,:user_feedback4show,:user_visitorlist] + :user_courses4show,:user_projects4show,:user_course_activities,:user_project_activities,:user_feedback4show,:user_visitorlist, + :user_resource,:user_resource_create,:user_resource_delete,:rename_resource,:search_user_course,:add_exist_file_to_course, + :search_user_project,:resource_preview,:resource_search,:add_exist_file_to_project] #edit has been deleted by huang, 2013-9-23 before_filter :find_user, :only => [:user_fanslist, :user_watchlist, :show, :edit, :update, :destroy, :edit_membership, :user_courses, :user_homeworks, :destroy_membership, :user_activities, :user_projects, :user_newfeedback, :user_comments, :watch_contests, :info, :watch_projects, :show_score, :topic_score_index, :project_score_index, :activity_score_index, :influence_score_index, :score_index,:show_new_score, :topic_new_score_index, :project_new_score_index, - :activity_new_score_index, :influence_new_score_index, :score_new_index,:user_projects_index, - :user_courses4show,:user_projects4show,:user_course_activities,:user_project_activities,:user_feedback4show,:user_visitorlist] + :activity_new_score_index, :influence_new_score_index, :score_new_index,:user_projects_index,:user_resource, + :user_courses4show,:user_projects4show,:user_course_activities,:user_project_activities,:user_feedback4show,:user_visitorlist,:user_messages] before_filter :auth_user_extension, only: :show #before_filter :rest_user_score, only: :show #before_filter :select_entry, only: :user_projects @@ -95,6 +100,87 @@ class UsersController < ApplicationController end end + # 用户消息 + # 说明: homework 发布作业;message:讨论区; news:新闻; poll:问卷;works_reviewers:作品评阅;works_reply:作品回复 + # issue:问题;journal:缺陷状态更新; forum:公共贴吧: user_feedback: 用户留言; new_reply:新闻回复(comment) + def user_messages + unless User.current.logged? + render_403 + return + end + # 当前用户查看消息,则设置消息为已读 + course_querys = @user.course_messages + forge_querys = @user.forge_messages + user_querys = @user.user_feedback_messages + forum_querys = @user.memo_messages + if User.current.id == @user.id + course_querys.update_all(:viewed => true) + forge_querys.update_all(:viewed => true) + user_querys.update_all(:viewed => true) + forum_querys.update_all(:viewed => true) + end + @new_message_count = @user.forge_messages.count + @user.memo_messages.count + @user.course_messages.count + @user.user_feedback_messages.count + case params[:type] + when nil + @user_course_messages = CourseMessage.where("user_id =?",@user).order("created_at desc") + @user_forge_messages = ForgeMessage.where("user_id =?",@user).order("created_at desc") + @user_memo_messages = MemoMessage.where("user_id =?",@user).order("created_at desc") + @user_feedback_messages = UserFeedbackMessage.where("user_id =?",@user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + @user_forge_messages_count = @user_forge_messages.count + @user_memo_messages_count = @user_memo_messages.count + @user_feedback_messages_count = @user_feedback_messages.count + when 'homework' + @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "HomeworkCommon", @user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + when 'course_message' + @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Message", @user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + when 'forge_message' + @user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Message", @user).order("created_at desc") + @user_forge_messages_count = @user_forge_messages.count + when 'course_news' + @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "News", @user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + when 'forge_news' + @user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "News", @user).order("created_at desc") + @user_forge_messages_count = @user_forge_messages.count + when 'course_news_reply' + @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Comment", @user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + when 'forge_news_reply' + @user_forge_messages = ForgeMessage.where("course_message_type =? and user_id =?", "Comment", @user).order("created_at desc") + @user_forge_messagess_count = @user_forge_messages.count + when 'poll' + @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Poll", @user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + when 'works_reviewers' + @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "StudentWorksScore", @user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + when 'works_reply' + @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "JournalsForMessage", @user).order("created_at desc") + @user_course_messages_count = @user_course_messages.count + when 'issue' + @user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Issue", @user).order("created_at desc") + @user_forge_messages_count = @user_forge_messages.count + when 'issue_update' # 缺陷状态更新、留言 + @user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Journal", @user).order("created_at desc") + @user_forge_messages_count = @user_forge_messages.count + when 'forum' + @user_memo_messages = MemoMessage.where("memo_type =? and user_id =?", "Memo", @user).order("created_at desc") + @user_memo_messages_count = @user_memo_messages.count + when 'user_feedback' + @user_feedback_messages = UserFeedbackMessage.where("journals_for_message_type =? and user_id =?", "Principal", @user).order("created_at desc") + @user_feedback_messages_count = @user_feedback_messages.count + else + render_404 + return + end + respond_to do |format| + format.html{render :layout=>'base_users_new'} + end + end + def user_projects_index if User.current.admin? memberships = @user.memberships.all(conditions: "projects.project_type = #{Project::ProjectType_project}").first @@ -112,39 +198,20 @@ class UsersController < ApplicationController #added by young def user_projects - - #add by huang unless User.current.admin? if !@user.active? #|| (@user != User.current && @memberships.empty? && events.empty?) render_404 return end end - #end - # if User.current.admin? - # @memberships = @user.memberships.all(conditions: "projects.project_type = #{Project::ProjectType_project}") - # else - # cond = Project.visible_condition(User.current) + " AND projects.project_type <> 1" - # @memberships = @user.memberships.all(:conditions => cond) - # end - #events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 20) - #@events_by_day = events.group_by(&:event_date) - # @state = 0 - - limit = 10; - query = Project.joins("join members m on #{Project.table_name}.id=m.project_id") - query = query.where("m.user_id = ? and #{Project.table_name}.project_type=?",@user.id,Project::ProjectType_project) + projects = @user.projects.visible.select("projects.*,(SELECT MAX(created_at) FROM `forge_activities` WHERE forge_activities.project_id = projects.id) AS a").order("a desc") if(params[:status] == '1') - query = query.where("#{Project.table_name}.user_id = ?",@user.id); + projects = projects.where("projects.user_id = ?",@user.id) elsif(params[:status] == '2') - query = query.where("#{Project.table_name}.user_id <> ?",@user.id); + projects = projects.where("projects.user_id <> ?",@user.id) end - @obj_count = query.count(); - - @obj_pages = Paginator.new @obj_count,limit,params['page'] - @list = query.order("#{Project.table_name}.updated_on desc,#{Project.table_name}.id desc").limit(limit).offset(@obj_pages.offset).all(); - @params = params - + @list = paginateHelper projects,10 + @params = params[:status] respond_to do |format| format.html{render :layout=>'base_users_new'} format.api @@ -262,75 +329,35 @@ class UsersController < ApplicationController def user_courses unless User.current.admin? - if !@user.active? #|| (@user != User.current && @memberships.empty? && events.empty?) + if !@user.active? render_404 return end end - - #@user.coursememberships.all(:conditions => Course.visible_condition(User.current)) - - limit = 10; - query = Course.joins("join members m on #{Course.table_name}.id=m.course_id") - query = query.where("m.user_id = ?",@user.id) + courses = @user.courses.visible.select("courses.*,(SELECT MAX(created_at) FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a").order("a desc") if(params[:status] == '1') - query = query.where("endup_time >= ? or endup_time is null or endup_time=''",Time.now); + courses = courses.where("endup_time >= ? or endup_time is null or endup_time=''",Time.now) elsif(params[:status] == '2') - query = query.where("endup_time < ?",Time.now); + courses = courses.where("endup_time < ?",Time.now) end - @obj_count = query.count(); - - @obj_pages = Paginator.new @obj_count,limit,params['page'] - @list = query.order("#{Course.table_name}.updated_at desc,#{Course.table_name}.id desc").limit(limit).offset(@obj_pages.offset).all(); - @params = params + @list = paginateHelper courses,10 + @params = params[:status] render :layout=>'base_users_new' - - # if User.current == @user || User.current.admin? - # membership = @user.coursememberships.all - # else - # membership = @user.coursememberships.all(:conditions => Course.visible_condition(User.current)) - # end - # - # membership.sort! {|older, newer| newer.created_on <=> older.created_on } - # @memberships = [] - # membership.collect { |e| - # @memberships.push(e) - # } - # ## 判断课程是否过期 [需封装] - # @memberships_doing = [] - # @memberships_done = [] - # #now_time = Time.now.year - # @memberships.map { |e| - # #end_time = e.course.get_time.year - # isDone = course_endTime_timeout?(e.course) - # if isDone - # @memberships_done.push e - # else - # @memberships_doing.push e - # end - # } - # respond_to do |format| - # format.html - # format.api - # end end # modified by fq def user_newfeedback - @jours = @user.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC') - @jours.update_all(:is_readed => true, :status => false) - @jours.each do |journal| - fetch_user_leaveWord_reply(journal).update_all(:is_readed => true, :status => false) + jours = @user.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC') + if User.current == @user + jours.update_all(:is_readed => true, :status => false) + jours.each do |journal| + fetch_user_leaveWord_reply(journal).update_all(:is_readed => true, :status => false) + end end - - #@limit = 10 - #@feedback_count = @jours.count - #@feedback_pages = Paginator.new @feedback_count, @limit, params['page'] - #@offset ||= @feedback_pages.offset - @jour = paginateHelper @jours,10 + @jour = paginateHelper jours,10 @state = false + render :layout=>'base_users_new' end - # end def user_comments @@ -448,7 +475,7 @@ class UsersController < ApplicationController def user_courses4show query = Course.joins("join members m on #{Course.table_name}.id=m.course_id") - query = query.where("m.user_id = ?",@user.id) + query = query.where("m.user_id = ?",@user.id).order("#{Course.table_name}.id desc") if User.current == @user #看自己 else if @user.user_extensions!=nil && @user.user_extensions.identity == 0 #看老师 @@ -456,13 +483,12 @@ class UsersController < ApplicationController query = query.where("r.role_id in(3,7,9)") end query = query.where(Course.table_name+".is_public = 1") - # or exists (select 1 from courses c2,members m2 where c2.id=m2.course_id and c2.id=#{Course.table_name}.id and m2.user_id= User.current.id) end if params[:lastid]!=nil && !params[:lastid].empty? - query = query.where("( (#{Course.table_name}.updated_at=? and #{Course.table_name}.id < ?) or #{Course.table_name}.updated_atnil end @@ -483,95 +509,6 @@ class UsersController < ApplicationController render :layout=>nil end - # def user_course_activities - # @list = [] - # lastid = nil - # if params[:lastid]!=nil && !params[:lastid].empty? - # lastid = params[:lastid]; - # end - # - # user_ids = [] - # if @user == User.current - # watcher = User.watched_by(@user) - # watcher.push(User.current) - # user_ids = watcher.map{|x| x.id} - # else - # user_ids << @user.id - # end - # - # query_rec_count = 8 - # query_times = 10 #query_times次没查到query_rec_count条记录就不查了 - # query_i = 0; - # while( true ) - # query_i = query_i+1 - # if(query_i>query_times) - # break - # end - # query = Activity.where(user_id: user_ids) - # if(lastid != nil) - # query = query.where("id < ?",lastid) - # end - # lastid,item_list = query_activities(query,'course'); - # for item in item_list - # @list << item - # if @list.count() >= query_rec_count - # break - # end - # end - # if @list.count() >= query_rec_count - # break - # end - # if lastid == nil - # break - # end - # end - # render :layout=>nil - # end - # - # def user_project_activities - # @list = [] - # lastid = nil - # if params[:lastid]!=nil && !params[:lastid].empty? - # lastid = params[:lastid]; - # end - # - # user_ids = [] - # if @user == User.current - # watcher = User.watched_by(@user) - # watcher.push(User.current) - # user_ids = watcher.map{|x| x.id} - # else - # user_ids << @user.id - # end - # - # query_rec_count = 8 - # query_times = 10 #query_times次没查到query_rec_count条记录就不查了 - # query_i = 0; - # while( true ) - # query_i = query_i+1 - # if(query_i>query_times) - # break - # end - # query = Activity.where(user_id: user_ids) - # if(lastid != nil) - # query = query.where("id < ?",lastid) - # end - # lastid,item_list = query_activities(query,'project'); - # for item in item_list - # @list << item - # if @list.count() >= query_rec_count - # break - # end - # end - # if @list.count() >= query_rec_count - # break - # end - # if lastid == nil - # break - # end - # end - # render :action=>'user_course_activities',:layout=>nil - # end def user_course_activities lastid = nil if params[:lastid]!=nil && !params[:lastid].empty? @@ -630,7 +567,7 @@ class UsersController < ApplicationController query = query.where("#{Activity.table_name}.id < ?",lastid) end query = query.order("#{Activity.table_name}.id desc") - @list = query_activities(query); + @list = query_activities(query) render :action=>'user_course_activities',:layout=>nil end @@ -956,6 +893,274 @@ class UsersController < ApplicationController end end + # 上传用户资源 + def user_resource_create + @user = User.find(params[:id]) + #@user.save_attachments(params[:attachments],User.current) + # Container_type为Principal + Attachment.attach_filesex(@user, params[:attachments], params[:attachment_type]) + if(params[:type].nil? || params[:type] == "1") #全部 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} #我的资源库的话,那么应该是我上传的所有资源 加上 我加入的课程的所有资源 + @attachments = Attachment.where("(author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) "+ + "or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #Ta的资源库的话,应该是他上传的公开资源 加上 他加入的所有我可见课程里的公开资源 + @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 " + + "and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) " + + "or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + end + elsif params[:type] == "2" #课程资源 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} + @attachments = Attachment.where("(author_id = #{params[:id]} and container_type = 'Course') or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')})) ").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中 + @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 and container_type = 'Course')"+ + "or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + end + elsif params[:type] == "3" #项目资源 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project'").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' ").order("created_on desc") + end + elsif params[:type] == "4" #附件 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc") + end + end + @type = params[:type] || 1 + @limit = 15 + @is_remote = true + @atta_count = @attachments.count + @atta_pages = Paginator.new @atta_count, @limit, params['page'] || 1 + @offset ||= @atta_pages.offset + #@curse_attachments_all = @all_attachments[@offset, @limit] + @attachments = paginateHelper @attachments,15 + respond_to do |format| + format.js + end + end + + # 删除用户资源,分为批量删除 和 单个删除,只能删除自己上传的资源 + def user_resource_delete + if params[:resource_id].present? + Attachment.where("author_id = #{User.current.id}").delete(params[:resource_id]) + elsif params[:checkbox1].present? + params[:checkbox1].each do |id| + Attachment.where("author_id = #{User.current.id}").delete(id) + end + end + + if(params[:type].nil? || params[:type] == "1") #全部 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} #我的资源库的话,那么应该是我上传的所有资源 加上 我加入的课程的所有资源 + @attachments = Attachment.where("(author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) "+ + "or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #Ta的资源库的话,应该是他上传的公开资源 加上 他加入的所有我可见课程里的公开资源 + @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 " + + "and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) " + + "or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + end + elsif params[:type] == "2" #课程资源 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} + @attachments = Attachment.where("(author_id = #{params[:id]} and container_type = 'Course') or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')})) ").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中 + @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 and container_type = 'Course')"+ + "or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + end + elsif params[:type] == "3" #项目资源 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project'").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' ").order("created_on desc") + end + elsif params[:type] == "4" #附件 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc") + end + end + @type = params[:type] + @limit = 15 + @is_remote = true + @atta_count = @attachments.count + @atta_pages = Paginator.new @atta_count, @limit, params['page'] || 1 + @offset ||= @atta_pages.offset + #@curse_attachments_all = @all_attachments[@offset, @limit] + @attachments = paginateHelper @attachments,15 + respond_to do |format| + format.js + end + end + + #根据id或者名称搜索教师或者助教为当前用户的课程 + def search_user_course + @user = User.current + if !params[:search].nil? + @course = @user.courses.where(" #{Course.table_name}.id = #{params[:search].to_i } or #{Course.table_name}.name like '%#{params[:search.to_s]}%'") + .select { |course| @user.allowed_to?(:as_teacher,course)} + else + @course = @user.courses + .select { |course| @user.allowed_to?(:as_teacher,course)} + end + #这里仅仅是传递需要发送的资源id + @send_id = params[:send_id] + @send_ids = params[:checkbox1] || params[:send_ids] + respond_to do |format| + format.js + end + end + + # 根据id或者名称搜索当前用户所在的项目 + def search_user_project + @user = User.current + if !params[:search].nil? + @projects = @user.projects.where(" #{Project.table_name}.id = #{params[:search].to_i } or #{Project.table_name}.name like '%#{params[:search.to_s]}%'") + else + @projects = @user.projects + end + #这里仅仅是传递需要发送的资源id + @send_id = params[:send_id] + @send_ids = params[:checkbox1] || params[:send_ids] #搜索的时候 和 直接 用表格提交的时候的send_ids + respond_to do |format| + format.js + end + end + + # 将资源发送到对应的课程,分为发送单个,或者批量发送 + def add_exist_file_to_course + if params[:send_id].present? + send_id = params[:send_id] + ori = Attachment.find_by_id(send_id) + course_ids = params[:course_ids] + unless course_ids.nil? + course_ids.each do |id| + next if ori.blank? + attach_copied_obj = ori.copy + attach_copied_obj.tag_list.add(ori.tag_list) # tag关联 + attach_copied_obj.container = Course.find(id) + attach_copied_obj.created_on = Time.now + attach_copied_obj.author_id = User.current.id + if attach_copied_obj.attachtype == nil + attach_copied_obj.attachtype = 4 + end + attach_copied_obj.save + @save_message = attach_copied_obj.errors.full_messages + end + end + elsif params[:send_ids].present? + send_ids = params[:send_ids].split(" ") + send_ids.each do |send_id| + ori = Attachment.find_by_id(send_id) + course_ids = params[:course_ids] + unless course_ids.nil? + course_ids.each do |id| + next if ori.blank? + attach_copied_obj = ori.copy + attach_copied_obj.tag_list.add(ori.tag_list) # tag关联 + attach_copied_obj.container = Course.find(id) + attach_copied_obj.created_on = Time.now + attach_copied_obj.author_id = User.current.id + if attach_copied_obj.attachtype == nil + attach_copied_obj.attachtype = 4 + end + attach_copied_obj.save + @save_message = attach_copied_obj.errors.full_messages + end + end + end + end + respond_to do |format| + format.js + end + end + + # 添加资源到对应的项目 + def add_exist_file_to_project + if params[:send_id].present? + send_id = params[:send_id] + project_ids = params[:projects_ids] + ori = Attachment.find_by_id(send_id) + unless project_ids.nil? + project_ids.each do |project_id| + next if ori.blank? + attach_copied_obj = ori.copy + attach_copied_obj.tag_list.add(ori.tag_list) # tag关联 + attach_copied_obj.container = Project.find(project_id) + attach_copied_obj.created_on = Time.now + attach_copied_obj.author_id = User.current.id + if attach_copied_obj.attachtype == nil + attach_copied_obj.attachtype = 1 + end + attach_copied_obj.save + end + end + elsif params[:send_ids].present? + send_ids = params[:send_ids].split(" ") + send_ids.each do |send_id| + project_ids = params[:projects_ids] + ori = Attachment.find_by_id(send_id) + unless project_ids.nil? + project_ids.each do |project_id| + next if ori.blank? + attach_copied_obj = ori.copy + attach_copied_obj.tag_list.add(ori.tag_list) # tag关联 + attach_copied_obj.container = Project.find(project_id) + attach_copied_obj.created_on = Time.now + attach_copied_obj.author_id = User.current.id + if attach_copied_obj.attachtype == nil + attach_copied_obj.attachtype = 1 + end + attach_copied_obj.save + end + end + end + else + end + + respond_to do |format| + format.js + end + end + + # 资源预览 + def resource_preview + preview_id = params[:resource_id] + @file = Attachment.find(preview_id) + @preview_able = false; + if %w(pdf pptx doc docx xls xlsx).any?{|x| @file.filename.downcase.end_with?(x)} + @preview_able = true; + end + respond_to do |format| + format.js + end + end + + # 重命名资源 + def rename_resource + @attachment = Attachment.find(params[:res_id]) if params[:res_id].present? + if @attachment != nil + @attachment.filename = params[:res_name] + @flag = @attachment.save + end + # respond_to do |format| + # format.js + # end + if @flag + render :text=> download_named_attachment_path(@attachment.id, @attachment.filename) + else + render :text=>'fail' + end + end + def destroy @user.destroy respond_to do |format| @@ -1157,6 +1362,113 @@ class UsersController < ApplicationController @user = User.find(params[:id]) end + # 资源库 分为全部 课程资源 项目资源 附件 + def user_resource + #确定container_type + # @user = User.find(params[:id]) + # 别人的资源库是没有权限去看的 + if User.current.id.to_i != params[:id].to_i + render_403 + return + end + if(params[:type].nil? || params[:type] == "1") #全部 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} #我的资源库的话,那么应该是我上传的所有资源 加上 我加入的课程的所有资源 + @attachments = Attachment.where("(author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) "+ + "or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #Ta的资源库的话,应该是他上传的公开资源 加上 他加入的所有我可见课程里的公开资源 + @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 " + + "and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) " + + "or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + end + elsif params[:type] == "2" #课程资源 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} + @attachments = Attachment.where("(author_id = #{params[:id]} and container_type = 'Course') or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')})) ").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中 + @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 and container_type = 'Course')"+ + "or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))").order("created_on desc") + end + elsif params[:type] == "3" #项目资源 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project'").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' ").order("created_on desc") + end + elsif params[:type] == "4" #附件 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc") + end + end + @type = params[:type] + @limit = 15 + @is_remote = true + @atta_count = @attachments.count + @atta_pages = Paginator.new @atta_count, @limit, params['page'] || 1 + @offset ||= @atta_pages.offset + #@curse_attachments_all = @all_attachments[@offset, @limit] + @attachments = paginateHelper @attachments,15 + respond_to do |format| + format.js + format.html {render :layout => 'base_users_new'} + end + end + + # 根据资源关键字进行搜索 + def resource_search + search = params[:search].to_s.strip.downcase + if(params[:type].nil? || params[:type] == "1") #全部 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} #我的资源库的话,那么应该是我上传的所有资源 加上 我加入的课程的所有资源 取交集并查询 + @attachments = Attachment.where("((author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) "+ + " or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')}))) and (filename like '%#{search}%') ").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中 + @attachments = Attachment.where("((author_id = #{params[:id]} and is_public = 1 and container_type in" + + " ('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon'))"+ + " or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')})) )" + + " and (filename like '%#{search}%') ").order("created_on desc") + end + elsif params[:type] == "2" #课程资源 + if User.current.id.to_i == params[:id].to_i + user_course_ids = User.current.courses.map { |c| c.id} + @attachments = Attachment.where("(author_id = #{params[:id]} and container_type = 'Course') or (container_type = 'Course' and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')})) and (filename like '%#{search}%') ").order("created_on desc") + else + user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中 + @attachments = Attachment.where("((author_id = #{params[:id]} and is_public = 1 and container_type = 'Course') "+ + "or (container_type = 'Course' and is_public = 1 and container_id in (#{user_course_ids.empty? ? '0': user_course_ids.join(',')})) )"+ + " and (filename like '%#{search}%') ").order("created_on desc") + end + elsif params[:type] == "3" #项目资源 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project' and (filename like '%#{search}%')").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' and (filename like '%#{search}%') ").order("created_on desc") + end + elsif params[:type] == "4" #附件 + if User.current.id.to_i == params[:id].to_i + @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%')").order("created_on desc") + else + @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%')").order("created_on desc") + end + end + @type = params[:type] + @limit = 15 + @is_remote = true + @atta_count = @attachments.count + @atta_pages = Paginator.new @atta_count, @limit, params['page'] || 1 + @offset ||= @atta_pages.offset + #@curse_attachments_all = @all_attachments[@offset, @limit] + @attachments = paginateHelper @attachments,15 + respond_to do |format| + format.js + end + end + private def find_user @@ -1170,7 +1482,7 @@ class UsersController < ApplicationController render_404 end - def setting_layout(default_base='base_users') + def setting_layout(default_base='base_users_new') User.current.admin? ? default_base : default_base end @@ -1220,4 +1532,7 @@ class UsersController < ApplicationController impl.save end end + + + end diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 9ce107f8b..6b14db9bb 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -100,44 +100,6 @@ class WelcomeController < ApplicationController @course_page = FirstPage.find_by_page_type('course') @school_id = params[:school_id] || User.current.user_extensions.school.try(:id) || 117 @logoLink ||= logolink() - - ##3-8月份为查找春季课程,9-2月份为查找秋季课程 - #month_now = Time.now.strftime("%m").to_i - #year_now = Time.new.strftime("%Y").to_i - #(month_now >= 3 && month_now < 9) ? course_term = l(:label_spring) : course_term = l(:label_autumn) - ##year_now -= 1 if year_now < 3 - #@school_id.nil? ? @cur_school_course = [] : @cur_school_course = find_miracle_course(10,7,@school_id, year_now, course_term) - ##未登录或者当前学校未开设课程 - #if @cur_school_course.empty? - # @has_course = false - # User.current.logged? ? course_count = 9 : course_count = 10 - # @cur_school_course += find_all_new_hot_course(course_count, @school_id, year_now, course_term) - # while @cur_school_course.count < 9 do - # if course_term == l(:label_spring) - # course_term = l(:label_autumn) - # year_now -= 1 - # else - # course_term = l(:label_spring) - # end - # @cur_school_course += find_all_new_hot_course((10-@cur_school_course.count), nil, year_now, course_term) - # end - #else - # if @cur_school_course.count < 9 - # @has_course = false - # @cur_school_course += find_all_new_hot_course(9-@cur_school_course.count, @school_id, year_now, course_term) - # if @cur_school_course.count < 9 - # if course_term == l(:label_spring) - # course_term = l(:label_autumn) - # year_now -= 1 - # else - # course_term = l(:label_spring) - # end - # @cur_school_course += find_all_new_hot_course(9-@cur_school_course.count, nil, year_now, course_term) - # end - # else - # @has_course = true - # end - #end end def logolink() diff --git a/app/controllers/words_controller.rb b/app/controllers/words_controller.rb index 161791954..5158a99c4 100644 --- a/app/controllers/words_controller.rb +++ b/app/controllers/words_controller.rb @@ -4,7 +4,7 @@ class WordsController < ApplicationController include ApplicationHelper before_filter :find_user, :only => [:new, :create, :destroy, :more, :back] def create - if params[:new_form][:user_message].size>0 + if params[:new_form][:user_message].size>0 && User.current.logged? unless params[:user_id].nil? if params[:reference_content] message = params[:new_form][:user_message] + "\n" + params[:reference_content] @@ -18,22 +18,13 @@ class WordsController < ApplicationController list = User.find(refer_user_id).add_jour(User.current, message, refer_user_id) end @jour = list.last - # @user.count_new_jour - # if a_message.size > 5 - # @message = a_message[-5, 5] - # else - # @message = a_message - # end - # @message_count = a_message.count end end - # @jours = @user.journals_for_messages.where('m_parent_id IS NULL').reverse - # @jour = paginateHelper @jours,10 + jours = @user.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC') + @jour = paginateHelper jours,10 respond_to do |format| - # format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}} format.js - #format.api { render_api_ok } end end @@ -79,21 +70,22 @@ class WordsController < ApplicationController end def destroy - @journal_destroyed = JournalsForMessage.delete_message(params[:object_id]) - if @journal_destroyed.jour_type == "Bid" - @bid = Bid.find(@journal_destroyed.jour_id) - @jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count - elsif @journal_destroyed.jour_type == "Course" - @course = Course.find @journal_destroyed.jour_id - @jours_count = @course.journals_for_messages.where('m_parent_id IS NULL').count - elsif @journal_destroyed.jour_type == "Principal" - @user = User.find(@journal_destroyed.jour_id) - @jours_count = @user.journals_for_messages.where('m_parent_id IS NULL').count - @is_user = true - end - respond_to do |format| - format.js - #format.api { render_api_ok } + @journal_destroyed = JournalsForMessage.find params[:object_id] + if @journal_destroyed.destroy + if @journal_destroyed.jour_type == "Bid" + @bid = Bid.find(@journal_destroyed.jour_id) + @jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count + elsif @journal_destroyed.jour_type == "Course" + @course = Course.find @journal_destroyed.jour_id + @jours_count = @course.journals_for_messages.where('m_parent_id IS NULL').count + elsif @journal_destroyed.jour_type == "Principal" + @user = User.find(@journal_destroyed.jour_id) + @jours_count = @user.journals_for_messages.where('m_parent_id IS NULL').count + @is_user = true + end + respond_to do |format| + format.js + end end end @@ -206,7 +198,15 @@ class WordsController < ApplicationController flash[:error] = feedback.errors.full_messages[0] redirect_to project_feedback_url(params[:id]) end + end + #给用户留言 + def leave_user_message + @user = User.find(params[:id]) + if params[:new_form][:user_message].size>0 && User.current.logged? && @user + @user.add_jour(User.current, params[:new_form][:user_message]) + end + redirect_to feedback_path(@user) end # add by nwb diff --git a/app/helpers/api_helper.rb b/app/helpers/api_helper.rb index 1f34112ad..f26f5c19b 100644 --- a/app/helpers/api_helper.rb +++ b/app/helpers/api_helper.rb @@ -1,5 +1,11 @@ # encoding: utf-8 module ApiHelper + ONE_MINUTE = 60 * 1000 + ONE_HOUR = 60 * ONE_MINUTE + ONE_DAY = 24 * ONE_HOUR + ONE_MONTH = 30 * ONE_DAY + + ONE_YEAR = 12 * ONE_MONTH #获取用户的工作单位 def get_user_work_unit user work_unit = "" @@ -163,5 +169,37 @@ module ApiHelper end + # 获取当前时间 + def time_from_now time + lastUpdateTime = time.to_i*1000 + + currentTime = Time.now.to_i*1000 + timePassed = currentTime - lastUpdateTime; + timeIntoFormat = 0 + updateAtValue = "" + if timePassed < 0 + updateAtValue = "时间有问题" + elsif timePassed < ONE_MINUTE + updateAtValue = "一分钟前" + elsif timePassed < ONE_HOUR + timeIntoFormat = timePassed / ONE_MINUTE + updateAtValue = timeIntoFormat.to_s + "分钟前" + elsif (timePassed < ONE_DAY) + timeIntoFormat = timePassed / ONE_HOUR + updateAtValue = timeIntoFormat.to_s + "小时前" + elsif (timePassed < ONE_MONTH) + timeIntoFormat = timePassed / ONE_DAY + updateAtValue = timeIntoFormat.to_s + "天前" + elsif (timePassed < ONE_YEAR) + timeIntoFormat = timePassed / ONE_MONTH + updateAtValue = timeIntoFormat.to_s + "个月前" + else + timeIntoFormat = timePassed / ONE_YEAR + updateAtValue = timeIntoFormat.to_s + "年前" + end + updateAtValue + + end + end \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 64a478187..7c7f0c63f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1812,7 +1812,7 @@ module ApplicationHelper #获取用户未过期的课程 def get_user_course user courses_doing = [] - user.courses.each do |course| + 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 @@ -1824,7 +1824,9 @@ module ApplicationHelper def attachment_candown attachment candown = false if attachment.container - if 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 + 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) @@ -1850,6 +1852,8 @@ module ApplicationHelper candown = true elsif attachment.container.class.to_s=="StudentWork" 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) @@ -2375,4 +2379,98 @@ module ApplicationHelper 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< activity.course_act.id) + when "News" + title = "通知公告 " + activity.course_act.title + url = course_news_index_path(activity.course) + when "Attachment" + title = "课件 " + activity.course_act.filename + url = course_files_path(activity.course) + when "Message" + title = "课程讨论区 " + activity.course_act.subject + url = course_boards_path(activity.course,:parent_id => activity.course_act.parent_id ? activity.course_act.parent_id : activity.course_act.id, :topic_id => activity.course_act.id) + when "JournalsForMessage" + title = "留言 " + activity.course_act.notes + url = course_feedback_path(activity.course) + when "Poll" + title = "问卷 " + activity.course_act.polls_name + url = poll_path(activity.course_act_id) + end + end + link_to title.gsub(/<(?!img)[^>]*>/,'').html_safe, url, :class => "problem_tit c_dblue fl fb" + end + + #课程动态的描述 + def course_activity_desc activity + desc = "" + if activity.course_act + case activity.course_act_type + when "Course" + desc = "" + when "HomeworkCommon" + desc = activity.course_act.description + when "News" + desc = activity.course_act.description + when "Attachment" + desc = "" + when "Message" + desc = activity.course_act.content + when "JournalsForMessage" + desc = "" + when "Poll" + desc = activity.course_act.polls_description + end + end + desc.html_safe + end end diff --git a/app/helpers/homework_common_helper.rb b/app/helpers/homework_common_helper.rb index 81f817ee9..43f815250 100644 --- a/app/helpers/homework_common_helper.rb +++ b/app/helpers/homework_common_helper.rb @@ -27,6 +27,19 @@ module HomeworkCommonHelper type end + def programing_languages_options + type = [] + option = [] + option << "C" + option << 1 + type << option + option_1 = [] + option_1 << "C++" + option_1 << 2 + type << option_1 + type + end + #缺评扣分 def absence_penalty_option type = [] @@ -53,4 +66,31 @@ module HomeworkCommonHelper link end + #将状态转换为错误信息 + def status_to_err_msg status + case status.to_i + when -1 + '编译出错' + when -2 + '输入和输出不匹配' + when -3 + '输入和输出不匹配' + when 1 + '运行出错' + when 2 + '超时' + when 3 + '内存超出' + when 4 + '输出超出' + when 5 + '禁用函数' + when 6 + '其他错误' + when 0 + '成功' + else + '未知错误' + end + end end \ No newline at end of file diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index 06b154d36..9dd0bed8c 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -38,7 +38,7 @@ module MembersHelper scope = [] end principals = paginateHelper scope,10 - s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5') + s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :id => 'principals') links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options| link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true } diff --git a/app/helpers/poll_helper.rb b/app/helpers/poll_helper.rb index 3156f1b3a..22ee21936 100644 --- a/app/helpers/poll_helper.rb +++ b/app/helpers/poll_helper.rb @@ -74,4 +74,13 @@ module PollHelper end end + #带勾选框的问卷列表 + def poll_check_box_tags(name,polls,current_poll) + s = '' + polls.each do |poll| + s << "
" + end + s.html_safe + end + end \ No newline at end of file diff --git a/app/helpers/praise_tread_helper.rb b/app/helpers/praise_tread_helper.rb index 90ce6d61d..c142f0973 100644 --- a/app/helpers/praise_tread_helper.rb +++ b/app/helpers/praise_tread_helper.rb @@ -20,9 +20,9 @@ module PraiseTreadHelper # when 0 # return @record.tread_num.nil? ? 0 : @record.tread_num # end - return (@record.praise_num.to_i-@record.tread_num.to_i) + return ((@record.praise_num.nil? ? 0 : @record.praise_num.to_i)-(@record.tread_num.nil? ? 0 : @record.tread_num.to_i)) else - return 0 + return 0 end end diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 5cbc3af5a..c77eba0c5 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -236,13 +236,14 @@ module RepositoriesHelper # 判断项目是否有主版本库 def judge_main_repository(pro) if pro.repositories.blank? - return false + status = false else - pro.repositories.sort.each do |rep| - rep.is_default? - return true + pro.repositories.each do |rep| + status = true and break if rep.is_default? + status = false end end + status end # def cvs_field_tags(form, repository) # content_tag('p', form.text_field( diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index d4f9e4eb8..342ee70be 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -29,6 +29,29 @@ module UsersHelper ["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", '3']], selected.to_s) end + def get_resource_type type + case type + when 'Course' + '课程资源' + when 'Project' + '项目资源' + when 'Issue' + '缺陷附件' + when 'Message' + '讨论区附件' + when 'Document' + '文档附件' + when 'News' + '通知附件' + when 'HomewCommon' + '作业附件' + when 'StudentWorkScore' + '批改附件' + when 'Principal' + '用户资源' + end + end + def user_mail_notification_options(user) user.valid_notification_options.collect {|o| [l(o.last), o.first]} end @@ -321,6 +344,7 @@ module UsersHelper list = obj.watcher_users.order("#{Watcher.table_name}.id desc").limit(10).all return [count,list]; end + def get_visitor_users(obj) query = Visitor.where("master_id=?",obj.id) count = query.count @@ -328,109 +352,67 @@ module UsersHelper return [0,[]] end list = query.order("updated_on desc").limit(10).all - return [count,list]; + return [count,list] end def get_create_course_count(user) - return Course.where("tea_id = ?",user.id).count() + user.courses.visible.where("tea_id = ?",user.id).count end + + #获取加入课程数 def get_join_course_count(user) - return user.coursememberships.count() - get_create_course_count(user) + user.courses.visible.count - get_create_course_count(user) end + + #发布作业数 def get_homework_commons_count(user) - return HomeworkCommon.where("user_id = ?",user.id).count() + HomeworkCommon.where("user_id = ?",user.id).count end + + #资源数 def get_projectandcourse_attachment_count(user) - return Attachment.where("author_id = ? and container_type in ('Project','Course')",user.id).count() + Attachment.where("author_id = ? and container_type in ('Project','Course')",user.id).count end + + #创建项目数 def get_create_project_count(user) - return Project.where("user_id = ? and project_type = ?",user.id,Project::ProjectType_project).count() + user.projects.visible.where("projects.user_id=#{user.id}").count end + + #加入项目数 def get_join_project_count(user) - return user.memberships.count(conditions: "projects.project_type = #{Project::ProjectType_project}") - get_create_project_count(user) + user.projects.visible.count - get_create_project_count(user) end + + #创建缺陷数 def get_create_issue_count(user) - return Issue.where("author_id = ?",user.id).count() + Issue.where("author_id = ?",user.id).count end + + #解决缺陷数 def get_resolve_issue_count(user) - return Issue.where("assigned_to_id = ? and status_id=3",user.id).count() + Issue.where("assigned_to_id = ? and status_id=3",user.id).count end + + #参与匿评数 def get_anonymous_evaluation_count(user) - return StudentWorksScore.where("user_id = ? and reviewer_role=3",user.id).count() - end - - - # def query_activities(query,type) - # query_rec_count = 8 - # # query = query.where("act_type='JournalsForMessage'") - # #query = query.where("act_type not in (?)", ['JournalsForMessage','Message','HomeworkCommon','News','Issue','Journal','Poll']) - # list = query.order("id desc").limit(query_rec_count).all - # - # result = []; - # for item in list - # container = get_activity_container(item,type) - # if( activity_is_show(item,container) ) - # result << { :item=>item,:e=>container } - # end - # end - # return [lastid,result] - # end - # def get_activity_container activity,type - # e = nil; - # if type == 'Project' - # if activity.act_type == 'Poll' - # # 项目没有问卷 - # # e = Project.find_by_id(activity.act.polls_group_id) - # else - # e = activity.act.project if activity.act.respond_to?('project') - # end - # end - # if type == 'Course' - # if activity.act_type == 'Poll' - # e = Course.find_by_id(activity.act.polls_group_id) - # else - # e = activity.act.course if activity.act.respond_to?('course') - # end - # end - # - # return e; - # end + StudentWorksScore.where("user_id = ? and reviewer_role=3",user.id).count + end + def query_activities(query) - list = query.limit(8).all - result = []; + list = query.limit(13).all + result = [] for item in list container = get_activity_container(item) result << { :item=>item,:e=>container } end - return result + result end + def get_activity_container activity return activity.activity_container - # if type == 'Project' - # return activity.act.project if activity.act.respond_to?('project') - # end - # if type == 'Course' - # if activity.act_type == 'Poll' - # return Course.find_by_id(activity.act.polls_group_id) - # end - # return activity.act.course if activity.act.respond_to?('course') - # end - # return nil; end - # def activity_is_show(activity,e) - # if(!e) - # return false - # end - # - # if activity.user_id == User.current.id - # return true - # end - # if( e.visible? ) - # return true - # end - # return false - # end def get_activity_act_showname_htmlclear(activity) str = get_activity_act_showname(activity) str = str.gsub(/<.*>/,'') @@ -442,6 +424,15 @@ module UsersHelper end return str.html_safe end + + def get_issue_des_update(journal) + arr = details_to_strings(journal.details,true) + arr << journal.notes + str = '' + arr.each { |item| str = str+item } + return str + end + def get_activity_act_showname(activity) case activity.act_type when "HomeworkCommon" @@ -472,6 +463,7 @@ module UsersHelper return activity.act_type end end + def get_activity_act_createtime(activity) case activity.act_type when "HomeworkCommon" @@ -482,6 +474,7 @@ module UsersHelper return activity.act.created_on end end + def get_activity_container_url e if !e.visible? return "javascript:;" @@ -492,6 +485,7 @@ module UsersHelper end return url_for(:controller => 'projects', :action=>"show", :id=>e.id, :host=>Setting.host_name) end + def get_activity_url(activity,e) if !e.visible? return "javascript:;" @@ -520,6 +514,7 @@ module UsersHelper return 'javascript:;' end end + def get_activity_opt(activity,e) case activity.act_type when "HomeworkCommon" @@ -529,14 +524,14 @@ module UsersHelper when "Issue" return '发表了问题' when "Journal" - return '回复了问题' + return '更新了问题' when "JournalsForMessage" return e.class.to_s == 'Course' ? '发表了留言' : '提交了反馈' #return ( activity.act.reply_id == nil || activity.act.reply_id == 0 ) ? '' : '' when "Message" return ( activity.act.parent_id == nil || activity.act.parent_id == '' ) ? '发布了帖子' : '回复了帖子' when "Poll" - return '发布了问卷' + return '创建了问卷' else return '有了新动态' end diff --git a/app/models/attachment.rb b/app/models/attachment.rb index f999e27d6..f7fb9b1aa 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -27,6 +27,8 @@ class Attachment < ActiveRecord::Base belongs_to :attachmentstype, :foreign_key => "attachtype",:primary_key => "id" # 被ForgeActivity虚拟关联 has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy + # 课程动态 + has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy # end include UserScoreHelper @@ -71,8 +73,8 @@ class Attachment < ActiveRecord::Base cattr_accessor :thumbnails_storage_path @@thumbnails_storage_path = File.join(Rails.root, "tmp", "thumbnails") - before_save :files_to_final_location - after_create :office_conver, :be_user_score,:act_as_forge_activity# user_score + before_save :files_to_final_location,:act_as_course_activity + after_create :office_conver, :be_user_score,:act_as_forge_activity after_update :office_conver, :be_user_score after_destroy :delete_from_disk,:down_user_score @@ -552,4 +554,10 @@ class Attachment < ActiveRecord::Base end end + #课程动态公共表记录 + def act_as_course_activity + if self.container_type == "Course" && self.course_acts.empty? + self.course_acts << CourseActivity.new(:user_id => self.author_id,:course_id => self.container_id) + end + end end diff --git a/app/models/comment.rb b/app/models/comment.rb index a4842a23f..bb31eb894 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -21,6 +21,10 @@ class Comment < ActiveRecord::Base has_many_kindeditor_assets :assets, :dependent => :destroy has_many :ActivityNotifies,:as => :activity, :dependent => :destroy + # 课程/项目 消息 + has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy + has_many :forge_messages, :class_name => 'ForgeMessage', :as => :forge_message, :dependent => :destroy + #end acts_as_event :datetime => :updated_on, :description => :comments, :type => 'news', @@ -31,7 +35,19 @@ class Comment < ActiveRecord::Base belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' validates_presence_of :commented, :author, :comments safe_attributes 'comments' - after_create :send_mail + after_create :send_mail, :act_as_system_message + + def act_as_system_message + if self.commented.course + if self.author_id != self.commented.author_id + self.course_messages << CourseMessage.new(:user_id => self.commented.author_id, :course_id => self.commented.course.id, :viewed => false) + end + else # 项目相关 + if self.author_id != self.commented.author_id + self.forge_messages << ForgeMessage.new(:user_id => self.commented.author_id, :project_id => self.commented.project.id, :viewed => false) + end + end + end def send_mail if self.commented.is_a?(News) && Setting.notified_events.include?('news_comment_added') diff --git a/app/models/course.rb b/app/models/course.rb index 6d71ad967..26220f245 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -33,6 +33,11 @@ class Course < ActiveRecord::Base has_many :student_works, :through => :homework_commons, :dependent => :destroy has_many :course_groups, :dependent => :destroy + # 课程动态 + has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy + + has_many :course_activities + has_many :course_messages acts_as_taggable acts_as_nested_set :order => 'name', :dependent => :destroy @@ -44,7 +49,7 @@ class Course < ActiveRecord::Base validates_format_of :name,:with =>/^[^ ]+[a-zA-Z0-9_\u4e00-\u9fa5\s\S]+$/ validates_length_of :description, :maximum => 10000 before_save :self_validate - after_create :create_board_sync + after_create :create_board_sync, :act_as_course_activity before_destroy :delete_all_members safe_attributes 'extra', @@ -310,6 +315,11 @@ class Course < ActiveRecord::Base end end + #课程动态公共表记录 + def act_as_course_activity + self.course_acts << CourseActivity.new(:user_id => self.tea_id,:course_id => self.id) + end + #项目与课程分离后,很多课程的名称等信息为空,这些数据信息存储在项目表中!!就是数据兼容的问题 #def name # read_attribute('name') || Project.find_by_identifier(self.extra).try(:name) diff --git a/app/models/course_activity.rb b/app/models/course_activity.rb new file mode 100644 index 000000000..02b6dacf1 --- /dev/null +++ b/app/models/course_activity.rb @@ -0,0 +1,7 @@ +class CourseActivity < ActiveRecord::Base + attr_accessible :user_id, :course_act_id,:course_act_type,:course_id + # 虚拟关联 + belongs_to :course_act ,:polymorphic => true + belongs_to :course + belongs_to :user +end diff --git a/app/models/course_message.rb b/app/models/course_message.rb new file mode 100644 index 000000000..59089829d --- /dev/null +++ b/app/models/course_message.rb @@ -0,0 +1,12 @@ +class CourseMessage < ActiveRecord::Base + attr_accessible :course_id, :course_message_id, :course_message_type, :user_id, :viewed + + # 多态 虚拟关联 + belongs_to :course_message ,:polymorphic => true + belongs_to :course + belongs_to :user + validates :user_id,presence: true + validates :course_id,presence: true + validates :course_message_id,presence: true + validates :course_message_type, presence: true +end diff --git a/app/models/forge_message.rb b/app/models/forge_message.rb new file mode 100644 index 000000000..1543fab58 --- /dev/null +++ b/app/models/forge_message.rb @@ -0,0 +1,20 @@ +class ForgeMessage < ActiveRecord::Base + # 公共表中活动类型,命名规则:TYPE_OF_{类名}_ACT + TYPE_OF_ISSUE_ACT = "Issue" + TYPE_OF_MESSAGE_ACT = "Message" + TYPE_OF_ATTACHMENT_ACT = "Attachment" + TYPE_OF_DOCUMENT_ACT = "Document" + TYPE_OF_JOURNAL_ACT = "Journal" + TYPE_OF_WIKI_ACT = "Wiki" + TYPE_OF_NEWS_ACT = "News" + + attr_accessible :forge_message_id, :forge_message_type, :project_id, :user_id, :viewed + + belongs_to :forge_message ,:polymorphic => true + belongs_to :project + belongs_to :user + validates :user_id,presence: true + validates :project_id,presence: true + validates :forge_message_id,presence: true + validates :forge_message_type, presence: true +end diff --git a/app/models/forum.rb b/app/models/forum.rb index 2af1abf9e..530639f81 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -39,6 +39,7 @@ class Forum < ActiveRecord::Base logger.debug "send mail for forum add." Mailer.run.forum_add(self) if Setting.notified_events.include?('forum_add') end + # Updates topic_count, memo_count and last_memo_id attributes for +board_id+ def self.reset_counters!(forum_id) forum_id = forum_id.to_i diff --git a/app/models/homework_common.rb b/app/models/homework_common.rb index 291c14563..217c7d770 100644 --- a/app/models/homework_common.rb +++ b/app/models/homework_common.rb @@ -13,17 +13,40 @@ class HomeworkCommon < ActiveRecord::Base has_many :student_works, :dependent => :destroy has_many :student_works_evaluation_distributions, :through => :student_works #一个作业的分配的匿评列表 has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy #用户活动 + # 课程动态 + has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy + # 课程消息 + has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy acts_as_attachable acts_as_event :title => Proc.new {|o| "#{l(:label_course_homework)} ##{o.id}: #{o.name}" }, :description => :description, :author => :author, :url => Proc.new {|o| {:controller => 'student_work', :action => 'index', :homework => o.id}} - after_create :act_as_activity, :send_mail + after_create :act_as_activity, :send_mail, :act_as_course_activity, :act_as_course_message after_destroy :delete_kindeditor_assets def act_as_activity self.acts << Activity.new(:user_id => self.user_id) end + + #课程动态公共表记录 + def act_as_course_activity + if self.course + self.course_acts << CourseActivity.new(:user_id => self.user_id,:course_id => self.course_id) + end + end + + #课程作业消息记录 + def act_as_course_message + if self.course + self.course.members.each do |m| + if m.user_id != self.user_id + self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.course_id, :viewed => false) + end + end + end + end + #删除对应的图片 def delete_kindeditor_assets delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::HOMEWORKCOMMON diff --git a/app/models/homework_test.rb b/app/models/homework_test.rb index 7c477bfaf..df2848194 100644 --- a/app/models/homework_test.rb +++ b/app/models/homework_test.rb @@ -1,6 +1,6 @@ class HomeworkTest < ActiveRecord::Base - attr_accessible :input, :output, :homework_common_id + attr_accessible :input, :output, :homework_common_id,:result,:error_msg belongs_to :homework_common - has_one :student_work_test + has_many :student_work_test end diff --git a/app/models/issue.rb b/app/models/issue.rb index c2670a0cc..1724e3484 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -49,6 +49,8 @@ class Issue < ActiveRecord::Base has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy # end has_many :praise_tread, as: :praise_tread_object, dependent: :destroy + # ForgeMessage虚拟关联(多态) + has_many :forge_messages, :class_name => 'ForgeMessage',:as =>:forge_message ,:dependent => :destroy acts_as_nested_set :scope => 'root_id', :dependent => :destroy @@ -80,8 +82,8 @@ class Issue < ActiveRecord::Base attr_reader :current_journal # fq - after_create :act_as_activity,:be_user_score_new_issue,:act_as_forge_activity - after_update :be_user_score + after_create :act_as_activity,:be_user_score_new_issue,:act_as_forge_activity, :act_as_forge_message + after_update :be_user_score, :act_as_forge_message_update after_destroy :down_user_score # after_create :be_user_score # end @@ -138,6 +140,25 @@ class Issue < ActiveRecord::Base :project_id => self.project_id) end # end + + # 发布缺陷forge_messages中添加记录 + def act_as_forge_message + # 指派给自己的缺陷不提示消息 + unless self.author_id == self.assigned_to_id + self.forge_messages << ForgeMessage.new(:user_id => self.assigned_to_id, + :project_id => self.project_id, + :viewed => false) + end + end + + # 更新缺陷 + def act_as_forge_message_update + unless self.author_id == self.assigned_to_id + self.forge_messages << ForgeMessage.new(:user_id => self.assigned_to_id, + :project_id => self.project_id, + :viewed => false) + end + end # Returns a SQL conditions string used to find all issues visible by the specified user @@ -235,9 +256,10 @@ class Issue < ActiveRecord::Base base_reload(*args) end - def to_param - @to_param ||= "#{id}_#{self.project.name}(#{self.project.issues.index(self).to_i+1}-#{self.project.issues.count})"#.parameterize - end + # 之所以注释是以为最终以id形式显示,另外如果项目名称带点号或者纯数字会出现问题 + # def to_param + # @to_param ||= "#{id}_#{self.project.name}(#{self.project.issues.index(self).to_i+1}-#{self.project.issues.count})"#.parameterize + # end # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields def available_custom_fields diff --git a/app/models/journal.rb b/app/models/journal.rb index 3b660132e..a5bea92af 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -29,6 +29,8 @@ class Journal < ActiveRecord::Base has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy # 被ForgeActivity虚拟关联 has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy + # 被ForgeMessage虚拟关联 + has_many :forge_messages, :class_name => 'ForgeMessage',:as =>:forge_message ,:dependent => :destroy # end attr_accessor :indice @@ -48,7 +50,7 @@ class Journal < ActiveRecord::Base before_create :split_private_notes # fq - after_save :act_as_activity,:be_user_score,:act_as_forge_activity + after_save :act_as_activity,:be_user_score,:act_as_forge_activity, :act_as_forge_message # end #after_destroy :down_user_score #before_save :be_user_score @@ -163,10 +165,19 @@ class Journal < ActiveRecord::Base # Description 公共表中需要保存一份该记录 def act_as_forge_activity self.forge_acts << ForgeActivity.new(:user_id => self.user_id, - :project_id => self.issue.project.id) + :project_id => self.issue.project.id) end + # 缺陷状态更改,消息提醒 + def act_as_forge_message + if self.user_id != self.issue.author_id + self.forge_messages << ForgeMessage.new(:user_id => self.issue.author_id, + :project_id => self.issue.project_id, + :viewed => false) + end + end + # 更新用户分数 -by zjc def be_user_score #新建了缺陷留言且留言不为空,不为空白 diff --git a/app/models/journals_for_message.rb b/app/models/journals_for_message.rb index b15c9b2d1..2c56dc035 100644 --- a/app/models/journals_for_message.rb +++ b/app/models/journals_for_message.rb @@ -56,9 +56,14 @@ class JournalsForMessage < ActiveRecord::Base acts_as_attachable has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy + # 课程动态 + has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy + # 消息关联 + has_many :course_messages, :class_name => 'CourseMessage',:as =>:course_message ,:dependent => :destroy + has_many :user_feedback_messages, :class_name => 'UserFeedbackMessage', :as =>:journals_for_message, :dependent => :destroy validates :notes, presence: true, if: :is_homework_jour? - after_create :act_as_activity #huang + after_create :act_as_activity, :act_as_course_activity, :act_as_course_message, :act_as_user_feedback_message after_create :reset_counters! after_destroy :reset_counters! after_save :be_user_score @@ -177,4 +182,61 @@ class JournalsForMessage < ActiveRecord::Base def delete_kindeditor_assets delete_kindeditor_assets_from_disk self.id,7 end + + #课程动态公共表记录 + def act_as_course_activity + if self.jour_type == 'Course' + self.course_acts << CourseActivity.new(:user_id => self.user_id,:course_id => self.jour_id) + end + end + + # 课程作品留言消息通知 + def act_as_course_message + if self.jour_type == 'StudentWorksScore' + if self.user_id != self.jour.user_id + self.course_messages << CourseMessage.new(:user_id => self.jour.user_id,:course_id => self.jour.student_work.homework_common.course.id, :viewed => false) + end + end + end + + # 用户留言消息通知 + def act_as_user_feedback_message + # 主留言 + receivers = [] + if self.reply_id == 0 + if self.user_id != self.jour_id # 过滤自己给自己的留言消息 + receivers << self.jour + end + else # 留言回复 + reply_to = User.find(self.reply_id) + if self.user_id != self.parent.user_id + receivers << reply_to + if self.reply_id != self.parent.user_id + receivers << self.parent.user + end + else + receivers << reply_to + end + + # 添加留言回复人 + #reply_to = User.find(self.reply_id) + #if self.user_id != self.parent.user_id && self.user_id != self.parent.jour_id # 如果回帖人不是用户自己 + # receivers << self.parent.user + # if self.reply_id != self.parent.user_id + # receivers << reply_to + # end + #else # 用户自己回复别人的,别人收到消息通知 + # if self.user_id != self.reply_id # 过滤掉自己回复自己的 + # receivers << reply_to + # end + #end + end + if self.jour_type == 'Principal' + + receivers.each do |r| + self.user_feedback_messages << UserFeedbackMessage.new(:user_id => r.id, :journals_for_message_id => self.id, :journals_for_message_type => "Principal", :viewed => false) + end + + end + end end diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 5ae9df001..a25aff6bb 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -388,7 +388,8 @@ class Mailer < ActionMailer::Base @user = applied.user recipients = @project.manager_recipients s = l(:text_applied_project, :id => "##{@user.show_name}", :project => @project.name) - @applied_url = url_for(:controller => 'projects', :action => 'settings', :id => @project.id,:tab=>'members') + @token = Token.get_token_from_user(@user, 'autologin') + @applied_url = url_for(:controller => 'projects', :action => 'settings', :id => @project.id,:tab=>'members', :token => @token.value) mail :to => recipients, :subject => s end diff --git a/app/models/memo.rb b/app/models/memo.rb index e0abaa19f..f1f9029c1 100644 --- a/app/models/memo.rb +++ b/app/models/memo.rb @@ -16,6 +16,9 @@ class Memo < ActiveRecord::Base acts_as_attachable has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj has_many :praise_tread, as: :praise_tread_object, dependent: :destroy + # 消息 + has_many :memo_messages, :class_name =>'MemoMessage', :dependent => :destroy + # end belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id' # acts_as_searchable :column => ['subject', 'content'], # #:include => { :forum => :p} @@ -44,7 +47,7 @@ class Memo < ActiveRecord::Base "parent_id", "replies_count" - after_create :add_author_as_watcher, :reset_counters!, :send_mail + after_create :add_author_as_watcher, :reset_counters!, :send_mail, :send_message # after_update :update_memos_forum after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分 # after_create :send_notification @@ -59,6 +62,32 @@ class Memo < ActiveRecord::Base Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added') end + # 公共贴吧消息记录 + # 原则:贴吧创始人;发帖人,wanglingchun(特殊用户) + def send_message + receivers = [] + u = User.find(6) + receivers << u + # 主贴 + if self.parent_id.nil? + if self.author_id != self.forum.creator_id # 发帖人不是吧主 + receivers << self.forum.creator + end + else # 回帖 + # 添加吧主 + if self.author_id != self.forum.creator_id + receivers << self.forum.creator + end + # 添加发帖人 + if self.forum.creator_id != self.parent.author_id + receivers << self.parent.author + end + end + receivers.each do |r| + self.memo_messages << MemoMessage.new(:user_id => r.id, :forum_id => self.forum_id, :memo_id => self.id, :memo_type => "Memo", :viewed => false) + end + end + def cannot_reply_to_locked_topic errors.add :base, l(:label_memo_locked) if root.locked? && self != root end diff --git a/app/models/memo_message.rb b/app/models/memo_message.rb new file mode 100644 index 000000000..051fac317 --- /dev/null +++ b/app/models/memo_message.rb @@ -0,0 +1,11 @@ +class MemoMessage < ActiveRecord::Base + attr_accessible :forum_id, :memo_id, :memo_type, :user_id, :viewed + + belongs_to :memo + belongs_to :user + + validates :user_id,presence: true + validates :forum_id,presence: true + validates :memo_id,presence: true + validates :memo_type, presence: true +end diff --git a/app/models/message.rb b/app/models/message.rb index 15d358789..37129885f 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -32,7 +32,13 @@ class Message < ActiveRecord::Base has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy # 被ForgeActivity虚拟关联 has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy + # 课程动态 + has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy # end + # 课程/项目 消息 + has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy + has_many :forge_messages, :class_name => 'ForgeMessage', :as => :forge_message, :dependent => :destroy + #end has_many :ActivityNotifies,:as => :activity, :dependent => :destroy @@ -68,7 +74,7 @@ class Message < ActiveRecord::Base after_update :update_messages_board after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets - after_create :act_as_activity,:be_user_score,:act_as_forge_activity, :send_mail + after_create :act_as_activity,:act_as_course_activity,:be_user_score,:act_as_forge_activity, :act_as_system_message, :send_mail #before_save :be_user_score scope :visible, lambda {|*args| @@ -185,11 +191,56 @@ class Message < ActiveRecord::Base :project_id => self.board.project.id) end end + + #课程动态公共表记录 + def act_as_course_activity + if self.course + self.course_acts << CourseActivity.new(:user_id => self.author_id,:course_id => self.board.course_id) + end + end + + # 课程讨论区添加消息: + # 老师发帖所有人都能收到消息 + # 学生发帖,有人回复则给该学生消息,没回复则不给其它人发送消息 + # 帖子被回复的可以收到消息通知 + # 项目讨论区添加消息: + # 主贴项目成员都能收到 + # 回帖:帖子的发布人收到 + def act_as_system_message + if self.course + if self.parent_id.nil? # 主贴 + self.course.members.each do |m| + if self.author.allowed_to?(:as_teacher, self.course) && m.user_id != self.author_id # 老师 自己的帖子不给自己发送消息 + self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.board.course_id, :viewed => false) + end + end + else # 回帖 + self.course.members.each do |m| + if m.user_id == Message.find(self.parent_id).author_id && m.user_id != self.author_id # 只针对主贴回复,回复自己的帖子不发消息 + self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.board.course_id, :viewed => false) + end + end + end + else # 项目相关 + if self.parent_id.nil? # 主贴 + self.project.members.each do |m| + if m.user_id != self.author_id + self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.board.project_id, :viewed => false) + end + end + else # 回帖 + self.project.members.each do |m| + if m.user_id == Message.find(self.parent_id).author_id && m.user_id != self.author_id # 只针对主贴回复,回复自己的帖子不发消息 + self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.board.project_id, :viewed => false) + end + end + end + end + end #更新用户分数 -by zjc def be_user_score #新建message且无parent的为发帖 - if self.parent_id.nil? && !self.board.project.nil? UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id }) update_memo_number(self.author,1) diff --git a/app/models/news.rb b/app/models/news.rb index 7d33d760e..6e2725d1c 100644 --- a/app/models/news.rb +++ b/app/models/news.rb @@ -23,12 +23,18 @@ class News < ActiveRecord::Base #added by nwb belongs_to :course belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' - has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on" + has_many :comments, :as => :commented, :dependent => :destroy, :order => "created_on" # fq has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy # 被ForgeActivity虚拟关联 has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy + # 课程动态 + has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy # end + # 课程/项目消息关联 + has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy + has_many :forge_messages, :class_name => 'ForgeMessage', :as => :forge_message, :dependent => :destroy + #end has_many :ActivityNotifies,:as => :activity, :dependent => :destroy @@ -49,7 +55,7 @@ class News < ActiveRecord::Base :author_key => :author_id acts_as_watchable - after_create :act_as_activity,:act_as_forge_activity,:add_author_as_watcher, :send_mail + after_create :act_as_activity,:act_as_forge_activity, :act_as_course_activity,:act_as_system_message, :add_author_as_watcher, :send_mail after_destroy :delete_kindeditor_assets @@ -121,6 +127,33 @@ class News < ActiveRecord::Base end end + #课程动态公共表记录 + def act_as_course_activity + if self.course + self.course_acts << CourseActivity.new(:user_id => self.author_id,:course_id => self.course_id) + end + end + + #课程/项目通知 消息发送 + #消息发送原则:除了消息的发布者,课程的其它成员都能收到消息提醒 + def act_as_system_message + if self.course + self.course.members.each do |m| + if m.user_id != self.author_id + self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.course_id, :viewed => false) + end + end + else + if !self.project.nil? + self.project.members.each do |m| + if m.user_id != self.author_id + self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.project_id, :viewed => false) + end + end + end + end + end + # Time 2015-03-31 13:50:54 # Author lizanle # Description 删除news后删除对应的资源 @@ -132,4 +165,4 @@ class News < ActiveRecord::Base Mailer.run.news_added(self) if Setting.notified_events.include?('news_added') end -end +end \ No newline at end of file diff --git a/app/models/poll.rb b/app/models/poll.rb index 64e9df79a..67bb9f5a8 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -8,7 +8,12 @@ class Poll < ActiveRecord::Base has_many :users, :through => :poll_users #该文件被哪些用户提交答案过 # 添加课程的poll动态 has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy - after_create :act_as_activity + # 课程动态 + has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy + after_create :act_as_activity, :act_as_course_activity + # 课程消息 + has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy + after_save :act_as_course_message, :act_as_activity, :act_as_course_activity acts_as_event :title => Proc.new {|o| "#{l(:label_course_poll)}: #{o.polls_name}" }, :description => :polls_description, @@ -27,4 +32,30 @@ class Poll < ActiveRecord::Base self.acts << Activity.new(:user_id => self.user_id) end + #课程动态公共表记录 + def act_as_course_activity + if self.polls_type == "Course" + if self.polls_status == 2 #问卷是发布状态 + self.course_acts << CourseActivity.new(:user_id => self.user_id,:course_id => self.polls_group_id) + elsif self.polls_status == 1 #问卷是新建状态 + self.course_acts.destroy_all + end + end + end + + # 发布问卷,出了发布者外,其他人都能收到消息通知 + def act_as_course_message + if self.polls_type == "Course" + if self.polls_status == 2 #问卷是发布状态 + Course.find(self.polls_group_id).members.each do |m| + if m.user_id != self.user_id + self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.polls_group_id, :viewed => false) + end + end + elsif self.polls_status == 1 #问卷是新建状态 + self.course_messages.destroy_all + end + end + end + end diff --git a/app/models/project.rb b/app/models/project.rb index 8ab377ccc..77711edff 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -91,6 +91,8 @@ class Project < ActiveRecord::Base has_many :tags, :through => :project_tags, :class_name => 'Tag' has_many :project_tags, :class_name => 'ProjectTags' + # 关联虚拟表 + has_many :forge_messages belongs_to :organization diff --git a/app/models/repository/git.rb b/app/models/repository/git.rb index c1f0020eb..7c484e87f 100644 --- a/app/models/repository/git.rb +++ b/app/models/repository/git.rb @@ -38,6 +38,12 @@ class Repository::Git < Repository 'Git' end + def commits(authors, start_date, end_date, branch='master') + scm.commits(authors, start_date, end_date,branch).map {|commit| + [commit[:author], commit[:num]] + } + end + def report_last_commit extra_report_last_commit end diff --git a/app/models/student_work.rb b/app/models/student_work.rb index c80d1315b..b95c11c11 100644 --- a/app/models/student_work.rb +++ b/app/models/student_work.rb @@ -7,7 +7,7 @@ class StudentWork < ActiveRecord::Base has_many :student_works_evaluation_distributions, :dependent => :destroy has_many :student_works_scores, :dependent => :destroy belongs_to :project - has_one :student_work_test + has_many :student_work_test before_destroy :delete_praise diff --git a/app/models/student_work_test.rb b/app/models/student_work_test.rb index d9ac5e935..413528b82 100644 --- a/app/models/student_work_test.rb +++ b/app/models/student_work_test.rb @@ -1,12 +1,12 @@ # encoding: utf-8 class StudentWorkTest < ActiveRecord::Base - attr_accessible :student_work_id, :homework_test_id + attr_accessible :student_work_id, :homework_test_id, :result, :error_msg belongs_to :homework_test belongs_to :student_work def status_to_s - case self.result + case self.result.to_i when -1 '编译出错' when -2 @@ -33,7 +33,7 @@ class StudentWorkTest < ActiveRecord::Base end def test_score - if self.result == 0 + if self.result.to_i == 0 format("%.1f",100.0 / self.student_work.homework_common.homework_tests.count) else 0 diff --git a/app/models/student_works_score.rb b/app/models/student_works_score.rb index 8fa14f8de..639722389 100644 --- a/app/models/student_works_score.rb +++ b/app/models/student_works_score.rb @@ -5,6 +5,17 @@ class StudentWorksScore < ActiveRecord::Base belongs_to :user belongs_to :student_work has_many :journals_for_messages, :as => :jour, :dependent => :destroy + has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy acts_as_attachable + + after_create :act_as_course_message + + # 评阅作品消息提示 + def act_as_course_message + if self.student_work + receiver = self.student_work.user + self.course_messages << CourseMessage.new(:user_id => receiver.id, :course_id => self.student_work.homework_common.course.id, :viewed => false) + end + end end diff --git a/app/models/user.rb b/app/models/user.rb index 005c394a8..61dd60eec 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -109,7 +109,6 @@ class User < Principal has_many :contests, :foreign_key => 'author_id', :dependent => :destroy has_many :softapplications, :foreign_key => 'user_id', :dependent => :destroy has_many :journals_for_messages, :as => :jour, :dependent => :destroy - has_many :new_jours, :as => :jour, :class_name => 'JournalsForMessage', :conditions => "status=1" has_many :journal_replies, :dependent => :destroy has_many :activities, :dependent => :destroy has_many :students_for_courses @@ -128,8 +127,16 @@ class User < Principal has_many :messages, :foreign_key => 'author_id' has_one :user_score, :dependent => :destroy has_many :documents # 项目中关联的文档再次与人关联 -# end +# 关联消息表 + has_many :forge_messages + has_many :course_messages + has_many :memo_messages + has_many :user_feedback_messages +# 虚拟转换 + has_many :new_jours, :as => :jour, :class_name => 'JournalsForMessage', :conditions => "status=1" + has_many :issue_assigns, :class_name => 'ForgeMessage', :conditions => 'viewed=0 and forge_message_type="Issue"' + has_many :status_updates, :class_name => 'ForgeMessage', :conditions => 'viewed=0 and forge_message_type="Journal"' # 邮件邀请状态 # has_many :invite_lists # end @@ -150,7 +157,8 @@ class User < Principal nil } - + acts_as_attachable :view_permission => :view_files, + :delete_permission => :manage_files acts_as_customizable ############################added by william acts_as_taggable @@ -235,10 +243,42 @@ class User < Principal # ====================================================================== + # 查询用户未读过的记录 + # 用户留言记录 + def count_new_jour + count = self.new_jours.count + # count = self.journals_for_messages(:conditions => ["status=? and is_readed = ? " ,1, 0]).count + end + + # 查询指派给我的缺陷记录 + def count_new_issue_assign_to + self.issue_assigns + end + + # 新消息统计 + def count_new_message + course_count = CourseMessage.where("user_id =? and viewed =?", User.current.id, 0).count + forge_count = ForgeMessage.where("user_id =? and viewed =?", User.current.id, 0).count + user_feedback_count = UserFeedbackMessage.where("user_id =? and viewed =?", User.current.id, 0).count + user_memo_count = MemoMessage.where("user_id =? and viewed =?", User.current.id, 0).count + messages_count = course_count + forge_count + user_feedback_count + user_memo_count + end + # 查询指派给我的缺陷记录 + def issue_status_update + self.status_updates + end + # end + def extensions self.user_extensions ||= UserExtensions.new end + # User现在可以作为一个Container_type,而Attachment的Container方法会有一个Container.try(:project), + # 所以这里定义一个空方法,保证不报错 + def project + + end + def user_score_attr self.user_score ||= UserScore.new end @@ -258,7 +298,7 @@ class User < Principal ###添加留言 fq def add_jour(user, notes, reference_user_id = 0, options = {}) if options.count == 0 - self.journals_for_messages << JournalsForMessage.new(:user_id => user.id, :notes => notes, :reply_id => reference_user_id, :status => true) + self.journals_for_messages << JournalsForMessage.new(:user_id => user.id, :notes => notes, :reply_id => reference_user_id, :status => true, :is_readed => false) else jfm = self.journals_for_messages.build(options) jfm.save @@ -291,11 +331,7 @@ class User < Principal name end ## end - - def count_new_jour - count = self.new_jours.count - end - + #added by nie def count_new_journal_reply count = self.journal_reply.count @@ -418,7 +454,7 @@ class User < Principal end def nickname(formatter = nil) - login + login.nil? || (login && login.empty?) ? "AnonymousUser" : login end def name(formatter = nil) diff --git a/app/models/user_feedback_message.rb b/app/models/user_feedback_message.rb new file mode 100644 index 000000000..98b53e973 --- /dev/null +++ b/app/models/user_feedback_message.rb @@ -0,0 +1,10 @@ +class UserFeedbackMessage < ActiveRecord::Base + attr_accessible :journals_for_message_id, :journals_for_message_type, :user_id, :viewed + + belongs_to :journals_for_message + belongs_to :user + + validates :user_id,presence: true + validates :journals_for_message_id,presence: true + validates :journals_for_message_type, presence: true +end diff --git a/app/services/courses_service.rb b/app/services/courses_service.rb index 2921cc825..c2944fed5 100644 --- a/app/services/courses_service.rb +++ b/app/services/courses_service.rb @@ -654,36 +654,42 @@ class CoursesService return end if current_user == @user || current_user.admin? - membership = @user.coursememberships.page(1).per(15) + membership = @user.coursememberships else - membership = @user.coursememberships.page(1).per(15).all(:conditions => Course.visible_condition(current_user)) + membership = @user.coursememberships.all(:conditions => Course.visible_condition(current_user)) end if membership.nil? || membership.count == 0 raise l(:label_no_courses, :locale => get_user_language(current_user)) end - membership.sort! { |older, newer| newer.created_on <=> older.created_on } + #membership.sort! { |older, newer| newer.created_on <=> older.created_on } #定义一个数组集合,存放hash数组,该hash数组包括课程的信息,并包含课程的最新发布的资源,最新的讨论区留言,最新的作业,最新的通知 result = [] #对用户所有的课程进行循环,找到每个课程最新发布的资源,最新的讨论区留言,最新的作业,最新的通知,并存进数组 + membership.each do |mp| course = mp.course latest_course_dynamics = [] + notices_count = 0 + topic_count = 0 + topics = nil + homeworkss = nil + notices = nil # 课程通知 latest_news = course.news.page(1).per(2).order("created_on desc") unless latest_news.first.nil? - latest_course_dynamics << {:type => 1, :time => latest_news.first.created_on,:count=>course.news.count, - :news => latest_news.all} + notices_count = course.news.count + notices = latest_news.all + latest_course_dynamics << {:time => latest_news.first.created_on } end - # 课程讨论区 latest_message = course.boards.first.topics.page(1).per(2) unless latest_message.first.nil? - latest_course_dynamics << {:type => 2, :time => latest_message.first.created_on, :count =>course.boards.nil? ? 0 : course.boards.first.topics.count, - :topics => latest_message.all} + topic_count = course.boards.nil? ? 0 : course.boards.first.topics.count + topics = latest_message.all + latest_course_dynamics << {:time => latest_message.first.created_on} end - # 课程资源 # latest_attachment = course.attachments.order("created_on desc").page(1).per(2) # unless latest_attachment.first.nil? @@ -694,14 +700,17 @@ class CoursesService #课程作业 已经交的学生列表(暂定显示6人),未交的学生列表,作业的状态 homeworks = course.homework_commons.page(1).per(2).order('created_at desc') unless homeworks.first.nil? - latest_course_dynamics << {:type => 4, :time => homeworks.first.updated_at, :count=>course.homework_commons.count , :homeworks => homeworks} + homeworkss = homeworks + latest_course_dynamics << {:time => homeworks.first.updated_at} end latest_course_dynamics.sort! { |order, newer| newer[:time] <=> order[:time] } # 课程学霸 学生总分数排名靠前的5个人 homework_count = course.homework_commons.count sql = "select users.*,ROUND(sum(student_works.final_score),2) score from student_works left outer join users on student_works.user_id = users.id" << " where homework_common_id in ( select id from homework_commons where homework_commons.course_id = #{course.id}) GROUP BY student_works.user_id ORDER BY score desc limit 0,4" + better_students = User.find_by_sql(sql) + # 找出在课程讨论区发帖回帖数最多的 active_students = [] sql1 = " select users.*,count(author_id)*2 active_count from messages " << @@ -710,20 +719,41 @@ class CoursesService " GROUP BY messages.author_id ORDER BY count(author_id) desc " << " limit 0,4" active_students = User.find_by_sql(sql1) + if homework_count != 0 && !better_students.empty? - latest_course_dynamics <<{:type=> 6,:time=>Time.now.to_s,:count=> 4,:better_students=> better_students} + latest_course_dynamics <<{:time=>"1970-01-01 0:0:0 +0800"} end unless active_students.empty? - latest_course_dynamics <<{:type=> 7,:time=>Time.now.to_s,:count=> 4,:active_students=>active_students} + latest_course_dynamics <<{:time=>"1970-01-01 0:0:0 +0800"} end latest_course_dynamic = latest_course_dynamics.first unless latest_course_dynamic.nil? - result << {:course_name => course.name,:current_user_is_member => current_user.member_of_course?(course),:current_user_is_teacher => is_course_teacher(current_user,course), :course_id => course.id, :course_img_url => url_to_avatar(course), :course_time => course.time, :course_term => course.term,:message => "", :dynamics => latest_course_dynamics, - :course_student_num=>course ? course.members.count : 0,:time_from_now=> distance_of_time_in_words(Time.now, latest_course_dynamic[:time].to_time) << "前"} + result << {:course_name => course.name, + :current_user_is_member => current_user.member_of_course?(course), + :current_user_is_teacher => is_course_teacher(current_user,course), + :course_id => course.id, + :course_img_url => url_to_avatar(course), + :course_time => course.time, + :course_term => course.term, + :news_count => notices_count, + :homework_count => homework_count, + :topic_count => topic_count, + :news => notices, + :homeworks => homeworkss, + :topics => topics, + :better_students => better_students, + :active_students => active_students, + :message => "", + :course_student_num=>course ? course.members.count : 0, + #:time_from_now=> distance_of_time_in_words(Time.now, latest_course_dynamic[:time].to_time) << "前", + :time_from_now=>time_from_now(latest_course_dynamic[:time].to_time), #.strftime('%Y-%m-%d %H:%M:%S').to_s, + :time=>latest_course_dynamic[:time].to_time} end + end #返回数组集合 - result.sort! { |order, newer| newer[:update_time] <=> order[:update_time] } + result.sort! { |order, newer| newer[:time] <=> order[:time] } + result end diff --git a/app/views/account/lost_password.html.erb b/app/views/account/lost_password.html.erb index 8ed93f36c..3c6c57f52 100644 --- a/app/views/account/lost_password.html.erb +++ b/app/views/account/lost_password.html.erb @@ -9,7 +9,7 @@

- <%= text_field_tag 'mail', nil, :size => 40 %> + <%= text_field_tag 'mail', nil, :size => 40, :placeholder => '请输入注册邮箱'%> <%= submit_tag l(:button_submit) %>

diff --git a/app/views/admin/_tab_messages.erb b/app/views/admin/_tab_messages.erb new file mode 100644 index 000000000..ec04246ba --- /dev/null +++ b/app/views/admin/_tab_messages.erb @@ -0,0 +1,8 @@ +
+
    +
  • <%= link_to l(:label_forum), {:action => 'messages_list'}, class: "#{current_page?(messages_list_path)? 'selected' : nil }" %>
  • +
  • <%= link_to l(:label_borad_course), {:action => 'course_messages'}, class: "#{current_page?(course_messages_path)? 'selected' : nil }" %>
  • +
  • <%= link_to l(:label_borad_project), {:action => 'project_messages'}, class: "#{current_page?(project_messages_path)? 'selected' : nil }" %>
  • + +
+
\ No newline at end of file diff --git a/app/views/admin/course_messages.html.erb b/app/views/admin/course_messages.html.erb new file mode 100644 index 000000000..c9e69357f --- /dev/null +++ b/app/views/admin/course_messages.html.erb @@ -0,0 +1,69 @@ +

+ <%=l(:label_message_plural)%> +

+ +<%= render 'tab_messages' %> +

<%=l(:label_borad_course) %>

+
+ + + + + + + + + + + + + <% @count=@page*30%> + <% for course in @course_ms -%> + + <% @count=@count + 1 %> + "> + + + + + + + + + <% end %> + +
+ 序号 + + 来源(课程ID) + + 作者 + + 时间 + + 标题 + + 回复数 +
+ <%= @count %> + + <%= Board.where('id=?',course.board_id).first.course_id %> + <%= course.try(:author)%><% else %><%=course.try(:author).try(:realname) %><% end %>'> + <% if course.try(:author).try(:realname) == ' '%> + <%= link_to(course.try(:author), user_path(course.author)) %> + <% else %> + <%= link_to(course.try(:author).try(:realname), user_path(course.author)) %> + <% end %> + + <%= format_date(course.created_on) %> + + <%= link_to(course.subject, course_boards_path(Board.where('id=?',course.board_id).first.course_id)) %> + + <%= link_to(course.replies_count, course_boards_path(Board.where('id=?',course.board_id).first.course_id)) %> +
+
+ + +<% html_title(l(:label_message_plural)) -%> diff --git a/app/views/admin/homework.html.erb b/app/views/admin/homework.html.erb new file mode 100644 index 000000000..7260d68ff --- /dev/null +++ b/app/views/admin/homework.html.erb @@ -0,0 +1,66 @@ +

+ <%=l(:label_user_homework)%> +

+ +
+ + + + + + + + + + + + + <%@count=@page*30 %> + <% for homework in @homework do %> + <% @count+=1 %> + + + + + + + + + <% end %> + +
+ 序号 + + 作业名称 + + 课程名称 + + 作者 + + 提交作品数 + + 提交截止日期 +
+ <%=@count %> + + <%=link_to(homework.name, student_work_index_path(:homework => homework.id))%> + + <%= link_to(homework.course.name, course_path(homework.course.id)) %> + <%= homework.try(:user)%><% else %><%=homework.try(:user).try(:realname) %><% end %>'> + <% if homework.try(:user).try(:realname) == ' '%> + <%= link_to(homework.try(:user), user_path(homework.user_id)) %> + <% else %> + <%= link_to(homework.try(:user).try(:realname), user_path(homework.user_id)) %> + <% end %> + + <%=link_to(StudentWork.where('homework_common_id=?',homework.id).count, student_work_index_path(:homework => homework.id))%> + + <%=format_date(homework.end_time) %> +
+
+ + + +<% html_title(l(:label_user_homework)) -%> diff --git a/app/views/admin/latest_login_users.html.erb b/app/views/admin/latest_login_users.html.erb new file mode 100644 index 000000000..89514726a --- /dev/null +++ b/app/views/admin/latest_login_users.html.erb @@ -0,0 +1,96 @@ +<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %> +

+ <%=l(:label_latest_login_user_list)%> +

+ +<%= form_tag({}, :method => :get) do %> +
+ + <%= l(:label_filter_plural) %> + + + <%= text_field_tag 'startdate', params[:startdate], :size => 15, :onchange=>"$('#ui-datepicker-div').hide()", :style=>"float:left"%> + <%= calendar_for('startdate')%>    + + <%= text_field_tag 'enddate', params[:enddate], :size => 15, :onchange =>"$('#ui-datepicker-div').hide()", :style=>"float:left"%> + <%= calendar_for('enddate')%>   + <%= submit_tag l(:button_apply), :class => "small", :name => nil %> + <%= link_to l(:button_clear), {:controller => 'admin', :action => 'latest_login_users'}, :class => 'icon icon-reload' %> +
+<% end %> +  + + +
+ + + + + + + + + + + + + <% @count=@page * 30 %> + <% for user in @user do %> + + <% @count +=1 %> + + + + + + + + <% end %> + +
+ 序号 + + 登录时间 + + 用户id + + 用户姓名 + + 用户昵称 + + 用户身份 +
+ <%=@count %> + + <%=format_date(user.last_login_on) %> + + <%=user.id %> + <%= user.login%><% else %><%=user.try(:realname) %><% end %>'> + <% if user.try(:realname) == ' '%> + <%= link_to(user.login, user_path(user)) %> + <% else %> + <%= link_to(user.try(:realname), user_path(user)) %> + <% end %> + + <%=link_to(user.login, user_path(user)) %> + + <% case user.user_extensions.identity %> + <% when 0 %> + <%='老师' %> + <% when 1 %> + <%='学生' %> + <% when 2 %> + <%='企业' %> + <% when 3 %> + <%='开发者' %> + <% else %> + <%='未知身份' %> + <% end %> +
+
+ + + +<% html_title(l(:label_latest_login_user_list)) -%> diff --git a/app/views/admin/leave_messages.html.erb b/app/views/admin/leave_messages.html.erb new file mode 100644 index 000000000..dee8b7443 --- /dev/null +++ b/app/views/admin/leave_messages.html.erb @@ -0,0 +1,96 @@ +

+ <%=l(:label_leave_message_list)%> +

+ + +
+ + + + + + + + + + + + + + <% @count = @page * 30 %> + <% for journal in @jour -%> + <% @count=@count + 1 %> + "> + + + + + + + + + <% end %> + +
+ 序号 + + 类型 + + 来源(课程或用户ID) + + 留言人 + + 留言时间 + + 留言内容 + + 回复数 +
+ <%= @count %> + + <%case journal.jour_type %> + <% when 'Principal' %> + <%='用户主页' %> + <% when 'Course' %> + <%='课程' %> + <% end %> + + <%= journal.jour_id %> + <%= journal.try(:user)%><% else %><%=journal.try(:user).try(:realname) %><% end %>'> + <% if journal.try(:user).try(:realname) == ' '%> + <%= link_to(journal.try(:user), user_path(journal.user)) %> + <% else %> + <%= link_to(journal.try(:user).try(:realname), user_path(journal.user)) %> + <% end %> + + <%= format_date(journal.created_on) %> + + <%case journal.jour_type %> + <% when 'Principal' %> + <%= link_to(journal.notes.html_safe, feedback_path(journal.jour_id)) %> + <% when 'Course' %> + <%= link_to(journal.notes.html_safe, course_feedback_path(journal.jour_id)) %> + <% end %> + + <% if(journal.m_reply_count) %> + <%case journal.jour_type %> + <% when 'Principal' %> + <%= link_to(journal.m_reply_count, feedback_path(journal.jour_id)) %> + <% when 'Course' %> + <%= link_to(journal.m_reply_count, course_feedback_path(journal.jour_id)) %> + <% end %> + <% else %> + <%case journal.jour_type %> + <% when 'Principal' %> + <%= link_to(0, feedback_path(journal.jour_id)) %> + <% when 'Course' %> + <%= link_to(0, course_feedback_path(journal.jour_id)) %> + <% end %> + <% end %> +
+
+ + +<% html_title(l(:label_leave_message_list)) -%> diff --git a/app/views/admin/messages_list.html.erb b/app/views/admin/messages_list.html.erb new file mode 100644 index 000000000..ca84baa24 --- /dev/null +++ b/app/views/admin/messages_list.html.erb @@ -0,0 +1,71 @@ +

+ <%=l(:label_message_plural)%> +

+ +<%= render 'tab_messages' %> +

<%=l(:label_forum) %>

+
+ + + + + + + + + + + + + <% @count=@page * 30%> + <% for memo in @memo -%> + <% @count=@count + 1 %> + "> + + + + + + + + <% end %> + +
+ 序号 + + 来源(贴吧ID) + + 作者 + + 时间 + + 标题 + + 回复数 +
+ <%= @count %> + + <%= memo.forum_id %> + <%= memo.try(:author)%><% else %><%=memo.try(:author).try(:realname) %><% end %>'> + <% if memo.try(:author).try(:realname) == ' '%> + <%= link_to(memo.try(:author), user_path(memo.author)) %> + <% else %> + <%= link_to(memo.try(:author).try(:realname), user_path(memo.author)) %> + <% end %> + + <%= format_date(memo.created_at) %> + + <% if memo.parent_id.nil? || memo.subject.starts_with?('RE:')%> + <%= link_to(memo.subject, forum_memo_path(memo.forum, memo)) %> + <% else %> + <%= link_to("RE:"+memo.subject, forum_memo_path(memo.forum, memo)) %> + <% end %> + + <%= link_to(memo.replies_count, forum_memo_path(memo.forum, memo)) %> +
+
+ + +<% html_title(l(:label_message_plural)) -%> diff --git a/app/views/admin/notices.html.erb b/app/views/admin/notices.html.erb new file mode 100644 index 000000000..f03a7b97a --- /dev/null +++ b/app/views/admin/notices.html.erb @@ -0,0 +1,78 @@ +

+ <%=l(:label_notification_list)%> +

+ +
+ + + + + + + + + + + + + + + <% @count=@page * 30%> + <% for news in @news -%> + <% @count=@count + 1 %> + "> + + + + + + + + + + <% end %> + +
+ 序号 + + 课程id + + 课程名称 + + 主讲老师 + + 作者 + + 时间 + + 标题 + + 回复数 +
+ <%= @count %> + + <%=news.course_id %> + + <%=link_to(news.course.name, course_path(news.course)) %> + + <%=link_to(news.course.try(:teacher).try(:realname), user_path(news.course.teacher)) %> + <%= news.try(:author)%><% else %><%=news.try(:author).try(:realname) %><% end %>'> + <% if news.try(:author).try(:realname) == ' '%> + <%= link_to(news.try(:author), user_path(news.author)) %> + <% else %> + <%= link_to(news.try(:author).try(:realname), user_path(news.author)) %> + <% end %> + + <%= format_date(news.created_on) %> + + <%= link_to(news.title, news_path(news)) %> + + <%= link_to(news.comments_count, news_path(news)) %> +
+
+ + + +<% html_title(l(:label_notification_list)) -%> diff --git a/app/views/admin/project_messages.html.erb b/app/views/admin/project_messages.html.erb new file mode 100644 index 000000000..a5639eba7 --- /dev/null +++ b/app/views/admin/project_messages.html.erb @@ -0,0 +1,70 @@ +

+ <%=l(:label_message_plural)%> +

+ +<%= render 'tab_messages' %> +

<%=l(:label_borad_project) %>

+
+ + + + + + + + + + + + + <% @count=@page * 30 %> + <% for project in @project_ms -%> + + <% @count=@count + 1 %> + "> + + + + + + + + + <% end %> + +
+ 序号 + + 来源(项目ID) + + 作者 + + 时间 + + 标题 + + 回复数 +
+ <%= @count %> + + <%= Board.where('id=?',project.board_id).first.project_id %> + <%= project.try(:author)%><% else %><%=project.try(:author).try(:realname) %><% end %>'> + <% if project.try(:author).try(:realname) == ' '%> + <%= link_to(project.try(:author), user_path(project.author)) %> + <% else %> + <%= link_to(project.try(:author).try(:realname), user_path(project.author)) %> + <% end %> + + <%= format_date(project.created_on) %> + + <%= link_to(project.subject, project_boards_path(Board.where('id=?',project.board_id).first.project_id)) %> + + <%= link_to(project.replies_count, project_boards_path(Board.where('id=?',project.board_id).first.project_id)) %> +
+
+ + + +<% html_title(l(:label_message_plural)) -%> diff --git a/app/views/admin/schools.html.erb b/app/views/admin/schools.html.erb new file mode 100644 index 000000000..0956981e8 --- /dev/null +++ b/app/views/admin/schools.html.erb @@ -0,0 +1,50 @@ +

+ <%=l(:label_school_plural)%> +

+<%= form_tag({:controller => 'admin', :action => 'schools' }, :method => :get,:id=>"search_course_form") do %> + <%= submit_tag "搜索",:style => "float: right;margin-right: 15px;"%> + +<% end %> +
+ +
+ + + + + + + + + + + <% @schools.each do |school|%> + "> + + + + + + <% end%> + +
+ 序号 + + LOGO + + 学校名称 +
+ <%= school.id %> + + <%= image_tag(school.logo_link,width:40,height:40) %> + + + <%= link_to school.name,"http://#{Setting.host_course}/?school_id=#{school.id}" %> + + + <%= link_to("修改", upload_logo_school_path(school.id,:school_name => @school_name), :class => 'icon icon-copy') %> + <%#= link_to(l(:button_delete), organization_path(school.id), :method => :delete,:confirm => l(:text_are_you_sure), :class => 'icon icon-del') %> +
+
+ +<% html_title(l(:label_project_plural)) -%> diff --git a/app/views/applied_project/_set_applied.js.erb b/app/views/applied_project/_set_applied.js.erb index 33d862d1c..472da3c09 100644 --- a/app/views/applied_project/_set_applied.js.erb +++ b/app/views/applied_project/_set_applied.js.erb @@ -17,6 +17,8 @@ if (window.Messenger) { Messenger().post({ id: "label_apply_project_waiting", message: "<%= l(:label_apply_project_waiting) %>", - showCloseButton: true, + showCloseButton: true }); }; + +$("#applied_project_link_<%= @project.id%>").replaceWith("<%= escape_javascript(link_to "加入项目",appliedproject_path(:user_id => User.current.id,:project_id => @project.id,:project_join => true),:class => "blue_n_btn fr mt20", :remote => "true",:method => "post",:id => "applied_project_link_#{@project.id}") %>"); diff --git a/app/views/applied_project/applied_join_project.js.erb b/app/views/applied_project/applied_join_project.js.erb index 846d2a61d..ae9d3f467 100644 --- a/app/views/applied_project/applied_join_project.js.erb +++ b/app/views/applied_project/applied_join_project.js.erb @@ -6,6 +6,7 @@ <% elsif @status == 2%> alert("<%= l('project.join.tips.success') %>"); hideModal($("#popbox")); + $("#applied_project_link_<%= @project.id%>").replaceWith("<%=escape_javascript(link_to '取消申请',appliedproject_applied_path(:project_id => @project.id,:user_id => User.current.id),:class => "blue_n_btn fr mt20", :remote => "true",:method => "delete",:id => "applied_project_link_#{@project.id}")%>"); <% elsif @status == 3%> alert("<%= l('project.join.tips.has') %>"); <%else%> diff --git a/app/views/attachments/_project_file_links.html.erb b/app/views/attachments/_project_file_links.html.erb index b6d934c64..3b76689f5 100644 --- a/app/views/attachments/_project_file_links.html.erb +++ b/app/views/attachments/_project_file_links.html.erb @@ -29,32 +29,32 @@ <% is_float ||= false %> <% for attachment in attachments %>
-

- <%if is_float%> -

- <% end%> - +

+ <%if is_float%> +

+ <% end%> + <% if options[:length] %> <%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true,:length => options[:length] -%> <% else %> <%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true -%> <% end %> - <%if is_float%> -
- <% end%> + <%if is_float%> +
+ <% end%> - <% if attachment.is_text? %> - <%= link_to image_tag('magnifier.png'), - :controller => 'attachments', - :action => 'show', - :id => attachment, - :filename => attachment.filename%> - <% end %> + <% if attachment.is_text? %> + <%= link_to image_tag('magnifier.png'), + :controller => 'attachments', + :action => 'show', + :id => attachment, + :filename => attachment.filename%> + <% end %>
- <%= h(" - #{attachment.description}") unless attachment.description.blank? %> -
+ <%= h(" - #{attachment.description}") unless attachment.description.blank? %> + ( <%= number_to_human_size attachment.filesize %>) @@ -66,6 +66,16 @@ :class => 'delete delete-homework-icon', :remote => true, :title => l(:button_delete) %> + <% elsif attachment.container_type == 'Issue' %> + <% if User.current == attachment.author %> + <%= link_to image_tag('delete.png'), attachment_path(attachment), + :data => {:confirm => l(:text_are_you_sure)}, + :method => :delete, + :class => 'delete', + #:remote => true, + #:id => "attachments_" + attachment.id.to_s, + :title => l(:button_delete) %> + <% end %> <% else %> <%= link_to image_tag('delete.png'), attachment_path(attachment), :data => {:confirm => l(:text_are_you_sure)}, @@ -89,13 +99,13 @@

<% end %>
- <% if defined?(thumbnails) && thumbnails %> - <% images = attachments.select(&:thumbnailable?) %> - <% if images.any? %> + <% if defined?(thumbnails) && thumbnails %> + <% images = attachments.select(&:thumbnailable?) %> + <% if images.any? %> <% images.each do |attachment| %>
<%= thumbnail_issue_tag(attachment) %>
<% end %> - <% end %> - <% end %> + <% end %> + <% end %>
diff --git a/app/views/avatar/_avatar_form.html.erb b/app/views/avatar/_avatar_form.html.erb index 632ea5d4d..43aaf9132 100644 --- a/app/views/avatar/_avatar_form.html.erb +++ b/app/views/avatar/_avatar_form.html.erb @@ -43,7 +43,7 @@
-<%#= link_to l(:button_delete_file),{:controller => :avatar,:action => :delete_image,:remote=>true,:source_type=> source.class,:source_id=>source.id},:confirm => l(:text_are_you_sure), :method => :post, :class => "btn_addPic", :style => "text-decoration:none;" %> +<%= link_to l(:button_delete_file),{:controller => :avatar,:action => :delete_image,:remote=>true,:source_type=> source.class,:source_id=>source.id},:confirm => l(:text_are_you_sure), :method => :post, :class => "btn_addPic", :style => "text-decoration:none;" %> <%= l(:button_upload_photo) %> diff --git a/app/views/boards/_form.html.erb b/app/views/boards/_form.html.erb index 47ae0672d..a4f58dcc3 100644 --- a/app/views/boards/_form.html.erb +++ b/app/views/boards/_form.html.erb @@ -1,7 +1,7 @@ <%= error_messages_for @board %>
-

+

<%= f.text_field :name, :required => true %>

diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index 5520f526d..609294161 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -1,12 +1,5 @@ \ No newline at end of file diff --git a/app/views/homework_common/index.html.erb b/app/views/homework_common/index.html.erb index 2de96bca1..4a804ae60 100644 --- a/app/views/homework_common/index.html.erb +++ b/app/views/homework_common/index.html.erb @@ -49,40 +49,54 @@

<% if homework.homework_type == 2 && homework.homework_detail_programing%> - - - "> - - - - <% homework.homework_tests.each do |test|%> + <% if @is_teacher%> +
- 输入 - - 输出 -
+ "> - <% end%> - -
- <%=test.input%> + 输入 - <%= test.output%> + 输出
+ <% homework.homework_tests.each do |test|%> + "> + + <%=test.input%> + + + <%= test.output%> + + + <% end%> + + +
+ <% end%> + +
+ 开发语言: +
+ <% if homework.homework_detail_programing.language.to_i == 1%> + C + <% elsif homework.homework_detail_programing.language.to_i == 2%> + C++ + <% end%> +
+
+
<% end%> -
-
- <% unless homework.attachments.empty?%> + <% unless homework.attachments.empty?%> +
附件:
<%= render :partial => 'student_work/work_attachments', :locals => {:attachments => homework.attachments} %>
- <% end%> -
-
+
+
+ <% end%>
扣分标准: diff --git a/app/views/homework_common/new.html.erb b/app/views/homework_common/new.html.erb index b3e433b74..6fc0fff0e 100644 --- a/app/views/homework_common/new.html.erb +++ b/app/views/homework_common/new.html.erb @@ -1,27 +1,17 @@ +<%= javascript_include_tag "/assets/kindeditor/kindeditor" %> +<%= error_messages_for 'homework_common' %>

<%= l(:label_course_homework_new)%>

-
- <%= form_for("new_homework_common",:url => next_step_homework_common_index_path) do |f|%> - -

- 请选择将要发布的作业类型 -

- - - 人工评分的作业(支持匿名互评、灵活设置评分比例) - -
- - - 自动评测的编程作业(支持C程序的自动评分) - -
- - 下一步 - +
+ <%= labelled_form_for @homework,:url => {:controller => 'homework_common',:action => 'create'} do |f| %> + <%= hidden_field_tag "course",@course.id%> + <%= render :partial => 'homework_common/homework_detail_manual_form', :locals => { :homework => @homework,:f => f,:edit_mode => false } %> + 提交 + <%#= link_to "上一步", new_homework_common_path(:course => @course.id), :class => "orange_btn_homework fl"%> + <%= link_to '取消',homework_common_index_path(:course => @course.id),:class => 'grey_btn fl'%> <% end%>
diff --git a/app/views/homework_common/next_step.html.erb b/app/views/homework_common/next_step.html.erb index 75e9f4c0a..e84d0f87a 100644 --- a/app/views/homework_common/next_step.html.erb +++ b/app/views/homework_common/next_step.html.erb @@ -11,7 +11,7 @@ <%= hidden_field_tag "course",@course.id%> <%= render :partial => 'homework_common/homework_detail_manual_form', :locals => { :homework => @homework,:f => f,:edit_mode => false } %> 提交 - <%= link_to "上一步", new_homework_common_path(:course => @course.id), :class => "orange_btn_homework fl"%> + <%#= link_to "上一步", new_homework_common_path(:course => @course.id), :class => "orange_btn_homework fl"%> <%= link_to '取消',homework_common_index_path(:course => @course.id),:class => 'grey_btn fl'%> <% end%>
@@ -22,7 +22,7 @@ <%= hidden_field_tag "homework_common[homework_type]","2"%> <%= render :partial => 'homework_common/homework_detail_programing_form', :locals => { :homework => @homework,:f => f,:edit_mode => false } %> 提交 - <%= link_to "上一步", new_homework_common_path(:course => @course.id), :class => "orange_btn_homework fl"%> + <%#= link_to "上一步", new_homework_common_path(:course => @course.id), :class => "orange_btn_homework fl"%> <%= link_to '取消',homework_common_index_path(:course => @course.id),:class => 'grey_btn fl'%> <% end%>
diff --git a/app/views/homework_common/programing_test.js.erb b/app/views/homework_common/programing_test.js.erb new file mode 100644 index 000000000..d1643329b --- /dev/null +++ b/app/views/homework_common/programing_test.js.erb @@ -0,0 +1,12 @@ +$("#test_send_<%= @index%>").replaceWith(" fl ml5 mt1 programing_test' onclick='programing_test(<%= @index%>)' id='test_send_<%= @index%>'><%= @result == 0 ? '正确' : '错误'%>"); +$("#test_result_<%= @index%>").val("<%= @result%>"); +<% if @err_msg || @result != 0%> + $("#homework_work_test_show").show(); + $("#homework_work_test_desc").text("<%= escape_javascript(@err_msg || status_to_err_msg(@result))%>"); + <% if @err_msg%> + $("#homework_test_error_msg").val("<%= escape_javascript(@err_msg)%>"); + <% end%> +<% else%> + $("#homework_work_test_show").hide(); + $("#homework_test_error_msg").val(""); +<% end%> \ No newline at end of file diff --git a/app/views/issues/show.html.erb b/app/views/issues/show.html.erb index 8c12d62e0..01cbea1c1 100644 --- a/app/views/issues/show.html.erb +++ b/app/views/issues/show.html.erb @@ -6,7 +6,7 @@
<%= link_to "#{@issue.project.name}"+">", project_issues_path(@issue.project) %> - <%= "#" + @issue.project_index %> + <%= "#" + @issue.id.to_s %>
diff --git a/app/views/layouts/_base_footer_public.html.erb b/app/views/layouts/_base_footer_public.html.erb new file mode 100644 index 000000000..dba26f1f6 --- /dev/null +++ b/app/views/layouts/_base_footer_public.html.erb @@ -0,0 +1,46 @@ + +
\ No newline at end of file diff --git a/app/views/layouts/_base_header.html.erb b/app/views/layouts/_base_header.html.erb index 16fa44c73..8dbacb523 100644 --- a/app/views/layouts/_base_header.html.erb +++ b/app/views/layouts/_base_header.html.erb @@ -18,7 +18,7 @@
<% end -%> diff --git a/app/views/layouts/_base_header_new.html.erb b/app/views/layouts/_base_header_new.html.erb index 71cf8ab02..c224ee0ab 100644 --- a/app/views/layouts/_base_header_new.html.erb +++ b/app/views/layouts/_base_header_new.html.erb @@ -9,65 +9,60 @@ + + <% end %> <%= render_menu :account_menu -%> diff --git a/app/views/layouts/_new_header.html.erb b/app/views/layouts/_new_header.html.erb index a756009f0..9252e23b9 100644 --- a/app/views/layouts/_new_header.html.erb +++ b/app/views/layouts/_new_header.html.erb @@ -26,7 +26,7 @@
  • <%=link_to l(:label_my_course), {:controller => 'users', :action => 'user_courses', id: User.current.id},target:"_blank", :class => "parent" %>
      - <% user_course.reverse.each do |course| %> + <% user_course.each do |course| %>
    • <%= link_to course.name, {:controller => 'courses',:action => 'show',:id => course.id},target:"_blank" %>
    • @@ -40,7 +40,7 @@
    • <%= link_to l(:label_my_projects), {:controller => 'users', :action => 'user_projects', id: User.current.id, host: Setting.host_name},target:"_blank", :class => "parent" %>
        - <% User.current.projects.reverse.each do |project| %> + <% User.current.projects.select("projects.*,(SELECT MAX(created_at) FROM `forge_activities` WHERE forge_activities.project_id = projects.id) AS a").order("a desc").each do |project| %>
      • <%= link_to project.name, {:controller => 'projects', :action => 'show',id: project.id, host: Setting.host_name }, target:"_blank" %>
      • @@ -53,6 +53,9 @@
    • + + + <% end -%> <%= header_render_menu :account_menu -%>
    diff --git a/app/views/layouts/_user_courses_list.html.erb b/app/views/layouts/_user_courses_list.html.erb index a5cd6f273..ce9282ee7 100644 --- a/app/views/layouts/_user_courses_list.html.erb +++ b/app/views/layouts/_user_courses_list.html.erb @@ -4,7 +4,7 @@
      <% course_index = 0 %> - <% User.current.courses.reverse.each do |course| %> + <% User.current.courses.each do |course| %> <% if !course_endTime_timeout?(course) %> <%= render :partial => 'layouts/user_homework_list', :locals => {:course => course,:course_index => course_index} %> <% course_index += 1 %> diff --git a/app/views/layouts/_user_project_list.html.erb b/app/views/layouts/_user_project_list.html.erb index 4df61b01b..924bfa9d4 100644 --- a/app/views/layouts/_user_project_list.html.erb +++ b/app/views/layouts/_user_project_list.html.erb @@ -2,7 +2,7 @@
    • <%= link_to l(:label_my_projects), {:controller => 'users', :action => 'user_projects', id: User.current.id, host: Setting.host_name} %>
        - <% User.current.projects.reverse.each do |project| %> + <% User.current.projects.select("projects.*,(SELECT MAX(created_at) FROM `forge_activities` WHERE forge_activities.project_id = projects.id) AS a").order("a desc").each do |project| %>
      • <%= link_to project.name, {:controller => 'projects', :action => 'show',id: project.id, host: Setting.host_name } %>
      • diff --git a/app/views/layouts/_user_watch_btn.html.erb b/app/views/layouts/_user_watch_btn.html.erb index 71eea7166..578319b68 100644 --- a/app/views/layouts/_user_watch_btn.html.erb +++ b/app/views/layouts/_user_watch_btn.html.erb @@ -1,8 +1,11 @@ -<% if(User.current.logged? && User.current!=target)%> - <%if(target.watched_by?(User.current))%> - 取消 - <% else %> - 关注 - <% end %> +<% if User.current.logged?%> + <% if User.current == target%> + 编辑资料 + <%else%> + <%if(target.watched_by?(User.current))%> + 取消关注 + <% else %> + 添加关注 + <% end %> + <% end%> <% end %> \ No newline at end of file diff --git a/app/views/layouts/_user_watch_list.html.erb b/app/views/layouts/_user_watch_list.html.erb index 00c0cdc40..7ccc8660d 100644 --- a/app/views/layouts/_user_watch_list.html.erb +++ b/app/views/layouts/_user_watch_list.html.erb @@ -1,5 +1,5 @@ <% watcher_count,watcher_list = get_watcher_users(user) %> -
        +

        关注

        更多
        diff --git a/app/views/layouts/base_courses.html.erb b/app/views/layouts/base_courses.html.erb index 7a32cb67d..3242d79e9 100644 --- a/app/views/layouts/base_courses.html.erb +++ b/app/views/layouts/base_courses.html.erb @@ -113,7 +113,7 @@
        diff --git a/app/views/layouts/base_users_new.html.erb b/app/views/layouts/base_users_new.html.erb index ef6d82245..e4fe188d2 100644 --- a/app/views/layouts/base_users_new.html.erb +++ b/app/views/layouts/base_users_new.html.erb @@ -17,79 +17,11 @@ <%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', 'public_new', 'leftside_new','users', :media => 'all' %> <%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %> <%= javascript_heads %> +<%= javascript_include_tag "avatars"%> <%= heads_for_theme %> <%= call_hook :view_layouts_base_html_head %> - <%= yield :header_tags -%> - - @@ -103,12 +35,6 @@ $(".subNav").click(function(){ <%=link_to l(:field_homepage), home_path %> > <%=link_to (@center_flag ? '个人中心' : '个人主页'), user_path(@user) %> > <%=link_to @user.name, user_path(@user) %>

        - - - - - -
        @@ -116,7 +42,7 @@ $(".subNav").click(function(){
        - <%= image_tag(url_to_avatar(@user), :id=>'nh_user_tx',:style=>"width:216px;height:216px;",:alt=>"头像") %> + <%= image_tag(url_to_avatar(@user), :id=>'nh_user_tx',:style=>"width:214px;height:214px;overflow:hidden",:alt=>"头像") %> <% if @center_flag %> <% end %> @@ -144,13 +70,15 @@ $(".subNav").click(function(){ <% end %>
        -
        +
          -
        • 加入时间 :
        • +
        • 最近登录 :
        • <% if @user.user_extensions!=nil && @user.user_extensions.identity == 2 %>
        • <%= l(:label_company_name) %> :
        • <% elsif !@user.firstname.empty? || !@user.lastname.empty? %> -
        • 真实姓名 :
        • + <% if @user.user_extensions.identity == 0 %> +
        • 真实姓名 :
        • + <% end %> <% end %> <% unless @user.user_extensions.nil? %> <% if @user.user_extensions.identity == 0 %> @@ -172,8 +100,10 @@ $(".subNav").click(function(){ <% end %>
          -
        • <%= format_date(@user.created_on) %>
        • -
        • <%= @user.show_name %>
        • +
        • <%= format_date(@user.last_login_on) %>
        • + <% if @user.user_extensions.identity == 0 %> +
        • <%= @user.show_name %>
        • + <% end %> <% unless @user.user_extensions.nil? %> <% if @user.user_extensions.identity == 0 %>
        • <%= get_technical_title @user %>
        • @@ -197,75 +127,154 @@ $(".subNav").click(function(){
        + @@ -281,7 +290,9 @@ $(".subNav").click(function(){ <%= render :partial => 'layouts/new_feedback' %> -<%= javascript_include_tag '/javascripts/avatars.js' %> + @@ -328,5 +339,17 @@ $(".subNav").click(function(){
        + + diff --git a/app/views/mailer/message_posted.html.erb b/app/views/mailer/message_posted.html.erb index c55f4b000..ed8cb8626 100644 --- a/app/views/mailer/message_posted.html.erb +++ b/app/views/mailer/message_posted.html.erb @@ -8,8 +8,9 @@ <% if @message.project %> <%=h @message.board.project.name %> - <%=h @message.board.name %>: <%= link_to(h(@message.subject), @message_url,:style=>'color:#1b55a7; font-weight:bold;') %> <% elsif @message.course %> - <%=h @message.board.course.name %> - <%=h @message.board.name %>: <%= link_to(h(@message.subject), @message_url,:style=>'color:#1b55a7; font-weight:bold;') %> - <% end %> + <%=h @message.board.course.name %> - <%=h @message.board.name %>: + <%= link_to(h(@message.subject), @message_url + "?topic_id=#{@message.id}&&parent_id=#{@message.parent_id ? @message.parent_id : @message.id}",:style=>'color:#1b55a7; font-weight:bold;') %> + <% end %> <%= l(:mail_issue_title_active)%>

          diff --git a/app/views/mailer/send_for_user_activities.html.erb b/app/views/mailer/send_for_user_activities.html.erb index 59dc1e674..7bd1b0bc2 100644 --- a/app/views/mailer/send_for_user_activities.html.erb +++ b/app/views/mailer/send_for_user_activities.html.erb @@ -81,7 +81,7 @@ :style => "color:#2E8DD7; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> <%= l(:label_course_homework) %> - <%= link_to truncate(bid.name.html_safe,length: 30,omission: '...'), student_work_index_path(:homework => bid.id,:token => @token.value), + <%= link_to truncate(bid.name.html_safe,length: 30,omission: '...'), student_work_index_url(:homework => bid.id,:token => @token.value), :class => 'wmail_info', :style => "color:#2E8DD7;float:left; font-weight:normal;margin-right:5px; display:block;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> @@ -225,10 +225,10 @@ :style => "color:#2E8DD7; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> <%= l(:label_project_issue_update) %> <% if issues_journal.notes.blank? || issues_journal.notes.nil? %> - <%= link_to truncate(l(:label_isuue_mail_status),length: 30,omission: '...'),issue_url(issues_journal.issue, :token => @token.value), + <%= link_to truncate(issues_journal.issue.subject.html_safe, length: 30,omission: '...'),issue_url(issues_journal.issue, :token => @token.value), :style => "color:#2E8DD7;float:left; font-weight:normal;margin-right:5px; display:block;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> <% else %> - <%= link_to truncate(issues_journal.notes.html_safe,length: 30,omission: '...'),issue_url(issues_journal.issue, :token => @token.value), + <%= link_to truncate(issues_journal.notes.html_safe, length: 30,omission: '...'),issue_url(issues_journal.issue, :token => @token.value), :style => "color:#2E8DD7;float:left; font-weight:normal;margin-right:5px; display:block;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> <% end %> <%= format_time(issues_journal.created_on) %> diff --git a/app/views/members/autocomplete.js.erb b/app/views/members/autocomplete.js.erb index 01faf7da9..5f21ee38e 100644 --- a/app/views/members/autocomplete.js.erb +++ b/app/views/members/autocomplete.js.erb @@ -1,4 +1,9 @@ <% if @project%> + var checked = $("#principals input:checked").size(); + if(checked > 0) + { + alert('翻页或搜索后将丢失当前选择的用户数据!'); + } <% if @flag == "true"%> $('#principals_for_new_member').html('<%= escape_javascript(render_project_members(@project)) %>'); <% else%> diff --git a/app/views/memos/show.html.erb b/app/views/memos/show.html.erb index 55a2410b0..586279504 100644 --- a/app/views/memos/show.html.erb +++ b/app/views/memos/show.html.erb @@ -7,7 +7,9 @@ <%= javascript_include_tag "/assets/kindeditor/kindeditor",'/assets/kindeditor/pasteimg' %>
          - <%= render :partial => "/praise_tread/praise_tread",:locals => {:obj => @memo,:show_flag => true,:user_id =>User.current.id,:horizontal => true}%> + + <%= render :partial => "/praise_tread/praise_tread",:locals => {:obj => @memo,:show_flag => true,:user_id =>User.current.id,:horizontal => true}%> +
          <%= link_to image_tag(url_to_avatar(@memo.author), :class => "avatar"), user_path(@memo.author) %> diff --git a/app/views/my/clear_user_avatar_temp.js.erb b/app/views/my/clear_user_avatar_temp.js.erb index 9513bdac4..788678673 100644 --- a/app/views/my/clear_user_avatar_temp.js.erb +++ b/app/views/my/clear_user_avatar_temp.js.erb @@ -4,4 +4,5 @@ $('#ajax-modal').siblings().hide(); $('#ajax-modal').parent().removeClass("alert_praise"); //$('#ajax-modal').parent().css("top","").css("left",""); - $('#ajax-modal').parent().addClass("alert_box"); \ No newline at end of file + $('#ajax-modal').parent().addClass("alert_box"); + $('#ajax-modal').parent().css("border", "2px solid #15bccf").css("border-radius", "0").css(" -webkit-border-radius", "0").css(" -moz-border-radius", "0"); \ No newline at end of file diff --git a/app/views/my/save_user_avatar.js.erb b/app/views/my/save_user_avatar.js.erb index ce4bae501..54cb3de48 100644 --- a/app/views/my/save_user_avatar.js.erb +++ b/app/views/my/save_user_avatar.js.erb @@ -1,2 +1,2 @@ -$("#nh_user_tx").replaceWith('<%= image_tag(url_to_avatar(@user), :id=>'nh_user_tx',:style=>"width:216px;height:216px;",:alt=>"头像") %>'); +$("#nh_user_tx").replaceWith('<%= image_tag(url_to_avatar(@user), :id=>'nh_user_tx',:style=>"width:214px;height:214px;overflow:hidden",:alt=>"头像") %>'); hideModal(); \ No newline at end of file diff --git a/app/views/news/_course_news.html.erb b/app/views/news/_course_news.html.erb index c89f0af26..e2c50fe24 100644 --- a/app/views/news/_course_news.html.erb +++ b/app/views/news/_course_news.html.erb @@ -2,70 +2,39 @@ btn_tips = l(:label_news_notice) label_tips = l(:label_course_news) %> +

          <%= label_tips %>

          -

          - <%= l(:label_total_news) %> - <%= @news_count %> - <%= l(:label_course_news_count) %> -

          - <% if @course && User.current.allowed_to?(:manage_news, @course) %> - <%= link_to(btn_tips,new_course_news_path(@course),:class => 'problem_new_btn fl c_dorange')%> -
          - - <% end %> -
          -
          - -
          - <% if @newss.empty? %> -

          - <%= l(:label_no_data) %> +

          +

          + <%= l(:label_total_news) %> + <%= @news_count %> + <%= l(:label_course_news_count) %>

          - <% else %> - <% @newss.each do |news| %> -
          - <%= link_to image_tag(url_to_avatar(news.author),:width => 42,:height => 42), user_path(news.author), :class => "problem_pic fl" %> -
          - <%= link_to_user_header(news.author,false,{:class=> 'problem_name c_orange fl'}) if news.respond_to?(:author) %> - - <%= l(:label_release_news) %>: - - <%= link_to h(news.title), news_path(news),:class => 'problem_tit fl fb c_dblue' %> - <%=link_to "#{news.comments.all.count}".html_safe, news_path(news.id), :class => "pro_mes_w" %> -
          -
          - -
          -
          - <%= news.description.html_safe %> -
          -
          -
          - -
          - <%= l(:label_create_time)%>:<%= format_time(news.created_on)%> - <%= link_to_attachments_course news %> -
          - <%#= render :partial => 'student_work/work_attachments', :locals => {:attachments => news.attachments} %> -
          -
          -
          + <% if @course && User.current.allowed_to?(:manage_news, @course) %> + <%= link_to(btn_tips,new_course_news_path(@course),:class => 'problem_new_btn fl c_dorange')%> +
          <% end %> - <% end %> +
          + +
          - -
            - <%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%> -
          +
          + <%= render :partial => 'course_news_list', :locals=>{ :newss=>@newss,:obj_pages=>@obj_pages, :obj_count=>@obj_count} %> +
          <% content_for :header_tags do %> <%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %> <%= stylesheet_link_tag 'scm' %> diff --git a/app/views/news/_course_news_list.html.erb b/app/views/news/_course_news_list.html.erb new file mode 100644 index 000000000..da963b3cd --- /dev/null +++ b/app/views/news/_course_news_list.html.erb @@ -0,0 +1,47 @@ +
          +<% if newss.empty? %> +

          + <%= l(:label_no_data) %> +

          +<% else %> + <% newss.each do |news| %> +
          + <%= link_to image_tag(url_to_avatar(news.author),:width => 42,:height => 42), user_path(news.author), :class => "problem_pic fl" %> +
          + <%= link_to_user_header(news.author,false,{:class=> 'problem_name c_orange fl'}) if news.respond_to?(:author) %> + + <%= l(:label_release_news) %>: + + <%= link_to h(news.title), news_path(news),:class => 'problem_tit fl fb c_dblue' %> + <%=link_to "#{news.comments.all.count}".html_safe, news_path(news.id), :class => "pro_mes_w" %> +
          +
          + +
          +
          + <%= news.description.html_safe %> +
          +
          +
          + +
          + <%= l(:label_create_time)%>:<%= format_time(news.created_on)%> + <%= link_to_attachments_course news %> +
          + <%#= render :partial => 'student_work/work_attachments', :locals => {:attachments => news.attachments} %> +
          +
          +
          + + <% end %> +<% end %> +
          + + +
            + <%= pagination_links_full obj_pages, obj_count, :per_page_links => false, :remote => false, :flag => true%> +
          \ No newline at end of file diff --git a/app/views/news/index.js.erb b/app/views/news/index.js.erb new file mode 100644 index 000000000..04671917b --- /dev/null +++ b/app/views/news/index.js.erb @@ -0,0 +1 @@ +$("#news_list").html("<%= escape_javascript(render :partial => 'course_news_list', :locals=>{ :newss=>@newss,:obj_pages=>@obj_pages, :obj_count=>@obj_count})%>"); \ No newline at end of file diff --git a/app/views/poll/_new_MC.html.erb b/app/views/poll/_new_MC.html.erb index 8c47baa01..e5f2a6b82 100644 --- a/app/views/poll/_new_MC.html.erb +++ b/app/views/poll/_new_MC.html.erb @@ -1,5 +1,6 @@ <%= form_for PollQuestion.new,:url =>create_poll_question_poll_path(@poll.id),:remote => true do |f|%> + <% insert_begin = insert_begin %>
          diff --git a/app/views/poll/_other_poll.html.erb b/app/views/poll/_other_poll.html.erb new file mode 100644 index 000000000..40ecbc569 --- /dev/null +++ b/app/views/poll/_other_poll.html.erb @@ -0,0 +1,37 @@ +
          +
          +

          选择问卷导入本课程

          +
          +
          + <%= form_tag import_other_poll_poll_index_path, + method: :post, + remote: true, + id: "relation_file_form" do %> + + <%= content_tag('div', poll_check_box_tags('polls[]', polls,polls_group_id), :id => 'courses',:style=> 'width: 300px;')%> + 导  入 + 取  消 + <% end -%> +
          + + +
          +
          + + \ No newline at end of file diff --git a/app/views/poll/_poll.html.erb b/app/views/poll/_poll.html.erb index 180fed0f0..1828ede6d 100644 --- a/app/views/poll/_poll.html.erb +++ b/app/views/poll/_poll.html.erb @@ -2,11 +2,13 @@ <% poll_name = poll.polls_name.empty? ? l(:label_poll_new) : poll.polls_name%> <% if @is_teacher%>
        • - <% if has_commit %> - <%= link_to poll_name, poll_result_poll_path(poll.id), :class => "polls_title polls_title_w fl c_dblue"%> - <% else %> - <%= link_to poll_name, poll_path(poll.id), :class => "polls_title polls_title_w fl c_dblue" %> - <% end %> +
          + <% if has_commit %> + <%= link_to poll_name, poll_result_poll_path(poll.id), :class => "polls_title polls_title_w fl c_dblue"%> + <% else %> + <%= link_to poll_name, poll_path(poll.id), :class => "polls_title polls_title_w fl c_dblue" %> + <% end %> +
        • <% if poll.polls_status == 1%> @@ -41,6 +43,7 @@
        • 导出
        • <% elsif poll.polls_status == 2 || poll.polls_status == 3 %>
        • <%= link_to "导出", export_poll_poll_path(poll.id,:format => "xls"), :class => "polls_de fr ml5"%>
        • + <% end%> diff --git a/app/views/poll/_poll_form.html.erb b/app/views/poll/_poll_form.html.erb index 74ca9fb32..c5c016583 100644 --- a/app/views/poll/_poll_form.html.erb +++ b/app/views/poll/_poll_form.html.erb @@ -2,27 +2,262 @@
          @@ -9,9 +12,11 @@ * <%end%>
          + <%= link_to("", delete_poll_question_poll_index_path(:poll_question => poll_question.id), method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "ur_icon_de") %> +
          @@ -29,4 +34,15 @@
          -
          \ No newline at end of file +
          + +
          +
          + \ No newline at end of file diff --git a/app/views/poll/_show_MCQ.html.erb b/app/views/poll/_show_MCQ.html.erb index 63b9d1c1f..f13cf17d3 100644 --- a/app/views/poll/_show_MCQ.html.erb +++ b/app/views/poll/_show_MCQ.html.erb @@ -12,6 +12,7 @@ <%= link_to("", delete_poll_question_poll_index_path(:poll_question => poll_question.id), method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "ur_icon_de") %> +
          @@ -29,4 +30,15 @@
          -
          \ No newline at end of file +
          + +
          +
          + \ No newline at end of file diff --git a/app/views/poll/_show_head.html.erb b/app/views/poll/_show_head.html.erb index 4a1b2256d..752a5b310 100644 --- a/app/views/poll/_show_head.html.erb +++ b/app/views/poll/_show_head.html.erb @@ -1,5 +1,8 @@ +
          + +

          <%= poll.polls_name%>

          <%= @poll.polls_description.nil? ? "" : @poll.polls_description.html_safe%>
          diff --git a/app/views/poll/_show_mulit.html.erb b/app/views/poll/_show_mulit.html.erb index 2d52fffb5..6c98b8257 100644 --- a/app/views/poll/_show_mulit.html.erb +++ b/app/views/poll/_show_mulit.html.erb @@ -13,9 +13,21 @@ <%= link_to("", delete_poll_question_poll_index_path(:poll_question => poll_question.id), method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "ur_icon_de") %> +
          -
          \ No newline at end of file +
          + +
          +
          + \ No newline at end of file diff --git a/app/views/poll/_show_single.html.erb b/app/views/poll/_show_single.html.erb index 8caa7b1a5..68b93d244 100644 --- a/app/views/poll/_show_single.html.erb +++ b/app/views/poll/_show_single.html.erb @@ -12,8 +12,20 @@ <%= link_to("", delete_poll_question_poll_index_path(:poll_question => poll_question.id), method: :delete, :confirm => l(:text_are_you_sure), :remote => true, :class => "ur_icon_de") %> +
          -
        \ No newline at end of file +
        + +
        +
        + \ No newline at end of file diff --git a/app/views/poll/create_poll_question.js.erb b/app/views/poll/create_poll_question.js.erb index ac44ebb4c..8a597514e 100644 --- a/app/views/poll/create_poll_question.js.erb +++ b/app/views/poll/create_poll_question.js.erb @@ -1,4 +1,8 @@ +<% if @is_insert %> + $("#poll_content").html('<%= escape_javascript(render :partial => 'poll_content', :locals => {:poll => @poll})%>'); +<% else %> $("#new_poll_question").html(""); + $("#poll_content").append("
        " + "
        " + "<% if @poll_questions.question_type == 1%>" + @@ -23,4 +27,4 @@ $("#poll_content").append("
        " + "<% end%>" + "
        " + "
        "); - +<% end %> diff --git a/app/views/poll/import_other_poll.js.erb b/app/views/poll/import_other_poll.js.erb new file mode 100644 index 000000000..f60cea1c5 --- /dev/null +++ b/app/views/poll/import_other_poll.js.erb @@ -0,0 +1 @@ +$('#polls_list').html('<%= escape_javascript(render :partial => 'polls_list', :locals => {:polls => @polls,:obj_pages=>@obj_pages,:obj_count=>@obj_count}) %>
        '); \ No newline at end of file diff --git a/app/views/poll/import_poll.js.erb b/app/views/poll/import_poll.js.erb new file mode 100644 index 000000000..9f1d8e7cb --- /dev/null +++ b/app/views/poll/import_poll.js.erb @@ -0,0 +1,4 @@ +/** + * Created by lizanle on 2015/7/29. + */ +$("#poll_content").html('<%= escape_javascript(render :partial => 'poll_content', :locals => {:poll => @poll})%>'); \ No newline at end of file diff --git a/app/views/poll/index.html.erb b/app/views/poll/index.html.erb index bede915b4..92a42cbac 100644 --- a/app/views/poll/index.html.erb +++ b/app/views/poll/index.html.erb @@ -80,6 +80,11 @@ $('#ajax-modal').parent().css("top","").css("left",""); $('#ajax-modal').parent().addClass("popbox_polls"); } + + function closeModal() + { + hideModal($("#popbox_upload")); + }
        <%= render :partial => 'poll_list'%> diff --git a/app/views/poll/other_poll.js.erb b/app/views/poll/other_poll.js.erb new file mode 100644 index 000000000..eee4ed4a1 --- /dev/null +++ b/app/views/poll/other_poll.js.erb @@ -0,0 +1,13 @@ + +<% if @polls.empty? %> + alert('您目前还没有自己新建的问卷'); +<% else %> + $('#ajax-modal').html('<%= escape_javascript(render :partial => 'other_poll',:locals => {:polls => @polls,:polls_group_id=>@polls_group_id}) %>'); + + + showModal('ajax-modal', '513px'); + $('#ajax-modal').siblings().remove(); + $('#ajax-modal').before(""); + $('#ajax-modal').parent().css("top","").css("left",""); + $('#ajax-modal').parent().addClass("popbox_polls"); +<% end %> \ No newline at end of file diff --git a/app/views/projects/_development_group.html.erb b/app/views/projects/_development_group.html.erb index d4bc7012a..915637ec5 100644 --- a/app/views/projects/_development_group.html.erb +++ b/app/views/projects/_development_group.html.erb @@ -31,7 +31,7 @@
      diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb index ca7bb6159..f1b3d9b7b 100644 --- a/app/views/projects/show.html.erb +++ b/app/views/projects/show.html.erb @@ -93,21 +93,7 @@
  • - - <% elsif e.forge_act_type == "Document" %> -
    - <%= image_tag(url_to_avatar(e.user), :width => "42", :height => "42") %> -
    - - <%= h(e.project) if @project.nil? || @project.id != e.project_id %> - <%= link_to h(e.user), user_path(e.user_id), :class => "problem_name c_orange fl" %> <%= l(:label_new_activity) %> : - <%= link_to format_activity_title("#{l(:label_document)}: #{act.title}"), {:controller => 'documents', :action => 'show', :id => act.id}, :class => "problem_tit fl fb" %>
    -

    <%= textAreailizable act,:description %>
    - <%= l :label_create_time %> :<%= format_activity_day(act.created_on) %> <%= format_time(act.created_on, false) %>

    -
    -
    -
    <% elsif e.forge_act_type == "Attachment" %>
    diff --git a/app/views/repositories/stats.html.erb b/app/views/repositories/stats.html.erb index 7e558119f..0bce15069 100644 --- a/app/views/repositories/stats.html.erb +++ b/app/views/repositories/stats.html.erb @@ -1,11 +1,30 @@

    <%= l(:label_statistics) %>

    -

    - <%= tag("embed", :width => 670, :height => 300, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "commits_per_month")) %> -

    -

    - <%= tag("embed", :width => 670, :height => 400, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "commits_per_author")) %> -

    -

    <%= link_to l(:button_back), :action => 'show', :id => @project %>

    -<% html_title(l(:label_repository), l(:label_statistics)) -%> +<% if @status_commit_count ==0 %> +
    该项目目前还没有提交过代码!
    +<% else %> +
    修订 是版本库的提交次数, 显示为橘红色。

    +
    变更 是对版本库中文件的修改次数, 显示为蓝色。
    + +

    + <%= tag("embed", :width => 670, :height => 300, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "commits_per_month")) %> +

    +

    + <%# 用户每月提交代码次数 %> + <%= tag("embed", :width => 670, :height => 400, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "commits_per_author")) %> +

    +

    + <%= tag("embed", :width => 670, :height => 400, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "author_commits_per_month")) %> +

    +

    + <%# 用户最近六个月的提交次数 %> + <%= tag("embed", :width => 670, :height => 400, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "author_commits_six_month")) %> +

    +

    + <%# 用户最近六个月的代码量 %> + <%= tag("embed", :width => 670, :height => 400, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "author_code_six_months")) %> +

    +

    <%= link_to l(:button_back), :action => 'show', :id => @project %>

    + <% html_title(l(:label_repository), l(:label_statistics)) -%> +<% end %> \ No newline at end of file diff --git a/app/views/school/upload_logo.html.erb b/app/views/school/upload_logo.html.erb index 97a3f171c..26da7e081 100644 --- a/app/views/school/upload_logo.html.erb +++ b/app/views/school/upload_logo.html.erb @@ -1,5 +1,28 @@ -<%= form_tag({action: :upload},method: "post", multipart: true) do %> - <%= text_field_tag 'school'%> - <%= file_field_tag 'logo' %> - <%= submit_tag('Upload') %> + + +<%= form_tag(upload_school_path(@school.id),method: "post", multipart: true) do %> + <%#= text_field_tag 'school'%> +
    + + <%= image_tag(@school.logo_link, id: "avatar_image", :class=>"school_avatar")%> + 上传图片 + <%= file_field_tag 'logo',:style => "display:none;", :id => "file", :onchange => "showPreview(this)"%> +
    +
    + <%= submit_tag('上传') %> + <%= submit_tag('取消') %> +
    +
    <% end %> + diff --git a/app/views/student_work/_evaluation_student_work.html.erb b/app/views/student_work/_evaluation_student_work.html.erb index b5bdd6f55..368c636df 100644 --- a/app/views/student_work/_evaluation_student_work.html.erb +++ b/app/views/student_work/_evaluation_student_work.html.erb @@ -9,7 +9,8 @@ <%= link_to student_work.user.show_name,user_path(student_work.user),:title => student_work.user.show_name, :class => "c_blue02"%>
  • - <%= link_to student_work.name, student_work_path(student_work.id),:remote => true,:title => student_work.name, :class => "c_blue02"%> + <% student_work_name = student_work.name.nil? || student_work.name.empty? ? student_work.user.show_name + '的作品' : student_work.name%> + <%= link_to student_work_name, student_work_path(student_work.id),:remote => true,:title => student_work.name, :class => "c_blue02"%>
  • <% if Time.parse(@homework.end_time.to_s).strftime("%Y-%m-%d") < Time.parse(student_work.created_at.to_s).strftime("%Y-%m-%d") %> @@ -47,8 +48,10 @@  <%= student_work.final_score%> 分。 迟交扣分  <%= student_work.late_penalty%> 分, - 缺评扣分 -  <%= student_work.absence_penalty%> 分, + <% if student_work.homework_common.homework_type == 1%> + 缺评扣分 +  <%= student_work.absence_penalty%> 分, + <% end%> 最终成绩为  <%= format("%.1f",score)%> 分。
  • diff --git a/app/views/student_work/_evaluation_work.html.erb b/app/views/student_work/_evaluation_work.html.erb index 11ce7b080..be07269c3 100644 --- a/app/views/student_work/_evaluation_work.html.erb +++ b/app/views/student_work/_evaluation_work.html.erb @@ -18,7 +18,8 @@ <% end%>
  • - <%= link_to student_work.name, student_work_path(student_work),:remote => true, :title => student_work.name, :class => "c_blue02"%> + <% student_work_name = student_work.name.nil? || student_work.name.empty? ? '匿名的作品' : student_work.name%> + <%= link_to student_work_name, student_work_path(student_work),:remote => true, :title => student_work.name, :class => "c_blue02"%>
  • <% my_score = student_work_score(student_work,User.current) %>
  • diff --git a/app/views/student_work/_programing_work_show.html.erb b/app/views/student_work/_programing_work_show.html.erb index 79c578525..b259e20a5 100644 --- a/app/views/student_work/_programing_work_show.html.erb +++ b/app/views/student_work/_programing_work_show.html.erb @@ -23,40 +23,42 @@
  • -
  • 测试结果: - - - - - - - - - - - - - - - <%@homework.homework_tests.each do |test|%> - "> - - - - + <% if @is_teacher%> +
  • 测试结果: +
  • - <%= test.input%> - - <%= test.output%> - <%= test.student_work_test.nil? ? "正在编译" : test.student_work_test.status_to_s%><%= test.student_work_test.nil? ? "0" : test.student_work_test.test_score%>
    + + + + + - <% end%> + <%@homework.homework_tests.each do |test|%> + "> + + + <% student_work_test = StudentWorkTest.where(:homework_test_id => test.id,:student_work_id => @work.id).first%> + + + + <% end%> + <% student_work_test = @work.student_work_test.first%> + <% if student_work_test && student_work_test.error_msg && !student_work_test.error_msg.empty?%> + + + + <% end%> - -
    输入输出测试结果
    <%= student_work_test.nil? ? "正在编译" : student_work_test.status_to_s%>
    + <%= student_work_test.error_msg%> +
    -
    -
  • - <% if @is_teacher%> + + +
    +
    <%= render :partial => 'add_score',:locals => {:work => @work,:score => @score}%> diff --git a/app/views/student_work/_show.html.erb b/app/views/student_work/_show.html.erb index 2b7d49402..f6580659e 100644 --- a/app/views/student_work/_show.html.erb +++ b/app/views/student_work/_show.html.erb @@ -36,7 +36,7 @@
  • 内容:
    - <%= text_format @work.description%> + <%= text_format(@work.description) if @work.description%>
  • diff --git a/app/views/student_work/_student_work.html.erb b/app/views/student_work/_student_work.html.erb index dd7ab7e2d..f7eb7514d 100644 --- a/app/views/student_work/_student_work.html.erb +++ b/app/views/student_work/_student_work.html.erb @@ -9,7 +9,8 @@ <%= link_to student_work.user.show_name,user_path(student_work.user),:title => student_work.user.show_name, :class => "c_blue02"%>
  • - <%= link_to student_work.name, student_work_path(student_work),:remote => true,:title => student_work.name, :class => "c_blue02"%> + <% student_work_name = student_work.name.nil? || student_work.name.empty? ? student_work.user.show_name + '的作品' : student_work.name%> + <%= link_to student_work_name, student_work_path(student_work),:remote => true,:title => student_work.name, :class => "c_blue02"%>
  • <% if Time.parse(@homework.end_time.to_s).strftime("%Y-%m-%d") < Time.parse(student_work.created_at.to_s).strftime("%Y-%m-%d") %> diff --git a/app/views/student_work/index.html.erb b/app/views/student_work/index.html.erb index 781277b57..0250a7eed 100644 --- a/app/views/student_work/index.html.erb +++ b/app/views/student_work/index.html.erb @@ -55,21 +55,23 @@ <% end%> <% if @is_teacher%>
    - <% if @homework.student_works.empty?%> - <%= link_to "附件", "javascript:void(0)", class: "down_btn fr zip_download_alert", :onclick => "alert('没有学生提交作业,无法下载附件')" %> - <% else%> - <%= link_to "附件", zipdown_assort_path(obj_class: @homework.class, obj_id: @homework, format: :json), - remote: true, class: "down_btn fr zip_download_alert", :id => "download_homework_attachments" %> + <% unless @homework.homework_type == 2%> + <% if @homework.student_works.empty?%> + <%= link_to "附件", "javascript:void(0)", class: "down_btn fr zip_download_alert", :onclick => "alert('没有学生提交作业,无法下载附件')" %> + <% else%> + <%= link_to "附件", zipdown_assort_path(obj_class: @homework.class, obj_id: @homework, format: :json), + remote: true, class: "down_btn fr zip_download_alert", :id => "download_homework_attachments" %> + <% end%> +
    + 使用 + winzip + 工具进行解压可能会导致 + 下载文件乱码 + ,建议您使用 + winrar + 工具进行解压 +
    <% end%> -
    - 使用 - winzip - 工具进行解压可能会导致 - 下载文件乱码 - ,建议您使用 - winrar - 工具进行解压 -
    <%= link_to("匿评", evaluation_list_student_work_index_path(:homework => @homework.id, :format => 'xls'),:class=>'down_btn fr') if @homework.homework_type == 1%> <%= link_to("缺评", absence_penalty_list_student_work_index_path(:homework => @homework.id, :format => 'xls'),:class=>'down_btn fr') if @homework.homework_type == 1%> <%= link_to l(:label_list), student_work_index_path(:homework => @homework.id,:order => @order, :sort => @b_sort, :name => @name, :format => 'xls'),:class=>'down_btn fr'%> @@ -135,22 +137,44 @@
    <% if @homework.homework_type == 2 && @homework.homework_detail_programing%> - - - <% @homework.homework_tests.each do |test|%> + <% if @is_teacher%> +
    + "> - <% end%> - -
    - <%=test.input%> + 输入 - <%= test.output%> + 输出
    + <% @homework.homework_tests.each do |test|%> + "> + + <%=test.input%> + + + <%= test.output%> + + + <% end%> + + +
    + <% end%> + +
    + 开发语言: +
    + <% if @homework.homework_detail_programing.language.to_i == 1%> + C + <% elsif @homework.homework_detail_programing.language.to_i == 2%> + C++ + <% end%> +
    +
    +
    <% end%> -
    <% unless @homework.attachments.empty?%> diff --git a/app/views/student_work/new.html.erb b/app/views/student_work/new.html.erb index eda09114e..c72f9d422 100644 --- a/app/views/student_work/new.html.erb +++ b/app/views/student_work/new.html.erb @@ -44,7 +44,7 @@

    - + <%= f.select :project_id,options_for_select(user_projects_option), {},{:class => "bo02 mb10"} %>

    @@ -54,7 +54,11 @@ <%= @homework.homework_type == 2 ? "提交代码" : "作品描述"%>    : - <%= f.text_area "description", :class => "w620 hwork_txt ", :placeholder => "作品描述不能为空", :onkeyup => "regexStudentWorkDescription();"%> + <% if @homework.homework_type == 2 && @homework.homework_detail_programing%> + <%= f.text_area "description", :class => "w620 hwork_txt h400", :placeholder => "作品描述不能为空", :onkeyup => "regexStudentWorkDescription();", :value => @homework.homework_detail_programing.language == "1" ? c_stantard_code_student : c_stantard_code_student_%> + <% else %> + <%= f.text_area "description", :class => "w620 hwork_txt", :placeholder => "作品描述不能为空", :onkeyup => "regexStudentWorkDescription();"%> + <% end%>

    diff --git a/app/views/tags/_project_tag.html.erb b/app/views/tags/_project_tag.html.erb index ce80e36ab..408f3ba1d 100644 --- a/app/views/tags/_project_tag.html.erb +++ b/app/views/tags/_project_tag.html.erb @@ -1,15 +1,6 @@ -
    - <%= render :partial => "tags/tag_name",:locals => {:obj => obj,:non_list_all => false ,:object_flag => object_flag} %> +
    +
    + <%= render :partial => "tags/tag_project_new_name",:locals => {:obj => obj,:non_list_all => false ,:object_flag => object_flag} %> +
    -<% if User.current.logged?%> - <%= l(:label_add_tag)%> - -<% end%> diff --git a/app/views/tags/_tag_name.html.erb b/app/views/tags/_tag_name.html.erb index cb00ac8d7..7cd7bc02b 100644 --- a/app/views/tags/_tag_name.html.erb +++ b/app/views/tags/_tag_name.html.erb @@ -42,7 +42,7 @@ <% else %>
    - + <%= link_to tag, :controller => "tags", :action => "index", :q => tag, :object_flag => object_flag, :obj_id => obj.id %> <% case object_flag %> diff --git a/app/views/tags/_tag_project_new_name.html.erb b/app/views/tags/_tag_project_new_name.html.erb new file mode 100644 index 000000000..e657071bc --- /dev/null +++ b/app/views/tags/_tag_project_new_name.html.erb @@ -0,0 +1,30 @@ +<% @tags = obj.reload.tag_list %> +<% if non_list_all && @tags.size > 0 %> + +<% else %> + + <% if @tags.size > 0 %> + <% @tags.each do |tag| %> + + <%= link_to tag, :controller => "tags", :action => "index", :q => tag, :object_flag => object_flag, :obj_id => obj.id, :class => 'pt5' %> + + <%= link_to('x', remove_tag_path(:tag_name => tag,:taggable_id => obj.id, :taggable_type => object_flag), :remote => true, :confirm => l(:text_are_you_sure) ) if (ProjectInfo.find_by_project_id(obj.id)).try(:user_id) == User.current.id %> + + + <% end %> + <% end %> +<% end %> + +<% if User.current.logged?%> + <%= l(:label_add_tag)%> + +<% end%> + + diff --git a/app/views/tags/_tag_user_new_name.html.erb b/app/views/tags/_tag_user_new_name.html.erb new file mode 100644 index 000000000..95730c22c --- /dev/null +++ b/app/views/tags/_tag_user_new_name.html.erb @@ -0,0 +1,30 @@ +<% @tags = obj.reload.tag_list %> +<% if non_list_all && @tags.size > 0 %> + +<% else %> + + <% if @tags.size > 0 %> + <% @tags.each do |tag| %> + + <%= link_to tag, :controller => "tags", :action => "index", :q => tag, :object_flag => object_flag, :obj_id => obj.id, :class => 'pt5' %> + + <%= link_to('x', remove_tag_path(:tag_name => tag,:taggable_id => obj.id, :taggable_type => object_flag), :remote => true, :confirm => l(:text_are_you_sure) ) if User.current.eql?(obj) %> + + + <% end %> + <% end %> +<% end %> + +<% if User.current.logged?%> + <%= l(:label_add_tag)%> + +<% end%> + + diff --git a/app/views/tags/_user_tag.html.erb b/app/views/tags/_user_tag.html.erb new file mode 100644 index 000000000..d04fb50a6 --- /dev/null +++ b/app/views/tags/_user_tag.html.erb @@ -0,0 +1,5 @@ +
    +
    + <%= render :partial => "tags/tag_user_new_name",:locals => {:obj => obj,:non_list_all => false ,:object_flag => object_flag} %> +
    +
    diff --git a/app/views/tags/remove_tag.js.erb b/app/views/tags/remove_tag.js.erb index b8c65c13e..4c4409c1c 100644 --- a/app/views/tags/remove_tag.js.erb +++ b/app/views/tags/remove_tag.js.erb @@ -2,6 +2,12 @@ <% if @object_flag == '3'%> $('#tags_show_issue').html('<%= escape_javascript(render :partial => 'tags/tag_name', :locals => {:obj => @obj,:non_list_all => false,:object_flag => @object_flag}) %>'); +<% elsif @object_flag == '1'%> +$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_user_new_name', + :locals => {:obj => @obj,:non_list_all => false,:object_flag => @object_flag}) %>'); +<% elsif @object_flag == '2'%> +$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_project_new_name', + :locals => {:obj => @obj,:non_list_all => false,:object_flag => @object_flag}) %>'); <% elsif @object_flag == '6'%> $("#tags_show-<%=@obj.class%>-<%=@obj.id%>").empty(); $("#tags_show-<%=@obj.class%>-<%=@obj.id%>").html('<%= escape_javascript(render :partial => 'tags/tag_name', diff --git a/app/views/tags/tag_save.js.erb b/app/views/tags/tag_save.js.erb index 74a38c99d..5a29c113c 100644 --- a/app/views/tags/tag_save.js.erb +++ b/app/views/tags/tag_save.js.erb @@ -4,6 +4,14 @@ $('#tags_show_issue').html('<%= escape_javascript(render :partial => 'tags/tag_n :locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>'); //$('#put-tag-form-issue').hide(); $('#name-issue').val(""); +<% elsif @obj_flag == '1'%> +$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_user_new_name', + :locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>'); +$('#tags_name3').val(""); +<% elsif @obj_flag == '2'%> +$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_project_new_name', + :locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>'); +$('#tags_name2').val(""); <% elsif @obj_flag == '6'%> <%if @course%> $("#tags_show-<%=@obj.class%>-<%=@obj.id%>").empty(); diff --git a/app/views/users/_attachment_list.html.erb b/app/views/users/_attachment_list.html.erb new file mode 100644 index 000000000..33e944498 --- /dev/null +++ b/app/views/users/_attachment_list.html.erb @@ -0,0 +1,30 @@ + + + + + 选择文件 +<%= file_field_tag 'attachments[dummy][file]', + :id => '_file', + :class => ie8? ? '':'file_selector', + :multiple => true, + :onchange => 'addInputFiles(this);', + :style => ie8? ? '': 'display:none', + :data => { + :max_file_size => Setting.attachment_max_size.to_i.kilobytes, + :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)), + :max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i, + :upload_path => uploads_path(:format => 'js'), + :description_placeholder => l(:label_optional_description), + :field_is_public => l(:field_is_public), + :are_you_sure => l(:text_are_you_sure), + :file_count => l(:label_file_count), + :delete_all_files => l(:text_are_you_sure_all) + } %> + + + + + + +<%#= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %> + diff --git a/app/views/users/_course_form.html.erb b/app/views/users/_course_form.html.erb index 3a6b317f0..dc277805c 100644 --- a/app/views/users/_course_form.html.erb +++ b/app/views/users/_course_form.html.erb @@ -30,7 +30,10 @@ 学生人数: item.id,:role=>2, :host=>Setting.host_course) %>"><%= studentCount(item) %> 开课学期: - <%= item.time %><%= get_course_term_locales item %> + + <%= item.time %> + <%= get_course_term_locales item %> +
    @@ -39,8 +42,10 @@ 课程结束 <% elsif(can_edit_flag) %> 发布作业 - <% else %> + <% elsif User.current.member_of_course? item %> 提交作品 + <% elsif User.current.logged?%> + <%= link_to "加入课程",try_join_path(:object_id => item.id), :class => "blue_n_btn fr mt20", :remote => "true",:id => "try_join_course_link"%> <% end %>
    \ No newline at end of file diff --git a/app/views/users/_resource_search_form.html.erb b/app/views/users/_resource_search_form.html.erb new file mode 100644 index 000000000..376007fec --- /dev/null +++ b/app/views/users/_resource_search_form.html.erb @@ -0,0 +1,7 @@ +<%= form_tag( url_for(:controller => 'users',:action => 'resource_search',:id=>user.id), + :remote=>true ,:method => 'get',:class=>'resourcesSearchloadBox',:id=>'resource_search_form') do %> + + <%= hidden_field_tag(:type,type) %> + <%= submit_tag '',:class=>'homepageSearchIcon',:onfocus=>'this.blur();',:style=>'border-style:none' %> + +<% end %> \ No newline at end of file diff --git a/app/views/users/_resource_share_for_project_popup.html.erb b/app/views/users/_resource_share_for_project_popup.html.erb new file mode 100644 index 000000000..9cd744c9a --- /dev/null +++ b/app/views/users/_resource_share_for_project_popup.html.erb @@ -0,0 +1,50 @@ + + +
    +
    +
    将资源发送至
    +
    + +
    +
    +
    +
    + <%= form_tag search_user_project_user_path(user),:method => 'get', + :remote=>true,:id=>'search_user_project_form',:class=>'resourcesSearchBox' do %> + <%= hidden_field_tag(:send_id, send_id) %> + <%= hidden_field_tag(:send_ids, send_ids) %> + + + <%= submit_tag '',:class=>'searchIconPopup',:onfocus=>"this.blur();",:style=>'border-style:none' %> + <% end %> +
    + <%= form_tag add_exist_file_to_project_user_path(user),:remote=>true,:id=>'projects_list_form' %> +
    + + <%= hidden_field_tag(:send_id, send_id) %> + <%= hidden_field_tag(:send_ids, send_ids) %> + <% if !projects.empty? %> + <% projects.each do |project| %> +
      +
    • + +
    • +
    • <%= truncate( project.name,:length=>18)%>
    • +
    + <% end %> + +
    +
    +
    + + <%= submit_tag '确定',:class=>'sendSourceText',:onfocus=>'this.blur();' %> +
    + +
    +
    + <% end %> +
    + diff --git a/app/views/users/_resource_share_popup.html.erb b/app/views/users/_resource_share_popup.html.erb new file mode 100644 index 000000000..ea1ada447 --- /dev/null +++ b/app/views/users/_resource_share_popup.html.erb @@ -0,0 +1,50 @@ + + +
    +
    +
    将资源发送至
    +
    + +
    +
    +
    +
    + <%= form_tag search_user_course_user_path(user),:method => 'get', + :remote=>true,:id=>'search_user_course_form',:class=>'resourcesSearchBox' do %> + <%= hidden_field_tag(:send_id, send_id) %> + <%= hidden_field_tag(:send_ids, send_ids) %> + + + <%= submit_tag '',:class=>'searchIconPopup',:onfocus=>"this.blur();",:style=>'border-style:none' %> + <% end %> +
    + <%= form_tag add_exist_file_to_course_user_path(user),:remote=>true,:id=>'course_list_form' %> +
    + + <%= hidden_field_tag(:send_id, send_id) %> + <%= hidden_field_tag(:send_ids, send_ids) %> + <% if !courses.empty? %> + <% courses.each do |course| %> +
      +
    • + +
    • +
    • <%= truncate(course.name,:length=>18)%>
    • +
    + <% end %> + +
    +
    +
    + + <%= submit_tag '确定',:class=>'sendSourceText',:onfocus=>'this.blur();' %> +
    + +
    +
    + <% end %> +
    + diff --git a/app/views/users/_resource_upload_popup.html.erb b/app/views/users/_resource_upload_popup.html.erb new file mode 100644 index 000000000..27eebceec --- /dev/null +++ b/app/views/users/_resource_upload_popup.html.erb @@ -0,0 +1,43 @@ + + + + + +
    上传资源 +
    +
    + +
    +
    (未选择文件)
    +
    您可以上传小于50MB的文件
    +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    + diff --git a/app/views/users/_resources_list.html.erb b/app/views/users/_resources_list.html.erb new file mode 100644 index 000000000..b41b9f28f --- /dev/null +++ b/app/views/users/_resources_list.html.erb @@ -0,0 +1,22 @@ + +<% if attachments.nil? || attachments.empty? %> +<% else %> + <% attachments.each do |attach| %> +
      +
    • + +
    • +
    • + + <%= link_to truncate(attach.filename,:length=>18), download_named_attachment_path(attach.id, attach.filename), + :title => attach.filename,:class=>'resourcesBlack'%> +
    • +
    • <%= number_to_human_size(attach.filesize) %>
    • +
    • <%= get_resource_type(attach.container_type)%>
    • +
    • <%=User.find(attach.author_id).realname.blank? ? User.find(attach.author_id).nickname : User.find(attach.author_id).realname %>
    • +
    • <%= attach.author_id %>
    • +
    • <%= format_date(attach.created_on) %>
    • +
    • <%= attach.id %>
    • +
    + <% end %> +<% end %> diff --git a/app/views/users/_upload_resource.html.erb b/app/views/users/_upload_resource.html.erb new file mode 100644 index 000000000..50807b080 --- /dev/null +++ b/app/views/users/_upload_resource.html.erb @@ -0,0 +1,53 @@ +
    上传资源 +
    +
    + <%= form_tag(user_resource_create_user_path, :multipart => true,:remote => !ie8?,:name=>"upload_form",:id=>'upload_form') do %> +
    + + <% if defined?(container) && container && container.saved_attachments %> + + <% container.attachments.each_with_index do |attachment, i| %> + + <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%> + <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") %> + <%= l(:field_is_public)%>: + <%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false,:class => 'remove-upload')%> + <%= if attachment.id.nil? + #待补充代码 + else + link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') + end + %> + <%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %> + + <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %> + + <% end %> + <% end %> + +
    +
    + + + <%= render :partial => 'attachment_list' %> +
    + + + +
    +
    +
    (未选择文件)
    +
    您可以上传小于50MB的文件
    +
    +
    +
    +
    +
    + + <%= submit_tag '确定',:onclick=>'submit_files();',:onfocus=>'this.blur()',:class=>'sendSourceText' %> +
    + +
    + <% end %> +
    +
    \ No newline at end of file diff --git a/app/views/users/_user_fans_item.html.erb b/app/views/users/_user_fans_item.html.erb index 66181d23b..4ca8fbefc 100644 --- a/app/views/users/_user_fans_item.html.erb +++ b/app/views/users/_user_fans_item.html.erb @@ -1,6 +1,6 @@
    diff --git a/app/views/users/_user_jour_reply.html.erb b/app/views/users/_user_jour_reply.html.erb new file mode 100644 index 000000000..60eda9fcd --- /dev/null +++ b/app/views/users/_user_jour_reply.html.erb @@ -0,0 +1,40 @@ +<% parent_jour = JournalsForMessage.where("id = #{reply.m_reply_id}").first %> +<% if parent_jour%> +
    + <%= link_to image_tag(url_to_avatar(reply.user),:width => '32',:height => '32'), user_path(reply.user),:class => "users_pic_sub fl mr5" %> +
    + <%= link_to "#{reply.user.nickname} ".html_safe, user_path(reply.user),:class => 'course_name fl c_blue02 ', :target => "_blank"%> +  回复  + <%= link_to "#{parent_jour.user.nickname} : ".html_safe, user_path(parent_jour.user),:class => 'course_name fl c_blue02 mr5 ', :target => "_blank"%> +
    + <%= reply.notes.html_safe %> +
    +
    + + <%= time_tag(reply.created_on).html_safe%> + +
    + <%= link_to l(:button_reply),'javascript:void(0);',:nhname=>"sub_reply_btn", :class => "ml5 c_purple" %> + <% if User.current.admin? || reply.user == User.current%> + <%= link_to(l(:label_newfeedback_delete), {:controller => 'words', :action => 'destroy', :object_id => reply, :user_id => reply.user}, + :remote => true, :confirm => l(:text_are_you_sure), :method => 'delete', :class => "c_purple ml5", :title => l(:button_delete)) %> + <% end %> +
    +
    + +
    +
    +<% end%> \ No newline at end of file diff --git a/app/views/users/_user_jours_new.html.erb b/app/views/users/_user_jours_new.html.erb new file mode 100644 index 000000000..0fe301641 --- /dev/null +++ b/app/views/users/_user_jours_new.html.erb @@ -0,0 +1,44 @@ +
    + <%= link_to image_tag(url_to_avatar(jour.user),:width => '46',:height => '46'), user_path(jour.user),:class => "users_pic fl" %> +
    +
    + <%= link_to "#{jour.user.nickname} : ".html_safe, user_path(jour.user),:class => 'fl c_blue02 f14 fb mb5', :target => "_blank"%> +
    +
    +
    + <%= jour.notes.html_safe %> +
    +
    + + <%= time_tag(jour.created_on).html_safe %> + +
    + <%= link_to l(:button_reply),'javascript:void(0);',:nhname=>"reply_btn", :class => "ml5 c_purple" %> + <% if User.current.admin? || jour.user == User.current%> + <%= link_to(l(:label_newfeedback_delete), {:controller => 'words', :action => 'destroy', :object_id => jour, :user_id => jour.user}, + :remote => true, :confirm => l(:text_are_you_sure), :method => 'delete', :class => "ml5 c_purple", :title => l(:button_delete)) %> + <% end %> +
    +
    + +
    + +
    + <% fetch_user_leaveWord_reply(jour).each do |reply|%> + <%= render :partial => 'user_jour_reply', :locals => {:reply => reply} %> + <% end %> +
    +
    \ No newline at end of file diff --git a/app/views/users/_user_show.html.erb b/app/views/users/_user_show.html.erb index 8e3d27666..7cbb20e40 100644 --- a/app/views/users/_user_show.html.erb +++ b/app/views/users/_user_show.html.erb @@ -23,8 +23,19 @@ - <%= l(:label_x_has_fans,:count=>user.watcher_users.count)%> - <%= l(:label_has_watchers,:count=>User.watched_by(user.id).count) %> + <%= l(:label_x_has_fans,:count=>user.watcher_users.count, :remote => true)%> + <%= l(:label_has_watchers,:count=>User.watched_by(user.id).count, :remote => true) %> + <% if User.current.logged?%> + <% if User.current == user%> + 编辑资料 + <%else%> + <%if(user.watched_by?(User.current))%> + 取消关注 + <% else %> + 添加关注 + <% end %> + <% end%> + <% end %> diff --git a/app/views/users/add_exist_file_to_course.js.erb b/app/views/users/add_exist_file_to_course.js.erb new file mode 100644 index 000000000..c5b9f8fbe --- /dev/null +++ b/app/views/users/add_exist_file_to_course.js.erb @@ -0,0 +1,2 @@ +alert('发送成功') +closeModal(); \ No newline at end of file diff --git a/app/views/users/add_exist_file_to_project.js.erb b/app/views/users/add_exist_file_to_project.js.erb new file mode 100644 index 000000000..6ed846821 --- /dev/null +++ b/app/views/users/add_exist_file_to_project.js.erb @@ -0,0 +1,2 @@ +alert('发送成功'); +closeModal(); \ No newline at end of file diff --git a/app/views/users/rename_resource.js.erb b/app/views/users/rename_resource.js.erb new file mode 100644 index 000000000..5556fb313 --- /dev/null +++ b/app/views/users/rename_resource.js.erb @@ -0,0 +1 @@ +alert(1) \ No newline at end of file diff --git a/app/views/users/resource_preview.js.erb b/app/views/users/resource_preview.js.erb new file mode 100644 index 000000000..c3e1fb3ab --- /dev/null +++ b/app/views/users/resource_preview.js.erb @@ -0,0 +1,5 @@ +<% if @preview_able %> +top.location.href = '<%=download_named_attachment_path(@file.id, @file.filename, preview: true) %>' +<% else %> +window.alert('该资源不可预览') +<% end %> \ No newline at end of file diff --git a/app/views/users/resource_search.js.erb b/app/views/users/resource_search.js.erb new file mode 100644 index 000000000..a956ed212 --- /dev/null +++ b/app/views/users/resource_search.js.erb @@ -0,0 +1,2 @@ +$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>'); +$("#pages").html('<%= pagination_links_full @atta_pages, @atta_count, :per_page_links => false, :remote => @is_remote, :flag => true %>'); \ No newline at end of file diff --git a/app/views/users/search_user_course.js.erb b/app/views/users/search_user_course.js.erb new file mode 100644 index 000000000..91002244a --- /dev/null +++ b/app/views/users/search_user_course.js.erb @@ -0,0 +1,11 @@ +//var screenWidth = $(window).width(); +//var screenHeight = $(window).height(); //当前浏览器窗口的 宽高 +//var scrolltop = $(document).scrollTop();//获取当前窗口距离页面顶部高度 +//var objLeft = (screenWidth - 2)/2.5 ; //2 可以根据需要修改 +//var objTop = (screenHeight - 100)/2 + scrolltop; //100可以根据需要修改 +var popupHeight = $(".resourceSharePopup").outerHeight(true); +$(".resourceSharePopup").css("marginTop",-popupHeight/2); + +$("#upload_box").css('left','').css('top',''); +$("#upload_box").html('<%= escape_javascript( render :partial => "resource_share_popup" ,:locals => {:courses=>@course,:user=>@user,:send_id=>@send_id,:send_ids=>@send_ids})%>'); +$("#upload_box").css('display','block'); \ No newline at end of file diff --git a/app/views/users/search_user_project.js.erb b/app/views/users/search_user_project.js.erb new file mode 100644 index 000000000..ee224970f --- /dev/null +++ b/app/views/users/search_user_project.js.erb @@ -0,0 +1,11 @@ +//var screenWidth = $(window).width(); +//var screenHeight = $(window).height(); //当前浏览器窗口的 宽高 +//var scrolltop = $(document).scrollTop();//获取当前窗口距离页面顶部高度 +//var objLeft = (screenWidth - 2)/2.5 ; //2 可以根据需要修改 +//var objTop = (screenHeight - 100)/2 + scrolltop; //100可以根据需要修改 +var popupHeight = $(".resourceSharePopup").outerHeight(true); +$(".resourceSharePopup").css("marginTop",-popupHeight/2); + +$("#upload_box").css('left','').css('top',''); +$("#upload_box").html('<%= escape_javascript( render :partial => "resource_share_for_project_popup" ,:locals => {:projects=>@projects,:user=>@user,:send_id=>@send_id,:send_ids=>@send_ids})%>'); +$("#upload_box").css('display','block'); \ No newline at end of file diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index efe5d0539..b2e6258ee 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,77 +1,23 @@ - -<%= javascript_include_tag "/assets/kindeditor/kindeditor",'/assets/kindeditor/pasteimg' %> +<%= javascript_include_tag "/assets/kindeditor/kindeditor",'/assets/kindeditor/pasteimg',"user" %> <% @center_flag = (User.current == @user) %> -<% if @center_flag %>
    <% if @user.allowed_to?(:add_project, nil, :global => true) %> 新建项目 <% else %> - 加入项目 + 加入项目 <% end %> <% if @user.user_extensions.identity == 0 && @user.allowed_to?(:add_course, nil, :global => true) %> - 新建课程 + 新建课程 <% else %> - 加入课程 + 加入课程 <% end %>
    -<% end %>
    -
    -
    -
    - -

    -
    - 取消 - 留言 -
    -
    -
    - - -
    - - <% if !@center_flag %> - - <% end %>
    - <% if !@center_flag %> - - <% end %> -
    - - diff --git a/app/views/users/user_course_activities.html.erb b/app/views/users/user_course_activities.html.erb index bdebee6a5..ed5b66ed4 100644 --- a/app/views/users/user_course_activities.html.erb +++ b/app/views/users/user_course_activities.html.erb @@ -10,10 +10,19 @@ <%= rec[:item].user.show_name %> <%= get_activity_opt(rec[:item],rec[:e]) %> - - <%= get_activity_act_showname_htmlclear(rec[:item]) %> - + <% if(( rec[:e].is_public == false || rec[:e].is_public == 0 )&& !rec[:e].visible?)%> + + <%= get_activity_act_showname_htmlclear(rec[:item]) %> + + <% else %> + + <%= get_activity_act_showname_htmlclear(rec[:item]) %> + + <% end %> + <%= time_tag(get_activity_act_createtime(rec[:item])).html_safe %>
    <% end %> \ No newline at end of file diff --git a/app/views/users/user_courses.html.erb b/app/views/users/user_courses.html.erb index 36e061efa..769642e99 100644 --- a/app/views/users/user_courses.html.erb +++ b/app/views/users/user_courses.html.erb @@ -2,8 +2,6 @@ <% if @user.user_extensions.identity == 0 && @user.allowed_to?(:add_course, nil, :global => true) %> 新建课程 - <% else %> - 加入课程 <% end %>
    @@ -13,9 +11,9 @@ diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb new file mode 100644 index 000000000..a74e1800f --- /dev/null +++ b/app/views/users/user_messages.html.erb @@ -0,0 +1,254 @@ +
    +
    + +
    +
    消息
    + +
    + +
    +<% if @new_message_count >0 %> + <%# 课程消息 %> + <% unless @user_course_messages.nil? %> + <% @user_course_messages.each do |ucm| %> + <% if ucm.course_message_type == "News" %> + + <% end %> + <% if ucm.course_message_type == "Comment" %> + + <% end %> + <% if ucm.course_message_type == "HomeworkCommon" %> + + <% end %> + <% if ucm.course_message_type == "Poll" %> + + <% end %> + <% if ucm.course_message_type == "Message" %> + + <% end %> + <% if ucm.course_message_type == "StudentWorksScore" %> + + <% end %> + <% if ucm.course_message_type == "JournalsForMessage" %> + + <% end %> +
    + <% end %> + <% end %> + + <% unless @user_forge_messages.nil? %> + <% @user_forge_messages.each do |ufm| %> + <% if ufm.forge_message_type == "Issue" %> + + <% end %> + <% if ufm.forge_message_type == "Journal" %> + + <% end %> + <% if ufm.forge_message_type == "Message" %> + + <% end %> + <% if ufm.forge_message_type == "News" %> + + <% end %> + <% if ufm.forge_message_type == "Comment" %> + + <% end %> + <% end %> + <% end %> + <%# 公共贴吧 %> + <% unless @user_memo_messages.nil? %> + <% @user_memo_messages.each do |urm| %> + <% if urm.memo_type == "Memo" %> + + <% end %> + <% end %> + <% end %> + <%# 用户留言消息 %> + <% unless @user_feedback_messages.nil? %> + <% @user_feedback_messages.each do |ufm| %> + <% if ufm.journals_for_message_type == "Principal" %> + + <% end %> + <% end %> + <% end %> +<% else %> +
    暂无消息!
    +<% end %> +
    +
    + +
    diff --git a/app/views/users/user_newfeedback.html.erb b/app/views/users/user_newfeedback.html.erb index deb360efd..a8107ce5f 100644 --- a/app/views/users/user_newfeedback.html.erb +++ b/app/views/users/user_newfeedback.html.erb @@ -1,7 +1,40 @@ -<% reply_allow = JournalsForMessage.create_by_user? User.current %> -<%= stylesheet_link_tag 'css', :media => 'all' %> +
    + + <% if @user.user_extensions.identity == 0 && @user.allowed_to?(:add_course, nil, :global => true) %> + 新建课程 + <% end %> +
    +
    -<%= render :partial => 'user_jours', - :locals => { :journals => @jour, :state => false} -%> -<% html_title(l(:label_responses)) -%> \ No newline at end of file +<%= javascript_include_tag "/assets/kindeditor/kindeditor",'/assets/kindeditor/pasteimg',"user" %> +
    + + + +
    +
    + <%= form_for('new_form',:url => leave_user_message_path(@user.id),:method => "post") do |f|%> + +

    +
    + 取消 + 留言 + <% end%> +
    +
    + +
    + <%if @jour%> + <% @jour.each do |jour|%> + <%= render :partial => 'user_jours_new', :locals => {:jour => jour} %> + <%end%> + <% end%> + +
      + <%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%> +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/app/views/users/user_projects.html.erb b/app/views/users/user_projects.html.erb index e7eeedb29..d76964020 100644 --- a/app/views/users/user_projects.html.erb +++ b/app/views/users/user_projects.html.erb @@ -2,8 +2,6 @@ <% if @user.allowed_to?(:add_project, nil, :global => true) %> 新建项目 - <% else %> - 加入项目 <% end %>
  • @@ -13,9 +11,16 @@ @@ -43,7 +48,16 @@ - item.id, :host=>Setting.host_name) %>" target="_blank" class="blue_n_btn fr mt20">发布问题 + <% if User.current.member_of? item%> + item.id, :host=>Setting.host_name) %>" target="_blank" class="blue_n_btn fr mt20">发布问题 + <% elsif User.current.logged?%> + <% if item.applied_projects.find_by_user_id(User.current.id)%> + <%= link_to '取消申请',appliedproject_applied_path(:project_id => item.id,:user_id => User.current.id),:class => "blue_n_btn fr mt20", :remote => "true",:method => "delete",:id => "applied_project_link_#{item.id}"%> + <% else%> + <%= link_to "加入项目",appliedproject_path(:user_id => User.current.id,:project_id => item.id,:project_join => true),:class => "blue_n_btn fr mt20", :remote => "true",:method => "post",:id => "applied_project_link_#{item.id}" %> + <% end%> + + <% end%>
    <% end %> diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb new file mode 100644 index 000000000..3c4ea18ca --- /dev/null +++ b/app/views/users/user_resource.html.erb @@ -0,0 +1,452 @@ + +<%= javascript_include_tag 'bootstrap'%> +<%= stylesheet_link_tag 'project' %> +<%= stylesheet_link_tag 'leftside' %> +<%= javascript_include_tag 'attachments'%> + + + + + + +
    +
    +
    资源库
    +
      +
    • +
        +
      • + <%= link_to '全部' ,user_resource_user_path(:id=>@user.id,:type=>1),:remote=>true,:method => 'get',:class=>'resourcesTypeAll resourcesGrey' %> +
      • +
      • + <%= link_to '课程资源' ,user_resource_user_path(:id=>@user.id,:type=>2),:remote=>true,:method => 'get',:class=>'homepagePostTypeAssignment postTypeGrey' %> +
      • +
      • + <%= link_to '项目资源' ,user_resource_user_path(:id=>@user.id,:type=>3),:remote=>true,:method => 'get',:class=>'homepagePostTypeQuiz postTypeGrey' %> +
      • +
      • + <%= link_to '附件' ,user_resource_user_path(:id=>@user.id,:type=>4),:remote=>true,:method => 'get',:class=>'resourcesTypeAtt resourcesGrey' %> +
      • +
      +
    • +
    +
    +
    + +
    + <%= render :partial => 'resource_search_form',:locals => {:user=>@user,:type=>@type} %> +
    +
    +
    +
      +
    • +
    • 资源名称
    • +
    • 大小
    • +
    • 类别
    • +
    • 上传者
    • +
    • 上传时间
    • +
    +
    +
    +
    + + <%= render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments} %> + +
    +
    +
    + +
    + 全选 + 删除 +
    +
    选择 0 个资源
    +
    + 发送 +
    +
    +
    +
    +
    +
    +
      + <%= pagination_links_full @atta_pages, @atta_count, :per_page_links => false, :remote => @is_remote, :flag => true%> +
    +
    +
    + + + + + diff --git a/app/views/users/user_resource.js.erb b/app/views/users/user_resource.js.erb new file mode 100644 index 000000000..551c08907 --- /dev/null +++ b/app/views/users/user_resource.js.erb @@ -0,0 +1,3 @@ +$("#search_div").html('<%= escape_javascript( render :partial => 'resource_search_form',:locals => {:user=>@user,:type=>@type} ) %>'); +$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>'); +$("#pages").html('<%= pagination_links_full @atta_pages, @atta_count, :per_page_links => false, :remote => @is_remote, :flag => true %>'); \ No newline at end of file diff --git a/app/views/users/user_resource_create.js.erb b/app/views/users/user_resource_create.js.erb new file mode 100644 index 000000000..16ec4d82a --- /dev/null +++ b/app/views/users/user_resource_create.js.erb @@ -0,0 +1,5 @@ + +closeModal(); +$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>'); + +$("#pages").html('<%= pagination_links_full @atta_pages, @atta_count, :per_page_links => false, :remote => @is_remote, :flag => true %>'); \ No newline at end of file diff --git a/app/views/users/user_resource_delete.js.erb b/app/views/users/user_resource_delete.js.erb new file mode 100644 index 000000000..a956ed212 --- /dev/null +++ b/app/views/users/user_resource_delete.js.erb @@ -0,0 +1,2 @@ +$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>'); +$("#pages").html('<%= pagination_links_full @atta_pages, @atta_count, :per_page_links => false, :remote => @is_remote, :flag => true %>'); \ No newline at end of file diff --git a/app/views/versions/_form.html.erb b/app/views/versions/_form.html.erb index f0ed7c84f..6ff8b070f 100644 --- a/app/views/versions/_form.html.erb +++ b/app/views/versions/_form.html.erb @@ -14,20 +14,20 @@ <%= f.select :status, Version::VERSION_STATUSES.collect {|s| [l("version_status_#{s}"), s]}, :label => "" %> -
  • - - <%= f.text_field :wiki_page_title, :size =>60, :label => "", :disabled => @project.wiki.nil? %> -
  • + + + +
  • <%= f.text_field :effective_date, :size => 10, :readonly => true,:class=>"fl" ,:style=>"margin-left:7px;",:label=>""%> <%= calendar_for('version_effective_date') %>
  • -
  • - - <%= f.select :sharing, @version.allowed_sharings.collect {|v| [format_version_sharing(v), v]},:label=>"" %> -
  • + + + + <% @version.custom_field_values.each do |value| %> diff --git a/app/views/versions/_overview.html.erb b/app/views/versions/_overview.html.erb index 47d65c34a..8d34a20da 100644 --- a/app/views/versions/_overview.html.erb +++ b/app/views/versions/_overview.html.erb @@ -13,5 +13,5 @@ project_issues_path(version.project, :status_id => 'o', :fixed_version_id => version, :set_filter => 1), :class =>"c_dblue") %>)

    <% else %> -

    <%= l(:label_roadmap_no_issues) %>

    +
    <%= l(:label_roadmap_no_issues) %>
    <% end %> diff --git a/app/views/versions/show.html.erb b/app/views/versions/show.html.erb index 1a7fce16d..6bfacbe86 100644 --- a/app/views/versions/show.html.erb +++ b/app/views/versions/show.html.erb @@ -4,7 +4,7 @@
    <%= link_to(l(:button_edit), edit_version_path(@version), :class => 'icon icon-edit') if User.current.allowed_to?(:manage_versions, @version.project) %> -<%= link_to_if_authorized(l(:button_edit_associated_wikipage, +<%#= link_to_if_authorized(l(:button_edit_associated_wikipage, :page_title => @version.wiki_page_title.truncate(30, omission: '...')), {:controller => 'wiki', :action => 'edit', @@ -17,7 +17,7 @@ <%= call_hook(:view_versions_show_contextual, { :version => @version, :project => @project }) %>
    -

    +

    <%= h(@version.name) %>

    @@ -27,11 +27,11 @@
    <% if @version.estimated_hours > 0 || User.current.allowed_to?(:view_time_entries, @project) %> -
    <%= l(:label_time_tracking) %> +
    <%= l(:label_time_tracking) %> ","
    -

    <%= l(:field_estimated_hours) %>:

    +

    <%= l(:field_estimated_hours) %>:

    <%= html_hours(l_hours(@version.estimated_hours)) %> @@ -40,7 +40,7 @@ <% if User.current.allowed_to?(:view_time_entries, @project) %>
    -

    <%= l(:label_spent_time) %>:

    +

    <%= l(:label_spent_time) %>:

    <%= html_hours(l_hours(@version.spent_hours)) %> diff --git a/app/views/welcome/course.html.erb b/app/views/welcome/course.html.erb index 143c32dbe..4edec2202 100644 --- a/app/views/welcome/course.html.erb +++ b/app/views/welcome/course.html.erb @@ -56,21 +56,11 @@ <% end %> - - <%= l(:label_welcome_trustie_course) %> + <%= l(:label_welcome_trustie_course) %> <% else %> <% unless @course_page.nil? %> - <%= l(:label_welcome_trustie_course) %> , @@ -112,7 +102,6 @@ course_term = "春季学期" end %> - <%# (month_now >= 3 && month_now < 9) ? course_term = "春季学期" : course_term = "秋季学期" %> <% cur_school_course = @school_id.nil? ? [] : find_miracle_course(10,7,@school_id, year_now, course_term) %> <% if cur_school_course.count == 0 %> diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb index c03b0de76..816d6550a 100644 --- a/app/views/welcome/index.html.erb +++ b/app/views/welcome/index.html.erb @@ -45,10 +45,10 @@ <% if @organization.nil? %> <% unless @first_page.nil? %> - <%= l(:label_welcome_trustie_project)%>,  - <%= l(:label_welcome_trustie_project_description)%> + + <%= @first_page.description.html_safe %> <% end %> <% else %> diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb index 28fab1243..c58f42dea 100644 --- a/app/views/wiki/show.html.erb +++ b/app/views/wiki/show.html.erb @@ -74,11 +74,11 @@ <% end %>

    -<% other_formats_links do |f| %> - <%= f.link_to 'PDF', :url => {:id => @page.title, :version => params[:version]} %> - <%= f.link_to 'HTML', :url => {:id => @page.title, :version => params[:version]} %> - <%= f.link_to 'TXT', :url => {:id => @page.title, :version => params[:version]} %> -<% end if User.current.allowed_to?(:export_wiki_pages, @project) %> +<%# other_formats_links do |f| %> + <%#= f.link_to 'PDF', :url => {:id => @page.title, :version => params[:version]} %> + <%#= f.link_to 'HTML', :url => {:id => @page.title, :version => params[:version]} %> + <%#= f.link_to 'TXT', :url => {:id => @page.title, :version => params[:version]} %> +<%# end if User.current.allowed_to?(:export_wiki_pages, @project) %> <% content_for :sidebar do %> <%= render :partial => 'sidebar' %> <% end %> diff --git a/app/views/words/create_reply.js.erb b/app/views/words/create_reply.js.erb index 8e57d7b0e..6aad1bfb5 100644 --- a/app/views/words/create_reply.js.erb +++ b/app/views/words/create_reply.js.erb @@ -1,11 +1,10 @@ <% if @save_succ %> <% if !@jfm.nil? && @jfm.jour_type == 'Principal' %> - var html = $("
    "+"<%= escape_javascript( render(:template => 'users/user_feedback4show',:locals => {:feed_list=>[@jfm]} )) %>"+"
    "); - $("div[nhname='container']",$("#nh_messages")).prepend(html.html()); -// $('#new_message_cancel_btn').click(); - $("a[nhname='reply_btn']",$("#nh_jours_<%= @jfm.m_reply_id %>")).click(); - var params = init_list_more_div_params($("#nh_messages")); - change_status_4_list_more_div(params); + $("#<%= @jfm.m_parent_id%>").children("div[nhname='reply_list']").prepend("<%= escape_javascript( render(:partial => 'users/user_jour_reply',:locals => {:reply=>@jfm} )) %>"); + div_1 = $("#<%= @jfm.m_reply_id%>").children("div[nhname='div_form']"); + div_1.hide(); + div_2 = $("#<%= @jfm.m_reply_id%>").children("div[nhname='sub_div_form']"); + div_2.hide(); <% else %> var pre_append = $('<%= j( diff --git a/app/views/words/destroy.js.erb b/app/views/words/destroy.js.erb index 92e15ab93..c138a7ea7 100644 --- a/app/views/words/destroy.js.erb +++ b/app/views/words/destroy.js.erb @@ -2,9 +2,10 @@ alert('<%=l(:notice_failed_delete)%>'); <% elsif (['Principal','Project','Course', 'Bid', 'Contest', 'Softapplication'].include? @journal_destroyed.jour_type)%> <% if @is_user%> - $("#nh_jours_<%= @journal_destroyed.id %>",$("div[nhname='container']",$("#nh_messages"))).remove(); - var params = init_list_more_div_params($("#nh_messages")); - change_status_4_list_more_div(params); + var destroyedItem = $('#<%=@journal_destroyed.id%>'); + destroyedItem.fadeOut(600,function(){ + destroyedItem.remove(); + }); <% else %> <% if @bid && @jours_count %> $('#jours_count').html("<%= @jours_count %>"); diff --git a/config/environments/development.rb b/config/environments/development.rb index 2aca152cb..a3e7dff99 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -7,6 +7,7 @@ RedmineApp::Application.configure do # Log error messages when you accidentally call methods on nil. config.whiny_nils = true + config.log_level =:debug config.logger = Logger.new('log/development.log', 'daily') # daily, weekly or monthly # Show full error reports and disable caching config.consider_all_requests_local = true diff --git a/config/locales/account/zh.yml b/config/locales/account/zh.yml index 69edc7aa3..c7c76707d 100644 --- a/config/locales/account/zh.yml +++ b/config/locales/account/zh.yml @@ -37,7 +37,7 @@ zh: label_password_lost: "忘记密码?" button_login: 登录 # account_controller中判断用户名或密码输入有误的提示信息 - notice_account_invalid_creditentials: "无效的用户名或密码" + notice_account_invalid_creditentials: "无效的用户名或密码,注意登录名区分大小写,谢谢!" # account_controller中判断未激活的提示信息 notice_account_invalid_creditentials_new: "您还未到邮箱激活。如果您丢失帐户,电子邮件验证帮助我们的支持团队验证帐户的所有权,并允许您接收所有您要求的通知。" diff --git a/config/locales/my/zh.yml b/config/locales/my/zh.yml index 4220aceca..25a949df4 100644 --- a/config/locales/my/zh.yml +++ b/config/locales/my/zh.yml @@ -33,7 +33,6 @@ zh: label_account_identity_studentID: 请输入学号 field_brief_introduction_my: 个人签名 - field_description: 个人简介 field_is_required: 必填 field_firstname: 名字或组织名 firstname_empty: 名字不能为空 diff --git a/config/locales/projects/en.yml b/config/locales/projects/en.yml index b142c6ca8..703e0878e 100644 --- a/config/locales/projects/en.yml +++ b/config/locales/projects/en.yml @@ -42,10 +42,10 @@ en: label_member: "Members" project_module_attachments: "Resources" - label_project_mail_attachments: Project Resources - label_project_mail_upload: had uploaded project resources + label_project_mail_attachments: "Project Resources" + label_project_mail_upload: "had uploaded project resources" - label_invite: Invitation + label_invite: "Invitation" label_invite_new_user: "Send email to invite new user" label_invite_trustie_user: "Invite the Trustie registered user" diff --git a/config/locales/projects/zh.yml b/config/locales/projects/zh.yml index 3ba438c0a..fe26aee1d 100644 --- a/config/locales/projects/zh.yml +++ b/config/locales/projects/zh.yml @@ -67,6 +67,13 @@ zh: label_project_mail_upload: 上传了资源 label_invite: 邀请 + + # 项目消息通知 + label_forge_message: 消息 + label_issue_message: 问题 + label_course_message: 课程消息 + label_project_message: 项目消息 + label_issue_tracking: 问题跟踪 label_release_issue: 发布问题 @@ -90,8 +97,13 @@ zh: label_project_tool_response: 用户反馈 label_project_news: 项目新闻 - label_project_dts_new: DTS测试 + label_project_dts_new: DTS缺陷测试 label_project_dts_statics: DTS缺陷报告 + label_project_dts_yun: 云化部署工具 + label_project_soft_knowledge: 软件知识库 + label_project_soft_file: 软件资源库 + label_project_online_dev: 在线开发平台 + label_project_soft_service: 软工服务平台 label_project_overview: "项目简介" label_expend_information: 展开更多信息 @@ -345,7 +357,7 @@ zh: label_input_email: 请输入邮箱地址 label_invite_trustie_user: "邀请Trustie注册用户" - label_invite_trustie_user_tips: "输入姓名、邮箱、昵称" + label_invite_trustie_user_tips: "支持姓名、邮箱、昵称搜索!" label_user_role_null: 用户和角色不能留空! label_invite_project: 邀请您加入项目 label_mail_invite_success: 您已成功加入项目! @@ -358,7 +370,6 @@ zh: # label_project_new_description: '项目可以是软件开发项目,也可以是协作研究项目。' field_name: 名称 - field_description: 描述 field_identifier: 标识 field_enterprise_name: 组织名称 label_organization_choose: --请选择组织-- diff --git a/config/locales/zh.yml b/config/locales/zh.yml index b2faa6319..c2c558cf5 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -381,6 +381,7 @@ zh: label_organization_choose: --请选择组织-- label_organization_name: 组织名称 label_organization_list: 组织列表 + label_school_plural: 学校列表 label_organization_new: 新建组织 label_organization_edit: 修改组织 label_project_plural: 项目列表 @@ -551,6 +552,7 @@ zh: label_registered_on: 注册于 label_overall_activity: 活动概览 label_new: 新建 + label_latest_login_user_list: 最近登录用户列表 label_logged_as: 登录为 label_environment: 环境 @@ -669,6 +671,8 @@ zh: label_tag: 标签 label_revision: 修订 label_revision_plural: 修订 + lable_revision_code_count: 代码量 + label_revision_commit_count: 提交次数 label_revision_id: 修订 %{value} label_associated_revisions: 相关修订版本 label_added: 已添加 @@ -687,7 +691,7 @@ zh: label_sort_lowest: 置底 label_roadmap_due_in: "截止日期到 %{value}" label_roadmap_overdue: "%{value} 延期" - label_roadmap_no_issues: 该版本没有问题 + label_roadmap_no_issues: 该版本还没有对应的缺陷,可以在“发布问题”的“目标版本”中指定版本! label_user_search_type: 搜索类型 label_search_by_login: 登录名 label_search_by_name: 名字 @@ -715,6 +719,11 @@ zh: label_commits_per_month: 每月提交次数 label_commits_per_author: 每用户提交次数 + label_author_commits_per_month: 用户最近一月的提交次数 + label_author_commits_six_month: 用户最近六个月提交次数 + label_author_commits_year: 最近一年的提交次数 + label_author_code_six_month: 用户最近六个月代码量 + label_author_code_year: 用户最近一年代码量 label_view_diff: 查看差别 label_diff_inline: 直列 label_diff_side_by_side: 并排 @@ -1244,6 +1253,7 @@ zh: label_leave_message_to: 给用户 %{name}留言 label_leave_message: 留言内容 label_message: 留言板 + label_leave_message_list: 留言列表 field_add: 添加于 %{time} 之前 label_student_response: 作业答疑 # modified by bai @@ -1740,6 +1750,7 @@ zh: cancel_apply: 取消申请 apply_master: 申请成为版主 you_are_master: 您是该项目的版主 + label_notification_list: 通知 #add by linchun (竞赛相关) label_upload_softwarepackage: 上传软件包 @@ -1835,6 +1846,7 @@ zh: excel_t_score: 教师评分 excel_ta_score: 教辅评分 excel_n_score: 匿名评分 + excel_s_score: 系统评分 excel_f_score: 成绩 excel_commit_time: 提交时间 excel_homework_score: 作业积分 @@ -2049,5 +2061,22 @@ zh: lable_unset: 未设置 label_chose_group: 请选择分班 +# label_hosted_organization: 主办单位 +# label_hosted_by: 国防科学技术大学并行与分布处理国家重点实验室 +# label_sponsor: 计算机科学与技术系 +# label_partners: 合作单位 +# label_co_organizer_NUDT: 国防科学技术大学计算机学院 +# label_co_organizer_EECS: 北京大学 +# label_co_organizer_BHU: 北京航空航天大学 +# label_co_organizer_CAS: 中国科学院软件研究所 +# label_co_organizer_InforS: 中创软件 +# label_rights_reserved: Copyright 2007~2015, All Rights Riserved +# label_about_us: 关于我们 +# label_contact_us: 联系我们 +# label_recruitment_information: 招聘信息 +# label_surpport_group: 帮助中心 +# label_forums: 论坛反馈 +# label_language: 语言 +# label_license: 湘ICP备09019772 diff --git a/config/routes.rb b/config/routes.rb index ef88e1c26..cdc9eec14 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -39,6 +39,17 @@ RedmineApp::Application.routes.draw do end + resources :school do + collection do + + end + + member do + get 'upload_logo' + post 'upload' + end + end + resources :homework_attach do collection do get 'get_homework_member_list' @@ -71,10 +82,14 @@ RedmineApp::Application.routes.draw do get 'poll_result' get 'close_poll' get 'export_poll' + get 'import_poll' + end collection do delete 'delete_poll_question' post 'update_poll_question' + get 'other_poll' + post 'import_other_poll' end end @@ -86,6 +101,7 @@ RedmineApp::Application.routes.draw do end collection do post 'next_step' + post 'programing_test' end end @@ -293,7 +309,7 @@ RedmineApp::Application.routes.draw do match 'user_projects_index', :to => 'users#user_projects_index', :via => :get match 'user_projects', :to => 'users#user_projects', :via => :get match 'user_activities', :to => 'users#user_activities', :via => :get, :as => "user_activities" - match 'user_newfeedback', :to => 'users#user_newfeedback', :via => :get, :as => "user_newfeedback" + # match 'user_newfeedback', :to => 'users#user_newfeedback', :via => :get, :as => "user_newfeedback" match 'info', :to => 'users#info', :via => [:get , :post], :as => 'user_info' match 'user_watchlist', :to => 'users#user_watchlist', :via => :get, :as => "user_watchlist" #add by huang match 'user_fanslist', :to => 'users#user_fanslist', :via => :get, :as => "user_fanslist" #add by huang @@ -306,6 +322,7 @@ RedmineApp::Application.routes.draw do match 'user_visitorlist', :to => 'users#user_visitorlist', :via => :get match 'user_homeworks', :to => 'users#user_homeworks', :via => :get match 'watch_projects', :to => 'users#watch_projects', :via => :get + # added by bai match 'show_score', :to => 'users#show_score', :via => :get match 'topic_score_index', :to => 'users#topic_score_index', :via => [:get, :post] @@ -328,11 +345,24 @@ RedmineApp::Application.routes.draw do match 'file_score_index', :to => 'projects#file_score_index', :via => [:get, :post] match 'code_submit_score_index', :to => 'projects#code_submit_score_index', :via => [:get, :post] match 'projects_topic_score_index', :to => 'projects#projects_topic_score_index', :via => [:get, :post] + get "user_resource" + get "resource_search" + post "user_resource_create" + post "user_resource_delete" + get "search_user_course" + post "add_exist_file_to_course" + post "add_exist_file_to_project" + get 'resource_preview' + post 'rename_resource' + get 'search_user_project' # end end end match 'users/:id/user_newfeedback', :to => 'users#user_newfeedback', :via => :get, :as => "feedback" match 'users/:id/user_projects', :to => 'users#user_projects', :via => :get + match 'users/:id/user_messages', :to => 'users#user_messages', :via => :get + + #end match 'my/account', :via => [:get, :post] @@ -385,11 +415,12 @@ RedmineApp::Application.routes.draw do get 'feedback', :action => 'feedback', :as => 'project_feedback' get 'watcherlist', :action=> 'watcherlist' - get 'dts_rep', :action=> 'dts_rep' + get 'invite_members', :action=> 'invite_members' get 'invite_members_by_mail', :action=> 'invite_members_by_mail' + # get 'dts_repos', :aciton => 'dts_repos' get 'send_mail_to_member', :action => 'send_mail_to_member' - match 'user_watcherlist', :to => 'projects#watcherlist', :via => :get, :as => "watcherlist" #add by huang + match 'user_watcherlist', :to => 'projects#watcherlist', :via => :get, :as => "watcherlist" #end post 'modules' post 'archive' @@ -661,6 +692,14 @@ RedmineApp::Application.routes.draw do match 'admin/test_email', :via => :get match 'admin/default_configuration', :via => :post get 'admin/organization' + get 'admin/schools' + get 'admin/leave_messages' + match 'admin/messages_list', as: :messages_list + match 'admin/project_messages', as: :project_messages + match'admin/course_messages', as: :course_messages + get 'admin/notices' + get 'admin/latest_login_users' + get 'admin/homework' resources :auth_sources do member do @@ -770,6 +809,7 @@ RedmineApp::Application.routes.draw do match 'words/:id/leave_project_message', :to => 'words#leave_project_message' match 'projects/:id/feedback', :to => 'projects#feedback', :via => :get, :as => 'project_feedback' match 'project/:id/share', :to => 'projects#share', :as => 'share_show' #share + post 'words/:id/leave_user_message', :to => 'words#leave_user_message', :as => "leave_user_message" post 'join_in/join', :to => 'courses#join', :as => 'join' delete 'join_in/join', :to => 'courses#unjoin' @@ -799,9 +839,6 @@ RedmineApp::Application.routes.draw do post 'school/search_school/', :to => 'school#search_school' get 'school/search_school/', :to => 'school#search_school' - post 'school/upload', :to => 'school#upload' - get 'school/upload_logo', :to => 'school#upload_logo' - ######added by nie match 'tags/show_projects_tags' ########### added by liuping @@ -825,6 +862,7 @@ RedmineApp::Application.routes.draw do match 'system_log/clear' ##ended by lizanle + resources :git_callback do collection do post 'post_update' diff --git a/db/migrate/20150722015428_add_errormsg_to_studen_work_test.rb b/db/migrate/20150722015428_add_errormsg_to_studen_work_test.rb new file mode 100644 index 000000000..dc973e142 --- /dev/null +++ b/db/migrate/20150722015428_add_errormsg_to_studen_work_test.rb @@ -0,0 +1,9 @@ +class AddErrormsgToStudenWorkTest < ActiveRecord::Migration + def up + add_column :student_work_tests,:error_msg,:text + end + + def down + remove_column :student_work_tests,:error_msg + end +end diff --git a/db/migrate/20150730093403_add_result_to_test.rb b/db/migrate/20150730093403_add_result_to_test.rb new file mode 100644 index 000000000..8494fbbf5 --- /dev/null +++ b/db/migrate/20150730093403_add_result_to_test.rb @@ -0,0 +1,9 @@ +class AddResultToTest < ActiveRecord::Migration + def up + add_column :homework_tests, :result, :integer,default: 0 + end + + def down + remove_column :homework_tests,:result + end +end diff --git a/db/migrate/20150730130816_add_errormsg_to_test.rb b/db/migrate/20150730130816_add_errormsg_to_test.rb new file mode 100644 index 000000000..31b1b2246 --- /dev/null +++ b/db/migrate/20150730130816_add_errormsg_to_test.rb @@ -0,0 +1,9 @@ +class AddErrormsgToTest < ActiveRecord::Migration + def up + add_column :homework_tests,:error_msg,:text + end + + def down + remove_column :homework_tests,:error_msg + end +end diff --git a/db/migrate/20150801034945_change_result_default.rb b/db/migrate/20150801034945_change_result_default.rb new file mode 100644 index 000000000..1f629aa45 --- /dev/null +++ b/db/migrate/20150801034945_change_result_default.rb @@ -0,0 +1,9 @@ +class ChangeResultDefault < ActiveRecord::Migration + def up + change_column :homework_tests,:result,:integer,:default => nil + end + + def down + change_column :homework_tests,:result,:integer,:default => 0 + end +end diff --git a/db/migrate/20150810064247_add_created_at_to_activities.rb b/db/migrate/20150810064247_add_created_at_to_activities.rb new file mode 100644 index 000000000..864ed82d6 --- /dev/null +++ b/db/migrate/20150810064247_add_created_at_to_activities.rb @@ -0,0 +1,8 @@ +class AddCreatedAtToActivities < ActiveRecord::Migration + def up + add_column :activities, :created_at, :timestamp + end + def end + remove_column :activities, :created_at + end +end diff --git a/db/migrate/20150811010817_update_activities_data.rb b/db/migrate/20150811010817_update_activities_data.rb new file mode 100644 index 000000000..7ed19a607 --- /dev/null +++ b/db/migrate/20150811010817_update_activities_data.rb @@ -0,0 +1,21 @@ +class UpdateActivitiesData < ActiveRecord::Migration + def up + count = Activity.all.count / 20 + 1 + transaction do + for i in 1 ... count do i + Activity.page(i).per(20).each do |activity| + type = activity.act_type + if type=='Contest' || type=='Message' || type=='News'|| type=='Journal'|| type=='Issue'|| type=='Principal'||type=='JournalsForMessage' + activity.created_at = activity.act.created_on if activity.act + elsif type=='Contestnotification' || type=='HomeworkCommon' || type=='Poll' + activity.created_at = activity.act.created_at if activity.act + end + activity.save + end + end + end + end + + def down + end +end diff --git a/db/migrate/20150811065543_add_course_activities.rb b/db/migrate/20150811065543_add_course_activities.rb new file mode 100644 index 000000000..03ec7e354 --- /dev/null +++ b/db/migrate/20150811065543_add_course_activities.rb @@ -0,0 +1,15 @@ +class AddCourseActivities < ActiveRecord::Migration + def up + create_table :course_activities do |t| + t.integer :user_id + t.integer :course_id + t.integer :course_act_id + t.string :course_act_type + t.timestamps + end + end + + def down + drop_table :course_activities + end +end diff --git a/db/migrate/20150811080754_course_activities.rb b/db/migrate/20150811080754_course_activities.rb new file mode 100644 index 000000000..a4cae915d --- /dev/null +++ b/db/migrate/20150811080754_course_activities.rb @@ -0,0 +1,40 @@ +#encoding=UTF-8 +class CourseActivities < ActiveRecord::Migration + def up + Course.all.each do |course| + transaction do + course.course_acts << CourseActivity.new(:user_id => course.tea_id,:course_id => course.id) + #作业 + course.homework_commons.each do |homework_common| + homework_common.course_acts << CourseActivity.new(:user_id => homework_common.user_id,:course_id => course.id) + end + #通知 + course.news.each do |new| + new.course_acts << CourseActivity.new(:user_id => new.author_id,:course_id => course.id) + end + #资源 + course.attachments.each do |attachment| + attachment.course_acts << CourseActivity.new(:user_id => attachment.author_id,:course_id => course.id) + end + #讨论区 + if course.boards.first + course.boards.first.messages.each do |message| + message.course_acts << CourseActivity.new(:user_id => message.author_id,:course_id => course.id) + end + end + #留言 + course.journals_for_messages.each do |jour| + jour.course_acts << CourseActivity.new(:user_id => jour.user_id,:course_id => course.id) + end + #问卷 + Poll.where("polls_type = 'Course' and polls_group_id = #{course.id}").each do |poll| + poll.course_acts << CourseActivity.new(:user_id => poll.user_id,:course_id => course.id) + end + end + end + end + + def down + CourseActivity.destroy_all + end +end diff --git a/db/migrate/20150811083322_create_forge_messages.rb b/db/migrate/20150811083322_create_forge_messages.rb new file mode 100644 index 000000000..f81b68712 --- /dev/null +++ b/db/migrate/20150811083322_create_forge_messages.rb @@ -0,0 +1,13 @@ +class CreateForgeMessages < ActiveRecord::Migration + def change + create_table :forge_messages do |t| + t.integer :user_id + t.integer :project_id + t.integer :forge_message_id + t.string :forge_message_type + t.integer :viewed + + t.timestamps + end + end +end diff --git a/db/migrate/20150814011838_create_course_messages.rb b/db/migrate/20150814011838_create_course_messages.rb new file mode 100644 index 000000000..266f2b075 --- /dev/null +++ b/db/migrate/20150814011838_create_course_messages.rb @@ -0,0 +1,13 @@ +class CreateCourseMessages < ActiveRecord::Migration + def change + create_table :course_messages do |t| + t.integer :user_id + t.integer :course_id + t.integer :course_message_id + t.string :course_message_type + t.integer :viewed + + t.timestamps + end + end +end diff --git a/db/migrate/20150814024425_change_attachment_time.rb b/db/migrate/20150814024425_change_attachment_time.rb new file mode 100644 index 000000000..fd1ffb7a7 --- /dev/null +++ b/db/migrate/20150814024425_change_attachment_time.rb @@ -0,0 +1,13 @@ +class ChangeAttachmentTime < ActiveRecord::Migration + def up + Attachment.where("container_type = 'Course'").each do |attachment| + if attachment.container && attachment.container.created_at.to_i > attachment.created_on.to_i + attachment.created_on = attachment.container.created_at + 3600 * 24 + attachment.save + end + end + end + + def down + end +end diff --git a/db/migrate/20150814031258_update_course_activity_time.rb b/db/migrate/20150814031258_update_course_activity_time.rb new file mode 100644 index 000000000..155e212a3 --- /dev/null +++ b/db/migrate/20150814031258_update_course_activity_time.rb @@ -0,0 +1,22 @@ +class UpdateCourseActivityTime < ActiveRecord::Migration + def up + count = CourseActivity.all.count / 10 + 1 + transaction do + for i in 1 ... count do i + CourseActivity.page(i).per(10).each do |activity| + if activity.course_act + if activity.course_act.respond_to?("created_at") + activity.created_at = activity.course_act.created_at + elsif activity.course_act.respond_to?("created_on") + activity.created_at = activity.course_act.created_on + end + activity.save + end + end + end + end + end + + def down + end +end diff --git a/db/migrate/20150815030833_add_system_score_to_student_work.rb b/db/migrate/20150815030833_add_system_score_to_student_work.rb new file mode 100644 index 000000000..1f2df648e --- /dev/null +++ b/db/migrate/20150815030833_add_system_score_to_student_work.rb @@ -0,0 +1,9 @@ +class AddSystemScoreToStudentWork < ActiveRecord::Migration + def up + add_column :student_works,:system_score,:integer + end + + def down + remove_column :student_works,:system_score + end +end diff --git a/db/migrate/20150819090720_create_memo_messages.rb b/db/migrate/20150819090720_create_memo_messages.rb new file mode 100644 index 000000000..d050a7815 --- /dev/null +++ b/db/migrate/20150819090720_create_memo_messages.rb @@ -0,0 +1,13 @@ +class CreateMemoMessages < ActiveRecord::Migration + def change + create_table :memo_messages do |t| + t.integer :user_id + t.integer :forum_id + t.integer :memo_id + t.string :memo_type + t.integer :viewed + + t.timestamps + end + end +end diff --git a/db/migrate/20150820004659_create_user_feedback_messages.rb b/db/migrate/20150820004659_create_user_feedback_messages.rb new file mode 100644 index 000000000..c5f5b85d9 --- /dev/null +++ b/db/migrate/20150820004659_create_user_feedback_messages.rb @@ -0,0 +1,12 @@ +class CreateUserFeedbackMessages < ActiveRecord::Migration + def change + create_table :user_feedback_messages do |t| + t.integer :user_id + t.integer :journals_for_message_id + t.string :journals_for_message_type + t.integer :viewed + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 243079ed8..1c77ff04b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,14 +11,15 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20150719092427) do +ActiveRecord::Schema.define(:version => 20150820025358) do create_table "activities", :force => true do |t| - t.integer "act_id", :null => false - t.string "act_type", :null => false - t.integer "user_id", :null => false - t.integer "activity_container_id" - t.string "activity_container_type", :default => "" + t.integer "act_id", :null => false + t.string "act_type", :null => false + t.integer "user_id", :null => false + t.integer "activity_container_id" + t.string "activity_container_type", :default => "" + t.datetime "created_at" end add_index "activities", ["act_id", "act_type"], :name => "index_activities_on_act_id_and_act_type" @@ -324,6 +325,15 @@ ActiveRecord::Schema.define(:version => 20150719092427) do t.datetime "updated_on", :null => false end + create_table "course_activities", :force => true do |t| + t.integer "user_id" + t.integer "course_id" + t.integer "course_act_id" + t.string "course_act_type" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "course_attachments", :force => true do |t| t.string "filename" t.string "disk_filename" @@ -356,6 +366,16 @@ ActiveRecord::Schema.define(:version => 20150719092427) do t.datetime "updated_at", :null => false end + create_table "course_messages", :force => true do |t| + t.integer "user_id" + t.integer "course_id" + t.integer "course_message_id" + t.string "course_message_type" + t.integer "viewed" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "course_statuses", :force => true do |t| t.integer "changesets_count" t.integer "watchers_count" @@ -542,6 +562,16 @@ ActiveRecord::Schema.define(:version => 20150719092427) do add_index "forge_activities", ["forge_act_id"], :name => "index_forge_activities_on_forge_act_id" + create_table "forge_messages", :force => true do |t| + t.integer "user_id" + t.integer "project_id" + t.integer "forge_message_id" + t.string "forge_message_type" + t.integer "viewed" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "forums", :force => true do |t| t.string "name", :null => false t.text "description" @@ -634,6 +664,8 @@ ActiveRecord::Schema.define(:version => 20150719092427) do t.integer "homework_common_id" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false + t.integer "result" + t.text "error_msg" end create_table "homework_users", :force => true do |t| @@ -817,6 +849,16 @@ ActiveRecord::Schema.define(:version => 20150719092427) do add_index "members", ["user_id", "project_id", "course_id"], :name => "index_members_on_user_id_and_project_id", :unique => true add_index "members", ["user_id"], :name => "index_members_on_user_id" + create_table "memo_messages", :force => true do |t| + t.integer "user_id" + t.integer "forum_id" + t.integer "memo_id" + t.string "memo_type" + t.integer "viewed" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "memos", :force => true do |t| t.integer "forum_id", :null => false t.integer "parent_id" @@ -1248,6 +1290,7 @@ ActiveRecord::Schema.define(:version => 20150719092427) do t.integer "result" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false + t.text "error_msg" end create_table "student_works", :force => true do |t| @@ -1264,6 +1307,7 @@ ActiveRecord::Schema.define(:version => 20150719092427) do t.datetime "updated_at", :null => false t.integer "late_penalty", :default => 0 t.integer "absence_penalty", :default => 0 + t.integer "system_score" end create_table "student_works_evaluation_distributions", :force => true do |t| @@ -1360,6 +1404,15 @@ ActiveRecord::Schema.define(:version => 20150719092427) do t.integer "fields_bits", :default => 0 end + create_table "user_activities", :force => true do |t| + t.string "act_type" + t.integer "act_id" + t.string "container_type" + t.integer "container_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "user_extensions", :force => true do |t| t.integer "user_id", :null => false t.date "birthday" @@ -1381,6 +1434,15 @@ ActiveRecord::Schema.define(:version => 20150719092427) do t.string "description", :default => "" end + create_table "user_feedback_messages", :force => true do |t| + t.integer "user_id" + t.integer "journals_for_message_id" + t.string "journals_for_message_type" + t.integer "viewed" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "user_grades", :force => true do |t| t.integer "user_id", :null => false t.integer "project_id", :null => false diff --git a/lib/redmine.rb b/lib/redmine.rb index 3043cfe5d..99b7ea22f 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -369,6 +369,7 @@ Redmine::MenuManager.map :admin_menu do |menu| menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural menu.push :courses, {:controller => 'admin', :action => 'courses'}, :caption => :label_course_all menu.push :users, {:controller => 'admin', :action => 'users'}, :caption => :label_user_plural + menu.push :schools, {:controller => 'admin', :action => 'schools'}, :caption => :label_school_plural menu.push :first_page_made, {:controller => 'admin',:action => 'first_page_made'},:caption => :label_first_page_made menu.push :mobile_version, {:controller => 'admin',:action => 'mobile_version'},:caption => :label_mobile_version menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural @@ -385,6 +386,11 @@ Redmine::MenuManager.map :admin_menu do |menu| :html => {:class => 'server_authentication'} menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true + menu.push :leave_messages, {:controller => 'admin', :action => 'leave_messages'}, :caption => :label_leave_message_list + menu.push :messages_list, {:controller => 'admin', :action => 'messages_list'}, :caption => :label_message_plural + menu.push :notices, {:controller => 'admin', :action => 'notices'}, :caption => :label_notification_list + menu.push :latest_login_users, {:controller => 'admin', :action => 'latest_login_users'}, :caption => :label_latest_login_user_list + menu.push :homework, {:controller => 'admin', :action => 'homework'}, :caption => :label_user_homework end #Modified by young diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index 1876190d9..927018b34 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -380,6 +380,36 @@ module Redmine nil end + def parse_commit(commits) + sum = {file: 0, insertion: 0, deletion: 0} + commits.split("\n").each do |commit| + if /(\d+)\s+?file/ =~ commit + sum[:file] += $1 .to_i + end + if /(\d+)\s+?insertion/ =~ commit + sum[:insertion] += $1.to_i + end + if /(\d+)\s+?deletion/ =~ commit + sum[:deletion] += $1.to_i + end + end + sum[:insertion] + sum[:deletion] + end + + def commits(authors, start_date, end_date, branch='master') + rs = [] + authors.each do |author| + cmd_args = %W|log #{branch} --pretty=tformat: --shortstat --author=#{author} --since=#{start_date} --until=#{end_date}| + commits = '' + git_cmd(cmd_args) do |io| + commits = io.read + end + logger.info "git log output for #{author} #{commits}" + rs << {author: author, num: parse_commit(commits)} + end + rs + end + class Revision < Redmine::Scm::Adapters::Revision # Returns the readable identifier def format_identifier diff --git a/public/assets/kindeditor/kindeditor.js b/public/assets/kindeditor/kindeditor.js index a9633861e..270618522 100644 --- a/public/assets/kindeditor/kindeditor.js +++ b/public/assets/kindeditor/kindeditor.js @@ -5104,8 +5104,8 @@ KEditor.prototype = { } } }); - statusbar.removeClass('statusbar').addClass('ke-statusbar') - .append(''); + //statusbar.removeClass('statusbar').addClass('ke-statusbar') + // .append(''); if (self._fullscreenResizeHandler) { K(window).unbind('resize', self._fullscreenResizeHandler); self._fullscreenResizeHandler = null; diff --git a/public/images/nav_icon.png b/public/images/nav_icon.png new file mode 100644 index 000000000..2c824efaf Binary files /dev/null and b/public/images/nav_icon.png differ diff --git a/public/images/news_icon_small.png b/public/images/news_icon_small.png new file mode 100644 index 000000000..4a835556e Binary files /dev/null and b/public/images/news_icon_small.png differ diff --git a/public/javascripts/bootstrap.js b/public/javascripts/bootstrap.js new file mode 100644 index 000000000..5debfd7de --- /dev/null +++ b/public/javascripts/bootstrap.js @@ -0,0 +1,2363 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under the MIT license + */ + +if (typeof jQuery === 'undefined') { + throw new Error('Bootstrap\'s JavaScript requires jQuery') +} + ++function ($) { + 'use strict'; + var version = $.fn.jquery.split(' ')[0].split('.') + if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) { + throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher') + } +}(jQuery); + +/* ======================================================================== + * Bootstrap: transition.js v3.3.5 + * http://getbootstrap.com/javascript/#transitions + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + WebkitTransition : 'webkitTransitionEnd', + MozTransition : 'transitionend', + OTransition : 'oTransitionEnd otransitionend', + transition : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + + return false // explicit for ie8 ( ._.) + } + + // http://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false + var $el = this + $(this).one('bsTransitionEnd', function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + + if (!$.support.transition) return + + $.event.special.bsTransitionEnd = { + bindType: $.support.transition.end, + delegateType: $.support.transition.end, + handle: function (e) { + if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) + } + } + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: alert.js v3.3.5 + * http://getbootstrap.com/javascript/#alerts + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // ALERT CLASS DEFINITION + // ====================== + + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.VERSION = '3.3.5' + + Alert.TRANSITION_DURATION = 150 + + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = $(selector) + + if (e) e.preventDefault() + + if (!$parent.length) { + $parent = $this.closest('.alert') + } + + $parent.trigger(e = $.Event('close.bs.alert')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + // detach from parent, fire event then clean up data + $parent.detach().trigger('closed.bs.alert').remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent + .one('bsTransitionEnd', removeElement) + .emulateTransitionEnd(Alert.TRANSITION_DURATION) : + removeElement() + } + + + // ALERT PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') + + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.alert + + $.fn.alert = Plugin + $.fn.alert.Constructor = Alert + + + // ALERT NO CONFLICT + // ================= + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + // ALERT DATA-API + // ============== + + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: button.js v3.3.5 + * http://getbootstrap.com/javascript/#buttons + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.VERSION = '3.3.5' + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state += 'Text' + + if (data.resetText == null) $el.data('resetText', $el[val]()) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + $el[val](data[state] == null ? this.options[state] : data[state]) + + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d) + } + }, this), 0) + } + + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked')) changed = false + $parent.find('.active').removeClass('active') + this.$element.addClass('active') + } else if ($input.prop('type') == 'checkbox') { + if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false + this.$element.toggleClass('active') + } + $input.prop('checked', this.$element.hasClass('active')) + if (changed) $input.trigger('change') + } else { + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) + this.$element.toggleClass('active') + } + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + var old = $.fn.button + + $.fn.button = Plugin + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + Plugin.call($btn, 'toggle') + if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: carousel.js v3.3.5 + * http://getbootstrap.com/javascript/#carousel + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = null + this.sliding = null + this.interval = null + this.$active = null + this.$items = null + + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) + + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element + .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) + .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) + } + + Carousel.VERSION = '3.3.5' + + Carousel.TRANSITION_DURATION = 600 + + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true, + keyboard: true + } + + Carousel.prototype.keydown = function (e) { + if (/input|textarea/i.test(e.target.tagName)) return + switch (e.which) { + case 37: this.prev(); break + case 39: this.next(); break + default: return + } + + e.preventDefault() + } + + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) + + this.interval && clearInterval(this.interval) + + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + + return this + } + + Carousel.prototype.getItemIndex = function (item) { + this.$items = item.parent().children('.item') + return this.$items.index(item || this.$active) + } + + Carousel.prototype.getItemForDirection = function (direction, active) { + var activeIndex = this.getItemIndex(active) + var willWrap = (direction == 'prev' && activeIndex === 0) + || (direction == 'next' && activeIndex == (this.$items.length - 1)) + if (willWrap && !this.options.wrap) return active + var delta = direction == 'prev' ? -1 : 1 + var itemIndex = (activeIndex + delta) % this.$items.length + return this.$items.eq(itemIndex) + } + + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || this.getItemForDirection(type, $active) + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var that = this + + if ($next.hasClass('active')) return (this.sliding = false) + + var relatedTarget = $next[0] + var slideEvent = $.Event('slide.bs.carousel', { + relatedTarget: relatedTarget, + direction: direction + }) + this.$element.trigger(slideEvent) + if (slideEvent.isDefaultPrevented()) return + + this.sliding = true + + isCycling && this.pause() + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) + $nextIndicator && $nextIndicator.addClass('active') + } + + var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one('bsTransitionEnd', function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { + that.$element.trigger(slidEvent) + }, 0) + }) + .emulateTransitionEnd(Carousel.TRANSITION_DURATION) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger(slidEvent) + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + var old = $.fn.carousel + + $.fn.carousel = Plugin + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + var clickHandler = function (e) { + var href + var $this = $(this) + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 + if (!$target.hasClass('carousel')) return + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + Plugin.call($target, options) + + if (slideIndex) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + } + + $(document) + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + Plugin.call($carousel, $carousel.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.3.5 + * http://getbootstrap.com/javascript/#collapse + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + + '[data-toggle="collapse"][data-target="#' + element.id + '"]') + this.transitioning = null + + if (this.options.parent) { + this.$parent = this.getParent() + } else { + this.addAriaAndCollapsedClass(this.$element, this.$trigger) + } + + if (this.options.toggle) this.toggle() + } + + Collapse.VERSION = '3.3.5' + + Collapse.TRANSITION_DURATION = 350 + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var activesData + var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') + + if (actives && actives.length) { + activesData = actives.data('bs.collapse') + if (activesData && activesData.transitioning) return + } + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + if (actives && actives.length) { + Plugin.call(actives, 'hide') + activesData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing')[dimension](0) + .attr('aria-expanded', true) + + this.$trigger + .removeClass('collapsed') + .attr('aria-expanded', true) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in')[dimension]('') + this.transitioning = 0 + this.$element + .trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element[dimension](this.$element[dimension]())[0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse in') + .attr('aria-expanded', false) + + this.$trigger + .addClass('collapsed') + .attr('aria-expanded', false) + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .removeClass('collapsing') + .addClass('collapse') + .trigger('hidden.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + Collapse.prototype.getParent = function () { + return $(this.options.parent) + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') + .each($.proxy(function (i, element) { + var $element = $(element) + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) + }, this)) + .end() + } + + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { + var isOpen = $element.hasClass('in') + + $element.attr('aria-expanded', isOpen) + $trigger + .toggleClass('collapsed', !isOpen) + .attr('aria-expanded', isOpen) + } + + function getTargetFromTrigger($trigger) { + var href + var target = $trigger.attr('data-target') + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + + return $(target) + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.collapse + + $.fn.collapse = Plugin + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { + var $this = $(this) + + if (!$this.attr('data-target')) e.preventDefault() + + var $target = getTargetFromTrigger($this) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + + Plugin.call($target, option) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.3.5 + * http://getbootstrap.com/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle="dropdown"]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.VERSION = '3.3.5' + + function getParent($this) { + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = selector && $(selector) + + return $parent && $parent.length ? $parent : $this.parent() + } + + function clearMenus(e) { + if (e && e.which === 3) return + $(backdrop).remove() + $(toggle).each(function () { + var $this = $(this) + var $parent = getParent($this) + var relatedTarget = { relatedTarget: this } + + if (!$parent.hasClass('open')) return + + if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return + + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this.attr('aria-expanded', 'false') + $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) + }) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $(document.createElement('div')) + .addClass('dropdown-backdrop') + .insertAfter($(this)) + .on('click', clearMenus) + } + + var relatedTarget = { relatedTarget: this } + $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this + .trigger('focus') + .attr('aria-expanded', 'true') + + $parent + .toggleClass('open') + .trigger('shown.bs.dropdown', relatedTarget) + } + + return false + } + + Dropdown.prototype.keydown = function (e) { + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return + + var $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + if (!isActive && e.which != 27 || isActive && e.which == 27) { + if (e.which == 27) $parent.find(toggle).trigger('focus') + return $this.trigger('click') + } + + var desc = ' li:not(.disabled):visible a' + var $items = $parent.find('.dropdown-menu' + desc) + + if (!$items.length) return + + var index = $items.index(e.target) + + if (e.which == 38 && index > 0) index-- // up + if (e.which == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items.eq(index).trigger('focus') + } + + + // DROPDOWN PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.dropdown') + + if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.dropdown + + $.fn.dropdown = Plugin + $.fn.dropdown.Constructor = Dropdown + + + // DROPDOWN NO CONFLICT + // ==================== + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + // APPLY TO STANDARD DROPDOWN ELEMENTS + // =================================== + + $(document) + .on('click.bs.dropdown.data-api', clearMenus) + .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: modal.js v3.3.5 + * http://getbootstrap.com/javascript/#modals + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // MODAL CLASS DEFINITION + // ====================== + + var Modal = function (element, options) { + this.options = options + this.$body = $(document.body) + this.$element = $(element) + this.$dialog = this.$element.find('.modal-dialog') + this.$backdrop = null + this.isShown = null + this.originalBodyPad = null + this.scrollbarWidth = 0 + this.ignoreBackdropClick = false + + if (this.options.remote) { + this.$element + .find('.modal-content') + .load(this.options.remote, $.proxy(function () { + this.$element.trigger('loaded.bs.modal') + }, this)) + } + } + + Modal.VERSION = '3.3.5' + + Modal.TRANSITION_DURATION = 300 + Modal.BACKDROP_TRANSITION_DURATION = 150 + + Modal.DEFAULTS = { + backdrop: true, + keyboard: true, + show: true + } + + Modal.prototype.toggle = function (_relatedTarget) { + return this.isShown ? this.hide() : this.show(_relatedTarget) + } + + Modal.prototype.show = function (_relatedTarget) { + var that = this + var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.checkScrollbar() + this.setScrollbar() + this.$body.addClass('modal-open') + + this.escape() + this.resize() + + this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) + + this.$dialog.on('mousedown.dismiss.bs.modal', function () { + that.$element.one('mouseup.dismiss.bs.modal', function (e) { + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true + }) + }) + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(that.$body) // don't move modals dom position + } + + that.$element + .show() + .scrollTop(0) + + that.adjustDialog() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + that.enforceFocus() + + var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) + + transition ? + that.$dialog // wait for modal to slide in + .one('bsTransitionEnd', function () { + that.$element.trigger('focus').trigger(e) + }) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + that.$element.trigger('focus').trigger(e) + }) + } + + Modal.prototype.hide = function (e) { + if (e) e.preventDefault() + + e = $.Event('hide.bs.modal') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + this.resize() + + $(document).off('focusin.bs.modal') + + this.$element + .removeClass('in') + .off('click.dismiss.bs.modal') + .off('mouseup.dismiss.bs.modal') + + this.$dialog.off('mousedown.dismiss.bs.modal') + + $.support.transition && this.$element.hasClass('fade') ? + this.$element + .one('bsTransitionEnd', $.proxy(this.hideModal, this)) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + this.hideModal() + } + + Modal.prototype.enforceFocus = function () { + $(document) + .off('focusin.bs.modal') // guard against infinite focus loop + .on('focusin.bs.modal', $.proxy(function (e) { + if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { + this.$element.trigger('focus') + } + }, this)) + } + + Modal.prototype.escape = function () { + if (this.isShown && this.options.keyboard) { + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { + e.which == 27 && this.hide() + }, this)) + } else if (!this.isShown) { + this.$element.off('keydown.dismiss.bs.modal') + } + } + + Modal.prototype.resize = function () { + if (this.isShown) { + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) + } else { + $(window).off('resize.bs.modal') + } + } + + Modal.prototype.hideModal = function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.$body.removeClass('modal-open') + that.resetAdjustments() + that.resetScrollbar() + that.$element.trigger('hidden.bs.modal') + }) + } + + Modal.prototype.removeBackdrop = function () { + this.$backdrop && this.$backdrop.remove() + this.$backdrop = null + } + + Modal.prototype.backdrop = function (callback) { + var that = this + var animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $(document.createElement('div')) + .addClass('modal-backdrop ' + animate) + .appendTo(this.$body) + + this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { + if (this.ignoreBackdropClick) { + this.ignoreBackdropClick = false + return + } + if (e.target !== e.currentTarget) return + this.options.backdrop == 'static' + ? this.$element[0].focus() + : this.hide() + }, this)) + + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow + + this.$backdrop.addClass('in') + + if (!callback) return + + doAnimate ? + this.$backdrop + .one('bsTransitionEnd', callback) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callback() + + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in') + + var callbackRemove = function () { + that.removeBackdrop() + callback && callback() + } + $.support.transition && this.$element.hasClass('fade') ? + this.$backdrop + .one('bsTransitionEnd', callbackRemove) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callbackRemove() + + } else if (callback) { + callback() + } + } + + // these following methods are used to handle overflowing modals + + Modal.prototype.handleUpdate = function () { + this.adjustDialog() + } + + Modal.prototype.adjustDialog = function () { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight + + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' + }) + } + + Modal.prototype.resetAdjustments = function () { + this.$element.css({ + paddingLeft: '', + paddingRight: '' + }) + } + + Modal.prototype.checkScrollbar = function () { + var fullWindowWidth = window.innerWidth + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 + var documentElementRect = document.documentElement.getBoundingClientRect() + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) + } + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth + this.scrollbarWidth = this.measureScrollbar() + } + + Modal.prototype.setScrollbar = function () { + var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) + this.originalBodyPad = document.body.style.paddingRight || '' + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) + } + + Modal.prototype.resetScrollbar = function () { + this.$body.css('padding-right', this.originalBodyPad) + } + + Modal.prototype.measureScrollbar = function () { // thx walsh + var scrollDiv = document.createElement('div') + scrollDiv.className = 'modal-scrollbar-measure' + this.$body.append(scrollDiv) + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth + this.$body[0].removeChild(scrollDiv) + return scrollbarWidth + } + + + // MODAL PLUGIN DEFINITION + // ======================= + + function Plugin(option, _relatedTarget) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.modal') + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('bs.modal', (data = new Modal(this, options))) + if (typeof option == 'string') data[option](_relatedTarget) + else if (options.show) data.show(_relatedTarget) + }) + } + + var old = $.fn.modal + + $.fn.modal = Plugin + $.fn.modal.Constructor = Modal + + + // MODAL NO CONFLICT + // ================= + + $.fn.modal.noConflict = function () { + $.fn.modal = old + return this + } + + + // MODAL DATA-API + // ============== + + $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + var href = $this.attr('href') + var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 + var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) + + if ($this.is('a')) e.preventDefault() + + $target.one('show.bs.modal', function (showEvent) { + if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown + $target.one('hidden.bs.modal', function () { + $this.is(':visible') && $this.trigger('focus') + }) + }) + Plugin.call($target, option, this) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: tooltip.js v3.3.5 + * http://getbootstrap.com/javascript/#tooltip + * Inspired by the original jQuery.tipsy by Jason Frame + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // TOOLTIP PUBLIC CLASS DEFINITION + // =============================== + + var Tooltip = function (element, options) { + this.type = null + this.options = null + this.enabled = null + this.timeout = null + this.hoverState = null + this.$element = null + this.inState = null + + this.init('tooltip', element, options) + } + + Tooltip.VERSION = '3.3.5' + + Tooltip.TRANSITION_DURATION = 150 + + Tooltip.DEFAULTS = { + animation: true, + placement: 'top', + selector: false, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + container: false, + viewport: { + selector: 'body', + padding: 0 + } + } + + Tooltip.prototype.init = function (type, element, options) { + this.enabled = true + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) + this.inState = { click: false, hover: false, focus: false } + + if (this.$element[0] instanceof document.constructor && !this.options.selector) { + throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') + } + + var triggers = this.options.trigger.split(' ') + + for (var i = triggers.length; i--;) { + var trigger = triggers[i] + + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' + var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' + + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + Tooltip.prototype.getDefaults = function () { + return Tooltip.DEFAULTS + } + + Tooltip.prototype.getOptions = function (options) { + options = $.extend({}, this.getDefaults(), this.$element.data(), options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay, + hide: options.delay + } + } + + return options + } + + Tooltip.prototype.getDelegateOptions = function () { + var options = {} + var defaults = this.getDefaults() + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }) + + return options + } + + Tooltip.prototype.enter = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true + } + + if (self.tip().hasClass('in') || self.hoverState == 'in') { + self.hoverState = 'in' + return + } + + clearTimeout(self.timeout) + + self.hoverState = 'in' + + if (!self.options.delay || !self.options.delay.show) return self.show() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + Tooltip.prototype.isInStateTrue = function () { + for (var key in this.inState) { + if (this.inState[key]) return true + } + + return false + } + + Tooltip.prototype.leave = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false + } + + if (self.isInStateTrue()) return + + clearTimeout(self.timeout) + + self.hoverState = 'out' + + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + Tooltip.prototype.show = function () { + var e = $.Event('show.bs.' + this.type) + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) + if (e.isDefaultPrevented() || !inDom) return + var that = this + + var $tip = this.tip() + + var tipId = this.getUID(this.type) + + this.setContent() + $tip.attr('id', tipId) + this.$element.attr('aria-describedby', tipId) + + if (this.options.animation) $tip.addClass('fade') + + var placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + var autoToken = /\s?auto?\s?/i + var autoPlace = autoToken.test(placement) + if (autoPlace) placement = placement.replace(autoToken, '') || 'top' + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(placement) + .data('bs.' + this.type, this) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + this.$element.trigger('inserted.bs.' + this.type) + + var pos = this.getPosition() + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (autoPlace) { + var orgPlacement = placement + var viewportDim = this.getPosition(this.$viewport) + + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : + placement + + $tip + .removeClass(orgPlacement) + .addClass(placement) + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) + + this.applyPlacement(calculatedOffset, placement) + + var complete = function () { + var prevHoverState = that.hoverState + that.$element.trigger('shown.bs.' + that.type) + that.hoverState = null + + if (prevHoverState == 'out') that.leave(that) + } + + $.support.transition && this.$tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + } + } + + Tooltip.prototype.applyPlacement = function (offset, placement) { + var $tip = this.tip() + var width = $tip[0].offsetWidth + var height = $tip[0].offsetHeight + + // manually read margins because getBoundingClientRect includes difference + var marginTop = parseInt($tip.css('margin-top'), 10) + var marginLeft = parseInt($tip.css('margin-left'), 10) + + // we must check for NaN for ie 8/9 + if (isNaN(marginTop)) marginTop = 0 + if (isNaN(marginLeft)) marginLeft = 0 + + offset.top += marginTop + offset.left += marginLeft + + // $.fn.offset doesn't round pixel values + // so we use setOffset directly with our own function B-0 + $.offset.setOffset($tip[0], $.extend({ + using: function (props) { + $tip.css({ + top: Math.round(props.top), + left: Math.round(props.left) + }) + } + }, offset), 0) + + $tip.addClass('in') + + // check to see if placing tip in new offset caused the tip to resize itself + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + } + + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) + + if (delta.left) offset.left += delta.left + else offset.top += delta.top + + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' + + $tip.offset(offset) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) + } + + Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { + this.arrow() + .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') + .css(isVertical ? 'top' : 'left', '') + } + + Tooltip.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + $tip.removeClass('fade in top bottom left right') + } + + Tooltip.prototype.hide = function (callback) { + var that = this + var $tip = $(this.$tip) + var e = $.Event('hide.bs.' + this.type) + + function complete() { + if (that.hoverState != 'in') $tip.detach() + that.$element + .removeAttr('aria-describedby') + .trigger('hidden.bs.' + that.type) + callback && callback() + } + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + $.support.transition && $tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + + this.hoverState = null + + return this + } + + Tooltip.prototype.fixTitle = function () { + var $e = this.$element + if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + Tooltip.prototype.hasContent = function () { + return this.getTitle() + } + + Tooltip.prototype.getPosition = function ($element) { + $element = $element || this.$element + + var el = $element[0] + var isBody = el.tagName == 'BODY' + + var elRect = el.getBoundingClientRect() + if (elRect.width == null) { + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) + } + var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null + + return $.extend({}, elRect, scroll, outerDims, elOffset) + } + + Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + + } + + Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { + var delta = { top: 0, left: 0 } + if (!this.$viewport) return delta + + var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 + var viewportDimensions = this.getPosition(this.$viewport) + + if (/right|left/.test(placement)) { + var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll + var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight + if (topEdgeOffset < viewportDimensions.top) { // top overflow + delta.top = viewportDimensions.top - topEdgeOffset + } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow + delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset + } + } else { + var leftEdgeOffset = pos.left - viewportPadding + var rightEdgeOffset = pos.left + viewportPadding + actualWidth + if (leftEdgeOffset < viewportDimensions.left) { // left overflow + delta.left = viewportDimensions.left - leftEdgeOffset + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow + delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset + } + } + + return delta + } + + Tooltip.prototype.getTitle = function () { + var title + var $e = this.$element + var o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + Tooltip.prototype.getUID = function (prefix) { + do prefix += ~~(Math.random() * 1000000) + while (document.getElementById(prefix)) + return prefix + } + + Tooltip.prototype.tip = function () { + if (!this.$tip) { + this.$tip = $(this.options.template) + if (this.$tip.length != 1) { + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') + } + } + return this.$tip + } + + Tooltip.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) + } + + Tooltip.prototype.enable = function () { + this.enabled = true + } + + Tooltip.prototype.disable = function () { + this.enabled = false + } + + Tooltip.prototype.toggleEnabled = function () { + this.enabled = !this.enabled + } + + Tooltip.prototype.toggle = function (e) { + var self = this + if (e) { + self = $(e.currentTarget).data('bs.' + this.type) + if (!self) { + self = new this.constructor(e.currentTarget, this.getDelegateOptions()) + $(e.currentTarget).data('bs.' + this.type, self) + } + } + + if (e) { + self.inState.click = !self.inState.click + if (self.isInStateTrue()) self.enter(self) + else self.leave(self) + } else { + self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + } + } + + Tooltip.prototype.destroy = function () { + var that = this + clearTimeout(this.timeout) + this.hide(function () { + that.$element.off('.' + that.type).removeData('bs.' + that.type) + if (that.$tip) { + that.$tip.detach() + } + that.$tip = null + that.$arrow = null + that.$viewport = null + }) + } + + + // TOOLTIP PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tooltip') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tooltip + + $.fn.tooltip = Plugin + $.fn.tooltip.Constructor = Tooltip + + + // TOOLTIP NO CONFLICT + // =================== + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(jQuery); + +/* ======================================================================== + * Bootstrap: popover.js v3.3.5 + * http://getbootstrap.com/javascript/#popovers + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // POPOVER PUBLIC CLASS DEFINITION + // =============================== + + var Popover = function (element, options) { + this.init('popover', element, options) + } + + if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') + + Popover.VERSION = '3.3.5' + + Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { + placement: 'right', + trigger: 'click', + content: '', + template: '' + }) + + + // NOTE: POPOVER EXTENDS tooltip.js + // ================================ + + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) + + Popover.prototype.constructor = Popover + + Popover.prototype.getDefaults = function () { + return Popover.DEFAULTS + } + + Popover.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + var content = this.getContent() + + $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) + $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events + this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' + ](content) + + $tip.removeClass('fade top bottom left right in') + + // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do + // this manually by checking the contents. + if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() + } + + Popover.prototype.hasContent = function () { + return this.getTitle() || this.getContent() + } + + Popover.prototype.getContent = function () { + var $e = this.$element + var o = this.options + + return $e.attr('data-content') + || (typeof o.content == 'function' ? + o.content.call($e[0]) : + o.content) + } + + Popover.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.arrow')) + } + + + // POPOVER PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.popover') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.popover + + $.fn.popover = Plugin + $.fn.popover.Constructor = Popover + + + // POPOVER NO CONFLICT + // =================== + + $.fn.popover.noConflict = function () { + $.fn.popover = old + return this + } + +}(jQuery); + +/* ======================================================================== + * Bootstrap: scrollspy.js v3.3.5 + * http://getbootstrap.com/javascript/#scrollspy + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // SCROLLSPY CLASS DEFINITION + // ========================== + + function ScrollSpy(element, options) { + this.$body = $(document.body) + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) + this.options = $.extend({}, ScrollSpy.DEFAULTS, options) + this.selector = (this.options.target || '') + ' .nav li > a' + this.offsets = [] + this.targets = [] + this.activeTarget = null + this.scrollHeight = 0 + + this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) + this.refresh() + this.process() + } + + ScrollSpy.VERSION = '3.3.5' + + ScrollSpy.DEFAULTS = { + offset: 10 + } + + ScrollSpy.prototype.getScrollHeight = function () { + return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) + } + + ScrollSpy.prototype.refresh = function () { + var that = this + var offsetMethod = 'offset' + var offsetBase = 0 + + this.offsets = [] + this.targets = [] + this.scrollHeight = this.getScrollHeight() + + if (!$.isWindow(this.$scrollElement[0])) { + offsetMethod = 'position' + offsetBase = this.$scrollElement.scrollTop() + } + + this.$body + .find(this.selector) + .map(function () { + var $el = $(this) + var href = $el.data('target') || $el.attr('href') + var $href = /^#./.test(href) && $(href) + + return ($href + && $href.length + && $href.is(':visible') + && [[$href[offsetMethod]().top + offsetBase, href]]) || null + }) + .sort(function (a, b) { return a[0] - b[0] }) + .each(function () { + that.offsets.push(this[0]) + that.targets.push(this[1]) + }) + } + + ScrollSpy.prototype.process = function () { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset + var scrollHeight = this.getScrollHeight() + var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() + var offsets = this.offsets + var targets = this.targets + var activeTarget = this.activeTarget + var i + + if (this.scrollHeight != scrollHeight) { + this.refresh() + } + + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) + } + + if (activeTarget && scrollTop < offsets[0]) { + this.activeTarget = null + return this.clear() + } + + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) + && this.activate(targets[i]) + } + } + + ScrollSpy.prototype.activate = function (target) { + this.activeTarget = target + + this.clear() + + var selector = this.selector + + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' + + var active = $(selector) + .parents('li') + .addClass('active') + + if (active.parent('.dropdown-menu').length) { + active = active + .closest('li.dropdown') + .addClass('active') + } + + active.trigger('activate.bs.scrollspy') + } + + ScrollSpy.prototype.clear = function () { + $(this.selector) + .parentsUntil(this.options.target, '.active') + .removeClass('active') + } + + + // SCROLLSPY PLUGIN DEFINITION + // =========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.scrollspy') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.scrollspy + + $.fn.scrollspy = Plugin + $.fn.scrollspy.Constructor = ScrollSpy + + + // SCROLLSPY NO CONFLICT + // ===================== + + $.fn.scrollspy.noConflict = function () { + $.fn.scrollspy = old + return this + } + + + // SCROLLSPY DATA-API + // ================== + + $(window).on('load.bs.scrollspy.data-api', function () { + $('[data-spy="scroll"]').each(function () { + var $spy = $(this) + Plugin.call($spy, $spy.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: tab.js v3.3.5 + * http://getbootstrap.com/javascript/#tabs + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // TAB CLASS DEFINITION + // ==================== + + var Tab = function (element) { + // jscs:disable requireDollarBeforejQueryAssignment + this.element = $(element) + // jscs:enable requireDollarBeforejQueryAssignment + } + + Tab.VERSION = '3.3.5' + + Tab.TRANSITION_DURATION = 150 + + Tab.prototype.show = function () { + var $this = this.element + var $ul = $this.closest('ul:not(.dropdown-menu)') + var selector = $this.data('target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + if ($this.parent('li').hasClass('active')) return + + var $previous = $ul.find('.active:last a') + var hideEvent = $.Event('hide.bs.tab', { + relatedTarget: $this[0] + }) + var showEvent = $.Event('show.bs.tab', { + relatedTarget: $previous[0] + }) + + $previous.trigger(hideEvent) + $this.trigger(showEvent) + + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return + + var $target = $(selector) + + this.activate($this.closest('li'), $ul) + this.activate($target, $target.parent(), function () { + $previous.trigger({ + type: 'hidden.bs.tab', + relatedTarget: $this[0] + }) + $this.trigger({ + type: 'shown.bs.tab', + relatedTarget: $previous[0] + }) + }) + } + + Tab.prototype.activate = function (element, container, callback) { + var $active = container.find('> .active') + var transition = callback + && $.support.transition + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) + + function next() { + $active + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', false) + + element + .addClass('active') + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + + if (transition) { + element[0].offsetWidth // reflow for transition + element.addClass('in') + } else { + element.removeClass('fade') + } + + if (element.parent('.dropdown-menu').length) { + element + .closest('li.dropdown') + .addClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + } + + callback && callback() + } + + $active.length && transition ? + $active + .one('bsTransitionEnd', next) + .emulateTransitionEnd(Tab.TRANSITION_DURATION) : + next() + + $active.removeClass('in') + } + + + // TAB PLUGIN DEFINITION + // ===================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tab') + + if (!data) $this.data('bs.tab', (data = new Tab(this))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tab + + $.fn.tab = Plugin + $.fn.tab.Constructor = Tab + + + // TAB NO CONFLICT + // =============== + + $.fn.tab.noConflict = function () { + $.fn.tab = old + return this + } + + + // TAB DATA-API + // ============ + + var clickHandler = function (e) { + e.preventDefault() + Plugin.call($(this), 'show') + } + + $(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: affix.js v3.3.5 + * http://getbootstrap.com/javascript/#affix + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // AFFIX CLASS DEFINITION + // ====================== + + var Affix = function (element, options) { + this.options = $.extend({}, Affix.DEFAULTS, options) + + this.$target = $(this.options.target) + .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) + + this.$element = $(element) + this.affixed = null + this.unpin = null + this.pinnedOffset = null + + this.checkPosition() + } + + Affix.VERSION = '3.3.5' + + Affix.RESET = 'affix affix-top affix-bottom' + + Affix.DEFAULTS = { + offset: 0, + target: window + } + + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + var targetHeight = this.$target.height() + + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false + + if (this.affixed == 'bottom') { + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' + } + + var initializing = this.affixed == null + var colliderTop = initializing ? scrollTop : position.top + var colliderHeight = initializing ? targetHeight : height + + if (offsetTop != null && scrollTop <= offsetTop) return 'top' + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' + + return false + } + + Affix.prototype.getPinnedOffset = function () { + if (this.pinnedOffset) return this.pinnedOffset + this.$element.removeClass(Affix.RESET).addClass('affix') + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + return (this.pinnedOffset = position.top - scrollTop) + } + + Affix.prototype.checkPositionWithEventLoop = function () { + setTimeout($.proxy(this.checkPosition, this), 1) + } + + Affix.prototype.checkPosition = function () { + if (!this.$element.is(':visible')) return + + var height = this.$element.height() + var offset = this.options.offset + var offsetTop = offset.top + var offsetBottom = offset.bottom + var scrollHeight = Math.max($(document).height(), $(document.body).height()) + + if (typeof offset != 'object') offsetBottom = offsetTop = offset + if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) + + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) + + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css('top', '') + + var affixType = 'affix' + (affix ? '-' + affix : '') + var e = $.Event(affixType + '.bs.affix') + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + this.affixed = affix + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null + + this.$element + .removeClass(Affix.RESET) + .addClass(affixType) + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') + } + + if (affix == 'bottom') { + this.$element.offset({ + top: scrollHeight - height - offsetBottom + }) + } + } + + + // AFFIX PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.affix') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.affix', (data = new Affix(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.affix + + $.fn.affix = Plugin + $.fn.affix.Constructor = Affix + + + // AFFIX NO CONFLICT + // ================= + + $.fn.affix.noConflict = function () { + $.fn.affix = old + return this + } + + + // AFFIX DATA-API + // ============== + + $(window).on('load', function () { + $('[data-spy="affix"]').each(function () { + var $spy = $(this) + var data = $spy.data() + + data.offset = data.offset || {} + + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom + if (data.offsetTop != null) data.offset.top = data.offsetTop + + Plugin.call($spy, data) + }) + }) + +}(jQuery); diff --git a/public/javascripts/course.js b/public/javascripts/course.js index b2736993b..be29fdc30 100644 --- a/public/javascripts/course.js +++ b/public/javascripts/course.js @@ -412,6 +412,24 @@ function regex_homework_name() } } +//处理迟交扣分 +function check_late_penalty() +{ + var obj = $("input[name='late_penalty']"); + var regex = /^\d+$/; + if(regex.test(obj.val())) + { + if(obj.val() > 50) + { + obj.val("50"); + } + } + else + { + obj.val("0"); + } +} + //验证匿评数量 function regex_evaluation_num() { @@ -546,10 +564,12 @@ function submit_homework_form(){if(regexHomeworkCommonName()&®exHomeworkCommo //增加测试结果 function add_programing_test(obj) { var now = new Date().getTime(); - obj.after("
  • " + - "
  • " + + obj.after("
  • " + + "
  • " + "
  • " + "" + + "测试" + + "" + "
  • "); } //删除测试结果 diff --git a/public/javascripts/header.js b/public/javascripts/header.js index 06748d726..d33b80e3d 100644 --- a/public/javascripts/header.js +++ b/public/javascripts/header.js @@ -46,6 +46,54 @@ $(document).ready(function () { addCourseSlipMenu(); }); +//消息提醒 +function MessageAddSlipMenu () { + var loggedas = $('#current_message_li a:first'); + var sub_menu = $('#message_sub_menu'); + loggedas.mouseenter(function() { + sub_menu.show(); + $('#my_projects_message_ul').hide(); + $('#my_courses_message_ul').hide(); + }); + sub_menu.mouseleave(function() { + sub_menu.hide(); + $('#my_projects_message_ul').hide(); + $('#my_courses_message_ul').hide(); + }); +} + +function MessageAddProjectSlipMenu () { + var loggedas = $('#my_projects_message_li'); + var project_sub_menu = $('#my_projects_message_ul'); + var course_sub_menu = $('#my_courses_message_ul'); + loggedas.mouseenter(function() { + course_sub_menu.hide(); + project_sub_menu.show(); + }); + loggedas.mouseleave(function() { + project_sub_menu.hide(); + course_sub_menu.hide(); + }); +} +function MessageAddCourseSlipMenu () { + var loggedas = $('#my_courses_message_li'); + var project_sub_menu = $('#my_projects_message_ul'); + var course_sub_menu = $('#my_courses_message_ul'); + loggedas.mouseenter(function() { + project_sub_menu.hide(); + course_sub_menu.show(); + }); + loggedas.mouseleave(function() { + course_sub_menu.hide(); + project_sub_menu.hide(); + }); +} + +$(document).ready(function () { + MessageAddSlipMenu(); + MessageAddProjectSlipMenu (); + MessageAddCourseSlipMenu(); +}); //将右侧的最小高度设置成左侧高度,美化界面 $(document).ready(function () { $("#RSide").css("min-height",$("#LSide").height()-30); diff --git a/public/javascripts/jquery-1.3.2.js b/public/javascripts/jquery-1.3.2.js new file mode 100644 index 000000000..b1ae21d8b --- /dev/null +++ b/public/javascripts/jquery-1.3.2.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!O.indexOf("
    "]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
    ","
    "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

    ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
    ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
    ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
    ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/public/javascripts/project.js b/public/javascripts/project.js index 98c148372..c7a615ba3 100644 --- a/public/javascripts/project.js +++ b/public/javascripts/project.js @@ -491,3 +491,8 @@ function judgeprojectname(){ } }); } + +//用户反馈 +function submitProjectFeedback() { + $("#project_feedback_form").submit(); +} \ No newline at end of file diff --git a/public/javascripts/sidebar.js b/public/javascripts/sidebar.js new file mode 100644 index 000000000..4c18b6423 --- /dev/null +++ b/public/javascripts/sidebar.js @@ -0,0 +1,64 @@ +/* ================================================= +// +// jQuery Fixed Plugins 1.3.1 +// author : +// Url: +// Data : 2012-03-30 +// +// : float --> [left or right] +// minStatue --> С״ֻ̬show_btn +// skin --> Ƥ +// durationTime --> ʱ +// : + $("#scrollsidebar2").fix({ + float : 'right', //default.left or right + minStatue : true, //default.false or true + skin : 'green', //default.gray or yellow blue green orange white + durationTime : 1000 // + }); +// +// =================================================*/ + +;(function($){ + $.fn.fix = function(options){ + var defaults = { + float : 'left', + minStatue : false, + skin : 'blue', + durationTime : 1000 + } + var options = $.extend(defaults, options); + + this.each(function(){ + //ȡ + var thisBox = $(this), + closeBtn = thisBox.find('.close_btn' ), + show_btn = thisBox.find('.show_btn' ), + sideContent = thisBox.find('.side_content'), + sideList = thisBox.find('.side_list') + ; + var defaultTop = thisBox.offset().top; //Ĭtop + + thisBox.css(options.float, 0); + if(options.minStatue){ + $(".show_btn").css("float", options.float); + sideContent.css('width', 0); + show_btn.css('width', 25); + + } + + //close¼ + closeBtn.bind("click",function(){ + sideContent.animate({width: '0px'},"fast"); + show_btn.stop(true, true).delay(300).animate({ width: '25px'},"fast"); + }); + //show¼ + show_btn.click(function() { + $(this).animate({width: '0px'},"fast"); + sideContent.stop(true, true).delay(200).animate({ width: '154px'},"fast"); + }); + + }); //end this.each + + }; +})(jQuery); \ No newline at end of file diff --git a/public/javascripts/user.js b/public/javascripts/user.js new file mode 100644 index 000000000..c7690a015 --- /dev/null +++ b/public/javascripts/user.js @@ -0,0 +1,261 @@ +//个人动态 +$(function(){ + function init_editor(params){ + var editor = params.kindutil.create(params.textarea, { + resizeType : 1,minWidth:"1px",width:"100%",height:"80px", + items:['emoticons'], + afterChange:function(){//按键事件 + nh_check_field({content:this,contentmsg:params.contentmsg,textarea:params.textarea}); + }, + afterCreate:function(){ + var toolbar = $("div[class='ke-toolbar']",params.div_form); + $(".ke-outline>.ke-toolbar-icon",toolbar).append('表情'); + params.toolbar_container.append(toolbar); + } + }).loadPlugin('paste'); + return editor; + } + + function nh_check_field(params){ + var result=true; + if(params.content!=undefined){ + if(params.content.isEmpty()){ + result=false; + } + if(params.content.html()!=params.textarea.html() || params.issubmit==true){ + params.textarea.html(params.content.html()); + params.content.sync(); + if(params.content.isEmpty()){ + params.contentmsg.html('内容不能为空'); + params.contentmsg.css({color:'#ff0000'}); + }else{ + params.contentmsg.html('填写正确'); + params.contentmsg.css({color:'#008000'}); + } + params.contentmsg.show(); + } + } + return result; + } + function init_form(params){ + params.form.submit(function(){ + var flag = false; + if(params.form.attr('data-remote') != undefined ){ + flag = true + } + var is_checked = nh_check_field({ + issubmit:true, + content:params.editor, + contentmsg:params.contentmsg, + textarea:params.textarea + }); + if(is_checked){ + if(flag){ + return true; + }else{ + $(this)[0].submit(); + return false; + } + } + return false; + }); + } + function nh_reset_form(params){ + params.form[0].reset(); + params.textarea.empty(); + if(params.editor != undefined){ + params.editor.html(params.textarea.html()); + } + params.contentmsg.hide(); + } + + KindEditor.ready(function(K){ + $("a[nhname='reply_btn']").live('click',function(){ + var params = {}; + params.kindutil = K; + params.container = $(this).parent().parent('div'); + params.div_form = $("div[nhname='div_form']",params.container); + params.form = $("form",params.div_form); + params.textarea = $("textarea[name='user_notes']",params.div_form); + params.textarea.prev('div').css("height","60px"); + params.contentmsg = $("p[nhname='contentmsg']",params.div_form); + params.toolbar_container = $("div[nhname='toolbar_container']",params.div_form); + params.cancel_btn = $("a[nhname='cancel_btn']",params.div_form); + params.submit_btn = $("a[nhname='submit_btn']",params.div_form); + if(params.textarea.data('init') == undefined){ + params.editor = init_editor(params); + init_form(params); + params.cancel_btn.click(function(){ + nh_reset_form(params); + toggleAndSettingWordsVal(params.div_form, params.textarea); + }); + params.submit_btn.click(function(){ + params.form.submit(); + }); + params.textarea.data('init',1); + } + params.cancel_btn.click(); + setTimeout(function(){ + if(!params.div_form.is(':hidden')){ + params.textarea.show(); + params.textarea.focus(); + params.textarea.hide(); + } + },300); + }); + + $("a[nhname='sub_reply_btn']").live('click',function(){ + var params = {}; + params.kindutil = K; + params.container = $(this).parent().parent('div'); + params.div_form = $("div[nhname='sub_div_form']",params.container); + params.form = $("form",params.div_form); + params.textarea = $("textarea[name='user_notes']",params.div_form); + params.textarea.prev('div').css("height","60px"); + params.contentmsg = $("p[nhname='sub_contentmsg']",params.div_form); + params.toolbar_container = $("div[nhname='sub_toolbar_container']",params.div_form); + params.cancel_btn = $("a[nhname='sub_cancel_btn']",params.div_form); + params.submit_btn = $("a[nhname='sub_submit_btn']",params.div_form); + if(params.textarea.data('init') == undefined){ + params.editor = init_editor(params); + init_form(params); + params.cancel_btn.click(function(){ + nh_reset_form(params); + toggleAndSettingWordsVal(params.div_form, params.textarea); + }); + params.submit_btn.click(function(){ + params.form.submit(); + }); + params.textarea.data('init',1); + } + params.cancel_btn.click(); + setTimeout(function(){ + if(!params.div_form.is(':hidden')){ + params.textarea.show(); + params.textarea.focus(); + params.textarea.hide(); + } + },300); + }); + + $("div[nhname='new_message']").each(function(){ + var params = {}; + params.kindutil = K; + params.div_form = $(this); + params.form = $("form",params.div_form); + if(params.form==undefined || params.form.length==0){ + return; + } + params.textarea = $("textarea[nhname='new_message_textarea']",params.div_form); + params.contentmsg = $("p[nhname='contentmsg']",params.div_form); + params.toolbar_container = $("div[nhname='toolbar_container']",params.div_form); + params.cancel_btn = $("#new_message_cancel_btn"); + params.submit_btn = $("#new_message_submit_btn"); + + if(params.textarea.data('init') == undefined){ + params.editor = init_editor(params); + init_form(params); + params.cancel_btn.click(function(){ + nh_reset_form(params); + }); + params.submit_btn.click(function(){ + params.form.submit(); + }); + params.textarea.data('init',1); + $(this).show(); + } + }); + }); +}); +function init_list_more_div(params){ + var p=params; + p.exbtn.click(function(){ + var isclose = p.container.data('isclose'); + var hasmore = p.container.data('hasmore'); + if(isclose == '1'){ + $("div[nhname='rec']",p.container).show(); + p.container.data('isclose','0'); + change_status_4_list_more_div(params); + return; + } + if(hasmore == '0'){ + change_status_4_list_more_div(params,'get'); + return; + } + var url = p.container.data('url'); + if($("div[nhname='rec']",p.container).length > 0){ + var lastid = $("div[nhname='rec']",p.container).filter(':last').data('id'); + url += "?lastid="+lastid; + var lasttime = $("div[nhname='rec']",p.container).filter(':last').data('time'); + if(lasttime != undefined){ + url += "&lasttime="+lasttime; + } + } + $.ajax( {url:url,dataType:'text',success:function(data){ + var html = $("
    "+data+"
    "); + var lens = $("div[nhname='rec']",html).length; + if(lens < p.size){ + p.container.data('hasmore','0'); + } + if(lens>0){ + var currpage = parseInt(p.container.data('currpage'))+1; + p.container.data('currpage',currpage); + p.container.append(html.html()) + } + change_status_4_list_more_div(params,'get'); + p.div.show(); + }} ); + }); + p.clbtn.click(function(){ + var i=0; + $("div[nhname='rec']",p.container).each(function(){ + i++; + if(i> p.size){ + $(this).hide(); + } + }); + p.container.data('isclose','1'); + change_status_4_list_more_div(params); + }); + p.exbtn.click(); +} +function change_status_4_list_more_div(params,opt){ + var p=params; + if($("div[nhname='rec']",p.container).length == 0 && opt != 'get'){ + p.exbtn.click(); + return; + } + var show_lens = $("div[nhname='rec']",p.container).length - $("div[nhname='rec']",p.container).filter(':hidden').length; + if( show_lens > p.size ){ + p.clbtn.show(); + }else{ + p.clbtn.hide(); + } + if($("div[nhname='rec']",p.container).length == 0){ + p.exbtn.html(p.nodatamsg); + }else if( p.container.data('hasmore') == '1' || p.container.data('isclose')=='1' ){ + p.exbtn.html('点击展开更多'); + }else{ + p.exbtn.html('没有更多了'); + } +} +function init_list_more_div_params(div){ + var params = {}; + params.div = div; + params.container = $("div[nhname='container']",div); + params.exbtn = $("a[nhname='expand']",div); + params.clbtn = $("a[nhname='close']",div); + params.size = params.container.data('pagesize'); + params.nodatamsg = params.container.data('nodatamsg'); + if( params.size == undefined ){ + params.size = 13; + } + return params; +} +$(function(){ + $("div[nhname='list_more_div']").each(function(){ + var params = init_list_more_div_params($(this)); + init_list_more_div(params) + }); +}); +//个人动态 end \ No newline at end of file diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index d4d309181..3e01d68ff 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -2796,4 +2796,15 @@ div.repos_explain{ .upload_img img{max-width: 100%;} #activity .upload_img img{max-width: 580px;} -img,embed{max-width: 100%;} \ No newline at end of file +img,embed{max-width: 100%;} + +img.school_avatar { + background: rgb(245, 245, 245); + padding: 4px; + border: 1px solid #e5dfc7; + float: left; + display: block; + width: 100px; + height: 100px; + max-width: none; +} \ No newline at end of file diff --git a/public/stylesheets/courses.css b/public/stylesheets/courses.css index 5a7bb001a..1393431d7 100644 --- a/public/stylesheets/courses.css +++ b/public/stylesheets/courses.css @@ -55,7 +55,7 @@ a:hover.problem_pic{border:1px solid #64bdd9;} .problem_txt{ width:610px; margin-left:10px; color:#777777;word-break: break-all;word-wrap: break-word;} a.problem_name{ color:#ff5722;max-width:60px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;} a:hover.problem_name{ color:#d33503;} -a.problem_tit{ color:#0781b4; max-width:410px; display:block; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;} +a.problem_tit{ color:#0781b4; max-width:410px; display:block; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;vertical-align: top;} a.pro_mes_w{ height:20px; float:right;display:block; color:#999999;} a:hover.problem_tit{ color:#09658c; } .problem_main{ border-bottom:1px dashed #d4d4d4; padding-bottom:10px; margin-bottom:10px;} @@ -88,8 +88,6 @@ a:hover.talk_edit{ color:#ff5722;} .talk_text{ border:1px solid #64bdd9; height:100px;width:550px; background:#fff; margin-left:5px; padding:5px; margin-bottom:10px;} .talk_new ul li{ } .sb{width:70px; height:26px; color:#606060; cursor:pointer;} -a.blue_btn{ background:#64bdd9; display:block; font-size:14px;color:#fff; font-weight:normal; text-align:center; margin-left:10px; margin-bottom:10px; padding:2px 10px;} -a:hover.blue_btn{ background:#329cbd;} a.grey_btn{ background:#d9d9d9; color:#656565;font-size:14px; font-weight:normal; text-align:center; margin-left:10px; margin-bottom:10px; padding:2px 10px;} a:hover.grey_btn{ background:#717171; color:#fff;} /****资源库***/ @@ -228,6 +226,7 @@ a:hover.ping_sub{ background:#14a8b9;} .w430{ width:470px;} .w557{ width:557px;} .w350{ width:350px;} +.h400{height: 400px !important;} .w620{ width:480px; height:160px; border:1px solid #CCC;} .bo{height:26px; border:1px solid #CCC; padding-left:5px; background:#fff;width:470px; } .bo02{height:26px; border:1px solid #CCC; padding-left:5px; background:#fff;width:480px; margin-left:2px; color: #999; } @@ -609,6 +608,7 @@ a:hover.Reply_pic{border:1px solid #64bdd9;} .w547{ width:544px;} .w196{ width:196px;} .w186{ width:186px;} +.w190{width: 190px;} .w200{width: 200px;} .w459{ width:459px;} .hwork_new_set{border:1px dashed #CCC; background:#f5f5f5; text-align:center; padding:10px 0; margin-bottom:10px;} @@ -665,7 +665,6 @@ a:hover.ping_pic{border:1px solid #64bdd9;} .ping_back_tit{ float:left; width:523px; margin-left:10px; } a.down_btn{ border:1px solid #CCC; color:#999; padding:0px 5px; font-size:12px; text-align:center; display:block;} a:hover.down_btn{ background:#14ad5a; color:#fff; border:1px solid #14ad5a;} -.fr{ float:right;} .min_search{ width:140px; height:20px; border:1px solid #d0d0d0; color:#666; background:url(../images/public_icon.png) 185px -193px no-repeat; } .li_min_search{ float:right; margin-right:-10px;} .info_ni_download{ width:100px; padding:5px;position: absolute;display:none;-moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; box-shadow:0px 0px 5px #194a81; color:#666; background:#fff; text-align:left;margin-left: 200px;margin-top: 10px;} @@ -685,12 +684,21 @@ input#score{ width:40px;} .ui-slider .ui-slider-handle:hover,.ui-slider .ui-slider-handle:focus{background:#64bdd9;} .ui-slider .ui-slider-handle:active{background-image:none;} .ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;top:0;height:100%;background:#64bdd9;left:0;} + /* 编程作品 */ .border_ce{ border:1px solid #e4e4e4; } .border_ce tr td{ height:26px; } -.td_tit{width:155px; text-align:center;} -.td_50{width:50px; text-align:center;} -a.work_list_tit{width:610px; display:block; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;} +.td_tit{width:170px; text-align:center;} +.td_50{width:60px; text-align:center;} +a.work_list_tit{width:580px; display:block; overflow:hidden; font-size:14px; font-weight:bold; white-space: nowrap; text-overflow:ellipsis;} +.work_list_pro{ width:670px;} +.border_l{border-left:1px solid #e4e4e4;} +.border_t{ border-top:1px solid #e4e4e4;} +.td_end{border-top:1px solid #e4e4e4; height:auto; padding:5px; } +.wl{text-align: left;} +.vt{vertical-align: top;} +.td_board_left{border-right: 1px solid #e4e4e4;} +.c_w{ color:#fff;} .filename { background: url(../images/pic_file.png) 0 -25px no-repeat;color: #3ca5c6;max-width: 150px;border: none; padding-left: 20px;margin-right: 10px;margin-bottom: 5px; white-space: nowrap; text-overflow:ellipsis;} .evaluation{position: relative;} @@ -705,6 +713,9 @@ a:hover.about_me{ color:#0781b4;} .mb5 li{width:200px;word-wrap: break-word; word-break: normal; } +#homework_work_test_show{margin-left: 35px;width: 94%;} + + diff --git a/public/stylesheets/images/homepage_icon.png b/public/stylesheets/images/homepage_icon.png new file mode 100644 index 000000000..bb32783b5 Binary files /dev/null and b/public/stylesheets/images/homepage_icon.png differ diff --git a/public/stylesheets/images/nav_icon.png b/public/stylesheets/images/nav_icon.png new file mode 100644 index 000000000..2c824efaf Binary files /dev/null and b/public/stylesheets/images/nav_icon.png differ diff --git a/public/stylesheets/images/resourceSearch_03.png b/public/stylesheets/images/resourceSearch_03.png new file mode 100644 index 000000000..702ce0e29 Binary files /dev/null and b/public/stylesheets/images/resourceSearch_03.png differ diff --git a/public/stylesheets/images/resourceSelect_03.png b/public/stylesheets/images/resourceSelect_03.png new file mode 100644 index 000000000..f5995a980 Binary files /dev/null and b/public/stylesheets/images/resourceSelect_03.png differ diff --git a/public/stylesheets/images/resourceSelected_03.png b/public/stylesheets/images/resourceSelected_03.png new file mode 100644 index 000000000..9b18c5dfa Binary files /dev/null and b/public/stylesheets/images/resourceSelected_03.png differ diff --git a/public/stylesheets/images/resourceUplaod_03.png b/public/stylesheets/images/resourceUplaod_03.png new file mode 100644 index 000000000..6f915a517 Binary files /dev/null and b/public/stylesheets/images/resourceUplaod_03.png differ diff --git a/public/stylesheets/images/resource_icon_list.png b/public/stylesheets/images/resource_icon_list.png new file mode 100644 index 000000000..1b5bc6f58 Binary files /dev/null and b/public/stylesheets/images/resource_icon_list.png differ diff --git a/public/stylesheets/leftside.css b/public/stylesheets/leftside.css index 50b47fff4..990c02d54 100644 --- a/public/stylesheets/leftside.css +++ b/public/stylesheets/leftside.css @@ -15,6 +15,7 @@ a.pr_join_a{ color:#fff; display:block; padding:0 5px 0 3px; padding-top:2px; h .pr_close{ display:block; background:url(../images/leftside.png) -1px -49px no-repeat; width:11px; height:11px; margin-top:3px; float:left; } .pr_add{display:block; background:url(../images/leftside.png) 0px -71px no-repeat; width:11px; height:11px; margin-top:3px; float:left; } .pr_arrow{display:block; background:url(../images/leftside.png) 0px -90px no-repeat; width:11px; height:11px; margin-top:3px; float:left; } +.pr_delete{ display:block; background:url(../images/leftside.png) -1px -157px no-repeat; width:11px; height:11px; margin-top:3px; float:left; } .pr_info_name{ color:#3e4040; font-size:14px; line-height:1.5;} a:hover.pr_info_name{ color:#3ca5c6;} .pr_info_score{ font-size:14px; color:#3e4040; } diff --git a/public/stylesheets/leftside_new.css b/public/stylesheets/leftside_new.css index c2d4d043c..2f31a1f65 100644 --- a/public/stylesheets/leftside_new.css +++ b/public/stylesheets/leftside_new.css @@ -31,7 +31,7 @@ a:hover.pr_join_a{ background:#41a8c8;} /*左侧导航*/ .subNavBox{width:240px; background:#fff;margin:10px 10px 0 0;} -.subNav{border-bottom:solid 1px #e5e3da;cursor:pointer;font-weight:bold;font-size:14px;color:#3ca5c6; height:26px;padding-left:10px;background-color:#fff; padding-top:2px;} +.subNav{border-bottom:solid 1px #e5e3da;cursor:auto;font-weight:bold;font-size:14px;color:#3ca5c6; height:26px;padding-left:10px;background-color:#fff; padding-top:2px;} .subNav_jiantou{background:url(../images/jiantou1.jpg) no-repeat;background-position:95% 50%; background-color:#fff;} .subNav_jiantou:hover{color:#0781b4; } .currentDd{color:#0781b4;} diff --git a/public/stylesheets/polls.css b/public/stylesheets/polls.css index 353ec3937..9f7b2d021 100644 --- a/public/stylesheets/polls.css +++ b/public/stylesheets/polls.css @@ -28,7 +28,7 @@ a:hover.pollsbtn{ background:#64bdd9; color:#fff; text-decoration:none;} #polls div{word-break: break-all;word-wrap: break-word;} .ur_prefix_content{ color:#656565; text-indent:30px; margin-top:10px; } .ur_card{border-top:1px solid #dcdcdc;margin-top:20px; color:#3a3a3a;} -.ur_title{ padding:20px 0px ; float:left; width:604px; } +.ur_title{ padding:20px 0px ; float:left; width:564px; } .ur_required{ font-weight: bold; color:red;} .ur_inputs{ color:#666;} .ur_table{border-top:1px solid #dcdcdc; background:#fff;} @@ -101,10 +101,13 @@ a:hover.icon_remove{background:url(images/icons.png) -20px -338px no-repeat;} .ur_editor02{width:648px; border:1px solid #cbcbcb; padding:10px; margin-bottom:10px;} a.ur_button_submit{ display:block; width:106px; height:31px; margin:0 auto; background:#15bccf; color:#fff; font-size:16px; text-align:center; padding-top:4px; margin-bottom:10px; } a:hover.ur_button_submit{ background:#0fa9bb; text-decoration:none;} + a.ur_icon_de{ background:url(images/icons.png) 0px -338px no-repeat; width:16px; height:27px; display:block;float:right; margin-top:15px;} a:hover.ur_icon_de{ background:url(images/icons.png) -20px -338px no-repeat;} .ur_icon_edit{ background:url(images/icons.png) 0px -272px no-repeat; width:16px; height:27px; display:block;float:right; margin-top:15px; margin-right:10px;} a:hover.ur_icon_edit{ background:url(images/icons.png) -21px -272px no-repeat;} +.ur_icon_add{ background:url(images/icons.png) 0px -310px no-repeat; width:16px; height:27px; display:block;float:right; margin-top:15px; margin-right:10px;} +a:hover.ur_icon_add{background:url(images/icons.png) -20px -310px no-repeat;} /***弹框***/ .popbox_polls{width:300px;height:100px;position:fixed !important;z-index:100;left:50%;top:50%;margin:-100px 0 0 -150px; background:#fff; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; box-shadow:0px 0px 8px #194a81; overflow:auto;} @@ -127,7 +130,7 @@ a:hover.btn_de{ background:#ff5d31;} a.btn_pu{ border:1px solid #3cb761; color:#3cb761; } a:hover.btn_pu{ background:#3cb761;} .pollsbtn_grey{ border:1px solid #b1b1b1; color:#b1b1b1; padding:0px 9px; height:19px; padding-top:3px; } -.polls_title_w { width:300px; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;} +.polls_title_w { max-width:280px; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;} .polls_title_st { max-width:530px; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;} .polls_de_grey{ color:#b1b1b1; margin-top:3px;} .ml5{ margin-left:5px;} diff --git a/public/stylesheets/project.css b/public/stylesheets/project.css index f005b2df6..8d86a6873 100644 --- a/public/stylesheets/project.css +++ b/public/stylesheets/project.css @@ -74,7 +74,11 @@ a:hover.problem_pic{border:1px solid #64bdd9;} .issues_icon{ background:url(../images/public_icon.png) 0 -342px no-repeat; width:16px; height:21px;} .problem_txt{ width:600px; margin-left:10px; color:#777777; } .pro_txt_w{width:610px;} -a.problem_name{ color:#ff5722; } +a.problem_name{ color:#ff5722;max-width: 80px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} a:hover.problem_name{ color:#d33503;} a.problem_tit{ color:#0781b4; max-width:430px; font-weight:bold; display:block; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;} a.problem_tit02{ color:#0781b4; font-weight:bold;max-width:400px;} @@ -551,7 +555,24 @@ p.percent { font-size: 12px; } .repositorytitle select{ width: 110px; height: 21px; } - +.riviseRed { + width:15px; + height:15px; + margin-right: 3px; + background-color:#FF0000; + filter:alpha(opacity=50); /* ie 有效*/ + -moz-opacity:0.5; /* Firefox 有效*/ + opacity: 0.5; /* 通用,其他浏览器 有效*/ +} +.changeBlue { + width:15px; + height:15px; + margin-right: 3px; + background-color:#0000FF; + filter:alpha(opacity=50); /* ie 有效*/ + -moz-opacity:0.5; /* Firefox 有效*/ + opacity: 0.5; /* 通用,其他浏览器 有效*/ +} /*导出*/ @@ -673,9 +694,10 @@ table.list thead th tr.changeset { height: 20px } tr.changeset ul, ol { margin-top: 0px; margin-bottom: 0px; } -tr.changeset td.revision_graph { width: 15%; background-color: #fffffb; } +tr.changeset td.revision_graph { width: 1%; background-color: #fffffb; } tr.changeset td.author { text-align: center; width: 15%; white-space:nowrap;} tr.changeset td.committed_on { text-align: center; width: 15%; white-space:nowrap;} +tr.changeset td.comments { text-align: center; word-break:break-all; word-wrap: break-word;;} div.changeset { padding: 4px;} div.changeset { border-bottom: 1px solid #ddd; } @@ -753,4 +775,6 @@ a:hover.Reply_pic{border:1px solid #64bdd9;} #about_newtalk{ display:none;} +/*version*/ +.time_tracter{color: #64BDD9;padding: 5px;} diff --git a/public/stylesheets/public.css b/public/stylesheets/public.css index 8e16c9436..4cc859721 100644 --- a/public/stylesheets/public.css +++ b/public/stylesheets/public.css @@ -73,12 +73,16 @@ h4{ font-size:14px; color:#3b3b3b;} .ml320{ margin-left:320px;} .mr5{ margin-right:5px;} .mr10{ margin-right:10px;} +.mr15 {margin-right: 15px;} .mr20{ margin-right:20px;} .mr30{ margin-right:30px;} .mr40{ margin-right:40px;} +.mr45{margin-right: 45px;} .mr50{margin-right: 50px;} .mr55{margin-right: 55px;} .mr70{margin-right: 70px;} +.mw15{margin:0 15px;} +.mw20{margin:0 20px;} .mt1{margin-top: 1px;} .mt3{ margin-top:3px;} .mt5{ margin-top:5px;} @@ -86,6 +90,7 @@ h4{ font-size:14px; color:#3b3b3b;} .mt10{ margin-top:10px;} .mt30{ margin-top: 30px;} .mb5{ margin-bottom:5px;} +.mb8{ margin-bottom:8px;} .mb10{ margin-bottom:10px;} .mb20{ margin-bottom:20px;} .pl15{ padding-left:15px;} @@ -96,6 +101,7 @@ h4{ font-size:14px; color:#3b3b3b;} .w60{ width:60px;} .w70{ width:70px;} .w90{ width:90px;} +.w100{width: 100px;} .w210{ width:210px;} .w150{ width:150px;} .w280{ width:280px;} @@ -163,11 +169,13 @@ a.c_green{ color:#28be6c;} .grey_btn{ background:#d9d9d9; color:#656565;font-size:14px; font-weight:normal; text-align:center;padding:2px 10px;} a.grey_btn{ background:#d9d9d9; color:#656565;font-size:14px; font-weight:normal; text-align:center;padding:2px 10px;} a:hover.grey_btn{ background:#717171; color:#fff;} -.green_btn{ background:#28be6c; color:#fff; font-size:14px; font-weight:normal;padding:2px 10px; text-align:center;} -a.green_btn{background:#28be6c;color:#fff;font-size:14px; font-weight:normal; padding:2px 10px; text-align:center;} +.green_btn{ background:#28be6c; color:#fff; font-size:14px; font-weight:normal;padding:2px 8px; text-align:center;} +a.green_btn{background:#28be6c;color:#fff;font-size:14px; font-weight:normal; padding:2px 8px; text-align:center;cursor: pointer;} a:hover.green_btn{ background:#14ad5a;} -.blue_btn{ background:#64bdd9; color:#fff; font-size:14px; font-weight:normal;padding:2px 10px; text-align:center;} -a.blue_btn{background:#64bdd9;color:#fff;font-size:14px; font-weight:normal; padding:2px 10px; text-align:center;} +.blue_btn{ background:#64bdd9; color:#fff; font-size:14px; font-weight:normal;padding:2px 8px; text-align:center;} +a.blue_btn{background:#64bdd9;color:#fff;font-size:14px; font-weight:normal; padding:2px 8px; text-align:center;cursor: pointer;} +.red_btn{ background:red; color:#fff; font-size:14px; font-weight:normal;padding:2px 8px; text-align:center;} +a.red_btn{background:red; color:#fff;font-size:14px; font-weight:normal; padding:2px 8px; text-align:center;cursor: pointer;} a.orange_btn_homework{background:#d63502;color:#fff;font-size:14px; font-weight:normal; padding:2px 10px; text-align:center;} a:hover.blue_btn{ background:#329cbd;cursor: pointer;} a.orange_btn{ background:#ff5722;color:#fff;font-size:14px; font-weight:normal; padding:2px 10px; text-align:center; } @@ -449,3 +457,78 @@ img,embed{max-width: 100%;} .is_public_checkbox{margin-left: 15px;margin-right: 10px;} .author_name{color: #3ca5c6 !important;} .ke-container-default{max-width: 100%;} + +/*底部*/ +/*#Footer{background-color:#ffffff; margin-bottom:10px; padding-bottom:15px; color:#666666;}*/ +/*.footerAboutContainer {width:auto; border-bottom:1px solid #efefef;}*/ +/*.footerAbout{ width:585px; margin:0 auto;height:35px; line-height:35px; border-bottom:1px solid #efefef; }*/ +/*.languageBox {width:55px; height:20px; margin-left:5px; outline:none; color:#666666; border:1px solid #d9d9d9;}*/ +/*.departments{ width:890px; margin:5px auto 0 auto;height:30px;line-height:30px;}*/ +/*.copyright{ width:390px; margin:0 auto;height:20px;line-height:20px;}*/ +/*a.f_grey {color:#666666;}*/ +/*a.f_grey:hover {color:#000000;}*/ + +/*资源库*/ +.resources {width:730px; background-color:#ffffff; padding:10px;} +.resourcesBanner {width:730px; height:40px; background-color:#eaeaea; margin-bottom:10px;} +.bannerName {background:#64bdd9; color:#ffffff; height:40px; line-height:40px; width:90px; text-align:center; font-weight:normal; vertical-align:middle; font-size: 16px; float:left;} +.resourcesSelect {width:40px; height:40px; float:right; position:relative;} +.resourcesSelected {width:25px; height:20px;} +.resourcesIcon {margin-top:15px; display:block; position:relative; background:url(../images/resource_icon_list.png) 0px 0px no-repeat; width:25px; height:20px;} +.resourcesIcon:hover { background:url(../images/resource_icon_list.png) 0px -25px no-repeat;} +.resourcesType {width:50px; background-color:#ffffff; float:left; list-style:none; position:absolute; border:1px solid #eaeaea; border-radius:5px; top:35px; padding:5px 10px; left:-30px; font-size:12px; color:#888888; display:none;} +a.resourcesGrey {font-size:12px; color:#888888;} +a.resourcesGrey:hover {font-size:12px; color:#15bccf;} +.resourcesBanner ul li:hover ul.resourcesType {display:block;} +ul li:hover ul {display:block;} +.resourcesUploadBox {float:right; width:103px; height:34px; background-color:#64bdd9; line-height:34px; vertical-align:middle; text-align:center; margin-left:12px;} +.uploadIcon {background:url(../images/resource_icon_list.png) -35px 10px no-repeat; float:left; display:block; width:30px; height:30px; margin-left:-3px;} +a.uploadText {color:#ffffff; font-size:14px;} +.resourcesSearchloadBox {border:1px solid #e6e6e6; width:225px; float:right; background-color:#ffffff;} +.searchResource {border:none; outline:none; background-color:#ffffff; width:184px; height:32px; padding-left:10px; display:block; float:left;} +.searchIcon{width:31px; height:32px; background-color:#ffffff; background:url(../images/resource_icon_list.png) -40px -15px no-repeat; display:block; float:left;} +.resourcesSearchBanner {height:34px; margin-bottom:10px;} +.resourcesListTab {width:730px; height:40px; background-color:#f6f6f6; border-bottom:1px solid #eaeaea; font-size:14px; color:#7a7a7a;} +.resourcesListName {width:175px; height:40px; line-height:40px; text-align:center;} +.resourcesListSize {width:110px; height:40px; line-height:40px; text-align:center;} +.resourcesListType {width:150px; height:40px; line-height:40px; text-align:center;} +.resourcesListUploader {width:130px; height:40px; line-height:40px; text-align:center;} +.resourcesListTime {width:165px; height:40px; line-height:40px; text-align:center;} +.resourcesList {width:730px; height:39px; background-color:#ffffff; border-bottom:1px dashed #eaeaea; color:#9a9a9a; font-size:12px;} +a.resourcesBlack {font-size:12px; color:#4c4c4c;} +a.resourcesBlack:hover {font-size:12px; color:#000000;} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 80px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 12px; + text-align: left; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.5; + color:#616060; + white-space: nowrap; +} +.dropdown-menu > li > a:hover{ + color: #ffffff; + text-decoration: none; + background-color: #64bdd9; + outline:none; +} diff --git a/public/stylesheets/public_new.css b/public/stylesheets/public_new.css index 428da5712..ec7ec26a1 100644 --- a/public/stylesheets/public_new.css +++ b/public/stylesheets/public_new.css @@ -6,7 +6,8 @@ div,img,tr,td,table{ border:0;} table,tr,td{border:0;cellspacing:0; cellpadding:0;} ol,ul,li{ list-style-type:none} a:link,a:visited{color:#7f7f7f;text-decoration:none;} -a:hover,a:active{color:#000;} +a:hover,a:active{color:#15bccf;} +/*img{max-width: 100%;}*/ /*常用*/ select,input,textarea{ border:1px solid #64bdd9; background:#fff; color:#000; padding-left:5px; } @@ -71,6 +72,9 @@ h4{ font-size:14px; color:#3b3b3b;} .mr20{ margin-right:20px;} .mr30{ margin-right:30px;} .mr40{ margin-right:40px;} +.mr45{margin-right: 45px;} +.mw15{margin:0 15px;} +.mw20{margin:0 20px;} .mt3{ margin-top:3px;} .mt5{ margin-top:5px;} .mt8{ margin-top:8px;} @@ -429,4 +433,358 @@ div.flash.warning, .conflict { a.box_close{ display:block; float:right; width:16px; height:16px; background:url(../images/img_floatbox.png) 0 0 no-repeat;} a:hover.box_close{background:url(../images/img_floatbox.png) -22px 0 no-repeat;} -div.ke-statusbar{height:1px; border-top:none;} \ No newline at end of file +div.ke-statusbar{height:1px; border-top:none;} + +/*底部*/ +/*#Footer{background-color:#ffffff; margin-bottom:10px; padding-bottom:15px; color:#666666;}*/ +/*.footerAboutContainer {width:auto; border-bottom:1px solid #efefef;}*/ +/*.footerAbout{ width:585px; margin:0 auto;height:35px; line-height:35px; border-bottom:1px solid #efefef; }*/ +/*.languageBox {width:55px; height:20px; margin-left:5px; outline:none; color:#666666; border:1px solid #d9d9d9;}*/ +/*.departments{ width:890px; margin:5px auto 0 auto;height:30px;line-height:30px;}*/ +/*.copyright{ width:390px; margin:0 auto;height:20px;line-height:20px;}*/ +/*a.f_grey {color:#666666;}*/ +/*a.f_grey:hover {color:#000000;}*/ +/*资源库*/ +.resources {width:728px; background-color:#ffffff; padding:10px; border:1px solid #dddddd;float: right} +/*.resources {width:730px; background-color:#ffffff; padding:10px;float: right}*/ +.resourcesBanner {width:730px; height:40px; background-color:#eaeaea; margin-bottom:10px;} +.bannerName {background:#64bdd9; color:#ffffff; height:40px; line-height:40px; width:90px; text-align:center; font-weight:normal; vertical-align:middle; font-size: 16px; float:left;} +.resourcesSelect {width:30px; height:34px; float:right; position:relative; margin-top:-6px;} +.resourcesSelected {width:25px; height:20px; position:relative; background:url(images/resource_icon_list.png) 0px 0px no-repeat;} +.resourcesSelected:hover { background:url(images/resource_icon_list.png) 0px -25px no-repeat;} +.resourcesIcon {margin-top:15px; display:block; width:25px; height:20px;} +/*.resourcesIcon {margin-top:15px; display:block; position:relative; background:url(images/resource_icon_list.png) 0px 0px no-repeat; width:25px; height:20px;}*/ +/*.resourcesIcon:hover { background:url(images/resource_icon_list.png) 0px -25px no-repeat;}*/ +/*.resourcesType {width:50px; background-color:#ffffff; float:left; list-style:none; position:absolute; border:1px solid #eaeaea; border-radius:5px; top:35px; padding:5px 10px; left:-30px; font-size:12px; color:#888888; display:none;}*/ +a.resourcesGrey {font-size:12px; color:#888888;} +a.resourcesGrey:hover {font-size:12px; color:#15bccf;} +.resourcesBanner ul li:hover ul.resourcesType {display:block;} +ul li:hover ul {display:block;} +.resourcesUploadBox {float:right; width:103px; height:34px; background-color:#64bdd9; line-height:34px; vertical-align:middle; text-align:center; margin-left:12px;} +.resourcesUploadBox:hover {background-color:#0781b4;} +.uploadIcon {background:url(images/resource_icon_list.png) -35px 10px no-repeat; float:left; display:block; width:30px; height:30px; margin-left:-3px;} +a.uploadText {color:#ffffff; font-size:14px;} +.resourcesSearchloadBox {border:1px solid #e6e6e6; width:225px; float:left; background-color:#ffffff;} +.searchResource {border:none; outline:none; background-color:#ffffff; width:184px; height:32px; padding-left:10px; display:block; float:left;} +.searchIcon{width:31px; height:32px; background-color:#ffffff; background:url(images/resource_icon_list.png) -40px -15px no-repeat; display:block; float:left;} +/*.resourcesSearchBanner {height:34px; margin-bottom:10px;}*/ +.resourcesSearchBanner {width:710px; height:34px; margin-bottom:10px; margin-top:15px; margin-left:auto; margin-right:auto;} +/*.resourcesListTab {width:730px; height:40px; background-color:#f6f6f6; border-bottom:1px solid #eaeaea; font-size:14px; color:#7a7a7a;}*/ +.resourcesListTab {width:710px; height:40px; background-color:#f6f6f6; border-bottom:1px solid #eaeaea; font-size:14px; color:#7a7a7a; margin-left:auto; margin-right:auto;} +/*.resourcesListName {width:175px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesListSize {width:110px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesListType {width:150px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesListUploader {width:130px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesListTime {width:165px; height:40px; line-height:40px; text-align:center;}*/ +.resourcesListName {width:160px; height:40px; line-height:40px; text-align:left;} +.resourcesListSize {width:105px; height:40px; line-height:40px; text-align:center;} +.resourcesListType {width:150px; height:40px; line-height:40px; text-align:center;} +.resourcesListUploader {width:180px; height:40px; line-height:40px; text-align:center;} +.resourcesListTime {width:95px; height:40px; line-height:40px; text-align:center;} +/*.resourcesList {width:730px; height:39px; background-color:#ffffff; border-bottom:1px dashed #eaeaea; color:#9a9a9a; font-size:12px;}*/ +a.resourcesBlack {font-size:12px; color:#4c4c4c;white-space: nowrap;text-align: left} +a.resourcesBlack:hover {font-size:12px; color:#000000;} +.resourcesListCheckbox {width:20px; height:40px; line-height:40px; text-align:center; vertical-align:middle;} +.resourcesCheckbox {padding:0px; margin:0px; margin-top:14px; width:12px; height:12px;} +.resourcesList {width:710px; height:39px; background-color:#ffffff; border-bottom:1px dashed #eaeaea; color:#9a9a9a; font-size:12px; margin-left:auto; margin-right:auto;} +.resourcesListOption {width:710px; height:40px; line-height:40px; vertical-align:middle; margin-left:auto; margin-right:auto; background-color:#f6f6f6;} +.resourcesCheckAll {width:20px; height:40px; line-height:40px; text-align:center; vertical-align:middle; float:left;} +.resourcesSelectSend {float:right;} +/*.resourcesSelectSendButton {width:75px; height:28px; background-color:#ffffff; line-height:28px; vertical-align:middle; margin-top:5px; margin-right:10px; margin-left:15px; text-align:center; border:1px solid #15bccf; border-radius:5px; float:right;}*/ +.resourcesSelectSendButton {width:75px; height:28px; background-color:#ffffff; line-height:28px; vertical-align:middle; margin-top:5px; margin-right:10px; margin-left:15px; text-align:center; border:1px solid #15bccf; border-radius:5px; float:right;} +a.sendButtonBlue {color:#15bccf;} +a.sendButtonBlue:hover {color:#ffffff;} +.resourcesSelectSendButton:hover {background-color:#15bccf;} +.db {display:block;} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 80px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 12px; + text-align: left; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.5; + color:#616060; + white-space: nowrap; +} +.dropdown-menu > li > a:hover{ + color: #ffffff; + text-decoration: none; + background-color: #64bdd9; + outline:none; +} +.homepageRightBanner {width:720px; height:34px; margin:0px auto; border-bottom:1px solid #e9e9e9;} +.NewsBannerName {font-size:16px; color:#4b4b4b; display:block; background:url(images/homepage_icon.png) -18px -230px no-repeat; width:150px; float:left; padding-left:15px; margin-top:4px;} +a.resourcesTypeAll {background:url(images/homepage_icon.png) -180px -89px no-repeat; padding-left:23px;} +a.resourcesTypeAtt {background:url(images/homepage_icon.png) -180px -49px no-repeat; padding-left:23px;} +.resourcesType {width:75px; background-color:#ffffff; float:left; list-style:none; position:absolute; border:1px solid #eaeaea; border-radius:5px; top:15px; padding:10px 20px; left:-90px; font-size:12px; color:#888888; display:none; line-height:2;} +.resourcesUploadBox {float:right; width:103px; height:34px; background-color:#64bdd9; line-height:34px; vertical-align:middle; text-align:center; margin-left:12px;} +.resourcesUploadBox:hover {background-color:#0781b4;} +/* 个人主页右边部分*/ +.homepageSearchIcon {width:30px; height:32px; background:url(images/nav_icon.png) -8px 3px no-repeat; float:left;} +a.homepagePostTypeQuiz {background:url(images/homepage_icon.png) -90px -124px no-repeat; padding-left:23px;} +a.homepagePostTypeAssignment {background:url(images/homepage_icon.png) -93px -318px no-repeat; padding-left:23px;} +a.replyGrey {color:#888888; display:inline-block;} +a.replyGrey:hover {color:#4b4b4b;} + +/*上传资源弹窗*/ +.resourceUploadPopup {width:400px; height:auto; border:3px solid #15bccf; padding-left:16px; padding-bottom:16px; background-color:#ffffff; position:absolute; top:50%; left:50%; margin-left:-200px; z-index:1000;} +.uploadDialogText {font-size:16px; color:#15bccf; line-height:16px; padding-top:20px; width:140px; display:inline-block;} +.uploadBoxContainer {height:33px; line-height:33px; margin-top:10px; position:relative} +.uploadBox {width:100px; height:33px; line-height:33px; text-align:center; vertical-align:middle; background-color:#64bdd9; border-radius:3px; float:left; margin-right:12px;} +a.uploadBoxIcon {background:url(images/resource_icon_list.png) -35px 10px no-repeat; float:left; display:block; width:81px; height:30px; padding-left:22px; font-size:14px; color:#ffffff;} +a.uploadIcon {background:url(images/resource_icon_list.png) 8px -60px no-repeat; width:100px; height:33px;} +.chooseFile {color:#ffffff; display:block; margin-left:32px;} +.uploadResourceIntr {width:250px; height:33px; float:left; line-height:33px; font-size:12px;} +.uploadResourceName {width:250px; display:inline-block; line-height:15px; font-size:12px; color:#444444; margin-bottom:2px;} +.uploadResourceIntr2 {width:250px; display:inline-block; line-height:15px; font-size:12px; color:#444444;} +.uploadType {margin:10px 0; border:1px solid #e6e6e6; width:100px; height:30px; outline:none; font-size:12px; color:#888888;} +.uploadKeyword {margin-bottom:10px; outline:none; border:1px solid #e6e6e6; height:30px; width:280px;} + +/*发送资源弹窗*/ +/*.resourceShareContainer {width:100%; height:100%; background:#666; filter:alpha(opacity=50); opacity:0.5; -moz-opacity:0.5; position:absolute; left:0; top:0; z-index:-999;}*/ +/*.resourceSharePopup {width:300px; height:auto; border:3px solid #15bccf; padding-left:16px; padding-bottom:16px; background-color:#ffffff; position:absolute; top:50%; left:50%; margin-left:-150px; z-index:1000;}*/ +.resourceSharePopup {width:300px; height:auto; border:3px solid #15bccf; padding-left:16px; padding-bottom:16px; background-color:#ffffff; position:absolute; top:50%; left:50%; margin-left:-150px; z-index:1000;} +.sendText {font-size:16px; color:#15bccf; line-height:16px; padding-top:20px; width:100px; display:inline-block;} +.resourcePopupClose {width:20px; height:20px; display:inline-block; float:right;} +.resourceClose {background:url(images/resource_icon_list.png) 0px -40px no-repeat; width:20px; height:20px; display:inline-block;} +.resourcesSearchBox {border:1px solid #e6e6e6; width:225px; height:25px; background-color:#ffffff; margin-top:12px; margin-bottom:15px;} +.searchResourcePopup {border:none; outline:none; background-color:#ffffff; width:184px; height:25px; padding-left:10px; display:inline-block; float:left;} +.searchIconPopup{width:31px; height:25px; background-color:#ffffff; background:url(images/resource_icon_list.png) -40px -18px no-repeat; display:inline-block; float:left;} +.courseSend {width:260px; height:15px; line-height:15px; margin-bottom:10px;} +.courseSendCheckbox {padding:0px; margin:0px; width:12px; height:12px; margin-right:10px; display:inline-block; margin-top:2px;} +.sendCourseName {font-size:12px; color:#5f6060;} +.courseSendSubmit {width:50px; height:25px; line-height:25px; text-align:center; vertical-align:middle; background-color:#64bdd9; margin-right:25px; float:left;} +.courseSendCancel {width:50px; height:25px; line-height:25px; text-align:center; vertical-align:middle; background-color:#c1c1c1; float:left} +a.sendSourceText {font-size:14px; color:#ffffff;} +input.sendSourceText {font-size:14px;color:#ffffff;background-color:#64bdd9;} +.resourcesSendTo {float:left; height:20px; margin-top:15px;} +.resourcesSendType {border:1px solid #e6e6e6; width:60px; height:24px; outline:none; font-size:14px; color:#888888;} + + + +/*主类容左右分栏*/ +#LSide{ width:240px; } +#RSide{ width:730px; margin-left:10px; background:#fff; padding:10px; margin-bottom:10px;} + + +/*资源库*/ +/*.resources {width:730px; background-color:#ffffff;}*/ +/*.resourcesBanner {width:730px; height:40px; background-color:#eaeaea; margin-bottom:10px;}*/ +/*.bannerName {background:#64bdd9; color:#ffffff; height:40px; line-height:40px; width:90px; text-align:center; font-weight:normal; vertical-align:middle; font-size: 16px; float:left;}*/ +/*.resourcesSelect {width:40px; height:40px; float:right; position:relative;}*/ +.resourcesSelected2 {width:25px; height:20px;} +.resourcesIcon2 {margin-top:20px; display:block; position:relative; background:url(images/resource_icon_list.png) 0px 0px no-repeat; width:25px; height:20px;} +.resourcesIcon2:hover { background:url(images/resource_icon_list.png) 0px -25px no-repeat;} +/*.resourcesType {width:50px; background-color:#ffffff; float:left; list-style:none; position:absolute; border:1px solid #eaeaea; border-radius:5px; top:35px; padding:5px 10px; left:-30px; font-size:12px; color:#888888; display:none;}*/ +/*a.resourcesGrey {font-size:12px; color:#888888;}*/ +/*a.resourcesGrey:hover {font-size:12px; color:#15bccf;}*/ +/*.resourcesBanner ul li:hover ul.resourcesType {display:block;}*/ +/*ul li:hover ul {display:block;}*/ +/*.resourcesUploadBox {float:right; width:103px; height:34px; background-color:#64bdd9; line-height:34px; vertical-align:middle; text-align:center; margin-left:12px;}*/ +/*.uploadIcon {background:url(images/resource_icon_list.png) -35px 10px no-repeat; float:left; display:block; width:30px; height:30px; margin-left:-3px;}*/ +/*a.uploadText {color:#ffffff; font-size:14px;}*/ +/*.resourcesSearchloadBox {border:1px solid #e6e6e6; width:225px; float:right; background-color:#ffffff;}*/ +/*.searchResource {border:none; outline:none; background-color:#ffffff; width:184px; height:32px; padding-left:10px; display:block; float:left;}*/ +/*.searchIcon{width:31px; height:32px; background-color:#ffffff; background:url(images/resource_icon_list.png) -40px -15px no-repeat; display:block; float:left;}*/ +/*.resourcesSearchBanner {height:34px; margin-bottom:10px;}*/ +/*.resourcesListTab {width:730px; height:40px; background-color:#f6f6f6; border-bottom:1px solid #eaeaea; font-size:14px; color:#7a7a7a;}*/ +/*.resourcesListCheckbox {width:40px; height:40px; line-height:40px; text-align:center; vertical-align:middle;}*/ +/*.resourcesCheckbox {padding:0px; margin:0px; margin-top:14px; width:12px; height:12px;}*/ +/*.resourcesListName {width:135px; height:40px; line-height:40px; text-align:left;}*/ +/*.resourcesListSize {width:110px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesListType {width:150px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesListUploader {width:130px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesListTime {width:165px; height:40px; line-height:40px; text-align:center;}*/ +/*.resourcesList {width:730px; height:39px; background-color:#ffffff; border-bottom:1px dashed #eaeaea; color:#9a9a9a; font-size:12px;}*/ +/*a.resourcesBlack {font-size:12px; color:#4c4c4c;}*/ +/*a.resourcesBlack:hover {font-size:12px; color:#000000;}*/ +/*.dropdown-menu {*/ + /*position: absolute;*/ + /*top: 100%;*/ + /*left: 0;*/ + /*z-index: 1000;*/ + /*display: none;*/ + /*float: left;*/ + /*min-width: 80px;*/ + /*padding: 5px 0;*/ + /*margin: 2px 0 0;*/ + /*font-size: 12px;*/ + /*text-align: left;*/ + /*background-color: #fff;*/ + /*-webkit-background-clip: padding-box;*/ + /*background-clip: padding-box;*/ + /*border: 1px solid #ccc;*/ + /*border-radius: 4px;*/ + /*-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);*/ + /*box-shadow: 0 6px 12px rgba(0, 0, 0, .175);*/ +/*}*/ +/*.dropdown-menu > li > a {*/ + /*display: block;*/ + /*padding: 3px 20px;*/ + /*clear: both;*/ + /*font-weight: normal;*/ + /*line-height: 1.5;*/ + /*color:#616060;*/ + /*white-space: nowrap;*/ +/*}*/ +/*.dropdown-menu > li > a:hover{*/ + /*color: #ffffff;*/ + /*text-decoration: none;*/ + /*background-color: #64bdd9;*/ + /*outline:none;*/ +/*}*/ + +/*发送资源弹窗*/ +/*.resourceShareContainer {width:100%; height:100%; background:#666; filter:alpha(opacity=50); opacity:0.5; -moz-opacity:0.5; position:absolute; left:0; top:0; z-index:-999;}*/ +/*.resourceSharePopup {width:300px; height:auto; border:3px solid #15bccf; padding-left:16px; padding-bottom:16px; background-color:#ffffff; position:absolute; top:50%; left:50%; margin-left:-150px; z-index:1000;}*/ +/*.sendText {font-size:16px; color:#15bccf; line-height:16px; padding-top:20px; width:140px; display:inline-block;}*/ +/*.resourcePopupClose {width:20px; height:20px; display:inline-block; float:right;}*/ +/*.resourceClose {background:url(images/resource_icon_list.png) 0px -40px no-repeat; width:20px; height:20px; display:inline-block;}*/ +/*.resourcesSearchBox {border:1px solid #e6e6e6; width:225px; height:25px; background-color:#ffffff; margin-top:12px; margin-bottom:15px;}*/ +/*.searchResourcePopup {border:none; outline:none; background-color:#ffffff; width:184px; height:25px; padding-left:10px; display:inline-block; float:left;}*/ +/*.searchIconPopup{width:31px; height:25px; background-color:#ffffff; background:url(images/resource_icon_list.png) -40px -18px no-repeat; display:inline-block; float:left;}*/ +/*.courseSend {width:260px; height:15px; line-height:15px; margin-bottom:10px;}*/ +/*.courseSendCheckbox {padding:0px; margin:0px; width:12px; height:12px; margin-right:10px; display:inline-block; margin-top:2px;}*/ +/*.sendCourseName {font-size:12px; color:#5f6060;}*/ +/*.courseSendSubmit {width:50px; height:25px; line-height:25px; text-align:center; vertical-align:middle; background-color:#64bdd9; margin-right:25px; float:left;}*/ +/*.courseSendCancel {width:50px; height:25px; line-height:25px; text-align:center; vertical-align:middle; background-color:#c1c1c1; float:left}*/ +/*a.sendSourceText {font-size:14px; color:#ffffff;}*/ + +/*上传资源弹窗*/ +/*.resourceUploadPopup {width:400px; height:auto; border:3px solid #15bccf; padding-left:16px; padding-bottom:16px; background-color:#ffffff; position:absolute; top:50%; left:50%; margin-left:-200px; z-index:1000;}*/ +/*.uploadText {font-size:16px; color:#15bccf; line-height:16px; padding-top:20px; width:140px; display:inline-block;}*/ +/*.uploadBoxContainer {height:33px; line-height:33px; margin-top:10px; position:relative;}*/ +/*.uploadBox {width:100px; height:33px; line-height:33px; text-align:center; vertical-align:middle; background-color:#64bdd9; border-radius:3px; float:left; margin-right:12px;}*/ +/*a.uploadIcon {background:url(images/resource_icon_list.png) 8px -60px no-repeat; width:100px; height:33px;}*/ +/*.chooseFile {color:#ffffff; display:block; margin-left:32px;}*/ +/*.uploadResourceIntr {width:250px; height:33px; float:left; line-height:33px; font-size:12px;}*/ +/*.uploadResourceName {width:250px; display:inline-block; line-height:15px; font-size:12px; color:#444444; margin-bottom:2px;}*/ +/*.uploadResourceIntr2 {width:250px; display:inline-block; line-height:15px; font-size:12px; color:#444444;}*/ +/*.uploadType {margin:10px 0; border:1px solid #e6e6e6; width:100px; height:30px; outline:none; font-size:12px; color:#888888;}*/ +/*.uploadKeyword {margin-bottom:10px; outline:none; border:1px solid #e6e6e6; height:30px; width:280px;}*/ + + +/*新个人主页框架css*/ +.navContainer {width:100%; margin:0 auto; background-color:#15bccf;} +.homepageContentContainer {width:100%; margin:0 auto; background-color:#eaebed;} +.homepageContent {width:1000px; background-color:#eaebed; margin:0 auto;} +.navHomepage {width:1000px; height:54px; background-color:#15bccf; margin:0 auto;} +.navHomepageLogo {width:60px; height:54px; line-height:54px; vertical-align:middle; margin-left:2px; margin-right:40px;} +.navHomepageMenu {margin-right:40px;display:inline-block;height:54px; line-height:54px; vertical-align:middle;} +.navHomepageSearchBox {width:380px; border:none; outline:none; height:32px; margin-top:11px; background-color:#ffffff;} +.navHomepageSearchInput {width:345px; height:32px; outline:none; border:none; float:left; padding-left:5px;; margin:0;} +.homepageSearchIcon {width:30px; height:32px; background:url(../images/nav_icon.png) -8px 3px no-repeat; float:left;} +a.homepageSearchIcon:hover {background:url(../images/nav_icon.png) -49px 3px no-repeat;} +.navHomepageNews {width:30px; display:block; float:right; margin-top:12px; position:relative;} +.homepageNewsIcon {background:url(../images/nav_icon.png) -5px -85px no-repeat; width:30px; height:29px; display:block;} +.newsActive {width:10px; height:10px; border-radius:50%; border:2px solid #ffffff; background-color:#ff0000; position:absolute; left:17px; top:5px;} +.navHomepageProfile {width:65px; display:block; float:right; margin-top:8px; margin-left:33px;} +.homepageProfileMenuIcon {background:url(../images/nav_icon.png) -8px -175px no-repeat; width:20px; height:25px; float:left; margin-top:15px;} +a.homepageProfileMenuIcon:hover {background:url(../images/nav_icon.png) -8px -175px no-repeat; width:12px; height:12px; float:left;} +.homepageLeft {width:240px; float:left; margin-right:10px;} +.homepageRight {width:750px; float:left;} +.homepagePortraitContainer {width:238px; height:348px; border:1px solid #dddddd; background-color:#ffffff; margin-top:15px;} +.homepagePortraitImage {width:208px; height:208px; margin:15px 16px 14px 16px;} +.homepageFollow {} +.homepageEditProfile {} +.homepageImageName {font-size:16px; color:#484848; margin-left:15px; display:inline-block; margin-right:8px;} +.homepageImageSex {float:left; top:116px; left:5px; width:14px; height:14px; display:inline-block;} +.homepageSignature {font-size:12px; color:#888888; margin-left:15px; margin-top:5px; margin-bottom:15px;} +.homepageImageBlock {margin:0 26px; float:left; text-align:center; display:inline-block;} +.homepageImageNumber {font-size:12px; color:#484848;} +.homepageImageText {width:26px; font-size:12px; color:#888888;} +.homepageVerDiv {height:28px; vertical-align:middle; width:1px; float:left; display:inline-block; background-color:#d1d1d1; margin-top:3px;} +.homepageLeftMenuContainer {width:238px; border:1px solid #dddddd; border-bottom:none; background-color:#ffffff; margin-top:10px;} +.homepageLeftMenuBlock {border-bottom:1px solid #dddddd; height:50px; line-height:50px; vertical-align:middle;} +a.homepageMenuText {color:#484848; font-size:16px; margin-left:20px;} +.homepageLeftLabelContainer {width:238px; border:1px solid #dddddd; background-color:#ffffff; margin-top:10px;} +.homepageRightBanner {} +.newsType {width:60px; background-color:#ffffff; float:left; list-style:none; position:absolute; border:1px solid #eaeaea; border-radius:5px; top:35px; padding:5px 10px; left:-40px; font-size:12px; color:#888888; display:none; line-height:2;} +.homepageRightBlock {} +.homepageNewsList {width:710px; height:39px; line-height:39px; vertical-align:middle; border-bottom:1px dashed #eaeaea; margin:0 auto;} +.homepageNewsPortrait {width:40px; display:block; margin-top:7px;} +.homepageNewsPublisher {width:80px; max-width:80px; margin-right:10px; font-size:12px; color:#15bccf; display:block; padding-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis; } +.homepageNewsType {width:95px; font-size:12px; color:#888888; display:block;} +.homepageNewsTypeNotRead {width:95px; font-size:12px; color:#888888; display:block;} +.homepageNewsContent {width:395px; max-width:395px; margin-right:10px; font-size:12px; color:#4b4b4b; display:block; overflow:hidden; white-space: nowrap; text-overflow:ellipsis; overflow: hidden;height:49px; max-height:49px;} +.homepageNewsTime {width:75px; font-size:12px; color:#888888; display:block; text-align:right;} +a.homepageWhite {color:#ffffff;} +a.homepageWhite:hover {color:#a1ebff} +a.newsGrey {color:#4b4b4b;} +a.newsGrey:hover {color:#000000;} +a.newsBlue {color:#15bccf;} +a.newsBlue:hover {color:#0781b4;} +a.newsBlack {color:#4b4b4b; font-size:12px;} +a.newsBlack:hover {color:#0781b4;} +a.resourcesGrey {font-size:12px; color:#888888;} +a.resourcesGrey:hover {font-size:12px; color:#15bccf;} + + +/***** Flash & error messages ****/ +#errorExplanation, div.flash, .nodata, .warning, .conflict { + padding: 4px 4px 4px 30px; + margin-bottom: 12px; + font-size: 1.1em; + border: 2px solid; +} + +div.flash {margin-top: 8px;} + +div.flash.error, #errorExplanation { + background: url(../images/exclamation.png) 8px 50% no-repeat; + background-color: #ffe3e3; + border-color: #dd0000; + color: #880000; +} + +div.flash.notice { + background: url(../images/true.png) 8px 5px no-repeat; + background-color: #dfffdf; + border-color: #9fcf9f; + color: #005f00; +} + +div.flash.warning, .conflict { + background: url(../images/warning.png) 8px 5px no-repeat; + background-color: #FFEBC1; + border-color: #FDBF3B; + color: #A6750C; + text-align: left; +} + +.nodata, .warning { + text-align: center; + background-color: #FFEBC1; + border-color: #FDBF3B; + color: #A6750C; +} + +#errorExplanation ul { font-size: 0.9em;} +#errorExplanation h2, #errorExplanation p { display: none; } + +.conflict-details {font-size:80%;} +/***** end Flash & error messages ****/ + +/*消息铃铛样式*/ +.navHomepageNews {width:30px; display:block; float:right; margin-top:4px; position:relative; margin-right: 8px;} +.newsActive {width:6px; height:6px; border-radius:50%; border:2px solid #ffffff; background-color:#ff0000; position:absolute; left:20px; top:8px;z-index:999} diff --git a/public/stylesheets/users.css b/public/stylesheets/users.css index 81529288c..9a809b7ce 100644 --- a/public/stylesheets/users.css +++ b/public/stylesheets/users.css @@ -8,7 +8,7 @@ .icon_female{ background:url(../images/pic_uersall.png) 0 -24px no-repeat; width:15px; height:15px;} .pf_intro{ width:222px; margin-top:5px; color:#696969;word-break: break-all; } .leftbox{ width:230px; padding:10px; padding-right:0px; padding-bottom:5px;background:#fff; margin-bottom:10px; margin-right:10px;} -.pic_members{ background:url(../images/pic_users.jpg) 0 0 no-repeat; display:block; width:38px; height:38px; border:1px solid #e9edf0; margin-right:5px; margin-bottom:5px;float:left;} +.pic_members{ display:block; width:38px; height:38px; border:1px solid #e9edf0; margin-right:5px; margin-bottom:5px;float:left;} .pic_members:hover{border:1px solid #c9c9c9;} /*新建*/ .top_new{ height:26px; border-bottom:10px solid #eaebed; padding:10px; background:#fff; float:left; margin-left:10px; width:730px; } @@ -24,12 +24,14 @@ a.icon_face{background:url(../images/public_icon.png) 0px -671px no-repeat; dis a:hover.icon_face{background:url(../images/public_icon.png) -79px -671px no-repeat; } .inputUsers_message{ border:1px solid #d2d2d2; width:718px; height:48px; color:#666; padding:5px; margin-bottom:5px;} .inputUsers_message02{ border:1px solid #d2d2d2; width:618px; height:26px; color:#666; padding:5px; margin-bottom:5px; } -.message_list_box{ background:#f5f5f5; padding:10px;} -.users_pic{ width:27px; height:27px; border:1px solid #e3e3e3;} +.message_list_box{ background:#f5f5f5; padding:10px;margin-top: 10px;} +.users_pic{ width:46px; height:46px; border:1px solid #e3e3e3;} .users_pic:hover{ border:1px solid #a5a5a5;} +.users_pic_sub{width:32px; height:32px; border:1px solid #e3e3e3;} +.users_pic_sub:hover{ border:1px solid #a5a5a5;} .massage_txt{ max-width:360px; color: #666;word-break:break-all;} .massage_time{ color:#8d8d8d; margin-top:5px;} -.message_list{ border-bottom:1px dashed #c9c9c9; padding-bottom:10px; margin-bottom:10px;} +.message_list{ border-bottom:1px dashed #c9c9c9; margin-bottom:10px;color: #5f5f5f;} .message_list_more{ text-align:center; width:720px;} /*课程动态*/ .line_box{ width:728px; border:1px solid #d9d9d9; padding-bottom:10px;} @@ -89,15 +91,17 @@ a.select_btn_select{ background:#64bddb; color:#fff;} .users_ctt input,.users_ctt select,.users_ctt textarea{ border:1px solid #CCC;} .users_ctt input,.users_ctt select,.users_ctt option{ height:26px;} .users_ctt input,.users_ctt textarea{ margin-left:2px;} -.users_ctt textarea{ margin-bottom:none;} +/*.users_ctt textarea{ margin-bottom:nor;}*/ .w450{ width:450px;} .w210{ width:200px;} .w70{ width:70px;} .h200{ height:200px;} /* 个人主页*/ -a.gz_btn{display:block; background:url(../images/pic_uersall.png) -318px -25px no-repeat; width:33px; height:18px; border:1px solid #cdcdcd; color:#333333; padding:0px 0 0 18px;} +a.edit_btn{display:block; background:url(../images/leftside.png) -1px 0 no-repeat; width:33px; height:18px; border:1px solid #cdcdcd; color:#333333; padding:0px 0 0 18px;} +a:hover.edit_btn{ color:#ff5722;} +a.gz_btn{display:block; background:url(../images/pic_uersall.png) -318px -25px no-repeat; width:53px; height:18px; border:1px solid #cdcdcd; color:#333333; padding:0px 0 0 18px;} a:hover.gz_btn{ color:#ff5722;} -a.qx_btn{display:block; background:url(../images/pic_uersall.png) -318px -47px no-repeat; width:33px; height:18px; border:1px solid #cdcdcd; color:#333333; padding:0px 0 0 18px;} +a.qx_btn{display:block; background:url(../images/pic_uersall.png) -318px -47px no-repeat; width:53px; height:18px; border:1px solid #cdcdcd; color:#333333; padding:0px 0 0 18px;} a:hover.qx_btn{color:#64bdd9;} a.c_lgrey{ color:#CCC;} a:hover.c_lgrey{ color:#3ca5c6;} @@ -113,7 +117,7 @@ a:hover.c_lgrey{ color:#3ca5c6;} /* 20150506上传头像*/ .uppicBox{ width:265px; height:265px; background:#f2f2f5; float:left; color:#666; text-align:center;} .showpicBox{width:133px; height:250px; background:#f2f2f5; float:left; margin-left:20px; text-align:center; padding-top:15px; color:#666;} -.mr2{ margin-right:2px;} +.mr15{ margin-right:15px;} .uppic_btn{border:none; width:150px; background:none; margin-bottom:5px; color:#666; margin-top:105px;} /* 新建作品*/ .mr8{ margin-right:8px;} @@ -123,5 +127,21 @@ a:hover.c_lgrey{ color:#3ca5c6;} .newhwork_div input,.newhwork_div select{ height:26px;border:1px solid #CCC; } .newhwork_div textarea{border:1px solid #CCC;} .w460{ width:460px;} +/* 留言新增*/ +.mes_box{ width:580px;} +.mes_box02{ margin-left:50px; border-top:1px dashed #c9c9c9; padding-top:10px;margin-bottom: 10px;} +.mes_box02_info{ width:540px; margin-left:5px;} +.users_r_top{ width:730px; height:40px; background:#eaeaea; margin-bottom:10px;} +.users_r_h2{background:#64bdd9; color:#fff; height:33px; width:90px; text-align:center; font-weight:normal; padding-top:7px; font-size:16px;} -a.hidepic>img{display:none;} \ No newline at end of file + +a.hidepic>img{display:none;} + +div.ke-toolbar{display:none;width:400px;border:none;background:none;padding:0px 0px;} +span.ke-toolbar-icon{line-height:26px;font-size:14px;padding-left:26px;} +span.ke-toolbar-icon-url{background-image:url( ../images/public_icon.png )} +div.ke-toolbar .ke-outline{padding:0px 0px;line-height:26px;font-size:14px;} +span.ke-icon-emoticons{background-position:0px -671px;width:50px;height:26px;} +span.ke-icon-emoticons:hover{background-position:-79px -671px;width:50px;height:26px;} +div.ke-toolbar .ke-outline{border:none;} +.cr{clear: right;} \ No newline at end of file diff --git a/public/themes/redpenny-master/stylesheets/application.css b/public/themes/redpenny-master/stylesheets/application.css index 4a23e59c5..1b32d4659 100644 --- a/public/themes/redpenny-master/stylesheets/application.css +++ b/public/themes/redpenny-master/stylesheets/application.css @@ -443,7 +443,6 @@ color: #000000; width:auto; /*float:center;*/ min-height:800px; - border: 1px solid #ffffff; } /*by huang*/ @@ -1122,6 +1121,11 @@ a.root { line-height: 1; } +.courses{ + margin:0px; + padding-left: 0em; +} + .project-table { margin-left: auto; margin-right: auto; diff --git a/spec/factories/course_messages.rb b/spec/factories/course_messages.rb new file mode 100644 index 000000000..7b2523adc --- /dev/null +++ b/spec/factories/course_messages.rb @@ -0,0 +1,10 @@ +FactoryGirl.define do + factory :course_message do + user_id 1 +course_id 1 +course_message_id 1 +course_message_type "MyString" +viewed 1 + end + +end diff --git a/spec/factories/forge_messages.rb b/spec/factories/forge_messages.rb new file mode 100644 index 000000000..05bc84cc1 --- /dev/null +++ b/spec/factories/forge_messages.rb @@ -0,0 +1,10 @@ +FactoryGirl.define do + factory :forge_message do + user_id 1 +project_id 1 +forge_message_id 1 +forge_message_type "MyString" +viewed 1 + end + +end diff --git a/spec/factories/memo_messages.rb b/spec/factories/memo_messages.rb new file mode 100644 index 000000000..edd5f7f54 --- /dev/null +++ b/spec/factories/memo_messages.rb @@ -0,0 +1,10 @@ +FactoryGirl.define do + factory :memo_message do + user_id 1 +forum_id 1 +memo_id 1 +memo_type "MyString" +viewed 1 + end + +end diff --git a/spec/factories/user_feedback_messages.rb b/spec/factories/user_feedback_messages.rb new file mode 100644 index 000000000..26a768dad --- /dev/null +++ b/spec/factories/user_feedback_messages.rb @@ -0,0 +1,9 @@ +FactoryGirl.define do + factory :user_feedback_message do + user_id 1 +journals_for_message_id 1 +journals_for_message_type "MyString" +viewed 1 + end + +end diff --git a/spec/models/course_message_spec.rb b/spec/models/course_message_spec.rb new file mode 100644 index 000000000..cddcdc0a1 --- /dev/null +++ b/spec/models/course_message_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe CourseMessage, :type => :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/forge_message_spec.rb b/spec/models/forge_message_spec.rb new file mode 100644 index 000000000..ce6cd7e26 --- /dev/null +++ b/spec/models/forge_message_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ForgeMessage, :type => :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/memo_message_spec.rb b/spec/models/memo_message_spec.rb new file mode 100644 index 000000000..a7921fc84 --- /dev/null +++ b/spec/models/memo_message_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe MemoMessage, :type => :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/user_feedback_message_spec.rb b/spec/models/user_feedback_message_spec.rb new file mode 100644 index 000000000..4ea61c36a --- /dev/null +++ b/spec/models/user_feedback_message_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe UserFeedbackMessage, :type => :model do + pending "add some examples to (or delete) #{__FILE__}" +end