feat(logs/popover): show message popover (#1157)
* add(logs/popover): add logs message popover * feat(logs/popover): display logs popover onclick * rename(logs/styles): renames logs styles w/ capital camel formatpull/10616/head
parent
1ef3ec7a76
commit
6a07d0d34b
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
ExpandableMessage
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.expandable--message {
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
align-items: center;
|
||||
cursor: zoom-in;
|
||||
display: block;
|
||||
|
||||
> .logs-message {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.expanded--message {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
white-space: pre-wrap;
|
||||
max-height: 300px;
|
||||
background-color: $g5-pepper;
|
||||
z-index: 100;
|
||||
border: solid $ix-border $c-pool;
|
||||
color: $g19-ghost;
|
||||
border-radius: $radius;
|
||||
cursor: text;
|
||||
transform: translate(-$ix-border, -$ix-border);
|
||||
font-size: 12px;
|
||||
font-family: $code-font;
|
||||
}
|
||||
|
||||
.expanded--dismiss {
|
||||
position: absolute;
|
||||
z-index: 5000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translate(-50%,-50%);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
outline: none;
|
||||
border-radius: 50%;
|
||||
background-color: $c-pool;
|
||||
transition: background-color 0.25s ease;
|
||||
border: 0;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 13px;
|
||||
height: 3px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
border-radius: 1px;
|
||||
background-color: $g20-white;
|
||||
}
|
||||
|
||||
&:before {
|
||||
transform: translate(-50%, -50%) rotate(45deg);
|
||||
}
|
||||
|
||||
&:after {
|
||||
transform: translate(-50%, -50%) rotate(-45deg);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $c-laser;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
// Libraries
|
||||
import React, {Component, MouseEvent} from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// Components
|
||||
import {ClickOutside} from 'src/shared/components/ClickOutside'
|
||||
import LogsMessage from 'src/logs/components/logs_message/LogsMessage'
|
||||
|
||||
// Types
|
||||
import {NotificationAction} from 'src/types'
|
||||
|
||||
// Decorators
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
interface State {
|
||||
expanded: boolean
|
||||
}
|
||||
|
||||
interface Props {
|
||||
formattedValue: string | JSX.Element
|
||||
notify: NotificationAction
|
||||
onExpand?: () => void
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
export class ExpandableMessage extends Component<Props, State> {
|
||||
private containerRef: React.RefObject<HTMLDivElement>
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.containerRef = React.createRef()
|
||||
this.state = {
|
||||
expanded: false,
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
onClick={this.handleClick}
|
||||
className="expandable--message"
|
||||
ref={this.containerRef}
|
||||
>
|
||||
{this.message}
|
||||
{this.expandedMessage}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private get message(): JSX.Element {
|
||||
const {notify, formattedValue} = this.props
|
||||
const valueString = `${formattedValue}`
|
||||
const trimmedValue = valueString.trimLeft()
|
||||
|
||||
return <LogsMessage formattedValue={trimmedValue} notify={notify} />
|
||||
}
|
||||
|
||||
private get expandedMessage() {
|
||||
const {expanded} = this.state
|
||||
|
||||
if (!expanded || !this.containerRef.current) {
|
||||
return null
|
||||
}
|
||||
|
||||
const portalElement = document.getElementById('expanded-message-container')
|
||||
const containerRect = this.containerRef.current.getBoundingClientRect()
|
||||
const padding = 8
|
||||
|
||||
const style = {
|
||||
top: containerRect.top - padding,
|
||||
left: containerRect.left - padding,
|
||||
width: containerRect.width + padding + padding,
|
||||
padding,
|
||||
}
|
||||
|
||||
const message = (
|
||||
<ClickOutside onClickOutside={this.handleClickOutside}>
|
||||
<div className="expanded--message" style={style}>
|
||||
{this.closeExpansionButton}
|
||||
{this.message}
|
||||
</div>
|
||||
</ClickOutside>
|
||||
)
|
||||
|
||||
return ReactDOM.createPortal(message, portalElement)
|
||||
}
|
||||
|
||||
private get closeExpansionButton(): JSX.Element {
|
||||
return (
|
||||
<button className="expanded--dismiss" onClick={this.handleClickDismiss} />
|
||||
)
|
||||
}
|
||||
|
||||
private handleClickDismiss = (e: MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
|
||||
this.setState({expanded: false})
|
||||
}
|
||||
|
||||
private handleClick = () => {
|
||||
const {expanded} = this.state
|
||||
const {onExpand} = this.props
|
||||
|
||||
if (!expanded && onExpand) {
|
||||
onExpand()
|
||||
}
|
||||
|
||||
this.setState({
|
||||
expanded: true,
|
||||
})
|
||||
}
|
||||
|
||||
private handleClickOutside = () => {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default ExpandableMessage
|
|
@ -10,6 +10,7 @@ import {color} from 'd3-color'
|
|||
import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar'
|
||||
import LoadingStatus from 'src/logs/components/loading_status/LoadingStatus'
|
||||
import LogsMessage from 'src/logs/components/logs_message/LogsMessage'
|
||||
import ExpandableMessage from 'src/logs/components/expandable_message/ExpandableMessage'
|
||||
|
||||
// Utils
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
@ -81,6 +82,7 @@ interface TableInfiniteScrollProps {
|
|||
}
|
||||
|
||||
interface TableHandlerProps {
|
||||
onExpand: () => void
|
||||
onChooseCustomTime: (time: string) => void
|
||||
onTagSelection: (selection: {tag: string; key: string}) => void
|
||||
}
|
||||
|
@ -664,6 +666,16 @@ class LogsTable extends Component<Props, State> {
|
|||
private renderMessage = (formattedValue: string): JSX.Element => {
|
||||
const {notify} = this.props
|
||||
|
||||
if (this.props.isTruncated) {
|
||||
return (
|
||||
<ExpandableMessage
|
||||
formattedValue={formattedValue}
|
||||
notify={notify}
|
||||
onExpand={this.props.onExpand}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return <LogsMessage notify={notify} formattedValue={formattedValue} />
|
||||
}
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ class LogsPage extends Component<Props, State> {
|
|||
/>
|
||||
<LogsTable
|
||||
data={this.tableData}
|
||||
onExpand={this.handleExpandMessage}
|
||||
onScrollVertical={this.handleVerticalScroll}
|
||||
onScrolledToTop={this.handleScrollToTop}
|
||||
isScrolledToTop={false}
|
||||
|
@ -184,6 +185,7 @@ class LogsPage extends Component<Props, State> {
|
|||
</div>
|
||||
</div>
|
||||
{this.configOverlay}
|
||||
{this.expandedMessageContainer}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -222,6 +224,15 @@ class LogsPage extends Component<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private get expandedMessageContainer(): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className="logs-viewer--expanded-message-container"
|
||||
id="expanded-message-container"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private get tableData(): TableData {
|
||||
const forwardData = applyChangesToTableData(
|
||||
this.props.tableInfiniteData.forward,
|
||||
|
@ -491,6 +502,10 @@ class LogsPage extends Component<Props, State> {
|
|||
this.setState({scrollMode})
|
||||
}
|
||||
|
||||
private handleExpandMessage = () => {
|
||||
this.handleVerticalScroll()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle choosing a custom time
|
||||
* @param time the custom date selected
|
||||
|
|
|
@ -51,8 +51,9 @@
|
|||
@import 'src/shared/components/views/Markdown';
|
||||
@import 'src/onboarding/OnboardingWizard.scss';
|
||||
|
||||
@import 'src/logs/containers/logs_page/logs-viewer';
|
||||
@import 'src/logs/components/loading_status/loading-status';
|
||||
@import 'src/logs/components/logs_filter_bar/logs-filter-bar';
|
||||
@import 'src/logs/components/options_overlay/logs-viewer-options';
|
||||
@import 'src/logs/components/logs_table/logs-table';
|
||||
@import 'src/logs/containers/logs_page/LogsPage';
|
||||
@import 'src/logs/components/loading_status/LoadingStatus';
|
||||
@import 'src/logs/components/logs_filter_bar/LogsFilterBar';
|
||||
@import 'src/logs/components/options_overlay/LogsViewerOptions';
|
||||
@import 'src/logs/components/logs_table/LogsTable';
|
||||
@import 'src/logs/components/expandable_message/ExpandableMessage';
|
||||
|
|
Loading…
Reference in New Issue