From 060b19111761d5c5e42bf8f041bee13eb7257447 Mon Sep 17 00:00:00 2001 From: Doug Martin Date: Tue, 5 Mar 2024 08:44:00 -0500 Subject: [PATCH] feat: Flesh out score with rubric [PT-187021252] This displays the rubric score when the question has been fully scored. This also only shows the rubric score value in the table if the score type is rubric. Finally this adds back code that was lost in a merge to check for a max score value of 999. --- .../feedback/activity-feedback-score.less | 13 +++++ .../feedback/feedback-rows.less | 53 +++++++------------ .../feedback/activity-feedback-score.tsx | 27 +++++++--- .../activity-level-feedback-student-rows.tsx | 4 +- .../feedback/rubric-table.tsx | 12 +++-- .../portal-dashboard/feedback/score-input.tsx | 6 ++- 6 files changed, 65 insertions(+), 50 deletions(-) create mode 100644 css/portal-dashboard/feedback/activity-feedback-score.less diff --git a/css/portal-dashboard/feedback/activity-feedback-score.less b/css/portal-dashboard/feedback/activity-feedback-score.less new file mode 100644 index 00000000..7f8c56d8 --- /dev/null +++ b/css/portal-dashboard/feedback/activity-feedback-score.less @@ -0,0 +1,13 @@ +@import "../variables"; + +.activityFeedbackScore { + display: flex; + flex-direction: column; + gap: 10px; + align-items: flex-end; + + .scoreLabel { + color: @cc-charcoal; + font-weight: bold; + } +} diff --git a/css/portal-dashboard/feedback/feedback-rows.less b/css/portal-dashboard/feedback/feedback-rows.less index 3afc6079..2b735ac2 100644 --- a/css/portal-dashboard/feedback/feedback-rows.less +++ b/css/portal-dashboard/feedback/feedback-rows.less @@ -68,45 +68,28 @@ margin-top: 7.5px; } - .textAndScore { - display: flex; - gap: 35px; - - textarea { - border: solid 1.5px @cc-charcoal-light2; - border-radius: 8px; - box-sizing: border-box; - font: 16px lato, arial, helvetica, sans-serif; - height: auto; - min-height: 50px; - outline: none; - padding: 5px 10px 13px; - resize: none; - width: 100%; - min-height: 80px; - - &:focus { - border-color: @cc-charcoal-light1; - } - } + textarea { + border: solid 1.5px @cc-charcoal-light2; + border-radius: 8px; + box-sizing: border-box; + font: 16px lato, arial, helvetica, sans-serif; + height: auto; + min-height: 50px; + outline: none; + padding: 5px 10px 13px; + resize: none; + width: 100%; + min-height: 80px; - .score { - display: flex; - flex-direction: column; - gap: 10px; - align-items: flex-end; - - &>div { - color: @cc-charcoal; - font-weight: bold; - } - - input { - width: 40px; - } + &:focus { + border-color: @cc-charcoal-light1; } } + .textAndScore { + display: flex; + gap: 35px; + } } } } diff --git a/js/components/portal-dashboard/feedback/activity-feedback-score.tsx b/js/components/portal-dashboard/feedback/activity-feedback-score.tsx index 7b175162..93e14179 100644 --- a/js/components/portal-dashboard/feedback/activity-feedback-score.tsx +++ b/js/components/portal-dashboard/feedback/activity-feedback-score.tsx @@ -4,6 +4,9 @@ import { TrackEventFunction } from "../../../actions"; import { ScoreInput } from "./score-input"; import { ScoringSettings } from "../../../util/scoring"; import { AUTOMATIC_SCORE, MANUAL_SCORE, NO_SCORE } from "../../../util/scoring-constants"; +import { Rubric } from "./rubric-utils"; + +import css from "../../../../css/portal-dashboard/feedback/activity-feedback-score.less"; interface IProps { activityId: string | null; @@ -14,12 +17,13 @@ interface IProps { studentId: string; updateActivityFeedback?: (activityId: string, activityIndex: number, platformStudentId: string, feedback: any) => void; trackEvent: TrackEventFunction; - className: string; scoringSettings: ScoringSettings; + rubricFeedback: any; + rubric: Rubric; } export const ActivityFeedbackScore: React.FC = (props) => { - const { activityId, activityIndex, activityStarted, score, studentId, updateActivityFeedback, trackEvent, className, scoringSettings } = props; + const { activityId, activityIndex, activityStarted, score, studentId, updateActivityFeedback, trackEvent, scoringSettings, rubricFeedback, rubric } = props; const scoreType = scoringSettings.scoreType ?? NO_SCORE; const [ scoreChanged, setScoreChanged ] = useState(false); @@ -54,21 +58,28 @@ export const ActivityFeedbackScore: React.FC = (props) => { score={score} minScore={0} disabled={false} - className={className} + className={css.activityFeedbackScore} onChange={handleScoreChange} onBlur={scoreChanged ? updateScoreLogged : undefined} > -
Score
+
Score
); } - const displayScore = "TBD"; // TBD: compute this in PT #187021252 + let displayScore = "N/A"; + if (rubricFeedback) { + const scoredValues = Object.values(rubricFeedback).filter((v: any) => v.score > 0); + if (scoredValues.length === rubric.criteria.length) { + const totalScore = scoredValues.reduce((acc, cur: any) => acc + cur.score, 0); + displayScore = String(totalScore); + } + } return ( -
-
Score
-
{displayScore}
+
+
Score
+
{displayScore}
); diff --git a/js/components/portal-dashboard/feedback/activity-level-feedback-student-rows.tsx b/js/components/portal-dashboard/feedback/activity-level-feedback-student-rows.tsx index ef362b51..78521640 100644 --- a/js/components/portal-dashboard/feedback/activity-level-feedback-student-rows.tsx +++ b/js/components/portal-dashboard/feedback/activity-level-feedback-student-rows.tsx @@ -70,6 +70,7 @@ export const ActivityLevelFeedbackStudentRows: React.FC = (props) => { rubricFeedback={rubricFeedback} setFeedbackSortRefreshEnabled={setFeedbackSortRefreshEnabled} updateActivityFeedback={updateActivityFeedback} + scoringSettings={scoringSettings} /> }
@@ -94,8 +95,9 @@ export const ActivityLevelFeedbackStudentRows: React.FC = (props) => { setFeedbackSortRefreshEnabled={setFeedbackSortRefreshEnabled} updateActivityFeedback={updateActivityFeedback} trackEvent={trackEvent} - className={css.score} scoringSettings={scoringSettings} + rubricFeedback={rubricFeedback} + rubric={rubric} />
diff --git a/js/components/portal-dashboard/feedback/rubric-table.tsx b/js/components/portal-dashboard/feedback/rubric-table.tsx index 44ccf70a..f9292310 100644 --- a/js/components/portal-dashboard/feedback/rubric-table.tsx +++ b/js/components/portal-dashboard/feedback/rubric-table.tsx @@ -4,6 +4,8 @@ import Markdown from "markdown-to-jsx"; import LaunchIcon from "../../../../img/svg-icons/launch-icon.svg"; import { hasRubricFeedback } from "../../../util/activity-feedback-helper"; import { Rubric, getFeedbackColor } from "./rubric-utils"; +import { ScoringSettings } from "../../../util/scoring"; +import { RUBRIC_SCORE } from "../../../util/scoring-constants"; import css from "../../../../css/portal-dashboard/feedback/rubric-table.less"; @@ -15,15 +17,16 @@ interface IProps { activityIndex: number; setFeedbackSortRefreshEnabled: (value: boolean) => void; updateActivityFeedback: (activityId: string, activityIndex: number, platformStudentId: string, feedback: any) => void; + scoringSettings: ScoringSettings; } export class RubricTableContainer extends React.PureComponent { render() { - const { rubric } = this.props; + const { rubric, scoringSettings } = this.props; const { criteria } = rubric; return (
- {this.renderColumnHeaders(rubric)} + {this.renderColumnHeaders(rubric, scoringSettings)}
{criteria.map((crit: any) =>
@@ -38,8 +41,9 @@ export class RubricTableContainer extends React.PureComponent { ); } - private renderColumnHeaders = (rubric: Rubric) => { + private renderColumnHeaders = (rubric: Rubric, scoringSettings: ScoringSettings) => { const { referenceURL } = rubric; + const showScore = scoringSettings.scoreType === RUBRIC_SCORE; return (
@@ -54,7 +58,7 @@ export class RubricTableContainer extends React.PureComponent { {rubric.ratings.map((rating: any) =>
{rating.label}
- {rubric.scoreUsingPoints &&
({rating.score})
} + {rubric.scoreUsingPoints && showScore &&
({rating.score})
}
)}
diff --git a/js/components/portal-dashboard/feedback/score-input.tsx b/js/components/portal-dashboard/feedback/score-input.tsx index 4278fe55..1185d09e 100644 --- a/js/components/portal-dashboard/feedback/score-input.tsx +++ b/js/components/portal-dashboard/feedback/score-input.tsx @@ -13,6 +13,8 @@ interface IProps { onBlur?: (score: number) => void; } +const maxScore = 999; + export class ScoreInput extends PureComponent { render() { @@ -21,7 +23,7 @@ export class ScoreInput extends PureComponent { return (
{children} - +
); } @@ -35,7 +37,7 @@ export class ScoreInput extends PureComponent { private handleChange = (e: React.ChangeEvent) => { const {minScore, onChange} = this.props; const score = parseInt(e.target.value, 10); - if (score >= minScore) { + if ((score >= minScore) && (score <= maxScore)) { onChange(score); } }