Compare commits

...

3 Commits

Author SHA1 Message Date
Leangseu Kim
bd799902f7 chore: rebase with nutmeg master 2023-02-06 09:23:13 -05:00
Ihor Romaniuk
75eeb45c8b fix: fix loss of field focus after each character for search field (#262)
* fix: fix loss of field focus after each character for search field

* fix: update package-lock file
2022-12-05 11:56:38 -05:00
Ihor Romaniuk
2536b93cbb fix: add an asterisk to the 'Email' name of column (#272)
* fix: add an asterisk to the 'Email' name of column

* fix: update package log
2022-11-23 10:48:30 -05:00
14 changed files with 134 additions and 43 deletions

51
package-lock.json generated
View File

@@ -18833,6 +18833,12 @@
"decamelize": "^1.2.0"
}
},
"node_modules/jquery": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.1.tgz",
"integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==",
"peer": true
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -22801,7 +22807,6 @@
},
"node_modules/npm/node_modules/lodash._baseindexof": {
"version": "3.1.0",
"dev": true,
"inBundle": true,
"license": "MIT"
},
@@ -22817,19 +22822,16 @@
},
"node_modules/npm/node_modules/lodash._bindcallback": {
"version": "3.0.1",
"dev": true,
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/lodash._cacheindexof": {
"version": "3.0.2",
"dev": true,
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/lodash._createcache": {
"version": "3.1.2",
"dev": true,
"inBundle": true,
"license": "MIT",
"dependencies": {
@@ -22844,7 +22846,6 @@
},
"node_modules/npm/node_modules/lodash._getnative": {
"version": "3.9.1",
"dev": true,
"inBundle": true,
"license": "MIT"
},
@@ -22862,7 +22863,6 @@
},
"node_modules/npm/node_modules/lodash.restparam": {
"version": "3.6.1",
"dev": true,
"inBundle": true,
"license": "MIT"
},
@@ -26181,6 +26181,17 @@
"node": ">= 8"
}
},
"node_modules/popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
@@ -48044,6 +48055,12 @@
"supports-color": "^7.0.0"
}
},
"jquery": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.1.tgz",
"integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==",
"peer": true
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -51063,8 +51080,7 @@
},
"lodash._baseindexof": {
"version": "3.1.0",
"bundled": true,
"dev": true
"bundled": true
},
"lodash._baseuniq": {
"version": "4.6.0",
@@ -51077,18 +51093,15 @@
},
"lodash._bindcallback": {
"version": "3.0.1",
"bundled": true,
"dev": true
"bundled": true
},
"lodash._cacheindexof": {
"version": "3.0.2",
"bundled": true,
"dev": true
"bundled": true
},
"lodash._createcache": {
"version": "3.1.2",
"bundled": true,
"dev": true,
"requires": {
"lodash._getnative": "^3.0.0"
}
@@ -51100,8 +51113,7 @@
},
"lodash._getnative": {
"version": "3.9.1",
"bundled": true,
"dev": true
"bundled": true
},
"lodash._root": {
"version": "3.0.1",
@@ -51115,8 +51127,7 @@
},
"lodash.restparam": {
"version": "3.6.1",
"bundled": true,
"dev": true
"bundled": true
},
"lodash.union": {
"version": "4.6.0",
@@ -53674,6 +53685,12 @@
}
}
},
"popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
"peer": true
},
"portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",

View File

