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:
@@ -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;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user