add RootDialog and Network contexts, update app bootstrapping

This commit is contained in:
John Mitchell
2019-04-08 12:19:13 -04:00
parent e20cf72dd6
commit aea4a04c66
7 changed files with 544 additions and 315 deletions

89
src/contexts/Config.jsx Normal file
View File

@@ -0,0 +1,89 @@
import React, { Component } from 'react';
import { withNetwork } from './Network';
const ConfigContext = React.createContext({});
class provider extends Component {
constructor (props) {
super(props);
this.state = {
value: {
ansible_version: null,
custom_virtualenvs: null,
version: null,
custom_logo: null,
custom_login_info: null
}
};
this.fetchConfig = this.fetchConfig.bind(this);
}
componentDidMount () {
this.fetchConfig();
}
async fetchConfig () {
const { api, handleHttpError } = this.props;
try {
const {
data: {
ansible_version,
custom_virtualenvs,
version
}
} = await api.getConfig();
const {
data: {
custom_logo,
custom_login_info
}
} = await api.getRoot();
this.setState({
value: {
ansible_version,
custom_virtualenvs,
version,
custom_logo,
custom_login_info
}
});
} catch (err) {
handleHttpError(err) || this.setState({
value: {
ansible_version: null,
custom_virtualenvs: null,
version: null,
custom_logo: null,
custom_login_info: null
}
});
}
}
render () {
const {
value
} = this.state;
const { children } = this.props;
return (
<ConfigContext.Provider value={value}>
{children}
</ConfigContext.Provider>
);
}
}
export const ConfigProvider = withNetwork(provider);
export const Config = ({ children }) => (
<ConfigContext.Consumer>
{value => children(value)}
</ConfigContext.Consumer>
);

84
src/contexts/Network.jsx Normal file
View File

@@ -0,0 +1,84 @@
import axios from 'axios';
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import { withRootDialog } from './RootDialog';
import APIClient from '../api';
const NetworkContext = React.createContext({});
class prov extends Component {
constructor (props) {
super(props);
this.state = {
value: {
api: new APIClient(axios.create({ xsrfCookieName: 'csrftoken', xsrfHeaderName: 'X-CSRFToken' })),
handleHttpError: err => {
if (err.response.status === 401) {
this.handle401();
} else if (err.response.status === 404) {
this.handle404();
}
return (err.response.status === 401 || err.response.status === 404);
}
}
};
}
handle401 () {
const { handle401, history, setRootDialogMessage } = this.props;
if (handle401) {
handle401();
return;
}
history.replace('/login');
setRootDialogMessage({
bodyText: 'You have been logged out.',
});
}
handle404 () {
const { handle404, history, setRootDialogMessage } = this.props;
if (handle404) {
handle404();
return;
}
history.replace('/home');
setRootDialogMessage({
title: '404',
bodyText: 'Cannot find resource.',
variant: 'warning'
});
}
render () {
const {
children
} = this.props;
const {
value
} = this.state;
return (
<NetworkContext.Provider value={value}>
{children}
</NetworkContext.Provider>
);
}
}
export const NetworkProvider = withRootDialog(withRouter(prov));
export function withNetwork (Child) {
return (props) => (
<NetworkContext.Consumer>
{context => <Child {...props} {...context} />}
</NetworkContext.Consumer>
);
}

View File

@@ -0,0 +1,53 @@
import React, { Component } from 'react';
const RootDialogContext = React.createContext({});
export class RootDialogProvider extends Component {
constructor (props) {
super(props);
this.state = {
value: {
title: null,
setRootDialogMessage: ({ title, bodyText, variant }) => {
const { value } = this.state;
this.setState({ value: { ...value, title, bodyText, variant } });
},
clearRootDialogMessage: () => {
const { value } = this.state;
this.setState({ value: { ...value, title: null, bodyText: null, variant: null } });
}
}
};
}
render () {
const {
children
} = this.props;
const {
value
} = this.state;
return (
<RootDialogContext.Provider value={value}>
{children}
</RootDialogContext.Provider>
);
}
}
export const RootDialog = ({ children }) => (
<RootDialogContext.Consumer>
{value => children(value)}
</RootDialogContext.Consumer>
);
export function withRootDialog (Child) {
return (props) => (
<RootDialogContext.Consumer>
{context => <Child {...props} {...context} />}
</RootDialogContext.Consumer>
);
}