mirror of
https://github.com/grafana/grafana.git
synced 2025-09-20 04:14:27 +08:00
Footer: Single footer component for both react & angular pages (#21389)
* Footer: Single footer implementation for both react & angular pages * Export type * Updates * Use footer links in help menu * Updates & Fixes * Updated snapshot * updated snapshot
This commit is contained in:
@ -352,11 +352,7 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
|
|||||||
Icon: "gicon gicon-question",
|
Icon: "gicon gicon-question",
|
||||||
HideFromMenu: true,
|
HideFromMenu: true,
|
||||||
SortWeight: dtos.WeightHelp,
|
SortWeight: dtos.WeightHelp,
|
||||||
Children: []*dtos.NavLink{
|
Children: []*dtos.NavLink{},
|
||||||
{Text: "Keyboard shortcuts", Url: "/shortcuts", Icon: "fa fa-fw fa-keyboard-o", Target: "_self"},
|
|
||||||
{Text: "Community site", Url: "http://community.grafana.com", Icon: "fa fa-fw fa-comment", Target: "_blank"},
|
|
||||||
{Text: "Documentation", Url: "http://docs.grafana.org", Icon: "fa fa-fw fa-file", Target: "_blank"},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
hs.HooksService.RunIndexDataHooks(&data)
|
hs.HooksService.RunIndexDataHooks(&data)
|
||||||
|
@ -21,8 +21,10 @@ import { GraphContextMenu } from 'app/plugins/panel/graph/GraphContextMenu';
|
|||||||
import ReactProfileWrapper from 'app/features/profile/ReactProfileWrapper';
|
import ReactProfileWrapper from 'app/features/profile/ReactProfileWrapper';
|
||||||
import { LokiAnnotationsQueryEditor } from '../plugins/datasource/loki/components/AnnotationsQueryEditor';
|
import { LokiAnnotationsQueryEditor } from '../plugins/datasource/loki/components/AnnotationsQueryEditor';
|
||||||
import { HelpModal } from './components/help/HelpModal';
|
import { HelpModal } from './components/help/HelpModal';
|
||||||
|
import { Footer } from './components/Footer/Footer';
|
||||||
|
|
||||||
export function registerAngularDirectives() {
|
export function registerAngularDirectives() {
|
||||||
|
react2AngularDirective('footer', Footer, []);
|
||||||
react2AngularDirective('helpModal', HelpModal, []);
|
react2AngularDirective('helpModal', HelpModal, []);
|
||||||
react2AngularDirective('sidemenu', SideMenu, []);
|
react2AngularDirective('sidemenu', SideMenu, []);
|
||||||
react2AngularDirective('functionEditor', FunctionEditor, ['func', 'onRemove', 'onMoveLeft', 'onMoveRight']);
|
react2AngularDirective('functionEditor', FunctionEditor, ['func', 'onRemove', 'onMoveLeft', 'onMoveRight']);
|
||||||
|
18
public/app/core/components/Branding/Branding.tsx
Normal file
18
public/app/core/components/Branding/Branding.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React, { FC } from 'react';
|
||||||
|
|
||||||
|
export interface BrandComponentProps {
|
||||||
|
className: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LogoIcon: FC<BrandComponentProps> = ({ className }) => {
|
||||||
|
return <img className={className} src="public/img/grafana_icon.svg" alt="Grafana" />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Wordmark: FC<BrandComponentProps> = ({ className }) => {
|
||||||
|
return <div className={className} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Branding {
|
||||||
|
static LogoIcon = LogoIcon;
|
||||||
|
static Wordmark = Wordmark;
|
||||||
|
}
|
@ -1,61 +1,77 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { Tooltip } from '@grafana/ui';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
interface Props {
|
export interface FooterLink {
|
||||||
appName: string;
|
text: string;
|
||||||
buildVersion: string;
|
icon?: string;
|
||||||
buildCommit: string;
|
url?: string;
|
||||||
newGrafanaVersionExists: boolean;
|
|
||||||
newGrafanaVersion: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Footer: FC<Props> = React.memo(
|
export let getFooterLinks = (): FooterLink[] => {
|
||||||
({ appName, buildVersion, buildCommit, newGrafanaVersionExists, newGrafanaVersion }) => {
|
return [
|
||||||
|
{
|
||||||
|
text: 'Docs',
|
||||||
|
icon: 'fa fa-file-code-o',
|
||||||
|
url: 'https://grafana.com/docs/grafana/latest/?utm_source=grafana_footer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Support & Enterprise',
|
||||||
|
icon: 'fa fa-support',
|
||||||
|
url: 'https://grafana.com/products/enterprise/?utm_source=grafana_footer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Community',
|
||||||
|
icon: 'fa fa-comments-o',
|
||||||
|
url: 'https://community.grafana.com/?utm_source=grafana_footer',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export let getVersionLinks = (): FooterLink[] => {
|
||||||
|
const { buildInfo } = config;
|
||||||
|
|
||||||
|
const links: FooterLink[] = [
|
||||||
|
{
|
||||||
|
text: `Grafana v${buildInfo.version} (commit: ${buildInfo.commit})`,
|
||||||
|
url: 'https://grafana.com',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (buildInfo.hasUpdate) {
|
||||||
|
links.push({
|
||||||
|
text: `New version available!`,
|
||||||
|
icon: 'fa fa-download',
|
||||||
|
url: 'https://grafana.com/grafana/download?utm_source=grafana_footer',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return links;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function setFooterLinksFn(fn: typeof getFooterLinks) {
|
||||||
|
getFooterLinks = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setVersionLinkFn(fn: typeof getFooterLinks) {
|
||||||
|
getVersionLinks = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Footer: FC = React.memo(() => {
|
||||||
|
const links = getFooterLinks().concat(getVersionLinks());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
{links.map(link => (
|
||||||
<a href="http://docs.grafana.org" target="_blank" rel="noopener">
|
<li key={link.text}>
|
||||||
<i className="fa fa-file-code-o" /> Docs
|
<a href={link.url} target="_blank" rel="noopener">
|
||||||
|
<i className={link.icon} /> {link.text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
))}
|
||||||
<a
|
|
||||||
href="https://grafana.com/products/enterprise/?utm_source=grafana_footer"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>
|
|
||||||
<i className="fa fa-support" /> Support & Enterprise
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://community.grafana.com/" target="_blank" rel="noopener">
|
|
||||||
<i className="fa fa-comments-o" /> Community
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://grafana.com" target="_blank" rel="noopener">
|
|
||||||
{appName}
|
|
||||||
</a>{' '}
|
|
||||||
<span>
|
|
||||||
v{buildVersion} (commit: {buildCommit})
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
{newGrafanaVersionExists && (
|
|
||||||
<li>
|
|
||||||
<Tooltip placement="auto" content={newGrafanaVersion}>
|
|
||||||
<a href="https://grafana.com/get" target="_blank" rel="noopener">
|
|
||||||
New version available!
|
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export default Footer;
|
|
||||||
|
@ -5,14 +5,15 @@ import LoginCtrl from './LoginCtrl';
|
|||||||
import { LoginForm } from './LoginForm';
|
import { LoginForm } from './LoginForm';
|
||||||
import { ChangePassword } from './ChangePassword';
|
import { ChangePassword } from './ChangePassword';
|
||||||
import { CSSTransition } from 'react-transition-group';
|
import { CSSTransition } from 'react-transition-group';
|
||||||
|
import { Branding } from 'app/core/components/Branding/Branding';
|
||||||
|
|
||||||
export const LoginPage: FC = () => {
|
export const LoginPage: FC = () => {
|
||||||
return (
|
return (
|
||||||
<div className="login container">
|
<div className="login container">
|
||||||
<div className="login-content">
|
<div className="login-content">
|
||||||
<div className="login-branding">
|
<div className="login-branding">
|
||||||
<img className="logo-icon" src="public/img/grafana_icon.svg" alt="Grafana" />
|
<Branding.LogoIcon className="logo-icon" />
|
||||||
<div className="logo-wordmark" />
|
<Branding.Wordmark className="logo-wordmark" />
|
||||||
</div>
|
</div>
|
||||||
<LoginCtrl>
|
<LoginCtrl>
|
||||||
{({
|
{({
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
// Libraries
|
// Libraries
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import config from 'app/core/config';
|
|
||||||
import { getTitleFromNavModel } from 'app/core/selectors/navModel';
|
import { getTitleFromNavModel } from 'app/core/selectors/navModel';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import PageHeader from '../PageHeader/PageHeader';
|
import PageHeader from '../PageHeader/PageHeader';
|
||||||
import Footer from '../Footer/Footer';
|
import { Footer } from '../Footer/Footer';
|
||||||
import PageContents from './PageContents';
|
import PageContents from './PageContents';
|
||||||
import { CustomScrollbar } from '@grafana/ui';
|
import { CustomScrollbar } from '@grafana/ui';
|
||||||
import { NavModel } from '@grafana/data';
|
import { NavModel } from '@grafana/data';
|
||||||
@ -45,20 +44,13 @@ class Page extends Component<Props> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { navModel } = this.props;
|
const { navModel } = this.props;
|
||||||
const { buildInfo } = config;
|
|
||||||
return (
|
return (
|
||||||
<div className="page-scrollbar-wrapper">
|
<div className="page-scrollbar-wrapper">
|
||||||
<CustomScrollbar autoHeightMin={'100%'} className="custom-scrollbar--page">
|
<CustomScrollbar autoHeightMin={'100%'} className="custom-scrollbar--page">
|
||||||
<div className="page-scrollbar-content">
|
<div className="page-scrollbar-content">
|
||||||
<PageHeader model={navModel} />
|
<PageHeader model={navModel} />
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
<Footer
|
<Footer />
|
||||||
appName="Grafana"
|
|
||||||
buildCommit={buildInfo.commit}
|
|
||||||
buildVersion={buildInfo.version}
|
|
||||||
newGrafanaVersion={buildInfo.latestVersion}
|
|
||||||
newGrafanaVersionExists={buildInfo.hasUpdate}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</CustomScrollbar>
|
</CustomScrollbar>
|
||||||
</div>
|
</div>
|
||||||
|
@ -90,11 +90,9 @@ describe('Render', () => {
|
|||||||
describe('Functions', () => {
|
describe('Functions', () => {
|
||||||
describe('item clicked', () => {
|
describe('item clicked', () => {
|
||||||
const wrapper = setup();
|
const wrapper = setup();
|
||||||
const mockEvent = { preventDefault: jest.fn() };
|
|
||||||
it('should emit show modal event if url matches shortcut', () => {
|
it('should emit show modal event if url matches shortcut', () => {
|
||||||
const child = { url: '/shortcuts', text: 'hello' };
|
|
||||||
const instance = wrapper.instance() as BottomNavLinks;
|
const instance = wrapper.instance() as BottomNavLinks;
|
||||||
instance.itemClicked(mockEvent as any, child);
|
instance.onOpenShortcuts();
|
||||||
|
|
||||||
expect(appEvents.emit).toHaveBeenCalledWith(CoreEvents.showModal, { templateHtml: '<help-modal></help-modal>' });
|
expect(appEvents.emit).toHaveBeenCalledWith(CoreEvents.showModal, { templateHtml: '<help-modal></help-modal>' });
|
||||||
});
|
});
|
||||||
|
@ -4,6 +4,7 @@ import { User } from '../../services/context_srv';
|
|||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { CoreEvents } from 'app/types';
|
import { CoreEvents } from 'app/types';
|
||||||
import { OrgSwitcher } from '../OrgSwitcher';
|
import { OrgSwitcher } from '../OrgSwitcher';
|
||||||
|
import { getFooterLinks } from '../Footer/Footer';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
link: NavModelItem;
|
link: NavModelItem;
|
||||||
@ -19,13 +20,10 @@ class BottomNavLinks extends PureComponent<Props, State> {
|
|||||||
showSwitcherModal: false,
|
showSwitcherModal: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
itemClicked = (event: React.SyntheticEvent, child: NavModelItem) => {
|
onOpenShortcuts = () => {
|
||||||
if (child.url === '/shortcuts') {
|
|
||||||
event.preventDefault();
|
|
||||||
appEvents.emit(CoreEvents.showModal, {
|
appEvents.emit(CoreEvents.showModal, {
|
||||||
templateHtml: '<help-modal></help-modal>',
|
templateHtml: '<help-modal></help-modal>',
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleSwitcherModal = () => {
|
toggleSwitcherModal = () => {
|
||||||
@ -38,6 +36,12 @@ class BottomNavLinks extends PureComponent<Props, State> {
|
|||||||
const { link, user } = this.props;
|
const { link, user } = this.props;
|
||||||
const { showSwitcherModal } = this.state;
|
const { showSwitcherModal } = this.state;
|
||||||
|
|
||||||
|
let children = link.children || [];
|
||||||
|
|
||||||
|
if (link.id === 'help') {
|
||||||
|
children = getFooterLinks();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sidemenu-item dropdown dropup">
|
<div className="sidemenu-item dropdown dropup">
|
||||||
<a href={link.url} className="sidemenu-link" target={link.target}>
|
<a href={link.url} className="sidemenu-link" target={link.target}>
|
||||||
@ -69,20 +73,25 @@ class BottomNavLinks extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
{showSwitcherModal && <OrgSwitcher onDismiss={this.toggleSwitcherModal} />}
|
{showSwitcherModal && <OrgSwitcher onDismiss={this.toggleSwitcherModal} />}
|
||||||
|
|
||||||
{link.children &&
|
{children.map((child, index) => {
|
||||||
link.children.map((child, index) => {
|
|
||||||
if (!child.hideFromMenu) {
|
|
||||||
return (
|
return (
|
||||||
<li key={`${child.text}-${index}`}>
|
<li key={`${child.text}-${index}`}>
|
||||||
<a href={child.url} target={child.target} onClick={event => this.itemClicked(event, child)}>
|
<a href={child.url} target="_blank" rel="noopener">
|
||||||
{child.icon && <i className={child.icon} />}
|
{child.icon && <i className={child.icon} />}
|
||||||
{child.text}
|
{child.text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
{link.id === 'help' && (
|
||||||
|
<li key="keyboard-shortcuts">
|
||||||
|
<a onClick={() => this.onOpenShortcuts()}>
|
||||||
|
<i className="fa fa-keyboard-o" /> Keyboard shortcuts
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
|
||||||
<li className="side-menu-header">
|
<li className="side-menu-header">
|
||||||
<span className="sidemenu-item-text">{link.text}</span>
|
<span className="sidemenu-item-text">{link.text}</span>
|
||||||
</li>
|
</li>
|
||||||
|
@ -19,21 +19,32 @@ exports[`Render should render children 1`] = `
|
|||||||
key="undefined-0"
|
key="undefined-0"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={[Function]}
|
rel="noopener"
|
||||||
|
target="_blank"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
key="undefined-1"
|
key="undefined-1"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={[Function]}
|
rel="noopener"
|
||||||
|
target="_blank"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
key="undefined-2"
|
key="undefined-2"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={[Function]}
|
rel="noopener"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
key="undefined-3"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
rel="noopener"
|
||||||
|
target="_blank"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
import config from 'app/core/config';
|
|
||||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
|
||||||
import { NavModelSrv } from 'app/core/core';
|
|
||||||
|
|
||||||
export default class StyleGuideCtrl {
|
|
||||||
theme: string;
|
|
||||||
buttonNames = ['primary', 'secondary', 'inverse', 'success', 'warning', 'danger'];
|
|
||||||
buttonSizes = ['btn-small', '', 'btn-large'];
|
|
||||||
buttonVariants = ['-'];
|
|
||||||
navModel: any;
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
constructor(private $routeParams: any, private backendSrv: BackendSrv, navModelSrv: NavModelSrv) {
|
|
||||||
this.navModel = navModelSrv.getNav('admin', 'styleguide', 0);
|
|
||||||
this.theme = config.bootData.user.lightTheme ? 'light' : 'dark';
|
|
||||||
}
|
|
||||||
|
|
||||||
switchTheme() {
|
|
||||||
this.$routeParams.theme = this.theme === 'dark' ? 'light' : 'dark';
|
|
||||||
|
|
||||||
const cmd = {
|
|
||||||
theme: this.$routeParams.theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.backendSrv.put('/api/user/preferences', cmd).then(() => {
|
|
||||||
window.location.href = window.location.href;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -159,13 +159,14 @@ exports[`ServerStats Should render table with stats 1`] = `
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="http://docs.grafana.org"
|
href="https://grafana.com/docs/grafana/latest/?utm_source=grafana_footer"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-file-code-o"
|
className="fa fa-file-code-o"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -178,18 +179,20 @@ exports[`ServerStats Should render table with stats 1`] = `
|
|||||||
<i
|
<i
|
||||||
className="fa fa-support"
|
className="fa fa-support"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Support & Enterprise
|
Support & Enterprise
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://community.grafana.com/"
|
href="https://community.grafana.com/?utm_source=grafana_footer"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-comments-o"
|
className="fa fa-comments-o"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Community
|
Community
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -199,16 +202,10 @@ exports[`ServerStats Should render table with stats 1`] = `
|
|||||||
rel="noopener"
|
rel="noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
Grafana
|
<i />
|
||||||
</a>
|
|
||||||
|
|
||||||
<span>
|
Grafana vv1.0 (commit: 1)
|
||||||
v
|
</a>
|
||||||
v1.0
|
|
||||||
(commit:
|
|
||||||
1
|
|
||||||
)
|
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,6 @@ import AdminListUsersCtrl from './AdminListUsersCtrl';
|
|||||||
import AdminEditUserCtrl from './AdminEditUserCtrl';
|
import AdminEditUserCtrl from './AdminEditUserCtrl';
|
||||||
import AdminListOrgsCtrl from './AdminListOrgsCtrl';
|
import AdminListOrgsCtrl from './AdminListOrgsCtrl';
|
||||||
import AdminEditOrgCtrl from './AdminEditOrgCtrl';
|
import AdminEditOrgCtrl from './AdminEditOrgCtrl';
|
||||||
import StyleGuideCtrl from './StyleGuideCtrl';
|
|
||||||
|
|
||||||
import coreModule from 'app/core/core_module';
|
import coreModule from 'app/core/core_module';
|
||||||
import { NavModelSrv } from 'app/core/core';
|
import { NavModelSrv } from 'app/core/core';
|
||||||
@ -21,4 +20,3 @@ coreModule.controller('AdminEditUserCtrl', AdminEditUserCtrl);
|
|||||||
coreModule.controller('AdminListOrgsCtrl', AdminListOrgsCtrl);
|
coreModule.controller('AdminListOrgsCtrl', AdminListOrgsCtrl);
|
||||||
coreModule.controller('AdminEditOrgCtrl', AdminEditOrgCtrl);
|
coreModule.controller('AdminEditOrgCtrl', AdminEditOrgCtrl);
|
||||||
coreModule.controller('AdminHomeCtrl', AdminHomeCtrl);
|
coreModule.controller('AdminHomeCtrl', AdminHomeCtrl);
|
||||||
coreModule.controller('StyleGuideCtrl', StyleGuideCtrl);
|
|
||||||
|
@ -9,3 +9,4 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -42,3 +42,5 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -181,3 +181,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -28,3 +28,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -37,3 +37,5 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -76,3 +76,5 @@
|
|||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -75,3 +75,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -57,3 +57,5 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -32,3 +32,5 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -3,3 +3,5 @@
|
|||||||
<div class="page-container page-body">
|
<div class="page-container page-body">
|
||||||
<manage-dashboards ng-if="ctrl.folderId && ctrl.uid" folder-id="ctrl.folderId" folder-uid="ctrl.uid" />
|
<manage-dashboards ng-if="ctrl.folderId && ctrl.uid" folder-id="ctrl.folderId" folder-uid="ctrl.uid" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -157,3 +157,5 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -3,3 +3,5 @@
|
|||||||
<div class="page-container page-body">
|
<div class="page-container page-body">
|
||||||
<manage-dashboards />
|
<manage-dashboards />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -34,3 +34,5 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -20,3 +20,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -24,3 +24,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -100,3 +100,5 @@
|
|||||||
<a class="btn-text" ng-click="ctrl.backToList()">Cancel</a>
|
<a class="btn-text" ng-click="ctrl.backToList()">Cancel</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -64,3 +64,5 @@
|
|||||||
proTipTarget="'_blank'" />
|
proTipTarget="'_blank'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -8,3 +8,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -32,3 +32,5 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -45,3 +45,5 @@
|
|||||||
<span class="react-resizable-handle" style="cursor: default"></span>
|
<span class="react-resizable-handle" style="cursor: default"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -54,3 +54,5 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -33,4 +33,4 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -43,3 +43,5 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer />
|
||||||
|
@ -378,11 +378,6 @@ export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locati
|
|||||||
controller: 'AppPageCtrl',
|
controller: 'AppPageCtrl',
|
||||||
controllerAs: 'ctrl',
|
controllerAs: 'ctrl',
|
||||||
})
|
})
|
||||||
.when('/styleguide/:page?', {
|
|
||||||
controller: 'StyleGuideCtrl',
|
|
||||||
controllerAs: 'ctrl',
|
|
||||||
templateUrl: 'public/app/features/admin/partials/styleguide.html',
|
|
||||||
})
|
|
||||||
.when('/alerting', {
|
.when('/alerting', {
|
||||||
redirectTo: '/alerting/list',
|
redirectTo: '/alerting/list',
|
||||||
})
|
})
|
||||||
|
@ -103,7 +103,6 @@
|
|||||||
@import 'pages/alerting';
|
@import 'pages/alerting';
|
||||||
@import 'pages/history';
|
@import 'pages/history';
|
||||||
@import 'pages/signup';
|
@import 'pages/signup';
|
||||||
@import 'pages/styleguide';
|
|
||||||
@import 'pages/errorpage';
|
@import 'pages/errorpage';
|
||||||
@import 'pages/explore';
|
@import 'pages/explore';
|
||||||
@import 'pages/plugins';
|
@import 'pages/plugins';
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
color: $footer-link-hover;
|
color: $footer-link-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
display: inline-block;
|
||||||
|
padding-right: $space-xxs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@ -23,10 +28,10 @@
|
|||||||
|
|
||||||
li {
|
li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-right: 2px;
|
|
||||||
&::after {
|
&::after {
|
||||||
content: ' | ';
|
content: ' | ';
|
||||||
padding-left: 2px;
|
padding: 0 $space-sm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,15 +43,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-react .footer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is-react .custom-scrollbar .footer {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keeping footer inside the graphic on Login screen
|
|
||||||
.login-page {
|
.login-page {
|
||||||
.footer {
|
.footer {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
.style-guide-color-card {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: $spacer;
|
|
||||||
width: 100%;
|
|
||||||
text-align: left;
|
|
||||||
text-shadow: 0 0 8px #fff;
|
|
||||||
color: $black;
|
|
||||||
font-size: $font-size-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.color-card-body-bg {
|
|
||||||
background-color: $body-bg;
|
|
||||||
}
|
|
||||||
.color-card-page-bg {
|
|
||||||
background-color: $page-bg;
|
|
||||||
}
|
|
||||||
.color-card-gray {
|
|
||||||
background-color: $gray-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.style-guide-button-list {
|
|
||||||
padding: $spacer;
|
|
||||||
button {
|
|
||||||
display: block;
|
|
||||||
margin: 0 $spacer $spacer 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.style-guide-icon-list {
|
|
||||||
font-size: 1.8em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
@ -214,45 +214,7 @@
|
|||||||
<dashboard-search></dashboard-search>
|
<dashboard-search></dashboard-search>
|
||||||
|
|
||||||
<div class="main-view">
|
<div class="main-view">
|
||||||
<div class="scroll-canvas">
|
<div ng-view class="scroll-canvas"></div>
|
||||||
<div ng-view></div>
|
|
||||||
|
|
||||||
<footer class="footer">
|
|
||||||
<div class="text-center">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="http://docs.grafana.org" target="_blank">
|
|
||||||
<i class="fa fa-file-code-o"></i>
|
|
||||||
Docs
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://grafana.com/services/support" target="_blank">
|
|
||||||
<i class="fa fa-support"></i>
|
|
||||||
Support Plans
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://community.grafana.com/" target="_blank">
|
|
||||||
<i class="fa fa-comments-o"></i>
|
|
||||||
Community
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://grafana.com" target="_blank">[[.AppName]]</a>
|
|
||||||
<span>v[[.BuildVersion]] (commit: [[.BuildCommit]])</span>
|
|
||||||
</li>
|
|
||||||
[[if .NewGrafanaVersionExists]]
|
|
||||||
<li>
|
|
||||||
<a href="https://grafana.com/get" target="_blank" bs-tooltip="'[[.NewGrafanaVersion]]'">
|
|
||||||
New version available!
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
[[end]]
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</grafana-app>
|
</grafana-app>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user