Skip to content

Commit 99e54ed

Browse files
Resolve loading indicator issues in grading table (#3064)
* Use updated AGGrid API for async loading logo Current implementation uses the outdated api.showLoadingOverlay(), which causes issues in loading as the loading logo disappears even before the data arrives. This commit uses the current method of using the "loading" field in the AGGrid component, which solves the loading mismatch issue. * Block refreshing while loading * Remove unnecesssary closing tag * Update tooltip position for visibility --------- Co-authored-by: Richard Dominick <34370238+RichDom2185@users.noreply.github.com>
1 parent 105546f commit 99e54ed

File tree

3 files changed

+63
-60
lines changed

3 files changed

+63
-60
lines changed

src/pages/academy/grading/Grading.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Button, Icon, NonIdealState, Position, Spinner, SpinnerSize } from '@blueprintjs/core';
22
import { IconNames } from '@blueprintjs/icons';
3-
import React, { useCallback, useEffect, useState } from 'react';
3+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
44
import { useDispatch } from 'react-redux';
55
import { Navigate, useParams } from 'react-router';
66
import SessionActions from 'src/commons/application/actions/SessionActions';
@@ -57,6 +57,9 @@ const Grading: React.FC = () => {
5757
const dispatch = useDispatch();
5858
const allColsSortStates = useTypedSelector(state => state.workspaces.grading.allColsSortStates);
5959
const hasLoadedBefore = useTypedSelector(state => state.workspaces.grading.hasLoadedBefore);
60+
const requestCounter = useTypedSelector(state => state.workspaces.grading.requestCounter);
61+
62+
const isLoading = useMemo(() => requestCounter > 0, [requestCounter]);
6063

6164
const updateGradingOverviewsCallback = useCallback(
6265
(page: number, filterParams: object) => {
@@ -207,6 +210,7 @@ const Grading: React.FC = () => {
207210
setAnimateRefresh(true);
208211
}}
209212
onAnimationEnd={e => setAnimateRefresh(false)}
213+
disabled={isLoading}
210214
>
211215
<Icon htmlTitle="Refresh" icon={IconNames.REFRESH} />
212216
</Button>

src/pages/academy/grading/subcomponents/GradingActions.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, Icon, Tooltip } from '@blueprintjs/core';
1+
import { Button, Icon, Position, Tooltip } from '@blueprintjs/core';
22
import { IconNames } from '@blueprintjs/icons';
33
import React from 'react';
44
import { useDispatch } from 'react-redux';
@@ -82,7 +82,7 @@ const GradingActions: React.FC<Props> = ({ submissionId, style, progress, filter
8282
{filterMode && (
8383
<Link to={`/courses/${courseId}/grading/${submissionId}`}>
8484
<GradingFlex alignItems="center" className="grading-action-icons grading-action-icons-bg">
85-
<Tooltip content="Grade">
85+
<Tooltip position={Position.TOP} content="Grade">
8686
<Icon icon={IconNames.EDIT} />
8787
</Tooltip>
8888
</GradingFlex>
@@ -96,7 +96,7 @@ const GradingActions: React.FC<Props> = ({ submissionId, style, progress, filter
9696
style={{ padding: 0 }}
9797
onClick={handleReautogradeClick}
9898
>
99-
<Tooltip content="Reautograde">
99+
<Tooltip position={Position.TOP} content="Reautograde">
100100
<Icon icon={IconNames.REFRESH} />
101101
</Tooltip>
102102
</Button>
@@ -109,23 +109,23 @@ const GradingActions: React.FC<Props> = ({ submissionId, style, progress, filter
109109
style={{ padding: 0 }}
110110
onClick={handleUnsubmitClick}
111111
>
112-
<Tooltip content="Unsubmit">
112+
<Tooltip position={Position.TOP} content="Unsubmit">
113113
<Icon icon={IconNames.UNDO} />
114114
</Tooltip>
115115
</Button>
116116
)}
117117

118118
{isGraded && (
119119
<Button className="grading-action-icons" minimal onClick={handlePublishClick}>
120-
<Tooltip content="Publish">
120+
<Tooltip position={Position.TOP} content="Publish">
121121
<Icon icon={IconNames.SEND_TO_GRAPH} />
122122
</Tooltip>
123123
</Button>
124124
)}
125125

126126
{isPublished && (
127127
<Button className="grading-action-icons" minimal onClick={handleUnpublishClick}>
128-
<Tooltip content="Unpublish">
128+
<Tooltip position={Position.TOP} content="Unpublish">
129129
<Icon icon={IconNames.EXCLUDE_ROW} />
130130
</Tooltip>
131131
</Button>

src/pages/academy/grading/subcomponents/GradingSubmissionsTable.tsx

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ const GradingSubmissionTable: React.FC<GradingSubmissionTableProps> = ({
9999
// This is what that controls Grading Mode. If future feedback says it's better to default to filter mode, change it here.
100100
const [filterMode, setFilterMode] = useState<boolean>(false);
101101

102+
const isLoading = useMemo(() => requestCounter > 0, [requestCounter]);
103+
102104
const maxPage = useMemo(() => Math.ceil(totalRows / pageSize) - 1, [totalRows, pageSize]);
103105
const resetPage = useCallback(() => setPage(0), [setPage]);
104106

@@ -264,56 +266,52 @@ const GradingSubmissionTable: React.FC<GradingSubmissionTableProps> = ({
264266

265267
useEffect(() => {
266268
if (gridRef.current?.api) {
267-
if (requestCounter <= 0) {
268-
const newData: IGradingTableRow[] = [];
269-
270-
const sameData: boolean = submissions.reduce((sameData, currentSubmission, index) => {
271-
const newRow: IGradingTableRow = {
272-
assessmentName: currentSubmission.assessmentName,
273-
assessmentType: currentSubmission.assessmentType,
274-
studentName: currentSubmission.studentName
275-
? currentSubmission.studentName
276-
: currentSubmission.studentNames
277-
? currentSubmission.studentNames.join(', ')
278-
: '',
279-
studentUsername: currentSubmission.studentUsername
280-
? currentSubmission.studentUsername
281-
: currentSubmission.studentUsernames
282-
? currentSubmission.studentUsernames.join(', ')
283-
: '',
284-
groupName: currentSubmission.groupName,
285-
progressStatus: currentSubmission.progress,
286-
xp:
287-
currentSubmission.currentXp +
288-
' (+' +
289-
currentSubmission.xpBonus +
290-
') / ' +
291-
currentSubmission.maxXp,
292-
actionsIndex: currentSubmission.submissionId,
293-
courseID: courseId!
294-
};
295-
newData.push(newRow);
296-
return (
297-
sameData &&
298-
newRow.actionsIndex === rowData?.[index]?.actionsIndex &&
299-
newRow.studentUsername === rowData?.[index]?.studentUsername &&
300-
newRow.groupName === rowData?.[index]?.groupName &&
301-
newRow.progressStatus === rowData?.[index]?.progressStatus &&
302-
newRow.xp === rowData?.[index]?.xp
303-
);
304-
}, submissions.length === rowData?.length);
305-
306-
if (!sameData) {
307-
setRowData(newData);
308-
}
269+
const newData: IGradingTableRow[] = [];
270+
271+
const sameData: boolean = submissions.reduce((sameData, currentSubmission, index) => {
272+
const newRow: IGradingTableRow = {
273+
assessmentName: currentSubmission.assessmentName,
274+
assessmentType: currentSubmission.assessmentType,
275+
studentName: currentSubmission.studentName
276+
? currentSubmission.studentName
277+
: currentSubmission.studentNames
278+
? currentSubmission.studentNames.join(', ')
279+
: '',
280+
studentUsername: currentSubmission.studentUsername
281+
? currentSubmission.studentUsername
282+
: currentSubmission.studentUsernames
283+
? currentSubmission.studentUsernames.join(', ')
284+
: '',
285+
groupName: currentSubmission.groupName,
286+
progressStatus: currentSubmission.progress,
287+
xp:
288+
currentSubmission.currentXp +
289+
' (+' +
290+
currentSubmission.xpBonus +
291+
') / ' +
292+
currentSubmission.maxXp,
293+
actionsIndex: currentSubmission.submissionId,
294+
courseID: courseId!
295+
};
296+
newData.push(newRow);
297+
return (
298+
sameData &&
299+
newRow.actionsIndex === rowData?.[index]?.actionsIndex &&
300+
newRow.studentUsername === rowData?.[index]?.studentUsername &&
301+
newRow.groupName === rowData?.[index]?.groupName &&
302+
newRow.progressStatus === rowData?.[index]?.progressStatus &&
303+
newRow.xp === rowData?.[index]?.xp
304+
);
305+
}, submissions.length === rowData?.length);
306+
307+
if (!sameData) {
308+
setRowData(newData);
309+
}
309310

310-
gridRef.current!.api.hideOverlay();
311+
gridRef.current!.api.hideOverlay();
311312

312-
if (newData.length === 0 && requestCounter <= 0) {
313-
gridRef.current!.api.showNoRowsOverlay();
314-
}
315-
} else {
316-
gridRef.current!.api.showLoadingOverlay();
313+
if (newData.length === 0 && requestCounter <= 0) {
314+
gridRef.current!.api.showNoRowsOverlay();
317315
}
318316
}
319317
// We ignore the dependency on rowData purposely as we setRowData above.
@@ -392,7 +390,7 @@ const GradingSubmissionTable: React.FC<GradingSubmissionTableProps> = ({
392390
large={true}
393391
value={searchQuery}
394392
onChange={handleSearchQueryUpdate}
395-
></InputGroup>
393+
/>
396394
</GradingFlex>
397395

398396
<div className="ag-theme-quartz" style={{ margin: tableProperties.tableMargins }}>
@@ -404,6 +402,7 @@ const GradingSubmissionTable: React.FC<GradingSubmissionTableProps> = ({
404402
components={tableProperties.customComponents}
405403
defaultColDef={tableProperties.defaultColDefs}
406404
headerHeight={tableProperties.headerHeight}
405+
loading={isLoading}
407406
overlayLoadingTemplate={tableProperties.overlayLoadingTemplate}
408407
overlayNoRowsTemplate={tableProperties.overlayNoRowsTemplate}
409408
pagination={tableProperties.pagination}
@@ -445,14 +444,14 @@ const GradingSubmissionTable: React.FC<GradingSubmissionTableProps> = ({
445444
minimal
446445
icon={IconNames.DOUBLE_CHEVRON_LEFT}
447446
onClick={() => setPage(0)}
448-
disabled={page <= 0}
447+
disabled={page <= 0 || isLoading}
449448
/>
450449
<Button
451450
small
452451
minimal
453452
icon={IconNames.ARROW_LEFT}
454453
onClick={() => setPage(page - 1)}
455-
disabled={page <= 0}
454+
disabled={page <= 0 || isLoading}
456455
/>
457456
<H6 style={{ margin: 'auto 0' }}>
458457
Page {maxPage + 1 === 0 ? 0 : page + 1} of {maxPage + 1}
@@ -462,14 +461,14 @@ const GradingSubmissionTable: React.FC<GradingSubmissionTableProps> = ({
462461
minimal
463462
icon={IconNames.ARROW_RIGHT}
464463
onClick={() => setPage(page + 1)}
465-
disabled={page >= maxPage}
464+
disabled={page >= maxPage || isLoading}
466465
/>
467466
<Button
468467
small
469468
minimal
470469
icon={IconNames.DOUBLE_CHEVRON_RIGHT}
471470
onClick={() => setPage(maxPage)}
472-
disabled={page >= maxPage}
471+
disabled={page >= maxPage || isLoading}
473472
/>
474473
</GradingFlex>
475474
</>

0 commit comments

Comments
 (0)