Compare commits

..

22 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
Usama Sadiq
97c58157f8 Merge pull request #238 from openedx/jenkins/transifex-client-migration-f07a96c
fix: transifex migration to new client
2022-04-06 12:42:11 +05:00
UsamaSadiq
ce093efba4 build: update transifex pull translations command 2022-04-05 15:26:42 +05:00
Jawayria
799ef5b8a1 Merge pull request #224 from openedx/jawayria/node-16
feat: added support for node 16
2022-03-31 12:13:11 +05:00
Jawayria
f956351cf7 feat: add support for node 16 2022-03-31 12:01:12 +05:00
edX requirements bot
7772e21c6a fix: transifex migration to new client 2022-03-17 08:47:39 -04:00
Sarina Canelake
f07a96ce58 Merge DEPR automation workflow
Add DEPR workflow automation
2022-02-24 15:21:36 -05:00
Sarina Canelake
f64bc8d4a6 build: add DEPR workflow automation 2022-02-23 14:36:18 -05:00
Michael Vlasov
134dabb710 fix: gradebook table rtl tooltip position (#225)
* fix: gradebook table rtl tooltip position

Co-authored-by: vlasovmichael <mykhailo.vlasov@raccoongang.com>
2022-02-10 10:36:46 -05:00
Matt Hughes
65c25f00b6 Merge pull request #227 from openedx/matthugs/rename-github-group-to-match-org-structure
chore: rename github group to match org. structure
2022-02-09 10:10:49 -05:00
Matt Hughes
31748e246e chore: rename github group to match org. structure 2022-02-09 10:06:03 -05:00
Michael Vlasov
650be29ef9 feat: gradebook main container classname (#226)
* feat: gradebook main container classname

* feat: gradebook main container classname / snapshot tests

Co-authored-by: vlasovmichael <mykhailo.vlasov@raccoongang.com>
2022-02-07 15:22:26 -05:00
Jhony Avella
b713ab5748 feat: enabling header override (#220)
feat: new versions of package.json and lock

fix: tests after adding header component

Fixing tests

change package files

Signed-off-by: Jhony Avella <jhony.avella@edunext.co>
2021-12-21 10:40:22 -05:00
Jhony Avella
5fe80b4a52 fix: build the course id properly when the MFE is deployed in a subdirectory (#213) 2021-12-21 10:38:58 -05:00
Carlos Muniz
9e04813d06 Merge pull request #219 from edx/i18n-string-definitions
docs: Describe messages descriptions better
2021-12-03 09:35:26 -05:00
Carlos Muniz
a0e1a60d23 docs: Describe messages descriptions better
These messages have been updated to be more descriptive.
The message descriptions need to be more descriptive in order to
be easily translated (i18n) into other languages.
2021-12-03 09:23:17 -05:00
Sarina Canelake
68c7944dd5 Merge pull request #217 from regisb/regisb/transifex
feat: add compatibility with transifex
2021-11-29 12:37:26 -05:00
Régis Behmo
f4f6e5551f feat: add compatibility with transifex
Now that the frontend-app-gradebook resource was added to Transifex, we can
start pulling strings fromt there. For now, the project contains very few
translated string.

Strings were pulled by running: make pull_translations

This is for https://github.com/openedx/build-test-release-wg/issues/107
2021-11-22 12:12:29 +01:00
Usama Sadiq
ee99bfdaa4 Merge pull request #212 from edx/usamasadiq/replace-travis-with-github-ci
BOM-2928: Replace Travis with GitHub CI
2021-11-16 16:56:36 +05:00
Usama Sadiq
318ce349fc build: Replace Travis with GitHub CI 2021-10-25 17:12:32 +05:00
32 changed files with 40382 additions and 11551 deletions

2
.github/CODEOWNERS vendored
View File

@@ -3,4 +3,4 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence, they will
# be requested for review when someone opens a pull request.
* @edx/masters-devs-gta
* @openedx/content-aurora

View File

@@ -26,4 +26,4 @@ Collectively, these should be completed by reviewers of this PR:
- [ ] I've tested the new functionality
FYI: @edx/masters-devs-gta
FYI: @openedx/content-aurora

View File

@@ -0,0 +1,19 @@
# Run the workflow that adds new tickets that are either:
# - labelled "DEPR"
# - title starts with "[DEPR]"
# - body starts with "Proposal Date" (this is the first template field)
# to the org-wide DEPR project board
name: Add newly created DEPR issues to the DEPR project board
on:
issues:
types: [opened]
jobs:
routeissue:
uses: openedx/.github/.github/workflows/add-depr-ticket-to-depr-board.yml@master
secrets:
GITHUB_APP_ID: ${{ secrets.GRAPHQL_AUTH_APP_ID }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.GRAPHQL_AUTH_APP_PEM }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_ISSUE_BOT_TOKEN }}

59
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,59 @@
name: node_js CI
on:
push:
branches:
- master
pull_request:
branches:
- "**"
jobs:
test:
runs-on: ubuntu-20.04
strategy:
matrix:
node: [12, 14, 16]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Nodejs
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- name: Install dependencies
run: npm ci
- name: Unit Tests
run: npm run test
- name: Validate Package Lock
run: make validate-no-uncommitted-package-lock-changes
- name: Run Lint
run: npm run lint
- name: Run Test
run: npm run test
- name: Run Build
run: npm run build
- name: Run Coverage
uses: codecov/codecov-action@v2
- name: Send failure notification
if: ${{ failure() }}
uses: dawidd6/action-send-mail@v3
with:
server_address: email-smtp.us-east-1.amazonaws.com
server_port: 465
username: ${{secrets.EDX_SMTP_USERNAME}}
password: ${{secrets.EDX_SMTP_PASSWORD}}
subject: CI workflow failed in ${{github.repository}}
to: masters-grades@edx.org
from: github-actions <github-actions@edx.org>
body: CI workflow in ${{github.repository}} failed! For details see "github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

33
.github/workflows/npm-publish.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Release CI
on:
push:
tags:
- '*'
jobs:
release:
name: Release
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 12
- name: Install dependencies
run: npm ci
- name: Create Build
run: npm run build
- name: Release Package
env:
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
run: npm semantic-release

View File

@@ -1,7 +1,6 @@
.eslintignore
.eslintrc.json
.gitignore
.travis.yml
docker-compose.yml
Dockerfile
Makefile

View File

@@ -1,28 +0,0 @@
language: node_js
node_js: 12
notifications:
email:
recipients:
- masters-grades@edx.org
on_success: never
on_failure: always
webhooks: https://www.travisbuddy.com/
on_success: never
before_install:
- npm install -g greenkeeper-lockfile@1.14.0
install:
- npm ci
before_script: greenkeeper-lockfile-update
after_script: greenkeeper-lockfile-upload
script:
- make validate-no-uncommitted-package-lock-changes
- npm run lint
- npm run test
- npm run build
after_success:
- npm run travis-deploy-once "npm run semantic-release"
- npm run coveralls
env:
global:
- secure: bBLQZVw1aVUxB7GFNXGrdKeztyFrCCJusVgFcSuej9S4qmj9/jrVsEc9dEcH+BMS+b49+SvILoxzd6ZYLaRygQLzevnO1/dX596DeCKVK48PTTZRsNyafaSMCkxNKqEmRcA9hYL52xJJ5GpKo7ViWsFy8VFgUfZEJxQi8/lYbfQ1vlXRpo2LJfJh09v85roSXdQmajyGJ1Dz6elcwUX5B+BgXmIHizJXUMfFci61xTEZmgKtfeCiwFQA5pCvVMHBQhgySqT2N3eRESzRt2jAfAdcRKBYXS0rwKymdlL1ZF349Jm8xwtqm19Fwsut21181Lnn6FmccMWhQ7man3WH1xfT0ahmHNs1KJMyZcwRJd/gDfbd6iD3LB9Pt9hEQ00Qh/m7MYeahMxTEL9bp2TyILi8cTP91jeBUHCExCdv2jRrUQEnUS5vZUYRdM8CR2DLoLmNh3APndKzwgr5U8rh6RdhbQBJp97Hb/YYVrBiP2atLJAaYPY/xEQHK/YoXelQgiZ6wHBMV+tF/L0ZRn7KyVWdkbBKWfbEjRKbEJD9WD+V7HayMR81tm5CSqlrG8mTvSy2boIGiX14GV11ZEfMj5bjb6W41BW+QGqQerZvmwk/4ywe304X85PD0OBhIYPRzeLIi0Gt6lD1aOpVxgm4M03tdgYQzCPWRPq32CB+1IA=
- secure: w1d/E+cc4+Bf017Jpp9YsKBzLSZw9sqKZGeM2tNrO6eJZbMJqfKTmfUrRw8BoLh1Z8YRkHF7RADDy3ln7XEdeAX3j9OoC3Cz0zN6iDX6TPcI461NuOIscJYb4tyFcuWm6FhgVlBAlo/BI3q+zqKwjfWuDaORpk6+haacCmvTe5V0vWhY+MYT7M+LfnKeKVzhI4magGt8jPTE21oziIFwCqCCjJc4+AmsWoWTzU0Q7Db0DZiJnLXFfXybLbkedAgJmcSgEGZCSpaZIOkX0/Lbazsz1Ky4KASfkrYT1Z5iKQ8TE3skmx1IIu+1egN8iBbdrY+NhvV24RkT+rpUvD7TBIHTrjQ5JYLe0kGjN70vG7YlKgjNSyTjkrEd7fCKpuIol3DVjBRz3tV5aCl0t/A8mIPqKyNI94MamWsExpqsxgcb9vBVno5caZvD8ZXNrGNqanB3MSoLGxZTLKif9u+AZfLnB3xtjaiJg3/BNoWaOBPlp/M6BvGIGHElwvLrAhUvl8wzrwJcQQWpmRMh0b6enr6Y7ox/mGGs7NBCT+CNKEsWeCfY4thZzgi6/GocXyqdTpXMkNSI1PDoPmi+vKafBd+7aAYbcUlJBTU6TAxyncln0tF2JF+ghTZ0v8nNzEQ9VmV4ddyoOHx6YnHvEcenWZGMROQnMCVifyDbaHpPbPI=

View File

@@ -1,9 +1,9 @@
[main]
host = https://www.transifex.com
[edx-platform.frontend-app-gradebook]
[o:open-edx:p:edx-platform:r:frontend-app-gradebook]
file_filter = src/i18n/messages/<lang>.json
source_file = src/i18n/transifex_input.json
source_lang = en
type = KEYVALUEJSON
type = KEYVALUEJSON

View File

@@ -57,9 +57,9 @@ push_translations:
# Pulls translations from Transifex.
pull_translations:
tx pull -f --mode reviewed --language=$(transifex_langs)
tx pull -f --mode reviewed --languages=$(transifex_langs)
# This target is used by Travis.
# This target is used by CI.
validate-no-uncommitted-package-lock-changes:
# Checking for package-lock.json changes...
git diff --exit-code package-lock.json

View File

@@ -1,77 +0,0 @@
# Travis Configuration
Your project might have different build requirements - however, this project's `.travis.yml` configuration is supposed to represent a good starting point.
## Node JS Version
The minimum `Node` and `npm` versions that edX supports is `8.9.3` and `5.5.1`, respectively.
## Caching node_modules
While [the `Travis` blog](https://blog.travis-ci.com/2016-11-21-travis-ci-now-supports-yarn) recommends
```yaml
cache:
directories:
- node_modules
```
this causes issues when testing different versions of `Node` because [`node_modules` will store the compiled native modules](https://stackoverflow.com/a/42523517/5225575).
Caching the `~/.npm` directory avoids storing these native modules.
## Notifications
This project uses a service called [`TravisBuddy`](https://www.travisbuddy.com/), which provides Travis build context within a PR via webhooks (configured only to add feedback for build failures).
![travis-buddy](https://i.imgur.com/VsR2TTs.png)
## Installing `greenkeeper-lockfile`
As explained in [the `Greenkeeper` documentation](https://greenkeeper.io/docs.html#greenkeeper-step-by-step), `Greenkeeper` is a service that keeps track of your project's dependencies, and will, for example, automatically open PRs with an updated `package.json` file when the latest version of a dependency is a major version ahead of the existing dependency version in your `package.json` file.
This automated updating is great, but `Greenkeeper` does not update your `package-lock.json` file, just your `package.json` file. This makes sense, as the only way to update the `package-lock.json` file would be to run `npm install` when building your project, using the latest `package.json`, and then committing the updated `package-lock.json` file.
This is essentially what you have to do manually when `Greenkeeper` opens a PR - `git checkout` the branch, `npm install` locally, `git commit` the `package-lock.json` changes, and then `git push` those changes to the `Greenkeeper` branch on `origin`. It's fun probably only the first time, and even then it gets old, fast.
What [`greenkeeper-lockfile`](https://github.com/greenkeeperio/greenkeeper-lockfile) does is that it automates the previous steps as part of the build process.
It will
* Check that the branch is a `Greenkeeper` branch
* Update the lockfile
* Push a commit with the updated lockfile back to the Greenkeeper branch
This is why it's important to install `greenkeeper-lockfile` in the `before_install` step, and since it's used exclusively only in the Travis Build, why it's not part of the package's dependencies.
## Scripts
Most of the `script`s are self-explanatory - you probably want to fail a build if there are linting violations, or if any tests don't pass, or if it cannot compile your files.
However, there are a couple additional `script`s that might seem less self-explanatory.
### What the heck is `make validate-no-uncommitted-package-lock-changes`?
There are only two requirements for a good `make target` name
1. Definitely make it really verbose so people can't remember what it's called
2. Definitely don't not use a double-negative
What `make validate-no-uncommitted-package-lock-changes` does is `git diff`s for any `package-lock.json` file changes in your project. It's important to remember that all build `script`s are executed in Travis *after* the `install` step (aka post-`npm install`).
This is important because `npm` uses the pinned dependencies in your `package-lock.json` file to build the `node_modules` directory. However, the dependencies defined within the `package.json` file can be modified manually, for example, to become misaligned with the dependencies defined within the `package-lock.json`. So when `npm install` executes, the `package-lock.json` file will be updated to mirror the modified `package.json` changes.
However, when these changes surface within a Travis build, this indicates differing dependency expectations between the committed `package.json` file and the `package-lock.json` file, which is a good reason to fail a build.
### What is this `npm run is-es5` check?
This project outputs production files to the `dist` folder. The `npm script`, `npm run is-es5`, checks the JavaScript files in the `dist` folder to make sure that they are `ES5`-compliant.
This check is important because `ES5` JavaScript has [greater browser compatibility](http://kangax.github.io/compat-table/es5/) than [`ES2015+`](http://kangax.github.io/compat-table/es6/) - particularly for `IE11`.
### `deploy` step
How your project deploys will probably differ between the cookie cutter and your own application.
For demonstrational purposes, the cookie cutter deploys to GitHub pages using [`Travis`'s GitHub pages configuration](https://docs.travis-ci.com/user/deployment/pages/).
Your application might deploy to an `S3` bucket or to `npm`.

40
documentation/CI.md Executable file
View File

@@ -0,0 +1,40 @@
# CI Configuration
Your project might have different build requirements - however, this project's `.github/ci.yml` configuration is supposed to represent a good starting point.
## Node JS Version
The minimum `Node` and `npm` versions that edX supports is `8.9.3` and `5.5.1`, respectively.
## Scripts
Most of the `script`s are self-explanatory - you probably want to fail a build if there are linting violations, or if any tests don't pass, or if it cannot compile your files.
However, there are a couple additional `script`s that might seem less self-explanatory.
### What the heck is `make validate-no-uncommitted-package-lock-changes`?
There are only two requirements for a good `make target` name
1. Definitely make it really verbose so people can't remember what it's called
2. Definitely don't not use a double-negative
What `make validate-no-uncommitted-package-lock-changes` does is `git diff`s for any `package-lock.json` file changes in your project. It's important to remember that all build `script`s are executed in CI *after* the `install` step (aka post-`npm install`).
This is important because `npm` uses the pinned dependencies in your `package-lock.json` file to build the `node_modules` directory. However, the dependencies defined within the `package.json` file can be modified manually, for example, to become misaligned with the dependencies defined within the `package-lock.json`. So when `npm install` executes, the `package-lock.json` file will be updated to mirror the modified `package.json` changes.
However, when these changes surface within a CI build, this indicates differing dependency expectations between the committed `package.json` file and the `package-lock.json` file, which is a good reason to fail a build.
### What is this `npm run is-es5` check?
This project outputs production files to the `dist` folder. The `npm script`, `npm run is-es5`, checks the JavaScript files in the `dist` folder to make sure that they are `ES5`-compliant.
This check is important because `ES5` JavaScript has [greater browser compatibility](http://kangax.github.io/compat-table/es5/) than [`ES2015+`](http://kangax.github.io/compat-table/es6/) - particularly for `IE11`.
### `deploy` step
How your project deploys will probably differ between the cookie cutter and your own application.
For demonstrational purposes, the cookie cutter deploys to GitHub pages using [ GitHUb CI ].
Your application might deploy to an `S3` bucket or to `npm`.

51484
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@edx/frontend-app-gradebook",
"version": "1.4.47",
"version": "1.5.0",
"description": "edx editable gradebook-ui to manipulate grade overrides on subsections",
"repository": {
"type": "git",
@@ -17,8 +17,7 @@
"semantic-release": "semantic-release",
"start": "fedx-scripts webpack-dev-server --progress",
"test": "TZ=GMT fedx-scripts jest --coverage --passWithNoTests",
"watch-tests": "jest --watch",
"travis-deploy-once": "travis-deploy-once"
"watch-tests": "jest --watch"
},
"author": "edX",
"license": "AGPL-3.0",
@@ -26,12 +25,17 @@
"publishConfig": {
"access": "public"
},
"browserslist": [
"last 2 versions",
"not ie > 0",
"not ie_mob > 0"
],
"dependencies": {
"@edx/brand": "npm:@edx/brand-edx.org@^1.3.2",
"@edx/frontend-component-footer": "10.1.6",
"@edx/frontend-component-header": "2.2.5",
"@edx/frontend-platform": "1.9.5",
"@edx/paragon": "14.16.4",
"@edx/frontend-component-footer": "10.2.1",
"@edx/frontend-component-header": "2.4.5",
"@edx/frontend-platform": "1.15.1",
"@edx/paragon": "19.6.0",
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-brands-svg-icons": "^5.11.2",
"@fortawesome/free-solid-svg-icons": "^5.11.2",
@@ -45,13 +49,12 @@
"enzyme-to-json": "^3.6.2",
"font-awesome": "4.7.0",
"history": "4.10.1",
"node-sass": "^4.14.1",
"prop-types": "15.7.2",
"query-string": "6.13.0",
"react": "16.13.1",
"react-dom": "16.13.1",
"react": "16.14.0",
"react-dom": "16.14.0",
"react-intl": "^2.9.0",
"react-redux": "^5.1.1",
"react-redux": "^7.1.1",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-router-redux": "^5.0.0-alpha.9",
@@ -61,11 +64,12 @@
"redux-logger": "3.0.6",
"redux-thunk": "2.3.0",
"regenerator-runtime": "^0.13.7",
"sass": "^1.49.0",
"util": "^0.12.3",
"whatwg-fetch": "^2.0.4"
},
"devDependencies": {
"@edx/frontend-build": "5.5.2",
"@edx/frontend-build": "9.1.1",
"axios": "0.21.1",
"axios-mock-adapter": "^1.17.0",
"codecov": "^3.6.1",
@@ -79,7 +83,6 @@
"react-test-renderer": "^16.10.1",
"reactifex": "1.1.1",
"redux-mock-store": "^1.5.3",
"semantic-release": "^17.2.3",
"travis-deploy-once": "^5.0.11"
"semantic-release": "^17.2.3"
}
}

View File

@@ -31,14 +31,14 @@ exports[`GradebookFilters Component snapshots basic snapshot 1`] = `
}
>
<div>
<Connect(AssignmentTypeFilter)
updateQueryParams={[MockFunction]}
<AssignmentTypeFilter
updateQueryParams={[MockFunction this.props.updateQueryParams]}
/>
<Connect(AssignmentFilter)
updateQueryParams={[MockFunction]}
<AssignmentFilter
updateQueryParams={[MockFunction this.props.updateQueryParams]}
/>
<Connect(AssignmentGradeFilter)
updateQueryParams={[MockFunction]}
<AssignmentGradeFilter
updateQueryParams={[MockFunction this.props.updateQueryParams]}
/>
</div>
</Collapsible>
@@ -53,8 +53,8 @@ exports[`GradebookFilters Component snapshots basic snapshot 1`] = `
/>
}
>
<Connect(CourseGradeFilter)
updateQueryParams={[MockFunction]}
<CourseGradeFilter
updateQueryParams={[MockFunction this.props.updateQueryParams]}
/>
</Collapsible>
<Collapsible
@@ -68,8 +68,8 @@ exports[`GradebookFilters Component snapshots basic snapshot 1`] = `
/>
}
>
<InjectIntl(ShimmedIntlComponent)
updateQueryParams={[MockFunction]}
<StudentGroupsFilter
updateQueryParams={[MockFunction this.props.updateQueryParams]}
/>
</Collapsible>
<Collapsible

View File

@@ -22,6 +22,11 @@ jest.mock('@edx/paragon', () => ({
jest.mock('@edx/paragon/icons', () => ({
Close: 'paragon.icons.Close',
}));
jest.mock('./AssignmentTypeFilter', () => 'AssignmentTypeFilter');
jest.mock('./AssignmentFilter', () => 'AssignmentFilter');
jest.mock('./AssignmentGradeFilter', () => 'AssignmentGradeFilter');
jest.mock('./CourseGradeFilter', () => 'CourseGradeFilter');
jest.mock('./StudentGroupsFilter', () => 'StudentGroupsFilter');
jest.mock('data/selectors', () => ({
__esModule: true,
default: {
@@ -50,7 +55,7 @@ describe('GradebookFilters', () => {
closeMenu: jest.fn().mockName('this.props.closeMenu'),
fetchGrades: jest.fn(),
updateIncludeCourseRoleMembers: jest.fn(),
updateQueryParams: jest.fn(),
updateQueryParams: jest.fn().mockName('this.props.updateQueryParams'),
};
});

View File

@@ -4,7 +4,7 @@ const messages = defineMessages({
downloadGradesBtn: {
id: 'gradebook.GradesView.BulkManagementControls.bulkManagementLabel',
defaultMessage: 'Download Grades',
description: 'Button text for bulk grades download control in GradesView',
description: 'A labeled button that allows an admin user to download course grades all at once (in bulk).',
},
});

View File

@@ -4,7 +4,7 @@ const messages = defineMessages({
editFilters: {
id: 'gradebook.GradesView.editFilterLabel',
defaultMessage: 'Edit Filters',
description: 'Button text on Grades tab to open/close the Filters tab',
description: 'A labeled button in the Grades tab that opens/closes the Filters tab, allowing the grades to be filtered',
},
});

View File

@@ -4,12 +4,12 @@ const messages = defineMessages({
csvUploadLabel: {
id: 'gradebook.BulkManagementHistoryView.csvUploadLabel',
defaultMessage: 'Upload Grade CSV',
description: 'Button in BulkManagementHistoryView Alerts',
description: 'A labeled button to upload a CSV containing course grades.',
},
importGradesBtnText: {
id: 'gradebook.GradesView.importGradesBtnText',
defaultMessage: 'Import Grades',
description: 'Button in BulkManagement Tab File Upload Form',
description: 'A labeled button to import grades in the BulkManagement Tab File Upload Form',
},
});

View File

@@ -4,12 +4,12 @@ const messages = defineMessages({
description: {
id: 'gradebook.GradesView.ImportSuccessToast.description',
defaultMessage: 'Import Successful! Grades will be updated momentarily.',
description: 'Import Success Toast description',
description: 'A message congratulating a successful Import of grades',
},
showHistoryViewBtn: {
id: 'gradebook.GradesView.ImportSuccessToast.showHistoryViewBtn',
defaultMessage: 'View Activity Log',
description: 'Button text for action that loads Bulk Management Activity Log view',
description: 'The text on a button that loads a view of the Bulk Management Activity Log',
},
});

View File

@@ -4,17 +4,17 @@ const messages = defineMessages({
title: {
id: 'gradebook.GradesView.InterventionsReport.title',
defaultMessage: 'Interventions Report',
description: 'Intervention report subsection label',
description: 'The title for the Intervention report subsection',
},
description: {
id: 'gradebook.GradesView.InterventionsReport.description',
defaultMessage: 'Need to find students who may be falling behind? Download the interventions report to obtain engagement metrics such as section attempts and visits.',
description: 'Intervention report subsection description',
description: 'The description for the Intervention report subsection',
},
downloadBtn: {
id: 'gradebook.GradesView.InterventionsReport.downloadBtn',
defaultMessage: 'Download Interventions',
description: 'Button text for intervention report download control in GradesView',
description: 'The labeled button to download the Intervention report from the Grades View',
},
});

View File

@@ -4,17 +4,17 @@ const messages = defineMessages({
scoreView: {
id: 'gradebook.GradesView.scoreViewLabel',
defaultMessage: 'Score View',
description: 'Score format select dropdown label',
description: 'The label for the dropdown list that allows a user to select the Score format',
},
absolute: {
id: 'gradebook.GradesView.absoluteOption',
defaultMessage: 'Absolute',
description: 'Score format select dropdown option',
description: 'A label within the Score Format dropdown list for the Absolute Grade Score option',
},
percent: {
id: 'gradebook.GradesView.percentOption',
defaultMessage: 'Percent',
description: 'Score format select dropdown option',
description: 'A label within the Score Format dropdown list for the Percent Grade Score option',
},
});

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

@@ -4,12 +4,12 @@ const messages = defineMessages({
label: {
id: 'gradebook.GradesView.search.label',
defaultMessage: 'Search for a learner',
description: 'Search description label',
description: 'Text prompting a user to use this functionality to search for a learner',
},
hint: {
id: 'gradebook.GradesView.search.hint',
defaultMessage: 'Search by username, email, or student key',
description: 'Search hint label',
description: 'A hint explaining the ways a user can search',
},
});

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

@@ -4,17 +4,17 @@ const messages = defineMessages({
editSuccessAlert: {
id: 'gradebook.GradesView.editSuccessAlert',
defaultMessage: 'The grade has been successfully edited. You may see a slight delay before updates appear in the Gradebook.',
description: 'Alert text for successful edit action',
description: 'An alert text for successfully editing a grade',
},
maxGradeInvalid: {
id: 'gradebook.GradesView.maxCourseGradeInvalid',
defaultMessage: 'Maximum course grade must be between 0 and 100',
description: 'Alert text for invalid maximum course grade',
description: 'An alert text for selecting a maximum course grade greater than 100',
},
minGradeInvalid: {
id: 'gradebook.GradesView.minCourseGradeInvalid',
defaultMessage: 'Minimum course grade must be between 0 and 100',
description: 'Alert text for invalid minimum course grade',
description: 'An alert text for selecting a minimum course grade less than 0',
},
});

View File

@@ -12,7 +12,7 @@ exports[`FilterMenuToggle component snapshots basic snapshot 1`] = `
<FormattedMessage
defaultMessage="Edit Filters"
description="Button text on Grades tab to open/close the Filters tab"
description="A labeled button in the Grades tab that opens/closes the Filters tab, allowing the grades to be filtered"
id="gradebook.GradesView.editFilterLabel"
/>
</Button>

View File

@@ -19,7 +19,7 @@ exports[`ImportGradesButton component snapshot snapshot - loads export form w/ a
label={
<FormattedMessage
defaultMessage="Upload Grade CSV"
description="Button in BulkManagementHistoryView Alerts"
description="A labeled button to upload a CSV containing course grades."
id="gradebook.BulkManagementHistoryView.csvUploadLabel"
/>
}
@@ -35,7 +35,7 @@ exports[`ImportGradesButton component snapshot snapshot - loads export form w/ a
label={
Object {
"defaultMessage": "Import Grades",
"description": "Button in BulkManagement Tab File Upload Form",
"description": "A labeled button to import grades in the BulkManagement Tab File Upload Form",
"id": "gradebook.GradesView.importGradesBtnText",
}
}

View File

@@ -7,7 +7,7 @@ exports[`InterventionsReport component snapshots snapshot 1`] = `
>
<FormattedMessage
defaultMessage="Interventions Report"
description="Intervention report subsection label"
description="The title for the Intervention report subsection"
id="gradebook.GradesView.InterventionsReport.title"
/>
</h4>
@@ -19,7 +19,7 @@ exports[`InterventionsReport component snapshots snapshot 1`] = `
>
<FormattedMessage
defaultMessage="Need to find students who may be falling behind? Download the interventions report to obtain engagement metrics such as section attempts and visits."
description="Intervention report subsection description"
description="The description for the Intervention report subsection"
id="gradebook.GradesView.InterventionsReport.description"
/>
</div>
@@ -27,7 +27,7 @@ exports[`InterventionsReport component snapshots snapshot 1`] = `
label={
Object {
"defaultMessage": "Download Interventions",
"description": "Button text for intervention report download control in GradesView",
"description": "The labeled button to download the Intervention report from the Grades View",
"id": "gradebook.GradesView.InterventionsReport.downloadBtn",
}
}

View File

@@ -7,7 +7,7 @@ exports[`ScoreViewInput component snapshot - select box with percent and absolut
<FormLabel>
<FormattedMessage
defaultMessage="Score View"
description="Score format select dropdown label"
description="The label for the dropdown list that allows a user to select the Score format"
id="gradebook.GradesView.scoreViewLabel"
/>
:

View File

@@ -6,13 +6,13 @@ exports[`SearchControls Component Snapshots basic snapshot 1`] = `
inputLabel={
<FormattedMessage
defaultMessage="Search for a learner"
description="Search description label"
description="Text prompting a user to use this functionality to search for a learner"
id="gradebook.GradesView.search.label"
/>
}
onChange={[MockFunction onChange]}
onBlur={[MockFunction onBlur]}
onClear={[MockFunction onClear]}
onSubmit={[MockFunction fetchGrades]}
onSubmit={[MockFunction onSubmit]}
value="alice"
/>
<small
@@ -20,7 +20,7 @@ exports[`SearchControls Component Snapshots basic snapshot 1`] = `
>
<FormattedMessage
defaultMessage="Search by username, email, or student key"
description="Search hint label"
description="A hint explaining the ways a user can search"
id="gradebook.GradesView.search.hint"
/>
</small>

View File

@@ -7,7 +7,7 @@ exports[`StatusAlerts snapshots basic snapshot 1`] = `
dialog={
<FormattedMessage
defaultMessage="The grade has been successfully edited. You may see a slight delay before updates appear in the Gradebook."
description="Alert text for successful edit action"
description="An alert text for successfully editing a grade"
id="gradebook.GradesView.editSuccessAlert"
/>
}

View File

@@ -4,37 +4,37 @@ const messages = defineMessages({
assignment: {
id: 'gradebook.GradesTab.FilterBadges.assignment',
defaultMessage: 'Assignment',
description: 'Assignment FilterBadge label',
description: 'A label describing the notification under the "Edit Filters" button that shows by which of the course\'s assignments the view is being filtered.',
},
assignmentGrade: {
id: 'gradebook.GradesTab.FilterBadges.assignmentGrade',
defaultMessage: 'Assignment Grade',
description: 'Assignment Grade FilterBadge label',
description: 'A label describing the notification under the "Edit Filters" button that shows that the view is being filtered to include assignment grades within the alloted range.',
},
assignmentType: {
id: 'gradebook.GradesTab.FilterBadges.assignmentType',
defaultMessage: 'Assignment Type',
description: 'Assignment Type FilterBadge label',
description: 'A label describing the notification under the "Edit Filters" button that shows by which of the course\'s assignment types the view is being filtered.',
},
cohort: {
id: 'gradebook.GradesTab.FilterBadges.cohort',
defaultMessage: 'Cohort',
description: 'Cohort FilterBadge label',
description: 'A label describing the notification under the "Edit Filters" button that shows by which of the course\'s cohorts the view is being filtered.',
},
courseGrade: {
id: 'gradebook.GradesTab.FilterBadges.courseGrade',
defaultMessage: 'Course Grade',
description: 'Course Grade FilterBadge label',
description: 'A label describing the notification under the "Edit Filters" button that shows that the view is being filtered to include course grades within the alloted range.',
},
includeCourseRoleMembers: {
id: 'gradebook.GradesTab.FilterBadges.includeCourseRoleMembers',
defaultMessage: 'Include Course Team Members',
description: 'Include Course Team Members FilterBadge label',
description: 'A label describing the notification under the "Edit Filters" button that shows that the view is being filtered to include course team members.',
},
track: {
id: 'gradebook.GradesTab.FilterBadges.track',
defaultMessage: 'Track',
description: 'Track FilterBadge label',
description: 'A label describing the notification under the "Edit Filters" button that shows by which of the course\'s tracks the view is being filtered.',
},
});