prompt",
- }
- }
- />
-
-`;
diff --git a/src/components/Prompt/index.test.jsx b/src/components/Prompt/index.test.jsx
deleted file mode 100644
index 627e22f4..00000000
--- a/src/components/Prompt/index.test.jsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import { shallow } from '@edx/react-unit-test-utils';
-import Prompt from '.';
-
-import usePromptHooks from './hooks';
-
-jest.mock('./hooks', () => jest.fn());
-
-describe('
', () => {
- const props = {
- prompt: '
prompt
',
- };
- const mockHooks = (overrides) => {
- usePromptHooks.mockReturnValueOnce({
- open: true,
- toggleOpen: jest.fn().mockName('toggleOpen'),
- ...overrides,
- });
- };
- it('renders', () => {
- mockHooks();
- const wrapper = shallow(
);
- expect(wrapper.snapshot).toMatchSnapshot();
-
- expect(wrapper.instance.findByType('Collapsible')[0].props.title).toEqual('');
- });
-
- it('renders closed', () => {
- mockHooks({ open: false });
- const wrapper = shallow(
);
- expect(wrapper.snapshot).toMatchSnapshot();
-
- expect(wrapper.instance.findByType('Collapsible')[0].props.title).not.toEqual('');
- });
-});
diff --git a/src/components/Prompt/messages.js b/src/components/Prompt/messages.js
index 9436ac09..e8025084 100644
--- a/src/components/Prompt/messages.js
+++ b/src/components/Prompt/messages.js
@@ -18,7 +18,7 @@ const messages = defineMessages({
id: 'frontend-app-ora.Prompt.header.self',
},
[stepNames.peer]: {
- defaultMessage: "grade your peers' responses to the prompt below",
+ defaultMessage: "Grade your peers' responses to the prompt below",
description: 'Peer step prompt header',
id: 'frontend-app-ora.Prompt.header.peer',
},
diff --git a/src/components/StatusAlert/hooks/constants.js b/src/components/StatusAlert/hooks/constants.js
new file mode 100644
index 00000000..7dfb6ec8
--- /dev/null
+++ b/src/components/StatusAlert/hooks/constants.js
@@ -0,0 +1,23 @@
+import { CheckCircle, Info, WarningFilled } from '@edx/paragon/icons';
+
+import { stepStates } from 'constants';
+
+export const alertTypes = {
+ success: { variant: 'success', icon: CheckCircle },
+ danger: { variant: 'danger', icon: Info },
+ warning: { variant: 'warning', icon: WarningFilled },
+ light: { variant: 'light', icon: null },
+ dark: { variant: 'dark', icon: null },
+};
+
+export const alertMap = {
+ [stepStates.done]: alertTypes.success,
+ [stepStates.submitted]: alertTypes.success,
+ [stepStates.closed]: alertTypes.danger,
+ [stepStates.teamAlreadySubmitted]: alertTypes.warning,
+ [stepStates.needTeam]: alertTypes.warning,
+ [stepStates.waiting]: alertTypes.warning,
+ [stepStates.cancelled]: alertTypes.warning,
+ [stepStates.notAvailable]: alertTypes.light,
+ [stepStates.inProgress]: alertTypes.dark,
+};
diff --git a/src/components/StatusAlert/hooks/simpleAlerts.js b/src/components/StatusAlert/hooks/simpleAlerts.js
new file mode 100644
index 00000000..425bed6c
--- /dev/null
+++ b/src/components/StatusAlert/hooks/simpleAlerts.js
@@ -0,0 +1,47 @@
+import { useActiveStepName } from 'hooks/app';
+import { useExitAction } from 'hooks/actions';
+
+import { stepNames, stepStates } from 'constants';
+
+import useCreateAlert from './useCreateAlert';
+import messages from '../messages';
+
+export const useGradedAlerts = ({ step }) => ([
+ useCreateAlert({ step })({
+ message: messages.alerts.done.status,
+ heading: messages.headings.done.status,
+ }),
+]);
+
+export const useTrainingErrorAlerts = ({ step }) => ([
+ useCreateAlert({ step })({
+ message: messages.alerts.studentTraining[stepStates.trainingValidation],
+ variant: 'warning',
+ }),
+]);
+
+export const useStaffAlerts = ({ step }) => ([
+ useCreateAlert({ step })({
+ message: messages.alerts[stepNames.staff],
+ heading: messages.headings[stepNames.staff],
+ }),
+]);
+
+export const useCreateFinishedAlert = ({ step }) => {
+ const createAlert = useCreateAlert({ step });
+ return (target) => createAlert({
+ message: messages.alerts[target].finished,
+ heading: messages.headings[target].finished,
+ });
+};
+
+export const useCreateExitAlert = ({ step }) => {
+ const createAlert = useCreateAlert({ step });
+ const exitAction = useExitAction();
+ const activeStepName = useActiveStepName();
+ return (target) => createAlert({
+ message: messages.alerts[activeStepName][target],
+ heading: messages.headings[activeStepName][target],
+ actions: [exitAction],
+ });
+};
diff --git a/src/components/StatusAlert/hooks/useCancelledAlerts.js b/src/components/StatusAlert/hooks/useCancelledAlerts.js
new file mode 100644
index 00000000..5cc65b48
--- /dev/null
+++ b/src/components/StatusAlert/hooks/useCancelledAlerts.js
@@ -0,0 +1,28 @@
+import messages from '../messages';
+import useCreateAlert from './useCreateAlert';
+
+const useCancelledAlerts = ({ step }) => {
+ const createAlert = useCreateAlert({ step });
+ return (cancellationInfo) => {
+ let out = [];
+ const {
+ hasCancelled,
+ cancelledBy,
+ cancelledAt,
+ } = cancellationInfo;
+ const alertMessages = messages.alerts.submission;
+ const headingMessages = messages.headings.submission;
+ if (hasCancelled) {
+ out = [
+ createAlert({
+ message: cancelledBy ? alertMessages.cancelledBy : alertMessages.cancelledAt,
+ heading: cancelledBy ? headingMessages.cancelledBy : headingMessages.cancelledAt,
+ messageVals: { cancelledAt, cancelledBy },
+ }),
+ ];
+ }
+ return { cancelledAlerts: out, hasCancelled };
+ };
+};
+
+export default useCancelledAlerts;
diff --git a/src/components/StatusAlert/hooks/useCreateAlert.js b/src/components/StatusAlert/hooks/useCreateAlert.js
new file mode 100644
index 00000000..36b48e3d
--- /dev/null
+++ b/src/components/StatusAlert/hooks/useCreateAlert.js
@@ -0,0 +1,28 @@
+import { useIntl } from '@edx/frontend-platform/i18n';
+
+import { useStepState } from 'hooks/app';
+
+import { alertMap } from './constants';
+
+export const useAlertConfig = ({ step }) => alertMap[useStepState({ step })];
+
+const useCreateAlert = ({ step }) => {
+ const { formatMessage } = useIntl();
+ const alertConfig = useAlertConfig({ step });
+ return ({
+ heading,
+ message,
+ actions,
+ headingVals = {},
+ messageVals = {},
+ ...overrides
+ }) => ({
+ ...alertConfig,
+ message: formatMessage(message, messageVals),
+ heading: heading && formatMessage(heading, headingVals),
+ actions,
+ ...overrides,
+ });
+};
+
+export default useCreateAlert;
diff --git a/src/components/StatusAlert/hooks/useModalAlerts.js b/src/components/StatusAlert/hooks/useModalAlerts.js
new file mode 100644
index 00000000..9d2b7ddd
--- /dev/null
+++ b/src/components/StatusAlert/hooks/useModalAlerts.js
@@ -0,0 +1,47 @@
+import { useViewStep } from 'hooks/routing';
+import { useGlobalState, useHasReceivedFinalGrade } from 'hooks/app';
+import { useHasSubmitted } from 'hooks/assessment';
+
+import { stepNames, stepStates } from 'constants';
+
+import { useTrainingErrorAlerts } from './simpleAlerts';
+
+import useRevisitAlerts from './useRevisitAlerts';
+import useSuccessAlerts from './useSuccessAlerts';
+
+const useModalAlerts = ({ step, showTrainingError }) => {
+ const { stepState } = useGlobalState({ step });
+ const isDone = useHasReceivedFinalGrade();
+ const viewStep = useViewStep();
+ const hasSubmitted = useHasSubmitted();
+ const { revisitAlerts, isRevisit } = useRevisitAlerts({ step });
+ const trainingErrorAlerts = useTrainingErrorAlerts({ step });
+ const successAlerts = useSuccessAlerts({ step });
+
+ // Do nothing if in xblock view
+ if (viewStep === stepNames.xblock) {
+ return [];
+ }
+
+ // No in-progress messages unless for submitted step
+ if (stepState === stepStates.inProgress && !hasSubmitted) {
+ return [];
+ }
+ // No modal alerts for graded state
+ if (isDone) {
+ return [];
+ }
+
+ if (isRevisit) {
+ return revisitAlerts;
+ }
+ if (showTrainingError) {
+ return trainingErrorAlerts;
+ }
+ if (hasSubmitted) {
+ return successAlerts;
+ }
+ return [];
+};
+
+export default useModalAlerts;
diff --git a/src/components/StatusAlert/hooks/useModalAlerts.jsx b/src/components/StatusAlert/hooks/useModalAlerts.jsx
new file mode 100644
index 00000000..0a00a31f
--- /dev/null
+++ b/src/components/StatusAlert/hooks/useModalAlerts.jsx
@@ -0,0 +1,249 @@
+import { useIntl } from '@edx/frontend-platform/i18n';
+import { CheckCircle, Info, WarningFilled } from '@edx/paragon/icons';
+
+import { useViewStep } from 'hooks/routing';
+import {
+ useActiveStepName,
+ useGlobalState,
+ useHasReceivedFinalGrade,
+ useStepState,
+} from 'hooks/app';
+import { useHasSubmitted } from 'hooks/assessment';
+import { useExitAction, useStartStepAction } from 'hooks/actions';
+
+import { stepNames, stepStates } from 'constants';
+
+import messages from './messages';
+
+const alertTypes = {
+ success: { variant: 'success', icon: CheckCircle },
+ danger: { variant: 'danger', icon: Info },
+ warning: { variant: 'warning', icon: WarningFilled },
+ light: { variant: 'light', icon: null },
+ dark: { variant: 'dark', icon: null },
+};
+
+export const alertMap = {
+ [stepStates.done]: alertTypes.success,
+ [stepStates.submitted]: alertTypes.success,
+ [stepStates.closed]: alertTypes.danger,
+ [stepStates.teamAlreadySubmitted]: alertTypes.warning,
+ [stepStates.needTeam]: alertTypes.warning,
+ [stepStates.waiting]: alertTypes.warning,
+ [stepStates.cancelled]: alertTypes.warning,
+ [stepStates.notAvailable]: alertTypes.light,
+ [stepStates.inProgress]: alertTypes.dark,
+};
+
+export const useAlertConfig = ({ step }) => alertMap[useStepState({ step })];
+
+export const useCreateAlert = ({ step }) => {
+ const { formatMessage } = useIntl();
+ const alertConfig = useAlertConfig({ step });
+ return ({
+ heading,
+ message,
+ actions,
+ headingVals = {},
+ messageVals = {},
+ ...overrides
+ }) => ({
+ ...alertConfig,
+ message: formatMessage(message, messageVals),
+ heading: heading && formatMessage(heading, headingVals),
+ actions,
+ ...overrides,
+ });
+};
+
+export const useGradedAlerts = ({ step }) => ([
+ useAlertConfig({ step })({
+ message: messages.alerts.done.status,
+ heading: messages.headings.done.status,
+ }),
+]);
+
+export const useTrainingErrorAlerts = ({ step }) => ([
+ useAlertConfig({ step })({
+ message: messages.alerts.studentTraining[stepStates.trainingValidation],
+ variant: 'warning',
+ }),
+]);
+
+export const useStaffAlerts = ({ step }) => {
+ const activeStepName = useActiveStepName();
+ return [
+ useAlertConfig({ step })({
+ message: messages.alerts[activeStepName].staffAssessment,
+ heading: messages.headings[activeStepName].staffAssessment,
+ }),
+ ];
+};
+
+export const useCreateFinishedAlert = ({ step }) => {
+ const createAlert = useCreateAlert({ step });
+ return (target) => createAlert({
+ message: messages.alerts[target].finished,
+ heading: messages.headings[target].finished,
+ });
+};
+
+export const useCreateExitAlert = ({ step }) => {
+ const createAlert = useCreateAlert({ step });
+ const exitAction = useExitAction();
+ const activeStepName = useActiveStepName();
+ return (target) => createAlert({
+ message: messages.alerts[activeStepName][target],
+ heading: messages.headings[activeStepName][target],
+ actions: [exitAction],
+ });
+};
+
+export const useRevisitAlerts = ({ step }) => {
+ const { activeStepName, stepState } = useGlobalState({ step });
+ const viewStep = useViewStep();
+ const stepName = step || activeStepName;
+ const finishedAlert = useCreateFinishedAlert({ step });
+ const isRevisit = viewStep !== stepNames.xblock && stepName !== activeStepName;
+ let out = [];
+ if (isRevisit) {
+ if (stepName === stepNames.submission) {
+ out = [finishedAlert(stepNames.submission)];
+ } else if (stepName === stepNames.peer && stepState !== stepStates.waiting) {
+ out = [finishedAlert(stepNames.peer)];
+ }
+ }
+ return { revisitAlerts: out, isRevisit };
+};
+
+export const useSuccessAlerts = ({ step }) => {
+ const { activeStepName, activeStepState } = useGlobalState({ step });
+ const viewStep = useViewStep();
+ const hasSubmitted = useHasSubmitted();
+ const startStepAction = useStartStepAction();
+ const exitAlert = useCreateExitAlert({ step });
+
+ const createAlert = useCreateAlert({ step });
+
+ const out = [];
+ if (hasSubmitted) {
+ const successAlert = {
+ message: messages.alerts[viewStep].submitted,
+ heading: messages.headings[viewStep].submitted,
+ ...alertTypes.success,
+ };
+ if (activeStepState === stepStates.inProgress && activeStepName !== viewStep) {
+ successAlert.actions = [startStepAction];
+ }
+ out.push(createAlert(successAlert));
+
+ if (activeStepState !== stepStates.inProgress) {
+ out.push(exitAlert(activeStepState));
+ }
+ if (activeStepName === stepNames.staff) {
+ out.push(exitAlert(stepNames.staff));
+ }
+ return out;
+ }
+ return null;
+};
+
+export const useCancelledAlerts = ({ step }) => {
+ const alertConfig = useAlertConfig({ step });
+ return (cancellationInfo) => {
+ let out = null;
+ const {
+ hasCancelled,
+ cancelledBy,
+ cancelledAt,
+ } = cancellationInfo;
+ const alertMessages = messages.alerts.submission;
+ const headingMessages = messages.headings.submission;
+ if (hasCancelled) {
+ out = [
+ alertConfig({
+ message: cancelledBy ? alertMessages.cancelledBy : alertMessages.cancelledAt,
+ heading: cancelledBy ? headingMeadings.cancelledBy : headingMessages.cancelledAt,
+ messageVals: { cancelledAt, cancelledBy },
+ }),
+ ];
+ }
+ return { cancelledAlerts: out, hasCancelled };
+};
+
+export const useModalAlerts = ({ step, showTrainingError }) => {
+ const { stepState } = useGlobalState({ step });
+ const isDone = useHasReceivedFinalGrade();
+ const viewStep = useViewStep();
+ const hasSubmitted = useHasSubmitted();
+ const { revisitAlerts, isRevisit } = useRevisitAlerts({ step });
+ const trainingErrorAlerts = useTrainingErrorAlerts({ step });
+ const successAlerts = useSuccessAlerts({ step });
+
+ // Do nothing if in xblock view
+ if (viewStep === stepNames.xblock) {
+ return null;
+ }
+
+ // No in-progress messages unless for submitted step
+ if (stepState === stepStates.inProgress && !hasSubmitted) {
+ return null;
+ }
+ // No modal alerts for graded state
+ if (isDone) {
+ return null;
+ }
+
+ if (isRevisit) {
+ return revisitAlerts;
+ }
+ if (showTrainingError) {
+ return trainingErrorAlerts;
+ }
+ if (hasSubmitted) {
+ return successAlerts;
+ }
+ return null;
+};
+
+
+const useStatusAlertData = ({
+ step = null,
+ showTrainingError,
+}) => {
+ const {
+ activeStepName,
+ stepState,
+ } = useGlobalState({ step });
+ const isDone = useHasReceivedFinalGrade();
+ const viewStep = useViewStep();
+
+ const createAlert = useCreateAlert({ step });
+ const modalAlerts = useModalAlerts({ step, showTrainingError });
+ const gradedAlerts = useGradedAlerts({ step });
+ const { hasCancelled, cancelledAlerts } = useCancelledAlerts({ step });
+ const staffAlerts = useStaffAlerts({ step });
+
+ const stepName = step || activeStepName;
+
+ if (isDone) {
+ return gradedAlerts;
+ }
+ if (viewStep !== stepNames.xblock) {
+ return modalAlerts;
+ }
+ if (hasCancelled) {
+ return cancelledAlerts;
+ }
+
+ if (stepName === stepNames.staff) {
+ return staffAlerts;
+ }
+
+ return [createAlert({
+ message: messages.alerts[stepName][stepState],
+ heading: messages.headings[stepName][stepState],
+ })];
+};
+
+export default useStatusAlertData;
diff --git a/src/components/StatusAlert/hooks/useRevisitAlerts.js b/src/components/StatusAlert/hooks/useRevisitAlerts.js
new file mode 100644
index 00000000..8cdf8fdf
--- /dev/null
+++ b/src/components/StatusAlert/hooks/useRevisitAlerts.js
@@ -0,0 +1,25 @@
+import { useViewStep } from 'hooks/routing';
+import { useGlobalState } from 'hooks/app';
+
+import { stepNames, stepStates } from 'constants';
+
+import { useCreateFinishedAlert } from './simpleAlerts';
+
+const useRevisitAlerts = ({ step }) => {
+ const { activeStepName, stepState } = useGlobalState({ step });
+ const viewStep = useViewStep();
+ const stepName = step || activeStepName;
+ const finishedAlert = useCreateFinishedAlert({ step });
+ const isRevisit = viewStep !== stepNames.xblock && stepName !== activeStepName;
+ let out = [];
+ if (isRevisit) {
+ if (stepName === stepNames.submission) {
+ out = [finishedAlert(stepNames.submission)];
+ } else if (stepName === stepNames.peer && stepState !== stepStates.waiting) {
+ out = [finishedAlert(stepNames.peer)];
+ }
+ }
+ return { revisitAlerts: out, isRevisit };
+};
+
+export default useRevisitAlerts;
diff --git a/src/components/StatusAlert/hooks/useStatusAlertData.jsx b/src/components/StatusAlert/hooks/useStatusAlertData.jsx
new file mode 100644
index 00000000..d42674de
--- /dev/null
+++ b/src/components/StatusAlert/hooks/useStatusAlertData.jsx
@@ -0,0 +1,58 @@
+import { useViewStep } from 'hooks/routing';
+import { useGlobalState, useHasReceivedFinalGrade } from 'hooks/app';
+
+import { stepNames, stepStates } from 'constants';
+
+import messages from '../messages';
+import useCreateAlert from './useCreateAlert';
+import {
+ useGradedAlerts,
+ useStaffAlerts,
+} from './simpleAlerts';
+
+import useModalAlerts from './useModalAlerts';
+import useCancelledAlerts from './useCancelledAlerts';
+
+const useStatusAlertData = ({
+ step = null,
+ showTrainingError,
+}) => {
+ const {
+ activeStepName,
+ stepState,
+ } = useGlobalState({ step });
+ const isDone = useHasReceivedFinalGrade();
+ const viewStep = useViewStep();
+
+ const createAlert = useCreateAlert({ step });
+ const modalAlerts = useModalAlerts({ step, showTrainingError });
+ const gradedAlerts = useGradedAlerts({ step });
+ const { hasCancelled, cancelledAlerts } = useCancelledAlerts({ step });
+ const staffAlerts = useStaffAlerts({ step });
+
+ const stepName = step || activeStepName;
+
+ if (isDone) {
+ return gradedAlerts;
+ }
+ if (viewStep !== stepNames.xblock) {
+ return modalAlerts;
+ }
+ if (hasCancelled) {
+ return cancelledAlerts;
+ }
+
+ if (stepName === stepNames.staff) {
+ return staffAlerts;
+ }
+ if (stepState === stepStates.inProgress) {
+ return [];
+ }
+
+ return [createAlert({
+ message: messages.alerts[stepName][stepState],
+ heading: messages.headings[stepName][stepState],
+ })];
+};
+
+export default useStatusAlertData;
diff --git a/src/components/StatusAlert/hooks/useSuccessAlerts.js b/src/components/StatusAlert/hooks/useSuccessAlerts.js
new file mode 100644
index 00000000..d17fa5c9
--- /dev/null
+++ b/src/components/StatusAlert/hooks/useSuccessAlerts.js
@@ -0,0 +1,44 @@
+import { useViewStep } from 'hooks/routing';
+import { useGlobalState } from 'hooks/app';
+import { useHasSubmitted } from 'hooks/assessment';
+import { useStartStepAction } from 'hooks/actions';
+
+import { stepNames, stepStates } from 'constants';
+
+import messages from '../messages';
+import { alertTypes } from './constants';
+import useCreateAlert from './useCreateAlert';
+import { useCreateExitAlert } from './simpleAlerts';
+
+const useSuccessAlerts = ({ step }) => {
+ const { activeStepName, activeStepState } = useGlobalState({ step });
+ const viewStep = useViewStep();
+ const hasSubmitted = useHasSubmitted();
+ const startStepAction = useStartStepAction();
+ const exitAlert = useCreateExitAlert({ step });
+
+ const createAlert = useCreateAlert({ step });
+
+ const out = [];
+ if (hasSubmitted) {
+ const successAlert = {
+ message: messages.alerts[viewStep].submitted,
+ heading: messages.headings[viewStep].submitted,
+ ...alertTypes.success,
+ };
+ if (activeStepState === stepStates.inProgress && activeStepName !== viewStep) {
+ successAlert.actions = [startStepAction];
+ }
+ out.push(createAlert(successAlert));
+
+ if (activeStepState !== stepStates.inProgress) {
+ out.push(exitAlert(activeStepState));
+ }
+ if (activeStepName === stepNames.staff) {
+ out.push(exitAlert(stepNames.staff));
+ }
+ }
+ return out;
+};
+
+export default useSuccessAlerts;
diff --git a/src/components/StatusAlert/index.jsx b/src/components/StatusAlert/index.jsx
index c460eb74..bf4f42ea 100644
--- a/src/components/StatusAlert/index.jsx
+++ b/src/components/StatusAlert/index.jsx
@@ -3,8 +3,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Alert, Skeleton } from '@edx/paragon';
+import ActionButton from 'components/ActionButton';
import { useIsPageDataLoading } from 'hooks/app';
-import useStatusAlertData from './useStatusAlertData';
+import useStatusAlertData from './hooks/useStatusAlertData';
import './index.scss';
@@ -30,14 +31,14 @@ const StatusAlert = ({
icon,
heading,
message,
- actions,
+ actions = [],
}) => (
)}
>
{heading}
{message}
diff --git a/src/components/StatusAlert/messages.js b/src/components/StatusAlert/messages.js
index 07cbca4f..32be1db3 100644
--- a/src/components/StatusAlert/messages.js
+++ b/src/components/StatusAlert/messages.js
@@ -220,7 +220,7 @@ export default {
[stepNames.self]: selfHeadings,
[stepNames.peer]: peerHeadings,
[stepNames.done]: doneHeadings,
- [stepNames.staff]: staffHeadings,
+ [stepNames.staff]: staffHeadings.staffAssessment,
},
alerts: {
[stepNames.submission]: submissionAlerts,
@@ -228,7 +228,7 @@ export default {
[stepNames.self]: selfAlerts,
[stepNames.peer]: peerAlerts,
[stepNames.done]: doneAlerts,
- [stepNames.staff]: staffAlerts,
+ [stepNames.staff]: staffAlerts.staffAssessment,
},
...messages,
};
diff --git a/src/components/StatusAlert/useStatusAlertData.jsx b/src/components/StatusAlert/useStatusAlertData.jsx
deleted file mode 100644
index dc0237e1..00000000
--- a/src/components/StatusAlert/useStatusAlertData.jsx
+++ /dev/null
@@ -1,168 +0,0 @@
-import { useIntl } from '@edx/frontend-platform/i18n';
-import { CheckCircle, Info, WarningFilled } from '@edx/paragon/icons';
-import { Button } from '@edx/paragon';
-
-import { useCloseModal } from 'hooks/modal';
-import { useViewStep } from 'hooks/routing';
-import {
- useHasReceivedFinalGrade,
- useGlobalState,
-} from 'hooks/app';
-import {
- useHasSubmitted,
-} from 'hooks/assessment';
-
-import {
- stepNames,
- stepStates,
-} from 'constants';
-
-import messages from './messages';
-
-const alertTypes = {
- success: { variant: 'success', icon: CheckCircle },
- danger: { variant: 'danger', icon: Info },
- warning: { variant: 'warning', icon: WarningFilled },
- light: {
- variant: 'light',
- icon: null,
- },
- dark: {
- variant: 'dark',
- icon: null,
- },
-};
-
-export const alertMap = {
- [stepStates.done]: alertTypes.success,
- [stepStates.submitted]: alertTypes.success,
- [stepStates.closed]: alertTypes.danger,
- [stepStates.teamAlreadySubmitted]: alertTypes.warning,
- [stepStates.needTeam]: alertTypes.warning,
- [stepStates.waiting]: alertTypes.warning,
- [stepStates.cancelled]: alertTypes.warning,
- [stepStates.notAvailable]: alertTypes.light,
-};
-
-const useStatusAlertData = ({
- step = null,
- showTrainingError,
-}) => {
- const { formatMessage } = useIntl();
- const {
- activeStepName,
- activeStepState,
- cancellationInfo,
- stepState,
- } = useGlobalState({ step });
- const closeModal = useCloseModal();
- const isDone = useHasReceivedFinalGrade();
- const viewStep = useViewStep();
- const hasSubmitted = useHasSubmitted();
-
- const stepName = step || activeStepName;
- const isRevisit = stepName !== activeStepName;
-
- if (stepState === stepStates.inProgress) {
- return [];
- }
- const { variant, icon } = alertMap[stepState];
-
- const alertConfig = ({
- heading,
- message,
- actions,
- headingVals = {},
- messageVals = {},
- ...overrides
- }) => ({
- variant,
- icon,
- message: formatMessage(message, messageVals),
- heading: heading && formatMessage(heading, headingVals),
- actions,
- ...overrides,
- });
-
- if (isDone) {
- return [alertConfig({
- message: messages.alerts.done.status,
- heading: messages.headings.done.status,
- })];
- }
-
- if (viewStep !== stepNames.xblock) {
- if (showTrainingError) {
- return [alertConfig({
- message: messages.alerts.studentTraining[stepStates.trainingValidation],
- variant: 'warning',
- })];
- }
- const out = [];
- if (hasSubmitted) {
- out.push(alertConfig({
- message: messages.alerts[viewStep].submitted,
- heading: messages.headings[viewStep].submitted,
- ...alertTypes.success,
- }));
- if (activeStepState !== stepStates.inProgress) {
- out.push(alertConfig({
- message: messages.alerts[activeStepName][activeStepState],
- heading: messages.headings[activeStepName][activeStepState],
- actions: [
- ,
- ],
- }));
- }
- if (activeStepName === stepNames.staff) {
- out.push(alertConfig({
- message: messages.alerts[activeStepName].staffAssessment,
- heading: messages.headings[activeStepName].staffAssessment,
- actions: [
- ,
- ],
- }));
- }
- return out;
- }
- }
- if (cancellationInfo.hasCancelled) {
- const { cancelledBy, cancelledAt } = cancellationInfo;
- if (cancelledBy) {
- return [alertConfig({
- message: messages.alerts.submission.cancelledBy,
- messageVals: { cancelledBy, cancelledAt },
- heading: messages.headings.submission.cancelledBy,
- })];
- }
- return [alertConfig({
- message: messages.alerts.submission.cancelledAt,
- messageVals: { cancelledAt },
- heading: messages.headings.submission.cancelledAt,
- })];
- }
- if (stepName === stepNames.submission && isRevisit) {
- return [alertConfig({
- message: messages.alerts.submission.finished,
- heading: messages.headings.submission.finished,
- })];
- }
- if (stepName === stepNames.peer && isRevisit && stepState !== stepStates.waiting) {
- return [alertConfig({
- message: messages.alerts.peer.finished,
- heading: messages.headings.peer.finished,
- })];
- }
- if (stepName === stepNames.staff) {
- return [alertConfig({
- message: messages.alerts[activeStepName].staffAssessment,
- heading: messages.headings[activeStepName].staffAssessment,
- })];
- }
- return [alertConfig({
- message: messages.alerts[stepName][stepState],
- heading: messages.headings[stepName][stepState],
- })];
-};
-
-export default useStatusAlertData;
diff --git a/src/data/services/lms/hooks/selectors/index.ts b/src/data/services/lms/hooks/selectors/index.ts
index 18ab17d8..61b2f667 100644
--- a/src/data/services/lms/hooks/selectors/index.ts
+++ b/src/data/services/lms/hooks/selectors/index.ts
@@ -4,9 +4,7 @@ import {
stepNames,
closedReasons,
stepStates,
- globalStates,
-} from 'constants';
-import { useViewStep } from 'hooks/routing';
+} from 'constants/index';
import * as oraConfigSelectors from './oraConfig';
import * as pageDataSelectors from './pageData';
diff --git a/src/data/services/lms/hooks/selectors/oraConfig.ts b/src/data/services/lms/hooks/selectors/oraConfig.ts
index 81142209..2a000fec 100644
--- a/src/data/services/lms/hooks/selectors/oraConfig.ts
+++ b/src/data/services/lms/hooks/selectors/oraConfig.ts
@@ -1,7 +1,7 @@
import React from 'react';
import * as data from 'data/services/lms/hooks/data';
import * as types from 'data/services/lms/types';
-import { stepNames } from 'constants';
+import { stepNames } from 'constants/index';
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ORA Config Data
diff --git a/src/hooks/actions/messages.js b/src/hooks/actions/messages.js
index 9481151b..cab576d4 100644
--- a/src/hooks/actions/messages.js
+++ b/src/hooks/actions/messages.js
@@ -34,7 +34,7 @@ const messages = defineMessages({
},
loadNext: {
id: 'ora-mfe.ModalActions.loadNext',
- defaultMessage: 'Load next',
+ defaultMessage: 'Grade next',
description: 'Action button to load next peer response',
},
loadingNext: {
diff --git a/src/views/AssessmentView/BaseAssessmentView/index.jsx b/src/views/AssessmentView/BaseAssessmentView/index.jsx
index ac671166..64ee27ed 100644
--- a/src/views/AssessmentView/BaseAssessmentView/index.jsx
+++ b/src/views/AssessmentView/BaseAssessmentView/index.jsx
@@ -8,6 +8,7 @@ import { useShowTrainingError } from 'hooks/assessment';
import { useViewStep } from 'hooks/routing';
import Assessment from 'components/Assessment';
+import Instructions from 'components/Instructions';
import ModalActions from 'components/ModalActions';
import StatusAlert from 'components/StatusAlert';
import StepProgressIndicator from 'components/StepProgressIndicator';
@@ -30,6 +31,7 @@ const BaseAssessmentView = ({
+
{children}
diff --git a/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap b/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap
index 1048ca16..a7c71025 100644
--- a/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap
+++ b/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap
@@ -2,7 +2,7 @@
exports[` render disabled 1`] = `
render disabled 1`] = `
)
render disabled 1`] = `
exports[`
render optional 1`] = `
render optional 1`] = `
)
render optional 1`] = `
exports[`
render required 1`] = `
render required 1`] = `
)
Date: Mon, 4 Dec 2023 16:22:11 -0500
Subject: [PATCH 61/66] Responsive ui for ora (#97)
* chore: fix assessment width out of proportion for long feedback
* chore: fix typo
* chore: update progress bar responsiveness
* chore: fix active step for xblock view
* chore: make base assessment responsive
* chore: update linting
---
src/App.jsx | 2 +-
src/components/Assessment/Assessment.scss | 1 +
.../EditableAssessment/AssessmentActions.jsx | 2 +-
.../Assessment/ReadonlyAssessment/messages.js | 2 +-
src/components/Assessment/messages.js | 2 +-
src/components/CriterionContainer/messages.js | 2 +-
src/components/Instructions/messages.js | 2 +-
src/components/ProgressBar/hooks.js | 4 +-
src/components/ProgressBar/index.jsx | 41 ++-
src/components/ProgressBar/index.scss | 21 ++
src/components/Rubric/messages.js | 2 +-
.../StatusAlert/hooks/useModalAlerts.jsx | 249 ------------------
.../StatusAlert/hooks/useStatusAlertData.jsx | 2 +-
src/components/StatusAlert/messages.js | 12 +-
.../lms/fakeData/pageData/progress.js | 2 +-
.../services/lms/hooks/actions/utils.test.ts | 6 +-
.../BaseAssessmentView.scss | 13 +-
.../BaseAssessmentView/index.jsx | 8 +-
src/views/GradeView/index.jsx | 38 +--
src/views/SubmissionView/index.scss | 2 +-
src/views/XBlockView/index.scss | 4 +-
21 files changed, 114 insertions(+), 303 deletions(-)
delete mode 100644 src/components/StatusAlert/hooks/useModalAlerts.jsx
diff --git a/src/App.jsx b/src/App.jsx
index 4c27c18c..40f069e6 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -71,7 +71,7 @@ const App = () => {
modalRoute(routes.selfAssessmentEmbed, SelfAssessmentView, 'ORA Self Assessment'),
modalRoute(routes.studentTrainingEmbed, StudentTrainingView, 'ORA Student Training'),
modalRoute(routes.submissionEmbed, SubmissionView, 'ORA Submission'),
- modaleoute(routes.gradedEmbed, GradeView, 'My Grade'),
+ modalRoute(routes.gradedEmbed, GradeView, 'My Grade'),
-
diff --git a/src/views/GradeView/index.jsx b/src/views/GradeView/index.jsx
index fd705bea..8e63e7c6 100644
--- a/src/views/GradeView/index.jsx
+++ b/src/views/GradeView/index.jsx
@@ -12,24 +12,26 @@ import Content from './Content';
import './index.scss';
const GradeView = () => (
-
-
-
-
-
-
-
-
-
-
+
);
GradeView.defaultProps = {};
diff --git a/src/views/SubmissionView/index.scss b/src/views/SubmissionView/index.scss
index 93387344..106fe5ee 100644
--- a/src/views/SubmissionView/index.scss
+++ b/src/views/SubmissionView/index.scss
@@ -12,7 +12,7 @@
height: 100%;
.content-wrapper {
- min-width: min-content;
+ max-width: $max-width-lg;
}
}
diff --git a/src/views/XBlockView/index.scss b/src/views/XBlockView/index.scss
index 8fe83a09..fedcb49f 100644
--- a/src/views/XBlockView/index.scss
+++ b/src/views/XBlockView/index.scss
@@ -1,6 +1,8 @@
+@import "@edx/paragon/scss/core/core";
+
#ora-xblock-view {
max-width: 1024px;
- @media (min-width: 830px) {
+ @include media-breakpoint-down(md) {
padding-left: 40px;
padding-right: 40px;
}
From 3b493af41b745609949a5a24c90d1b8bfd1e0a8c Mon Sep 17 00:00:00 2001
From: Leangseu Kim
Date: Wed, 6 Dec 2023 11:43:00 -0500
Subject: [PATCH 62/66] chore: fix tinymce modal transparent problem
---
.../TextResponseEditor/RichTextEditor.jsx | 9 ++++++---
.../__snapshots__/RichTextEditor.test.jsx.snap | 15 +++++++++------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/views/SubmissionView/TextResponseEditor/RichTextEditor.jsx b/src/views/SubmissionView/TextResponseEditor/RichTextEditor.jsx
index 328cdaf7..9ea3db27 100644
--- a/src/views/SubmissionView/TextResponseEditor/RichTextEditor.jsx
+++ b/src/views/SubmissionView/TextResponseEditor/RichTextEditor.jsx
@@ -9,7 +9,6 @@ import 'tinymce/plugins/lists';
import 'tinymce/plugins/code';
import 'tinymce/plugins/image';
import 'tinymce/themes/silver';
-import 'tinymce/skins/ui/oxide/skin.min.css';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
@@ -43,8 +42,12 @@ const RichTextEditor = ({
init={{
menubar: false,
statusbar: false,
- skin: false,
- content_css: false,
+ // TODO: rewrite this to use skin=false and content_css=false when we figure
+ // which part of css-loader to change to stop tinymce from changing the
+ // oxide skin css.
+ base_url: `${process.env.LMS_BASE_URL}/static/js/vendor/tinymce/js/tinymce`,
+ skin: 'studio-tmce5',
+ content_css: 'studio-tmce5',
height: '300',
schema: 'html5',
plugins: 'code image link lists',
diff --git a/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap b/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap
index a7c71025..fb23e1ef 100644
--- a/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap
+++ b/src/views/SubmissionView/TextResponseEditor/__snapshots__/RichTextEditor.test.jsx.snap
@@ -17,13 +17,14 @@ exports[` render disabled 1`] = `
disabled={true}
init={
Object {
- "content_css": false,
+ "base_url": "http://localhost:18000/static/js/vendor/tinymce/js/tinymce",
+ "content_css": "studio-tmce5",
"height": "300",
"menubar": false,
"plugins": "code image link lists",
"readonly": 1,
"schema": "html5",
- "skin": false,
+ "skin": "studio-tmce5",
"statusbar": false,
"toolbar": false,
}
@@ -52,12 +53,13 @@ exports[` render optional 1`] = `
disabled={false}
init={
Object {
- "content_css": false,
+ "base_url": "http://localhost:18000/static/js/vendor/tinymce/js/tinymce",
+ "content_css": "studio-tmce5",
"height": "300",
"menubar": false,
"plugins": "code image link lists",
"schema": "html5",
- "skin": false,
+ "skin": "studio-tmce5",
"statusbar": false,
"toolbar": "formatselect | bold italic underline | link blockquote image | numlist bullist outdent indent | strikethrough | code | undo redo",
}
@@ -86,12 +88,13 @@ exports[` render required 1`] = `
disabled={false}
init={
Object {
- "content_css": false,
+ "base_url": "http://localhost:18000/static/js/vendor/tinymce/js/tinymce",
+ "content_css": "studio-tmce5",
"height": "300",
"menubar": false,
"plugins": "code image link lists",
"schema": "html5",
- "skin": false,
+ "skin": "studio-tmce5",
"statusbar": false,
"toolbar": "formatselect | bold italic underline | link blockquote image | numlist bullist outdent indent | strikethrough | code | undo redo",
}
From de12d963c9849d9cea3214df75aa35f6da5279b4 Mon Sep 17 00:00:00 2001
From: leangseu-edx <83240113+leangseu-edx@users.noreply.github.com>
Date: Wed, 6 Dec 2023 12:29:22 -0500
Subject: [PATCH 63/66] chore: update messages (#99)
* chore: update messages
* chore: add space
---
.../EditableAssessment/AssessmentActions.jsx | 8 +++++--
src/components/Assessment/messages.js | 23 +++++++++++++++++--
src/components/Assessment/types.ts | 4 +---
src/components/ModalActions/hooks/messages.js | 4 ++--
src/components/ModalActions/messages.js | 4 ++--
src/components/ProgressBar/messages.js | 4 ++--
src/components/Rubric/types.ts | 4 +---
src/hooks/actions/messages.js | 4 ++--
src/views/AssessmentView/index.jsx | 5 ++--
src/views/AssessmentView/messages.js | 2 +-
src/views/SubmissionView/messages.js | 2 +-
src/views/XBlockView/Actions/messages.js | 6 ++---
src/views/XBlockView/index.jsx | 6 ++---
13 files changed, 47 insertions(+), 29 deletions(-)
diff --git a/src/components/Assessment/EditableAssessment/AssessmentActions.jsx b/src/components/Assessment/EditableAssessment/AssessmentActions.jsx
index 4a823e07..d8618b3b 100644
--- a/src/components/Assessment/EditableAssessment/AssessmentActions.jsx
+++ b/src/components/Assessment/EditableAssessment/AssessmentActions.jsx
@@ -7,7 +7,8 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import { useCloseModal } from 'hooks/modal';
import { MutationStatus } from 'constants';
-import messages from '../messages';
+import { useViewStep } from 'hooks/routing';
+import messages, { viewStepMessages } from '../messages';
/**
*
@@ -18,6 +19,9 @@ const AssessmentActions = ({
}) => {
const closeModal = useCloseModal();
const { formatMessage } = useIntl();
+ const step = useViewStep();
+ const viewStep = viewStepMessages[step] ? `${formatMessage(viewStepMessages[step])} ` : '';
+
return (
@@ -28,7 +32,7 @@ const AssessmentActions = ({
onClick={onSubmit}
state={submitStatus}
labels={{
- [MutationStatus.idle]: formatMessage(messages.submitGrade),
+ [MutationStatus.idle]: formatMessage(messages.submitGrade, { viewStep }),
[MutationStatus.loading]: formatMessage(messages.submittingGrade),
[MutationStatus.success]: formatMessage(messages.gradeSubmitted),
}}
diff --git a/src/components/Assessment/messages.js b/src/components/Assessment/messages.js
index c175200f..1de43eda 100644
--- a/src/components/Assessment/messages.js
+++ b/src/components/Assessment/messages.js
@@ -1,4 +1,5 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
+import { stepNames } from 'constants';
const messages = defineMessages({
gradeSubmitted: {
@@ -13,7 +14,7 @@ const messages = defineMessages({
},
submitGrade: {
id: 'frontend-app-ora.EditableAssessment.submitGrade',
- defaultMessage: 'Submit grade',
+ defaultMessage: 'Submit {viewStep}grade',
description: 'Submit Grade button text',
},
submittingGrade: {
@@ -43,9 +44,27 @@ const messages = defineMessages({
},
finishLater: {
id: 'frontend-app-ora.EditableAssessment.finishLater',
- defaultMessage: 'Finish grading later',
+ defaultMessage: 'Exit without saving',
description: 'Button text for close modal action in the assessment view',
},
});
+export const viewStepMessages = defineMessages({
+ [stepNames.self]: {
+ id: 'frontend-app-ora.EditableAssessment.viewStep.self',
+ defaultMessage: 'self',
+ description: 'View step label for self assessment',
+ },
+ [stepNames.peer]: {
+ id: 'frontend-app-ora.EditableAssessment.viewStep.peer',
+ defaultMessage: 'peer',
+ description: 'View step label for peer assessment',
+ },
+ [stepNames.studentTraining]: {
+ id: 'frontend-app-ora.EditableAssessment.viewStep.studentTraining',
+ defaultMessage: 'practice',
+ description: 'View step label for student training',
+ },
+});
+
export default messages;
diff --git a/src/components/Assessment/types.ts b/src/components/Assessment/types.ts
index 48bf3aa5..de70fd82 100644
--- a/src/components/Assessment/types.ts
+++ b/src/components/Assessment/types.ts
@@ -1,4 +1,4 @@
-import { CriterionConfig, MutationStatus, RubricData } from "data/services/lms/types";
+import { CriterionConfig, MutationStatus } from "data/services/lms/types";
export type Criterion = {
optionsValue: string | null;
@@ -11,8 +11,6 @@ export type Criterion = {
} & CriterionConfig;
export type RubricHookData = {
- rubricData: RubricData;
- setRubricData: (data: RubricData) => void;
criteria: Criterion[];
onSubmit: () => void;
submitStatus: MutationStatus;
diff --git a/src/components/ModalActions/hooks/messages.js b/src/components/ModalActions/hooks/messages.js
index d86a4a5a..7a3f9920 100644
--- a/src/components/ModalActions/hooks/messages.js
+++ b/src/components/ModalActions/hooks/messages.js
@@ -3,8 +3,8 @@ import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
finishLater: {
id: 'ora-mfe.ModalActions.simpleAction.finishLater',
- defaultMessage: 'Finish later',
- description: 'Finish later (close) button text',
+ defaultMessage: 'Save for later',
+ description: 'Save for later (close) button text',
},
submitResponse: {
id: 'ora-mfe.ModalActions.submitResponse',
diff --git a/src/components/ModalActions/messages.js b/src/components/ModalActions/messages.js
index 4259ace4..a5a40429 100644
--- a/src/components/ModalActions/messages.js
+++ b/src/components/ModalActions/messages.js
@@ -29,12 +29,12 @@ const messages = defineMessages({
},
startTraining: {
id: 'ora-mfe.ModalActions.startTraining',
- defaultMessage: 'Begin practice grading',
+ defaultMessage: 'Go to practice grading',
description: 'Action button to begin studentTraining step',
},
startSelf: {
id: 'ora-mfe.ModalActions.startSelf',
- defaultMessage: 'Begin self grading',
+ defaultMessage: 'Go to self grading',
description: 'Action button to begin self assessment step',
},
startPeer: {
diff --git a/src/components/ProgressBar/messages.js b/src/components/ProgressBar/messages.js
index 9cdfc667..985a6cc8 100644
--- a/src/components/ProgressBar/messages.js
+++ b/src/components/ProgressBar/messages.js
@@ -3,7 +3,7 @@ import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
createSubmission: {
id: 'frontend-app-ora.ProgressBar.createSubmission',
- defaultMessage: 'Create your response',
+ defaultMessage: 'Create response',
description: 'Create response progress indicator',
},
studentTraining: {
@@ -13,7 +13,7 @@ const messages = defineMessages({
},
selfAssess: {
id: 'frontend-app-ora.ProgressBar.selfAssess',
- defaultMessage: 'Grade yourself',
+ defaultMessage: 'Self grading',
description: 'Self assessment step progress indicator',
},
peerAssess: {
diff --git a/src/components/Rubric/types.ts b/src/components/Rubric/types.ts
index 48bf3aa5..de70fd82 100644
--- a/src/components/Rubric/types.ts
+++ b/src/components/Rubric/types.ts
@@ -1,4 +1,4 @@
-import { CriterionConfig, MutationStatus, RubricData } from "data/services/lms/types";
+import { CriterionConfig, MutationStatus } from "data/services/lms/types";
export type Criterion = {
optionsValue: string | null;
@@ -11,8 +11,6 @@ export type Criterion = {
} & CriterionConfig;
export type RubricHookData = {
- rubricData: RubricData;
- setRubricData: (data: RubricData) => void;
criteria: Criterion[];
onSubmit: () => void;
submitStatus: MutationStatus;
diff --git a/src/hooks/actions/messages.js b/src/hooks/actions/messages.js
index cab576d4..eabaf1ec 100644
--- a/src/hooks/actions/messages.js
+++ b/src/hooks/actions/messages.js
@@ -9,12 +9,12 @@ const messages = defineMessages({
},
startTraining: {
id: 'ora-mfe.ModalActions.startTraining',
- defaultMessage: 'Begin practice grading',
+ defaultMessage: 'Go to practice grading',
description: 'Action button to begin studentTraining step',
},
startSelf: {
id: 'ora-mfe.ModalActions.startSelf',
- defaultMessage: 'Begin self grading',
+ defaultMessage: 'Go to self grading',
description: 'Action button to begin self assessment step',
},
startPeer: {
diff --git a/src/views/AssessmentView/index.jsx b/src/views/AssessmentView/index.jsx
index d347e41d..aa17b107 100644
--- a/src/views/AssessmentView/index.jsx
+++ b/src/views/AssessmentView/index.jsx
@@ -2,11 +2,10 @@ import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
-import { useActiveStepName } from 'hooks/app';
-
import Prompt from 'components/Prompt';
import TextResponse from 'components/TextResponse';
import FileUpload from 'components/FileUpload';
+import { useViewStep } from 'hooks/routing';
import BaseAssessmentView from './BaseAssessmentView';
import useAssessmentData from './useAssessmentData';
@@ -15,7 +14,7 @@ import messages from './messages';
export const AssessmentView = () => {
const { prompts, response, isLoaded } = useAssessmentData();
const { formatMessage } = useIntl();
- const step = useActiveStepName();
+ const step = useViewStep();
if (!isLoaded) {
return null;
}
diff --git a/src/views/AssessmentView/messages.js b/src/views/AssessmentView/messages.js
index 163b2700..0c339ba3 100644
--- a/src/views/AssessmentView/messages.js
+++ b/src/views/AssessmentView/messages.js
@@ -3,7 +3,7 @@ import { stepNames } from 'constants';
const messages = defineMessages({
[stepNames.self]: {
- defaultMessage: 'Grade yourself',
+ defaultMessage: 'Self grading',
description: 'Self assessment view header text',
id: 'frontend-app-ora.selfAssessmentView.header',
},
diff --git a/src/views/SubmissionView/messages.js b/src/views/SubmissionView/messages.js
index eb1f8d8d..97195051 100644
--- a/src/views/SubmissionView/messages.js
+++ b/src/views/SubmissionView/messages.js
@@ -54,7 +54,7 @@ export const submitActionMessages = defineMessages({
export const saveActionMessages = defineMessages({
[MutationStatus.idle]: {
id: 'ora-grading.SaveAction.save',
- defaultMessage: 'Finish later',
+ defaultMessage: 'Save for later',
description: 'Save for later button text',
},
[MutationStatus.loading]: {
diff --git a/src/views/XBlockView/Actions/messages.js b/src/views/XBlockView/Actions/messages.js
index 2c5f5c68..ac2fa913 100644
--- a/src/views/XBlockView/Actions/messages.js
+++ b/src/views/XBlockView/Actions/messages.js
@@ -4,17 +4,17 @@ import { stepNames } from 'constants';
const messages = defineMessages({
[stepNames.submission]: {
- defaultMessage: 'Create your response',
+ defaultMessage: 'Create response',
description: 'Xblock view action button for submission step to work on response',
id: 'frontend-app-ora.XBlockView.Actions.submission',
},
[stepNames.studentTraining]: {
- defaultMessage: 'Begin practice grading',
+ defaultMessage: 'Go to practice grading',
description: 'Xblock view action button for studentTraining step to practice grading',
id: 'frontend-app-ora.XBlockView.Actions.studentTraining',
},
[stepNames.self]: {
- defaultMessage: 'Begin self grading',
+ defaultMessage: 'Go to self grading',
description: 'Xblock view action button for self step to self-grade',
id: 'frontend-app-ora.XBlockView.Actions.self',
},
diff --git a/src/views/XBlockView/index.jsx b/src/views/XBlockView/index.jsx
index d7a2c989..4458c58f 100644
--- a/src/views/XBlockView/index.jsx
+++ b/src/views/XBlockView/index.jsx
@@ -1,6 +1,6 @@
import React, { useEffect } from 'react';
-import { usePrompts } from 'hooks/app';
+import { usePrompts, useRubricConfig } from 'hooks/app';
import ProgressBar from 'components/ProgressBar';
import Prompt from 'components/Prompt';
@@ -15,6 +15,7 @@ import './index.scss';
export const XBlockView = () => {
const prompts = usePrompts();
+ const rubricConfig = useRubricConfig();
useEffect(() => {
if (window.parent.length > 0) {
@@ -33,8 +34,7 @@ export const XBlockView = () => {
{prompts.map(prompt => )}
-
-
+ {rubricConfig.showDuringResponse && }
);
};
From 7dcd9b2428fd837a12f3fec0e900f0e2be3a6406 Mon Sep 17 00:00:00 2001
From: Ben Warzeski
Date: Tue, 5 Dec 2023 15:34:21 +0000
Subject: [PATCH 64/66] fix: ora title as modal header
---
src/App.jsx | 14 ++++++-------
src/components/ModalContainer.jsx | 33 +++++++++++++++++--------------
src/hooks/app.js | 1 +
3 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/src/App.jsx b/src/App.jsx
index 40f069e6..a68ef3c0 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -52,12 +52,12 @@ const App = () => {
element={pageWrapper()}
/>
);
- const modalRoute = (route, Component, title) => (
+ const modalRoute = (route, Component) => (
+
,
)}
@@ -81,11 +81,11 @@ const App = () => {
*/
const baseRoutes = [
appRoute(routes.xblock, XBlockView),
- modalRoute(routes.peerAssessment, AssessmentView, 'Assess your peers'),
- modalRoute(routes.selfAssessment, AssessmentView, 'Assess yourself'),
- modalRoute(routes.studentTraining, AssessmentView, 'Practice grading'),
- modalRoute(routes.submission, SubmissionView, 'Your response'),
- modalRoute(routes.graded, GradeView, 'My Grade'),
+ modalRoute(routes.peerAssessment, AssessmentView),
+ modalRoute(routes.selfAssessment, AssessmentView),
+ modalRoute(routes.studentTraining, AssessmentView),
+ modalRoute(routes.submission, SubmissionView),
+ modalRoute(routes.graded, GradeView),
} />,
];
diff --git a/src/components/ModalContainer.jsx b/src/components/ModalContainer.jsx
index 4d548973..7c7f5fdc 100644
--- a/src/components/ModalContainer.jsx
+++ b/src/components/ModalContainer.jsx
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { FullscreenModal } from '@edx/paragon';
import { nullMethod } from 'utils';
+import { useORAConfigData } from 'hooks/app';
import ProgressBar from 'components/ProgressBar';
@@ -10,23 +11,25 @@ import ProgressBar from 'components/ProgressBar';
* where we need to run non-embedded
*/
-const ModalContainer = ({ title, children }) => (
- }
- >
-
- {children}
-
-
-);
+const ModalContainer = ({ children }) => {
+ const { title } = useORAConfigData();
+ return (
+ }
+ >
+
+ {children}
+
+
+ );
+};
ModalContainer.propTypes = {
children: PropTypes.node.isRequired,
- title: PropTypes.string.isRequired,
};
export default ModalContainer;
diff --git a/src/hooks/app.js b/src/hooks/app.js
index e094a4ce..c5d45aff 100644
--- a/src/hooks/app.js
+++ b/src/hooks/app.js
@@ -22,6 +22,7 @@ export const {
useIsORAConfigLoaded,
useIsPageDataLoaded,
useIsPageDataLoading,
+ useORAConfigData,
usePageDataStatus,
usePrompts,
useResponseData,
From 8c448a775f84999999818551445d727365b98b09 Mon Sep 17 00:00:00 2001
From: Ben Warzeski
Date: Wed, 6 Dec 2023 15:59:14 +0000
Subject: [PATCH 65/66] chore: jsx hook cleanup
---
.../hooks/{useStatusAlertData.jsx => useStatusAlertData.js} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename src/components/StatusAlert/hooks/{useStatusAlertData.jsx => useStatusAlertData.js} (100%)
diff --git a/src/components/StatusAlert/hooks/useStatusAlertData.jsx b/src/components/StatusAlert/hooks/useStatusAlertData.js
similarity index 100%
rename from src/components/StatusAlert/hooks/useStatusAlertData.jsx
rename to src/components/StatusAlert/hooks/useStatusAlertData.js
From b47e2c28cbca12adc5205a9894de980e5e093552 Mon Sep 17 00:00:00 2001
From: Leangseu Kim
Date: Wed, 6 Dec 2023 13:22:02 -0500
Subject: [PATCH 66/66] chore: rewrite modal container
---
src/components/ModalContainer.jsx | 26 ++++++++++++--------------
src/index.jsx | 7 -------
2 files changed, 12 insertions(+), 21 deletions(-)
diff --git a/src/components/ModalContainer.jsx b/src/components/ModalContainer.jsx
index 7c7f5fdc..2934e3cc 100644
--- a/src/components/ModalContainer.jsx
+++ b/src/components/ModalContainer.jsx
@@ -1,31 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { FullscreenModal } from '@edx/paragon';
-
-import { nullMethod } from 'utils';
import { useORAConfigData } from 'hooks/app';
import ProgressBar from 'components/ProgressBar';
/* The purpose of this component is to wrap views with a header/footer for situations
- * where we need to run non-embedded
+ * where we need to run non-embedded. It is a replicated style of FullScreenModal from
+ * paragon. The reason we use this instead of FullScreenModal is because FullScreenModal
+ * is very opinionated on other components that it uses on top of it. Since we are not
+ * using the modality of the component, it would be better to just replicate the style
+ * instead of using the component.
*/
const ModalContainer = ({ children }) => {
const { title } = useORAConfigData();
return (
- }
- >
-
+
);
};
ModalContainer.propTypes = {
diff --git a/src/index.jsx b/src/index.jsx
index 58ac232b..313bdbb5 100644
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -25,13 +25,6 @@ const queryClient = new QueryClient({
subscribe(APP_READY, () => {
const isDev = process.env.NODE_ENV === 'development';
const rootEl = document.getElementById('root');
- if (isDev) {
- setTimeout(() => {
- // This is a hack to prevent the Paragon Modal overlay stop query devtools from clickable
- rootEl.removeAttribute('data-focus-on-hidden');
- rootEl.removeAttribute('aria-hidden');
- }, 3000);
- }
ReactDOM.render(