Skip to content

Transfer pagination work from frontend to backend #2787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 110 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
7612c87
hello world.
josh1248 Jan 26, 2024
bb5bf9f
Y this so hard
josh1248 Jan 26, 2024
b067e6f
commit test: remove junk text files
josh1248 Jan 27, 2024
385be38
changed pagination index from +1 to +12345 to explore consequences
josh1248 Jan 27, 2024
4b0f6c2
prototype page query parameter upon right arrow click. TODO: clean up…
josh1248 Jan 27, 2024
22f2975
page querying and loading proof of concept
josh1248 Jan 27, 2024
8a27d0c
Now accepts page query when loading, albeit naively
josh1248 Jan 27, 2024
bb40de7
now adds query based on view.
josh1248 Jan 27, 2024
5397ac6
renamed frontend query parameters to index to avoid confusion with ba…
josh1248 Feb 4, 2024
bb092ee
Sanity check: hardcoded offset / pageSize values to verify redux.
josh1248 Feb 4, 2024
9c83900
Redux action updated to channel page query to backend
josh1248 Feb 4, 2024
1a99fde
Input validation for page querying
josh1248 Feb 4, 2024
fdf7920
Now also accepts pageSize query
josh1248 Feb 4, 2024
3039476
mapped button to dispatch (WIP - very bad UI now.)
josh1248 Feb 6, 2024
8b8f1e2
now with slightly more passable UI =D
josh1248 Feb 6, 2024
22d58e8
neutralized innate pagination of tanstack.
josh1248 Feb 6, 2024
9d38543
i bow down to the redux spaghetti
josh1248 Feb 6, 2024
0c02df7
remove URL querying
josh1248 Feb 13, 2024
6344b99
dispatch moved into page, prop passed into component now
josh1248 Feb 13, 2024
6b1a2d9
table now uses zero-indexed pagination, and converts page to offset b…
josh1248 Feb 13, 2024
ab8ea02
Test query builder - do not pull this commit
josh1248 Feb 13, 2024
49aae24
Filtering for name and type (Proof of concept)
josh1248 Feb 13, 2024
af3e887
State dispatch modified to utilize backend response format changes
josh1248 Feb 13, 2024
c0cb4e6
table columns and Filterable now included within the GradingSubmissio…
josh1248 Feb 14, 2024
a76d0aa
simple list selection for pageSize.
josh1248 Feb 14, 2024
572c9d1
Filtering for student name and student username transferred to backend
josh1248 Feb 14, 2024
9fc1c82
Unused tanstack pagination has been removed, as backend filters ensur…
josh1248 Feb 16, 2024
3979b69
Separation of concerns test commit
josh1248 Feb 16, 2024
411d6d6
SubmissionStatus now runs on backend filtering. Remaining: GroupName …
josh1248 Feb 16, 2024
57467d8
Refactored filter parameters from Gradings page into Grading Submissi…
josh1248 Feb 17, 2024
d86de79
Frontend filtering for graded status removed. (BUG: False positives)
josh1248 Feb 17, 2024
0320686
Removees prop passing for Filterable to take advantage of its nested …
josh1248 Feb 17, 2024
4968e12
Swapped underlying boolean values for group filtering to filter only …
josh1248 Feb 17, 2024
e0baff0
Merge branch 'master' into josh/pagination
josh1248 Feb 17, 2024
6a7d61d
Merge branch 'master' into josh/pagination
RichDom2185 Feb 18, 2024
f1762e9
Fix format
RichDom2185 Feb 18, 2024
5adee7f
Remove commented code
RichDom2185 Feb 18, 2024
cf3d000
Use dependency injection for Filterable
RichDom2185 Feb 18, 2024
15792fb
Revert unintended changes
RichDom2185 Feb 18, 2024
199c8e1
Use destructuring for simplicity
RichDom2185 Feb 18, 2024
355bee9
Use type alias for GradingOverviews
RichDom2185 Feb 18, 2024
263919f
Fix incorrect typing
RichDom2185 Feb 18, 2024
a410e25
Remove extra whitespace
RichDom2185 Feb 18, 2024
5aeec75
Fix tests
RichDom2185 Feb 18, 2024
8584e9b
Use new type alias in test file
RichDom2185 Feb 18, 2024
4b628c5
Now includes backend filtering by group name. All backend filters imp…
josh1248 Feb 19, 2024
0e8152e
Fixed bug where filtering did not reset page.
josh1248 Feb 19, 2024
6500126
Updated correct page options.
josh1248 Feb 19, 2024
460fa77
formatting
josh1248 Feb 19, 2024
ab1e7e0
Update GradingSubmissionsTable.tsx
josh1248 Feb 19, 2024
67c2993
Update EnvVisualizer.tsx.snap
josh1248 Feb 19, 2024
a4c627e
Update EnvVisualizer.tsx.snap
josh1248 Feb 19, 2024
eb29f13
Smarter derived state usage with useMemo
josh1248 Feb 19, 2024
8bfe2ea
fixed infinite re-rendering.
josh1248 Feb 19, 2024
28f11b8
linting
josh1248 Feb 19, 2024
565bd2a
Move columns outside component again
RichDom2185 Feb 19, 2024
18ff516
Remove unnecessary type arguments
RichDom2185 Feb 19, 2024
9d3598f
Reorder lines
RichDom2185 Feb 19, 2024
dbab9c0
Merge branch 'source-academy:master' into josh/pagination
josh1248 Feb 20, 2024
ea08346
memoized getGradingOverviewsCallback
josh1248 Feb 20, 2024
a7e32c9
revert
josh1248 Feb 20, 2024
5fcdc45
PR comment 1: overviews callback function now memoized
josh1248 Feb 20, 2024
31d0f8d
Update src/pages/academy/grading/subcomponents/GradingSubmissionsTabl…
josh1248 Feb 20, 2024
fd89443
PR Comment 2: derived maxPage + semantic change
josh1248 Feb 20, 2024
de88695
Update test snapshots
RichDom2185 Feb 20, 2024
52a32d9
Merge branch 'master' into josh/pagination
josh1248 Feb 20, 2024
7f419b6
Remove grading summary from Grading page
RichDom2185 Feb 21, 2024
49824b5
Move expensive util function out of component
josh1248 Feb 21, 2024
6e754c2
PR change: util function + shift dropdown back to grading page
josh1248 Feb 21, 2024
87e072b
linting
josh1248 Feb 21, 2024
a1d8bfd
Actually pushes grading util migration
josh1248 Feb 21, 2024
44f0a14
useRef flag to disable re-initialization of callback prop in submissi…
josh1248 Feb 21, 2024
da82dc0
Revert: Submissions from groups now default to all / my groups based…
josh1248 Feb 21, 2024
5b997a3
Move dropdown options out of component
josh1248 Feb 21, 2024
be95a88
Update whitespace
RichDom2185 Feb 21, 2024
a905b6f
Invert `limitGroup` back to `showAllGroups`
RichDom2185 Feb 21, 2024
da27738
Rename `showSubmissionOptions` back to `showOptions`
RichDom2185 Feb 21, 2024
9187b20
Reorder lines
RichDom2185 Feb 21, 2024
3d747db
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 Feb 21, 2024
6ba9a5a
Improve code readability
RichDom2185 Feb 21, 2024
61f06af
globalFilter removed from tanstack, search now mapped to mission titl…
josh1248 Feb 21, 2024
7ef4d84
update test types
josh1248 Feb 21, 2024
4b076a7
removed globalFilter in test
josh1248 Feb 21, 2024
212ad35
lint
josh1248 Feb 21, 2024
6fe844a
Merge branch 'master' into josh/pagination
RichDom2185 Feb 22, 2024
987123c
Removed filtering support for individual grading stauses, filtering b…
josh1248 Feb 22, 2024
daee139
All frontend filtering removed.
Feb 22, 2024
a68c46e
fix: Add notFullyGraded to query param for ungraded filter
GabrielCWT Feb 23, 2024
d990a37
Debouncing added to search bar.
Feb 23, 2024
6358e22
Revert "Debouncing added to search bar."
RichDom2185 Feb 23, 2024
844c38b
Use lodash for debouncing over setTimeout
RichDom2185 Feb 23, 2024
8157a3f
Fix controlled search field regression
RichDom2185 Feb 23, 2024
52f8fbf
Move pagination logic back inside table component
RichDom2185 Feb 23, 2024
6d115f9
Use `loadContentDispatch` prop for initial fetch
RichDom2185 Feb 23, 2024
8d0816d
Remove unnecessary `useRef` logic
RichDom2185 Feb 23, 2024
a84c92e
Remove old pagination logic
RichDom2185 Feb 23, 2024
2c36d1d
Fix debounce not debouncing
RichDom2185 Feb 23, 2024
b4bc1db
Remove unnecessary flex container
RichDom2185 Feb 23, 2024
b33d957
Remove extra whitespace
RichDom2185 Feb 23, 2024
c0c5ffd
Add deletion TODO
RichDom2185 Feb 23, 2024
236d9fc
Improve type safety
RichDom2185 Feb 23, 2024
690844f
Improve request param generation
RichDom2185 Feb 23, 2024
bb4aa44
Fix query param generation bugs
RichDom2185 Feb 23, 2024
915866d
Reorganize lines
RichDom2185 Feb 23, 2024
5b23087
Merge branch 'master' into josh/pagination
RichDom2185 Feb 23, 2024
8548356
Merge branch 'master' into josh/pagination
RichDom2185 Feb 23, 2024
791cea1
invert control flow of gradedOnly to correct state, return empty obje…
josh1248 Feb 23, 2024
7b1ecc6
invert control flow of gradedOnly to correct state
josh1248 Feb 23, 2024
4c8675f
Priority of params switched in RequestsSaga. This allows the ungraded…
josh1248 Feb 23, 2024
cc8618c
Fix page not resetting on dropdown option change
RichDom2185 Feb 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/commons/application/ApplicationTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,7 @@ export const defaultWorkspaceManager: WorkspaceManagerState = {
grading: {
...createDefaultWorkspace('grading'),
submissionsTableFilters: {
columnFilters: [],
globalFilter: null
columnFilters: []
},
currentSubmission: undefined,
currentQuestion: undefined,
Expand Down
23 changes: 18 additions & 5 deletions src/commons/application/actions/SessionActions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import {
paginationToBackendParams,
ungradedToBackendParams
} from 'src/features/grading/GradingUtils';
import { action } from 'typesafe-actions'; // EDITED

import { GradingOverview, GradingQuery } from '../../../features/grading/GradingTypes';
import { GradingOverviews, GradingQuery } from '../../../features/grading/GradingTypes';
import {
Assessment,
AssessmentConfiguration,
Expand Down Expand Up @@ -102,11 +106,20 @@ export const fetchTotalXpAdmin = (courseRegId: number) => action(FETCH_TOTAL_XP_
export const fetchGrading = (submissionId: number) => action(FETCH_GRADING, submissionId);

/**
* @param filterToGroup - param when set to true, only shows submissions under the group
* @param filterToGroup - param that when set to true, only shows submissions under the group
* of the grader
* @param gradedFilter - backend params to filter to ungraded
* @param pageParams - param that contains offset and pageSize, informing backend about how
* many entries, starting from what offset, to get
* @param filterParams - param that contains columnFilters converted into JSON for
* processing into query parameters
*/
export const fetchGradingOverviews = (filterToGroup = true) =>
action(FETCH_GRADING_OVERVIEWS, filterToGroup);
export const fetchGradingOverviews = (
filterToGroup = true,
gradedFilter = ungradedToBackendParams(false),
pageParams = paginationToBackendParams(0, 10),
filterParams = {}
) => action(FETCH_GRADING_OVERVIEWS, { filterToGroup, gradedFilter, pageParams, filterParams });

export const login = (providerId: string) => action(LOGIN, providerId);

Expand Down Expand Up @@ -202,7 +215,7 @@ export const updateTotalXp = (totalXp: number) => action(UPDATE_TOTAL_XP, totalX

export const updateAssessment = (assessment: Assessment) => action(UPDATE_ASSESSMENT, assessment);

export const updateGradingOverviews = (overviews: GradingOverview[]) =>
export const updateGradingOverviews = (overviews: GradingOverviews) =>
action(UPDATE_GRADING_OVERVIEWS, overviews);

/**
Expand Down
72 changes: 46 additions & 26 deletions src/commons/application/actions/__tests__/SessionActions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Chapter, Variant } from 'js-slang/dist/types';
import {
paginationToBackendParams,
ungradedToBackendParams
} from 'src/features/grading/GradingUtils';

import { GradingOverview, GradingQuery } from '../../../../features/grading/GradingTypes';
import { GradingOverviews, GradingQuery } from '../../../../features/grading/GradingTypes';
import { Assessment, AssessmentOverview } from '../../../assessment/AssessmentTypes';
import { Notification } from '../../../notificationBadge/NotificationBadgeTypes';
import { GameState, Role, Story } from '../../ApplicationTypes';
Expand Down Expand Up @@ -150,16 +154,29 @@ test('fetchGradingOverviews generates correct default action object', () => {
const action = fetchGradingOverviews();
expect(action).toEqual({
type: FETCH_GRADING_OVERVIEWS,
payload: true
payload: {
filterToGroup: true,
gradedFilter: ungradedToBackendParams(false),
pageParams: paginationToBackendParams(0, 10),
filterParams: {}
}
});
});

test('fetchGradingOverviews generates correct action object', () => {
const filterToGroup = false;
const action = fetchGradingOverviews(filterToGroup);
const gradedFilter = ungradedToBackendParams(true);
const pageParams = { offset: 123, pageSize: 456 };
const filterParams = { abc: 'xxx', def: 'yyy' };
const action = fetchGradingOverviews(filterToGroup, gradedFilter, pageParams, filterParams);
expect(action).toEqual({
type: FETCH_GRADING_OVERVIEWS,
payload: filterToGroup
payload: {
filterToGroup: filterToGroup,
gradedFilter: gradedFilter,
pageParams: pageParams,
filterParams: filterParams
}
});
});

Expand Down Expand Up @@ -510,28 +527,31 @@ test('updateAssessment generates correct action object', () => {
});

test('updateGradingOverviews generates correct action object', () => {
const overviews: GradingOverview[] = [
{
assessmentId: 1,
assessmentNumber: 'M1A',
assessmentName: 'test assessment',
assessmentType: 'Contests',
initialXp: 0,
xpBonus: 100,
xpAdjustment: 50,
currentXp: 50,
maxXp: 500,
studentId: 100,
studentName: 'test student',
studentUsername: 'E0123456',
submissionId: 1,
submissionStatus: 'attempting',
groupName: 'group',
gradingStatus: 'excluded',
questionCount: 6,
gradedCount: 0
}
];
const overviews: GradingOverviews = {
count: 1,
data: [
{
assessmentId: 1,
assessmentNumber: 'M1A',
assessmentName: 'test assessment',
assessmentType: 'Contests',
initialXp: 0,
xpBonus: 100,
xpAdjustment: 50,
currentXp: 50,
maxXp: 500,
studentId: 100,
studentName: 'test student',
studentUsername: 'E0123456',
submissionId: 1,
submissionStatus: 'attempting',
groupName: 'group',
gradingStatus: 'excluded',
questionCount: 6,
gradedCount: 0
}
]
};

const action = updateGradingOverviews(overviews);
expect(action).toEqual({
Expand Down
5 changes: 4 additions & 1 deletion src/commons/application/reducers/__tests__/SessionReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,10 @@ test('UPDATE_GRADING_OVERVIEWS works correctly in inserting grading overviews',
test('UPDATE_GRADING_OVERVIEWS works correctly in updating grading overviews', () => {
const newDefaultSession = {
...defaultSession,
gradingOverviews: gradingOverviewTest1
gradingOverviews: {
count: gradingOverviewTest1.length,
data: gradingOverviewTest1
}
};
const gradingOverviewsPayload = [...gradingOverviewTest2, ...gradingOverviewTest1];
const action = {
Expand Down
4 changes: 2 additions & 2 deletions src/commons/application/types/SessionTypes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Octokit } from '@octokit/rest';
import { Chapter, Variant } from 'js-slang/dist/types';

import { GradingOverview, GradingQuery } from '../../../features/grading/GradingTypes';
import { GradingOverviews, GradingQuery } from '../../../features/grading/GradingTypes';
import { Device, DeviceSession } from '../../../features/remoteExecution/RemoteExecutionTypes';
import {
Assessment,
Expand Down Expand Up @@ -114,7 +114,7 @@ export type SessionState = {

readonly assessmentOverviews?: AssessmentOverview[];
readonly assessments: Map<number, Assessment>;
readonly gradingOverviews?: GradingOverview[];
readonly gradingOverviews?: GradingOverviews;
readonly gradings: Map<number, GradingQuery>;
readonly notifications: Notification[];
readonly googleUser?: string;
Expand Down
4 changes: 2 additions & 2 deletions src/commons/assessment/AssessmentTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export enum QuestionTypes {
export type QuestionType = keyof typeof QuestionTypes;

/*
W* Used to display information regarding an assessment in the UI.
*
* Used to display information regarding an assessment in the UI.
*
* @property closeAt an ISO 8601 compliant date string specifiying when
* the assessment closes
* @property openAt an ISO 8601 compliant date string specifiying when
Expand Down
22 changes: 13 additions & 9 deletions src/commons/mocks/BackendMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { call, put, select, takeEvery } from 'redux-saga/effects';

import { FETCH_GROUP_GRADING_SUMMARY } from '../../features/dashboard/DashboardTypes';
import {
GradingOverview,
GradingOverviews,
GradingQuery,
GradingQuestion
} from '../../features/grading/GradingTypes';
Expand Down Expand Up @@ -166,12 +166,12 @@ export function* mockBackendSaga(): SagaIterator {
FETCH_GRADING_OVERVIEWS,
function* (action: ReturnType<typeof actions.fetchGradingOverviews>): any {
const accessToken = yield select((state: OverallState) => state.session.accessToken);
const filterToGroup = action.payload;
const { filterToGroup, pageParams, filterParams } = action.payload;
const gradingOverviews = yield call(() =>
mockFetchGradingOverview(accessToken, filterToGroup)
mockFetchGradingOverview(accessToken, filterToGroup, pageParams, filterParams)
);
if (gradingOverviews !== null) {
yield put(actions.updateGradingOverviews([...gradingOverviews]));
yield put(actions.updateGradingOverviews(gradingOverviews));
}
}
);
Expand All @@ -189,25 +189,29 @@ export function* mockBackendSaga(): SagaIterator {
UNSUBMIT_SUBMISSION,
function* (action: ReturnType<typeof actions.unsubmitSubmission>) {
const { submissionId } = action.payload;
const overviews: GradingOverview[] = yield select(
(state: OverallState) => state.session.gradingOverviews || []
const overviews: GradingOverviews = yield select(
(state: OverallState) =>
state.session.gradingOverviews || {
count: 0,
data: []
}
);
const index = overviews.findIndex(
const index = overviews.data.findIndex(
overview =>
overview.submissionId === submissionId && overview.submissionStatus === 'submitted'
);
if (index === -1) {
yield call(showWarningMessage, '400: Bad Request');
return;
}
const newOverviews = (overviews as GradingOverview[]).map(overview => {
const newOverviews = overviews.data.map(overview => {
if (overview.submissionId === submissionId) {
return { ...overview, submissionStatus: 'attempted' };
}
return overview;
});
yield call(showSuccessMessage, 'Unsubmit successful!', 1000);
yield put(actions.updateGradingOverviews(newOverviews));
yield put(actions.updateGradingOverviews({ ...overviews, data: newOverviews }));
}
);

Expand Down
6 changes: 5 additions & 1 deletion src/commons/mocks/GradingMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@ export const mockGradingOverviews: GradingOverview[] = [
*
* @param accessToken a valid access token for the cadet backend.
* @param group a boolean if true, only fetches submissions from the grader's group
* @param pageParams contains pagination details on offset and page index.
* @param backendParams contains filters to set conditions in SQL query.
*/
export const mockFetchGradingOverview = (
accessToken: string,
group: boolean
group: boolean,
pageParams: { offset: number; pageSize: number },
backendParams: Object
): GradingOverview[] | null => {
// mocks backend role fetching
const permittedRoles: Role[] = [Role.Admin, Role.Staff];
Expand Down
20 changes: 15 additions & 5 deletions src/commons/sagas/BackendSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '../../features/dashboard/DashboardTypes';
import {
GradingOverview,
GradingOverviews,
GradingQuery,
GradingQuestion
} from '../../features/grading/GradingTypes';
Expand Down Expand Up @@ -414,12 +415,15 @@ function* BackendSaga(): SagaIterator {
function* (action: ReturnType<typeof actions.fetchGradingOverviews>) {
const tokens: Tokens = yield selectTokens();

const filterToGroup = action.payload;
const { filterToGroup, gradedFilter, pageParams, filterParams } = action.payload;

const gradingOverviews: GradingOverview[] | null = yield call(
const gradingOverviews: GradingOverviews | null = yield call(
getGradingOverviews,
tokens,
filterToGroup
filterToGroup,
gradedFilter,
pageParams,
filterParams
);
if (gradingOverviews) {
yield put(actions.updateGradingOverviews(gradingOverviews));
Expand Down Expand Up @@ -452,7 +456,7 @@ function* BackendSaga(): SagaIterator {
}

const overviews: GradingOverview[] = yield select(
(state: OverallState) => state.session.gradingOverviews || []
(state: OverallState) => state.session.gradingOverviews?.data || []
);
const newOverviews = overviews.map(overview => {
if (overview.submissionId === submissionId) {
Expand All @@ -461,8 +465,14 @@ function* BackendSaga(): SagaIterator {
return overview;
});

const totalPossibleEntries = yield select(
(state: OverallState) => state.session.gradingOverviews?.count
);

yield call(showSuccessMessage, 'Unsubmit successful', 1000);
yield put(actions.updateGradingOverviews(newOverviews));
yield put(
actions.updateGradingOverviews({ count: totalPossibleEntries, data: newOverviews })
);
}
);

Expand Down
Loading