mirror of
https://gitlab.com/MrFry/qmining-data-editor
synced 2025-04-01 20:24:01 +02:00
Initial commit, with fully working project :p
This commit is contained in:
commit
53b4158967
21 changed files with 894 additions and 0 deletions
23
src/pages/_app.js
Normal file
23
src/pages/_app.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
// import App from 'next/app'
|
||||
|
||||
import '../defaultStyles.css'
|
||||
|
||||
function MyApp ({ Component, pageProps, router }) {
|
||||
return (
|
||||
<Component {...pageProps} />
|
||||
)
|
||||
}
|
||||
|
||||
// Only uncomment this method if you have blocking data requirements for
|
||||
// every single page in your application. This disables the ability to
|
||||
// perform automatic static optimization, causing every page in your app to
|
||||
// be server-side rendered.
|
||||
//
|
||||
// MyApp.getInitialProps = async (appContext) => {
|
||||
// // calls page's `getInitialProps` and fills `appProps.pageProps`
|
||||
// const appProps = await App.getInitialProps(appContext);
|
||||
//
|
||||
// return { ...appProps }
|
||||
// }
|
||||
|
||||
export default MyApp
|
22
src/pages/_document.js
Normal file
22
src/pages/_document.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps (ctx) {
|
||||
const initialProps = await Document.getInitialProps(ctx)
|
||||
return { ...initialProps }
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<body bgcolor='#212127'>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
136
src/pages/index.js
Normal file
136
src/pages/index.js
Normal file
|
@ -0,0 +1,136 @@
|
|||
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'
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Add question on subjects view
|
||||
// question.data editor
|
||||
// save data to server / load it from there
|
||||
// save: save question count and subj count
|
||||
// save deleted/removed questions ?
|
||||
// edit \n-s in questions / answers
|
||||
|
||||
export default function Index (props) {
|
||||
const [data, setData] = useState(null)
|
||||
const [view, setView] = useState(views.subject)
|
||||
|
||||
const setIndexes = (d) => {
|
||||
d.Subjects.forEach((subj, i) => {
|
||||
subj.ind = i
|
||||
subj.Questions.forEach((question, j) => {
|
||||
question.ind = j
|
||||
})
|
||||
})
|
||||
return d
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.info('Fetching data')
|
||||
fetch(`${constants.apiUrl}data.json`)
|
||||
.then((resp) => {
|
||||
return resp.json()
|
||||
})
|
||||
.then((resp) => {
|
||||
if (data) {
|
||||
console.warn('Tried to refetch data when it was still set!')
|
||||
} else {
|
||||
setData(setIndexes(resp))
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
const deleteQuestion = (subjInd, questionInd) => {
|
||||
data.Subjects[subjInd].Questions.splice(questionInd, 1)
|
||||
|
||||
setData({
|
||||
...setIndexes(data)
|
||||
})
|
||||
}
|
||||
|
||||
const onChange = (subjInd, questionInd, newVal) => {
|
||||
data.Subjects[subjInd].Questions[questionInd] = newVal
|
||||
setData({
|
||||
...data
|
||||
})
|
||||
}
|
||||
|
||||
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 {
|
||||
return (
|
||||
<div>
|
||||
No view!
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const downloadFile = async (data) => {
|
||||
const json = JSON.stringify(data)
|
||||
const blob = new Blob([json], { type: 'application/json' }) // eslint-disable-line
|
||||
const href = await URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = href
|
||||
link.download = 'data.json'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<LoadingIndicator />
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.buttonContainer}>
|
||||
<span
|
||||
className={styles.tabButton}
|
||||
onClick={() => { setView(views.subject) }}>
|
||||
Subject view
|
||||
</span>
|
||||
<span
|
||||
className={styles.tabButton}
|
||||
onClick={() => { setView(views.question) }}>
|
||||
Question view
|
||||
</span>
|
||||
<span
|
||||
className={styles.downloadButton}
|
||||
onClick={() => {
|
||||
downloadFile(data)
|
||||
}}
|
||||
>
|
||||
Download result
|
||||
</span>
|
||||
</div>
|
||||
{renderView()}
|
||||
</div>
|
||||
)
|
||||
}
|
33
src/pages/index.module.css
Normal file
33
src/pages/index.module.css
Normal file
|
@ -0,0 +1,33 @@
|
|||
.tabButton {
|
||||
display: inline-block;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
height: 45px;
|
||||
font-size: 30px;
|
||||
width: 25%;
|
||||
text-align: center;
|
||||
border-color: var(--background-color);
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
.downloadButton {
|
||||
display: inline-block;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
height: 45px;
|
||||
font-size: 30px;
|
||||
width: 26%;
|
||||
text-align: center;
|
||||
border-color: var(--background-color);
|
||||
border: 1px solid;
|
||||
word-wrap: none;
|
||||
}
|
||||
|
||||
.tabButton:hover {
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue