实训任务详情页面的一级回复功能

This commit is contained in:
daiao 2017-02-21 14:38:05 +08:00
parent e4b582fbb7
commit 544432adce
15 changed files with 217 additions and 75 deletions

View File

@ -29,6 +29,8 @@ class AtController < ApplicationController
case type
when "Issue"
find_issue(id)
whne 'TrainingTask'
find_training_task(id)
when 'Project'
find_project(id)
when 'Course'
@ -69,6 +71,13 @@ class AtController < ApplicationController
at_persons.uniq { |u| u.id }.delete_if { |u| u.id == User.current.id }
end
def find_training_task(id)
training_task = TrainingTask.find(id)
journals = training_task.journals
at_persons = journals.map(&:user) + training_task.project.users
at_persons.uniq { |u| u.id }.delete_if { |u| u.id == User.current.id }
end
def find_project(id)
return [] if id.to_i<0
at_persons = Project.find(id).users

View File

@ -88,6 +88,7 @@ class TrainingTasksController < ApplicationController
@journal = Journal.new(:journalized => @training_task)
respond_to do |format|
format.html
format.js
end
end
@ -358,19 +359,19 @@ class TrainingTasksController < ApplicationController
jour = Journal.new
jour.user_id = User.current.id
jour.notes = params[:notes]
jour.journalized = @issue
jour.journalized = @training_task
jour.save_attachments(params[:attachments])
jour.save
update_user_activity(@issue.class,@issue.id)
update_forge_activity(@issue.class,@issue.id)
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
update_user_activity(@training_task.class, @training_task.id)
update_forge_activity(@training_task.class, @training_task.id)
# @allowed_statuses = @training_task.new_statuses_allowed_to(User.current)
@user_activity_id = params[:user_activity_id]
@priorities = IssuePriority.active
respond_to do |format|
# Issue详情单独处理
if params[:is_issue_show]
format.js{redirect_to issue_path(@issue)}
format.js{ redirect_to training_task_path(@training_task) }
else
format.js
end
@ -397,7 +398,7 @@ class TrainingTasksController < ApplicationController
#对某个journ回复,显示回复框
def reply
@issue = Issue.find(params[:id])
@training_task = TrainingTask.find(params[:id])
@jour = Journal.find(params[:journal_id])
respond_to do |format|
format.js
@ -408,25 +409,25 @@ class TrainingTasksController < ApplicationController
def add_reply
if User.current.logged?
jour = Journal.find(params[:journal_id])
@issue = Issue.find params[:id]
@project = @issue.project
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@training_task = TrainingTask.find params[:id]
@project = @training_task.project
@allowed_statuses = @training_task.new_statuses_allowed_to(User.current)
@priorities = IssuePriority.active
new_jour = Journal.new
new_jour.user_id = User.current.id
new_jour.reply_id = params[:journal_id]
new_jour.parent_id = jour.id
new_jour.notes = params[:content]
new_jour.journalized = @issue
new_jour.journalized = @training_task
new_jour.save_attachments(params[:attachments])
# new_jour = @issue.journals.build(:user_id => User.current.id, :reply_id => params[:journal_id], :notes => params[:content], :parent_id => jour.id)
@user_activity_id = params[:user_activity_id]
if new_jour.save
update_user_activity(@issue.class,@issue.id)
update_forge_activity(@issue.class,@issue.id)
update_user_activity(@training_task.class,@issue.id)
update_forge_activity(@training_task.class,@issue.id)
respond_to do |format|
if params[:is_issue_show]
format.js{redirect_to issue_path(@issue)}
format.js{ redirect_to project_training_task_path(@training_task) }
else
format.js
end

View File

