faculty note support in new inbox

also pull in course/group user so we can use it in the future

Change-Id: I34c2aea2fea9b56c988d4903fb2fcf32d96d4f10
Reviewed-on: https://gerrit.instructure.com/5190
Reviewed-by: Jon Jensen <jon@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
This commit is contained in:
Jon Jensen 2011-08-20 18:16:40 -06:00
parent b77558c281
commit 274f8880ad
14 changed files with 167 additions and 59 deletions

View File

@ -20,6 +20,8 @@ class TokenInput
@tokens.html('')
@change?(@token_values())
@added = @options.added
@placeholder = $('<span />')
@placeholder.text(@options.placeholder)
@placeholder.appendTo(@fake_input) if @options.placeholder
@ -95,6 +97,7 @@ class TokenInput
@tokens.append($token)
@val('') unless data?.no_clear
@placeholder.hide()
@added?(data.data) if data
@change?(@token_values())
@selector?.reposition()
@ -393,7 +396,7 @@ class TokenSelector
state = !@input.has_token(value: id) unless state?
if state
@selection.addClass('on') if @selection_toggleable()
@input.add_token value: id, text: @selection.find('b').text(), no_clear: true
@input.add_token value: id, text: @selection.find('b').text(), no_clear: true, data: @selection.data('user_data')
else
@selection.removeClass('on')
@input.remove_token value: id
@ -538,6 +541,7 @@ I18n.scoped 'conversations', (I18n) ->
$form.attr action: $selected_conversation.find('a.details_link').attr('add_url')
reset_message_form()
$form.find('#user_note_info').showIf($selected_conversation?.hasClass('private')).find('input').attr('checked', false)
$form.show().find(':input:visible:first').focus()
reset_message_form = ->
@ -594,7 +598,7 @@ I18n.scoped 'conversations', (I18n) ->
$selected_conversation.scrollIntoView()
else
if params and params.user_id and params.user_name
$('#recipients').data('token_input').add_token value: params.user_id, text: params.user_name
$('#recipients').data('token_input').add_token value: params.user_id, text: params.user_name, data: {id: params.user_id, name: params.user_name, can_add_notes: params.can_add_notes}
$('#from_conversation_id').val(params.from_conversation_id)
return
@ -603,7 +607,7 @@ I18n.scoped 'conversations', (I18n) ->
completion = (data) ->
return unless is_selected($c)
for user in data.participants when !MessageInbox.user_cache[user.id]
for user in data.participants when !MessageInbox.user_cache[user.id]?.avatar
MessageInbox.user_cache[user.id] = user
user.html_name = html_name_for_user(user)
$messages.show()
@ -634,8 +638,8 @@ I18n.scoped 'conversations', (I18n) ->
$form.loadingImage('remove')
MessageInbox.shared_contexts_for_user = (user, limit=2) ->
shared_contexts = (course.name for course_id in user.course_ids when course = @contexts.courses[course_id]).
concat(group.name for group_id in user.group_ids when group = @contexts.groups[group_id])
shared_contexts = (course.name for course_id, roles of user.common_courses when course = @contexts.courses[course_id]).
concat(group.name for group_id, roles of user.common_groups when group = @contexts.groups[group_id])
shared_contexts.sort (a, b) ->
a = a.toLowerCase()
b = b.toLowerCase()
@ -651,6 +655,12 @@ I18n.scoped 'conversations', (I18n) ->
shared_contexts = MessageInbox.shared_contexts_for_user(user)
$.htmlEscape(user.name) + if shared_contexts.length then " <em>" + $.htmlEscape(shared_contexts) + "</em>" else ''
can_add_notes_for = (user) ->
return true if user.can_add_notes
for course_id, roles of user.common_courses
return true if 'StudentEnrollment' in roles and (MessageInbox.can_add_notes or MessageInbox.contexts.courses[course_id]?.can_add_notes)
false
build_message = (data) ->
$message = $("#message_blank").clone(true).attr('id', 'message_' + data.id)
$message.data('id', data.id)
@ -1287,6 +1297,11 @@ I18n.scoped 'conversations', (I18n) ->
$('.recipients').tokenInput
placeholder: I18n.t('recipient_field_placeholder', "Enter a name, course, or group")
added: (data) ->
unless data.id and "#{data.id}".match(/^(course|group)_/)
data = $.extend({}, data)
delete data.avatar # since it's the wrong size and possibly a blank image
MessageInbox.user_cache[data.id] ?= data
selector:
messages: {no_results: I18n.t('no_results', 'No results found')}
populator: ($node, data, options={}) ->
@ -1297,10 +1312,11 @@ I18n.scoped 'conversations', (I18n) ->
$b = $('<b />')
$b.text(data.name)
$span = $('<span />')
$span.text(MessageInbox.shared_contexts_for_user(data)) if data.course_ids?
$span.text(MessageInbox.shared_contexts_for_user(data)) if data.common_courses?
$node.append($b, $span)
$node.attr('title', data.name)
$node.data('id', data.id)
$node.data('user_data', data)
$node.addClass(if data.type then data.type else 'user')
if options.level > 0
$node.prepend('<a class="toggle"><i></i></a>')
@ -1322,9 +1338,11 @@ I18n.scoped 'conversations', (I18n) ->
if tokens.length > 1 or tokens[0]?.match(/^(course|group)_/)
$form.find('#group_conversation').attr('checked', true) if !$form.find('#group_conversation_info').is(':visible')
$form.find('#group_conversation_info').show()
$form.find('#user_note_info').hide()
else
$form.find('#group_conversation').attr('checked', true)
$form.find('#group_conversation_info').hide()
$form.find('#user_note_info').showIf((user = MessageInbox.user_cache[tokens[0]]) and can_add_notes_for(user))
$(window).resize inbox_resize
setTimeout inbox_resize

