Support students in CreateCourseModal
Since this modal will be used everywhere in Canvas, support students and users with no enrollments creating courses (when enabled at the root account). Students will see all accounts where they have enrollments; users with no enrollments will only see the manually- created courses subaccount. Don't show homeroom sync options to students/users with no enrollments. Expose the manually-created courses subaccount ID/basic info through a new API. flag = create_course_subaccount_picker closes LS-2678 Test plan: - Enable root account FF: create_course_subaccount_picker - In root account settings, allow techers, students, and users with no enrollments to create courses - Login to k5 dashboard as an admin and click the + (New Subject) button - Expect to see a manageable_courses network request and a dropdown to select an account (along with the checkbox to sync homerooms) - Login and open the modal as a teacher - Expect to see an enrollments network request and a dropdown with all the accounts where the user has a teacher enrollment (and the homeroom sync checkbox) - Login and open the modal as a student - Expect another enrollments network request and a dropdown with all their accounts (if there's more than one) - Expect to not see the sync options - Login as a user with no enrollments - Expect a network request to the manually_created_courses_account api - Expect to not see a dropdown with accounts or the sync options - Disable 'X can create courses' at the root account and expect the associated users to no longer see the create course modal at all - With FF disabled, expect course creation to work as before Change-Id: I0e7d49628ce6395fd366037a3134133084fe6275 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/274986 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Product-Review: Peyton Craighill <pcraighill@instructure.com> Reviewed-by: Robin Kuss <rkuss@instructure.com> QA-Review: Robin Kuss <rkuss@instructure.com>
This commit is contained in:
parent
bbe7c5d357
commit
498aaa11db
|
@ -293,7 +293,7 @@ require 'csv'
|
|||
# }
|
||||
|
||||
class AccountsController < ApplicationController
|
||||
before_action :require_user, :only => [:index, :help_links]
|
||||
before_action :require_user, :only => [:index, :help_links, :manually_created_courses_account]
|
||||
before_action :reject_student_view_student
|
||||
before_action :get_context
|
||||
before_action :rce_js_env, only: [:settings]
|
||||
|
@ -516,6 +516,15 @@ class AccountsController < ApplicationController
|
|||
render :json => links
|
||||
end
|
||||
|
||||
# @API Get the manually-created courses sub-account for the domain root account
|
||||
#
|
||||
# @returns Account
|
||||
def manually_created_courses_account
|
||||
account = @domain_root_account.manually_created_courses_account
|
||||
read_only = !account.grants_right?(@current_user, session, :read)
|
||||
render :json => account_json(account, @current_user, session, [], read_only)
|
||||
end
|
||||
|
||||
include Api::V1::Course
|
||||
|
||||
# @API List active courses in an account
|
||||
|
|
|
@ -498,6 +498,7 @@ class CoursesController < ApplicationController
|
|||
format.html {
|
||||
css_bundle :context_list, :course_list
|
||||
js_bundle :course_list
|
||||
js_env({ CREATE_COURSES_PERMISSION: @current_user.create_courses_right(@domain_root_account) })
|
||||
|
||||
set_k5_mode(require_k5_theme: true)
|
||||
|
||||
|
@ -887,7 +888,7 @@ class CoursesController < ApplicationController
|
|||
Auditors::Course.record_published(@course, @current_user, source: :api)
|
||||
end
|
||||
# Sync homeroom enrollments and participation if enabled and the course isn't a SIS import
|
||||
if @course.elementary_enabled? && params[:course][:sync_enrollments_from_homeroom] && params[:course][:homeroom_course_id] && @course.sis_batch_id.blank?
|
||||
if @course.elementary_enabled? && value_to_boolean(params[:course][:sync_enrollments_from_homeroom]) && params[:course][:homeroom_course_id] && @course.sis_batch_id.blank?
|
||||
progress = Progress.new(context: @course, tag: :sync_homeroom_enrollments)
|
||||
progress.user = @current_user
|
||||
progress.reset!
|
||||
|
|
|
@ -513,7 +513,8 @@ class UsersController < ApplicationController
|
|||
STUDENT_PLANNER_ENABLED: planner_enabled?,
|
||||
STUDENT_PLANNER_COURSES: planner_enabled? && map_courses_for_menu(@current_user.courses_with_primary_enrollment),
|
||||
STUDENT_PLANNER_GROUPS: planner_enabled? && map_groups_for_planner(@current_user.current_groups),
|
||||
CAN_ENABLE_K5_DASHBOARD: k5_disabled && k5_user
|
||||
CAN_ENABLE_K5_DASHBOARD: k5_disabled && k5_user,
|
||||
CREATE_COURSES_PERMISSION: @current_user.create_courses_right(@domain_root_account)
|
||||
})
|
||||
|
||||
if k5_user?
|
||||
|
@ -527,10 +528,6 @@ class UsersController < ApplicationController
|
|||
SELECTED_CONTEXT_CODES: @current_user.get_preference(:selected_calendar_contexts),
|
||||
SELECTED_CONTEXTS_LIMIT: @domain_root_account.settings[:calendar_contexts_limit] || 10,
|
||||
INITIAL_NUM_K5_CARDS: Rails.cache.read(['last_known_k5_cards_count', @current_user.global_id].cache_key) || 5,
|
||||
PERMISSIONS: {
|
||||
create_courses_as_admin: @current_user.roles(@domain_root_account).include?('admin'),
|
||||
create_courses_as_teacher: @domain_root_account.grants_right?(@current_user, session, :create_courses)
|
||||
},
|
||||
CAN_ADD_OBSERVEE: @current_user
|
||||
.profile
|
||||
.tabs_available(@current_user, :root_account => @domain_root_account)
|
||||
|
|
|
@ -1316,32 +1316,7 @@ class Account < ActiveRecord::Base
|
|||
given { |user| self.root_account? && self.cached_all_account_users_for(user).any? }
|
||||
can :read_terms
|
||||
|
||||
#################### Begin legacy permission block #########################
|
||||
given do |user|
|
||||
user && !root_account.feature_enabled?(:granular_permissions_manage_courses) &&
|
||||
self.cached_account_users_for(user).any? do |au|
|
||||
au.has_permission_to?(self, :manage_courses)
|
||||
end
|
||||
end
|
||||
can :create_courses
|
||||
##################### End legacy permission block ##########################
|
||||
|
||||
given do |user|
|
||||
result = false
|
||||
next false if user&.fake_student?
|
||||
|
||||
if user && !root_account.site_admin?
|
||||
scope = root_account.enrollments.active.where(user_id: user)
|
||||
result = root_account.teachers_can_create_courses? &&
|
||||
scope.where(:type => ['TeacherEnrollment', 'DesignerEnrollment']).exists?
|
||||
result ||= root_account.students_can_create_courses? &&
|
||||
scope.where(:type => ['StudentEnrollment', 'ObserverEnrollment']).exists?
|
||||
result ||= root_account.no_enrollments_can_create_courses? &&
|
||||
!scope.exists?
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
given { |user| user&.create_courses_right(self).present? }
|
||||
can :create_courses
|
||||
|
||||
# allow teachers to view term dates
|
||||
|
|
|
@ -3250,4 +3250,18 @@ class User < ActiveRecord::Base
|
|||
def pronouns=(pronouns)
|
||||
write_attribute(:pronouns, untranslate_pronouns(pronouns))
|
||||
end
|
||||
|
||||
def create_courses_right(account)
|
||||
return :admin if account.cached_account_users_for(self).any? do |au|
|
||||
au.has_permission_to?(account, :manage_courses) || au.has_permission_to?(account, :manage_courses_add)
|
||||
end
|
||||
return nil if fake_student? || account.root_account.site_admin?
|
||||
|
||||
scope = account.root_account.enrollments.active.where(user_id: self)
|
||||
return :teacher if account.root_account.teachers_can_create_courses? && scope.exists?(type: %w[TeacherEnrollment DesignerEnrollment])
|
||||
return :student if account.root_account.students_can_create_courses? && scope.exists?(type: %w[StudentEnrollment ObserverEnrollment])
|
||||
return :no_enrollments if account.root_account.no_enrollments_can_create_courses? && !scope.exists?
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -274,7 +274,7 @@
|
|||
<div class="tall-row">
|
||||
<div class="nobr">
|
||||
<%= f.check_box :sync_enrollments_from_homeroom, class: 'sync_enrollments_from_homeroom_checkbox', :disabled => !can_manage || @context.homeroom_course %>
|
||||
<%= f.label :sync_enrollments_from_homeroom, :en => "Sync enrollments and course start/end dates from homeroom" %><br/>
|
||||
<%= f.label :sync_enrollments_from_homeroom, :en => "Sync enrollments and subject start/end dates from homeroom" %><br/>
|
||||
</div>
|
||||
<div class="sync_enrollments_from_homeroom_select">
|
||||
<% format_options = options_from_collection_for_select(@homeroom_courses, 'id', 'name', @context.homeroom_course_id) %>
|
||||
|
|
|
@ -1518,6 +1518,7 @@ CanvasRails::Application.routes.draw do
|
|||
get 'accounts/:account_id/courses/:id', controller: :courses, action: :show, as: 'account_course_show'
|
||||
get 'accounts/:account_id/permissions', action: :permissions
|
||||
get 'accounts/:account_id/settings', action: :show_settings
|
||||
get 'manually_created_courses_account', action: :manually_created_courses_account
|
||||
delete 'accounts/:account_id/users/:user_id', action: :remove_user
|
||||
put 'accounts/:account_id/users/:user_id/restore', action: :restore_user
|
||||
end
|
||||
|
|
|
@ -1180,6 +1180,33 @@ describe AccountsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe "manually_created_courses_account" do
|
||||
it "returns unauthorized if there's no user" do
|
||||
get 'manually_created_courses_account'
|
||||
assert_unauthorized
|
||||
end
|
||||
|
||||
it "returns the account with lots of detail if user has :read on the account" do
|
||||
account_with_admin_logged_in(active_all: true)
|
||||
|
||||
get 'manually_created_courses_account'
|
||||
expect(response).to be_successful
|
||||
account = json_parse(response.body)
|
||||
expect(account['name']).to eq('Manually-Created Courses')
|
||||
expect(account['default_storage_quota_mb']).to be(500)
|
||||
end
|
||||
|
||||
it "returns limited details about the account to students" do
|
||||
course_with_student_logged_in(active_all: true)
|
||||
|
||||
get 'manually_created_courses_account'
|
||||
expect(response).to be_successful
|
||||
account = json_parse(response.body)
|
||||
expect(account['name']).to eq('Manually-Created Courses')
|
||||
expect(account['default_storage_quota_mb']).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "#account_courses" do
|
||||
before do
|
||||
@account = Account.create!
|
||||
|
|
|
@ -52,6 +52,7 @@ describe CoursesController do
|
|||
expect(assigns[:current_enrollments][0]).to eql(@enrollment)
|
||||
expect(assigns[:past_enrollments]).not_to be_nil
|
||||
expect(assigns[:future_enrollments]).not_to be_nil
|
||||
expect(assigns[:js_env][:CREATE_COURSES_PERMISSION]).to be_nil
|
||||
end
|
||||
|
||||
it "does not duplicate enrollments in variables" do
|
||||
|
|
|
@ -2685,37 +2685,6 @@ describe UsersController do
|
|||
end
|
||||
end
|
||||
|
||||
context "ENV.PERMISSIONS" do
|
||||
it "sets :create_courses_as_admin to true if user is admin" do
|
||||
account_admin_user
|
||||
user_session @user
|
||||
get 'user_dashboard'
|
||||
expect(assigns[:js_env][:PERMISSIONS][:create_courses_as_admin]).to be_truthy
|
||||
end
|
||||
|
||||
it "sets only :create_courses_as_teacher to true if user is a teacher and teachers can create courses" do
|
||||
Account.default.settings[:teachers_can_create_courses] = true
|
||||
course_with_teacher_logged_in
|
||||
get 'user_dashboard'
|
||||
expect(assigns[:js_env][:PERMISSIONS][:create_courses_as_admin]).to be_falsey
|
||||
expect(assigns[:js_env][:PERMISSIONS][:create_courses_as_teacher]).to be_truthy
|
||||
end
|
||||
|
||||
it "sets :create_courses_as_admin and :create_courses_as_teacher to false if user is a teacher but teachers can't create courses" do
|
||||
course_with_teacher_logged_in
|
||||
get 'user_dashboard'
|
||||
expect(assigns[:js_env][:PERMISSIONS][:create_courses_as_admin]).to be_falsey
|
||||
expect(assigns[:js_env][:PERMISSIONS][:create_courses_as_teacher]).to be_falsey
|
||||
end
|
||||
|
||||
it "sets :create_courses_as_admin and :create_courses_as_teacher to false if user is a student" do
|
||||
course_with_student_logged_in
|
||||
get 'user_dashboard'
|
||||
expect(assigns[:js_env][:PERMISSIONS][:create_courses_as_admin]).to be_falsey
|
||||
expect(assigns[:js_env][:PERMISSIONS][:create_courses_as_teacher]).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context "@cards_prefetch_observer_param" do
|
||||
before :once do
|
||||
Account.site_admin.enable_feature!(:k5_parent_support)
|
||||
|
@ -2743,6 +2712,15 @@ describe UsersController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "sets ENV.CREATE_COURSES_PERMISSION to teacher if user is a teacher and can create courses" do
|
||||
Account.default.settings[:teachers_can_create_courses] = true
|
||||
Account.default.save!
|
||||
course_with_teacher_logged_in(active_all: true)
|
||||
|
||||
get 'user_dashboard'
|
||||
expect(assigns[:js_env][:CREATE_COURSES_PERMISSION]).to be(:teacher)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#pandata_events_token" do
|
||||
|
|
|
@ -3675,4 +3675,66 @@ describe User do
|
|||
expect(@teacher.comment_bank_items).to eq [@c1]
|
||||
end
|
||||
end
|
||||
|
||||
describe "create_courses_right" do
|
||||
before :once do
|
||||
@user = user_factory(active_all: true)
|
||||
@account = Account.default
|
||||
end
|
||||
|
||||
it "returns :admin for AccountUsers with :manage_courses" do
|
||||
account_admin_user(user: @user)
|
||||
expect(@user.create_courses_right(@account)).to be(:admin)
|
||||
end
|
||||
|
||||
it "returns nil for AccountUsers without :manage_courses" do
|
||||
account_admin_user_with_role_changes(user: @user, role_changes: { manage_courses: false })
|
||||
expect(@user.create_courses_right(@account)).to be_nil
|
||||
end
|
||||
|
||||
it "returns nil if fake student" do
|
||||
fake_student = course_factory(active_all: true).student_view_student
|
||||
expect(fake_student.create_courses_right(@account)).to be_nil
|
||||
end
|
||||
|
||||
it "returns :teacher if user has teacher enrollments iff teachers_can_create_courses?" do
|
||||
course_with_teacher(user: @user, active_all: true)
|
||||
expect(@user.create_courses_right(@account)).to be_nil
|
||||
@account.settings[:teachers_can_create_courses] = true
|
||||
@account.save!
|
||||
expect(@user.create_courses_right(@account)).to be(:teacher)
|
||||
end
|
||||
|
||||
it "returns :student if user has student enrollments iff students_can_create_courses?" do
|
||||
course_with_student(user: @user, active_all: true)
|
||||
expect(@user.create_courses_right(@account)).to be_nil
|
||||
@account.settings[:students_can_create_courses] = true
|
||||
@account.save!
|
||||
expect(@user.create_courses_right(@account)).to be(:student)
|
||||
end
|
||||
|
||||
it "returns :no_enrollments if user has teacher enrollments iff no_enrollments_can_create_courses?" do
|
||||
expect(@user.create_courses_right(@account)).to be_nil
|
||||
@account.settings[:no_enrollments_can_create_courses] = true
|
||||
@account.save!
|
||||
expect(@user.create_courses_right(@account)).to be(:no_enrollments)
|
||||
end
|
||||
|
||||
it "does not count deleted teacher enrollments" do
|
||||
enrollment = course_with_teacher(user: @user)
|
||||
enrollment.workflow_state = 'deleted'
|
||||
enrollment.save!
|
||||
@account.settings[:teachers_can_create_courses] = true
|
||||
@account.save!
|
||||
expect(@user.create_courses_right(@account)).to be_nil
|
||||
end
|
||||
|
||||
it "returns :student if user has teacher and student enrollments but teachers_can_create_courses is false" do
|
||||
course_with_teacher(user: @user, active_all: true)
|
||||
course_with_student(user: @user, active_all: true)
|
||||
@account.settings[:students_can_create_courses] = true
|
||||
@account.save!
|
||||
expect(@user.create_courses_right(@account)).to be(:student)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -290,7 +290,7 @@ module K5DashboardPageObject
|
|||
end
|
||||
|
||||
def sync_enrollments_checkbox_selector
|
||||
"input + label:contains('Sync enrollments and course start/end dates from homeroom')"
|
||||
"input + label:contains('Sync enrollments and subject start/end dates from homeroom')"
|
||||
end
|
||||
|
||||
def welcome_title_selector
|
||||
|
|
|
@ -73,22 +73,13 @@ ready(() => {
|
|||
const container = document.getElementById('create_subject_modal_container')
|
||||
if (container) {
|
||||
startButton.addEventListener('click', () => {
|
||||
let role
|
||||
if (ENV.current_user_roles.includes('admin')) {
|
||||
role = 'admin'
|
||||
} else if (ENV.current_user_roles.includes('teacher')) {
|
||||
role = 'teacher'
|
||||
} else {
|
||||
// should never get here
|
||||
return
|
||||
}
|
||||
ReactDOM.render(
|
||||
<CreateCourseModal
|
||||
isModalOpen
|
||||
setModalOpen={isOpen => {
|
||||
if (!isOpen) ReactDOM.unmountComponentAtNode(container)
|
||||
}}
|
||||
permissions={role}
|
||||
permissions={ENV.CREATE_COURSES_PERMISSION}
|
||||
isK5User={ENV.K5_USER}
|
||||
/>,
|
||||
container
|
||||
|
|
|
@ -270,18 +270,7 @@ function showTodoList() {
|
|||
|
||||
const startButton = document.getElementById('start_new_course')
|
||||
const modalContainer = document.getElementById('create_course_modal_container')
|
||||
let role
|
||||
if (ENV.current_user_roles.includes('admin')) {
|
||||
role = 'admin'
|
||||
} else if (ENV.current_user_roles.includes('teacher')) {
|
||||
role = 'teacher'
|
||||
}
|
||||
if (
|
||||
startButton &&
|
||||
modalContainer &&
|
||||
role &&
|
||||
ENV.FEATURES?.create_course_subaccount_picker
|
||||
) {
|
||||
if (startButton && modalContainer && ENV.FEATURES?.create_course_subaccount_picker) {
|
||||
startButton.addEventListener('click', () => {
|
||||
ReactDOM.render(
|
||||
<CreateCourseModal
|
||||
|
@ -289,7 +278,7 @@ function showTodoList() {
|
|||
setModalOpen={isOpen => {
|
||||
if (!isOpen) ReactDOM.unmountComponentAtNode(modalContainer)
|
||||
}}
|
||||
permissions={role}
|
||||
permissions={ENV.CREATE_COURSES_PERMISSION}
|
||||
isK5User={false} // can't be k5 user if classic dashboard is showing
|
||||
/>,
|
||||
modalContainer
|
||||
|
|
|
@ -35,13 +35,7 @@ ready(() => {
|
|||
plannerEnabled={ENV.STUDENT_PLANNER_ENABLED}
|
||||
timeZone={ENV.TIMEZONE}
|
||||
hideGradesTabForStudents={ENV.HIDE_K5_DASHBOARD_GRADES_TAB}
|
||||
createPermissions={
|
||||
ENV.PERMISSIONS?.create_courses_as_admin
|
||||
? 'admin'
|
||||
: ENV.PERMISSIONS?.create_courses_as_teacher
|
||||
? 'teacher'
|
||||
: 'none'
|
||||
}
|
||||
createPermissions={ENV.CREATE_COURSES_PERMISSION}
|
||||
showImportantDates={!!ENV.FEATURES.important_dates}
|
||||
selectedContextCodes={ENV.SELECTED_CONTEXT_CODES}
|
||||
selectedContextsLimit={ENV.SELECTED_CONTEXTS_LIMIT}
|
||||
|
|
|
@ -81,8 +81,6 @@ const HomeroomPage = ({
|
|||
</div>
|
||||
)
|
||||
|
||||
const canCreateCourses = createPermissions === 'admin' || createPermissions === 'teacher'
|
||||
|
||||
return (
|
||||
<section
|
||||
id="dashboard_page_homeroom"
|
||||
|
@ -100,7 +98,7 @@ const HomeroomPage = ({
|
|||
<Flex.Item>
|
||||
<Heading level="h2">{I18n.t('My Subjects')}</Heading>
|
||||
</Flex.Item>
|
||||
{canCreateCourses && (
|
||||
{createPermissions && (
|
||||
<Flex.Item>
|
||||
<Tooltip renderTip={I18n.t('Start a new subject')}>
|
||||
<IconButton
|
||||
|
@ -141,7 +139,7 @@ const HomeroomPage = ({
|
|||
|
||||
HomeroomPage.propTypes = {
|
||||
cards: PropTypes.array,
|
||||
createPermissions: PropTypes.oneOf(['admin', 'teacher', 'none']).isRequired,
|
||||
createPermissions: PropTypes.oneOf(['admin', 'teacher', 'student', 'no_enrollments']),
|
||||
homeroomAnnouncements: PropTypes.array.isRequired,
|
||||
loadingAnnouncements: PropTypes.bool.isRequired,
|
||||
visible: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -389,7 +389,7 @@ K5Dashboard.propTypes = {
|
|||
assignmentsDueToday: PropTypes.object.isRequired,
|
||||
assignmentsMissing: PropTypes.object.isRequired,
|
||||
assignmentsCompletedForToday: PropTypes.object.isRequired,
|
||||
createPermissions: PropTypes.oneOf(['admin', 'teacher', 'none']).isRequired,
|
||||
createPermissions: PropTypes.oneOf(['admin', 'teacher', 'student', 'no_enrollments']),
|
||||
currentUser: PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
display_name: PropTypes.string,
|
||||
|
|
|
@ -87,8 +87,8 @@ describe('HomeroomPage', () => {
|
|||
})
|
||||
|
||||
describe('start a new subject button', () => {
|
||||
it('is not present if createPermissions is set to none', () => {
|
||||
const {queryByText} = render(<HomeroomPage {...getProps({createPermissions: 'none'})} />)
|
||||
it('is not present if createPermissions is set to null', () => {
|
||||
const {queryByText} = render(<HomeroomPage {...getProps({createPermissions: null})} />)
|
||||
expect(queryByText('Open new subject modal')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ const defaultProps = {
|
|||
canDisableElementaryDashboard: false,
|
||||
currentUser,
|
||||
currentUserRoles: ['admin'],
|
||||
createPermissions: 'none',
|
||||
createPermissions: null,
|
||||
plannerEnabled: false,
|
||||
loadAllOpportunities: () => {},
|
||||
timeZone: defaultEnv.TIMEZONE,
|
||||
|
|
|
@ -76,7 +76,7 @@ export const CreateCourseModal = ({isModalOpen, setModalOpen, permissions, isK5U
|
|||
})
|
||||
}
|
||||
|
||||
const teacherFetchOpts = {
|
||||
const teacherStudentFetchOpts = {
|
||||
path: '/api/v1/users/self/courses',
|
||||
success: useCallback(enrollments => {
|
||||
const accounts = getAccountsFromEnrollments(enrollments)
|
||||
|
@ -89,7 +89,8 @@ export const CreateCourseModal = ({isModalOpen, setModalOpen, permissions, isK5U
|
|||
params: {
|
||||
per_page: 100,
|
||||
include: ['account'],
|
||||
enrollment_type: 'teacher'
|
||||
// Show teachers only accounts where they have a teacher enrollment
|
||||
...(permissions === 'teacher' && {enrollment_type: 'teacher'})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,11 +106,22 @@ export const CreateCourseModal = ({isModalOpen, setModalOpen, permissions, isK5U
|
|||
}
|
||||
}
|
||||
|
||||
const noEnrollmentsFetchOpts = {
|
||||
path: '/api/v1/manually_created_courses_account',
|
||||
success: useCallback(account => {
|
||||
setAllAccounts(account)
|
||||
setSelectedAccount(account[0])
|
||||
setAccountSearchTerm(account[0].name)
|
||||
}, [])
|
||||
}
|
||||
|
||||
useFetchApi({
|
||||
loading: setLoading,
|
||||
error: useCallback(err => showFlashError(I18n.t('Unable to get accounts'))(err), []),
|
||||
fetchAllPages: true,
|
||||
...(permissions === 'teacher' ? teacherFetchOpts : adminFetchOpts)
|
||||
...(['teacher', 'student'].includes(permissions) && teacherStudentFetchOpts),
|
||||
...(permissions === 'admin' && adminFetchOpts),
|
||||
...(permissions === 'no_enrollments' && noEnrollmentsFetchOpts)
|
||||
})
|
||||
|
||||
const handleAccountSelected = id => {
|
||||
|
@ -159,7 +171,10 @@ export const CreateCourseModal = ({isModalOpen, setModalOpen, permissions, isK5U
|
|||
},
|
||||
error: useCallback(err => showFlashError(I18n.t('Unable to get homerooms'))(err), []),
|
||||
fetchAllPages: true,
|
||||
...(permissions === 'teacher' ? teacherHomeroomFetchOpts : adminHomeroomFetchOpts)
|
||||
// don't let students/users with no enrollments sync homeroom data
|
||||
forceResult: ['no_enrollments', 'student'].includes(permissions) ? [] : undefined,
|
||||
...(permissions === 'teacher' && teacherHomeroomFetchOpts),
|
||||
...(permissions === 'admin' && adminHomeroomFetchOpts)
|
||||
})
|
||||
|
||||
const handleHomeroomSelected = id => {
|
||||
|
@ -180,8 +195,10 @@ export const CreateCourseModal = ({isModalOpen, setModalOpen, permissions, isK5U
|
|||
))
|
||||
}
|
||||
|
||||
// Don't show the account select for teachers with only one account to show
|
||||
const hideAccountSelect = permissions === 'teacher' && allAccounts?.length === 1
|
||||
// Don't show the account select for non-admins with only one account to show
|
||||
const hideAccountSelect = permissions !== 'admin' && allAccounts?.length === 1
|
||||
// Don't show homeroom sync to non-k5 users or to students/users with no enrollments
|
||||
const showHomeroomSyncOptions = isK5User && ['admin', 'teacher'].includes(permissions)
|
||||
|
||||
return (
|
||||
<Modal label={modalLabel} open={isModalOpen} size="small" onDismiss={clearModal}>
|
||||
|
@ -210,15 +227,15 @@ export const CreateCourseModal = ({isModalOpen, setModalOpen, permissions, isK5U
|
|||
{accountOptions}
|
||||
</CanvasAsyncSelect>
|
||||
)}
|
||||
{isK5User && (
|
||||
{showHomeroomSyncOptions && (
|
||||
<Checkbox
|
||||
label={I18n.t('Sync enrollments and course start/end dates from homeroom')}
|
||||
label={I18n.t('Sync enrollments and subject start/end dates from homeroom')}
|
||||
value="syncHomeroomEnrollments"
|
||||
checked={syncHomeroomEnrollments}
|
||||
onChange={event => setSyncHomeroomEnrollments(event.target.checked)}
|
||||
/>
|
||||
)}
|
||||
{isK5User && syncHomeroomEnrollments && (
|
||||
{showHomeroomSyncOptions && syncHomeroomEnrollments && (
|
||||
<SimpleSelect
|
||||
data-testid="homeroom-select"
|
||||
renderLabel={I18n.t('Select a homeroom')}
|
||||
|
@ -265,6 +282,6 @@ export const CreateCourseModal = ({isModalOpen, setModalOpen, permissions, isK5U
|
|||
CreateCourseModal.propTypes = {
|
||||
isModalOpen: PropTypes.bool.isRequired,
|
||||
setModalOpen: PropTypes.func.isRequired,
|
||||
permissions: PropTypes.oneOf(['admin', 'teacher']).isRequired,
|
||||
permissions: PropTypes.oneOf(['admin', 'teacher', 'student', 'no_enrollments']).isRequired,
|
||||
isK5User: PropTypes.bool.isRequired
|
||||
}
|
||||
|
|
|
@ -65,10 +65,20 @@ const ENROLLMENTS = [
|
|||
}
|
||||
]
|
||||
|
||||
const MCC_ACCOUNT = {
|
||||
id: 3,
|
||||
name: 'Manually-Created Courses',
|
||||
workflow_state: 'active'
|
||||
}
|
||||
|
||||
const MANAGEABLE_COURSES_URL = '/api/v1/manageable_accounts?per_page=100'
|
||||
const ENROLLMENTS_URL = encodeURI(
|
||||
const TEACHER_ENROLLMENTS_URL = encodeURI(
|
||||
'/api/v1/users/self/courses?per_page=100&include[]=account&enrollment_type=teacher'
|
||||
)
|
||||
const STUDENT_ENROLLMENTS_URL = encodeURI(
|
||||
'/api/v1/users/self/courses?per_page=100&include[]=account'
|
||||
)
|
||||
const MCC_ACCOUNT_URL = 'api/v1/manually_created_courses_account'
|
||||
|
||||
describe('CreateCourseModal', () => {
|
||||
const setModalOpen = jest.fn()
|
||||
|
@ -101,7 +111,7 @@ describe('CreateCourseModal', () => {
|
|||
).toBeInTheDocument()
|
||||
expect(getByLabelText('Subject Name')).toBeInTheDocument()
|
||||
expect(
|
||||
getByLabelText('Sync enrollments and course start/end dates from homeroom')
|
||||
getByLabelText('Sync enrollments and subject start/end dates from homeroom')
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
@ -194,44 +204,98 @@ describe('CreateCourseModal', () => {
|
|||
expect(getByRole('button', {name: 'Cancel'})).not.toBeDisabled()
|
||||
})
|
||||
|
||||
it('fetches accounts from enrollments api if permission is set to teacher', async () => {
|
||||
fetchMock.get(ENROLLMENTS_URL, ENROLLMENTS)
|
||||
const {getByText, getByLabelText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'teacher'})} />
|
||||
)
|
||||
await waitFor(() => expect(getByLabelText('Subject Name')).toBeInTheDocument())
|
||||
act(() => getByLabelText('Which account will this subject be associated with?').click())
|
||||
expect(getByText('Orange Elementary')).toBeInTheDocument()
|
||||
expect(getByText('Clark HS')).toBeInTheDocument()
|
||||
describe('with teacher permission', () => {
|
||||
it('fetches accounts from enrollments api', async () => {
|
||||
fetchMock.get(TEACHER_ENROLLMENTS_URL, ENROLLMENTS)
|
||||
const {getByText, getByLabelText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'teacher'})} />
|
||||
)
|
||||
await waitFor(() => expect(getByLabelText('Subject Name')).toBeInTheDocument())
|
||||
act(() => getByLabelText('Which account will this subject be associated with?').click())
|
||||
expect(getByText('Orange Elementary')).toBeInTheDocument()
|
||||
expect(getByText('Clark HS')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('hides the account select if there is only one enrollment', async () => {
|
||||
fetchMock.get(TEACHER_ENROLLMENTS_URL, [ENROLLMENTS[0]])
|
||||
const {queryByText, getByLabelText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'teacher'})} />
|
||||
)
|
||||
await waitFor(() => expect(getByLabelText('Subject Name')).toBeInTheDocument())
|
||||
expect(
|
||||
queryByText('Which account will this subject be associated with?')
|
||||
).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it("doesn't break if the user has restricted enrollments", async () => {
|
||||
fetchMock.get(TEACHER_ENROLLMENTS_URL, [
|
||||
...ENROLLMENTS,
|
||||
{
|
||||
id: 1033,
|
||||
access_restricted_by_date: true
|
||||
}
|
||||
])
|
||||
const {getByLabelText, queryByText, getByText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'teacher'})} />
|
||||
)
|
||||
await waitFor(() => expect(getByLabelText('Subject Name')).toBeInTheDocument())
|
||||
expect(queryByText('Unable to get accounts')).not.toBeInTheDocument()
|
||||
act(() => getByLabelText('Which account will this subject be associated with?').click())
|
||||
expect(getByText('Orange Elementary')).toBeInTheDocument()
|
||||
expect(getByText('Clark HS')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
it('hides the account select for teachers with only one enrollment', async () => {
|
||||
fetchMock.get(ENROLLMENTS_URL, [ENROLLMENTS[0]])
|
||||
const {queryByText, getByLabelText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'teacher'})} />
|
||||
)
|
||||
await waitFor(() => expect(getByLabelText('Subject Name')).toBeInTheDocument())
|
||||
expect(
|
||||
queryByText('Which account will this subject be associated with?')
|
||||
).not.toBeInTheDocument()
|
||||
describe('with student permission', () => {
|
||||
beforeEach(() => {
|
||||
fetchMock.get(STUDENT_ENROLLMENTS_URL, ENROLLMENTS)
|
||||
})
|
||||
|
||||
it('fetches accounts from enrollments api', async () => {
|
||||
const {findByLabelText, getByLabelText, getByText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'student'})} />
|
||||
)
|
||||
expect(await findByLabelText('Subject Name')).toBeInTheDocument()
|
||||
act(() => getByLabelText('Which account will this subject be associated with?').click())
|
||||
expect(getByText('Orange Elementary')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it("doesn't show the homeroom sync options", async () => {
|
||||
const {findByLabelText, queryByText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'student'})} />
|
||||
)
|
||||
expect(await findByLabelText('Subject Name')).toBeInTheDocument()
|
||||
expect(
|
||||
queryByText('Sync enrollments and subject start/end dates from homeroom')
|
||||
).not.toBeInTheDocument()
|
||||
expect(queryByText('Select a homeroom')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
it("doesn't break if the user has restricted enrollments", async () => {
|
||||
fetchMock.get(ENROLLMENTS_URL, [
|
||||
...ENROLLMENTS,
|
||||
{
|
||||
id: 1033,
|
||||
access_restricted_by_date: true
|
||||
}
|
||||
])
|
||||
const {getByLabelText, queryByText, getByText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'teacher'})} />
|
||||
)
|
||||
await waitFor(() => expect(getByLabelText('Subject Name')).toBeInTheDocument())
|
||||
expect(queryByText('Unable to get accounts')).not.toBeInTheDocument()
|
||||
act(() => getByLabelText('Which account will this subject be associated with?').click())
|
||||
expect(getByText('Orange Elementary')).toBeInTheDocument()
|
||||
expect(getByText('Clark HS')).toBeInTheDocument()
|
||||
describe('with no_enrollments permission', () => {
|
||||
beforeEach(() => {
|
||||
fetchMock.get(MCC_ACCOUNT_URL, MCC_ACCOUNT)
|
||||
})
|
||||
|
||||
it('uses the manually_created_courses_account api to get the right account', async () => {
|
||||
const {findByLabelText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'no_enrollments'})} />
|
||||
)
|
||||
expect(await findByLabelText('Subject Name')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it("doesn't show the homeroom sync options or account dropdown", async () => {
|
||||
const {findByLabelText, queryByText} = render(
|
||||
<CreateCourseModal {...getProps({permissions: 'no_enrollments'})} />
|
||||
)
|
||||
expect(await findByLabelText('Subject Name')).toBeInTheDocument()
|
||||
expect(
|
||||
queryByText('Sync enrollments and subject start/end dates from homeroom')
|
||||
).not.toBeInTheDocument()
|
||||
expect(
|
||||
queryByText('Which account will this subject be associated with?')
|
||||
).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('with isK5User set to false', () => {
|
||||
|
@ -245,7 +309,7 @@ describe('CreateCourseModal', () => {
|
|||
)
|
||||
expect(await findByLabelText('Course Name')).toBeInTheDocument()
|
||||
expect(
|
||||
queryByText('Sync enrollments and course start/end dates from homeroom')
|
||||
queryByText('Sync enrollments and subject start/end dates from homeroom')
|
||||
).not.toBeInTheDocument()
|
||||
expect(queryByText('Select a homeroom')).not.toBeInTheDocument()
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue