Changes the courses page to include additional functionality

closes CNVS-14683, CNVS-14684, CNVS-14685

test plan:
   - Go to the courses page (/courses)
   - Make sure you have enrollments in various courses in various
     states (e.g., unpublished/published, past/future/current)
   - Each section (My Courses, etc.) should have a table within
   - My Courses should have stars in the first column
   - Clicking on a star should toggle the color of the star
     if the course is favoritable, e.g. students can favorite
     courses that are unpublished, while teachers can.
   - Stars that are colored yellow, should appear in the courses
     dropdown on the main navigation after a refresh.
   - The type of enrollment should be indicated on the far right.
   - Unpublished courses should have an indicator to the left
     of the enrollment type.
   - Hovering over the unpublished courses should have a
     tooltip saying:
     "This course has not been published. Students should contact
      the course instructor for access."
   - Screenreaders should also detect this information.

Change-Id: I660485b5143f877ef231b0edb52b2c82b8cdaab3
Reviewed-on: https://gerrit.instructure.com/39227
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Jeremy Stanley <jeremy@instructure.com>
QA-Review: Clare Strong <clare@instructure.com>
Product-Review: Hilary Scharton <hilary@instructure.com>
This commit is contained in:
Clay Diffrient 2014-08-13 09:22:06 -06:00
parent 5ab6d5beb5
commit 62a447c569
8 changed files with 166 additions and 47 deletions

View File

@ -0,0 +1,33 @@
require [
'jquery'
'i18n!course_list'
], ($, I18n) ->
success = (target) ->
favorited_tooltip = I18n.t('favorited_tooltip', "Click to remove from the courses menu.")
nonfavorite_tooltip = I18n.t('nonfavorited_tooltip', 'Click to add to the courses menu.')
if target.hasClass 'course-list-favorite-course'
target.removeClass 'course-list-favorite-course'
target.attr('title', nonfavorite_tooltip)
# The tooltip wouldn't update with just changing the title so
# it's forced to do so here. Same below in the else case.
target.data('ui-tooltip-title', nonfavorite_tooltip)
target.children('.screenreader-only').text(nonfavorite_tooltip)
else
target.addClass 'course-list-favorite-course'
target.attr('title', favorited_tooltip)
target.data('ui-tooltip-title', favorited_tooltip)
target.children('.screenreader-only').text(favorited_tooltip)
$('[data-favorite-url]').on 'click keyclick', (event) ->
event.preventDefault();
url = $(this).data('favoriteUrl')
target = $(event.currentTarget)
if target.hasClass 'course-list-favorite-course'
$.ajaxJSON url, 'DELETE', {}, success(target), null
else
$.ajaxJSON url, 'POST', {}, success(target), null

View File

@ -0,0 +1,44 @@
table.course-list-table
{
td.course-list-star-column {
width: 3%;
padding-left: 15px;
color: #eee;
text-shadow: -1px 0 #eee, 0 1px #eee, 1px 0 #eee, 0 -1px #eee;
}
td.course-list-enrolled-as-column {
width: 20%;
text-align: right;
padding-right: 15px;
}
td.course-list-course-title-column {
width: 57%;
}
td.course-list-unpublished-column {
width: 20%;
}
td.course-list-no-left-border {
border-left: 0;
}
.course-list-not-favoritable {
width: 60%;
}
.course-list-table-row:hover {
background-color: #eee;
}
}
.course-list-favorite-course {
color: #ffdba1;
text-shadow: none;
}
.course-list-label-hollow {
background: none;
border: 2px solid #999;
color: #999;
text-shadow: none;
}

View File

