added dynamic domain

This commit is contained in:
mrfry 2023-04-08 11:03:23 +02:00
parent 39dfd7a0f4
commit 5a665bc766
10 changed files with 1537 additions and 1455 deletions

View file

@ -12,38 +12,24 @@ module.exports = {
version: 'detect', version: 'detect',
}, },
}, },
plugins: ['react'],
extends: [ extends: [
'plugin:react/recommended', 'plugin:react/recommended',
'plugin:react/jsx-runtime', 'plugin:react/jsx-runtime',
'plugin:@next/next/recommended', 'plugin:@next/next/recommended',
], ],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
},
rules: { rules: {
'react/prop-types': 0, 'react/prop-types': 0,
'no-undef': ['error'], 'no-undef': ['error'],
eqeqeq: ['warn', 'smart'], eqeqeq: ['warn', 'smart'],
'react/jsx-uses-vars': 'error',
'react/jsx-uses-react': 'error',
'@next/next/no-img-element': 'off',
'no-unused-vars': 'warn', 'no-unused-vars': 'warn',
'no-prototype-builtins': 'off', 'no-prototype-builtins': 'off',
'id-length': [ 'id-length': [
'warn', 'warn',
{ { exceptions: ['x', 'i', 'j', 't', 'Q', 'A', 'C', 'q', 'a', 'b', 'e'] },
exceptions: [
'x',
'i',
'j',
't',
'Q',
'A',
'C',
'q',
'a',
'b',
'e',
],
},
], ],
}, },
root: true, root: true,

View file

