Home page and pw request page refactor

This commit is contained in:
mrfry 2020-11-17 12:48:05 +01:00
parent f159b9379c
commit 0ea9ecb5a3
6 changed files with 191 additions and 212 deletions

View file

@ -1,14 +1,14 @@
{ {
"install": { "install": {
"href": "install", "href": "/install",
"text": "Install" "text": "Install"
}, },
"allqr": { "allqr": {
"href": "allqr.txt", "href": "/allqr.txt",
"text": "Összes kérdés TXT" "text": "Összes kérdés TXT"
}, },
"data": { "data": {
"href": "data.json", "href": "/data.json",
"text": "Összes kérdés JSON" "text": "Összes kérdés JSON"
} }
} }

View file

@ -10,11 +10,11 @@ const getDefaultQuestion = () => {
return { return {
Q: '', Q: '',
A: '', A: '',
data: { type: 'simple' } data: { type: 'simple' },
} }
} }
export default function AddQuestion (props) { export default function AddQuestion(props) {
const [form, setForm] = useState({ quiz: [getDefaultQuestion()] }) const [form, setForm] = useState({ quiz: [getDefaultQuestion()] })
const [subjects, setSubjects] = useState(undefined) const [subjects, setSubjects] = useState(undefined)
const [isSubmitting, setIsSubmitting] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false)
@ -23,7 +23,7 @@ export default function AddQuestion (props) {
useEffect(() => { useEffect(() => {
console.info('Fetching subject names') console.info('Fetching subject names')
fetch(`${constants.apiUrl}dataCount?detailed=true`, { fetch(`${constants.apiUrl}dataCount?detailed=true`, {
credentials: 'include' credentials: 'include',
}) })
.then((resp) => { .then((resp) => {
return resp.json() return resp.json()
@ -43,7 +43,7 @@ export default function AddQuestion (props) {
setForm({ setForm({
...form, ...form,
quiz: quiz quiz: quiz,
}) })
} }
@ -54,40 +54,37 @@ export default function AddQuestion (props) {
return ( return (
<div className={styles.questionContainer}> <div className={styles.questionContainer}>
<div <div className={styles.inputContainer}>
className={styles.inputContainer}
>
<input <input
placeholder='Kérdés...' placeholder="Kérdés..."
type='text' type="text"
onChange={e => onChange({ ...currData, Q: e.target.value }, index)} onChange={(e) =>
onChange({ ...currData, Q: e.target.value }, index)
}
value={Q || ''} value={Q || ''}
className={styles.questionInput} className={styles.questionInput}
/> />
</div> </div>
<div <div className={styles.inputContainer}>
className={styles.inputContainer}
>
<input <input
placeholder='Válasz...' placeholder="Válasz..."
type='text' type="text"
onChange={e => onChange({ ...currData, A: e.target.value }, index)} onChange={(e) =>
onChange({ ...currData, A: e.target.value }, index)
}
value={A || ''} value={A || ''}
className={styles.questionInput} className={styles.questionInput}
/> />
</div> </div>
<div <div className={styles.inputContainer}>
className={styles.inputContainer}
>
<input <input
type='text' type="text"
onChange={e => { onChange={(e) => {
// TODO: handle JSON // TODO: handle JSON
// try { // try {
// let newData = JSON.parse(e.target.value) // let newData = JSON.parse(e.target.value)
// onChange({ ...currData, data: newData }, index) // onChange({ ...currData, data: newData }, index)
// } catch (e) { // } catch (e) {
// } // }
}} }}
value={JSON.stringify(data) || ''} value={JSON.stringify(data) || ''}
@ -112,7 +109,7 @@ export default function AddQuestion (props) {
setForm({ setForm({
...form, ...form,
quiz: quiz quiz: quiz,
}) })
} }
@ -143,17 +140,18 @@ export default function AddQuestion (props) {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
headers: { headers: {
'Accept': 'application/json', Accept: 'application/json',
'Content-Type': 'application/json' 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
...form, ...form,
id: cid, id: cid,
version: 'WEBSITE', version: 'WEBSITE',
scriptVersion: version scriptVersion: version,
}),
}) })
}) rawResponse
rawResponse.json() .json()
.then((resp) => { .then((resp) => {
if (resp.success) { if (resp.success) {
alert('Sikeres beküldés, ' + resp.newQuestions + ' új kérdés') // eslint-disable-line alert('Sikeres beküldés, ' + resp.newQuestions + ' új kérdés') // eslint-disable-line
@ -179,12 +177,12 @@ export default function AddQuestion (props) {
<div key={i}> <div key={i}>
{renderQuestionInput({ {renderQuestionInput({
index: i, index: i,
onChange onChange,
})} })}
</div> </div>
) )
})} })}
<div className={styles.buttonContainer} > <div className={styles.buttonContainer}>
<button <button
className={styles.button} className={styles.button}
onClick={() => { onClick={() => {
@ -192,32 +190,26 @@ export default function AddQuestion (props) {
quiz.push(getDefaultQuestion()) quiz.push(getDefaultQuestion())
setForm({ setForm({
...form, ...form,
quiz: quiz quiz: quiz,
}) })
}} }}
> >
Új kérdés hozzáadása Új kérdés hozzáadása
</button> </button>
</div> </div>
{isSubmitting {isSubmitting ? (
? <div className={styles.issubmitting}> <div className={styles.issubmitting}>
Kérdések feldolgozása folyamatban, ha sokat küldtél, akkor több perc is lehet Kérdések feldolgozása folyamatban, ha sokat küldtél, akkor több perc
is lehet
</div> </div>
: <div className={styles.buttonContainer} > ) : (
<button <div className={styles.buttonContainer}>
className={styles.button} <button className={styles.button} onClick={handleSubmit}>
onClick={handleSubmit}
>
Kérdések beküldése Kérdések beküldése
</button> </button>
</div> </div>
} )}
<input <input type="text" id="cid" name="cid" hidden />
type='text'
id='cid'
name='cid'
hidden
/>
</div> </div>
) )
} }
@ -226,43 +218,47 @@ export default function AddQuestion (props) {
// TODO: handle if new subject // TODO: handle if new subject
return ( return (
<div className={styles.subjSelectorContainer}> <div className={styles.subjSelectorContainer}>
{isNewSubj {isNewSubj ? (
? <input <input
placeholder='Új tárgy neve...' placeholder="Új tárgy neve..."
type='text' type="text"
className={styles.questionInput} className={styles.questionInput}
onChange={(e) => { onChange={(e) => {
setForm({ setForm({
...form, ...form,
subj: e.target.value subj: e.target.value,
}) })
}} /> }}
: <select />
) : (
<select
className={styles.subjSelector} className={styles.subjSelector}
onChange={(e) => { onChange={(e) => {
setForm({ setForm({
...form, ...form,
subj: subjects[e.target.value] subj: subjects[e.target.value],
}) })
}}> }}
<option key={-1} value={-1}>Válassz egy tárgyat...</option> >
<option key={-1} value={-1}>
Válassz egy tárgyat...
</option>
{props.subjects.map((subjName, i) => { {props.subjects.map((subjName, i) => {
return ( return (
<option key={i} value={i}>{subjName}</option> <option key={i} value={i}>
{subjName}
</option>
) )
})} })}
</select> </select>
)}
}
<span <span
className={styles.newSubj} className={styles.newSubj}
onClick={() => { setIsNewSubj(!isNewSubj) }} onClick={() => {
setIsNewSubj(!isNewSubj)
}}
> >
{isNewSubj {isNewSubj ? 'Létező tárgy ...' : 'Új tárgy ...'}
? 'Létező tárgy ...'
: 'Új tárgy ...'
}
</span> </span>
</div> </div>
) )
@ -270,31 +266,28 @@ export default function AddQuestion (props) {
const renderUsage = () => { const renderUsage = () => {
return ( return (
<ul className={styles.usage} > <ul className={styles.usage}>
<li>Ezen az oldalon kérdéseket tudsz beküldeni manuálisan.</li>
<li>Ezek a kérdések ellenőrizve lesznek hogy megvannak-e már</li>
<li> <li>
Ezen az oldalon kérdéseket tudsz beküldeni manuálisan. Ha több válasz van, akkor ', '-vel válaszd el őket ( "válasz1,
válasz2, válasz3" )
</li> </li>
<li> <li>
Ezek a kérdések ellenőrizve lesznek hogy megvannak-e már 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
</li> </li>
<li> <li>
Ha több válasz van, akkor ', '-vel válaszd el őket ( "válasz1, válasz2, válasz3" ) Ha sok új kérdést küldsze 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
</li> </li>
<li> <li>
Kérdéseknél az utolsó sor (ahol a JSON cucc van) jelenleg nem módosítható, csak olyan Bármilyen szöveget beküldhettek, de ne tegyétek, más felhasználóknak
kérdéseket lehet beküldeni, amik sima kérdés-válaszok, szóval pl nincs benne kép. Ez és magatoknak lesz rosz, ty!
később bővül majd
</li>
<li>
Ha sok új kérdést küldsze 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
</li>
<li>
Bármilyen szöveget beküldhettek, de ne tegyétek, más felhasználóknak és magatoknak lesz
rosz, ty!
</li> </li>
</ul> </ul>
) )
} }
@ -308,8 +301,6 @@ export default function AddQuestion (props) {
</div> </div>
) )
} else { } else {
return ( return <LoadingIndicator />
<LoadingIndicator />
)
} }
} }