@ -18,47 +18,52 @@
<% end %> <% end %>
<% end %> <% end %>
<% jammit_css :context_list %> <% jammit_css :context_list, :course_list %>
<% js_bundle :course_list %>
<% @favorite_course_ids = @current_user.courses_with_primary_enrollment(:favorite_courses).map(&:id) %>
<% @show_star_column = true %>
<% unless @current_enrollments.empty? %> <% unless @current_enrollments.empty? %>
<h2><%= t('headings.my_courses', %{My Courses}) %></h2> <h2><%= t('headings.my_courses', %{My Courses}) %></h2>
<ul class="unstyled_list context_list current_enrollments"> <table id="my_courses_table" class="table table-bordered current_enrollments course-list-table">
<% @current_enrollments.each do |enrollment| %> <% @current_enrollments.each do |enrollment| %>
<%= render :partial => "shared/current_enrollment", :object => enrollment %> <%= render :partial => "shared/current_enrollment", :object => enrollment %>
<% end %> <% end %>
</ul> </table>
<% end %> <% end %>
<% @show_star_column = false %>
<% unless @current_user.current_groups.empty? %> <% unless @current_user.current_groups.empty? %>
<h2><%= t('headings.my_groups', %{My Groups}) %></h2> <h2><%= t('headings.my_groups', %{My Groups}) %></h2>
<ul class="unstyled_list context_list current_groups"> <table id="my_groups_table" class="table table-bordered current_groups course-list-table">
<% @current_user.current_groups.each do |group| %> <% @current_user.current_groups.each do |group| %>
<% group_name = group.name %> <% group_name = group.name %>
<li> <tr>
<td>
<a href=<%= group_path(group) %>> <a href=<%= group_path(group) %>>
<span class="name ellipsis" title=<%= group_name %>> <span class="name ellipsis" title=<%= group_name %>>
<%= group_name %> <%= group_name %>
</span> </span>
</a> </a>
</li> </td>
</tr>
<% end %> <% end %>
</ul> </table>
<% end %> <% end %>
<% unless @past_enrollments.empty? %> <% unless @past_enrollments.empty? %>
<h2><%= t('headings.past_enrollments', %{Past Enrollments}) %></h2> <h2><%= t('headings.past_enrollments', %{Past Enrollments}) %></h2>
<ul class="unstyled_list context_list past_enrollments"> <table id="past_enrollments_table" class="table table-bordered past_enrollments course-list-table">
<% @past_enrollments.each do |enrollment| %> <% @past_enrollments.each do |enrollment| %>
<%= render :partial => "shared/current_enrollment", :object => enrollment %> <%= render :partial => "shared/current_enrollment", :object => enrollment %>
<% end %> <% end %>
</ul> </table>
<% end %> <% end %>
<% unless @future_enrollments.empty? %> <% unless @future_enrollments.empty? %>
<h2><%= t('headings.future_enrollments', 'Future Enrollments') %></h2> <h2><%= t('headings.future_enrollments', 'Future Enrollments') %></h2>
<ul class="unstyled_list context_list future_enrollments"> <table id="future_enrollments_table" class="table table-bordered future_enrollments course-list-table">
<% @future_enrollments.each do |enrollment| %> <% @future_enrollments.each do |enrollment| %>
<%= render :partial => 'shared/current_enrollment', :object => enrollment %> <%= render :partial => 'shared/current_enrollment', :object => enrollment %>
<% end %> <% end %>
</ul> </table>
<% end %> <% end %>

View File