@ -1,2 +1,44 @@
module TrainingTasksHelper
include ApplicationHelper
include TagsHelper
require 'iconv'
# Returns the textual representation of a journal details
# as an array of strings
def details_to_strings(details, no_html=false, options={})
options[:only_path] = (options[:only_path] == false ? false : true)
options[:token] = options[:token] if options[:token]
strings = []
values_by_field = {}
details.each do |detail|
if detail.property == 'cf'
field_id = detail.prop_key
field = CustomField.find_by_id(field_id)
if field && field.multiple?
values_by_field[field_id] ||= {:added => [], :deleted => []}
if detail.old_value
values_by_field[field_id][:deleted] << detail.old_value
end
if detail.value
values_by_field[field_id][:added] << detail.value
end
next
end
end
strings << show_detail(detail, no_html, options)
end
values_by_field.each do |field_id, changes|
detail = JournalDetail.new(:property => 'cf', :prop_key => field_id)
if changes[:added].any?
detail.value = changes[:added]
strings << show_detail(detail, no_html, options)
elsif changes[:deleted].any?
detail.old_value = changes[:deleted]
strings << show_detail(detail, no_html, options)
end
end
strings
end
end

View File

@ -23,7 +23,8 @@ class Journal < ActiveRecord::Base
belongs_to :journalized, :polymorphic => true,:touch => true
# added as a quick fix to allow eager loading of the polymorphic association
# since always associated to an issue, for now
belongs_to :issue, :foreign_key => :journalized_id,:touch => true
belongs_to :issue, :foreign_key => :journalized_id, :touch => true
belongs_to :training_task, :foreign_key => :journalized_id, :touch => true
belongs_to :user
has_many :details, :class_name => "JournalDetail", :dependent => :delete_all
@ -192,6 +193,7 @@ class Journal < ActiveRecord::Base
def act_as_forge_message
receivers = []
# 直接回复
if self.journalized_type == 'Issue'
if self.user_id != self.issue.author_id
receivers << self.issue.author_id
end
@ -201,10 +203,19 @@ class Journal < ActiveRecord::Base
receivers.each do |r|
self.forge_messages << ForgeMessage.new(:user_id => r, :project_id => self.issue.project_id, :viewed => false)
end
elsif self.journalized_type == 'TrainingTask'
if self.user_id != self.training_task.author_id
receivers << self.training_task.author_id
end
receivers.each do |r|
self.forge_messages << ForgeMessage.new(:user_id => r, :project_id => self.training_task.project, :viewed => false)
end
end
end
# 更新用户分数 -by zjc
def be_user_score
if (self.journalized_type == 'Issue')
#新建了缺陷留言且留言不为空,不为空白
if !self.notes.nil? && self.notes.gsub(' ','') != ''
#协同得分加分
@ -212,7 +223,14 @@ class Journal < ActiveRecord::Base
update_messges_for_issue(self.user,1)
update_messges_for_issue(self.user,2,self.issue.project)
end
elsif( self.journalized_type == 'TrainingTask')
if !self.notes.nil? && self.notes.gsub(' ','') != ''
#协同得分加分
UserScore.joint(:post_issue_message, self.user, self.training_task.author, self, { message_id: self.id })
update_messges_for_issue(self.user, 1)
update_messges_for_issue(self.user, 2, self.training_task.project)
end
end
end
# 减少用户分数 -by zjc
def down_user_score
@ -237,12 +255,18 @@ class Journal < ActiveRecord::Base
# issue留言总数更新
def add_journals_count
if self.journalized_type == 'Issue'
if !self.issue.project.nil? && self.journalized_type == "Issue" && !self.issue.project.project_score.nil?
project = self.issue.project
project.project_score.update_attribute(:issue_journal_num, project.project_score.issue_journal_num + 1)
end
elsif self.journalized_type == 'TrainingTask'
if !self.training_task.project.nil? && self.journalized_type == "TrainingTask" && !self.training_task.project.project_score.nil?
project = self.training_task.project
project.project_score.update_attribute(:issue_journal_num, project.project_score.issue_journal_num + 1)
end
end
end
# 回复issue的时候更新issue的时候
def update_issue_time
if self.journalized_type == "Issue"

View File

