storybook component for inline grading

fixes VICE-2221
flag=none

textinput rules? responsive?

test plan:
- yarn storybook
- visit the InlineGrade stories for
needs grading, loading, and graded

Change-Id: Id70a396f2c5597e2747b1049afb474edd596637c
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/277454
Reviewed-by: Drake Harper <drake.harper@instructure.com>
QA-Review: Drake Harper <drake.harper@instructure.com>
Product-Review: Drake Harper <drake.harper@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
This commit is contained in:
Caleb Guanzon 2021-11-01 15:24:47 -06:00
parent 81f653edd8
commit a3d1a17758
3 changed files with 200 additions and 0 deletions

View File

@ -0,0 +1,82 @@
/*
* 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 React from 'react'
import PropTypes from 'prop-types'
import I18n from 'i18n!discussion_posts'
import {Flex} from '@instructure/ui-flex'
import {Text} from '@instructure/ui-text'
import {TextInput} from '@instructure/ui-text-input'
import {IconGradebookLine, IconNotGradedLine} from '@instructure/ui-icons'
import {ScreenReaderContent} from '@instructure/ui-a11y-content'
import {Spinner} from '@instructure/ui-spinner'
export const InlineGrade = props => {
const gradeStatusIcon = () => {
if (props.isLoading) {
return (
<Flex.Item data-testid="inline-grade-loading-status">
<Spinner renderTitle="Loading" size="x-small" />
</Flex.Item>
)
} else if (props.isGraded) {
return (
<Flex.Item margin="none xx-small none" data-testid="inline-grade-graded-status">
<IconGradebookLine color="success" />
</Flex.Item>
)
}
return (
<Flex.Item margin="none xx-small none" data-testid="inline-grade-ungraded-status">
<IconNotGradedLine color="error" />
</Flex.Item>
)
}
return (
<Flex>
{gradeStatusIcon()}
<Flex.Item margin="none xx-small none">
<Text>{I18n.t('Grade')}</Text>
</Flex.Item>
<Flex.Item margin="none xx-small none">
<TextInput
defaultValue={props.currentGrade}
renderLabel={<ScreenReaderContent>{I18n.t('Enter the grade')}</ScreenReaderContent>}
display="inline-block"
width="3rem"
size="small"
onChange={event => {
props.onGradeChange(event.target.value)
}}
/>
</Flex.Item>
<Flex.Item margin="none xx-small none">
<Text>/{props.pointsPossible}</Text>
</Flex.Item>
</Flex>
)
}
InlineGrade.prototypes = {
isGraded: PropTypes.bool,
isLoading: PropTypes.bool,
onGradeChange: PropTypes.func,
pointsPossible: PropTypes.string.isRequired,
currentGrade: PropTypes.string
}

View File

@ -0,0 +1,49 @@
/*
* 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 React from 'react'
import {InlineGrade} from './InlineGrade'
export default {
title: 'Examples/Discussion Posts/Components/InlineGrade',
component: InlineGrade,
argTypes: {onGradeChange: {action: 'Grade Change'}}
}
const Template = args => <InlineGrade {...args} />
export const NeedsGrading = Template.bind({})
NeedsGrading.args = {
isGraded: false,
pointsPossible: '100'
}
export const Loading = Template.bind({})
Loading.args = {
currentGrade: '90',
isLoading: true,
isGraded: false,
pointsPossible: '100'
}
export const Graded = Template.bind({})
Graded.args = {
currentGrade: '90',
isGraded: true,
pointsPossible: '100'
}

View File

@ -0,0 +1,69 @@
/*
* 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 {render} from '@testing-library/react'
import React from 'react'
import {InlineGrade} from '../InlineGrade'
jest.mock('../../../utils', () => ({
...jest.requireActual('../../../utils'),
responsiveQuerySizes: () => ({desktop: {maxWidth: '1024px'}})
}))
const setup = props => {
return render(<InlineGrade {...props} />)
}
const defaultProps = ({
isGraded = false,
isLoading = false,
currentGrade = '',
pointsPossible = '100'
} = {}) => ({
isGraded,
isLoading,
currentGrade,
pointsPossible
})
describe('DiscussionTopicAlertManager', () => {
it('should render ungraded icon', async () => {
const container = setup(defaultProps())
expect(await container.findByTestId('inline-grade-ungraded-status')).toBeTruthy()
})
it('should render loading icon', async () => {
const container = setup(defaultProps({isLoading: true}))
expect(await container.findByTestId('inline-grade-loading-status')).toBeTruthy()
})
it('should render graded icon', async () => {
const container = setup(defaultProps({isGraded: true}))
expect(await container.findByTestId('inline-grade-graded-status')).toBeTruthy()
})
it('should set current grade', () => {
const container = setup(defaultProps({currentGrade: '80'}))
expect(container.container.querySelector('input').value).toEqual('80')
})
it('should set points possible', () => {
const container = setup(defaultProps())
expect(container.getByText('/100')).toBeTruthy()
})
})