add discussion checkpoints checkbox to form

closes EVAL-3887
flag=discussion_checkpoints
flag=discussion_create

Test Plan:
- turn on the discussion checkpoints feature flag
- go to create a discussion
- click on the Graded checkbox
- confirm that the Assign graded checkpoints checkbox shows up
- confirm that the Checkpoint Settings title appears below the
  peer review options
- confirm that the checkbox toggles on and off when clicked
- hover over the information icon and confirm that the message
  matches that in the figma
- confirm that the checkpoints checkbox does not appear when the
  feature flag is off

Change-Id: I5ddf42e72bd08538ef5eb55325230093af7bedc3
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/343600
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Caleb Guanzon <cguanzon@instructure.com>
Reviewed-by: Omar Soto-Fortuño <omar.soto@instructure.com>
Product-Review: Omar Soto-Fortuño <omar.soto@instructure.com>
This commit is contained in:
Samuel Lee 2024-03-23 13:14:14 -05:00
parent e93b146531
commit 91751a3b7a
6 changed files with 111 additions and 2 deletions

View File

@ -621,6 +621,7 @@ class DiscussionTopicsController < ApplicationController
allow_student_anonymous_discussion_topics: @context.allow_student_anonymous_discussion_topics,
context_is_not_group: !@context.is_a?(Group),
GRADING_SCHEME_UPDATES_ENABLED: Account.site_admin.feature_enabled?(:grading_scheme_updates),
DISCUSSION_CHECKPOINTS_ENABLED: @context.root_account.feature_enabled?(:discussion_checkpoints)
}
post_to_sis = Assignment.sis_grade_export_enabled?(@context)

View File

@ -1404,6 +1404,13 @@ describe DiscussionTopicsController do
get :new, params: { course_id: @course.id }
expect(assigns[:js_bundles].first).to include(:discussion_topic_edit_v2)
end
it "js_env DISCUSSION_CHECKPOINTS_ENABLED is set to true when creating a discussion and discussion checkpoints ff is on" do
user_session(@teacher)
@course.root_account.enable_feature!(:discussion_checkpoints)
get :new, params: { course_id: @course.id }
expect(assigns[:js_env][:DISCUSSION_CHECKPOINTS_ENABLED]).to be_truthy
end
end
describe "GET 'edit'" do
@ -1536,6 +1543,13 @@ describe DiscussionTopicsController do
expect(assigns[:js_env][:allow_student_anonymous_discussion_topics]).to be true
end
it "js_env DISCUSSION_CHECKPOINTS_ENABLED is set to true when editing a discussion and discussion checkpoints ff is on" do
user_session(@teacher)
@course.root_account.enable_feature!(:discussion_checkpoints)
get :edit, params: { course_id: @course.id, id: @topic.id }
expect(assigns[:js_env][:DISCUSSION_CHECKPOINTS_ENABLED]).to be_truthy
end
context "conditional-release" do
before do
user_session(@teacher)

View File

