diff --git a/src/components/Questions.module.css b/src/components/Questions.module.css
index ae9b987..bd942e4 100644
--- a/src/components/Questions.module.css
+++ b/src/components/Questions.module.css
@@ -3,5 +3,30 @@
background-color: #9999ff;
color: black;
padding: 10px;
+ margin: 10px 0px;
word-wrap: break-word;
}
+
+.actions {
+ display: flex;
+ justify-content: space-around;
+}
+
+.actions > div {
+ cursor: pointer;
+ padding: 5px 20px;
+
+ color: #eee;
+ border: 1px solid #555;
+ border-radius: 3px;
+ user-select: none;
+}
+
+.actions > div:hover {
+ background-color: #444;
+ color: white;
+}
+
+.unsaved {
+ background-color: #333333;
+}
diff --git a/src/components/Subject.js b/src/components/Subject.js
index b05db08..7f9f32e 100644
--- a/src/components/Subject.js
+++ b/src/components/Subject.js
@@ -1,33 +1,101 @@
-import React, { PureComponent } from 'react'
+import React from 'react'
import Question from './Question.js'
-class Subject extends PureComponent {
- render () {
- const { subj, onChange, deleteQuestion } = this.props
+import styles from './subject.module.css'
+import commonStyles from '../commonStyles.module.css'
- if (subj) {
- return (
-
- {subj.Questions.map((question, i) => {
- return (
-
- )
- })}
+function DeletedQuestion({ reset }) {
+ return (
+
+
Törölt kérdés
+
+
{
+ reset()
+ }}
+ >
+ Visszaállítás
- )
- } else {
- return (
-
- )
- }
- }
+
+
+ )
}
-export default Subject
+export default function Subject(props) {
+ const {
+ subj,
+ unsavedIndexes,
+ deletedIndexes,
+ editedIndexes,
+ resetQuestion,
+ handleQuestionChange,
+ saveQuestion,
+ deleteQuestion,
+ } = props
+
+ if (subj) {
+ return (
+
+ {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 (
+
+
+ {deleted ? (
+ {
+ resetQuestion(i)
+ }}
+ index={i}
+ />
+ ) : (
+
+
{
+ handleQuestionChange(newq, i)
+ }}
+ question={question}
+ />
+
+
{
+ resetQuestion(i)
+ }}
+ >
+ Visszaállítás
+
+
{
+ saveQuestion(i)
+ }}
+ >
+ {edited ? 'Kérdés mentve' : 'Kérdés mentése'}
+
+
{
+ deleteQuestion(i)
+ }}
+ >
+ Kérdés törlése
+
+
+
+ )}
+
+ )
+ })}
+
+ )
+ } else {
+ return
+ }
+}
diff --git a/src/components/SubjectSelector.js b/src/components/SubjectSelector.js
index 197b5da..3c06fab 100644
--- a/src/components/SubjectSelector.js
+++ b/src/components/SubjectSelector.js
@@ -1,3 +1,5 @@
+import React from 'react'
+
import styles from './SubjectSelector.module.css'
export default function SubjectSelector(props) {
diff --git a/src/components/SubjectSelector.module.css b/src/components/SubjectSelector.module.css
index 38ad577..ae3f01d 100644
--- a/src/components/SubjectSelector.module.css
+++ b/src/components/SubjectSelector.module.css
@@ -13,3 +13,6 @@
margin: 10px;
}
+.subjectSelector:nth-child(2n) {
+ background-color: #444;
+}
diff --git a/src/components/dbSelector.js b/src/components/dbSelector.js
new file mode 100644
index 0000000..8e4ed38
--- /dev/null
+++ b/src/components/dbSelector.js
@@ -0,0 +1,28 @@
+import React from 'react'
+
+export default function DbSelector(props) {
+ const { qdbs, onChange } = props
+
+ return (
+ <>
+
{
+ onChange(qdbs[event.target.value])
+ }}
+ >
+
+ {' -- Válassz egy kérdés adatbázist -- '}
+
+ {qdbs.map((qdb, i) => {
+ return (
+
+ {qdb.name}
+
+ )
+ })}
+
+ >
+ )
+}
diff --git a/src/components/possibleAnswers.js b/src/components/possibleAnswers.js
new file mode 100644
index 0000000..a26d4dc
--- /dev/null
+++ b/src/components/possibleAnswers.js
@@ -0,0 +1,256 @@
+import React, { useEffect, useState } from 'react'
+
+import LoadingIndicator from '../components/LoadingIndicator'
+import SearchBar from '../components/searchBar'
+import TestView from '../components/testView'
+
+import constants from '../constants.json'
+import styles from './possibleAnswers.module.css'
+
+const Infos = () => {
+ return (
+
+
+ Itt azok a tesztek találhatók, amiknek a kitöltése után nem volt
+ ellenőrző oldal. A script így nem tudja, hogy melyik a helyes megoldás.
+ De ha ti igen, akkor jelöljétek be / írjátok be, és mentsétek el. Így
+ mikor legközelebb találkoztok a kérdéssel a script tudni fogja a helyes
+ választ. Ezzel másoknak is nagyon sokat segítetek.
+
+
+ )
+}
+
+const fetchPossibleAnswers = () => {
+ return new Promise((resolve) => {
+ fetch(`${constants.apiUrl}possibleAnswers`, {
+ credentials: 'include',
+ })
+ .then((resp) => {
+ return resp.json()
+ })
+ .then((res) => {
+ resolve(res)
+ })
+ })
+}
+
+const fetchSubject = (subj, savedQuestionsFileName) => {
+ return new Promise((resolve) => {
+ fetch(
+ `${constants.apiUrl}/savedQuestions/${subj}/${savedQuestionsFileName}`,
+ {
+ credentials: 'include',
+ }
+ )
+ .then((resp) => {
+ return resp.json()
+ })
+ .then((resp) => {
+ resolve(resp)
+ })
+ })
+}
+
+const fetchTest = (subj, test) => {
+ return new Promise((resolve) => {
+ fetch(`${constants.apiUrl}/savedQuestions/${subj}/${test}`, {
+ credentials: 'include',
+ })
+ .then((resp) => {
+ return resp.json()
+ })
+ .then((resp) => {
+ resolve(resp)
+ })
+ })
+}
+
+export default function PossibleAnswers({ router, refetchDbs }) {
+ const [currSubjName, setCurrSubjName] = useState(null)
+ const [currTestName, setCurrTestName] = useState(null)
+
+ const [subjects, setSubjects] = useState([])
+ const [currSubj, setCurrSubj] = useState(null)
+ const [currTest, setCurrTest] = useState(null)
+
+ const [savedQuestionsFileName, setSavedQuestionsFileName] = useState(null)
+ const [searchTerm, setSearchTerm] = useState('')
+
+ useEffect(() => {
+ fetchPossibleAnswers().then((resp) => {
+ setSubjects(resp.subjects)
+ setSavedQuestionsFileName(resp.savedQuestionsFileName)
+
+ const subj = router.query.subj
+ ? decodeURIComponent(router.query.subj)
+ : ''
+ const test = router.query.test
+ ? decodeURIComponent(router.query.test)
+ : ''
+
+ if (subj) {
+ fetchSubject(subj, resp.savedQuestionsFileName).then((resp) => {
+ setCurrSubj(resp)
+ setCurrSubjName(subj)
+ router.push(
+ `${router.pathname}?v=pa&subj=${encodeURIComponent(subj)}`,
+ undefined,
+ { shallow: true }
+ )
+ if (subj && test) {
+ fetchTest(subj, test).then((resp) => {
+ setCurrTest(resp)
+ setCurrTestName(test)
+ router.push(
+ `${router.pathname}?v=pa&subj=${encodeURIComponent(
+ subj
+ )}&test=${encodeURIComponent(test)}`,
+ undefined,
+ { shallow: true }
+ )
+ })
+ }
+ })
+ }
+ })
+ }, [])
+
+ const renderStuff = () => {
+ if (subjects && currSubj && currTest) {
+ return (
+ <>
+
{
+ setCurrTest(null)
+ router.back()
+ }}
+ >
+ Vissza
+
+
+ {currTest && (
+ {
+ refetchDbs()
+ setCurrTest(null)
+ fetchSubject(currSubjName, savedQuestionsFileName).then(
+ (resp) => {
+ setCurrSubj(resp)
+ }
+ )
+ }}
+ />
+ )}
+
+ >
+ )
+ } else if (subjects && currSubj) {
+ return (
+ <>
+
+
{
+ setCurrSubj(null)
+ router.back()
+ }}
+ >
+ Vissza
+
+
{currSubjName}
+
+
+ <>
+
+
Dátum
+
Felhasználó ID
+
Tárgy
+
Teszt URL
+
+ {currSubj &&
+ currSubj.map((test, i) => {
+ return (
+
{
+ setCurrTestName(test.fname)
+ router.push(
+ `${router.pathname}?v=pa&subj=${encodeURIComponent(
+ currSubjName
+ )}&test=${encodeURIComponent(test.fname)}`,
+ undefined,
+ { shallow: true }
+ )
+
+ fetchTest(currSubjName, test.fname).then((resp) => {
+ setCurrTest(resp)
+ })
+ }}
+ >
+
{new Date(test.date).toLocaleString()}
+
{test.userid}
+
{test.subj}
+
{test.testUrl}
+
+ )
+ })}
+ >
+
+ >
+ )
+ } else if (subjects) {
+ return (
+ <>
+
+
setSearchTerm(e)} />
+
+ <>
+
Tárgy neve
+ {subjects.map((subj, i) => {
+ if (
+ !subj.name.toLowerCase().includes(searchTerm.toLowerCase())
+ ) {
+ return null
+ }
+ return (
+
{
+ setCurrSubjName(subj.name)
+ router.push(
+ `${router.pathname}?v=pa&subj=${encodeURIComponent(
+ subj.name
+ )}`,
+ undefined,
+ { shallow: true }
+ )
+
+ fetchSubject(subj.name, savedQuestionsFileName).then(
+ (resp) => {
+ setCurrSubj(resp)
+ }
+ )
+ }}
+ >
+ {subj.name}
+
+ )
+ })}
+ >
+
+ >
+ )
+ } else {
+ return
+ }
+ }
+
+ return renderStuff()
+}
diff --git a/src/components/possibleAnswers.module.css b/src/components/possibleAnswers.module.css
new file mode 100644
index 0000000..dbdbe77
--- /dev/null
+++ b/src/components/possibleAnswers.module.css
@@ -0,0 +1,85 @@
+.tableContainer {
+ padding: 5px;
+}
+
+.tableContainer > div {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 6px 10px;
+}
+
+.tableContainer > div > div:nth-child(1) {
+ flex: 0 100px;
+}
+
+.tableContainer > div > div:nth-child(2) {
+ text-align: center;
+ flex: 0 120px;
+}
+
+.tableContainer > div > div:nth-child(3) {
+ flex: 1 0;
+}
+
+.tableContainer > div > div:nth-child(4) {
+ flex: 0 200px;
+}
+
+.tableContainer > div:first-child {
+ text-align: center;
+ padding: 13px 10px;
+ background-color: #444;
+ color: #fff;
+}
+
+.tableContainer > div:not(:first-child) {
+ cursor: pointer;
+}
+
+.tableContainer > div:nth-child(2n) {
+ background-color: #2c2c2c;
+}
+
+.tableContainer > div:not(:first-child):hover {
+ background-color: #444;
+}
+
+.backButton {
+ color: white;
+ display: inline-block;
+ margin: 10px 5px;
+ padding: 10px 40px;
+ font-size: 16px;
+ cursor: pointer;
+ border: 1px solid #444;
+ border-radius: 3px;
+}
+
+.backButton:hover {
+ background-color: #444;
+}
+
+.subjName {
+ font-size: 24px;
+ color: white;
+ padding: 8px 0px;
+}
+
+.headerContainer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.infoContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 5px;
+}
+
+.infoContainer > div {
+ margin: 2px;
+ text-align: center;
+}
diff --git a/src/components/question.module.css b/src/components/question.module.css
index 91eeeec..dc13988 100644
--- a/src/components/question.module.css
+++ b/src/components/question.module.css
@@ -1,20 +1,21 @@
-.questionInput {
- flex-grow: 1;
+.questionContainer > input,
+.questionContainer > textarea {
background-color: var(--background-color);
color: white;
- border: none;
- padding: 8px;
+ border-radius: 5px;
+ border: 1px solid #333;
+ padding: 6px;
+ margin: 3px;
+}
+
+.questionContainer > input:hover,
+.questionContainer > textarea:hover {
+ border: 1px solid #99f;
}
.questionContainer {
- margin-top: 30px;
- margin-bottom: 30px;
- margin-right: 10px;
- margin-left: 10px;
-}
-.inputContainer {
- width: 100%;
display: flex;
+ flex-flow: column;
}
.deleteButton {
@@ -29,3 +30,26 @@
.deleteButton:hover {
border: 1px solid;
}
+
+.possibleAnswers > div {
+ display: flex;
+ justify-content: space-between;
+ padding: 5px;
+}
+
+.possibleAnswers > div:hover {
+ background-color: #444;
+}
+
+.text {
+ padding: 0px 6px;
+}
+
+.delete {
+ padding: 1px 5px;
+ cursor: pointer;
+}
+
+.delete:hover {
+ background-color: #666;
+}
diff --git a/src/components/questionAdder.js b/src/components/questionAdder.js
index a3754cf..8a28333 100644
--- a/src/components/questionAdder.js
+++ b/src/components/questionAdder.js
@@ -1,10 +1,103 @@
import React, { useState, useEffect } from 'react'
-import Head from 'next/head'
-import LoadingIndicator from '../components/LoadingIndicator'
+import Question from '../components/Question'
import styles from './questionAdder.module.css'
import constants from '../constants.json'
+import commonStyles from '../commonStyles.module.css'
+
+const handleSubmit = async (form) => {
+ return new Promise((resolve, reject) => {
+ if (!form.subj) {
+ reject('nosubj')
+ return
+ }
+ let isValid = form.quiz.every((x) => {
+ return x.Q && x.A
+ })
+ if (!isValid || form.quiz.length === 0) {
+ reject('notvalid')
+ return
+ }
+
+ const t = document.getElementById('cid').value
+ let cid = ''
+ let version = ''
+ if (t) {
+ cid = t.split('|')[0]
+ version = t.split('|')[1]
+ }
+
+ // console.log(form)
+ // {
+ // "quiz": [
+ // {
+ // "Q": "aaaaaaaaaaaa",
+ // "A": "bbbbbbbbbbbbbb",
+ // "data": {
+ // "type": "simple"
+ // }
+ // }
+ // ],
+ // "selectedDb": {
+ // "path": "questionDbs/elearning.uni-obuda.hu.json",
+ // "name": "elearning.uni-obuda.hu"
+ // },
+ // "subj": "Elektronika"
+ // }
+
+ const toSend = {
+ id: cid,
+ version: version,
+ location: `https://${form.selectedDb.name}`,
+ subj: form.subj,
+ quiz: form.quiz,
+ }
+
+ fetch(constants.apiUrl + 'isAdding', {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(toSend),
+ })
+ .then((res) => {
+ return res.json()
+ })
+ .then((resp) => {
+ resolve(resp)
+ })
+ })
+}
+
+const renderUsage = () => {
+ return (
+
+ Ezek a kérdések ellenőrizve lesznek hogy megvannak-e már
+
+ {
+ "Ha több válasz van, akkor ', '-vel válaszd el őket ( 'válasz1, válasz2, válasz3' )"
+ }
+
+
+ Kérdéseknél az utolsó sor (ahol a JSON cucc van) jelenleg nem
+ módosítható, csak olyan kérdéseket lehet beküldeni, amik sima
+ kérdés-válaszok, szóval pl nincs benne kép. Ez később bővül majd
+
+
+ Ha sok új kérdést küldesz be, akkor akár több percig is eltarthat a
+ dolog. Akárhány kérdést be lehet egyszerre küldeni, de max 10-15 az
+ ajánlott
+
+
+ Bármilyen szöveget beküldhettek, de ne tegyétek, más felhasználóknak és
+ magatoknak lesz rosz, ty!
+
+
+ )
+}
const getDefaultQuestion = () => {
return {
@@ -14,100 +107,44 @@ const getDefaultQuestion = () => {
}
}
-export default function QuestionAdder() {
+export default function QuestionAdder({ data, selectedDb, refetchDbs }) {
const [form, setForm] = useState({ quiz: [getDefaultQuestion()] })
- const [subjects, setSubjects] = useState(undefined)
+ const [subjects, setSubjects] = useState(null)
const [isSubmitting, setIsSubmitting] = useState(false)
const [isNewSubj, setIsNewSubj] = useState(false)
useEffect(() => {
- console.info('Fetching subject names')
- fetch(`${constants.apiUrl}dataCount?detailed=true`, {
- credentials: 'include',
- })
- .then((resp) => {
- return resp.json()
+ if (selectedDb) {
+ setForm({
+ ...form,
+ selectedDb: selectedDb,
})
- .then((data) => {
- let res = data.reduce((acc, x) => {
- return [
- ...acc,
- ...x.subjs.map((subj) => {
- return subj.name
- }),
- ]
- }, [])
+ }
+ }, [selectedDb])
- res = res.sort()
- setSubjects(res)
- })
- }, [])
-
- const onChange = (newData, index) => {
- let quiz = form.quiz
- quiz[index] = newData
+ useEffect(() => {
+ if (data) {
+ setSubjects(
+ data.map((subj) => {
+ return subj.Name
+ })
+ )
+ }
+ }, [data])
+ const handleQuestionChange = (index, newVal) => {
setForm({
...form,
- quiz: quiz,
+ quiz: form.quiz.map((q, i) => {
+ if (i !== index) {
+ return q
+ } else {
+ return newVal
+ }
+ }),
})
}
- const renderQuestionInput = (params) => {
- const { index, onChange } = params
- const currData = form.quiz[index]
- const { Q, A, data } = form.quiz[index] || {}
-
- return (
-
- )
- }
-
const deleteQuestion = (index) => {
let quiz = form.quiz
@@ -119,82 +156,33 @@ export default function QuestionAdder() {
})
}
- const handleSubmit = async () => {
- if (!form.subj) {
- alert('Nem választottál ki tantárgyat!') // eslint-disable-line
- return
- }
- let isValid = form.quiz.every((x) => {
- return x.Q && x.A
- })
- if (!isValid || form.quiz.length === 0) {
- alert('Kérdés kitöltése kötelező!') // eslint-disable-line
- return
- }
-
- const t = document.getElementById('cid').value
- let cid = ''
- let version = ''
- if (t) {
- cid = t.split('|')[0]
- version = t.split('|')[1]
- }
-
- setIsSubmitting(true)
-
- const rawResponse = await fetch(constants.apiUrl + 'isAdding', {
- method: 'POST',
- credentials: 'include',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- ...form,
- id: cid,
- version: 'WEBSITE',
- scriptVersion: version,
- }),
- })
- rawResponse
- .json()
- .then((resp) => {
- console.log(resp)
- if (resp.success) {
- alert(
- 'Sikeres beküldés, ' +
- resp.newQuestions.reduce((acc, res) => {
- return acc + res.newQuestions
- }, 0) +
- ' új kérdés'
- ) // eslint-disable-line
- setIsSubmitting(false)
- } else {
- alert('Hiba beküldés közben :/') // eslint-disable-line
- setIsSubmitting(false)
- }
- })
- .catch((err) => {
- alert('Hiba beküldés közben :/') // eslint-disable-line
- console.log(err)
- setIsSubmitting(false)
- })
- }
-
const renderStuff = () => {
return (
{form.quiz.map((q, i) => {
return (
-
- {renderQuestionInput({
- index: i,
- onChange,
- })}
-
+
+
+ {
+ handleQuestionChange(i, newVal)
+ }}
+ />
+
+
{
+ deleteQuestion(i)
+ }}
+ >
+ Törlés
+
+
+
)
})}
-
+
+
{
let quiz = form.quiz
@@ -207,26 +195,57 @@ export default function QuestionAdder() {
>
Új kérdés
+
{
+ if (isSubmitting) {
+ return
+ }
+ setIsSubmitting(true)
+ handleSubmit(form)
+ .then((res) => {
+ // console.log(res)
+ // {
+ // "success": true,
+ // "newQuestions": [
+ // {
+ // "newQuestions": 1,
+ // "qdbName": "elearning.uni-obuda.hu"
+ // }
+ // ],
+ // "totalNewQuestions": 1
+ // }
+
+ if (res.success) {
+ alert(
+ `Sikeres beküldés, ${res.totalNewQuestions} új kérdés`
+ )
+ } else {
+ alert('Hiba beküldés közben :/')
+ }
+ refetchDbs()
+ setIsSubmitting(false)
+ })
+ .catch((res) => {
+ if (res === 'nosubj') {
+ alert('Nem választottál ki tantárgyat!') // eslint-disable-line
+ }
+ if (res === 'notvalid') {
+ alert('Kérdés kitöltése kötelező!') // eslint-disable-line
+ }
+ setIsSubmitting(false)
+ })
+ }}
+ >
+ {isSubmitting ? 'Beküldés folyamatban ...' : 'Kérdések beküldése'}
+
- {isSubmitting ? (
-
- Kérdések feldolgozása folyamatban, ha sokat küldtél, akkor több perc
- is lehet
-
- ) : (
-
-
- Kérdések beküldése
-
-
- )}
)
}
const renderSubjSelector = () => {
- // TODO: handle if new subject
return (
{isNewSubj ? (
@@ -243,7 +262,6 @@ export default function QuestionAdder() {
/>
) : (
{
setForm({
...form,
@@ -263,61 +281,29 @@ export default function QuestionAdder() {
})}
)}
-
{
setIsNewSubj(!isNewSubj)
}}
>
- {isNewSubj ? 'Létező tárgy ...' : 'Új tárgy ...'}
-
+
{isNewSubj ? 'Létező tárgy ...' : 'Új tárgy ...'}
+
)
}
- const renderUsage = () => {
- return (
-
- Ezen az oldalon kérdéseket tudsz beküldeni manuálisan.
- Ezek a kérdések ellenőrizve lesznek hogy megvannak-e már
-
- {
- "Ha több válasz van, akkor ', '-vel válaszd el őket ( 'válasz1, válasz2, válasz3' )"
- }
-
-
- Kérdéseknél az utolsó sor (ahol a JSON cucc van) jelenleg nem
- módosítható, csak olyan kérdéseket lehet beküldeni, amik sima
- kérdés-válaszok, szóval pl nincs benne kép. Ez később bővül majd
-
-
- Ha sok új kérdést küldesz be, akkor akár több percig is eltarthat a
- dolog. Akárhány kérdést be lehet egyszerre küldeni, de max 10-15 az
- ajánlott
-
-
- Bármilyen szöveget beküldhettek, de ne tegyétek, más felhasználóknak
- és magatoknak lesz rosz, ty!
-
-
- )
- }
-
return (
-
-
Qmining - Kérdés beküldés | Frylabs.net
-
+
+ {renderUsage()}
{subjects ? (
<>
- {renderUsage()}
{renderSubjSelector()}
{renderStuff()}
>
- ) : (
-
- )}
+ ) : null}
)
}
diff --git a/src/components/questionAdder.module.css b/src/components/questionAdder.module.css
index bba190a..82733ab 100644
--- a/src/components/questionAdder.module.css
+++ b/src/components/questionAdder.module.css
@@ -1,116 +1,28 @@
.questionInput {
- flex-grow: 1;
- font-size: 16px;
+ width: 80%;
background-color: var(--background-color);
color: white;
- border: none;
- padding: 8px;
- margin: 4px;
- border: 1px solid;
- border-color: var(--background-color);
-}
-
-.questionContainer {
- margin-top: 30px;
- margin-bottom: 30px;
- margin-right: 10px;
- margin-left: 10px;
-}
-
-.inputContainer {
- width: 100%;
- display: flex;
-}
-
-.buttonContainer {
- text-align: center;
- width: 200px;
- margin: 0 auto;
- padding: 10px;
-}
-
-.deleteButton {
- display: flex;
- align-items: center;
- background-color: #333;
+ border-radius: 5px;
+ border: 1px solid #333;
padding: 6px;
- font-size: 16px;
- color: white;
- cursor: pointer;
- border: 1px solid;
- border-color: var(--background-color);
-}
-
-.deleteButton:hover {
- background-color: #666;
+ margin: 3px;
}
.questionInput:hover {
- border: 1px solid;
-}
-
-.button {
- cursor: pointer;
- background-color: var(--text-color);
- border: none;
- padding: 10px 30px;
- color: white;
- width: 200px;
+ border: 1px solid #99f;
}
.subjSelectorContainer {
- width: 100%;
display: flex;
+ align-items: center;
+ justify-content: space-between;
}
-.subjSelector {
- flex-grow: 1;
- background-color: var(--background-color);
-}
-
-.newSubj {
- display: flex;
- justify-content: center;
-
- background-color: #333;
- width: 150px;
- margin: 0px 4px;
- padding: 10px;
- cursor: pointer;
- font-size: 14px;
- color: white;
-}
-
-.newSubj:hover {
- background-color: #666;
-}
-
-.usage li {
- margin: 5px;
-}
-
-.usage {
- font-size: 15px;
- color: white;
+.subjSelectorContainer > select {
+ width: 80%;
}
.issubmitting {
text-align: center;
color: white;
}
-
-.newQuestionButton {
- display: flex;
- justify-content: center;
-}
-
-.newQuestionButton div {
- background-color: #333;
- color: white;
- cursor: pointer;
- padding: 10px 20px;
-}
-
-.newQuestionButton div:hover {
- background-color: #666;
-}
diff --git a/src/components/questionSearchResult.module.css b/src/components/questionSearchResult.module.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/questionView.js b/src/components/questionView.js
index 0a4ca93..b18069a 100644
--- a/src/components/questionView.js
+++ b/src/components/questionView.js
@@ -1,43 +1,204 @@
-import React, { useState } from 'react'
+import React, { useState, useEffect } from 'react'
import LoadingIndicator from '../components/LoadingIndicator.js'
import QuestionSearchResult from '../components/QuestionSearchResult.js'
+import SearchBar from '../components/searchBar'
-import styles from './questionView.module.css'
+import constants from '../constants.json'
+// import styles from './questionView.module.css'
+
+const updateQuestion = (e, selectedDb) => {
+ return new Promise((resolve) => {
+ fetch(constants.apiUrl + 'updateQuestion', {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ ...e,
+ selectedDb: selectedDb,
+ }),
+ })
+ .then((res) => {
+ return res.json()
+ })
+ .then((res) => {
+ resolve(res)
+ })
+ })
+}
+
+const rmQuestion = (e, selectedDb) => {
+ return new Promise((resolve) => {
+ fetch(constants.apiUrl + 'updateQuestion', {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ ...e,
+ selectedDb: selectedDb,
+ }),
+ })
+ .then((res) => {
+ return res.json()
+ })
+ .then((res) => {
+ resolve(res)
+ })
+ })
+}
export default function questionView(props) {
- const { data, onChange, deleteQuestion } = props
+ const { selectedDb } = props
+ const [data, setData] = useState(props.data)
const [searchTerm, setSearchTerm] = useState('')
+ const [edits, setEdits] = useState([])
+
+ useEffect(() => {
+ setData(props.data)
+ }, [props.data])
+
+ const updateEdits = (e) => {
+ setEdits(
+ edits.map((edit, i) => {
+ if (i === e.index) {
+ return e
+ } else {
+ return edit
+ }
+ })
+ )
+ }
+
+ const removeFromEdits = (e) => {
+ setEdits(
+ edits.filter((edit, i) => {
+ return i !== e.index
+ })
+ )
+ }
+
+ const onChange = (e) => {
+ const editIndex = edits.findIndex((edit) => {
+ return edit.subjName === e.subjName && edit.index === e.index
+ })
+ if (editIndex === -1) {
+ if (e.type === 'edit') {
+ if (editIndex === -1) {
+ setEdits([...edits, e])
+ }
+ }
+ if (e.type === 'delete') {
+ rmQuestion(e, selectedDb).then((res) => {
+ if (res.status === 'OK') {
+ alert('Sikeres törlés')
+ } else {
+ alert('Hiba mentés közben :/')
+ }
+
+ setData(
+ data.map((subj) => {
+ if (subj.Name !== e.subjName) {
+ return subj
+ } else {
+ return {
+ ...subj,
+ Questions: subj.Questions.filter((question, i) => {
+ return i !== e.index
+ }),
+ }
+ }
+ })
+ )
+ })
+ }
+ } else {
+ if (e.type === 'reset') {
+ // edits -> saves -> resets? => should do nothing, no reset after saving
+ removeFromEdits(e)
+ setData(
+ data.map((subj) => {
+ if (subj.Name !== e.subjName) {
+ return subj
+ } else {
+ return {
+ ...subj,
+ Questions: subj.Questions.map((question, i) => {
+ if (i !== e.index) {
+ return question
+ } else {
+ const ps = props.data.find((subj) => {
+ return subj.Name === e.subjName
+ })
+ if (ps) {
+ return ps.Questions[i]
+ }
+ }
+ }),
+ }
+ }
+ })
+ )
+ }
+ if (e.type === 'save') {
+ updateQuestion(
+ edits.find((edit) => {
+ return edit.index === e.index
+ }),
+ selectedDb
+ ).then((res) => {
+ if (res.status === 'OK') {
+ alert('Sikeres mentés')
+ } else {
+ alert('Hiba mentés közben :/')
+ }
+
+ removeFromEdits(e)
+ })
+ }
+ if (e.type === 'edit') {
+ updateEdits(e)
+ }
+ }
+
+ if (e.type === 'edit') {
+ setData(
+ data.map((subj) => {
+ if (subj.Name !== e.subjName) {
+ return subj
+ } else {
+ return {
+ ...subj,
+ Questions: subj.Questions.map((question, i) => {
+ if (i !== e.index) {
+ return question
+ } else {
+ return e.newVal
+ }
+ }),
+ }
+ }
+ })
+ )
+ }
+ }
if (data) {
return (
-
- {
- setSearchTerm(e.target.value)
- }}
- />
- {
- setSearchTerm('')
- }}
- className={styles.clearButton}
- >
- X
-
-
+
setSearchTerm(e)} />
diff --git a/src/components/searchBar.js b/src/components/searchBar.js
new file mode 100644
index 0000000..a4de0c9
--- /dev/null
+++ b/src/components/searchBar.js
@@ -0,0 +1,28 @@
+import React from 'react'
+
+import styles from './searchBar.module.css'
+
+export default function SearchBar(props) {
+ const { onChange, value } = props
+ return (
+
+ {
+ onChange(e.target.value)
+ }}
+ />
+ {
+ onChange('')
+ }}
+ className={styles.clearButton}
+ >
+ ❌
+
+
+ )
+}
diff --git a/src/components/searchBar.module.css b/src/components/searchBar.module.css
new file mode 100644
index 0000000..a2aea8f
--- /dev/null
+++ b/src/components/searchBar.module.css
@@ -0,0 +1,27 @@
+.searchBar {
+ margin: 10px;
+ padding: 10px;
+ color: white;
+ background-color: #222426;
+ border: none;
+ flex-grow: 1;
+ font-size: 18px;
+}
+
+.searchContainer {
+ width: 100%;
+ display: flex;
+}
+
+.clearButton {
+ font-size: 30px;
+ width: 80px;
+ background-color: var(--background-color);
+ color: white;
+ cursor: pointer;
+ border: none;
+}
+
+.clearButton:hover {
+ background-color: #333;
+}
diff --git a/src/components/subject.module.css b/src/components/subject.module.css
new file mode 100644
index 0000000..38b36a1
--- /dev/null
+++ b/src/components/subject.module.css
@@ -0,0 +1,16 @@
+.questionContainer > div {
+ padding: 10px 0px;
+}
+
+.unsaved {
+ background-color: #333333;
+}
+
+.edited {
+ background-color: #222926;
+}
+
+.deletedQuestion {
+ padding: 10px;
+ text-align: center;
+}
diff --git a/src/components/subjectView.js b/src/components/subjectView.js
index d09c49d..d85e9fc 100644
--- a/src/components/subjectView.js
+++ b/src/components/subjectView.js
@@ -3,71 +3,219 @@ import React, { useState, useEffect } from 'react'
import LoadingIndicator from '../components/LoadingIndicator.js'
import Subject from '../components/Subject.js'
import SubjectSelector from '../components/SubjectSelector.js'
+import SearchBar from '../components/searchBar'
-import styles from './subjectView.module.css'
+import constants from '../constants.json'
+// import styles from './subjectView.module.css'
+import commonStyles from '../commonStyles.module.css'
+
+const onSave = (subjName, changedQuestions, deletedQuestions, selectedDb) => {
+ return new Promise((resolve) => {
+ fetch(constants.apiUrl + 'updateQuestion', {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ subjName: subjName,
+ changedQuestions: changedQuestions,
+ deletedQuestions: deletedQuestions,
+ type: 'subjEdit',
+ selectedDb: selectedDb,
+ }),
+ })
+ .then((res) => {
+ return res.json()
+ })
+ .then((res) => {
+ resolve(res)
+ })
+ })
+}
export default function SubjectView(props) {
- const { data, onChange, deleteQuestion } = props
+ const { data, selectedDb } = props
const [activeSubjName, setActiveSubjName] = useState('')
const [searchTerm, setSearchTerm] = useState('')
- const [sCount, setSCount] = useState(0)
- const [qCount, setQCount] = useState(0)
+ const [unsavedIndexes, setUnsavedIndexes] = useState([])
+ const [editedIndexes, setEditedIndexes] = useState([])
+ const [deletedIndexes, setDeletedIndexes] = useState([])
+ const [subj, setSubj] = useState(null)
+
+ const hasChange = editedIndexes.length > 0 || deletedIndexes.length > 0
useEffect(() => {
- setSCount(data.length)
- setQCount(
- data.reduce((acc, subj) => {
- return acc + subj.Questions.length
- }, 0)
- )
- }, [])
+ let currSubj = data.find((subj) => {
+ return subj.Name === activeSubjName
+ })
+ setSubj(currSubj)
+ }, [activeSubjName])
+
+ const resetQuestion = (i) => {
+ if (deletedIndexes.includes(i)) {
+ setDeletedIndexes(
+ deletedIndexes.filter((ind) => {
+ return ind !== i
+ })
+ )
+ }
+
+ if (editedIndexes.includes(i)) {
+ setEditedIndexes(
+ editedIndexes.filter((ind) => {
+ return ind !== i
+ })
+ )
+ }
+
+ if (unsavedIndexes.includes(i)) {
+ setUnsavedIndexes(
+ unsavedIndexes.filter((ind) => {
+ return ind !== i
+ })
+ )
+ }
- if (data) {
let currSubj = data.find((subj) => {
return subj.Name === activeSubjName
})
+ setSubj({
+ ...subj,
+ Questions: subj.Questions.map((q, j) => {
+ if (i === j) {
+ return currSubj.Questions[i]
+ } else {
+ return q
+ }
+ }),
+ })
+ }
+
+ const handleQuestionChange = (newq, i) => {
+ if (!unsavedIndexes.includes(i)) {
+ setUnsavedIndexes([...unsavedIndexes, i])
+ }
+
+ if (editedIndexes.includes(i)) {
+ setEditedIndexes(
+ editedIndexes.filter((ind) => {
+ return ind !== i
+ })
+ )
+ }
+
+ setSubj({
+ ...subj,
+ Questions: subj.Questions.map((q, j) => {
+ if (i !== j) {
+ return q
+ } else {
+ return newq
+ }
+ }),
+ })
+ }
+
+ const saveQuestion = (i) => {
+ setUnsavedIndexes(
+ unsavedIndexes.filter((ind) => {
+ return ind !== i
+ })
+ )
+ setEditedIndexes([...editedIndexes, i])
+ }
+
+ const deleteQuestion = (i) => {
+ setDeletedIndexes([...deletedIndexes, i])
+ }
+
+ const handleSave = () => {
+ if (unsavedIndexes.length > 0) {
+ alert(
+ 'Mentetlen módosításaid vannak, kérek mentsd, vagy állítsd vissza azokat'
+ )
+ return
+ }
+ if (editedIndexes.length === 0 && deletedIndexes.length === 0) {
+ alert('Nem módosítottál még semmit')
+ return
+ }
+ const changedQuestions = editedIndexes.map((ei) => {
+ return {
+ index: ei,
+ value: subj.Questions[ei],
+ }
+ })
+ const deletedQuestions = deletedIndexes
+ onSave(subj.Name, changedQuestions, deletedQuestions, selectedDb).then(
+ (res) => {
+ if (res.status === 'OK') {
+ alert('Sikeres mentés')
+ } else {
+ alert('Hiba mentés közben :/')
+ }
+
+ setUnsavedIndexes([])
+ setEditedIndexes([])
+ setDeletedIndexes([])
+ }
+ )
+ }
+
+ if (data) {
return (
-
- {
- setSearchTerm(e.target.value)
- }}
- />
- {
- setSearchTerm('')
- }}
- className={styles.clearButton}
- >
- X
-
-
+
setSearchTerm(e)} />
{
- setActiveSubjName(subjName)
+ if (
+ !hasChange ||
+ confirm(
+ 'Mentetlen módosításaid vannak a tárgynál, biztos bezárod?'
+ )
+ ) {
+ setActiveSubjName(subjName)
+ setUnsavedIndexes([])
+ setEditedIndexes([])
+ setDeletedIndexes([])
+ } else {
+ console.log('canceld')
+ }
}}
/>
-
- {qCount} kérdés, {sCount} tárgy
+
+ {subj && (
+
{
+ handleSave()
+ }}
+ >
+ Tárgy módosításainak mentése
+
+ )}
-
+ {subj && (
+
+ )}
)
diff --git a/src/components/subjectView.module.css b/src/components/subjectView.module.css
index 61dbdf7..feb8dcc 100644
--- a/src/components/subjectView.module.css
+++ b/src/components/subjectView.module.css
@@ -1,21 +1,19 @@
-.searchBar {
- margin: 10px;
- padding: 10px;
- color: white;
- background-color: #222426;
- border: none;
- flex-grow: 1;
-}
-
-.searchContainer {
- width: 100%;
+.actions {
display: flex;
+ justify-content: space-around;
}
-.clearButton {
- width: 80px;
- background-color: var(--background-color);
- color: white;
+.actions > div {
cursor: pointer;
- border: none;
+ padding: 5px 20px;
+
+ color: #eee;
+ border: 1px solid #555;
+ border-radius: 3px;
+ user-select: none;
+}
+
+.actions > div:hover {
+ background-color: #444;
+ color: white;
}
diff --git a/src/components/testView.js b/src/components/testView.js
new file mode 100644
index 0000000..77cbc3f
--- /dev/null
+++ b/src/components/testView.js
@@ -0,0 +1,189 @@
+import React, { useState } from 'react'
+
+import Question from '../components/Question'
+
+import constants from '../constants.json'
+import styles from './testView.module.css'
+import commonStyles from '../commonStyles.module.css'
+
+const rmTest = (subjName, testName) => {
+ return new Promise((resolve) => {
+ fetch(constants.apiUrl + 'rmPossibleAnswer', {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ subj: subjName,
+ file: testName,
+ }),
+ })
+ .then((res) => {
+ return res.json()
+ })
+ .then((res) => {
+ resolve(res)
+ })
+ })
+}
+
+export default function TestView(props) {
+ const { subjName, testName, router, onDelete } = props
+ const [test, setTest] = useState(props.test)
+
+ const renderActions = () => {
+ return (
+
+
{
+ if (confirm('Biztos véglegesen törlöd ezt az egész tesztet?')) {
+ rmTest(subjName, testName).then((res) => {
+ if (res.res === 'ok') {
+ // alert('sikeres törlés')
+ router.back()
+ onDelete()
+ } else {
+ alert('hiba törlés közben!')
+ }
+ })
+ }
+ }}
+ >
+ Teszt törlése
+
+
{
+ if (
+ confirm(
+ 'Biztos beküldöd? Beküldés után törlődik a teszt, de a Kérdések/Tárgyak nézetnél megtalálhatóak lesznek'
+ )
+ ) {
+ const questions = test.questions.map((q) => {
+ return {
+ Q: q.Q,
+ A: q.A,
+ data: {
+ ...q.data,
+ ...(q.possibleAnswers && {
+ possibleAnswers: q.possibleAnswers,
+ }),
+ },
+ }
+ })
+ const toSend = {
+ id: 'WEBSITE',
+ version: 'WEBSITE',
+ location: `https://${test.testUrl}`,
+ subj: test.subj,
+ quiz: questions,
+ }
+
+ fetch(constants.apiUrl + 'isAdding', {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(toSend),
+ })
+ .then((res) => {
+ return res.json()
+ })
+ .then((res) => {
+ if (res.success) {
+ alert(
+ `Sikeres beküldés, ${res.totalNewQuestions} új kérdés`
+ )
+ rmTest(subjName, testName).then((res) => {
+ if (res.res === 'ok') {
+ router.back()
+ onDelete()
+ }
+ })
+ } else {
+ alert('Hiba beküldés közben :/')
+ }
+ })
+ }
+ }}
+ >
+ Teszt mentése
+
+
+ )
+ }
+
+ return (
+
+
+
+
Tárgy neve
+
{test.subj}
+
+
+
Teszt URL
+
{test.testUrl}
+
+
+
Beküldő felhasználó ID
+
{test.userid}
{' '}
+
+
+
Beküldés ideje
+
{new Date(test.date).toLocaleString()}
{' '}
+
+
+
+ {renderActions()}
+
+ {test.questions.map((question, i) => {
+ return (
+
+
+
+
{
+ setTest({
+ ...test,
+ questions: test.questions.map((q, j) => {
+ if (j === i) {
+ return newQ
+ }
+ return q
+ }),
+ })
+ }}
+ question={question}
+ />
+
+
{
+ setTest({
+ ...test,
+ questions: test.questions.filter((q, j) => {
+ return j !== i
+ }),
+ })
+ }}
+ >
+ Kérdés törlése
+
+
+
+
+ )
+ })}
+
+ {test.questions.length > 2 ? (
+ <>
+
+ {renderActions()}
+ >
+ ) : null}
+
+ )
+}
diff --git a/src/components/testView.module.css b/src/components/testView.module.css
new file mode 100644
index 0000000..16a2b91
--- /dev/null
+++ b/src/components/testView.module.css
@@ -0,0 +1,46 @@
+.headerContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.header {
+ display: flex;
+}
+
+.header:hover {
+ background-color: #444;
+}
+
+.header :first-child {
+ color: white;
+ flex: 0 170px;
+ text-align: right;
+}
+
+.header > * {
+ margin: 0px 5px;
+}
+
+.questionsContainer > div {
+ padding: 20px 0px;
+}
+
+.actions {
+ display: flex;
+ justify-content: space-around;
+}
+
+.actions > div {
+ cursor: pointer;
+ padding: 5px 20px;
+
+ color: #eee;
+ border: 1px solid #555;
+ border-radius: 3px;
+ user-select: none;
+}
+
+.actions > div:hover {
+ background-color: #444;
+ color: white;
+}
diff --git a/src/constants.json b/src/constants.json
index 3465eed..9cc2871 100644
--- a/src/constants.json
+++ b/src/constants.json
@@ -1,4 +1,5 @@
{
- "apiUrl": "https://api.frylabs.net/",
+ "apiUrl": "http://localhost:8080/",
+ "siteUrl": "http://localhost:8080/",
"maxQuestionsToRender": 250
}
diff --git a/src/pages/_app.js b/src/pages/_app.js
index 4d54978..54eda57 100644
--- a/src/pages/_app.js
+++ b/src/pages/_app.js
@@ -1,11 +1,10 @@
// import App from 'next/app'
+import React from 'react'
import '../defaultStyles.css'
-function MyApp ({ Component, pageProps, router }) {
- return (
-
- )
+function MyApp({ Component, pageProps, router }) {
+ return
}
// Only uncomment this method if you have blocking data requirements for
diff --git a/src/pages/index.js b/src/pages/index.js
index 05e74f7..0057ffa 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -1,37 +1,118 @@
import React, { useState, useEffect } from 'react'
-import fetch from 'unfetch'
+import Head from 'next/head'
import SubjectView from '../components/subjectView'
import QuestionView from '../components/questionView'
import QuestionAdder from '../components/questionAdder.js'
+import PossibleAnswers from '../components/possibleAnswers.js'
+
+import DbSelector from '../components/dbSelector.js'
import LoadingIndicator from '../components/LoadingIndicator'
import styles from './index.module.css'
+import commonStyles from '../commonStyles.module.css'
import constants from '../constants.json'
-const views = {
- welcome: 'WELCOME',
- subject: 'SUBJECT',
- question: 'QUESTION',
- questionAdder: 'QADDER',
+const Infos = ({ onClick, renderOKButton }) => {
+ return (
+
+
Kérdés szerkesztő
+
+ Ezen az oldalon az éles adatbázisban levő kérdéseket tudod szerkeszteni,
+ vagy azokhoz tudsz adni.{' '}
+
+ A törléshez és módosításokhoz nem kér megerősítést, ezek azonnal
+ megtörténnek, és nem visszavonhatóak.
+
+
+
+
Néhány dolog, amit kérlek tarts be szerkesztés közben:
+
+
+
+ Ne rontsd el a kérdéseket sok törléssel / rossz válasz
+ megadásával. Sok más felhasználónak lesz rossz, és visszakereshető
+ / tiltható a módosító
+
+
+ Arra is vigyázz, hogy véletlen se történjen ilyesmi, vagy ha mégis
+ valami baj történt, akkor azt{' '}
+ jelezd . Van sok biztonsági
+ mentés
+
+
+ Ahhoz, hogy a script megtalálja a helyes választ a kérdés
+ szövegének pontosan olyannak kell lennie, mint a teszt
+ közben (elírásokkal, .... -okkal, meg mindennel)
+
+
+
+
+
+ {renderOKButton && (
+
+ OK
+
+ )}
+
+ )
}
-// TODO: Add question on subjects view
-// TODO: Add subject on subjects view
-// TODO: question.data editor
-// TODO: edit \n-s in questions / answers
+const fetchDbs = () => {
+ return new Promise((resolve) => {
+ fetch(`${constants.apiUrl}getdbs`, {
+ credentials: 'include',
+ })
+ .then((resp) => {
+ return resp.json()
+ })
+ .then((resp) => {
+ resolve(resp)
+ })
+ })
+}
-export default function Index() {
+const fetchData = (selectedDb) => {
+ return new Promise((resolve) => {
+ const toFetch = `${constants.apiUrl}${selectedDb.path}`
+ fetch(toFetch, {
+ credentials: 'include',
+ })
+ .then((resp) => {
+ return resp.json()
+ })
+ .then((resp) => {
+ resolve(resp)
+ })
+ })
+}
+
+const views = {
+ welcome: 'w',
+ subject: 's',
+ question: 'q',
+ questionAdder: 'qa',
+ possibleAnswers: 'pa',
+}
+
+export default function Index({ router }) {
+ const [infoRead, setInfoRead] = useState(false)
const [data, setData] = useState(null)
const [qdbs, setQdbs] = useState(null)
const [selectedDb, setSelectedDb] = useState()
const [view, setView] = useState(views.welcome)
- const [sending, setSending] = useState(false)
- const [error, setError] = useState(null)
- const [password, setPassword] = useState('')
- const [editedQuestions, setEditedQuestions] = useState({})
- const [initialCount, setInitialCount] = useState({})
+ const [error, setError] = useState(null)
useEffect(() => {
if (selectedDb) {
@@ -39,25 +120,16 @@ export default function Index() {
}
}, [selectedDb])
- const getCount = (data) => {
- return {
- subjectCount: data.length,
- questionCount: data.reduce((acc, subj) => {
- acc += subj.Questions.length
- return acc
- }, 0),
- }
- }
+ useEffect(() => {
+ fetchDbs().then((resp) => {
+ setQdbs(resp)
- const setIndexes = (data) => {
- data.forEach((subj, i) => {
- subj.ind = i
- subj.Questions.forEach((question, j) => {
- question.ind = j
- })
+ const view = router.query.v
+ ? decodeURIComponent(router.query.v)
+ : views.welcome
+ setView(view)
})
- return data
- }
+ }, [])
const loadData = () => {
setData(null)
@@ -66,18 +138,9 @@ export default function Index() {
return
}
- const toFetch = `${constants.apiUrl}${selectedDb.path}`
- console.info('Fetching', toFetch)
- fetch(toFetch, {
- credentials: 'include',
- })
+ fetchData(selectedDb)
.then((resp) => {
- return resp.json()
- })
- .then((resp) => {
- setData(setIndexes(resp))
- const count = getCount(resp)
- setInitialCount(count)
+ setData(resp)
})
.catch((error) => {
console.error(error)
@@ -86,240 +149,162 @@ export default function Index() {
})
}
- useEffect(() => {
- fetch(`${constants.apiUrl}getdbs`, {
- credentials: 'include',
- })
- .then((resp) => {
- return resp.json()
+ const refetchDbs = () => {
+ if (selectedDb) {
+ fetchData(selectedDb).then((resp) => {
+ setData(resp)
})
- .then((resp) => {
- setQdbs(resp)
- })
- }, [])
-
- if (error) {
- return {error}
- }
-
- const deleteQuestion = (subjInd, questionInd) => {
- data[subjInd].Questions.splice(questionInd, 1)
-
- setData([...setIndexes(data)])
- }
-
- const onChange = (subjInd, questionInd, newVal) => {
- const key = subjInd + '/' + questionInd
- setEditedQuestions({
- ...editedQuestions,
- [key]: editedQuestions[key] ? editedQuestions[key] + 1 : 1,
- })
-
- data[subjInd].Questions[questionInd] = newVal
- setData([...data])
- }
-
- const SendDataToServer = async () => {
- if (sending) {
- alert('Adatok már feltöltés alatt, várd meg míg feltölti') // eslint-disable-line
- return
}
-
- data.forEach((subj) => {
- delete subj.ind
- subj.Questions.forEach((question) => {
- delete question.ind
- })
+ fetchDbs().then((resp) => {
+ setQdbs(resp)
})
+ }
- setSending(true)
- try {
- const rawResponse = await fetch(constants.apiUrl + 'uploaddata', {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- },
- credentials: 'include',
- body: JSON.stringify({
- newData: data,
- count: getCount(data),
- initialCount: initialCount,
- password: password,
- editedQuestions: editedQuestions,
- }),
- })
- rawResponse
- .json()
- .then((resp) => {
- setSending(false)
- if (resp.status === 'ok') {
- alert(`Sikeres feltöltés! thankx ${resp.user}!`) // eslint-disable-line
- console.log('OK')
- loadData()
- } else if (resp.status === 'invalidPass') {
- alert('Hibás jelszó!') // eslint-disable-line
- console.log('invalidPass')
- } else {
- alert(
- 'Hiba feltöltés közben! (szerver oldalon)! Több adat konzolban'
- ) // eslint-disable-line
- console.error('RESPONSE', resp)
- console.error(resp.message)
- }
- })
- .catch((error) => {
- setSending(false)
- alert('Hiba feltöltés közben! (kliens oldalon)! Több adat konzolban') // eslint-disable-line
- console.error('Error posting data', error)
- })
- } catch (error) {
- setSending(false)
- alert('Hiba feltöltés közben! (kliens oldalon)! Több adat konzolban') // eslint-disable-line
- console.error('Error posting data', error)
- }
+ const onQuestionDelete = (deletedQuestions) => {
+ console.log(deletedQuestions)
+ }
+
+ const onQuestionChange = (newVal, subjName, questionIndex) => {
+ console.log(newVal, subjName, questionIndex)
}
const renderView = () => {
if (view === views.subject) {
return (
-
+ <>
+
+ Tárgyak - Data Editor | Frylabs.net
+
+
+ {data && }
+ >
)
} else if (view === views.question) {
return (
-
+ <>
+
+ Kérdések - Data Editor | Frylabs.net
+
+
+ {data && (
+
+ )}
+ >
)
} else if (view === views.questionAdder) {
- return
- } else if (view === views.welcome) {
return (
-
- Kérdés szerkesztő
-
- {initialCount.questionCount || '...'} kérdés,{' '}
- {initialCount.subjectCount || '...'} tárgy
-
- Itt az éles adatbázis kérdései jelennek meg, amiket tudsz
- szerkeszteni. A kérdésekhez tartozó .data prop-ot még nem tudod
- rendesen szerkeszteni, az később lesz implementálva. A Tárgy / Kérdés
- nézet között tudsz válogatni.
-
- Tárgy nézet: a tárgyak dobozban kattints egy tárgyra, minden kérdés
- ott lessz hozzá.
-
- Kérdés nézet: Kereső sávba írd be a kérdést / választ, a találatok ha
- kevesebb mint 250 megjelennek, és ott tudod szerkeszteni
-
+ <>
+
+ Kérdés beküldés - Data Editor | Frylabs.net
+
+
+
+ >
)
+ } else if (view === views.possibleAnswers) {
+ return (
+ <>
+
+ Kitöltetlen tesztek - Data Editor | Frylabs.net
+
+
+ >
+ )
+ } else if (view === views.welcome) {
+ return
} else {
return No view!
}
}
- const renderDbSelector = () => {
+ function renderViewSelector() {
return (
- <>
- {
- setSelectedDb(qdbs[event.target.value])
+
+
{
+ router.replace(
+ `${router.pathname}?v=${views.question}`,
+ undefined,
+ { shallow: true }
+ )
+ setView(views.question)
}}
>
-
- {' -- Válassz egy kérdés adatbázist -- '}
-
- {qdbs.map((qdb, i) => {
- return (
-
- {qdb.name}
-
+ Kérdések
+
+
{
+ router.replace(`${router.pathname}?v=${views.subject}`, undefined, {
+ shallow: true,
+ })
+ setView(views.subject)
+ }}
+ >
+ Tárgyak
+
+
{
+ router.replace(
+ `${router.pathname}?v=${views.questionAdder}`,
+ undefined,
+ { shallow: true }
)
- })}
-
- >
+ setView(views.questionAdder)
+ }}
+ >
+ Kérdés beküldés
+
+
{
+ router.replace(
+ `${router.pathname}?v=${views.possibleAnswers}`,
+ undefined,
+ { shallow: true }
+ )
+ setView(views.possibleAnswers)
+ }}
+ >
+ Kitöltetlen tesztek
+
+
)
}
+ if (error) {
+ return {error}
+ }
+
+ if (!infoRead) {
+ return setInfoRead(true)} renderOKButton />
+ }
+
if (!qdbs) {
return
}
return (
- {renderDbSelector()}
-
- {
- loadData()
- }}
- >
- Újratöltés
-
-
- {
- setPassword(event.target.value)
- }}
- />
-
- {
- if (password && selectedDb) {
- SendDataToServer()
- } else {
- alert('Nincs jelszó, vagy nem választottál ki adatbázist!') // eslint-disable-line
- }
- }}
- >
- {sending ? 'Feltöltés ...' : 'Mentés'}
-
-
-
- {
- if (selectedDb) {
- setView(views.question)
- } else {
- alert('Válassz egy adatbázist!')
- }
- }}
- >
- Kérdés nézet
-
- {
- if (selectedDb) {
- setView(views.subject)
- } else {
- alert('Válassz egy adatbázist!')
- }
- }}
- >
- Tárgy nézet
-
- {
- setView(views.questionAdder)
- }}
- >
- Kérdés beküldés
-
-
+ {renderViewSelector()}
{renderView()}
)
diff --git a/src/pages/index.module.css b/src/pages/index.module.css
index fb795df..07d2fc0 100644
--- a/src/pages/index.module.css
+++ b/src/pages/index.module.css
@@ -1,57 +1,32 @@
-.viewButtonContainer span {
+.viewButtonContainer {
+ display: flex;
+}
+
+.viewButtonContainer div {
cursor: pointer;
display: inline-block;
- margin: 5px;
+ margin: 0px 2px;
padding: 10px;
font-size: 18px;
width: 25%;
text-align: center;
border-color: var(--background-color);
border: 1px solid;
+ border-radius: 3px;
}
-.optionsButtonContainer span {
- cursor: pointer;
- display: inline-block;
- margin: 3px;
- padding: 3px;
- height: 25px;
- font-size: 18px;
- width: 26%;
- text-align: center;
- border-color: var(--background-color);
- border: 1px solid;
- word-wrap: none;
-}
-
-.optionsButtonContainer span input {
- width: 95%;
- font-size: 16px;
- background-color: var(--background-color);
+.viewButtonContainer div:hover {
+ border-color: white;
color: white;
- border: 0px solid;
-}
-
-.optionsButtonContainer span:hover {
- border-color: white;
-}
-
-.viewButtonContainer span:hover {
- border-color: white;
-}
-
-.optionsButtonContainer {
- text-align: center;
- width: 100%;
-}
-
-.viewButtonContainer {
- text-align: center;
- width: 100%;
}
.welcome {
+ padding: 5px;
text-align: center;
font-size: 18px;
color: white;
}
+
+.activeView {
+ color: #99f;
+}