Skip to content

Commit 05cad2b

Browse files
zhyuhanRichDom2185
andauthored
Redesign Avenger dashboard (#2437)
* feat: redesign submissions table with basic column filtering * feat: make new submission action buttons functional * feat: improving submissions table filtering * feat: add submissions table filter state to Redux store * fix: use React Router's `Link` instead of `a` tag * feat: add grading summary to show progress * refactor: make `loadContentDispatch` optional * feat: use new grading dashboard * feat: move `Export to CSV` button * fix: sort imports * fix: skip missing assessments instead of throwing an error * refactor: add helper to get badge color * refactor: use nullish coallescing Co-authored-by: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> * refactor: remove unnecessary check for Paths * refactor: reorganize components and logic for badges * fix: wrap csv fields in quotes * fix: wraps column headers in quotes too --------- Co-authored-by: Richard Dominick <34370238+RichDom2185@users.noreply.github.com>
1 parent f2b05b2 commit 05cad2b

20 files changed

+1058
-669
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
"@sourceacademy/sharedb-ace": "^2.0.2",
3636
"@sourceacademy/sling-client": "^0.1.0",
3737
"@szhsin/react-menu": "^3.2.0",
38+
"@tanstack/react-table": "^8.7.9",
39+
"@tremor/react": "^1.7.0",
3840
"ace-builds": "^1.4.14",
3941
"acorn": "^8.8.2",
4042
"ag-grid-community": "^28.0.2",

src/commons/ContentDisplay.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import React, { useEffect } from 'react';
44
export type ContentDisplayProps = {
55
fullWidth?: boolean;
66
display: JSX.Element;
7-
loadContentDispatch: () => void;
7+
loadContentDispatch?: () => void;
88
};
99

1010
const ContentDisplay: React.FC<ContentDisplayProps> = props => {
1111
// eslint-disable-next-line react-hooks/exhaustive-deps
12-
useEffect(() => props.loadContentDispatch(), []);
12+
useEffect(() => props.loadContentDispatch?.(), []);
1313

1414
return (
1515
<div className="ContentDisplay row center-xs">

src/commons/application/ApplicationTypes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ export const defaultWorkspaceManager: WorkspaceManagerState = {
328328
},
329329
grading: {
330330
...createDefaultWorkspace('grading'),
331+
submissionsTableFilters: {
332+
columnFilters: [],
333+
globalFilter: null
334+
},
331335
currentSubmission: undefined,
332336
currentQuestion: undefined,
333337
hasUnsavedChanges: false

src/commons/workspace/WorkspaceActions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
SEND_REPL_INPUT_TO_OUTPUT,
4545
SET_FOLDER_MODE,
4646
SHIFT_EDITOR_TAB,
47+
SubmissionsTableFilters,
4748
TOGGLE_EDITOR_AUTORUN,
4849
TOGGLE_FOLDER_MODE,
4950
TOGGLE_UPDATE_ENV,
@@ -61,6 +62,7 @@ import {
6162
UPDATE_HAS_UNSAVED_CHANGES,
6263
UPDATE_REPL_VALUE,
6364
UPDATE_SUBLANGUAGE,
65+
UPDATE_SUBMISSIONS_TABLE_FILTERS,
6466
UPDATE_WORKSPACE,
6567
WorkspaceLocation,
6668
WorkspaceState
@@ -313,6 +315,9 @@ export const setIsEditorReadonly = (
313315
isEditorReadonly: isEditorReadonly
314316
});
315317

318+
export const updateSubmissionsTableFilters = (filters: SubmissionsTableFilters) =>
319+
action(UPDATE_SUBMISSIONS_TABLE_FILTERS, { filters });
320+
316321
export const updateCurrentAssessmentId = (assessmentId: number, questionId: number) =>
317322
action(UPDATE_CURRENT_ASSESSMENT_ID, {
318323
assessmentId,

src/commons/workspace/WorkspaceReducer.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import {
7373
UPDATE_HAS_UNSAVED_CHANGES,
7474
UPDATE_REPL_VALUE,
7575
UPDATE_SUBLANGUAGE,
76+
UPDATE_SUBMISSIONS_TABLE_FILTERS,
7677
UPDATE_WORKSPACE,
7778
WorkspaceLocation,
7879
WorkspaceManagerState
@@ -605,6 +606,14 @@ export const WorkspaceReducer: Reducer<WorkspaceManagerState> = (
605606
} else {
606607
return state;
607608
}
609+
case UPDATE_SUBMISSIONS_TABLE_FILTERS:
610+
return {
611+
...state,
612+
grading: {
613+
...state.grading,
614+
submissionsTableFilters: action.payload.filters
615+
}
616+
};
608617
case UPDATE_CURRENT_ASSESSMENT_ID:
609618
return {
610619
...state,

src/commons/workspace/WorkspaceTypes.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const TOGGLE_EDITOR_AUTORUN = 'TOGGLE_EDITOR_AUTORUN';
3737
export const TOGGLE_USING_SUBST = 'TOGGLE_USING_SUBST';
3838
export const TOGGLE_USING_ENV = 'TOGGLE_USING_ENV';
3939
export const TOGGLE_UPDATE_ENV = 'TOGGLE_UPDATE_ENV';
40+
export const UPDATE_SUBMISSIONS_TABLE_FILTERS = 'UPDATE_SUBMISSIONS_TABLE_FILTERS';
4041
export const UPDATE_CURRENT_ASSESSMENT_ID = 'UPDATE_CURRENT_ASSESSMENT_ID';
4142
export const UPDATE_CURRENT_SUBMISSION_ID = 'UPDATE_CURRENT_SUBMISSION_ID';
4243
export const TOGGLE_FOLDER_MODE = 'TOGGLE_FOLDER_MODE';
@@ -71,6 +72,7 @@ type AssessmentWorkspaceAttr = {
7172
type AssessmentWorkspaceState = AssessmentWorkspaceAttr & WorkspaceState;
7273

7374
type GradingWorkspaceAttr = {
75+
readonly submissionsTableFilters: SubmissionsTableFilters;
7476
readonly currentSubmission?: number;
7577
readonly currentQuestion?: number;
7678
readonly hasUnsavedChanges: boolean;
@@ -147,3 +149,8 @@ export type DebuggerContext = {
147149
context: Context;
148150
workspaceLocation?: WorkspaceLocation;
149151
};
152+
153+
export type SubmissionsTableFilters = {
154+
columnFilters: { id: string; value: unknown }[];
155+
globalFilter: string | null;
156+
};

src/commons/workspace/__tests__/WorkspaceActions.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ import {
4646
updateEditorValue,
4747
updateHasUnsavedChanges,
4848
updateReplValue,
49-
updateSublanguage
49+
updateSublanguage,
50+
updateSubmissionsTableFilters
5051
} from '../WorkspaceActions';
5152
import {
5253
ADD_EDITOR_TAB,
@@ -90,6 +91,7 @@ import {
9091
UPDATE_HAS_UNSAVED_CHANGES,
9192
UPDATE_REPL_VALUE,
9293
UPDATE_SUBLANGUAGE,
94+
UPDATE_SUBMISSIONS_TABLE_FILTERS,
9395
WorkspaceLocation
9496
} from '../WorkspaceTypes';
9597

@@ -541,6 +543,30 @@ test('resetWorkspace generates correct action object with provided workspace', (
541543
});
542544
});
543545

546+
test('updateSubmissionsTableFilters generates correct action object', () => {
547+
const columnFilters = [
548+
{
549+
id: 'groupName',
550+
value: '1A'
551+
},
552+
{
553+
id: 'assessmentType',
554+
value: 'Missions'
555+
}
556+
];
557+
const globalFilter = 'runes';
558+
const action = updateSubmissionsTableFilters({ columnFilters, globalFilter });
559+
expect(action).toEqual({
560+
type: UPDATE_SUBMISSIONS_TABLE_FILTERS,
561+
payload: {
562+
filters: {
563+
columnFilters,
564+
globalFilter
565+
}
566+
}
567+
});
568+
});
569+
544570
test('updateCurrentAssessmentId generates correct action object', () => {
545571
const assessmentId = 2;
546572
const questionId = 4;

src/pages/academy/Academy.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Redirect, Route, Switch, useParams, useRouteMatch } from 'react-router'
66
import { useTypedSelector } from 'src/commons/utils/Hooks';
77

88
import {
9+
fetchGradingOverviews,
910
fetchNotifications,
1011
updateLatestViewedCourse
1112
} from '../../commons/application/actions/SessionActions';
@@ -18,7 +19,7 @@ import NotFound from '../notFound/NotFound';
1819
import AdminPanel from './adminPanel/AdminPanel';
1920
import Dashboard from './dashboard/Dashboard';
2021
import Game from './game/Game';
21-
import Grading from './grading/GradingContainer';
22+
import Grading from './grading/Grading';
2223
import GroundControl from './groundControl/GroundControlContainer';
2324
import Sourcereel from './sourcereel/SourcereelContainer';
2425
import StorySimulator from './storySimulator/StorySimulator';
@@ -29,6 +30,7 @@ const Academy: React.FC<{}> = () => {
2930
const dispatch = useDispatch();
3031
React.useEffect(() => {
3132
dispatch(fetchNotifications());
33+
dispatch(fetchGradingOverviews(false));
3234
}, [dispatch]);
3335

3436
const assessmentConfigurations = useTypedSelector(

0 commit comments

Comments
 (0)