@ -1,11 +1,23 @@
<% if PraiseTread.praised(activity) %>
<a href='<%= praise_tread_praise_plus_path({:obj_id=>activity.id,:obj_type=>activity.class,:user_activity_id=>user_activity_id,:type=>type }) %>' data-remote="true" class="<%=type == 'reply'? 'fr' : 'ml15' %> likeButton" title="点赞" >
<a href='<%= praise_tread_praise_plus_path({:obj_id => activity.id,
:obj_type => activity.class,
:user_activity_id => user_activity_id,
:type => type }) %>'
data-remote="true"
class="<%= type == 'reply'? 'fr' : 'ml15' %> likeButton"
title="点赞" >
<span class="likeText">赞</span>
<% num = activity.praise_tread_cache ? activity.praise_tread_cache.praise_num : 0 %>
<span class="likeNum"><%= (num.nil? ? 0 : num) > 0 ? "#{(num.nil? ? 0 : num)}" : "" %></span>
</a>
<% else %>
<a href='<%= praise_tread_praise_minus_path({:obj_id=>activity.id,:obj_type=>activity.class,:user_activity_id=>user_activity_id,:type=>type }) %>' data-remote="true" class="<%=type == 'reply'? 'fr' : 'ml15' %> likeButton" title="取消点赞" >
<a href='<%= praise_tread_praise_minus_path({:obj_id => activity.id,
:obj_type => activity.class,
:user_activity_id => user_activity_id,
:type => type }) %>'
data-remote="true"
class="<%= type == 'reply'? 'fr' : 'ml15' %> likeButton"
title="取消点赞" >
<span class="likeText">已赞</span>
<% num = activity.praise_tread_cache ? activity.praise_tread_cache.praise_num : 0 %>
<span class="likeNum"><%= (num.nil? ? 0 : num) > 0 ? "#{(num.nil? ? 0 : num)}" : "" %></span>

View File

@ -4,19 +4,7 @@
</div>
<div class="talk_txt fl">
<p class="pro_page_tit" style="word-break:break-all;">
<% case @training_task.tracker_id %>
<% when 1%>
<span class="fl" title="缺陷">【缺陷】</span>
<% when 2%>
<span class="fl" title="功能">【功能】</span>
<% when 3%>
<span class="fl" title="支持">【支持】</span>
<% when 4%>
<span class="fl" title="任务">【任务】</span>
<% when 5%>
<span class="fl" title="周报">【周报】</span>
<% end %>
</span> <span style="padding-left: 5px;"><%= @training_task.subject %></span></p>
<span style="padding-left: 5px;"><%= @training_task.subject %></span></p>
<!--<span class='<%#= "#{get_issue_priority(@training_task.priority_id)[0]} " %>'><%#= get_issue_priority(@training_task.priority_id)[1] %></span></p>-->
<br>
<div class="cl"></div>
@ -38,8 +26,8 @@
<% end -%>
<%# 附件局部刷新 %>
<div id = "div_issue_attachment_<%=@training_task.id %>">
<%= render :partial => 'task_attachments',:locals => {:training_task => @training_task} %>
<div id = "div_issue_attachment_<%= @training_task.id %>">
<%= render :partial => 'task_attachments', :locals => {:training_task => @training_task} %>
</div>
<!--属性-->
<%#= render :partial => 'issues/attributes_show' %>

View File

