add filter-enrollmentless-course functionality. refs #4497, closes #4602

Change-Id: Ie49f5d4baf236f104cba89eac940c473e1fb00f0
Reviewed-on: https://gerrit.instructure.com/3859
Reviewed-by: Jacob Fugal <jacob@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
This commit is contained in:
JT Olds 2011-05-26 16:23:06 -06:00
parent a97820789c
commit 6496094a1b
6 changed files with 206 additions and 41 deletions

View File

@ -28,7 +28,7 @@ class AccountsController < ApplicationController
return redirect_to account_settings_url(@account) if @account.site_admin?
if authorized_action(@account, @current_user, :read)
load_course_right_side
@courses = @account.fast_all_courses(:term => @term, :limit => @maximum_courses_im_gonna_show)
@courses = @account.fast_all_courses(:term => @term, :limit => @maximum_courses_im_gonna_show, :hide_enrollmentless_courses => @hide_enrollmentless_courses)
build_course_stats
end
end
@ -192,9 +192,15 @@ class AccountsController < ApplicationController
def load_course_right_side
@root_account = @account.root_account || @account
@maximum_courses_im_gonna_show = 100
@term = nil
if params[:enrollment_term_id].present?
@term = @root_account.enrollment_terms.active.find(params[:enrollment_term_id]) rescue nil
@term ||= @root_account.enrollment_terms.active[-1]
@associated_courses_count = @account.associated_courses.active.for_term(@term).uniq.count
end
associated_courses = @account.associated_courses.active
associated_courses = associated_courses.for_term(@term) if @term
@associated_courses_count = associated_courses.uniq.count
@hide_enrollmentless_courses = params[:hide_enrollmentless_courses] == "1"
end
protected :load_course_right_side
@ -325,7 +331,9 @@ class AccountsController < ApplicationController
load_course_right_side
@courses = []
@query = (params[:course] && params[:course][:name]) || params[:query]
@courses = @context.courses_name_like(@query) if @context && @context.is_a?(Account) && @query
if @context && @context.is_a?(Account) && @query
@courses = @context.courses_name_like(@query, :term => @term, :hide_enrollmentless_courses => @hide_enrollmentless_courses)
end
respond_to do |format|
format.html {
build_course_stats

View File

@ -226,10 +226,20 @@ class Account < ActiveRecord::Base
@cached_users_name_like[query] ||= self.fast_all_users.name_like(query)
end
def fast_all_courses(opts = {})
def fast_course_base(opts)
columns = "courses.id, courses.name, courses.section, courses.workflow_state, courses.course_code, courses.sis_source_id"
conditions = []
if opts[:hide_enrollmentless_courses]
conditions = ["exists (#{Enrollment.active.send(:construct_finder_sql, {:select => "1", :conditions => ["enrollments.course_id = courses.id"]})})"]
end
associated_courses = self.associated_courses.active
associated_courses = associated_courses.for_term(opts[:term]) if opts[:term].present?
(yield associated_courses).limit(opts[:limit]).active_first.find(:all, :select => columns, :group => columns, :conditions => conditions)
end
def fast_all_courses(opts={})
@cached_fast_all_courses ||= {}
@cached_fast_all_courses[opts] ||= self.associated_courses.active.for_term(opts[:term]).active_first.limit(opts[:limit]).find(:all, :select => columns, :group => columns)
@cached_fast_all_courses[opts] ||= self.fast_course_base(opts) {|q| q}
end
def all_users(limit=250)
@ -254,11 +264,11 @@ class Account < ActiveRecord::Base
ORDER BY u.sortable_name ASC", self.id], :page => page, :per_page => per_page)
end
def courses_name_like(query="")
columns = "courses.id, name, courses.workflow_state, courses.course_code, courses.sis_source_id"
self.associated_courses.active.active_first.name_like(query).limit(200).find(:all, :select => columns, :group => columns)
def courses_name_like(query="", opts={})
opts[:limit] ||= 200
@cached_courses_name_like ||= {}
@cached_courses_name_like[[query, opts]] ||= self.fast_course_base(opts) {|q| q.name_like(query)}
end
memoize :courses_name_like
def file_namespace
root = self.root_account || self

View File

@ -348,7 +348,7 @@ class Course < ActiveRecord::Base
term ? {:conditions => ['courses.enrollment_term_id = ?', term.id]} : {}
}
named_scope :active_first, lambda {
{:order => "CASE WHEN workflow_state='available' THEN 0 ELSE 1 END, name"}
{:order => "CASE WHEN courses.workflow_state='available' THEN 0 ELSE 1 END, name"}
}
named_scope :limit, lambda {|limit|
{:limit => limit }

View File

@ -1,19 +1,29 @@
<% term_count = @root_account.enrollment_terms.active.count %>
<% if term_count > 1 || @associated_courses_count > 0 %>
<% if term_count > 1 %>
<h2><%= t(:choose_term_label, "Choose Term")%></h2>
<h2><%= t(:course_filtering, "Course Filtering")%></h2>
<div class="rs-margin-lr rs-margin-bottom">
<form method="get">
<% if term_count > 1 %>
<label for="enrollment_term"><%= before_label(t(:enrollment_term_label, "Show courses from the term")) %></label><br />
<select id="enrollment_term">
<select name="enrollment_term_id">
<option value="" <%= 'selected' unless @term %>><%= t(:all_terms, "All Terms") %></option>
<% @root_account.enrollment_terms.active.each do |term| %>
<option value="<%= context_url(@account, :context_url, :enrollment_term_id => term.id) %>" <%= 'selected' if term == @term %>><%= term.name %></option>
<option value="<%= term.id %>" <%= 'selected' if term == @term %>><%= term.name %></option>
<% end %>
</select>
</div>
<br />
<% end %>
<% if @query.present? %><input name="course[name]" type="hidden" value="<%= @query %>" /><% end %>
<input name="hide_enrollmentless_courses" type="hidden" value="0" />
<input name="hide_enrollmentless_courses" type="checkbox" value="1" <% if params[:hide_enrollmentless_courses] == "1" %>checked="checked"<% end %>/>
<label for="hide_enrollmentless_courses"><%= t(:hide_enrollmentless_courses, "Hide enrollmentless courses") %></label>
<br />
<button class='button'><%= t("#buttons.filter", "Filter") %></button>
</form>
</div>
<% if @associated_courses_count > 0 %>
<h2><label for="filter"><%= t(:filter_label, "Find a Course") %></label></h2>
<h2><label><%= t(:filter_label, "Find a Course") %></label></h2>
<div class="rs-margin-lr rs-margin-bottom">
<% form_for :course, :url => account_courses_path(@account), :html => {:id => "new_course", :method => :get} do |f| -%>
<fieldset class="textfield-inline-with-button">

View File

@ -37,13 +37,6 @@
<% js_block do %>
<script type="text/javascript">
$(document).ready(function() {
$("#filter").keyup(function(){
var val = $(this).val().toLowerCase();
$(".courses li .name a").each(function(){
$(this).closest('li')[ $(this).text().toLowerCase().match(val) ? 'show' : 'hide']();
});
});
$(".courses .course,.groups .group").bind('focus mouseover', function(event) {
$(this).find(".info").addClass('info_hover');
@ -51,11 +44,6 @@ $(document).ready(function() {
$(".courses .course,.groups .group").bind('blur mouseout', function(event) {
$(this).find(".info").removeClass('info_hover');
});
$("#enrollment_term").change(function() {
if(location.href != $(this).val()) {
location.href = $(this).val();
}
});
if($("#new_course").length > 0) {
var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');
var $newCourseForm = $("#new_course"),

View File

@ -45,6 +45,155 @@ describe Account do
# @a.to_atom.should be_is_a(Atom::Entry)
# end
def process_csv_data(account, lines)
tmp = Tempfile.new("sis_rspec")
path = "#{tmp.path}.csv"
tmp.close!
File.open(path, "w+") { |f| f.puts lines.join "\n" }
importer = SIS::SisCsv.process(@account, :files => [path],
:allow_printing => false)
File.unlink path
importer.warnings.should == []
importer.errors.should == []
end
context "course lists" do
before(:each) do
@account = Account.create!
process_csv_data(@account, [
"user_id,login_id,first_name,last_name,email,status",
"U001,user1,User,One,user1@example.com,active",
"U002,user2,User,Two,user2@example.com,active",
"U003,user3,User,Three,user3@example.com,active",
"U004,user4,User,Four,user4@example.com,active",
"U005,user5,User,Five,user5@example.com,active",
"U006,user6,User,Six,user6@example.com,active",
"U007,user7,User,Seven,user7@example.com,active",
"U008,user8,User,Eight,user8@example.com,active",
"U009,user9,User,Nine,user9@example.com,active",
"U010,user10,User,Ten,user10@example.com,active",
"U011,user11,User,Eleven,user11@example.com,deleted"
])
process_csv_data(@account, [
"term_id,name,status,start_date,end_date",
"T001,Term 1,active,,",
"T002,Term 2,active,,",
"T003,Term 3,active,,"
])
process_csv_data(@account, [
"course_id,short_name,long_name,account_id,term_id,status",
"C001,C001,Test Course 1,,T001,active",
"C002,C002,Test Course 2,,T001,deleted",
"C003,C003,Test Course 3,,T002,deleted",
"C004,C004,Test Course 4,,T002,deleted",
"C005,C005,Test Course 5,,T003,active",
"C006,C006,Test Course 6,,T003,active",
"C007,C007,Test Course 7,,T003,active",
"C008,C008,Test Course 8,,T003,active",
"C009,C009,Test Course 9,,T003,active",
"C001S,C001S,Test search Course 1,,T001,active",
"C002S,C002S,Test search Course 2,,T001,deleted",
"C003S,C003S,Test search Course 3,,T002,deleted",
"C004S,C004S,Test search Course 4,,T002,deleted",
"C005S,C005S,Test search Course 5,,T003,active",
"C006S,C006S,Test search Course 6,,T003,active",
"C007S,C007S,Test search Course 7,,T003,active",
"C008S,C008S,Test search Course 8,,T003,active",
"C009S,C009S,Test search Course 9,,T003,active"
])
process_csv_data(@account, [
"section_id,course_id,name,start_date,end_date,status",
"S001,C001,Sec1,,,active",
"S002,C002,Sec2,,,active",
"S003,C003,Sec3,,,active",
"S004,C004,Sec4,,,active",
"S005,C005,Sec5,,,active",
"S006,C006,Sec6,,,active",
"S007,C007,Sec7,,,deleted",
"S008,C001,Sec8,,,deleted",
"S009,C008,Sec9,,,active",
"S001S,C001S,Sec1,,,active",
"S002S,C002S,Sec2,,,active",
"S003S,C003S,Sec3,,,active",
"S004S,C004S,Sec4,,,active",
"S005S,C005S,Sec5,,,active",
"S006S,C006S,Sec6,,,active",
"S007S,C007S,Sec7,,,deleted",
"S008S,C001S,Sec8,,,deleted",
"S009S,C008S,Sec9,,,active"
])
process_csv_data(@account, [
"course_id,user_id,role,section_id,status,associated_user_id",
",U001,student,S001,active,",
",U002,student,S002,active,",
",U003,student,S003,active,",
",U004,student,S004,active,",
",U005,student,S005,active,",
",U006,student,S006,deleted,",
",U007,student,S007,active,",
",U008,student,S008,active,",
",U009,student,S005,deleted,",
",U001,student,S001S,active,",
",U002,student,S002S,active,",
",U003,student,S003S,active,",
",U004,student,S004S,active,",
",U005,student,S005S,active,",
",U006,student,S006S,deleted,",
",U007,student,S007S,active,",
",U008,student,S008S,active,",
",U009,student,S005S,deleted,"
])
end
context "fast list" do
it "should list associated courses" do
@account.fast_all_courses.map(&:sis_source_id).sort.should == [
"C001", "C005", "C006", "C007", "C008", "C009",
"C001S", "C005S", "C006S", "C007S", "C008S", "C009S", ].sort
end
it "should list associated courses by term" do
@account.fast_all_courses({:term => EnrollmentTerm.find_by_sis_source_id("T001")}).map(&:sis_source_id).sort.should == ["C001", "C001S"]
@account.fast_all_courses({:term => EnrollmentTerm.find_by_sis_source_id("T002")}).map(&:sis_source_id).sort.should == []
@account.fast_all_courses({:term => EnrollmentTerm.find_by_sis_source_id("T003")}).map(&:sis_source_id).sort.should == ["C005", "C006", "C007", "C008", "C009", "C005S", "C006S", "C007S", "C008S", "C009S"].sort
end
it "should list associated nonenrollmentless courses" do
@account.fast_all_courses({:hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == ["C001", "C005", "C007", "C001S", "C005S", "C007S"].sort #C007 probably shouldn't be here, cause the enrollment section is deleted, but we kinda want to minimize database traffic
end
it "should list associated nonenrollmentless courses by term" do
@account.fast_all_courses({:term => EnrollmentTerm.find_by_sis_source_id("T001"), :hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == ["C001", "C001S"]
@account.fast_all_courses({:term => EnrollmentTerm.find_by_sis_source_id("T002"), :hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == []
@account.fast_all_courses({:term => EnrollmentTerm.find_by_sis_source_id("T003"), :hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == ["C005", "C007", "C005S", "C007S"].sort
end
end
context "name searching" do
it "should list associated courses" do
@account.courses_name_like("search").map(&:sis_source_id).sort.should == [
"C001S", "C005S", "C006S", "C007S", "C008S", "C009S"]
end
it "should list associated courses by term" do
@account.courses_name_like("search", {:term => EnrollmentTerm.find_by_sis_source_id("T001")}).map(&:sis_source_id).sort.should == ["C001S"]
@account.courses_name_like("search", {:term => EnrollmentTerm.find_by_sis_source_id("T002")}).map(&:sis_source_id).sort.should == []
@account.courses_name_like("search", {:term => EnrollmentTerm.find_by_sis_source_id("T003")}).map(&:sis_source_id).sort.should == ["C005S", "C006S", "C007S", "C008S", "C009S"]
end
it "should list associated nonenrollmentless courses" do
@account.courses_name_like("search", {:hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == ["C001S", "C005S", "C007S"] #C007 probably shouldn't be here, cause the enrollment section is deleted, but we kinda want to minimize database traffic
end
it "should list associated nonenrollmentless courses by term" do
@account.courses_name_like("search", {:term => EnrollmentTerm.find_by_sis_source_id("T001"), :hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == ["C001S"]
@account.courses_name_like("search", {:term => EnrollmentTerm.find_by_sis_source_id("T002"), :hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == []
@account.courses_name_like("search", {:term => EnrollmentTerm.find_by_sis_source_id("T003"), :hide_enrollmentless_courses => true}).map(&:sis_source_id).sort.should == ["C005S", "C007S"]
end
end
end
context "services" do
before(:each) do
@a = Account.new