spanish-quizzer

An app to quiz you on Spanish vocabulary and verb conjugations
git clone https://git.ashermorgan.net/spanish-quizzer/
Log | Files | Refs | README

commit 912507f5a8177fee5f925f8dca32ebb4c79e3ec7
parent 4fee5a0b49db290a36d1c2d63baa1874ad1007e3
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Sat, 20 Mar 2021 16:14:17 -0700

Add conjugationColors setting

Diffstat:
Mcss/reference.css | 29+++++++++++++++++++++++++++++
Mjs/global.js | 24++++++++++++++++--------
Mjs/reference.js | 54++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mjs/settingsPage.js | 4++++
Mtests/index.html | 2++
Mtests/test.global.js | 46+++++++++++++++++++++++++++++-----------------
Atests/test.reference.js | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 219 insertions(+), 27 deletions(-)

diff --git a/css/reference.css b/css/reference.css @@ -44,6 +44,32 @@ cursor: pointer; } +/* Cell colors */ +.referenceTable td.normal { + color: inherit; +} +.referenceTable td.irregular { + color: hsl(0, 100%, 45%); +} +.referenceTable td.nonregular { + color: hsl(40, 100%, 45%); +} +.referenceTable td.regular { + color: hsl(120, 100%, 25%); +} +.dark .referenceTable td.normal { + color: inherit; +} +.dark .referenceTable td.irregular { + color: hsl(0, 100%, 55%); +} +.dark .referenceTable td.nonregular { + color: hsl(40, 100%, 55%); +} +.dark .referenceTable td.regular { + color: hsl(120, 100%, 35%); +} + /* Print styles */ @media print { body, body.dark { @@ -61,4 +87,7 @@ table { border-collapse: collapse; } + .referenceTable td { + color: #000000 !important; + } } diff --git a/js/global.js b/js/global.js @@ -27,13 +27,16 @@ function getSettings() { // Initialize settings let settings = { darkTheme: false, + conjugationColors: true, + promptType: "Text", inputType: "Text", + multiplePrompts: "Show together", + removeDuplicates: false, + onMissedPrompt: "Correct me", repeatPrompts: "Never", - multiplePrompts: "Show together", multipleAnswers: "Require all", - removeDuplicates: false, }; // Parse settings @@ -54,27 +57,32 @@ function getSettings() { } catch { } } + if ([true, false].includes(parsedSettings.conjugationColors)) { + settings.conjugationColors = parsedSettings.conjugationColors; + } + if (["Text", "Audio", "Both"].includes(parsedSettings.promptType)) { settings.promptType = parsedSettings.promptType; } if (["Text", "Voice", "Either"].includes(parsedSettings.inputType)) { settings.inputType = parsedSettings.inputType; } + if (["Show together", "Show separately", "Show one"].includes(parsedSettings.multiplePrompts)) { + settings.multiplePrompts = parsedSettings.multiplePrompts; + } + if ([true, false].includes(parsedSettings.removeDuplicates)) { + settings.removeDuplicates = parsedSettings.removeDuplicates; + } + if (["Correct me", "Tell me", "Ignore it"].includes(parsedSettings.onMissedPrompt)) { settings.onMissedPrompt = parsedSettings.onMissedPrompt; } if (["Never", "Immediately", "5 prompts later", "5 & 10 prompts later", "At the end"].includes(parsedSettings.repeatPrompts)) { settings.repeatPrompts = parsedSettings.repeatPrompts; } - if (["Show together", "Show separately", "Show one"].includes(parsedSettings.multiplePrompts)) { - settings.multiplePrompts = parsedSettings.multiplePrompts; - } if (["Require all", "Require any"].includes(parsedSettings.multipleAnswers)) { settings.multipleAnswers = parsedSettings.multipleAnswers; } - if ([true, false].includes(parsedSettings.removeDuplicates)) { - settings.removeDuplicates = parsedSettings.removeDuplicates; - } // Return parsed settings return settings; diff --git a/js/reference.js b/js/reference.js @@ -9,10 +9,55 @@ const referenceTables = Vue.component("referenceTables", { data: function() { return { category: "Choose a category", - tableData: {...{"Choose a category":[]}, ...this.data}, query: "", + conjugationColors: true, } }, + computed: { + /** + * The color classes for verb conjugation cells + */ + conjugationColorClasses: function() { + let result = []; + for (let row in this.tableData.verbs) { + result.push([]); + for (let column = 0; column < this.tableData.verbs[row].length; column++) { + // Check if cell is a type cell + if (!this.tableData.verbs[0][column].includes("Type")) { + if (column > 0) { + // Cell isn't a type cell, use color class of previous cell + result[row].push(result[row][column-1]); + } + else { + // Cell is in the first column + result[row].push("normal"); + } + } + + // Get color class + else if (this.tableData.verbs[row][column].includes("Irregular")) { + result[row].push("irregular"); + } + else if (this.tableData.verbs[row][column].includes("Regular")) { + result[row].push("regular"); + } + else if (this.tableData.verbs[row][column].includes("Stem Changing") || this.tableData.verbs[row][column].includes("Orthographic")) { + result[row].push("nonregular"); + } + else { + result[row].push("normal"); + } + } + } + return result; + }, + /** + * The data used by the table + */ + tableData: function() { + return {...{"Choose a category":[]}, ...this.data}; + }, + }, methods: { /** * Set the table height. @@ -79,6 +124,10 @@ const referenceTables = Vue.component("referenceTables", { // Remove keyup handler window.removeEventListener("keyup", this.keyup); }, + activated: function() { + // Update conjugationColors setting + this.conjugationColors = getSettings().conjugationColors; + }, template: ` <div> <div class="referenceTableControls"> @@ -95,7 +144,8 @@ const referenceTables = Vue.component("referenceTables", { <table> <tr v-for="(row, rowIndex) in data[category]" v-show="rowIndex === 0 || row.join(',').toLowerCase().includes(query.toLowerCase())"> <th v-if="rowIndex === 0" v-for="column in row">{{ column }}</th> - <td v-if="rowIndex !== 0" v-for="(column, columnIndex) in row" @click="Read(column, data[category][0][columnIndex])" :lang="getLang(data[category][0][columnIndex])">{{ column }}</td> + <td v-if="rowIndex !== 0" v-for="(column, columnIndex) in row" @click="Read(column, data[category][0][columnIndex])" + :lang="getLang(data[category][0][columnIndex])" :class="(conjugationColors && category === 'verbs') ? conjugationColorClasses[rowIndex][columnIndex] : 'normal'">{{ column }}</td> </tr> </table> </div> diff --git a/js/settingsPage.js b/js/settingsPage.js @@ -31,6 +31,10 @@ const settingsInput = Vue.component("settingsInput", { <input type="checkbox" id="settingsDarkTheme" v-model="value.darkTheme"> <label for="settingsDarkTheme">Dark Mode</label> </div> + <div> + <input type="checkbox" id="settingsConjugationColors" v-model="value.conjugationColors"> + <label for="settingsConjugationColors">Colored conjugations in reference tables</label> + </div> </div> <div class="quizzerPromptsSettings"> diff --git a/tests/index.html b/tests/index.html @@ -21,6 +21,7 @@ <script src="../js/settingsPage.js"></script> <script src="../js/filters.js"></script> <script src="../js/quizzer.js"></script> + <script src="../js/reference.js"></script> <!-- Setup tests --> <script class="mocha-init"> @@ -35,6 +36,7 @@ <script src="test.settingsPage.js"></script> <script src="test.filters.js"></script> <script src="test.quizzer.js"></script> + <script src="test.reference.js"></script> <!-- Run tests --> <script class="mocha-exec"> diff --git a/tests/test.global.js b/tests/test.global.js @@ -7,13 +7,16 @@ describe("Global.js", function() { // Set localStorage settings let expected = { darkTheme: true, + conjugationColors: true, + promptType: "Audio", inputType: "Voice", + multiplePrompts: "Show one", + removeDuplicates: true, + onMissedPrompt: "Tell me", repeatPrompts: "5 prompts later", - multiplePrompts: "Show one", multipleAnswers: "Require any", - removeDuplicates: true, }; localStorage.setItem("settings", JSON.stringify(expected)); @@ -58,13 +61,19 @@ describe("Global.js", function() { let settings = getSettings(); // Assert default settings loaded - expect(settings.promptType).to.equal("Text"); - expect(settings.inputType).to.equal("Text"); - expect(settings.onMissedPrompt).to.equal("Correct me"); - expect(settings.repeatPrompts).to.equal("Never"); - expect(settings.multiplePrompts).to.equal("Show together"); - expect(settings.multipleAnswers).to.equal("Require all"); - expect(settings.removeDuplicates).to.equal(false); + expect(settings).to.deep.equal({ + darkTheme: false, + conjugationColors: true, + + promptType: "Text", + inputType: "Text", + multiplePrompts: "Show together", + removeDuplicates: false, + + onMissedPrompt: "Correct me", + repeatPrompts: "Never", + multipleAnswers: "Require all", + }); // Restore original setting to localStorage localStorage.setItem("settings", originalValue); @@ -79,20 +88,23 @@ describe("Global.js", function() { // Set settings let settings = { darkTheme : "A", - promptType : "B", - inputType : "C", - onMissedPrompt : "D", - repeatPrompts : "E", - multiplePrompts : "F", - multipleAnswers : "G", - removeDuplicates : "H", + conjugationColors: "B", + + promptType : "C", + inputType : "D", + multiplePrompts : "E", + removeDuplicates : "F", + + onMissedPrompt : "G", + repeatPrompts : "H", + multipleAnswers : "I", } // Call setSettings setSettings(settings); // Assert localStorage setting updated - expect(localStorage.getItem("settings")).to.equal(`{"darkTheme":"A","promptType":"B","inputType":"C","onMissedPrompt":"D","repeatPrompts":"E","multiplePrompts":"F","multipleAnswers":"G","removeDuplicates":"H"}`); + expect(localStorage.getItem("settings")).to.equal(JSON.stringify(settings)); // Restore original setting to localStorage localStorage.setItem("settings", originalValue); diff --git a/tests/test.reference.js b/tests/test.reference.js @@ -0,0 +1,87 @@ +describe("ReferenceTables", function() { + let ReferenceTables; + beforeEach(function() { + // Create referenceTables component + ReferenceTables = new referenceTables(); + }); + + describe("Initial state", function() { + it("Category should be 'Choose a category'", function() { + expect(ReferenceTables.category).to.equal("Choose a category"); + }); + + it("Query should be empty", function() { + expect(ReferenceTables.query).to.equal(""); + }); + + it("ConjugationColors should be true", function() { + expect(ReferenceTables.conjugationColors).to.be.true; + }); + }); + + describe("ConjugationColorClasses property", function() { + it("Should produce correct color", function() { + // Set reference tables data + ReferenceTables.data = {verbs:[ + // Test table headers + ["English", "Infinitive","Present Type","Present Yo","Present Tú","Present Él","Present Nosotros","Present Ellos","Preterite Type","Preterite Yo","Preterite Tú","Preterite Él","Preterite Nosotros","Preterite Ellos"], + + // Test regular conjugations and orthographic conjugations + ["To read","Leer","Regular","Leo","Lees","Lee","Leemos","Leen","Orthographic","Leí","Leíste","Leyó","Leímos","Leyeron"], + + // Test stem changing conjugations and irregular conjugations + ["To want","Querer","Stem Changing","Quiero","Quieres","Quiere","Queremos","Quieren","Irregular","Quise","Quisiste","Quiso","Quisimos","Quisieron"], + + // Test irregular and stem changing conjugations + ["To have","Tener","Irregular, Stem Changing","Tengo","Tienes","Tiene","Tenemos","Tienen","Irregular","Tuve","Tuviste","Tuvo","Tuvimos","Tuvieron"], + + // Test reflexive conjugations + ["To go to bed","Acostarse","Reflexive, Stem Changing","Me acuesto","Te acuestas","Se acuesta","Nos acostamos","Se acuestan","Reflexive, Regular","Me acosté","Te acostaste","Se acostó","Nos acostamos","Se acostaron"], + ]}; + + // Assert conjugationColorClasses is correct + expect(ReferenceTables.conjugationColorClasses).to.deep.equal([ + // Test table headers + ["normal","normal","normal","normal","normal","normal","normal","normal","normal","normal","normal","normal","normal","normal"], + + // Test regular conjugations and orthographic conjugations + ["normal","normal","regular","regular","regular","regular","regular","regular","nonregular","nonregular","nonregular","nonregular","nonregular","nonregular"], + + // Test stem changing conjugations and irregular conjugations + ["normal","normal","nonregular","nonregular","nonregular","nonregular","nonregular","nonregular","irregular","irregular","irregular","irregular","irregular","irregular"], + + // Test irregular and stem changing conjugations + ["normal","normal","irregular","irregular","irregular","irregular","irregular","irregular","irregular","irregular","irregular","irregular","irregular","irregular"], + + // Test reflexive conjugations + ["normal","normal","nonregular","nonregular","nonregular","nonregular","nonregular","nonregular","regular","regular","regular","regular","regular","regular"], + ]); + }); + }); + + describe("TableData property", function() { + it("Should be calculated correctly", function() { + // Set reference tables data + let data = {verbs:[ + // Test table headers + ["English", "Infinitive","Present Type","Present Yo","Present Tú","Present Él","Present Nosotros","Present Ellos","Preterite Type","Preterite Yo","Preterite Tú","Preterite Él","Preterite Nosotros","Preterite Ellos"], + + // Test regular conjugations and orthographic conjugations + ["To read","Leer","Regular","Leo","Lees","Lee","Leemos","Leen","Orthographic","Leí","Leíste","Leyó","Leímos","Leyeron"], + + // Test stem changing conjugations and irregular conjugations + ["To want","Querer","Stem Changing","Quiero","Quieres","Quiere","Queremos","Quieren","Irregular","Quise","Quisiste","Quiso","Quisimos","Quisieron"], + + // Test irregular and stem changing conjugations + ["To have","Tener","Irregular, Stem Changing","Tengo","Tienes","Tiene","Tenemos","Tienen","Irregular","Tuve","Tuviste","Tuvo","Tuvimos","Tuvieron"], + + // Test reflexive conjugations + ["To go to bed","Acostarse","Reflexive, Stem Changing","Me acuesto","Te acuestas","Se acuesta","Nos acostamos","Se acuestan","Reflexive, Regular","Me acosté","Te acostaste","Se acostó","Nos acostamos","Se acostaron"], + ]}; + ReferenceTables.data = data; + + // Assert tableData is correct + expect(ReferenceTables.tableData).to.deep.equal({...{"Choose a category":[]}, ...data}); + }); + }); +});