Bug: fixed korean empty string issue

Feat: combined Answer and Diff buttons into a single diff button
This commit is contained in:
Richard Wong 2024-08-19 16:21:54 +09:00
parent 32363c9d7b
commit 31772fec80
Signed by: richard
GPG Key ID: 72948FBB6D359A6D
5 changed files with 171 additions and 1599 deletions

View File

@ -18,5 +18,67 @@
"input_chapter_title": "Input Chapter Title:", "input_chapter_title": "Input Chapter Title:",
"input_title": "Input Title:", "input_title": "Input Title:",
"input_verse": "Input Verse:" "input_verse": "Input Verse:"
},
"nodes": [
{
"value": "loa",
"label": "Lessons on Assurance"
},
{
"value": "tms60",
"label": "TMS60",
"children": [
{ "value": "tms-60-pack-a", "label": "Living the New Life" },
{ "value": "tms-60-pack-b", "label": "Proclaiming Christ" },
{ "value": "tms-60-pack-c", "label": "Reliance on God's Resources" },
{ "value": "tms-60-pack-d", "label": "Being Christ's Disciple" },
{ "value": "tms-60-pack-e", "label": "Growth in Christlikeness" }
]
},
{
"value": "dep-1",
"label": "DEP 1"
},
{
"value": "dep-2",
"label": "DEP 2",
"children": [
{ "value": "dep-2-part-a", "label": "Why do we have Quiet Time?" },
{ "value": "dep-2-part-b", "label": "What is Quiet Time?" },
{ "value": "dep-2-part-c", "label": "Examples of Quiet Time" }
]
},
{
"value": "dep-3",
"label": "DEP 3",
"children": [
{ "value": "dep-3-part-a", "label": "Authority of the Word" },
{ "value": "dep-3-part-b", "label": "value of the Word" },
{ "value": "dep-3-part-c", "label": "Attitude to the Word" },
{ "value": "dep-3-part-d", "label": "How to take in the Word (Word Hand Illustration)" }
]
},
{
"value": "dep-4",
"label": "DEP 4",
"children": [
{ "value": "dep-4-part-a", "label": "Command of Prayer" },
{ "value": "dep-4-part-b", "label": "Promises and Blessings of Prayer" },
{ "value": "dep-4-part-c", "label": "Conditions for Answered Prayer" },
{ "value": "dep-4-part-d", "label": "Examples of Prayer" },
{ "value": "dep-4-part-e", "label": "Prayer Hand Illustration" }
]
},
{
"value": "dep-5",
"label": "DEP 5",
"children": [
{ "value": "dep-5-part-a", "label": "Foundation of Christian Fellowship" },
{ "value": "dep-5-part-b", "label": "Importance of fellowship" },
{ "value": "dep-5-part-c", "label": "Essentials of fellowship" },
{ "value": "dep-5-part-d", "label": "Attitude of fellowship" },
{ "value": "dep-5-part-e", "label": "Problem solving in fellowship" }
]
} }
]
} }

View File

@ -1,11 +1,11 @@
{ {
"main": { "main": {
"title": "Scripture Memory Tester (kr)", "title": "성경 암송 앱",
"pick_lang": "Pick Language (kr)", "pick_lang": "언어 선택",
"pick_num_verses": "Pick Number of Verses: (kr)", "pick_num_verses": "암송 구절 선택:",
"num_verses_tested": "Number of Verses Tested:", "num_verses_tested": "구절 수 선택:",
"note_num_verses": "(It will only give you as many verses as there are in selected packs)", "note_num_verses": "(It will only give you as many verses as there are in selected packs)",
"set_shuffle": "Set Shuffle:", "set_shuffle": "무작위 설정:",
"note_set_shuffle": "(Otherwise cards will appear in sequential order)", "note_set_shuffle": "(Otherwise cards will appear in sequential order)",
"hide_reference": "Set Hide Reference:", "hide_reference": "Set Hide Reference:",
"note_hide_reference": "(If you also want to test the verse reference)", "note_hide_reference": "(If you also want to test the verse reference)",
@ -18,5 +18,11 @@
"input_chapter_title": "Input Chapter Title: (KR)", "input_chapter_title": "Input Chapter Title: (KR)",
"input_title": "Input Title: (KR)", "input_title": "Input Title: (KR)",
"input_verse": "Input Verse: (KR)" "input_verse": "Input Verse: (KR)"
},
"nodes": [
{
"value": "loa",
"label": "Lessons on Assurance"
} }
]
} }

View File

@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next';
import logo from './assets/droplet.svg'; import logo from './assets/droplet.svg';
import { Suspense } from "react"; import { Suspense } from "react";
const GenerateTestList = ({ VerseData, packs, testCount, toShuffle, toHideReference}) => { const GenerateTestList = ({ VerseData, packs, testCount, toShuffle, toHideReference, translate}) => {
let testList = packs.reduce( let testList = packs.reduce(
// grab all elements included checked in "packs" // grab all elements included checked in "packs"
(accumulator, currentValue) => accumulator.concat(VerseData[currentValue]), (accumulator, currentValue) => accumulator.concat(VerseData[currentValue]),
@ -22,84 +22,28 @@ const GenerateTestList = ({ VerseData, packs, testCount, toShuffle, toHideRefere
); );
testList = toShuffle ? _.sample(testList, testCount) : _.first(testList, testCount); testList = toShuffle ? _.sample(testList, testCount) : _.first(testList, testCount);
return ( return (
<ArrayTester array={testList} toHideReference={toHideReference} /> <ArrayTester
array={testList}
toHideReference={toHideReference}
translate={translate}
/>
) )
} }
const ArrayTester = ({ array, toHideReference }) => { const ArrayTester = ({ array, toHideReference, translate}) => {
const list = array.map((element) => ( const list = array.map((element) => (
// key needs to be unique; chose 3 elements that will separate all elements // key needs to be unique; chose 3 elements that will separate all elements
<VerseValidator key={element.pack + element.title + element.reference} <VerseValidator
element={element} toHideReference={toHideReference} /> key={element.pack + element.title + element.reference}
element={element}
toHideReference={toHideReference}
t={translate} // this passes the t i18 object to the function
/>
)) ))
return list return list
} }
const CheckboxWidget = ({nodes, checked, expanded, setChecked, setExpanded}) => {
const nodes = [
{
value: "loa",
label: "Lessons on Assurance",
},
{
value: "tms60",
label: "TMS60",
children: [
{ value: "tms-60-pack-a", label: "Living the New Life" },
{ value: "tms-60-pack-b", label: "Proclaiming Christ" },
{ value: "tms-60-pack-c", label: "Reliance on God's Resources" },
{ value: "tms-60-pack-d", label: "Being Christ's Disciple" },
{ value: "tms-60-pack-e", label: "Growth in Christlikeness" }
],
},
{
value: "dep-1",
label: "DEP 1",
},
{
value: "dep-2",
label: "DEP 2",
children: [
{ value: "dep-2-part-a", label: "Why do we have Quiet Time?" },
{ value: "dep-2-part-b", label: "What is Quiet Time?" },
{ value: "dep-2-part-c", label: "Examples of Quiet Time" }
],
},
{
value: "dep-3",
label: "DEP 3",
children: [
{ value: "dep-3-part-a", label: "Authority of the Word" },
{ value: "dep-3-part-b", label: "Value of the Word" },
{ value: "dep-3-part-c", label: "Attitude to the Word" },
{ value: "dep-3-part-d", label: "How to take in the Word (Word Hand Illustration)" }
],
},
{
value: "dep-4",
label: "DEP 4",
children: [
{ value: "dep-4-part-a", label: "Command of Prayer" },
{ value: "dep-4-part-b", label: "Promises and Blessings of Prayer" },
{ value: "dep-4-part-c", label: "Conditions for Answered Prayer" },
{ value: "dep-4-part-d", label: "Examples of Prayer" },
{ value: "dep-4-part-e", label: "Prayer Hand Illustration" }
],
},
{
value: "dep-5",
label: "DEP 5",
children: [
{ value: "dep-5-part-a", label: "Foundation of Christian Fellowship" },
{ value: "dep-5-part-b", label: "Importance of fellowship" },
{ value: "dep-5-part-c", label: "Essentials of fellowship" },
{ value: "dep-5-part-d", label: "Attitude of fellowship" },
{ value: "dep-5-part-e", label: "Problem solving in fellowship" }
],
},
];
const CheckboxWidget = ({checked, expanded, setChecked, setExpanded}) => {
return ( return (
<div className="CheckboxTree"> <div className="CheckboxTree">
<CheckboxTree <CheckboxTree
@ -116,7 +60,7 @@ const CheckboxWidget = ({checked, expanded, setChecked, setExpanded}) => {
// loadCustomData // loadCustomData
const loadCustomData = (language) => { const loadCustomData = (language) => {
let data; let data;
console.log(language) // console.log(language)
switch (language) { switch (language) {
case 'kn': case 'kn':
data = fullVerseData.kn; data = fullVerseData.kn;
@ -232,7 +176,7 @@ function Page() {
<p>{t('main.note_num_verses')}</p> <p>{t('main.note_num_verses')}</p>
<h2> <h2>
Set Shuffle: {t('main.set_shuffle')}
<input <input
type="checkbox" type="checkbox"
checked={toShuffle} checked={toShuffle}
@ -260,6 +204,7 @@ function Page() {
<h2>{t('main.pick_pack')}</h2> <h2>{t('main.pick_pack')}</h2>
<CheckboxWidget <CheckboxWidget
nodes={t('nodes', { returnObjects: true })}
checked={checked} checked={checked}
expanded={expanded} expanded={expanded}
setChecked={setChecked} setChecked={setChecked}
@ -282,6 +227,7 @@ function Page() {
testCount={testCount} testCount={testCount}
toShuffle={toShuffle} toShuffle={toShuffle}
toHideReference={toHideReference} toHideReference={toHideReference}
translate={t}
/> />
<hr /> <hr />

View File

@ -1,14 +1,10 @@
import { useState } from "react"; import { useState } from "react";
import "./VerseValidator.css"; import "./VerseValidator.css";
import { StringDiff } from "react-string-diff"; import { StringDiff } from "react-string-diff";
import { useTranslation } from 'react-i18next';
// function to render and handle logic of each of the cells // function to render and handle logic of each of the cells
const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse } , toHideReference}) => { // useful use of destructuring here const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse } , toHideReference, t}) => { // useful use of destructuring here
// setup i18 for function
const { t } = useTranslation();
const [inputReference, setReference] = useState('') const [inputReference, setReference] = useState('')
const [referenceBool, setReferenceBool] = useState(false) const [referenceBool, setReferenceBool] = useState(false)
@ -25,16 +21,15 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
// function to check correctness of verse input // function to check correctness of verse input
// so far only perform checking on full spelling of reference names // so far only perform checking on full spelling of reference names
const referenceChange = (e) => { const referenceChange = (e) => {
const value = e.target.value; const value = e.target.value;
const string1 = String(value) const string1 = String(value)
.replace(/\s+/g, "") .replace(/\s+/g, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
const string2 = String(reference) const string2 = String(reference)
.replace(/\s+/g, "") .replace(/\s+/g, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
const bool = (string1 === string2); const bool = (string1 === string2);
setReference(value); setReference(value);
@ -47,13 +42,15 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
let string1 = value; let string1 = value;
let string2 = verse; let string2 = verse;
string1 = String(string1) string1 = String(string1)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "")
.replace(/\s+/g, "") .replace(/\s+/g, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
string2 = String(string2) string2 = String(string2)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "")
.replace(/\s+/g, "") .replace(/\s+/g, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
const bool = string1 === string2; const bool = string1 === string2;
@ -67,13 +64,16 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
let string1 = value; let string1 = value;
let string2 = title; let string2 = title;
string1 = String(string1) string1 = String(string1)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "") // Removes punctuation and symbols
.replace(/\s+/g, "") .replace(/\s+/g, "") // Removes all whitespace
.toLowerCase(); .toLowerCase()
.normalize("NFC"); // Normalizes to NFC form
string2 = String(string2) string2 = String(string2)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "")
.replace(/\s+/g, "") .replace(/\s+/g, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
const bool = string1 === string2; const bool = string1 === string2;
@ -84,17 +84,22 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
{/* function to check correctness of chapter title input */} {/* function to check correctness of chapter title input */}
const chapterTitleChange = (e) => { const chapterTitleChange = (e) => {
const value = e.target.value; const value = e.target.value;
let string1 = value; let string1 = value;
let string2 = chapterTitle; let string2 = chapterTitle;
string1 = String(string1) string1 = String(string1)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "")
.replace(/\s+/g, "") .replace(/\s+/g, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
string2 = String(string2) string2 = String(string2)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "")
.replace(/\s+/g, "") .replace(/\s+/g, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
const bool = string1 === string2; const bool = string1 === string2;
@ -104,12 +109,27 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
const DiffViewer = ({oldValue, newValue}) => { const DiffViewer = ({oldValue, newValue}) => {
const string1 = String(oldValue) const string1 = String(oldValue)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
const string2 = String(newValue) const string2 = String(newValue)
.replace(/[^\w\s]/g, "") .replace(/[\p{P}\p{S}]/gu, "")
.toLowerCase(); .toLowerCase()
.normalize("NFC");
return (<StringDiff oldValue={string1} newValue={string2} diffMethod="diffWords" />)
}
const DiffViewerStrict = ({oldValue, newValue}) => {
const string1 = String(oldValue)
.toLowerCase()
.normalize("NFC");
const string2 = String(newValue)
.toLowerCase()
.normalize("NFC");
return (<StringDiff oldValue={string1} newValue={string2} diffMethod="diffWords" />) return (<StringDiff oldValue={string1} newValue={string2} diffMethod="diffWords" />)
} }
@ -179,29 +199,25 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
{/* button to toggle show answer*/} {/* button to toggle show answer*/}
<div className="answer-button-box"> <div className="answer-button-box">
<button onClick={() => setHintBool(!hintBool)}>Show Answer:</button> {/* <button onClick={() => setHintBool(!hintBool)}>Show Answer:</button> */}
<button onClick={() => setDiffBool(!diffBool)}>Show Diff:</button> <button onClick={() => setDiffBool(!diffBool)}>Show Answer:</button>
</div> </div>
{/* This shows the answers*/}
{hintBool && (
<div className="answer-box">
<h3>Answers</h3>
<p>Reference:<br />{reference}</p>
{chapterTitle && (
<>
<p>ChapterTitle<br />{chapterTitle}</p>
</>
)}
<p>Title:<br />{title}</p>
<p>Verse:<br />{verse}</p>
</div>
)}
{/* This shows the difference between given and input answers*/} {/* This shows the difference between given and input answers*/}
{diffBool && ( {diffBool && (
<div className="diff-box"> <div className="diff-box">
<h3>Differences</h3> <h3>Differences</h3>
<p></p>
<div>
Reference:
<DiffViewerStrict
oldValue={reference}
newValue={inputReference}
/>
</div>
<p></p>
{chapterTitle && ( {chapterTitle && (
<div> <div>
ChapterTitle: ChapterTitle:
@ -211,13 +227,23 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
/> />
</div> </div>
)} )}
<p></p> <p></p>
<div> <div>
Title: <DiffViewer oldValue={title} newValue={inputTitle} /> Title:
<DiffViewer
oldValue={title}
newValue={inputTitle}
/>
</div> </div>
<p></p> <p></p>
<div> <div>
Verse: <DiffViewer oldValue={verse} newValue={inputVerse} /> Verse:
<DiffViewer
oldValue={verse}
newValue={inputVerse}
/>
</div> </div>
</div> </div>
)} )}

File diff suppressed because it is too large Load Diff