Compare commits

..

6 Commits

Author SHA1 Message Date
Leangseu Kim
54c6c57b42 feat: upgraded to node v18, added .nvmrc and updated workflows 2023-06-09 09:19:12 +02:00
Adolfo R. Brandes
6722dbdce5 Merge pull request #185 from arbrandes/runtime-config-palm 2023-06-05 16:40:57 +01:00
Adolfo R. Brandes
fed06641df refactor: use getConfig 2023-05-31 12:46:23 -03:00
Adolfo R. Brandes
689b8b48f0 feat: Support runtime configuration
frontend-platform supports runtime configuration since 2.5.0 (see the PR
that introduced it[1], but it requires MFE cooperation.  This implements
just that: by avoiding making configuration values constant, it should
now be possible to change them after initialization.

Almost all changes here relate to the `LMS_BASE_URL` setting, which in
most places was treated as a constant.

[1] openedx/frontend-platform#335
2023-05-31 12:46:23 -03:00
Adolfo R. Brandes
258f4377d8 Merge pull request #181 from raccoongang/palm/fix-location-id 2023-05-15 10:37:48 -03:00
Eugene Dyudyunov
dcdc96778c fix: BadOraLocationResponse error
Refactor the locationId constant for the subdirectory-based
deployments support.

Exclude the MFE's `PUBLIC_PATH` from the constant.

The `window.location.pathname` example:
```
<PUBLIC_PATH>block-v1:oragrading+oragrading+oragrading+type@openassessment+block@ee217e897a954c1faa3b29317da0f2e7
```
Where the `PUBLIC_PATH` could be:
- `'/'` - for subdomain-based deployments (default)
- `'/mfe-specifix-public-path/'` - for subdirectory-based deployments
2023-05-12 15:37:12 +03:00
22 changed files with 29830 additions and 7290 deletions

View File

@@ -11,7 +11,6 @@ const config = createConfig('eslint', {
"react/forbid-prop-types": ["error", { "forbid": ["any", "array"] }], // arguable object proptype is use when I do not care about the shape of the object
'no-import-assign': 'off',
'no-promise-executor-return': 'off',
'import/no-cycle': 'off',
},
});

View File

@@ -10,4 +10,4 @@ on:
jobs:
version-check:
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master
uses: openedx/.github/.github/workflows/lockfileversion-check.yml@master

2
.nvmrc
View File

@@ -1 +1 @@
18.16
18.15

View File

@@ -5,7 +5,6 @@ npm-install-%: ## install specified % npm package
transifex_resource = frontend-app-ora-grading
transifex_langs = "ar,fr,es_419,zh_CN,fr_CA,it_IT,pt_PT,de_DE,uk,ru,hi"
intl_imports = ./node_modules/.bin/intl-imports.js
transifex_utils = ./node_modules/.bin/transifex-utils.js
i18n = ./src/i18n
transifex_input = $(i18n)/transifex_input.json
@@ -54,24 +53,9 @@ push_translations:
# Pushing comments to Transifex...
./node_modules/@edx/reactifex/bash_scripts/put_comments_v3.sh
ifeq ($(OPENEDX_ATLAS_PULL),)
# Pulls translations from Transifex.
pull_translations:
tx pull -t -f --mode reviewed --languages=$(transifex_langs)
else
# Experimental: OEP-58 Pulls translations using atlas
pull_translations:
rm -rf src/i18n/messages
mkdir src/i18n/messages
cd src/i18n/messages \
&& atlas pull --filter=$(transifex_langs) \
translations/frontend-component-footer/src/i18n/messages:frontend-component-footer \
translations/frontend-component-header/src/i18n/messages:frontend-component-header \
translations/paragon/src/i18n/messages:paragon \
translations/frontend-app-ora-grading/src/i18n/messages:frontend-app-ora-grading
$(intl_imports) frontend-component-footer frontend-component-header paragon frontend-app-ora-grading
endif
# This target is used by CI.
validate-no-uncommitted-package-lock-changes:

21
README.md Normal file
View File

