mirror of
https://gitlab.com/MrFry/qmining-page
synced 2025-04-01 20:23:44 +02:00
Merge
This commit is contained in:
commit
6d2b682117
14 changed files with 329 additions and 122 deletions
49
src/components/todoStuff/todoBoard.js
Normal file
49
src/components/todoStuff/todoBoard.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
import React from 'react'
|
||||
|
||||
import TodoCard from './todoCard.js'
|
||||
|
||||
import styles from './todoBoard.module.css'
|
||||
|
||||
export default function TodoBoard(props) {
|
||||
const { columns, cards, userId, categories, onCardClick } = 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]
|
||||
return (
|
||||
<div className={styles.tableCol} key={key}>
|
||||
<div className={styles.categoryName}>{category.name}</div>
|
||||
{cards.map((card, i) => {
|
||||
if (card.state === key) {
|
||||
// TODO: determine if clickable here
|
||||
return (
|
||||
<TodoCard
|
||||
key={i}
|
||||
cardData={card}
|
||||
userId={userId}
|
||||
categories={categories}
|
||||
onClick={onCardClick}
|
||||
clickable={clickableTypes.includes(key)}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
23
src/components/todoStuff/todoBoard.module.css
Normal file
23
src/components/todoStuff/todoBoard.module.css
Normal file
|
@ -0,0 +1,23 @@
|
|||
.tableContainer {
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
margin: 5px 0px;
|
||||
}
|
||||
|
||||
.table {
|
||||
display: flex;
|
||||
min-width: 800px;
|
||||
}
|
||||
|
||||
.categoryName {
|
||||
text-align: center;
|
||||
margin: 5px 0px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tableCol {
|
||||
flex: 1;
|
||||
}
|
|
@ -2,12 +2,9 @@ import React from 'react'
|
|||
|
||||
import styles from './todoCard.module.css'
|
||||
|
||||
const clickableTypes = ['todo', 'blocked', 'inprogress', 'testing']
|
||||
|
||||
export default function TodoCard(props) {
|
||||
const { categories, type, onClick, userId } = props
|
||||
const { categories, onClick, userId, clickable } = props
|
||||
const { name, description, category, points, votes, id } = props.cardData
|
||||
const clickable = clickableTypes.includes(type)
|
||||
const voted = votes.includes(userId)
|
||||
|
||||
return (
|
||||
|
|
34
src/components/todoStuff/todoRow.js
Normal file
34
src/components/todoStuff/todoRow.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
import React from 'react'
|
||||
|
||||
import styles from './todoRow.module.css'
|
||||
|
||||
export default function TodoRow(props) {
|
||||
const { categories, userId } = props
|
||||
const { name, description, category, votes, id } = props.rowData
|
||||
const voted = votes.includes(userId)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.row} ${voted && styles.voted}`}
|
||||
title={description}
|
||||
>
|
||||
<div className={styles.id}>{`#${id}`}</div>
|
||||
<div className={styles.description}>{name}</div>
|
||||
<div className={styles.catName}>
|
||||
<div
|
||||
style={{
|
||||
wordBreak: 'break-all',
|
||||
fontSize: '10px',
|
||||
backgroundColor: categories[category].color,
|
||||
color: 'white',
|
||||
borderRadius: '2px',
|
||||
padding: '0px 2px',
|
||||
}}
|
||||
>
|
||||
{categories[category].name}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.votes}>{`Votes: ${votes.length}`}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
40
src/components/todoStuff/todoRow.module.css
Normal file
40
src/components/todoStuff/todoRow.module.css
Normal file
|
@ -0,0 +1,40 @@
|
|||
.row {
|
||||
display: flex;
|
||||
border: 2px solid #99f;
|
||||
border-radius: 2px;
|
||||
padding: 5px;
|
||||
margin: 6px 3px;
|
||||
}
|
||||
|
||||
.row > div {
|
||||
margin: 0px 5px;
|
||||
}
|
||||
|
||||
.id {
|
||||
flex: 0 20px;
|
||||
margin: 0px 3px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.description {
|
||||
flex: 1;
|
||||
word-break: normal;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.votes {
|
||||
}
|
||||
|
||||
.voted {
|
||||
border: 2px solid #cf9;
|
||||
}
|
||||
|
||||
.catName {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.category {
|
||||
word-break: break-all;
|
||||
font-size: 10px;
|
||||
}
|
|
@ -1,80 +1,35 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import React from 'react'
|
||||
|
||||
import LoadingIndicator from '../LoadingIndicator.js'
|
||||
import TodoCard from './todoCard.js'
|
||||
import TodoRow from './todoRow.js'
|
||||
|
||||
import constants from '../../constants.json'
|
||||
import styles from './todoTable.module.css'
|
||||
|
||||
export default function TodoTable() {
|
||||
const [cards, setCards] = useState(null)
|
||||
const [columns, setColumns] = useState(null)
|
||||
const [categories, setCategories] = useState(null)
|
||||
const [userId, setUserId] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
console.info('Fetching todos')
|
||||
fetch(`${constants.apiUrl}todos`, {
|
||||
credentials: 'include',
|
||||
})
|
||||
.then((resp) => {
|
||||
return resp.json()
|
||||
})
|
||||
.then((data) => {
|
||||
setTodos(data)
|
||||
})
|
||||
}, [])
|
||||
|
||||
const setTodos = (data) => {
|
||||
setCards(
|
||||
data.todos.cards.sort((a, b) => {
|
||||
return b.votes.length - a.votes.length
|
||||
})
|
||||
)
|
||||
setColumns(data.todos.columns)
|
||||
setCategories(data.todos.categories)
|
||||
setUserId(data.userId)
|
||||
}
|
||||
|
||||
const onCardClick = (id) => {
|
||||
fetch(`${constants.apiUrl}voteTodo?id=${id}`, {
|
||||
credentials: 'include',
|
||||
})
|
||||
.then((resp) => {
|
||||
return resp.json()
|
||||
})
|
||||
.then((data) => {
|
||||
setTodos(data)
|
||||
})
|
||||
}
|
||||
|
||||
if (!cards || !columns || !categories) {
|
||||
return <LoadingIndicator />
|
||||
}
|
||||
export default function TodoBoard(props) {
|
||||
const { tables, cards, userId, categories } = props
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.tableContainer}>
|
||||
<div className={styles.table}>
|
||||
{Object.keys(columns).map((key) => {
|
||||
const category = columns[key]
|
||||
{Object.keys(tables).map((key) => {
|
||||
const table = tables[key]
|
||||
|
||||
const tableCards = cards.filter((card) => {
|
||||
return card.state === key
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={styles.tableCol} key={key}>
|
||||
<div className={styles.categoryName}>{category.name}</div>
|
||||
{cards.map((card, i) => {
|
||||
if (card.state === key) {
|
||||
return (
|
||||
<TodoCard
|
||||
key={i}
|
||||
type={key}
|
||||
cardData={card}
|
||||
userId={userId}
|
||||
categories={categories}
|
||||
onClick={onCardClick}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
<div className={styles.container} key={key}>
|
||||
<div className={styles.title}>{table.name}</div>
|
||||
{tableCards.map((card, i) => {
|
||||
return (
|
||||
<TodoRow
|
||||
key={i}
|
||||
type={key}
|
||||
rowData={card}
|
||||
userId={userId}
|
||||
categories={categories}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
.table {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.categoryName {
|
||||
text-align: center;
|
||||
.tableContainer {
|
||||
margin: 5px 0px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tableCol {
|
||||
flex: 1;
|
||||
.table {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
107
src/components/todoStuff/todos.js
Normal file
107
src/components/todoStuff/todos.js
Normal file
|
@ -0,0 +1,107 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import LoadingIndicator from '../LoadingIndicator.js'
|
||||
import TodoBoard from './todoBoard.js'
|
||||
import TodoTable from './todoTable.js'
|
||||
|
||||
import constants from '../../constants.json'
|
||||
|
||||
const byVotes = (a, b) => {
|
||||
return b.votes.length - a.votes.length
|
||||
}
|
||||
|
||||
export default function Todos() {
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const [columns, setColumns] = useState(null)
|
||||
const [boardCards, setBoardCards] = useState(null)
|
||||
const [tables, setTables] = useState(null)
|
||||
const [tableCards, setTableCards] = useState(null)
|
||||
const [categories, setCategories] = useState(null)
|
||||
const [userId, setUserId] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
console.info('Fetching todos')
|
||||
fetch(`${constants.apiUrl}todos`, {
|
||||
credentials: 'include',
|
||||
})
|
||||
.then((resp) => {
|
||||
return resp.json()
|
||||
})
|
||||
.then((data) => {
|
||||
setTodos(data)
|
||||
})
|
||||
}, [])
|
||||
|
||||
const setTodos = (data) => {
|
||||
setCategories(data.todos.categories)
|
||||
setUserId(data.userId)
|
||||
|
||||
let bCards = []
|
||||
let tCards = []
|
||||
data.todos.cards.forEach((card) => {
|
||||
if (data.todos.columns[card.state].type === 'table') {
|
||||
tCards.push(card)
|
||||
} else {
|
||||
bCards.push(card)
|
||||
}
|
||||
})
|
||||
|
||||
setTableCards(tCards.sort(byVotes))
|
||||
setBoardCards(bCards.sort(byVotes))
|
||||
|
||||
let cols = {}
|
||||
let tables = {}
|
||||
Object.keys(data.todos.columns).forEach((key) => {
|
||||
const col = data.todos.columns[key]
|
||||
if (col.type !== 'table') {
|
||||
cols = {
|
||||
...cols,
|
||||
[key]: col,
|
||||
}
|
||||
} else {
|
||||
tables = {
|
||||
...tables,
|
||||
[key]: col,
|
||||
}
|
||||
}
|
||||
})
|
||||
setColumns(cols)
|
||||
setTables(tables)
|
||||
|
||||
setLoaded(true)
|
||||
}
|
||||
|
||||
const onCardClick = (id) => {
|
||||
fetch(`${constants.apiUrl}todos?id=${id}`, {
|
||||
credentials: 'include',
|
||||
})
|
||||
.then((resp) => {
|
||||
return resp.json()
|
||||
})
|
||||
.then((data) => {
|
||||
setTodos(data)
|
||||
})
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
return <LoadingIndicator />
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TodoBoard
|
||||
columns={columns}
|
||||
cards={boardCards}
|
||||
userId={userId}
|
||||
categories={categories}
|
||||
onCardClick={onCardClick}
|
||||
/>
|
||||
<TodoTable
|
||||
tables={tables}
|
||||
cards={tableCards}
|
||||
userId={userId}
|
||||
categories={categories}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -10,5 +10,13 @@
|
|||
"data": {
|
||||
"href": "/data.json",
|
||||
"text": "Összes kérdés JSON"
|
||||
},
|
||||
"irc": {
|
||||
"href": "/irc",
|
||||
"text": "IRC chat"
|
||||
},
|
||||
"dataeditor": {
|
||||
"href": "/dataeditor",
|
||||
"text": "Dataeditor"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
},
|
||||
"contribute": {
|
||||
"href": "/contribute",
|
||||
"text": "Contribute / Todos"
|
||||
"text": "Todos, contribute"
|
||||
},
|
||||
"ranklist": {
|
||||
"href": "/ranklist",
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React, { useState } from 'react'
|
||||
import Head from 'next/head'
|
||||
|
||||
import Button from '../components/Button.js'
|
||||
import Sleep from '../components/sleep'
|
||||
import TodoTable from '../components/todoStuff/todoTable'
|
||||
import Todos from '../components/todoStuff/todos'
|
||||
|
||||
import constants from '../constants.json'
|
||||
import styles from './contribute.module.css'
|
||||
|
@ -72,39 +71,26 @@ export default function contribute() {
|
|||
annál nehezebb a feladat. Tartsd egeret kártyán részletesebb leírásért
|
||||
(ha van hozzá)
|
||||
</div>
|
||||
<TodoTable />
|
||||
<Todos />
|
||||
<div className={styles.description}>Itt írhatsz todo-ra ötleteket </div>
|
||||
{renderNewTaskArea()}
|
||||
<Sleep />
|
||||
<hr />
|
||||
<div className={styles.description}>
|
||||
Csak álnévvel commitolj git repókhoz!
|
||||
</div>
|
||||
<div className={styles.title}>Git repos</div>
|
||||
<hr />
|
||||
<hr />
|
||||
<div className={styles.repos}>
|
||||
<div>Git repo links</div>
|
||||
{Object.keys(repos.repos).map((key) => {
|
||||
let repo = repos.repos[key]
|
||||
return (
|
||||
<div key={key}>
|
||||
<a href={repo.href}>{repo.description}</a>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<ul>
|
||||
{Object.keys(repos.repos).map((key) => {
|
||||
let repo = repos.repos[key]
|
||||
return (
|
||||
<li key={key}>
|
||||
<a href={repo.href}>{repo.description}</a>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
<hr />
|
||||
<div className={styles.description}>
|
||||
IRC chat: egy IRC chatszoba van létrehozva egy random szerveren, ahol
|
||||
tudsz azonnal üzenni, és ha épp fent vagyok akkor azonnal válaszolok
|
||||
</div>
|
||||
<Button text="IRC chat" href="/irc" />
|
||||
<hr />
|
||||
<div className={styles.description}>
|
||||
Kérdés szerkesztő: Ezen az oldalon lehet szerkeszteni az összes kérdést,
|
||||
duplikációkat eltávolítani vagy helytelen válaszokat kijavítani kézzel.
|
||||
Ha van hozzá jelszavad, akkor ezt azonnal el tudod menteni, ha nincs és
|
||||
úgy érzed szeretnél akkor kattints a fenti IRC chat gombra!
|
||||
</div>
|
||||
<Button text="Data Editor" href="/dataeditor" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
.repos {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 15px;
|
||||
color: white;
|
||||
|
@ -39,3 +33,9 @@
|
|||
.inputArea {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #9999ff;
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -167,6 +167,7 @@ export default function Index({ router }) {
|
|||
{renderMotd()}
|
||||
{userSpecificMotd && renderUserSpecificMotd()}
|
||||
<hr />
|
||||
<hr />
|
||||
<Sleep />
|
||||
{renderNews()}
|
||||
</div>
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
color: white;
|
||||
background-color: #303030;
|
||||
margin: 2px;
|
||||
padding: 15px 32px;
|
||||
padding: 10px 5px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
word-wrap: break-word;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -69,3 +70,8 @@
|
|||
margin: 0px 5px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.repos {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue