Skip to content

Commit

Permalink
Add conditional grade column to assignment activity table
Browse files Browse the repository at this point in the history
  • Loading branch information
acelaya committed Sep 10, 2024
1 parent 08c5d13 commit e1ad56e
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 26 deletions.
1 change: 1 addition & 0 deletions lms/static/scripts/frontend_apps/api-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export type Student = {

export type StudentWithMetrics = Student & {
annotation_metrics: AnnotationMetrics;
auto_grading_grade?: number;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { replaceURLParams } from '../../utils/url';
import DashboardActivityFilters from './DashboardActivityFilters';
import DashboardBreadcrumbs from './DashboardBreadcrumbs';
import FormattedDate from './FormattedDate';
import GradeStatusChip from './GradeStatusChip';
import type { OrderableActivityTableColumn } from './OrderableActivityTable';
import OrderableActivityTable from './OrderableActivityTable';

type StudentsTableRow = {
Expand All @@ -22,6 +24,7 @@ type StudentsTableRow = {
last_activity: string | null;
annotations: number;
replies: number;
auto_grading_grade?: number;
};

/**
Expand All @@ -43,6 +46,7 @@ export default function AssignmentActivity() {
const assignment = useAPIFetch<AssignmentDetails>(
replaceURLParams(routes.assignment, { assignment_id: assignmentId }),
);
const autoGradingEnabled = !!assignment.data?.auto_grading_config;

const students = useAPIFetch<StudentsMetricsResponse>(
routes.students_metrics,
Expand All @@ -56,14 +60,49 @@ export default function AssignmentActivity() {
const rows: StudentsTableRow[] = useMemo(
() =>
(students.data?.students ?? []).map(
({ lms_id, display_name, annotation_metrics }) => ({
({ lms_id, display_name, auto_grading_grade, annotation_metrics }) => ({
lms_id,
display_name,
auto_grading_grade,
...annotation_metrics,
}),
),
[students.data],
);
const columns = useMemo(() => {
const firstColumns: OrderableActivityTableColumn<StudentsTableRow>[] = [
{
field: 'display_name',
label: 'Student',
},
];
const lastColumns: OrderableActivityTableColumn<StudentsTableRow>[] = [
{
field: 'annotations',
label: 'Annotations',
initialOrderDirection: 'descending',
},
{
field: 'replies',
label: 'Replies',
initialOrderDirection: 'descending',
},
{
field: 'last_activity',
label: 'Last Activity',
initialOrderDirection: 'descending',
},
];

if (autoGradingEnabled) {
firstColumns.push({
field: 'auto_grading_grade',
label: 'Grade',
});
}

return [...firstColumns, ...lastColumns];
}, [autoGradingEnabled]);

const title = assignment.data?.title ?? 'Untitled assignment';
useDocumentTitle(title);
Expand Down Expand Up @@ -134,27 +173,7 @@ export default function AssignmentActivity() {
students.error ? 'Could not load students' : 'No students found'
}
rows={rows}
columns={[
{
field: 'display_name',
label: 'Student',
},
{
field: 'annotations',
label: 'Annotations',
initialOrderDirection: 'descending',
},
{
field: 'replies',
label: 'Replies',
initialOrderDirection: 'descending',
},
{
field: 'last_activity',
label: 'Last Activity',
initialOrderDirection: 'descending',
},
]}
columns={columns}
defaultOrderField="display_name"
renderItem={(stats, field) => {
switch (field) {
Expand All @@ -179,6 +198,8 @@ export default function AssignmentActivity() {
</span>
)
);
case 'auto_grading_grade':
return <GradeStatusChip grade={stats.auto_grading_grade ?? 0} />;
default:
return '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { DataTableProps, Order } from '@hypothesis/frontend-shared';
import { DataTable } from '@hypothesis/frontend-shared';
import { useOrderedRows } from '@hypothesis/frontend-shared';
import type { OrderDirection } from '@hypothesis/frontend-shared/lib/types';
import classnames from 'classnames';
import { useMemo, useState } from 'preact/hooks';
import { useLocation } from 'wouter-preact';

Expand Down Expand Up @@ -46,7 +47,13 @@ export default function OrderableActivityTable<T>({
columns.map(({ field, label }, index) => ({
field,
label,
classes: index === 0 ? 'lg:w-[60%] md:w-[45%]' : undefined,
classes: classnames({
// For assignments with auto-grading, a fifth column is displayed.
// In that case, we need to reserve less space for the first column,
// otherwise the rest overflow.
'lg:w-[60%] md:w-[45%]': index === 0 && columns.length < 5,
'lg:w-[45%] md:w-[30%]': index === 0 && columns.length >= 5,
}),
})),
[columns],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,17 @@ describe('AssignmentActivity', () => {
let fakeConfig;
let wrappers;

beforeEach(() => {
fakeUseAPIFetch = sinon.stub().callsFake(url => ({
function setUpFakeUseAPIFetch(assignment = activeAssignment) {
fakeUseAPIFetch.callsFake(url => ({
isLoading: false,
data: url.endsWith('metrics') ? { students } : activeAssignment,
data: url.endsWith('metrics') ? { students } : assignment,
}));
}

beforeEach(() => {
fakeUseAPIFetch = sinon.stub();
setUpFakeUseAPIFetch();

fakeNavigate = sinon.stub();
fakeUseSearch = sinon.stub().returns('current=query');
fakeConfig = {
Expand Down Expand Up @@ -297,6 +303,94 @@ describe('AssignmentActivity', () => {
});
});

context('when auto-grading is enabled', () => {
[
{
autoGradingEnabled: false,
expectedColumns: [
{
field: 'display_name',
label: 'Student',
},
{
field: 'annotations',
label: 'Annotations',
initialOrderDirection: 'descending',
},
{
field: 'replies',
label: 'Replies',
initialOrderDirection: 'descending',
},
{
field: 'last_activity',
label: 'Last Activity',
initialOrderDirection: 'descending',
},
],
},
{
autoGradingEnabled: true,
expectedColumns: [
{
field: 'display_name',
label: 'Student',
},
{
field: 'auto_grading_grade',
label: 'Grade',
},
{
field: 'annotations',
label: 'Annotations',
initialOrderDirection: 'descending',
},
{
field: 'replies',
label: 'Replies',
initialOrderDirection: 'descending',
},
{
field: 'last_activity',
label: 'Last Activity',
initialOrderDirection: 'descending',
},
],
},
].forEach(({ autoGradingEnabled, expectedColumns }) => {
it('shows one more column in the metrics table', () => {
setUpFakeUseAPIFetch({
...activeAssignment,
auto_grading_config: autoGradingEnabled ? {} : null,
});

const wrapper = createComponent();
const tableElement = wrapper.find('OrderableActivityTable');

assert.deepEqual(tableElement.prop('columns'), expectedColumns);
});
});

[{ auto_grading_grade: undefined }, { auto_grading_grade: 25 }].forEach(
({ auto_grading_grade }) => {
it('shows the grade for every student', () => {
setUpFakeUseAPIFetch({
...activeAssignment,
auto_grading_config: {},
});

const wrapper = createComponent();
const item = wrapper
.find('OrderableActivityTable')
.props()
.renderItem({ auto_grading_grade }, 'auto_grading_grade');

assert.equal(mount(item).prop('grade'), auto_grading_grade ?? 0);
});
},
);
});

it(
'should pass a11y checks',
checkAccessibility({
Expand Down

0 comments on commit e1ad56e

Please sign in to comment.