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