mirror of
https://github.com/ansible/awx.git
synced 2026-03-18 01:17:35 -02:30
initialize and pass api client to subviews
This commit is contained in:
@@ -38,8 +38,17 @@ class App extends Component {
|
|||||||
config: {},
|
config: {},
|
||||||
error: false,
|
error: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.onLogout = this.onLogout.bind(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async onLogout () {
|
||||||
|
const { api } = this.props;
|
||||||
|
|
||||||
|
await api.logout();
|
||||||
|
window.location.replace('/#/login')
|
||||||
|
}
|
||||||
|
|
||||||
onNavToggle = () => {
|
onNavToggle = () => {
|
||||||
this.setState(({ isNavOpen }) => ({ isNavOpen: !isNavOpen }));
|
this.setState(({ isNavOpen }) => ({ isNavOpen: !isNavOpen }));
|
||||||
};
|
};
|
||||||
|
|||||||
74
src/api.js
74
src/api.js
@@ -1,33 +1,35 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import {
|
const API_ROOT = '/api/';
|
||||||
API_CONFIG,
|
const API_LOGIN = `${API_ROOT}login/`;
|
||||||
API_LOGIN,
|
const API_LOGOUT = `${API_ROOT}logout/`;
|
||||||
API_ROOT,
|
const API_V2 = `${API_ROOT}v2/`;
|
||||||
} from './endpoints';
|
const API_CONFIG = `${API_V2}config/`;
|
||||||
|
const API_ORGANIZATIONS = `${API_V2}organizations/`;
|
||||||
|
|
||||||
const CSRF_COOKIE_NAME = 'csrftoken';
|
const CSRF_COOKIE_NAME = 'csrftoken';
|
||||||
const CSRF_HEADER_NAME = 'X-CSRFToken';
|
const CSRF_HEADER_NAME = 'X-CSRFToken';
|
||||||
|
|
||||||
const LOGIN_CONTENT_TYPE = 'application/x-www-form-urlencoded';
|
const LOGIN_CONTENT_TYPE = 'application/x-www-form-urlencoded';
|
||||||
|
|
||||||
class APIClient {
|
const defaultHttpAdapter = axios.create({
|
||||||
constructor () {
|
xsrfCookieName: CSRF_COOKIE_NAME,
|
||||||
this.http = axios.create({
|
xsrfHeaderName: CSRF_HEADER_NAME,
|
||||||
xsrfCookieName: CSRF_COOKIE_NAME,
|
});
|
||||||
xsrfHeaderName: CSRF_HEADER_NAME,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* eslint class-methods-use-this: ["error", { "exceptMethods": ["getCookie"] }] */
|
class APIClient {
|
||||||
getCookie () {
|
static getCookie () {
|
||||||
return document.cookie;
|
return document.cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
isAuthenticated () {
|
constructor (httpAdapter = defaultHttpAdapter) {
|
||||||
let authenticated = false;
|
this.http = httpAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
const parsed = (`; ${this.getCookie()}`).split('; userLoggedIn=');
|
isAuthenticated () {
|
||||||
|
const cookie = this.constructor.getCookie();
|
||||||
|
const parsed = (`; ${cookie}`).split('; userLoggedIn=');
|
||||||
|
|
||||||
|
let authenticated = false;
|
||||||
|
|
||||||
if (parsed.length === 2) {
|
if (parsed.length === 2) {
|
||||||
authenticated = parsed.pop().split(';').shift() === 'true';
|
authenticated = parsed.pop().split(';').shift() === 'true';
|
||||||
@@ -36,10 +38,6 @@ class APIClient {
|
|||||||
return authenticated;
|
return authenticated;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRoot () {
|
|
||||||
return this.http.get(API_ROOT);
|
|
||||||
}
|
|
||||||
|
|
||||||
async login (username, password, redirect = API_CONFIG) {
|
async login (username, password, redirect = API_CONFIG) {
|
||||||
const un = encodeURIComponent(username);
|
const un = encodeURIComponent(username);
|
||||||
const pw = encodeURIComponent(password);
|
const pw = encodeURIComponent(password);
|
||||||
@@ -49,12 +47,36 @@ class APIClient {
|
|||||||
const headers = { 'Content-Type': LOGIN_CONTENT_TYPE };
|
const headers = { 'Content-Type': LOGIN_CONTENT_TYPE };
|
||||||
|
|
||||||
await this.http.get(API_LOGIN, { headers });
|
await this.http.get(API_LOGIN, { headers });
|
||||||
await this.http.post(API_LOGIN, data, { headers });
|
const response = await this.http.post(API_LOGIN, data, { headers });
|
||||||
|
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
get = (endpoint, params = {}) => this.http.get(endpoint, { params });
|
logout () {
|
||||||
|
return this.http.get(API_LOGOUT);
|
||||||
|
}
|
||||||
|
|
||||||
post = (endpoint, data) => this.http.post(endpoint, data);
|
getRoot () {
|
||||||
|
return this.http.get(API_ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfig () {
|
||||||
|
return this.http.get(API_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrganizations (params = {}) {
|
||||||
|
return this.http.get(API_ORGANIZATIONS, { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
createOrganization (data) {
|
||||||
|
return this.http.post(API_ORGANIZATIONS, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrganizationDetails (id) {
|
||||||
|
const endpoint = `${API_ORGANIZATIONS}${id}/`;
|
||||||
|
|
||||||
|
return this.http.get(endpoint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new APIClient();
|
export default APIClient;
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ import './app.scss';
|
|||||||
import './components/Pagination/styles.scss';
|
import './components/Pagination/styles.scss';
|
||||||
import './components/DataListToolbar/styles.scss';
|
import './components/DataListToolbar/styles.scss';
|
||||||
|
|
||||||
import api from './api';
|
import APIClient from './api';
|
||||||
|
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import Background from './components/Background';
|
import Background from './components/Background';
|
||||||
import Applications from './pages/Applications';
|
import Applications from './pages/Applications';
|
||||||
@@ -55,7 +56,7 @@ const language = (navigator.languages && navigator.languages[0])
|
|||||||
|| navigator.userLanguage;
|
|| navigator.userLanguage;
|
||||||
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
|
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
|
||||||
|
|
||||||
export async function main () {
|
export async function main (api) {
|
||||||
const el = document.getElementById('app');
|
const el = document.getElementById('app');
|
||||||
// fetch additional config from server
|
// fetch additional config from server
|
||||||
const { data } = await api.getRoot();
|
const { data } = await api.getRoot();
|
||||||
@@ -67,6 +68,7 @@ export async function main () {
|
|||||||
path="/login"
|
path="/login"
|
||||||
render={() => (
|
render={() => (
|
||||||
<Login
|
<Login
|
||||||
|
api={api}
|
||||||
logo={custom_logo}
|
logo={custom_logo}
|
||||||
loginInfo={custom_login_info}
|
loginInfo={custom_login_info}
|
||||||
/>
|
/>
|
||||||
@@ -92,6 +94,7 @@ export async function main () {
|
|||||||
<Route
|
<Route
|
||||||
render={() => (
|
render={() => (
|
||||||
<App
|
<App
|
||||||
|
api={api}
|
||||||
navLabel={i18n._(t`Primary Navigation`)}
|
navLabel={i18n._(t`Primary Navigation`)}
|
||||||
routeGroups={[
|
routeGroups={[
|
||||||
{
|
{
|
||||||
@@ -244,6 +247,7 @@ export async function main () {
|
|||||||
path={path}
|
path={path}
|
||||||
render={({ match }) => (
|
render={({ match }) => (
|
||||||
<PageComponent
|
<PageComponent
|
||||||
|
api={api}
|
||||||
match={match}
|
match={match}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -262,4 +266,4 @@ export async function main () {
|
|||||||
</HashRouter>, el);
|
</HashRouter>, el);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default main();
|
export default main(new APIClient());
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import towerLogo from '../../images/tower-logo-header.svg';
|
import towerLogo from '../../images/tower-logo-header.svg';
|
||||||
import api from '../api';
|
|
||||||
|
|
||||||
class AtLogin extends Component {
|
class AtLogin extends Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -34,6 +33,7 @@ class AtLogin extends Component {
|
|||||||
|
|
||||||
handleSubmit = async event => {
|
handleSubmit = async event => {
|
||||||
const { username, password, loading } = this.state;
|
const { username, password, loading } = this.state;
|
||||||
|
const { api } = this.props;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ class AtLogin extends Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { username, password, isValidPassword } = this.state;
|
const { username, password, isValidPassword } = this.state;
|
||||||
const { logo, alt } = this.props;
|
const { api, alt, logo } = this.props;
|
||||||
const logoSrc = logo ? `data:image/jpeg;${logo}` : towerLogo;
|
const logoSrc = logo ? `data:image/jpeg;${logo}` : towerLogo;
|
||||||
|
|
||||||
if (api.isAuthenticated()) {
|
if (api.isAuthenticated()) {
|
||||||
|
|||||||
@@ -5,12 +5,31 @@ import OrganizationAdd from './views/Organization.add';
|
|||||||
import OrganizationView from './views/Organization.view';
|
import OrganizationView from './views/Organization.view';
|
||||||
import OrganizationsList from './views/Organizations.list';
|
import OrganizationsList from './views/Organizations.list';
|
||||||
|
|
||||||
const Organizations = ({ match }) => (
|
export default ({ api, match }) => (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path={`${match.path}/add`} component={OrganizationAdd} />
|
<Route
|
||||||
<Route path={`${match.path}/:id`} component={OrganizationView} />
|
path={`${match.path}/add`}
|
||||||
<Route path={`${match.path}`} component={OrganizationsList} />
|
render={() => (
|
||||||
|
<OrganizationAdd
|
||||||
|
api={api}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={`${match.path}/:id`}
|
||||||
|
render={() => (
|
||||||
|
<OrganizationView
|
||||||
|
api={api}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={`${match.path}`}
|
||||||
|
render={() => (
|
||||||
|
<OrganizationsList
|
||||||
|
api={api}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default Organizations;
|
|
||||||
|
|||||||
@@ -2,16 +2,13 @@ import React, { Component, Fragment } from 'react';
|
|||||||
import { i18nMark } from '@lingui/react';
|
import { i18nMark } from '@lingui/react';
|
||||||
import {
|
import {
|
||||||
Switch,
|
Switch,
|
||||||
Route
|
Route,
|
||||||
|
withRouter,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import OrganizationBreadcrumb from '../components/OrganizationBreadcrumb';
|
import OrganizationBreadcrumb from '../components/OrganizationBreadcrumb';
|
||||||
import OrganizationDetail from '../components/OrganizationDetail';
|
import OrganizationDetail from '../components/OrganizationDetail';
|
||||||
import OrganizationEdit from '../components/OrganizationEdit';
|
import OrganizationEdit from '../components/OrganizationEdit';
|
||||||
|
|
||||||
import api from '../../../api';
|
|
||||||
import { API_ORGANIZATIONS } from '../../../endpoints';
|
|
||||||
|
|
||||||
class OrganizationView extends Component {
|
class OrganizationView extends Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -47,13 +44,15 @@ class OrganizationView extends Component {
|
|||||||
|
|
||||||
async fetchOrganization () {
|
async fetchOrganization () {
|
||||||
const { mounted } = this.state;
|
const { mounted } = this.state;
|
||||||
|
const { api } = this.props;
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
this.setState({ error: false, loading: true });
|
this.setState({ error: false, loading: true });
|
||||||
|
|
||||||
const { match } = this.props;
|
const { match } = this.props;
|
||||||
const { parentBreadcrumbObj, organization } = this.state;
|
const { parentBreadcrumbObj, organization } = this.state;
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get(`${API_ORGANIZATIONS}${match.params.id}/`);
|
const { data } = await api.getOrganizationDetails(match.params.id);
|
||||||
if (organization === 'loading') {
|
if (organization === 'loading') {
|
||||||
this.setState({ organization: data });
|
this.setState({ organization: data });
|
||||||
}
|
}
|
||||||
@@ -118,4 +117,4 @@ class OrganizationView extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OrganizationView;
|
export default withRouter(OrganizationView);
|
||||||
|
|||||||
@@ -17,9 +17,6 @@ import DataListToolbar from '../../../components/DataListToolbar';
|
|||||||
import OrganizationListItem from '../components/OrganizationListItem';
|
import OrganizationListItem from '../components/OrganizationListItem';
|
||||||
import Pagination from '../../../components/Pagination';
|
import Pagination from '../../../components/Pagination';
|
||||||
|
|
||||||
import api from '../../../api';
|
|
||||||
import { API_ORGANIZATIONS } from '../../../endpoints';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
encodeQueryString,
|
encodeQueryString,
|
||||||
parseQueryString,
|
parseQueryString,
|
||||||
@@ -132,6 +129,7 @@ class Organizations extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchOrganizations (queryParams) {
|
async fetchOrganizations (queryParams) {
|
||||||
|
const { api } = this.props;
|
||||||
const { page, page_size, order_by } = queryParams;
|
const { page, page_size, order_by } = queryParams;
|
||||||
|
|
||||||
let sortOrder = 'ascending';
|
let sortOrder = 'ascending';
|
||||||
@@ -145,7 +143,7 @@ class Organizations extends Component {
|
|||||||
this.setState({ error: false, loading: true });
|
this.setState({ error: false, loading: true });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get(API_ORGANIZATIONS, queryParams);
|
const { data } = await api.getOrganizations(queryParams);
|
||||||
const { count, results } = data;
|
const { count, results } = data;
|
||||||
|
|
||||||
const pageCount = Math.ceil(count / page_size);
|
const pageCount = Math.ceil(count / page_size);
|
||||||
|
|||||||
Reference in New Issue
Block a user