Przeglądaj źródła

Merge pull request #15339 from grafana/navbar-back-btn

Navbar back btn
Torkel Ödegaard 6 lat temu
rodzic
commit
a402a3713f

+ 10 - 0
public/app/core/components/sidemenu/SideMenu.test.tsx

@@ -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,

+ 7 - 0
public/app/core/components/sidemenu/SideMenu.tsx

@@ -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');
   };
   };

+ 2 - 0
public/app/core/reducers/location.ts

@@ -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(),
       };
       };
     }
     }
   }
   }

+ 38 - 21
public/app/features/dashboard/components/DashNav/DashNav.tsx

@@ -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() {
-    const { dashboard, isFullscreen, editview, onAddPanel } = this.props;
-    const { canStar, canSave, canShare, folderTitle, showSettings, isStarred } = dashboard.meta;
-    const { snapshot } = dashboard;
+  renderDashboardTitleSearchButton() {
+    const { dashboard } = this.props;
 
 
+    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>
     );
     );
   }
   }

+ 2 - 2
public/app/store/configureStore.ts

@@ -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))));
   }
   }

+ 1 - 0
public/app/types/location.ts

@@ -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[];

+ 32 - 5
public/sass/components/_navbar.scss

@@ -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;
+  }
+}
+
+

+ 4 - 0
public/sass/components/_panel_editor.scss

@@ -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 {

+ 1 - 1
public/sass/components/_search.scss

@@ -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 {