mirror of
https://gitlab.com/MrFry/qmining-page
synced 2025-04-01 20:23:44 +02:00
Merge branch 'p2p-frontend' of gitlab.com:MrFry/qmining-page into p2p-frontend
This commit is contained in:
commit
b2a41bc160
48 changed files with 610 additions and 1249 deletions
16
constants.js
Normal file
16
constants.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
const useLocalhost = process && process.env.NODE_ENV === 'development'
|
||||
|
||||
const constants = {
|
||||
siteUrl: !useLocalhost ? 'http://frylabs.net/' : 'http://localhost:8080/',
|
||||
apiUrl: !useLocalhost
|
||||
? 'http://frylabs.net/api/'
|
||||
: 'http://localhost:8080/api/',
|
||||
chatUrl: !useLocalhost ? 'http://frylabs.net/' : 'http://localhost:8080/',
|
||||
mobileWindowWidth: 700,
|
||||
maxQuestionsToRender: 250,
|
||||
imageExts: ['gif', 'png', 'jpeg', 'jpg'],
|
||||
videoExts: ['mp4', 'mkv', 'webm'],
|
||||
}
|
||||
|
||||
export default constants
|
|
@ -6,7 +6,15 @@ function highlightText(text, toHighlight) {
|
|||
}
|
||||
try {
|
||||
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) {
|
||||
return text
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
|
||||
import Questions from './Questions'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
const countReducer = (acc, subj) => {
|
||||
return acc + subj.Questions.length
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
const soundCount = 7
|
||||
function GetRandom(min, max) {
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, { useState } from 'react'
|
|||
import Modal from './modal'
|
||||
|
||||
import styles from './composer.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
export default function Composer({ onSubmit, allowFile, fileOnly }) {
|
||||
const [editorShowing, setEditorShowing] = useState(false)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import Modal from './modal'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
import styles from './dbSelector.module.css'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from 'react'
|
||||
|
||||
import styles from './feedbackArea.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
function FileUploader({ onChange }) {
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,7 @@ import Header from '../components/header'
|
|||
import Modal from '../components/modal'
|
||||
|
||||
import styles from './forum.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
const forumPostPerPage = 5
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ const Snowfall = dynamic(() => import('react-snowfall'), { ssr: false })
|
|||
|
||||
import LogoutIcon from './logoutIcon'
|
||||
import Modal from './modal'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
import BB from './b'
|
||||
|
||||
import styles from './layout.module.css'
|
||||
|
@ -67,36 +67,35 @@ function TopBar({
|
|||
unreads,
|
||||
userId,
|
||||
}) {
|
||||
return <>
|
||||
<MenuIcon setSidebarOpen={setSidebarOpen} sidebarOpen={sidebarOpen} />
|
||||
<Link href="/">
|
||||
return (
|
||||
<>
|
||||
<MenuIcon setSidebarOpen={setSidebarOpen} sidebarOpen={sidebarOpen} />
|
||||
<Link href="/">
|
||||
<img
|
||||
src={`${constants.siteUrl}img/frylabs-logo_small_transparent.png`}
|
||||
alt="FryLabs"
|
||||
/>
|
||||
</Link>
|
||||
<div className={styles.topBarLinks}>
|
||||
{Object.keys(topBarLinks).map((key) => {
|
||||
const item = topBarLinks[key]
|
||||
|
||||
<img
|
||||
src={`${constants.siteUrl}img/frylabs-logo_small_transparent.png`}
|
||||
alt="FryLabs"
|
||||
/>
|
||||
|
||||
</Link>
|
||||
<div className={styles.topBarLinks}>
|
||||
{Object.keys(topBarLinks).map((key) => {
|
||||
const item = topBarLinks[key]
|
||||
|
||||
return (
|
||||
(<Link
|
||||
key={key}
|
||||
href={item.href}
|
||||
onClick={closeSideBar}
|
||||
className={href.includes(key) ? styles.active : undefined}>
|
||||
|
||||
{item.text}
|
||||
|
||||
</Link>)
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className={'seperator'} />
|
||||
<UserStatus onClick={closeSideBar} unreads={unreads} userId={userId} />
|
||||
</>;
|
||||
return (
|
||||
<Link
|
||||
key={key}
|
||||
href={item.href}
|
||||
onClick={closeSideBar}
|
||||
className={href.includes(key) ? styles.active : undefined}
|
||||
>
|
||||
{item.text}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<div className={'seperator'} />
|
||||
<UserStatus onClick={closeSideBar} unreads={unreads} userId={userId} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SideBar({ sidebarOpen, closeSideBar, href, setDonateShowing }) {
|
||||
|
@ -110,17 +109,16 @@ function SideBar({ sidebarOpen, closeSideBar, href, setDonateShowing }) {
|
|||
}
|
||||
|
||||
return (
|
||||
(<Link
|
||||
<Link
|
||||
href={item.href}
|
||||
key={key}
|
||||
onClick={closeSideBar}
|
||||
className={href.includes(key) ? styles.active : undefined}
|
||||
id={item.id || undefined}>
|
||||
|
||||
id={item.id || undefined}
|
||||
>
|
||||
{item.text}
|
||||
|
||||
</Link>)
|
||||
);
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
<a
|
||||
onClick={() => {
|
||||
|
@ -132,7 +130,7 @@ function SideBar({ sidebarOpen, closeSideBar, href, setDonateShowing }) {
|
|||
</a>
|
||||
</div>
|
||||
</>
|
||||
) : null;
|
||||
) : null
|
||||
}
|
||||
|
||||
function Donate() {
|
||||
|
@ -187,11 +185,10 @@ function UserStatus({ userId, unreads, onClick }) {
|
|||
href="/chat"
|
||||
onClick={onClick}
|
||||
title={`Chat${unreadCount ? ' (' + unreadCount + ' új üzenet)' : ''}`}
|
||||
className={styles.unreadNotification}>
|
||||
|
||||
className={styles.unreadNotification}
|
||||
>
|
||||
<span>💬</span>
|
||||
{unreadCount ? <div>{unreadCount}</div> : null}
|
||||
|
||||
</Link>
|
||||
|
||||
<div
|
||||
|
@ -215,7 +212,7 @@ function UserStatus({ userId, unreads, onClick }) {
|
|||
<LogoutIcon size={28} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function MenuIcon({ setSidebarOpen, sidebarOpen }) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import ReactButton from './reactButton'
|
|||
import Comments from './comments'
|
||||
import Link from 'next/link'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
import styles from './newsEntry.module.css'
|
||||
|
||||
|
@ -95,9 +95,9 @@ export default function NewsEntry({
|
|||
<Link
|
||||
href={`/chat?user=${user}`}
|
||||
title={`Chat #${user}-el`}
|
||||
className={'userId'}>
|
||||
className={'userId'}
|
||||
>
|
||||
User #{user}
|
||||
|
||||
</Link>
|
||||
<div className={styles.newsDate} title={dateObj.toLocaleString()}>
|
||||
@
|
||||
|
@ -145,5 +145,5 @@ export default function NewsEntry({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
export default function Sleep() {
|
||||
const hours = new Date().getHours()
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
}
|
15
src/constants.js
Normal file
15
src/constants.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
const useLocalhost = process && process.env.NODE_ENV === 'development'
|
||||
|
||||
const constants = {
|
||||
siteUrl: !useLocalhost ? 'http://frylabs.net/' : 'http://localhost:8080/',
|
||||
apiUrl: !useLocalhost
|
||||
? 'http://frylabs.net/api/'
|
||||
: 'http://localhost:8080/api/',
|
||||
chatUrl: !useLocalhost ? 'http://frylabs.net/' : 'http://localhost:8080/',
|
||||
mobileWindowWidth: 700,
|
||||
maxQuestionsToRender: 250,
|
||||
imageExts: ['gif', 'png', 'jpeg', 'jpg'],
|
||||
videoExts: ['mp4', 'mkv', 'webm'],
|
||||
}
|
||||
export default constants
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"siteUrl": "https://qmining.frylabs.net/",
|
||||
"apiUrl": "https://api.frylabs.net/",
|
||||
"mobileWindowWidth": 700,
|
||||
"maxQuestionsToRender": 250,
|
||||
"imageExts" : ["gif", "png", "jpeg", "jpg"],
|
||||
"videoExts" : ["mp4", "mkv", "webm"]
|
||||
}
|
|
@ -1,11 +1,7 @@
|
|||
{
|
||||
"index": {
|
||||
"href": "/",
|
||||
"text": "Fórum"
|
||||
},
|
||||
"news": {
|
||||
"href": "/news",
|
||||
"text": "Hírek"
|
||||
"text": "Főoldal"
|
||||
},
|
||||
"script": {
|
||||
"href": "/script",
|
||||
|
@ -26,5 +22,9 @@
|
|||
"contact": {
|
||||
"href": "/contact",
|
||||
"text": "Kapcsolat"
|
||||
},
|
||||
"p2pinfo": {
|
||||
"href": "/p2pinfo",
|
||||
"text": "P2P infó"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"contribute": {
|
||||
"href": "/contribute",
|
||||
"text": "Teendők"
|
||||
},
|
||||
"pwRequest": {
|
||||
"href": "/pwRequest",
|
||||
"text": "Jelszó kérés"
|
||||
},
|
||||
"validation": {
|
||||
"href": "/validation",
|
||||
"text": "Validálás"
|
||||
},
|
||||
"ranklist": {
|
||||
"href": "/ranklist",
|
||||
"text": "Ranklista"
|
||||
|
|
|
@ -5,7 +5,7 @@ import Head from 'next/head'
|
|||
import Layout from '../components/layout'
|
||||
|
||||
import '../defaultStyles.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
export const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
|
|
|
@ -10,7 +10,7 @@ import SearchBar from '../components/searchBar'
|
|||
|
||||
import styles from './allQuestions.module.css'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
const countReducer = (acc, subj) => {
|
||||
return acc + subj.Questions.length
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import io from 'socket.io-client'
|
||||
import linkifyString from 'linkify-string'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
import LoadingIndicator from '../components/LoadingIndicator'
|
||||
import { queryClient } from '../pages/_app'
|
||||
import Header from '../components/header'
|
||||
|
@ -202,7 +202,7 @@ export default class Chat extends React.Component {
|
|||
return
|
||||
}
|
||||
// https://socket.io/docs/v4/handling-cors/#Configuration
|
||||
const socket = io(`${constants.apiUrl}`, {
|
||||
const socket = io(`${constants.chatUrl}`, {
|
||||
withCredentials: true,
|
||||
extraHeaders: {
|
||||
'qmining-chat': 'qmining-chat',
|
||||
|
|
|
@ -3,7 +3,7 @@ import Link from 'next/link'
|
|||
|
||||
import Header from '../components/header'
|
||||
import FeedbackArea from '../components/feedbackArea'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
import LoadingIndicator from '../components/LoadingIndicator'
|
||||
|
||||
import styles from './contact.module.css'
|
||||
|
@ -62,13 +62,10 @@ export default function Contact({ globalState, setGlobalState }) {
|
|||
<div className={styles.container}>
|
||||
{contacts ? (
|
||||
<>
|
||||
<div>
|
||||
<div className={'subtitle'}>Alternatív módok</div>
|
||||
<div className={styles.text}>
|
||||
Az alábbi módokat is nyugodtan használhatod, a nevedet, e-mail
|
||||
címedet, illetve semmilyen egyéb adatot nem adok ki harmadik fél
|
||||
számára. (egyedül én fogom látni)
|
||||
</div>
|
||||
<div className={styles.text}>
|
||||
Figyelem! A szerver üzemeltetőjének kontaktját a
|
||||
<Link href="/p2pinfo">{'"P2P infó"'}</Link>
|
||||
részlegen találod!
|
||||
</div>
|
||||
<div className={styles.contactsContainer}>
|
||||
{Object.keys(contacts).map((key) => {
|
||||
|
@ -78,8 +75,7 @@ export default function Contact({ globalState, setGlobalState }) {
|
|||
<div>{description}</div>
|
||||
{href ? (
|
||||
<a target="blank" rel="noreferrer" href={href}>
|
||||
{' '}
|
||||
{value}{' '}
|
||||
{value}
|
||||
</a>
|
||||
) : (
|
||||
<div>{value}</div>
|
||||
|
@ -94,5 +90,5 @@ export default function Contact({ globalState, setGlobalState }) {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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%;
|
||||
}
|
|
@ -3,7 +3,7 @@ import Link from 'next/link'
|
|||
|
||||
import Header from '../components/header'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
import styles from './faq.module.css'
|
||||
|
||||
function PasswordSection() {
|
||||
|
@ -90,11 +90,7 @@ function FAQSection() {
|
|||
(így nicknevek sem kellenek), és még IP cím sincs sehol letárolva
|
||||
szerver oldalon.
|
||||
<br />
|
||||
Több infó a{' '}
|
||||
<Link href="/faq?tab=risk">
|
||||
kockázatok résznél
|
||||
</Link>
|
||||
.
|
||||
Több infó a <Link href="/faq?tab=risk">kockázatok résznél</Link>.
|
||||
</li>
|
||||
<li>
|
||||
<b>Ki és miért csinálja ezt a weboldalt?</b>
|
||||
|
@ -108,130 +104,130 @@ function FAQSection() {
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function RiskSection() {
|
||||
return <>
|
||||
Itt {'"én"'} alatt a szerver, weboldal és script egyedüli üzemeltetője
|
||||
értendő, az egyetlen személy, aki hozzáfér akármilyen szolgáltatással
|
||||
kapcsolatos adathoz, pl.: szerver statisztikák, szerver operációs
|
||||
rendszere, beküldött fájlok. A weboldalon a felhasználó azonosítója:{' '}
|
||||
<i>#1</i>
|
||||
<ul>
|
||||
<li>
|
||||
<b>Beküldött fájlok kezelése</b>A beküldött fájlokban szerepelhet
|
||||
személyes adat, pl.: név. Ha ilyen információval találkozok, akkor azt
|
||||
ki szoktam törölni. Ezekhez a fájlokhoz és információkhoz csak én
|
||||
férek hozzá, és sehova sincs kiadva. Ezek az információk nincsenek
|
||||
sehol gyűjtve.
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
Ha esetleg {'"'}lebukik{'"'} a szerver, és tárolt személyes infók
|
||||
</b>
|
||||
Semmi személyes információ nincs eltárolva szerveren. Egyedüli
|
||||
információ amit egyáltalán ki tudnék deríteni az amúgy is az IP címed,
|
||||
de az nincs letárolva. Ha nagyon gonosz lennék, akkor a script el
|
||||
tudná küldeni a neved és talán még 1-2 adatot a szervernek, de ezt nem
|
||||
teszi.
|
||||
<p />
|
||||
Bizonyíték? A script, weboldal és szerver teljesen nyílt forráskódú,{' '}
|
||||
<Link href="/contribute#gitrepo">
|
||||
ezek repository-ja publikus
|
||||
</Link>{' '}
|
||||
(contribute oldal alja), és akármikor felülvizsgálható. A script a te
|
||||
böngésződben fut, tampermonkey bővítmény menüjében megtekinthető
|
||||
milyen kód fut pontosan.
|
||||
</li>
|
||||
<li>
|
||||
<b>Bármikor észrevehetik hogy használod a scriptet</b>A weboldalt már
|
||||
kevésbé, de úgy nem menti el a kérdéseket a script, mert nem fut.{' '}
|
||||
<a
|
||||
href={`${constants.siteUrl}dataeditor`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Manuálisan is be lehet küldeni kérdés-válaszokat.
|
||||
</a>
|
||||
<p />
|
||||
A script shadow-root hoz teszi hozzá az összes megjelenített
|
||||
elementet, így ezeket szinte lehetetlen detektálni. A moodle
|
||||
semmiféleképpen nem látja, hogy milyen más oldalak vannak megnyitva a
|
||||
böngésződben. Nem látja az XMLHttp requesteket se, amit a script
|
||||
végez. Egy Matomo nevű script látja hogy milyen oldalakra navigálsz a
|
||||
moodle-ről, de a script nem linkekkel irányít át, hanem javascript
|
||||
eseménnyel, amit nem tud nyomon követni.
|
||||
<p />
|
||||
Aztán ki tudja ténylegesen hogy lehet
|
||||
</li>
|
||||
<li>
|
||||
<b>Bármikor leállhat a szerver</b>
|
||||
És akkor nem bírod megnézni a válaszokat. Erre van az{' '}
|
||||
<a
|
||||
href="http://qmining.frylabs.net/allqr.txt?man"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
összes kérdés TXT
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<b>Akármelyik válasz rossz lehet</b>
|
||||
Pl.: ha a script rosszul menti le, vagy rossz kérdésre ad választ
|
||||
</li>
|
||||
</ul>
|
||||
</>;
|
||||
return (
|
||||
<>
|
||||
Itt {'"én"'} alatt a szerver, weboldal és script egyedüli üzemeltetője
|
||||
értendő, az egyetlen személy, aki hozzáfér akármilyen szolgáltatással
|
||||
kapcsolatos adathoz, pl.: szerver statisztikák, szerver operációs
|
||||
rendszere, beküldött fájlok. A weboldalon a felhasználó azonosítója:{' '}
|
||||
<i>#1</i>
|
||||
<ul>
|
||||
<li>
|
||||
<b>Beküldött fájlok kezelése</b>A beküldött fájlokban szerepelhet
|
||||
személyes adat, pl.: név. Ha ilyen információval találkozok, akkor azt
|
||||
ki szoktam törölni. Ezekhez a fájlokhoz és információkhoz csak én
|
||||
férek hozzá, és sehova sincs kiadva. Ezek az információk nincsenek
|
||||
sehol gyűjtve.
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
Ha esetleg {'"'}lebukik{'"'} a szerver, és tárolt személyes infók
|
||||
</b>
|
||||
Semmi személyes információ nincs eltárolva szerveren. Egyedüli
|
||||
információ amit egyáltalán ki tudnék deríteni az amúgy is az IP címed,
|
||||
de az nincs letárolva. Ha nagyon gonosz lennék, akkor a script el
|
||||
tudná küldeni a neved és talán még 1-2 adatot a szervernek, de ezt nem
|
||||
teszi.
|
||||
<p />
|
||||
Bizonyíték? A script, weboldal és szerver teljesen nyílt forráskódú,{' '}
|
||||
<Link href="/contribute#gitrepo">
|
||||
ezek repository-ja publikus
|
||||
</Link>{' '}
|
||||
(contribute oldal alja), és akármikor felülvizsgálható. A script a te
|
||||
böngésződben fut, tampermonkey bővítmény menüjében megtekinthető
|
||||
milyen kód fut pontosan.
|
||||
</li>
|
||||
<li>
|
||||
<b>Bármikor észrevehetik hogy használod a scriptet</b>A weboldalt már
|
||||
kevésbé, de úgy nem menti el a kérdéseket a script, mert nem fut.{' '}
|
||||
<a
|
||||
href={`${constants.siteUrl}dataeditor`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Manuálisan is be lehet küldeni kérdés-válaszokat.
|
||||
</a>
|
||||
<p />
|
||||
A script shadow-root hoz teszi hozzá az összes megjelenített
|
||||
elementet, így ezeket szinte lehetetlen detektálni. A moodle
|
||||
semmiféleképpen nem látja, hogy milyen más oldalak vannak megnyitva a
|
||||
böngésződben. Nem látja az XMLHttp requesteket se, amit a script
|
||||
végez. Egy Matomo nevű script látja hogy milyen oldalakra navigálsz a
|
||||
moodle-ről, de a script nem linkekkel irányít át, hanem javascript
|
||||
eseménnyel, amit nem tud nyomon követni.
|
||||
<p />
|
||||
Aztán ki tudja ténylegesen hogy lehet
|
||||
</li>
|
||||
<li>
|
||||
<b>Bármikor leállhat a szerver</b>
|
||||
És akkor nem bírod megnézni a válaszokat. Erre van az{' '}
|
||||
<a
|
||||
href="http://qmining.frylabs.net/allqr.txt?man"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
összes kérdés TXT
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<b>Akármelyik válasz rossz lehet</b>
|
||||
Pl.: ha a script rosszul menti le, vagy rossz kérdésre ad választ
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function WebsiteSaveSection() {
|
||||
return <>
|
||||
<p>
|
||||
Ha hibát találsz, kérlek jelents. Hogy a hibákat a saját gépemen
|
||||
reprodukálni tudjam, és könnyen ki bírjam javítani, sokszor jól jön, ha
|
||||
egy lementett weboldalt megkapok, amin a hiba történik. Így lehet
|
||||
menteni egy oldalt:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Lementett oldalon jobb klikk, oldal mentése
|
||||
<br />
|
||||
<img
|
||||
src="img/faq/sitesave-1.jpg"
|
||||
alt="img"
|
||||
className={'manual_img'}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
A lementett oldal egy fájlból és mappából áll.
|
||||
<br />
|
||||
<img
|
||||
src="img/faq/sitesave-2.jpg"
|
||||
alt="img"
|
||||
className={'manual_img'}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
A fájlt nyisd meg szövegszerkesztővel (notepad), és keress rá a
|
||||
nevedre, majd (csak a neved, ne a sort) töröld ki, és mentsd el. Nem
|
||||
szoktam megnézni a neveket, nem is tudok velük mit kezdeni, és nem is
|
||||
adom ki soha. Amit beküldesz, azt csak én látom.{' '}
|
||||
<Link href="/faq?tab=risk">
|
||||
Több infó itt
|
||||
</Link>{' '}
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact">
|
||||
Ide tudod feltölteni
|
||||
</Link>{' '}
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Mivel nincs hozzáférésem semmilyen egyetemi oldalhoz, így csak így tudom
|
||||
hatékonyan tesztelni a scriptet. Ezért hatalmas segítség ha feltöltöd
|
||||
azt az oldalt amin hibával találkozol.
|
||||
</p>
|
||||
</>;
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Ha hibát találsz, kérlek jelents. Hogy a hibákat a saját gépemen
|
||||
reprodukálni tudjam, és könnyen ki bírjam javítani, sokszor jól jön, ha
|
||||
egy lementett weboldalt megkapok, amin a hiba történik. Így lehet
|
||||
menteni egy oldalt:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Lementett oldalon jobb klikk, oldal mentése
|
||||
<br />
|
||||
<img
|
||||
src="img/faq/sitesave-1.jpg"
|
||||
alt="img"
|
||||
className={'manual_img'}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
A lementett oldal egy fájlból és mappából áll.
|
||||
<br />
|
||||
<img
|
||||
src="img/faq/sitesave-2.jpg"
|
||||
alt="img"
|
||||
className={'manual_img'}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
A fájlt nyisd meg szövegszerkesztővel (notepad), és keress rá a
|
||||
nevedre, majd (csak a neved, ne a sort) töröld ki, és mentsd el. Nem
|
||||
szoktam megnézni a neveket, nem is tudok velük mit kezdeni, és nem is
|
||||
adom ki soha. Amit beküldesz, azt csak én látom.{' '}
|
||||
<Link href="/faq?tab=risk">Több infó itt</Link>{' '}
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact">Ide tudod feltölteni</Link>{' '}
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Mivel nincs hozzáférésem semmilyen egyetemi oldalhoz, így csak így tudom
|
||||
hatékonyan tesztelni a scriptet. Ezért hatalmas segítség ha feltöltöd
|
||||
azt az oldalt amin hibával találkozol.
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function ScriptSection() {
|
||||
|
@ -240,9 +236,7 @@ function ScriptSection() {
|
|||
<ul>
|
||||
<li>
|
||||
<b>Hogy kell a scriptet telepíteni, és milyen oldalakon működik? </b>
|
||||
<Link href="/script">
|
||||
Ezen az oldalon van leírva
|
||||
</Link>{' '}
|
||||
<Link href="/script">Ezen az oldalon van leírva</Link>{' '}
|
||||
</li>
|
||||
<li>
|
||||
<b>Hogyan működik a script?</b>
|
||||
|
@ -258,10 +252,7 @@ function ScriptSection() {
|
|||
</li>
|
||||
<li>
|
||||
Más felhasználóknak köszönhetően már valószínűleg lesznek
|
||||
megoldások a tesztjeidhez.{' '}
|
||||
<Link href="/allQuestions">
|
||||
Itt
|
||||
</Link>{' '}
|
||||
megoldások a tesztjeidhez. <Link href="/allQuestions">Itt</Link>{' '}
|
||||
meg tudod tekinteni, hogy vannak-e válaszok a tárgyadhoz.
|
||||
</li>
|
||||
<li>
|
||||
|
@ -378,77 +369,74 @@ function ScriptSection() {
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function AddSite() {
|
||||
return <>
|
||||
Jelenleg az, hogy a script melyik oldalakon fut bele van égetve a script
|
||||
forráskódjába. Ez itt látható:{' '}
|
||||
<a
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
href="https://gitlab.com/MrFry/moodle-test-userscript/-/blob/master/stable.user.js#L52"
|
||||
>
|
||||
stable.user.js#L52
|
||||
</a>
|
||||
{'. '}
|
||||
Ez azért van így, hogy biztos csak olyan oldalakon fusson a script amit
|
||||
támogat is.
|
||||
<p />
|
||||
Ehhez persze kézzel hozzá lehet adni ideiglenesen bármilyen oldalt, hogy
|
||||
kipróbáld ott működik-e. Akár működik, akár nem kérlek szólj, és frissítem
|
||||
a scriptet hogy azon a domainen is fusson és működjön alapból.
|
||||
<p />
|
||||
Egyetem moodle oldalának hozzáadása a scripthez kézzel:
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/script">
|
||||
Először telepítsd a scriptet rendesen
|
||||
</Link>{' '}
|
||||
</li>
|
||||
<li>
|
||||
Böngészőben nyisd meg a Tampermonkey bővítményt <br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-1.png`} />
|
||||
<br />
|
||||
Itt kattints a Dashboard-ra.
|
||||
</li>
|
||||
<li>
|
||||
Keresd meg a scriptet, majd kattints rá:
|
||||
<br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-2.png`} />
|
||||
</li>
|
||||
<li>
|
||||
A felugró szerkesztőben keresd meg a következő sorokat:
|
||||
<br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-3.png`} />
|
||||
</li>
|
||||
<li>
|
||||
Itt az egyik <i>@match ...</i> sor után egy új sorban írd be az
|
||||
egyetemed moodle oldalának címét. Ha ez a cím pl.:{' '}
|
||||
<i>https://moodle.egyetem.hu/main/akármi</i>, akkor a következőre írd
|
||||
át: <i>https://moodle.egyetem.hu/*</i>. Fenti képen látsz néhány
|
||||
példát. <i>A {'"*"'} a végén fontos!</i>
|
||||
</li>
|
||||
<li>
|
||||
Ezután mentsd el (ctrl + s, vagy file {'->'} save). Ha minden jól
|
||||
ment, akkor elég frissíteni a moodle oldalát, és a script futni fog
|
||||
rajta. Ezek után azon az oldalon amit beírtál meg kell jelennie a
|
||||
Tampermonkey menüjében is:
|
||||
<br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-4.png`} />
|
||||
</li>
|
||||
<li>
|
||||
Ha a tesztek közben mégsem megy, akkor ellenőrizd, hogy a beírt moodle
|
||||
cím egyezik-e a teszt közbenivel. Ha kell egy kis segítség, kérdésed
|
||||
van, nem működik valami, vagy éppen működik, de alapból nincs
|
||||
hozzáadva:{' '}
|
||||
<Link href="/contact">
|
||||
írj a kapcsolat oldalon!
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</>;
|
||||
return (
|
||||
<>
|
||||
Jelenleg az, hogy a script melyik oldalakon fut bele van égetve a script
|
||||
forráskódjába. Ez itt látható:{' '}
|
||||
<a
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
href="https://gitlab.com/MrFry/moodle-test-userscript/-/blob/master/stable.user.js#L52"
|
||||
>
|
||||
stable.user.js#L52
|
||||
</a>
|
||||
{'. '}
|
||||
Ez azért van így, hogy biztos csak olyan oldalakon fusson a script amit
|
||||
támogat is.
|
||||
<p />
|
||||
Ehhez persze kézzel hozzá lehet adni ideiglenesen bármilyen oldalt, hogy
|
||||
kipróbáld ott működik-e. Akár működik, akár nem kérlek szólj, és frissítem
|
||||
a scriptet hogy azon a domainen is fusson és működjön alapból.
|
||||
<p />
|
||||
Egyetem moodle oldalának hozzáadása a scripthez kézzel:
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/script">Először telepítsd a scriptet rendesen</Link>{' '}
|
||||
</li>
|
||||
<li>
|
||||
Böngészőben nyisd meg a Tampermonkey bővítményt <br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-1.png`} />
|
||||
<br />
|
||||
Itt kattints a Dashboard-ra.
|
||||
</li>
|
||||
<li>
|
||||
Keresd meg a scriptet, majd kattints rá:
|
||||
<br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-2.png`} />
|
||||
</li>
|
||||
<li>
|
||||
A felugró szerkesztőben keresd meg a következő sorokat:
|
||||
<br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-3.png`} />
|
||||
</li>
|
||||
<li>
|
||||
Itt az egyik <i>@match ...</i> sor után egy új sorban írd be az
|
||||
egyetemed moodle oldalának címét. Ha ez a cím pl.:{' '}
|
||||
<i>https://moodle.egyetem.hu/main/akármi</i>, akkor a következőre írd
|
||||
át: <i>https://moodle.egyetem.hu/*</i>. Fenti képen látsz néhány
|
||||
példát. <i>A {'"*"'} a végén fontos!</i>
|
||||
</li>
|
||||
<li>
|
||||
Ezután mentsd el (ctrl + s, vagy file {'->'} save). Ha minden jól
|
||||
ment, akkor elég frissíteni a moodle oldalát, és a script futni fog
|
||||
rajta. Ezek után azon az oldalon amit beírtál meg kell jelennie a
|
||||
Tampermonkey menüjében is:
|
||||
<br />
|
||||
<img className={'manual_img'} src={`img/faq/siteadd-4.png`} />
|
||||
</li>
|
||||
<li>
|
||||
Ha a tesztek közben mégsem megy, akkor ellenőrizd, hogy a beírt moodle
|
||||
cím egyezik-e a teszt közbenivel. Ha kell egy kis segítség, kérdésed
|
||||
van, nem működik valami, vagy éppen működik, de alapból nincs
|
||||
hozzáadva: <Link href="/contact">írj a kapcsolat oldalon!</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const pages = {
|
||||
|
|
|
@ -25,12 +25,11 @@ export default function UserForum({
|
|||
</div>
|
||||
)}
|
||||
<Forum
|
||||
allowPost
|
||||
router={router}
|
||||
globalState={globalState}
|
||||
setGlobalState={setGlobalState}
|
||||
globalData={globalData}
|
||||
forumName={'userForum'}
|
||||
forumName={'frontpage'}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -9,7 +9,7 @@ import Composer from '../components/composer'
|
|||
import Modal from '../components/modal'
|
||||
|
||||
import styles from './memes.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
const forumPostPerPage = 5
|
||||
const frontpageForumName = 'memes'
|
||||
|
|
|
@ -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;
|
||||
}
|
184
src/pages/p2pinfo.jsx
Normal file
184
src/pages/p2pinfo.jsx
Normal file
|
@ -0,0 +1,184 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
|
||||
import Header from '../components/header'
|
||||
import constants from '../constants'
|
||||
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: 'Script version',
|
||||
key: 'scriptVersion',
|
||||
},
|
||||
{
|
||||
title: 'Szerver build time',
|
||||
key: 'serverBuildTime',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
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ó'} />
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
A weboldal peer to peer (p2p) megoldást implementál, folyamatosan
|
||||
megosztja az új kérdéseket a lent megadott regisztrált szerverekkel,
|
||||
és hozzáadja a kapott új kérdéseket a helyi adatbázishoz.
|
||||
<p />
|
||||
Ha az egyik szerver kiesne, a script a megadott szerverek közül
|
||||
választ egy újat. A felhasználók is szinkronizálva vannak, így a
|
||||
jelenlegi jelszavaddal bármelyik másik oldalra be tudsz lépni
|
||||
<p />A szervert akár te is hostolhatod, érdeklődj a lentebb megadott
|
||||
kontakton
|
||||
</div>
|
||||
<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'}
|
||||
rel="noreferrer"
|
||||
>
|
||||
{peer.host}:{peer.port}
|
||||
</a>
|
||||
</div>
|
||||
<div>{new Date(peer.lastSync).toLocaleString()}</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{p2pInfo.myPeers.length === 0 && (
|
||||
<div className={styles.peerContainer}>
|
||||
Ennél a szervernél jelenleg nincs peer regisztrálva
|
||||
</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;
|
||||
}
|
|
@ -4,7 +4,7 @@ import Link from 'next/link'
|
|||
import Header from '../components/header'
|
||||
|
||||
import styles from './pwRequest.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
function fetchAvailablePWS() {
|
||||
return new Promise((resolve) => {
|
||||
|
@ -107,10 +107,7 @@ export default function PwRequest({ globalData, globalState, setGlobalState }) {
|
|||
Minden felhasználó egyedi jelszót kap. Ne használjatok többen egy
|
||||
jelszót, mert egy idő után -biztonsági okokból- kidob a rendszer,
|
||||
ha ugyan az a felhasználó több helyen is belépve marad. A
|
||||
jelszavakról bővebben a{' '}
|
||||
<Link href="/faq?tab=pw">
|
||||
GYIK
|
||||
</Link>{' '}
|
||||
jelszavakról bővebben a <Link href="/faq?tab=pw">GYIK</Link>{' '}
|
||||
vonatkozó részében olvashatsz.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -191,5 +188,5 @@ export default function PwRequest({ globalData, globalState, setGlobalState }) {
|
|||
</div>
|
||||
</center>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import Header from '../components/header'
|
|||
import LoadingIndicator from '../components/LoadingIndicator'
|
||||
|
||||
import styles from './ranklist.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
const selectOptions = {
|
||||
newQuestions: { name: 'Beküldött új kérdések' },
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useQuery } from 'react-query'
|
|||
import Header from '../components/header'
|
||||
import Link from 'next/link'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
import ExternalLinkIcon from '../components/externalLinkIcon'
|
||||
|
||||
import styles from './script.module.css'
|
||||
|
@ -102,13 +102,9 @@ export default function Script() {
|
|||
<li>
|
||||
Ha be vagy jelentkezve, akkor a teszt oldalakon a megoldásokat
|
||||
kellene látnod egy felugró ablakban felül. Ha nem, akkor{' '}
|
||||
<Link href="/faq">
|
||||
GYIK
|
||||
</Link>
|
||||
<Link href="/faq">GYIK</Link>
|
||||
-be olvass bele, vagy{' '}
|
||||
<Link href="/contact">
|
||||
írj üzenetet mi nem működik
|
||||
</Link>
|
||||
<Link href="/contact">írj üzenetet mi nem működik</Link>
|
||||
</li>
|
||||
</ol>
|
||||
<b>Példa felugró ablakokra:</b>
|
||||
|
@ -161,5 +157,5 @@ export default function Script() {
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react'
|
||||
import styles from './thanks.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
import Head from 'next/head'
|
||||
|
||||
export default function Thanks() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import UpDownVote from '../components/upDownVote'
|
|||
import Header from '../components/header'
|
||||
|
||||
import styles from './userfiles.module.css'
|
||||
import constants from '../constants.json'
|
||||
import constants from '../constants'
|
||||
|
||||
function vote(to, item) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -382,7 +382,11 @@ export default function UserFiles({
|
|||
<div className={`${styles.tableContainer} ${styles.rows}`}>
|
||||
{currDir && (
|
||||
<div
|
||||
style={{ height: 40, justifyContent: "center", display: "flex" }}
|
||||
style={{
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
display: 'flex',
|
||||
}}
|
||||
onClick={() => {
|
||||
goBack()
|
||||
}}
|
||||
|
@ -482,13 +486,14 @@ export default function UserFiles({
|
|||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
className={'userId'}>
|
||||
className={'userId'}
|
||||
>
|
||||
{`#${user}`}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</>
|
||||
) : (
|
||||
|
@ -513,7 +518,7 @@ export default function UserFiles({
|
|||
<LoadingIndicator />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -535,10 +540,8 @@ export default function UserFiles({
|
|||
vállalás nincs.
|
||||
</b>{' '}
|
||||
Ha valami nem idevalót látsz, azt a{' '}
|
||||
<Link href="/contact">
|
||||
Kapcsolat
|
||||
</Link>{' '}
|
||||
oldalon jelezd kérlek. Tudatos károkozásért ban jár.
|
||||
<Link href="/contact">Kapcsolat</Link> oldalon jelezd kérlek. Tudatos
|
||||
károkozásért ban jár.
|
||||
</div>
|
||||
)}
|
||||
<hr />
|
||||
|
@ -602,5 +605,5 @@ export default function UserFiles({
|
|||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
46
src/pages/validation.jsx
Normal file
46
src/pages/validation.jsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import Header from '../components/header'
|
||||
|
||||
import styles from './validation.module.css'
|
||||
import constants from '../constants'
|
||||
|
||||
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:
|
||||
</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