Enable answer count and [FIX] option copying

Add option to display number of answers to current prompt and ensure test options get copied to new tests that are created at the end of an existing test (with the restart test/restart test with incorrect buttons)
This commit is contained in:
2022-01-30 20:18:57 +00:00
parent 98491163fa
commit 2073e5b828
6 changed files with 92 additions and 1 deletions

View File

@@ -167,6 +167,14 @@ exports.createProgress = functions.https.onCall((data, context) => {
throw new functions.https.HttpsError("invalid-argument", "switch_language must be a boolean"); throw new functions.https.HttpsError("invalid-argument", "switch_language must be a boolean");
} }
if (typeof data.ignoreCaps !== "boolean") {
throw new functions.https.HttpsError("invalid-argument", "ignoreCaps must be a boolean");
}
if (typeof data.showNumberOfAnswers !== "boolean") {
throw new functions.https.HttpsError("invalid-argument", "showNumberOfAnswers must be a boolean");
}
if (data.mode !== "questions" && data.mode !== "lives") { if (data.mode !== "questions" && data.mode !== "lives") {
throw new functions.https.HttpsError("invalid-argument", "mode must be \"questions\" or \"lives\""); throw new functions.https.HttpsError("invalid-argument", "mode must be \"questions\" or \"lives\"");
} }
@@ -239,6 +247,7 @@ exports.createProgress = functions.https.onCall((data, context) => {
set_titles: setIds.map((setId) => setTitlesDict[setId]), set_titles: setIds.map((setId) => setTitlesDict[setId]),
typo: false, typo: false,
ignoreCaps: data.ignoreCaps, ignoreCaps: data.ignoreCaps,
showNumberOfAnswers: data.showNumberOfAnswers,
} }
return { return {
@@ -263,10 +272,12 @@ exports.createProgress = functions.https.onCall((data, context) => {
const terms = { const terms = {
"item": doc.data().term, "item": doc.data().term,
"sound": doc.data().sound, "sound": doc.data().sound,
"numberOfAnswers": doc.data().definition.split("/").length,
}; };
const definitions = { const definitions = {
"item": doc.data().definition, "item": doc.data().definition,
"sound": doc.data().sound, "sound": doc.data().sound,
"numberOfAnswers": doc.data().term.split("/").length,
}; };
data.dataToSet.questions.push(vocabId); data.dataToSet.questions.push(vocabId);
@@ -345,6 +356,8 @@ exports.createProgressWithIncorrect = functions.https.onCall((data, context) =>
typo: false, typo: false,
setIds: progressData.setIds, setIds: progressData.setIds,
set_titles: progressData.set_titles, set_titles: progressData.set_titles,
ignoreCaps: progressData.ignoreCaps,
showNumberOfAnswers: progressData.showNumberOfAnswers,
}; };
if (progressData.mode === "lives") { if (progressData.mode === "lives") {
dataToSet.lives = progressData.start_lives; dataToSet.lives = progressData.start_lives;
@@ -607,6 +620,7 @@ exports.processAnswer = functions.https.onCall((data, context) => {
totalCorrect: docData.correct.length, totalCorrect: docData.correct.length,
totalIncorrect: docData.incorrect.length, totalIncorrect: docData.incorrect.length,
typo: false, typo: false,
numberOfAnswers: progressDoc.data().showNumberOfAnswers === true ? 0 : null,
} }
docData.typo = false; docData.typo = false;
@@ -747,6 +761,7 @@ exports.processAnswer = functions.https.onCall((data, context) => {
sound: sound, sound: sound,
set_owner: nextSetOwner, set_owner: nextSetOwner,
} }
returnData.numberOfAnswers = promptDoc.data().numberOfAnswers;
transaction.set(progressDocId, docData); transaction.set(progressDocId, docData);
return returnData; return returnData;
}); });
@@ -771,7 +786,8 @@ exports.processAnswer = functions.https.onCall((data, context) => {
item: promptDoc.data().item, item: promptDoc.data().item,
sound: sound, sound: sound,
set_owner: nextSetOwner, set_owner: nextSetOwner,
} };
returnData.numberOfAnswers = promptDoc.data().numberOfAnswers;
transaction.set(progressDocId, docData); transaction.set(progressDocId, docData);
return returnData; return returnData;
}); });

View File

@@ -70,6 +70,14 @@ export default function ClassicTestStart(props) {
/> />
<span>Ignore capitals</span> <span>Ignore capitals</span>
</label> </label>
<label>
<Checkbox
checked={props.showNumberOfAnswers}
onChange={props.handleShowNumberOfAnswersChange}
inputProps={{ 'aria-label': 'checkbox' }}
/>
<span>Show number of answers</span>
</label>
</div> </div>
<Button <Button

View File

@@ -70,6 +70,14 @@ export default function LivesTestStart(props) {
/> />
<span>Ignore capitals</span> <span>Ignore capitals</span>
</label> </label>
<label>
<Checkbox
checked={props.showNumberOfAnswers}
onChange={props.handleShowNumberOfAnswersChange}
inputProps={{ 'aria-label': 'checkbox' }}
/>
<span>Show number of answers</span>
</label>
</div> </div>
<Button <Button

View File

@@ -72,6 +72,7 @@ export default withRouter(class LoggedInHome extends React.Component {
sliderValue: 1, sliderValue: 1,
switchLanguage: false, switchLanguage: false,
ignoreCaps: false, ignoreCaps: false,
showNumberOfAnswers: false,
totalTestQuestions: 1, totalTestQuestions: 1,
pendingDeletions: {}, pendingDeletions: {},
}; };
@@ -200,6 +201,7 @@ export default withRouter(class LoggedInHome extends React.Component {
mode: mode, mode: mode,
limit: this.state.sliderValue, limit: this.state.sliderValue,
ignoreCaps: this.state.ignoreCaps, ignoreCaps: this.state.ignoreCaps,
showNumberOfAnswers: this.state.showNumberOfAnswers,
}).then((result) => { }).then((result) => {
const progressId = result.data; const progressId = result.data;
this.stopLoading(); this.stopLoading();
@@ -358,6 +360,12 @@ export default withRouter(class LoggedInHome extends React.Component {
}); });
} }
handleShowNumberOfAnswersChange = (event) => {
this.setState({
showNumberOfAnswers: event.target.checked,
});
}
render() { render() {
return ( return (
<div> <div>
@@ -578,8 +586,10 @@ export default withRouter(class LoggedInHome extends React.Component {
onSliderChange={this.changeSliderValue} onSliderChange={this.changeSliderValue}
switchLanguage={this.state.switchLanguage} switchLanguage={this.state.switchLanguage}
ignoreCaps={this.state.ignoreCaps} ignoreCaps={this.state.ignoreCaps}
showNumberOfAnswers={this.state.showNumberOfAnswers}
handleSwitchLanguageChange={this.handleSwitchLanguageChange} handleSwitchLanguageChange={this.handleSwitchLanguageChange}
handleIgnoreCapsChange={this.handleIgnoreCapsChange} handleIgnoreCapsChange={this.handleIgnoreCapsChange}
handleShowNumberOfAnswersChange={this.handleShowNumberOfAnswersChange}
loading={this.state.loading} loading={this.state.loading}
/> />
} }
@@ -593,8 +603,10 @@ export default withRouter(class LoggedInHome extends React.Component {
onSliderChange={this.changeSliderValue} onSliderChange={this.changeSliderValue}
switchLanguage={this.state.switchLanguage} switchLanguage={this.state.switchLanguage}
ignoreCaps={this.state.ignoreCaps} ignoreCaps={this.state.ignoreCaps}
showNumberOfAnswers={this.state.showNumberOfAnswers}
handleSwitchLanguageChange={this.handleSwitchLanguageChange} handleSwitchLanguageChange={this.handleSwitchLanguageChange}
handleIgnoreCapsChange={this.handleIgnoreCapsChange} handleIgnoreCapsChange={this.handleIgnoreCapsChange}
handleShowNumberOfAnswersChange={this.handleShowNumberOfAnswersChange}
loading={this.state.loading} loading={this.state.loading}
/> />
} }

View File

@@ -59,6 +59,7 @@ export default withRouter(class Progress extends React.Component {
startTime: null, startTime: null,
sound: false, sound: false,
ignoreCaps: false, ignoreCaps: false,
numberOfAnswers: null,
} }
constructor(props) { constructor(props) {
@@ -131,6 +132,8 @@ export default withRouter(class Progress extends React.Component {
originalTotalQuestions: [...new Set(data.questions)].length, originalTotalQuestions: [...new Set(data.questions)].length,
setComplete: data.duration !== null, setComplete: data.duration !== null,
pageLoaded: true, pageLoaded: true,
numberOfAnswers: data.showNumberOfAnswers ? 0 : null,
ignoreCaps: data.ignoreCaps,
}; };
if (data.lives) { if (data.lives) {
@@ -165,6 +168,7 @@ export default withRouter(class Progress extends React.Component {
await nextPromptRef.get().then((doc) => { await nextPromptRef.get().then((doc) => {
newState.currentPrompt = doc.data().item; newState.currentPrompt = doc.data().item;
newState.currentSound = doc.data().sound === true; newState.currentSound = doc.data().sound === true;
if (newState.numberOfAnswers === 0) newState.numberOfAnswers = doc.data().numberOfAnswers;
}).catch((error) => { }).catch((error) => {
newState.progressInaccessible = true; newState.progressInaccessible = true;
console.log(`Progress data inaccessible: ${error}`); console.log(`Progress data inaccessible: ${error}`);
@@ -356,6 +360,7 @@ export default withRouter(class Progress extends React.Component {
typo: false, typo: false,
canStartTest: true, canStartTest: true,
}; };
if (this.state.numberOfAnswers !== null && data.numberOfAnswers !== 0) newState.numberOfAnswers = data.numberOfAnswers;
if (this.state.mode === "lives") newState.lives = data.lives; if (this.state.mode === "lives") newState.lives = data.lives;
@@ -555,11 +560,17 @@ export default withRouter(class Progress extends React.Component {
limit: this.state.mode === "questions" ? this.state.progress - this.state.incorrect limit: this.state.mode === "questions" ? this.state.progress - this.state.incorrect
: this.state.mode === "lives" ? this.state.lives : this.state.mode === "lives" ? this.state.lives
: 1, : 1,
ignoreCaps: this.state.ignoreCaps,
showNumberOfAnswers: this.state.numberOfAnswers === null,
}).then((result) => { }).then((result) => {
const progressId = result.data; const progressId = result.data;
this.stopLoading(); this.stopLoading();
this.props.history.push("/progress/" + progressId); this.props.history.push("/progress/" + progressId);
this.setState({
incorrectAnswers: {},
});
this.props.logEvent("restart_test", { this.props.logEvent("restart_test", {
progress_id: progressId, progress_id: progressId,
}); });
@@ -579,6 +590,10 @@ export default withRouter(class Progress extends React.Component {
this.stopLoading(); this.stopLoading();
this.props.history.push("/progress/" + progressId); this.props.history.push("/progress/" + progressId);
this.setState({
incorrectAnswers: {},
});
this.props.logEvent("start_test_with_incorrect", { this.props.logEvent("start_test_with_incorrect", {
progress_id: progressId, progress_id: progressId,
}); });
@@ -667,6 +682,10 @@ export default withRouter(class Progress extends React.Component {
{ {
this.state.moreAnswers this.state.moreAnswers
? ?
this.state.numberOfAnswers !== null
?
`${this.state.currentCorrect.length} of ${this.state.numberOfAnswers} correct so far:`
:
"Correct so far:" "Correct so far:"
: :
"Answers:" "Answers:"
@@ -677,6 +696,12 @@ export default withRouter(class Progress extends React.Component {
)} )}
</> </>
: :
this.state.numberOfAnswers !== null
?
<h2>
{this.state.currentCorrect.length} of {this.state.numberOfAnswers} correct so far
</h2>
:
"" ""
} }
</div> </div>
@@ -823,6 +848,10 @@ export default withRouter(class Progress extends React.Component {
{ {
this.state.moreAnswers this.state.moreAnswers
? ?
this.state.numberOfAnswers !== null
?
`${this.state.currentCorrect.length} of ${this.state.numberOfAnswers} correct so far:`
:
"Correct so far:" "Correct so far:"
: :
"Answers:" "Answers:"
@@ -833,6 +862,12 @@ export default withRouter(class Progress extends React.Component {
)} )}
</> </>
: :
this.state.numberOfAnswers !== null
?
<h2>
{this.state.currentCorrect.length} of {this.state.numberOfAnswers} correct so far
</h2>
:
"" ""
} }
</div> </div>

View File

@@ -54,6 +54,7 @@ export default withRouter(class SetPage extends React.Component {
sliderValue: 1, sliderValue: 1,
switchLanguage: false, switchLanguage: false,
ignoreCaps: false, ignoreCaps: false,
showNumberOfAnswers: false,
totalTestQuestions: 1, totalTestQuestions: 1,
}; };
@@ -136,6 +137,7 @@ export default withRouter(class SetPage extends React.Component {
mode: mode, mode: mode,
limit: this.state.sliderValue, limit: this.state.sliderValue,
ignoreCaps: this.state.ignoreCaps, ignoreCaps: this.state.ignoreCaps,
showNumberOfAnswers: this.state.showNumberOfAnswers,
}).then((result) => { }).then((result) => {
const progressId = result.data; const progressId = result.data;
this.stopLoading(); this.stopLoading();
@@ -340,6 +342,12 @@ export default withRouter(class SetPage extends React.Component {
}); });
} }
handleShowNumberOfAnswersChange = (event) => {
this.setState({
showNumberOfAnswers: event.target.checked,
});
}
render() { render() {
return ( return (
<div> <div>
@@ -488,8 +496,10 @@ export default withRouter(class SetPage extends React.Component {
onSliderChange={this.changeSliderValue} onSliderChange={this.changeSliderValue}
switchLanguage={this.state.switchLanguage} switchLanguage={this.state.switchLanguage}
ignoreCaps={this.state.ignoreCaps} ignoreCaps={this.state.ignoreCaps}
showNumberOfAnswers={this.state.showNumberOfAnswers}
handleSwitchLanguageChange={this.handleSwitchLanguageChange} handleSwitchLanguageChange={this.handleSwitchLanguageChange}
handleIgnoreCapsChange={this.handleIgnoreCapsChange} handleIgnoreCapsChange={this.handleIgnoreCapsChange}
handleShowNumberOfAnswersChange={this.handleShowNumberOfAnswersChange}
loading={this.state.loading} loading={this.state.loading}
disabled={!this.state.canStartTest} disabled={!this.state.canStartTest}
/> />
@@ -504,8 +514,10 @@ export default withRouter(class SetPage extends React.Component {
onSliderChange={this.changeSliderValue} onSliderChange={this.changeSliderValue}
switchLanguage={this.state.switchLanguage} switchLanguage={this.state.switchLanguage}
ignoreCaps={this.state.ignoreCaps} ignoreCaps={this.state.ignoreCaps}
showNumberOfAnswers={this.state.showNumberOfAnswers}
handleSwitchLanguageChange={this.handleSwitchLanguageChange} handleSwitchLanguageChange={this.handleSwitchLanguageChange}
handleIgnoreCapsChange={this.handleIgnoreCapsChange} handleIgnoreCapsChange={this.handleIgnoreCapsChange}
handleShowNumberOfAnswersChange={this.handleShowNumberOfAnswersChange}
loading={this.state.loading} loading={this.state.loading}
disabled={!this.state.canStartTest} disabled={!this.state.canStartTest}
/> />