mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
commit
a402a3713f
@ -8,6 +8,16 @@ jest.mock('../../app_events', () => ({
|
|||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock('app/store/store', () => ({
|
||||||
|
store: {
|
||||||
|
getState: jest.fn().mockReturnValue({
|
||||||
|
location: {
|
||||||
|
lastUpdated: 0,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
jest.mock('app/core/services/context_srv', () => ({
|
jest.mock('app/core/services/context_srv', () => ({
|
||||||
contextSrv: {
|
contextSrv: {
|
||||||
sidemenu: true,
|
sidemenu: true,
|
||||||
|
@ -3,9 +3,16 @@ import appEvents from '../../app_events';
|
|||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import TopSection from './TopSection';
|
import TopSection from './TopSection';
|
||||||
import BottomSection from './BottomSection';
|
import BottomSection from './BottomSection';
|
||||||
|
import { store } from 'app/store/store';
|
||||||
|
|
||||||
export class SideMenu extends PureComponent {
|
export class SideMenu extends PureComponent {
|
||||||
toggleSideMenu = () => {
|
toggleSideMenu = () => {
|
||||||
|
// ignore if we just made a location change, stops hiding sidemenu on double clicks of back button
|
||||||
|
const timeSinceLocationChanged = new Date().getTime() - store.getState().location.lastUpdated;
|
||||||
|
if (timeSinceLocationChanged < 1000) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
contextSrv.toggleSideMenu();
|
contextSrv.toggleSideMenu();
|
||||||
appEvents.emit('toggle-sidemenu');
|
appEvents.emit('toggle-sidemenu');
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,7 @@ export const initialState: LocationState = {
|
|||||||
query: {},
|
query: {},
|
||||||
routeParams: {},
|
routeParams: {},
|
||||||
replace: false,
|
replace: false,
|
||||||
|
lastUpdated: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const locationReducer = (state = initialState, action: Action): LocationState => {
|
export const locationReducer = (state = initialState, action: Action): LocationState => {
|
||||||
@ -28,6 +29,7 @@ export const locationReducer = (state = initialState, action: Action): LocationS
|
|||||||
query: { ...query },
|
query: { ...query },
|
||||||
routeParams: routeParams || state.routeParams,
|
routeParams: routeParams || state.routeParams,
|
||||||
replace: replace === true,
|
replace: replace === true,
|
||||||
|
lastUpdated: new Date().getTime(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,13 @@ import { PlaylistSrv } from 'app/features/playlist/playlist_srv';
|
|||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { DashNavButton } from './DashNavButton';
|
import { DashNavButton } from './DashNavButton';
|
||||||
|
import { Tooltip } from '@grafana/ui';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
import { updateLocation } from 'app/core/actions';
|
import { updateLocation } from 'app/core/actions';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { DashboardModel } from '../../state/DashboardModel';
|
import { DashboardModel } from '../../state';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
dashboard: DashboardModel;
|
dashboard: DashboardModel;
|
||||||
@ -33,7 +34,6 @@ export class DashNav extends PureComponent<Props> {
|
|||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.playlistSrv = this.props.$injector.get('playlistSrv');
|
this.playlistSrv = this.props.$injector.get('playlistSrv');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,26 +123,54 @@ export class DashNav extends PureComponent<Props> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
renderDashboardTitleSearchButton() {
|
||||||
const { dashboard, isFullscreen, editview, onAddPanel } = this.props;
|
const { dashboard } = this.props;
|
||||||
const { canStar, canSave, canShare, folderTitle, showSettings, isStarred } = dashboard.meta;
|
|
||||||
const { snapshot } = dashboard;
|
|
||||||
|
|
||||||
|
const folderTitle = dashboard.meta.folderTitle;
|
||||||
const haveFolder = dashboard.meta.folderId > 0;
|
const haveFolder = dashboard.meta.folderId > 0;
|
||||||
const snapshotUrl = snapshot && snapshot.originalUrl;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="navbar">
|
<>
|
||||||
<div>
|
<div>
|
||||||
<a className="navbar-page-btn" onClick={this.onOpenSearch}>
|
<a className="navbar-page-btn" onClick={this.onOpenSearch}>
|
||||||
<i className="gicon gicon-dashboard" />
|
{!this.isInFullscreenOrSettings && <i className="gicon gicon-dashboard" />}
|
||||||
{haveFolder && <span className="navbar-page-btn--folder">{folderTitle} / </span>}
|
{haveFolder && <span className="navbar-page-btn--folder">{folderTitle} / </span>}
|
||||||
{dashboard.title}
|
{dashboard.title}
|
||||||
<i className="fa fa-caret-down" />
|
<i className="fa fa-caret-down" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="navbar__spacer" />
|
<div className="navbar__spacer" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get isInFullscreenOrSettings() {
|
||||||
|
return this.props.editview || this.props.isFullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderBackButton() {
|
||||||
|
return (
|
||||||
|
<div className="navbar-edit">
|
||||||
|
<Tooltip content="Go back (Esc)">
|
||||||
|
<button className="navbar-edit__back-btn" onClick={this.onClose}>
|
||||||
|
<i className="fa fa-arrow-left" />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { dashboard, onAddPanel } = this.props;
|
||||||
|
const { canStar, canSave, canShare, showSettings, isStarred } = dashboard.meta;
|
||||||
|
const { snapshot } = dashboard;
|
||||||
|
|
||||||
|
const snapshotUrl = snapshot && snapshot.originalUrl;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="navbar">
|
||||||
|
{this.isInFullscreenOrSettings && this.renderBackButton()}
|
||||||
|
{this.renderDashboardTitleSearchButton()}
|
||||||
|
|
||||||
{this.playlistSrv.isPlaying && (
|
{this.playlistSrv.isPlaying && (
|
||||||
<div className="navbar-buttons navbar-buttons--playlist">
|
<div className="navbar-buttons navbar-buttons--playlist">
|
||||||
@ -228,17 +256,6 @@ export class DashNav extends PureComponent<Props> {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="gf-timepicker-nav" ref={element => (this.timePickerEl = element)} />
|
<div className="gf-timepicker-nav" ref={element => (this.timePickerEl = element)} />
|
||||||
|
|
||||||
{(isFullscreen || editview) && (
|
|
||||||
<div className="navbar-buttons navbar-buttons--close">
|
|
||||||
<DashNavButton
|
|
||||||
tooltip="Back to dashboard"
|
|
||||||
classSuffix="primary"
|
|
||||||
icon="fa fa-reply"
|
|
||||||
onClick={this.onClose}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import { createLogger } from 'redux-logger';
|
// import { createLogger } from 'redux-logger';
|
||||||
import sharedReducers from 'app/core/reducers';
|
import sharedReducers from 'app/core/reducers';
|
||||||
import alertingReducers from 'app/features/alerting/state/reducers';
|
import alertingReducers from 'app/features/alerting/state/reducers';
|
||||||
import teamsReducers from 'app/features/teams/state/reducers';
|
import teamsReducers from 'app/features/teams/state/reducers';
|
||||||
@ -41,7 +41,7 @@ export function configureStore() {
|
|||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
// DEV builds we had the logger middleware
|
// DEV builds we had the logger middleware
|
||||||
setStore(createStore(rootReducer, {}, composeEnhancers(applyMiddleware(thunk, createLogger()))));
|
setStore(createStore(rootReducer, {}, composeEnhancers(applyMiddleware(thunk))));
|
||||||
} else {
|
} else {
|
||||||
setStore(createStore(rootReducer, {}, composeEnhancers(applyMiddleware(thunk))));
|
setStore(createStore(rootReducer, {}, composeEnhancers(applyMiddleware(thunk))));
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ export interface LocationState {
|
|||||||
query: UrlQueryMap;
|
query: UrlQueryMap;
|
||||||
routeParams: UrlQueryMap;
|
routeParams: UrlQueryMap;
|
||||||
replace: boolean;
|
replace: boolean;
|
||||||
|
lastUpdated: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[];
|
export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.navbar {
|
.navbar {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 40px;
|
padding-left: 20px;
|
||||||
z-index: $zindex-navbar-fixed;
|
z-index: $zindex-navbar-fixed;
|
||||||
height: $navbarHeight;
|
height: $navbarHeight;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
@ -41,15 +41,12 @@
|
|||||||
|
|
||||||
.panel-in-fullscreen {
|
.panel-in-fullscreen {
|
||||||
.navbar {
|
.navbar {
|
||||||
padding-left: 15px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-button--add-panel,
|
.navbar-button--add-panel,
|
||||||
.navbar-button--star,
|
.navbar-button--star,
|
||||||
.navbar-button--tv,
|
.navbar-button--tv,
|
||||||
.navbar-page-btn .fa-caret-down {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-buttons--close {
|
.navbar-buttons--close {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -179,3 +176,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar-edit {
|
||||||
|
display: flex;
|
||||||
|
height: $navbarHeight;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-edit__back-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid $text-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
transition: transform 0.1s ease 0.1s;
|
||||||
|
color: $text-color;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
position: relative;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $text-color-strong;
|
||||||
|
border-color: $text-color-strong;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +86,10 @@
|
|||||||
.panel-editor-container__panel {
|
.panel-editor-container__panel {
|
||||||
margin: 0 $dashboard-padding;
|
margin: 0 $dashboard-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-container {
|
||||||
|
left: 0 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-editor-container__resizer {
|
.panel-editor-container__resizer {
|
||||||
|
@ -21,9 +21,9 @@
|
|||||||
// Search
|
// Search
|
||||||
.search-field-wrapper {
|
.search-field-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: $navbarHeight;
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: $navbarBackground;
|
background-color: $navbarBackground;
|
||||||
box-shadow: $navbarShadow;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
& > input {
|
& > input {
|
||||||
|
Loading…
Reference in New Issue
Block a user