mirror of
				https://gitlab.com/MrFry/qmining-data-editor
				synced 2025-04-01 20:24:01 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			261 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import React, { useState, useEffect } from 'react'
 | |
| import fetch from 'unfetch'
 | |
| 
 | |
| import SubjectView from '../components/subjectView'
 | |
| import QuestionView from '../components/questionView'
 | |
| import LoadingIndicator from '../components/LoadingIndicator'
 | |
| 
 | |
| import styles from './index.module.css'
 | |
| import constants from '../constants.json'
 | |
| 
 | |
| const views = {
 | |
|   subject: 'SUBJECT',
 | |
|   question: 'QUESTION',
 | |
|   welcome: 'WELCOME',
 | |
| }
 | |
| 
 | |
| // TODO: Add question on subjects view
 | |
| // TODO: Add subject on subjects view
 | |
| // TODO: question.data editor
 | |
| // TODO: edit \n-s in questions / answers
 | |
| 
 | |
| export default function Index(props) {
 | |
|   const [data, setData] = useState(null)
 | |
|   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 getCount = (d) => {
 | |
|     return {
 | |
|       subjectCount: d.length,
 | |
|       questionCount: d.reduce((acc, subj) => {
 | |
|         acc += subj.Questions.length
 | |
|         return acc
 | |
|       }, 0),
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   const setIndexes = (d) => {
 | |
|     d.forEach((subj, i) => {
 | |
|       subj.ind = i
 | |
|       subj.Questions.forEach((question, j) => {
 | |
|         question.ind = j
 | |
|       })
 | |
|     })
 | |
|     return d
 | |
|   }
 | |
| 
 | |
|   const LoadData = () => {
 | |
|     setData(null)
 | |
|     const toFetch = `${constants.apiUrl}data.json`
 | |
|     console.info('Fetching', toFetch)
 | |
|     fetch(toFetch, {
 | |
|       credentials: 'include',
 | |
|     })
 | |
|       .then((resp) => {
 | |
|         if (resp && resp.ok) {
 | |
|           return resp.json()
 | |
|         } else {
 | |
|           console.error('Error while fetching data')
 | |
|           setError('Error while fetching data')
 | |
|         }
 | |
|       })
 | |
|       .then((resp) => {
 | |
|         setData(setIndexes(resp))
 | |
|         const count = getCount(resp)
 | |
|         setInitialCount(count)
 | |
|       })
 | |
|       .catch((e) => {
 | |
|         console.error(e)
 | |
|         console.error('Error while fetching data')
 | |
|         setError('Error while fetching data')
 | |
|       })
 | |
|   }
 | |
| 
 | |
|   useEffect(() => {
 | |
|     LoadData()
 | |
|   }, [])
 | |
| 
 | |
|   if (error) {
 | |
|     return <div>{error}</div>
 | |
|   }
 | |
| 
 | |
|   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
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     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((e) => {
 | |
|           setSending(false)
 | |
|           alert('Hiba feltöltés közben! (kliens oldalon)! Több adat konzolban') // eslint-disable-line
 | |
|           console.error('Error posting data', e)
 | |
|         })
 | |
|     } catch (e) {
 | |
|       setSending(false)
 | |
|       alert('Hiba feltöltés közben! (kliens oldalon)! Több adat konzolban') // eslint-disable-line
 | |
|       console.error('Error posting data', e)
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   const renderView = () => {
 | |
|     if (view === views.subject) {
 | |
|       return (
 | |
|         <SubjectView
 | |
|           onChange={onChange}
 | |
|           data={data}
 | |
|           deleteQuestion={deleteQuestion}
 | |
|         />
 | |
|       )
 | |
|     } else if (view === views.question) {
 | |
|       return (
 | |
|         <QuestionView
 | |
|           onChange={onChange}
 | |
|           data={data}
 | |
|           deleteQuestion={deleteQuestion}
 | |
|         />
 | |
|       )
 | |
|     } else if (view === views.welcome) {
 | |
|       return (
 | |
|         <div className={styles.welcome}>
 | |
|           Kérdés szerkesztő
 | |
|           <br />
 | |
|           {initialCount.questionCount || '...'} kérdés,{' '}
 | |
|           {initialCount.subjectCount || '...'} tárgy
 | |
|           <p />
 | |
|           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.
 | |
|           <br />
 | |
|           Tárgy nézet: a tárgyak dobozban kattints egy tárgyra, minden kérdés
 | |
|           ott lessz hozzá.
 | |
|           <br />
 | |
|           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
 | |
|         </div>
 | |
|       )
 | |
|     } else {
 | |
|       return <div>No view!</div>
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return (
 | |
|     <div>
 | |
|       <div className={styles.optionsButtonContainer}>
 | |
|         <span
 | |
|           onClick={() => {
 | |
|             LoadData()
 | |
|           }}
 | |
|         >
 | |
|           Újratöltés
 | |
|         </span>
 | |
|         <span>
 | |
|           <input
 | |
|             placeholder="Jelszó feltöltéshez"
 | |
|             type="text"
 | |
|             value={password}
 | |
|             onChange={(e) => {
 | |
|               setPassword(e.target.value)
 | |
|             }}
 | |
|           />
 | |
|         </span>
 | |
|         <span
 | |
|           onClick={() => {
 | |
|             if (password) {
 | |
|               SendDataToServer()
 | |
|             } else {
 | |
|               alert('Hibás jelszó!') // eslint-disable-line
 | |
|             }
 | |
|           }}
 | |
|         >
 | |
|           {sending ? 'Feltöltés ...' : 'Mentés'}
 | |
|         </span>
 | |
|       </div>
 | |
|       <div className={styles.viewButtonContainer}>
 | |
|         <span
 | |
|           onClick={() => {
 | |
|             setView(views.question)
 | |
|           }}
 | |
|         >
 | |
|           Kérdés nézet
 | |
|         </span>
 | |
|         <span
 | |
|           onClick={() => {
 | |
|             setView(views.subject)
 | |
|           }}
 | |
|         >
 | |
|           Tárgy nézet
 | |
|         </span>
 | |
|       </div>
 | |
|       {renderView()}
 | |
|     </div>
 | |
|   )
 | |
| }
 |