View File

@ -84,7 +84,6 @@ class ConversationsController < ApplicationController
recipients = Array(recipients)
@conversation = @current_user.initiate_conversation(recipients)
@message = create_message_on_conversation(@conversation, !batch_private_messages)
@message.generate_user_note if params[:user_note]
@conversation
end
if batch_private_messages
@ -245,16 +244,20 @@ class ConversationsController < ApplicationController
def load_all_contexts
@contexts = {:courses => {}, :groups => {}}
@current_user.concluded_courses.each do |course|
@contexts[:courses][course.id] = {:id => course.id, :name => course.name, :type => :course, :active => course.recently_ended? }
@contexts[:courses][course.id] = {:id => course.id, :name => course.name, :type => :course, :active => course.recently_ended?, :can_add_notes => can_add_notes_to?(course) }
end
@current_user.courses.each do |course|
@contexts[:courses][course.id] = {:id => course.id, :name => course.name, :type => :course, :active => true }
@contexts[:courses][course.id] = {:id => course.id, :name => course.name, :type => :course, :active => true, :can_add_notes => can_add_notes_to?(course) }
end
@current_user.groups.each do |group|
@contexts[:groups][group.id] = {:id => group.id, :name => group.name, :type => :group, :active => group.active? }
end
end
def can_add_notes_to?(course)
course.enable_user_notes && course.grants_right?(@current_user, nil, :manage_user_notes)
end
def matching_contexts(search, exclude = [])
avatar_url = avatar_url_for_group(true)
@contexts.values.map(&:values).flatten.
@ -311,13 +314,13 @@ class ConversationsController < ApplicationController
end
def jsonify_users(users, blank_avatar_fallback = false)
ids_present = users.first.respond_to?(:common_course_ids)
ids_present = users.first.respond_to?(:common_courses)
users.map { |user|
{:id => user.id,
:name => user.short_name,
:avatar => avatar_url_for_user(user, blank_avatar_fallback),
:course_ids => ids_present ? user.common_course_ids : [],
:group_ids => ids_present ? user.common_group_ids : []
:common_courses => ids_present ? user.common_courses : [],
:common_groups => ids_present ? user.common_groups : []
}
}
end

