basic frontend structure
This commit is contained in:
parent
c3ece37824
commit
f2ec466e2d
25 changed files with 81 additions and 1516 deletions
|
@ -27,5 +27,5 @@
|
|||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
],
|
||||
"proxy": "http://localhost:3001"
|
||||
"proxy": "http://localhost:9051"
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
BIN
client/public/images/logo.jpg
Normal file
BIN
client/public/images/logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 285 KiB |
|
@ -22,7 +22,7 @@
|
|||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>NWAP - Stand der Dinge</title>
|
||||
<title>Quarantale</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
|
|
@ -1,218 +1,22 @@
|
|||
import ApiService from '../services/ApiService';
|
||||
import {
|
||||
CONFIG_LOADED,
|
||||
CONFIG_LOAD_ERROR,
|
||||
CONFIG_UPDATED,
|
||||
CONFIG_SAVED,
|
||||
OBJECT_STARTED,
|
||||
OBJECT_PAUSED,
|
||||
OBJECT_STOPPED,
|
||||
OBJECT_STATUS_LOADED,
|
||||
FILE_UPLOADED,
|
||||
FILES_LOADED,
|
||||
FILE_DELETED,
|
||||
PARAMS_LOADED,
|
||||
PARAMS_LOAD_ERROR,
|
||||
PLAYERS_LOADED,
|
||||
PLAYERS_LOAD_ERROR
|
||||
QUESTIONS_LOADED,
|
||||
QUESTIONS_LOAD_ERROR,
|
||||
} from './types';
|
||||
|
||||
|
||||
export const loadConfig = (onSuccess, onError) => dispatch => {
|
||||
export const loadQuestions = (userId) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: CONFIG_LOADED,
|
||||
config: data
|
||||
type: QUESTIONS_LOADED,
|
||||
data: data
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
dispatch({
|
||||
type: CONFIG_LOAD_ERROR,
|
||||
type: QUESTIONS_LOAD_ERROR,
|
||||
error: error
|
||||
});
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.getConfig(scb, ecb);
|
||||
};
|
||||
|
||||
export const updateConfig = (requestData, onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: CONFIG_UPDATED,
|
||||
config: data
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.udpateConfig(requestData, scb, ecb);
|
||||
};
|
||||
|
||||
export const saveConfig = (onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: CONFIG_SAVED,
|
||||
config: data
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.saveConfig(scb, ecb);
|
||||
};
|
||||
|
||||
export const getObjectConfig = (onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: OBJECT_STATUS_LOADED,
|
||||
status: data.status
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.getObjectStatus(scb, ecb);
|
||||
};
|
||||
|
||||
export const startObject = (onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: OBJECT_STARTED,
|
||||
status: data.status
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.startObject(scb, ecb);
|
||||
};
|
||||
|
||||
export const pauseObject = (onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: OBJECT_PAUSED,
|
||||
status: data.status
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.pauseObject(scb, ecb);
|
||||
};
|
||||
|
||||
export const stopObject = (onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: OBJECT_STOPPED,
|
||||
status: data.status
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.stopObject(scb, ecb);
|
||||
};
|
||||
|
||||
export const fileUploaded = (fileData) => dispatch => {
|
||||
dispatch({
|
||||
type: FILE_UPLOADED,
|
||||
file: fileData
|
||||
});
|
||||
}
|
||||
|
||||
export const loadFiles = (onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: FILES_LOADED,
|
||||
files: data
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.getFiles(scb, ecb);
|
||||
};
|
||||
|
||||
export const uploadFile = (formData, onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: FILE_UPLOADED,
|
||||
file: data
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.uploadFile(formData, scb, ecb);
|
||||
};
|
||||
|
||||
export const deleteFile = (name, onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: FILE_DELETED,
|
||||
fileName: name
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.deleteFile(name, scb, ecb);
|
||||
};
|
||||
|
||||
export const loadParams = (onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: PARAMS_LOADED,
|
||||
params: data
|
||||
});
|
||||
if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
dispatch({
|
||||
type: PARAMS_LOAD_ERROR,
|
||||
error: error
|
||||
});
|
||||
if (onError) onError(error);
|
||||
}
|
||||
service.getParams(scb, ecb);
|
||||
};
|
||||
|
||||
export const loadPlayers = (showId, onSuccess, onError) => dispatch => {
|
||||
const service = new ApiService();
|
||||
const scb = (data) => {
|
||||
dispatch({
|
||||
type: PLAYERS_LOADED,
|
||||
players: data
|
||||
});
|
||||
//if (onSuccess) onSuccess(data);
|
||||
}
|
||||
const ecb = (error) => {
|
||||
dispatch({
|
||||
type: PLAYERS_LOAD_ERROR,
|
||||
error: error
|
||||
});
|
||||
//if (onError) onError(error);
|
||||
}
|
||||
service.getPlayers(showId, scb, ecb);
|
||||
service.getQuestions(userId, scb, ecb);
|
||||
};
|
||||
|
|
|
@ -1,15 +1,2 @@
|
|||
export const CONFIG_LOADED = 'CONFIG_LOADED';
|
||||
export const CONFIG_LOAD_ERROR = 'CONFIG_LOAD_ERROR';
|
||||
export const CONFIG_UPDATED = 'CONFIG_SAVED';
|
||||
export const CONFIG_SAVED = 'CONFIG_SAVED';
|
||||
export const OBJECT_STARTED = 'OBJECT_STARTED';
|
||||
export const OBJECT_PAUSED = 'OBJECT_PAUSED';
|
||||
export const OBJECT_STOPPED = 'OBJECT_STOPPED';
|
||||
export const OBJECT_STATUS_LOADED = 'OBJECT_STATUS_LOADED';
|
||||
export const FILE_UPLOADED = 'FILE_UPLOADED';
|
||||
export const FILES_LOADED = 'FILES_LOADED';
|
||||
export const FILE_DELETED = 'FILE_DELETED';
|
||||
export const PARAMS_LOADED = 'PARAMS_LOADED';
|
||||
export const PARAMS_LOAD_ERROR = 'PARAMS_LOAD_ERROR';
|
||||
export const PLAYERS_LOADED = 'PLAYERS_LOADED';
|
||||
export const PLAYERS_LOAD_ERROR = 'PLAYERS_LOAD_ERROR';
|
||||
export const QUESTIONS_LOADED = 'QUESTIONS_LOADED';
|
||||
export const QUESTIONS_LOAD_ERROR = 'QUESTIONS_LOADED';
|
||||
|
|
|
@ -1,395 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { loadConfig, updateConfig, saveConfig } from '../../actions/appActions';
|
||||
import { Form, Switch, Select, Input, Button, Icon, Card, Tooltip } from 'antd';
|
||||
import FormItem from 'antd/lib/form/FormItem';
|
||||
import { NumericInput } from '../';
|
||||
|
||||
class AppConfig extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
config: {},
|
||||
loadingConfig: true,
|
||||
updatingConfig: false,
|
||||
savingConfig: false,
|
||||
configLoadError: false,
|
||||
configUpdateError: false,
|
||||
configSaveError: false
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
let scb = (data) => {
|
||||
if (data.custom === undefined) {
|
||||
data.custom = {};
|
||||
};
|
||||
if (data.custom.printer === undefined) {
|
||||
data.custom.printer = {};
|
||||
}
|
||||
if (data.custom.printer.margins === undefined) {
|
||||
data.custom.printer.margins = {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 10,
|
||||
right: 10
|
||||
};
|
||||
}
|
||||
this.setState({
|
||||
config: data,
|
||||
loadingConfig: false
|
||||
});
|
||||
}
|
||||
let ecb = (error) => {
|
||||
this.setState({
|
||||
configLoadError: error,
|
||||
loadingConfig: false
|
||||
});
|
||||
}
|
||||
this.props.loadConfig(scb, ecb);
|
||||
}
|
||||
|
||||
updateConfig = (e) => {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
updatingConfig: true
|
||||
});
|
||||
|
||||
let scb = (data) => {
|
||||
this.setState({
|
||||
config: data,
|
||||
updatingConfig: false
|
||||
});
|
||||
}
|
||||
let ecb = (error) => {
|
||||
this.setState({
|
||||
configUpdateError: error,
|
||||
updatingConfig: false
|
||||
});
|
||||
}
|
||||
|
||||
this.props.updateConfig(this.state.config, scb, ecb);
|
||||
};
|
||||
|
||||
saveConfig = (e) => {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
savingConfig: true
|
||||
});
|
||||
|
||||
let scb = (data) => {
|
||||
this.setState({
|
||||
config: data,
|
||||
savingConfig: false
|
||||
});
|
||||
}
|
||||
let ecb = (error) => {
|
||||
this.setState({
|
||||
configSaveError: error,
|
||||
savingConfig: false
|
||||
});
|
||||
}
|
||||
this.props.saveConfig(scb, ecb);
|
||||
};
|
||||
|
||||
handleChange = name => event => {
|
||||
let v = 0;
|
||||
let c = JSON.parse(JSON.stringify(this.state.config));
|
||||
switch (name) {
|
||||
case 'key':
|
||||
c.objectOptions.key = event.target.value;
|
||||
break;
|
||||
case 'objectType':
|
||||
c.objectType = event;
|
||||
break;
|
||||
case 'secret':
|
||||
c.objectOptions.secret = event.target.value;
|
||||
break;
|
||||
case 'server':
|
||||
c.objectOptions.server = event.target.value;
|
||||
break;
|
||||
case 'dataDir':
|
||||
c.dataDir = event.target.value;
|
||||
break;
|
||||
case 'tempDir':
|
||||
c.tempDir = event.target.value;
|
||||
break;
|
||||
case 'polling':
|
||||
const pi = parseInt(event, 10);
|
||||
c.objectOptions.pollingInterval = pi;
|
||||
break;
|
||||
case 'start':
|
||||
c.startsImmediately = !c.startsImmediately;
|
||||
break;
|
||||
case 'printermargintop':
|
||||
v = parseInt(event, 10);
|
||||
c.custom.printer.margins.top = v;
|
||||
break;
|
||||
case 'printermarginbottom':
|
||||
v = parseInt(event, 10);
|
||||
c.custom.printer.margins.bottom = v;
|
||||
break;
|
||||
case 'printermarginleft':
|
||||
v = parseInt(event, 10);
|
||||
c.custom.printer.margins.left = v;
|
||||
break;
|
||||
case 'printermarginright':
|
||||
v = parseInt(event, 10);
|
||||
c.custom.printer.margins.right = v;
|
||||
break;
|
||||
case 'printerAdditionalCmdArgs':
|
||||
c.custom.printer.additionalCmdArgs = event.target.value;
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
}
|
||||
this.setState({
|
||||
config: c
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 8 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
},
|
||||
};
|
||||
|
||||
const tailFormItemLayout = {
|
||||
wrapperCol: {
|
||||
xs: {
|
||||
span: 24,
|
||||
offset: 0,
|
||||
},
|
||||
sm: {
|
||||
span: 16,
|
||||
offset: 8,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let updateButtonDisabled = JSON.stringify(this.props.config) === JSON.stringify(this.state.config);
|
||||
|
||||
let saveButtonDisabled = true;
|
||||
if (updateButtonDisabled === true && this.state.config.saved === false) saveButtonDisabled = false;
|
||||
|
||||
let error = '';
|
||||
if (this.state.configUpdateError) error = this.state.configUpdateError;
|
||||
if (this.state.configSaveError) error = this.state.configSaveError;
|
||||
|
||||
const Option = Select.Option;
|
||||
|
||||
return (
|
||||
|
||||
<Card title="application config">
|
||||
|
||||
{this.state.loadingConfig &&
|
||||
<pre>loading config...</pre>
|
||||
}
|
||||
|
||||
{!this.state.loadingConfig &&
|
||||
<Form>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Determines if the server should start polling immediately after bootup.'>
|
||||
<span>starts immediately</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Switch
|
||||
checked={this.state.config.startsImmediately}
|
||||
onChange={this.handleChange('start')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Select the type of the object.'>
|
||||
<span>object type</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Select defaultValue={this.state.config.objectType} style={{ width: 150 }} onChange={this.handleChange('objectType')}>
|
||||
<Option value='default'>Default</Option>
|
||||
<Option value='osc'>OSC</Option>
|
||||
<Option value="printer">Printer</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Enter the path to the data directory.'>
|
||||
<span>data directory</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Input
|
||||
value={this.state.config.dataDir}
|
||||
onChange={this.handleChange('dataDir')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Enter the path to the temp directory.'>
|
||||
<span>temp directory</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Input
|
||||
value={this.state.config.tempDir}
|
||||
onChange={this.handleChange('tempDir')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Enter the url of the toto object service instance.'>
|
||||
<span>server</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Input
|
||||
value={this.state.config.objectOptions.server}
|
||||
onChange={this.handleChange('server')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Enter the key of the toto object.'>
|
||||
<span>object key</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Input
|
||||
value={this.state.config.objectOptions.key}
|
||||
onChange={this.handleChange('key')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Enter the secret of the toto object.'>
|
||||
<span>object secret</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Input
|
||||
value={this.state.config.objectOptions.secret}
|
||||
onChange={this.handleChange('secret')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='How often should the object ask for new payloads.'>
|
||||
<span>polling interval</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<NumericInput
|
||||
style={{ width: 80 }}
|
||||
value={this.state.config.objectOptions.pollingInterval}
|
||||
onChange={this.handleChange('polling')} />
|
||||
</Form.Item>
|
||||
<FormItem {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='If it is saved on the object so it will automatically load when start the device up.'>
|
||||
<span>saved</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
{this.state.config.saved &&
|
||||
<Icon type="check" />
|
||||
}
|
||||
</FormItem>
|
||||
<hr />
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='custom printer processor properties'>
|
||||
<span>custom printer</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Margin top.'>
|
||||
<span>margin top</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<NumericInput
|
||||
style={{ width: 80 }}
|
||||
value={this.state.config.custom.printer.margins.top}
|
||||
onChange={this.handleChange('printermargintop')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Margin bottom.'>
|
||||
<span>margin bottom</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<NumericInput
|
||||
style={{ width: 80 }}
|
||||
value={this.state.config.custom.printer.margins.bottom}
|
||||
onChange={this.handleChange('printermarginbottom')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Margin left.'>
|
||||
<span>margin left</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<NumericInput
|
||||
style={{ width: 80 }}
|
||||
value={this.state.config.custom.printer.margins.left}
|
||||
onChange={this.handleChange('printermarginleft')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Margin right.'>
|
||||
<span>margin right</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<NumericInput
|
||||
style={{ width: 80 }}
|
||||
value={this.state.config.custom.printer.margins.right}
|
||||
onChange={this.handleChange('printermarginright')} />
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout}
|
||||
label={(
|
||||
<Tooltip title='Enter additional command line arguments.'>
|
||||
<span>additional cmd args</span>
|
||||
</Tooltip>
|
||||
)}>
|
||||
<Input
|
||||
value={this.state.config.custom.printer.additionalCmdArgs}
|
||||
onChange={this.handleChange('printerAdditionalCmdArgs')} />
|
||||
</Form.Item>
|
||||
<hr />
|
||||
<Form.Item {...tailFormItemLayout}>
|
||||
<Button
|
||||
style={{ width: 100 }}
|
||||
disabled={updateButtonDisabled}
|
||||
type="primary"
|
||||
onClick={this.updateConfig}>
|
||||
update
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginLeft: 20, width: 100 }}
|
||||
disabled={saveButtonDisabled}
|
||||
type="primary"
|
||||
onClick={this.saveConfig}>
|
||||
save
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<FormItem {...tailFormItemLayout}
|
||||
validateStatus="error"
|
||||
help={error.message}>
|
||||
</FormItem>
|
||||
</Form>
|
||||
}
|
||||
</Card>
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
AppConfig.propTypes = {
|
||||
loadConfig: PropTypes.func.isRequired,
|
||||
updateConfig: PropTypes.func.isRequired,
|
||||
saveConfig: PropTypes.func.isRequired,
|
||||
config: PropTypes.object
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
config: state.appData.config,
|
||||
configLoadError: state.appData.configLoadError
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { loadConfig, updateConfig, saveConfig })(AppConfig);
|
|
@ -1,10 +1,10 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
//import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { loadParams } from '../../actions/appActions';
|
||||
//import { loadParams } from '../../actions/appActions';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { withRouter } from "react-router";
|
||||
import { Layout, Menu } from 'antd';
|
||||
import { Layout } from 'antd';
|
||||
import 'antd/dist/antd.css';
|
||||
|
||||
const { Header } = Layout;
|
||||
|
@ -15,7 +15,7 @@ const styles = {
|
|||
color: 'white',
|
||||
fontSize: '1.4em',
|
||||
marginRight: 30,
|
||||
fontFamily: 'Super-FamiFont'
|
||||
fontFamily: 'Helvetica'
|
||||
},
|
||||
|
||||
logoImage: {
|
||||
|
@ -40,60 +40,25 @@ class AppHeader extends Component {
|
|||
|
||||
render() {
|
||||
|
||||
let selectedKeys = [];
|
||||
if (this.props.location.pathname === '/controls') selectedKeys = (['controls']);
|
||||
if (this.props.location.pathname === '/config') selectedKeys = (['config']);
|
||||
if (this.props.location.pathname === '/files') selectedKeys = (['files']);
|
||||
let menu;
|
||||
if (selectedKeys.length > 0) {
|
||||
menu =
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="horizontal"
|
||||
selectedKeys={selectedKeys}
|
||||
style={{ lineHeight: '64px' }}>
|
||||
<Menu.Item key="controls">
|
||||
<Link to="/controls">controls</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="config">
|
||||
<Link to="/config">config</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="files">
|
||||
<Link to="/files">files</Link>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
||||
let currentShow = this.props.params.find((param) => {
|
||||
return param.key === 'current show';
|
||||
});
|
||||
if (currentShow) {
|
||||
currentShow = currentShow.value;
|
||||
} else {
|
||||
currentShow = '';
|
||||
}
|
||||
|
||||
return (
|
||||
<Header style={{ position: 'fixed', zIndex: 1, width: '100%', background: '#3399cc' }}>
|
||||
<div style={styles.logo}>
|
||||
<img style={styles.logoImage} src='images/nwap_logo.png' alt='' onClick={this.reloadParams} />
|
||||
<Link style={styles.logo} to="/">Post Labour Index</Link>
|
||||
<span style={styles.hiddenShowId}>{currentShow}</span>
|
||||
<img style={styles.logoImage} src='images/logo.jpg' alt='' />
|
||||
<Link style={styles.logo} to="/">Quarantale</Link>
|
||||
</div>
|
||||
{menu}
|
||||
</Header>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
AppHeader.propTypes = {
|
||||
loadParams: PropTypes.func.isRequired,
|
||||
params: PropTypes.array
|
||||
// loadParams: PropTypes.func.isRequired,
|
||||
// params: PropTypes.array
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
params: state.appData.params,
|
||||
paramsLoadError: state.appData.paramsLoadError
|
||||
// params: state.appData.params,
|
||||
// paramsLoadError: state.appData.paramsLoadError
|
||||
});
|
||||
|
||||
export default withRouter(connect(mapStateToProps, { loadParams })(AppHeader));
|
||||
export default withRouter(connect(mapStateToProps, { })(AppHeader));
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
//import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { loadParams } from '../actions/appActions';
|
||||
//import { loadParams } from '../actions/appActions';
|
||||
import { BrowserRouter as Router, Route } from 'react-router-dom';
|
||||
import { ConfigPage, ControlsPage, FilesPage, ScoreboardPage } from '../pages';
|
||||
import { DashboardPage } from '../pages';
|
||||
import { Layout } from 'antd';
|
||||
import { AppHeader } from '../components';
|
||||
import 'antd/dist/antd.css';
|
||||
|
@ -13,7 +13,7 @@ const { Content } = Layout;
|
|||
class AppRouter extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.loadParams();
|
||||
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -24,10 +24,7 @@ class AppRouter extends Component {
|
|||
<AppHeader />
|
||||
<Content style={{ padding: '0 50px', marginTop: 64 }}>
|
||||
<div style={{ background: '#fff', padding: 24, minHeight: '100%' }}>
|
||||
<Route exact path='/' component={ScoreboardPage} />
|
||||
<Route exact path='/controls' component={ControlsPage} />
|
||||
<Route exact path='/config' component={ConfigPage} />
|
||||
<Route exact path='/files' component={FilesPage} />
|
||||
<Route exact path='/' component={DashboardPage} />
|
||||
</div>
|
||||
</Content>
|
||||
</Layout>
|
||||
|
@ -37,13 +34,9 @@ class AppRouter extends Component {
|
|||
};
|
||||
|
||||
AppRouter.propTypes = {
|
||||
loadParams: PropTypes.func.isRequired,
|
||||
params: PropTypes.array
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
params: state.appData.players,
|
||||
paramsLoadError: state.appData.paramsLoadError
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { loadParams })(AppRouter);
|
||||
export default connect(mapStateToProps, { })(AppRouter);
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { loadFiles, deleteFile } from '../../actions/appActions';
|
||||
import { Card, Table, Button, notification } from 'antd';
|
||||
|
||||
class FileList extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.loadFiles();
|
||||
};
|
||||
|
||||
openNotificationWithIcon = (type, title, description) => {
|
||||
notification[type]({
|
||||
message: title,
|
||||
description: description,
|
||||
});
|
||||
};
|
||||
|
||||
_deleteFile(record) {
|
||||
let _this = this;
|
||||
const scb = (data) => {
|
||||
_this.openNotificationWithIcon('success', 'File deleted', '');
|
||||
}
|
||||
const ecb = (error) => {
|
||||
_this.openNotificationWithIcon('error', 'Error deleting file', error.message);
|
||||
}
|
||||
this.props.deleteFile(record.name, scb, ecb);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
const _this = this;
|
||||
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
render: (text, record) => (
|
||||
<Button
|
||||
type='danger'
|
||||
size='small'
|
||||
onClick={() => _this._deleteFile(record)}>
|
||||
delete
|
||||
</Button>
|
||||
)
|
||||
}];
|
||||
|
||||
return (
|
||||
<Card title='files'>
|
||||
<Table dataSource={this.props.files} columns={columns} />
|
||||
</Card>
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
FileList.propTypes = {
|
||||
loadFiles: PropTypes.func.isRequired,
|
||||
deleteFile: PropTypes.func.isRequired,
|
||||
files: PropTypes.array
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
files: state.appData.files
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { loadFiles, deleteFile })(FileList);
|
|
@ -1,77 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { uploadFile, fileUploaded } from '../../actions/appActions';
|
||||
import { Button, Icon, Card, Upload, notification } from 'antd';
|
||||
|
||||
class FileUpload extends Component {
|
||||
|
||||
openNotificationWithIcon = (type, title, description) => {
|
||||
notification[type]({
|
||||
message: title,
|
||||
description: description,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
let _this = this;
|
||||
|
||||
const uploadProps = {
|
||||
action: '/api/files',
|
||||
multiple: false,
|
||||
headers: {},
|
||||
onStart(file) {
|
||||
},
|
||||
onSuccess(ret, file) {
|
||||
_this.openNotificationWithIcon('success', 'Upload successful', '');
|
||||
},
|
||||
onError(err) {
|
||||
_this.openNotificationWithIcon('error', 'Upload failed', err.message);
|
||||
},
|
||||
onProgress({ percent }, file) {
|
||||
console.log('onProgress', `${percent}%`, file.name);
|
||||
},
|
||||
customRequest({
|
||||
action,
|
||||
data,
|
||||
file,
|
||||
filename,
|
||||
headers,
|
||||
onError,
|
||||
onProgress,
|
||||
onSuccess,
|
||||
}) {
|
||||
const formData = new FormData();
|
||||
formData.append(filename, file);
|
||||
|
||||
_this.props.uploadFile(formData, onSuccess, onError);
|
||||
|
||||
return {
|
||||
abort() {
|
||||
console.log('upload progress is aborted.');
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Card title='file upload'>
|
||||
<Upload {...uploadProps}>
|
||||
<Button>
|
||||
<Icon type="upload" /> Click to Upload
|
||||
</Button>
|
||||
</Upload>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
FileUpload.propTypes = {
|
||||
uploadFile: PropTypes.func.isRequired,
|
||||
fileUploaded: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({});
|
||||
|
||||
export default connect(mapStateToProps, {uploadFile, fileUploaded })(FileUpload);
|
|
@ -1,42 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Input } from 'antd';
|
||||
|
||||
class NumericInput extends Component {
|
||||
|
||||
formatNumber = (value) => {
|
||||
value += '';
|
||||
const list = value.split('.');
|
||||
const prefix = list[0].charAt(0) === '-' ? '-' : '';
|
||||
let num = prefix ? list[0].slice(1) : list[0];
|
||||
let result = '';
|
||||
while (num.length > 3) {
|
||||
result = `,${num.slice(-3)}${result}`;
|
||||
num = num.slice(0, num.length - 3);
|
||||
}
|
||||
if (num) {
|
||||
result = num + result;
|
||||
}
|
||||
return `${prefix}${result}${list[1] ? `.${list[1]}` : ''}`;
|
||||
}
|
||||
|
||||
onChange = (e) => {
|
||||
const { value } = e.target;
|
||||
const reg = /^-?(0|[1-9][0-9]*)(\.[0-9]*)?$/;
|
||||
if ((!Number.isNaN(value) && reg.test(value)) || value === '' || value === '-') {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Input
|
||||
{...this.props}
|
||||
onChange={this.onChange}
|
||||
placeholder="Input a number"
|
||||
maxLength={25}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default NumericInput;
|
|
@ -1,166 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from "react-router";
|
||||
import { loadPlayers, loadParams } from '../../actions/appActions';
|
||||
import { Avatar } from 'antd';
|
||||
|
||||
const styles = {
|
||||
rowGrundig: {
|
||||
backgroundColor: '#333',
|
||||
color: '#eee',
|
||||
border: '1px solid lightgrey'
|
||||
},
|
||||
rowNormal: {
|
||||
backgroundColor: 'white',
|
||||
color: '#111',
|
||||
border: '1px solid lightgrey'
|
||||
},
|
||||
tbl: {
|
||||
border: '1px solid lightgrey',
|
||||
cellPadding: '4',
|
||||
cellSpacing: '4'
|
||||
},
|
||||
hiddenText: {
|
||||
color: 'white'
|
||||
},
|
||||
textGrundig: {
|
||||
fontSize: '1.8em',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
};
|
||||
|
||||
class PostLabourIndex extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
players: [],
|
||||
playersLoadError: false,
|
||||
params: []
|
||||
};
|
||||
this.loadPlayerInterval = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadPlayerInterval = setInterval(
|
||||
() => this.loadPlayers(),
|
||||
3000
|
||||
);
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.loadPlayerInterval);
|
||||
};
|
||||
|
||||
loadPlayers = () => {
|
||||
let currentShow = this.props.params.find((param) => {
|
||||
return param.key === 'current show';
|
||||
});
|
||||
if (currentShow) {
|
||||
this.props.loadPlayers(currentShow.value);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
const tableHeight = window.innerHeight - 150;
|
||||
const tableContentStyle = {
|
||||
tblContent: {
|
||||
overflow: 'scroll',
|
||||
height: tableHeight
|
||||
}
|
||||
}
|
||||
|
||||
let orderedPlayers = this.props.players.sort(function (a, b) {
|
||||
return b.values.score - a.values.score;
|
||||
});
|
||||
|
||||
for (var i = 0; i < orderedPlayers.length; i++) {
|
||||
orderedPlayers[i].standing = i + 1;
|
||||
}
|
||||
|
||||
const rows = orderedPlayers.map((player) => {
|
||||
const standing = <td>{player.standing}</td>
|
||||
const avatar = <td><Avatar size={64} src={'https://platform.thegameisover.de/v2/account/' + player.playerId + '/avatar?v=s'} /></td>
|
||||
const name = <td>{player.name}</td>
|
||||
if (player.group === 'grundig') {
|
||||
return (
|
||||
<tr style={styles.rowGrundig} key={player.standing}>
|
||||
{standing}
|
||||
{avatar}
|
||||
{name}
|
||||
<td colSpan="6" align='center'><span style={styles.textGrundig}>G.R.UN.DIG.</span></td>
|
||||
</tr>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<tr style={styles.rowNormal} key={player.standing}>
|
||||
{standing}
|
||||
{avatar}
|
||||
{name}
|
||||
<td>{player.cluster}</td>
|
||||
<td style={styles.hiddenText}>{player.values.lust}</td>
|
||||
<td>{player.values.power}</td>
|
||||
<td>{player.values.psyche}</td>
|
||||
<td>{player.values.structure}</td>
|
||||
<td><span style={{ fontWeight: 'bold', fontSize: '1.2em' }}>{player.values.score}</span></td>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<table width='100%' cellPadding='5' border='0' style={styles.tbl}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50px"></th>
|
||||
<th width="100px">Avatar</th>
|
||||
<th width="25%">Name</th>
|
||||
<th width="25%">Berufsfeld</th>
|
||||
<th width="50px"></th>
|
||||
<th width="100px">Macht</th>
|
||||
<th width="100px">Psyche</th>
|
||||
<th width="100px">Struktur</th>
|
||||
<th width="150px">Post Labour Score</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div style={tableContentStyle.tblContent}>
|
||||
<table width='100%' border='0' cellPadding='5' style={styles.tbl}>
|
||||
<tbody>
|
||||
{rows}
|
||||
<tr style={{ color: 'white' }}>
|
||||
<td width="50px"></td>
|
||||
<td width="100px"> </td>
|
||||
<td width="25%"> </td>
|
||||
<td width="25%">num player: {orderedPlayers.length}</td>
|
||||
<td width="50px"> </td>
|
||||
<td width="100px"> </td>
|
||||
<td width="100px"> </td>
|
||||
<td width="100px"> </td>
|
||||
<td width="150px"> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
PostLabourIndex.propTypes = {
|
||||
loadPlayers: PropTypes.func.isRequired,
|
||||
players: PropTypes.array,
|
||||
loadParams: PropTypes.func.isRequired,
|
||||
params: PropTypes.array
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
players: state.appData.players,
|
||||
playersLoadError: state.appData.playersLoadError,
|
||||
params: state.appData.params
|
||||
});
|
||||
|
||||
export default withRouter(connect(mapStateToProps, { loadPlayers, loadParams })(PostLabourIndex));
|
25
client/src/components/QuestionList/QuestionList.js
Normal file
25
client/src/components/QuestionList/QuestionList.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { loadQuestions } from '../../actions/appActions';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
class QuestionList extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<h1>Questions</h1>
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
QuestionList.propTypes = {
|
||||
loadQuestions: PropTypes.func.isRequired,
|
||||
questions: PropTypes.array,
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
questions: state.appData.questions,
|
||||
questionsLoadError: state.appData.questionsLoadError
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { loadQuestions })(QuestionList);
|
|
@ -1,126 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { loadPlayers, loadParams } from '../../actions/appActions';
|
||||
import { Avatar, Table } from 'antd';
|
||||
|
||||
class Scoreboard extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
players: [],
|
||||
playersLoadError: false,
|
||||
params: []
|
||||
};
|
||||
this.loadPlayerInterval = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadPlayerInterval = setInterval(
|
||||
() => this.loadPlayers(),
|
||||
3000
|
||||
);
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.loadPlayerInterval);
|
||||
};
|
||||
|
||||
loadPlayers = () => {
|
||||
let currentShow = this.props.params.find((param) => {
|
||||
return param.key === 'current show';
|
||||
});
|
||||
if (currentShow) {
|
||||
this.props.loadPlayers(currentShow.value);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
let orderedPlayers = this.props.players.sort(function (a, b) {
|
||||
return b.values.score - a.values.score;
|
||||
});
|
||||
|
||||
for (var i = 0; i < orderedPlayers.length; i++) {
|
||||
orderedPlayers[i].standing = i + 1;
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'standing',
|
||||
key: 'standing',
|
||||
width: 50
|
||||
}, {
|
||||
title: 'Avatar',
|
||||
dataIndex: 'playerId',
|
||||
key: 'playerId',
|
||||
width: 100,
|
||||
render: (playerId) => (
|
||||
<Avatar size={64} src={'https://platform.thegameisover.de/v2/account/' + playerId + '/avatar?v=s'} />
|
||||
)
|
||||
}, {
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
style: 'tableHeader'
|
||||
}, {
|
||||
title: 'Berufsfeld',
|
||||
dataIndex: 'cluster',
|
||||
key: 'cluster'
|
||||
}, {
|
||||
title: 'Macht',
|
||||
dataIndex: 'values.power',
|
||||
key: 'macht',
|
||||
width: 100
|
||||
}, {
|
||||
title: 'Psyche',
|
||||
dataIndex: 'values.psyche',
|
||||
key: 'psyche',
|
||||
width: 100
|
||||
}, {
|
||||
title: 'Struktur',
|
||||
dataIndex: 'values.structure',
|
||||
key: 'structure',
|
||||
width: 100
|
||||
}, {
|
||||
title: 'Post Labour Score',
|
||||
dataIndex: 'values.score',
|
||||
key: 'score',
|
||||
width: 200,
|
||||
render: (score) => (
|
||||
<span style={{ fontWeight: 'bold', fontSize: '1.2em' }}>{score}</span>
|
||||
)
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={orderedPlayers}
|
||||
pagination={false}
|
||||
rowKey='id'
|
||||
size="small"
|
||||
bordered
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Scoreboard.propTypes = {
|
||||
loadPlayers: PropTypes.func.isRequired,
|
||||
players: PropTypes.array,
|
||||
loadParams: PropTypes.func.isRequired,
|
||||
params: PropTypes.array
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
players: state.appData.players,
|
||||
playersLoadError: state.appData.playersLoadError,
|
||||
params: state.appData.params
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { loadPlayers, loadParams })(Scoreboard);
|
|
@ -1,101 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { Card, Button, notification } from 'antd';
|
||||
import { startObject, pauseObject, stopObject, getObjectConfig } from '../../actions/appActions';
|
||||
|
||||
class TotoObjectControls extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.getObjectConfig();
|
||||
}
|
||||
|
||||
openNotificationWithIcon = (type, title, description) => {
|
||||
notification[type]({
|
||||
message: title,
|
||||
description: description,
|
||||
});
|
||||
};
|
||||
|
||||
_startObject = () => {
|
||||
const scb = (data) => {
|
||||
this.openNotificationWithIcon('success', 'object started', '');
|
||||
}
|
||||
const ecb = (error) => {
|
||||
this.openNotificationWithIcon('error', 'error starting object', error.message);
|
||||
}
|
||||
this.props.startObject(scb, ecb);
|
||||
}
|
||||
|
||||
_pauseObject = () => {
|
||||
const scb = (data) => {
|
||||
this.openNotificationWithIcon('success', 'object paused', '');
|
||||
}
|
||||
const ecb = (error) => {
|
||||
this.openNotificationWithIcon('error', 'error pausing object', error.message);
|
||||
}
|
||||
this.props.pauseObject(scb, ecb);
|
||||
}
|
||||
|
||||
_stopObject = () => {
|
||||
const scb = (data) => {
|
||||
this.openNotificationWithIcon('success', 'object stopped', '');
|
||||
}
|
||||
const ecb = (error) => {
|
||||
this.openNotificationWithIcon('error', 'error stopping object', error.message);
|
||||
}
|
||||
this.props.stopObject(scb, ecb);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const startObjectDisabled = this.props.status === 'running';
|
||||
const pauseObjectDisabled = this.props.status === 'paused' || this.props.status === 'stopped';
|
||||
const stopObjectDisabled = this.props.status === 'stopped';
|
||||
|
||||
return (
|
||||
<Card title="toto-object controlls">
|
||||
<div style={{marginBottom: 30}}>
|
||||
<h4>status: {this.props.status}</h4>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
style={{ width: 120 }}
|
||||
onClick={this._startObject}
|
||||
type='primary'
|
||||
disabled={startObjectDisabled}>
|
||||
start
|
||||
</Button>
|
||||
<Button
|
||||
style={{ width: 120, marginLeft: 20 }}
|
||||
onClick={this._pauseObject}
|
||||
type='primary'
|
||||
disabled={pauseObjectDisabled}>
|
||||
pause
|
||||
</Button>
|
||||
<Button
|
||||
style={{ width: 120, marginLeft: 20 }}
|
||||
onClick={this._stopObject}
|
||||
type='primary'
|
||||
disabled={stopObjectDisabled}>
|
||||
stop
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TotoObjectControls.propTypes = {
|
||||
getObjectConfig: PropTypes.func.isRequired,
|
||||
startObject: PropTypes.func.isRequired,
|
||||
pauseObject: PropTypes.func.isRequired,
|
||||
stopObject: PropTypes.func.isRequired,
|
||||
status: PropTypes.string
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
status: state.appData.status
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { startObject, pauseObject, stopObject, getObjectConfig })(TotoObjectControls);
|
|
@ -1,19 +1,7 @@
|
|||
import AppConfig from './AppConfig/AppConfig';
|
||||
import AppHeader from './AppHeader/AppHeader';
|
||||
import FileList from './FileList/FileList';
|
||||
import FileUpload from './FileUpload/FileUpload';
|
||||
import NumericInput from './NumericInput/NumericInput';
|
||||
import PostLabourIndex from './PostLabourIndex/PostLabourIndex';
|
||||
import Scoreboard from './Scoreboard/Scoreboard';
|
||||
import TotoObjectControls from './TotoObjectControls/TotoObjectControls';
|
||||
import QuestionList from './QuestionList/QuestionList';
|
||||
|
||||
export {
|
||||
AppConfig,
|
||||
AppHeader,
|
||||
FileList,
|
||||
FileUpload,
|
||||
NumericInput,
|
||||
PostLabourIndex,
|
||||
Scoreboard,
|
||||
TotoObjectControls
|
||||
QuestionList
|
||||
};
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { AppConfig } from '../../components';
|
||||
|
||||
class ConfigPage extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<AppConfig />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ConfigPage;
|
|
@ -1,15 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { TotoObjectControls } from '../../components';
|
||||
|
||||
class ControlsPage extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<TotoObjectControls />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ControlsPage;
|
15
client/src/pages/DashboardPage/DashboardPage.js
Normal file
15
client/src/pages/DashboardPage/DashboardPage.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import React, { Component } from 'react';
|
||||
//import { QuestionList } from '../../components/QuestionList';
|
||||
|
||||
class DashboardPage extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
QuestionList
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default DashboardPage;
|
|
@ -1,17 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { FileList, FileUpload } from '../../components';
|
||||
|
||||
class FilesPage extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<FileUpload />
|
||||
<br/>
|
||||
<FileList />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default FilesPage;
|
|
@ -1,16 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { PostLabourIndex } from '../../components';
|
||||
|
||||
class ScoreboardPage extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PostLabourIndex />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ScoreboardPage;
|
|
@ -1,11 +1,5 @@
|
|||
import ConfigPage from './ConfigPage/ConfigPage';
|
||||
import ControlsPage from './ControlsPage/ControlsPage';
|
||||
import FilesPage from './FilesPage/FilesPage';
|
||||
import ScoreboardPage from './ScoreboardPage/ScoreboardPage';
|
||||
import DashboardPage from './DashboardPage/DashboardPage';
|
||||
|
||||
export {
|
||||
ConfigPage,
|
||||
ControlsPage,
|
||||
FilesPage,
|
||||
ScoreboardPage
|
||||
DashboardPage
|
||||
};
|
||||
|
|
|
@ -1,134 +1,25 @@
|
|||
import {
|
||||
CONFIG_LOADED,
|
||||
CONFIG_LOAD_ERROR,
|
||||
CONFIG_UPDATED,
|
||||
CONFIG_SAVED,
|
||||
OBJECT_STARTED,
|
||||
OBJECT_PAUSED,
|
||||
OBJECT_STOPPED,
|
||||
OBJECT_STATUS_LOADED,
|
||||
FILE_UPLOADED,
|
||||
FILES_LOADED,
|
||||
FILE_DELETED,
|
||||
PARAMS_LOADED,
|
||||
PARAMS_LOAD_ERROR,
|
||||
PLAYERS_LOADED,
|
||||
PLAYERS_LOAD_ERROR
|
||||
QUESTIONS_LOADED,
|
||||
QUESTIONS_LOAD_ERROR
|
||||
} from '../actions/types';
|
||||
|
||||
const initialState = {
|
||||
config: undefined,
|
||||
params: [],
|
||||
files: [],
|
||||
players: []
|
||||
questions: []
|
||||
};
|
||||
|
||||
export default function (state = initialState, action) {
|
||||
|
||||
switch (action.type) {
|
||||
case CONFIG_LOADED: {
|
||||
case QUESTIONS_LOADED: {
|
||||
return {
|
||||
...state,
|
||||
config: action.config
|
||||
questions: action.data
|
||||
}
|
||||
}
|
||||
case CONFIG_UPDATED: {
|
||||
case QUESTIONS_LOAD_ERROR: {
|
||||
return {
|
||||
...state,
|
||||
config: action.config
|
||||
}
|
||||
}
|
||||
case CONFIG_SAVED: {
|
||||
return {
|
||||
...state,
|
||||
config: action.config
|
||||
}
|
||||
}
|
||||
case CONFIG_LOAD_ERROR: {
|
||||
return {
|
||||
...state,
|
||||
configLoadError: action.error
|
||||
}
|
||||
}
|
||||
case OBJECT_STARTED: {
|
||||
return {
|
||||
...state,
|
||||
status: action.status
|
||||
}
|
||||
}
|
||||
case OBJECT_PAUSED: {
|
||||
return {
|
||||
...state,
|
||||
status: action.status
|
||||
}
|
||||
}
|
||||
case OBJECT_STOPPED: {
|
||||
return {
|
||||
...state,
|
||||
status: action.status
|
||||
}
|
||||
}
|
||||
case OBJECT_STATUS_LOADED: {
|
||||
return {
|
||||
...state,
|
||||
status: action.status
|
||||
};
|
||||
}
|
||||
case FILE_UPLOADED: {
|
||||
let files = JSON.parse(JSON.stringify(state.files));
|
||||
files.push({
|
||||
key: action.file.name,
|
||||
name: action.file.name
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
files: files
|
||||
};
|
||||
}
|
||||
case FILES_LOADED: {
|
||||
let files = action.files.map((file) => {
|
||||
return {
|
||||
key: file.name,
|
||||
name: file.name
|
||||
}
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
files: files
|
||||
};
|
||||
}
|
||||
case FILE_DELETED: {
|
||||
let files = state.files.filter((file) => {
|
||||
return file.name !== action.fileName
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
files: files
|
||||
};
|
||||
}
|
||||
case PLAYERS_LOADED: {
|
||||
return {
|
||||
...state,
|
||||
players: action.players
|
||||
};
|
||||
}
|
||||
case PLAYERS_LOAD_ERROR: {
|
||||
return {
|
||||
...state,
|
||||
players: [],
|
||||
playersLoadError: action.error
|
||||
};
|
||||
}
|
||||
case PARAMS_LOADED: {
|
||||
return {
|
||||
...state,
|
||||
params: action.params
|
||||
};
|
||||
}
|
||||
case PARAMS_LOAD_ERROR: {
|
||||
return {
|
||||
...state,
|
||||
paramsLoadError: action.error
|
||||
questionsLoadError: action.error
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -1,65 +1,9 @@
|
|||
class ApiService {
|
||||
|
||||
getConfig(onSuccess, onError) {
|
||||
this._get('/api/config', onSuccess, onError);
|
||||
getQuestions(userId, onSuccess, onError) {
|
||||
this._get('/api/questions' + userId, onSuccess, onError);
|
||||
};
|
||||
|
||||
udpateConfig(requestData, onSuccess, onError) {
|
||||
this._put('/api/config/update', requestData, onSuccess, onError);
|
||||
};
|
||||
|
||||
saveConfig(onSuccess, onError) {
|
||||
this._post('/api/config/save', {}, onSuccess, onError);
|
||||
};
|
||||
|
||||
startObject(onSuccess, onError) {
|
||||
this._post('/api/obj/start', {}, onSuccess, onError);
|
||||
};
|
||||
|
||||
pauseObject(onSuccess, onError) {
|
||||
this._post('/api/obj/pause', {}, onSuccess, onError);
|
||||
};
|
||||
|
||||
stopObject(onSuccess, onError) {
|
||||
this._post('/api/obj/stop', {}, onSuccess, onError);
|
||||
};
|
||||
|
||||
getObjectStatus(onSuccess, onError) {
|
||||
this._get('/api/obj/status', onSuccess, onError);
|
||||
};
|
||||
|
||||
getFiles(onSuccess, onError) {
|
||||
this._get('/api/files', onSuccess, onError);
|
||||
};
|
||||
|
||||
getParams(onSuccess, onError) {
|
||||
this._get('/api/nwap/params', onSuccess, onError);
|
||||
};
|
||||
|
||||
getPlayers(showId, onSuccess, onError) {
|
||||
this._get('/api/nwap/show/' + showId, onSuccess, onError);
|
||||
};
|
||||
|
||||
uploadFile(formData, onSuccess, onError) {
|
||||
fetch('/api/files', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(this._handleResponse(onSuccess, onError))
|
||||
.catch((error) => {
|
||||
onError({ error: error.message });
|
||||
});
|
||||
};
|
||||
|
||||
deleteFile(name, onSuccess, onError) {
|
||||
const url = '/api/files/' + name;
|
||||
fetch(url, { method: 'DELETE' })
|
||||
.then(this._handleResponse(onSuccess, onError))
|
||||
.catch((error) => {
|
||||
onError({ error: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
_get(url, onSuccess, onError) {
|
||||
fetch(url)
|
||||
.then(this._handleResponse(onSuccess, onError))
|
||||
|
|
Loading…
Reference in a new issue