From 75745488c01f70b3c1710d14013da674df814120 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 03:36:05 +0800
Subject: [PATCH 01/26] Change hasTokenCounter to hasVotingAttributes in
Assessment Config. Enable tokencounter depending on assessment
hasTokenCounter, not assessmentConfig
---
.../actions/__tests__/SessionActions.ts | 21 ++++++-----
src/commons/assessment/AssessmentTypes.ts | 6 ++-
.../assessment/__tests__/Assessment.tsx | 2 +-
.../AssessmentWorkspace.tsx | 8 +---
.../__tests__/AssessmentWorkspace.tsx | 2 +-
src/commons/mocks/AssessmentMocks.ts | 37 +++++++++++--------
src/commons/profile/__tests__/Profile.tsx | 2 +-
src/commons/sagas/BackendSaga.ts | 2 +-
src/commons/sagas/__tests__/BackendSaga.ts | 12 +++---
.../AssessmentConfigPanel.tsx | 16 ++++----
10 files changed, 57 insertions(+), 51 deletions(-)
diff --git a/src/commons/application/actions/__tests__/SessionActions.ts b/src/commons/application/actions/__tests__/SessionActions.ts
index a2def9171e..d3fe24a515 100644
--- a/src/commons/application/actions/__tests__/SessionActions.ts
+++ b/src/commons/application/actions/__tests__/SessionActions.ts
@@ -295,7 +295,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -304,7 +304,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission2',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -313,7 +313,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission3',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
@@ -520,7 +520,8 @@ test('updateAssessment generates correct action object', () => {
longSummary: 'long summary here',
missionPDF: 'www.google.com',
questions: [],
- title: 'first assessment'
+ title: 'first assessment',
+ hasVotingAttributes: false
};
const action = updateAssessment(assessment);
@@ -680,7 +681,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -689,7 +690,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Quests',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -698,7 +699,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Paths',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -707,7 +708,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Contests',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -716,7 +717,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Others',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
@@ -734,7 +735,7 @@ test('deleteAssessmentConfig generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
};
diff --git a/src/commons/assessment/AssessmentTypes.ts b/src/commons/assessment/AssessmentTypes.ts
index 28aed1f6ca..7404d8d87d 100644
--- a/src/commons/assessment/AssessmentTypes.ts
+++ b/src/commons/assessment/AssessmentTypes.ts
@@ -81,6 +81,7 @@ export type Assessment = {
type: AssessmentType;
globalDeployment?: Library; // For mission control
graderDeployment?: Library; // For mission control
+ hasVotingAttributes: boolean;
hasTokenCounter?: boolean;
id: number;
longSummary: string;
@@ -96,7 +97,7 @@ export type AssessmentConfiguration = {
displayInDashboard: boolean;
hoursBeforeEarlyXpDecay: number;
earlySubmissionXp: number;
- hasTokenCounter: boolean;
+ hasVotingAttributes: boolean;
};
export interface IProgrammingQuestion extends BaseQuestion {
@@ -318,6 +319,7 @@ export const assessmentTemplate = (): Assessment => {
longSummary: 'Insert mission briefing here',
missionPDF: 'www.google.com',
questions: [programmingTemplate()],
- title: 'Insert title here'
+ title: 'Insert title here',
+ hasVotingAttributes: false
};
};
diff --git a/src/commons/assessment/__tests__/Assessment.tsx b/src/commons/assessment/__tests__/Assessment.tsx
index bb7aee31c9..135227f4db 100644
--- a/src/commons/assessment/__tests__/Assessment.tsx
+++ b/src/commons/assessment/__tests__/Assessment.tsx
@@ -17,7 +17,7 @@ const mockAssessmentProps = assertType()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
diff --git a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
index ed790279c3..1d0b661845 100644
--- a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
+++ b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
@@ -251,16 +251,12 @@ const AssessmentWorkspace: React.FC = props => {
* Handles toggling enabling and disabling token counter depending on assessment properties
*/
useEffect(() => {
- if (props.assessmentConfiguration.hasTokenCounter) {
+ if (assessment?.hasTokenCounter) {
handleEnableTokenCounter();
} else {
handleDisableTokenCounter();
}
- }, [
- props.assessmentConfiguration.hasTokenCounter,
- handleEnableTokenCounter,
- handleDisableTokenCounter
- ]);
+ }, [assessment?.hasTokenCounter, handleEnableTokenCounter, handleDisableTokenCounter]);
/**
* Handles toggling of relevant SideContentTabs when mobile breakpoint it hit
diff --git a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
index 6ffcf33954..f47bb4695e 100644
--- a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
+++ b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
@@ -26,7 +26,7 @@ const defaultProps = assertType()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
diff --git a/src/commons/mocks/AssessmentMocks.ts b/src/commons/mocks/AssessmentMocks.ts
index 10ec12626a..82d4318016 100644
--- a/src/commons/mocks/AssessmentMocks.ts
+++ b/src/commons/mocks/AssessmentMocks.ts
@@ -22,7 +22,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -31,7 +31,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -40,7 +40,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -49,7 +49,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: true,
+ hasVotingAttributes: true,
earlySubmissionXp: 200
},
{
@@ -58,7 +58,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
}
],
@@ -69,7 +69,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -78,7 +78,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -87,7 +87,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
}
]
@@ -910,7 +910,8 @@ export const mockAssessments: Assessment[] = [
'This is the mission briefing. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas viverra, sem scelerisque ultricies ullamcorper, sem nibh sollicitudin enim, at ultricies sem orci eget odio. Pellentesque varius et mauris quis vestibulum. Etiam in egestas dolor. Nunc consectetur, sapien sodales accumsan convallis, lectus mi tempus ipsum, vel ornare metus turpis sed justo. Vivamus at tellus sed ex convallis commodo at in lectus. Pellentesque pharetra pulvinar sapien pellentesque facilisis. Curabitur efficitur malesuada urna sed aliquam. Quisque massa metus, aliquam in sagittis non, cursus in sem. Morbi vel nunc at nunc pharetra lobortis. Aliquam feugiat ultricies ipsum vel sollicitudin. Vivamus nulla massa, hendrerit sit amet nibh quis, porttitor convallis nisi. ',
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
- title: 'An Odessey to Runes'
+ title: 'An Odessey to Runes',
+ hasVotingAttributes: false
},
{
type: 'Missions',
@@ -919,7 +920,8 @@ export const mockAssessments: Assessment[] = [
'This is the mission briefing. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas viverra, sem scelerisque ultricies ullamcorper, sem nibh sollicitudin enim, at ultricies sem orci eget odio. Pellentesque varius et mauris quis vestibulum. Etiam in egestas dolor. Nunc consectetur, sapien sodales accumsan convallis, lectus mi tempus ipsum, vel ornare metus turpis sed justo. Vivamus at tellus sed ex convallis commodo at in lectus. Pellentesque pharetra pulvinar sapien pellentesque facilisis. Curabitur efficitur malesuada urna sed aliquam. Quisque massa metus, aliquam in sagittis non, cursus in sem. Morbi vel nunc at nunc pharetra lobortis. Aliquam feugiat ultricies ipsum vel sollicitudin. Vivamus nulla massa, hendrerit sit amet nibh quis, porttitor convallis nisi. ',
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
- title: 'The Secret to Streams'
+ title: 'The Secret to Streams',
+ hasVotingAttributes: false
},
{
type: 'Quests',
@@ -945,7 +947,8 @@ export const mockAssessments: Assessment[] = [
\`\`\``,
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
- title: 'A sample Sidequest'
+ title: 'A sample Sidequest',
+ hasVotingAttributes: false
},
{
type: 'Missions',
@@ -954,7 +957,8 @@ export const mockAssessments: Assessment[] = [
'This is the closed mission briefing. The save button should not be there. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas viverra, sem scelerisque ultricies ullamcorper, sem nibh sollicitudin enim, at ultricies sem orci eget odio. Pellentesque varius et mauris quis vestibulum. Etiam in egestas dolor. Nunc consectetur, sapien sodales accumsan convallis, lectus mi tempus ipsum, vel ornare metus turpis sed justo. Vivamus at tellus sed ex convallis commodo at in lectus. Pellentesque pharetra pulvinar sapien pellentesque facilisis. Curabitur efficitur malesuada urna sed aliquam. Quisque massa metus, aliquam in sagittis non, cursus in sem. Morbi vel nunc at nunc pharetra lobortis. Aliquam feugiat ultricies ipsum vel sollicitudin. Vivamus nulla massa, hendrerit sit amet nibh quis, porttitor convallis nisi. ',
missionPDF: 'www.google.com',
questions: mockClosedAssessmentQuestions,
- title: 'A Closed Mission'
+ title: 'A Closed Mission',
+ hasVotingAttributes: false
},
{
type: 'Quests',
@@ -963,7 +967,8 @@ export const mockAssessments: Assessment[] = [
'This is the closed sidequest briefing. The save button should not exist. This is a placeholder sidequest for testing rendering of grading statuses.',
missionPDF: 'www.google.com',
questions: mockClosedAssessmentQuestions,
- title: 'A Closed Sidequest'
+ title: 'A Closed Sidequest',
+ hasVotingAttributes: false
},
{
type: 'Paths',
@@ -975,7 +980,8 @@ export const mockAssessments: Assessment[] = [
The path comprises 4 questions and is fully autograded and guided, and there are **no private test cases** - there will be no manual review by default. Please consult your Avenger if you require assistance!`,
missionPDF: 'www.google.com',
questions: mockPathQuestions,
- title: 'A sample guided path'
+ title: 'A sample guided path',
+ hasVotingAttributes: false
},
// mock assessment used for testing contest voting assessments
{
@@ -984,6 +990,7 @@ export const mockAssessments: Assessment[] = [
title: 'A sample contest voting assessment',
longSummary: 'Vote for your favourite contest entries here!',
missionPDF: 'www.google.com',
- questions: mockContestEntryQuestion
+ questions: mockContestEntryQuestion,
+ hasVotingAttributes: false
}
];
diff --git a/src/commons/profile/__tests__/Profile.tsx b/src/commons/profile/__tests__/Profile.tsx
index 55583cb291..a4cc5f364b 100644
--- a/src/commons/profile/__tests__/Profile.tsx
+++ b/src/commons/profile/__tests__/Profile.tsx
@@ -25,7 +25,7 @@ const assessmentConfigurations: AssessmentConfiguration[] = [
type: c,
isManuallyGraded: false,
displayInDashboard: false,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
hoursBeforeEarlyXpDecay: 0,
earlySubmissionXp: 0
}));
diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts
index 55bb55990a..1df6c6de9b 100644
--- a/src/commons/sagas/BackendSaga.ts
+++ b/src/commons/sagas/BackendSaga.ts
@@ -986,7 +986,7 @@ function* BackendSaga(): SagaIterator {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 0
}
];
diff --git a/src/commons/sagas/__tests__/BackendSaga.ts b/src/commons/sagas/__tests__/BackendSaga.ts
index 4bc740624f..74940dba14 100644
--- a/src/commons/sagas/__tests__/BackendSaga.ts
+++ b/src/commons/sagas/__tests__/BackendSaga.ts
@@ -218,7 +218,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -227,7 +227,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -236,7 +236,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
},
{
@@ -245,7 +245,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: true,
+ hasVotingAttributes: true,
earlySubmissionXp: 200
},
{
@@ -254,7 +254,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 200
}
];
@@ -1007,7 +1007,7 @@ describe('Test CREATE_COURSE action', () => {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 0
}
];
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index 0871fb53af..c476ec8008 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -51,14 +51,14 @@ const AssessmentConfigPanel: React.FC = ({
gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('displayInDashboard', value);
};
- const setHasTokenCounter = (index: number, value: boolean) => {
+ const setHasVotingAttributes = (index: number, value: boolean) => {
const temp = [...assessmentConfig.current];
temp[index] = {
...temp[index],
- hasTokenCounter: value
+ hasVotingAttributes: value
};
setAssessmentConfig(temp);
- gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('hasTokenCounter', value);
+ gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('hasVotingAttributes', value);
};
const setEarlyXp = (index: number, value: number) => {
@@ -94,7 +94,7 @@ const AssessmentConfigPanel: React.FC = ({
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
- hasTokenCounter: false,
+ hasVotingAttributes: false,
earlySubmissionXp: 0
});
setAssessmentConfig(temp);
@@ -140,12 +140,12 @@ const AssessmentConfigPanel: React.FC = ({
}
},
{
- headerName: 'Has Token Counter',
- field: 'hasTokenCounter',
+ headerName: 'Has Voting Attributes',
+ field: 'hasVotingAttributes',
cellRenderer: BooleanCell,
cellRendererParams: {
- setStateHandler: setHasTokenCounter,
- field: 'hasTokenCounter'
+ setStateHandler: setHasVotingAttributes,
+ field: 'hasVotingAttributes'
}
},
{
From f934853aee59474471593997fb27c586d5a03cca Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 03:43:14 +0800
Subject: [PATCH 02/26] Rename hasVotingAttributes to hasVotingFeatures
---
.../actions/__tests__/SessionActions.ts | 20 ++++++-------
src/commons/assessment/AssessmentTypes.ts | 6 ++--
.../assessment/__tests__/Assessment.tsx | 2 +-
.../__tests__/AssessmentWorkspace.tsx | 2 +-
src/commons/mocks/AssessmentMocks.ts | 30 +++++++++----------
src/commons/profile/__tests__/Profile.tsx | 2 +-
src/commons/sagas/BackendSaga.ts | 2 +-
src/commons/sagas/__tests__/BackendSaga.ts | 12 ++++----
.../AssessmentConfigPanel.tsx | 16 +++++-----
9 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/src/commons/application/actions/__tests__/SessionActions.ts b/src/commons/application/actions/__tests__/SessionActions.ts
index d3fe24a515..eebc86244e 100644
--- a/src/commons/application/actions/__tests__/SessionActions.ts
+++ b/src/commons/application/actions/__tests__/SessionActions.ts
@@ -295,7 +295,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -304,7 +304,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission2',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -313,7 +313,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission3',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
@@ -521,7 +521,7 @@ test('updateAssessment generates correct action object', () => {
missionPDF: 'www.google.com',
questions: [],
title: 'first assessment',
- hasVotingAttributes: false
+ hasVotingFeatures: false
};
const action = updateAssessment(assessment);
@@ -681,7 +681,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -690,7 +690,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Quests',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -699,7 +699,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Paths',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -708,7 +708,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Contests',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
@@ -717,7 +717,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Others',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
@@ -735,7 +735,7 @@ test('deleteAssessmentConfig generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
};
diff --git a/src/commons/assessment/AssessmentTypes.ts b/src/commons/assessment/AssessmentTypes.ts
index 7404d8d87d..32c4a139e4 100644
--- a/src/commons/assessment/AssessmentTypes.ts
+++ b/src/commons/assessment/AssessmentTypes.ts
@@ -81,7 +81,7 @@ export type Assessment = {
type: AssessmentType;
globalDeployment?: Library; // For mission control
graderDeployment?: Library; // For mission control
- hasVotingAttributes: boolean;
+ hasVotingFeatures: boolean;
hasTokenCounter?: boolean;
id: number;
longSummary: string;
@@ -97,7 +97,7 @@ export type AssessmentConfiguration = {
displayInDashboard: boolean;
hoursBeforeEarlyXpDecay: number;
earlySubmissionXp: number;
- hasVotingAttributes: boolean;
+ hasVotingFeatures: boolean;
};
export interface IProgrammingQuestion extends BaseQuestion {
@@ -320,6 +320,6 @@ export const assessmentTemplate = (): Assessment => {
missionPDF: 'www.google.com',
questions: [programmingTemplate()],
title: 'Insert title here',
- hasVotingAttributes: false
+ hasVotingFeatures: false
};
};
diff --git a/src/commons/assessment/__tests__/Assessment.tsx b/src/commons/assessment/__tests__/Assessment.tsx
index 135227f4db..a1f8bfe121 100644
--- a/src/commons/assessment/__tests__/Assessment.tsx
+++ b/src/commons/assessment/__tests__/Assessment.tsx
@@ -17,7 +17,7 @@ const mockAssessmentProps = assertType()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
diff --git a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
index f47bb4695e..b74e85b5e2 100644
--- a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
+++ b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
@@ -26,7 +26,7 @@ const defaultProps = assertType()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
diff --git a/src/commons/mocks/AssessmentMocks.ts b/src/commons/mocks/AssessmentMocks.ts
index 82d4318016..3bd0172252 100644
--- a/src/commons/mocks/AssessmentMocks.ts
+++ b/src/commons/mocks/AssessmentMocks.ts
@@ -22,7 +22,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -31,7 +31,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -40,7 +40,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -49,7 +49,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: true,
+ hasVotingFeatures: true,
earlySubmissionXp: 200
},
{
@@ -58,7 +58,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
}
],
@@ -69,7 +69,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -78,7 +78,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -87,7 +87,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
}
]
@@ -911,7 +911,7 @@ export const mockAssessments: Assessment[] = [
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
title: 'An Odessey to Runes',
- hasVotingAttributes: false
+ hasVotingFeatures: false
},
{
type: 'Missions',
@@ -921,7 +921,7 @@ export const mockAssessments: Assessment[] = [
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
title: 'The Secret to Streams',
- hasVotingAttributes: false
+ hasVotingFeatures: false
},
{
type: 'Quests',
@@ -948,7 +948,7 @@ export const mockAssessments: Assessment[] = [
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
title: 'A sample Sidequest',
- hasVotingAttributes: false
+ hasVotingFeatures: false
},
{
type: 'Missions',
@@ -958,7 +958,7 @@ export const mockAssessments: Assessment[] = [
missionPDF: 'www.google.com',
questions: mockClosedAssessmentQuestions,
title: 'A Closed Mission',
- hasVotingAttributes: false
+ hasVotingFeatures: false
},
{
type: 'Quests',
@@ -968,7 +968,7 @@ export const mockAssessments: Assessment[] = [
missionPDF: 'www.google.com',
questions: mockClosedAssessmentQuestions,
title: 'A Closed Sidequest',
- hasVotingAttributes: false
+ hasVotingFeatures: false
},
{
type: 'Paths',
@@ -981,7 +981,7 @@ export const mockAssessments: Assessment[] = [
missionPDF: 'www.google.com',
questions: mockPathQuestions,
title: 'A sample guided path',
- hasVotingAttributes: false
+ hasVotingFeatures: false
},
// mock assessment used for testing contest voting assessments
{
@@ -991,6 +991,6 @@ export const mockAssessments: Assessment[] = [
longSummary: 'Vote for your favourite contest entries here!',
missionPDF: 'www.google.com',
questions: mockContestEntryQuestion,
- hasVotingAttributes: false
+ hasVotingFeatures: false
}
];
diff --git a/src/commons/profile/__tests__/Profile.tsx b/src/commons/profile/__tests__/Profile.tsx
index a4cc5f364b..05b9247c3f 100644
--- a/src/commons/profile/__tests__/Profile.tsx
+++ b/src/commons/profile/__tests__/Profile.tsx
@@ -25,7 +25,7 @@ const assessmentConfigurations: AssessmentConfiguration[] = [
type: c,
isManuallyGraded: false,
displayInDashboard: false,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 0,
earlySubmissionXp: 0
}));
diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts
index 1df6c6de9b..11437f1330 100644
--- a/src/commons/sagas/BackendSaga.ts
+++ b/src/commons/sagas/BackendSaga.ts
@@ -986,7 +986,7 @@ function* BackendSaga(): SagaIterator {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 0
}
];
diff --git a/src/commons/sagas/__tests__/BackendSaga.ts b/src/commons/sagas/__tests__/BackendSaga.ts
index 74940dba14..5ad79a4832 100644
--- a/src/commons/sagas/__tests__/BackendSaga.ts
+++ b/src/commons/sagas/__tests__/BackendSaga.ts
@@ -218,7 +218,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -227,7 +227,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -236,7 +236,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
},
{
@@ -245,7 +245,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: true,
+ hasVotingFeatures: true,
earlySubmissionXp: 200
},
{
@@ -254,7 +254,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 200
}
];
@@ -1007,7 +1007,7 @@ describe('Test CREATE_COURSE action', () => {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 0
}
];
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index c476ec8008..527369ae30 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -51,14 +51,14 @@ const AssessmentConfigPanel: React.FC = ({
gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('displayInDashboard', value);
};
- const setHasVotingAttributes = (index: number, value: boolean) => {
+ const setHasVotingFeatures = (index: number, value: boolean) => {
const temp = [...assessmentConfig.current];
temp[index] = {
...temp[index],
- hasVotingAttributes: value
+ hasVotingFeatures: value
};
setAssessmentConfig(temp);
- gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('hasVotingAttributes', value);
+ gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('hasVotingFeatures', value);
};
const setEarlyXp = (index: number, value: number) => {
@@ -94,7 +94,7 @@ const AssessmentConfigPanel: React.FC = ({
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
- hasVotingAttributes: false,
+ hasVotingFeatures: false,
earlySubmissionXp: 0
});
setAssessmentConfig(temp);
@@ -140,12 +140,12 @@ const AssessmentConfigPanel: React.FC = ({
}
},
{
- headerName: 'Has Voting Attributes',
- field: 'hasVotingAttributes',
+ headerName: 'Has Voting Features',
+ field: 'hasVotingFeatures',
cellRenderer: BooleanCell,
cellRendererParams: {
- setStateHandler: setHasVotingAttributes,
- field: 'hasVotingAttributes'
+ setStateHandler: setHasVotingFeatures,
+ field: 'hasVotingFeatures'
}
},
{
From 4a45bf62e1c753591f4ccab4d915f35ab8f31df3 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 04:25:19 +0800
Subject: [PATCH 03/26] Create dialog box for configuration in ground control
---
src/commons/XMLParser/XMLParserHelper.ts | 3 +-
.../AssessmentWorkspace.tsx | 9 ++-
.../academy/groundControl/GroundControl.tsx | 21 +++++-
.../GroundControlConfigureCell.tsx | 69 +++++++++++++++++++
4 files changed, 97 insertions(+), 5 deletions(-)
create mode 100644 src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
diff --git a/src/commons/XMLParser/XMLParserHelper.ts b/src/commons/XMLParser/XMLParserHelper.ts
index fbf9385575..914db95f15 100644
--- a/src/commons/XMLParser/XMLParserHelper.ts
+++ b/src/commons/XMLParser/XMLParserHelper.ts
@@ -101,7 +101,8 @@ const makeAssessment = (result: any): [Assessment, number] => {
longSummary: task.TEXT[0],
missionPDF: 'google.com',
questions: questionArr[0],
- title: rawOverview.title
+ title: rawOverview.title,
+ hasVotingFeatures: false
},
questionArr[1]
];
diff --git a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
index 1d0b661845..b9848c2ed0 100644
--- a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
+++ b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
@@ -251,12 +251,17 @@ const AssessmentWorkspace: React.FC = props => {
* Handles toggling enabling and disabling token counter depending on assessment properties
*/
useEffect(() => {
- if (assessment?.hasTokenCounter) {
+ if (assessment?.hasVotingFeatures && assessment?.hasTokenCounter) {
handleEnableTokenCounter();
} else {
handleDisableTokenCounter();
}
- }, [assessment?.hasTokenCounter, handleEnableTokenCounter, handleDisableTokenCounter]);
+ }, [
+ assessment?.hasTokenCounter,
+ handleEnableTokenCounter,
+ handleDisableTokenCounter,
+ assessment?.hasVotingFeatures
+ ]);
/**
* Handles toggling of relevant SideContentTabs when mobile breakpoint it hit
diff --git a/src/pages/academy/groundControl/GroundControl.tsx b/src/pages/academy/groundControl/GroundControl.tsx
index 375bbe6bc3..4d0268af22 100644
--- a/src/pages/academy/groundControl/GroundControl.tsx
+++ b/src/pages/academy/groundControl/GroundControl.tsx
@@ -13,6 +13,7 @@ import {
} from '../../../commons/assessment/AssessmentTypes';
import ContentDisplay from '../../../commons/ContentDisplay';
import DefaultChapterSelect from './subcomponents/DefaultChapterSelect';
+import ConfigureCell from './subcomponents/GroundControlConfigureCell';
import DeleteCell from './subcomponents/GroundControlDeleteCell';
import Dropzone from './subcomponents/GroundControlDropzone';
import EditCell from './subcomponents/GroundControlEditCell';
@@ -26,6 +27,7 @@ export type DispatchProps = {
handleUploadAssessment: (file: File, forceUpdate: boolean, assessmentConfigId: number) => void;
handlePublishAssessment: (togglePublishTo: boolean, id: number) => void;
handleAssessmentChangeDate: (id: number, openAt: string, closeAt: string) => void;
+ handleAssessmentConfigure: (id: number, hasVotingFeatures: boolean, useCounter: boolean) => void;
handleFetchCourseConfigs: () => void;
};
@@ -105,7 +107,7 @@ class GroundControl extends React.Component {
cellRendererParams: {
handlePublishAssessment: this.props.handlePublishAssessment
},
- width: 100,
+ width: 80,
filter: false,
resizable: false,
sortable: false,
@@ -120,7 +122,22 @@ class GroundControl extends React.Component {
cellRendererParams: {
handleDeleteAssessment: this.props.handleDeleteAssessment
},
- width: 100,
+ width: 80,
+ filter: false,
+ resizable: false,
+ sortable: false,
+ cellStyle: {
+ padding: 0
+ }
+ },
+ {
+ headerName: 'Configure',
+ field: '',
+ cellRenderer: ConfigureCell,
+ cellRendererParams: {
+ handleAssessmentConfigure: this.props.handleAssessmentConfigure
+ },
+ width: 80,
filter: false,
resizable: false,
sortable: false,
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
new file mode 100644
index 0000000000..b69e015e32
--- /dev/null
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -0,0 +1,69 @@
+import { Dialog, DialogBody, DialogFooter, Intent, Switch } from '@blueprintjs/core';
+import { IconNames } from '@blueprintjs/icons';
+import React, { ChangeEvent, ChangeEventHandler, useCallback, useState } from 'react';
+
+import { AssessmentOverview } from '../../../../commons/assessment/AssessmentTypes';
+import ControlButton from '../../../../commons/ControlButton';
+
+type Props = {
+ handleAssessmentConfigure: (id: number, hasVotingFeatures: boolean, useCounter: boolean) => void;
+ data: AssessmentOverview;
+};
+
+const ConfigureCell: React.FC = ({ handleAssessmentConfigure, data }) => {
+ const [isDialogOpen, setDialogState] = useState(false);
+ const [hasVotingFeatures, setHasVotingFeatures] = useState(false);
+
+ const handleOpenDialog = useCallback(() => setDialogState(true), []);
+ const handleCloseDialog = useCallback(() => setDialogState(false), []);
+
+ const handleConfigure = (hasVotingFeatures: boolean, useCounter: boolean) => {
+ const { id } = data;
+ handleAssessmentConfigure(id, hasVotingFeatures, useCounter);
+ handleCloseDialog();
+ };
+
+ const handleVotingFeaturesChange = () => {
+ setHasVotingFeatures(!hasVotingFeatures);
+ };
+ return (
+ <>
+
+
+ >
+ );
+};
+
+export default ConfigureCell;
From 3e3c2f786c971bee70877b426a211934e3be9a24 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 15:35:10 +0800
Subject: [PATCH 04/26] Create dialog box for configurations with voting config
toggles
---
src/commons/assessment/AssessmentTypes.ts | 2 +
.../groundControl/GroundControlActions.ts | 12 ++++
.../groundControl/GroundControlTypes.ts | 2 +
.../academy/groundControl/GroundControl.tsx | 6 +-
.../groundControl/GroundControlContainer.ts | 6 +-
.../GroundControlConfigureCell.tsx | 59 +++++++++++--------
6 files changed, 59 insertions(+), 28 deletions(-)
diff --git a/src/commons/assessment/AssessmentTypes.ts b/src/commons/assessment/AssessmentTypes.ts
index 32c4a139e4..7c72663eea 100644
--- a/src/commons/assessment/AssessmentTypes.ts
+++ b/src/commons/assessment/AssessmentTypes.ts
@@ -62,6 +62,8 @@ export type AssessmentOverview = {
gradingStatus: GradingStatus;
id: number;
isPublished?: boolean;
+ hasVotingFeatures?: boolean;
+ hasTokenCounter?: boolean;
maxXp: number;
number?: string; // For mission control
openAt: string;
diff --git a/src/features/groundControl/GroundControlActions.ts b/src/features/groundControl/GroundControlActions.ts
index ecdc77aab7..5c61cc8903 100644
--- a/src/features/groundControl/GroundControlActions.ts
+++ b/src/features/groundControl/GroundControlActions.ts
@@ -4,6 +4,8 @@ import {
CHANGE_DATE_ASSESSMENT,
DELETE_ASSESSMENT,
PUBLISH_ASSESSMENT,
+ TOGGLE_TOKEN_COUNTER_ASSESSMENT,
+ TOGGLE_VOTING_FEATURES_ASSESSMENT,
UPLOAD_ASSESSMENT
} from './GroundControlTypes';
@@ -25,3 +27,13 @@ export const uploadAssessment = createAction(
payload: { file, forceUpdate, assessmentConfigId }
})
);
+
+export const toggleVotingFeaturesAssessment = createAction(
+ TOGGLE_VOTING_FEATURES_ASSESSMENT,
+ (id: number, hasVotingFeatures: boolean) => ({ payload: { id, hasVotingFeatures } })
+);
+
+export const toggleTokenCounterAssessment = createAction(
+ TOGGLE_TOKEN_COUNTER_ASSESSMENT,
+ (id: number, hasTokenCounter: boolean) => ({ payload: { id, hasTokenCounter } })
+);
diff --git a/src/features/groundControl/GroundControlTypes.ts b/src/features/groundControl/GroundControlTypes.ts
index d248b2d7c8..61a3fb0444 100644
--- a/src/features/groundControl/GroundControlTypes.ts
+++ b/src/features/groundControl/GroundControlTypes.ts
@@ -2,3 +2,5 @@ export const CHANGE_DATE_ASSESSMENT = 'CHANGE_DATE_ASSESSMENT';
export const DELETE_ASSESSMENT = 'DELETE_ASSESSMENT';
export const PUBLISH_ASSESSMENT = 'PUBLISH_ASSESSMENT';
export const UPLOAD_ASSESSMENT = 'UPLOAD_ASSESSMENT';
+export const TOGGLE_VOTING_FEATURES_ASSESSMENT = 'TOGGLE_VOTING_FEATURES_ASSESSMENT';
+export const TOGGLE_TOKEN_COUNTER_ASSESSMENT = 'TOGGLE_TOKEN_COUNTER_ASSESSMENT';
diff --git a/src/pages/academy/groundControl/GroundControl.tsx b/src/pages/academy/groundControl/GroundControl.tsx
index 4d0268af22..e167bd43ed 100644
--- a/src/pages/academy/groundControl/GroundControl.tsx
+++ b/src/pages/academy/groundControl/GroundControl.tsx
@@ -27,7 +27,8 @@ export type DispatchProps = {
handleUploadAssessment: (file: File, forceUpdate: boolean, assessmentConfigId: number) => void;
handlePublishAssessment: (togglePublishTo: boolean, id: number) => void;
handleAssessmentChangeDate: (id: number, openAt: string, closeAt: string) => void;
- handleAssessmentConfigure: (id: number, hasVotingFeatures: boolean, useCounter: boolean) => void;
+ handleAssessmentToggleVotingFeatures: (id: number, hasVotingFeatures: boolean) => void;
+ handleAssessmentToggleTokenCounter: (id: number, hasTokenCounter: boolean) => void;
handleFetchCourseConfigs: () => void;
};
@@ -135,7 +136,8 @@ class GroundControl extends React.Component {
field: '',
cellRenderer: ConfigureCell,
cellRendererParams: {
- handleAssessmentConfigure: this.props.handleAssessmentConfigure
+ handleAssessmentVotingFeaturesChange: this.props.handleAssessmentToggleVotingFeatures,
+ handleAssessmentTokenCounterChange: this.props.handleAssessmentToggleTokenCounter
},
width: 80,
filter: false,
diff --git a/src/pages/academy/groundControl/GroundControlContainer.ts b/src/pages/academy/groundControl/GroundControlContainer.ts
index d050fca668..70113618b8 100644
--- a/src/pages/academy/groundControl/GroundControlContainer.ts
+++ b/src/pages/academy/groundControl/GroundControlContainer.ts
@@ -10,6 +10,8 @@ import {
changeDateAssessment,
deleteAssessment,
publishAssessment,
+ toggleTokenCounterAssessment,
+ toggleVotingFeaturesAssessment,
uploadAssessment
} from '../../../features/groundControl/GroundControlActions';
import GroundControl, { DispatchProps, StateProps } from './GroundControl';
@@ -27,7 +29,9 @@ const mapDispatchToProps: MapDispatchToProps = (dispatch: Dis
handleDeleteAssessment: deleteAssessment,
handleUploadAssessment: uploadAssessment,
handlePublishAssessment: publishAssessment,
- handleFetchCourseConfigs: fetchCourseConfig
+ handleFetchCourseConfigs: fetchCourseConfig,
+ handleAssessmentToggleVotingFeatures: toggleVotingFeaturesAssessment,
+ handleAssessmentToggleTokenCounter: toggleTokenCounterAssessment
},
dispatch
);
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index b69e015e32..84d67cc8b7 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -1,31 +1,38 @@
-import { Dialog, DialogBody, DialogFooter, Intent, Switch } from '@blueprintjs/core';
+import { Collapse, Dialog, DialogBody, Divider, Switch } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
-import React, { ChangeEvent, ChangeEventHandler, useCallback, useState } from 'react';
+import React, { useCallback, useState } from 'react';
import { AssessmentOverview } from '../../../../commons/assessment/AssessmentTypes';
import ControlButton from '../../../../commons/ControlButton';
type Props = {
- handleAssessmentConfigure: (id: number, hasVotingFeatures: boolean, useCounter: boolean) => void;
+ handleAssessmentVotingFeaturesChange: (id: number, hasVotingFeatures: boolean) => void;
+ handleAssessmentTokenCounterChange: (id: number, hasTokenCounter: boolean) => void;
data: AssessmentOverview;
};
-const ConfigureCell: React.FC = ({ handleAssessmentConfigure, data }) => {
+const ConfigureCell: React.FC = ({
+ handleAssessmentTokenCounterChange,
+ handleAssessmentVotingFeaturesChange,
+ data
+}) => {
const [isDialogOpen, setDialogState] = useState(false);
- const [hasVotingFeatures, setHasVotingFeatures] = useState(false);
+ const [hasVotingFeatures] = useState(!!data.hasVotingFeatures);
+ const [hasTokenCounter] = useState(!!data.hasTokenCounter);
const handleOpenDialog = useCallback(() => setDialogState(true), []);
const handleCloseDialog = useCallback(() => setDialogState(false), []);
- const handleConfigure = (hasVotingFeatures: boolean, useCounter: boolean) => {
+ const handleToggleHasVotingFeatures = useCallback(() => {
const { id } = data;
- handleAssessmentConfigure(id, hasVotingFeatures, useCounter);
- handleCloseDialog();
- };
+ handleAssessmentVotingFeaturesChange(id, !hasVotingFeatures);
+ }, [data, handleAssessmentVotingFeaturesChange, hasVotingFeatures]);
+
+ const handleToggleHasTokenCounter = useCallback(() => {
+ const { id } = data;
+ handleAssessmentTokenCounterChange(id, !hasTokenCounter);
+ }, [data, handleAssessmentTokenCounterChange, hasTokenCounter]);
- const handleVotingFeaturesChange = () => {
- setHasVotingFeatures(!hasVotingFeatures);
- };
return (
<>
@@ -42,25 +49,27 @@ const ConfigureCell: React.FC = ({ handleAssessmentConfigure, data }) =>
ensure it meets your specific needs.
+
+ Voting-Related Configurations
+
+
+
+
+
-
-
- >
- }
- />
>
);
From b0aabfb80d88baa608d1d569d91ce0cca569d1b2 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 15:52:00 +0800
Subject: [PATCH 05/26] Combine toggleHasTokenCounter and toggleVotingFeatures
into configureAssessment
---
src/commons/sagas/BackendSaga.ts | 17 ++++++
.../groundControl/GroundControlActions.ts | 16 ++---
.../groundControl/GroundControlTypes.ts | 3 +-
.../academy/groundControl/GroundControl.tsx | 10 +--
.../groundControl/GroundControlContainer.ts | 6 +-
.../GroundControlConfigureCell.tsx | 61 +++++++++++++------
6 files changed, 74 insertions(+), 39 deletions(-)
diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts
index 11437f1330..b360e206f5 100644
--- a/src/commons/sagas/BackendSaga.ts
+++ b/src/commons/sagas/BackendSaga.ts
@@ -19,6 +19,8 @@ import {
CHANGE_DATE_ASSESSMENT,
DELETE_ASSESSMENT,
PUBLISH_ASSESSMENT,
+ TOGGLE_TOKEN_COUNTER_ASSESSMENT,
+ TOGGLE_VOTING_FEATURES_ASSESSMENT,
UPLOAD_ASSESSMENT
} from '../../features/groundControl/GroundControlTypes';
import { FETCH_SOURCECAST_INDEX } from '../../features/sourceRecorder/sourcecast/SourcecastTypes';
@@ -1171,6 +1173,21 @@ function* BackendSaga(): SagaIterator {
yield put(actions.fetchAssessmentOverviews());
}
);
+ yield takeEvery(
+ TOGGLE_TOKEN_COUNTER_ASSESSMENT,
+ function* (action: ReturnType): any {
+ const tokens: Tokens = yield selectTokens();
+ const id = action.payload;
+
+ const resp: Response | null = yield deleteAssessment(id, tokens);
+ if (!resp || !resp.ok) {
+ return yield handleResponseError(resp);
+ }
+
+ yield put(actions.fetchAssessmentOverviews());
+ yield call(showSuccessMessage, 'Deleted successfully!', 1000);
+ }
+ );
}
function* handleReautogradeResponse(resp: Response | null): any {
diff --git a/src/features/groundControl/GroundControlActions.ts b/src/features/groundControl/GroundControlActions.ts
index 5c61cc8903..bf9433b124 100644
--- a/src/features/groundControl/GroundControlActions.ts
+++ b/src/features/groundControl/GroundControlActions.ts
@@ -2,10 +2,9 @@ import { createAction } from '@reduxjs/toolkit';
import {
CHANGE_DATE_ASSESSMENT,
+ CONFIGURE_ASSESSMENT,
DELETE_ASSESSMENT,
PUBLISH_ASSESSMENT,
- TOGGLE_TOKEN_COUNTER_ASSESSMENT,
- TOGGLE_VOTING_FEATURES_ASSESSMENT,
UPLOAD_ASSESSMENT
} from './GroundControlTypes';
@@ -28,12 +27,9 @@ export const uploadAssessment = createAction(
})
);
-export const toggleVotingFeaturesAssessment = createAction(
- TOGGLE_VOTING_FEATURES_ASSESSMENT,
- (id: number, hasVotingFeatures: boolean) => ({ payload: { id, hasVotingFeatures } })
-);
-
-export const toggleTokenCounterAssessment = createAction(
- TOGGLE_TOKEN_COUNTER_ASSESSMENT,
- (id: number, hasTokenCounter: boolean) => ({ payload: { id, hasTokenCounter } })
+export const configureAssessment = createAction(
+ CONFIGURE_ASSESSMENT,
+ (id: number, hasVotingFeatures: boolean, hasTokenCounter) => ({
+ payload: { id, hasVotingFeatures, hasTokenCounter }
+ })
);
diff --git a/src/features/groundControl/GroundControlTypes.ts b/src/features/groundControl/GroundControlTypes.ts
index 61a3fb0444..12fae808f8 100644
--- a/src/features/groundControl/GroundControlTypes.ts
+++ b/src/features/groundControl/GroundControlTypes.ts
@@ -2,5 +2,4 @@ export const CHANGE_DATE_ASSESSMENT = 'CHANGE_DATE_ASSESSMENT';
export const DELETE_ASSESSMENT = 'DELETE_ASSESSMENT';
export const PUBLISH_ASSESSMENT = 'PUBLISH_ASSESSMENT';
export const UPLOAD_ASSESSMENT = 'UPLOAD_ASSESSMENT';
-export const TOGGLE_VOTING_FEATURES_ASSESSMENT = 'TOGGLE_VOTING_FEATURES_ASSESSMENT';
-export const TOGGLE_TOKEN_COUNTER_ASSESSMENT = 'TOGGLE_TOKEN_COUNTER_ASSESSMENT';
+export const CONFIGURE_ASSESSMENT = 'CONFIGURE_ASSESSMENT';
diff --git a/src/pages/academy/groundControl/GroundControl.tsx b/src/pages/academy/groundControl/GroundControl.tsx
index e167bd43ed..6164938695 100644
--- a/src/pages/academy/groundControl/GroundControl.tsx
+++ b/src/pages/academy/groundControl/GroundControl.tsx
@@ -27,8 +27,11 @@ export type DispatchProps = {
handleUploadAssessment: (file: File, forceUpdate: boolean, assessmentConfigId: number) => void;
handlePublishAssessment: (togglePublishTo: boolean, id: number) => void;
handleAssessmentChangeDate: (id: number, openAt: string, closeAt: string) => void;
- handleAssessmentToggleVotingFeatures: (id: number, hasVotingFeatures: boolean) => void;
- handleAssessmentToggleTokenCounter: (id: number, hasTokenCounter: boolean) => void;
+ handleConfigureAssessment: (
+ id: number,
+ hasVotingFeatures: boolean,
+ hasTokenCounter: boolean
+ ) => void;
handleFetchCourseConfigs: () => void;
};
@@ -136,8 +139,7 @@ class GroundControl extends React.Component {
field: '',
cellRenderer: ConfigureCell,
cellRendererParams: {
- handleAssessmentVotingFeaturesChange: this.props.handleAssessmentToggleVotingFeatures,
- handleAssessmentTokenCounterChange: this.props.handleAssessmentToggleTokenCounter
+ handleConfigureAssessment: this.props.handleConfigureAssessment
},
width: 80,
filter: false,
diff --git a/src/pages/academy/groundControl/GroundControlContainer.ts b/src/pages/academy/groundControl/GroundControlContainer.ts
index 70113618b8..85f6b929f1 100644
--- a/src/pages/academy/groundControl/GroundControlContainer.ts
+++ b/src/pages/academy/groundControl/GroundControlContainer.ts
@@ -8,10 +8,9 @@ import {
import { OverallState } from '../../../commons/application/ApplicationTypes';
import {
changeDateAssessment,
+ configureAssessment,
deleteAssessment,
publishAssessment,
- toggleTokenCounterAssessment,
- toggleVotingFeaturesAssessment,
uploadAssessment
} from '../../../features/groundControl/GroundControlActions';
import GroundControl, { DispatchProps, StateProps } from './GroundControl';
@@ -30,8 +29,7 @@ const mapDispatchToProps: MapDispatchToProps = (dispatch: Dis
handleUploadAssessment: uploadAssessment,
handlePublishAssessment: publishAssessment,
handleFetchCourseConfigs: fetchCourseConfig,
- handleAssessmentToggleVotingFeatures: toggleVotingFeaturesAssessment,
- handleAssessmentToggleTokenCounter: toggleTokenCounterAssessment
+ handleConfigureAssessment: configureAssessment
},
dispatch
);
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 84d67cc8b7..3c69c871a7 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -1,4 +1,12 @@
-import { Collapse, Dialog, DialogBody, Divider, Switch } from '@blueprintjs/core';
+import {
+ Collapse,
+ Dialog,
+ DialogBody,
+ DialogFooter,
+ Divider,
+ Intent,
+ Switch
+} from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import React, { useCallback, useState } from 'react';
@@ -6,32 +14,35 @@ import { AssessmentOverview } from '../../../../commons/assessment/AssessmentTyp
import ControlButton from '../../../../commons/ControlButton';
type Props = {
- handleAssessmentVotingFeaturesChange: (id: number, hasVotingFeatures: boolean) => void;
- handleAssessmentTokenCounterChange: (id: number, hasTokenCounter: boolean) => void;
+ handleConfigureAssessment: (
+ id: number,
+ hasVotingFeatures: boolean,
+ hasTokenCounter: boolean
+ ) => void;
data: AssessmentOverview;
};
-const ConfigureCell: React.FC = ({
- handleAssessmentTokenCounterChange,
- handleAssessmentVotingFeaturesChange,
- data
-}) => {
+const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) => {
const [isDialogOpen, setDialogState] = useState(false);
- const [hasVotingFeatures] = useState(!!data.hasVotingFeatures);
- const [hasTokenCounter] = useState(!!data.hasTokenCounter);
+ const [hasVotingFeatures, setHasVotingFeatures] = useState(!!data.hasVotingFeatures);
+ const [hasTokenCounter, setHasTokenCounter] = useState(!!data.hasTokenCounter);
const handleOpenDialog = useCallback(() => setDialogState(true), []);
const handleCloseDialog = useCallback(() => setDialogState(false), []);
- const handleToggleHasVotingFeatures = useCallback(() => {
+ const handleConfigure = useCallback(() => {
const { id } = data;
- handleAssessmentVotingFeaturesChange(id, !hasVotingFeatures);
- }, [data, handleAssessmentVotingFeaturesChange, hasVotingFeatures]);
+ handleConfigureAssessment(id, hasVotingFeatures, hasTokenCounter);
+ }, [data, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
- const handleToggleHasTokenCounter = useCallback(() => {
- const { id } = data;
- handleAssessmentTokenCounterChange(id, !hasTokenCounter);
- }, [data, handleAssessmentTokenCounterChange, hasTokenCounter]);
+ const toggleHasTokenCounter = useCallback(
+ () => setHasTokenCounter(!hasTokenCounter),
+ [hasTokenCounter]
+ );
+ const toggleVotingFeatures = useCallback(
+ () => setHasVotingFeatures(!hasVotingFeatures),
+ [hasVotingFeatures]
+ );
return (
<>
@@ -56,7 +67,7 @@ const ConfigureCell: React.FC = ({
@@ -64,12 +75,24 @@ const ConfigureCell: React.FC = ({
+
+
+ >
+ }
+ >
>
);
From cea6f31a5d19d67a97e6c5af68f5bc46dd2e5c90 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 16:04:26 +0800
Subject: [PATCH 06/26] Create backend request for updating configurations
---
src/commons/sagas/BackendSaga.ts | 19 ++++++++++++-------
src/commons/sagas/RequestsSaga.ts | 8 +++++++-
.../groundControl/GroundControlActions.ts | 5 +++--
.../academy/groundControl/GroundControl.tsx | 8 ++------
.../GroundControlConfigureCell.tsx | 13 +++++++------
5 files changed, 31 insertions(+), 22 deletions(-)
diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts
index b360e206f5..a869b2a09f 100644
--- a/src/commons/sagas/BackendSaga.ts
+++ b/src/commons/sagas/BackendSaga.ts
@@ -17,10 +17,9 @@ import {
} from '../../features/grading/GradingTypes';
import {
CHANGE_DATE_ASSESSMENT,
+ CONFIGURE_ASSESSMENT,
DELETE_ASSESSMENT,
PUBLISH_ASSESSMENT,
- TOGGLE_TOKEN_COUNTER_ASSESSMENT,
- TOGGLE_VOTING_FEATURES_ASSESSMENT,
UPLOAD_ASSESSMENT
} from '../../features/groundControl/GroundControlTypes';
import { FETCH_SOURCECAST_INDEX } from '../../features/sourceRecorder/sourcecast/SourcecastTypes';
@@ -1173,19 +1172,25 @@ function* BackendSaga(): SagaIterator {
yield put(actions.fetchAssessmentOverviews());
}
);
+
yield takeEvery(
- TOGGLE_TOKEN_COUNTER_ASSESSMENT,
- function* (action: ReturnType): any {
+ CONFIGURE_ASSESSMENT,
+ function* (action: ReturnType): any {
const tokens: Tokens = yield selectTokens();
- const id = action.payload;
+ const id = action.payload.id;
+ const votingConfigurations = action.payload.votingConfigurations;
- const resp: Response | null = yield deleteAssessment(id, tokens);
+ const resp: Response | null = yield updateAssessment(
+ id,
+ { votingConfigurations: votingConfigurations },
+ tokens
+ );
if (!resp || !resp.ok) {
return yield handleResponseError(resp);
}
yield put(actions.fetchAssessmentOverviews());
- yield call(showSuccessMessage, 'Deleted successfully!', 1000);
+ yield call(showSuccessMessage, '', 1000);
}
);
}
diff --git a/src/commons/sagas/RequestsSaga.ts b/src/commons/sagas/RequestsSaga.ts
index 784c1d859f..4d8a77bfef 100644
--- a/src/commons/sagas/RequestsSaga.ts
+++ b/src/commons/sagas/RequestsSaga.ts
@@ -1,4 +1,5 @@
import { call } from 'redux-saga/effects';
+import { VotingConfiguration } from 'src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell';
import {
AchievementGoal,
@@ -898,7 +899,12 @@ export const deleteSourcecastEntry = async (
*/
export const updateAssessment = async (
id: number,
- body: { openAt?: string; closeAt?: string; isPublished?: boolean },
+ body: {
+ openAt?: string;
+ closeAt?: string;
+ isPublished?: boolean;
+ votingConfigurations?: VotingConfiguration;
+ },
tokens: Tokens
): Promise => {
const resp = await request(`${courseId()}/admin/assessments/${id}`, 'POST', {
diff --git a/src/features/groundControl/GroundControlActions.ts b/src/features/groundControl/GroundControlActions.ts
index bf9433b124..15dfe35d39 100644
--- a/src/features/groundControl/GroundControlActions.ts
+++ b/src/features/groundControl/GroundControlActions.ts
@@ -1,4 +1,5 @@
import { createAction } from '@reduxjs/toolkit';
+import { VotingConfiguration } from 'src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell';
import {
CHANGE_DATE_ASSESSMENT,
@@ -29,7 +30,7 @@ export const uploadAssessment = createAction(
export const configureAssessment = createAction(
CONFIGURE_ASSESSMENT,
- (id: number, hasVotingFeatures: boolean, hasTokenCounter) => ({
- payload: { id, hasVotingFeatures, hasTokenCounter }
+ (id: number, votingConfigurations: VotingConfiguration) => ({
+ payload: { id, votingConfigurations }
})
);
diff --git a/src/pages/academy/groundControl/GroundControl.tsx b/src/pages/academy/groundControl/GroundControl.tsx
index 6164938695..db6828da37 100644
--- a/src/pages/academy/groundControl/GroundControl.tsx
+++ b/src/pages/academy/groundControl/GroundControl.tsx
@@ -13,7 +13,7 @@ import {
} from '../../../commons/assessment/AssessmentTypes';
import ContentDisplay from '../../../commons/ContentDisplay';
import DefaultChapterSelect from './subcomponents/DefaultChapterSelect';
-import ConfigureCell from './subcomponents/GroundControlConfigureCell';
+import ConfigureCell, { VotingConfiguration } from './subcomponents/GroundControlConfigureCell';
import DeleteCell from './subcomponents/GroundControlDeleteCell';
import Dropzone from './subcomponents/GroundControlDropzone';
import EditCell from './subcomponents/GroundControlEditCell';
@@ -27,11 +27,7 @@ export type DispatchProps = {
handleUploadAssessment: (file: File, forceUpdate: boolean, assessmentConfigId: number) => void;
handlePublishAssessment: (togglePublishTo: boolean, id: number) => void;
handleAssessmentChangeDate: (id: number, openAt: string, closeAt: string) => void;
- handleConfigureAssessment: (
- id: number,
- hasVotingFeatures: boolean,
- hasTokenCounter: boolean
- ) => void;
+ handleConfigureAssessment: (id: number, votingConfiguration: VotingConfiguration) => void;
handleFetchCourseConfigs: () => void;
};
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 3c69c871a7..4d2e851f9f 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -14,14 +14,15 @@ import { AssessmentOverview } from '../../../../commons/assessment/AssessmentTyp
import ControlButton from '../../../../commons/ControlButton';
type Props = {
- handleConfigureAssessment: (
- id: number,
- hasVotingFeatures: boolean,
- hasTokenCounter: boolean
- ) => void;
+ handleConfigureAssessment: (id: number, votingConfigurations: VotingConfiguration) => void;
data: AssessmentOverview;
};
+export type VotingConfiguration = {
+ hasVotingFeatures: boolean;
+ hasTokenCounter: boolean;
+};
+
const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) => {
const [isDialogOpen, setDialogState] = useState(false);
const [hasVotingFeatures, setHasVotingFeatures] = useState(!!data.hasVotingFeatures);
@@ -32,7 +33,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
const handleConfigure = useCallback(() => {
const { id } = data;
- handleConfigureAssessment(id, hasVotingFeatures, hasTokenCounter);
+ handleConfigureAssessment(id, { hasVotingFeatures, hasTokenCounter });
}, [data, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
const toggleHasTokenCounter = useCallback(
From 3f02090b67ee92a86198a822079416c3b47464ba Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 16:05:24 +0800
Subject: [PATCH 07/26] Add message for updating assessment configurations
---
src/commons/sagas/BackendSaga.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts
index a869b2a09f..f28c9f9115 100644
--- a/src/commons/sagas/BackendSaga.ts
+++ b/src/commons/sagas/BackendSaga.ts
@@ -1190,7 +1190,7 @@ function* BackendSaga(): SagaIterator {
}
yield put(actions.fetchAssessmentOverviews());
- yield call(showSuccessMessage, '', 1000);
+ yield call(showSuccessMessage, 'Assessment configurations updated successfully!', 1000);
}
);
}
From bb452ce7d8784346235e06a7ccf5055b4b94573e Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 17:08:44 +0800
Subject: [PATCH 08/26] Isolate hastokencounter as its own field
---
.../actions/__tests__/SessionActions.ts | 3 +-
.../reducers/__tests__/SessionReducer.ts | 15 ++++++----
src/commons/assessment/AssessmentTypes.ts | 8 ++---
src/commons/mocks/AssessmentMocks.ts | 30 ++++++++++++-------
src/commons/sagas/BackendSaga.ts | 7 +++--
src/commons/sagas/RequestsSaga.ts | 4 +--
.../groundControl/GroundControlActions.ts | 5 ++--
.../academy/groundControl/GroundControl.tsx | 8 +++--
.../GroundControlConfigureCell.tsx | 17 +++++------
9 files changed, 58 insertions(+), 39 deletions(-)
diff --git a/src/commons/application/actions/__tests__/SessionActions.ts b/src/commons/application/actions/__tests__/SessionActions.ts
index eebc86244e..08e4f31460 100644
--- a/src/commons/application/actions/__tests__/SessionActions.ts
+++ b/src/commons/application/actions/__tests__/SessionActions.ts
@@ -501,7 +501,8 @@ test('updateAssessmentOverviews generates correct action object', () => {
status: 'not_attempted',
story: null,
xp: 0,
- gradingStatus: 'none'
+ gradingStatus: 'none',
+ hasVotingFeatures: false
}
];
const action = updateAssessmentOverviews(overviews);
diff --git a/src/commons/application/reducers/__tests__/SessionReducer.ts b/src/commons/application/reducers/__tests__/SessionReducer.ts
index bdd39ae661..a8ebafc834 100644
--- a/src/commons/application/reducers/__tests__/SessionReducer.ts
+++ b/src/commons/application/reducers/__tests__/SessionReducer.ts
@@ -238,7 +238,8 @@ const assessmentTest1: Assessment = {
longSummary: 'long summary here',
missionPDF: 'www.google.com',
questions: [],
- title: 'first assessment'
+ title: 'first assessment',
+ hasVotingFeatures: false
};
const assessmentTest2: Assessment = {
@@ -249,7 +250,8 @@ const assessmentTest2: Assessment = {
longSummary: 'another long summary',
missionPDF: 'www.comp.nus.edu.sg',
questions: [],
- title: 'updated first assessment'
+ title: 'updated first assessment',
+ hasVotingFeatures: false
};
const assessmentTest3: Assessment = {
@@ -260,7 +262,8 @@ const assessmentTest3: Assessment = {
longSummary: 'another long summary here',
missionPDF: 'www.yahoo.com',
questions: [],
- title: 'path'
+ title: 'path',
+ hasVotingFeatures: false
};
test('UPDATE_ASSESSMENT works correctly in inserting assessment', () => {
@@ -324,7 +327,8 @@ const assessmentOverviewsTest1: AssessmentOverview[] = [
status: AssessmentStatuses.not_attempted,
story: null,
xp: 0,
- gradingStatus: GradingStatuses.none
+ gradingStatus: GradingStatuses.none,
+ hasVotingFeatures: false
}
];
@@ -343,7 +347,8 @@ const assessmentOverviewsTest2: AssessmentOverview[] = [
status: AssessmentStatuses.attempted,
story: null,
xp: 1,
- gradingStatus: GradingStatuses.grading
+ gradingStatus: GradingStatuses.grading,
+ hasVotingFeatures: false
}
];
diff --git a/src/commons/assessment/AssessmentTypes.ts b/src/commons/assessment/AssessmentTypes.ts
index 7c72663eea..bfdbf7bba7 100644
--- a/src/commons/assessment/AssessmentTypes.ts
+++ b/src/commons/assessment/AssessmentTypes.ts
@@ -62,7 +62,7 @@ export type AssessmentOverview = {
gradingStatus: GradingStatus;
id: number;
isPublished?: boolean;
- hasVotingFeatures?: boolean;
+ hasVotingFeatures: boolean;
hasTokenCounter?: boolean;
maxXp: number;
number?: string; // For mission control
@@ -246,7 +246,8 @@ export const overviewTemplate = (): AssessmentOverview => {
status: AssessmentStatuses.not_attempted,
story: 'mission',
xp: 0,
- gradingStatus: 'none'
+ gradingStatus: 'none',
+ hasVotingFeatures: false
};
};
@@ -321,7 +322,6 @@ export const assessmentTemplate = (): Assessment => {
longSummary: 'Insert mission briefing here',
missionPDF: 'www.google.com',
questions: [programmingTemplate()],
- title: 'Insert title here',
- hasVotingFeatures: false
+ title: 'Insert title here'
};
};
diff --git a/src/commons/mocks/AssessmentMocks.ts b/src/commons/mocks/AssessmentMocks.ts
index 3bd0172252..f24a6c389a 100644
--- a/src/commons/mocks/AssessmentMocks.ts
+++ b/src/commons/mocks/AssessmentMocks.ts
@@ -108,7 +108,8 @@ const mockUnopenedAssessmentsOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.not_attempted,
story: 'mission-1',
xp: 0,
- gradingStatus: GradingStatuses.none
+ gradingStatus: GradingStatuses.none,
+ hasVotingFeatures: false
}
];
@@ -139,7 +140,8 @@ const mockOpenedAssessmentsOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.attempted,
story: 'mission-1',
xp: 1,
- gradingStatus: GradingStatuses.none
+ gradingStatus: GradingStatuses.none,
+ hasVotingFeatures: false
},
{
type: 'Missions',
@@ -155,7 +157,8 @@ const mockOpenedAssessmentsOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.attempting,
story: 'mission-2',
xp: 2,
- gradingStatus: GradingStatuses.none
+ gradingStatus: GradingStatuses.none,
+ hasVotingFeatures: false
},
{
type: 'Quests',
@@ -171,7 +174,8 @@ const mockOpenedAssessmentsOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.not_attempted,
story: 'sidequest-2.1',
xp: 3,
- gradingStatus: GradingStatuses.none
+ gradingStatus: GradingStatuses.none,
+ hasVotingFeatures: false
},
{
type: 'Paths',
@@ -187,7 +191,8 @@ const mockOpenedAssessmentsOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.not_attempted,
story: null,
xp: 0,
- gradingStatus: GradingStatuses.excluded
+ gradingStatus: GradingStatuses.excluded,
+ hasVotingFeatures: false
},
{
type: 'Others',
@@ -204,7 +209,8 @@ const mockOpenedAssessmentsOverviews: AssessmentOverview[] = [
story: 'sidequest-2.1',
xp: 3,
gradingStatus: GradingStatuses.none,
- private: true
+ private: true,
+ hasVotingFeatures: false
}
];
@@ -223,7 +229,8 @@ const mockClosedAssessmentOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.submitted,
story: 'mission-3',
xp: 800,
- gradingStatus: GradingStatuses.grading
+ gradingStatus: GradingStatuses.grading,
+ hasVotingFeatures: false
},
{
type: 'Quests',
@@ -239,7 +246,8 @@ const mockClosedAssessmentOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.submitted,
story: null,
xp: 500,
- gradingStatus: GradingStatuses.none
+ gradingStatus: GradingStatuses.none,
+ hasVotingFeatures: false
},
{
type: 'Quests',
@@ -255,7 +263,8 @@ const mockClosedAssessmentOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.submitted,
story: null,
xp: 150,
- gradingStatus: GradingStatuses.graded
+ gradingStatus: GradingStatuses.graded,
+ hasVotingFeatures: false
},
{
type: 'Quests',
@@ -271,7 +280,8 @@ const mockClosedAssessmentOverviews: AssessmentOverview[] = [
status: AssessmentStatuses.submitted,
story: null,
xp: 100,
- gradingStatus: GradingStatuses.excluded
+ gradingStatus: GradingStatuses.excluded,
+ hasVotingFeatures: false
}
];
diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts
index f28c9f9115..815ffdea05 100644
--- a/src/commons/sagas/BackendSaga.ts
+++ b/src/commons/sagas/BackendSaga.ts
@@ -1178,11 +1178,12 @@ function* BackendSaga(): SagaIterator {
function* (action: ReturnType): any {
const tokens: Tokens = yield selectTokens();
const id = action.payload.id;
- const votingConfigurations = action.payload.votingConfigurations;
+ const hasVotingFeatures = action.payload.hasVotingFeatures;
+ const hasTokenCounter = action.payload.hasTokenCounter;
const resp: Response | null = yield updateAssessment(
id,
- { votingConfigurations: votingConfigurations },
+ { hasVotingFeatures: hasVotingFeatures, hasTokenCounter: hasTokenCounter },
tokens
);
if (!resp || !resp.ok) {
@@ -1190,7 +1191,7 @@ function* BackendSaga(): SagaIterator {
}
yield put(actions.fetchAssessmentOverviews());
- yield call(showSuccessMessage, 'Assessment configurations updated successfully!', 1000);
+ yield call(showSuccessMessage, 'Updated successfully!', 1000);
}
);
}
diff --git a/src/commons/sagas/RequestsSaga.ts b/src/commons/sagas/RequestsSaga.ts
index 4d8a77bfef..1e48ec81fc 100644
--- a/src/commons/sagas/RequestsSaga.ts
+++ b/src/commons/sagas/RequestsSaga.ts
@@ -1,5 +1,4 @@
import { call } from 'redux-saga/effects';
-import { VotingConfiguration } from 'src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell';
import {
AchievementGoal,
@@ -903,7 +902,8 @@ export const updateAssessment = async (
openAt?: string;
closeAt?: string;
isPublished?: boolean;
- votingConfigurations?: VotingConfiguration;
+ hasTokenCounter?: boolean;
+ hasVotingFeatures?: boolean;
},
tokens: Tokens
): Promise => {
diff --git a/src/features/groundControl/GroundControlActions.ts b/src/features/groundControl/GroundControlActions.ts
index 15dfe35d39..4499ce2e64 100644
--- a/src/features/groundControl/GroundControlActions.ts
+++ b/src/features/groundControl/GroundControlActions.ts
@@ -1,5 +1,4 @@
import { createAction } from '@reduxjs/toolkit';
-import { VotingConfiguration } from 'src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell';
import {
CHANGE_DATE_ASSESSMENT,
@@ -30,7 +29,7 @@ export const uploadAssessment = createAction(
export const configureAssessment = createAction(
CONFIGURE_ASSESSMENT,
- (id: number, votingConfigurations: VotingConfiguration) => ({
- payload: { id, votingConfigurations }
+ (id: number, hasTokenCounter: boolean, hasVotingFeatures: boolean) => ({
+ payload: { id, hasTokenCounter, hasVotingFeatures }
})
);
diff --git a/src/pages/academy/groundControl/GroundControl.tsx b/src/pages/academy/groundControl/GroundControl.tsx
index db6828da37..a89ab3e200 100644
--- a/src/pages/academy/groundControl/GroundControl.tsx
+++ b/src/pages/academy/groundControl/GroundControl.tsx
@@ -13,7 +13,7 @@ import {
} from '../../../commons/assessment/AssessmentTypes';
import ContentDisplay from '../../../commons/ContentDisplay';
import DefaultChapterSelect from './subcomponents/DefaultChapterSelect';
-import ConfigureCell, { VotingConfiguration } from './subcomponents/GroundControlConfigureCell';
+import ConfigureCell from './subcomponents/GroundControlConfigureCell';
import DeleteCell from './subcomponents/GroundControlDeleteCell';
import Dropzone from './subcomponents/GroundControlDropzone';
import EditCell from './subcomponents/GroundControlEditCell';
@@ -27,7 +27,11 @@ export type DispatchProps = {
handleUploadAssessment: (file: File, forceUpdate: boolean, assessmentConfigId: number) => void;
handlePublishAssessment: (togglePublishTo: boolean, id: number) => void;
handleAssessmentChangeDate: (id: number, openAt: string, closeAt: string) => void;
- handleConfigureAssessment: (id: number, votingConfiguration: VotingConfiguration) => void;
+ handleConfigureAssessment: (
+ id: number,
+ hasTokenCounter: boolean,
+ hasVotingFeatures: boolean
+ ) => void;
handleFetchCourseConfigs: () => void;
};
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 4d2e851f9f..4f7d3da9fc 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -14,15 +14,14 @@ import { AssessmentOverview } from '../../../../commons/assessment/AssessmentTyp
import ControlButton from '../../../../commons/ControlButton';
type Props = {
- handleConfigureAssessment: (id: number, votingConfigurations: VotingConfiguration) => void;
+ handleConfigureAssessment: (
+ id: number,
+ hasVotingFeatures: boolean,
+ hasTokenCounter: boolean
+ ) => void;
data: AssessmentOverview;
};
-export type VotingConfiguration = {
- hasVotingFeatures: boolean;
- hasTokenCounter: boolean;
-};
-
const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) => {
const [isDialogOpen, setDialogState] = useState(false);
const [hasVotingFeatures, setHasVotingFeatures] = useState(!!data.hasVotingFeatures);
@@ -33,7 +32,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
const handleConfigure = useCallback(() => {
const { id } = data;
- handleConfigureAssessment(id, { hasVotingFeatures, hasTokenCounter });
+ handleConfigureAssessment(id, hasVotingFeatures, hasTokenCounter);
}, [data, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
const toggleHasTokenCounter = useCallback(
@@ -57,8 +56,8 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
>
- This assessment configuration tool allows you to fine-tune this assessment to
- ensure it meets your specific needs.
+ This configuration tool allows you to fine-tune this assessment to ensure it
+ meets your specific needs.
From 0eb08efb0a9d594190705394d8a602af48e09466 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 17:40:03 +0800
Subject: [PATCH 09/26] Add non-functional voting controls
---
.../GroundControlConfigureCell.tsx | 60 ++++++++++++++-----
src/styles/_groundcontrol.scss | 18 ++++++
2 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 4f7d3da9fc..62f19baabb 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -56,22 +56,15 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
>
- This configuration tool allows you to fine-tune this assessment to ensure it
- meets your specific needs.
+ This configuration tool allows you to fine-tune this assessment. Any changes made
+ here will override any assessment configurations in the admin panel.
-
- Voting-Related Configurations
-
-
-
-
+
+
+ General Configurations
+
+
= ({ handleConfigureAssessment, data }) =>
inline
label="Has Token Counter"
>
-
+
+
+
+ Voting-Related Configurations
+
+
+
+
+
+
+
Date: Thu, 21 Mar 2024 18:23:21 +0800
Subject: [PATCH 10/26] Fix tests
---
src/commons/XMLParser/XMLParserHelper.ts | 6 ++--
.../actions/__tests__/SessionActions.ts | 12 ++++++--
.../reducers/__tests__/SessionReducer.ts | 9 ++----
src/commons/assessment/AssessmentTypes.ts | 2 +-
.../assessment/__tests__/Assessment.tsx | 1 +
.../AssessmentWorkspace.tsx | 9 ++----
.../__tests__/AssessmentWorkspace.tsx | 1 +
src/commons/mocks/AssessmentMocks.ts | 29 ++++++++++---------
src/commons/profile/__tests__/Profile.tsx | 1 +
src/commons/sagas/BackendSaga.ts | 1 +
src/commons/sagas/__tests__/BackendSaga.ts | 6 ++++
.../AssessmentConfigPanel.tsx | 1 +
12 files changed, 45 insertions(+), 33 deletions(-)
diff --git a/src/commons/XMLParser/XMLParserHelper.ts b/src/commons/XMLParser/XMLParserHelper.ts
index 914db95f15..4f4a4d2e9d 100644
--- a/src/commons/XMLParser/XMLParserHelper.ts
+++ b/src/commons/XMLParser/XMLParserHelper.ts
@@ -84,7 +84,8 @@ const makeAssessmentOverview = (result: any, maxXpVal: number): AssessmentOvervi
status: AssessmentStatuses.attempting,
story: rawOverview.story,
xp: 0,
- gradingStatus: 'none' as GradingStatuses
+ gradingStatus: 'none' as GradingStatuses,
+ hasVotingFeatures: false
};
};
@@ -101,8 +102,7 @@ const makeAssessment = (result: any): [Assessment, number] => {
longSummary: task.TEXT[0],
missionPDF: 'google.com',
questions: questionArr[0],
- title: rawOverview.title,
- hasVotingFeatures: false
+ title: rawOverview.title
},
questionArr[1]
];
diff --git a/src/commons/application/actions/__tests__/SessionActions.ts b/src/commons/application/actions/__tests__/SessionActions.ts
index 08e4f31460..7f0898ac80 100644
--- a/src/commons/application/actions/__tests__/SessionActions.ts
+++ b/src/commons/application/actions/__tests__/SessionActions.ts
@@ -295,6 +295,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -304,6 +305,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission2',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -313,6 +315,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission3',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -521,8 +524,7 @@ test('updateAssessment generates correct action object', () => {
longSummary: 'long summary here',
missionPDF: 'www.google.com',
questions: [],
- title: 'first assessment',
- hasVotingFeatures: false
+ title: 'first assessment'
};
const action = updateAssessment(assessment);
@@ -682,6 +684,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -691,6 +694,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Quests',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -700,6 +704,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Paths',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -709,6 +714,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Contests',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -718,6 +724,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Others',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
@@ -736,6 +743,7 @@ test('deleteAssessmentConfig generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
diff --git a/src/commons/application/reducers/__tests__/SessionReducer.ts b/src/commons/application/reducers/__tests__/SessionReducer.ts
index a8ebafc834..c5e2742de5 100644
--- a/src/commons/application/reducers/__tests__/SessionReducer.ts
+++ b/src/commons/application/reducers/__tests__/SessionReducer.ts
@@ -238,8 +238,7 @@ const assessmentTest1: Assessment = {
longSummary: 'long summary here',
missionPDF: 'www.google.com',
questions: [],
- title: 'first assessment',
- hasVotingFeatures: false
+ title: 'first assessment'
};
const assessmentTest2: Assessment = {
@@ -250,8 +249,7 @@ const assessmentTest2: Assessment = {
longSummary: 'another long summary',
missionPDF: 'www.comp.nus.edu.sg',
questions: [],
- title: 'updated first assessment',
- hasVotingFeatures: false
+ title: 'updated first assessment'
};
const assessmentTest3: Assessment = {
@@ -262,8 +260,7 @@ const assessmentTest3: Assessment = {
longSummary: 'another long summary here',
missionPDF: 'www.yahoo.com',
questions: [],
- title: 'path',
- hasVotingFeatures: false
+ title: 'path'
};
test('UPDATE_ASSESSMENT works correctly in inserting assessment', () => {
diff --git a/src/commons/assessment/AssessmentTypes.ts b/src/commons/assessment/AssessmentTypes.ts
index bfdbf7bba7..efece3b4d1 100644
--- a/src/commons/assessment/AssessmentTypes.ts
+++ b/src/commons/assessment/AssessmentTypes.ts
@@ -83,7 +83,6 @@ export type Assessment = {
type: AssessmentType;
globalDeployment?: Library; // For mission control
graderDeployment?: Library; // For mission control
- hasVotingFeatures: boolean;
hasTokenCounter?: boolean;
id: number;
longSummary: string;
@@ -99,6 +98,7 @@ export type AssessmentConfiguration = {
displayInDashboard: boolean;
hoursBeforeEarlyXpDecay: number;
earlySubmissionXp: number;
+ hasTokenCounter: boolean;
hasVotingFeatures: boolean;
};
diff --git a/src/commons/assessment/__tests__/Assessment.tsx b/src/commons/assessment/__tests__/Assessment.tsx
index a1f8bfe121..1863ffe91e 100644
--- a/src/commons/assessment/__tests__/Assessment.tsx
+++ b/src/commons/assessment/__tests__/Assessment.tsx
@@ -17,6 +17,7 @@ const mockAssessmentProps = assertType()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
diff --git a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
index b9848c2ed0..1d0b661845 100644
--- a/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
+++ b/src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
@@ -251,17 +251,12 @@ const AssessmentWorkspace: React.FC = props => {
* Handles toggling enabling and disabling token counter depending on assessment properties
*/
useEffect(() => {
- if (assessment?.hasVotingFeatures && assessment?.hasTokenCounter) {
+ if (assessment?.hasTokenCounter) {
handleEnableTokenCounter();
} else {
handleDisableTokenCounter();
}
- }, [
- assessment?.hasTokenCounter,
- handleEnableTokenCounter,
- handleDisableTokenCounter,
- assessment?.hasVotingFeatures
- ]);
+ }, [assessment?.hasTokenCounter, handleEnableTokenCounter, handleDisableTokenCounter]);
/**
* Handles toggling of relevant SideContentTabs when mobile breakpoint it hit
diff --git a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
index b74e85b5e2..34206febe5 100644
--- a/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
+++ b/src/commons/assessmentWorkspace/__tests__/AssessmentWorkspace.tsx
@@ -26,6 +26,7 @@ const defaultProps = assertType()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
diff --git a/src/commons/mocks/AssessmentMocks.ts b/src/commons/mocks/AssessmentMocks.ts
index f24a6c389a..1abad14abd 100644
--- a/src/commons/mocks/AssessmentMocks.ts
+++ b/src/commons/mocks/AssessmentMocks.ts
@@ -22,6 +22,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -31,6 +32,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -40,6 +42,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -49,6 +52,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: true,
earlySubmissionXp: 200
},
@@ -58,6 +62,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
}
@@ -69,6 +74,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -78,6 +84,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -87,6 +94,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
}
@@ -920,8 +928,7 @@ export const mockAssessments: Assessment[] = [
'This is the mission briefing. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas viverra, sem scelerisque ultricies ullamcorper, sem nibh sollicitudin enim, at ultricies sem orci eget odio. Pellentesque varius et mauris quis vestibulum. Etiam in egestas dolor. Nunc consectetur, sapien sodales accumsan convallis, lectus mi tempus ipsum, vel ornare metus turpis sed justo. Vivamus at tellus sed ex convallis commodo at in lectus. Pellentesque pharetra pulvinar sapien pellentesque facilisis. Curabitur efficitur malesuada urna sed aliquam. Quisque massa metus, aliquam in sagittis non, cursus in sem. Morbi vel nunc at nunc pharetra lobortis. Aliquam feugiat ultricies ipsum vel sollicitudin. Vivamus nulla massa, hendrerit sit amet nibh quis, porttitor convallis nisi. ',
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
- title: 'An Odessey to Runes',
- hasVotingFeatures: false
+ title: 'An Odessey to Runes'
},
{
type: 'Missions',
@@ -930,8 +937,7 @@ export const mockAssessments: Assessment[] = [
'This is the mission briefing. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas viverra, sem scelerisque ultricies ullamcorper, sem nibh sollicitudin enim, at ultricies sem orci eget odio. Pellentesque varius et mauris quis vestibulum. Etiam in egestas dolor. Nunc consectetur, sapien sodales accumsan convallis, lectus mi tempus ipsum, vel ornare metus turpis sed justo. Vivamus at tellus sed ex convallis commodo at in lectus. Pellentesque pharetra pulvinar sapien pellentesque facilisis. Curabitur efficitur malesuada urna sed aliquam. Quisque massa metus, aliquam in sagittis non, cursus in sem. Morbi vel nunc at nunc pharetra lobortis. Aliquam feugiat ultricies ipsum vel sollicitudin. Vivamus nulla massa, hendrerit sit amet nibh quis, porttitor convallis nisi. ',
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
- title: 'The Secret to Streams',
- hasVotingFeatures: false
+ title: 'The Secret to Streams'
},
{
type: 'Quests',
@@ -957,8 +963,7 @@ export const mockAssessments: Assessment[] = [
\`\`\``,
missionPDF: 'www.google.com',
questions: mockAssessmentQuestions,
- title: 'A sample Sidequest',
- hasVotingFeatures: false
+ title: 'A sample Sidequest'
},
{
type: 'Missions',
@@ -967,8 +972,7 @@ export const mockAssessments: Assessment[] = [
'This is the closed mission briefing. The save button should not be there. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas viverra, sem scelerisque ultricies ullamcorper, sem nibh sollicitudin enim, at ultricies sem orci eget odio. Pellentesque varius et mauris quis vestibulum. Etiam in egestas dolor. Nunc consectetur, sapien sodales accumsan convallis, lectus mi tempus ipsum, vel ornare metus turpis sed justo. Vivamus at tellus sed ex convallis commodo at in lectus. Pellentesque pharetra pulvinar sapien pellentesque facilisis. Curabitur efficitur malesuada urna sed aliquam. Quisque massa metus, aliquam in sagittis non, cursus in sem. Morbi vel nunc at nunc pharetra lobortis. Aliquam feugiat ultricies ipsum vel sollicitudin. Vivamus nulla massa, hendrerit sit amet nibh quis, porttitor convallis nisi. ',
missionPDF: 'www.google.com',
questions: mockClosedAssessmentQuestions,
- title: 'A Closed Mission',
- hasVotingFeatures: false
+ title: 'A Closed Mission'
},
{
type: 'Quests',
@@ -977,8 +981,7 @@ export const mockAssessments: Assessment[] = [
'This is the closed sidequest briefing. The save button should not exist. This is a placeholder sidequest for testing rendering of grading statuses.',
missionPDF: 'www.google.com',
questions: mockClosedAssessmentQuestions,
- title: 'A Closed Sidequest',
- hasVotingFeatures: false
+ title: 'A Closed Sidequest'
},
{
type: 'Paths',
@@ -990,8 +993,7 @@ export const mockAssessments: Assessment[] = [
The path comprises 4 questions and is fully autograded and guided, and there are **no private test cases** - there will be no manual review by default. Please consult your Avenger if you require assistance!`,
missionPDF: 'www.google.com',
questions: mockPathQuestions,
- title: 'A sample guided path',
- hasVotingFeatures: false
+ title: 'A sample guided path'
},
// mock assessment used for testing contest voting assessments
{
@@ -1000,7 +1002,6 @@ export const mockAssessments: Assessment[] = [
title: 'A sample contest voting assessment',
longSummary: 'Vote for your favourite contest entries here!',
missionPDF: 'www.google.com',
- questions: mockContestEntryQuestion,
- hasVotingFeatures: false
+ questions: mockContestEntryQuestion
}
];
diff --git a/src/commons/profile/__tests__/Profile.tsx b/src/commons/profile/__tests__/Profile.tsx
index 05b9247c3f..d12e179e09 100644
--- a/src/commons/profile/__tests__/Profile.tsx
+++ b/src/commons/profile/__tests__/Profile.tsx
@@ -25,6 +25,7 @@ const assessmentConfigurations: AssessmentConfiguration[] = [
type: c,
isManuallyGraded: false,
displayInDashboard: false,
+ hasTokenCounter: false,
hasVotingFeatures: false,
hoursBeforeEarlyXpDecay: 0,
earlySubmissionXp: 0
diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts
index 815ffdea05..245250be65 100644
--- a/src/commons/sagas/BackendSaga.ts
+++ b/src/commons/sagas/BackendSaga.ts
@@ -987,6 +987,7 @@ function* BackendSaga(): SagaIterator {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 0
}
diff --git a/src/commons/sagas/__tests__/BackendSaga.ts b/src/commons/sagas/__tests__/BackendSaga.ts
index 5ad79a4832..3cb9eb1f06 100644
--- a/src/commons/sagas/__tests__/BackendSaga.ts
+++ b/src/commons/sagas/__tests__/BackendSaga.ts
@@ -218,6 +218,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -227,6 +228,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -236,6 +238,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
},
@@ -245,6 +248,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: true,
earlySubmissionXp: 200
},
@@ -254,6 +258,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 200
}
@@ -1007,6 +1012,7 @@ describe('Test CREATE_COURSE action', () => {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 0
}
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index 527369ae30..1b8cad2c17 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -94,6 +94,7 @@ const AssessmentConfigPanel: React.FC = ({
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
+ hasTokenCounter: false,
hasVotingFeatures: false,
earlySubmissionXp: 0
});
From b948ae43ac1cd1c1deada0cd726dfcb1c764d679 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 18:25:19 +0800
Subject: [PATCH 11/26] Add new column for token counter in admin panel
---
.../AssessmentConfigPanel.tsx | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index 1b8cad2c17..0a58b2c640 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -51,6 +51,16 @@ const AssessmentConfigPanel: React.FC = ({
gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('displayInDashboard', value);
};
+ const setHasTokenCounter = (index: number, value: boolean) => {
+ const temp = [...assessmentConfig.current];
+ temp[index] = {
+ ...temp[index],
+ hasTokenCounter: value
+ };
+ setAssessmentConfig(temp);
+ gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('hasVotingFeatures', value);
+ };
+
const setHasVotingFeatures = (index: number, value: boolean) => {
const temp = [...assessmentConfig.current];
temp[index] = {
@@ -149,6 +159,15 @@ const AssessmentConfigPanel: React.FC = ({
field: 'hasVotingFeatures'
}
},
+ {
+ headerName: 'Has Token Counter',
+ field: 'hasTokenCounter',
+ cellRenderer: BooleanCell,
+ cellRendererParams: {
+ setStateHandler: setHasTokenCounter,
+ field: 'hasTokenCounter'
+ }
+ },
{
headerName: 'Max Bonus XP',
field: 'earlySubmissionXp',
From ace43d8c3d416bcef80627db97847bba8e9bb0e2 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 18:38:49 +0800
Subject: [PATCH 12/26] Fix bugs relating to tokencounter switch
---
.../AssessmentConfigPanel.tsx | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index 0a58b2c640..e2d739a9ed 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -58,7 +58,7 @@ const AssessmentConfigPanel: React.FC = ({
hasTokenCounter: value
};
setAssessmentConfig(temp);
- gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('hasVotingFeatures', value);
+ gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('hasTokenCounter', value);
};
const setHasVotingFeatures = (index: number, value: boolean) => {
@@ -151,22 +151,26 @@ const AssessmentConfigPanel: React.FC = ({
}
},
{
- headerName: 'Has Voting Features',
+ headerName: 'Voting Features',
field: 'hasVotingFeatures',
cellRenderer: BooleanCell,
cellRendererParams: {
setStateHandler: setHasVotingFeatures,
field: 'hasVotingFeatures'
- }
+ },
+ maxWidth: 300,
+ resizable: false
},
{
- headerName: 'Has Token Counter',
+ headerName: 'Token Counter',
field: 'hasTokenCounter',
cellRenderer: BooleanCell,
cellRendererParams: {
setStateHandler: setHasTokenCounter,
field: 'hasTokenCounter'
- }
+ },
+ maxWidth: 300,
+ resizable: false
},
{
headerName: 'Max Bonus XP',
From afdbfe5e6fd12dc02ffc18d897098a34d8a35368 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Thu, 21 Mar 2024 18:40:43 +0800
Subject: [PATCH 13/26] Remove unnecessary maxwidth property on tokencounter
switch
---
.../assessmentConfigPanel/AssessmentConfigPanel.tsx | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index e2d739a9ed..4a35478695 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -157,9 +157,7 @@ const AssessmentConfigPanel: React.FC = ({
cellRendererParams: {
setStateHandler: setHasVotingFeatures,
field: 'hasVotingFeatures'
- },
- maxWidth: 300,
- resizable: false
+ }
},
{
headerName: 'Token Counter',
@@ -168,9 +166,7 @@ const AssessmentConfigPanel: React.FC = ({
cellRendererParams: {
setStateHandler: setHasTokenCounter,
field: 'hasTokenCounter'
- },
- maxWidth: 300,
- resizable: false
+ }
},
{
headerName: 'Max Bonus XP',
From 4b313c5afd30afd3a71c6e72536a73d7d4bd5931 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Fri, 22 Mar 2024 01:29:16 +0800
Subject: [PATCH 14/26] Fix bug where toggling tokencounter would request
voting features to be true to backend
---
.../groundControl/subcomponents/GroundControlConfigureCell.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 62f19baabb..469daac4fb 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -32,7 +32,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
const handleConfigure = useCallback(() => {
const { id } = data;
- handleConfigureAssessment(id, hasVotingFeatures, hasTokenCounter);
+ handleConfigureAssessment(id, hasTokenCounter, hasVotingFeatures);
}, [data, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
const toggleHasTokenCounter = useCallback(
From 4298cac6ed55daa0b39e11f7a3d3271c2ee417eb Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Fri, 22 Mar 2024 15:23:08 +0800
Subject: [PATCH 15/26] Create footer text to clarify usage of hastokencounter
and hasVotingFeatures
---
.../assessmentConfigPanel/AssessmentConfigPanel.tsx | 9 +++++++--
src/styles/_academy.scss | 5 +++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
index 4a35478695..3d10e8818b 100644
--- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
+++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx
@@ -151,7 +151,7 @@ const AssessmentConfigPanel: React.FC = ({
}
},
{
- headerName: 'Voting Features',
+ headerName: 'Voting Features*',
field: 'hasVotingFeatures',
cellRenderer: BooleanCell,
cellRendererParams: {
@@ -160,7 +160,7 @@ const AssessmentConfigPanel: React.FC = ({
}
},
{
- headerName: 'Token Counter',
+ headerName: 'Token Counter*',
field: 'hasTokenCounter',
cellRenderer: BooleanCell,
cellRendererParams: {
@@ -268,6 +268,11 @@ const AssessmentConfigPanel: React.FC = ({
onRowDragEnd={onRowDragLeaveOrEnd}
onCellValueChanged={onCellValueChanged}
/>
+
+ *If you create an assessment with these toggles enabled, they will be activated within the
+ assessment by default. However, you can also visit ground control to manually
+ override these settings if needed.
+
);
diff --git a/src/styles/_academy.scss b/src/styles/_academy.scss
index 6058cc9477..985afb1fba 100644
--- a/src/styles/_academy.scss
+++ b/src/styles/_academy.scss
@@ -438,6 +438,11 @@
right: 0;
}
}
+
+ .footer-text {
+ margin-top: 12px;
+ text-align: left;
+ }
}
.users-configuration {
From 505c11501771cddc15ab043335cf0ffa3efe25ba Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Fri, 22 Mar 2024 15:48:05 +0800
Subject: [PATCH 16/26] Align text on configure dialogbox
---
.../groundControl/subcomponents/GroundControlConfigureCell.tsx | 3 +--
src/styles/_groundcontrol.scss | 3 ++-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 469daac4fb..b9789d990e 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -59,8 +59,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
This configuration tool allows you to fine-tune this assessment. Any changes made
here will override any assessment configurations in the admin panel.
-
-
+
General Configurations
diff --git a/src/styles/_groundcontrol.scss b/src/styles/_groundcontrol.scss
index 0536c2c48e..6cb433c70a 100644
--- a/src/styles/_groundcontrol.scss
+++ b/src/styles/_groundcontrol.scss
@@ -78,10 +78,11 @@
.control-button-container {
display: flex;
+ margin-left: 5px;
}
.publish-voting {
- margin-top: 4px;
+ margin-top: 5px;
}
}
}
From 712c106fdbb69c890e4804033709e873887c0719 Mon Sep 17 00:00:00 2001
From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com>
Date: Sat, 23 Mar 2024 15:48:42 +0800
Subject: [PATCH 17/26] Fix tests post-merge
The stronger type checking had been causing compile errors.
---
.../reducers/__tests__/SessionReducer.ts | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/commons/application/reducers/__tests__/SessionReducer.ts b/src/commons/application/reducers/__tests__/SessionReducer.ts
index 3db5f7ffc7..f39cd7f073 100644
--- a/src/commons/application/reducers/__tests__/SessionReducer.ts
+++ b/src/commons/application/reducers/__tests__/SessionReducer.ts
@@ -8,10 +8,9 @@ import {
GradingStatuses
} from '../../../assessment/AssessmentTypes';
import { Notification } from '../../../notificationBadge/NotificationBadgeTypes';
-import { defaultSession, GameState, Role, Story } from '../../ApplicationTypes';
+import { GameState, Role, Story, defaultSession } from '../../ApplicationTypes';
import { LOG_OUT } from '../../types/CommonsTypes';
import {
- SessionState,
SET_ADMIN_PANEL_COURSE_REGISTRATIONS,
SET_ASSESSMENT_CONFIGURATIONS,
SET_COURSE_CONFIGURATION,
@@ -19,6 +18,7 @@ import {
SET_GITHUB_ACCESS_TOKEN,
SET_TOKENS,
SET_USER,
+ SessionState,
UPDATE_ASSESSMENT,
UPDATE_ASSESSMENT_OVERVIEWS,
UPDATE_GRADING,
@@ -158,7 +158,8 @@ test('SET_ASSESSMENT_CONFIGURATIONS works correctly', () => {
earlySubmissionXp: 200,
isManuallyGraded: false,
displayInDashboard: true,
- hasTokenCounter: false
+ hasTokenCounter: false,
+ hasVotingFeatures: false
},
{
assessmentConfigId: 1,
@@ -170,7 +171,8 @@ test('SET_ASSESSMENT_CONFIGURATIONS works correctly', () => {
earlySubmissionXp: 200,
isManuallyGraded: false,
displayInDashboard: true,
- hasTokenCounter: false
+ hasTokenCounter: false,
+ hasVotingFeatures: false
},
{
assessmentConfigId: 1,
@@ -182,7 +184,8 @@ test('SET_ASSESSMENT_CONFIGURATIONS works correctly', () => {
earlySubmissionXp: 200,
isManuallyGraded: false,
displayInDashboard: true,
- hasTokenCounter: false
+ hasTokenCounter: false,
+ hasVotingFeatures: false
}
];
From 702a12ffabd562378218c697c64422c061bed677 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Sun, 24 Mar 2024 02:34:49 +0800
Subject: [PATCH 18/26] Fix imports
---
src/commons/application/reducers/__tests__/SessionReducer.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/commons/application/reducers/__tests__/SessionReducer.ts b/src/commons/application/reducers/__tests__/SessionReducer.ts
index f39cd7f073..94b35c3a6f 100644
--- a/src/commons/application/reducers/__tests__/SessionReducer.ts
+++ b/src/commons/application/reducers/__tests__/SessionReducer.ts
@@ -8,9 +8,10 @@ import {
GradingStatuses
} from '../../../assessment/AssessmentTypes';
import { Notification } from '../../../notificationBadge/NotificationBadgeTypes';
-import { GameState, Role, Story, defaultSession } from '../../ApplicationTypes';
+import { defaultSession, GameState, Role, Story } from '../../ApplicationTypes';
import { LOG_OUT } from '../../types/CommonsTypes';
import {
+ SessionState,
SET_ADMIN_PANEL_COURSE_REGISTRATIONS,
SET_ASSESSMENT_CONFIGURATIONS,
SET_COURSE_CONFIGURATION,
@@ -18,7 +19,6 @@ import {
SET_GITHUB_ACCESS_TOKEN,
SET_TOKENS,
SET_USER,
- SessionState,
UPDATE_ASSESSMENT,
UPDATE_ASSESSMENT_OVERVIEWS,
UPDATE_GRADING,
From aa7e428c8480ba25dfc3b5e2f4af29d802e3771f Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Sun, 24 Mar 2024 03:07:58 +0800
Subject: [PATCH 19/26] Add close dialog upon saving
---
.../groundControl/subcomponents/GroundControlConfigureCell.tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index b9789d990e..62a789de5c 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -33,7 +33,8 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
const handleConfigure = useCallback(() => {
const { id } = data;
handleConfigureAssessment(id, hasTokenCounter, hasVotingFeatures);
- }, [data, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
+ handleCloseDialog();
+ }, [data, handleCloseDialog, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
const toggleHasTokenCounter = useCallback(
() => setHasTokenCounter(!hasTokenCounter),
From b9b3e9956c641777f9595d5403989d5d374b7f96 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Sun, 24 Mar 2024 03:32:25 +0800
Subject: [PATCH 20/26] Uncapitalise letters in config dialog
---
.../subcomponents/GroundControlConfigureCell.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 62a789de5c..fe922d1765 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -70,7 +70,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
checked={hasTokenCounter}
onChange={toggleHasTokenCounter}
inline
- label="Has Token Counter"
+ label="Has token counter"
>
@@ -83,7 +83,7 @@ const ConfigureCell: React.FC
= ({ handleConfigureAssessment, data }) =>
checked={hasVotingFeatures}
onChange={toggleVotingFeatures}
inline
- label="Enable Voting Features"
+ label="Enable voting features"
>
From 9e576ce6f350f3eb4857efe0a8e81a5bd9da688b Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Sun, 24 Mar 2024 03:38:44 +0800
Subject: [PATCH 21/26] Change label from has token counter to enable token
counter
---
.../groundControl/subcomponents/GroundControlConfigureCell.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index fe922d1765..d497163cf8 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -70,7 +70,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
checked={hasTokenCounter}
onChange={toggleHasTokenCounter}
inline
- label="Has token counter"
+ label="Enable token counter"
>
From 25aeab1d47fb573f137554992dc6195383043cd6 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Sun, 24 Mar 2024 03:46:30 +0800
Subject: [PATCH 22/26] Code quality improvements
---
src/features/groundControl/GroundControlActions.ts | 4 ++--
src/pages/academy/groundControl/GroundControl.tsx | 4 ++--
.../subcomponents/GroundControlConfigureCell.tsx | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/features/groundControl/GroundControlActions.ts b/src/features/groundControl/GroundControlActions.ts
index 4499ce2e64..0a7162558d 100644
--- a/src/features/groundControl/GroundControlActions.ts
+++ b/src/features/groundControl/GroundControlActions.ts
@@ -29,7 +29,7 @@ export const uploadAssessment = createAction(
export const configureAssessment = createAction(
CONFIGURE_ASSESSMENT,
- (id: number, hasTokenCounter: boolean, hasVotingFeatures: boolean) => ({
- payload: { id, hasTokenCounter, hasVotingFeatures }
+ (id: number, hasVotingFeatures: boolean, hasTokenCounter: boolean) => ({
+ payload: { id, hasVotingFeatures, hasTokenCounter }
})
);
diff --git a/src/pages/academy/groundControl/GroundControl.tsx b/src/pages/academy/groundControl/GroundControl.tsx
index a89ab3e200..6164938695 100644
--- a/src/pages/academy/groundControl/GroundControl.tsx
+++ b/src/pages/academy/groundControl/GroundControl.tsx
@@ -29,8 +29,8 @@ export type DispatchProps = {
handleAssessmentChangeDate: (id: number, openAt: string, closeAt: string) => void;
handleConfigureAssessment: (
id: number,
- hasTokenCounter: boolean,
- hasVotingFeatures: boolean
+ hasVotingFeatures: boolean,
+ hasTokenCounter: boolean
) => void;
handleFetchCourseConfigs: () => void;
};
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index d497163cf8..02af03acf9 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -32,7 +32,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
const handleConfigure = useCallback(() => {
const { id } = data;
- handleConfigureAssessment(id, hasTokenCounter, hasVotingFeatures);
+ handleConfigureAssessment(id, hasVotingFeatures, hasTokenCounter);
handleCloseDialog();
}, [data, handleCloseDialog, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
From 7e4f84684d4b945f432ce798244fa6aea3d61c17 Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Mon, 25 Mar 2024 21:30:37 +0800
Subject: [PATCH 23/26] Create new section for team-related configurations
---
.../GroundControlConfigureCell.tsx | 27 ++++++++++++++++++-
src/styles/_groundcontrol.scss | 14 +++++++++-
2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index 02af03acf9..bf32730c2c 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -5,9 +5,10 @@ import {
DialogFooter,
Divider,
Intent,
+ NumericInput,
Switch
} from '@blueprintjs/core';
-import { IconNames } from '@blueprintjs/icons';
+import { IconNames, Team } from '@blueprintjs/icons';
import React, { useCallback, useState } from 'react';
import { AssessmentOverview } from '../../../../commons/assessment/AssessmentTypes';
@@ -26,6 +27,7 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
const [isDialogOpen, setDialogState] = useState(false);
const [hasVotingFeatures, setHasVotingFeatures] = useState(!!data.hasVotingFeatures);
const [hasTokenCounter, setHasTokenCounter] = useState(!!data.hasTokenCounter);
+ const [isTeamAssessment, setIsTeamAssessment] = useState(false);
const handleOpenDialog = useCallback(() => setDialogState(true), []);
const handleCloseDialog = useCallback(() => setDialogState(false), []);
@@ -44,6 +46,10 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
() => setHasVotingFeatures(!hasVotingFeatures),
[hasVotingFeatures]
);
+ const toggleIsTeamAssessment = useCallback(
+ () => setIsTeamAssessment(!isTeamAssessment),
+ [isTeamAssessment]
+ );
return (
<>
@@ -73,6 +79,25 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
label="Enable token counter"
>
+
+
+ Team-Related Configurations
+
+
+
+
+
+
+
Voting-Related Configurations
diff --git a/src/styles/_groundcontrol.scss b/src/styles/_groundcontrol.scss
index 6cb433c70a..8328139e8e 100644
--- a/src/styles/_groundcontrol.scss
+++ b/src/styles/_groundcontrol.scss
@@ -69,7 +69,8 @@
}
.voting-related-configs,
-.general-configs {
+.general-configs,
+.team-related-configs {
margin-top: 20px;
.voting-related-controls {
@@ -85,4 +86,15 @@
margin-top: 5px;
}
}
+
+ .numeric-input-container {
+ display: flex;
+ margin-left: 14px;
+ gap: 8px;
+ align-items: center;
+
+ .max-team-size {
+ margin-top: 10px;
+ }
+ }
}
From 5a767136d43b93d66da01fd592aa1b5cc3a9239c Mon Sep 17 00:00:00 2001
From: positivelyjon
Date: Tue, 26 Mar 2024 14:17:00 +0800
Subject: [PATCH 24/26] Fix code quality per suggestion
---
.../GroundControlConfigureCell.tsx | 51 ++++++++-----------
1 file changed, 20 insertions(+), 31 deletions(-)
diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
index bf32730c2c..e8a300ab2e 100644
--- a/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
+++ b/src/pages/academy/groundControl/subcomponents/GroundControlConfigureCell.tsx
@@ -38,18 +38,9 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
handleCloseDialog();
}, [data, handleCloseDialog, handleConfigureAssessment, hasTokenCounter, hasVotingFeatures]);
- const toggleHasTokenCounter = useCallback(
- () => setHasTokenCounter(!hasTokenCounter),
- [hasTokenCounter]
- );
- const toggleVotingFeatures = useCallback(
- () => setHasVotingFeatures(!hasVotingFeatures),
- [hasVotingFeatures]
- );
- const toggleIsTeamAssessment = useCallback(
- () => setIsTeamAssessment(!isTeamAssessment),
- [isTeamAssessment]
- );
+ const toggleHasTokenCounter = useCallback(() => setHasTokenCounter(prev => !prev), []);
+ const toggleVotingFeatures = useCallback(() => setHasVotingFeatures(prev => !prev), []);
+ const toggleIsTeamAssessment = useCallback(() => setIsTeamAssessment(prev => !prev), []);
return (
<>
@@ -70,31 +61,31 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
General Configurations
-
+
+ />
Team-Related Configurations
-
+
+ />
@@ -102,14 +93,14 @@ const ConfigureCell: React.FC = ({ handleConfigureAssessment, data }) =>
Voting-Related Configurations
-
+
+ />
@@ -117,35 +108,33 @@ const ConfigureCell: React.FC
= ({ handleConfigureAssessment, data }) =>
icon={IconNames.PEOPLE}
isDisabled={true}
label="Export Popular Vote Leaderboard (Coming soon!)"
- >
+ />
+ />
+ />
-
- >
+
}
>
From fd1c90026a60601142eb02bf22862261470eec82 Mon Sep 17 00:00:00 2001
From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com>
Date: Tue, 26 Mar 2024 22:09:34 +0800
Subject: [PATCH 25/26] Fix errors post-merge
---
.../academy/groundControl/GroundControl.tsx | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/pages/academy/groundControl/GroundControl.tsx b/src/pages/academy/groundControl/GroundControl.tsx
index 06128069ec..4a5e2ccd0b 100644
--- a/src/pages/academy/groundControl/GroundControl.tsx
+++ b/src/pages/academy/groundControl/GroundControl.tsx
@@ -151,21 +151,21 @@ const GroundControl: React.FC
= props => {
handleDeleteAssessment: props.handleDeleteAssessment
},
width: 80,
- filter: false,
- resizable: false,
- sortable: false,
- cellStyle: {
- padding: 0
- }
+ filter: false,
+ resizable: false,
+ sortable: false,
+ cellStyle: {
+ padding: 0
+ }
+ },
+ {
+ headerName: 'Configure',
+ field: 'placeholderConfigure' as any,
+ cellRenderer: ConfigureCell,
+ cellRendererParams: {
+ handleConfigureAssessment: props.handleConfigureAssessment
},
- {
- headerName: 'Configure',
- field: '',
- cellRenderer: ConfigureCell,
- cellRendererParams: {
- handleConfigureAssessment: this.props.handleConfigureAssessment
- },
- width: 80,
+ width: 80,
filter: false,
resizable: false,
sortable: false,
From 1f22fa552110890c0f2d6354f7066938982443a2 Mon Sep 17 00:00:00 2001
From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com>
Date: Tue, 26 Mar 2024 22:15:18 +0800
Subject: [PATCH 26/26] Fix lint errors
---
src/commons/application/reducers/__tests__/SessionReducer.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/commons/application/reducers/__tests__/SessionReducer.ts b/src/commons/application/reducers/__tests__/SessionReducer.ts
index 9355cc20bb..e5a9007c93 100644
--- a/src/commons/application/reducers/__tests__/SessionReducer.ts
+++ b/src/commons/application/reducers/__tests__/SessionReducer.ts
@@ -8,9 +8,10 @@ import {
GradingStatuses
} from '../../../assessment/AssessmentTypes';
import { Notification } from '../../../notificationBadge/NotificationBadgeTypes';
-import { GameState, Role, Story, defaultSession } from '../../ApplicationTypes';
+import { defaultSession, GameState, Role, Story } from '../../ApplicationTypes';
import { LOG_OUT } from '../../types/CommonsTypes';
import {
+ SessionState,
SET_ADMIN_PANEL_COURSE_REGISTRATIONS,
SET_ASSESSMENT_CONFIGURATIONS,
SET_COURSE_CONFIGURATION,
@@ -18,7 +19,6 @@ import {
SET_GITHUB_ACCESS_TOKEN,
SET_TOKENS,
SET_USER,
- SessionState,
UPDATE_ASSESSMENT,
UPDATE_ASSESSMENT_OVERVIEWS,
UPDATE_GRADING,