Fix homeroom courses having annoucements mistakenly hidden
Fixes: LS-2507 flag=none test plan: - With a k5 account, create a role without :read_announcements permission - Have 2 courses (say A and B) with announcements - Enroll the teacher into course A using the default teacher role - Enroll the teacher into course B using the role you created. - Make course A a homeroom course. - Favorite both courses - Visit the homeroom page as the teacher - Check that the announcements for course A are shown - Check that the announcements for course B are hidden Change-Id: Ic02a35abd5afda0ba17b6408dd01328a59b8428b Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/271572 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Ed Schiebel <eschiebel@instructure.com> QA-Review: Ed Schiebel <eschiebel@instructure.com> Product-Review: Luis Oliveira <luis.oliveira@instructure.com>
This commit is contained in:
parent
6f849ee3ca
commit
c58d0cc0af
|
@ -88,7 +88,6 @@ class AnnouncementsApiController < ApplicationController
|
|||
# @returns [DiscussionTopic]
|
||||
def index
|
||||
courses = api_find_all(Course, @course_ids)
|
||||
return unless courses.all? { |course| authorized_action(course, @current_user, :read_announcements) }
|
||||
|
||||
scope = Announcement.where(:context_type => 'Course', :context_id => courses)
|
||||
|
||||
|
|
|
@ -509,6 +509,14 @@ class AssignmentsController < ApplicationController
|
|||
rce_js_env
|
||||
add_crumb @context.elementary_enabled? ? t("Important Info") : t('#crumbs.syllabus', "Syllabus")
|
||||
active_tab = "Syllabus"
|
||||
|
||||
@course_home_sub_navigation_tools =
|
||||
ContextExternalTool.all_tools_for(@context, placements: :course_home_sub_navigation,
|
||||
root_account: @domain_root_account, current_user: @current_user).to_a
|
||||
unless @context.grants_right?(@current_user, session, :manage_content)
|
||||
@course_home_sub_navigation_tools.reject! {|tool| tool.course_home_sub_navigation(:visibility) == 'admins'}
|
||||
end
|
||||
|
||||
if authorized_action(@context, @current_user, [:read, :read_syllabus])
|
||||
return unless tab_enabled?(@context.class::TAB_SYLLABUS)
|
||||
@groups = @context.assignment_groups.active.order(
|
||||
|
|
|
@ -2104,6 +2104,7 @@ class CoursesController < ApplicationController
|
|||
@course_home_view ||= default_view
|
||||
@course_home_view = "k5_dashboard" if @context.elementary_subject_course?
|
||||
@course_home_view = "announcements" if @context.elementary_homeroom_course?
|
||||
@course_home_view = "syllabus" if @context.elementary_homeroom_course? && !@context.grants_right?(@current_user, session, :read_announcements)
|
||||
|
||||
course_env_variables = {}
|
||||
# env.COURSE variables that apply to both classic and k5 courses
|
||||
|
@ -2163,7 +2164,7 @@ class CoursesController < ApplicationController
|
|||
when 'syllabus'
|
||||
set_active_tab "syllabus"
|
||||
rce_js_env
|
||||
add_crumb(t('#crumbs.syllabus', "Syllabus"))
|
||||
add_crumb @context.elementary_enabled? ? t("Important Info") : t('#crumbs.syllabus', "Syllabus")
|
||||
@groups = @context.assignment_groups.active.order(
|
||||
:position,
|
||||
AssignmentGroup.best_unicode_collation_key('name')
|
||||
|
@ -2234,7 +2235,8 @@ class CoursesController < ApplicationController
|
|||
CONTEXT_MODULE_ASSIGNMENT_INFO_URL: context_url(@context, :context_context_modules_assignment_info_url),
|
||||
PERMISSIONS: {
|
||||
manage: @context.grants_right?(@current_user, session, :manage),
|
||||
read_as_admin: @context.grants_right?(@current_user, session, :read_as_admin)
|
||||
read_as_admin: @context.grants_right?(@current_user, session, :read_as_admin),
|
||||
read_announcements: @context.grants_right?(@current_user, session, :read_announcements)
|
||||
},
|
||||
STUDENT_PLANNER_ENABLED: planner_enabled?,
|
||||
TABS: @context.tabs_available(@current_user, course_subject_tabs: true),
|
||||
|
|
|
@ -59,6 +59,7 @@ class CourseForMenuPresenter
|
|||
isK5Subject: course.elementary_subject_course?,
|
||||
isHomeroom: course.homeroom_course,
|
||||
canManage: course.grants_right?(@user, :manage_content),
|
||||
canReadAnnouncements: course.grants_right?(@user, :read_announcements),
|
||||
image: course.image,
|
||||
color: course.elementary_enabled? ? course.course_color : nil,
|
||||
position: position.present? ? position.to_i : nil,
|
||||
|
|
|
@ -28,8 +28,12 @@
|
|||
<%= page_title %>
|
||||
<% end %>
|
||||
|
||||
<% unless @context.elementary_enabled? %>
|
||||
<% provide :right_side do %>
|
||||
<% provide :right_side do %>
|
||||
<% if @context.elementary_homeroom_course? && !@context.grants_right?(@current_user, session, :read_announcements) # Sylalbus is serving as course_home %>
|
||||
<%= render :partial => '/courses/course_show_secondary' %>
|
||||
<% end %>
|
||||
|
||||
<% unless @context.elementary_enabled? %>
|
||||
<%= render :partial => 'assignments/syllabus_right_side' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
<div id="course_show_secondary">
|
||||
<% @can_manage = can_do(@context, @current_user, :manage) %>
|
||||
<% @can_create_announcements = @context.announcements.temp_record.grants_right?(@current_user, session, :create) %>
|
||||
<% if can_do(@context, @current_user, :change_course_state, :manage_courses_publish) && (@context.unpublished? || @context.unpublishable?) %>
|
||||
<div id="course_status">
|
||||
<h3>
|
||||
<%= t('headers.course_status', %{Course Status}) %>
|
||||
</h3>
|
||||
<%= render :partial => '/courses/publish_buttons', :locals => {redirect_to_settings: false} %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if can_do(@context, @current_user, :manage_content) %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :context_content_migrations_url) %>">
|
||||
<i class="icon-import"></i>
|
||||
<%= t('links.import', %{Import Existing Content}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @can_manage || @can_create_announcements || @course_home_view != 'feed' || @course_home_sub_navigation_tools.present? %>
|
||||
<div class="course-options">
|
||||
<%= external_tools_menu_items(@course_home_sub_navigation_tools, {link_class: "btn button-sidebar-wide course-home-sub-navigation-lti", settings_key: :course_home_sub_navigation}) %>
|
||||
<% if @can_manage && !@context.elementary_homeroom_course? %>
|
||||
<div id="choose_home_page"></div>
|
||||
<div id="choose_home_page_not_modules"></div>
|
||||
<% end %>
|
||||
|
||||
<% if @course_home_view != 'feed' && !@context.elementary_homeroom_course? %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :context_url, :view => 'feed') %>">
|
||||
<i class="icon-stats"></i>
|
||||
<%= t('links.view_course_stream', %{View Course Stream}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @can_manage && !@domain_root_account.try(:feature_enabled?, :new_user_tutorial) && !@context.elementary_homeroom_course? %>
|
||||
<script>
|
||||
Object.assign(
|
||||
ENV,
|
||||
<%= raw StringifyIds.recursively_stringify_ids({
|
||||
COURSE_WIZARD: {
|
||||
just_saved: @context_just_saved,
|
||||
checklist_states: {
|
||||
import_step: !@context.attachments.active.exists?,
|
||||
assignment_step: !@context.assignments.active.exists?,
|
||||
add_student_step: !@context.students.exists?,
|
||||
navigation_step: @context.tab_configuration.empty?,
|
||||
home_page_step: true,
|
||||
# The current wizard just always marks this as complete.
|
||||
calendar_event_step: !@context.calendar_events.active.exists?,
|
||||
add_ta_step: !@context.tas.exists?,
|
||||
publish_step: @context.workflow_state === 'available'
|
||||
},
|
||||
urls: {
|
||||
content_import: context_url(@context, :context_content_migrations_url),
|
||||
add_assignments: context_url(@context, :context_assignments_url, wizard: 1),
|
||||
add_students: course_users_path(course_id: @context),
|
||||
add_files: context_url(@context, :context_files_url, wizard: 1),
|
||||
select_navigation: context_url(@context, :context_details_url),
|
||||
course_calendar: calendar_path(course_id: @context),
|
||||
add_tas: course_users_path(course_id: @context),
|
||||
publish_course: course_path(@context)
|
||||
},
|
||||
permissions: {
|
||||
can_change_course_publish_state: can_do(@context, @current_user, :change_course_state, :manage_courses_publish)
|
||||
}
|
||||
}
|
||||
}).to_json %>
|
||||
)
|
||||
</script>
|
||||
|
||||
<% js_bundle :course_wizard %>
|
||||
<% css_bundle :course_wizard %>
|
||||
<a href="#" class="btn button-sidebar-wide wizard_popup_link <%= 'auto_open' if @context.created? || @context.claimed? %>">
|
||||
<i class="icon-question"></i> <%= t('links.course_setup', %{Course Setup Checklist}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @can_create_announcements && !@context.elementary_homeroom_course? %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :new_context_discussion_topic_url, :is_announcement => true) %>"><i class="icon-announcement"></i> <%= t('links.new_announcement', %{New Announcement}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% course_custom_links.each do |link| %>
|
||||
<a class="btn button-sidebar-wide" href="<%= link[:url] %>"><i class="<%= link[:icon_class] %>" role="presentation"></i> <%= link[:text] %></a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @context.available? && @context.self_enrollment_enabled? && @context.open_enrollment && (!@context_enrollment || !@context_enrollment.active?) %>
|
||||
<a href="<%= enroll_url(@context.self_enrollment_code) %>" class="btn button-sidebar-wide self_enrollment_link">
|
||||
<i class="icon-user-add"></i>
|
||||
<%= t('links.join_course', %{Join this Course}) %>
|
||||
</a>
|
||||
<% elsif @context_enrollment && @context_enrollment.self_enrolled && @context_enrollment.active? %>
|
||||
<a href="#" class="btn button-sidebar-wide self_unenrollment_link">
|
||||
<i class="icon-end"></i>
|
||||
<%= t('links.drop_course', %{Drop this Course}) %>
|
||||
</a>
|
||||
<div id="self_unenrollment_dialog" style="display: none;">
|
||||
<h2><i class="icon-warning"></i> <%= t('headings.confirm_unenroll', %{Confirm Unenrollment}) %></h2>
|
||||
<%= t('details.confirm_unenroll', %{Are you sure you want to unenroll in this course? You will no longer be able to see the course roster or communicate directly with the teachers, and you will no longer see course events in your stream and as notifications.}) %>
|
||||
<div class="button-container">
|
||||
<a href="<%= course_self_unenrollment_path(@context, @context_enrollment.uuid) %>" class="btn btn-primary action"><i class="icon-end"></i> <span><%= t('links.drop_course', %{Drop this Course}) %></span></a>
|
||||
<a href="#" class="btn dialog_closer"><%= t('#buttons.cancel', %{Cancel}) %></a>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @context_enrollment&.student? %>
|
||||
<a class="btn button-sidebar-wide" href="<%= calendar_url_for(@context) %>">
|
||||
<i class="icon-calendar-day"></i>
|
||||
<%= t('links.view_course_calendar', %{View Course Calendar}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @context_enrollment %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :context_url, :view => 'notifications') %>">
|
||||
<i class="icon-<%= @course_notifications_enabled ? "unmuted" : "muted" %>"></i>
|
||||
<%= t('links.view_course_notification_settings', %{View Course Notifications}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => '/courses/to_do_list', :locals => {:contexts => [@context], :show_legacy_todo_list => !@context_enrollment&.student?} %>
|
||||
<%= render :partial => "/courses/group_list", :locals => {:group_list => @user_groups} %>
|
||||
<%= nbsp unless @current_user %>
|
||||
</div>
|
|
@ -22,135 +22,10 @@
|
|||
|
||||
<% unless @context.elementary_subject_course? %>
|
||||
<% provide :right_side do %>
|
||||
<div id="course_show_secondary">
|
||||
<% @can_manage = can_do(@context, @current_user, :manage) %>
|
||||
<% @can_create_announcements = @context.announcements.temp_record.grants_right?(@current_user, session, :create) %>
|
||||
<% if can_do(@context, @current_user, :change_course_state, :manage_courses_publish) && (@context.unpublished? || @context.unpublishable?) %>
|
||||
<div id="course_status">
|
||||
<h3>
|
||||
<%= t('headers.course_status', %{Course Status}) %>
|
||||
</h3>
|
||||
<%= render :partial => 'publish_buttons', :locals => {redirect_to_settings: false} %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if can_do(@context, @current_user, :manage_content) %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :context_content_migrations_url) %>">
|
||||
<i class="icon-import"></i>
|
||||
<%= t('links.import', %{Import Existing Content}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @can_manage || @can_create_announcements || @course_home_view != 'feed' || @course_home_sub_navigation_tools.present? %>
|
||||
<div class="course-options">
|
||||
<%= external_tools_menu_items(@course_home_sub_navigation_tools, {link_class: "btn button-sidebar-wide course-home-sub-navigation-lti", settings_key: :course_home_sub_navigation}) %>
|
||||
<% if @can_manage && !@context.elementary_homeroom_course? %>
|
||||
<div id="choose_home_page"></div>
|
||||
<div id="choose_home_page_not_modules"></div>
|
||||
<% end %>
|
||||
|
||||
<% if @course_home_view != 'feed' && !@context.elementary_homeroom_course? %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :context_url, :view => 'feed') %>">
|
||||
<i class="icon-stats"></i>
|
||||
<%= t('links.view_course_stream', %{View Course Stream}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @can_manage && !@domain_root_account.try(:feature_enabled?, :new_user_tutorial) && !@context.elementary_homeroom_course? %>
|
||||
<script>
|
||||
Object.assign(
|
||||
ENV,
|
||||
<%= raw StringifyIds.recursively_stringify_ids({
|
||||
COURSE_WIZARD: {
|
||||
just_saved: @context_just_saved,
|
||||
checklist_states: {
|
||||
import_step: !@context.attachments.active.exists?,
|
||||
assignment_step: !@context.assignments.active.exists?,
|
||||
add_student_step: !@context.students.exists?,
|
||||
navigation_step: @context.tab_configuration.empty?,
|
||||
home_page_step: true,
|
||||
# The current wizard just always marks this as complete.
|
||||
calendar_event_step: !@context.calendar_events.active.exists?,
|
||||
add_ta_step: !@context.tas.exists?,
|
||||
publish_step: @context.workflow_state === 'available'
|
||||
},
|
||||
urls: {
|
||||
content_import: context_url(@context, :context_content_migrations_url),
|
||||
add_assignments: context_url(@context, :context_assignments_url, wizard: 1),
|
||||
add_students: course_users_path(course_id: @context),
|
||||
add_files: context_url(@context, :context_files_url, wizard: 1),
|
||||
select_navigation: context_url(@context, :context_details_url),
|
||||
course_calendar: calendar_path(course_id: @context),
|
||||
add_tas: course_users_path(course_id: @context),
|
||||
publish_course: course_path(@context)
|
||||
},
|
||||
permissions: {
|
||||
can_change_course_publish_state: can_do(@context, @current_user, :change_course_state, :manage_courses_publish)
|
||||
}
|
||||
}
|
||||
}).to_json %>
|
||||
)
|
||||
</script>
|
||||
|
||||
<% js_bundle :course_wizard %>
|
||||
<% css_bundle :course_wizard %>
|
||||
<a href="#" class="btn button-sidebar-wide wizard_popup_link <%= 'auto_open' if @context.created? || @context.claimed? %>">
|
||||
<i class="icon-question"></i> <%= t('links.course_setup', %{Course Setup Checklist}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @can_create_announcements && !@context.elementary_homeroom_course? %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :new_context_discussion_topic_url, :is_announcement => true) %>"><i class="icon-announcement"></i> <%= t('links.new_announcement', %{New Announcement}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% course_custom_links.each do |link| %>
|
||||
<a class="btn button-sidebar-wide" href="<%= link[:url] %>"><i class="<%= link[:icon_class] %>" role="presentation"></i> <%= link[:text] %></a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @context.available? && @context.self_enrollment_enabled? && @context.open_enrollment && (!@context_enrollment || !@context_enrollment.active?) %>
|
||||
<a href="<%= enroll_url(@context.self_enrollment_code) %>" class="btn button-sidebar-wide self_enrollment_link">
|
||||
<i class="icon-user-add"></i>
|
||||
<%= t('links.join_course', %{Join this Course}) %>
|
||||
</a>
|
||||
<% elsif @context_enrollment && @context_enrollment.self_enrolled && @context_enrollment.active? %>
|
||||
<a href="#" class="btn button-sidebar-wide self_unenrollment_link">
|
||||
<i class="icon-end"></i>
|
||||
<%= t('links.drop_course', %{Drop this Course}) %>
|
||||
</a>
|
||||
<div id="self_unenrollment_dialog" style="display: none;">
|
||||
<h2><i class="icon-warning"></i> <%= t('headings.confirm_unenroll', %{Confirm Unenrollment}) %></h2>
|
||||
<%= t('details.confirm_unenroll', %{Are you sure you want to unenroll in this course? You will no longer be able to see the course roster or communicate directly with the teachers, and you will no longer see course events in your stream and as notifications.}) %>
|
||||
<div class="button-container">
|
||||
<a href="<%= course_self_unenrollment_path(@context, @context_enrollment.uuid) %>" class="btn btn-primary action"><i class="icon-end"></i> <span><%= t('links.drop_course', %{Drop this Course}) %></span></a>
|
||||
<a href="#" class="btn dialog_closer"><%= t('#buttons.cancel', %{Cancel}) %></a>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @context_enrollment&.student? %>
|
||||
<a class="btn button-sidebar-wide" href="<%= calendar_url_for(@context) %>">
|
||||
<i class="icon-calendar-day"></i>
|
||||
<%= t('links.view_course_calendar', %{View Course Calendar}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<% if @context_enrollment %>
|
||||
<a class="btn button-sidebar-wide" href="<%= context_url(@context, :context_url, :view => 'notifications') %>">
|
||||
<i class="icon-<%= @course_notifications_enabled ? "unmuted" : "muted" %>"></i>
|
||||
<%= t('links.view_course_notification_settings', %{View Course Notifications}) %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => 'to_do_list', :locals => {:contexts => [@context], :show_legacy_todo_list => !@context_enrollment&.student?} %>
|
||||
<%= render :partial => "group_list", :locals => {:group_list => @user_groups} %>
|
||||
<%= nbsp unless @current_user %>
|
||||
</div>
|
||||
<%= render :partial => 'courses/course_show_secondary' %>
|
||||
<% if @course_home_view == 'assignments' %>
|
||||
<%= render :partial => 'assignments/assignments_list_right_side', :locals => {:course_home => true} %>
|
||||
<% elsif @course_home_view == 'syllabus' %>
|
||||
<% elsif @course_home_view == 'syllabus' && !@context.elementary_enabled? %>
|
||||
<%= render :partial => 'assignments/syllabus_right_side', :locals => {:course_home => true} %>
|
||||
<% elsif @context.elementary_homeroom_course? %>
|
||||
<% elsif !@context_enrollment&.student? %>
|
||||
|
@ -188,9 +63,9 @@
|
|||
<% elsif @course_home_view == 'modules' %>
|
||||
<%= render :partial => 'context_modules/content_next', :locals => {:course_home => true} %>
|
||||
<% elsif @course_home_view == 'assignments' %>
|
||||
<% elsif @context.elementary_homeroom_course? %>
|
||||
<% elsif @course_home_view == 'syllabus' %>
|
||||
<%= render :partial => 'assignments/syllabus_content', :locals => {:course_home => true} %>
|
||||
<% elsif @context.elementary_homeroom_course? %>
|
||||
<% elsif @course_home_view == 'k5_dashboard' %>
|
||||
<div id="course-dashboard-container"></div>
|
||||
<div id="k5-modules-container" style="display: none; padding-top: 17px;">
|
||||
|
|
|
@ -65,11 +65,21 @@ describe "Announcements API", type: :request do
|
|||
expect(json['message']).to include 'Invalid context_codes'
|
||||
end
|
||||
|
||||
it "requires :read_announcements permission on all courses" do
|
||||
random_course = Course.create!
|
||||
api_call_as_user(@teacher, :get, "/api/v1/announcements",
|
||||
@params.merge(:context_codes => [ "course_#{@course1.id}", "course_#{random_course.id}" ]),
|
||||
{}, {}, { :expected_status => 401 })
|
||||
it "filters out announcements with :read_announcements permission lacking" do
|
||||
@account = Account.default
|
||||
custom_role = custom_teacher_role('No Announcement Viewing')
|
||||
@account.role_overrides.create!(role: custom_role, enabled: false, permission: :read_announcements)
|
||||
|
||||
course_with_teacher(active_all: true, user: @teacher, role: custom_role)
|
||||
|
||||
@other_course = @course
|
||||
@other_course.announcements.create :title => "Announcement That Should Be Filtered", :message => '1'
|
||||
|
||||
context_codes = ["course_#{@course1.id}", "course_#{@course2.id}", "course_#{@other_course.id}"]
|
||||
json = api_call_as_user @teacher, :get, "/api/v1/announcements",
|
||||
@params.merge(:context_codes => context_codes), {}, {},
|
||||
{ :expected_status => 200 }
|
||||
expect(json.length).to eq 6
|
||||
end
|
||||
|
||||
it "returns announcements for the the surrounding 14 days by default" do
|
||||
|
|
|
@ -1658,7 +1658,7 @@ describe CoursesController do
|
|||
user_session(@teacher)
|
||||
|
||||
get 'show', params: {:id => @course.id}
|
||||
expect(assigns[:js_env][:PERMISSIONS]).to eq({manage: true, read_as_admin: true})
|
||||
expect(assigns[:js_env][:PERMISSIONS]).to eq({manage: true, read_announcements: true, read_as_admin: true})
|
||||
end
|
||||
|
||||
it "sets COURSE.color appropriately in js_env" do
|
||||
|
@ -1681,6 +1681,17 @@ describe CoursesController do
|
|||
expect(bundle.size).to eq 1
|
||||
end
|
||||
|
||||
it "sets the course_home_view to 'Important Info' if the teacher has no announcement reading permission for the homeroom" do
|
||||
@course.homeroom_course = true
|
||||
@course.save!
|
||||
|
||||
@course.account.role_overrides.create!(permission: :read_announcements, role: teacher_role, enabled: false)
|
||||
user_session(@teacher)
|
||||
|
||||
get 'show', params: {:id => @course.id}
|
||||
expect(assigns[:course_home_view]).to eq 'syllabus'
|
||||
end
|
||||
|
||||
it "sets COURSE.has_syllabus_body to true when syllabus exists" do
|
||||
@course.syllabus_body = "Welcome"
|
||||
@course.save!
|
||||
|
|
|
@ -30,6 +30,7 @@ ready(() => {
|
|||
<K5Course
|
||||
canManage={ENV.PERMISSIONS.manage}
|
||||
canReadAsAdmin={ENV.PERMISSIONS.read_as_admin}
|
||||
canReadAnnouncements={ENV.PERMISSIONS.read_announcements}
|
||||
currentUser={ENV.current_user}
|
||||
id={ENV.COURSE.id}
|
||||
bannerImageUrl={ENV.COURSE.banner_image_url}
|
||||
|
|
|
@ -280,6 +280,7 @@ export function K5Course({
|
|||
timeZone,
|
||||
canManage = false,
|
||||
canReadAsAdmin,
|
||||
canReadAnnouncements,
|
||||
plannerEnabled = false,
|
||||
hideFinalGrades,
|
||||
currentUser,
|
||||
|
@ -422,7 +423,8 @@ export function K5Course({
|
|||
id,
|
||||
shortName: name,
|
||||
href: `/courses/${id}`,
|
||||
canManage
|
||||
canManage,
|
||||
canReadAnnouncements
|
||||
})
|
||||
|
||||
return (
|
||||
|
@ -500,6 +502,7 @@ K5Course.propTypes = {
|
|||
cardImageUrl: PropTypes.string,
|
||||
canManage: PropTypes.bool,
|
||||
canReadAsAdmin: PropTypes.bool.isRequired,
|
||||
canReadAnnouncements: PropTypes.bool.isRequired,
|
||||
color: PropTypes.string,
|
||||
defaultTab: PropTypes.string,
|
||||
plannerEnabled: PropTypes.bool,
|
||||
|
|
|
@ -44,6 +44,7 @@ export default function HomeroomAnnouncementsLayout({homeroomAnnouncements, load
|
|||
courseName={homeroom.courseName}
|
||||
courseUrl={homeroom.courseUrl}
|
||||
canEdit={homeroom.canEdit}
|
||||
canReadAnnouncements={homeroom.canReadAnnouncements}
|
||||
published={homeroom.published}
|
||||
showCourseDetails
|
||||
firstAnnouncement={homeroom.announcement}
|
||||
|
|
|
@ -26,6 +26,7 @@ const homeroomAnnouncements = [
|
|||
courseName: 'Homeroom - Mr. Jessie',
|
||||
courseUrl: 'http://google.com/course',
|
||||
canEdit: true,
|
||||
canReadAnnouncements: true,
|
||||
announcement: {
|
||||
title: 'Welcome to Class!',
|
||||
message: '<p>Yayyyy</p>',
|
||||
|
@ -43,6 +44,7 @@ const homeroomAnnouncements = [
|
|||
courseName: 'Homeroom 0144232',
|
||||
courseUrl: 'http://google.com/course2',
|
||||
canEdit: true,
|
||||
canReadAnnouncements: true,
|
||||
announcement: {
|
||||
title: 'Sign the permission slip!',
|
||||
message: '<p>Hello</p>',
|
||||
|
@ -55,6 +57,7 @@ const homeroomAnnouncements = [
|
|||
courseName: 'New Homeroom',
|
||||
courseUrl: 'http://google.com',
|
||||
canEdit: true,
|
||||
canReadAnnouncements: true,
|
||||
published: true
|
||||
}
|
||||
]
|
||||
|
@ -86,7 +89,8 @@ describe('HomeroomAnnouncementsLayout', () => {
|
|||
courseId: 1236,
|
||||
courseName: 'New Homeroom',
|
||||
courseUrl: 'http://google.com',
|
||||
canEdit: true
|
||||
canEdit: true,
|
||||
canReadAnnouncements: true
|
||||
}
|
||||
]
|
||||
})}
|
||||
|
@ -107,7 +111,8 @@ describe('HomeroomAnnouncementsLayout', () => {
|
|||
courseId: 1236,
|
||||
courseName: 'New Homeroom',
|
||||
courseUrl: 'http://google.com',
|
||||
canEdit: false
|
||||
canEdit: false,
|
||||
canReadAnnouncements: true
|
||||
}
|
||||
]
|
||||
})}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import I18n from 'i18n!empty_homeroom_announcement'
|
||||
import React from 'react'
|
||||
import {string} from 'prop-types'
|
||||
import {string, bool} from 'prop-types'
|
||||
import {View} from '@instructure/ui-view'
|
||||
import {Heading} from '@instructure/ui-heading'
|
||||
import {Link} from '@instructure/ui-link'
|
||||
|
@ -45,7 +45,7 @@ K5AddAnnouncementButton.propTypes = {
|
|||
courseName: string.isRequired
|
||||
}
|
||||
|
||||
export default function EmptyK5Announcement({courseUrl, courseName}) {
|
||||
export default function EmptyK5Announcement({courseUrl, courseName, canReadAnnouncements}) {
|
||||
return (
|
||||
<View>
|
||||
<Heading level="h3" as="h2" margin="medium 0 small">
|
||||
|
@ -54,9 +54,13 @@ export default function EmptyK5Announcement({courseUrl, courseName}) {
|
|||
</Link>
|
||||
</Heading>
|
||||
<Text as="div">
|
||||
{I18n.t('New announcements show up in this area. Create a new announcement now.')}
|
||||
{canReadAnnouncements
|
||||
? I18n.t('New announcements show up in this area. Create a new announcement now.')
|
||||
: I18n.t('You do not have permission to view announcements in this course.')}
|
||||
</Text>
|
||||
<K5AddAnnouncementButton courseUrl={courseUrl} courseName={courseName} />
|
||||
{canReadAnnouncements && (
|
||||
<K5AddAnnouncementButton courseUrl={courseUrl} courseName={courseName} />
|
||||
)}
|
||||
<PresentationContent>
|
||||
<hr />
|
||||
</PresentationContent>
|
||||
|
@ -66,5 +70,6 @@ export default function EmptyK5Announcement({courseUrl, courseName}) {
|
|||
|
||||
EmptyK5Announcement.propTypes = {
|
||||
courseUrl: string.isRequired,
|
||||
courseName: string.isRequired
|
||||
courseName: string.isRequired,
|
||||
canReadAnnouncements: bool.isRequired
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ export default function K5Announcement({
|
|||
courseUrl,
|
||||
published,
|
||||
canEdit,
|
||||
canReadAnnouncements,
|
||||
showCourseDetails,
|
||||
firstAnnouncement
|
||||
}) {
|
||||
|
@ -323,7 +324,7 @@ export default function K5Announcement({
|
|||
<Text data-testid="no-recent-announcements" color="secondary" size="large">
|
||||
{I18n.t('No recent announcements')}
|
||||
</Text>
|
||||
{canEdit && (
|
||||
{canEdit && canReadAnnouncements && (
|
||||
<View as="div">
|
||||
<K5AddAnnouncementButton courseName={courseName} courseUrl={courseUrl} />
|
||||
</View>
|
||||
|
@ -363,7 +364,13 @@ export default function K5Announcement({
|
|||
|
||||
// if there are no announcements at all, show teachers something
|
||||
if (canEdit && noAnnouncementsAtAll()) {
|
||||
return <EmptyK5Announcement courseUrl={courseUrl} courseName={courseName} />
|
||||
return (
|
||||
<EmptyK5Announcement
|
||||
courseUrl={courseUrl}
|
||||
courseName={courseName}
|
||||
canReadAnnouncements={canReadAnnouncements}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -410,6 +417,7 @@ K5Announcement.propTypes = {
|
|||
courseUrl: PropTypes.string,
|
||||
published: PropTypes.bool,
|
||||
canEdit: PropTypes.bool.isRequired,
|
||||
canReadAnnouncements: PropTypes.bool.isRequired,
|
||||
showCourseDetails: PropTypes.bool.isRequired,
|
||||
// announcement
|
||||
firstAnnouncement: K5AnnouncementType
|
||||
|
|
|
@ -24,6 +24,7 @@ describe('EmptyK5Announcement', () => {
|
|||
const getProps = (overrides = {}) => ({
|
||||
courseName: "Mr. Smith's Homeroom 2",
|
||||
courseUrl: 'http://google.com/courseurl2',
|
||||
canReadAnnouncements: true,
|
||||
...overrides
|
||||
})
|
||||
|
||||
|
@ -41,6 +42,13 @@ describe('EmptyK5Announcement', () => {
|
|||
).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows permission related text when applicable', () => {
|
||||
const {getByText} = render(<EmptyK5Announcement {...getProps({canReadAnnouncements: false})} />)
|
||||
expect(
|
||||
getByText('You do not have permission to view announcements in this course.')
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows a button to create a new announcement with correct url', () => {
|
||||
const {getByRole} = render(<EmptyK5Announcement {...getProps()} />)
|
||||
const button = getByRole('link', {name: "Create a new announcement for Mr. Smith's Homeroom 2"})
|
||||
|
|
|
@ -28,6 +28,7 @@ describe('K5Announcement', () => {
|
|||
courseName: "Mrs. Jensen's Homeroom",
|
||||
courseUrl: 'http://google.com/courseurl',
|
||||
canEdit: true,
|
||||
canReadAnnouncements: true,
|
||||
published: true,
|
||||
showCourseDetails: true,
|
||||
...overrides
|
||||
|
|
|
@ -282,6 +282,7 @@ export const parseAnnouncementDetails = (announcement, course) => {
|
|||
courseName: course.shortName,
|
||||
courseUrl: course.href,
|
||||
canEdit: course.canManage,
|
||||
canReadAnnouncements: course.canReadAnnouncements,
|
||||
published: course.published
|
||||
}
|
||||
if (announcement) {
|
||||
|
|
Loading…
Reference in New Issue