@ -19,7 +19,8 @@
import React from 'react'
import {View} from '@instructure/ui-view'
import {Text} from '@instructure/ui-text'
import {useScope as useI18nScope} from '@canvas/i18n'
import {AssignmentGroupSelect} from './AssignmentGroupSelect'
import {DisplayGradeAs} from './DisplayGradeAs'
import {PointsPossible} from './PointsPossible'
@ -48,8 +49,11 @@ type Props = {
setGradingSchemeId: (gradingSchemeId: string) => void
intraGroupPeerReviews: boolean
setIntraGroupPeerReviews: (intraGroupPeerReviews: boolean) => void
isCheckPoints: boolean
}
const I18n = useI18nScope('discussion_create')
export const GradedDiscussionOptions = ({
assignmentGroups,
pointsPossible,
@ -70,6 +74,7 @@ export const GradedDiscussionOptions = ({
setGradingSchemeId,
intraGroupPeerReviews,
setIntraGroupPeerReviews,
isCheckPoints,
}: Props) => {
return (
<View as="div">
@ -116,6 +121,11 @@ export const GradedDiscussionOptions = ({
setIntraGroupPeerReviews={setIntraGroupPeerReviews}
/>
</View>
{isCheckPoints && (
<View as="div" margin="medium 0">
<Text size="large">{I18n.t('Checkpoint Settings')}</Text>
</View>
)}
<View as="div" margin="medium 0">
<AssignmentDueDatesManager />
</View>

View File

@ -37,6 +37,7 @@ const defaultProps = {
setPeerReviewDueDate: () => {},
assignedInfoList: [],
setAssignedInfoList: () => {},
isCheckPoints: false,
}
const renderGradedDiscussionOptions = (props = {}) => {
@ -60,4 +61,11 @@ describe('GradedDiscussionOptions', () => {
expect(getByText('Peer Reviews')).toBeInTheDocument()
expect(getByText('Assignment Settings')).toBeInTheDocument()
})
describe('Checkpoints', () => {
it('renders the section Checkpoint Settings when the checkpoints checkbox is selected', () => {
const {getByText} = renderGradedDiscussionOptions({isCheckPoints: true})
expect(getByText('Checkpoint Settings')).toBeInTheDocument()
})
})
})

View File

@ -25,14 +25,21 @@ import {View} from '@instructure/ui-view'
import {Flex} from '@instructure/ui-flex'
import {TextInput} from '@instructure/ui-text-input'
import {FormFieldGroup} from '@instructure/ui-form-field'
import {IconAddLine, IconPublishSolid, IconUnpublishedLine} from '@instructure/ui-icons'
import {
IconAddLine,
IconPublishSolid,
IconUnpublishedLine,
IconInfoLine,
} from '@instructure/ui-icons'
import {Text} from '@instructure/ui-text'
import {Checkbox} from '@instructure/ui-checkbox'
import {Tooltip} from '@instructure/ui-tooltip'
import {SimpleSelect} from '@instructure/ui-simple-select'
import {DateTimeInput} from '@instructure/ui-date-time-input'
import CanvasMultiSelect from '@canvas/multi-select'
import CanvasRce from '@canvas/rce/react/CanvasRce'
import {Alert} from '@instructure/ui-alerts'
import theme from '@instructure/canvas-theme'
import {FormControlButtons} from './FormControlButtons'
import {GradedDiscussionOptions} from '../DiscussionOptions/GradedDiscussionOptions'
@ -120,6 +127,10 @@ export default function DiscussionTopicForm({
const allSectionsOption = {id: 'all', name: 'All Sections'}
const checkPointsToolTipText = I18n.t(
'Checkpoints can be set to have different due dates and point values for the initial response and the subsequent replies.'
)
const inputWidth = '100%'
const [title, setTitle] = useState(currentDiscussionTopic?.title || '')
@ -154,6 +165,9 @@ export default function DiscussionTopicForm({
currentDiscussionTopic?.podcastHasStudentPosts || false
)
const [isGraded, setIsGraded] = useState(!!currentDiscussionTopic?.assignment || false)
const [isCheckPoints, setIsCheckPoints] = useState(
!!currentDiscussionTopic?.assignment?.checkpoints || false
)
const [allowLiking, setAllowLiking] = useState(currentDiscussionTopic?.allowRating || false)
const [onlyGradersCanLike, setOnlyGradersCanLike] = useState(
currentDiscussionTopic?.onlyGradersCanRate || false
@ -676,6 +690,29 @@ export default function DiscussionTopicForm({
// disabled={sectionIdsToPostTo === [allSectionsOption._id]}
/>
)}
{isGraded && ENV.DISCUSSION_CHECKPOINTS_ENABLED && (
<>
<View display="inline-block">
<Checkbox
data-testid="checkpoints-checkbox"
label={I18n.t('Assign graded checkpoints')}
value="checkpoints"
checked={isCheckPoints}
onChange={() => setIsCheckPoints(!isCheckPoints)}
/>
</View>
<Tooltip renderTip={checkPointsToolTipText} on={['hover', 'focus']} color="primary">
<div
style={{display: "inline-block", marginLeft: theme.spacing.xxSmall}}
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
tabIndex="0"
>
<IconInfoLine />
<ScreenReaderContent>{checkPointsToolTipText}</ScreenReaderContent>
</div>
</Tooltip>
</>
)}
{shouldShowLikingOption && (
<>
<Checkbox
@ -851,6 +888,7 @@ export default function DiscussionTopicForm({
setGradingSchemeId={setGradingSchemeId}
intraGroupPeerReviews={intraGroupPeerReviews}
setIntraGroupPeerReviews={setIntraGroupPeerReviews}
isCheckPoints={isCheckPoints && ENV.DISCUSSION_CHECKPOINTS_ENABLED}
/>
</GradedDiscussionDueDatesContext.Provider>
</View>

View File

@ -410,5 +410,43 @@ describe('DiscussionTopicForm', () => {
expect(document.queryByTestId('group-category-not-editable')).toBeFalsy()
})
it('displays the checkpoints checkbox when the Graded option is selected and discussion checkpoints flag is on', () => {
ENV.DISCUSSION_CHECKPOINTS_ENABLED = true
const {queryByTestId, getByLabelText} = setup()
expect(queryByTestId('checkpoints-checkbox')).not.toBeInTheDocument()
getByLabelText('Graded').click()
expect(queryByTestId('checkpoints-checkbox')).toBeInTheDocument()
})
it('does not display the checkpoints checkbox when the Graded option is not selected and discussion checkpoints flag is on', () => {
ENV.DISCUSSION_CHECKPOINTS_ENABLED = true
const {queryByTestId} = setup()
expect(queryByTestId('checkpoints-checkbox')).not.toBeInTheDocument()
})
it('does not display the checkpoints checkbox when the discussion checkpoints flag is off', () => {
ENV.DISCUSSION_CHECKPOINTS_ENABLED = false
const {queryByTestId, getByLabelText} = setup()
getByLabelText('Graded').click()
expect(queryByTestId('checkpoints-checkbox')).not.toBeInTheDocument()
})
})
describe('Checkpoints', () => {
it('toggles the checkpoints checkbox when clicked', () => {
ENV.DISCUSSION_CHECKPOINTS_ENABLED = true
const {queryByTestId, getByLabelText} = setup()
getByLabelText('Graded').click()
const checkbox = queryByTestId('checkpoints-checkbox')
checkbox.click()
expect(checkbox.checked).toBe(true)
checkbox.click()
expect(checkbox.checked).toBe(false)
})
})
})