instUI5 upgrade: meaningful gradezilla/grading stuff

refs: CORE-1437
closes: CORE-1489

the commit to upgrade gradezilla/grading stuff to instUI 5 has been
split in 2. The other, that this is based on takes care of the trivial
stuff: components whose API has not changed, who just need to have their
import paths  renamed to the new location in the split-up instUI
packages.

This one takes care of the stuff that actually has meaningful changes
like <NumberInput> and <Select>. it will need more scrutiny, but
since the changes are isolated to just a couple components it won’t
be as scary.

Test plan:
* verify these components still work as they used to and tests pass
* look at the things that @solsen found in his Code Review and make sure
  they work

Change-Id: I72996ead775793237fc9a527f3da366f8ad6a6e3
Reviewed-on: https://gerrit.instructure.com/151772
Tested-by: Jenkins
Reviewed-by: Spencer Olson <solson@instructure.com>
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
QA-Review: Rohan Cheeniyil <rcheeniyil@instructure.com>
Product-Review: Pert Eilers <peilers@instructure.com>
This commit is contained in:
Ryan Shaw 2018-06-04 12:14:02 -06:00
parent 3e0849ecd2
commit 32e889e07e
5 changed files with 46 additions and 59 deletions

View File

@ -21,7 +21,7 @@ import { bool, func, number, shape, string } from 'prop-types';
import Alert from '@instructure/ui-alerts/lib/components/Alert';
import View from '@instructure/ui-layout/lib/components/View';
import FormFieldGroup from '@instructure/ui-forms/lib/components/FormFieldGroup';
import NumberInput from '@instructure/ui-core/lib/components/NumberInput';
import NumberInput from '@instructure/ui-forms/lib/components/NumberInput';
import PresentationContent from '@instructure/ui-a11y/lib/components/PresentationContent';
import Spinner from '@instructure/ui-elements/lib/components/Spinner';
import Text from '@instructure/ui-elements/lib/components/Text';
@ -50,21 +50,22 @@ function validationError (input) {
return null;
}
const errorMessages = {
missingSubmissionDeduction: {
notNumeric: I18n.t('Missing submission grade must be numeric'),
outOfRange: I18n.t('Missing submission grade must be between 0 and 100')
},
lateSubmissionDeduction: {
notNumeric: I18n.t('Late submission deduction must be numeric'),
outOfRange: I18n.t('Late submission deduction must be between 0 and 100')
},
lateSubmissionMinimumPercent: {
notNumeric: I18n.t('Lowest possible grade must be numeric'),
outOfRange: I18n.t('Lowest possible grade must be between 0 and 100')
}
};
function validationErrorMessage (input, validationType) {
const errorMessages = {
missingSubmissionDeduction: {
notNumeric: I18n.t('Missing submission grade must be numeric'),
outOfRange: I18n.t('Missing submission grade must be between 0 and 100')
},
lateSubmissionDeduction: {
notNumeric: I18n.t('Late submission deduction must be numeric'),
outOfRange: I18n.t('Late submission deduction must be between 0 and 100')
},
lateSubmissionMinimumPercent: {
notNumeric: I18n.t('Lowest possible grade must be numeric'),
outOfRange: I18n.t('Lowest possible grade must be between 0 and 100')
}
};
const error = validationError(input);
return errorMessages[validationType][error];
}
@ -111,15 +112,10 @@ class LatePoliciesTabPanel extends React.Component {
showAlert: bool.isRequired
};
constructor (props) {
super(props);
this.state = { showAlert: props.showAlert };
this.changeMissingSubmissionDeduction = this.validateAndChangeNumber.bind(this, 'missingSubmissionDeduction');
this.changeLateSubmissionDeduction = this.validateAndChangeNumber.bind(this, 'lateSubmissionDeduction');
this.changeLateSubmissionMinimumPercent = this.validateAndChangeNumber.bind(this, 'lateSubmissionMinimumPercent');
this.missingPolicyMessages = messages.bind(this, ['missingSubmissionDeduction'])
this.latePolicyMessages = messages.bind(this, ['lateSubmissionDeduction', 'lateSubmissionMinimumPercent'])
}
state = { showAlert: this.props.showAlert };
missingPolicyMessages = messages.bind(this, ['missingSubmissionDeduction'])
latePolicyMessages = messages.bind(this, ['lateSubmissionDeduction', 'lateSubmissionMinimumPercent'])
componentDidUpdate(_prevProps, prevState) {
if (!prevState.showAlert || this.state.showAlert) {
@ -158,8 +154,7 @@ class LatePoliciesTabPanel extends React.Component {
this.props.changeLatePolicy({ ...this.props.latePolicy, changes: this.calculateChanges(updates) });
}
validateAndChangeNumber = (name) => {
const inputValue = this[`${name}Input`].value;
validateAndChangeNumber = (name, inputValue) => {
const errorMessage = validationErrorMessage(inputValue, name);
if (errorMessage) {
const validationErrors = { ...this.props.latePolicy.validationErrors, [name]: errorMessage };
@ -192,7 +187,7 @@ class LatePoliciesTabPanel extends React.Component {
this.props.changeLatePolicy({ ...this.props.latePolicy, changes });
}
calculateChanges = (newData) => {
calculateChanges(newData) {
const changes = { ...this.props.latePolicy.changes };
Object.keys(newData).forEach((key) => {
const initialValue = this.props.latePolicy.data[key];
@ -257,7 +252,7 @@ class LatePoliciesTabPanel extends React.Component {
label={<ScreenReaderContent>{I18n.t('Missing submission grade percent')}</ScreenReaderContent>}
disabled={!this.getLatePolicyAttribute('missingSubmissionDeductionEnabled')}
defaultValue={markMissingSubmissionsDefaultValue(data.missingSubmissionDeduction)}
onChange={this.changeMissingSubmissionDeduction}
onChange={(_e, val) => this.validateAndChangeNumber('missingSubmissionDeduction', val)}
min="0"
max="100"
inline
@ -301,7 +296,7 @@ class LatePoliciesTabPanel extends React.Component {
>
<View as="div" margin="small small small large">
<div style={{ marginLeft: '0.25rem' }}>
<View display="inline" as="div" margin="0 small 0 0">
<View display="inline-block" as="div" margin="0 small 0 0">
<PresentationContent>
<View as="div" margin="0 0 x-small 0">
<label htmlFor="late-submission-deduction">
@ -318,7 +313,7 @@ class LatePoliciesTabPanel extends React.Component {
label={<ScreenReaderContent>{I18n.t('Late submission deduction percent')}</ScreenReaderContent>}
defaultValue={data.lateSubmissionDeduction.toString()}
disabled={!this.getLatePolicyAttribute('lateSubmissionDeductionEnabled')}
onChange={this.changeLateSubmissionDeduction}
onChange={(_e, val) => this.validateAndChangeNumber('lateSubmissionDeduction', val)}
min="0"
max="100"
inline
@ -332,7 +327,7 @@ class LatePoliciesTabPanel extends React.Component {
</div>
</View>
<View display="inline" as="div" margin="0 0 0 small">
<View display="inline-block" as="div" margin="0 0 0 small">
<PresentationContent>
<View as="div" margin="0 0 x-small 0">
<label htmlFor="late-submission-interval">
@ -375,7 +370,7 @@ class LatePoliciesTabPanel extends React.Component {
label={<ScreenReaderContent>{I18n.t('Lowest possible grade percent')}</ScreenReaderContent>}
defaultValue={data.lateSubmissionMinimumPercent.toString()}
disabled={!this.getLatePolicyAttribute('lateSubmissionDeductionEnabled')}
onChange={this.changeLateSubmissionMinimumPercent}
onChange={(_e, val) => this.validateAndChangeNumber('lateSubmissionMinimumPercent', val)}
min="0"
max="100"
inline

View File

@ -20,7 +20,7 @@ import React from 'react';
import { func, string, bool } from 'prop-types';
import I18n from 'i18n!gradebook';
import Button from '@instructure/ui-buttons/lib/components/Button';
import Popover, { PopoverTrigger, PopoverContent } from '@instructure/ui-core/lib/components/Popover';
import Popover, { PopoverTrigger, PopoverContent } from '@instructure/ui-overlays/lib/components/Popover';
import Text from '@instructure/ui-elements/lib/components/Text';
import IconDiscussionReplySolid from '@instructure/ui-icons/lib/Solid/IconDiscussionReply';
import ScreenReaderContent from '@instructure/ui-a11y/lib/components/ScreenReaderContent';
@ -98,7 +98,6 @@ class StatusColorListItem extends React.Component {
show={isColorPickerShown}
onToggle={colorPickerOnToggle}
contentRef={colorPickerContentRef}
applicationElement={() => document.getElementById('application')}
>
<PopoverTrigger>

View File

@ -20,10 +20,10 @@ import React from 'react';
import { func, number, shape, string, bool } from 'prop-types';
import I18n from 'i18n!gradebook';
import View from '@instructure/ui-layout/lib/components/View';
import NumberInput from '@instructure/ui-core/lib/components/NumberInput';
import NumberInput from '@instructure/ui-forms/lib/components/NumberInput';
import PresentationContent from '@instructure/ui-a11y/lib/components/PresentationContent';
import Text from '@instructure/ui-elements/lib/components/Text';
import RadioInput from '@instructure/ui-core/lib/components/RadioInput';
import RadioInput from '@instructure/ui-forms/lib/components/RadioInput';
import ScreenReaderContent from '@instructure/ui-a11y/lib/components/ScreenReaderContent';
import classnames from 'classnames';
import round from 'coffeescripts/util/round';

View File

@ -263,10 +263,12 @@ test('calls the changeLatePolicy function with a validationError if the missing
});
test('does not allow entering negative numbers for missing submission deduction', function () {
this.wrapper = mountComponent();
const changeLatePolicy = this.stub();
this.wrapper = mountComponent({}, { changeLatePolicy });
const input = missingDeductionInput(this.wrapper);
input.simulate('change', { target: { value: '-0.1' } });
strictEqual(input.node.value, '0.1');
deepEqual(changeLatePolicy.getCall(0).args[0].changes, {});
strictEqual(input.node.value, '100');
});
test('calls the changeLatePolicy function with a validationError if the missing submission ' +
@ -412,7 +414,7 @@ test('does not allow entering negative numbers for late submission deduction', f
this.wrapper = mountComponent();
const input = lateDeductionInput(this.wrapper);
input.simulate('change', { target: { value: '-0.1' } });
strictEqual(input.node.value, '0.1')
strictEqual(input.node.value, '0')
});
test('calls the changeLatePolicy function with a validationError if the late submission ' +
@ -577,7 +579,7 @@ test('does not allow entering negative numbers for late submission minimum perce
this.wrapper = mountComponent();
const input = lateSubmissionMinimumPercentInput(this.wrapper);
input.simulate('change', { target: { value: '-0.1' } });
strictEqual(input.node.value, '0.1');
strictEqual(input.node.value, '0');
});
test('calls the changeLatePolicy function with a validationError if the late submission ' +

View File

@ -19,7 +19,7 @@
import React from 'react'
import { mount } from 'enzyme'
import SubmissionTrayRadioInput from 'jsx/gradezilla/default_gradebook/components/SubmissionTrayRadioInput'
import NumberInput from '@instructure/ui-core/lib/components/NumberInput'
import NumberInput from '@instructure/ui-forms/lib/components/NumberInput'
let wrapper
let updateSubmission
@ -203,48 +203,42 @@ QUnit.module('SubmissionTrayRadioInput', function (hooks) {
test('does not call updateSubmission if the input value is an empty string', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: '' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '' } })
strictEqual(updateSubmission.callCount, 0)
})
test('does not call updateSubmission if the input value cannot be parsed as a number', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: 'foo' } })
input.simulate('blur')
input.simulate('blur', { target: { value: 'foo' } })
strictEqual(updateSubmission.callCount, 0)
})
test('does not call updateSubmission if the input value matches the current value', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: '0' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '0' } })
strictEqual(updateSubmission.callCount, 0)
})
test('does not call updateSubmission if the parsed value (2 decimals) matches the current value', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: '0.004' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '0.004' } })
strictEqual(updateSubmission.callCount, 0)
})
test('calls updateSubmission if the parsed value (2 decimals) differs from the current value', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: '2' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '2' } })
strictEqual(updateSubmission.callCount, 1)
})
test('calls updateSubmission with latePolicyStatus set to "late"', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: '2' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '2' } })
strictEqual(updateSubmission.getCall(0).args[0].latePolicyStatus, 'late')
})
@ -256,8 +250,7 @@ QUnit.module('SubmissionTrayRadioInput', function (hooks) {
})
const input = numberInput()
input.simulate('change', { target: { value: '2' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '2' } })
const expectedSeconds = 2 * 3600
strictEqual(updateSubmission.getCall(0).args[0].secondsLateOverride, expectedSeconds)
})
@ -265,8 +258,7 @@ QUnit.module('SubmissionTrayRadioInput', function (hooks) {
test('interval is day: calls updateSubmission with the input converted to seconds', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: '2' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '2' } })
const expectedSeconds = 2 * 86400
strictEqual(updateSubmission.getCall(0).args[0].secondsLateOverride, expectedSeconds)
})
@ -274,8 +266,7 @@ QUnit.module('SubmissionTrayRadioInput', function (hooks) {
test('truncates the remainder if one exists', function () {
wrapper = mountComponent({ value: 'late', checked: true, updateSubmission })
const input = numberInput()
input.simulate('change', { target: { value: '2.3737' } })
input.simulate('blur')
input.simulate('blur', { target: { value: '2.3737' } })
const expectedSeconds = Math.trunc(2.3737 * 86400)
strictEqual(updateSubmission.getCall(0).args[0].secondsLateOverride, expectedSeconds)
})