diff --git a/js/api.js b/js/api.js
index 3c5db29..83f281b 100644
--- a/js/api.js
+++ b/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, {})
+ });
}
}
diff --git a/js/components/ErrorComponents.js b/js/components/ErrorComponents.js
new file mode 100644
index 0000000..d33190b
--- /dev/null
+++ b/js/components/ErrorComponents.js
@@ -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 (
+
+
+
turnie.re - Error {this.props.statusCode}
+
+
+
+
+
+ );
+ }
+}
+
+function ErrorPage(props){
+ return (
+
+
+
+

+
+
+
{props.statusCode}
+
+
+
+
+ );
+}
+
+function ErrorMessage(props) {
+ switch (props.code) {
+ case 400:
+ return (
+
Deine Anfrage ist fehlerhaft.
+
+ Wir empfehlen, die eingegebene Seite über die Startseite zu suchen.
+
+
);
+ case 403:
+ return (
+
Du bist nicht autorisiert, diese Seite aufzurufen.
+
+ Bitte stelle sicher, dass Du angemeldet bist und auf dieses Turnier oder dieses Match zugreifen darfst.
+
+
+ Wir empfehlen, die eingegebene Seite über die Startseite zu suchen.
+
+
);
+ case 404:
+ return (
+
Die aufgerufene Seite wurde leider nicht gefunden.
+
+ Entweder hast Du dich vertippt, oder die gesuchte Seite gibt es nicht.
+
+
+ Wir empfehlen, die eingegebene Seite über die Startseite zu suchen.
+
+
);
+ case 500:
+ return (
+
Diese Seite funktioniert nicht.
+
+ turnie.re kann Deine Anfrage im Moment nicht verarbeiten. Bitte versuche es später erneut.
+
+
);
+ default:
+ return (
+
Ein unbekannter Fehler ist aufgetreten.
+ );
+ }
+}
diff --git a/package.json b/package.json
index 50ad571..601fd1b 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/pages/_app.js b/pages/_app.js
index 3bf91cd..39529b0 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -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 (
+
diff --git a/pages/_error.js b/pages/_error.js
index 202f1ca..c0babdc 100644
--- a/pages/_error.js
+++ b/pages/_error.js
@@ -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 (
-
-
-
turnie.re - Error {this.props.statusCode}
-
-
-
-
-
+
);
}
}
-
-function ErrorPage(props){
- return (
-
-
-
-

-
-
-
{props.statusCode}
-
-
-
-
- );
-}
-
-function ErrorMessage(props) {
- switch (props.code) {
- case 400:
- return (
-
Deine Anfrage ist fehlerhaft.
-
- Wir empfehlen, die eingegebene Seite über die Startseite zu suchen.
-
-
);
- case 403:
- return (
-
Du bist nicht autorisiert, diese Seite aufzurufen.
-
- Bitte stelle sicher, dass Du angemeldet bist und auf dieses Turnier oder dieses Match zugreifen darfst.
-
-
- Wir empfehlen, die eingegebene Seite über die Startseite zu suchen.
-
-
);
- case 404:
- return (
-
Die aufgerufene Seite wurde leider nicht gefunden.
-
- Entweder hast Du dich vertippt, oder die gesuchte Seite gibt es nicht.
-
-
- Wir empfehlen, die eingegebene Seite über die Startseite zu suchen.
-
-
);
- case 500:
- return (
-
Diese Seite funktioniert nicht.
-
- turnie.re kann Deine Anfrage im Moment nicht verarbeiten. Bitte versuche es später erneut.
-
-
);
- default:
- return (
-
Ein unbekannter Fehler ist aufgetreten.
- );
- }
-}
\ No newline at end of file
diff --git a/pages/create.js b/pages/create.js
index d2ee8db..b1606f4 100644
--- a/pages/create.js
+++ b/pages/create.js
@@ -16,20 +16,34 @@ import {
Label
} from 'reactstrap';
+import {
+ verifyCredentials
+} from '../js/api';
+
import EditableStringList from '../js/EditableStringList';
-export default () => (
-
-
-
Turnier erstellen: turnie.re
-
-
-
-
-
-
-
-);
+export default class CreatePage extends React.Component {
+
+ componentDidMount() {
+ verifyCredentials();
+ }
+
+ render() {
+ return (
+
+
+
Turnier erstellen: turnie.re
+
+
+
+
+
+
+
+ );
+ }
+}
+
function CreateTournamentCard() {
return (
diff --git a/pages/faq.js b/pages/faq.js
index 57e3bdb..d747e7d 100644
--- a/pages/faq.js
+++ b/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 (
@@ -216,14 +220,23 @@ function TournamentFaq() {
);
}
-export default () => (
-
-
-
FAQ: turnie.re
-
-
-
-
-
-
-);
+export default class FaqPage extends React.Component {
+
+ componentDidMount() {
+ verifyCredentials();
+ }
+
+ render() {
+ return (
+
+
+
FAQ: turnie.re
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/pages/imprint.js b/pages/imprint.js
index feec607..34fb942 100644
--- a/pages/imprint.js
+++ b/pages/imprint.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 (
@@ -69,14 +73,23 @@ function ImprintText(){
}
-export default () => (
-
-
-
Impressum: turnie.re
-
-
-
-
-
-
-);
+export default class ImprintPage extends React.Component {
+
+ componentDidMount() {
+ verifyCredentials();
+ }
+
+ render() {
+ return (
+
+
+
Impressum: turnie.re
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/pages/index.js b/pages/index.js
index dee8a02..8dfc2ea 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -12,6 +12,10 @@ import '../static/css/index.css';
import { connect } from 'react-redux';
+import {
+ verifyCredentials
+} from '../js/api';
+
function Main() {
return (
@@ -114,7 +118,7 @@ function PromotedLinkTournamentCode() {
Gib hier einen Turnier Code ein, um direkt zum entsprechenden Turnier zu gelangen.
@@ -165,6 +169,11 @@ function PromotedLinkCreateTournament() {
class Index extends React.Component {
+
+ componentDidMount() {
+ verifyCredentials();
+ }
+
render () {
return (
diff --git a/pages/list.js b/pages/list.js
index 8e03fa4..200e412 100644
--- a/pages/list.js
+++ b/pages/list.js
@@ -1,22 +1,37 @@
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 () => (
-
-
-
Öffentliche Turniere: turnie.re
-
-
-
-
-
-
-
-);
+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 (
+
+
+
Öffentliche Turniere: turnie.re
+
+
+
+
+
+
+
+ );
+ }
+}
class TournamentList extends React.Component {
constructor(props) {
diff --git a/pages/login.js b/pages/login.js
index 6acc489..1a58e49 100644
--- a/pages/login.js
+++ b/pages/login.js
@@ -6,18 +6,31 @@ import { Button, Card, CardBody, Container, Form, FormGroup, Input, Label } from
import { login } from '../js/api';
import { connect } from 'react-redux';
-export default () => (
-
-
-
Login: turnie.re
-
-
-
-
-
-
-
-);
+import {
+ verifyCredentials
+} from '../js/api';
+
+export default class LoginPage extends React.Component {
+
+ componentDidMount() {
+ verifyCredentials();
+ }
+
+ render() {
+ return (
+
+
+
Login: turnie.re
+
+
+
+
+
+
+
+ );
+ }
+}
function Login() {
return (
diff --git a/pages/privacy.js b/pages/privacy.js
index 9f0c2b9..e4263eb 100644
--- a/pages/privacy.js
+++ b/pages/privacy.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 (
@@ -488,14 +492,23 @@ function PrivacyText(){
}
-export default () => (
-
-
-
Datenschutzerklärung: turnie.re
-
-
-
-
-
-
-);
+export default class PrivacyPage extends React.Component {
+
+ componentDidMount() {
+ verifyCredentials();
+ }
+
+ render() {
+ return (
+
+
+
Datenschutzerklärung: turnie.re
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/pages/register.js b/pages/register.js
index cf0365f..096d6c1 100644
--- a/pages/register.js
+++ b/pages/register.js
@@ -6,19 +6,32 @@ import { Button, Card, CardBody, Container, Form, FormGroup, FormText, Input, La
import { register } from '../js/api';
import { connect } from 'react-redux';
-export default () => (
-
-
-
Registrieren: turnie.re
-
-
-
-
-
-);
+import {
+ verifyCredentials
+} from '../js/api';
+
+export default class RegisterPage extends React.Component {
+
+ componentDidMount() {
+ verifyCredentials();
+ }
+
+ render() {
+ return (
+
+
+
Registrieren: turnie.re
+
+
+
+
+
+ );
+ }
+}
function Register() {
return (
diff --git a/pages/tournament-edit.js b/pages/tournament-edit.js
new file mode 100644
index 0000000..0c89d91
--- /dev/null
+++ b/pages/tournament-edit.js
@@ -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 (
+
+
+
Turnie.re - Turnier bearbeiten
+
+
+
+
+ { this._edittournamentcontent = edittournamentcontent; }}/>
+
+
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ }
+}
+
+function mapStateToTournamentInfo(state) {
+ const { name } = state.tournamentinfo;
+ return { name };
+}
+
+export default connect(
+ mapStateToTournamentInfo
+)(EditTournamentPage);
+
+class EditTournamentContent extends React.Component {
+
+ render() {
+ return (
+
+
+ { this._edittournamentpropertiesfield = field; }}/>
+ { this._editteamfield = field; }}/>
+
+ );
+ }
+
+ notifyOfContentUpdate() {
+ this._edittournamentpropertiesfield.notifyOfContentUpdate();
+ this._editteamfield.notifyOfContentUpdate();
+ }
+}
+
+function ReturnToTournamentButton() {
+ return (
+
+
+
+ );
+}
+
+class EditTournamentPropertiesField extends React.Component {
+
+ render() {
+ return (
+
+
+ Turnier-Eigenschaften ändern
+ { this._visibleedittournamentform = form; }}/>
+
+
+ );
+ }
+
+ 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 (
+
+ );
+ }
+
+ 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 (
+
+
+ Team-Namen ändern
+ { this._visibleeditteamnamesform = form; }}/>
+
+
+ );
+ }
+
+ notifyOfContentUpdate() {
+ this._visibleeditteamnamesform.getWrappedInstance().notifyOfContentUpdate();
+ }
+}
+
+class EditTeamNamesForm extends React.Component {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ teams : []
+ };
+ }
+
+ render() {
+ const { teams } = this.state;
+
+ return (
+
+ );
+ }
+
+ 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);
+
diff --git a/pages/tournament-fullscreen.js b/pages/tournament-fullscreen.js
index 09cde55..21fddff 100644
--- a/pages/tournament-fullscreen.js
+++ b/pages/tournament-fullscreen.js
@@ -1,11 +1,19 @@
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 (
diff --git a/pages/tournament.js b/pages/tournament.js
index d864dd8..40753f5 100644
--- a/pages/tournament.js
+++ b/pages/tournament.js
@@ -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) {
- // TODO: Change href-prop of the anchor tag to contain the tournament code
- return (
-
-
- Turnier bearbeiten
- {props.tournament.description}
-
-
- {props.tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'}
-
- Turnier-Code: {props.tournament.code}
- von {props.tournament.ownerUsername}
-
-
-
- {props.tournament.playoffStages.map(stage =>
-
)}
+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 (
+
+
+ Turnier bearbeiten
+ {description}
+
+
+ {isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'}
+
+ Turnier-Code: {code}
+ von {ownerUsername}
+
+
+
+ {playoffStages.map(stage =>
+ )}
+
-
- );
+ );
+ }
}
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
null;
} else {
- return
;
+ return ;
}
}
@@ -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 (
diff --git a/server.js b/server.js
index daccc7d..188d268 100644
--- a/server.js
+++ b/server.js
@@ -8,7 +8,7 @@ const handle = app.getRequestHandler();
app.prepare()
.then(() => {
const server = express();
-
+
server.get('/t/:code', (req, res) => {
const actualPage = '/tournament';
const queryParam = { code: req.params.code };
@@ -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);
});
diff --git a/static/css/index.css b/static/css/index.css
index 0ae4d38..665ccab 100644
--- a/static/css/index.css
+++ b/static/css/index.css
@@ -1,4 +1,8 @@
.index-cards {
background: url("/static/images/tennis-blurred.jpg") no-repeat center;
background-size: cover;
+}
+
+h2, h3, h4 {
+ font-family: Halt, sans-serif;
}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 042a220..912caed 100644
--- a/yarn.lock
+++ b/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"