@ -1,6 +1,6 @@
<% dashboard ||= false %> <% dashboard ||= false %>
<% unless dashboard %> <% unless dashboard %>
<li class="<%= 'unpublished' if current_enrollment.course.created? || current_enrollment.course.claimed? %> <%= current_enrollment.state_based_on_date %>"> <tr class="course-list-table-row">
<% end %> <% end %>
<% if current_enrollment.workflow_state == "invited" %> <% if current_enrollment.workflow_state == "invited" %>
<div class="<%= dashboard ? 'communication_message dashboard_notification alert alert-info' : 'reminder' %>"> <div class="<%= dashboard ? 'communication_message dashboard_notification alert alert-info' : 'reminder' %>">
@ -11,34 +11,68 @@
</div> </div>
<% else %> <% else %>
<% show_link = current_enrollment.course.grants_right?(@current_user, session, :read) %> <% show_link = current_enrollment.course.grants_right?(@current_user, session, :read) %>
<% if show_link %><a href="<%= course_path(current_enrollment.course_id) %>"><% end %> <% if @show_star_column %>
<span class="name ellipsis" title="<%= current_enrollment.long_name %>"> <td class="course-list-star-column">
<%= current_enrollment.long_name %> <% favorite_course = @favorite_course_ids.include?(current_enrollment.course_id) %>
<% if current_enrollment.admin? && (current_enrollment.course.created? || current_enrollment.course.claimed?) %> <% tooltip_message = t('favorited_tooltip', "Click to remove from the courses menu.") if favorite_course %>
<%= image_tag "hammer.png", :title => t('course_unpublished', "This course hasn't been published yet"), :alt => "Unpublished", :class => "unpublished_icon" %> <% tooltip_message = t('nonfavorited_tooltip', "Click to add to the courses menu.") if !favorite_course %>
<% tooltip_message = t('not_favoritable_tooltip', "This course cannot be add to the courses menu at this time.") if !show_link %>
<span
class="<%= "course-list-favorite-course" if favorite_course %> <%= "course-list-not-favoritable disabled" if !show_link %> <%= "course-list-favoritable" if show_link %>"
data-tooltip="bottom"
title="<%= tooltip_message %>"
role="button"
tabindex="0"
data-course-id="<%= current_enrollment.course_id %>"
<%= "data-favorite-url=#{api_v1_add_favorite_course_url(current_enrollment.course_id)}" if show_link %>
>
<i class="icon-star" ></i>
<span id="course_list_screenreader_message_<%= current_enrollment.course_id %>" class="screenreader-only">
<%= tooltip_message %>
</span>
</span>
</td>
<% end %> <% end %>
</span> <td class="course-list-course-title-column
<%= "course-list-no-left-border" if @show_star_column %>
<%= "course-list-not-favoritable" unless @show_star_column %>">
<% if show_link %><a href="<%= course_path(current_enrollment.course_id) %>"><% end %>
<span class="name ellipsis" title="<%= current_enrollment.long_name %>">
<%= current_enrollment.long_name %>
</span>
<% unless current_enrollment.course.enrollment_term.default_term? %>
<span class="subtitle ellipsis"><%= current_enrollment.course.enrollment_term.name %></span>
<% end %>
<% if show_link %></a><% end %>
</td>
<td class="course-list-unpublished-column course-list-no-left-border">
<% if current_enrollment.course.created? || current_enrollment.course.claimed? %>
<span data-tooltip title="<%= t('unpublished_course_tooltip', "This course has not been published. Students should contact the course instructor for access.") %>"
class="label label-hollow"><%= t('unpublished_course', "unpublished") %></span>
<span class="screenreader-only"><%= t('unpublished_course_tooltip', "This course has not been published. Students should contact the course instructor for access.") %></span>
<% end %>
</td>
<td class="course-list-enrolled-as-column course-list-no-left-border">
<%
message = t('enrolled_as_student', "Enrolled as a student")
case current_enrollment.type
when 'TeacherEnrollment'
message = t('enrolled_as_teacher', "Enrolled as a teacher")
when 'TaEnrollment'
message = t('enrolled_as_ta', "Enrolled as a TA")
when 'ObserverEnrollment'
message = t('enrolled_as_observer', "Enrolled as an observer")
when 'DesignerEnrollment'
message = t('enrolled_as_designer', "Enrolled as a designer")
end
%>
<span class="subtitle ellipsis"><%= message %></span>
</td>
<% unless current_enrollment.course.enrollment_term.default_term? %>
<span class="subtitle ellipsis"><%= current_enrollment.course.enrollment_term.name %></span>
<% end %>
<%
message = t('enrolled_as_student', "Enrolled as a student")
case current_enrollment.type
when 'TeacherEnrollment'
message = t('enrolled_as_teacher', "Enrolled as a teacher")
when 'TaEnrollment'
message = t('enrolled_as_ta', "Enrolled as a TA")
when 'ObserverEnrollment'
message = t('enrolled_as_observer', "Enrolled as an observer")
when 'DesignerEnrollment'
message = t('enrolled_as_designer', "Enrolled as a designer")
end
%>
<span class="subtitle ellipsis"><%= message %></span>
<% if show_link %></a><% end %>
<% end %> <% end %>
<% unless dashboard %> <% unless dashboard %>
</li> </tr>
<% end %> <% end %>