@@ -0,0 +1,21 @@
# frontend-app-ora-grading
The ORA Staff Grading App is a microfrontend (MFE) staff grading experience for Open Response Assessments (ORAs). This experience was designed to streamline the grading process and enable richer previews of submission content.
When enabled, ORAs with a staff grading step will link to this new MFE when clicking "Grade Available Responses" from the ORA or link in the instructor dashboard.
## Quickstart
To start the MFE and enable the feature in LMS:
1. Start the MFE with `npm run start`. Take a note of the path/port (defaults to `http://localhost:1993`).
2. Add the route root to `edx-platform` settings: In `edx-platform/lms/envs/private.py` or similar, add `ORA_GRADING_MICROFRONTEND_URL = 'http://localhost:1993'`
3. Enable the feature: In Django Admin go to django-waffle > Flags and add/enable a new flag called `openresponseassessment.enhanced_staff_grader`.
From there, visit the new experience by going to the Instructor Dashboard > Open Responses or an ORA with a Staff Graded Step and click a link to begin grading.
## Resources
See the [ORA Staff Grading](https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/open_response_assessments/ORA_Staff_Grading.html#ora-staff-grading) section on ReadTheDocs for usage information.

View File

@@ -1,202 +0,0 @@
frontend-app-ora-grading
########################
|ci-badge| |codecov-badge| |doc-badge| |license-badge| |status-badge|
Purpose
*******
The ORA Staff Grading App is a micro-frontend (MFE) staff grading experience
for Open Response Assessments (ORAs). This experience was designed to
streamline the grading process and enable richer previews of submission content
and, eventually, replace on-platform grading workflows for ORA.
When enabled, ORAs with a staff grading step will link to this new MFE when
clicking "Grade Available Responses" from the ORA or link in the instructor
dashboard.
The ORA Staff Grader depends on the `lms/djangoapps/ora_staff_grader
<https://github.com/openedx/edx-platform/tree/master/lms/djangoapps/ora_staff_grader>`_
app in ``edx-platform``.
Getting Started
***************
Developing
==========
One Time Setup
--------------
First, clone the repo, install code prerequisites, and start the app.
.. code-block::
# Clone the repository
git clone git@github.com:openedx/frontend-app-ora-grading.git
cd frontend-app-ora-grading
# Install prerequisites
npm install
# Start the MFE
npm run start
The app will, by default, run on `http://localhost:1993` unless otherwise
specified in ``.env.development:PORT`` and ``.env.development:BASE_URL``.
Next, enable the ORA Grading micro-frontend in `edx-platform`
#. Add the path to the ORA Grading app in `edx-platform`:
#. Go to your environment settings (e.g. `edx-platform/lms/envs/private.py`)
#. Add the environment variable, ``ORA_GRADING_MICROFRONTEND_URL`` pointing
to the ORA Grading app location (e.g. ``http://localhost:1993``).
#. Start / restart the ``edx-platform`` ``lms``.
#. Enable the ORA Grading feature in Django Admin.
#. Go to Django Admin (`{lms-root}/admin`)
#. Navigate to ``django-waffle`` > ``Flags`` and click ``add/enable a new
flag``.
#. Add a new flag called ``openresponseassessment.enhanced_staff_grader``
and enable it.
From there, visit an Open Response Assessment with a Staff Graded Step and
click the "View and grade responses" button to begin grading in the ORA Staff
Grader experience.
Making Changes
--------------
Get / install the latest code:
.. code-block::
# Grab the latest code
git checkout master
git pull
# Install/update the dev requirements
npm install
Before committing:
.. code-block::
# Make a new branch for your changes
git checkout -b <your_github_username>/<short_description>
# Using your favorite editor, edit the code to make your change.
# Run your new tests
npm test
# Commit all your changes
git commit ...
git push
# Open a PR and ask for review.
Deploying
=========
This component follows the standard deploy process for MFEs. For details, see
the `MFE production deployment guide`_
.. _MFE production deployment guide: https://openedx.github.io/frontend-platform/#production-deployment-strategy
Getting Help
************
Documentation
=============
See `ORA Staff Grading on ReadTheDocs`_ for more in-depth usage information.
.. _ORA Staff Grading on ReadTheDocs: https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/open_response_assessments/ORA_Staff_Grading.html#ora-staff-grading
More Help
=========
If you're having trouble, we have discussion forums at
https://discuss.openedx.org where you can connect with others in the community.
Our real-time conversations are on Slack. You can request a `Slack
invitation`_, then join our `community Slack workspace`_.
For anything non-trivial, the best path is to open an issue in this repository
with as many details about the issue you are facing as you can provide.
https://github.com/openedx/frontend-app-ora-grading/issues
For more information about these options, see the `Getting Help`_ page.
.. _Slack invitation: https://openedx.org/slack
.. _community Slack workspace: https://openedx.slack.com/
.. _Getting Help: https://openedx.org/getting-help
License
*******
The code in this repository is licensed under the GNU Affero General Public
License v3.0 unless otherwise noted.
Please see `LICENSE <LICENSE>`_ for details.
Contributing
************
This project is currently only accepting bug fixes, security fixes, and
maintenance work. New features should be discussed in advance with the owning
team and added to the public roadmap or they may not be accepted. You can start
a conversation by creating a new issue on this repo summarizing your feature
idea.
Please read `How To Contribute <https://openedx.org/r/how-to-contribute>`_ for
details.
The Open edX Code of Conduct
****************************
All community members are expected to follow the `Open edX Code of Conduct`_.
.. _Open edX Code of Conduct: https://openedx.org/code-of-conduct/
People
******
The assigned maintainers for this component and other project details may be
found in `Backstage`_. Backstage pulls this data from the ``catalog-info.yaml``
file in this repo.
.. _Backstage: https://open-edx-backstage.herokuapp.com/catalog/default/component/frontend-app-ora-grading
Reporting Security Issues
*************************
Please do not report security issues in public. Please email security@openedx.org.
.. |ci-badge| image:: https://github.com/openedx/frontend-app-ora-grading/actions/workflows/ci.yml/badge.svg
:target: https://github.com/openedx/frontend-app-ora-grading/actions/workflows/ci.yml
:alt: CI
.. |codecov-badge| image:: https://codecov.io/github/openedx/frontend-app-ora-grading/coverage.svg?branch=master
:target: https://codecov.io/github/openedx/frontend-app-ora-grading?branch=master
:alt: Codecov
.. |doc-badge| image:: https://readthedocs.org/projects/frontend-app-ora-grading/badge/?version=latest
:target: https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/open_response_assessments/ORA_Staff_Grading.html
:alt: Documentation
.. |license-badge| image:: https://img.shields.io/github/license/openedx/frontend-app-ora-grading.svg
:target: https://github.com/openedx/frontend-app-ora-grading/blob/master/LICENSE
:alt: License
.. |status-badge| image:: https://img.shields.io/badge/Status-Maintained-brightgreen

View File

@@ -1,19 +0,0 @@
# This file records information about this repo. Its use is described in OEP-55:
# https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: 'frontend-app-ora-grading'
description: "Frontend grading experience for Open Response Assessments (ORAs)"
links:
- url: "https://ora-grading.edx.org"
title: "Production Site"
icon: "Web"
- url: "https://ora-grading.stage.edx.org"
title: "Stage Site"
icon: "Web"
spec:
owner: group:content-aurora
type: 'website'
lifecycle: 'production'

36446
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -25,21 +25,21 @@
},
"dependencies": {
"@edx/brand": "npm:@edx/brand-edx.org@^2.0.3",
"@edx/frontend-component-footer": "^12.0.0",
"@edx/frontend-component-header": "^4.2.2",
"@edx/frontend-platform": "^4.6.1",
"@edx/paragon": "^20.30.0",
"@edx/frontend-component-footer": "^11.1.1",
"@edx/frontend-component-header": "^3.1.1",
"@edx/frontend-platform": "^2.5.1",
"@edx/paragon": "^19.9.0",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.2.0",
"@fortawesome/react-fontawesome": "^0.1.15",
"@redux-beacon/segment": "^1.1.0",
"@reduxjs/toolkit": "^1.6.1",
"@testing-library/user-event": "^14.0.0",
"@testing-library/user-event": "^13.5.0",
"@zip.js/zip.js": "^2.4.6",
"axios": "^0.27.0",
"axios": "^0.21.4",
"classnames": "^2.3.1",
"core-js": "3.31.1",
"core-js": "3.16.2",
"dompurify": "^2.3.1",
"email-prop-type": "^3.0.1",
"enzyme": "^3.11.0",
@@ -47,43 +47,42 @@
"file-saver": "^2.0.5",
"filesize": "^8.0.6",
"font-awesome": "4.7.0",
"history": "5.3.0",
"history": "5.0.1",
"html-react-parser": "^1.3.0",
"lodash": "^4.17.21",
"moment": "^2.29.3",
"prop-types": "15.8.1",
"query-string": "7.1.3",
"prop-types": "15.7.2",
"query-string": "7.0.1",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-helmet": "^6.1.0",
"react-intl": "^5.20.9",
"react-pdf": "^5.5.0",
"react-redux": "^7.2.4",
"react-router": "5.3.4",
"react-router-dom": "5.3.4",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-router-redux": "^5.0.0-alpha.9",
"redux": "4.2.1",
"redux": "4.1.1",
"redux-beacon": "^2.1.0",
"redux-devtools-extension": "2.13.9",
"redux-logger": "3.0.6",
"redux-thunk": "2.4.2",
"redux-thunk": "2.3.0",
"regenerator-runtime": "^0.13.9",
"reselect": "^4.0.0",
"util": "^0.12.4",
"whatwg-fetch": "^3.6.2"
},
"devDependencies": {
"@edx/browserslist-config": "^1.2.0",
"@edx/frontend-build": "^12.9.0-alpha.1",
"@edx/frontend-build": "12.4",
"@edx/reactifex": "^2.1.1",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.5",
"@testing-library/react": "^12.1.0",
"axios-mock-adapter": "^1.20.0",
"enzyme-adapter-react-16": "^1.15.6",
"fetch-mock": "^9.11.0",
"husky": "^7.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "29.6.1",
"jest": "27.0.6",
"jest-expect-message": "^1.0.2",
"react-dev-utils": "^12.0.1",
"react-test-renderer": "^16.14.0",

View File

@@ -1,34 +0,0 @@
{
"extends": [
"config:base",
"schedule:weekly",
":automergeLinters",
":automergeMinor",
":automergeTesters",
":enableVulnerabilityAlerts",
":rebaseStalePrs",
":semanticCommits",
":updateNotScheduled"
],
"packageRules": [
{
"matchDepTypes": [
"devDependencies"
],
"matchUpdateTypes": [
"lockFileMaintenance",
"minor",
"patch",
"pin"
],
"automerge": true
},
{
"matchPackagePatterns": ["@edx", "@openedx"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
}
],
"timezone": "America/New_York",
"schedule": ["before 11pm"]
}

View File

@@ -7,17 +7,29 @@ exports[`app registry subscribe: APP_INIT_ERROR. snapshot: displays an ErrorPag
`;
exports[`app registry subscribe: APP_READY. links App to root element 1`] = `
<AppProvider
store={
Object {
"dispatch": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
Symbol(Symbol.observable): [Function],
}
}
<IntlProvider
defaultFormats={Object {}}
defaultLocale="en"
fallbackOnEmptyString={true}
formats={Object {}}
locale="en"
messages={Object {}}
onError={[Function]}
onWarn={[Function]}
textComponent={Symbol(react.fragment)}
>
<App />
</AppProvider>
<AppProvider
store={
Object {
"dispatch": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
Symbol(Symbol.observable): [Function],
}
}
>
<App />
</AppProvider>
</IntlProvider>
`;

View File

@@ -81,12 +81,13 @@ describe('Text file preview hooks', () => {
});
});
describe('onError', () => {
it('calls get on the passed url when it changes', async () => {
it('calls get on the passed url when it changes', async (done) => {
axios.get.mockReturnValueOnce(Promise.reject(
{ response: { status: testValue } },
));
await hooks.fetchFile({ ...props, setContent: state.setState.content });
expect(props.onError).toHaveBeenCalledWith(testValue);
done();
});
});
});

View File

@@ -26,7 +26,7 @@ export const FileInfo = ({ onClick, children }) => (
)}
>
<Button
size="sm"
size="small"
variant="tertiary"
onClick={onClick}
iconAfter={InfoOutline}

View File

@@ -21,7 +21,7 @@ exports[`File Preview Card component snapshot 1`] = `
<Button
iconAfter={[MockFunction icons.InfoOutline]}
onClick={[MockFunction this.props.onClick]}
size="sm"
size="small"
variant="tertiary"
>
<FormattedMessage

View File

@@ -32,7 +32,7 @@ validation.criteria = createSelector(
criterion.feedback === feedbackRequirement.required
&& gradingData.criteria[index].feedback === ''
),
selectedOption: rubricConfig.criteria[index].options.length === 0 || gradingData.criteria[index].selectedOption !== '',
selectedOption: gradingData.criteria[index].selectedOption !== '',
})),
);

View File

@@ -64,8 +64,8 @@ describe('validation grading selectors unit tests', () => {
expect(preSelectors).toEqual([selected.gradingData, appSelectors.rubric.config]);
});
describe('returned object', () => {
const feedbackOptional = { feedback: feedbackRequirement.optional, options: [1] };
const feedbackRequired = { feedback: feedbackRequirement.required, options: [1] };
const feedbackOptional = { feedback: feedbackRequirement.optional };
const feedbackRequired = { feedback: feedbackRequirement.required };
describe('feedback', () => {
const validFeedback = { feedback: 'Fair' };
const emptyFeedback = { feedback: '' };
@@ -85,14 +85,6 @@ describe('validation grading selectors unit tests', () => {
);
expect(output.map(({ selectedOption }) => selectedOption)).toEqual([true, false]);
});
it('returns true criteria options are empty', () => {
const emptyOptionsFeedback = { ...feedbackOptional, options: [] };
const output = cb(
{ criteria: [{ selectedOption: '' }, { selectedOption: 'Invalid' }] },
{ criteria: [emptyOptionsFeedback, emptyOptionsFeedback] },
);
expect(output.map(({ selectedOption }) => selectedOption)).toEqual([true, true]);
});
});
});
});

View File

@@ -1,7 +1,3 @@
import { messages as footerMessages } from '@edx/frontend-component-footer';
import { messages as headerMesssages } from '@edx/frontend-component-header';
import { messages as paragonMessages } from '@edx/paragon';
import arMessages from './messages/ar.json';
// no need to import en messages-- they are in the defaultMessage field
import es419Messages from './messages/es_419.json';
@@ -15,7 +11,7 @@ import ptptMessages from './messages/pt_PT.json';
import ruMessages from './messages/ru.json';
import ukMessages from './messages/uk.json';
const appMessages = {
const messages = {
ar: arMessages,
'es-419': es419Messages,
fr: frMessages,
@@ -29,9 +25,4 @@ const appMessages = {
uk: ukMessages,
};
export default [
headerMesssages,
footerMessages,
paragonMessages,
appMessages,
];
export default messages;

View File

@@ -1,105 +1,105 @@
{
"ora-grading.demoAlert.warningMessage": "A submissão de classificações está desativada no modo Demonstração no novo ORA Staff Grader.",
"ora-grading.demoAlert.confirm": "Confirmar",
"ora-grading.demoAlert.title": "Submissão impedida no modo de Demonstração",
"ora-grading.FilePopoverContent.filePopoverNameTitle": "Nome do ficheiro",
"ora-grading.FilePopoverCellContent.filePopoverDescriptionTitle": "Descrição do Ficheiro",
"ora-grading.FilePopoverCellContent.fileSizeTitle": "Tamanho do Ficheiro",
"ora-grading.InfoPopover.fileInfo": "Informações do Ficheiro",
"ora-grading.ResponseDisplay.FileRenderer.retryButton": "Tentar novamente",
"ora-grading.ResponseDisplay.FileRenderer.fileNotFound": "Ficheiro não encontrado",
"ora-grading.ResponseDisplay.FileRenderer.unknownError": "Erros desconhecidos",
"PageTitle": "Classificação pela equipa no ORA {siteName}",
"ora-grading.InfoPopover.alt-text": "Mostrar mais informações",
"ora-grading.CriterionFeedback.addCommentsLabel": "Adicionar comentários",
"ora-grading.CriterionFeedback.commentsLabel": "Comentários",
"ora-grading.CriterionFeedback.optional": "(Opcional)",
"ora-grading.RadioCriterion.optionPoints": "{points} pontos",
"ora-grading.RadioCriterion.rubricSelectedError": "A seleção de rúbricas é necessária",
"ora-grading.CriterionFeedback.criterionFeedbackError": "O feedback é obrigatório",
"ora-grading.CTA.feedbackMessage": "Obrigado por utilizar a nova experiência de classificação pela equipa do ORA.",
"ora-grading.CTA.linkMessage": "Forneça algum tipo de feedback",
"ora-grading.CTA.letUsKnowMessage": "e deixe-nos a sua opinião!",
"ora-grading.ReviewModal.demoHeading": "Modo de Demonstração",
"ora-grading.ReviewModal.demoMessage": "Está a fazer uma demonstração da nova experiência de classificação de equipa do ORA. Não poderá submeter as classificações até ativar a funcionalidade. Esta tornar-se-á a experiência de classificação padrão a 9 de Maio (09/05/2022). Para optar por entrar mais cedo, ou optar por sair, contacte o Apoio ao Parceiro.",
"ora-grading.ListView.ListViewBreadcrumbs.backToResponses": "Voltar a todas as respostas abertas",
"ora-grading.ListView.noResultsFoundTitle": "Ainda não há aqui nada",
"ora-grading.ListView.noResultsFoundBody": "Quando os estudantes submeterem as respostas, elas aparecerão aqui",
"ora-grading.ListView.viewAllResponses": "Ver todas as respostas",
"ora-grading.ListView.viewSelectedResponses": "Ver as respostas selecionadas ({value})",
"ora-grading.ListView.tableHeaders.username": "Nome de utilizador",
"ora-grading.ListView.tableHeaders.teamName": "Nome da equipa",
"ora-grading.ListView.tableHeaders.learnerSubmissionDate": "Data de submissão do estudante",
"ora-grading.ListView.tableHeaders.teamSubmissionDate": "Data de submissão da equipa",
"ora-grading.ListView.tableHeaders.grade": "Classificação",
"ora-grading.ListView.tableHeaders.gradingStatus": "Estado de classificação",
"ora-grading.ListView.loadErrorHeading": "Erro ao carregar as submissões",
"ora-grading.ListView.loadErrorMessage1": "Ocorreu um erro ao carregar as submissões para esta resposta. Tente recarregar a página ou ir {backToResponses}.",
"ora-grading.ListView.backToResponsesLowercase": "voltar a todas as Respostas Abertas",
"ora-grading.ListView.reloadSubmissions": "Recarregar submissões",
"ora-grading.ListView.loadingResponses": "A carregar respostas",
"ora-grading.ResponseDisplay.FilePopoverCell.filePopoverNameTitle": "Nome do Ficheiro",
"ora-grading.ResponseDisplay.FilePopoverCell.filePopoverDescriptionTitle": "Descrição do Ficheiro",
"ora-grading.ResponseDisplay.SubmissionFiles.tableNameHeader": "Nome",
"ora-grading.ResponseDisplay.SubmissionFiles.tableExtensionHeader": "Extensão do Ficheiro",
"ora-grading.ResponseDisplay.SubmissionFiles.tablePopoverHeader": "Metadados do Ficheiro",
"ora-grading.ResponseDisplay.SubmissionFiles.downloadFiles": "Transferir ficheiros",
"ora-grading.ResponseDisplay.SubmissionFiles.downloading": "A transferir",
"ora-grading.ResponseDisplay.SubmissionFiles.downloaded": "Transferido!",
"ora-grading.ResponseDisplay.SubmissionFiles.retryDownload": "Repetir a transferência",
"ora-grading.ResponseDisplay.SubmissionFiles.submissionFile": "Submissão de Ficheiros",
"ora-grading.ResponseDisplay.SubmissionFiles.fileSizeExceed": "Excedeu o limite de tamanho de download",
"ora-grading.ReviewActions.overrideConfirmTitle": "Tem a certeza de que quer substituir esta classificação?",
"ora-grading.ReviewActions.overrideConfirmWarning": "Isto não pode ser desfeito. O estudante pode já ter recebido a sua classificação.",
"ora-grading.ReviewActions.overrideConfirmContinue": "Continuar a substituição da classificação",
"ora-grading.ReviewActions.StartGradingButton.startGrading": "Iniciar a classificação",
"ora-grading.ReviewActions.StartGradingButton.overrideGrade": "Substituir a classificação",
"ora-grading.ReviewActions.StartGradingButton.stopGrading": "Parar de classificar esta resposta",
"ora-grading.ReviewActions.StopGradingConfirmModal.override.title": "Tem a certeza de que quer parar a substituição da classificação?",
"ora-grading.ReviewActions.StopGradingConfirmModal.title": "Tem a certeza de que quer parar de classificar esta resposta?",
"ora-grading.ReviewActions.StopGradingConfirmModal.warning": "O seu progresso será perdido.",
"ora-grading.ReviewActions.StopGradingConfirmModal.override.confirmText": "Parar a substituição da classificação",
"ora-grading.ReviewActions.StopGradingConfirmModal.confirmText": "Cancelar a classificação",
"ora-grading.ReviewActions.goBack": "Voltar Atrás",
"ora-grading.ReviewActions.loadPrevious": "Carregar a submissão anterior",
"ora-grading.ReviewActions.loadNext": "Carregar a próxima submissão",
"ora-grading.ReviewActions.navigationLabel": "{current} de {total}",
"ora-grading.ReviewActions.pointsDisplay": "Pontuação: {pointsEarned}/{pointsPossible}",
"ora-grading.ReviewActions.hideRubric": "Ocultar Rúbrica",
"ora-grading.ReviewActions.showRubric": "Mostrar Rúbrica",
"ora-grading.ReviewModal.closeReviewConfirm.title": "Tem a certeza de que quer fechar este modal?",
"ora-grading.ReviewModal.closeReviewConfirmWarning": "Isto não pode ser desfeito. Isto irá desfazer o trabalho que não guardou e parar este processo de classificação.",
"ora-grading.ReviewModal.goBack": "Voltar atrás",
"ora-grading.ReviewModal.CloseReviewConfirmModal.confirmText": "Fechar Modal",
"ora-grading.ReviewModal.loadingResponse": "A carregar resposta",
"ora-grading.ReviewModal.demoTitleMessage": "Demonstração de Avaliação",
"ora-grading.ReviewModal.loadErrorHeading": "Erro ao carregar submissões",
"ora-grading.ReviewModal.loadErrorMessage1": "Ocorreu um erro ao carregar esta submissão. Tente recarregar esta submissão.",
"ora-grading.ReviewModal.reloadSubmission": "Recarregar a submissão",
"ora-grading.ReviewModal.gradeNotSubmitted.heading": "Classificação não submetida",
"ora-grading.ReviewModal.gradeNotSubmitted.Content": "Lamentamos, algo correu mal quando tentámos submeter esta classificação. Por favor, tente novamente.",
"ora-grading.ReviewModal.resubmitGrade": "Voltar a submeter a grelha",
"ora-grading.ReviewModal.dismiss": "Ignorar",
"ora-grading.ReviewModal.errorSubmittingGrade.Heading": "Erro ao submeter classificação",
"ora-grading.ReviewModal.errorSubmittingGrade.Content": "Parece que outra pessoa chegou aqui primeiro! A sua submissão de classificações foi rejeitada",
"ora-grading.ReviewModal.errorLockContestedHeading": "O bloqueio pertencente a outro utilizador",
"ora-grading.ReviewModal.errorLockContested": "O bloqueio pertencente a outro utilizador",
"ora-grading.ReviewModal.errorLockBadRequestHeading": "Pedido inválido. Por favor, verifique a sua entrada.",
"ora-grading.ReviewModal.errorLockBadRequest": "Pedido inválido. Por favor, verifique a sua entrada.",
"ora-grading.ReviewModal.errorDownloadFailed": "Não foi possível transferir os ficheiros",
"ora-grading.ReviewModal.errorDownloadFailedContent": "Lamentamos, mas algo correu mal quando tentámos transferir estes ficheiros. Por favor, tente novamente.",
"ora-grading.ReviewModal.errorRetryDownload": "Repetir a transferência",
"ora-grading.ReviewModal.errorDownloadFailedFiles": "Ficheiros com falhas:",
"ora-grading.Rubric.gradeSubmitted": "Classificação Submetida",
"ora-grading.Rubric.rubric": "Rúbrica",
"ora-grading.Rubric.submitGrade": "Submeter classificação",
"ora-grading.Rubric.submittingGrade": "A submeter classificação",
"ora-grading.Rubric.overallComments": "Comentários gerais",
"ora-grading.Rubric.addComments": "Adicionar comentários (Opcional)",
"ora-grading.Rubric.comments": "Comentários (Opcional)",
"ora-grading.RubricFeedback.error": "O comentário geral é obrigatório",
"ora-grading.lms-api.gradingStatusDisplay.ungraded": "Não classificado",
"ora-grading.lms-api.gradingStatusDisplay.locked": "A ser classificado por outra pessoa neste momento",
"ora-grading.lms-api.gradingStatusDisplay.graded": "Avaliação Concluída",
"ora-grading.lms-api.gradingStatusDisplay.inProgress": "Está a classificar esta resposta neste momento"
"ora-grading.demoAlert.warningMessage": "Grade submission is disabled in the Demo mode of the new ORA Staff Grader.",
"ora-grading.demoAlert.confirm": "Confirm",
"ora-grading.demoAlert.title": "Demo submit prevented",
"ora-grading.FilePopoverContent.filePopoverNameTitle": "File Name",
"ora-grading.FilePopoverCellContent.filePopoverDescriptionTitle": "File Description",
"ora-grading.FilePopoverCellContent.fileSizeTitle": "File Size",
"ora-grading.InfoPopover.fileInfo": "File info",
"ora-grading.ResponseDisplay.FileRenderer.retryButton": "Retry",
"ora-grading.ResponseDisplay.FileRenderer.fileNotFound": "File not found",
"ora-grading.ResponseDisplay.FileRenderer.unknownError": "Unknown errors",
"PageTitle": "ORA staff grading | {siteName}",
"ora-grading.InfoPopover.alt-text": "Display more info",
"ora-grading.CriterionFeedback.addCommentsLabel": "Add comments",
"ora-grading.CriterionFeedback.commentsLabel": "Comments",
"ora-grading.CriterionFeedback.optional": "(Optional)",
"ora-grading.RadioCriterion.optionPoints": "{points} points",
"ora-grading.RadioCriterion.rubricSelectedError": "Rubric selection is required",
"ora-grading.CriterionFeedback.criterionFeedbackError": "The feedback is required",
"ora-grading.CTA.feedbackMessage": "Thanks for using the new ORA staff grading experience. ",
"ora-grading.CTA.linkMessage": "Provide some feedback",
"ora-grading.CTA.letUsKnowMessage": " and let us know what you think!",
"ora-grading.ReviewModal.demoHeading": "Demo Mode",
"ora-grading.ReviewModal.demoMessage": "You are demoing the new ORA staff grading experience. You will be unable to submit grades until you activate the feature. This will become the default grading experience on May 9th (05/09/2022). To opt-in early, or opt-out, please contact Partner Support.",
"ora-grading.ListView.ListViewBreadcrumbs.backToResponses": "Back to all open responses",
"ora-grading.ListView.noResultsFoundTitle": "Nothing here yet",
"ora-grading.ListView.noResultsFoundBody": "When learners submit responses, they will appear here",
"ora-grading.ListView.viewAllResponses": "View all responses",
"ora-grading.ListView.viewSelectedResponses": "View selected responses ({value})",
"ora-grading.ListView.tableHeaders.username": "Username",
"ora-grading.ListView.tableHeaders.teamName": "Team name",
"ora-grading.ListView.tableHeaders.learnerSubmissionDate": "Learner submission date",
"ora-grading.ListView.tableHeaders.teamSubmissionDate": "Team submission date",
"ora-grading.ListView.tableHeaders.grade": "Grade",
"ora-grading.ListView.tableHeaders.gradingStatus": "Grading status",
"ora-grading.ListView.loadErrorHeading": "Error loading submissions",
"ora-grading.ListView.loadErrorMessage1": "An error occurred while loading the submissions for this response. Try reloading the page or going {backToResponses}.",
"ora-grading.ListView.backToResponsesLowercase": "back to all Open Responses",
"ora-grading.ListView.reloadSubmissions": "Reload submissions",
"ora-grading.ListView.loadingResponses": "Loading responses",
"ora-grading.ResponseDisplay.FilePopoverCell.filePopoverNameTitle": "File Name",
"ora-grading.ResponseDisplay.FilePopoverCell.filePopoverDescriptionTitle": "File Description",
"ora-grading.ResponseDisplay.SubmissionFiles.tableNameHeader": "Name",
"ora-grading.ResponseDisplay.SubmissionFiles.tableExtensionHeader": "File Extension",
"ora-grading.ResponseDisplay.SubmissionFiles.tablePopoverHeader": "File Metadata",
"ora-grading.ResponseDisplay.SubmissionFiles.downloadFiles": "Download files",
"ora-grading.ResponseDisplay.SubmissionFiles.downloading": "Downloading",
"ora-grading.ResponseDisplay.SubmissionFiles.downloaded": "Downloaded!",
"ora-grading.ResponseDisplay.SubmissionFiles.retryDownload": "Retry download",
"ora-grading.ResponseDisplay.SubmissionFiles.submissionFile": "Submission Files",
"ora-grading.ResponseDisplay.SubmissionFiles.fileSizeExceed": "Exceeded the allow download size",
"ora-grading.ReviewActions.overrideConfirmTitle": "Are you sure you want to override this grade?",
"ora-grading.ReviewActions.overrideConfirmWarning": "This cannot be undone. The learner may have already received their grade.",
"ora-grading.ReviewActions.overrideConfirmContinue": "Continue grade override",
"ora-grading.ReviewActions.StartGradingButton.startGrading": "Start grading",
"ora-grading.ReviewActions.StartGradingButton.overrideGrade": "Override grade",
"ora-grading.ReviewActions.StartGradingButton.stopGrading": "Stop grading this response",
"ora-grading.ReviewActions.StopGradingConfirmModal.override.title": "Are you sure you want to stop grade override?",
"ora-grading.ReviewActions.StopGradingConfirmModal.title": "Are you sure you want to stop grading this response?",
"ora-grading.ReviewActions.StopGradingConfirmModal.warning": "Your progress will be lost.",
"ora-grading.ReviewActions.StopGradingConfirmModal.override.confirmText": "Stop grade override",
"ora-grading.ReviewActions.StopGradingConfirmModal.confirmText": "Cancel grading",
"ora-grading.ReviewActions.goBack": "Go back",
"ora-grading.ReviewActions.loadPrevious": "Load previous submission",
"ora-grading.ReviewActions.loadNext": "Load next submission",
"ora-grading.ReviewActions.navigationLabel": "{current} of {total}",
"ora-grading.ReviewActions.pointsDisplay": "Score: {pointsEarned}/{pointsPossible}",
"ora-grading.ReviewActions.hideRubric": "Hide Rubric",
"ora-grading.ReviewActions.showRubric": "Show Rubric",
"ora-grading.ReviewModal.closeReviewConfirm.title": "Are you sure you want to close this modal?",
"ora-grading.ReviewModal.closeReviewConfirmWarning": "This cannot be undone. This will discard unsaved work and stop this grading process.",
"ora-grading.ReviewModal.goBack": "Go back",
"ora-grading.ReviewModal.CloseReviewConfirmModal.confirmText": "Close Modal",
"ora-grading.ReviewModal.loadingResponse": "Loading response",
"ora-grading.ReviewModal.demoTitleMessage": "Grading Demo",
"ora-grading.ReviewModal.loadErrorHeading": "Error loading submissions",
"ora-grading.ReviewModal.loadErrorMessage1": "An error occurred while loading this submission. Try reloading this submission.",
"ora-grading.ReviewModal.reloadSubmission": "Reload submission",
"ora-grading.ReviewModal.gradeNotSubmitted.heading": "Grade not submitted",
"ora-grading.ReviewModal.gradeNotSubmitted.Content": "We're sorry, something went wrong when we tried to submit this grade. Please try again.",
"ora-grading.ReviewModal.resubmitGrade": "Resubmit grate",
"ora-grading.ReviewModal.dismiss": "Dismiss",
"ora-grading.ReviewModal.errorSubmittingGrade.Heading": "Error submitting grade",
"ora-grading.ReviewModal.errorSubmittingGrade.Content": "It looks like someone else got here first! Your grade submission has been rejected",
"ora-grading.ReviewModal.errorLockContestedHeading": "The lock owned by another user",
"ora-grading.ReviewModal.errorLockContested": "The lock owned by another user",
"ora-grading.ReviewModal.errorLockBadRequestHeading": "Invalid request. Please check your input.",
"ora-grading.ReviewModal.errorLockBadRequest": "Invalid request. Please check your input.",
"ora-grading.ReviewModal.errorDownloadFailed": "Couldn't download files",
"ora-grading.ReviewModal.errorDownloadFailedContent": "We're sorry, something went wrong when we tried to download these files. Please try again.",
"ora-grading.ReviewModal.errorRetryDownload": "Retry download",
"ora-grading.ReviewModal.errorDownloadFailedFiles": "Failed files:",
"ora-grading.Rubric.gradeSubmitted": "Grade Submitted",
"ora-grading.Rubric.rubric": "Rubric",
"ora-grading.Rubric.submitGrade": "Submit grade",
"ora-grading.Rubric.submittingGrade": "Submitting grade",
"ora-grading.Rubric.overallComments": "Overall comments",
"ora-grading.Rubric.addComments": "Add comments (Optional)",
"ora-grading.Rubric.comments": "Comments (Optional)",
"ora-grading.RubricFeedback.error": "The overall feedback is required",
"ora-grading.lms-api.gradingStatusDisplay.ungraded": "Ungraded",
"ora-grading.lms-api.gradingStatusDisplay.locked": "Currently being graded by someone else",
"ora-grading.lms-api.gradingStatusDisplay.graded": "Grading Completed",
"ora-grading.lms-api.gradingStatusDisplay.inProgress": "You are currently grading this response"
}

View File

@@ -15,15 +15,22 @@ import {
mergeConfig,
} from '@edx/frontend-platform';
import { messages as footerMessages } from '@edx/frontend-component-footer';
import { messages as headerMesssages } from '@edx/frontend-component-header';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import messages from './i18n';
import App from './App';
subscribe(APP_READY, () => {
ReactDOM.render(
<AppProvider store={store}>
<App />
</AppProvider>,
<IntlProvider locale="en">
<AppProvider store={store}>
<App />
</AppProvider>
</IntlProvider>,
document.getElementById('root'),
);
});
@@ -45,6 +52,10 @@ initialize({
}, appName);
},
},
messages,
messages: [
messages,
headerMesssages,
footerMessages,
],
requireAuthenticatedUser: true,
});

View File

@@ -8,7 +8,10 @@ import {
subscribe,
} from '@edx/frontend-platform';
import messages from './i18n';
import { messages as footerMessages } from '@edx/frontend-component-footer';
import { messages as headerMesssages } from '@edx/frontend-component-header';
import appMessages from './i18n';
import * as app from '.';
jest.mock('react-dom', () => ({
@@ -67,7 +70,7 @@ describe('app registry', () => {
test('initialize is called with footerMessages and requireAuthenticatedUser', () => {
expect(initialize).toHaveBeenCalledTimes(1);
const initializeArg = initialize.mock.calls[0][0];
expect(initializeArg.messages).toEqual(messages);
expect(initializeArg.messages).toEqual([appMessages, headerMesssages, footerMessages]);
expect(initializeArg.requireAuthenticatedUser).toEqual(true);
});
test('initialize config loads support url if available', () => {

View File

@@ -40,11 +40,6 @@ jest.mock('@edx/frontend-platform/auth', () => ({
getLoginRedirectUrl: jest.fn(),
}));
jest.mock('@edx/frontend-component-header', () => ({
LearningHeader: () => 'Header',
}));
// jest.mock('@edx/frontend-component-footer', () => () => 'Footer');
jest.mock('react-pdf', () => ({
Document: () => <div>Document</div>,
Image: () => <div>Image</div>,
@@ -191,12 +186,8 @@ const initialize = async () => {
* Wait for the review page to show and update the top-level state object.
*/
const makeTableSelections = async () => {
[0, 1, 2, 3, 4].forEach(
index => userEvent.click(inspector.listView.listCheckbox(index))
);
await inspector.find.listView.selectedBtn(5);
await userEvent.click(inspector.listView.selectedBtn(5));
[0, 1, 2, 3, 4].forEach(index => userEvent.click(inspector.listView.listCheckbox(index)));
userEvent.click(inspector.listView.selectedBtn(5));
// wait for navigation, which will show while request is pending
try {
await inspector.find.review.prevNav();
@@ -222,7 +213,7 @@ describe('ESG app integration tests', () => {
inspector = new Inspector(el);
});
test('initialization', async () => {
test('initialization', async (done) => {
const verifyInitialState = async () => {
await waitForRequestStatus(RequestKeys.initialize, RequestStates.pending);
const testInitialState = (key) => expect(
@@ -284,6 +275,7 @@ describe('ESG app integration tests', () => {
await makeTableSelections();
await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.pending);
done();
});
describe('initialized', () => {
@@ -294,7 +286,7 @@ describe('ESG app integration tests', () => {
await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.pending);
});
test('initial review state', async () => {
test('initial review state', async (done) => {
// Make table selection and load Review pane
expect(
state.grading.selection,
@@ -312,9 +304,10 @@ describe('ESG app integration tests', () => {
inspector.review.loadingResponse(),
'Loading Responses pending state text should be displayed in the ReviewModal',
).toBeVisible();
done();
});
test('fetch network error and retry', async () => {
test('fetch network error and retry', async (done) => {
await resolveFns.fetch.networkError();
await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.failed);
expect(
@@ -324,9 +317,10 @@ describe('ESG app integration tests', () => {
// fetch: retry and succeed
await userEvent.click(inspector.review.retryFetchLink());
await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.pending);
done()
});
test('fetch success and nav chain', async () => {
test('fetch success and nav chain', async (done) => {
let showRubric = false;
// fetch: success with chained navigation
const verifyFetchSuccess = async (submissionIndex) => {
@@ -402,6 +396,7 @@ describe('ESG app integration tests', () => {
await userEvent.click(inspector.review.prevNav());
await verifyFetchSuccess(i);
}
done();
});
describe('grading (basic)', () => {
@@ -421,7 +416,7 @@ describe('ESG app integration tests', () => {
const overallFeedback = 'some overall feedback';
// Set basic grade and feedback
const setGrade = async () => {
const setGrade = async (done) => {
const {
criterionOption,
criterionFeedback,
@@ -484,25 +479,26 @@ describe('ESG app integration tests', () => {
await resolveFns.lock.success();
}
/*
test('submit pending', async () => {
test('submit pending', async (done) => {
done();
});
test('submit failed', async () => {
test('submit failed', async (done) => {
done();
});
*/
test('grade and submit',
async () => {
async (done) => {
expect(await inspector.find.review.submitGradeBtn()).toBeVisible();
await setGrade();
checkGradingState();
await userEvent.click(inspector.review.rubric.submitGradeBtn());
await resolveFns.updateGrade.success();
checkGradeSuccess();
done();
},
);
test('grade, navigate, and return, maintaining gradingState',
async () => {
async (done) => {
expect(await inspector.find.review.submitGradeBtn()).toBeVisible();
await setGrade();
checkGradingState();
@@ -511,6 +507,7 @@ describe('ESG app integration tests', () => {
await loadPrev();
await waitForEqual(() => getState().grading.activeIndex, 0, 'activeIndex');
checkGradingState();
done();
},
);
});

View File

@@ -92,7 +92,6 @@ class Inspector {
return {
listView: {
viewAllResponsesBtn: () => this.findByText(appMessages.ListView.viewAllResponses),
selectedBtn: (num) => this.findByText(`View selected responses (${num})`),
loadErrorHeading: () => this.findByText(appMessages.ListView.loadErrorHeading),
},
review: {