import React from 'react'; import { withSnackbar, WithSnackbarProps } from 'notistack'; import { redirectingAuthorizedFetch } from '../authentication'; export interface RestControllerProps extends WithSnackbarProps { handleValueChange: (name: keyof D) => (event: React.ChangeEvent) => void; setData: (data: D, callback?: () => void) => void; saveData: () => void; loadData: () => void; data?: D; loading: boolean; errorMessage?: string; } export const extractEventValue = (event: React.ChangeEvent) => { switch (event.target.type) { case "number": return event.target.valueAsNumber; case "checkbox": return event.target.checked; default: return event.target.value } } interface RestControllerState { data?: D; loading: boolean; errorMessage?: string; } export function restController>(endpointUrl: string, RestController: React.ComponentType

>) { return withSnackbar( class extends React.Component> & WithSnackbarProps, RestControllerState> { state: RestControllerState = { data: undefined, loading: false, errorMessage: undefined }; setData = (data: D, callback?: () => void) => { this.setState({ data, loading: false, errorMessage: undefined }, callback); } loadData = () => { this.setState({ data: undefined, loading: true, errorMessage: undefined }); redirectingAuthorizedFetch(endpointUrl).then(response => { if (response.status === 200) { return response.json(); } throw Error("Invalid status code: " + response.status); }).then(json => { this.setState({ data: json, loading: false }) }).catch(error => { const errorMessage = error.message || "Unknown error"; this.props.enqueueSnackbar("Problem fetching: " + errorMessage, { variant: 'error' }); this.setState({ data: undefined, loading: false, errorMessage }); }); } saveData = () => { this.setState({ loading: true }); 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, loading: false }); }).catch(error => { const errorMessage = error.message || "Unknown error"; this.props.enqueueSnackbar("Problem saving: " + errorMessage, { variant: 'error' }); this.setState({ data: undefined, loading: false, errorMessage }); }); } handleValueChange = (name: keyof D) => (event: React.ChangeEvent) => { const data = { ...this.state.data!, [name]: extractEventValue(event) }; this.setState({ data }); } render() { return ; } }); }