import React from 'react'; import { withSnackbar } from 'notistack'; import { redirectingAuthorizedFetch } from '../authentication/Authentication'; /* * It is unlikely this application will grow complex enough to require redux. * * This HOC acts as an interface to a REST service, providing data and change * event callbacks to the wrapped components along with a function to persist the * changes. */ export const restComponent = (endpointUrl, FormComponent) => { return withSnackbar( class extends React.Component { constructor(props) { super(props); this.state = { data: null, fetched: false, errorMessage: null }; this.setState = this.setState.bind(this); this.loadData = this.loadData.bind(this); this.saveData = this.saveData.bind(this); this.setData = this.setData.bind(this); } setData(data) { this.setState({ data: data, fetched: true, errorMessage: null }); } loadData() { this.setState({ data: null, fetched: false, errorMessage: null }); redirectingAuthorizedFetch(endpointUrl) .then(response => { if (response.status === 200) { return response.json(); } throw Error("Invalid status code: " + response.status); }) .then(json => { this.setState({ data: json, fetched: true }) }) .catch(error => { const errorMessage = error.message || "Unknown error"; this.props.enqueueSnackbar("Problem fetching: " + errorMessage, { variant: 'error', }); this.setState({ data: null, fetched: true, errorMessage }); }); } saveData(e) { this.setState({ fetched: false }); redirectingAuthorizedFetch(endpointUrl, { method: 'POST', body: JSON.stringify(this.state.data), headers: { 'Content-Type': 'application/json' } }) .then(response => { if (response.status === 200) { return response.json(); } throw Error("Invalid status code: " + response.status); }) .then(json => { this.props.enqueueSnackbar("Changes successfully applied.", { variant: 'success', }); this.setState({ data: json, fetched: true }); }).catch(error => { const errorMessage = error.message || "Unknown error"; this.props.enqueueSnackbar("Problem saving: " + errorMessage, { variant: 'error', }); this.setState({ data: null, fetched: true, errorMessage }); }); } handleValueChange = name => (event) => { const { data } = this.state; data[name] = event.target.value; this.setState({ data }); }; handleSliderChange = name => (event, newValue) => { const { data } = this.state; data[name] = newValue; this.setState({ data }); }; handleCheckboxChange = name => event => { const { data } = this.state; data[name] = event.target.checked; this.setState({ data }); } render() { return ; } } ); }