View File

@ -22,6 +22,8 @@ stylesheets:
- public/stylesheets/compiled/pages/instructure_eportfolio.css - public/stylesheets/compiled/pages/instructure_eportfolio.css
course_show: course_show:
- public/stylesheets/compiled/pages/course_show.css - public/stylesheets/compiled/pages/course_show.css
course_list:
- public/stylesheets/compiled/pages/course_list.css
content_migrations: content_migrations:
- public/stylesheets/compiled/pages/content_migrations.css - public/stylesheets/compiled/pages/content_migrations.css
vendor: vendor:
@ -125,9 +127,9 @@ stylesheets:
select_content_dialog: select_content_dialog:
- public/stylesheets/compiled/pages/select_content_dialog.css - public/stylesheets/compiled/pages/select_content_dialog.css
conversations_new: conversations_new:
# TODO: we need to look at what's being used here and if we can get purge this file and use # TODO: we need to look at what's being used here and if we can get purge this file and use
# the styles in /bootstrap/ # the styles in /bootstrap/
- public/javascripts/vendor/bootstrap-select/bootstrap-select.css - public/javascripts/vendor/bootstrap-select/bootstrap-select.css
# end # end
- public/stylesheets/compiled/pages/conversations/compiler-conversations.css - public/stylesheets/compiled/pages/conversations/compiler-conversations.css
alerts: alerts:

View File

@ -1278,8 +1278,8 @@ CanvasRails::Application.routes.draw do
scope(:controller => :favorites) do scope(:controller => :favorites) do
get "users/self/favorites/courses", :action => :list_favorite_courses, :path_name => :list_favorite_courses get "users/self/favorites/courses", :action => :list_favorite_courses, :path_name => :list_favorite_courses
post "users/self/favorites/courses/:id", :action => :add_favorite_course post "users/self/favorites/courses/:id", :action => :add_favorite_course, :path_name => :add_favorite_course
delete "users/self/favorites/courses/:id", :action => :remove_favorite_course delete "users/self/favorites/courses/:id", :action => :remove_favorite_course, :path_name => :remove_favorite_course
delete "users/self/favorites/courses", :action => :reset_course_favorites delete "users/self/favorites/courses", :action => :reset_course_favorites
end end

View File

@ -44,11 +44,12 @@ describe "enrollment_date_restrictions" do
get "/courses" get "/courses"
page = Nokogiri::HTML(response.body) page = Nokogiri::HTML(response.body)
active_enrollments = page.css(".current_enrollments li") active_enrollments = page.css(".current_enrollments tr")
active_enrollments.length.should == 1 active_enrollments.length.should == 1
active_enrollments[0]['class'].should match /active/ # Make sure that the active coures have the star column.
active_enrollments[0].css('td')[0]['class'].should match /star-column/
page.css(".past_enrollments li").should be_empty page.css(".past_enrollments tr").should be_empty
end end
it "should not show deleted enrollments in past enrollments when course is completed" do it "should not show deleted enrollments in past enrollments when course is completed" do

View File

@ -396,7 +396,7 @@ describe "dashboard" do
c1.reload c1.reload
get "/courses" get "/courses"
f('.past_enrollments').should include_text(c1.name) fj("#past_enrollments_table a[href='/courses/#{@course.id}']").should include_text(c1.name)
end end
it "should display assignment to grade in to do list and assignments menu for a teacher" do it "should display assignment to grade in to do list and assignments menu for a teacher" do