From c80905dba9d331cc518624c8182191e12a9d4377 Mon Sep 17 00:00:00 2001 From: Matthew Grove Date: Sat, 23 Oct 2021 16:42:52 +0100 Subject: [PATCH] [FIX] orphaned data causing errors Set titles now stored in progress & incorrect answer records --- functions/index.js | 39 +++++++++--------- src/GroupStats.js | 91 ++++++++++++++++++++---------------------- src/MistakesHistory.js | 28 +++++-------- test/functions.test.js | 32 +++++++++++++++ 4 files changed, 108 insertions(+), 82 deletions(-) diff --git a/functions/index.js b/functions/index.js index 3efd724..f1cb2a3 100644 --- a/functions/index.js +++ b/functions/index.js @@ -172,7 +172,7 @@ exports.createProgress = functions.https.onCall((data, context) => { return db.runTransaction(async (transaction) => { const setsId = db.collection("sets"); - let allSetTitles = []; + let setTitlesDict = {}; let allVocab = []; await Promise.all(data.sets.map((setId) => { @@ -192,7 +192,7 @@ exports.createProgress = functions.https.onCall((data, context) => { throw new functions.https.HttpsError("failed-precondition", "Set must have at least one term/definition pair"); } - allSetTitles.push(setDoc.data().title); + setTitlesDict[setId] = setDoc.data().title; return setVocab.docs.map((vocabDoc) => { let newVocabData = vocabDoc; @@ -209,7 +209,18 @@ exports.createProgress = functions.https.onCall((data, context) => { const progressDocId = db .collection("progress").doc(); - const setTitle = allSetTitles.sort().slice(0, -1).join(", ") + (allSetTitles.length > 1 ? " & " : "") + allSetTitles.sort().slice(-1); + const allSetTitles = [...Object.values(setTitlesDict)].sort(); + const setTitle = allSetTitles.slice(0, -1).join(", ") + (allSetTitles.length > 1 ? " & " : "") + allSetTitles.slice(-1); + + const setIds = data.sets.sort((a, b) => { + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + return 0; + }); let dataToSet = { questions: [], @@ -223,15 +234,8 @@ exports.createProgress = functions.https.onCall((data, context) => { switch_language: switchLanguage, duration: null, mode: mode, - setIds: data.sets.sort((a, b) => { - if (a < b) { - return -1; - } - if (a > b) { - return 1; - } - return 0; - }), + setIds: setIds, + set_titles: setIds.map((setId) => setTitlesDict[setId]), typo: false, } @@ -648,6 +652,7 @@ exports.processAnswer = functions.https.onCall((data, context) => { answer: inputAnswer.trim(), switch_language: progressDoc.data().switch_language, setIds: progressDoc.data().setIds, + set_titles: progressDoc.data().set_titles, }); const totalPercentage = completedProgressDoc.data().total_percentage + (docData.correct.length / docData.questions.length * 100); @@ -661,12 +666,7 @@ exports.processAnswer = functions.https.onCall((data, context) => { transaction.set(progressDocId, docData); return returnData; }).catch(async (error) => { - const allSetTitles = await Promise.all(progressDoc.data().setIds.map((setId) => - transaction.get(db.collection("sets") - .doc(setId)) - .then((setDoc) => setDoc.data().title) - .catch((error) => "")) - ); + const allSetTitles = progressDoc.data().set_titles; const setTitle = allSetTitles.slice(0, -1).join(", ") + (allSetTitles.length > 1 ? " & " : "") + allSetTitles.sort().slice(-1); if (!isCorrectAnswer) transaction.set(incorrectAnswerDoc, { uid: uid, @@ -676,6 +676,7 @@ exports.processAnswer = functions.https.onCall((data, context) => { answer: inputAnswer.trim(), switch_language: progressDoc.data().switch_language, setIds: progressDoc.data().setIds, + set_titles: progressDoc.data().set_titles, }); const totalPercentage = docData.correct.length / docData.questions.length * 100; @@ -706,6 +707,7 @@ exports.processAnswer = functions.https.onCall((data, context) => { answer: inputAnswer.trim(), switch_language: progressDoc.data().switch_language, setIds: progressDoc.data().setIds, + set_titles: progressDoc.data().set_titles, }); returnData.nextPrompt = { @@ -729,6 +731,7 @@ exports.processAnswer = functions.https.onCall((data, context) => { answer: inputAnswer.trim(), switch_language: progressDoc.data().switch_language, setIds: progressDoc.data().setIds, + set_titles: progressDoc.data().set_titles, }); const sound = promptDoc.data().sound; diff --git a/src/GroupStats.js b/src/GroupStats.js index e1d62f2..bab4d1f 100644 --- a/src/GroupStats.js +++ b/src/GroupStats.js @@ -56,7 +56,6 @@ export default withRouter(class GroupStats extends Component { } async componentDidMount() { - let promises = []; let newState = { sets: {}, setsWithHistory: {}, @@ -77,40 +76,39 @@ export default withRouter(class GroupStats extends Component { }); if (newState.role === "owner") { - promises.push( - this.state.db - .collection("groups") - .doc(this.props.match.params.groupId) - .get() - .then(async (groupDoc) => { - document.title = `Stats | ${groupDoc.data().display_name} | Parandum`; - newState.groupName = groupDoc.data().display_name; - - return Promise.all(groupDoc.data().sets.map((setId) => { - return this.state.db.collection("sets") - .doc(setId) - .get() - .then((doc) => { - newState.sets[setId] = { - title: doc.data().title, - }; - }); - })); - }).catch((error) => { - console.log(`Can't access group: ${error}`); - newState.groupName = ""; - document.title = "Stats | Parandum"; - }) - ); + await this.state.db + .collection("groups") + .doc(this.props.match.params.groupId) + .get() + .then(async (groupDoc) => { + document.title = `Stats | ${groupDoc.data().display_name} | Parandum`; + newState.groupName = groupDoc.data().display_name; + + return Promise.all(groupDoc.data().sets.map((setId) => { + return this.state.db.collection("sets") + .doc(setId) + .get() + .then((doc) => { + newState.sets[setId] = { + title: doc.data().title, + }; + }); + })); + }).catch((error) => { + console.log(`Can't access group: ${error}`); + newState.groupName = ""; + document.title = "Stats | Parandum"; + }); - promises.push( - this.state.db.collection("incorrect_answers") - .where("groups", "array-contains", this.props.match.params.groupId) - .orderBy("term", "asc") - .get() - .then((querySnapshot) => { - let incorrectAnswers = []; - querySnapshot.docs.map((doc, index, array) => { + const groupSetIds = Object.keys(newState.sets); + if (groupSetIds.length > 0) await this.state.db.collection("incorrect_answers") + .where("groups", "array-contains", this.props.match.params.groupId) + .orderBy("term", "asc") + .get() + .then((querySnapshot) => { + let incorrectAnswers = []; + querySnapshot.docs.map((doc, index, array) => { + if (doc.data().setIds.some(item => groupSetIds.includes(item))) { if (index === 0 || doc.data().term !== array[index - 1].data().term || doc.data().definition !== array[index - 1].data().definition) { incorrectAnswers.push({ term: doc.data().term, @@ -145,19 +143,18 @@ export default withRouter(class GroupStats extends Component { doc.data().setIds.map((setId) => newState.setsWithHistory[setId] = true); return true; - }); - newState.incorrectAnswers = incorrectAnswers.sort((a, b) => b.count + b.switchedCount - a.count - a.switchedCount); - newState.filteredIncorrectAnswers = newState.incorrectAnswers; - newState.totalIncorrect = querySnapshot.docs.length; - }) - .catch((error) => { - newState.incorrectAnswers = []; - newState.totalIncorrect = 0; - console.log(`Couldn't get group progress: ${error}`); - }) - ); - - await Promise.all(promises); + } + return false; + }); + newState.incorrectAnswers = incorrectAnswers.sort((a, b) => b.count + b.switchedCount - a.count - a.switchedCount); + newState.filteredIncorrectAnswers = newState.incorrectAnswers; + newState.totalIncorrect = querySnapshot.docs.length; + }) + .catch((error) => { + newState.incorrectAnswers = []; + newState.totalIncorrect = 0; + console.log(`Couldn't get group progress: ${error}`); + }); } this.setState(newState); diff --git a/src/MistakesHistory.js b/src/MistakesHistory.js index 64c8bbd..79ea246 100644 --- a/src/MistakesHistory.js +++ b/src/MistakesHistory.js @@ -132,14 +132,17 @@ export default class IncorrectHistory extends Component { } } - doc.data().setIds.map((setId) => subPromises.push( - this.state.db.collection("sets") - .doc(setId) - .get() - .then((doc) => - newState.setsWithHistory[setId] = doc.data().title - ) - )); + // doc.data().setIds.map((setId) => subPromises.push( + // this.state.db.collection("sets") + // .doc(setId) + // .get() + // .then((doc) => + // newState.setsWithHistory[setId] = doc.data().title + // ) + // )); + doc.data().setIds.map((setId, setIndex) => + newState.setsWithHistory[setId] = doc.data().set_titles[setIndex] + ); return true; }); @@ -166,7 +169,6 @@ export default class IncorrectHistory extends Component { setIds: doc.data().setIds, }) ); - console.log(newState.progressHistory); newState.totalTests = newState.progressHistory.length; }) ); @@ -230,14 +232,6 @@ export default class IncorrectHistory extends Component { return newVocabItem; }); - console.log(this.state.progressHistory - .filter((progressItem) => - this.arraysHaveSameMembers(progressItem.setIds, [selectedSet.value]) || - ( - this.state.includeCompoundTests && - progressItem.setIds.includes(selectedSet.value) - ) - )); this.setState({ filteredIncorrectAnswers: filteredIncorrectAnswers, selectedSet: selectedSet, diff --git a/test/functions.test.js b/test/functions.test.js index a939e06..b2e7746 100644 --- a/test/functions.test.js +++ b/test/functions.test.js @@ -147,6 +147,7 @@ describe("Parandum Cloud Functions", function () { assert.strictEqual(snapAfter.progress, 0); assert.deepStrictEqual(snapAfter.setIds, [setOne]); assert.strictEqual(snapAfter.set_title, setOne); + assert.deepStrictEqual(snapAfter.set_titles, [setOne]); assert.notStrictEqual(snapAfter.start_time, null); assert.strictEqual(snapAfter.switch_language, false); assert.strictEqual(snapAfter.uid, userOne); @@ -232,6 +233,7 @@ describe("Parandum Cloud Functions", function () { assert.strictEqual(snapAfter.progress, 0); assert.deepStrictEqual(snapAfter.setIds, [setOne, setTwo]); assert.strictEqual(snapAfter.set_title, `${setOne} & ${setTwo}`); + assert.deepStrictEqual(snapAfter.set_titles, [setOne, setTwo]); assert.notStrictEqual(snapAfter.start_time, null); assert.strictEqual(snapAfter.switch_language, false); assert.strictEqual(snapAfter.uid, userOne); @@ -287,6 +289,7 @@ describe("Parandum Cloud Functions", function () { assert.strictEqual(snapAfter.progress, 0); assert.deepStrictEqual(snapAfter.setIds, [setOne]); assert.strictEqual(snapAfter.set_title, setOne); + assert.deepStrictEqual(snapAfter.set_titles, [setOne]); assert.notStrictEqual(snapAfter.start_time, null); assert.strictEqual(snapAfter.switch_language, false); assert.strictEqual(snapAfter.uid, userOne); @@ -379,6 +382,7 @@ describe("Parandum Cloud Functions", function () { progressVocabTwo ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -483,6 +487,7 @@ describe("Parandum Cloud Functions", function () { progressVocabTwo ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -502,6 +507,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -534,6 +540,7 @@ describe("Parandum Cloud Functions", function () { assert.notStrictEqual(snapAfterCorrectData.duration, null); assert.strictEqual(snapAfterCorrectData.progress, 3); assert.strictEqual(snapAfterCorrectData.set_title, setOne); + assert.deepStrictEqual(snapAfterCorrectData.set_titles, [setOne]); assert.strictEqual(snapAfterCorrectData.start_time, 1627308670962); assert.strictEqual(snapAfterCorrectData.switch_language, false); assert.strictEqual(snapAfterCorrectData.uid, userOne); @@ -554,6 +561,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -638,6 +646,7 @@ describe("Parandum Cloud Functions", function () { progressVocabTwo ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -725,6 +734,7 @@ describe("Parandum Cloud Functions", function () { progressVocabTwo ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -750,6 +760,7 @@ describe("Parandum Cloud Functions", function () { progressVocabTwo ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -769,6 +780,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -805,6 +817,7 @@ describe("Parandum Cloud Functions", function () { assert.notStrictEqual(snapAfterCorrectData.duration, null); assert.strictEqual(snapAfterCorrectData.progress, 3); assert.strictEqual(snapAfterCorrectData.set_title, setOne); + assert.deepStrictEqual(snapAfterCorrectData.set_titles, [setOne]); assert.strictEqual(snapAfterCorrectData.start_time, 1627308670962); assert.strictEqual(snapAfterCorrectData.switch_language, false); assert.strictEqual(snapAfterCorrectData.uid, userOne); @@ -826,6 +839,7 @@ describe("Parandum Cloud Functions", function () { progressVocabTwo ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -886,6 +900,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -936,6 +951,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -984,6 +1000,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1034,6 +1051,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1084,6 +1102,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1134,6 +1153,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1182,6 +1202,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1232,6 +1253,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1282,6 +1304,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1334,6 +1357,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1390,6 +1414,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: `${setOne}__${setTwo}`, + set_titles: [setOne, setTwo], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1449,6 +1474,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: `${setOne}__${setTwo}`, + set_titles: [setOne, setTwo], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1521,6 +1547,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1563,6 +1590,7 @@ describe("Parandum Cloud Functions", function () { switch_language: false, answer: incorrectAnswer, setIds: [setOne], + set_titles: [setOne], }); }); @@ -1590,6 +1618,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1641,6 +1670,7 @@ describe("Parandum Cloud Functions", function () { switch_language: false, answer: incorrectAnswer, setIds: [setOne], + set_titles: [setOne], }); }); @@ -1663,6 +1693,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne, @@ -1719,6 +1750,7 @@ describe("Parandum Cloud Functions", function () { progressVocabOne ], set_title: setOne, + set_titles: [setOne], start_time: 1627308670962, switch_language: false, uid: userOne,