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/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/issue.rb b/app/models/issue.rb index 147e26cef..66627c00a 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,7 +82,7 @@ class Issue < ActiveRecord::Base attr_reader :current_journal # fq - after_create :act_as_activity,:be_user_score_new_issue,:act_as_forge_activity + after_create :act_as_activity,:be_user_score_new_issue,:act_as_forge_activity, :act_as_forge_message after_update :be_user_score after_destroy :down_user_score # after_create :be_user_score @@ -138,6 +140,16 @@ 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 # Returns a SQL conditions string used to find all issues visible by the specified user diff --git a/app/models/journal.rb b/app/models/journal.rb index 3b660132e..c705b1a09 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,17 @@ 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 + self.forge_messages << ForgeMessage.new(:user_id => self.issue.author_id, + :project_id => self.issue.project_id, + :viewed => false) + end + # 更新用户分数 -by zjc def be_user_score #新建了缺陷留言且留言不为空,不为空白 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/user.rb b/app/models/user.rb index 1cd0675c8..3cd248c8a 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,14 @@ class User < Principal has_many :messages, :foreign_key => 'author_id' has_one :user_score, :dependent => :destroy has_many :documents # 项目中关联的文档再次与人关联 +# 关联虚拟表 + has_many :forge_messages # end +# 虚拟转换 + 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 @@ -235,6 +240,24 @@ 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 issue_status_update + self.status_updates + end + # end + def extensions self.user_extensions ||= UserExtensions.new end @@ -258,7 +281,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 @@ -292,11 +315,6 @@ class User < Principal end ## end - # 查询用户未读过的记录 - def count_new_jour - count = self.journals_for_messages.where("status=?", 1).count - end - #added by nie def count_new_journal_reply count = self.journal_reply.count diff --git a/app/views/layouts/_base_header.html.erb b/app/views/layouts/_base_header.html.erb index c6ba7cf10..8dbacb523 100644 --- a/app/views/layouts/_base_header.html.erb +++ b/app/views/layouts/_base_header.html.erb @@ -37,6 +37,7 @@ {:controller=> 'users', :action => 'user_newfeedback', id: User.current.id, host: Setting.host_user}, {:class => 'my-message'} if User.current.logged?%> + <% end -%> diff --git a/app/views/layouts/_new_header.html.erb b/app/views/layouts/_new_header.html.erb index 5fbf3638d..f6f09e075 100644 --- a/app/views/layouts/_new_header.html.erb +++ b/app/views/layouts/_new_header.html.erb @@ -53,6 +53,50 @@ + + +
  • + <%= link_to "#{l(:label_forge_message)}".html_safe %> + +
  • + <% end -%> <%= header_render_menu :account_menu -%> diff --git a/config/locales/projects/zh.yml b/config/locales/projects/zh.yml index e47cd476c..bd3815375 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: 发布问题 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/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/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/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