View file

@ -10,10 +10,10 @@ const results = {
success: 'SUCCESS', success: 'SUCCESS',
error: 'ERROR', error: 'ERROR',
notSent: 'NOTSENT', notSent: 'NOTSENT',
invalid: 'INVALID' invalid: 'INVALID',
} }
export default function Feedback (props) { export default function Feedback(props) {
const [form, setForm] = useState({}) const [form, setForm] = useState({})
const [file, setFile] = useState(undefined) const [file, setFile] = useState(undefined)
const [result, setResult] = useState(results.notSent) const [result, setResult] = useState(results.notSent)
@ -22,18 +22,16 @@ export default function Feedback (props) {
const onChange = (e) => { const onChange = (e) => {
setForm({ setForm({
...form, ...form,
[e.target.name]: e.target.value [e.target.name]: e.target.value,
}) })
} }
const renderTextInputArea = (params) => { const renderTextInputArea = (params) => {
return ( return (
<div className={styles.inputArea}> <div className={styles.inputArea}>
<div className={styles.textTitle}> <div className={styles.textTitle}>{params.text}</div>
{params.text}
</div>
<textarea <textarea
onChange={e => params.onChange(e)} onChange={(e) => params.onChange(e)}
value={form[params.name] || ''} value={form[params.name] || ''}
className={styles.feedback} className={styles.feedback}
name={params.name} name={params.name}
@ -45,7 +43,7 @@ export default function Feedback (props) {
const onFileChangeHandler = (e) => { const onFileChangeHandler = (e) => {
setForm({ setForm({
...form, ...form,
file: e.target.files[0].name file: e.target.files[0].name,
}) })
setFile(e.target.files[0]) setFile(e.target.files[0])
} }
@ -53,13 +51,11 @@ export default function Feedback (props) {
const renderFileUploader = () => { const renderFileUploader = () => {
return ( return (
<div className={styles.inputArea}> <div className={styles.inputArea}>
<div className={styles.textTitle}> <div className={styles.textTitle}>Fájl csatolása</div>
Fájl csatolása
</div>
<input <input
className={styles.fileInput} className={styles.fileInput}
type='file' type="file"
name='file' name="file"
onChange={onFileChangeHandler} onChange={onFileChangeHandler}
/> />
</div> </div>
@ -83,16 +79,17 @@ export default function Feedback (props) {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
headers: { headers: {
'Accept': 'application/json', Accept: 'application/json',
'Content-Type': 'application/json' 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
...form, ...form,
cid: cid, cid: cid,
version: version version: version,
}),
}) })
}) rawResponse
rawResponse.json() .json()
.then((resp) => { .then((resp) => {
if (resp.success) { if (resp.success) {
setResult(results.success) setResult(results.success)
@ -110,15 +107,19 @@ export default function Feedback (props) {
const formData = new FormData() // eslint-disable-line const formData = new FormData() // eslint-disable-line
formData.append('file', file) formData.append('file', file)
const rawFileResponse = await fetch(constants.apiUrl + 'postfeedbackfile', { const rawFileResponse = await fetch(
constants.apiUrl + 'postfeedbackfile',
{
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
headers: { headers: {
'Accept': 'application/json' Accept: 'application/json',
}, },
body: formData body: formData,
}) }
rawFileResponse.json() )
rawFileResponse
.json()
.then((resp) => { .then((resp) => {
if (resp.success) { if (resp.success) {
setFileResult(results.success) setFileResult(results.success)
@ -136,23 +137,11 @@ export default function Feedback (props) {
const renderResult = () => { const renderResult = () => {
if (results === result.success) { if (results === result.success) {
return ( return <div>sucess</div>
<div>
sucess
</div>
)
} else if (results === result.error) { } else if (results === result.error) {
return ( return <div>error</div>
<div>
error
</div>
)
} else if (results === result.invalid) { } else if (results === result.invalid) {
return ( return <div>invalid</div>
<div>
invalid
</div>
)
} else { } else {
return null return null
} }
@ -161,57 +150,52 @@ export default function Feedback (props) {
// action={constants.apiUrl + 'badtestsender'} encType='multipart/form-data' method='post' // action={constants.apiUrl + 'badtestsender'} encType='multipart/form-data' method='post'
const renderForm = (props) => { const renderForm = (props) => {
return ( return (
<div className={styles.feedback} > <div className={styles.feedback}>
{props.noDesc {props.noDesc ? (
? <div className={styles.errorMsg}> <div className={styles.errorMsg}>Mező kitöltése kötelező!</div>
Mező kitöltése kötelező! ) : null}
</div>
: null}
{renderTextInputArea({ {renderTextInputArea({
text: 'Rövid leírás', text: 'Rövid leírás',
name: 'description', name: 'description',
onChange: onChange onChange: onChange,
})} })}
<div className={styles.desc}> <div className={styles.desc}>
Főoldalon lesz válasz (ha kell válasz) Főoldalon lesz válasz MOTD-ben, amit csak te látsz (ha kell
válasz)
</div> </div>
<div className={styles.buttonContainer} > <div className={styles.buttonContainer}>
<button <button className={styles.button} onClick={handleSubmit}>
className={styles.button}
onClick={handleSubmit}
>
Küldés Küldés
</button> </button>
</div> </div>
<hr /> <hr />
<div className={styles.desc}> <div className={styles.desc}>
Az alábbi mezők kitöltése opcionális, de hiba leírásnál nagyon sokat tud segíteni! <b> Az alábbi mezők kitöltése opcionális, de hiba leírásnál nagyon sokat
Legnagyobb segítség ha azt a kérdés oldalt és a hozzátartozó eredmények oldalt ahol nem tud segíteni!{' '}
helyesen működnek a dolgok Ctrl+S -el lemented, és egy zip-ben feltöltöd a .html <b>
fájlt!</b> Így egyszerűen reprodukálni tudom a hibát. TY! Legnagyobb segítség ha azt a kérdés oldalt és a hozzátartozó
eredmények oldalt ahol nem helyesen működnek a dolgok Ctrl+S -el
lemented, és egy zip-ben feltöltöd a .html fájlt!
</b>{' '}
Így egyszerűen reprodukálni tudom a hibát. TY!
</div> </div>
{renderTextInputArea({ {renderTextInputArea({
text: 'Lépések amikkel előáll a hiba', text: 'Lépések amikkel előáll a hiba',
name: 'steps', name: 'steps',
onChange: onChange onChange: onChange,
})} })}
{renderTextInputArea({ {renderTextInputArea({
text: 'Elvárt működés', text: 'Elvárt működés',
name: 'expected', name: 'expected',
onChange: onChange onChange: onChange,
})} })}
{renderTextInputArea({ {renderTextInputArea({
text: 'Ami történik helyette', text: 'Ami történik helyette',
name: 'current', name: 'current',
onChange: onChange onChange: onChange,
})} })}
{renderFileUploader()} {renderFileUploader()}
<input <input type="text" id="cid" name="cid" hidden />
type='text'
id='cid'
name='cid'
hidden
/>
{renderResult()} {renderResult()}
</div> </div>
) )
@ -220,32 +204,18 @@ export default function Feedback (props) {
const renderStuff = () => { const renderStuff = () => {
if (result === results.notSent && fileResult === results.notSent) { if (result === results.notSent && fileResult === results.notSent) {
console.log('both not sent') console.log('both not sent')
return ( return <div className={styles.textTitle}>{renderForm({})}</div>
<div className={styles.textTitle}>
{renderForm({})}
</div>
)
} else if (result === results.invalid) { } else if (result === results.invalid) {
console.log('result is invalid') console.log('result is invalid')
return ( return (
<div className={styles.textTitle}> <div className={styles.textTitle}>{renderForm({ noDesc: true })}</div>
{renderForm({ noDesc: true })}
</div>
) )
} else if (result === results.success && !file) { } else if (result === results.success && !file) {
console.log('text sucess, no file') console.log('text sucess, no file')
return ( return <div className={styles.textTitle}>Visszajelzés elküldve c:</div>
<div className={styles.textTitle}>
Visszajelzés elküldve c:
</div>
)
} else if (result === results.error && fileResult === results.success) { } else if (result === results.error && fileResult === results.success) {
console.log('file sucess only') console.log('file sucess only')
return ( return <div className={styles.textTitle}>Hiba küldés közben :c</div>
<div className={styles.textTitle}>
Hiba küldés közben :c
</div>
)
} else if (result === results.success && fileResult === results.error) { } else if (result === results.success && fileResult === results.error) {
console.log('text sucess only') console.log('text sucess only')
return ( return (
@ -255,23 +225,15 @@ export default function Feedback (props) {
) )
} else if (result === results.success && fileResult === results.success) { } else if (result === results.success && fileResult === results.success) {
console.log('both sucess') console.log('both sucess')
return ( return <div className={styles.textTitle}>Visszajelzés elküldve c:</div>
<div className={styles.textTitle}>
Visszajelzés elküldve c:
</div>
)
} else { } else {
return ( return <div className={styles.textTitle}>Bit of a fuckup here</div>
<div className={styles.textTitle}>
Bit of a fuckup here
</div>
)
} }
} }
return ( return (
<div> <div>
<Button text='IRC chat' href='/irc' /> <Button text="IRC chat" href="/irc" />
<p /> <p />
<hr /> <hr />
<p /> <p />

View file

@ -11,7 +11,7 @@ import styles from './index.module.css'
import links from '../data/links.json' import links from '../data/links.json'
import constants from '../constants.json' import constants from '../constants.json'
export default function Index(props) { export default function Index({ router }) {
const [motd, setMotd] = useState('loading...') const [motd, setMotd] = useState('loading...')
const [userSpecificMotd, setUserSpecificMotd] = useState('loading...') const [userSpecificMotd, setUserSpecificMotd] = useState('loading...')
const [news, setNews] = useState(null) const [news, setNews] = useState(null)
@ -100,7 +100,14 @@ export default function Index(props) {
}) })
.reverse() .reverse()
return <div className={styles.questionscontainer}>{questions}</div> return (
<div>
<div className={styles.title}>News</div>
<hr />
<hr />
<div className={styles.questionscontainer}>{questions}</div>
</div>
)
} else { } else {
return <LoadingIndicator /> return <LoadingIndicator />
} }
@ -109,7 +116,9 @@ export default function Index(props) {
const renderMotd = () => { const renderMotd = () => {
return ( return (
<div> <div>
<div className={styles.motdHeader}>MOTD:</div> <div className={styles.title}>MOTD</div>
<hr />
<hr />
<div <div
className={styles.motd} className={styles.motd}
dangerouslySetInnerHTML={{ __html: motd }} dangerouslySetInnerHTML={{ __html: motd }}
@ -134,20 +143,26 @@ export default function Index(props) {
return ( return (
<div> <div>
{renderMotd()} <div className={styles.buttonContainer}>
{userSpecificMotd && renderUserSpecificMotd()}
<center>
{Object.keys(links).map((key) => { {Object.keys(links).map((key) => {
let link = links[key] let link = links[key]
return ( return (
<span className="link" key={key}> <div
<a href={link.href}> className={styles.button}
<div className={styles.button}>{link.text}</div> key={key}
</a> onClick={() => {
</span> router.push(link.href)
}}
>
{link.text}
</div>
) )
})} })}
</center> </div>
<hr />
{renderMotd()}
{userSpecificMotd && renderUserSpecificMotd()}
<hr />
<Sleep /> <Sleep />
{renderNews()} {renderNews()}
</div> </div>

View file

@ -1,18 +1,24 @@
.button { .buttonContainer {
background-color: #9999ff; display: flex;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 5px;
} }
.motdHeader { .button {
flex: 1;
color: white;
background-color: #303030;
margin: 2px;
padding: 15px 32px;
text-align: center; text-align: center;
font-size: 24px; font-size: 16px;
cursor: pointer;
display: flex;
flex-direction: column;
justify-content: center;
}
.button:hover {
background-color: #555;
} }
.motd { .motd {
@ -35,6 +41,12 @@
color: #fff; color: #fff;
} }
.title {
color: #9999ff;
font-size: 30px;
text-align: center;
}
.newsTitle { .newsTitle {
font-size: 28px; font-size: 28px;
color: var(--text-color); color: var(--text-color);
@ -42,7 +54,7 @@
} }
.question { .question {
font-weight: "bold"; font-weight: 'bold';
font-size: 16px; font-size: 16px;
color: #fff; color: #fff;
margin: 0px 5px; margin: 0px 5px;

View file

@ -25,7 +25,6 @@ export default function PwRequest(props) {
return resp.json() return resp.json()
}) })
.then((data) => { .then((data) => {
console.log(data)
setRemaining(data.avaiblePWS) setRemaining(data.avaiblePWS)
setCreateDate(data.userCreated) setCreateDate(data.userCreated)
setRequestedPWS(data.requestedPWS) setRequestedPWS(data.requestedPWS)