mirror of
https://github.com/ansible/awx.git
synced 2026-03-05 02:31:03 -03:30
add RootDialog and Network contexts, update app bootstrapping
This commit is contained in:
165
src/App.jsx
165
src/App.jsx
@@ -6,13 +6,20 @@ import {
|
|||||||
Page,
|
Page,
|
||||||
PageHeader,
|
PageHeader,
|
||||||
PageSidebar,
|
PageSidebar,
|
||||||
|
Button
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
|
import { I18n } from '@lingui/react';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
|
import { RootDialog } from './contexts/RootDialog';
|
||||||
|
import { withNetwork } from './contexts/Network';
|
||||||
|
|
||||||
|
import AlertModal from './components/AlertModal';
|
||||||
import About from './components/About';
|
import About from './components/About';
|
||||||
import NavExpandableGroup from './components/NavExpandableGroup';
|
import NavExpandableGroup from './components/NavExpandableGroup';
|
||||||
import TowerLogo from './components/TowerLogo';
|
import TowerLogo from './components/TowerLogo';
|
||||||
import PageHeaderToolbar from './components/PageHeaderToolbar';
|
import PageHeaderToolbar from './components/PageHeaderToolbar';
|
||||||
import { ConfigContext } from './context';
|
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -23,29 +30,24 @@ class App extends Component {
|
|||||||
&& window.innerWidth >= parseInt(global_breakpoint_md.value, 10);
|
&& window.innerWidth >= parseInt(global_breakpoint_md.value, 10);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
ansible_version: null,
|
|
||||||
custom_virtualenvs: null,
|
|
||||||
isAboutModalOpen: false,
|
isAboutModalOpen: false,
|
||||||
isNavOpen,
|
isNavOpen
|
||||||
version: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fetchConfig = this.fetchConfig.bind(this);
|
|
||||||
this.onLogout = this.onLogout.bind(this);
|
this.onLogout = this.onLogout.bind(this);
|
||||||
this.onAboutModalClose = this.onAboutModalClose.bind(this);
|
this.onAboutModalClose = this.onAboutModalClose.bind(this);
|
||||||
this.onAboutModalOpen = this.onAboutModalOpen.bind(this);
|
this.onAboutModalOpen = this.onAboutModalOpen.bind(this);
|
||||||
this.onNavToggle = this.onNavToggle.bind(this);
|
this.onNavToggle = this.onNavToggle.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
this.fetchConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
async onLogout () {
|
async onLogout () {
|
||||||
const { api } = this.props;
|
const { api, handleHttpError } = this.props;
|
||||||
|
try {
|
||||||
await api.logout();
|
await api.logout();
|
||||||
window.location.replace('/#/login');
|
window.location.replace('/#/login');
|
||||||
|
} catch (err) {
|
||||||
|
handleHttpError(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onAboutModalOpen () {
|
onAboutModalOpen () {
|
||||||
@@ -60,24 +62,12 @@ class App extends Component {
|
|||||||
this.setState(({ isNavOpen }) => ({ isNavOpen: !isNavOpen }));
|
this.setState(({ isNavOpen }) => ({ isNavOpen: !isNavOpen }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchConfig () {
|
|
||||||
const { api } = this.props;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { data: { ansible_version, custom_virtualenvs, version } } = await api.getConfig();
|
|
||||||
this.setState({ ansible_version, custom_virtualenvs, version });
|
|
||||||
} catch (err) {
|
|
||||||
this.setState({ ansible_version: null, custom_virtualenvs: null, version: null });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
ansible_version,
|
ansible_version,
|
||||||
custom_virtualenvs,
|
|
||||||
isAboutModalOpen,
|
isAboutModalOpen,
|
||||||
isNavOpen,
|
isNavOpen,
|
||||||
version,
|
version
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -86,63 +76,76 @@ class App extends Component {
|
|||||||
navLabel = '',
|
navLabel = '',
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const config = {
|
|
||||||
ansible_version,
|
|
||||||
custom_virtualenvs,
|
|
||||||
version,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<I18n>
|
||||||
<Page
|
{({ i18n }) => (
|
||||||
usecondensed="True"
|
<RootDialog>
|
||||||
header={(
|
{({ title, bodyText, variant = 'info', clearRootDialogMessage }) => (
|
||||||
<PageHeader
|
<Fragment>
|
||||||
showNavToggle
|
{(title || bodyText) && (
|
||||||
onNavToggle={this.onNavToggle}
|
<AlertModal
|
||||||
logo={<TowerLogo linkTo="/" />}
|
variant={variant}
|
||||||
toolbar={(
|
isOpen={!!(title || bodyText)}
|
||||||
<PageHeaderToolbar
|
onClose={clearRootDialogMessage}
|
||||||
isAboutDisabled={!version}
|
title={title}
|
||||||
onAboutClick={this.onAboutModalOpen}
|
actions={[
|
||||||
onLogoutClick={this.onLogout}
|
<Button key="close" variant="secondary" onClick={clearRootDialogMessage}>{i18n._(t`Close`)}</Button>
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{bodyText}
|
||||||
|
</AlertModal>
|
||||||
|
)}
|
||||||
|
<Page
|
||||||
|
usecondensed="True"
|
||||||
|
header={(
|
||||||
|
<PageHeader
|
||||||
|
showNavToggle
|
||||||
|
onNavToggle={this.onNavToggle}
|
||||||
|
logo={<TowerLogo linkTo="/" />}
|
||||||
|
toolbar={(
|
||||||
|
<PageHeaderToolbar
|
||||||
|
isAboutDisabled={!version}
|
||||||
|
onAboutClick={this.onAboutModalOpen}
|
||||||
|
onLogoutClick={this.onLogout}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
sidebar={(
|
||||||
|
<PageSidebar
|
||||||
|
isNavOpen={isNavOpen}
|
||||||
|
nav={(
|
||||||
|
<Nav aria-label={navLabel}>
|
||||||
|
<NavList>
|
||||||
|
{routeGroups.map(({ groupId, groupTitle, routes }) => (
|
||||||
|
<NavExpandableGroup
|
||||||
|
key={groupId}
|
||||||
|
groupId={groupId}
|
||||||
|
groupTitle={groupTitle}
|
||||||
|
routes={routes}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</NavList>
|
||||||
|
</Nav>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{render && render({ routeGroups })}
|
||||||
|
</Page>
|
||||||
|
<About
|
||||||
|
ansible_version={ansible_version}
|
||||||
|
version={version}
|
||||||
|
isOpen={isAboutModalOpen}
|
||||||
|
onClose={this.onAboutModalClose}
|
||||||
/>
|
/>
|
||||||
)}
|
</Fragment>
|
||||||
/>
|
)}
|
||||||
)}
|
</RootDialog>
|
||||||
sidebar={(
|
)}
|
||||||
<PageSidebar
|
</I18n>
|
||||||
isNavOpen={isNavOpen}
|
|
||||||
nav={(
|
|
||||||
<Nav aria-label={navLabel}>
|
|
||||||
<NavList>
|
|
||||||
{routeGroups.map(({ groupId, groupTitle, routes }) => (
|
|
||||||
<NavExpandableGroup
|
|
||||||
key={groupId}
|
|
||||||
groupId={groupId}
|
|
||||||
groupTitle={groupTitle}
|
|
||||||
routes={routes}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</NavList>
|
|
||||||
</Nav>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ConfigContext.Provider value={config}>
|
|
||||||
{render && render({ routeGroups })}
|
|
||||||
</ConfigContext.Provider>
|
|
||||||
</Page>
|
|
||||||
<About
|
|
||||||
ansible_version={ansible_version}
|
|
||||||
version={version}
|
|
||||||
isOpen={isAboutModalOpen}
|
|
||||||
onClose={this.onAboutModalClose}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default withNetwork(App);
|
||||||
|
|||||||
44
src/RootProvider.jsx
Normal file
44
src/RootProvider.jsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
I18nProvider,
|
||||||
|
} from '@lingui/react';
|
||||||
|
|
||||||
|
import { NetworkProvider } from './contexts/Network';
|
||||||
|
import { RootDialogProvider } from './contexts/RootDialog';
|
||||||
|
import { ConfigProvider } from './contexts/Config';
|
||||||
|
|
||||||
|
import ja from '../build/locales/ja/messages';
|
||||||
|
import en from '../build/locales/en/messages';
|
||||||
|
|
||||||
|
export function getLanguage (nav) {
|
||||||
|
const language = (nav.languages && nav.languages[0]) || nav.language || nav.userLanguage;
|
||||||
|
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
|
||||||
|
|
||||||
|
return languageWithoutRegionCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RootProvider extends Component {
|
||||||
|
render () {
|
||||||
|
const { children } = this.props;
|
||||||
|
|
||||||
|
const catalogs = { en, ja };
|
||||||
|
const language = getLanguage(navigator);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<I18nProvider
|
||||||
|
language={language}
|
||||||
|
catalogs={catalogs}
|
||||||
|
>
|
||||||
|
<RootDialogProvider>
|
||||||
|
<NetworkProvider>
|
||||||
|
<ConfigProvider>
|
||||||
|
{children}
|
||||||
|
</ConfigProvider>
|
||||||
|
</NetworkProvider>
|
||||||
|
</RootDialogProvider>
|
||||||
|
</I18nProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RootProvider;
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const ConfigContext = React.createContext({});
|
|
||||||
89
src/contexts/Config.jsx
Normal file
89
src/contexts/Config.jsx
Normal 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
84
src/contexts/Network.jsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
53
src/contexts/RootDialog.jsx
Normal file
53
src/contexts/RootDialog.jsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
420
src/index.jsx
420
src/index.jsx
@@ -1,15 +1,13 @@
|
|||||||
import axios from 'axios';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import {
|
import {
|
||||||
HashRouter,
|
HashRouter,
|
||||||
Redirect,
|
|
||||||
Route,
|
Route,
|
||||||
Switch,
|
Switch,
|
||||||
|
Redirect
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
I18n,
|
I18n
|
||||||
I18nProvider,
|
|
||||||
} from '@lingui/react';
|
} from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
@@ -19,10 +17,13 @@ import './components/Pagination/styles.scss';
|
|||||||
import './components/DataListToolbar/styles.scss';
|
import './components/DataListToolbar/styles.scss';
|
||||||
import './components/SelectedList/styles.scss';
|
import './components/SelectedList/styles.scss';
|
||||||
|
|
||||||
import APIClient from './api';
|
import { Config } from './contexts/Config';
|
||||||
|
|
||||||
import App from './App';
|
|
||||||
import Background from './components/Background';
|
import Background from './components/Background';
|
||||||
|
|
||||||
|
import RootProvider from './RootProvider';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
import Applications from './pages/Applications';
|
import Applications from './pages/Applications';
|
||||||
import Credentials from './pages/Credentials';
|
import Credentials from './pages/Credentials';
|
||||||
import CredentialTypes from './pages/CredentialTypes';
|
import CredentialTypes from './pages/CredentialTypes';
|
||||||
@@ -46,242 +47,201 @@ import License from './pages/License';
|
|||||||
import Teams from './pages/Teams';
|
import Teams from './pages/Teams';
|
||||||
import Templates from './pages/Templates';
|
import Templates from './pages/Templates';
|
||||||
import Users from './pages/Users';
|
import Users from './pages/Users';
|
||||||
import ja from '../build/locales/ja/messages';
|
|
||||||
import en from '../build/locales/en/messages';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize http
|
|
||||||
//
|
|
||||||
|
|
||||||
const http = axios.create({ xsrfCookieName: 'csrftoken', xsrfHeaderName: 'X-CSRFToken' });
|
|
||||||
|
|
||||||
//
|
|
||||||
// Derive the language and region from global user agent data. Example: es-US
|
|
||||||
// see: https://developer.mozilla.org/en-US/docs/Web/API/Navigator
|
|
||||||
//
|
|
||||||
|
|
||||||
export function getLanguage (nav) {
|
|
||||||
const language = (nav.languages && nav.languages[0]) || nav.language || nav.userLanguage;
|
|
||||||
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
|
|
||||||
|
|
||||||
return languageWithoutRegionCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Function Main
|
|
||||||
//
|
|
||||||
|
|
||||||
export async function main (render, api) {
|
|
||||||
const catalogs = { en, ja };
|
|
||||||
const language = getLanguage(navigator);
|
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export async function main (render) {
|
||||||
const el = document.getElementById('app');
|
const el = document.getElementById('app');
|
||||||
const { data: { custom_logo, custom_login_info } } = await api.getRoot();
|
|
||||||
|
|
||||||
const defaultRedirect = () => (<Redirect to="/home" />);
|
|
||||||
const loginRoutes = (
|
|
||||||
<Switch>
|
|
||||||
<Route
|
|
||||||
path="/login"
|
|
||||||
render={() => (
|
|
||||||
<Login
|
|
||||||
api={api}
|
|
||||||
logo={custom_logo}
|
|
||||||
loginInfo={custom_login_info}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Redirect to="/login" />
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<I18nProvider
|
<RootProvider>
|
||||||
language={language}
|
|
||||||
catalogs={catalogs}
|
|
||||||
>
|
|
||||||
<I18n>
|
<I18n>
|
||||||
{({ i18n }) => (
|
{({ i18n }) => (
|
||||||
<Background>
|
<Background>
|
||||||
{!api.isAuthenticated() ? loginRoutes : (
|
<Switch>
|
||||||
<Switch>
|
<Route
|
||||||
<Route path="/login" render={defaultRedirect} />
|
path="/login"
|
||||||
<Route exact path="/" render={defaultRedirect} />
|
render={() => (
|
||||||
<Route
|
<Config>
|
||||||
render={() => (
|
{({ custom_logo, custom_login_info }) => (
|
||||||
<App
|
<Login
|
||||||
api={api}
|
logo={custom_logo}
|
||||||
navLabel={i18n._(t`Primary Navigation`)}
|
loginInfo={custom_login_info}
|
||||||
routeGroups={[
|
/>
|
||||||
{
|
)}
|
||||||
groupTitle: i18n._(t`Views`),
|
</Config>
|
||||||
groupId: 'views_group',
|
)}
|
||||||
routes: [
|
/>
|
||||||
{
|
<Route exact path="/" render={() => <Redirect to="/home" />} />
|
||||||
title: i18n._(t`Dashboard`),
|
<Route
|
||||||
path: '/home',
|
render={() => (
|
||||||
component: Dashboard
|
<App
|
||||||
},
|
navLabel={i18n._(t`Primary Navigation`)}
|
||||||
{
|
routeGroups={[
|
||||||
title: i18n._(t`Jobs`),
|
{
|
||||||
path: '/jobs',
|
groupTitle: i18n._(t`Views`),
|
||||||
component: Jobs
|
groupId: 'views_group',
|
||||||
},
|
routes: [
|
||||||
{
|
{
|
||||||
title: i18n._(t`Schedules`),
|
title: i18n._(t`Dashboard`),
|
||||||
path: '/schedules',
|
path: '/home',
|
||||||
component: Schedules
|
component: Dashboard
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n._(t`My View`),
|
title: i18n._(t`Jobs`),
|
||||||
path: '/portal',
|
path: '/jobs',
|
||||||
component: Portal
|
component: Jobs
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
},
|
title: i18n._(t`Schedules`),
|
||||||
{
|
path: '/schedules',
|
||||||
groupTitle: i18n._(t`Resources`),
|
component: Schedules
|
||||||
groupId: 'resources_group',
|
},
|
||||||
routes: [
|
{
|
||||||
{
|
title: i18n._(t`My View`),
|
||||||
title: i18n._(t`Templates`),
|
path: '/portal',
|
||||||
path: '/templates',
|
component: Portal
|
||||||
component: Templates
|
},
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
title: i18n._(t`Credentials`),
|
{
|
||||||
path: '/credentials',
|
groupTitle: i18n._(t`Resources`),
|
||||||
component: Credentials
|
groupId: 'resources_group',
|
||||||
},
|
routes: [
|
||||||
{
|
{
|
||||||
title: i18n._(t`Projects`),
|
title: i18n._(t`Templates`),
|
||||||
path: '/projects',
|
path: '/templates',
|
||||||
component: Projects
|
component: Templates
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n._(t`Inventories`),
|
title: i18n._(t`Credentials`),
|
||||||
path: '/inventories',
|
path: '/credentials',
|
||||||
component: Inventories
|
component: Credentials
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n._(t`Inventory Scripts`),
|
title: i18n._(t`Projects`),
|
||||||
path: '/inventory_scripts',
|
path: '/projects',
|
||||||
component: InventoryScripts
|
component: Projects
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
},
|
title: i18n._(t`Inventories`),
|
||||||
{
|
path: '/inventories',
|
||||||
groupTitle: i18n._(t`Access`),
|
component: Inventories
|
||||||
groupId: 'access_group',
|
},
|
||||||
routes: [
|
{
|
||||||
{
|
title: i18n._(t`Inventory Scripts`),
|
||||||
title: i18n._(t`Organizations`),
|
path: '/inventory_scripts',
|
||||||
path: '/organizations',
|
component: InventoryScripts
|
||||||
component: Organizations
|
},
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
title: i18n._(t`Users`),
|
{
|
||||||
path: '/users',
|
groupTitle: i18n._(t`Access`),
|
||||||
component: Users
|
groupId: 'access_group',
|
||||||
},
|
routes: [
|
||||||
{
|
{
|
||||||
title: i18n._(t`Teams`),
|
title: i18n._(t`Organizations`),
|
||||||
path: '/teams',
|
path: '/organizations',
|
||||||
component: Teams
|
component: Organizations
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
},
|
title: i18n._(t`Users`),
|
||||||
{
|
path: '/users',
|
||||||
groupTitle: i18n._(t`Administration`),
|
component: Users
|
||||||
groupId: 'administration_group',
|
},
|
||||||
routes: [
|
{
|
||||||
{
|
title: i18n._(t`Teams`),
|
||||||
title: i18n._(t`Credential Types`),
|
path: '/teams',
|
||||||
path: '/credential_types',
|
component: Teams
|
||||||
component: CredentialTypes
|
},
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
title: i18n._(t`Notifications`),
|
{
|
||||||
path: '/notification_templates',
|
groupTitle: i18n._(t`Administration`),
|
||||||
component: NotificationTemplates
|
groupId: 'administration_group',
|
||||||
},
|
routes: [
|
||||||
{
|
{
|
||||||
title: i18n._(t`Management Jobs`),
|
title: i18n._(t`Credential Types`),
|
||||||
path: '/management_jobs',
|
path: '/credential_types',
|
||||||
component: ManagementJobs
|
component: CredentialTypes
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n._(t`Instance Groups`),
|
title: i18n._(t`Notifications`),
|
||||||
path: '/instance_groups',
|
path: '/notification_templates',
|
||||||
component: InstanceGroups
|
component: NotificationTemplates
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n._(t`Integrations`),
|
title: i18n._(t`Management Jobs`),
|
||||||
path: '/applications',
|
path: '/management_jobs',
|
||||||
component: Applications
|
component: ManagementJobs
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
},
|
title: i18n._(t`Instance Groups`),
|
||||||
{
|
path: '/instance_groups',
|
||||||
groupTitle: i18n._(t`Settings`),
|
component: InstanceGroups
|
||||||
groupId: 'settings_group',
|
},
|
||||||
routes: [
|
{
|
||||||
{
|
title: i18n._(t`Integrations`),
|
||||||
title: i18n._(t`Authentication`),
|
path: '/applications',
|
||||||
path: '/auth_settings',
|
component: Applications
|
||||||
component: AuthSettings
|
},
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
title: i18n._(t`Jobs`),
|
{
|
||||||
path: '/jobs_settings',
|
groupTitle: i18n._(t`Settings`),
|
||||||
component: JobsSettings
|
groupId: 'settings_group',
|
||||||
},
|
routes: [
|
||||||
{
|
{
|
||||||
title: i18n._(t`System`),
|
title: i18n._(t`Authentication`),
|
||||||
path: '/system_settings',
|
path: '/auth_settings',
|
||||||
component: SystemSettings
|
component: AuthSettings
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n._(t`User Interface`),
|
title: i18n._(t`Jobs`),
|
||||||
path: '/ui_settings',
|
path: '/jobs_settings',
|
||||||
component: UISettings
|
component: JobsSettings
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n._(t`License`),
|
title: i18n._(t`System`),
|
||||||
path: '/license',
|
path: '/system_settings',
|
||||||
component: License
|
component: SystemSettings
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
},
|
title: i18n._(t`User Interface`),
|
||||||
]}
|
path: '/ui_settings',
|
||||||
render={({ routeGroups }) => (
|
component: UISettings
|
||||||
routeGroups
|
},
|
||||||
.reduce((allRoutes, { routes }) => allRoutes.concat(routes), [])
|
{
|
||||||
.map(({ component: PageComponent, path }) => (
|
title: i18n._(t`License`),
|
||||||
<Route
|
path: '/license',
|
||||||
key={path}
|
component: License
|
||||||
path={path}
|
},
|
||||||
render={({ match }) => (
|
],
|
||||||
<PageComponent
|
},
|
||||||
api={api}
|
]}
|
||||||
match={match}
|
render={({ routeGroups }) => (
|
||||||
/>
|
routeGroups
|
||||||
)}
|
.reduce((allRoutes, { routes }) => allRoutes.concat(routes), [])
|
||||||
/>
|
.map(({ component: PageComponent, path }) => (
|
||||||
))
|
<Route
|
||||||
)}
|
key={path}
|
||||||
/>
|
path={path}
|
||||||
)}
|
render={({ match }) => (
|
||||||
/>
|
<PageComponent match={match} />
|
||||||
</Switch>
|
)}
|
||||||
)}
|
/>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
</Background>
|
</Background>
|
||||||
)}
|
)}
|
||||||
</I18n>
|
</I18n>
|
||||||
</I18nProvider>
|
</RootProvider>
|
||||||
</HashRouter>, el
|
</HashRouter>, el
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
main(ReactDOM.render, new APIClient(http));
|
main(ReactDOM.render);
|
||||||
|
|||||||
Reference in New Issue
Block a user