View File

@ -201,6 +201,12 @@ module ApplicationHelper
end
@context_url_lookup[lookup] = res
end
def message_user_path(user)
params = {:user_id => user.id, :user_name => user.short_name}
params[:can_add_notes] = true if user.grants_right?(@current_user, :create_user_notes)
conversations_path + "#/conversations?" + params.to_query.gsub('+', '%20')
end
def hidden(include_style=false)
include_style ? "style='display:none;'" : "display: none;"

View File

@ -8,7 +8,7 @@ module ConversationsHelper
def formatted_contexts(contexts)
if contexts.is_a? User
contexts = {:courses => contexts.common_course_ids, :groups => contexts.common_group_ids}
contexts = {:courses => contexts.common_courses.keys, :groups => contexts.common_groups.keys}
end
"<em>#{ERB::Util.h(context_names(contexts).to_sentence)}</em>".html_safe
end
@ -23,8 +23,8 @@ module ConversationsHelper
# get up to two contexts that are shared by >= 50% of the audience
contexts = audience.inject({}) { |hash, user|
user.common_course_ids.each { |id| (hash[[:courses, id]] ||= []) << user.id }
user.common_group_ids.each { |id| (hash[[:groups, id]] ||= []) << user.id }
user.common_courses.each { |id, roles| (hash[[:courses, id]] ||= []) << user.id }
user.common_groups.each { |id, roles| (hash[[:groups, id]] ||= []) << user.id }
hash
}.
sort_by{ |c| - c.last.size}.

View File

@ -27,12 +27,12 @@ class Conversation < ActiveRecord::Base
has_many :participants,
:through => :conversation_participants,
:source => :user,
:select => User::MESSAGEABLE_USER_COLUMN_SQL + ", NULL AS common_course_ids, NULL AS common_group_ids",
:select => User::MESSAGEABLE_USER_COLUMN_SQL + ", NULL AS common_courses, NULL AS common_groups",
:order => 'last_authored_at IS NULL, last_authored_at DESC, LOWER(COALESCE(short_name, name))'
has_many :subscribed_participants,
:through => :subscribed_conversation_participants,
:source => :user,
:select => User::MESSAGEABLE_USER_COLUMN_SQL + ", NULL AS common_course_ids, NULL AS common_group_ids",
:select => User::MESSAGEABLE_USER_COLUMN_SQL + ", NULL AS common_courses, NULL AS common_groups",
:order => 'last_authored_at IS NULL, last_authored_at DESC, LOWER(COALESCE(short_name, name))'
has_many :attachments, :through => :conversation_messages

View File

@ -97,7 +97,7 @@ class ConversationParticipant < ActiveRecord::Base
}.map{ |m|
m.forwarded_messages.map(&:author_id)
}.flatten.uniq - [self.user_id]
participants |= User.find(:all, :select => User::MESSAGEABLE_USER_COLUMN_SQL + ", NULL AS common_course_ids, NULL AS common_group_ids", :conditions => {:id => user_ids})
participants |= User.find(:all, :select => User::MESSAGEABLE_USER_COLUMN_SQL + ", NULL AS common_courses, NULL AS common_groups", :conditions => {:id => user_ids})
end
return participants unless include_context_info
# we do this to find out the contexts they share with the user
@ -105,8 +105,8 @@ class ConversationParticipant < ActiveRecord::Base
context_info[user.id] = user
}
participants.each { |user|
user.common_course_ids = context_info[user.id].common_course_ids
user.common_group_ids = context_info[user.id].common_group_ids
user.common_courses = context_info[user.id].common_courses
user.common_groups = context_info[user.id].common_groups
}
end

View File

