Skip to content

Commit

Permalink
Lk/integration (#74)
Browse files Browse the repository at this point in the history
* chore: hide file upload if it was disabled

* chore: prevent status alert from crashing for now

* chore: change step states from complete to done

* chore: change assessment data shape to match backend

* chore: remove unnecessary onclick on info popover

* chore: update some logic on progress bar

* chore: update url to use the real backend

* chore: update step state complete to done

* chore: update requested change

* chore: update requested change
  • Loading branch information
leangseu-edx authored Nov 6, 2023
1 parent b0a1912 commit 7ff5c5d
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';
import PropTypes from 'prop-types';

import { useIntl } from '@edx/frontend-platform/i18n';
import Feedback from './Feedback';
import messages from './messages';
import { useORAConfigData } from 'data/services/lms/hooks/selectors';

Check failure on line 7 in src/components/Assessment/ReadonlyAssessment/AssessmentCriterion.jsx

View workflow job for this annotation

GitHub Actions / test

`data/services/lms/hooks/selectors` import should occur before import of `./Feedback`

const AssessmentCriterion = ({
criteria,
overallFeedback,
stepLabel,
}) => {
const { formatMessage } = useIntl();
const { rubricConfig } = useORAConfigData();
return (
<>
{rubricConfig.criteria.map((criterion, i) => {
const assessmentCriterion = criteria[i];
const option = criterion.options[assessmentCriterion.selectedOption];
return (
<Feedback
key={criterion.name}
criterionName={criterion.name}
criterionDescription={criterion.description}
selectedOption={option.name}
selectedPoints={option.points}
commentHeader={stepLabel}
commentBody={assessmentCriterion.feedback}
/>
);
})}
<Feedback
criterionName={formatMessage(messages.overallFeedback)}
commentHeader={stepLabel}
commentBody={overallFeedback}
/>
</>
);
};
AssessmentCriterion.defaultProps = {};
AssessmentCriterion.propTypes = {
criteria: PropTypes.arrayOf(PropTypes.shape({

Check failure on line 43 in src/components/Assessment/ReadonlyAssessment/AssessmentCriterion.jsx

View workflow job for this annotation

GitHub Actions / test

propType "criteria" is not required, but has no corresponding defaultProps declaration
selectedOption: PropTypes.number,
// selectedPoints: PropTypes.number,
feedback: PropTypes.string,
})),
overallFeedback: PropTypes.string,

Check failure on line 48 in src/components/Assessment/ReadonlyAssessment/AssessmentCriterion.jsx

View workflow job for this annotation

GitHub Actions / test

propType "overallFeedback" is not required, but has no corresponding defaultProps declaration
stepLabel: PropTypes.string.isRequired,
};

export default AssessmentCriterion;
2 changes: 1 addition & 1 deletion src/components/Assessment/ReadonlyAssessment/Feedback.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const Feedback = ({
<div className="d-flex justify-content-between align-items-center">
<h5 className="mb-0">{criterionName}</h5>
{criterionDescription && (
<InfoPopover onClick={() => {}}>
<InfoPopover>
<p>{criterionDescription}</p>
</InfoPopover>
)}
Expand Down
4 changes: 4 additions & 0 deletions src/components/FileUpload/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DataTable, Dropzone } from '@edx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';

import { nullMethod } from 'hooks';
import { useFileUploadEnabled } from 'data/services/lms/hooks/selectors';

import UploadConfirmModal from './UploadConfirmModal';
import ActionCell from './ActionCell';
Expand All @@ -28,6 +29,9 @@ const FileUpload = ({
defaultCollapsePreview,
}) => {
const { formatMessage } = useIntl();
if ( !useFileUploadEnabled() ) {
return null;
}

const {
confirmUpload,
Expand Down
4 changes: 2 additions & 2 deletions src/components/ProgressBar/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ export const useProgressStepData = ({ step, canRevisit = false }) => {
const isEnabled = (
isActive
|| (stepState === stepStates.inProgress)
|| (canRevisit && stepState === stepStates.completed)
|| (canRevisit && stepState === stepStates.done)
);
const myGrade = useEffectiveGrade()?.stepScore;
return {
href,
isEnabled,
isActive,
isComplete: stepState === stepStates.completed,
isComplete: stepState === stepStates.done,
inProgress: stepState === stepStates.inProgress,
isPastDue: stepState === stepStates.closed,
myGrade,
Expand Down
38 changes: 21 additions & 17 deletions src/components/ProgressBar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { Navbar } from '@edx/paragon';

import {
useAssessmentStepOrder,
useHasReceivedFinalGrade,
useIsPageDataLoaded,
useStepInfo,
} from 'data/services/lms/hooks/selectors';
import { stepNames } from 'data/services/lms/constants';

Expand All @@ -34,33 +36,35 @@ export const stepCanRevisit = {

export const ProgressBar = ({ className }) => {
const isLoaded = useIsPageDataLoaded();
const stepInfo = useStepInfo();
const hasReceivedFinalGrade = useHasReceivedFinalGrade();

const stepOrder = useAssessmentStepOrder();
const stepOrders = [
stepNames.submission,
...useAssessmentStepOrder(),
stepNames.done,
];
const { formatMessage } = useIntl();

if (!isLoaded) {
return null;
}

const stepEl = (step) => (
stepLabels[step]
? (
<ProgressStep
step={step}
key={step}
label={formatMessage(stepLabels[step])}
canRevisit={stepCanRevisit[step]}
/>
) : null
);
const stepEl = (curStep) =>
stepLabels[curStep] ? (
<ProgressStep
step={curStep}
key={curStep}
label={formatMessage(stepLabels[curStep])}
canRevisit={(curStep === 'done' && hasReceivedFinalGrade) || !!stepInfo[curStep]}
/>
) : null;

return (
<Navbar className={classNames('px-0', className)}>
<Navbar.Collapse className="ora-progress-nav-group bg-white">
<hr className="ora-progress-divider" />
{stepEl(stepNames.submission)}
{stepOrder.map(stepEl)}
{stepEl(stepNames.done)}
<Navbar.Collapse className='ora-progress-nav-group bg-white'>
<hr className='ora-progress-divider' />
{stepOrders.map(stepEl)}
</Navbar.Collapse>
</Navbar>
);
Expand Down
3 changes: 3 additions & 0 deletions src/components/StatusAlert/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const StatusAlert = ({
step,
showTrainingError,
}) => {
if ( step === null ) {
return null;
}
const {
variant,
icon,
Expand Down
92 changes: 92 additions & 0 deletions src/components/StatusAlert/useStatusAlert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { CheckCircle, Info, WarningFilled } from '@edx/paragon/icons';
import { StrictDict } from '@edx/react-unit-test-utils';

import {
stepNames,
stepStates,
} from 'data/services/lms/constants';
import { useGlobalState } from 'data/services/lms/hooks/selectors';
import messages from './messages';
import alertMessages from './alertMessages';
import headingMessages from './alertHeadingMessages';

export const alertMap = {
[stepStates.done]: {
variant: 'success',
icon: CheckCircle,
},
[stepStates.closed]: {
variant: 'danger',
icon: Info,
},
[stepStates.teamAlreadySubmitted]: {
variant: 'warning',
icon: WarningFilled,
},
[stepStates.cancelled]: {
variant: 'warning',
icon: WarningFilled,
},
[stepStates.inProgress]: {
variant: 'dark',
icon: null,
},
};

const useStatusAlertMessages = (step = null) => {
const { formatMessage } = useIntl();
const {
activeStepName,
stepState,
cancellationInfo,
} = useGlobalState({ step });
const stepName = step || activeStepName;
const isRevisit = stepName !== activeStepName;
if (cancellationInfo.hasCancelled) {
const { cancelledBy, cancelledAt } = cancellationInfo;
if (cancelledBy) {
return {
message: formatMessage(
alertMessages.submission.cancelledBy,
{ cancelledBy, cancelledAt },
),
heading: formatMessage(headingMessages.submission.cancelledBy),
};
}
return {
message: formatMessage(alertMessages.submission.cancelledAt, { cancelledAt }),
heading: formatMessage(headingMessages.submission.cancelledAt),
};
}
if (stepName === stepNames.submission && isRevisit) {
return {
message: formatMessage(alertMessages.submission.finished),
heading: formatMessage(headingMessages.submission.finished),
};
}
if (stepName === stepNames.peer && isRevisit && stepState !== stepStates.waiting) {
return {
message: formatMessage(alertMessages.peer.finished),
heading: formatMessage(headingMessages.peer.finished),
};
}
return {
message: formatMessage(alertMessages[stepName][stepState]),
heading: formatMessage(headingMessages[stepName][stepState]),
};
};

const useStatusAlert = (step = null) => {
const { stepState } = useGlobalState({ step });
const { variant, icon } = alertMap[stepState];
const { message, heading } = useStatusAlertMessages(step);
return {
variant,
icon,
message,
heading,
};
};

export default useStatusAlert;
2 changes: 1 addition & 1 deletion src/components/StatusAlert/useStatusAlertData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import alertMessages from './alertMessages';
import headingMessages from './alertHeadingMessages';

export const alertMap = {
[stepStates.completed]: {
[stepStates.done]: {
variant: 'success',
icon: CheckCircle,
},
Expand Down
2 changes: 1 addition & 1 deletion src/data/services/lms/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const MutationStatus = StrictDict({

export const stepStates = StrictDict({
inProgress: 'inProgress',
completed: 'completed',
done: 'done',
cancelled: 'cancelled',
closed: 'closed',
notAvailable: 'notAvailable',
Expand Down
2 changes: 1 addition & 1 deletion src/data/services/lms/fakeData/dataStates.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const loadState = (opts) => {
const state = {
progress: pageData.getProgressState({ progressKey, stepConfig, viewStep }),
response: pageData.getResponseState({ progressKey, isTeam }),
assessments: pageData.getAssessmentState({ progressKey, stepConfig }),
assessment: pageData.getAssessmentState({ progressKey, stepConfig }),
};
console.log({
opts, progressKey, state, isTeam,
Expand Down
9 changes: 0 additions & 9 deletions src/data/services/lms/hooks/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,9 @@ export const useORAConfig = (): types.QueryData<types.ORAConfig> => {
return useQuery({
queryKey: [queryKeys.oraConfig],
queryFn: () => {
/*
return getAuthenticatedHttpClient().post(oraConfigUrl, {}).then(
({ data }) => camelCaseObject(data)
);
*/
console.log({ oraConfig: camelCaseObject(fakeData.oraConfig.assessmentTinyMCE) });
return Promise.resolve(
camelCaseObject(fakeData.oraConfig.assessmentTinyMCE)
);
},
});
};
Expand All @@ -39,12 +33,9 @@ export const usePageData = (): types.QueryData<types.PageData> => {
return useQuery({
queryKey: [queryKeys.pageData],
queryFn: () => {
/*
return getAuthenticatedHttpClient().post(pageDataUrl, {}).then(
({ data }) => camelCaseObject(data)
);
*/
return Promise.resolve(camelCaseObject(loadState({ view, progressKey })));
},
});
};
Expand Down
6 changes: 3 additions & 3 deletions src/data/services/lms/hooks/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const useStepState = ({ step = null } = {}) => {
const stepIndex = selectors.useStepIndex({ step: stepName });
const subState = selectors.useSubmissionState();
if (hasReceivedFinalGrade) {
return stepStates.completed;
return stepStates.done;
}

if (step === stepNames.submission) {
Expand All @@ -41,14 +41,14 @@ export const useStepState = ({ step = null } = {}) => {
if (hasCancelled) { return stepStates.cancelled; }

if (step === stepNames.done) {
return hasReceivedFinalGrade ? stepStates.completed : stepStates.notAvailable;
return hasReceivedFinalGrade ? stepStates.done : stepStates.notAvailable;
}

if (step === stepNames.peer && stepInfo?.peer?.isWaitingForSubmissions) {
return stepStates.waiting;
}
// For Assessment steps
if (stepIndex < activeStepIndex) { return stepStates.completed; }
if (stepIndex < activeStepIndex) { return stepStates.done; }
if (stepIndex > activeStepIndex) { return stepStates.notAvailable; }

// only check for closed or not-available on active step
Expand Down
2 changes: 2 additions & 0 deletions src/data/services/lms/hooks/selectors/oraConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export const useAssessmentStepConfig = (): types.AssessmentStepConfig => (
useORAConfigData().assessmentSteps
);

export const useFileUploadEnabled = (): boolean => useSubmissionConfig().fileResponseConfig.enabled;

export const useAssessmentStepOrder = (): string[] => useAssessmentStepConfig()?.order;
export const useStepIndex = ({ step }): number => useAssessmentStepOrder().indexOf(step);

Expand Down
15 changes: 6 additions & 9 deletions src/data/services/lms/hooks/selectors/pageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const useSubmissionState = () => {
}

if (subStatus.hasSubmitted) {
return stepStates.completed;
return stepStates.done;
}
if (subStatus.isClosed) {
if (subStatus.closedReason === closedReasons.pastDue) {
Expand All @@ -68,13 +68,10 @@ export const useSubmissionState = () => {
return stepStates.inProgress;
};

// Assessments
export const useAssessmentsData = (): types.AssessmentsData => {
console.log({ pageData: usePageData() });
return usePageData().assessments;
};
export const useHasReceivedFinalGrade = (): boolean => useAssessmentsData() !== null;
// Assessment
export const useAssessmentData = (): types.AssessmentsData => usePageData().assessment;
export const useHasReceivedFinalGrade = (): boolean => useAssessmentData() !== null;
export const useEffectiveGrade = () => {
const assessments = useAssessmentsData();
return assessments ? assessments[assessments.effectiveAssessmentType] : null;
const assessment = useAssessmentData();
return assessment ? assessment[assessment.effectiveAssessmentType] : null;
};
4 changes: 2 additions & 2 deletions src/data/services/lms/types/pageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export interface ResponseData {

// Assessments Data
export interface AssessmentData {
assessmentCriterions: {
criteria: {
selectedOption: number | null,
feedback: string,
}[],
Expand Down Expand Up @@ -106,5 +106,5 @@ export interface AssessmentsData {
export interface PageData {
progress: ProgressData,
response: ResponseData,
assessments: AssessmentsData
assessment: AssessmentsData
}
Loading

0 comments on commit 7ff5c5d

Please sign in to comment.