mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 08:21:15 +03:00
Add logged in username to top level header bar.
This commit is contained in:
parent
ffade973a9
commit
5287af1b9f
47
src/App.jsx
47
src/App.jsx
@ -64,24 +64,22 @@ class App extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
isAboutModalOpen,
|
||||
isNavOpen
|
||||
} = this.state;
|
||||
const { isAboutModalOpen, isNavOpen } = this.state;
|
||||
|
||||
const {
|
||||
render,
|
||||
routeGroups = [],
|
||||
navLabel = '',
|
||||
} = this.props;
|
||||
const { render, routeGroups = [], navLabel = '' } = this.props;
|
||||
|
||||
return (
|
||||
<Config>
|
||||
{({ ansible_version, version }) => (
|
||||
{({ ansible_version, version, me }) => (
|
||||
<I18n>
|
||||
{({ i18n }) => (
|
||||
<RootDialog>
|
||||
{({ title, bodyText, variant = 'info', clearRootDialogMessage }) => (
|
||||
{({
|
||||
title,
|
||||
bodyText,
|
||||
variant = 'info',
|
||||
clearRootDialogMessage
|
||||
}) => (
|
||||
<Fragment>
|
||||
{(title || bodyText) && (
|
||||
<AlertModal
|
||||
@ -90,7 +88,13 @@ class App extends Component {
|
||||
onClose={clearRootDialogMessage}
|
||||
title={title}
|
||||
actions={[
|
||||
<Button key="close" variant="secondary" onClick={clearRootDialogMessage}>{i18n._(t`Close`)}</Button>
|
||||
<Button
|
||||
key="close"
|
||||
variant="secondary"
|
||||
onClick={clearRootDialogMessage}
|
||||
>
|
||||
{i18n._(t`Close`)}
|
||||
</Button>
|
||||
]}
|
||||
>
|
||||
{bodyText}
|
||||
@ -105,6 +109,7 @@ class App extends Component {
|
||||
logo={<TowerLogo linkTo="/" />}
|
||||
toolbar={(
|
||||
<PageHeaderToolbar
|
||||
loggedInUser={me}
|
||||
isAboutDisabled={!version}
|
||||
onAboutClick={this.onAboutModalOpen}
|
||||
onLogoutClick={this.onLogout}
|
||||
@ -118,14 +123,16 @@ class App extends Component {
|
||||
nav={(
|
||||
<Nav aria-label={navLabel}>
|
||||
<NavList>
|
||||
{routeGroups.map(({ groupId, groupTitle, routes }) => (
|
||||
<NavExpandableGroup
|
||||
key={groupId}
|
||||
groupId={groupId}
|
||||
groupTitle={groupTitle}
|
||||
routes={routes}
|
||||
/>
|
||||
))}
|
||||
{routeGroups.map(
|
||||
({ groupId, groupTitle, routes }) => (
|
||||
<NavExpandableGroup
|
||||
key={groupId}
|
||||
groupId={groupId}
|
||||
groupTitle={groupTitle}
|
||||
routes={routes}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</NavList>
|
||||
</Nav>
|
||||
)}
|
||||
|
23
src/app.scss
23
src/app.scss
@ -25,16 +25,28 @@
|
||||
}
|
||||
|
||||
.pf-c-page__header-tools .pf-c-dropdown__toggle:before {
|
||||
--pf-c-dropdown__toggle--BorderBottomColor: var(--pf-global--BackgroundColor--light-100);
|
||||
--pf-c-dropdown__toggle--hover--BorderBottomColor: var(--pf-global--BackgroundColor--light-100);
|
||||
--pf-c-dropdown__toggle--expanded--BorderBottomColor: var(--pf-global--BackgroundColor--light-100);
|
||||
--pf-c-dropdown__toggle--BorderBottomColor: var(
|
||||
--pf-global--BackgroundColor--light-100
|
||||
);
|
||||
--pf-c-dropdown__toggle--hover--BorderBottomColor: var(
|
||||
--pf-global--BackgroundColor--light-100
|
||||
);
|
||||
--pf-c-dropdown__toggle--expanded--BorderBottomColor: var(
|
||||
--pf-global--BackgroundColor--light-100
|
||||
);
|
||||
}
|
||||
|
||||
.pf-c-page__header {
|
||||
.pf-c-dropdown__toggle .pf-c-dropdown__toggle-icon {
|
||||
--pf-c-dropdown__toggle-icon--MarginLeft: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// sidebar overrides
|
||||
//
|
||||
|
||||
.pf-c-page__sidebar{
|
||||
.pf-c-page__sidebar {
|
||||
--pf-c-page__sidebar--md--Width: 255px;
|
||||
|
||||
.pf-c-nav {
|
||||
@ -83,7 +95,8 @@
|
||||
--pf-global--target-size--MinWidth: 32px;
|
||||
--pf-global--FontSize--md: 14px;
|
||||
|
||||
.pf-c-badge:not(:last-child), .pf-c-switch:not(:last-child) {
|
||||
.pf-c-badge:not(:last-child),
|
||||
.pf-c-switch:not(:last-child) {
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
|
@ -13,10 +13,7 @@ import {
|
||||
ToolbarItem,
|
||||
Tooltip
|
||||
} from '@patternfly/react-core';
|
||||
import {
|
||||
QuestionCircleIcon,
|
||||
UserIcon,
|
||||
} from '@patternfly/react-icons';
|
||||
import { QuestionCircleIcon, UserIcon } from '@patternfly/react-icons';
|
||||
|
||||
const DOCLINK = 'https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html';
|
||||
|
||||
@ -25,7 +22,7 @@ class PageHeaderToolbar extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
isHelpOpen: false,
|
||||
isUserOpen: false,
|
||||
isUserOpen: false
|
||||
};
|
||||
|
||||
this.handleHelpSelect = this.handleHelpSelect.bind(this);
|
||||
@ -56,19 +53,19 @@ class PageHeaderToolbar extends Component {
|
||||
|
||||
render () {
|
||||
const { isHelpOpen, isUserOpen } = this.state;
|
||||
const { isAboutDisabled, onAboutClick, onLogoutClick } = this.props;
|
||||
const {
|
||||
isAboutDisabled,
|
||||
onAboutClick,
|
||||
onLogoutClick,
|
||||
loggedInUser
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<I18n>
|
||||
{({ i18n }) => (
|
||||
<Toolbar>
|
||||
<ToolbarGroup>
|
||||
<Tooltip
|
||||
position="left"
|
||||
content={
|
||||
<div>Help</div>
|
||||
}
|
||||
>
|
||||
<Tooltip position="left" content={<div>Help</div>}>
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
isPlain
|
||||
@ -76,18 +73,12 @@ class PageHeaderToolbar extends Component {
|
||||
position={DropdownPosition.right}
|
||||
onSelect={this.handleHelpSelect}
|
||||
toggle={(
|
||||
<DropdownToggle
|
||||
onToggle={this.handleHelpToggle}
|
||||
>
|
||||
<DropdownToggle onToggle={this.handleHelpToggle}>
|
||||
<QuestionCircleIcon />
|
||||
</DropdownToggle>
|
||||
)}
|
||||
dropdownItems={[
|
||||
<DropdownItem
|
||||
key="help"
|
||||
target="_blank"
|
||||
href={DOCLINK}
|
||||
>
|
||||
<DropdownItem key="help" target="_blank" href={DOCLINK}>
|
||||
{i18n._(t`Help`)}
|
||||
</DropdownItem>,
|
||||
<DropdownItem
|
||||
@ -102,12 +93,7 @@ class PageHeaderToolbar extends Component {
|
||||
/>
|
||||
</ToolbarItem>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
position="left"
|
||||
content={
|
||||
<div>User</div>
|
||||
}
|
||||
>
|
||||
<Tooltip position="left" content={<div>User</div>}>
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
isPlain
|
||||
@ -115,18 +101,17 @@ class PageHeaderToolbar extends Component {
|
||||
position={DropdownPosition.right}
|
||||
onSelect={this.handleUserSelect}
|
||||
toggle={(
|
||||
<DropdownToggle
|
||||
onToggle={this.handleUserToggle}
|
||||
>
|
||||
<DropdownToggle onToggle={this.handleUserToggle}>
|
||||
<UserIcon />
|
||||
User Name
|
||||
{loggedInUser && (
|
||||
<span style={{ marginLeft: '10px' }}>
|
||||
{loggedInUser.username}
|
||||
</span>
|
||||
)}
|
||||
</DropdownToggle>
|
||||
)}
|
||||
dropdownItems={[
|
||||
<DropdownItem
|
||||
key="user"
|
||||
href="#/home"
|
||||
>
|
||||
<DropdownItem key="user" href="#/home">
|
||||
{i18n._(t`User Details`)}
|
||||
</DropdownItem>,
|
||||
<DropdownItem
|
||||
@ -151,11 +136,11 @@ class PageHeaderToolbar extends Component {
|
||||
PageHeaderToolbar.propTypes = {
|
||||
isAboutDisabled: PropTypes.bool,
|
||||
onAboutClick: PropTypes.func.isRequired,
|
||||
onLogoutClick: PropTypes.func.isRequired,
|
||||
onLogoutClick: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
PageHeaderToolbar.defaultProps = {
|
||||
isAboutDisabled: false,
|
||||
isAboutDisabled: false
|
||||
};
|
||||
|
||||
export default PageHeaderToolbar;
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { withNetwork } from './Network';
|
||||
@ -33,12 +32,8 @@ class Provider extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
updateConfig = (config) => {
|
||||
const {
|
||||
ansible_version,
|
||||
custom_virtualenvs,
|
||||
version
|
||||
} = config;
|
||||
updateConfig = config => {
|
||||
const { ansible_version, custom_virtualenvs, version } = config;
|
||||
|
||||
this.setState(prevState => ({
|
||||
value: {
|
||||
@ -46,31 +41,36 @@ class Provider extends Component {
|
||||
ansible_version,
|
||||
custom_virtualenvs,
|
||||
version
|
||||
},
|
||||
}
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
async fetchMe () {
|
||||
const { api, handleHttpError } = this.props;
|
||||
try {
|
||||
const { data: { results: [me] } } = await api.getMe();
|
||||
const {
|
||||
data: {
|
||||
results: [me]
|
||||
}
|
||||
} = await api.getMe();
|
||||
this.setState(prevState => ({
|
||||
value: {
|
||||
...prevState.value,
|
||||
me
|
||||
},
|
||||
}
|
||||
}));
|
||||
} catch (err) {
|
||||
handleHttpError(err) || this.setState({
|
||||
value: {
|
||||
ansible_version: null,
|
||||
custom_virtualenvs: null,
|
||||
version: null,
|
||||
custom_logo: null,
|
||||
custom_login_info: null,
|
||||
me: {}
|
||||
}
|
||||
});
|
||||
handleHttpError(err)
|
||||
|| this.setState({
|
||||
value: {
|
||||
ansible_version: null,
|
||||
custom_virtualenvs: null,
|
||||
version: null,
|
||||
custom_logo: null,
|
||||
custom_login_info: null,
|
||||
me: {}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,20 +90,21 @@ class Provider extends Component {
|
||||
version: configRes.data.version,
|
||||
custom_logo: rootRes.data.custom_logo,
|
||||
custom_login_info: rootRes.data.custom_login_info,
|
||||
me: meRes.data.results
|
||||
me: meRes.data.results[0]
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
handleHttpError(err) || this.setState({
|
||||
value: {
|
||||
ansible_version: null,
|
||||
custom_virtualenvs: null,
|
||||
version: null,
|
||||
custom_logo: null,
|
||||
custom_login_info: null,
|
||||
me: {}
|
||||
}
|
||||
});
|
||||
handleHttpError(err)
|
||||
|| this.setState({
|
||||
value: {
|
||||
ansible_version: null,
|
||||
custom_virtualenvs: null,
|
||||
version: null,
|
||||
custom_logo: null,
|
||||
custom_login_info: null,
|
||||
me: {}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +130,5 @@ class Provider extends Component {
|
||||
export const ConfigProvider = withNetwork(Provider);
|
||||
|
||||
export const Config = ({ children }) => (
|
||||
<ConfigContext.Consumer>
|
||||
{value => children(value)}
|
||||
</ConfigContext.Consumer>
|
||||
<ConfigContext.Consumer>{value => children(value)}</ConfigContext.Consumer>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user