@@ -20,15 +20,28 @@ export class AdjustedGradeInput extends React.Component {
}
onChange = ({ target }) => {
this.props.setModalState({ adjustedGradeValue: target.value });
let adjustedGradeValue;
switch (true) {
case target.value < 0:
adjustedGradeValue = 0;
break;
case this.props.possibleGrade && target.value > this.props.possibleGrade:
adjustedGradeValue = this.props.possibleGrade;
break;
default:
adjustedGradeValue = target.value;
}
this.props.setModalState({ adjustedGradeValue });
};
render() {
return (
<span>
<Form.Control
type="text"
type="number"
name="adjustedGradeValue"
min="0"
max={this.props.possibleGrade ? this.props.possibleGrade : ''}
value={this.props.value}
onChange={this.onChange}
/>

View File

@@ -54,9 +54,34 @@ describe('AdjustedGradeInput', () => {
});
describe('behavior', () => {
describe('onChange', () => {
it('calls props.setModalState event target value', () => {
it('calls props.setModalState event target value with correct value', () => {
const value = 3;
el.instance().onChange({ target: { value } });
expect(props.setModalState).toHaveBeenCalledWith({
adjustedGradeValue: value,
});
});
it('calls props.setModalState event target value with a value more then the possibleGrade value', () => {
const value = 42;
el.instance().onChange({ target: { value } });
expect(props.setModalState).toHaveBeenCalledWith({
adjustedGradeValue: props.possibleGrade,
});
});
it('calls props.setModalState event target value with less then 0', () => {
const value = -5;
el.instance().onChange({ target: { value } });
expect(props.setModalState).toHaveBeenCalledWith({
adjustedGradeValue: 0,
});
});
it('calls props.setModalState event target value without possibleGrade value', () => {
const value = 100;
const newEl = shallow(<AdjustedGradeInput {...props} possibleGrade={null} />);
newEl.instance().onChange({ target: { value } });
expect(props.setModalState).toHaveBeenCalledWith({
adjustedGradeValue: value,
});

View File

@@ -3,9 +3,11 @@
exports[`AdjustedGradeInput Component snapshots displays input control and "out of possible grade" label 1`] = `
<span>
<Control
max={5}
min="0"
name="adjustedGradeValue"
onChange={[MockFunction this.onChange]}
type="text"
type="number"
value={1}
/>
/ 5

View File

@@ -17,7 +17,7 @@ exports[`GradebookTable component snapshot - fields1 and 2 between email and tot
Object {
"key": "Email",
"label": <FormattedMessage
defaultMessage="Email"
defaultMessage="Email*"
description="Gradebook table email column header"
id="gradebook.GradesView.table.headings.email"
/>,

View File

@@ -3,7 +3,7 @@ import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
emailHeading: {
id: 'gradebook.GradesView.table.headings.email',
defaultMessage: 'Email',
defaultMessage: 'Email*',
description: 'Gradebook table email column header',
},
totalGradeHeading: {

View File

@@ -18,13 +18,17 @@ import messages from './SearchControls.messages';
export class SearchControls extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onBlur = this.onBlur.bind(this);
this.onClear = this.onClear.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
/** Changing the search value stores the key in Gradebook. Currently unused */
onChange(searchValue) {
this.props.setSearchValue(searchValue);
onBlur(e) {
const { value } = e.target;
if (this.props.searchValue !== value) {
this.props.setSearchValue(value);
}
}
onClear() {
@@ -32,13 +36,20 @@ export class SearchControls extends React.Component {
this.props.fetchGrades();
}
onSubmit(value) {
if (this.props.searchValue !== value) {
this.props.setSearchValue(value);
}
this.props.fetchGrades();
}
render() {
return (
<div>
<SearchField
onSubmit={this.props.fetchGrades}
onSubmit={this.onSubmit}
inputLabel={<FormattedMessage {...messages.label} />}
onChange={this.onChange}
onBlur={this.onBlur}
onClear={this.onClear}
value={this.props.searchValue}
/>

View File

@@ -52,18 +52,25 @@ describe('SearchControls', () => {
describe('Snapshots', () => {
test('basic snapshot', () => {
const wrapper = searchControls();
wrapper.instance().onChange = jest.fn().mockName('onChange');
wrapper.instance().onBlur = jest.fn().mockName('onBlur');
wrapper.instance().onClear = jest.fn().mockName('onClear');
wrapper.instance().onSubmit = jest.fn().mockName('onSubmit');
expect(wrapper.instance().render()).toMatchSnapshot();
});
});
describe('onChange', () => {
describe('onBlur', () => {
it('saves the changed search value to Gradebook state', () => {
const wrapper = searchControls();
wrapper.instance().onChange('bob');
wrapper.instance().onBlur({ target: { value: 'bob' } });
expect(props.setSearchValue).toHaveBeenCalledWith('bob');
});
it('doesnt save the same as previous value to Gradebook state', () => {
const wrapper = searchControls({ searchValue: 'bob' });
wrapper.instance().onBlur({ target: { value: 'bob' } });
expect(props.setSearchValue).not.toHaveBeenCalled();
});
});
describe('onChange', () => {
@@ -75,6 +82,22 @@ describe('SearchControls', () => {
});
});
describe('onSubmit', () => {
it('saves the changed search value to Gradebook state and calls fetchGrades', () => {
const wrapper = searchControls();
wrapper.instance().onSubmit('bob');
expect(props.setSearchValue).toHaveBeenCalledWith('bob');
expect(props.fetchGrades).toHaveBeenCalled();
});
it('doesnt save the same as previous value to Gradebook state and calls fetchGrades', () => {
const wrapper = searchControls({ searchValue: 'bob' });
wrapper.instance().onSubmit('bob');
expect(props.setSearchValue).not.toHaveBeenCalled();
expect(props.fetchGrades).toHaveBeenCalled();
});
});
describe('mapStateToProps', () => {
const testState = { never: 'gonna', give: 'you up' };
test('searchValue from app.searchValue', () => {

View File

@@ -10,9 +10,9 @@ exports[`SearchControls Component Snapshots basic snapshot 1`] = `
id="gradebook.GradesView.search.label"
/>
}
onChange={[MockFunction onChange]}
onBlur={[MockFunction onBlur]}
onClear={[MockFunction onClear]}
onSubmit={[MockFunction fetchGrades]}
onSubmit={[MockFunction onSubmit]}
value="alice"
/>
<small

View File

@@ -37,7 +37,7 @@
"gradebook.GradesView.EditModal.Overrides.reasonHeader": "Reason",
"gradebook.GradesTab.usersVisibilityLabel'": "Showing {filteredUsers} of {totalUsers} total learners",
"gradebook.GradesView.editFilterLabel": "Edit Filters",
"gradebook.GradesView.table.headings.email": "Email",
"gradebook.GradesView.table.headings.email": "Email*",
"gradebook.GradesView.table.headings.totalGrade": "Total Grade (%)",
"gradebook.GradesView.table.headings.username": "Username",
"gradebook.GradesView.table.labels.studentKey": "Student Key*",
@@ -70,4 +70,4 @@
"gradebook.GradesTab.FilterBadges.courseGrade": "Course Grade",
"gradebook.GradesTab.FilterBadges.includeCourseRoleMembers": "Include Course Team Members",
"gradebook.GradesTab.FilterBadges.track": "Track"
}
}

View File

@@ -37,7 +37,7 @@
"gradebook.GradesView.EditModal.Overrides.reasonHeader": "Reason",
"gradebook.GradesTab.usersVisibilityLabel'": "Showing {filteredUsers} of {totalUsers} total learners",
"gradebook.GradesView.editFilterLabel": "Edit Filters",
"gradebook.GradesView.table.headings.email": "Email",
"gradebook.GradesView.table.headings.email": "Email*",
"gradebook.GradesView.table.headings.totalGrade": "Total Grade (%)",
"gradebook.GradesView.table.headings.username": "Username",
"gradebook.GradesView.table.labels.studentKey": "Student Key*",
@@ -70,4 +70,4 @@
"gradebook.GradesTab.FilterBadges.courseGrade": "Course Grade",
"gradebook.GradesTab.FilterBadges.includeCourseRoleMembers": "Include Course Team Members",
"gradebook.GradesTab.FilterBadges.track": "Track"
}
}

View File

@@ -37,7 +37,7 @@
"gradebook.GradesView.EditModal.Overrides.reasonHeader": "Motif",
"gradebook.GradesTab.usersVisibilityLabel'": "Showing {filteredUsers} of {totalUsers} total learners",
"gradebook.GradesView.editFilterLabel": "Editer les filtres",
"gradebook.GradesView.table.headings.email": "Email",
"gradebook.GradesView.table.headings.email": "Email*",
"gradebook.GradesView.table.headings.totalGrade": "Note totale (%)",
"gradebook.GradesView.table.headings.username": "Nom dutilisateur",
"gradebook.GradesView.table.labels.studentKey": "Clé d'étudiant",
@@ -70,4 +70,4 @@
"gradebook.GradesTab.FilterBadges.courseGrade": "Note du cours",
"gradebook.GradesTab.FilterBadges.includeCourseRoleMembers": "Include Course Team Members",
"gradebook.GradesTab.FilterBadges.track": "Track"
}
}

View File

@@ -37,7 +37,7 @@
"gradebook.GradesView.EditModal.Overrides.reasonHeader": "Reason",
"gradebook.GradesTab.usersVisibilityLabel'": "Showing {filteredUsers} of {totalUsers} total learners",
"gradebook.GradesView.editFilterLabel": "Edit Filters",
"gradebook.GradesView.table.headings.email": "Email",
"gradebook.GradesView.table.headings.email": "Email*",
"gradebook.GradesView.table.headings.totalGrade": "Total Grade (%)",
"gradebook.GradesView.table.headings.username": "Username",
"gradebook.GradesView.table.labels.studentKey": "Student Key*",
@@ -70,4 +70,4 @@
"gradebook.GradesTab.FilterBadges.courseGrade": "Course Grade",
"gradebook.GradesTab.FilterBadges.includeCourseRoleMembers": "Include Course Team Members",
"gradebook.GradesTab.FilterBadges.track": "Track"
}
}

View File

@@ -37,7 +37,7 @@
"gradebook.GradesView.EditModal.Overrides.reasonHeader": "Reason",
"gradebook.GradesTab.usersVisibilityLabel'": "Showing {filteredUsers} of {totalUsers} total learners",
"gradebook.GradesView.editFilterLabel": "Edit Filters",
"gradebook.GradesView.table.headings.email": "Email",
"gradebook.GradesView.table.headings.email": "Email*",
"gradebook.GradesView.table.headings.totalGrade": "Total Grade (%)",
"gradebook.GradesView.table.headings.username": "Username",
"gradebook.GradesView.table.labels.studentKey": "Student Key*",
@@ -70,4 +70,4 @@
"gradebook.GradesTab.FilterBadges.courseGrade": "Course Grade",
"gradebook.GradesTab.FilterBadges.includeCourseRoleMembers": "Include Course Team Members",
"gradebook.GradesTab.FilterBadges.track": "Track"
}
}