Merge pull request #5 from turniere/ticket/TURNIERE-113
Make "Edit Tournament"-Page with working editing of team names
This commit is contained in:
commit
e7004de3c3
149
js/api.js
149
js/api.js
|
|
@ -40,6 +40,28 @@ const defaultstate_userinfo = {
|
|||
uid : null
|
||||
};
|
||||
|
||||
const actiontypes_tournamentinfo = {
|
||||
'REQUEST_TOURNAMENT' : 'REQUEST_TOURNAMENT',
|
||||
'REQUEST_TOURNAMENT_SUCCESS' : 'REQUEST_TOURNAMENT_SUCCESS',
|
||||
|
||||
'MODIFY_TOURNAMENT' : 'MODIFY_TOURNAMENT',
|
||||
'MODIFY_TOURNAMENT_SUCCESS' : 'MODIFY_TOURNAMENT_SUCCESS',
|
||||
'MODIFY_TOURNAMENT_ERROR' : 'MODIFY_TOURNAMENT_ERROR',
|
||||
|
||||
'REHYDRATE' : 'TOURNAMENTINFO_REHYDRATE',
|
||||
'CLEAR' : 'TOURNAMENTINFO_CLEAR',
|
||||
};
|
||||
|
||||
const defaultstate_tournamentinfo = {
|
||||
code : '',
|
||||
description : '',
|
||||
id : -1,
|
||||
name : '',
|
||||
isPublic : '',
|
||||
stages: [],
|
||||
teams : []
|
||||
};
|
||||
|
||||
export function postRequest(state, url, data) {
|
||||
return axios.post(api_url + url, data, {
|
||||
headers : generateHeaders(state)
|
||||
|
|
@ -58,12 +80,18 @@ export function deleteRequest(state, url) {
|
|||
});
|
||||
}
|
||||
|
||||
export function patchRequest(state, url, data) {
|
||||
return axios.patch(api_url + url, data, {
|
||||
headers : generateHeaders(state)
|
||||
});
|
||||
}
|
||||
|
||||
function generateHeaders(state) {
|
||||
if(state.isSignedIn) {
|
||||
if(state.userinfo.isSignedIn) {
|
||||
return {
|
||||
'access-token' : state.accesstoken,
|
||||
'client' : state.client,
|
||||
'uid' : state.uid
|
||||
'access-token' : state.userinfo.accesstoken,
|
||||
'client' : state.userinfo.client,
|
||||
'uid' : state.userinfo.uid
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
|
|
@ -102,7 +130,7 @@ function checkForAuthenticationHeaders(response) {
|
|||
const reducer_userinfo = (state = defaultstate_userinfo, action) => {
|
||||
switch(action.type) {
|
||||
case actiontypes_userinfo.REGISTER:
|
||||
postRequest(state, '/users', {
|
||||
postRequest(action.state, '/users', {
|
||||
'username' : action.parameters.username,
|
||||
'email' : action.parameters.email,
|
||||
'password' : action.parameters.password
|
||||
|
|
@ -143,7 +171,7 @@ const reducer_userinfo = (state = defaultstate_userinfo, action) => {
|
|||
errorMessages : action.parameters.errorMessages
|
||||
});
|
||||
case actiontypes_userinfo.LOGIN:
|
||||
postRequest(state, '/users/sign_in', {
|
||||
postRequest(action.state, '/users/sign_in', {
|
||||
email : action.parameters.email,
|
||||
password : action.parameters.password
|
||||
}).then((resp) => {
|
||||
|
|
@ -186,7 +214,7 @@ const reducer_userinfo = (state = defaultstate_userinfo, action) => {
|
|||
errorMessages : action.parameters.errorMessages
|
||||
});
|
||||
case actiontypes_userinfo.LOGOUT:
|
||||
deleteRequest(state, '/users/sign_out').then(() => {
|
||||
deleteRequest(action.state, '/users/sign_out').then(() => {
|
||||
__store.dispatch({ type : actiontypes_userinfo.CLEAR });
|
||||
}).catch(() => {
|
||||
__store.dispatch({ type : actiontypes_userinfo.CLEAR });
|
||||
|
|
@ -200,7 +228,7 @@ const reducer_userinfo = (state = defaultstate_userinfo, action) => {
|
|||
uid : action.parameters.uid
|
||||
});
|
||||
case actiontypes_userinfo.VERIFY_CREDENTIALS:
|
||||
getRequest(state, '/users/validate_token').then((resp) => {
|
||||
getRequest(action.state, '/users/validate_token').then((resp) => {
|
||||
storeOptionalToken(resp);
|
||||
}).catch(() => {
|
||||
__store.dispatch({ type: actiontypes_userinfo.CLEAR });
|
||||
|
|
@ -224,12 +252,68 @@ const reducer_userinfo = (state = defaultstate_userinfo, action) => {
|
|||
}
|
||||
};
|
||||
|
||||
const reducer_tournamentinfo = (state = defaultstate_tournamentinfo, action) => {
|
||||
switch(action.type) {
|
||||
case actiontypes_tournamentinfo.REQUEST_TOURNAMENT:
|
||||
getRequest(action.state, '/tournaments/' + action.parameters.code).then((resp) => {
|
||||
__store.dispatch({
|
||||
type: actiontypes_tournamentinfo.REQUEST_TOURNAMENT_SUCCESS,
|
||||
parameters: resp.data
|
||||
});
|
||||
storeOptionalToken(resp);
|
||||
action.parameters.successCallback();
|
||||
}).catch(() => {
|
||||
action.parameters.errorCallback();
|
||||
});
|
||||
return Object.assign({}, state, {});
|
||||
case actiontypes_tournamentinfo.REQUEST_TOURNAMENT_SUCCESS:
|
||||
return Object.assign({}, state, {
|
||||
code : action.parameters.code,
|
||||
description : action.parameters.description,
|
||||
id : action.parameters.id,
|
||||
name : action.parameters.name,
|
||||
isPublic : action.parameters.public,
|
||||
stages: action.parameters.stages,
|
||||
teams : action.parameters.teams
|
||||
});
|
||||
case actiontypes_tournamentinfo.MODIFY_TOURNAMENT:
|
||||
patchRequest(action.state, '/teams/' + action.parameters.teamid, {
|
||||
name: action.parameters.name
|
||||
}).then((resp) => {
|
||||
storeOptionalToken(resp);
|
||||
action.parameters.onSuccess();
|
||||
}).catch((error) => {
|
||||
if(error.response) {
|
||||
storeOptionalToken(error.response);
|
||||
}
|
||||
action.parameters.onError();
|
||||
});
|
||||
return Object.assign({}, state, {});
|
||||
case actiontypes_tournamentinfo.MODIFY_TOURNAMENT_SUCCESS:
|
||||
|
||||
return Object.assign({}, state, {});
|
||||
case actiontypes_tournamentinfo.MODIFY_TOURNAMENT_ERROR:
|
||||
|
||||
return Object.assign({}, state, {});
|
||||
|
||||
case actiontypes_tournamentinfo.REHYDRATE:
|
||||
|
||||
return Object.assign({}, state, {});
|
||||
case actiontypes_tournamentinfo.CLEAR:
|
||||
|
||||
return Object.assign({}, state, {});
|
||||
default: return state;
|
||||
}
|
||||
};
|
||||
|
||||
const reducers = {
|
||||
userinfo: reducer_userinfo
|
||||
userinfo: reducer_userinfo,
|
||||
tournamentinfo: reducer_tournamentinfo
|
||||
};
|
||||
|
||||
const default_applicationstate = {
|
||||
userinfo : defaultstate_userinfo
|
||||
userinfo : defaultstate_userinfo,
|
||||
tournamentinfo: defaultstate_tournamentinfo
|
||||
};
|
||||
|
||||
var __store;
|
||||
|
|
@ -250,7 +334,10 @@ export function verifyCredentials() {
|
|||
rehydrateApplicationState();
|
||||
|
||||
if(__store.getState().userinfo.isSignedIn) {
|
||||
__store.dispatch({ type: actiontypes_userinfo.VERIFY_CREDENTIALS });
|
||||
__store.dispatch({
|
||||
type: actiontypes_userinfo.VERIFY_CREDENTIALS,
|
||||
state: __store.getState()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +348,8 @@ export function register(username, email, password) {
|
|||
username: username,
|
||||
email: email,
|
||||
password: password
|
||||
}
|
||||
},
|
||||
state: __store.getState()
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -271,12 +359,41 @@ export function login(email, password) {
|
|||
parameters: {
|
||||
email: email,
|
||||
password: password
|
||||
}
|
||||
},
|
||||
state: __store.getState()
|
||||
});
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
__store.dispatch({ type : actiontypes_userinfo.LOGOUT });
|
||||
__store.dispatch({
|
||||
type : actiontypes_userinfo.LOGOUT,
|
||||
state: __store.getState()
|
||||
});
|
||||
}
|
||||
|
||||
export function requestTournament(code, successCallback, errorCallback) {
|
||||
__store.dispatch({
|
||||
type: actiontypes_tournamentinfo.REQUEST_TOURNAMENT,
|
||||
parameters: {
|
||||
code: code,
|
||||
successCallback: successCallback,
|
||||
errorCallback: errorCallback
|
||||
},
|
||||
state: __store.getState()
|
||||
});
|
||||
}
|
||||
|
||||
export function updateTeamName(team, successCB, errorCB) {
|
||||
__store.dispatch({
|
||||
type: actiontypes_tournamentinfo.MODIFY_TOURNAMENT,
|
||||
parameters: {
|
||||
teamid: team.id,
|
||||
name: team.name,
|
||||
onSuccess : successCB,
|
||||
onError : errorCB
|
||||
},
|
||||
state: __store.getState()
|
||||
});
|
||||
}
|
||||
|
||||
export function getState() {
|
||||
|
|
@ -293,6 +410,10 @@ function rehydrateApplicationState() {
|
|||
type : actiontypes_userinfo.REHYDRATE,
|
||||
parameters : Object.assign({}, persistedState.userinfo, {})
|
||||
});
|
||||
__store.dispatch({
|
||||
type : actiontypes_tournamentinfo.REHYDRATE,
|
||||
parameters : Object.assign({}, persistedState.tournamentinfo, {})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
import Head from 'next/head';
|
||||
import React from 'react';
|
||||
import {Footer, TurniereNavigation} from '../CommonComponents';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import {Container} from 'reactstrap';
|
||||
import '../../static/everypage.css';
|
||||
import '../../static/css/error.css';
|
||||
|
||||
export class ErrorPageComponent extends React.Component {
|
||||
|
||||
static getInitialProps({ statusCode }) {
|
||||
return { statusCode };
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>turnie.re - Error {this.props.statusCode}</title>
|
||||
</Head>
|
||||
<TurniereNavigation/>
|
||||
<ErrorPage statusCode={this.props.statusCode}/>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function ErrorPage(props){
|
||||
return (
|
||||
<Container className="mb-5">
|
||||
<div className="row mb-5">
|
||||
<div className="col-lg text-center">
|
||||
<img src="/static/images/logo-questionmark.png" className="w-75 img-fluid"/>
|
||||
</div>
|
||||
<div className="col-lg error-code-box">
|
||||
<h1 className="custom-font py-5">{props.statusCode}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<ErrorMessage code={props.statusCode}/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
function ErrorMessage(props) {
|
||||
switch (props.code) {
|
||||
case 400:
|
||||
return (<div className="running-text">
|
||||
<h2>Deine Anfrage ist fehlerhaft.</h2>
|
||||
<p>
|
||||
Wir empfehlen, die eingegebene Seite über die <a href="/">Startseite</a> zu suchen.
|
||||
</p>
|
||||
</div>);
|
||||
case 403:
|
||||
return (<div className="running-text">
|
||||
<h2>Du bist nicht autorisiert, diese Seite aufzurufen.</h2>
|
||||
<p>
|
||||
Bitte stelle sicher, dass Du angemeldet bist und auf dieses Turnier oder dieses Match zugreifen darfst.
|
||||
</p>
|
||||
<p>
|
||||
Wir empfehlen, die eingegebene Seite über die <a href="/">Startseite</a> zu suchen.
|
||||
</p>
|
||||
</div>);
|
||||
case 404:
|
||||
return (<div className="running-text">
|
||||
<h2>Die aufgerufene Seite wurde leider nicht gefunden.</h2>
|
||||
<p>
|
||||
Entweder hast Du dich vertippt, oder die gesuchte Seite gibt es nicht.
|
||||
</p>
|
||||
<p>
|
||||
Wir empfehlen, die eingegebene Seite über die <a href="/">Startseite</a> zu suchen.
|
||||
</p>
|
||||
</div>);
|
||||
case 500:
|
||||
return (<div className="running-text">
|
||||
<h2>Diese Seite funktioniert nicht.</h2>
|
||||
<p>
|
||||
turnie.re kann Deine Anfrage im Moment nicht verarbeiten. Bitte versuche es später erneut.
|
||||
</p>
|
||||
</div>);
|
||||
default:
|
||||
return (<div>
|
||||
<h2>Ein unbekannter Fehler ist aufgetreten.</h2>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
"next": "^7.0.2",
|
||||
"react": "^16.6.1",
|
||||
"react-dom": "^16.6.1",
|
||||
"react-notify-toast": "^0.5.0",
|
||||
"react-redux": "^5.1.1",
|
||||
"reactstrap": "^6.5.0",
|
||||
"redux": "^4.0.1",
|
||||
|
|
|
|||
|
|
@ -2,18 +2,15 @@ import App, {Container} from 'next/app';
|
|||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import withReduxStore from '../js/redux/reduxStoreBinder';
|
||||
import { verifyCredentials } from '../js/api';
|
||||
import Notifications from 'react-notify-toast';
|
||||
|
||||
class TurniereApp extends App {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render () {
|
||||
const {Component, pageProps, reduxStore} = this.props;
|
||||
return (
|
||||
<Container>
|
||||
<Notifications />
|
||||
<Provider store={reduxStore}>
|
||||
<Component {...pageProps} />
|
||||
</Provider>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import Head from 'next/head';
|
||||
import { ErrorPageComponent } from '../js/components/ErrorComponents.js';
|
||||
import React from 'react';
|
||||
import {Footer, TurniereNavigation} from '../js/CommonComponents';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import {Container} from 'reactstrap';
|
||||
import '../static/everypage.css';
|
||||
import '../static/css/error.css';
|
||||
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
export default class Error extends React.Component {
|
||||
static getInitialProps({ res, err }) {
|
||||
|
|
@ -12,75 +11,13 @@ export default class Error extends React.Component {
|
|||
return { statusCode };
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>turnie.re - Error {this.props.statusCode}</title>
|
||||
</Head>
|
||||
<TurniereNavigation/>
|
||||
<ErrorPage statusCode={this.props.statusCode}/>
|
||||
<Footer/>
|
||||
</div>
|
||||
<ErrorPageComponent statusCode={this.props.statusCode}/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function ErrorPage(props){
|
||||
return (
|
||||
<Container className="mb-5">
|
||||
<div className="row mb-5">
|
||||
<div className="col-lg text-center">
|
||||
<img src="/static/images/logo-questionmark.png" className="w-75 img-fluid"/>
|
||||
</div>
|
||||
<div className="col-lg error-code-box">
|
||||
<h1 className="custom-font py-5">{props.statusCode}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<ErrorMessage code={props.statusCode}/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
function ErrorMessage(props) {
|
||||
switch (props.code) {
|
||||
case 400:
|
||||
return (<div className="running-text">
|
||||
<h2>Deine Anfrage ist fehlerhaft.</h2>
|
||||
<p>
|
||||
Wir empfehlen, die eingegebene Seite über die <a href="/">Startseite</a> zu suchen.
|
||||
</p>
|
||||
</div>);
|
||||
case 403:
|
||||
return (<div className="running-text">
|
||||
<h2>Du bist nicht autorisiert, diese Seite aufzurufen.</h2>
|
||||
<p>
|
||||
Bitte stelle sicher, dass Du angemeldet bist und auf dieses Turnier oder dieses Match zugreifen darfst.
|
||||
</p>
|
||||
<p>
|
||||
Wir empfehlen, die eingegebene Seite über die <a href="/">Startseite</a> zu suchen.
|
||||
</p>
|
||||
</div>);
|
||||
case 404:
|
||||
return (<div className="running-text">
|
||||
<h2>Die aufgerufene Seite wurde leider nicht gefunden.</h2>
|
||||
<p>
|
||||
Entweder hast Du dich vertippt, oder die gesuchte Seite gibt es nicht.
|
||||
</p>
|
||||
<p>
|
||||
Wir empfehlen, die eingegebene Seite über die <a href="/">Startseite</a> zu suchen.
|
||||
</p>
|
||||
</div>);
|
||||
case 500:
|
||||
return (<div className="running-text">
|
||||
<h2>Diese Seite funktioniert nicht.</h2>
|
||||
<p>
|
||||
turnie.re kann Deine Anfrage im Moment nicht verarbeiten. Bitte versuche es später erneut.
|
||||
</p>
|
||||
</div>);
|
||||
default:
|
||||
return (<div>
|
||||
<h2>Ein unbekannter Fehler ist aufgetreten.</h2>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,9 +16,20 @@ import {
|
|||
Label
|
||||
} from 'reactstrap';
|
||||
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
import EditableStringList from '../js/EditableStringList';
|
||||
|
||||
export default () => (
|
||||
export default class CreatePage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="main generic-fullpage-bg">
|
||||
<Head>
|
||||
<title>Turnier erstellen: turnie.re</title>
|
||||
|
|
@ -29,7 +40,10 @@ export default () => (
|
|||
</div>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function CreateTournamentCard() {
|
||||
return (
|
||||
|
|
|
|||
17
pages/faq.js
17
pages/faq.js
|
|
@ -5,6 +5,10 @@ import 'bootstrap/dist/css/bootstrap.min.css';
|
|||
import { BigImage, Footer, TurniereNavigation } from '../js/CommonComponents.js';
|
||||
import '../static/everypage.css';
|
||||
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
function Main() {
|
||||
return (
|
||||
<div className="main">
|
||||
|
|
@ -216,7 +220,14 @@ function TournamentFaq() {
|
|||
);
|
||||
}
|
||||
|
||||
export default () => (
|
||||
export default class FaqPage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>FAQ: turnie.re</title>
|
||||
|
|
@ -226,4 +237,6 @@ export default () => (
|
|||
<Main/>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ import 'bootstrap/dist/css/bootstrap.min.css';
|
|||
import {BigImage, Footer, TurniereNavigation} from '../js/CommonComponents.js';
|
||||
import '../static/everypage.css';
|
||||
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
function Main() {
|
||||
return (
|
||||
<div className="main running-text">
|
||||
|
|
@ -69,7 +73,14 @@ function ImprintText(){
|
|||
}
|
||||
|
||||
|
||||
export default () => (
|
||||
export default class ImprintPage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>Impressum: turnie.re</title>
|
||||
|
|
@ -79,4 +90,6 @@ export default () => (
|
|||
<Main/>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ import '../static/css/index.css';
|
|||
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
function Main() {
|
||||
return (
|
||||
<div className="main">
|
||||
|
|
@ -114,7 +118,7 @@ function PromotedLinkTournamentCode() {
|
|||
<CardBody className="row">
|
||||
<form id="turniercode-form" className="col-lg-4" action="/t" method="get">
|
||||
<input className="form-control" type="search" name="code" placeholder="Turnier-Code"/>
|
||||
<button className="btn btn-outline-success w-100 my-2" type="submit">Turnier-Code öffnen</button>
|
||||
<Button className="btn btn-outline-success w-100 my-2" type="submit">Turnier-Code öffnen</Button>
|
||||
</form>
|
||||
<div className="col-lg-8">
|
||||
<p>Gib hier einen Turnier Code ein, um direkt zum entsprechenden Turnier zu gelangen.</p>
|
||||
|
|
@ -165,6 +169,11 @@ function PromotedLinkCreateTournament() {
|
|||
|
||||
|
||||
class Index extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,24 @@
|
|||
import Head from 'next/head';
|
||||
import '../static/everypage.css';
|
||||
import { Footer, TurniereNavigation } from '../js/CommonComponents';
|
||||
import React from 'react';
|
||||
import { Card, CardBody, Container } from 'reactstrap';
|
||||
import { getRequest, getState } from '../js/api';
|
||||
|
||||
export default () => (
|
||||
import { Footer, TurniereNavigation } from '../js/CommonComponents';
|
||||
import {
|
||||
getRequest,
|
||||
getState,
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
import '../static/everypage.css';
|
||||
|
||||
export default class ListPage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="main generic-fullpage-bg">
|
||||
<Head>
|
||||
<title>Öffentliche Turniere: turnie.re</title>
|
||||
|
|
@ -16,7 +29,9 @@ export default () => (
|
|||
</div>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TournamentList extends React.Component {
|
||||
constructor(props) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,18 @@ import { Button, Card, CardBody, Container, Form, FormGroup, Input, Label } from
|
|||
import { login } from '../js/api';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
export default () => (
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
export default class LoginPage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="main generic-fullpage-bg">
|
||||
<Head>
|
||||
<title>Login: turnie.re</title>
|
||||
|
|
@ -17,7 +28,9 @@ export default () => (
|
|||
</div>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function Login() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ import 'bootstrap/dist/css/bootstrap.min.css';
|
|||
import { BigImage, Footer, TurniereNavigation } from '../js/CommonComponents.js';
|
||||
import '../static/everypage.css';
|
||||
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
function Main() {
|
||||
return (
|
||||
<div className="main running-text">
|
||||
|
|
@ -488,7 +492,14 @@ function PrivacyText(){
|
|||
}
|
||||
|
||||
|
||||
export default () => (
|
||||
export default class PrivacyPage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>Datenschutzerklärung: turnie.re</title>
|
||||
|
|
@ -498,4 +509,6 @@ export default () => (
|
|||
<Main/>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,18 @@ import { Button, Card, CardBody, Container, Form, FormGroup, FormText, Input, La
|
|||
import { register } from '../js/api';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
export default () => (
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
export default class RegisterPage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="main generic-fullpage-bg">
|
||||
<Head>
|
||||
<title>Registrieren: turnie.re</title>
|
||||
|
|
@ -18,7 +29,9 @@ export default () => (
|
|||
</div>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function Register() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
import Head from 'next/head';
|
||||
import React from 'react';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import { connect } from 'react-redux';
|
||||
import { notify } from 'react-notify-toast';
|
||||
|
||||
import { requestTournament } from '../js/api';
|
||||
import { BigImage, Footer, TurniereNavigation } from '../js/CommonComponents.js';
|
||||
import { ErrorPageComponent } from '../js/components/ErrorComponents.js';
|
||||
|
||||
import {
|
||||
Container,
|
||||
Button,
|
||||
Card,
|
||||
CardBody,
|
||||
Table
|
||||
} from 'reactstrap';
|
||||
|
||||
import {
|
||||
verifyCredentials,
|
||||
updateTeamName
|
||||
} from '../js/api';
|
||||
|
||||
import '../static/everypage.css';
|
||||
import '../static/css/index.css';
|
||||
|
||||
class EditTournamentPage extends React.Component {
|
||||
|
||||
static async getInitialProps({query}) {
|
||||
return {query};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
validCode: true
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
requestTournament(this.props.query.code, () => {
|
||||
this.setState({ validCode: true });
|
||||
this._edittournamentcontent.notifyOfContentUpdate();
|
||||
}, () => {
|
||||
this.setState({ validCode: false });
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { validCode } = this.state;
|
||||
const { name } = this.props;
|
||||
|
||||
if(validCode) {
|
||||
return (
|
||||
<div className='pb-5'>
|
||||
<Head>
|
||||
<title>Turnie.re - Turnier bearbeiten</title>
|
||||
</Head>
|
||||
<TurniereNavigation/>
|
||||
<BigImage text={ name }/>
|
||||
|
||||
<EditTournamentContent ref={(edittournamentcontent) => { this._edittournamentcontent = edittournamentcontent; }}/>
|
||||
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<ErrorPageComponent statusCode={ 404 }/>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToTournamentInfo(state) {
|
||||
const { name } = state.tournamentinfo;
|
||||
return { name };
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToTournamentInfo
|
||||
)(EditTournamentPage);
|
||||
|
||||
class EditTournamentContent extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className='mb-5'>
|
||||
<ReturnToTournamentButton/>
|
||||
<EditTournamentPropertiesField ref={(field) => { this._edittournamentpropertiesfield = field; }}/>
|
||||
<EditTeamField ref={(field) => { this._editteamfield = field; }}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
notifyOfContentUpdate() {
|
||||
this._edittournamentpropertiesfield.notifyOfContentUpdate();
|
||||
this._editteamfield.notifyOfContentUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
function ReturnToTournamentButton() {
|
||||
return (
|
||||
<Container className="px-0">
|
||||
<Button color="secondary" className="mb-5 w-100" href="./">Zurück zum Turnier</Button>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
class EditTournamentPropertiesField extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Card className="container">
|
||||
<CardBody>
|
||||
<h2>Turnier-Eigenschaften ändern</h2>
|
||||
<VisibleEditTournamentForm ref={(form) => { this._visibleedittournamentform = form; }}/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
notifyOfContentUpdate() {
|
||||
this._visibleedittournamentform.getWrappedInstance().notifyOfContentUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
class EditTournamentForm extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
name : '',
|
||||
description : '',
|
||||
isPublic : false
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { name, description, isPublic } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="name">Turnier-Name</label>
|
||||
<input className="form-control" type="text" name="name" id="edittournament-textfield-name" value={ name } placeholder={ name } onChange={ this.handleNameInput.bind(this) } />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="name">Turnier-Beschreibung</label>
|
||||
<input className="form-control" type="text" name="name" id="edittournament-textfield-description" value={ description } placeholder={ description } onChange={ this.handleDescriptionInput.bind(this) } />
|
||||
</div>
|
||||
<div className="form-group custom-control custom-checkbox">
|
||||
<input className="custom-control-input" type="checkbox" name="isPublic" id="edittournament-checkbox-isPublic" value={ isPublic } onChange={ this.handlePublicInput.bind(this) } />
|
||||
<label htmlFor="isPublic" className="custom-control-label">Das Turnier öffentlich anzeigen</label>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div className="input-group">
|
||||
<Button color="success" className="px-5" id="edittournament-button" onClick={ this.handleClick.bind(this) }>Ändern</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
notifyOfContentUpdate() {
|
||||
const { name, description, isPublic } = this.props;
|
||||
|
||||
this.setState({
|
||||
name : name? name : '',
|
||||
description : description? description : '',
|
||||
isPublic : isPublic
|
||||
});
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
// TODO: Apply changes to the tournament properties
|
||||
}
|
||||
|
||||
handleNameInput(input) {
|
||||
this.setState({ name : input.target.value });
|
||||
}
|
||||
|
||||
handleDescriptionInput(input) {
|
||||
this.setState({ description : input.target.value });
|
||||
}
|
||||
|
||||
handlePublicInput(input) {
|
||||
this.setState({ public : input.target.value });
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToTournamentFormProps(state) {
|
||||
const { name, description, isPublic } = state.tournamentinfo;
|
||||
return { name, description, isPublic };
|
||||
}
|
||||
|
||||
const VisibleEditTournamentForm = connect(
|
||||
mapStateToTournamentFormProps,
|
||||
null, null, { withRef : true}
|
||||
)(EditTournamentForm);
|
||||
|
||||
class EditTeamField extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Card className="container my-4">
|
||||
<CardBody>
|
||||
<h2>Team-Namen ändern</h2>
|
||||
<VisibleEditTeamNamesForm ref={(form) => { this._visibleeditteamnamesform = form; }}/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
notifyOfContentUpdate() {
|
||||
this._visibleeditteamnamesform.getWrappedInstance().notifyOfContentUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
class EditTeamNamesForm extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
teams : []
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { teams } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table className="table-striped mt-3">
|
||||
<tbody>
|
||||
{
|
||||
teams.map((team, index) =>
|
||||
<tr key={index}>
|
||||
<td><Button outline size="sm" className="changeTeamnameButton" id={ 'editteam-button-team_' + team.id } onClick={ this.handleClick.bind(this, index) }>Ändern</Button></td>
|
||||
<td className="w-100"><input className="form-control" type="text" id={ 'editteam-textfield-team_' + team.id } value={ team.name } placeholder={ team.name } onChange={ this.handleNameInput.bind(this, index) } /></td>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
notifyOfContentUpdate() {
|
||||
const { teams } = this.props;
|
||||
|
||||
this.setState({
|
||||
teams : teams
|
||||
});
|
||||
}
|
||||
|
||||
handleNameInput(index, input) {
|
||||
var team = this.state.teams.slice();
|
||||
|
||||
team[index].name = input.target.value;
|
||||
|
||||
this.setState({
|
||||
teams : team
|
||||
});
|
||||
}
|
||||
|
||||
handleClick(index) {
|
||||
updateTeamName(this.state.teams[index], () => {
|
||||
notify.show('Team Name wurde erfolgreich geändert.', 'success', 5000);
|
||||
}, () => {
|
||||
notify.show('Team Name konnte nicht geändert werden.', 'warning', 5000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToTeamFormProps(state) {
|
||||
const { teams } = state.tournamentinfo;
|
||||
return { teams };
|
||||
}
|
||||
|
||||
const VisibleEditTeamNamesForm = connect(
|
||||
mapStateToTeamFormProps,
|
||||
null, null, { withRef : true }
|
||||
)(EditTeamNamesForm);
|
||||
|
||||
|
|
@ -1,12 +1,20 @@
|
|||
import Head from 'next/head';
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
class FullscreenTournamentPage extends React.Component {
|
||||
|
||||
static async getInitialProps({query}) {
|
||||
return {query};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -22,29 +22,39 @@ import 'bootstrap/dist/css/bootstrap.min.css';
|
|||
import {BigImage, Footer, TurniereNavigation} from '../js/CommonComponents.js';
|
||||
import '../static/everypage.css';
|
||||
import '../static/css/tournament.css';
|
||||
import { getRequest, getState } from '../js/api';
|
||||
|
||||
function Tournament(props) {
|
||||
import {
|
||||
getRequest,
|
||||
getState,
|
||||
verifyCredentials
|
||||
} from '../js/api';
|
||||
|
||||
class TournamentPage extends React.Component {
|
||||
|
||||
render() {
|
||||
const { id, description, isPublic, code, ownerUsername, playoffStages } = this.props.tournament;
|
||||
|
||||
// TODO: Change href-prop of the anchor tag to contain the tournament code
|
||||
return (
|
||||
<div className='pb-5'>
|
||||
<Container>
|
||||
<a href={'/t/' + props.tournament.id + '/edit'} className='btn btn-outline-secondary'>Turnier bearbeiten</a>
|
||||
<p>{props.tournament.description}</p>
|
||||
<a href={'/t/' + id + '/edit'} className='btn btn-outline-secondary'>Turnier bearbeiten</a>
|
||||
<p>{description}</p>
|
||||
<ListGroup>
|
||||
<ListGroupItem>
|
||||
{props.tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'}
|
||||
{isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'}
|
||||
</ListGroupItem>
|
||||
<ListGroupItem>Turnier-Code: <b>{props.tournament.code}</b></ListGroupItem>
|
||||
<ListGroupItem>von <b>{props.tournament.ownerUsername}</b></ListGroupItem>
|
||||
<ListGroupItem>Turnier-Code: <b>{code}</b></ListGroupItem>
|
||||
<ListGroupItem>von <b>{ownerUsername}</b></ListGroupItem>
|
||||
</ListGroup>
|
||||
</Container>
|
||||
<div className='stages pt-5'>
|
||||
{props.tournament.playoffStages.map(stage =>
|
||||
{playoffStages.map(stage =>
|
||||
<Stage level={getLevelName(stage.level)} matches={stage.matches} key={stage.level}/>)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getLevelName(levelNumber) {
|
||||
|
|
@ -57,10 +67,12 @@ function getLevelName(levelNumber) {
|
|||
}
|
||||
|
||||
function TournamentContainer(props) {
|
||||
if (props.data === null) {
|
||||
const { tournament } = props.data;
|
||||
|
||||
if (tournament === null) {
|
||||
return <Container>null</Container>;
|
||||
} else {
|
||||
return <Tournament tournament={props.data.tournament}/>;
|
||||
return <TournamentPage tournament={tournament}/>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -339,9 +351,24 @@ function convertMatch(apiMatch) {
|
|||
}
|
||||
|
||||
class Main extends React.Component {
|
||||
|
||||
static async getInitialProps({query}) {
|
||||
return {query};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
tournament : null
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
verifyCredentials();
|
||||
|
||||
const code = this.props.query.code;
|
||||
|
||||
getRequest(getState(), '/tournaments/' + code)
|
||||
.then(response => {
|
||||
this.setState({tournament: convertTournament(response.data)});
|
||||
|
|
@ -349,12 +376,9 @@ class Main extends React.Component {
|
|||
.catch(() => { /* TODO: Show some kind of error or smth */ });
|
||||
}
|
||||
|
||||
static async getInitialProps({query}) {
|
||||
return {query};
|
||||
}
|
||||
|
||||
render() {
|
||||
const tournamentName = this.state === null ? 'Turnier' : this.state.tournament.name;
|
||||
const tournamentName = this.state.tournament === null ? 'Turnier' : this.state.tournament.name;
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@ app.prepare()
|
|||
app.render(req, res, actualPage, queryParam);
|
||||
});
|
||||
|
||||
server.get('/t/:code/edit', (req, res) => {
|
||||
const actualPage = '/tournament-edit';
|
||||
const queryParam = { code: req.params.code };
|
||||
app.render(req, res, actualPage, queryParam);
|
||||
});
|
||||
|
||||
server.get('*', (req, res) => {
|
||||
return handle(req, res);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,3 +2,7 @@
|
|||
background: url("/static/images/tennis-blurred.jpg") no-repeat center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
h2, h3, h4 {
|
||||
font-family: Halt, sans-serif;
|
||||
}
|
||||
10
yarn.lock
10
yarn.lock
|
|
@ -5635,7 +5635,7 @@ number-is-nan@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
|
@ -6388,6 +6388,14 @@ react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
|
|||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-notify-toast@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/react-notify-toast/-/react-notify-toast-0.5.0.tgz#b00cf50a3cc97a1d222ecd7d7a8e7f14bef5fa67"
|
||||
integrity sha1-sAz1CjzJeh0iLs19eo5/FL71+mc=
|
||||
dependencies:
|
||||
object-assign "^4.0.0"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
react-popper@^0.10.4:
|
||||
version "0.10.4"
|
||||
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-0.10.4.tgz#af2a415ea22291edd504678d7afda8a6ee3295aa"
|
||||
|
|
|
|||
Loading…
Reference in New Issue