mirror of
https://gitlab.com/MrFry/qmining-data-editor
synced 2025-04-01 20:24:01 +02:00
possible answers fix, next path fix, prettier format
This commit is contained in:
parent
e17bbe6402
commit
70b53e89aa
9 changed files with 377 additions and 360 deletions
|
@ -1,3 +1,3 @@
|
|||
module.exports = {
|
||||
basePath: '/data-editor',
|
||||
basePath: '/dataeditor',
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ import React from 'react'
|
|||
import styles from './LoadingIndicator.module.css'
|
||||
|
||||
export default function LoadingIndicator() {
|
||||
return (
|
||||
<div className={styles.loadContainer}>
|
||||
<div className={styles.load} />
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div className={styles.loadContainer}>
|
||||
<div className={styles.load} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,125 +5,130 @@ import styles from './question.module.css'
|
|||
const overflowLength = 140
|
||||
|
||||
export default function Question({ question, onChange, index }) {
|
||||
// FIXME: focus change when input changes to textarea
|
||||
const possibleAnswers =
|
||||
question.possibleAnswers || question.data.possibleAnswers
|
||||
// FIXME: focus change when input changes to textarea
|
||||
const possibleAnswers =
|
||||
question.possibleAnswers || question.data.possibleAnswers
|
||||
|
||||
return (
|
||||
<div className={styles.questionContainer}>
|
||||
{question.Q && question.Q.length > overflowLength ? (
|
||||
<textarea
|
||||
placeholder="Kérdés..."
|
||||
value={question.Q}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
Q: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
placeholder="Kérdés..."
|
||||
type="text"
|
||||
value={question.Q}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
Q: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{question.A && question.A.length > overflowLength ? (
|
||||
<textarea
|
||||
placeholder="Helyes válasz..."
|
||||
value={question.A}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
A: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
placeholder="Helyes válasz..."
|
||||
type="text"
|
||||
value={question.A}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
A: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{possibleAnswers && possibleAnswers.length > 0 ? (
|
||||
<>
|
||||
<div className={styles.text}>Lehetséges válaszok:</div>
|
||||
<div className={styles.possibleAnswers}>
|
||||
{possibleAnswers.map((possibleAnswer, i) => {
|
||||
// {"text":"a. Kétismeretlenes egyenletrendszert használunk.",
|
||||
// "selectedByUser":true}
|
||||
|
||||
const pa =
|
||||
typeof possibleAnswer === 'string'
|
||||
? possibleAnswer
|
||||
: possibleAnswer.text
|
||||
|
||||
return (
|
||||
<div key={i}>
|
||||
<div>
|
||||
<input
|
||||
onChange={() => {
|
||||
return (
|
||||
<div className={styles.questionContainer}>
|
||||
{question.Q && question.Q.length > overflowLength ? (
|
||||
<textarea
|
||||
placeholder="Kérdés..."
|
||||
value={question.Q}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
A: pa,
|
||||
...question,
|
||||
Q: e.target.value,
|
||||
})
|
||||
}}
|
||||
checked={pa === question.A}
|
||||
value={pa}
|
||||
type="radio"
|
||||
name={`possiblea${index ? index : ''}`}
|
||||
/>
|
||||
<span>{pa}</span>
|
||||
</div>
|
||||
<span
|
||||
onClick={() => {
|
||||
const newPossibleAnswers = possibleAnswers.filter(
|
||||
(pa, j) => {
|
||||
return j !== i
|
||||
}
|
||||
)
|
||||
// FIXME: 2 possible answers?
|
||||
onChange({
|
||||
...question,
|
||||
data: {
|
||||
...question.data,
|
||||
possibleAnswers: newPossibleAnswers,
|
||||
},
|
||||
possibleAnswers: newPossibleAnswers,
|
||||
})
|
||||
}}
|
||||
className={styles.delete}
|
||||
>
|
||||
Törlés
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
<input
|
||||
type="text"
|
||||
value={JSON.stringify(question.data)}
|
||||
name="data"
|
||||
onChange={(e) => {
|
||||
console.log(e.target.value)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
placeholder="Kérdés..."
|
||||
type="text"
|
||||
value={question.Q}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
Q: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{question.A && question.A.length > overflowLength ? (
|
||||
<textarea
|
||||
placeholder="Helyes válasz..."
|
||||
value={question.A}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
A: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
placeholder="Helyes válasz..."
|
||||
type="text"
|
||||
value={question.A}
|
||||
onChange={(e) => {
|
||||
onChange({
|
||||
...question,
|
||||
A: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{possibleAnswers && possibleAnswers.length > 0 ? (
|
||||
<>
|
||||
<div className={styles.text}>Lehetséges válaszok:</div>
|
||||
<div className={styles.possibleAnswers}>
|
||||
{possibleAnswers.map((possibleAnswer, i) => {
|
||||
// {"text":"a. Kétismeretlenes egyenletrendszert használunk.",
|
||||
// "selectedByUser":true}
|
||||
|
||||
const pa =
|
||||
typeof possibleAnswer === 'string'
|
||||
? possibleAnswer
|
||||
: possibleAnswer.val
|
||||
|
||||
return (
|
||||
<div key={i}>
|
||||
<div>
|
||||
<input
|
||||
onChange={() => {
|
||||
onChange({
|
||||
...question,
|
||||
A: pa,
|
||||
})
|
||||
}}
|
||||
checked={pa === question.A}
|
||||
value={pa}
|
||||
type="radio"
|
||||
name={`possiblea${
|
||||
index ? index : ''
|
||||
}`}
|
||||
/>
|
||||
<span>{pa}</span>
|
||||
</div>
|
||||
<span
|
||||
onClick={() => {
|
||||
const newPossibleAnswers =
|
||||
possibleAnswers.filter(
|
||||
(pa, j) => {
|
||||
return j !== i
|
||||
}
|
||||
)
|
||||
// FIXME: 2 possible answers?
|
||||
onChange({
|
||||
...question,
|
||||
data: {
|
||||
...question.data,
|
||||
possibleAnswers:
|
||||
newPossibleAnswers,
|
||||
},
|
||||
possibleAnswers:
|
||||
newPossibleAnswers,
|
||||
})
|
||||
}}
|
||||
className={styles.delete}
|
||||
>
|
||||
Törlés
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
<input
|
||||
type="text"
|
||||
value={JSON.stringify(question.data)}
|
||||
name="data"
|
||||
onChange={(e) => {
|
||||
console.log(e.target.value)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,80 +6,86 @@ import styles from './Questions.module.css'
|
|||
import commonStyles from '../commonStyles.module.css'
|
||||
|
||||
class Questions extends PureComponent {
|
||||
render() {
|
||||
const { subjs, onChange } = this.props
|
||||
render() {
|
||||
const { subjs, onChange } = this.props
|
||||
|
||||
return (
|
||||
<div>
|
||||
{subjs.map((subj) => {
|
||||
return (
|
||||
<div key={subj.Name}>
|
||||
<div className={styles.subjName}>{subj.Name}</div>
|
||||
{subj.Questions.map((qo, i) => {
|
||||
const question = qo.q
|
||||
const unsaved = qo.unsaved
|
||||
return (
|
||||
<div>
|
||||
{subjs.map((subj) => {
|
||||
return (
|
||||
<div key={subj.Name}>
|
||||
<div className={styles.subjName}>{subj.Name}</div>
|
||||
{subj.Questions.map((qo, i) => {
|
||||
const question = qo.q
|
||||
const unsaved = qo.unsaved
|
||||
|
||||
return (
|
||||
<React.Fragment key={i}>
|
||||
<hr />
|
||||
<div className={`${unsaved ? styles.unsaved : ''}`}>
|
||||
<Question
|
||||
index={`${subj.Name}_${i}`}
|
||||
question={question}
|
||||
onChange={(newVal) => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'edit',
|
||||
newVal: newVal,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<div className={commonStyles.actions}>
|
||||
<div
|
||||
onClick={() => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'reset',
|
||||
})
|
||||
}}
|
||||
>
|
||||
Visszaállítás
|
||||
return (
|
||||
<React.Fragment key={i}>
|
||||
<hr />
|
||||
<div
|
||||
className={`${
|
||||
unsaved ? styles.unsaved : ''
|
||||
}`}
|
||||
>
|
||||
<Question
|
||||
index={`${subj.Name}_${i}`}
|
||||
question={question}
|
||||
onChange={(newVal) => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'edit',
|
||||
newVal: newVal,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={commonStyles.actions}
|
||||
>
|
||||
<div
|
||||
onClick={() => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'reset',
|
||||
})
|
||||
}}
|
||||
>
|
||||
Visszaállítás
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'save',
|
||||
})
|
||||
}}
|
||||
>
|
||||
Mentés
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'delete',
|
||||
})
|
||||
}}
|
||||
>
|
||||
Törlés
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'save',
|
||||
})
|
||||
}}
|
||||
>
|
||||
Mentés
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
onChange({
|
||||
index: i,
|
||||
subjName: subj.Name,
|
||||
type: 'delete',
|
||||
})
|
||||
}}
|
||||
>
|
||||
Törlés
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
})}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Questions
|
||||
|
|
|
@ -6,96 +6,98 @@ import styles from './subject.module.css'
|
|||
import commonStyles from '../commonStyles.module.css'
|
||||
|
||||
function DeletedQuestion({ reset }) {
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.deletedQuestion}>Törölt kérdés</div>
|
||||
<div className={commonStyles.actions}>
|
||||
<div
|
||||
onClick={() => {
|
||||
reset()
|
||||
}}
|
||||
>
|
||||
Visszaállítás
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.deletedQuestion}>Törölt kérdés</div>
|
||||
<div className={commonStyles.actions}>
|
||||
<div
|
||||
onClick={() => {
|
||||
reset()
|
||||
}}
|
||||
>
|
||||
Visszaállítás
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export default function Subject(props) {
|
||||
const {
|
||||
subj,
|
||||
unsavedIndexes,
|
||||
deletedIndexes,
|
||||
editedIndexes,
|
||||
resetQuestion,
|
||||
handleQuestionChange,
|
||||
saveQuestion,
|
||||
deleteQuestion,
|
||||
} = props
|
||||
const {
|
||||
subj,
|
||||
unsavedIndexes,
|
||||
deletedIndexes,
|
||||
editedIndexes,
|
||||
resetQuestion,
|
||||
handleQuestionChange,
|
||||
saveQuestion,
|
||||
deleteQuestion,
|
||||
} = props
|
||||
|
||||
if (subj) {
|
||||
return (
|
||||
<div className={styles.questionContainer}>
|
||||
{subj.Questions.map((question, i) => {
|
||||
// FIXME: list edited questions first?
|
||||
const unsaved = unsavedIndexes.includes(i)
|
||||
const edited = editedIndexes.includes(i)
|
||||
const deleted = deletedIndexes.includes(i)
|
||||
return (
|
||||
<React.Fragment key={i}>
|
||||
<hr />
|
||||
{deleted ? (
|
||||
<DeletedQuestion
|
||||
reset={() => {
|
||||
resetQuestion(i)
|
||||
}}
|
||||
index={i}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={`${unsaved ? styles.unsaved : ''} ${
|
||||
edited ? styles.edited : ''
|
||||
}`}
|
||||
>
|
||||
<Question
|
||||
index={i}
|
||||
onChange={(newq) => {
|
||||
handleQuestionChange(newq, i)
|
||||
}}
|
||||
question={question}
|
||||
/>
|
||||
<div className={commonStyles.actions}>
|
||||
<div
|
||||
onClick={() => {
|
||||
resetQuestion(i)
|
||||
}}
|
||||
>
|
||||
Visszaállítás
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
saveQuestion(i)
|
||||
}}
|
||||
>
|
||||
{edited ? 'Kérdés mentve' : 'Kérdés mentése'}
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
deleteQuestion(i)
|
||||
}}
|
||||
>
|
||||
Kérdés törlése
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return <div />
|
||||
}
|
||||
if (subj) {
|
||||
return (
|
||||
<div className={styles.questionContainer}>
|
||||
{subj.Questions.map((question, i) => {
|
||||
// FIXME: list edited questions first?
|
||||
const unsaved = unsavedIndexes.includes(i)
|
||||
const edited = editedIndexes.includes(i)
|
||||
const deleted = deletedIndexes.includes(i)
|
||||
return (
|
||||
<React.Fragment key={i}>
|
||||
<hr />
|
||||
{deleted ? (
|
||||
<DeletedQuestion
|
||||
reset={() => {
|
||||
resetQuestion(i)
|
||||
}}
|
||||
index={i}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={`${
|
||||
unsaved ? styles.unsaved : ''
|
||||
} ${edited ? styles.edited : ''}`}
|
||||
>
|
||||
<Question
|
||||
index={i}
|
||||
onChange={(newq) => {
|
||||
handleQuestionChange(newq, i)
|
||||
}}
|
||||
question={question}
|
||||
/>
|
||||
<div className={commonStyles.actions}>
|
||||
<div
|
||||
onClick={() => {
|
||||
resetQuestion(i)
|
||||
}}
|
||||
>
|
||||
Visszaállítás
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
saveQuestion(i)
|
||||
}}
|
||||
>
|
||||
{edited
|
||||
? 'Kérdés mentve'
|
||||
: 'Kérdés mentése'}
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
deleteQuestion(i)
|
||||
}}
|
||||
>
|
||||
Kérdés törlése
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return <div />
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,32 +3,34 @@ import React from 'react'
|
|||
import styles from './SubjectSelector.module.css'
|
||||
|
||||
export default function SubjectSelector(props) {
|
||||
const { activeSubjName, searchTerm, data, onSubjSelect } = props
|
||||
const { activeSubjName, searchTerm, data, onSubjSelect } = props
|
||||
|
||||
return (
|
||||
<div className={styles.subjectSelector}>
|
||||
{data.map((subj, i) => {
|
||||
if (!subj.Name.toLowerCase().includes(searchTerm.toLowerCase())) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<div className={styles.subjectSelector}>
|
||||
{data.map((subj, i) => {
|
||||
if (
|
||||
!subj.Name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
activeSubjName === subj.Name
|
||||
? 'subjItem activeSubjItem'
|
||||
: 'subjItem'
|
||||
}
|
||||
key={i}
|
||||
onClick={() => onSubjSelect(subj.Name)}
|
||||
>
|
||||
<span className={styles.subjName}>{subj.Name}</span>
|
||||
<span className={styles.questionCount}>
|
||||
[ {subj.Questions.length} ]
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
activeSubjName === subj.Name
|
||||
? 'subjItem activeSubjItem'
|
||||
: 'subjItem'
|
||||
}
|
||||
key={i}
|
||||
onClick={() => onSubjSelect(subj.Name)}
|
||||
>
|
||||
<span className={styles.subjName}>{subj.Name}</span>
|
||||
<span className={styles.questionCount}>
|
||||
[ {subj.Questions.length} ]
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,37 +1,39 @@
|
|||
import React from 'react'
|
||||
|
||||
export default function DbSelector(props) {
|
||||
const { selectedDb, qdbs, onChange, hideLockedDbs } = props
|
||||
const selectedIndex =
|
||||
qdbs && selectedDb
|
||||
? qdbs.findIndex((qdb) => {
|
||||
return qdb.name === selectedDb.name
|
||||
})
|
||||
: -1
|
||||
const { selectedDb, qdbs, onChange, hideLockedDbs } = props
|
||||
const selectedIndex =
|
||||
qdbs && selectedDb
|
||||
? qdbs.findIndex((qdb) => {
|
||||
return qdb.name === selectedDb.name
|
||||
})
|
||||
: -1
|
||||
|
||||
return (
|
||||
<>
|
||||
<select
|
||||
style={{ margin: '10px 0px' }}
|
||||
defaultValue={selectedIndex}
|
||||
value={selectedIndex}
|
||||
onChange={(event) => {
|
||||
onChange(qdbs[event.target.value])
|
||||
}}
|
||||
>
|
||||
<option value={-1}>{' -- Válassz egy kérdés adatbázist -- '}</option>
|
||||
{qdbs.map((qdb, i) => {
|
||||
if (hideLockedDbs && qdb.locked) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<select
|
||||
style={{ margin: '10px 0px' }}
|
||||
defaultValue={selectedIndex}
|
||||
value={selectedIndex}
|
||||
onChange={(event) => {
|
||||
onChange(qdbs[event.target.value])
|
||||
}}
|
||||
>
|
||||
<option value={-1}>
|
||||
{' -- Válassz egy kérdés adatbázist -- '}
|
||||
</option>
|
||||
{qdbs.map((qdb, i) => {
|
||||
if (hideLockedDbs && qdb.locked) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<option value={i} key={qdb.name}>
|
||||
{qdb.name}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</>
|
||||
)
|
||||
return (
|
||||
<option value={i} key={qdb.name}>
|
||||
{qdb.name}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,26 +3,26 @@ import React from 'react'
|
|||
import styles from './searchBar.module.css'
|
||||
|
||||
export default function SearchBar(props) {
|
||||
const { onChange, value } = props
|
||||
return (
|
||||
<div className={styles.searchContainer}>
|
||||
<input
|
||||
placeholder="Keresés..."
|
||||
className={styles.searchBar}
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
onChange('')
|
||||
}}
|
||||
className={styles.clearButton}
|
||||
>
|
||||
❌
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
const { onChange, value } = props
|
||||
return (
|
||||
<div className={styles.searchContainer}>
|
||||
<input
|
||||
placeholder="Keresés..."
|
||||
className={styles.searchBar}
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
onChange('')
|
||||
}}
|
||||
className={styles.clearButton}
|
||||
>
|
||||
❌
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import React from 'react'
|
|||
import '../defaultStyles.css'
|
||||
|
||||
function MyApp({ Component, pageProps, router }) {
|
||||
return <Component {...pageProps} router={router} />
|
||||
return <Component {...pageProps} router={router} />
|
||||
}
|
||||
|
||||
// Only uncomment this method if you have blocking data requirements for
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue