Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
bf24cbba
Unverified
Commit
bf24cbba
authored
Sep 20, 2019
by
Andrej Ocenas
Committed by
GitHub
Sep 20, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Explore: live tail UI fixes and improvements (#19187)
parent
9feac775
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
221 additions
and
75 deletions
+221
-75
public/app/features/explore/Explore.tsx
+13
-1
public/app/features/explore/ExploreToolbar.tsx
+21
-8
public/app/features/explore/LiveLogs.tsx
+2
-2
public/app/features/explore/LiveTailButton.tsx
+62
-23
public/app/features/explore/Logs.tsx
+0
-1
public/app/features/explore/LogsContainer.tsx
+39
-36
public/app/features/explore/ResponsiveButton.tsx
+12
-2
public/app/features/explore/RunButton.tsx
+2
-1
public/app/features/explore/state/reducers.ts
+1
-1
public/app/features/explore/utils/LogsCrossFadeTransition.tsx
+69
-0
No files found.
public/app/features/explore/Explore.tsx
View file @
bf24cbba
// Libraries
import
React
,
{
ComponentClass
}
from
'react'
;
import
{
hot
}
from
'react-hot-loader'
;
import
{
css
}
from
'emotion'
;
// @ts-ignore
import
{
connect
}
from
'react-redux'
;
import
{
AutoSizer
}
from
'react-virtualized'
;
...
...
@@ -52,6 +53,16 @@ import { ErrorContainer } from './ErrorContainer';
import
{
scanStopAction
}
from
'./state/actionTypes'
;
import
{
ExploreGraphPanel
}
from
'./ExploreGraphPanel'
;
const
getStyles
=
memoizeOne
(()
=>
{
return
{
logsMain
:
css
`
label: logsMain;
// Is needed for some transition animations to work.
position: relative;
`
,
};
});
interface
ExploreProps
{
StartPage
?:
ComponentClass
<
ExploreStartPageProps
>
;
changeSize
:
typeof
changeSize
;
...
...
@@ -257,6 +268,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
queryResponse
,
}
=
this
.
props
;
const
exploreClass
=
split
?
'explore explore-split'
:
'explore'
;
const
styles
=
getStyles
();
return
(
<
div
className=
{
exploreClass
}
ref=
{
this
.
getRef
}
>
...
...
@@ -284,7 +296,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
}
return
(
<
main
className=
"m-t-2"
style=
{
{
width
}
}
>
<
main
className=
{
`m-t-2 ${styles.logsMain}`
}
style=
{
{
width
}
}
>
<
ErrorBoundaryAlert
>
{
showingStartPage
&&
(
<
div
className=
"grafana-info-box grafana-info-box--max-lg"
>
...
...
public/app/features/explore/ExploreToolbar.tsx
View file @
bf24cbba
...
...
@@ -4,6 +4,7 @@ import { connect } from 'react-redux';
import
{
hot
}
from
'react-hot-loader'
;
import
memoizeOne
from
'memoize-one'
;
import
classNames
from
'classnames'
;
import
{
css
}
from
'emotion'
;
import
{
ExploreId
,
ExploreItemState
,
ExploreMode
}
from
'app/types/explore'
;
import
{
...
...
@@ -39,6 +40,14 @@ import { LiveTailButton } from './LiveTailButton';
import
{
ResponsiveButton
}
from
'./ResponsiveButton'
;
import
{
RunButton
}
from
'./RunButton'
;
const
getStyles
=
memoizeOne
(()
=>
{
return
{
liveTailButtons
:
css
`
margin-left: 10px;
`
,
};
});
interface
OwnProps
{
exploreId
:
ExploreId
;
onChangeTime
:
(
range
:
RawTimeRange
,
changedByScanner
?:
boolean
)
=>
void
;
...
...
@@ -132,6 +141,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
stopLive
=
()
=>
{
const
{
exploreId
}
=
this
.
props
;
this
.
pauseLive
();
// TODO referencing this from perspective of refresh picker when there is designated button for it now is not
// great. Needs another refactor.
this
.
props
.
changeRefreshIntervalAction
({
exploreId
,
refreshInterval
:
RefreshPicker
.
offOption
.
value
});
...
...
@@ -174,6 +184,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
originPanelId
,
}
=
this
.
props
;
const
styles
=
getStyles
();
const
originDashboardIsEditable
=
Number
.
isInteger
(
originPanelId
);
const
panelReturnClasses
=
classNames
(
'btn'
,
'navbar-button'
,
{
'btn--radius-right-0'
:
originDashboardIsEditable
,
...
...
@@ -293,14 +304,16 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
</
div
>
{
hasLiveOption
&&
(
<
LiveTailButton
isLive=
{
isLive
}
isPaused=
{
isPaused
}
start=
{
this
.
startLive
}
pause=
{
this
.
pauseLive
}
resume=
{
this
.
resumeLive
}
stop=
{
this
.
stopLive
}
/>
<
div
className=
{
`explore-toolbar-content-item ${styles.liveTailButtons}`
}
>
<
LiveTailButton
isLive=
{
isLive
}
isPaused=
{
isPaused
}
start=
{
this
.
startLive
}
pause=
{
this
.
pauseLive
}
resume=
{
this
.
resumeLive
}
stop=
{
this
.
stopLive
}
/>
</
div
>
)
}
</
div
>
</
div
>
...
...
public/app/features/explore/LiveLogs.tsx
View file @
bf24cbba
...
...
@@ -157,7 +157,7 @@ class LiveLogs extends PureComponent<Props, State> {
const
{
logsRow
,
logsRowLocalTime
,
logsRowMessage
}
=
getLogRowStyles
(
theme
);
return
(
<>
<
div
>
<
div
onScroll=
{
isPaused
?
undefined
:
this
.
onScroll
}
className=
{
cx
([
'logs-rows'
,
styles
.
logsRowsLive
])
}
...
...
@@ -210,7 +210,7 @@ class LiveLogs extends PureComponent<Props, State> {
</
span
>
)
}
</
div
>
</>
</
div
>
);
}
}
...
...
public/app/features/explore/LiveTailButton.tsx
View file @
bf24cbba
...
...
@@ -2,28 +2,30 @@ import React from 'react';
import
classNames
from
'classnames'
;
import
{
css
}
from
'emotion'
;
import
memoizeOne
from
'memoize-one'
;
import
{
GrafanaTheme
,
GrafanaThemeType
,
useTheme
}
from
'@grafana/ui'
;
import
tinycolor
from
'tinycolor2'
;
import
{
CSSTransition
}
from
'react-transition-group'
;
const
orangeDark
=
'#FF780A'
;
const
orangeDarkLighter
=
tinycolor
(
orangeDark
)
.
lighten
(
10
)
.
toString
();
const
orangeLight
=
'#ED5700'
;
const
orangeLightLighter
=
tinycolor
(
orangeLight
)
.
lighten
(
10
)
.
toString
();
import
{
GrafanaTheme
,
GrafanaThemeType
,
useTheme
}
from
'@grafana/ui'
;
const
getStyles
=
memoizeOne
((
theme
:
GrafanaTheme
)
=>
{
const
orange
=
theme
.
type
===
GrafanaThemeType
.
Dark
?
orangeDark
:
orangeLight
;
const
orangeLighter
=
theme
.
type
===
GrafanaThemeType
.
Dark
?
orangeDarkLighter
:
orangeLightLighter
;
const
textColor
=
theme
.
type
===
GrafanaThemeType
.
Dark
?
theme
.
colors
.
white
:
theme
.
colors
.
black
;
const
orange
=
theme
.
type
===
GrafanaThemeType
.
Dark
?
'#FF780A'
:
'#ED5700'
;
const
orangeLighter
=
tinycolor
(
orange
)
.
lighten
(
10
)
.
toString
();
const
pulseTextColor
=
tinycolor
(
orange
)
.
desaturate
(
90
)
.
toString
();
return
{
noRightBorderStyle
:
css
`
label: noRightBorderStyle;
border-right: 0;
`
,
liveButton
:
css
`
label: liveButton;
transition: background-color 1s, border-color 1s, color 1s;
margin: 0;
`
,
isLive
:
css
`
label: isLive;
border-color:
${
orange
}
;
...
...
@@ -43,7 +45,7 @@ const getStyles = memoizeOne((theme: GrafanaTheme) => {
label: isPaused;
border-color:
${
orange
}
;
background: transparent;
animation: pulse
2
s ease-out 0s infinite normal forwards;
animation: pulse
3
s ease-out 0s infinite normal forwards;
&:focus {
border-color:
${
orange
}
;
}
...
...
@@ -53,16 +55,40 @@ const getStyles = memoizeOne((theme: GrafanaTheme) => {
}
@keyframes pulse {
0% {
color:
${
t
extColor
}
;
color:
${
pulseT
extColor
}
;
}
50% {
color:
${
orange
}
;
}
100% {
color:
${
t
extColor
}
;
color:
${
pulseT
extColor
}
;
}
}
`
,
stopButtonEnter
:
css
`
label: stopButtonEnter;
width: 0;
opacity: 0;
overflow: hidden;
`
,
stopButtonEnterActive
:
css
`
label: stopButtonEnterActive;
opacity: 1;
width: 32px;
transition: opacity 500ms ease-in 50ms, width 500ms ease-in 50ms;
`
,
stopButtonExit
:
css
`
label: stopButtonExit;
width: 32px;
opacity: 1;
overflow: hidden;
`
,
stopButtonExitActive
:
css
`
label: stopButtonExitActive;
opacity: 0;
width: 0;
transition: opacity 500ms ease-in 50ms, width 500ms ease-in 50ms;
`
,
};
});
...
...
@@ -82,9 +108,9 @@ export function LiveTailButton(props: LiveTailButtonProps) {
const
onClickMain
=
isLive
?
(
isPaused
?
resume
:
pause
)
:
start
;
return
(
<
div
className=
"explore-toolbar-content-item"
>
<>
<
button
className=
{
classNames
(
'btn navbar-button'
,
{
className=
{
classNames
(
'btn navbar-button'
,
styles
.
liveButton
,
{
[
`btn--radius-right-0 ${styles.noRightBorderStyle}`
]:
isLive
,
[
styles
.
isLive
]:
isLive
&&
!
isPaused
,
[
styles
.
isPaused
]:
isLive
&&
isPaused
,
...
...
@@ -94,11 +120,24 @@ export function LiveTailButton(props: LiveTailButtonProps) {
<
i
className=
{
classNames
(
'fa'
,
isPaused
||
!
isLive
?
'fa-play'
:
'fa-pause'
)
}
/>
Live tailing
</
button
>
{
isLive
&&
(
<
button
className=
{
`btn navbar-button navbar-button--attached ${styles.isLive}`
}
onClick=
{
stop
}
>
<
i
className=
{
'fa fa-stop'
}
/>
</
button
>
)
}
</
div
>
<
CSSTransition
mountOnEnter=
{
true
}
unmountOnExit=
{
true
}
timeout=
{
500
}
in=
{
isLive
}
classNames=
{
{
enter
:
styles
.
stopButtonEnter
,
enterActive
:
styles
.
stopButtonEnterActive
,
exit
:
styles
.
stopButtonExit
,
exitActive
:
styles
.
stopButtonExitActive
,
}
}
>
<
div
>
<
button
className=
{
`btn navbar-button navbar-button--attached ${styles.isLive}`
}
onClick=
{
stop
}
>
<
i
className=
{
'fa fa-stop'
}
/>
</
button
>
</
div
>
</
CSSTransition
>
</>
);
}
public/app/features/explore/Logs.tsx
View file @
bf24cbba
import
_
from
'lodash'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
{
...
...
public/app/features/explore/LogsContainer.tsx
View file @
bf24cbba
...
...
@@ -27,6 +27,7 @@ import { deduplicatedLogsSelector, exploreItemUIStateSelector } from 'app/featur
import
{
getTimeZone
}
from
'../profile/state/selectors'
;
import
{
LiveLogsWithTheme
}
from
'./LiveLogs'
;
import
{
Logs
}
from
'./Logs'
;
import
{
LogsCrossFadeTransition
}
from
'./utils/LogsCrossFadeTransition'
;
interface
LogsContainerProps
{
datasourceInstance
:
DataSourceApi
|
null
;
...
...
@@ -64,6 +65,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
onStopLive
=
()
=>
{
const
{
exploreId
}
=
this
.
props
;
this
.
onPause
();
this
.
props
.
stopLive
({
exploreId
,
refreshInterval
:
RefreshPicker
.
offOption
.
value
});
};
...
...
@@ -116,43 +118,44 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
isLive
,
}
=
this
.
props
;
if
(
isLive
)
{
return
(
<
Collapse
label=
"Logs"
loading=
{
false
}
isOpen
>
<
LiveLogsWithTheme
logsResult=
{
logsResult
}
timeZone=
{
timeZone
}
stopLive=
{
this
.
onStopLive
}
isPaused=
{
this
.
props
.
isPaused
}
onPause=
{
this
.
onPause
}
onResume=
{
this
.
onResume
}
/>
</
Collapse
>
);
}
return
(
<
Collapse
label=
"Logs"
loading=
{
loading
}
isOpen
>
<
Logs
dedupStrategy=
{
this
.
props
.
dedupStrategy
||
LogsDedupStrategy
.
none
}
data=
{
logsResult
}
dedupedData=
{
dedupedResult
}
highlighterExpressions=
{
logsHighlighterExpressions
}
loading=
{
loading
}
onChangeTime=
{
this
.
onChangeTime
}
onClickLabel=
{
onClickLabel
}
onStartScanning=
{
onStartScanning
}
onStopScanning=
{
onStopScanning
}
onDedupStrategyChange=
{
this
.
handleDedupStrategyChange
}
onToggleLogLevel=
{
this
.
handleToggleLogLevel
}
absoluteRange=
{
absoluteRange
}
timeZone=
{
timeZone
}
scanning=
{
scanning
}
scanRange=
{
range
.
raw
}
width=
{
width
}
getRowContext=
{
this
.
getLogRowContext
}
/>
</
Collapse
>
<>
<
LogsCrossFadeTransition
visible=
{
isLive
}
>
<
Collapse
label=
"Logs"
loading=
{
false
}
isOpen
>
<
LiveLogsWithTheme
logsResult=
{
logsResult
}
timeZone=
{
timeZone
}
stopLive=
{
this
.
onStopLive
}
isPaused=
{
this
.
props
.
isPaused
}
onPause=
{
this
.
onPause
}
onResume=
{
this
.
onResume
}
/>
</
Collapse
>
</
LogsCrossFadeTransition
>
<
LogsCrossFadeTransition
visible=
{
!
isLive
}
>
<
Collapse
label=
"Logs"
loading=
{
loading
}
isOpen
>
<
Logs
dedupStrategy=
{
this
.
props
.
dedupStrategy
||
LogsDedupStrategy
.
none
}
data=
{
logsResult
}
dedupedData=
{
dedupedResult
}
highlighterExpressions=
{
logsHighlighterExpressions
}
loading=
{
loading
}
onChangeTime=
{
this
.
onChangeTime
}
onClickLabel=
{
onClickLabel
}
onStartScanning=
{
onStartScanning
}
onStopScanning=
{
onStopScanning
}
onDedupStrategyChange=
{
this
.
handleDedupStrategyChange
}
onToggleLogLevel=
{
this
.
handleToggleLogLevel
}
absoluteRange=
{
absoluteRange
}
timeZone=
{
timeZone
}
scanning=
{
scanning
}
scanRange=
{
range
.
raw
}
width=
{
width
}
getRowContext=
{
this
.
getLogRowContext
}
/>
</
Collapse
>
</
LogsCrossFadeTransition
>
</>
);
}
}
...
...
public/app/features/explore/ResponsiveButton.tsx
View file @
bf24cbba
...
...
@@ -28,9 +28,19 @@ export const ResponsiveButton = (props: Props) => {
onClick=
{
onClick
}
disabled=
{
disabled
||
false
}
>
{
iconClassName
&&
iconSide
===
IconSide
.
left
?
<
i
className=
{
`${iconClassName}`
}
/>
:
null
}
{
iconClassName
&&
iconSide
===
IconSide
.
left
?
(
<>
<
i
className=
{
`${iconClassName}`
}
/>
</>
)
:
null
}
<
span
className=
"btn-title"
>
{
!
splitted
?
title
:
''
}
</
span
>
{
iconClassName
&&
iconSide
===
IconSide
.
right
?
<
i
className=
{
`${iconClassName}`
}
/>
:
null
}
{
iconClassName
&&
iconSide
===
IconSide
.
right
?
(
<>
<
i
className=
{
`${iconClassName}`
}
/>
</>
)
:
null
}
</
button
>
);
};
public/app/features/explore/RunButton.tsx
View file @
bf24cbba
...
...
@@ -2,6 +2,7 @@ import React from 'react';
import
{
RefreshPicker
}
from
'@grafana/ui'
;
import
memoizeOne
from
'memoize-one'
;
import
{
css
}
from
'emotion'
;
import
classNames
from
'classnames'
;
import
{
ResponsiveButton
}
from
'./ResponsiveButton'
;
...
...
@@ -33,7 +34,7 @@ export function RunButton(props: Props) {
splitted=
{
splitted
}
title=
"Run Query"
onClick=
{
onRun
}
buttonClassName=
"navbar-button--secondary btn--radius-right-0 "
buttonClassName=
{
classNames
(
'navbar-button--secondary'
,
{
'btn--radius-right-0'
:
showDropdown
})
}
iconClassName=
{
loading
?
'fa fa-spinner fa-fw fa-spin run-icon'
:
'fa fa-refresh fa-fw'
}
/>
);
...
...
public/app/features/explore/state/reducers.ts
View file @
bf24cbba
...
...
@@ -206,7 +206,7 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
state
:
live
?
LoadingState
.
Streaming
:
LoadingState
.
NotStarted
,
},
isLive
:
live
,
isPaused
:
false
,
isPaused
:
live
?
false
:
state
.
isPaused
,
loading
:
live
,
logsResult
,
};
...
...
public/app/features/explore/utils/LogsCrossFadeTransition.tsx
0 → 100644
View file @
bf24cbba
import
React
from
'react'
;
import
memoizeOne
from
'memoize-one'
;
import
{
css
}
from
'emotion'
;
import
{
CSSTransition
}
from
'react-transition-group'
;
const
transitionDuration
=
500
;
// We add a bit of delay to the transition as another perf optimisation. As at the start we need to render
// quite a bit of new rows, if we start transition at the same time there can be frame rate drop. This gives time
// for react to first render them and then do the animation.
const
transitionDelay
=
100
;
const
getStyles
=
memoizeOne
(()
=>
{
return
{
logsEnter
:
css
`
label: logsEnter;
position: absolute;
opacity: 0;
height: auto;
width: auto;
`
,
logsEnterActive
:
css
`
label: logsEnterActive;
opacity: 1;
transition: opacity
${
transitionDuration
}
ms ease-out
${
transitionDelay
}
ms;
`
,
logsExit
:
css
`
label: logsExit;
position: absolute;
opacity: 1;
height: auto;
width: auto;
`
,
logsExitActive
:
css
`
label: logsExitActive;
opacity: 0;
transition: opacity
${
transitionDuration
}
ms ease-out
${
transitionDelay
}
ms;
`
,
};
});
type
Props
=
{
children
:
React
.
ReactNode
;
visible
:
boolean
;
};
/**
* Cross fade transition component that is tied a bit too much to the logs containers so not very useful elsewhere
* right now.
*/
export
function
LogsCrossFadeTransition
(
props
:
Props
)
{
const
{
visible
,
children
}
=
props
;
const
styles
=
getStyles
();
return
(
<
CSSTransition
in=
{
visible
}
mountOnEnter=
{
true
}
unmountOnExit=
{
true
}
timeout=
{
transitionDuration
+
transitionDelay
}
classNames=
{
{
enter
:
styles
.
logsEnter
,
enterActive
:
styles
.
logsEnterActive
,
exit
:
styles
.
logsExit
,
exitActive
:
styles
.
logsExitActive
,
}
}
>
{
children
}
</
CSSTransition
>
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment