mirror of
https://gitlab.com/MrFry/qmining-page
synced 2025-04-01 20:23:44 +02:00
removed forum, todos, added p2p info page & lots of minor changes/fixes
This commit is contained in:
parent
32522097c0
commit
e2d304c130
28 changed files with 303 additions and 954 deletions
3
.babelrc
Normal file
3
.babelrc
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"presets": ["@babel/preset-react"]
|
||||||
|
}
|
|
@ -6,7 +6,15 @@ function highlightText(text, toHighlight) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const re = new RegExp(toHighlight, 'gi')
|
const re = new RegExp(toHighlight, 'gi')
|
||||||
return text.replace(re, `<mark>${toHighlight}</mark>`)
|
const splitText = text.split(toHighlight)
|
||||||
|
console.log(splitText)
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{splitText[0]}
|
||||||
|
<span style={{ color: '#99f' }}>{toHighlight}</span>
|
||||||
|
{splitText[1]}
|
||||||
|
</>
|
||||||
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
.groupDescription {
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.todoButtons {
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import TodoCard from './todoCard'
|
|
||||||
|
|
||||||
import styles from './todoBoard.module.css'
|
|
||||||
|
|
||||||
export default function TodoBoard(props) {
|
|
||||||
const { columns, cards, userId, categories, onCardClick, selectedGroup } =
|
|
||||||
props
|
|
||||||
|
|
||||||
const clickableTypes = Object.keys(columns).reduce((acc, key) => {
|
|
||||||
const col = columns[key]
|
|
||||||
if (col.clickable) {
|
|
||||||
acc.push(key)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.tableContainer}>
|
|
||||||
<div className={styles.table}>
|
|
||||||
{Object.keys(columns).map((key) => {
|
|
||||||
const category = columns[key]
|
|
||||||
const cardsToShow = cards.filter((card) => {
|
|
||||||
const shouldHide =
|
|
||||||
card.state !== key ||
|
|
||||||
(selectedGroup !== null &&
|
|
||||||
selectedGroup !== 'uncat' &&
|
|
||||||
card.group !== selectedGroup) ||
|
|
||||||
(selectedGroup === 'uncat' && card.group !== undefined)
|
|
||||||
|
|
||||||
return !shouldHide
|
|
||||||
})
|
|
||||||
return (
|
|
||||||
<div className={styles.tableCol} key={key}>
|
|
||||||
<div className={styles.categoryName}>{category.name}</div>
|
|
||||||
|
|
||||||
{cardsToShow.length === 0 && (
|
|
||||||
<div className={styles.empty}>Üres</div>
|
|
||||||
)}
|
|
||||||
{cardsToShow.map((card, i) => {
|
|
||||||
return (
|
|
||||||
<TodoCard
|
|
||||||
key={i}
|
|
||||||
cardData={card}
|
|
||||||
userId={userId}
|
|
||||||
categories={categories}
|
|
||||||
onClick={onCardClick}
|
|
||||||
clickable={clickableTypes.includes(key)}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
.tableContainer {
|
|
||||||
overflow-y: hidden;
|
|
||||||
overflow-x: auto;
|
|
||||||
margin: 5px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.categoryName {
|
|
||||||
text-align: center;
|
|
||||||
margin: 5px 0px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: white;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tableCol {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 10px 0px;
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import styles from './todoCard.module.css'
|
|
||||||
|
|
||||||
export default function TodoCard(props) {
|
|
||||||
const { categories, onClick, userId } = props
|
|
||||||
const { name, category, points, votes, id, group } = props.cardData
|
|
||||||
const voted = votes.includes(userId)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={styles.card}
|
|
||||||
style={{
|
|
||||||
border: `1px solid ${group || '#f2cb05'}`,
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
onClick(props.cardData)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className={styles.description}>
|
|
||||||
<span className={styles.id}>{`#${id}`}</span>
|
|
||||||
{name}
|
|
||||||
</div>
|
|
||||||
<div className={styles.category}>
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
backgroundColor: categories[category].color,
|
|
||||||
color: 'white',
|
|
||||||
borderRadius: '2px',
|
|
||||||
padding: '3px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{categories[category].name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.numbers}>
|
|
||||||
<div
|
|
||||||
className={`${voted && styles.voted}`}
|
|
||||||
>{`Szavazatok: ${votes.length}`}</div>
|
|
||||||
<div>{`Nehézség: ${points}`}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
.card {
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 7px;
|
|
||||||
margin: 8px 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #171616;
|
|
||||||
}
|
|
||||||
|
|
||||||
.voted {
|
|
||||||
color: var(--text-color);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card:hover {
|
|
||||||
background-color: #333;
|
|
||||||
border: 2px solid #f99;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card > div {
|
|
||||||
margin: 6px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
word-break: normal;
|
|
||||||
font-size: 14px;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category {
|
|
||||||
font-size: 12px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.numbers {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.numbers > div {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.id {
|
|
||||||
margin: 1px 6px 1px 1px;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import styles from './todoRow.module.css'
|
|
||||||
|
|
||||||
export default function TodoRow(props) {
|
|
||||||
const { categories, userId, onClick } = props
|
|
||||||
const { name, category, votes, id, group } = props.rowData
|
|
||||||
const voted = votes.includes(userId)
|
|
||||||
const borderColor =
|
|
||||||
categories[category].borderColor || categories[category].color
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
onClick(props.rowData)
|
|
||||||
}}
|
|
||||||
className={styles.row}
|
|
||||||
style={{
|
|
||||||
border: `2px dashed ${borderColor || 'white'}`,
|
|
||||||
borderRadius: '3px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className={styles.id}>{`#${id}`}</div>
|
|
||||||
<div className={styles.description}>{name}</div>
|
|
||||||
<div className={styles.catName}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
wordBreak: 'break-all',
|
|
||||||
fontSize: '12px',
|
|
||||||
backgroundColor: categories[category].color,
|
|
||||||
color: 'white',
|
|
||||||
borderRadius: '2px',
|
|
||||||
padding: '3px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{categories[category].name}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`${styles.votes} ${voted && styles.voted}`}
|
|
||||||
>{`Szavazatok: ${votes.length}`}</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
.row {
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 7px;
|
|
||||||
margin: 8px 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #171616;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row:hover {
|
|
||||||
background-color: #333;
|
|
||||||
border: 2px solid #f99;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row > div {
|
|
||||||
margin: 6px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.id {
|
|
||||||
flex: 0 20px;
|
|
||||||
margin: 1px 6px 1px 1px;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
flex: 1;
|
|
||||||
word-break: normal;
|
|
||||||
font-size: 14px;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.votes {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.voted {
|
|
||||||
color: var(--text-color);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.catName {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category {
|
|
||||||
font-size: 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import styles from './todoSidebar.module.css'
|
|
||||||
|
|
||||||
export default function Todos({
|
|
||||||
card,
|
|
||||||
userId,
|
|
||||||
categories,
|
|
||||||
columns,
|
|
||||||
voteOn,
|
|
||||||
namedGroups,
|
|
||||||
}) {
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
category,
|
|
||||||
points,
|
|
||||||
votes,
|
|
||||||
id,
|
|
||||||
group,
|
|
||||||
gitlink,
|
|
||||||
} = card
|
|
||||||
const voteable = columns[card.state].clickable
|
|
||||||
|
|
||||||
// TODO: hide vote button if not voteable
|
|
||||||
return (
|
|
||||||
<div className={styles.container}>
|
|
||||||
<div className={styles.title}>
|
|
||||||
<span className={styles.id}>#{id}</span>
|
|
||||||
<div className={'subtitle'} style={{ textAlign: 'left' }}>
|
|
||||||
{name}
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
backgroundColor: categories[category].color,
|
|
||||||
color: 'white',
|
|
||||||
fontSize: '12px',
|
|
||||||
borderRadius: '2px',
|
|
||||||
padding: '3px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{categories[category].name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
{group && (
|
|
||||||
<div className={styles.row}>
|
|
||||||
<div style={{ color: group }}>Csoport:</div>
|
|
||||||
<div style={{ color: group }}>
|
|
||||||
{namedGroups[group] ? namedGroups[group].name : group}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className={styles.row} title={'Minél több a pont, annál nehezebb'}>
|
|
||||||
<div>Nehézség:</div>
|
|
||||||
<div>{points}</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`${styles.row} ${votes.includes(userId) &&
|
|
||||||
styles.votedtext}`}
|
|
||||||
title={'Hány felhasználó szavazott a feladatra'}
|
|
||||||
>
|
|
||||||
<div>Szavazatok:</div>
|
|
||||||
<div>{votes.length}</div>
|
|
||||||
</div>
|
|
||||||
{gitlink && (
|
|
||||||
<center>
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href={gitlink}
|
|
||||||
style={{ textDecoration: 'none' }}
|
|
||||||
target={'_blank'}
|
|
||||||
rel={'noreferrer'}
|
|
||||||
>
|
|
||||||
Git link
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</center>
|
|
||||||
)}
|
|
||||||
<hr />
|
|
||||||
{description && (
|
|
||||||
<>
|
|
||||||
<div className={'subtitle'} style={{ textAlign: 'left' }}>
|
|
||||||
Leírás
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={styles.description}
|
|
||||||
dangerouslySetInnerHTML={{ __html: description }}
|
|
||||||
/>
|
|
||||||
<hr />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<div className={styles.category} />
|
|
||||||
{voteable && (
|
|
||||||
<center>
|
|
||||||
<div className={'buttonContainer'} style={{ width: '40%' }}>
|
|
||||||
<div
|
|
||||||
className={`${styles.button} ${votes.includes(userId) &&
|
|
||||||
styles.voted}`}
|
|
||||||
onClick={() => {
|
|
||||||
voteOn(card)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{votes.includes(userId) ? 'Szavazat visszavonása' : 'Szavazás'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</center>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container > hr {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: var(--text-color);
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: var(--text-color);
|
|
||||||
font-size: 20px;
|
|
||||||
margin: 5px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
}
|
|
||||||
|
|
||||||
.category {
|
|
||||||
word-break: break-all;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.id {
|
|
||||||
font-size: 20px;
|
|
||||||
margin: 0px 3px;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: auto;
|
|
||||||
max-height: calc(38vh);
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin: 2px 10px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
border: 2px solid var(--text-color);
|
|
||||||
border-radius: 3px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover {
|
|
||||||
background-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.votedtext {
|
|
||||||
color: #cf9;
|
|
||||||
}
|
|
||||||
.voted {
|
|
||||||
border: 2px solid #cf9;
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import TodoRow from './todoRow'
|
|
||||||
|
|
||||||
import styles from './todoTable.module.css'
|
|
||||||
|
|
||||||
export default function TodoBoard(props) {
|
|
||||||
const { tables, cards, userId, categories, onClick, selectedGroup } = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.tableContainer}>
|
|
||||||
<div className={styles.table}>
|
|
||||||
{Object.keys(tables).map((key) => {
|
|
||||||
const table = tables[key]
|
|
||||||
|
|
||||||
const tableCards = cards.filter((card) => {
|
|
||||||
return card.state === key
|
|
||||||
})
|
|
||||||
|
|
||||||
const tableCardsToShow = tableCards.filter((card) => {
|
|
||||||
const shouldHide =
|
|
||||||
card.state !== key ||
|
|
||||||
(selectedGroup !== null &&
|
|
||||||
selectedGroup !== 'uncat' &&
|
|
||||||
card.group !== selectedGroup) ||
|
|
||||||
(selectedGroup === 'uncat' && card.group !== undefined)
|
|
||||||
|
|
||||||
return !shouldHide
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.container} key={key}>
|
|
||||||
<div className={styles.title}>{table.name}</div>
|
|
||||||
<div className={styles.scroll}>
|
|
||||||
{tableCardsToShow.length === 0 && (
|
|
||||||
<div className={styles.empty}>Üres</div>
|
|
||||||
)}
|
|
||||||
{tableCardsToShow.map((card, i) => {
|
|
||||||
return (
|
|
||||||
<TodoRow
|
|
||||||
onClick={onClick}
|
|
||||||
key={i}
|
|
||||||
type={key}
|
|
||||||
rowData={card}
|
|
||||||
userId={userId}
|
|
||||||
categories={categories}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
.tableContainer {
|
|
||||||
overflow-y: hidden;
|
|
||||||
overflow-x: auto;
|
|
||||||
margin: 5px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
flex-direction: column;
|
|
||||||
margin-top: 30px;
|
|
||||||
margin-bottom: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll {
|
|
||||||
max-height: 500px;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 10px 0px;
|
|
||||||
}
|
|
|
@ -1,227 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react'
|
|
||||||
|
|
||||||
import LoadingIndicator from '../LoadingIndicator'
|
|
||||||
import TodoBoard from './todoBoard'
|
|
||||||
import TodoTable from './todoTable'
|
|
||||||
import TodoSidebar from './todoSidebar'
|
|
||||||
import Modal from '../modal'
|
|
||||||
|
|
||||||
import styles from './todo.module.css'
|
|
||||||
import constants from '../../constants.json'
|
|
||||||
|
|
||||||
const byVotes = (a, b) => {
|
|
||||||
return b.votes.length - a.votes.length
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Todos({ globalState, setGlobalState }) {
|
|
||||||
const [loaded, setLoaded] = useState(false)
|
|
||||||
const [columns, setColumns] = useState(null)
|
|
||||||
const [cards, setCards] = useState(null)
|
|
||||||
const [categories, setCategories] = useState(null)
|
|
||||||
const [userId, setUserId] = useState(null)
|
|
||||||
const [sidebarCard, setSidebarCard] = useState(null)
|
|
||||||
const [namedGroups, setGroups] = useState(null)
|
|
||||||
const [selectedGroup, setSelectedGroup] = useState(null)
|
|
||||||
|
|
||||||
const [activeGroups, setActiveGroups] = useState(null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (globalState.todos) {
|
|
||||||
setTodos(globalState.todos)
|
|
||||||
} else {
|
|
||||||
fetch(`${constants.apiUrl}todos`, {
|
|
||||||
credentials: 'include',
|
|
||||||
})
|
|
||||||
.then((resp) => {
|
|
||||||
return resp.json()
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
setTodos(data)
|
|
||||||
setGlobalState({
|
|
||||||
todos: data,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const setTodos = (data) => {
|
|
||||||
setCategories(data.todos.categories)
|
|
||||||
setGroups(data.todos.groups)
|
|
||||||
setUserId(data.userId)
|
|
||||||
|
|
||||||
setCards(data.todos.cards)
|
|
||||||
setColumns(data.todos.columns)
|
|
||||||
setLoaded(true)
|
|
||||||
|
|
||||||
const notTables = Object.keys(data.todos.columns).reduce((acc, key) => {
|
|
||||||
const col = data.todos.columns[key]
|
|
||||||
if (col.type !== 'table') {
|
|
||||||
acc.push(key)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
setActiveGroups(
|
|
||||||
data.todos.cards.reduce((acc, card) => {
|
|
||||||
if (card.group && notTables.includes(card.state)) {
|
|
||||||
if (!acc.includes(card.group)) acc.push(card.group)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, [])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onClick = (card) => {
|
|
||||||
setSidebarCard(card.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loaded) {
|
|
||||||
return <LoadingIndicator />
|
|
||||||
}
|
|
||||||
|
|
||||||
let bCards = []
|
|
||||||
let tCards = []
|
|
||||||
cards.forEach((card) => {
|
|
||||||
if (columns[card.state].type === 'table') {
|
|
||||||
tCards.push(card)
|
|
||||||
} else {
|
|
||||||
bCards.push(card)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
bCards = bCards.sort(byVotes)
|
|
||||||
tCards = tCards.sort(byVotes)
|
|
||||||
|
|
||||||
let cols = {}
|
|
||||||
let tables = {}
|
|
||||||
Object.keys(columns).forEach((key) => {
|
|
||||||
const col = columns[key]
|
|
||||||
if (col.type !== 'table') {
|
|
||||||
cols = {
|
|
||||||
...cols,
|
|
||||||
[key]: col,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tables = {
|
|
||||||
...tables,
|
|
||||||
[key]: col,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const groups = cards.reduce((acc, card) => {
|
|
||||||
if (!acc.includes(card.group) && card.group) {
|
|
||||||
acc.push(card.group)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const renderGrouper = () => {
|
|
||||||
const sg = namedGroups[selectedGroup]
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className={'buttonContainer'}>
|
|
||||||
{groups.map((group) => {
|
|
||||||
const namedGroup = namedGroups[group]
|
|
||||||
const shouldSkip = activeGroups && !activeGroups.includes(group)
|
|
||||||
|
|
||||||
if (shouldSkip) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`${'buttonContainer'}, ${styles.todoButtons} ${
|
|
||||||
group === selectedGroup && 'activeButton'
|
|
||||||
}`}
|
|
||||||
key={group}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedGroup(group)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{namedGroup ? namedGroup.name : group}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
<div
|
|
||||||
className={`${'buttonContainer'}, ${styles.todoButtons} ${
|
|
||||||
'uncat' === selectedGroup && 'activeButton'
|
|
||||||
}`}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedGroup('uncat')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{'Kategorizálatlan'}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`${'buttonContainer'}, ${styles.todoButtons} ${
|
|
||||||
null === selectedGroup && 'activeButton'
|
|
||||||
}`}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedGroup(null)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{'Összes'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{sg && sg.description ? (
|
|
||||||
<div className={styles.groupDescription}>{sg.description}</div>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{sidebarCard && (
|
|
||||||
<Modal
|
|
||||||
closeClick={() => {
|
|
||||||
setSidebarCard(null)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TodoSidebar
|
|
||||||
card={cards.find((card) => {
|
|
||||||
return card.id === sidebarCard
|
|
||||||
})}
|
|
||||||
userId={userId}
|
|
||||||
categories={categories}
|
|
||||||
columns={columns}
|
|
||||||
namedGroups={namedGroups}
|
|
||||||
voteOn={(card) => {
|
|
||||||
fetch(`${constants.apiUrl}voteTodo?id=${card.id}`, {
|
|
||||||
credentials: 'include',
|
|
||||||
})
|
|
||||||
.then((resp) => {
|
|
||||||
return resp.json()
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
setTodos(data)
|
|
||||||
setGlobalState({
|
|
||||||
todos: data,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
)}
|
|
||||||
{renderGrouper()}
|
|
||||||
<div>
|
|
||||||
<TodoBoard
|
|
||||||
columns={cols}
|
|
||||||
cards={bCards}
|
|
||||||
userId={userId}
|
|
||||||
categories={categories}
|
|
||||||
onCardClick={onClick}
|
|
||||||
selectedGroup={selectedGroup}
|
|
||||||
/>
|
|
||||||
<TodoTable
|
|
||||||
tables={tables}
|
|
||||||
cards={tCards}
|
|
||||||
userId={userId}
|
|
||||||
categories={categories}
|
|
||||||
onClick={onClick}
|
|
||||||
selectedGroup={selectedGroup}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"siteUrl": "https://qmining.frylabs.net/",
|
"siteUrl": "http://localhost:8080/",
|
||||||
"apiUrl": "https://api.frylabs.net/",
|
"apiUrl": "http://localhost:8080/",
|
||||||
"mobileWindowWidth": 700,
|
"mobileWindowWidth": 700,
|
||||||
"maxQuestionsToRender": 250,
|
"maxQuestionsToRender": 250,
|
||||||
"imageExts" : ["gif", "png", "jpeg", "jpg"],
|
"imageExts": ["gif", "png", "jpeg", "jpg"],
|
||||||
"videoExts" : ["mp4", "mkv", "webm"]
|
"videoExts": ["mp4", "mkv", "webm"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
{
|
{
|
||||||
"index": {
|
"index": {
|
||||||
"href": "/",
|
"href": "/",
|
||||||
"text": "Fórum"
|
"text": "Főoldal"
|
||||||
},
|
|
||||||
"news": {
|
|
||||||
"href": "/news",
|
|
||||||
"text": "Hírek"
|
|
||||||
},
|
},
|
||||||
"script": {
|
"script": {
|
||||||
"href": "/script",
|
"href": "/script",
|
||||||
|
@ -26,5 +22,9 @@
|
||||||
"contact": {
|
"contact": {
|
||||||
"href": "/contact",
|
"href": "/contact",
|
||||||
"text": "Kapcsolat"
|
"text": "Kapcsolat"
|
||||||
|
},
|
||||||
|
"p2pinfo": {
|
||||||
|
"href": "/p2pinfo",
|
||||||
|
"text": "P2P infó"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"contribute": {
|
|
||||||
"href": "/contribute",
|
|
||||||
"text": "Teendők"
|
|
||||||
},
|
|
||||||
"pwRequest": {
|
"pwRequest": {
|
||||||
"href": "/pwRequest",
|
"href": "/pwRequest",
|
||||||
"text": "Jelszó kérés"
|
"text": "Jelszó kérés"
|
||||||
},
|
},
|
||||||
|
"validation": {
|
||||||
|
"href": "/validation",
|
||||||
|
"text": "Validálás"
|
||||||
|
},
|
||||||
"ranklist": {
|
"ranklist": {
|
||||||
"href": "/ranklist",
|
"href": "/ranklist",
|
||||||
"text": "Ranklista"
|
"text": "Ranklista"
|
||||||
|
|
|
@ -36,7 +36,7 @@ function fetchData(db) {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
return respon()
|
return resp.json()
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
resolve({
|
resolve({
|
||||||
|
@ -61,7 +61,7 @@ function fetchDbs() {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
return respon()
|
return resp.json()
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
resolve(data)
|
resolve(data)
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
import React, { useState } from 'react'
|
|
||||||
|
|
||||||
import Todos from '../components/todoStuff/todos'
|
|
||||||
import FeedbackArea from '../components/feedbackArea'
|
|
||||||
import Modal from '../components/modal'
|
|
||||||
import Header from '../components/header'
|
|
||||||
|
|
||||||
import constants from '../constants.json'
|
|
||||||
import styles from './contribute.module.css'
|
|
||||||
import repos from '../data/repos.json'
|
|
||||||
|
|
||||||
export default function Contribute({ globalState, setGlobalState }) {
|
|
||||||
const [showFeedback, setShowFeedback] = useState(false)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Header title={'Todos'} />
|
|
||||||
<div className={'pageHeader'}>
|
|
||||||
<h1>Teendők</h1>
|
|
||||||
</div>
|
|
||||||
<div className={'description'}>
|
|
||||||
<p>
|
|
||||||
Ezen az oldalon új ötleteket adhatsz hozzá megvalósításra a teendők
|
|
||||||
listájához.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Emellet ha hozzáértő vagy, adott feladatok megvalósításában is
|
|
||||||
segíthetsz. (lásd: <a href="#gitrepo">lentebb</a>)
|
|
||||||
<br /> Ha egy kártyára kattintasz, a megjelenő ablakban láthatod annak
|
|
||||||
részleteit, illetve{' '}
|
|
||||||
<b>
|
|
||||||
<i>szavazhatsz</i>
|
|
||||||
</b>{' '}
|
|
||||||
is a feladatra, annak érdekében, hogy minél hamarabb megvalósulhasson.
|
|
||||||
Minél több szavazat érkezik egy kártyára, annál magasabb lesz a
|
|
||||||
prioritása. (értsd: a legtöbb szavazatot kapó kártya teendője lesz
|
|
||||||
legelőször megvalósítva)
|
|
||||||
<br /> A kurzort az oszlopcímekre mozgatva, további információkat
|
|
||||||
olvashatsz a kategóriák tulajdonságairól.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className={`buttonContainer`}>
|
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
setShowFeedback(true)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Új feladat
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
<hr />
|
|
||||||
<Todos globalState={globalState} setGlobalState={setGlobalState} />
|
|
||||||
<hr />
|
|
||||||
<div id={'gitrepo'} className={styles.gitRepos}>
|
|
||||||
<div>
|
|
||||||
<div className={'subtitle'}>
|
|
||||||
<b>Git repos</b>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{Object.keys(repos.repos).map((key) => {
|
|
||||||
let repo = repos.repos[key]
|
|
||||||
return (
|
|
||||||
<div key={key}>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a key={key} href={repo.href}>
|
|
||||||
{repo.description}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<img src={`${constants.siteUrl}img/bug.png`} />
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
{showFeedback && (
|
|
||||||
<Modal
|
|
||||||
closeClick={() => {
|
|
||||||
setShowFeedback(false)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FeedbackArea from={'contribute'} />
|
|
||||||
</Modal>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
.warning {
|
|
||||||
color: white;
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 26px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: var(--text-color);
|
|
||||||
font-size: 30px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gitRepos {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 700px) {
|
|
||||||
.gitRepos {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.gitRepos a {
|
|
||||||
margin: 0px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gitRepos img {
|
|
||||||
width: 400px;
|
|
||||||
max-width: 90%;
|
|
||||||
}
|
|
|
@ -25,12 +25,11 @@ export default function UserForum({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Forum
|
<Forum
|
||||||
allowPost
|
|
||||||
router={router}
|
router={router}
|
||||||
globalState={globalState}
|
globalState={globalState}
|
||||||
setGlobalState={setGlobalState}
|
setGlobalState={setGlobalState}
|
||||||
globalData={globalData}
|
globalData={globalData}
|
||||||
forumName={'userForum'}
|
forumName={'frontpage'}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import Forum from '../components/forum'
|
|
||||||
|
|
||||||
export default function Index({
|
|
||||||
router,
|
|
||||||
globalData,
|
|
||||||
globalState,
|
|
||||||
setGlobalState,
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Forum
|
|
||||||
router={router}
|
|
||||||
globalState={globalState}
|
|
||||||
setGlobalState={setGlobalState}
|
|
||||||
globalData={globalData}
|
|
||||||
forumName={'frontpage'}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
.title {
|
|
||||||
color: var(--text-color);
|
|
||||||
font-size: 32px;
|
|
||||||
text-align: center;
|
|
||||||
letter-spacing: 2.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.motd {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 20px;
|
|
||||||
|
|
||||||
border: 2px dashed var(--text-color);
|
|
||||||
padding-top: 13px;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
margin-top: 18px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
168
src/pages/p2pinfo.jsx
Normal file
168
src/pages/p2pinfo.jsx
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
import Header from '../components/header'
|
||||||
|
import constants from '../constants.json'
|
||||||
|
import LoadingIndicator from '../components/LoadingIndicator'
|
||||||
|
|
||||||
|
import styles from './p2pinfo.module.css'
|
||||||
|
|
||||||
|
const infos = [
|
||||||
|
{
|
||||||
|
title: 'Név',
|
||||||
|
key: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Kontakt',
|
||||||
|
key: 'contact',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Utolsó szinkronizálás',
|
||||||
|
key: 'lastSync',
|
||||||
|
type: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Kérdés DB-k',
|
||||||
|
key: 'questionDbCount',
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Tárgyak',
|
||||||
|
key: 'subjectCount',
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Kérdések',
|
||||||
|
key: 'questionCount',
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Szerver build time',
|
||||||
|
key: 'serverBuildTime',
|
||||||
|
type: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Script version',
|
||||||
|
key: 'scriptVersion',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Weboldal build time',
|
||||||
|
key: 'qminingPageBuildTime',
|
||||||
|
type: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Data editor build time',
|
||||||
|
key: 'dataEditorBuildTime',
|
||||||
|
type: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Szerver revision',
|
||||||
|
key: 'serverRevision',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Script revision',
|
||||||
|
key: 'scriptRevision',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Weboldal revision',
|
||||||
|
key: 'qminingPageRevision',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Data editor revision',
|
||||||
|
key: 'dataEditorRevision',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function P2PInfo({ globalState, setGlobalState }) {
|
||||||
|
const [p2pInfo, setP2pinfo] = useState()
|
||||||
|
const info = p2pInfo
|
||||||
|
? {
|
||||||
|
...p2pInfo,
|
||||||
|
...p2pInfo.selfInfo,
|
||||||
|
...p2pInfo.qdbInfo,
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (globalState.p2pinfo) {
|
||||||
|
setP2pinfo(globalState.p2pinfo)
|
||||||
|
} else {
|
||||||
|
fetch(constants.apiUrl + 'p2pinfo', {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'include',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
return res.json()
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
setP2pinfo(res)
|
||||||
|
setGlobalState({
|
||||||
|
p2pinfo: res,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (!p2pInfo) return <LoadingIndicator />
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={'pageHeader'}>
|
||||||
|
<h1>Peer to peer infó</h1>
|
||||||
|
</div>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<Header title={'P2P infó'} />
|
||||||
|
A weboldal peer to peer (p2p) megoldást implementál, így több szerverrel
|
||||||
|
együtt tud működni, és a más szerveren hozzáadott adatokat időközönként
|
||||||
|
elkéri, és hozzáadja a helyileg tárolt adatokhoz. Vagy valami ilyesmi
|
||||||
|
TODO: normális duma
|
||||||
|
<hr />
|
||||||
|
<div className={styles.title}>Szerver P2P információja:</div>
|
||||||
|
<br />
|
||||||
|
{infos.map((x) => {
|
||||||
|
const { title, key, type } = x
|
||||||
|
|
||||||
|
let text = info[key]
|
||||||
|
switch (type) {
|
||||||
|
case 'date':
|
||||||
|
text = new Date(text).toLocaleString()
|
||||||
|
break
|
||||||
|
case 'number':
|
||||||
|
text = text.toLocaleString()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div key={key} className={styles.infoRow}>
|
||||||
|
<div>{title}</div>
|
||||||
|
<div>{text}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<hr />
|
||||||
|
<div className={styles.title}>Regisztrált peer-ek:</div>
|
||||||
|
<div className={styles.peerHeader}>
|
||||||
|
<div>Név</div>
|
||||||
|
<div>Host</div>
|
||||||
|
<div>Utolsó szinkronizálás</div>
|
||||||
|
</div>
|
||||||
|
{p2pInfo.myPeers.map((peer, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i} className={styles.peerContainer}>
|
||||||
|
<div>{peer.name}</div>
|
||||||
|
<div>
|
||||||
|
<a href={`https://${peer.host}:${peer.port}`} target={'_blank'}>
|
||||||
|
{peer.host}:{peer.port}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>{new Date(peer.lastSync).toLocaleString()}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
44
src/pages/p2pinfo.module.css
Normal file
44
src/pages/p2pinfo.module.css
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
.container {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoRow {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoRow > * {
|
||||||
|
padding: 0px 8px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoRow :first-child {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoRow :last-child {
|
||||||
|
flex: 2;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.peerContainer, .peerHeader {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-content: center;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.peerContainer {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.peerContainer > *, .peerHeader > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
47
src/pages/validation.jsx
Normal file
47
src/pages/validation.jsx
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
|
||||||
|
import Header from '../components/header'
|
||||||
|
|
||||||
|
import styles from './validation.module.css'
|
||||||
|
import constants from '../constants.json'
|
||||||
|
|
||||||
|
function fetchValidation() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
fetch(`${constants.apiUrl}validationtoken`, {
|
||||||
|
credentials: 'include',
|
||||||
|
})
|
||||||
|
.then((resp) => {
|
||||||
|
return resp.json()
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
resolve(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Validation() {
|
||||||
|
const [token, setToken] = React.useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchValidation().then((res) => {
|
||||||
|
setToken(res.key)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Header title={'Validálás'} />
|
||||||
|
<div className={'pageHeader'}>
|
||||||
|
<h1>Validálás</h1>
|
||||||
|
</div>
|
||||||
|
<center>
|
||||||
|
<div className={styles.descrip}>
|
||||||
|
Különböző okokból kellhet, hogy bizonyítsd hogy az oldalhoz van
|
||||||
|
hozzáférésed. Ebben az esetben ezzel a tokennel tudod: TODO: normális
|
||||||
|
duma
|
||||||
|
</div>
|
||||||
|
{token && <div className={styles.tokenContainer}>{token}</div>}
|
||||||
|
</center>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
16
src/pages/validation.module.css
Normal file
16
src/pages/validation.module.css
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
.descrip {
|
||||||
|
color: #acabab;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-top: 4%;
|
||||||
|
padding-bottom: 4%;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tokenContainer {
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue