show mult. enroll. in groups; fixes #6998
We want to show all sections that a user belongs to when building groups, and make sure that section-restricted groups take into account multiple sections. The data model already (mostly) supported this, but the UI did not. Test plan: - create a course with > 2 sections, > 2 users, at least one in multiple sections. - Go to the groups page, make sure that both sections show up under the user. - Make the group category section-restricted, make sure things work as you expect. Change-Id: Ic13bc81cf62811a0e5dcb9572240fae685056989 Reviewed-on: https://gerrit.instructure.com/8435 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com>
This commit is contained in:
parent
12af0a5d67
commit
6e0bf1954d
|
@ -16,11 +16,11 @@
|
|||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
class GroupsController < ApplicationController
|
||||
class GroupsController < ApplicationController
|
||||
before_filter :get_context
|
||||
before_filter :require_context, :only => [:create_category, :delete_category]
|
||||
before_filter :get_group_as_context, :only => [:show]
|
||||
|
||||
|
||||
def context_group_members
|
||||
@group = @context
|
||||
if authorized_action(@group, @current_user, :read_roster)
|
||||
|
@ -29,7 +29,7 @@ class GroupsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def unassigned_members
|
||||
category = @context.group_categories.find_by_id(params[:category_id])
|
||||
return render :json => {}, :status => :not_found unless category
|
||||
|
@ -40,7 +40,7 @@ class GroupsController < ApplicationController
|
|||
groups = []
|
||||
end
|
||||
users = @context.paginate_users_not_in_groups(groups, page)
|
||||
|
||||
|
||||
if authorized_action(@context, @current_user, :manage)
|
||||
respond_to do |format|
|
||||
format.json { render :json => {
|
||||
|
@ -50,18 +50,12 @@ class GroupsController < ApplicationController
|
|||
:previous_page => users.previous_page,
|
||||
:total_entries => users.total_entries,
|
||||
:pagination_html => render_to_string(:partial => 'user_pagination', :locals => { :users => users }),
|
||||
:users => users.map do |u|
|
||||
h = { :user_id => u.id, :name => u.last_name_first }
|
||||
if @context.is_a?(Course) && (section = u.section_for_course(@context))
|
||||
h = h.merge(:section_id => section.id, :section_code => section.section_code)
|
||||
end
|
||||
h
|
||||
end
|
||||
:users => users.map { |u| u.group_member_json(@context) }
|
||||
} }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def index
|
||||
return context_index if @context
|
||||
@groups = @current_user ? @current_user.groups.active : []
|
||||
|
@ -121,7 +115,7 @@ class GroupsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update_category
|
||||
if authorized_action(@context, @current_user, :manage_groups)
|
||||
@group_category = @context.group_categories.find_by_id(params[:category_id])
|
||||
|
@ -133,7 +127,7 @@ class GroupsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def delete_category
|
||||
if authorized_action(@context, @current_user, :manage_groups)
|
||||
@group_category = @context.group_categories.find_by_id(params[:category_id])
|
||||
|
@ -147,7 +141,7 @@ class GroupsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def add_user
|
||||
@group = @context
|
||||
if authorized_action(@group, @current_user, :manage)
|
||||
|
@ -160,7 +154,7 @@ class GroupsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def remove_user
|
||||
@group = @context
|
||||
if authorized_action(@group, @current_user, :manage)
|
||||
|
@ -326,7 +320,7 @@ class GroupsController < ApplicationController
|
|||
# sort by name, but with the student organized category in the back
|
||||
@categories = @categories.sort_by{|c| [ (c.student_organized? ? 1 : 0), c.name ] }
|
||||
@groups = @groups.sort_by{ |g| [(g.name || '').downcase, g.created_at] }
|
||||
|
||||
|
||||
if authorized_action(@context, @current_user, :read_roster)
|
||||
respond_to do |format|
|
||||
if @context.grants_right?(@current_user, session, :manage_groups)
|
||||
|
@ -361,7 +355,7 @@ class GroupsController < ApplicationController
|
|||
@group_category.configure_self_signup(enable_self_signup, restrict_self_signup)
|
||||
@group_category.save
|
||||
end
|
||||
|
||||
|
||||
def create_default_groups_in_category
|
||||
self_signup = params[:category][:enable_self_signup] == "1"
|
||||
distribute_members = !self_signup && params[:category][:split_groups] == "1"
|
||||
|
|
|
@ -471,7 +471,7 @@ class Course < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def users_not_in_groups_sql(groups, opts={})
|
||||
["SELECT u.id, u.name
|
||||
["SELECT DISTINCT u.id, u.name#{", #{opts[:order_by]}" if opts[:order_by].present?}
|
||||
FROM users u
|
||||
INNER JOIN enrollments e ON e.user_id = u.id
|
||||
WHERE e.course_id = ? AND e.workflow_state NOT IN ('rejected', 'completed', 'deleted') AND e.type = 'StudentEnrollment'
|
||||
|
@ -479,7 +479,8 @@ class Course < ActiveRecord::Base
|
|||
FROM group_memberships gm
|
||||
WHERE gm.user_id = u.id AND
|
||||
gm.group_id IN (#{groups.map(&:id).join ','}))" unless groups.empty?}
|
||||
#{"ORDER BY #{opts[:order_by]}" if opts[:order_by].present?}", self.id]
|
||||
#{"ORDER BY #{opts[:order_by]}" if opts[:order_by].present?}
|
||||
#{"#{opts[:order_by_dir]}" if opts[:order_by_dir]}", self.id]
|
||||
end
|
||||
|
||||
def users_not_in_groups(groups)
|
||||
|
@ -487,7 +488,7 @@ class Course < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def paginate_users_not_in_groups(groups, page, per_page = 15)
|
||||
User.paginate_by_sql(users_not_in_groups_sql(groups, :order_by => "#{User.sortable_name_order_by_clause('u')} ASC"),
|
||||
User.paginate_by_sql(users_not_in_groups_sql(groups, :order_by => "#{User.sortable_name_order_by_clause('u')}", :order_by_dir => "ASC"),
|
||||
:page => page, :per_page => per_page)
|
||||
end
|
||||
|
||||
|
|
|
@ -2174,9 +2174,8 @@ class User < ActiveRecord::Base
|
|||
associated_root_accounts.any? { |a| a.settings[:users_can_edit_name] != false } || associated_root_accounts.empty?
|
||||
end
|
||||
|
||||
def section_for_course(course)
|
||||
enrollment = course.student_enrollments.active.for_user(self).first
|
||||
enrollment && enrollment.course_section
|
||||
def sections_for_course(course)
|
||||
course.student_enrollments.active.for_user(self).map { |e| e.course_section }
|
||||
end
|
||||
|
||||
def can_create_enrollment_for?(course, session, type)
|
||||
|
@ -2189,8 +2188,11 @@ class User < ActiveRecord::Base
|
|||
|
||||
def group_member_json(context)
|
||||
h = { :user_id => self.id, :name => self.last_name_first, :display_name => self.short_name }
|
||||
if context && context.is_a?(Course) && (section = self.section_for_course(context))
|
||||
h = h.merge(:section_id => section.id, :section_code => section.section_code)
|
||||
if context && context.is_a?(Course)
|
||||
self.sections_for_course(context).each do |section|
|
||||
h[:sections] ||= []
|
||||
h[:sections] << { :section_id => section.id, :section_code => section.section_code }
|
||||
end
|
||||
end
|
||||
h
|
||||
end
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<% section = student && student.section_for_course(@context) %>
|
||||
<% sections = student && student.sections_for_course(@context) %>
|
||||
<li class="student user_<%= student ? student.id : "blank" %>" title="<%= t :drag_drop_instructions, "Click and Drag to move student to another group" %>">
|
||||
<div class="name"><%= student.last_name_first rescue "" %></div>
|
||||
<div class="section_code"><%= section ? section.section_code : "" %></div>
|
||||
<div class="section_code"><%= sections ? sections.map { |s| s.section_code }.join(", ") : "" %></div>
|
||||
<div style="display: none;" class="data">
|
||||
<% student && @memberships.select{|m| m.user_id == student.id}.each do |membership| %>
|
||||
<% next unless category = membership.group && membership.group.group_category %>
|
||||
<span class="category_<%= category.id %>_group_id"><%= membership.group.id %></span>
|
||||
<% end %>
|
||||
<span class="user_id"><%= student ? student.id : nbsp %></span>
|
||||
<span class="section_id"><%= section ? section.id : "" %></span>
|
||||
<span class="section_id"><%= sections ? sections.map { |s| s.id }.join(",") : "" %></span>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -34,32 +34,41 @@ require([
|
|||
|
||||
window.contextGroups = {
|
||||
autoLoadGroupThreshold: 15,
|
||||
|
||||
|
||||
populateUserElement: function($user, data) {
|
||||
data.section_id = data.sections.map(function(s) {
|
||||
return s.section_id;
|
||||
}).join(",");
|
||||
data.section_code = data.sections.map(function(s) {
|
||||
return s.section_code;
|
||||
}).join(", ");
|
||||
|
||||
$user.removeClass('user_template');
|
||||
$user.addClass('user_id_' + data.user_id);
|
||||
$user.fillTemplateData({ data: data });
|
||||
},
|
||||
|
||||
loadMembersForGroup: function($group) {
|
||||
var url = $("#manage_group_urls .list_users_url").attr('href');
|
||||
var id = $group.getTemplateData({textValues: ['group_id']}).group_id;
|
||||
url = $.replaceTags(url, "id", id)
|
||||
|
||||
|
||||
$group.find(".load_members_link").hide();
|
||||
$group.find(".loading_members").show();
|
||||
|
||||
|
||||
$.ajaxJSON(url, "GET", null, function(data) {
|
||||
// remove existing students from group (this should have returned everyone)
|
||||
$group.find(".student").remove();
|
||||
|
||||
|
||||
// create new entries for everyone we got back, and insert them into the list.
|
||||
// TODO: we should presort the list and give an "append" option to insertIntoGroup.
|
||||
// Right now it takes O(n^2) to insert students, which can be painful in a large list.
|
||||
var user_template = $(".user_template");
|
||||
var $user_template = $(".user_template");
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var user_info = data[i];
|
||||
var user_el = user_template.clone();
|
||||
user_el.removeClass('user_template');
|
||||
user_el.addClass('user_id_' + user_info['user_id']);
|
||||
user_el.fillTemplateData({ data: user_info });
|
||||
|
||||
contextGroups.insertIntoGroup(user_el, $group);
|
||||
|
||||
var $user = $user_template.clone();
|
||||
contextGroups.populateUserElement($user, data[i]);
|
||||
contextGroups.insertIntoGroup($user, $group);
|
||||
|
||||
$group.find(".user_count_hidden").text("0");
|
||||
$(window).triggerHandler('resize');
|
||||
contextGroups.updateCategoryCounts($group.parents(".group_category"));
|
||||
|
@ -67,45 +76,40 @@ require([
|
|||
$group.find(".loading_members").hide();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 0 means to reload the current page, whatever it is
|
||||
// < 0 means to only load that page if no other page is loaded
|
||||
loadUnassignedMembersPage: function($group, page) {
|
||||
if (page < 0 && $group.data("page_loaded")) { return; }
|
||||
page = Math.abs(page);
|
||||
|
||||
|
||||
if (page == 0) {
|
||||
page = $group.data("page_loaded") || 1;
|
||||
}
|
||||
|
||||
|
||||
// This is lots of duplicated code from above, with tweaks. TODO: Refactor
|
||||
var category_id = $group.closest(".group_category").data('category_id');
|
||||
var url = $("#manage_group_urls .list_unassigned_users_url").attr('href');
|
||||
url += "?category_id=" + category_id + "&page=" + page;
|
||||
|
||||
|
||||
$group.find(".load_members_link").hide();
|
||||
$group.find(".loading_members").text(I18n.t('status.loading', "Loading..."));
|
||||
$group.find(".loading_members").show();
|
||||
|
||||
|
||||
$.ajaxJSON(url, "GET", null, function(data) {
|
||||
$group.data("page_loaded", page);
|
||||
$group.find(".user_count").text(I18n.t('category.student', 'student', {count: data['total_entries']}));
|
||||
$group.find(".user_count_hidden").text(data['total_entries'] - data['users'].length);
|
||||
$group.find(".group_user_count").show();
|
||||
$group.find(".student").remove();
|
||||
|
||||
var user_template = $(".user_template");
|
||||
|
||||
var $user_template = $(".user_template");
|
||||
var users = data['users'];
|
||||
for (var i = 0; i < users.length; i++) {
|
||||
var user_info = users[i];
|
||||
var user_el = user_template.clone();
|
||||
user_el.removeClass('user_template');
|
||||
user_el.addClass('user_id_' + user_info['user_id']);
|
||||
user_el.fillTemplateData({ data: user_info });
|
||||
|
||||
contextGroups.insertIntoGroup(user_el, $group);
|
||||
var $user = $user_template.clone();
|
||||
contextGroups.populateUserElement($user, users[i]);
|
||||
contextGroups.insertIntoGroup($user, $group);
|
||||
}
|
||||
|
||||
|
||||
$group.find(".loading_members").html(data['pagination_html']);
|
||||
$group.find(".unassigned_members_pagination a").click(function(event) {
|
||||
event.preventDefault();
|
||||
|
@ -116,11 +120,11 @@ require([
|
|||
contextGroups.loadUnassignedMembersPage($(this).closest(".group_blank").first(), link_page)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(window).triggerHandler('resize');
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
moveToGroup: function($student, $group) {
|
||||
if ($student.parents(".group")[0] == $group[0]) { return; }
|
||||
var id = $group.getTemplateData({textValues: ['group_id']}).group_id;
|
||||
|
@ -138,7 +142,7 @@ require([
|
|||
user_id: user_id
|
||||
}
|
||||
$student.remove();
|
||||
|
||||
|
||||
var $student_instances = $student;
|
||||
contextGroups.insertIntoGroup($student, $group);
|
||||
$category = $group.parents(".group_category")
|
||||
|
@ -161,18 +165,18 @@ require([
|
|||
}
|
||||
$span.text(data.group_membership.group_id || "");
|
||||
});
|
||||
|
||||
|
||||
$student.removeClass('event_pending');
|
||||
contextGroups.updateCategoryCounts($group.parents(".group_category"));
|
||||
|
||||
var groups = $($original_group);
|
||||
groups = groups.add($group);
|
||||
contextGroups.updateCategoryHeterogeneity($group.parents(".group_category"), groups);
|
||||
|
||||
|
||||
var unassigned_group = $group.parents(".group_category").find(".group_blank");
|
||||
var students_visible = unassigned_group.find(".student_list .student").length;
|
||||
var students_hidden = parseInt(unassigned_group.find(".user_count_hidden").text());
|
||||
|
||||
|
||||
if (students_visible <= 5 && students_hidden > 0) {
|
||||
contextGroups.loadUnassignedMembersPage(unassigned_group, 0);
|
||||
}
|
||||
|
@ -196,15 +200,15 @@ require([
|
|||
$.flashError(message);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
insertIntoGroup: function($student, $group) {
|
||||
var $before = null;
|
||||
var data = $student.getTemplateData({textValues: ['name', 'user_id']})
|
||||
var student_name = data.name;
|
||||
|
||||
|
||||
// don't insert users into a group they're already in
|
||||
if ($group.find(".student_list .user_id_" + data.user_id).length > 0) { return; }
|
||||
|
||||
|
||||
$group.find(".student.user_" + data.user_id).remove();
|
||||
$group.find(".student_list .student").each(function() {
|
||||
var compare_name = $(this).getTemplateData({textValues: ['name']}).name;
|
||||
|
@ -228,46 +232,54 @@ require([
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
updateCategoryCounts: function($category) {
|
||||
$category.find(".group").each(function() {
|
||||
var userCount = $(this).find(".student_list .student").length + parseInt($(this).find(".user_count_hidden").text());
|
||||
$(this).find(".user_count").text(I18n.t('category.student', 'student', {count: userCount}));
|
||||
});
|
||||
|
||||
|
||||
var groupCount = $category.find(".group:not(.group_blank)").length;
|
||||
$category.find(".group_count").text(I18n.t('group', 'Group', {count: groupCount}));
|
||||
|
||||
|
||||
$category.find(".group").each(function() {
|
||||
$(this).find(".expand_collapse_links").showIf($(this).find(".student_list li").length > 0);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
updateCategoryHeterogeneity: function($category, groups) {
|
||||
// check if any of the provided groups are heterogenous now (skipping the
|
||||
// "unassigned" group should it be involved). this assumes exactly one
|
||||
// section per student, which isn't enforced by the server data model,
|
||||
// but should be true of students for the forseeable future.
|
||||
// "unassigned" group should it be involved).
|
||||
var heterogenous = false;
|
||||
groups.each(function() {
|
||||
var section_id = null;
|
||||
if (!$(this).hasClass('group_blank')) {
|
||||
$(this).find(".student_list .student .section_id").each(function() {
|
||||
other_section_id = $(this).text();
|
||||
if (section_id === null || section_id === "") {
|
||||
section_id = other_section_id;
|
||||
} else if (other_section_id !== "" && section_id !== other_section_id) {
|
||||
heterogenous = true;
|
||||
var section_id_counts = {};
|
||||
$section_ids = $(this).find(".student_list .student .section_id");
|
||||
if (!$(this).hasClass('group_blank') && $section_ids.length > 0) {
|
||||
$section_ids.each(function() {
|
||||
var section_ids = $(this).text().split(",");
|
||||
for (var i = 0; i < section_ids.length; i++) {
|
||||
if (!section_id_counts[section_ids[i]]) {
|
||||
section_id_counts[section_ids[i]] = 0;
|
||||
}
|
||||
section_id_counts[section_ids[i]] += 1;
|
||||
}
|
||||
});
|
||||
|
||||
var found = true;
|
||||
for (var section_id in section_id_counts) {
|
||||
if (section_id_counts[section_id] === $section_ids.length) {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
heterogenous = heterogenous || found;
|
||||
}
|
||||
});
|
||||
$category.find('.heterogenous').text(heterogenous ? 'true' : 'false');
|
||||
},
|
||||
|
||||
|
||||
populateCategory: function(panel) {
|
||||
var $category = $(panel);
|
||||
|
||||
|
||||
// Start loading groups that have < X members automatically
|
||||
$category.find(".group").each(function() {
|
||||
var members = parseInt($(this).find(".user_count_hidden").text());
|
||||
|
@ -275,13 +287,13 @@ require([
|
|||
contextGroups.loadMembersForGroup($(this));
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// -1 means to load page 1, but only if there aren't any other pages loaded (for switching between tabs)
|
||||
if ($category.length) {
|
||||
contextGroups.loadUnassignedMembersPage($category.find(".group_blank"), -1);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
updateCategory: function($category, category) {
|
||||
// update name in $category, tab, and sidebar
|
||||
$category.find('.category_name').text(category.name);
|
||||
|
@ -319,7 +331,7 @@ require([
|
|||
$category.find("ul").append($group.show());
|
||||
$("#category_header").show();
|
||||
},
|
||||
|
||||
|
||||
droppable_options: {
|
||||
accept: '.student',
|
||||
hoverClass: 'hover',
|
||||
|
@ -330,7 +342,7 @@ require([
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
$("li.student").live('mousedown', function(event) { event.preventDefault(); return false; });
|
||||
$("#group_tabs").tabs();
|
||||
|
@ -542,7 +554,7 @@ require([
|
|||
});
|
||||
$category.find(".clearer").before($group);
|
||||
contextGroups.addGroupToSidebar(group)
|
||||
|
||||
|
||||
if (group.users) {
|
||||
for(var jdx in group.users) {
|
||||
var user = group.users[jdx].user;
|
||||
|
@ -551,7 +563,7 @@ require([
|
|||
$(".student.user_" + user.id).find(".data").append($span);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$group.find(".name.blank_name").hide().end()
|
||||
.find(".group_name").show();
|
||||
$group.find(".group_user_count").show();
|
||||
|
@ -569,7 +581,7 @@ require([
|
|||
$category.find('.self_signup_text').showIf(group_category.self_signup);
|
||||
$category.find('.restricted_self_signup_text').showIf(group_category.self_signup == 'restricted');
|
||||
$category.find('.assign_students_link').showIf(group_category.self_signup !== 'restricted');
|
||||
|
||||
|
||||
var newIndex = $("#group_tabs").tabs('length');
|
||||
if ($("li.category").last().hasClass('student_organized')) {
|
||||
newIndex -= 1;
|
||||
|
@ -705,16 +717,13 @@ require([
|
|||
var $group = $category.find('#group_' + group.id);
|
||||
for (var j = 0; j < group.new_members.length; j++) {
|
||||
var user = group.new_members[j];
|
||||
var user_class = 'user_id_' + user.user_id;
|
||||
|
||||
// remove existing user element, if any
|
||||
$category.find('.' + user_class).remove();
|
||||
$category.find('.user_id_' + user.user_id).remove();
|
||||
|
||||
// create new user element and place it in the right group
|
||||
var $user = user_template.clone();
|
||||
$user.removeClass('user_template');
|
||||
$user.addClass(user_class);
|
||||
$user.fillTemplateData({ data: user });
|
||||
contextGroups.populateUserElement($user, user);
|
||||
contextGroups.insertIntoGroup($user, $group);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -545,8 +545,8 @@ describe GroupsController do
|
|||
|
||||
get 'unassigned_members', :course_id => @course.id, :category_id => group.group_category.id
|
||||
data = json_parse
|
||||
data['users'].first['section_id'].should == @course.default_section.id
|
||||
data['users'].first['section_code'].should == @course.default_section.section_code
|
||||
data['users'].first['sections'].first['section_id'].should == @course.default_section.id
|
||||
data['users'].first['sections'].first['section_code'].should == @course.default_section.section_code
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -559,8 +559,8 @@ describe GroupsController do
|
|||
|
||||
get 'context_group_members', :group_id => group.id
|
||||
data = json_parse
|
||||
data.first['section_id'].should == @course.default_section.id
|
||||
data.first['section_code'].should == @course.default_section.section_code
|
||||
data.first['sections'].first['section_id'].should == @course.default_section.id
|
||||
data.first['sections'].first['section_code'].should == @course.default_section.section_code
|
||||
end
|
||||
|
||||
it "should require :read_roster permission" do
|
||||
|
|
|
@ -915,9 +915,9 @@ describe User do
|
|||
end
|
||||
end
|
||||
|
||||
it "should find section for course" do
|
||||
it "should find sections for course" do
|
||||
course_with_student
|
||||
@student.section_for_course(@course).should == @course.default_section
|
||||
@student.sections_for_course(@course).should include @course.default_section
|
||||
end
|
||||
|
||||
describe "name_parts" do
|
||||
|
@ -1002,8 +1002,10 @@ describe User do
|
|||
:user_id => @student.id,
|
||||
:name => 'Doe, John',
|
||||
:display_name => 'Johnny',
|
||||
:section_id => @section.id,
|
||||
:section_code => @section.section_code
|
||||
:sections => [ {
|
||||
:section_id => @section.id,
|
||||
:section_code => @section.section_code
|
||||
} ]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -218,4 +218,4 @@ describe "manage groups" do
|
|||
|
||||
find_with_jquery("#category_#{group_category.id} #group_#{group.id}").should_not be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,7 +33,67 @@ describe "manage groups students" do
|
|||
category.find_elements(:css, ".group_blank .user_id_#{john.id}").should_not be_empty
|
||||
end
|
||||
|
||||
it "should list all sections a student belongs to" do
|
||||
@other_section = @course.course_sections.create!(:name => "Other Section")
|
||||
student_in_course(:active_all => true)
|
||||
@course.student_enrollments.create!(:user => @student,
|
||||
:workflow_state => "active",
|
||||
:course_section => @other_section)
|
||||
|
||||
gc1 = @course.group_categories.create(:name => "Group Category 1")
|
||||
|
||||
get "/courses/#{@course.id}/groups"
|
||||
wait_for_ajaximations
|
||||
|
||||
sections = driver.find_element(:css, ".user_id_#{@student.id} .section_code")
|
||||
sections.should include_text(@course.default_section.name)
|
||||
sections.should include_text(@other_section.name)
|
||||
|
||||
driver.find_element(:css, "#category_#{gc1.id} .group_blank .user_count").should include_text("1")
|
||||
end
|
||||
|
||||
it "should paginate and count users correctly" do
|
||||
students_count = 20
|
||||
students_count.times do |i|
|
||||
student_in_course(:name => "Student #{i}")
|
||||
end
|
||||
|
||||
@other_section = @course.course_sections.create!(:name => "Other Section")
|
||||
@course.student_enrollments.create!(:user => @student,
|
||||
:workflow_state => "active",
|
||||
:course_section => @other_section)
|
||||
|
||||
group_category = @course.group_categories.create(:name => "My Groups")
|
||||
|
||||
get "/courses/#{@course.id}/groups"
|
||||
wait_for_ajaximations
|
||||
|
||||
category = driver.find_element(:css, ".group_category")
|
||||
unassigned_div = category.find_element(:css, ".group_blank")
|
||||
|
||||
unassigned_div.find_element(:css, ".user_count").should include_text(students_count.to_s)
|
||||
unassigned_div.find_elements(:css, ".student").length.should == 15
|
||||
# 15 comes from window.contextGroups.autoLoadGroupThreshold
|
||||
|
||||
driver.find_element(:css, ".next_page").click
|
||||
wait_for_ajaximations
|
||||
|
||||
unassigned_div.find_element(:css, ".user_count").should include_text(students_count.to_s)
|
||||
unassigned_div.find_elements(:css, ".student").length.should == 5
|
||||
end
|
||||
|
||||
context "dragging a user between groups" do
|
||||
# use blank as the group id for "unassigned"
|
||||
def simulate_group_drag(user_id, from_group_id, to_group_id)
|
||||
from_group = (from_group_id == "blank" ? ".group_blank:visible" : "#group_#{from_group_id}")
|
||||
to_group = (to_group_id == "blank" ? ".group_blank:visible" : "#group_#{to_group_id}")
|
||||
driver.execute_script(<<-SCRIPT)
|
||||
window.contextGroups.moveToGroup(
|
||||
$('#{from_group} .user_id_#{user_id}'),
|
||||
$('#{to_group}'))
|
||||
SCRIPT
|
||||
end
|
||||
|
||||
it "should remove a user from the old group if the category is not student organized" do
|
||||
@course.enroll_student(john = user_model(:name => "John Doe"))
|
||||
|
||||
|
@ -53,31 +113,19 @@ describe "manage groups students" do
|
|||
# from unassigned to group1
|
||||
# drag_and_drop version doesn't work for some reason
|
||||
# driver.action.drag_and_drop(john_li, group1_div).perform
|
||||
driver.execute_script(<<-SCRIPT)
|
||||
window.contextGroups.moveToGroup(
|
||||
$('.group_category:visible .group_blank .user_id_#{john.id}'),
|
||||
$('#group_#{group1.id}'))
|
||||
SCRIPT
|
||||
simulate_group_drag(john.id, "blank", group1.id)
|
||||
unassigned_div.find_elements(:css, ".user_id_#{john.id}").should be_empty
|
||||
group1_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
|
||||
# from group1 to group2
|
||||
# driver.action.drag_and_drop(john_li, group2_div).perform
|
||||
driver.execute_script(<<-SCRIPT)
|
||||
window.contextGroups.moveToGroup(
|
||||
$('#group_#{group1.id} .user_id_#{john.id}'),
|
||||
$('#group_#{group2.id}'))
|
||||
SCRIPT
|
||||
simulate_group_drag(john.id, group1.id, group2.id)
|
||||
group1_div.find_elements(:css, ".user_id_#{john.id}").should be_empty
|
||||
group2_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
|
||||
# from group2 to unassigned
|
||||
# driver.action.drag_and_drop(john_li, unassigned_div).perform
|
||||
driver.execute_script(<<-SCRIPT)
|
||||
window.contextGroups.moveToGroup(
|
||||
$('#group_#{group2.id} .user_id_#{john.id}'),
|
||||
$('.group_category:visible .group_blank'))
|
||||
SCRIPT
|
||||
simulate_group_drag(john.id, group2.id, "blank")
|
||||
group2_div.find_elements(:css, ".user_id_#{john.id}").should be_empty
|
||||
unassigned_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
end
|
||||
|
@ -102,38 +150,82 @@ describe "manage groups students" do
|
|||
# from unassigned to group1
|
||||
# drag_and_drop version doesn't work for some reason
|
||||
# driver.action.drag_and_drop(john_li, group1_div).perform
|
||||
driver.execute_script(<<-SCRIPT)
|
||||
window.contextGroups.moveToGroup(
|
||||
$('.group_category:visible .group_blank .user_id_#{john.id}'),
|
||||
$('#group_#{group1.id}'))
|
||||
SCRIPT
|
||||
simulate_group_drag(john.id, "blank", group1.id)
|
||||
unassigned_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
group1_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
|
||||
# from group1 to group2
|
||||
# driver.action.drag_and_drop(john_li, group2_div).perform
|
||||
driver.execute_script(<<-SCRIPT)
|
||||
window.contextGroups.moveToGroup(
|
||||
$('#group_#{group1.id} .user_id_#{john.id}'),
|
||||
$('#group_#{group2.id}'))
|
||||
SCRIPT
|
||||
simulate_group_drag(john.id, group1.id, group2.id)
|
||||
group1_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
group2_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
|
||||
# from group2 to unassigned
|
||||
# driver.action.drag_and_drop(john_li, unassigned_div).perform
|
||||
driver.execute_script(<<-SCRIPT)
|
||||
window.contextGroups.moveToGroup(
|
||||
$('#group_#{group2.id} .user_id_#{john.id}'),
|
||||
$('.group_category:visible .group_blank'))
|
||||
SCRIPT
|
||||
simulate_group_drag(john.id, group2.id, "blank")
|
||||
group2_div.find_elements(:css, ".user_id_#{john.id}").should be_empty
|
||||
unassigned_div.find_elements(:css, ".user_id_#{john.id}").should_not be_empty
|
||||
end
|
||||
|
||||
it "should check all user sections for a section specific group" do
|
||||
@other_section = @course.course_sections.create!(:name => "Other Section")
|
||||
@third_section = @course.course_sections.create!(:name => "Third Section")
|
||||
|
||||
@course.enroll_student(s1 = user_model(:name => "Student 1"))
|
||||
@course.enroll_student(s2 = user_model(:name => "Student 2"), :section => @other_section)
|
||||
@course.enroll_student(s3 = user_model(:name => "Student 3"), :section => @third_section)
|
||||
@course.enroll_student(s4 = user_model(:name => "Student 4"))
|
||||
|
||||
@course.student_enrollments.create!(:user => s4,
|
||||
:workflow_state => "active",
|
||||
:course_section => @other_section)
|
||||
|
||||
group_category = @course.group_categories.create(:name => "Other Groups")
|
||||
group1 = @course.groups.create(:name => "Group 1", :group_category => group_category)
|
||||
group2 = @course.groups.create(:name => "Group 2", :group_category => group_category)
|
||||
group3 = @course.groups.create(:name => "Group 3", :group_category => group_category)
|
||||
|
||||
get "/courses/#{@course.id}/groups"
|
||||
wait_for_ajaximations
|
||||
|
||||
category_div = driver.find_element(:css, ".group_category")
|
||||
group1_div = category_div.find_element(:css, "#group_#{group1.id}")
|
||||
group2_div = category_div.find_element(:css, "#group_#{group2.id}")
|
||||
group3_div = category_div.find_element(:css, "#group_#{group3.id}")
|
||||
|
||||
edit_category(:enable_self_signup => true, :restrict_self_signup => true)
|
||||
simulate_group_drag(s1.id, "blank", group1.id)
|
||||
simulate_group_drag(s2.id, "blank", group2.id)
|
||||
simulate_group_drag(s3.id, "blank", group3.id)
|
||||
wait_for_ajaximations
|
||||
|
||||
simulate_group_drag(s4.id, "blank", group1.id)
|
||||
wait_for_ajaximations
|
||||
|
||||
group1.reload; group2.reload; group2.reload;
|
||||
group1.users.length.should == 2
|
||||
group2.users.length.should == 1
|
||||
group3.users.length.should == 1
|
||||
|
||||
simulate_group_drag(s4.id, group1.id, group2.id)
|
||||
wait_for_ajaximations
|
||||
|
||||
group1.reload; group2.reload; group2.reload;
|
||||
group1.users.length.should == 1
|
||||
group2.users.length.should == 2
|
||||
group3.users.length.should == 1
|
||||
|
||||
simulate_group_drag(s4.id, group2.id, group3.id)
|
||||
wait_for_ajaximations
|
||||
|
||||
group1.reload; group2.reload; group2.reload;
|
||||
group1.users.length.should == 1
|
||||
group2.users.length.should == 2
|
||||
group3.users.length.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
context "assign_students_link" do
|
||||
|
||||
def assign_students(category)
|
||||
assign_students = find_with_jquery("#category_#{category.id} .assign_students_link:visible")
|
||||
assign_students.should_not be_nil
|
||||
|
@ -212,4 +304,4 @@ describe "manage groups students" do
|
|||
assert_flash_notice_message /Students assigned to groups/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue