Render react student grades page
refs VICE-3474 refs VICE-3471 refs VICE-3472 refs VICE-3473 flag=restrict_quantitative_data Test Plan: - with “Update grade summary table to use a modern framework” turned on - go to the student grade summary page - table should calculate grades correctly according to - assignment group weights - grading period weights - turn RQD ff on - students grade table should show correct letter grades Change-Id: I5685a2db505734c8b4cea3592de66802456e9426 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/318040 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Jason Gillett <jason.gillett@instructure.com> QA-Review: Caleb Guanzon <cguanzon@instructure.com> Product-Review: Drake Harper <drake.harper@instructure.com>
This commit is contained in:
parent
4377d3c7e3
commit
ba9bb1c467
|
@ -28,6 +28,7 @@ import '@canvas/jquery/jquery.disableWhileLoading'
|
|||
// Ensure the gradebook summary code has had a chance to setup all its handlers
|
||||
GradeSummary.setup()
|
||||
|
||||
let router
|
||||
class GradebookSummaryRouter extends Backbone.Router {
|
||||
initialize() {
|
||||
if (!ENV.student_outcome_gradebook_enabled) return
|
||||
|
@ -77,10 +78,11 @@ GradebookSummaryRouter.prototype.routes = {
|
|||
'tab-:route(/*path)': 'tab',
|
||||
}
|
||||
|
||||
let router
|
||||
$(() => {
|
||||
GradeSummary.renderSelectMenuGroup()
|
||||
GradeSummary.renderSubmissionCommentsTray()
|
||||
if (ENV.student_grade_summary_upgrade || ENV.restrict_quantitative_data)
|
||||
GradeSummary.renderGradeSummaryTable()
|
||||
|
||||
router = new GradebookSummaryRouter()
|
||||
Backbone.history.start()
|
||||
|
|
|
@ -38,6 +38,7 @@ import {scopeToUser} from '@canvas/grading/EffectiveDueDates'
|
|||
import {scoreToGrade} from '@canvas/grading/GradingSchemeHelper'
|
||||
import GradeFormatHelper from '@canvas/grading/GradeFormatHelper'
|
||||
import StatusPill from '@canvas/grading-status-pill'
|
||||
import GradeSummaryManager from '../react/GradeSummary/GradeSummaryManager'
|
||||
import SelectMenuGroup from '../react/SelectMenuGroup'
|
||||
import SubmissionCommentsTray from '../react/SubmissionCommentsTray'
|
||||
import {scoreToPercentage} from '@canvas/grading/GradeCalculationHelper'
|
||||
|
@ -610,6 +611,10 @@ function renderSelectMenuGroup() {
|
|||
)
|
||||
}
|
||||
|
||||
function renderGradeSummaryTable() {
|
||||
ReactDOM.render(<GradeSummaryManager />, document.getElementById('grade-summary-react'))
|
||||
}
|
||||
|
||||
function handleSubmissionsCommentTray(assignmentId) {
|
||||
const {submissionTrayAssignmentId, submissionTrayOpen} = useStore.getState()
|
||||
|
||||
|
@ -875,6 +880,7 @@ export default _.extend(GradeSummary, {
|
|||
formatPercentGrade,
|
||||
getSelectMenuGroupProps,
|
||||
renderSelectMenuGroup,
|
||||
renderGradeSummaryTable,
|
||||
getSubmissionCommentsTrayProps,
|
||||
handleSubmissionsCommentTray,
|
||||
renderSubmissionCommentsTray,
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import {useQuery} from 'react-apollo'
|
||||
import {useScope as useI18nScope} from '@canvas/i18n'
|
||||
import GenericErrorPage from '@canvas/generic-error-page'
|
||||
import errorShipUrl from '@canvas/images/ErrorShip.svg'
|
||||
|
||||
import {CloseButton} from '@instructure/ui-buttons'
|
||||
import {Flex} from '@instructure/ui-flex'
|
||||
import {Heading} from '@instructure/ui-heading'
|
||||
import {Responsive} from '@instructure/ui-responsive'
|
||||
import {Spinner} from '@instructure/ui-spinner'
|
||||
import {Tray} from '@instructure/ui-tray'
|
||||
import {View} from '@instructure/ui-view'
|
||||
|
||||
import {ASSIGNMENTS} from '../../graphql/queries'
|
||||
|
||||
import AssignmentTable from './AssignmentTable'
|
||||
import SubmissionComment from './SubmissionComment'
|
||||
import {getGradingPeriodID} from './utils'
|
||||
|
||||
const I18n = useI18nScope('grade_summary')
|
||||
|
||||
const GradeSummaryContainer = () => {
|
||||
const [showTray, setShowTray] = React.useState(false)
|
||||
const [selectedSubmission, setSelectedSubmission] = React.useState([])
|
||||
|
||||
const gradingPeriod = getGradingPeriodID()
|
||||
|
||||
const assignmentQuery = useQuery(ASSIGNMENTS, {
|
||||
variables: {
|
||||
courseID: ENV.course_id,
|
||||
studentID: ENV.current_user.id,
|
||||
gradingPeriodID: gradingPeriod && gradingPeriod !== '0' ? gradingPeriod : null,
|
||||
},
|
||||
})
|
||||
|
||||
if (assignmentQuery.loading) {
|
||||
return (
|
||||
<Flex alignItems="center" justifyItems="center" width="100%">
|
||||
<Flex.Item>
|
||||
<Spinner renderTitle="Loading" size="large" margin="0 0 0 medium" />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
if (assignmentQuery.error || !assignmentQuery?.data?.legacyNode) {
|
||||
return (
|
||||
<GenericErrorPage
|
||||
imageUrl={errorShipUrl}
|
||||
errorSubject={I18n.t('Grade Summary initial query error')}
|
||||
errorCategory={I18n.t('Grade Summary Error Page')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const renderCloseButton = () => {
|
||||
return (
|
||||
<Flex>
|
||||
<Flex.Item shouldGrow={true} shouldShrink={true}>
|
||||
<Heading>Submission Comments</Heading>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<CloseButton
|
||||
placement="end"
|
||||
offset="small"
|
||||
screenReaderLabel="Close"
|
||||
onClick={() => setShowTray(false)}
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Responsive
|
||||
query={{
|
||||
small: {maxWidth: '40rem'},
|
||||
large: {minWidth: '41rem'},
|
||||
}}
|
||||
props={{
|
||||
small: {layout: 'stacked'},
|
||||
large: {layout: 'fixed'},
|
||||
}}
|
||||
>
|
||||
{({layout}) => (
|
||||
<View as="div">
|
||||
<AssignmentTable
|
||||
queryData={assignmentQuery?.data?.legacyNode}
|
||||
layout={layout}
|
||||
setShowTray={setShowTray}
|
||||
setSelectedSubmission={setSelectedSubmission}
|
||||
/>
|
||||
<Tray
|
||||
label={I18n.t('Submission Comments Tray')}
|
||||
open={showTray}
|
||||
onDismiss={() => {
|
||||
setShowTray(false)
|
||||
}}
|
||||
size="medium"
|
||||
placement="end"
|
||||
>
|
||||
<View as="div" padding="medium">
|
||||
{renderCloseButton()}
|
||||
{selectedSubmission?.commentsConnection?.nodes?.map(comment => {
|
||||
return <SubmissionComment comment={comment} key={comment?._id} />
|
||||
})}
|
||||
</View>
|
||||
</Tray>
|
||||
</View>
|
||||
)}
|
||||
</Responsive>
|
||||
)
|
||||
}
|
||||
|
||||
export default GradeSummaryContainer
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// import PropTypes from 'prop-types'
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {ApolloProvider, createClient, createPersistentCache} from '@canvas/apollo'
|
||||
import {useScope as useI18nScope} from '@canvas/i18n'
|
||||
import ErrorBoundary from '@canvas/error-boundary'
|
||||
import GenericErrorPage from '@canvas/generic-error-page'
|
||||
import errorShipUrl from '@canvas/images/ErrorShip.svg'
|
||||
|
||||
import GradeSummaryContainer from './GradeSummaryContainer'
|
||||
|
||||
import LoadingIndicator from '@canvas/loading-indicator'
|
||||
|
||||
const I18n = useI18nScope('grade_summary')
|
||||
|
||||
const GradeSummaryManager = () => {
|
||||
const [client, setClient] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
document.querySelector('body').classList.add('full-width')
|
||||
document.querySelector('div.ic-Layout-contentMain').classList.remove('ic-Layout-contentMain')
|
||||
const setupApolloClient = async () => {
|
||||
if (ENV.apollo_caching) {
|
||||
const cache = await createPersistentCache(ENV.conversation_cache_key)
|
||||
setClient(createClient({cache}))
|
||||
} else {
|
||||
setClient(createClient())
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
setupApolloClient()
|
||||
}, [])
|
||||
|
||||
if (loading) {
|
||||
return <LoadingIndicator />
|
||||
}
|
||||
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<ErrorBoundary
|
||||
errorComponent={
|
||||
<GenericErrorPage
|
||||
imageUrl={errorShipUrl}
|
||||
errorCategory={I18n.t('Grade Summary Error Page')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<GradeSummaryContainer />
|
||||
</ErrorBoundary>
|
||||
</ApolloProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default GradeSummaryManager
|
Loading…
Reference in New Issue