@ -128,8 +128,10 @@ class Enrollment < ActiveRecord::Base
:conditions => "courses.workflow_state = 'aborted' or courses.workflow_state = 'completed' or enrollments.workflow_state = 'rejected' or enrollments.workflow_state = 'completed'"
ENROLLMENT_RANK = ['TeacherEnrollment','TaEnrollment','DesignerEnrollment','StudentEnrollment','ObserverEnrollment']
ENROLLMENT_RANK_SQL = ENROLLMENT_RANK.size.times.inject('CASE '){|s, i| s << "WHEN type = '#{ENROLLMENT_RANK[i]}' THEN #{i} "} << 'END'
def self.highest_enrollment_type(type, type2)
res = ['TeacherEnrollment','TaEnrollment','DesignerEnrollment','StudentEnrollment','ObserverEnrollment'].find{|t| t == type || t == type2}
res = ENROLLMENT_RANK.find{|t| t == type || t == type2}
res ||= type || type2
res
end

View File

@ -1632,8 +1632,8 @@ class User < ActiveRecord::Base
end
end
MESSAGEABLE_USER_COLUMNS = ['id', 'short_name', 'name', 'avatar_image_url', 'avatar_image_source']
MESSAGEABLE_USER_COLUMN_SQL = "users." + (MESSAGEABLE_USER_COLUMNS.join(", users."))
MESSAGEABLE_USER_COLUMNS = ['id', 'short_name', 'name', 'avatar_image_url', 'avatar_image_source'].map{|col|"users.#{col}"}
MESSAGEABLE_USER_COLUMN_SQL = MESSAGEABLE_USER_COLUMNS.join(", ")
def messageable_users(options = {})
hash = enrollment_visibility
full_course_ids = hash[:full_course_ids]
@ -1684,25 +1684,37 @@ class User < ActiveRecord::Base
course_sql << "(course_section_id IN (#{section_ids.join(',')}))" if section_ids.present?
course_sql << "(course_id IN (#{restricted_course_hash.keys.join(',')}) AND (enrollments.type = 'TeacherEnrollment' OR enrollments.type = 'TaEnrollment' OR enrollments.user_id IN (#{([self.id] + restricted_course_hash.values.flatten.uniq).join(',')})))" if restricted_course_hash.present?
user_sql << <<-SQL if course_sql.present?
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, course_id, null AS group_id
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, course_id, NULL AS group_id, #{connection.func(:group_concat, :'enrollments.type', ':')} AS roles
FROM users, enrollments, courses
WHERE (#{course_sql.join(' OR ')}) AND users.id = user_id AND courses.id = course_id
AND (#{self.class.reflections[:current_and_invited_enrollments].options[:conditions]}
OR #{self.class.reflections[:concluded_enrollments].options[:conditions]}
)
AND #{user_condition_sql}
GROUP BY #{connection.group_by(*(MESSAGEABLE_USER_COLUMNS + [:course_id]))}
SQL
user_sql << <<-SQL if group_ids.present?
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, null AS course_id, group_id
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, NULL AS course_id, group_id, NULL AS roles
FROM users, group_memberships
WHERE group_id IN (#{group_ids.join(',')}) AND users.id = user_id
AND group_memberships.workflow_state <> 'deleted'
AND #{user_condition_sql}
SQL
# if this is an account admin who doesn't have any courses/groups in common
# with the user, we want to know the user's highest current enrollment type
highest_enrollment_sql = <<-SQL
SELECT type
FROM enrollments, courses
WHERE
user_id = users.id AND courses.id = course_id
AND #{self.class.reflections[:current_and_invited_enrollments].options[:conditions]}
ORDER BY #{Enrollment::ENROLLMENT_RANK_SQL}
LIMIT 1
SQL
user_sql << <<-SQL if account_ids.present?
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, null AS course_id, null AS group_id
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, 0 AS course_id, NULL AS group_id, (#{highest_enrollment_sql}) AS roles
FROM users, user_account_associations
WHERE user_account_associations.account_id IN (#{account_ids.join(',')})
AND user_account_associations.user_id = users.id
@ -1715,7 +1727,7 @@ class User < ActiveRecord::Base
# conversation with that user)
if options[:conversation_id].present?
user_sql << <<-SQL
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, null AS course_id, null AS group_id
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, NULL AS course_id, NULL AS group_id, NULL AS roles
FROM users, conversation_participants
WHERE #{user_condition_sql}
AND conversation_participants.user_id = users.id
@ -1723,7 +1735,7 @@ class User < ActiveRecord::Base
SQL
elsif options[:no_check_context]
user_sql << <<-SQL
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, null AS course_id, null AS group_id
SELECT #{MESSAGEABLE_USER_COLUMN_SQL}, NULL AS course_id, NULL AS group_id, NULL AS roles
FROM users
WHERE #{user_condition_sql}
SQL
@ -1733,10 +1745,12 @@ class User < ActiveRecord::Base
# if none of our potential sources was included, we're done
return [] if user_sql.empty?
concat_sql = connection.adapter_name =~ /postgres/i ? :"course_id::text || ':' || roles::text" : :"course_id || ':' || roles"
users = User.find_by_sql(<<-SQL)
SELECT #{MESSAGEABLE_USER_COLUMN_SQL},
#{connection.func(:group_concat, :course_id)} AS common_course_ids,
#{connection.func(:group_concat, :group_id)} AS common_group_ids
#{connection.func(:group_concat, concat_sql)} AS common_courses,
#{connection.func(:group_concat, :group_id)} AS common_groups
FROM (
#{user_sql.join(' UNION ')}
) users
@ -1746,8 +1760,16 @@ class User < ActiveRecord::Base
#{options[:limit] ? "LIMIT #{options[:limit].to_i}" : ""}
SQL
users.each do |user|
user.common_course_ids = user.common_course_ids.to_s.split(",").map(&:to_i)
user.common_group_ids = user.common_group_ids.to_s.split(",").map(&:to_i)
user.common_courses = user.common_courses.to_s.split(",").inject({}){ |hash, info|
roles = info.split(/:/)
hash[roles.shift.to_i] = roles
hash
}
user.common_groups = user.common_groups.to_s.split(",").inject({}){ |hash, info|
roles = info.split(/:/)
hash[roles.shift.to_i] = ['Member']
hash
}
end
end

View File

@ -12,7 +12,7 @@
<a class="button button-sidebar button-sidebar-wide" href="<%= context_url(@context, :controller => :gradebooks, :action => :grade_summary, :id => @user.id) %>"><%= image_tag "grading_icon.png" %> <%= t 'links.user_grades', "Grades for %{user}", :user => context_user_name(@context, @user) %></a>
<% end %>
<% if can_do(@context, @current_user, :send_messages) %>
<a class="button button-sidebar-wide" href="<%= conversations_path %>#/conversations?<%= {:user_id => @user.id, :user_name => @user.short_name}.to_query.gsub('+', '%20') %>"><%= image_tag "email.png" %> <%= t 'links.message_user', "Message %{user}", :user => context_user_name(@context, @user) %></a>
<a class="button button-sidebar-wide" href="<%= message_user_path(@user) %>"><%= image_tag "email.png" %> <%= t 'links.message_user', "Message %{user}", :user => context_user_name(@context, @user) %></a>
<% end %>
<% if @domain_root_account.enable_user_notes and can_do(@user, @current_user, :read_user_notes) %>
<a href="<%= user_user_notes_path(@user) %>" class="button button-sidebar-wide"> <%= t 'links.faculty_journal', "Faculty Journal for %{user}", :user => context_user_name(@context, @user) %></a>

View File

@ -65,8 +65,9 @@
</ul>
<table>
<tr id="recipient_info"><th><%= label_tag :recipients, :to, :en => "To", :before => true %></th><td><%= text_field_tag :recipients, nil, :finder_url => conversations_find_recipients_url, :class => "recipients" %></td></tr>
<tr id="group_conversation_info"><th></th><td><%= check_box_tag :group_conversation %> <%= label_tag :group_conversation, :en => "This is a group conversation. Participants will see all messages" %></td></tr>
<tr><th><%= label_tag :body, :message, :en => "Message", :before => true %></th><td><%= text_area_tag :body %></td></tr>
<tr id="group_conversation_info"><th></th><td><%= check_box_tag :group_conversation %> <%= label_tag :group_conversation, :en => "This is a group conversation. Participants will see all messages" %></td></tr>
<tr id="user_note_info"><th></th><td><%= check_box_tag :user_note, "1", false, :id => :add_to_faculty_journal %> <%= label_tag :add_to_faculty_journal, :en => "Add as a Faculty Journal entry" %></td></tr>
<tr>
<th>&nbsp;</th>
<td>
@ -221,6 +222,7 @@
MessageInbox.initial_conversations_count = <%= @conversations_count %>;
MessageInbox.scope = <%= raw @scope.to_json %>;
MessageInbox.label_scope = <%= raw @label.to_json %>;
MessageInbox.can_add_notes = <%= raw @current_user.associated_accounts.any?{|a| a.enable_user_notes && a.grants_right?(@current_user, nil, :manage_students) } %>;
<% unless @current_user.watched_conversations_intro? %>
$.conversationsIntroSlideshow()
<% end %>

View File

@ -6,7 +6,7 @@
<a class="button button-sidebar button-sidebar-wide" href="<%= context_url(@context, :context_student_grades_url, @user.id) %>"><%= image_tag "grading_icon.png" %> <%= t('links.grades', "Grades for %{user}", :user => context_user_name(@context, @user)) %></a>
<% end %>
<% if can_do(@context, @current_user, :send_messages) %>
<a class="button button-sidebar button-sidebar-wide" href="<%= conversations_url %>#/conversations?user_id=<%= @user.id %>&amp;user_name=<%= URI.escape(@user.short_name) %>"><%= image_tag "email.png" %> <%= t('links.message_user', "Message %{user}", :user => context_user_name(@context, @user)) %></a>
<a class="button button-sidebar button-sidebar-wide" href="<%= message_user_path(@user) %>"><%= image_tag "email.png" %> <%= t('links.message_user', "Message %{user}", :user => context_user_name(@context, @user)) %></a>
<% end %>
</div>
<% end %>

View File

@ -75,7 +75,7 @@
</td>
<% if course.user_is_teacher?(@current_user) %>
<td>
<a href="<%= inbox_url %>#reply<%= {'context_code' => course.asset_string, 'recipients' => student[:enrollment].user_id.to_s}.to_json %>" class="message_student_link" title="<%= t 'message_student', 'Message this student' %>"><%= image_tag "email.png" %></a>
<a href="<%= message_user_path(student[:enrollment].user) %>" class="message_student_link" title="<%= t 'message_student', 'Message this student' %>"><%= image_tag "email.png" %></a>
</td>
<% end %>
</tr>

View File

@ -444,12 +444,17 @@ class ActiveRecord::ConnectionAdapters::AbstractAdapter
# for functions that differ from one adapter to the next, use the following
# method (overriding as needed in non-standard adapters), e.g.
#
# connection.func(:group_concat, :name) ->
# group_concat(name) (default)
# string_agg(name::text, ',') (postgres)
# connection.func(:group_concat, :name, '|') ->
# group_concat(name, '|') (default)
# group_concat(name SEPARATOR '|') (mysql)
# string_agg(name::text, '|') (postgres)
def func(name, *args)
"#{name}(#{args.map{ |arg| arg.is_a?(Symbol) ? arg : quote_value(arg) }.join(', ')})"
"#{name}(#{args.map{ |arg| func_arg_esc(arg) }.join(', ')})"
end
def func_arg_esc(arg)
arg.is_a?(Symbol) ? arg : quote(arg)
end
def group_by(*columns)
@ -457,12 +462,24 @@ class ActiveRecord::ConnectionAdapters::AbstractAdapter
end
end
if defined?(ActiveRecord::ConnectionAdapters::MySQLAdapter)
ActiveRecord::ConnectionAdapters::MySQLAdapter.class_eval do
def func(name, *args)
case name
when :group_concat
"group_concat(#{func_arg_esc(args.first)} SEPARATOR #{quote(args[1] || ',')})"
else
super
end
end
end
end
if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
def func(name, *args)
case name
when :group_concat
"string_agg(#{args.first}::text, ',')"
"string_agg((#{func_arg_esc(args.first)})::text, #{quote(args[1] || ',')})"
else
super
end

View File

@ -28,6 +28,7 @@
this.tokens.html('');
return typeof this.change === "function" ? this.change(this.token_values()) : void 0;
}, this));
this.added = this.options.added;
this.placeholder = $('<span />');
this.placeholder.text(this.options.placeholder);
if (this.options.placeholder) {
@ -104,6 +105,11 @@
this.val('');
}
this.placeholder.hide();
if (data) {
if (typeof this.added === "function") {
this.added(data.data);
}
}
if (typeof this.change === "function") {
this.change(this.token_values());
}
@ -534,7 +540,8 @@
return this.input.add_token({
value: id,
text: this.selection.find('b').text(),
no_clear: true
no_clear: true,
data: this.selection.data('user_data')
});
} else {
this.selection.removeClass('on');
@ -710,7 +717,7 @@
}
};
I18n.scoped('conversations', function(I18n) {
var add_conversation, build_attachment, build_media_object, build_message, build_submission, build_submission_comment, close_menus, html_name_for_user, inbox_action, inbox_action_url_for, inbox_resize, is_selected, open_conversation_menu, open_menu, parse_query_string, remove_conversation, reposition_conversation, reset_message_form, select_conversation, select_unloaded_conversation, set_conversation_state, set_hash, set_last_label, show_message_form, toggle_message_actions, update_conversation;
var add_conversation, build_attachment, build_media_object, build_message, build_submission, build_submission_comment, can_add_notes_for, close_menus, html_name_for_user, inbox_action, inbox_action_url_for, inbox_resize, is_selected, open_conversation_menu, open_menu, parse_query_string, remove_conversation, reposition_conversation, reset_message_form, select_conversation, select_unloaded_conversation, set_conversation_state, set_hash, set_last_label, show_message_form, toggle_message_actions, update_conversation;
show_message_form = function() {
var newMessage;
newMessage = !($selected_conversation != null);
@ -733,6 +740,7 @@
});
}
reset_message_form();
$form.find('#user_note_info').showIf($selected_conversation != null ? $selected_conversation.hasClass('private') : void 0).find('input').attr('checked', false);
return $form.show().find(':input:visible:first').focus();
};
reset_message_form = function() {
@ -812,7 +820,12 @@
if (params && params.user_id && params.user_name) {
$('#recipients').data('token_input').add_token({
value: params.user_id,
text: params.user_name
text: params.user_name,
data: {
id: params.user_id,
name: params.user_name,
can_add_notes: params.can_add_notes
}
});
$('#from_conversation_id').val(params.from_conversation_id);
}
@ -821,14 +834,14 @@
$form.loadingImage();
$c = $selected_conversation;
completion = function(data) {
var i, j, message, submission, user, _i, _len, _ref;
var i, j, message, submission, user, _i, _len, _ref, _ref2;
if (!is_selected($c)) {
return;
}
_ref = data.participants;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
user = _ref[_i];
if (!MessageInbox.user_cache[user.id]) {
if (!((_ref2 = MessageInbox.user_cache[user.id]) != null ? _ref2.avatar : void 0)) {
MessageInbox.user_cache[user.id] = user;
user.html_name = html_name_for_user(user);
}
@ -863,27 +876,27 @@
}
};
MessageInbox.shared_contexts_for_user = function(user, limit) {
var course, course_id, group, group_id, shared_contexts;
var course, course_id, group, group_id, roles, shared_contexts;
if (limit == null) {
limit = 2;
}
shared_contexts = ((function() {
var _i, _len, _ref, _results;
_ref = user.course_ids;
var _ref, _results;
_ref = user.common_courses;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
course_id = _ref[_i];
for (course_id in _ref) {
roles = _ref[course_id];
if (course = this.contexts.courses[course_id]) {
_results.push(course.name);
}
}
return _results;
}).call(this)).concat((function() {
var _i, _len, _ref, _results;
_ref = user.group_ids;
var _ref, _results;
_ref = user.common_groups;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
group_id = _ref[_i];
for (group_id in _ref) {
roles = _ref[group_id];
if (group = this.contexts.groups[group_id]) {
_results.push(group.name);
}
@ -907,6 +920,20 @@
shared_contexts = MessageInbox.shared_contexts_for_user(user);
return $.htmlEscape(user.name) + (shared_contexts.length ? " <em>" + $.htmlEscape(shared_contexts) + "</em>" : '');
};
can_add_notes_for = function(user) {
var course_id, roles, _ref, _ref2;
if (user.can_add_notes) {
return true;
}
_ref = user.common_courses;
for (course_id in _ref) {
roles = _ref[course_id];
if (__indexOf.call(roles, 'StudentEnrollment') >= 0 && (MessageInbox.can_add_notes || ((_ref2 = MessageInbox.contexts.courses[course_id]) != null ? _ref2.can_add_notes : void 0))) {
return true;
}
}
return false;
};
build_message = function(data) {
var $attachment_blank, $media_object_blank, $message, $pm_action, $ul, attachment, avatar, pm_url, submessage, user, user_name, _i, _j, _len, _len2, _ref, _ref2, _ref3, _ref4, _ref5, _ref6;
$message = $("#message_blank").clone(true).attr('id', 'message_' + data.id);
@ -1791,6 +1818,14 @@
$('#no_messages').showIf(!$conversation_list.find('li').length);
$('.recipients').tokenInput({
placeholder: I18n.t('recipient_field_placeholder', "Enter a name, course, or group"),
added: function(data) {
var _base, _name, _ref3;
if (!(data.id && ("" + data.id).match(/^(course|group)_/))) {
data = $.extend({}, data);
delete data.avatar;
return (_ref3 = (_base = MessageInbox.user_cache)[_name = data.id]) != null ? _ref3 : _base[_name] = data;
}
},
selector: {
messages: {
no_results: I18n.t('no_results', 'No results found')
@ -1808,12 +1843,13 @@
$b = $('<b />');
$b.text(data.name);
$span = $('<span />');
if (data.course_ids != null) {
if (data.common_courses != null) {
$span.text(MessageInbox.shared_contexts_for_user(data));
}
$node.append($b, $span);
$node.attr('title', data.name);
$node.data('id', data.id);
$node.data('user_data', data);
$node.addClass(data.type ? data.type : 'user');
if (options.level > 0) {
$node.prepend('<a class="toggle"><i></i></a>');
@ -1840,15 +1876,17 @@
token_input = $('#recipients').data('token_input');
token_input.fake_input.css('width', '100%');
token_input.change = function(tokens) {
var _ref3;
var user, _ref3;
if (tokens.length > 1 || ((_ref3 = tokens[0]) != null ? _ref3.match(/^(course|group)_/) : void 0)) {
if (!$form.find('#group_conversation_info').is(':visible')) {
$form.find('#group_conversation').attr('checked', true);
}
return $form.find('#group_conversation_info').show();
$form.find('#group_conversation_info').show();
return $form.find('#user_note_info').hide();
} else {
$form.find('#group_conversation').attr('checked', true);
return $form.find('#group_conversation_info').hide();
$form.find('#group_conversation_info').hide();
return $form.find('#user_note_info').showIf((user = MessageInbox.user_cache[tokens[0]]) && can_add_notes_for(user));
}
};
$(window).resize(inbox_resize);