@ -2,7 +2,7 @@ import React from 'react'
import Questions from './Questions.js' import Questions from './Questions.js'
import constants from '../constants.json' import constants from '../constants.js'
const countReducer = (acc, subj) => { const countReducer = (acc, subj) => {
return acc + subj.Questions.length return acc + subj.Questions.length
@ -16,9 +16,14 @@ export default function QuestionSearchResult(props) {
if (searchTerm || edits.length > 0) { if (searchTerm || edits.length > 0) {
subjs = data.reduce((acc, subj) => { subjs = data.reduce((acc, subj) => {
const resultQuestions = subj.Questions.reduce((qacc, question, i) => { const resultQuestions = subj.Questions.reduce(
(qacc, question, i) => {
const unsaved = edits.some((e) => { const unsaved = edits.some((e) => {
if (e.subjName === subj.Name && e.index === i && e.type === 'edit') { if (
e.subjName === subj.Name &&
e.index === i &&
e.type === 'edit'
) {
return true return true
} }
}) })
@ -38,14 +43,18 @@ export default function QuestionSearchResult(props) {
if ( if (
searchTerm && searchTerm &&
question[key] && question[key] &&
question[key].toLowerCase().includes(searchTerm.toLowerCase()) question[key]
.toLowerCase()
.includes(searchTerm.toLowerCase())
) { ) {
qacc.push({ q: question }) qacc.push({ q: question })
return true return true
} }
}) })
return qacc return qacc
}, []) },
[]
)
if (resultQuestions.length > 0) { if (resultQuestions.length > 0) {
acc.push({ acc.push({
Name: subj.Name, Name: subj.Name,

View file

@ -4,7 +4,7 @@ import LoadingIndicator from '../components/LoadingIndicator'
import SearchBar from '../components/searchBar' import SearchBar from '../components/searchBar'
import TestView from '../components/testView' import TestView from '../components/testView'
import constants from '../constants.json' import constants from '../constants.js'
import styles from './possibleAnswers.module.css' import styles from './possibleAnswers.module.css'
const Infos = () => { const Infos = () => {
@ -12,14 +12,16 @@ const Infos = () => {
<div className={styles.infoContainer}> <div className={styles.infoContainer}>
<div> <div>
Itt azok a tesztek találhatók, amiknek a kitöltése után nem volt 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. ellenőrző oldal. A script így nem tudja, hogy melyik a helyes
De ha ti igen, akkor jelöljétek be / írjátok be, és mentsétek el. Így megoldás. De ha ti igen, akkor jelöljétek be / írjátok be, és
mikor legközelebb találkoztok a kérdéssel a script tudni fogja a helyes mentsétek el. Így mikor legközelebb találkoztok a kérdéssel a
választ. Ezzel másoknak is nagyon sokat segítetek. script tudni fogja a helyes választ. Ezzel másoknak is nagyon
sokat segítetek.
</div> </div>
<div> <div>
Jelenleg azok a tesztek is megjelennek itt, amiknek elérhető a teszt eredmény oldala, és meg is Jelenleg azok a tesztek is megjelennek itt, amiknek elérhető a
van hozzá a helyes válasz. A jövőben ezek ki lesznek automatikusan törölve. teszt eredmény oldala, és meg is van hozzá a helyes válasz. A
jövőben ezek ki lesznek automatikusan törölve.
</div> </div>
</div> </div>
) )
@ -98,7 +100,9 @@ export default function PossibleAnswers({ router, refetchDbs }) {
setCurrSubj(resp) setCurrSubj(resp)
setCurrSubjName(subj) setCurrSubjName(subj)
router.push( router.push(
`${router.pathname}?v=pa&subj=${encodeURIComponent(subj)}`, `${router.pathname}?v=pa&subj=${encodeURIComponent(
subj
)}`,
undefined, undefined,
{ shallow: true } { shallow: true }
) )
@ -107,7 +111,9 @@ export default function PossibleAnswers({ router, refetchDbs }) {
setCurrTest(resp) setCurrTest(resp)
setCurrTestName(test) setCurrTestName(test)
router.push( router.push(
`${router.pathname}?v=pa&subj=${encodeURIComponent( `${
router.pathname
}?v=pa&subj=${encodeURIComponent(
subj subj
)}&test=${encodeURIComponent(test)}`, )}&test=${encodeURIComponent(test)}`,
undefined, undefined,
@ -143,11 +149,12 @@ export default function PossibleAnswers({ router, refetchDbs }) {
onDelete={() => { onDelete={() => {
refetchDbs() refetchDbs()
setCurrTest(null) setCurrTest(null)
fetchSubject(currSubjName, savedQuestionsFileName).then( fetchSubject(
(resp) => { currSubjName,
savedQuestionsFileName
).then((resp) => {
setCurrSubj(resp) setCurrSubj(resp)
} })
)
}} }}
/> />
)} )}
@ -186,19 +193,30 @@ export default function PossibleAnswers({ router, refetchDbs }) {
onClick={() => { onClick={() => {
setCurrTestName(test.fname) setCurrTestName(test.fname)
router.push( router.push(
`${router.pathname}?v=pa&subj=${encodeURIComponent( `${
router.pathname
}?v=pa&subj=${encodeURIComponent(
currSubjName currSubjName
)}&test=${encodeURIComponent(test.fname)}`, )}&test=${encodeURIComponent(
test.fname
)}`,
undefined, undefined,
{ shallow: true } { shallow: true }
) )
fetchTest(currSubjName, test.fname).then((resp) => { fetchTest(
currSubjName,
test.fname
).then((resp) => {
setCurrTest(resp) setCurrTest(resp)
}) })
}} }}
> >
<div>{new Date(test.date).toLocaleString()}</div> <div>
{new Date(
test.date
).toLocaleString()}
</div>
<div>{test.userid}</div> <div>{test.userid}</div>
<div>{test.subj}</div> <div>{test.subj}</div>
<div>{test.testUrl}</div> <div>{test.testUrl}</div>
@ -213,13 +231,18 @@ export default function PossibleAnswers({ router, refetchDbs }) {
return ( return (
<> <>
<Infos /> <Infos />
<SearchBar value={searchTerm} onChange={(e) => setSearchTerm(e)} /> <SearchBar
value={searchTerm}
onChange={(e) => setSearchTerm(e)}
/>
<div className={styles.tableContainer}> <div className={styles.tableContainer}>
<> <>
<div>Tárgy neve</div> <div>Tárgy neve</div>
{subjects.map((subj, i) => { {subjects.map((subj, i) => {
if ( if (
!subj.name.toLowerCase().includes(searchTerm.toLowerCase()) !subj.name
.toLowerCase()
.includes(searchTerm.toLowerCase())
) { ) {
return null return null
} }
@ -229,18 +252,21 @@ export default function PossibleAnswers({ router, refetchDbs }) {
onClick={() => { onClick={() => {
setCurrSubjName(subj.name) setCurrSubjName(subj.name)
router.push( router.push(
`${router.pathname}?v=pa&subj=${encodeURIComponent( `${
router.pathname
}?v=pa&subj=${encodeURIComponent(
subj.name subj.name
)}`, )}`,
undefined, undefined,
{ shallow: true } { shallow: true }
) )
fetchSubject(subj.name, savedQuestionsFileName).then( fetchSubject(
(resp) => { subj.name,
savedQuestionsFileName
).then((resp) => {
setCurrSubj(resp) setCurrSubj(resp)
} })
)
}} }}
> >
{subj.name} {subj.name}

View file

@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react'
import Question from '../components/Question' import Question from '../components/Question'
import styles from './questionAdder.module.css' import styles from './questionAdder.module.css'
import constants from '../constants.json' import constants from '../constants.js'
import commonStyles from '../commonStyles.module.css' import commonStyles from '../commonStyles.module.css'
const handleSubmit = async (form) => { const handleSubmit = async (form) => {
@ -87,13 +87,13 @@ const renderUsage = () => {
kérdés-válaszok, szóval pl nincs benne kép. Ez később bővül majd 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 sok új kérdést küldesz be, akkor akár több percig is eltarthat a Ha sok új kérdést küldesz be, akkor akár több percig is
dolog. Akárhány kérdést be lehet egyszerre küldeni, de max 10-15 az eltarthat a dolog. Akárhány kérdést be lehet egyszerre küldeni,
ajánlott de max 10-15 az ajánlott
</li> </li>
<li> <li>
Bármilyen szöveget beküldhettek, de ne tegyétek, más felhasználóknak és Bármilyen szöveget beküldhettek, de ne tegyétek, más
magatoknak lesz rosz, ty! felhasználóknak és magatoknak lesz rosz, ty!
</li> </li>
</ul> </ul>
) )
@ -238,7 +238,9 @@ export default function QuestionAdder({ data, selectedDb, refetchDbs }) {
}) })
}} }}
> >
{isSubmitting ? 'Beküldés folyamatban ...' : 'Kérdések beküldése'} {isSubmitting
? 'Beküldés folyamatban ...'
: 'Kérdések beküldése'}
</div> </div>
</div> </div>
<input type="text" id="cid" name="cid" hidden /> <input type="text" id="cid" name="cid" hidden />

View file

@ -4,7 +4,7 @@ import LoadingIndicator from '../components/LoadingIndicator.js'
import QuestionSearchResult from '../components/QuestionSearchResult.js' import QuestionSearchResult from '../components/QuestionSearchResult.js'
import SearchBar from '../components/searchBar' import SearchBar from '../components/searchBar'
import constants from '../constants.json' import constants from '../constants.js'
// import styles from './questionView.module.css' // import styles from './questionView.module.css'
const updateQuestion = (e, selectedDb) => { const updateQuestion = (e, selectedDb) => {
@ -108,9 +108,11 @@ export default function questionView(props) {
} else { } else {
return { return {
...subj, ...subj,
Questions: subj.Questions.filter((question, i) => { Questions: subj.Questions.filter(
(question, i) => {
return i !== e.index return i !== e.index
}), }
),
} }
} }
}) })
@ -191,7 +193,10 @@ export default function questionView(props) {
if (data) { if (data) {
return ( return (
<div> <div>
<SearchBar value={searchTerm} onChange={(e) => setSearchTerm(e)} /> <SearchBar
value={searchTerm}
onChange={(e) => setSearchTerm(e)}
/>
<hr /> <hr />
<div> <div>
<QuestionSearchResult <QuestionSearchResult

View file

@ -5,7 +5,7 @@ import Subject from '../components/Subject.js'
import SubjectSelector from '../components/SubjectSelector.js' import SubjectSelector from '../components/SubjectSelector.js'
import SearchBar from '../components/searchBar' import SearchBar from '../components/searchBar'
import constants from '../constants.json' import constants from '../constants.js'
// import styles from './subjectView.module.css' // import styles from './subjectView.module.css'
import commonStyles from '../commonStyles.module.css' import commonStyles from '../commonStyles.module.css'
@ -169,7 +169,10 @@ export default function SubjectView(props) {
if (data) { if (data) {
return ( return (
<div> <div>
<SearchBar value={searchTerm} onChange={(e) => setSearchTerm(e)} /> <SearchBar
value={searchTerm}
onChange={(e) => setSearchTerm(e)}
/>
<hr /> <hr />
<SubjectSelector <SubjectSelector
data={data} data={data}

View file

@ -2,7 +2,7 @@ import React, { useState } from 'react'
import Question from '../components/Question' import Question from '../components/Question'
import constants from '../constants.json' import constants from '../constants.js'
import styles from './testView.module.css' import styles from './testView.module.css'
import commonStyles from '../commonStyles.module.css' import commonStyles from '../commonStyles.module.css'
@ -38,7 +38,11 @@ export default function TestView(props) {
<div className={styles.actions}> <div className={styles.actions}>
<div <div
onClick={() => { onClick={() => {
if (confirm('Biztos véglegesen törlöd ezt az egész tesztet?')) { if (
confirm(
'Biztos véglegesen törlöd ezt az egész tesztet?'
)
) {
rmTest(subjName, testName).then((res) => { rmTest(subjName, testName).then((res) => {
if (res.res === 'ok') { if (res.res === 'ok') {
// alert('sikeres törlés') // alert('sikeres törlés')
@ -97,12 +101,14 @@ export default function TestView(props) {
alert( alert(
`Sikeres beküldés, ${res.totalNewQuestions} új kérdés` `Sikeres beküldés, ${res.totalNewQuestions} új kérdés`
) )
rmTest(subjName, testName).then((res) => { rmTest(subjName, testName).then(
(res) => {
if (res.res === 'ok') { if (res.res === 'ok') {
router.back() router.back()
onDelete() onDelete()
} }
}) }
)
} else { } else {
alert('Hiba beküldés közben :/') alert('Hiba beküldés közben :/')
} }
@ -149,12 +155,14 @@ export default function TestView(props) {
onChange={(newQ) => { onChange={(newQ) => {
setTest({ setTest({
...test, ...test,
questions: test.questions.map((q, j) => { questions: test.questions.map(
(q, j) => {
if (j === i) { if (j === i) {
return newQ return newQ
} }
return q return q
}), }
),
}) })
}} }}
question={question} question={question}
@ -164,9 +172,12 @@ export default function TestView(props) {
onClick={() => { onClick={() => {
setTest({ setTest({
...test, ...test,
questions: test.questions.filter((q, j) => { questions:
test.questions.filter(
(q, j) => {
return j !== i return j !== i
}), }
),
}) })
}} }}
> >

19
src/constants.js Normal file
View file

@ -0,0 +1,19 @@
// eslint-disable-next-line no-undef
const useLocalhost = process && process.env.NODE_ENV === 'development'
// eslint-disable-next-line no-undef
const domain = process && process.env.DOMAIN
if (!domain && !useLocalhost) {
throw new Error('Domain is not defined! Please set DOMAIN env variable!')
}
const constants = {
domain: domain || 'localhost',
siteUrl: useLocalhost ? 'http://localhost:8080/' : `https://${domain}/`,
apiUrl: useLocalhost
? 'http://localhost:8080/api/'
: `https://${domain}/api/`,
maxQuestionsToRender: 250,
}
export default constants

View file

@ -1,5 +0,0 @@
{
"siteUrl": "https://qmining.frylabs.net/",
"apiUrl": "https://api.frylabs.net/",
"maxQuestionsToRender": 250
}

View file

@ -11,18 +11,18 @@ import LoadingIndicator from '../components/LoadingIndicator'
import styles from './index.module.css' import styles from './index.module.css'
import commonStyles from '../commonStyles.module.css' import commonStyles from '../commonStyles.module.css'
import constants from '../constants.json' import constants from '../constants.js'
const Infos = ({ onClick, renderOKButton }) => { const Infos = ({ onClick, renderOKButton }) => {
return ( return (
<div className={commonStyles.infoContainer}> <div className={commonStyles.infoContainer}>
<div className={commonStyles.infoHeader}>Kérdés szerkesztő</div> <div className={commonStyles.infoHeader}>Kérdés szerkesztő</div>
<div> <div>
Ezen az oldalon az éles adatbázisban levő kérdéseket tudod szerkeszteni, Ezen az oldalon az éles adatbázisban levő kérdéseket tudod
vagy azokhoz tudsz adni.{' '} szerkeszteni, vagy azokhoz tudsz adni.{' '}
<b> <b>
A törléshez és módosításokhoz nem kér megerősítést, ezek azonnal A törléshez és módosításokhoz nem kér megerősítést, ezek
megtörténnek, és nem visszavonhatóak. azonnal megtörténnek, és nem visszavonhatóak.
</b> </b>
</div> </div>
<div> <div>
@ -30,20 +30,21 @@ const Infos = ({ onClick, renderOKButton }) => {
<div style={{ textAlign: 'left', width: '700px' }}> <div style={{ textAlign: 'left', width: '700px' }}>
<ul> <ul>
<li> <li>
Ne rontsd el a kérdéseket sok törléssel / rossz válasz Ne rontsd el a kérdéseket sok törléssel / rossz
megadásával. Sok más felhasználónak lesz rossz, és visszakereshető válasz megadásával. Sok más felhasználónak lesz
/ tiltható a módosító rossz, és visszakereshető / tiltható a módosító
</li> </li>
<li> <li>
Arra is vigyázz, hogy véletlen se történjen ilyesmi, vagy ha mégis Arra is vigyázz, hogy véletlen se történjen ilyesmi,
valami baj történt, akkor azt{' '} vagy ha mégis valami baj történt, akkor azt{' '}
<a href={`${constants.siteUrl}irc`}>jelezd</a>. Van sok biztonsági <a href={`${constants.siteUrl}irc`}>jelezd</a>. Van
mentés sok biztonsági mentés
</li> </li>
<li> <li>
Ahhoz, hogy a script megtalálja a helyes választ a kérdés Ahhoz, hogy a script megtalálja a helyes választ a
szövegének <b>pontosan</b> olyannak kell lennie, mint a teszt kérdés szövegének <b>pontosan</b> olyannak kell
közben (elírásokkal, .... -okkal, meg mindennel) lennie, mint a teszt közben (elírásokkal, ....
-okkal, meg mindennel)
</li> </li>
</ul> </ul>
</div> </div>
@ -167,35 +168,45 @@ export default function Index({ router }) {
return ( return (
<> <>
<Head> <Head>
<title>Tárgyak - Data Editor | Frylabs.net</title> <title>
Tárgyak - Data Editor | {constants.domain}
</title>
</Head> </Head>
<DbSelector <DbSelector
qdbs={qdbs} qdbs={qdbs}
selectedDb={selectedDb} selectedDb={selectedDb}
onChange={setSelectedDb} onChange={setSelectedDb}
/> />
{data && <SubjectView selectedDb={selectedDb} data={data} />} {data && (
<SubjectView selectedDb={selectedDb} data={data} />
)}
</> </>
) )
} else if (view === views.question) { } else if (view === views.question) {
return ( return (
<> <>
<Head> <Head>
<title>Kérdések - Data Editor | Frylabs.net</title> <title>
Kérdések - Data Editor | {constants.domain}
</title>
</Head> </Head>
<DbSelector <DbSelector
qdbs={qdbs} qdbs={qdbs}
selectedDb={selectedDb} selectedDb={selectedDb}
onChange={setSelectedDb} onChange={setSelectedDb}
/> />
{data && <QuestionView selectedDb={selectedDb} data={data} />} {data && (
<QuestionView selectedDb={selectedDb} data={data} />
)}
</> </>
) )
} else if (view === views.questionAdder) { } else if (view === views.questionAdder) {
return ( return (
<> <>
<Head> <Head>
<title>Kérdés beküldés - Data Editor | Frylabs.net</title> <title>
Kérdés beküldés - Data Editor | {constants.domain}
</title>
</Head> </Head>
<DbSelector <DbSelector
hideLockedDbs hideLockedDbs
@ -214,7 +225,10 @@ export default function Index({ router }) {
return ( return (
<> <>
<Head> <Head>
<title>Kitöltetlen tesztek - Data Editor | Frylabs.net</title> <title>
Kitöltetlen tesztek - Data Editor |{' '}
{constants.domain}
</title>
</Head> </Head>
<PossibleAnswers refetchDbs={refetchDbs} router={router} /> <PossibleAnswers refetchDbs={refetchDbs} router={router} />
</> </>
@ -230,7 +244,9 @@ export default function Index({ router }) {
return ( return (
<div className={styles.viewButtonContainer}> <div className={styles.viewButtonContainer}>
<div <div
className={view === views.question ? styles.activeView : undefined} className={
view === views.question ? styles.activeView : undefined
}
onClick={() => { onClick={() => {
router.replace( router.replace(
`${router.pathname}?v=${views.question}`, `${router.pathname}?v=${views.question}`,
@ -246,11 +262,17 @@ export default function Index({ router }) {
title={ title={
'Választott adatbázisban lévő tárgyak megjelenítése, és tárgyakon belüli kérdések szerkesztése' 'Választott adatbázisban lévő tárgyak megjelenítése, és tárgyakon belüli kérdések szerkesztése'
} }
className={view === views.subject ? styles.activeView : undefined} className={
view === views.subject ? styles.activeView : undefined
}
onClick={() => { onClick={() => {
router.replace(`${router.pathname}?v=${views.subject}`, undefined, { router.replace(
`${router.pathname}?v=${views.subject}`,
undefined,
{
shallow: true, shallow: true,
}) }
)
setView(views.subject) setView(views.subject)
}} }}
> >
@ -258,7 +280,9 @@ export default function Index({ router }) {
</div> </div>
<div <div
className={ className={
view === views.questionAdder ? styles.activeView : undefined view === views.questionAdder
? styles.activeView
: undefined
} }
onClick={() => { onClick={() => {
router.replace( router.replace(
@ -274,7 +298,9 @@ export default function Index({ router }) {
</div> </div>
<div <div
className={ className={
view === views.possibleAnswers ? styles.activeView : undefined view === views.possibleAnswers
? styles.activeView
: undefined
} }
onClick={() => { onClick={() => {
router.replace( router.replace(