Sync tool status across all clients
This commit is contained in:
@@ -4,29 +4,62 @@ import Category from './Category';
|
||||
import Tool from './Tool';
|
||||
import { Container, Dimmer, Dropdown, Header, Icon, Item, Loader, Menu, Segment, Input } from 'semantic-ui-react';
|
||||
import { Link, Route } from 'react-router-dom';
|
||||
import io from 'socket.io-client';
|
||||
|
||||
// Move to env var
|
||||
const SERVER_URL = "http://localhost:8080";
|
||||
|
||||
class App extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.socket = io(SERVER_URL);
|
||||
|
||||
this.state = {
|
||||
user: null,
|
||||
toolData: null,
|
||||
toolStatus: null,
|
||||
connected: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
fetch('http://localhost:8080/api/tooldata')
|
||||
fetch(SERVER_URL + '/api/tooldata')
|
||||
.then(response => response.json())
|
||||
.then(data => this.setState({ toolData: data }));
|
||||
fetch('http://localhost:8080/api/user')
|
||||
fetch(SERVER_URL + '/api/user')
|
||||
.then(response => response.json())
|
||||
.then(data => this.setState({ user: data }));
|
||||
|
||||
this.socket.on('toolStatus', toolStatus =>
|
||||
this.setState({ toolStatus: toolStatus })
|
||||
);
|
||||
|
||||
this.socket.on('connect', toolStatus =>
|
||||
this.setState({ connected: true })
|
||||
);
|
||||
|
||||
this.socket.on('disconnect', toolStatus =>
|
||||
this.setState({ toolStatus: null, connected: false })
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.socket.removeAllListeners();
|
||||
}
|
||||
|
||||
requestInterlock = change => {
|
||||
this.socket.emit('requestInterlock', {
|
||||
username: this.state.user.username,
|
||||
change: change,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const toolData = this.state.toolData;
|
||||
const toolStatus = this.state.toolStatus;
|
||||
const user = this.state.user;
|
||||
const connected = this.state.connected;
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -37,6 +70,9 @@ class App extends Component {
|
||||
<Menu.Item as={Link} to='/'>
|
||||
<Icon name='home' size='big' />
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<Icon name='circle' color={connected ? 'green' : 'red'} />
|
||||
</Menu.Item>
|
||||
<Menu.Menu position='right'>
|
||||
<Menu.Item position='right'>
|
||||
<Input transparent inverted placeholder='Search...' icon='search' />
|
||||
@@ -49,7 +85,7 @@ class App extends Component {
|
||||
{toolData && user ?
|
||||
<div>
|
||||
<Route exact path='/' render={props =>
|
||||
<Categories {...props} data={toolData} user={user} />
|
||||
<Categories {...props} data={toolData} />
|
||||
} />
|
||||
|
||||
<Route exact path='/:category' render={props =>
|
||||
@@ -57,7 +93,12 @@ class App extends Component {
|
||||
} />
|
||||
|
||||
<Route exact path='/:category/:id' render={props =>
|
||||
<Tool {...props} data={toolData} user={user} />
|
||||
<Tool {...props}
|
||||
data={toolData}
|
||||
user={user}
|
||||
toolStatus={toolStatus}
|
||||
requestInterlock={this.requestInterlock}
|
||||
/>
|
||||
} />
|
||||
</div>
|
||||
:
|
||||
|
@@ -8,7 +8,7 @@ class Category extends Component {
|
||||
const user = this.props.user;
|
||||
const match = this.props.match;
|
||||
|
||||
const category = data.categories.find((x) =>
|
||||
const category = data.categories.find(x =>
|
||||
x.slug === match.params.category
|
||||
);
|
||||
|
||||
|
@@ -3,19 +3,41 @@ import { Breadcrumb, Button, Container, Dropdown, Header, Icon, Image, Item, Lab
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
class Tool extends Component {
|
||||
decodeStatus = status => {
|
||||
if (status === null) {
|
||||
return { msg: 'Unknown! Connection error?', canArm: false, canDisarm: false, };
|
||||
} else if (!status.armed && !status.on) {
|
||||
return { msg: 'Off', canArm: true, canDisarm: false, };
|
||||
} else if (status.armed && !status.on) {
|
||||
return { msg: 'Armed', canArm: false, canDisarm: true, };
|
||||
} else if (status.armed && status.on) {
|
||||
return { msg: 'On', canArm: false, canDisarm: true, };
|
||||
} else if (!status.armed && status.on) {
|
||||
return { msg: 'Error: Impossible state!', canArm: false, canDisarm: false, };
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = this.props.data;
|
||||
const user = this.props.user;
|
||||
const match = this.props.match;
|
||||
const toolStatus = this.props.toolStatus || [];
|
||||
const requestInterlock = this.props.requestInterlock;
|
||||
|
||||
const category = data.categories.find((x) =>
|
||||
const category = data.categories.find(x =>
|
||||
x.slug === match.params.category
|
||||
);
|
||||
|
||||
const tool = category.tools.find((x) =>
|
||||
const tool = category.tools.find(x =>
|
||||
x.id.toString() === match.params.id
|
||||
);
|
||||
|
||||
const status = toolStatus.find(x =>
|
||||
x.id.toString() === match.params.id
|
||||
) || null;
|
||||
const decodedStatus = this.decodeStatus(status);
|
||||
console.log(decodedStatus);
|
||||
|
||||
const approved = user.authorizedTools.includes(tool.id);
|
||||
|
||||
return (
|
||||
@@ -32,12 +54,18 @@ class Tool extends Component {
|
||||
<Segment>
|
||||
<Image src={tool.photo} size='medium' centered rounded />
|
||||
<Segment textAlign='center' basic>
|
||||
<p>Status: Off</p>
|
||||
<p> Status: {decodedStatus.msg}</p>
|
||||
<div>
|
||||
<Button color='green' disabled={!approved}>
|
||||
<Icon name='lightning' /> Arm
|
||||
<Button color='green'
|
||||
disabled={!approved || !decodedStatus.canArm}
|
||||
onClick={() => requestInterlock({toolId: tool.id, action: 'arm',})}
|
||||
>
|
||||
<Icon name='lightning' /> Arm
|
||||
</Button>
|
||||
<Button color='red' disabled={!approved}>
|
||||
<Button color='red'
|
||||
disabled={!approved || !decodedStatus.canDisarm}
|
||||
onClick={() => requestInterlock({toolId: tool.id, action: 'disarm',})}
|
||||
>
|
||||
<Icon name='stop' /> Disarm
|
||||
</Button>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user