---
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import { useState, useEffect } from "react"
|
||||
import Select from 'react-select'
|
||||
import { customTheme } from "../../constants"
|
||||
import { isObject } from '../../helpers/isObject'
|
||||
import './style.css'
|
||||
export const EditableSelector = (props) => {
|
||||
const { defaultSelectValue, onUpdate, style, options, defaultValue, multi, components, styles, placeholder, isSearchable } = props
|
||||
const [value, setValue] = useState(defaultValue)
|
||||
useEffect(() => {
|
||||
setValue(defaultValue)
|
||||
}, [defaultValue])
|
||||
useEffect(() => {
|
||||
onUpdate(value)
|
||||
}, [value])
|
||||
const updateValue = (val) => {
|
||||
if (multi) {
|
||||
if (Array.isArray(defaultValue)) {
|
||||
if (val != undefined && val != null) {
|
||||
if (val.length == 0) {
|
||||
setValue([])
|
||||
}
|
||||
else {
|
||||
let tempValue = []
|
||||
val.forEach(item => {
|
||||
tempValue.push(item.value)
|
||||
})
|
||||
setValue(tempValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isObject(defaultValue)) {
|
||||
if (val != undefined && val != null) {
|
||||
if (val.length == 0) {
|
||||
setValue({})
|
||||
}
|
||||
else {
|
||||
let newValue = {}
|
||||
val.forEach(item => {
|
||||
Object.keys(item.value).forEach(key => {
|
||||
newValue[`${key}`] = item.value[`${key}`]
|
||||
})
|
||||
})
|
||||
setValue(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (val == undefined || val == null) {
|
||||
setValue("")
|
||||
}
|
||||
else {
|
||||
setValue(val.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{
|
||||
multi ?
|
||||
<Select className="editable_selector"
|
||||
isMulti={true}
|
||||
theme={customTheme}
|
||||
style={style}
|
||||
options={options}
|
||||
defaultValue={defaultSelectValue}
|
||||
onChange={updateValue}
|
||||
components={components}
|
||||
styles={styles}
|
||||
isSearchable={isSearchable} //false
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
:
|
||||
<Select className="editable_selector"
|
||||
isMulti={false}
|
||||
theme={customTheme}
|
||||
style={style}
|
||||
options={options}
|
||||
defaultValue={defaultSelectValue}
|
||||
onChange={updateValue}
|
||||
isClearable={true}
|
||||
components={components}
|
||||
styles={styles}
|
||||
placeholder={placeholder}
|
||||
isSearchable={isSearchable}
|
||||
/>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
.editable_selector {
|
||||
width: 100%;
|
||||
}
|
||||
.editable_selector input {
|
||||
font-family: "Lora", serif;
|
||||
font-size: 0.7rem !important;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { useState, useEffect, useRef } from "react"
|
||||
import _ from "lodash"
|
||||
import './style.css'
|
||||
export const EditableText = (props) => {
|
||||
const { defaultValue, onUpdate, style } = props;
|
||||
const [value, setValue] = useState(defaultValue)
|
||||
const onUpdateWithDebounce = _.debounce(onUpdate, 500)
|
||||
const inputRef = useRef(null)
|
||||
const unfocusInput = (e) => {
|
||||
if (e.keyCode == 13) inputRef.current.blur();
|
||||
}
|
||||
useEffect(() => {
|
||||
setValue(defaultValue)
|
||||
}, [defaultValue])
|
||||
useEffect(() => {
|
||||
onUpdateWithDebounce(value);
|
||||
}, [value])
|
||||
useEffect(() => {
|
||||
inputRef && inputRef.current &&
|
||||
inputRef.current.addEventListener('keyup', unfocusInput);
|
||||
}, [inputRef])
|
||||
return (
|
||||
<input ref={inputRef} className="editable_text" type="text" spellCheck={false} value={value} style={style} onChange={(e) => setValue(e.target.value)} />
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
.editable_text {
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
/* display: flex;
|
||||
justify-content: center;
|
||||
align-items: center; */
|
||||
font-family: "Lora", serif;
|
||||
}
|
||||
/* .editable_text:focus {
|
||||
border: 1px solid black;
|
||||
outline: none;
|
||||
} */
|
||||
@@ -0,0 +1,26 @@
|
||||
import { useState, useEffect, useRef } from "react"
|
||||
import TextareaAutosize from "react-textarea-autosize"
|
||||
import _ from "lodash"
|
||||
import './style.css'
|
||||
export const EditableTextArea = (props) => {
|
||||
const { defaultValue, onUpdate, style } = props;
|
||||
const [value, setValue] = useState(defaultValue)
|
||||
const onUpdateWithDebounce = _.debounce(onUpdate, 500)
|
||||
const inputRef = useRef(null)
|
||||
const unfocusInput = (e) => {
|
||||
if (e.keyCode == 13) inputRef.current.blur();
|
||||
}
|
||||
useEffect(() => {
|
||||
setValue(defaultValue)
|
||||
}, [defaultValue])
|
||||
useEffect(() => {
|
||||
onUpdateWithDebounce(value);
|
||||
}, [value])
|
||||
useEffect(() => {
|
||||
inputRef && inputRef.current &&
|
||||
inputRef.current.addEventListener('keyup', unfocusInput);
|
||||
}, [inputRef])
|
||||
return (
|
||||
<TextareaAutosize spellCheck={false} ref={inputRef} className="editable_text_area" type="text" value={value} style={style} onChange={(e) => setValue(e.target.value)} />
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
.editable_text_area {
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: "Lora", serif;
|
||||
resize: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* .editable_text_area:focus {
|
||||
border: 1px solid black;
|
||||
outline: none;
|
||||
} */
|
||||
@@ -0,0 +1,68 @@
|
||||
import { isBrowser } from 'react-device-detect'
|
||||
import { useStylesPC } from './stylePC'
|
||||
import { useStylesMobile } from './styleMobile'
|
||||
|
||||
export const InformationContainer = () => {
|
||||
const classesPC = useStylesPC()
|
||||
const classesMobile = useStylesMobile()
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
isBrowser
|
||||
? classesPC.informationContainer
|
||||
: classesMobile.informationContainer
|
||||
}
|
||||
>
|
||||
<div className='topLane'>
|
||||
<button>
|
||||
<a href='/about'>ABOUT</a>
|
||||
</button>
|
||||
</div>
|
||||
<div className='midLane'>
|
||||
{/* I no longer use Facebook. */}
|
||||
<a href='about:blank'>
|
||||
<button>
|
||||
<i className='fab fa-facebook-square' />
|
||||
</button>
|
||||
</a>
|
||||
{/* I no longer use Twitter. */}
|
||||
<a href='about:blank'>
|
||||
<button>
|
||||
<i className='fab fa-twitter-square' />
|
||||
</button>
|
||||
</a>
|
||||
<a href='https://gitea.elliot-at-zuri.ch/admin'>
|
||||
<button>
|
||||
<i className='fab fa-github-square' />
|
||||
</button>
|
||||
</a>
|
||||
{/* I no longer use Patreon. */}
|
||||
<a href='about:blank'>
|
||||
<button>
|
||||
<i className='fab fa-patreon' />
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div className='botLane'>
|
||||
<div className='introText'>
|
||||
<div>
|
||||
Debaters' toolkit is an open-source software licensed under the{' '}
|
||||
<a href='https://choosealicense.com/licenses/mit/'>
|
||||
<span>MIT license</span>
|
||||
</a>{' '}
|
||||
that aims to be useful to all debaters. Our motions are collected
|
||||
from various sources. While we strive to update the database as
|
||||
regularly as possible, we cannot warrant absolute correctness for
|
||||
all motions. If you have any issue with our content or detect any
|
||||
bug in our app, please contact us at{' '}
|
||||
<a href='mailto: quyanh.nguyen@helsinki'>
|
||||
<span>quyanh.nguyen@helsinki</span>
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
<div className='aboutSubHeader'>© 2021 [Quy Anh] «Elliot» Nguyen.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
.informationContainer {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #282a35 !important;
|
||||
height: 38vh;
|
||||
min-height: 14.3rem;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
margin-top: auto;
|
||||
.topLane {
|
||||
width: 100%;
|
||||
height: 20%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
button {
|
||||
padding: 0.3rem;
|
||||
border-radius: 5px;
|
||||
border: 1px solid white;
|
||||
background-color: transparent;
|
||||
font-weight: 500;
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
button:hover {
|
||||
background-color: white;
|
||||
a {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
.midLane {
|
||||
width: 100%;
|
||||
height: 20%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
button {
|
||||
background-color: #282a35;
|
||||
border: 1px solid white;
|
||||
border-radius: 5px;
|
||||
padding: 0.4rem;
|
||||
margin-left: 0.2rem;
|
||||
margin-right: 0.2rem;
|
||||
i {
|
||||
color: white;
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
button:hover {
|
||||
background-color: white;
|
||||
i {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
.botLane {
|
||||
width: 100%;
|
||||
height: 60%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.introText {
|
||||
color: white !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 90%;
|
||||
div {
|
||||
margin: 0.5rem;
|
||||
text-align: center;
|
||||
a {
|
||||
color: white;
|
||||
span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
span:hover {
|
||||
color: #4caf50;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 379px) {
|
||||
.informationContainer {
|
||||
height: 47vh;
|
||||
.topLane {
|
||||
height: 12%;
|
||||
}
|
||||
.midLane {
|
||||
height: 10%;
|
||||
}
|
||||
.botLane {
|
||||
height: 78%;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 425px) and (min-width: 380px) {
|
||||
.informationContainer {
|
||||
height: 40vh;
|
||||
.topLane {
|
||||
height: 17%;
|
||||
}
|
||||
.midLane {
|
||||
height: 13%;
|
||||
}
|
||||
.botLane {
|
||||
height: 70%;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 768px) and (min-width: 426px) {
|
||||
.informationContainer {
|
||||
height: 25vh;
|
||||
.topLane {
|
||||
}
|
||||
.midLane {
|
||||
}
|
||||
.botLane {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
import { makeStyles } from '@mui/styles'
|
||||
|
||||
export const useStylesMobile = makeStyles({
|
||||
'informationContainer': {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: '#282a35 !important',
|
||||
height: '38vh',
|
||||
minHeight: '14.3rem',
|
||||
fontFamily: '"Source Sans Pro", sans-serif',
|
||||
marginTop: 'auto',
|
||||
'& .topLane': {
|
||||
width: '100%',
|
||||
height: '20%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'& button': {
|
||||
padding: '0.3rem',
|
||||
borderRadius: '5px',
|
||||
border: '1px solid white',
|
||||
backgroundColor: 'transparent',
|
||||
fontWeight: 500,
|
||||
'& a': {
|
||||
textDecoration: 'none',
|
||||
color: 'white'
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'white',
|
||||
'& a': {
|
||||
color: 'black'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'& .midLane': {
|
||||
width: '100%',
|
||||
height: '20%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'& button': {
|
||||
backgroundColor: '#282a35',
|
||||
border: '1px solid white',
|
||||
borderRadius: '5px',
|
||||
padding: '0.4rem',
|
||||
marginLeft: '0.2rem',
|
||||
marginRight: '0.2rem',
|
||||
'& i': {
|
||||
color: 'white',
|
||||
fontSize: '2rem'
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'white',
|
||||
'& i': {
|
||||
color: 'black'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'& .botLane': {
|
||||
width: '100%',
|
||||
height: '60%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'& .introText': {
|
||||
color: 'white !important',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
width: '90%',
|
||||
'& div': {
|
||||
margin: '0.5rem',
|
||||
textAlign: 'center',
|
||||
'& a': {
|
||||
color: 'white',
|
||||
'& span': {
|
||||
textDecoration: 'underline',
|
||||
'&:hover': {
|
||||
color: '#4caf50'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 379px)': {
|
||||
'informationContainer': {
|
||||
height: '47vh',
|
||||
'& .topLane': {
|
||||
height: '12%'
|
||||
},
|
||||
'& .midLane': {
|
||||
height: '10%',
|
||||
},
|
||||
'& .botLane': {
|
||||
height: '78%',
|
||||
marginBottom: '0.5rem'
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 425px) and (min-width: 380px)': {
|
||||
'informationContainer': {
|
||||
height: '40vh',
|
||||
'& .topLane': {
|
||||
height: '17%',
|
||||
},
|
||||
'& .midLane': {
|
||||
height: '13%',
|
||||
},
|
||||
'& .botLane': {
|
||||
height: '70%',
|
||||
marginBottom: '0.5rem'
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 768px) and (min-width: 426px)': {
|
||||
'informationContainer': {
|
||||
height: '25vh'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,138 @@
|
||||
import { makeStyles } from '@mui/styles'
|
||||
|
||||
export const useStylesPC = makeStyles({
|
||||
'informationContainer': {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: '#282a35 !important',
|
||||
height: '38vh',
|
||||
minHeight: '14.3rem',
|
||||
fontFamily: '"Source Sans Pro", sans-serif',
|
||||
marginTop: 'auto',
|
||||
'& .topLane': {
|
||||
width: '100%',
|
||||
height: '20%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'& button': {
|
||||
padding: '0.3rem',
|
||||
borderRadius: '5px',
|
||||
border: '1px solid white',
|
||||
backgroundColor: 'transparent',
|
||||
fontWeight: 500,
|
||||
'& a': {
|
||||
textDecoration: 'none',
|
||||
color: 'white'
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'white',
|
||||
'& a': {
|
||||
color: 'black'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'& .midLane': {
|
||||
width: '100%',
|
||||
height: '20%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'& button': {
|
||||
backgroundColor: '#282a35',
|
||||
border: '1px solid white',
|
||||
borderRadius: '5px',
|
||||
padding: '0.4rem',
|
||||
marginLeft: '0.2rem',
|
||||
marginRight: '0.2rem',
|
||||
'& i': {
|
||||
color: 'white',
|
||||
fontSize: '2rem'
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'white',
|
||||
'& i': {
|
||||
color: 'black'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'& .botLane': {
|
||||
width: '100%',
|
||||
height: '60%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'& .introText': {
|
||||
color: 'white !important',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
width: '90%',
|
||||
fontSize: '1rem',
|
||||
'& div': {
|
||||
margin: '0.5rem',
|
||||
textAlign: 'center',
|
||||
'& a': {
|
||||
color: 'white',
|
||||
'& span': {
|
||||
textDecoration: 'underline',
|
||||
'&:hover': {
|
||||
color: '#4caf50'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 379px)': {
|
||||
'informationContainer': {
|
||||
height: '47vh',
|
||||
'& .topLane': {
|
||||
height: '12%'
|
||||
},
|
||||
'& .midLane': {
|
||||
height: '10%',
|
||||
},
|
||||
'& .botLane': {
|
||||
height: '78%',
|
||||
marginBottom: '0.5rem',
|
||||
'& .introText': {
|
||||
fontSize: '0.8rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 425px) and (min-width: 380px)': {
|
||||
'informationContainer': {
|
||||
height: '40vh',
|
||||
'& .topLane': {
|
||||
height: '17%',
|
||||
},
|
||||
'& .midLane': {
|
||||
height: '13%',
|
||||
},
|
||||
'& .botLane': {
|
||||
height: '70%',
|
||||
marginBottom: '0.5rem',
|
||||
'& .introText': {
|
||||
fontSize: '0.8rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 768px) and (min-width: 426px)': {
|
||||
'informationContainer': {
|
||||
height: '25vh',
|
||||
'& .botLane': {
|
||||
'& .introText': {
|
||||
fontSize: '0.8rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,44 @@
|
||||
import './style.css'
|
||||
import { useState, useEffect } from 'react';
|
||||
export const Message = (props) => {
|
||||
const { status, successMessage, failureMessage } = props;
|
||||
const [show, setShow] = useState(false)
|
||||
useEffect(() => {
|
||||
if (status != undefined) {
|
||||
setShow(true)
|
||||
}
|
||||
}, [status])
|
||||
useEffect(() => {
|
||||
const resetShow = () => { setShow(false) }
|
||||
if (show) setTimeout(resetShow, 1500)
|
||||
return(() => {
|
||||
clearTimeout(resetShow)
|
||||
})
|
||||
}, [show])
|
||||
return (
|
||||
<>
|
||||
{show &&
|
||||
<div className='message'>
|
||||
{
|
||||
<div>{status == true ? <i className="fas fa-check-circle statusIcon" id="successIcon" color="#abe491" /> : <i className="fas fa-times-circle statusIcon" id="failureIcon" color="#e49191" />}</div>
|
||||
}
|
||||
<div className="messageBox">
|
||||
{
|
||||
<div>{
|
||||
status == true ?
|
||||
<div>
|
||||
<div>{successMessage}</div>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
<div>{failureMessage}</div>
|
||||
</div>
|
||||
}</div>
|
||||
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
.successLineOne {
|
||||
color: #abe491;
|
||||
}
|
||||
.successLineTwo {
|
||||
color: #b9b9b9;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.failureLineOne {
|
||||
color: #e49191;
|
||||
}
|
||||
.failureLineTwo {
|
||||
color: #b9b9b9;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.message {
|
||||
font-weight: bolder;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
#successIcon {
|
||||
color: #abe491;
|
||||
}
|
||||
#failureIcon {
|
||||
color: #e49191;
|
||||
}
|
||||
.statusIcon {
|
||||
margin-right: 0.6rem;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { NavBarItem } from './navBarItem'
|
||||
import { isBrowser } from 'react-device-detect'
|
||||
import { useStylesPC } from './stylePC'
|
||||
import { useStylesMobile } from './styleMobile'
|
||||
|
||||
const navBarConfig = [
|
||||
{
|
||||
tabID: 'home', to: '/', specificTabName: "home", children:
|
||||
<>
|
||||
<i className="fas fa-home" />
|
||||
</>
|
||||
},
|
||||
{
|
||||
tabID: 'motionGenerator', to: '/generator', children:
|
||||
<>
|
||||
<div>Motion </div>
|
||||
<div>Generator</div>
|
||||
</>
|
||||
},
|
||||
{
|
||||
tabID: 'database', to: '/database', children:
|
||||
<>
|
||||
<div>Motion </div>
|
||||
<div>Database</div>
|
||||
</>
|
||||
},
|
||||
{
|
||||
tabID: 'breakCalc', to: '/break_calculator', children:
|
||||
<>
|
||||
<div>Break</div>
|
||||
<div>Calculator</div>
|
||||
</>
|
||||
},
|
||||
{
|
||||
tabID: 'keeper', to: '/keeper/bp', children:
|
||||
<>
|
||||
<div>Timekeeper</div>
|
||||
</>
|
||||
}
|
||||
]
|
||||
export const NavBar = () => {
|
||||
const [activeTab, setActiveTab] = useState(`/`)
|
||||
useEffect(() => {
|
||||
setActiveTab(window.location.pathname)
|
||||
}, [window.location.pathname])
|
||||
const classesPC = useStylesPC()
|
||||
const classesMobile = useStylesMobile()
|
||||
return (
|
||||
<div className={isBrowser ? classesPC.navBar : classesMobile.navBar}>
|
||||
{navBarConfig.map(config => {
|
||||
return (
|
||||
<NavBarItem specificTabName={config.specificTabName} isActive={activeTab === config.to} to={config.to} tabID={config.tabID} setActiveTab={setActiveTab}>{config.children}</NavBarItem>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export const NavBarItem = (props) => {
|
||||
const { to, tabID, setActiveTab, children, isActive, specificTabName } = props // setActiveTab(to)
|
||||
return (
|
||||
<Link to={to} className={`anchor ${specificTabName} ${isActive ? 'active' : ''}`} id={tabID} onClick={() => { setActiveTab(to) }}>
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { makeStyles } from '@mui/styles'
|
||||
|
||||
export const useStylesMobile = makeStyles({
|
||||
'navBar': {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#282a35',
|
||||
fontFamily: '"Source Sans Pro", sans-serif',
|
||||
height: '7vh',
|
||||
width: '100%',
|
||||
'& .anchor': {
|
||||
color: 'white',
|
||||
textDecoration: 'none',
|
||||
display: 'flex',
|
||||
fontWeight: 'bolder',
|
||||
fontSize: '0.8rem',
|
||||
height: '100%',
|
||||
width: '24vw',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'&:hover': {
|
||||
backgroundColor: '#000000'
|
||||
}
|
||||
},
|
||||
'& .home': {
|
||||
width: '4vw !important',
|
||||
'& i': {
|
||||
fontSize: '1.2rem'
|
||||
}
|
||||
},
|
||||
'& .active': {
|
||||
backgroundColor: '#000000'
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 379px)': {
|
||||
'navBar': {
|
||||
'& .anchor': {
|
||||
fontSize: '0.7rem',
|
||||
width: '22vw',
|
||||
},
|
||||
'& .home': {
|
||||
width: '12vw !important',
|
||||
'& i': {
|
||||
fontSize: '1rem !important'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 425px) and (min-width: 380px)': {
|
||||
'navBar': {
|
||||
'& .anchor': {
|
||||
fontSize: '0.8rem',
|
||||
width: '22vw'
|
||||
},
|
||||
'& .home': {
|
||||
width: '12vw !important',
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 768px) and (min-width: 426px)': {
|
||||
'navBar': {
|
||||
'& .anchor': {
|
||||
fontSize: '1.1rem',
|
||||
width: '22.5vw',
|
||||
},
|
||||
'& .home': {
|
||||
width: '10vw !important',
|
||||
'& i': {
|
||||
fontSize: '2rem !important'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,81 @@
|
||||
import { makeStyles } from '@mui/styles'
|
||||
|
||||
export const useStylesPC = makeStyles({
|
||||
'navBar': {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#282a35',
|
||||
fontFamily: '"Source Sans Pro", sans-serif',
|
||||
height: '7vh',
|
||||
minHeight: '2.63rem', /**/
|
||||
width: '100%',
|
||||
minWidth: '48.125rem', /**/
|
||||
'& .anchor': {
|
||||
color: 'white',
|
||||
textDecoration: 'none',
|
||||
display: 'flex',
|
||||
fontWeight: 'bolder',
|
||||
fontSize: '0.8rem !important',
|
||||
height: '100%',
|
||||
width: '24vw',
|
||||
minWidth: '13.5rem', /**/
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
'&:hover': {
|
||||
backgroundColor: '#000000'
|
||||
}
|
||||
},
|
||||
'& .home': {
|
||||
width: '4vw !important',
|
||||
minWidth: '3.375rem !important', /**/
|
||||
'& i': {
|
||||
fontSize: '1.2rem !important'
|
||||
}
|
||||
},
|
||||
'& .active': {
|
||||
backgroundColor: '#000000'
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 379px)': {
|
||||
'navBar': {
|
||||
'& .anchor': {
|
||||
fontSize: '0.7rem',
|
||||
width: '22vw',
|
||||
},
|
||||
'& .home': {
|
||||
width: '12vw !important',
|
||||
'& i': {
|
||||
fontSize: '1rem !important'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 425px) and (min-width: 380px)': {
|
||||
'navBar': {
|
||||
'& .anchor': {
|
||||
fontSize: '0.8rem',
|
||||
width: '22vw'
|
||||
},
|
||||
'& .home': {
|
||||
width: '12vw !important'
|
||||
}
|
||||
}
|
||||
},
|
||||
'@media only screen and (max-width: 768px) and (min-width: 426px)': {
|
||||
'navBar': {
|
||||
'& .anchor': {
|
||||
fontSize: '1.1rem',
|
||||
width: '22.5vw',
|
||||
},
|
||||
'& .home': {
|
||||
width: '10vw !important',
|
||||
'& i': {
|
||||
fontSize: '2rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
import { components } from 'react-select'
|
||||
export const ClearIndicator = ({ children, ...props }) => {
|
||||
return (
|
||||
<components.ClearIndicator {...props}>
|
||||
{children}
|
||||
</components.ClearIndicator>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { components } from 'react-select'
|
||||
export const DropdownIndicator = ({ children, ...props }) => {
|
||||
return (
|
||||
<components.DropdownIndicator {...props}>
|
||||
{children}
|
||||
</components.DropdownIndicator>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import { components } from 'react-select'
|
||||
export const Input = props => {
|
||||
return (
|
||||
<components.Input {...props} />
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import { components } from 'react-select'
|
||||
export const MultiValueContainer = props => {
|
||||
return (
|
||||
<components.MultiValueContainer {...props} />
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import { components } from 'react-select'
|
||||
export const Option = props => {
|
||||
return (
|
||||
<components.Option {...props} />
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import { components } from 'react-select'
|
||||
export const Placeholder = props => {
|
||||
return <components.Placeholder {...props} />;
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { components } from 'react-select'
|
||||
export const SelectContainer = ({ children, ...props }) => {
|
||||
return (
|
||||
<components.SelectContainer {...props}>
|
||||
{children}
|
||||
</components.SelectContainer>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import { components } from 'react-select'
|
||||
export const SingleValue = ({ children, ...props }) => (
|
||||
<components.SingleValue {...props}>{children}</components.SingleValue>
|
||||
);
|
||||
@@ -0,0 +1,4 @@
|
||||
import { components } from 'react-select'
|
||||
export const ValueContainer = ({ children, ...props }) => (
|
||||
<components.ValueContainer {...props}>{children}</components.ValueContainer>
|
||||
);
|
||||
@@ -0,0 +1,9 @@
|
||||
export * from './ClearIndicator'
|
||||
export * from './DropdownIndicator'
|
||||
export * from './MultiValueContainer'
|
||||
export * from './SelectContainer'
|
||||
export * from './ValueContainer'
|
||||
export * from './Placeholder'
|
||||
export * from './Option'
|
||||
export * from './SingleValue'
|
||||
export * from './Input'
|
||||
@@ -0,0 +1,47 @@
|
||||
export const Table = (props) => {
|
||||
const { dataSource, columns, showActions, names, ref } = props
|
||||
return (
|
||||
<>
|
||||
{
|
||||
dataSource.length != 0 ?
|
||||
<table className={names.tableName} ref={ref}>
|
||||
<tr className={names.headerName}>
|
||||
{
|
||||
columns.map(columnItem => {
|
||||
if (columnItem.type != "action") {
|
||||
return (
|
||||
<th className={names.headerCellName} style={{
|
||||
width: columnItem.width
|
||||
}}>{columnItem.name}</th>
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
{
|
||||
showActions && <th width={columns[columns.length - 1].width} className={names.emptyHeaderCellName}></th>
|
||||
}
|
||||
</tr>
|
||||
{
|
||||
dataSource.map(item => {
|
||||
return (
|
||||
<tr className={names.rowName}>
|
||||
{
|
||||
columns.map(columnItem => {
|
||||
return (
|
||||
<td style={{
|
||||
width: columnItem.width
|
||||
}} className={`${names.rowCellName} ${columnItem.type == "action" ? `${names.actionCellName}` : ""}`}>{columnItem.render(item)}</td>
|
||||
)
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
</table>
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export * from './NavBar'
|
||||
export * from './EditableSelector'
|
||||
export * from './EditableText'
|
||||
export * from './EditableTextArea'
|
||||
export * from './InformationContainer'
|
||||
export * from './Message'
|
||||
export * from './Table'
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,237 @@
|
||||
[
|
||||
{
|
||||
"name": "BY Online Debate Open",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Uhuru Worlds",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Cambridge Asia BP",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Asian English Olympics",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Beihang International Winter Online BP Open",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Philippines Queer Open",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "UMT Parliamentary Debate Open",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Trouvaille Debate Open",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "DAV IR Cup",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "HWS Round Robin",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Korea WUDC",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "DTU Parliamentary Debate",
|
||||
"format": "AP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Vietnam University Debating Championship (VUDC)",
|
||||
"format": "AP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "NEU Debate Open",
|
||||
"format": "AP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Cogic Debate Online (CODO)",
|
||||
"format": "AP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "The Anime Open",
|
||||
"format": "AP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Netflix International Debate",
|
||||
"format": "AP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Da Nang Debate Open",
|
||||
"format": "AP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Asian Online Debating Championship (AODC) - WSDC",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Oldham Cup International League",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Nanjing Debate Open",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "The Tabate",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "FLSS Debate Tournament",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Hanoi Debate Tournament (HDT)",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Lychee Debate Open",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Canopus Debate Championship",
|
||||
"format": "WSDC",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Gấu Debate Tournament",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Vietname BP Championship (BP)",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Gấu Online Debating Championship",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Beihang International Online Debating Championship",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Japan BP",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Melbourne Mini",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "PKU Pro-Am",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Asian Online Debating Championship (AODC) - WSDC",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Taiwan Online Debate Open",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Northern Coast Debate Open",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Hòa Vang Debate Online",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Teen X Debate Online",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Gấu Online Debate Open",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Hong Kong Debate Open",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "UPenn World Schools Online Debating Tournament",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "The Debaters VTV7",
|
||||
"format": "",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "WSDC",
|
||||
"format": "WSDC",
|
||||
"year": "2019"
|
||||
},
|
||||
{
|
||||
"name": "Vietnam Schools Debating Championship (VSDC)",
|
||||
"format": "WSDC",
|
||||
"year": "2019"
|
||||
},
|
||||
{
|
||||
"name": "Ka Paio Debate Open",
|
||||
"format": "WSDC",
|
||||
"year": "2019"
|
||||
},
|
||||
{
|
||||
"name": "Ka Paio Online Debate Open",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "WSDC",
|
||||
"format": "WSDC",
|
||||
"year": "2018"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,97 @@
|
||||
[
|
||||
{
|
||||
"name": "Hong Kong Parliamentary Debating Society (HKPDS)",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Asian Online Debating Championship (AODC) - BP",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "6th Shanghai International Debate Open (SIDO)",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Trường Teen",
|
||||
"format": "",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Cogic Debate Online (CODO)",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Spring KNC",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "CNH Debate Open (CDO)",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Hanoi Debate Tournament (HDT)",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Southern Debate Open (SDO)",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Hong Kong Schools Debate Open (HKSDO)",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "DAV Debate Open (DDO)",
|
||||
"format": "AP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Vietnam Debate Online (VNDO)",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Vietnam Debate Online (VNDO) - BP",
|
||||
"format": "BP",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Nghe Tinh Debate Open (NTDO)",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "Vietnam BP Championship (VBC)",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Pre VBC",
|
||||
"format": "BP",
|
||||
"year": "2021"
|
||||
},
|
||||
{
|
||||
"name": "Online WSDC",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "6th Oldham Cup",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
},
|
||||
{
|
||||
"name": "MOE Invitational Debating Championship (MIDC)",
|
||||
"format": "WSDC",
|
||||
"year": "2020"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
export function customTheme(theme) {
|
||||
return {
|
||||
...theme,
|
||||
colors: {
|
||||
...theme.colors,
|
||||
primary25: 'grey',
|
||||
primary: 'black',
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
export const formats = [
|
||||
{ value: 'BP', label: 'BP' },
|
||||
{ value: 'AP', label: 'AP' },
|
||||
{ value: 'WSDC', label: 'WSDC' },
|
||||
{ value: 'Others', label: 'Others' }
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
export * as englishIDs from './englishIDs.json'
|
||||
export * as vietnameseIDs from './vietnameseIDs.json'
|
||||
export * from './topics'
|
||||
export * from './topicsForMotions'
|
||||
export * from './formats'
|
||||
export * from './languages'
|
||||
export * from './customTheme'
|
||||
export * from './tourneys.json'
|
||||
export * from './PAtourneys.json'
|
||||
export * from './MOJItourneys.json'
|
||||
export * as tournamentsFromDatabase from './tournamentsFromDatabase.json'
|
||||
export * as tournamentOptions from './tournamentOptions.json'
|
||||
export * from './tournamentData.json'
|
||||
export * from './motions.json'
|
||||
export * from './motionDataRaw.json'
|
||||
export * as motionsFromDatabase from './motionsFromDatabase.json'
|
||||
export * from './PAmotions.json'
|
||||
export * from './MOJImotions.json'
|
||||
export * from './tableClassNames'
|
||||
@@ -0,0 +1,4 @@
|
||||
export const languages = [
|
||||
{ value: 'English', label: 'English' },
|
||||
{ value: 'Vietnamese', label: 'Vietnamese' }
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,40 @@
|
||||
export const tableClassNames = {
|
||||
adminLoadTournaments: {
|
||||
"tableName": "loadedTournamentsTable",
|
||||
"headerName": "tournamentsTableHeaderRow",
|
||||
"headerCellName": "tournamentsTableHeader",
|
||||
"emptyHeaderCellName": "emptyTournamentsTableHeaderCell",
|
||||
"rowName": "tournamentTableRow",
|
||||
"rowCellName": "tournamentTableCell",
|
||||
"actionCellName": "deleteTournamentCell"
|
||||
},
|
||||
adminLoadMotions: {
|
||||
"tableName": "loadedMotionsTable",
|
||||
"headerName": "motionsTableHeaderRow",
|
||||
"headerCellName": "motionsTableHeader",
|
||||
"emptyHeaderCellName": "emptyMotionsTableHeaderCell",
|
||||
"rowName": "motionTableRow",
|
||||
"rowCellName": "motionTableCell",
|
||||
"actionCellName": "deleteMotionCell"
|
||||
},
|
||||
adminPendingRequests: {
|
||||
"tableName": "loadedRequestsTable",
|
||||
"headerName": "requestsTableHeaderRow",
|
||||
"headerCellName": "requestsTableHeader",
|
||||
"emptyHeaderCellName": "emptyRequestsTableHeaderCell",
|
||||
"rowName": "requestTableRow",
|
||||
"rowCellName": "requestTableCell",
|
||||
"actionCellName": "actionRequestCell"
|
||||
|
||||
},
|
||||
userLoadMotions: {
|
||||
"tableName": "tableDatabase",
|
||||
"headerName": "databaseHeaderRow",
|
||||
"headerCellName": "databaseTableHeader",
|
||||
"emptyHeaderCellName": "",
|
||||
"rowName": "databaseTableRow",
|
||||
"rowCellName": "databaseTableCell",
|
||||
"actionCellName": ""
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
export const topics = [
|
||||
{ value: 'aac', label: 'Art & Culture' },
|
||||
{ value: 'ar', label: "Animals' rights" },
|
||||
{ value: 'business', label: 'Business' },
|
||||
{ value: 'cjs', label: 'Criminal Justice System' },
|
||||
{ value: 'development', label: 'Development' },
|
||||
{ value: 'economics', label: 'Economics' },
|
||||
{ value: 'education', label: 'Education' },
|
||||
{ value: 'entertainment', label: 'Entertainment'},
|
||||
{ value: 'environment', label: 'Environment' },
|
||||
{ value: 'family', label: 'Family' },
|
||||
{ value: 'feminism', label: 'Feminism' },
|
||||
{ value: 'freedoms', label: 'Freedoms' },
|
||||
{ value: 'fiction', label: 'Fiction' },
|
||||
{ value: 'funny', label: 'Funny' },
|
||||
{ value: 'history', label: 'History' },
|
||||
{ value: 'hr', label: 'Human Relationships' },
|
||||
{ value: 'ir', label: 'International Relations' },
|
||||
{ value: 'law', label: 'Law'},
|
||||
{ value: 'lgbtqia+', label: 'LGBTQIA+' },
|
||||
{ value: 'media', label: 'Media' },
|
||||
{ value: 'me', label: 'Medical Ethics' },
|
||||
{ value: 'mc', label: 'Minority Communities' },
|
||||
{ value: 'morality', label: 'Morality' },
|
||||
{ value: 'philosophy', label: 'Philosophy' },
|
||||
{ value: 'politics', label: 'Politics' },
|
||||
{ value: 'religion', label: 'Religion' },
|
||||
{ value: 'sat', label: 'Science & Technology' },
|
||||
{ value: 'swm', label: 'Security, War and Military' },
|
||||
{ value: 'sp', label: 'Social Policy' },
|
||||
{ value: 'sm', label: 'Social Movements' },
|
||||
{ value: 'sports', label: 'Sports' },
|
||||
{ value: 'terrorism', label: 'Terrorism' },
|
||||
{ value: 'the', label: 'The Human Experience' },
|
||||
{ value: 'others', label: 'Others' },
|
||||
]
|
||||
// module.exports = topics
|
||||
@@ -0,0 +1,308 @@
|
||||
export const topicsForMotions = [
|
||||
{
|
||||
"value": {
|
||||
"aac": {
|
||||
"check": true,
|
||||
"title": "Art & Culture"
|
||||
}
|
||||
},
|
||||
"label": "Art & Culture"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"ar": {
|
||||
"check": true,
|
||||
"title": "Animals' rights"
|
||||
}
|
||||
},
|
||||
"label": "Animals' rights"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"business": {
|
||||
"check": true,
|
||||
"title": "Business"
|
||||
}
|
||||
},
|
||||
"label": "Business"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"cjs": {
|
||||
"check": true,
|
||||
"title": "Criminal Justice System"
|
||||
}
|
||||
},
|
||||
"label": "Criminal Justice System"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"development": {
|
||||
"check": true,
|
||||
"title": "Development"
|
||||
}
|
||||
},
|
||||
"label": "Development"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"economics": {
|
||||
"check": true,
|
||||
"title": "Economics"
|
||||
}
|
||||
},
|
||||
"label": "Economics"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"education": {
|
||||
"check": true,
|
||||
"title": "Education"
|
||||
}
|
||||
},
|
||||
"label": "Education"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"entertainment": {
|
||||
"check": true,
|
||||
"title": "Entertainment"
|
||||
}
|
||||
},
|
||||
"label": "Entertainment"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"environment": {
|
||||
"check": true,
|
||||
"title": "Environment"
|
||||
}
|
||||
},
|
||||
"label": "Environment"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"family": {
|
||||
"check": true,
|
||||
"title": "Family"
|
||||
}
|
||||
},
|
||||
"label": "Family"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"feminism": {
|
||||
"check": true,
|
||||
"title": "Feminism"
|
||||
}
|
||||
},
|
||||
"label": "Feminism"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"freedoms": {
|
||||
"check": true,
|
||||
"title": "Freedoms"
|
||||
}
|
||||
},
|
||||
"label": "Freedoms"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"fiction": {
|
||||
"check": true,
|
||||
"title": "Fiction"
|
||||
}
|
||||
},
|
||||
"label": "Fiction"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"funny": {
|
||||
"check": true,
|
||||
"title": "Funny"
|
||||
}
|
||||
},
|
||||
"label": "Funny"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"history": {
|
||||
"check": true,
|
||||
"title": "History"
|
||||
}
|
||||
},
|
||||
"label": "History"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"hr": {
|
||||
"check": true,
|
||||
"title": "Human Relationships"
|
||||
}
|
||||
},
|
||||
"label": "Human Relationships"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"ir": {
|
||||
"check": true,
|
||||
"title": "International Relations"
|
||||
}
|
||||
},
|
||||
"label": "International Relations"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"law": {
|
||||
"check": true,
|
||||
"title": "Law"
|
||||
}
|
||||
},
|
||||
"label": "Law"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"lgbtqia+": {
|
||||
"check": true,
|
||||
"title": "LGBTQIA+"
|
||||
}
|
||||
},
|
||||
"label": "LGBTQIA+"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"media": {
|
||||
"check": true,
|
||||
"title": "Media"
|
||||
}
|
||||
},
|
||||
"label": "Media"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"me": {
|
||||
"check": true,
|
||||
"title": "Medical Ethics"
|
||||
}
|
||||
},
|
||||
"label": "Medical Ethics"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"mc": {
|
||||
"check": true,
|
||||
"title": "Minority Communities"
|
||||
}
|
||||
},
|
||||
"label": "Minority Communities"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"morality": {
|
||||
"check": true,
|
||||
"title": "Morality"
|
||||
}
|
||||
},
|
||||
"label": "Morality"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"philosophy": {
|
||||
"check": true,
|
||||
"title": "Philosophy"
|
||||
}
|
||||
},
|
||||
"label": "Philosophy"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"politics": {
|
||||
"check": true,
|
||||
"title": "Politics"
|
||||
}
|
||||
},
|
||||
"label": "Politics"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"religion": {
|
||||
"check": true,
|
||||
"title": "Religion"
|
||||
}
|
||||
},
|
||||
"label": "Religion"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"sat": {
|
||||
"check": true,
|
||||
"title": "Science & Technology"
|
||||
}
|
||||
},
|
||||
"label": "Science & Technology"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"swm": {
|
||||
"check": true,
|
||||
"title": "Security, War and Military"
|
||||
}
|
||||
},
|
||||
"label": "Security, War and Military"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"sp": {
|
||||
"check": true,
|
||||
"title": "Social Policy"
|
||||
}
|
||||
},
|
||||
"label": "Social Policy"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"sm": {
|
||||
"check": true,
|
||||
"title": "Social Movements"
|
||||
}
|
||||
},
|
||||
"label": "Social Movements"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"sports": {
|
||||
"check": true,
|
||||
"title": "Sports"
|
||||
}
|
||||
},
|
||||
"label": "Sports"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"terrorism": {
|
||||
"check": true,
|
||||
"title": "Terrorism"
|
||||
}
|
||||
},
|
||||
"label": "Terrorism"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"the": {
|
||||
"check": true,
|
||||
"title": "The Human Experience"
|
||||
}
|
||||
},
|
||||
"label": "The Human Experience"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"others": {
|
||||
"check": true,
|
||||
"title": "Others"
|
||||
}
|
||||
},
|
||||
"label": "Others"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,87 @@
|
||||
[
|
||||
{
|
||||
"name": "HKPDS",
|
||||
"year": "2020",
|
||||
"format": "BP"
|
||||
},
|
||||
{
|
||||
"name": "AODC",
|
||||
"year": "2020",
|
||||
"format": "BP"
|
||||
},
|
||||
{
|
||||
"name": "6th SIDO",
|
||||
"year": "2020",
|
||||
"format": "BP"
|
||||
},
|
||||
{
|
||||
"name": "Trường Teen",
|
||||
"year": "2020",
|
||||
"format": ""
|
||||
},
|
||||
{
|
||||
"name": "CDO (CNH Debat Open)",
|
||||
"year": "2020",
|
||||
"format": "WSDC"
|
||||
},
|
||||
{
|
||||
"name": "Spring KNC",
|
||||
"year": "2020",
|
||||
"format": "AP"
|
||||
},
|
||||
{
|
||||
"name": "CODO (Cogic Debate Online)",
|
||||
"year": "2020",
|
||||
"format": "AP"
|
||||
},
|
||||
{
|
||||
"name": "HDT",
|
||||
"year": "2020",
|
||||
"format": "WSDC"
|
||||
},
|
||||
{
|
||||
"name": "SDO",
|
||||
"year": "2020",
|
||||
"format": "BP"
|
||||
},
|
||||
{
|
||||
"name": "HKSDO",
|
||||
"year": "2020",
|
||||
"format": "WSDC"
|
||||
},
|
||||
{
|
||||
"name": "DDO",
|
||||
"year": "2020",
|
||||
"format": "AP"
|
||||
},
|
||||
{
|
||||
"name": "VNDO",
|
||||
"year": "2020",
|
||||
"format": "BP"
|
||||
},
|
||||
{
|
||||
"name": "NTDO (Nghe Tinh Debate Open)",
|
||||
"year": "2020",
|
||||
"format": "WSDC"
|
||||
},
|
||||
{
|
||||
"name": "VBC",
|
||||
"year": "2020",
|
||||
"format": "BP"
|
||||
},
|
||||
{
|
||||
"name": "Pre VBC",
|
||||
"year": "2021",
|
||||
"format": "BP"
|
||||
},
|
||||
{
|
||||
"name": "Online WSDC",
|
||||
"year": "2020",
|
||||
"format": "WSDC"
|
||||
},
|
||||
{
|
||||
"name": "6th Oldham Cup",
|
||||
"year": "2020",
|
||||
"format": "WSDC"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,74 @@
|
||||
export function calculateBreaks({format, teamNumber, roundNumber, breakNumber}){
|
||||
var teamarr1 = [];
|
||||
var teamarr2 = [];
|
||||
|
||||
//All teams at zero points in the beginning.
|
||||
for (var i=0; i<teamNumber; i++) {
|
||||
teamarr1.push(0);
|
||||
teamarr2.push(0);
|
||||
}
|
||||
|
||||
switch(format) {
|
||||
case 'ap':
|
||||
for (var j = 0; j < roundNumber; j++) {
|
||||
for (var i = 0; i < teamNumber; i++) {
|
||||
if (i % 2 === 0) { //Case 1 : Where all pull ups win
|
||||
teamarr1[i]+=1;
|
||||
} else { //Case 2 : Where all pull ups lose
|
||||
teamarr2[i]+=1;
|
||||
}
|
||||
}
|
||||
teamarr1.sort();
|
||||
teamarr2.sort();
|
||||
}
|
||||
break;
|
||||
case 'bp':
|
||||
for (var j = 0; j < roundNumber; j++) {
|
||||
for (var i = 0; i < teamNumber; i++) {
|
||||
//Case 1 : Where all pull ups win
|
||||
if(i%4 === 0){
|
||||
teamarr1[i]+=3;
|
||||
teamarr1[i+1]+=2;
|
||||
teamarr1[i+2]+=1;
|
||||
}
|
||||
//Case 2 : Where all pull ups lose
|
||||
if(i%4 === 0){
|
||||
teamarr2[i+1]+=1;
|
||||
teamarr2[i+2]+=2;
|
||||
teamarr2[i+3]+=3;
|
||||
}
|
||||
}
|
||||
teamarr1.sort();
|
||||
teamarr2.sort();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return({
|
||||
pullUpLose: output(teamarr1, breakNumber, teamNumber),
|
||||
pullUpWin: output(teamarr2, breakNumber, teamNumber)
|
||||
})
|
||||
}
|
||||
export function output(teamarr, num_break, num_teams){
|
||||
var breakTeams = teamarr.slice(-num_break);
|
||||
var breakMin = breakTeams[0];
|
||||
var breakMax = breakTeams[num_break-1];
|
||||
var breakCount = {};
|
||||
var totalCount = {};
|
||||
for(var i = breakMin;i <= breakMax;i++) {
|
||||
breakCount[i] = 0;
|
||||
totalCount[i] = 0;
|
||||
}
|
||||
for (var i = 0;i<breakTeams.length;i++) {
|
||||
breakCount[breakTeams[i]]++;
|
||||
}
|
||||
for (var i = 0;i<num_teams;i++){
|
||||
if (teamarr[i]>=breakMin){
|
||||
totalCount[teamarr[i]]++;;
|
||||
}
|
||||
}
|
||||
return({
|
||||
breakCount, totalCount
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
const motionsFromDatabase = require('./data/motionsFromDatabase.json')
|
||||
let eng = 0, vn = 0;
|
||||
motionsFromDatabase.forEach(motion => {
|
||||
if (motion.language == "English") {
|
||||
eng++;
|
||||
}
|
||||
else {
|
||||
vn++;
|
||||
}
|
||||
})
|
||||
console.log(`Number of English motions: ${eng}`)
|
||||
console.log(`Number of Vietnamese motions: ${vn}`)
|
||||
@@ -0,0 +1,46 @@
|
||||
const fs = require('fs');
|
||||
const tournaments = require('../constants/tournamentsFromDatabase.json');
|
||||
const optionsUnsorted = []
|
||||
const labels = []
|
||||
tournaments.forEach(tournament => {
|
||||
const name = tournament.name
|
||||
const year = tournament.year
|
||||
const id = tournament.id
|
||||
let label
|
||||
if (year == "") {
|
||||
label = name
|
||||
}
|
||||
else {
|
||||
label = `${name} ${year}`
|
||||
}
|
||||
labels.push(label)
|
||||
optionsUnsorted.push({
|
||||
value: id,
|
||||
label: label
|
||||
})
|
||||
})
|
||||
labels.sort()
|
||||
let optionsSorted = []
|
||||
labels.forEach(label => {
|
||||
let id = undefined
|
||||
optionsUnsorted.forEach(option => {
|
||||
if (option.label == label) {
|
||||
id = option.value
|
||||
}
|
||||
})
|
||||
optionsSorted.push({
|
||||
value: id,
|
||||
label: label
|
||||
})
|
||||
})
|
||||
optionsSorted = optionsSorted.filter((obj, index, self) =>
|
||||
index === self.findIndex((el) => el.value === obj.value)
|
||||
);
|
||||
const optionsJSON = JSON.stringify(optionsSorted)
|
||||
fs.writeFile(`../constants/tournamentOptions.json`, optionsJSON, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.log("An error occured while writing JSON Object to File.");
|
||||
return console.log(err);
|
||||
}
|
||||
console.log("JSON file has been saved.");
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
export const endWithDot = (str) => {
|
||||
if (str.slice(-1) == ".") {
|
||||
return (str)
|
||||
}
|
||||
else {
|
||||
return (str + ".")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// const fetch = require("node-fetch");
|
||||
const fs = require('fs');
|
||||
const run = async () => {
|
||||
let numCount = 1;
|
||||
let firstPart = 'https://spreadsheets.google.com/feeds/cells/10_KEaM4jA5tnMPp4OD9eXnR7n_zx3rOtPnw6YW2ww5M/'
|
||||
let secondPart = '/public/full?alt=json'
|
||||
for (let i = 1; i<=13; i++) {
|
||||
const fullURL = `${firstPart}${i}${secondPart}`
|
||||
const jsonResponse = await fetch(`${fullURL}`);
|
||||
const jsonData = await jsonResponse.json();
|
||||
const jsonString = JSON.stringify(jsonData);
|
||||
fs.writeFile(`data/${i}.json`, jsonString, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.log("An error occured while writing JSON Object to File.");
|
||||
return console.log(err);
|
||||
}
|
||||
console.log("JSON file has been saved.");
|
||||
});
|
||||
}
|
||||
}
|
||||
run();
|
||||
@@ -0,0 +1,15 @@
|
||||
import { topics } from '../constants/topics'
|
||||
export const getFormattedTopicsFromValues = (topicValues) => {
|
||||
let topicArray = {}
|
||||
topicValues.forEach(topicValue => {
|
||||
topics.forEach(topicItem => {
|
||||
if (topicItem.value == topicValue) {
|
||||
topicArray[`${topicValue}`] = {
|
||||
check: true,
|
||||
title: topicItem.label
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
return topicArray
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
const fs = require('fs');
|
||||
const motions = require("./data/motionsFromDatabase.json")
|
||||
const vietnameseIDs = [], englishIDs = [];
|
||||
motions.forEach(motion => {
|
||||
if (motion.language == "English") {
|
||||
englishIDs.push(motion.id);
|
||||
}
|
||||
else if (motion.language == "Vietnamese") {
|
||||
vietnameseIDs.push (motion.id);
|
||||
}
|
||||
})
|
||||
let englishIDsJSON = JSON.stringify(englishIDs);
|
||||
let vietnameseIDsJSON = JSON.stringify(vietnameseIDs);
|
||||
fs.writeFile(`data/vietnameseIDs.json`, vietnameseIDsJSON, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.log("An error occured while writing JSON Object to File.");
|
||||
return console.log(err);
|
||||
}
|
||||
console.log("JSON file has been saved.");
|
||||
});
|
||||
fs.writeFile(`data/englishIDs.json`, englishIDsJSON, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.log("An error occured while writing JSON Object to File.");
|
||||
return console.log(err);
|
||||
}
|
||||
console.log("JSON file has been saved.");
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { firebaseFirestore } from "../../firebase"
|
||||
export const getTourneyID = async (name, year, format) => {
|
||||
let tournamentsRef = firebaseFirestore.collection('tournaments').where('name', '==', name)
|
||||
if (year != '') {
|
||||
tournamentsRef = tournamentsRef.where('year', '==', year)
|
||||
}
|
||||
if (format != '') {
|
||||
tournamentsRef = tournamentsRef.where('format', '==', format)
|
||||
}
|
||||
const tournamentData = await tournamentsRef.get()
|
||||
if (tournamentData.docs.length == 0) {
|
||||
await firebaseFirestore.collection("tournaments").add({ name: name, year: year, format: format })
|
||||
const newTournamentData = await tournamentsRef.get()
|
||||
return newTournamentData.docs[0].id
|
||||
}
|
||||
else {
|
||||
return tournamentData.docs[0].id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { firebaseFirestore } from "../../firebase"
|
||||
export const getTourneyInfo = async (id) => {
|
||||
const tournamentsRef = firebaseFirestore.collection('tournaments').doc(id)
|
||||
const tournamentData = await tournamentsRef.get();
|
||||
if (tournamentData.exists == false) {
|
||||
return {}
|
||||
}
|
||||
else {
|
||||
const name = tournamentData.data().name
|
||||
const year = tournamentData.data().year
|
||||
const format = tournamentData.data().format
|
||||
return {
|
||||
name,
|
||||
year,
|
||||
format
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export * from './breakCalculator'
|
||||
export * from './endWithDot'
|
||||
export * from './getFormattedTopicsFromValues'
|
||||
export * from './getTourneyID'
|
||||
export * from './getTourneyInfo'
|
||||
export * from './isObject'
|
||||
@@ -0,0 +1,3 @@
|
||||
export function isObject(value) {
|
||||
return value && typeof value === 'object' && value.constructor === Object;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
const fs = require('fs');
|
||||
const motionDataRaw = require('./data/motionDataRaw.json');
|
||||
const endWithDot = (str) => {
|
||||
if (str.slice(-1) == ".") {
|
||||
return (str)
|
||||
}
|
||||
else {
|
||||
return (str + ".")
|
||||
}
|
||||
}
|
||||
let motions = [];
|
||||
motionDataRaw.forEach(async (motion) => {
|
||||
let date = new Date(motion.Date);
|
||||
let year = date.getFullYear().toString();
|
||||
if (year == "NaN") {
|
||||
year = ""
|
||||
}
|
||||
let tournament = motion.Tournament;
|
||||
let lastFour = tournament.slice(-4)
|
||||
if (!isNaN(lastFour)) {
|
||||
year = tournament.slice(-4)
|
||||
tournament = tournament.slice(0, -5)
|
||||
}
|
||||
let id = ""
|
||||
let content = endWithDot(motion.Motion)
|
||||
let infoSlide = ''
|
||||
if (motion.InfoSlide != undefined) {
|
||||
infoSlide = endWithDot(motion.InfoSlide)
|
||||
}
|
||||
const curMot = { tournament: tournament, year: year, format: "", content: content, infoSlide: infoSlide, division: '', language: 'English', link: '', round: motion.Round, topic: {}, tournamentID: id }
|
||||
motions.push(curMot)
|
||||
})
|
||||
let motionJSON = JSON.stringify(motions)
|
||||
fs.writeFile(`data/motions.json`, motionJSON, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.log("An error occured while writing JSON Object to File.");
|
||||
return console.log(err);
|
||||
}
|
||||
console.log("JSON file has been saved.");
|
||||
});
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
const topics = require('./data/topics')
|
||||
const fs = require('fs');
|
||||
const topicsForMotions = []
|
||||
topics.forEach(topic => {
|
||||
const topicForMotion = {
|
||||
value: {
|
||||
[`${topic.value}`]: {
|
||||
"check": true,
|
||||
"title": `${topic.label}`
|
||||
}
|
||||
},
|
||||
label: `${topic.label}`
|
||||
}
|
||||
topicsForMotions.push(topicForMotion)
|
||||
})
|
||||
console.log(topicsForMotions)
|
||||
let topicsForMotionsJSON = JSON.stringify(topicsForMotions, null, 4)
|
||||
fs.writeFile(`data/topicsForMotions.js`,`export const topicsForMotions = ${topicsForMotionsJSON}`, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.log("An error occured while writing JSON Object to File.");
|
||||
return console.log(err);
|
||||
}
|
||||
console.log("JSON file has been saved.");
|
||||
});
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
//motionDataRaw.json was scraped from hellomotions.com which belongs to Jessica Yung
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Jessica Yung.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const _ = require('lodash');
|
||||
const motionDataRaw = require('./data/motionDataRaw.json');
|
||||
let tourneys = [];
|
||||
for (let motion of motionDataRaw) {
|
||||
let date = new Date(motion.Date);
|
||||
let year = date.getFullYear().toString();
|
||||
if (year == "NaN") {
|
||||
year = ""
|
||||
}
|
||||
let tournament = motion.Tournament;
|
||||
let firstFour = tournament.slice(0,4)
|
||||
let lastFour = tournament.slice(-4)
|
||||
if (!isNaN(lastFour)) {
|
||||
year = lastFour
|
||||
tournament = tournament.slice(0, -5)
|
||||
}
|
||||
if (!isNaN(firstFour)) {
|
||||
year = firstFour
|
||||
tournament = tournament.slice(5)
|
||||
}
|
||||
let newTournament = {
|
||||
"name": tournament,
|
||||
"format": "",
|
||||
"year": year
|
||||
}
|
||||
tourneys.push(newTournament)
|
||||
}
|
||||
const uniqueTourneys = _.uniqBy(tourneys, (tourney) => {
|
||||
return tourney.name + tourney.year
|
||||
})
|
||||
let tourneyJSON = JSON.stringify(uniqueTourneys)
|
||||
fs.writeFile(`data/tourneys.json`, tourneyJSON, 'utf8', function (err) {
|
||||
if (err) {
|
||||
console.log("An error occured while writing JSON Object to File.");
|
||||
return console.log(err);
|
||||
}
|
||||
console.log("JSON file has been saved.");
|
||||
});
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './useForm'
|
||||
export * from './useDeviceBreakPoint'
|
||||
export * from './useDocumentTitle'
|
||||
export * from './usePageTracker'
|
||||
@@ -0,0 +1,7 @@
|
||||
import { useMediaQuery } from 'react-responsive'
|
||||
export const useDeviceBreakPoint = () => {
|
||||
const isExtraSmall = useMediaQuery({ maxWidth: 379 })
|
||||
const isPhone = useMediaQuery({ minWidth: 380, maxWidth: 425 })
|
||||
const isTablet = useMediaQuery({ minWidth: 426, maxWidth: 768 })
|
||||
return { isPhone, isTablet, isExtraSmall }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export const useDocumentTitle = (title) => {
|
||||
useEffect(() => {
|
||||
document.title = title
|
||||
}, [])
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useState } from 'react'
|
||||
export const useForm = (defaultFormValues) => {
|
||||
const [formValue, setFormValue] = useState(defaultFormValues)
|
||||
function changeFormValue(fieldName, fieldValue) {
|
||||
setFormValue({ ...formValue, [fieldName]: fieldValue });
|
||||
}
|
||||
function resetFormValue() {
|
||||
setFormValue(defaultFormValues)
|
||||
}
|
||||
return ({
|
||||
formValue,
|
||||
changeFormValue,
|
||||
resetFormValue,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useEffect } from 'react'
|
||||
import ReactGA4 from 'react-ga4' // for GA
|
||||
import ReactGA from 'react-ga' // for UA (old)
|
||||
|
||||
export const usePageTracker = () => {
|
||||
useEffect(() => {
|
||||
ReactGA4.send('pageview')
|
||||
ReactGA.pageview(window.location.pathname)
|
||||
}, [])
|
||||
}
|
||||
Reference in New Issue
Block a user