@ -10,7 +10,7 @@
<div class="homepagePostReplyPortrait" >
<%= link_to image_tag(url_to_avatar(comment.user), :width => "33", :height => "33"), user_path(comment.user_id), :alt => "用户头像" %>
</div>
<div class="reply-content ml15" onmouseover="$('#delete_reply_<%=comment.id %>').show();" onmouseout="$('#delete_reply_<%=comment.id %>').hide();">
<div class="reply-content ml15" onmouseover="$('#delete_reply_<%= comment.id %>').show();" onmouseout="$('#delete_reply_<%= comment.id %>').hide();">
<%= render :partial => 'users/news_contents', :locals => {:comment => comment, :type => 'Issue', :user_activity_id => issue.id}%>
<div class="homepagePostReplyContent break_word list_style upload_img table_maxWidth" id="reply_content_<%= comment.id %>">
@ -28,17 +28,22 @@
<%= render :partial => "praise_tread/praise", :locals => {:activity => comment, :user_activity_id => comment.id, :type => "reply"} %>
</span>
<span style="position: relative" class="fr mr20">
<%= link_to(
l(:button_reply),
{:controller => 'training_tasks', :action => 'reply', :user_id => comment.user_id, :id => issue.id, :journal_id => comment.id},
<%= link_to(l(:button_reply),
{:controller => 'training_tasks',
:action => 'reply',
:user_id => comment.user_id,
:id => @training_task.id,
:journal_id => comment.id},
:remote => true,
:method => 'get',
:title => l(:button_reply)) %>
<span id="reply_iconup_<%= comment.id %>" class="reply_iconup02" style="display: none"> ︿</span>
</span>
<%= link_to(
l(:button_delete),
{:controller => 'training_tasks',:action => 'delete_journal', :id => issue.id, :journal_id=>comment.id},
<%= link_to(l(:button_delete),
{:controller => 'training_tasks',
:action => 'delete_journal',
:id => @training_task.id,
:journal_id=>comment.id},
:method => :get,
:remote => true,
:id => "delete_reply_#{comment.id}",
@ -50,7 +55,7 @@
<div class="cl"></div>
</div>
</div>
<p id="reply_message_<%= comment.id%>"></p>
<p id="reply_message_<%= comment.id %>"></p>
</div>
<div class="cl"></div>
</li>

View File

@ -1,5 +1,6 @@
<% count = @training_task.journals.count %>
回复<sapn class="mr15"><%= count>0 ? "#{count}" : "" %></sapn><span style="color: #cecece;">▪</span>
回复<span class="mr15"><%= count > 0 ? "#{count}" : "" %></span>
<span style="color: #cecece;">▪</span>
<span id="praise_count_<%= @training_task.id %>">
<%=render :partial=> "praise_tread/praise", :locals => {:activity => @training_task, :user_activity_id=> @training_task.id, :type => "activity"}%>
<%=render :partial => "praise_tread/praise", :locals => {:activity => @training_task, :user_activity_id => @training_task.id, :type => "activity"}%>
</span>

View File

@ -0,0 +1,27 @@
<div class="ReplyToMessageContainer borderBottomNone " id="reply_to_message_<%= @jour.id %>" style="width:895px;">
<div class="homepagePostReplyPortrait mr15 imageFuzzy" id="reply_image_<%= @jour.id%>">
<%= link_to image_tag(url_to_avatar(User.current), :width => "33", :height => "33"), user_path(@training_task.author_id), :alt => "用户头像" %>
</div>
<div class="ReplyToMessageInputContainer">
<% if User.current.logged? %>
<div nhname='new_message_<%= @jour.id %>' style="display:none;">
<%= form_for('new_form',:url => add_reply_training_tasks_path(@training_task.id, :is_issue_show => true),:method => "post", :remote => true) do |f|%>
<input type="hidden" name="journal_id" value="<%= @jour.id %>"/>
<div nhname='toolbar_container_<%= @jour.id %>' ></div>
<div class="cl"></div>
<textarea placeholder="有问题或有建议,请直接给我留言吧!" style="display: none" nhname='new_message_textarea_<%= @jour.id%>' name="content"></textarea>
<div class="cl"></div>
<span nhname='contentmsg_<%= @jour.id %>' class="fl"></span>
<a id="new_message_submit_btn_<%= @jour.id %>" href="javascript:void(0)" onclick="this.style.display='none'" class="blue_n_btn fr" style="display:none;margin-top:6px;">发送</a>
<div class="cl"></div>
<% end %>
</div>
<% else %>
<%= render :partial => "users/show_unlogged" %>
<% end %>
<div class="cl"></div>
</div>
</div>

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,8 @@
if($("#reply_message_<%= @jour.id %>").length > 0) {
$("#reply_message_<%= @jour.id %>").replaceWith("<%= escape_javascript(render :partial => 'training_tasks/training_tasks_reply_ke_form') %>");
$(function(){
sd_create_editor_from_data(<%= @jour.id %>, null, "100%", "<%= @jour.class.name %>");
});
}else if($("#reply_to_message_<%= @jour.id %>").length >0) {
$("#reply_to_message_<%= @jour.id %>").replaceWith("<p id='reply_message_<%= @jour.id %>'></p>");
}

View File

@ -3,13 +3,13 @@
<%= javascript_include_tag 'create_kindeditor'%>
<% end %>
<script>
sd_create_editor_from_data(<%= @training_task.id%>, null, "100%", "<%= @training_task.class.name %>");
sd_create_editor_from_data(<%= @training_task.id %>, null, "100%", "<%= @training_task.class.name %>");
</script>
<div class="mt10 mb10" id =issue_show_total"">
<div class="banner-big f16 fontGrey3">
任务详情
<a href="<%= new_project_training_task_path(@project)%>" class="sy_btn_green fr" >新建</a>
<a href="<%= new_project_training_task_path(@project) %>" class="sy_btn_green fr" >新建</a>
</div>
<div class="container-big mt10" style="float:left;">
@ -23,15 +23,15 @@
<!--problem_main end-->
<div style="clear: both;"></div>
<div class="container-big-grey">
<div class="topBorder" style="display: <%= @training_task.journals.count>0 ? 'none': '' %>"></div>
<div class="topBorder" style="display: <%= @training_task.journals.count > 0 ? 'none': '' %>"></div>
<div class="reply-banner" >
<div class="homepagePostReplyBannerCount">
<%=render :partial => 'reply_banner' %>
<div class="homepagePostReplyBannerCount" id="training_task_reply_banner">
<%= render :partial => 'reply_banner' %>
</div>
<div class="homepagePostReplyBannerTime"></div>
</div>
<div class="" id="reply_div_<%= @training_task.id %>" >
<%= render :partial => 'issue_replies',:locals => {:issue => @training_task, :replies_all_i => 0} %>
<%= render :partial => 'issue_replies',:locals => {:issue => @training_task, :replies_all_i => 0 } %>
</div>
</div>
</div>

View File

@ -0,0 +1,19 @@
// $("#div_user_issue_reply_<%#= @user_activity_id %>").html("<%#= escape_javascript(render :partial => 'projects/project_issue_reply', :locals => {:activity => @issue, :user_activity_id => @user_activity_id}) %>");
$("#reply_div_<%= @training_task.id %>").html("<%= escape_javascript(render :partial => 'training_tasks/issue_replies', :locals => {:issue => @training_task}) %>");
$("#div_issue_attachment_<%=@training_task.id %>").html("<%= escape_javascript(render :partial => 'issues/issue_attachments', :locals => {:issue => @training_task}) %>");
issue_desc_editor = KindEditor.create('#issue_description',
{"width":"85%",
"resizeType":0,
"no_label":true,
"at_id":<%= @training_task.project_id%>,
"at_type":"Project",
"autoHeightMode":true,
"afterCreate":"eval(function(){ if(typeof enablePasteImg ==='function'){enablePasteImg(self);};if(typeof enableAt ==='function'){enableAt(self, \"<%= @training_task.project_id %>\", 'Project');}; this.loadPlugin('autoheight')})",
"emotionsBasePath":'<%= Setting.host_name%>',
"height":300,
"allowFileManager":true,
"uploadJson":"/kindeditor/upload",
"fileManagerJson":"/kindeditor/filemanager"});
$(".homepagePostReplyBannerCount").html('<%= escape_javascript(render :partial => 'reply_banner') %>');
sd_create_editor_from_data(<%= @training_task.id %>, null, "100%", "<%= @training_task.class.name %>");

View File

@ -1099,6 +1099,11 @@ RedmineApp::Application.routes.draw do
post 'complete_training_task'
end
collection do
post 'add_journal'
post 'add_journal_in_org'
get 'delete_journal'
get 'reply'
post 'add_reply'
end
end