create components for new student grade table
refs VICE-3474 refs VICE-3471 refs VICE-3472 refs VICE-3473 flag=restrict_quantitative_data Test Plan: - run `yarn storybook .` - view the student grade summary folder - all components should render properly Change-Id: I60f67b293e80c4d4d3648b57ebb080c3f0550005 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/317803 Reviewed-by: Jason Gillett <jason.gillett@instructure.com> Product-Review: Jody Sailor Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> QA-Review: Caleb Guanzon <cguanzon@instructure.com>
This commit is contained in:
parent
80d0310aa2
commit
4377d3c7e3
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 {useScope as useI18nScope} from '@canvas/i18n'
|
||||
import {nanoid} from 'nanoid'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {Table} from '@instructure/ui-table'
|
||||
|
||||
import {getGradingPeriodID} from './utils'
|
||||
|
||||
import {totalRow} from './AssignmentTableRows/TotalRow'
|
||||
import {assignmentGroupRow} from './AssignmentTableRows/AssignmentGroupRow'
|
||||
import {gradingPeriodRow} from './AssignmentTableRows/GradingPeriodRow'
|
||||
import {assignmentRow} from './AssignmentTableRows/AssignmentRow'
|
||||
|
||||
const I18n = useI18nScope('grade_summary')
|
||||
|
||||
const headers = [
|
||||
{key: 'name', value: I18n.t('Name'), id: nanoid()},
|
||||
{key: 'dueAt', value: I18n.t('Due Date'), id: nanoid()},
|
||||
{key: 'status', value: I18n.t('Status'), id: nanoid()},
|
||||
{key: 'score', value: I18n.t('Score'), id: nanoid()},
|
||||
]
|
||||
|
||||
const AssignmentTable = ({queryData, layout, setShowTray, setSelectedSubmission}) => {
|
||||
return (
|
||||
<Table caption={I18n.t('Student Grade Summary')} layout={layout}>
|
||||
<Table.Head>
|
||||
<Table.Row>
|
||||
{(headers || []).map(header => (
|
||||
<Table.ColHeader key={header?.key} id={header?.id}>
|
||||
{header?.value}
|
||||
</Table.ColHeader>
|
||||
))}
|
||||
</Table.Row>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{queryData?.assignmentsConnection?.nodes?.map(assignment => {
|
||||
return assignmentRow(assignment, queryData, setShowTray, setSelectedSubmission)
|
||||
})}
|
||||
{getGradingPeriodID() !== '0'
|
||||
? queryData?.assignmentGroupsConnection?.nodes?.map(assignmentGroup => {
|
||||
return assignmentGroupRow(assignmentGroup, queryData)
|
||||
})
|
||||
: queryData?.gradingPeriodsConnection?.nodes?.map(gradingPeriod => {
|
||||
return gradingPeriodRow(gradingPeriod, queryData)
|
||||
})}
|
||||
{totalRow(queryData)}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
}
|
||||
|
||||
AssignmentTable.propTypes = {
|
||||
queryData: PropTypes.object,
|
||||
layout: PropTypes.string,
|
||||
setShowTray: PropTypes.func,
|
||||
setSelectedSubmission: PropTypes.func,
|
||||
}
|
||||
|
||||
export default AssignmentTable
|
|
@ -0,0 +1,758 @@
|
|||
/*
|
||||
* Copyright (C) 2021 - 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 AssignmentTable from './AssignmentTable'
|
||||
import React from 'react'
|
||||
|
||||
export default {
|
||||
title: 'Examples/Student Grade Summary/AssignmentTable',
|
||||
component: AssignmentTable,
|
||||
}
|
||||
|
||||
const defaultQueryData = {
|
||||
id: 'Q291cnNlLTE=',
|
||||
name: 'Dragon Riding',
|
||||
applyGroupWeights: true,
|
||||
assignmentsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '3',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Graded discussion for submission comments',
|
||||
pointsPossible: 1000,
|
||||
assignmentGroup: {
|
||||
_id: '3',
|
||||
name: 'Test Assignment Group',
|
||||
groupWeight: 30,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '12',
|
||||
gradingStatus: 'graded',
|
||||
grade: '567',
|
||||
score: 567,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
comment: 'What am I supposed to do with this ron?',
|
||||
createdAt: '2022-04-19T10:32:29-06:00',
|
||||
author: {
|
||||
name: 'Drake Harper',
|
||||
shortName: 'Drake Harper',
|
||||
__typename: 'User',
|
||||
},
|
||||
__typename: 'SubmissionComment',
|
||||
},
|
||||
{
|
||||
comment:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor nunc non arcu placerat, at mollis massa suscipit. Nullam tincidunt bibendum turpis vitae consectetur. Proin posuere placerat elit, id mollis erat blandit porta. Aliquam laoreet dui sit amet ultricies pharetra. Aliquam euismod, ex at faucibus viverra, mauris velit ullamcorper massa, ut ultricies orci orci eu lorem. Pellentesque quis lectus nisl. Suspendisse sem dolor, facilisis eu velit et, varius tempus massa. Sed luctus imperdiet metus at tempor. Suspendisse tincidunt neque eu velit luctus gravida. Suspendisse sed aliquet nisi. Curabitur sagittis consequat euismod. Cras aliquam nulla vel dolor semper placerat. Nunc in dolor enim.',
|
||||
createdAt: '2022-04-19T10:51:32-06:00',
|
||||
author: {
|
||||
name: 'Ron Weasley',
|
||||
shortName: 'Ron Weasley',
|
||||
__typename: 'User',
|
||||
},
|
||||
__typename: 'SubmissionComment',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '8',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Test Assignment Grading',
|
||||
pointsPossible: 100,
|
||||
assignmentGroup: {
|
||||
_id: '3',
|
||||
name: 'Test Assignment Group',
|
||||
groupWeight: 30,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '37',
|
||||
gradingStatus: 'graded',
|
||||
grade: null,
|
||||
score: null,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: true,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '11',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'New Discussion =D',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '3',
|
||||
name: 'Test Assignment Group',
|
||||
groupWeight: 30,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '722',
|
||||
gradingStatus: 'graded',
|
||||
grade: '8',
|
||||
score: 8,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '13',
|
||||
dueAt: '2023-04-21T23:59:59-06:00',
|
||||
htmlUrl: '',
|
||||
name: 'Late Assignment',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '3',
|
||||
name: 'Test Assignment Group',
|
||||
groupWeight: 30,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '735',
|
||||
gradingStatus: 'graded',
|
||||
grade: '8',
|
||||
score: 8,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '14',
|
||||
dueAt: '2023-04-21T23:59:59-06:00',
|
||||
htmlUrl: '',
|
||||
name: 'Missing Assignment ',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '3',
|
||||
name: 'Test Assignment Group',
|
||||
groupWeight: 30,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '15',
|
||||
dueAt: '2023-04-21T23:59:59-06:00',
|
||||
htmlUrl: '',
|
||||
name: 'Excused Assignment',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '3',
|
||||
name: 'Test Assignment Group',
|
||||
groupWeight: 30,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '749',
|
||||
gradingStatus: 'excused',
|
||||
grade: null,
|
||||
score: null,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '4',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Welcome New Riders',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '1',
|
||||
name: 'Assignments',
|
||||
groupWeight: 70,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '17',
|
||||
gradingStatus: 'graded',
|
||||
grade: '9',
|
||||
score: 9,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
comment: 'Welcome Ron, happy to have you',
|
||||
createdAt: '2022-04-19T11:22:13-06:00',
|
||||
author: {
|
||||
name: 'Drake Harper',
|
||||
shortName: 'Drake Harper',
|
||||
__typename: 'User',
|
||||
},
|
||||
__typename: 'SubmissionComment',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
],
|
||||
__typename: 'AssignmentConnection',
|
||||
},
|
||||
assignmentGroupsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '3',
|
||||
name: 'Test Assignment Group',
|
||||
groupWeight: 30,
|
||||
gradesConnection: {
|
||||
nodes: [
|
||||
{
|
||||
currentGrade: 'F',
|
||||
currentScore: 57.39,
|
||||
overrideGrade: null,
|
||||
overrideScore: null,
|
||||
__typename: 'Grades',
|
||||
},
|
||||
],
|
||||
__typename: 'GradesConnection',
|
||||
},
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
{
|
||||
_id: '1',
|
||||
name: 'Assignments',
|
||||
groupWeight: 70,
|
||||
gradesConnection: {
|
||||
nodes: [
|
||||
{
|
||||
currentGrade: 'D+',
|
||||
currentScore: 68.06,
|
||||
overrideGrade: null,
|
||||
overrideScore: null,
|
||||
__typename: 'Grades',
|
||||
},
|
||||
],
|
||||
__typename: 'GradesConnection',
|
||||
},
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
],
|
||||
__typename: 'AssignmentGroupConnection',
|
||||
},
|
||||
gradingStandard: {
|
||||
data: [
|
||||
{
|
||||
letterGrade: 'A',
|
||||
baseValue: 0.94,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'A-',
|
||||
baseValue: 0.9,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'B+',
|
||||
baseValue: 0.87,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'B',
|
||||
baseValue: 0.84,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'B-',
|
||||
baseValue: 0.8,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'C+',
|
||||
baseValue: 0.77,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'C',
|
||||
baseValue: 0.74,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'C-',
|
||||
baseValue: 0.7,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'D+',
|
||||
baseValue: 0.67,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'D',
|
||||
baseValue: 0.64,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'D-',
|
||||
baseValue: 0.61,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'F',
|
||||
baseValue: 0,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
],
|
||||
title: 'Default Grading Scheme',
|
||||
__typename: 'GradingStandard',
|
||||
},
|
||||
gradingPeriodsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '3',
|
||||
title: 'U',
|
||||
weight: 70,
|
||||
__typename: 'GradingPeriod',
|
||||
},
|
||||
{
|
||||
_id: '4',
|
||||
title: 'V',
|
||||
weight: 30,
|
||||
__typename: 'GradingPeriod',
|
||||
},
|
||||
],
|
||||
__typename: 'GradingPeriodConnection',
|
||||
},
|
||||
__typename: 'Course',
|
||||
}
|
||||
|
||||
const varyingAssignmentTypes = {
|
||||
id: 'Q291cnNlLTEwMTM=',
|
||||
name: 'Varying Assignment Types',
|
||||
applyGroupWeights: false,
|
||||
assignmentsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '20',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Percentage',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '754',
|
||||
gradingStatus: 'graded',
|
||||
grade: '99%',
|
||||
score: 9.9,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '21',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Complete/Incomplete',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '755',
|
||||
gradingStatus: 'graded',
|
||||
grade: 'complete',
|
||||
score: 10,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '22',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Points',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '756',
|
||||
gradingStatus: 'graded',
|
||||
grade: '8',
|
||||
score: 8,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '23',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Letter Grade',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '757',
|
||||
gradingStatus: 'graded',
|
||||
grade: 'B+',
|
||||
score: 8.9,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '24',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'GPA Scale',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '758',
|
||||
gradingStatus: 'graded',
|
||||
grade: 'B',
|
||||
score: 8.6,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '25',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Not Graded',
|
||||
pointsPossible: null,
|
||||
assignmentGroup: {
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
{
|
||||
_id: '26',
|
||||
dueAt: null,
|
||||
htmlUrl: '',
|
||||
name: 'Manual post',
|
||||
pointsPossible: 10,
|
||||
assignmentGroup: {
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
submissionsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '767',
|
||||
gradingStatus: 'graded',
|
||||
grade: '7',
|
||||
score: 7,
|
||||
gradingPeriodId: '4',
|
||||
hideGradeFromStudent: false,
|
||||
commentsConnection: {
|
||||
nodes: [],
|
||||
__typename: 'SubmissionCommentConnection',
|
||||
},
|
||||
__typename: 'Submission',
|
||||
},
|
||||
],
|
||||
__typename: 'SubmissionConnection',
|
||||
},
|
||||
__typename: 'Assignment',
|
||||
},
|
||||
],
|
||||
__typename: 'AssignmentConnection',
|
||||
},
|
||||
assignmentGroupsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '16',
|
||||
name: 'Assignments',
|
||||
groupWeight: 0,
|
||||
gradesConnection: {
|
||||
nodes: [
|
||||
{
|
||||
currentGrade: null,
|
||||
currentScore: 87.33,
|
||||
overrideGrade: null,
|
||||
overrideScore: null,
|
||||
__typename: 'Grades',
|
||||
},
|
||||
],
|
||||
__typename: 'GradesConnection',
|
||||
},
|
||||
__typename: 'AssignmentGroup',
|
||||
},
|
||||
],
|
||||
__typename: 'AssignmentGroupConnection',
|
||||
},
|
||||
gradingStandard: {
|
||||
data: [
|
||||
{
|
||||
letterGrade: 'A',
|
||||
baseValue: 0.94,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'A-',
|
||||
baseValue: 0.9,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'B+',
|
||||
baseValue: 0.87,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'B',
|
||||
baseValue: 0.84,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'B-',
|
||||
baseValue: 0.8,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'C+',
|
||||
baseValue: 0.77,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'C',
|
||||
baseValue: 0.74,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'C-',
|
||||
baseValue: 0.7,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'D+',
|
||||
baseValue: 0.67,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'D',
|
||||
baseValue: 0.64,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'D-',
|
||||
baseValue: 0.61,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
{
|
||||
letterGrade: 'F',
|
||||
baseValue: 0,
|
||||
__typename: 'GradingStandardItem',
|
||||
},
|
||||
],
|
||||
title: 'Default Grading Scheme',
|
||||
__typename: 'GradingStandard',
|
||||
},
|
||||
gradingPeriodsConnection: {
|
||||
nodes: [
|
||||
{
|
||||
_id: '3',
|
||||
title: 'U',
|
||||
weight: 70,
|
||||
__typename: 'GradingPeriod',
|
||||
},
|
||||
{
|
||||
_id: '4',
|
||||
title: 'V',
|
||||
weight: 30,
|
||||
__typename: 'GradingPeriod',
|
||||
},
|
||||
],
|
||||
__typename: 'GradingPeriodConnection',
|
||||
},
|
||||
__typename: 'Course',
|
||||
}
|
||||
|
||||
const Template = args => <AssignmentTable {...args} />
|
||||
|
||||
export const Default = Template.bind({})
|
||||
Default.args = {
|
||||
queryData: defaultQueryData,
|
||||
layout: 'fixed',
|
||||
setShowTray: () => {},
|
||||
setSelectedSubmission: () => {},
|
||||
}
|
||||
|
||||
export const Mobile = Template.bind({})
|
||||
Mobile.args = {
|
||||
queryData: defaultQueryData,
|
||||
layout: 'stacked',
|
||||
setShowTray: () => {},
|
||||
setSelectedSubmission: () => {},
|
||||
}
|
||||
|
||||
export const VaryingAssignmentTypes = Template.bind({})
|
||||
VaryingAssignmentTypes.args = {
|
||||
queryData: varyingAssignmentTypes,
|
||||
layout: 'fixed',
|
||||
setShowTray: () => {},
|
||||
setSelectedSubmission: () => {},
|
||||
}
|
|
@ -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 React from 'react'
|
||||
import {Table} from '@instructure/ui-table'
|
||||
import {Text} from '@instructure/ui-text'
|
||||
|
||||
import {
|
||||
getAssignmentGroupPercentage,
|
||||
formatNumber,
|
||||
scoreToLetterGrade,
|
||||
getAssignmentGroupEarnedPoints,
|
||||
getAssignmentGroupTotalPoints,
|
||||
filteredAssignments,
|
||||
} from '../utils'
|
||||
|
||||
export const assignmentGroupRow = (assignmentGroup, queryData) => {
|
||||
return (
|
||||
<Table.Row key={assignmentGroup?._id}>
|
||||
<Table.Cell textAlign="start" colSpan="3">
|
||||
<Text weight="bold">{assignmentGroup?.name}</Text>
|
||||
</Table.Cell>
|
||||
{!ENV.restrict_quantitative_data && (
|
||||
<Table.Cell textAlign="start">
|
||||
<Text weight="bold">
|
||||
{formatNumber(
|
||||
getAssignmentGroupPercentage(assignmentGroup, filteredAssignments(queryData), false)
|
||||
)}
|
||||
%
|
||||
</Text>
|
||||
</Table.Cell>
|
||||
)}
|
||||
<Table.Cell textAlign="start">
|
||||
<Text weight="bold">
|
||||
{ENV.restrict_quantitative_data
|
||||
? scoreToLetterGrade(
|
||||
getAssignmentGroupPercentage(
|
||||
assignmentGroup,
|
||||
filteredAssignments(queryData),
|
||||
false
|
||||
),
|
||||
queryData?.gradingStandard
|
||||
)
|
||||
: `${
|
||||
formatNumber(
|
||||
getAssignmentGroupEarnedPoints(assignmentGroup, filteredAssignments(queryData))
|
||||
) || '-'
|
||||
}/${
|
||||
formatNumber(
|
||||
getAssignmentGroupTotalPoints(assignmentGroup, filteredAssignments(queryData))
|
||||
) || '-'
|
||||
}`}
|
||||
</Text>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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 DateHelper from '@canvas/datetime/dateHelper'
|
||||
import {useScope as useI18nScope} from '@canvas/i18n'
|
||||
|
||||
import {IconButton} from '@instructure/ui-buttons'
|
||||
import {Flex} from '@instructure/ui-flex'
|
||||
import {IconCommentLine, IconMutedLine} from '@instructure/ui-icons'
|
||||
import {Table} from '@instructure/ui-table'
|
||||
import {Text} from '@instructure/ui-text'
|
||||
import {Tooltip} from '@instructure/ui-tooltip'
|
||||
|
||||
import {getDisplayStatus, getDisplayScore, submissionCommentsPresent} from '../utils'
|
||||
|
||||
const I18n = useI18nScope('grade_summary')
|
||||
|
||||
export const assignmentRow = (assignment, queryData, setShowTray, setSelectedSubmission) => {
|
||||
return (
|
||||
<Table.Row key={assignment._id}>
|
||||
<Table.Cell textAlign="start">
|
||||
<Flex direction="column">
|
||||
<Flex.Item>
|
||||
<a href={assignment.htmlUrl}>{assignment.name}</a>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Text size="small">{assignment.assignmentGroup.name}</Text>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Table.Cell>
|
||||
<Table.Cell textAlign="start">
|
||||
{DateHelper.formatDatetimeForDisplay(assignment.dueAt)}
|
||||
</Table.Cell>
|
||||
<Table.Cell textAlign="start">{getDisplayStatus(assignment)}</Table.Cell>
|
||||
<Table.Cell textAlign="start">
|
||||
{assignment?.submissionsConnection?.nodes[0]?.hideGradeFromStudent ? (
|
||||
<Tooltip renderTip={I18n.t('This assignment is muted')}>
|
||||
<IconMutedLine />
|
||||
</Tooltip>
|
||||
) : (
|
||||
getDisplayScore(assignment, queryData?.gradingStandard)
|
||||
)}
|
||||
</Table.Cell>
|
||||
<Table.Cell textAlign="center">
|
||||
{submissionCommentsPresent(assignment) && (
|
||||
<IconButton
|
||||
margin="0 small"
|
||||
screenReaderLabel="Submission Comments"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setShowTray(true)
|
||||
setSelectedSubmission(assignment?.submissionsConnection?.nodes[0])
|
||||
}}
|
||||
>
|
||||
<IconCommentLine />
|
||||
<Text size="small">
|
||||
{assignment?.submissionsConnection.nodes[0].commentsConnection.nodes.length}
|
||||
</Text>
|
||||
</IconButton>
|
||||
)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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 {Table} from '@instructure/ui-table'
|
||||
import {Text} from '@instructure/ui-text'
|
||||
|
||||
import {
|
||||
formatNumber,
|
||||
scoreToLetterGrade,
|
||||
getGradingPeriodTotalPoints,
|
||||
getGradingPeriodPercentage,
|
||||
getGradingPeriodTotalWeighted,
|
||||
getGradingPeriodEarnedPoints,
|
||||
filteredAssignments,
|
||||
} from '../utils'
|
||||
|
||||
export const gradingPeriodRow = (gradingPeriod, queryData) => {
|
||||
const filterByGradingPeriod = filteredAssignments(queryData).filter(assignment => {
|
||||
return assignment?.submissionsConnection?.nodes[0]?.gradingPeriodId === gradingPeriod?._id
|
||||
})
|
||||
|
||||
const periodPercentage = queryData?.applyGroupWeights
|
||||
? getGradingPeriodTotalWeighted(
|
||||
[gradingPeriod],
|
||||
filterByGradingPeriod,
|
||||
queryData?.assignmentGroupsConnection?.nodes
|
||||
)
|
||||
: getGradingPeriodPercentage(gradingPeriod, filteredAssignments(queryData))
|
||||
|
||||
const weightedOrUnweighted = queryData?.applyGroupWeights
|
||||
? getGradingPeriodTotalWeighted(
|
||||
[gradingPeriod],
|
||||
filterByGradingPeriod,
|
||||
queryData?.assignmentGroupsConnection?.nodes
|
||||
)
|
||||
: getGradingPeriodPercentage(gradingPeriod, filteredAssignments(queryData))
|
||||
|
||||
return (
|
||||
<Table.Row key={gradingPeriod._id}>
|
||||
<Table.Cell textAlign="start" colSpan="3">
|
||||
<Text weight="bold">{gradingPeriod.title}</Text>
|
||||
</Table.Cell>
|
||||
{!ENV.restrict_quantitative_data && (
|
||||
<Table.Cell textAlign="start">
|
||||
<Text weight="bold">
|
||||
{Number.isNaN(periodPercentage) ? 'N/A' : `${formatNumber(periodPercentage)}%`}
|
||||
</Text>
|
||||
</Table.Cell>
|
||||
)}
|
||||
<Table.Cell textAlign="start">
|
||||
<Text weight="bold">
|
||||
{ENV.restrict_quantitative_data
|
||||
? scoreToLetterGrade(weightedOrUnweighted, queryData?.gradingStandard)
|
||||
: `${
|
||||
formatNumber(
|
||||
getGradingPeriodEarnedPoints(gradingPeriod, filteredAssignments(queryData))
|
||||
) || '-'
|
||||
}/${
|
||||
formatNumber(
|
||||
getGradingPeriodTotalPoints(gradingPeriod, filteredAssignments(queryData))
|
||||
) || '-'
|
||||
}`}
|
||||
</Text>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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 {useScope as useI18nScope} from '@canvas/i18n'
|
||||
import {Table} from '@instructure/ui-table'
|
||||
import {Text} from '@instructure/ui-text'
|
||||
|
||||
import {formatNumber, scoreToLetterGrade, getTotal, filteredAssignments} from '../utils'
|
||||
|
||||
const I18n = useI18nScope('grade_summary')
|
||||
|
||||
export const totalRow = queryData => {
|
||||
const formattedTotal = formatNumber(
|
||||
getTotal(
|
||||
filteredAssignments(queryData),
|
||||
queryData?.assignmentGroupsConnection?.nodes,
|
||||
queryData?.gradingPeriodsConnection?.nodes,
|
||||
queryData?.applyGroupWeights
|
||||
)
|
||||
)
|
||||
return (
|
||||
<Table.Row>
|
||||
<Table.Cell textAlign="start" colSpan="3">
|
||||
<Text weight="bold">{I18n.t('Total')}</Text>
|
||||
</Table.Cell>
|
||||
<Table.Cell textAlign="start">
|
||||
<Text weight="bold">
|
||||
{ENV.restrict_quantitative_data
|
||||
? scoreToLetterGrade(formattedTotal, queryData?.gradingStandard)
|
||||
: `${formattedTotal}%`}
|
||||
</Text>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 DateHelper from '@canvas/datetime/dateHelper'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {Avatar} from '@instructure/ui-avatar'
|
||||
import {Flex} from '@instructure/ui-flex'
|
||||
import {Text} from '@instructure/ui-text'
|
||||
|
||||
const SubmissionComment = ({comment}) => {
|
||||
return (
|
||||
<Flex as="div" direction="column">
|
||||
<Flex.Item padding="medium 0 0 0">
|
||||
<Flex>
|
||||
<Flex.Item>
|
||||
<Avatar name={comment?.author?.shortName} margin="0 small 0 0" />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Flex direction="column">
|
||||
<Flex.Item shouldGrow={true} shouldShrink={true}>
|
||||
<Text size="small">{comment?.author?.shortName}</Text>
|
||||
</Flex.Item>
|
||||
<Flex.Item shouldGrow={true} shouldShrink={true}>
|
||||
<Text size="small">{DateHelper.formatDatetimeForDisplay(comment?.createdAt)}</Text>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Flex.Item>
|
||||
<Flex.Item shouldGrow={true} shouldShrink={true} padding="medium 0 0 0">
|
||||
<Text>{comment.comment}</Text>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
SubmissionComment.propTypes = {
|
||||
comment: PropTypes.shape({
|
||||
author: PropTypes.shape({
|
||||
shortName: PropTypes.string,
|
||||
}),
|
||||
createdAt: PropTypes.string,
|
||||
comment: PropTypes.string,
|
||||
}),
|
||||
}
|
||||
|
||||
export default SubmissionComment
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2021 - 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 SubmissionComment from './SubmissionComment'
|
||||
import React from 'react'
|
||||
|
||||
export default {
|
||||
title: 'Examples/Student Grade Summary/SubmissionComment',
|
||||
component: SubmissionComment,
|
||||
}
|
||||
|
||||
const defaultComment = {
|
||||
comment:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor nunc non arcu placerat, at mollis massa suscipit. Nullam tincidunt bibendum turpis vitae consectetur. Proin posuere placerat elit, id mollis erat blandit porta. Aliquam laoreet dui sit amet ultricies pharetra. Aliquam euismod, ex at faucibus viverra, mauris velit ullamcorper massa, ut ultricies orci orci eu lorem. Pellentesque quis lectus nisl. Suspendisse sem dolor, facilisis eu velit et, varius tempus massa. Sed luctus imperdiet metus at tempor. Suspendisse tincidunt neque eu velit luctus gravida. Suspendisse sed aliquet nisi. Curabitur sagittis consequat euismod. Cras aliquam nulla vel dolor semper placerat. Nunc in dolor enim.',
|
||||
createdAt: '2022-04-19T10:32:29-06:00',
|
||||
author: {
|
||||
name: 'Ron Weasley',
|
||||
shortName: 'Ron Weasley',
|
||||
__typename: 'User',
|
||||
},
|
||||
__typename: 'SubmissionComment',
|
||||
}
|
||||
|
||||
const Template = args => <SubmissionComment {...args} />
|
||||
|
||||
export const Default = Template.bind({})
|
||||
Default.args = {
|
||||
comment: defaultComment,
|
||||
key: '1',
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 {render} from '@testing-library/react'
|
||||
|
||||
import AssignmentTable from '../AssignmentTable'
|
||||
|
||||
import {Assignment} from '../../../graphql/Assignment'
|
||||
import {AssignmentGroup} from '../../../graphql/AssignmentGroup'
|
||||
import {GradingStandard} from '../../../graphql/GradingStandard'
|
||||
|
||||
const defaultProps = {
|
||||
queryData: {
|
||||
name: 'Course Name',
|
||||
_id: '1',
|
||||
assignmentsConnection: {nodes: [Assignment.mock()]},
|
||||
assignmentsGroupsConnection: {nodes: [AssignmentGroup.mock()]},
|
||||
gradingStandard: GradingStandard.mock(),
|
||||
},
|
||||
layout: 'fixed',
|
||||
setShowTray: () => {},
|
||||
setSelectedSubmission: () => {},
|
||||
}
|
||||
|
||||
describe('AssignmentTable', () => {
|
||||
it('renders', () => {
|
||||
const {getByText} = render(<AssignmentTable {...defaultProps} />)
|
||||
expect(getByText(Assignment.mock().name)).toBeInTheDocument()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 {render} from '@testing-library/react'
|
||||
|
||||
import SubmissionComment from '../SubmissionComment'
|
||||
|
||||
import {Submission} from '../../../graphql/Submission'
|
||||
|
||||
const defaultProps = {
|
||||
comment: Submission.mock().commentsConnection.nodes[0],
|
||||
}
|
||||
|
||||
describe('SubmissionComment', () => {
|
||||
it('renders', () => {
|
||||
const {getByText} = render(<SubmissionComment {...defaultProps} />)
|
||||
expect(
|
||||
getByText(Submission.mock().commentsConnection.nodes[0]?.author?.shortName)
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* 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 {IconCheckLine, IconXLine} from '@instructure/ui-icons'
|
||||
import {Pill} from '@instructure/ui-pill'
|
||||
import {useScope as useI18nScope} from '@canvas/i18n'
|
||||
|
||||
const I18n = useI18nScope('grade_summary')
|
||||
|
||||
export const getGradingPeriodID = () => {
|
||||
return window?.location?.search
|
||||
?.split('?')[1]
|
||||
?.split('&')
|
||||
?.filter(param => param.includes('grading_period_id'))[0]
|
||||
?.split('=')[1]
|
||||
}
|
||||
|
||||
export const filteredAssignments = data => {
|
||||
return (
|
||||
data?.assignmentsConnection?.nodes.filter(assignment => {
|
||||
return !assignment?.submissionsConnection?.nodes[0]?.hideGradeFromStudent
|
||||
}) || []
|
||||
)
|
||||
}
|
||||
|
||||
export const getAssignmentGroupScore = assignmentGroup => {
|
||||
if (assignmentGroup?.gradesConnection.nodes[0].overrideScore)
|
||||
return `${assignmentGroup?.gradesConnection.nodes[0].overrideScore}%`
|
||||
else if (assignmentGroup?.gradesConnection.nodes[0].currentScore)
|
||||
return `${assignmentGroup?.gradesConnection.nodes[0].currentScore}%`
|
||||
else return I18n.t('N/A')
|
||||
}
|
||||
|
||||
export const formatNumber = number => {
|
||||
return number?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})
|
||||
}
|
||||
|
||||
export const submissionCommentsPresent = assignment => {
|
||||
return (
|
||||
assignment?.submissionsConnection.nodes.filter(submission => {
|
||||
return submission?.commentsConnection?.nodes?.length > 0
|
||||
}).length > 0
|
||||
)
|
||||
}
|
||||
|
||||
export const getDisplayStatus = assignment => {
|
||||
if (assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'excused') {
|
||||
return <Pill>{I18n.t('Excused')}</Pill>
|
||||
} else if (assignment?.gradingType === 'not_graded') {
|
||||
return <Pill>{I18n.t('Not Graded')}</Pill>
|
||||
} else if (assignment?.submissionsConnection?.nodes.length > 0 === 'missing') {
|
||||
return getNoSubmissionStatus(assignment?.dueDate)
|
||||
} else if (assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'late') {
|
||||
return <Pill color="warning">{I18n.t('Late')}</Pill>
|
||||
} else if (assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'graded') {
|
||||
return <Pill color="success">{I18n.t('Graded')}</Pill>
|
||||
} else {
|
||||
return <Pill>{I18n.t('Not Graded')}</Pill>
|
||||
}
|
||||
}
|
||||
|
||||
export const getNoSubmissionStatus = dueDate => {
|
||||
const assignmentDueDate = new Date(dueDate)
|
||||
const currentDate = new Date()
|
||||
if (assignmentDueDate < currentDate) {
|
||||
return <Pill color="danger">{I18n.t('Missing')}</Pill>
|
||||
} else {
|
||||
return <Pill>{I18n.t('Not Submitted')}</Pill>
|
||||
}
|
||||
}
|
||||
|
||||
export const getDisplayScore = (assignment, gradingStandard) => {
|
||||
if (
|
||||
assignment?.submissionsConnection?.nodes[assignment?.submissionsConnection?.nodes.length - 1]
|
||||
?.gradingStatus === 'excused'
|
||||
) {
|
||||
return '-'
|
||||
} else if (
|
||||
ENV.restrict_quantitative_data &&
|
||||
(assignment?.gradingType === 'gpa_scale' ||
|
||||
assignment?.gradingType === 'percent' ||
|
||||
assignment?.gradingType === 'points')
|
||||
) {
|
||||
return getAssignmentLetterGrade(assignment, gradingStandard)
|
||||
} else if (
|
||||
assignment?.gradingType === 'letter_grade' ||
|
||||
assignment?.gradingType === 'gpa_scale'
|
||||
) {
|
||||
return getAssignmentLetterGrade(assignment, gradingStandard)
|
||||
} else if (assignment?.gradingType === 'percentage') {
|
||||
return `${getAssignmentPercentage(assignment)}%`
|
||||
} else if (assignment?.gradingType === 'pass_fail') {
|
||||
return assignment?.submissionsConnection?.nodes[0]?.score ? <IconCheckLine /> : <IconXLine />
|
||||
} else {
|
||||
const earned = getAssignmentEarnedPoints(assignment)
|
||||
const total = getAssignmentTotalPoints(assignment)
|
||||
return `${earned || '-'}/${total || '-'}`
|
||||
}
|
||||
}
|
||||
|
||||
export const scoreToLetterGrade = (score, gradingStandard) => {
|
||||
let letter = null
|
||||
gradingStandard?.data?.forEach(gradeLevel => {
|
||||
if (score / 100 >= gradeLevel.baseValue && !letter) {
|
||||
letter = gradeLevel.letterGrade
|
||||
}
|
||||
})
|
||||
return letter
|
||||
}
|
||||
|
||||
// **************** ASSIGNMENTS ***************************************************
|
||||
|
||||
export const getAssignmentTotalPoints = assignment => {
|
||||
return assignment?.pointsPossible || 0
|
||||
}
|
||||
|
||||
export const getAssignmentEarnedPoints = assignment => {
|
||||
return parseFloat(assignment?.submissionsConnection?.nodes[0]?.score) || 0
|
||||
}
|
||||
|
||||
export const getAssignmentPercentage = assignment => {
|
||||
if (!getAssignmentTotalPoints(assignment)) return 0
|
||||
return (getAssignmentEarnedPoints(assignment) / getAssignmentTotalPoints(assignment) || 1) * 100
|
||||
}
|
||||
|
||||
export const getAssignmentLetterGrade = (assignment, gradingStandard) => {
|
||||
return scoreToLetterGrade(getAssignmentPercentage(assignment), gradingStandard)
|
||||
}
|
||||
|
||||
// **************** ASSIGNMENT GROUPS **********************************************
|
||||
|
||||
export const getAssignmentGroupTotalPoints = (assignmentGroup, assignments) => {
|
||||
return assignments.reduce((total, assignment) => {
|
||||
if (
|
||||
!(
|
||||
assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'excused' ||
|
||||
assignment?.assignmentGroup?._id !== assignmentGroup?._id
|
||||
) &&
|
||||
assignment?.submissionsConnection?.nodes.length > 0
|
||||
) {
|
||||
total += getAssignmentTotalPoints(assignment)
|
||||
}
|
||||
return total
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export const getAssignmentGroupEarnedPoints = (assignmentGroup, assignments) => {
|
||||
return assignments.reduce((total, assignment) => {
|
||||
if (
|
||||
!(
|
||||
assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'excused' ||
|
||||
assignment?.assignmentGroup?._id !== assignmentGroup?._id
|
||||
) &&
|
||||
assignment?.submissionsConnection?.nodes.length > 0
|
||||
) {
|
||||
total += getAssignmentEarnedPoints(assignment)
|
||||
}
|
||||
return total
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export const getAssignmentGroupPercentage = (assignmentGroup, assignments, applyGroupWeights) => {
|
||||
if (applyGroupWeights) {
|
||||
if (!getAssignmentGroupTotalPoints(assignmentGroup, assignments)) return 0
|
||||
return (
|
||||
(getAssignmentGroupEarnedPoints(assignmentGroup, assignments) /
|
||||
getAssignmentGroupTotalPoints(assignmentGroup, assignments)) *
|
||||
assignmentGroup?.groupWeight
|
||||
)
|
||||
}
|
||||
return (
|
||||
(getAssignmentGroupEarnedPoints(assignmentGroup, assignments) /
|
||||
getAssignmentGroupTotalPoints(assignmentGroup, assignments)) *
|
||||
100
|
||||
)
|
||||
}
|
||||
|
||||
export const getAssignmentGroupLetterGrade = (assignmentGroup, assignments, gradingStandard) => {
|
||||
return scoreToLetterGrade(
|
||||
getAssignmentGroupPercentage(assignmentGroup, assignments),
|
||||
gradingStandard
|
||||
)
|
||||
}
|
||||
|
||||
export const getAssignmentGroupWeighted = (assignmentGroups, assignments) => {
|
||||
return assignmentGroups.reduce((total, assignmentGroup) => {
|
||||
if (!getAssignmentGroupTotalPoints(assignmentGroup, assignments)) return total
|
||||
return (
|
||||
total +
|
||||
(getAssignmentGroupEarnedPoints(assignmentGroup, assignments) /
|
||||
getAssignmentGroupTotalPoints(assignmentGroup, assignments)) *
|
||||
assignmentGroup?.groupWeight
|
||||
)
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// **************** GRADING PERIODS ***********************************************
|
||||
|
||||
export const getGradingPeriodTotalPoints = (gradingPeriod, assignments) => {
|
||||
return assignments.reduce((total, assignment) => {
|
||||
if (
|
||||
assignment?.submissionsConnection?.nodes[0]?.gradingPeriodId === gradingPeriod?._id &&
|
||||
!(assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'excused')
|
||||
) {
|
||||
total += getAssignmentTotalPoints(assignment) || 0
|
||||
}
|
||||
return total
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export const getGradingPeriodEarnedPoints = (gradingPeriod, assignments) => {
|
||||
return assignments.reduce((total, assignment) => {
|
||||
if (
|
||||
assignment?.submissionsConnection?.nodes[0]?.gradingPeriodId === gradingPeriod?._id &&
|
||||
!(assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'excused')
|
||||
) {
|
||||
total += getAssignmentEarnedPoints(assignment) || 0
|
||||
}
|
||||
return total
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export const getGradingPeriodPercentage = (gradingPeriod, assignments) => {
|
||||
return (
|
||||
(getGradingPeriodEarnedPoints(gradingPeriod, assignments) /
|
||||
getGradingPeriodTotalPoints(gradingPeriod, assignments)) *
|
||||
100
|
||||
)
|
||||
}
|
||||
|
||||
export const getGradingPeriodLetterGrade = (gradingPeriod, assignments, gradingStandard) => {
|
||||
return scoreToLetterGrade(getGradingPeriodPercentage(gradingPeriod, assignments), gradingStandard)
|
||||
}
|
||||
|
||||
export const getGradingPeriodTotalWeighted = (gradingPeriods, assignments, assignmentGroups) => {
|
||||
return gradingPeriods.reduce((total, _gradingPeriod) => {
|
||||
return total + getAssignmentGroupWeighted(assignmentGroups, assignments)
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// **************** COURSES *******************************************************
|
||||
|
||||
export const getCourseTotalPoints = assignments => {
|
||||
return assignments.reduce((total, assignment) => {
|
||||
if (
|
||||
!(assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'excused') &&
|
||||
assignment?.submissionsConnection?.nodes.length > 0
|
||||
) {
|
||||
total += getAssignmentTotalPoints(assignment)
|
||||
}
|
||||
return total
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export const getCourseEarnedPoints = assignments => {
|
||||
return assignments.reduce((total, assignment) => {
|
||||
if (
|
||||
!(assignment?.submissionsConnection?.nodes[0]?.gradingStatus === 'excused') &&
|
||||
assignment?.submissionsConnection?.nodes.length > 0
|
||||
) {
|
||||
total += getAssignmentEarnedPoints(assignment)
|
||||
}
|
||||
return total
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export const getCoursePercentage = assignments => {
|
||||
return (getCourseEarnedPoints(assignments) / getCourseTotalPoints(assignments)) * 100
|
||||
}
|
||||
|
||||
export const getCourseLetterGrade = (course, assignments, gradingStandard) => {
|
||||
return scoreToLetterGrade(getCoursePercentage(course, assignments), gradingStandard)
|
||||
}
|
||||
|
||||
// **************** TOTAL *********************************************************
|
||||
|
||||
export const getTotal = (assignments, assignmentGroups, gradingPeriods, applyWeights) => {
|
||||
let returnTotal = 0
|
||||
if (getGradingPeriodID() === '0' && applyWeights) {
|
||||
returnTotal = gradingPeriods.reduce((total, period) => {
|
||||
return (
|
||||
total +
|
||||
getGradingPeriodTotalWeighted(
|
||||
[period],
|
||||
assignments.filter(assignment => {
|
||||
return assignment?.submissionsConnection?.nodes[0]?.gradingPeriodId === period?._id
|
||||
}),
|
||||
assignmentGroups
|
||||
) *
|
||||
(period?.weight / 100)
|
||||
)
|
||||
}, 0)
|
||||
} else if (getGradingPeriodID() === '0') {
|
||||
returnTotal = gradingPeriods.reduce((total, gradingPeriod) => {
|
||||
if (!getGradingPeriodTotalPoints(gradingPeriod, assignments)) return total
|
||||
return (
|
||||
total +
|
||||
(getGradingPeriodEarnedPoints(gradingPeriod, assignments) /
|
||||
getGradingPeriodTotalPoints(gradingPeriod, assignments)) *
|
||||
gradingPeriod?.weight
|
||||
)
|
||||
}, 0)
|
||||
} else if (applyWeights) {
|
||||
returnTotal = getAssignmentGroupWeighted(assignmentGroups, assignments)
|
||||
} else {
|
||||
returnTotal = getCoursePercentage(assignments)
|
||||
}
|
||||
return returnTotal
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
Loading…
Reference in New Issue