mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: display log line context (#17097)
* Extend DataSourceAPI to enable log row context retrieval * Add react-use package * Display log row context in UI * Make Loki datasource return "after" log context in correct order * Don't show Load more context links when there are no more new results * Update getLogRowContext to return DataQueryResponse * Use DataQueryResponse in log row context provider, filter out original row being duplicated in context
This commit is contained in:
parent
ae1df1cf89
commit
12e0616413
@ -224,6 +224,7 @@
|
|||||||
"react-sizeme": "2.5.2",
|
"react-sizeme": "2.5.2",
|
||||||
"react-table": "6.9.2",
|
"react-table": "6.9.2",
|
||||||
"react-transition-group": "2.6.1",
|
"react-transition-group": "2.6.1",
|
||||||
|
"react-use": "9.0.0",
|
||||||
"react-virtualized": "9.21.0",
|
"react-virtualized": "9.21.0",
|
||||||
"react-window": "1.7.1",
|
"react-window": "1.7.1",
|
||||||
"redux": "4.0.1",
|
"redux": "4.0.1",
|
||||||
|
@ -172,6 +172,11 @@ export abstract class DataSourceApi<
|
|||||||
*/
|
*/
|
||||||
getQueryDisplayText?(query: TQuery): string;
|
getQueryDisplayText?(query: TQuery): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve context for a given log row
|
||||||
|
*/
|
||||||
|
getLogRowContext?(row: any, limit?: number): Promise<DataQueryResponse>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set after constructor call, as the data source instance is the most common thing to pass around
|
* Set after constructor call, as the data source instance is the most common thing to pass around
|
||||||
* we attach the components to this instance for easy access
|
* we attach the components to this instance for easy access
|
||||||
@ -282,6 +287,10 @@ export interface DataQueryResponse {
|
|||||||
data: DataQueryResponseData[];
|
data: DataQueryResponseData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LogRowContextQueryResponse {
|
||||||
|
data: Array<Array<string | DataQueryError>>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface DataQuery {
|
export interface DataQuery {
|
||||||
/**
|
/**
|
||||||
* A - Z
|
* A - Z
|
||||||
|
@ -8,6 +8,16 @@ import { LogLabels } from './LogLabels';
|
|||||||
import { findHighlightChunksInText } from 'app/core/utils/text';
|
import { findHighlightChunksInText } from 'app/core/utils/text';
|
||||||
import { LogLabelStats } from './LogLabelStats';
|
import { LogLabelStats } from './LogLabelStats';
|
||||||
import { LogMessageAnsi } from './LogMessageAnsi';
|
import { LogMessageAnsi } from './LogMessageAnsi';
|
||||||
|
import { css, cx } from 'emotion';
|
||||||
|
import {
|
||||||
|
LogRowContextProvider,
|
||||||
|
LogRowContextRows,
|
||||||
|
HasMoreContextRows,
|
||||||
|
LogRowContextQueryErrors,
|
||||||
|
} from './LogRowContextProvider';
|
||||||
|
import { ThemeContext, selectThemeVariant, GrafanaTheme, DataQueryResponse } from '@grafana/ui';
|
||||||
|
import { LogRowContext } from './LogRowContext';
|
||||||
|
import tinycolor from 'tinycolor2';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
highlighterExpressions?: string[];
|
highlighterExpressions?: string[];
|
||||||
@ -18,6 +28,9 @@ interface Props {
|
|||||||
showUtc: boolean;
|
showUtc: boolean;
|
||||||
getRows: () => LogRowModel[];
|
getRows: () => LogRowModel[];
|
||||||
onClickLabel?: (label: string, value: string) => void;
|
onClickLabel?: (label: string, value: string) => void;
|
||||||
|
onContextClick?: () => void;
|
||||||
|
getRowContext?: (row: LogRowModel, limit: number) => Promise<DataQueryResponse>;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@ -29,6 +42,7 @@ interface State {
|
|||||||
parser?: LogsParser;
|
parser?: LogsParser;
|
||||||
parsedFieldHighlights: string[];
|
parsedFieldHighlights: string[];
|
||||||
showFieldStats: boolean;
|
showFieldStats: boolean;
|
||||||
|
showContext: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,6 +58,32 @@ const FieldHighlight = onClick => props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const logRowStyles = css`
|
||||||
|
position: relative;
|
||||||
|
/* z-index: 0; */
|
||||||
|
/* outline: none; */
|
||||||
|
`;
|
||||||
|
|
||||||
|
const getLogRowWithContextStyles = (theme: GrafanaTheme, state: State) => {
|
||||||
|
const outlineColor = selectThemeVariant(
|
||||||
|
{
|
||||||
|
light: theme.colors.white,
|
||||||
|
dark: theme.colors.black,
|
||||||
|
},
|
||||||
|
theme.type
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
row: css`
|
||||||
|
z-index: 1;
|
||||||
|
outline: 9999px solid
|
||||||
|
${tinycolor(outlineColor)
|
||||||
|
.setAlpha(0.7)
|
||||||
|
.toRgbString()};
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a log line.
|
* Renders a log line.
|
||||||
*
|
*
|
||||||
@ -63,6 +103,7 @@ export class LogRow extends PureComponent<Props, State> {
|
|||||||
parser: undefined,
|
parser: undefined,
|
||||||
parsedFieldHighlights: [],
|
parsedFieldHighlights: [],
|
||||||
showFieldStats: false,
|
showFieldStats: false,
|
||||||
|
showContext: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@ -89,11 +130,21 @@ export class LogRow extends PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMouseOverMessage = () => {
|
onMouseOverMessage = () => {
|
||||||
|
if (this.state.showContext) {
|
||||||
|
// When showing context we don't want to the LogRow rerender as it will mess up state of context block
|
||||||
|
// making the "after" context to be scrolled to the top, what is desired only on open
|
||||||
|
// The log row message needs to be refactored to separate component that encapsulates parsing and parsed message state
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Don't parse right away, user might move along
|
// Don't parse right away, user might move along
|
||||||
this.mouseMessageTimer = setTimeout(this.parseMessage, 500);
|
this.mouseMessageTimer = setTimeout(this.parseMessage, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMouseOutMessage = () => {
|
onMouseOutMessage = () => {
|
||||||
|
if (this.state.showContext) {
|
||||||
|
// See comment in onMouseOverMessage method
|
||||||
|
return;
|
||||||
|
}
|
||||||
clearTimeout(this.mouseMessageTimer);
|
clearTimeout(this.mouseMessageTimer);
|
||||||
this.setState({ parsed: false });
|
this.setState({ parsed: false });
|
||||||
};
|
};
|
||||||
@ -110,7 +161,25 @@ export class LogRow extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
toggleContext = () => {
|
||||||
|
this.setState(state => {
|
||||||
|
return {
|
||||||
|
showContext: !state.showContext,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onContextToggle = (e: React.SyntheticEvent<HTMLElement>) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.toggleContext();
|
||||||
|
};
|
||||||
|
|
||||||
|
renderLogRow(
|
||||||
|
context?: LogRowContextRows,
|
||||||
|
errors?: LogRowContextQueryErrors,
|
||||||
|
hasMoreContextRows?: HasMoreContextRows,
|
||||||
|
updateLimit?: () => void
|
||||||
|
) {
|
||||||
const {
|
const {
|
||||||
getRows,
|
getRows,
|
||||||
highlighterExpressions,
|
highlighterExpressions,
|
||||||
@ -129,6 +198,7 @@ export class LogRow extends PureComponent<Props, State> {
|
|||||||
parsed,
|
parsed,
|
||||||
parsedFieldHighlights,
|
parsedFieldHighlights,
|
||||||
showFieldStats,
|
showFieldStats,
|
||||||
|
showContext,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { entry, hasAnsi, raw } = row;
|
const { entry, hasAnsi, raw } = row;
|
||||||
const previewHighlights = highlighterExpressions && !_.isEqual(highlighterExpressions, row.searchWords);
|
const previewHighlights = highlighterExpressions && !_.isEqual(highlighterExpressions, row.searchWords);
|
||||||
@ -139,7 +209,14 @@ export class LogRow extends PureComponent<Props, State> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logs-row">
|
<ThemeContext.Consumer>
|
||||||
|
{theme => {
|
||||||
|
const styles = this.state.showContext
|
||||||
|
? cx(logRowStyles, getLogRowWithContextStyles(theme, this.state).row)
|
||||||
|
: logRowStyles;
|
||||||
|
console.log(styles);
|
||||||
|
return (
|
||||||
|
<div className={`logs-row ${this.props.className}`}>
|
||||||
{showDuplicates && (
|
{showDuplicates && (
|
||||||
<div className="logs-row__duplicates">{row.duplicates > 0 ? `${row.duplicates + 1}x` : null}</div>
|
<div className="logs-row__duplicates">{row.duplicates > 0 ? `${row.duplicates + 1}x` : null}</div>
|
||||||
)}
|
)}
|
||||||
@ -159,7 +236,31 @@ export class LogRow extends PureComponent<Props, State> {
|
|||||||
<LogLabels getRows={getRows} labels={row.uniqueLabels} onClickLabel={onClickLabel} />
|
<LogLabels getRows={getRows} labels={row.uniqueLabels} onClickLabel={onClickLabel} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="logs-row__message" onMouseEnter={this.onMouseOverMessage} onMouseLeave={this.onMouseOutMessage}>
|
<div
|
||||||
|
className="logs-row__message"
|
||||||
|
onMouseEnter={this.onMouseOverMessage}
|
||||||
|
onMouseLeave={this.onMouseOutMessage}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={css`
|
||||||
|
position: relative;
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{showContext && context && (
|
||||||
|
<LogRowContext
|
||||||
|
row={row}
|
||||||
|
context={context}
|
||||||
|
errors={errors}
|
||||||
|
hasMoreContextRows={hasMoreContextRows}
|
||||||
|
onOutsideClick={this.toggleContext}
|
||||||
|
onLoadMoreContext={() => {
|
||||||
|
if (updateLimit) {
|
||||||
|
updateLimit();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<span className={styles}>
|
||||||
{parsed && (
|
{parsed && (
|
||||||
<Highlighter
|
<Highlighter
|
||||||
autoEscape
|
autoEscape
|
||||||
@ -190,8 +291,50 @@ export class LogRow extends PureComponent<Props, State> {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</span>
|
||||||
|
{row.searchWords && row.searchWords.length > 0 && (
|
||||||
|
<span
|
||||||
|
onClick={this.onContextToggle}
|
||||||
|
className={css`
|
||||||
|
visibility: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: relative;
|
||||||
|
z-index: ${showContext ? 1 : 0};
|
||||||
|
cursor: pointer;
|
||||||
|
.logs-row:hover & {
|
||||||
|
visibility: visible;
|
||||||
|
margin-left: 10px;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{showContext ? 'Hide' : 'Show'} context
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}}
|
||||||
|
</ThemeContext.Consumer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { showContext } = this.state;
|
||||||
|
|
||||||
|
if (showContext) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LogRowContextProvider row={this.props.row} getRowContext={this.props.getRowContext}>
|
||||||
|
{({ result, errors, hasMoreContextRows, updateLimit }) => {
|
||||||
|
return <>{this.renderLogRow(result, errors, hasMoreContextRows, updateLimit)}</>;
|
||||||
|
}}
|
||||||
|
</LogRowContextProvider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.renderLogRow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
239
public/app/features/explore/LogRowContext.tsx
Normal file
239
public/app/features/explore/LogRowContext.tsx
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
import React, { useContext, useRef, useState, useLayoutEffect } from 'react';
|
||||||
|
import {
|
||||||
|
ThemeContext,
|
||||||
|
List,
|
||||||
|
GrafanaTheme,
|
||||||
|
selectThemeVariant,
|
||||||
|
ClickOutsideWrapper,
|
||||||
|
CustomScrollbar,
|
||||||
|
DataQueryError,
|
||||||
|
} from '@grafana/ui';
|
||||||
|
import { css, cx } from 'emotion';
|
||||||
|
import { LogRowContextRows, HasMoreContextRows, LogRowContextQueryErrors } from './LogRowContextProvider';
|
||||||
|
import { LogRowModel } from 'app/core/logs_model';
|
||||||
|
import { Alert } from './Error';
|
||||||
|
|
||||||
|
interface LogRowContextProps {
|
||||||
|
row: LogRowModel;
|
||||||
|
context: LogRowContextRows;
|
||||||
|
errors?: LogRowContextQueryErrors;
|
||||||
|
hasMoreContextRows: HasMoreContextRows;
|
||||||
|
onOutsideClick: () => void;
|
||||||
|
onLoadMoreContext: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLogRowContextStyles = (theme: GrafanaTheme) => {
|
||||||
|
const gradientTop = selectThemeVariant(
|
||||||
|
{
|
||||||
|
light: theme.colors.white,
|
||||||
|
dark: theme.colors.dark1,
|
||||||
|
},
|
||||||
|
theme.type
|
||||||
|
);
|
||||||
|
const gradientBottom = selectThemeVariant(
|
||||||
|
{
|
||||||
|
light: theme.colors.gray7,
|
||||||
|
dark: theme.colors.dark2,
|
||||||
|
},
|
||||||
|
theme.type
|
||||||
|
);
|
||||||
|
|
||||||
|
const boxShadowColor = selectThemeVariant(
|
||||||
|
{
|
||||||
|
light: theme.colors.gray5,
|
||||||
|
dark: theme.colors.black,
|
||||||
|
},
|
||||||
|
theme.type
|
||||||
|
);
|
||||||
|
const borderColor = selectThemeVariant(
|
||||||
|
{
|
||||||
|
light: theme.colors.gray5,
|
||||||
|
dark: theme.colors.dark9,
|
||||||
|
},
|
||||||
|
theme.type
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
commonStyles: css`
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% + 20px);
|
||||||
|
left: -10px;
|
||||||
|
height: 250px;
|
||||||
|
z-index: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
background: ${theme.colors.pageBg};
|
||||||
|
background: linear-gradient(180deg, ${gradientTop} 0%, ${gradientBottom} 104.25%);
|
||||||
|
box-shadow: 0px 2px 4px ${boxShadowColor}, 0px 0px 2px ${boxShadowColor};
|
||||||
|
border: 1px solid ${borderColor};
|
||||||
|
border-radius: ${theme.border.radius.md};
|
||||||
|
`,
|
||||||
|
header: css`
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: ${borderColor};
|
||||||
|
`,
|
||||||
|
logs: css`
|
||||||
|
height: 220px;
|
||||||
|
padding: 10px;
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
interface LogRowContextGroupHeaderProps {
|
||||||
|
row: LogRowModel;
|
||||||
|
rows: Array<string | DataQueryError>;
|
||||||
|
onLoadMoreContext: () => void;
|
||||||
|
shouldScrollToBottom?: boolean;
|
||||||
|
canLoadMoreRows?: boolean;
|
||||||
|
}
|
||||||
|
interface LogRowContextGroupProps extends LogRowContextGroupHeaderProps {
|
||||||
|
rows: Array<string | DataQueryError>;
|
||||||
|
className: string;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LogRowContextGroupHeader: React.FunctionComponent<LogRowContextGroupHeaderProps> = ({
|
||||||
|
row,
|
||||||
|
rows,
|
||||||
|
onLoadMoreContext,
|
||||||
|
canLoadMoreRows,
|
||||||
|
}) => {
|
||||||
|
const theme = useContext(ThemeContext);
|
||||||
|
const { header } = getLogRowContextStyles(theme);
|
||||||
|
|
||||||
|
// Filtering out the original row from the context.
|
||||||
|
// Loki requires a rowTimestamp+1ns for the following logs to be queried.
|
||||||
|
// We don't to ns-precision calculations in Loki log row context retrieval, hence the filtering here
|
||||||
|
// Also see: https://github.com/grafana/loki/issues/597
|
||||||
|
const logRowsToRender = rows.filter(contextRow => contextRow !== row.raw);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={header}>
|
||||||
|
<span
|
||||||
|
className={css`
|
||||||
|
opacity: 0.6;
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
Found {logRowsToRender.length} rows.
|
||||||
|
</span>
|
||||||
|
{(rows.length >= 10 || (rows.length > 10 && rows.length % 10 !== 0)) && canLoadMoreRows && (
|
||||||
|
<span
|
||||||
|
className={css`
|
||||||
|
margin-left: 10px;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
onClick={() => onLoadMoreContext()}
|
||||||
|
>
|
||||||
|
Load 10 more
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const LogRowContextGroup: React.FunctionComponent<LogRowContextGroupProps> = ({
|
||||||
|
row,
|
||||||
|
rows,
|
||||||
|
error,
|
||||||
|
className,
|
||||||
|
shouldScrollToBottom,
|
||||||
|
canLoadMoreRows,
|
||||||
|
onLoadMoreContext,
|
||||||
|
}) => {
|
||||||
|
const theme = useContext(ThemeContext);
|
||||||
|
const { commonStyles, logs } = getLogRowContextStyles(theme);
|
||||||
|
const [scrollTop, setScrollTop] = useState(0);
|
||||||
|
const listContainerRef = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (shouldScrollToBottom && listContainerRef.current) {
|
||||||
|
setScrollTop(listContainerRef.current.offsetHeight);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const headerProps = {
|
||||||
|
row,
|
||||||
|
rows,
|
||||||
|
onLoadMoreContext,
|
||||||
|
canLoadMoreRows,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cx(className, commonStyles)}>
|
||||||
|
{/* When displaying "after" context */}
|
||||||
|
{shouldScrollToBottom && !error && <LogRowContextGroupHeader {...headerProps} />}
|
||||||
|
<div className={logs}>
|
||||||
|
<CustomScrollbar autoHide scrollTop={scrollTop}>
|
||||||
|
<div ref={listContainerRef}>
|
||||||
|
{!error && (
|
||||||
|
<List
|
||||||
|
items={rows}
|
||||||
|
renderItem={item => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={css`
|
||||||
|
padding: 5px 0;
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{error && <Alert message={error} />}
|
||||||
|
</div>
|
||||||
|
</CustomScrollbar>
|
||||||
|
</div>
|
||||||
|
{/* When displaying "before" context */}
|
||||||
|
{!shouldScrollToBottom && !error && <LogRowContextGroupHeader {...headerProps} />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LogRowContext: React.FunctionComponent<LogRowContextProps> = ({
|
||||||
|
row,
|
||||||
|
context,
|
||||||
|
errors,
|
||||||
|
onOutsideClick,
|
||||||
|
onLoadMoreContext,
|
||||||
|
hasMoreContextRows,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<ClickOutsideWrapper onClick={onOutsideClick}>
|
||||||
|
<div>
|
||||||
|
{context.after && (
|
||||||
|
<LogRowContextGroup
|
||||||
|
rows={context.after}
|
||||||
|
error={errors && errors.after}
|
||||||
|
row={row}
|
||||||
|
className={css`
|
||||||
|
top: -250px;
|
||||||
|
`}
|
||||||
|
shouldScrollToBottom
|
||||||
|
canLoadMoreRows={hasMoreContextRows.after}
|
||||||
|
onLoadMoreContext={onLoadMoreContext}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{context.before && (
|
||||||
|
<LogRowContextGroup
|
||||||
|
onLoadMoreContext={onLoadMoreContext}
|
||||||
|
canLoadMoreRows={hasMoreContextRows.before}
|
||||||
|
row={row}
|
||||||
|
rows={context.before}
|
||||||
|
error={errors && errors.before}
|
||||||
|
className={css`
|
||||||
|
top: 100%;
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ClickOutsideWrapper>
|
||||||
|
);
|
||||||
|
};
|
104
public/app/features/explore/LogRowContextProvider.tsx
Normal file
104
public/app/features/explore/LogRowContextProvider.tsx
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { LogRowModel } from 'app/core/logs_model';
|
||||||
|
import { LogRowContextQueryResponse, SeriesData, DataQueryResponse, DataQueryError } from '@grafana/ui';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import useAsync from 'react-use/lib/useAsync';
|
||||||
|
|
||||||
|
export interface LogRowContextRows {
|
||||||
|
before?: Array<string | DataQueryError>;
|
||||||
|
after?: Array<string | DataQueryError>;
|
||||||
|
}
|
||||||
|
export interface LogRowContextQueryErrors {
|
||||||
|
before?: string;
|
||||||
|
after?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HasMoreContextRows {
|
||||||
|
before: boolean;
|
||||||
|
after: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LogRowContextProviderProps {
|
||||||
|
row: LogRowModel;
|
||||||
|
getRowContext: (row: LogRowModel, limit: number) => Promise<DataQueryResponse>;
|
||||||
|
children: (props: {
|
||||||
|
result: LogRowContextRows;
|
||||||
|
errors: LogRowContextQueryErrors;
|
||||||
|
hasMoreContextRows: HasMoreContextRows;
|
||||||
|
updateLimit: () => void;
|
||||||
|
}) => JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LogRowContextProvider: React.FunctionComponent<LogRowContextProviderProps> = ({
|
||||||
|
getRowContext,
|
||||||
|
row,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const [limit, setLimit] = useState(10);
|
||||||
|
const [result, setResult] = useState<LogRowContextQueryResponse>(null);
|
||||||
|
const [errors, setErrors] = useState<LogRowContextQueryErrors>(null);
|
||||||
|
const [hasMoreContextRows, setHasMoreContextRows] = useState({
|
||||||
|
before: true,
|
||||||
|
after: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { value } = useAsync(async () => {
|
||||||
|
const context = await getRowContext(row, limit);
|
||||||
|
return {
|
||||||
|
data: context.data.map(series => {
|
||||||
|
if ((series as SeriesData).rows) {
|
||||||
|
return (series as SeriesData).rows.map(row => row[1]);
|
||||||
|
} else {
|
||||||
|
return [series];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}, [limit]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (value) {
|
||||||
|
setResult(currentResult => {
|
||||||
|
let hasMoreLogsBefore = true,
|
||||||
|
hasMoreLogsAfter = true;
|
||||||
|
let beforeContextError, afterContextError;
|
||||||
|
|
||||||
|
if (currentResult && currentResult.data[0].length === value.data[0].length) {
|
||||||
|
hasMoreLogsBefore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentResult && currentResult.data[1].length === value.data[1].length) {
|
||||||
|
hasMoreLogsAfter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.data[0] && value.data[0].length > 0 && value.data[0][0].message) {
|
||||||
|
beforeContextError = value.data[0][0].message;
|
||||||
|
}
|
||||||
|
if (value.data[1] && value.data[1].length > 0 && value.data[1][0].message) {
|
||||||
|
afterContextError = value.data[1][0].message;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHasMoreContextRows({
|
||||||
|
before: hasMoreLogsBefore,
|
||||||
|
after: hasMoreLogsAfter,
|
||||||
|
});
|
||||||
|
|
||||||
|
setErrors({
|
||||||
|
before: beforeContextError,
|
||||||
|
after: afterContextError,
|
||||||
|
});
|
||||||
|
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
return children({
|
||||||
|
result: {
|
||||||
|
before: result ? result.data[0] : [],
|
||||||
|
after: result ? result.data[1] : [],
|
||||||
|
},
|
||||||
|
errors,
|
||||||
|
hasMoreContextRows,
|
||||||
|
updateLimit: () => setLimit(limit + 10),
|
||||||
|
});
|
||||||
|
};
|
@ -5,7 +5,7 @@ import * as rangeUtil from '@grafana/ui/src/utils/rangeutil';
|
|||||||
import { RawTimeRange, Switch, LogLevel, TimeZone, TimeRange, AbsoluteTimeRange } from '@grafana/ui';
|
import { RawTimeRange, Switch, LogLevel, TimeZone, TimeRange, AbsoluteTimeRange } from '@grafana/ui';
|
||||||
import TimeSeries from 'app/core/time_series2';
|
import TimeSeries from 'app/core/time_series2';
|
||||||
|
|
||||||
import { LogsDedupDescription, LogsDedupStrategy, LogsModel, LogsMetaKind } from 'app/core/logs_model';
|
import { LogsDedupDescription, LogsDedupStrategy, LogsModel, LogsMetaKind, LogRowModel } from 'app/core/logs_model';
|
||||||
|
|
||||||
import ToggleButtonGroup, { ToggleButton } from 'app/core/components/ToggleButtonGroup/ToggleButtonGroup';
|
import ToggleButtonGroup, { ToggleButton } from 'app/core/components/ToggleButtonGroup/ToggleButtonGroup';
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ interface Props {
|
|||||||
onStopScanning?: () => void;
|
onStopScanning?: () => void;
|
||||||
onDedupStrategyChange: (dedupStrategy: LogsDedupStrategy) => void;
|
onDedupStrategyChange: (dedupStrategy: LogsDedupStrategy) => void;
|
||||||
onToggleLogLevel: (hiddenLogLevels: Set<LogLevel>) => void;
|
onToggleLogLevel: (hiddenLogLevels: Set<LogLevel>) => void;
|
||||||
|
getRowContext?: (row: LogRowModel, limit: number) => Promise<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@ -252,6 +253,7 @@ export default class Logs extends PureComponent<Props, State> {
|
|||||||
<LogRow
|
<LogRow
|
||||||
key={index}
|
key={index}
|
||||||
getRows={getRows}
|
getRows={getRows}
|
||||||
|
getRowContext={this.props.getRowContext}
|
||||||
highlighterExpressions={highlighterExpressions}
|
highlighterExpressions={highlighterExpressions}
|
||||||
row={row}
|
row={row}
|
||||||
showDuplicates={showDuplicates}
|
showDuplicates={showDuplicates}
|
||||||
@ -268,6 +270,7 @@ export default class Logs extends PureComponent<Props, State> {
|
|||||||
<LogRow
|
<LogRow
|
||||||
key={PREVIEW_LIMIT + index}
|
key={PREVIEW_LIMIT + index}
|
||||||
getRows={getRows}
|
getRows={getRows}
|
||||||
|
getRowContext={this.props.getRowContext}
|
||||||
row={row}
|
row={row}
|
||||||
showDuplicates={showDuplicates}
|
showDuplicates={showDuplicates}
|
||||||
showLabels={showLabels && hasLabel}
|
showLabels={showLabels && hasLabel}
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RawTimeRange, TimeRange, LogLevel, TimeZone, AbsoluteTimeRange, toUtc, dateTime } from '@grafana/ui';
|
import {
|
||||||
|
RawTimeRange,
|
||||||
|
TimeRange,
|
||||||
|
LogLevel,
|
||||||
|
TimeZone,
|
||||||
|
AbsoluteTimeRange,
|
||||||
|
toUtc,
|
||||||
|
dateTime,
|
||||||
|
DataSourceApi,
|
||||||
|
} from '@grafana/ui';
|
||||||
|
|
||||||
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
||||||
import { LogsModel, LogsDedupStrategy } from 'app/core/logs_model';
|
import { LogsModel, LogsDedupStrategy, LogRowModel } from 'app/core/logs_model';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
|
|
||||||
import { changeDedupStrategy, changeTime } from './state/actions';
|
import { changeDedupStrategy, changeTime } from './state/actions';
|
||||||
@ -15,6 +24,7 @@ import { deduplicatedLogsSelector, exploreItemUIStateSelector } from 'app/featur
|
|||||||
import { getTimeZone } from '../profile/state/selectors';
|
import { getTimeZone } from '../profile/state/selectors';
|
||||||
|
|
||||||
interface LogsContainerProps {
|
interface LogsContainerProps {
|
||||||
|
datasourceInstance: DataSourceApi | null;
|
||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
logsHighlighterExpressions?: string[];
|
logsHighlighterExpressions?: string[];
|
||||||
@ -58,9 +68,20 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getLogRowContext = async (row: LogRowModel, limit: number) => {
|
||||||
|
const { datasourceInstance } = this.props;
|
||||||
|
|
||||||
|
if (datasourceInstance) {
|
||||||
|
return datasourceInstance.getLogRowContext(row, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
exploreId,
|
exploreId,
|
||||||
|
|
||||||
loading,
|
loading,
|
||||||
logsHighlighterExpressions,
|
logsHighlighterExpressions,
|
||||||
logsResult,
|
logsResult,
|
||||||
@ -97,6 +118,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
scanRange={scanRange}
|
scanRange={scanRange}
|
||||||
width={width}
|
width={width}
|
||||||
hiddenLogLevels={hiddenLogLevels}
|
hiddenLogLevels={hiddenLogLevels}
|
||||||
|
getRowContext={this.getLogRowContext}
|
||||||
/>
|
/>
|
||||||
</Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
@ -106,7 +128,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
function mapStateToProps(state: StoreState, { exploreId }) {
|
function mapStateToProps(state: StoreState, { exploreId }) {
|
||||||
const explore = state.explore;
|
const explore = state.explore;
|
||||||
const item: ExploreItemState = explore[exploreId];
|
const item: ExploreItemState = explore[exploreId];
|
||||||
const { logsHighlighterExpressions, logsResult, logIsLoading, scanning, scanRange, range } = item;
|
const { logsHighlighterExpressions, logsResult, logIsLoading, scanning, scanRange, range, datasourceInstance } = item;
|
||||||
const loading = logIsLoading;
|
const loading = logIsLoading;
|
||||||
const { dedupStrategy } = exploreItemUIStateSelector(item);
|
const { dedupStrategy } = exploreItemUIStateSelector(item);
|
||||||
const hiddenLogLevels = new Set(item.hiddenLogLevels);
|
const hiddenLogLevels = new Set(item.hiddenLogLevels);
|
||||||
@ -124,6 +146,7 @@ function mapStateToProps(state: StoreState, { exploreId }) {
|
|||||||
dedupStrategy,
|
dedupStrategy,
|
||||||
hiddenLogLevels,
|
hiddenLogLevels,
|
||||||
dedupedResult,
|
dedupedResult,
|
||||||
|
datasourceInstance,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +379,6 @@ export const itemReducer = reducerFactory<ExploreItemState>({} as ExploreItemSta
|
|||||||
const { queryIntervals } = state;
|
const { queryIntervals } = state;
|
||||||
const { result, resultType, latency } = action.payload;
|
const { result, resultType, latency } = action.payload;
|
||||||
const results = calculateResultsFromQueryTransactions(result, resultType, queryIntervals.intervalMs);
|
const results = calculateResultsFromQueryTransactions(result, resultType, queryIntervals.intervalMs);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
graphResult: resultType === 'Graph' ? results.graphResult : state.graphResult,
|
graphResult: resultType === 'Graph' ? results.graphResult : state.graphResult,
|
||||||
|
@ -21,6 +21,7 @@ import { LokiQuery, LokiOptions } from './types';
|
|||||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||||
import { safeStringifyValue } from 'app/core/utils/explore';
|
import { safeStringifyValue } from 'app/core/utils/explore';
|
||||||
|
import { LogRowModel } from 'app/core/logs_model';
|
||||||
|
|
||||||
export const DEFAULT_MAX_LINES = 1000;
|
export const DEFAULT_MAX_LINES = 1000;
|
||||||
|
|
||||||
@ -187,6 +188,83 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
|||||||
return Math.ceil(date.valueOf() * 1e6);
|
return Math.ceil(date.valueOf() * 1e6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepareLogRowContextQueryTargets = (row: LogRowModel, limit: number) => {
|
||||||
|
const query = Object.keys(row.labels)
|
||||||
|
.map(label => {
|
||||||
|
return `${label}="${row.labels[label]}"`;
|
||||||
|
})
|
||||||
|
.join(',');
|
||||||
|
const contextTimeBuffer = 2 * 60 * 60 * 1000 * 1e6; // 2h buffer
|
||||||
|
const timeEpochNs = row.timeEpochMs * 1e6;
|
||||||
|
|
||||||
|
const commontTargetOptons = {
|
||||||
|
limit,
|
||||||
|
query: `{${query}}`,
|
||||||
|
};
|
||||||
|
return [
|
||||||
|
// Target for "before" context
|
||||||
|
{
|
||||||
|
...commontTargetOptons,
|
||||||
|
start: timeEpochNs - contextTimeBuffer,
|
||||||
|
end: timeEpochNs,
|
||||||
|
direction: 'BACKWARD',
|
||||||
|
},
|
||||||
|
// Target for "after" context
|
||||||
|
{
|
||||||
|
...commontTargetOptons,
|
||||||
|
start: timeEpochNs, // TODO: We should add 1ns here for the original row not no be included in the result
|
||||||
|
end: timeEpochNs + contextTimeBuffer,
|
||||||
|
direction: 'FORWARD',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
getLogRowContext = (row: LogRowModel, limit?: number) => {
|
||||||
|
// Preparing two targets, for preceeding and following log queries
|
||||||
|
const targets = this.prepareLogRowContextQueryTargets(row, limit || 10);
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
targets.map(target => {
|
||||||
|
return this._request('/api/prom/query', target).catch(e => {
|
||||||
|
const error: DataQueryError = {
|
||||||
|
message: 'Error during context query. Please check JS console logs.',
|
||||||
|
status: e.status,
|
||||||
|
statusText: e.statusText,
|
||||||
|
};
|
||||||
|
return error;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
).then((results: any[]) => {
|
||||||
|
const series: Array<Array<SeriesData | DataQueryError>> = [];
|
||||||
|
const emptySeries = {
|
||||||
|
fields: [],
|
||||||
|
rows: [],
|
||||||
|
} as SeriesData;
|
||||||
|
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
const result = results[i];
|
||||||
|
series[i] = [];
|
||||||
|
if (result.data) {
|
||||||
|
for (const stream of result.data.streams || []) {
|
||||||
|
const seriesData = logStreamToSeriesData(stream);
|
||||||
|
series[i].push(seriesData);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
series[i].push(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Following context logs are requested in "forward" direction.
|
||||||
|
// This means, that we need to reverse those to make them sorted
|
||||||
|
// in descending order (by timestamp)
|
||||||
|
if (series[1][0] && (series[1][0] as SeriesData).rows) {
|
||||||
|
(series[1][0] as SeriesData).rows.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { data: [series[0][0] || emptySeries, series[1][0] || emptySeries] };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
testDatasource() {
|
testDatasource() {
|
||||||
return this._request('/api/prom/label')
|
return this._request('/api/prom/label')
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
@ -179,6 +179,7 @@ export interface ExploreItemState {
|
|||||||
* Log query result to be displayed in the logs result viewer.
|
* Log query result to be displayed in the logs result viewer.
|
||||||
*/
|
*/
|
||||||
logsResult?: LogsModel;
|
logsResult?: LogsModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query intervals for graph queries to determine how many datapoints to return.
|
* Query intervals for graph queries to determine how many datapoints to return.
|
||||||
* Needs to be updated when `datasourceInstance` or `containerWidth` is changed.
|
* Needs to be updated when `datasourceInstance` or `containerWidth` is changed.
|
||||||
|
@ -73,6 +73,7 @@ $column-horizontal-spacing: 10px;
|
|||||||
padding-right: $column-horizontal-spacing;
|
padding-right: $column-horizontal-spacing;
|
||||||
border-top: 1px solid transparent;
|
border-top: 1px solid transparent;
|
||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid transparent;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
131
yarn.lock
131
yarn.lock
@ -4054,6 +4054,11 @@ boolbase@^1.0.0, boolbase@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||||
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
|
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
|
||||||
|
|
||||||
|
bowser@^1.7.3:
|
||||||
|
version "1.9.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a"
|
||||||
|
integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==
|
||||||
|
|
||||||
boxen@^1.2.1:
|
boxen@^1.2.1:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
|
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
|
||||||
@ -5143,7 +5148,7 @@ copy-descriptor@^0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
||||||
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
||||||
|
|
||||||
copy-to-clipboard@^3.0.8:
|
copy-to-clipboard@^3.0.8, copy-to-clipboard@^3.1.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.2.0.tgz#d2724a3ccbfed89706fac8a894872c979ac74467"
|
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.2.0.tgz#d2724a3ccbfed89706fac8a894872c979ac74467"
|
||||||
integrity sha512-eOZERzvCmxS8HWzugj4Uxl8OJxa7T2k1Gi0X5qavwydHIfuSHq2dTD09LOg/XyGq4Zpb5IsR/2OJ5lbOegz78w==
|
integrity sha512-eOZERzvCmxS8HWzugj4Uxl8OJxa7T2k1Gi0X5qavwydHIfuSHq2dTD09LOg/XyGq4Zpb5IsR/2OJ5lbOegz78w==
|
||||||
@ -5366,6 +5371,14 @@ css-declaration-sorter@^4.0.1:
|
|||||||
postcss "^7.0.1"
|
postcss "^7.0.1"
|
||||||
timsort "^0.3.0"
|
timsort "^0.3.0"
|
||||||
|
|
||||||
|
css-in-js-utils@^2.0.0:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99"
|
||||||
|
integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==
|
||||||
|
dependencies:
|
||||||
|
hyphenate-style-name "^1.0.2"
|
||||||
|
isobject "^3.0.1"
|
||||||
|
|
||||||
css-loader@2.1.1, css-loader@^2.1.0:
|
css-loader@2.1.1, css-loader@^2.1.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea"
|
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea"
|
||||||
@ -5416,7 +5429,7 @@ css-tree@1.0.0-alpha.28:
|
|||||||
mdn-data "~1.1.0"
|
mdn-data "~1.1.0"
|
||||||
source-map "^0.5.3"
|
source-map "^0.5.3"
|
||||||
|
|
||||||
css-tree@1.0.0-alpha.29:
|
css-tree@1.0.0-alpha.29, css-tree@^1.0.0-alpha.28:
|
||||||
version "1.0.0-alpha.29"
|
version "1.0.0-alpha.29"
|
||||||
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39"
|
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39"
|
||||||
integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==
|
integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==
|
||||||
@ -5541,7 +5554,7 @@ cssstyle@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
cssom "0.3.x"
|
cssom "0.3.x"
|
||||||
|
|
||||||
csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.7:
|
csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.5, csstype@^2.5.7:
|
||||||
version "2.6.4"
|
version "2.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f"
|
||||||
integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==
|
integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==
|
||||||
@ -6801,6 +6814,13 @@ error-ex@^1.2.0, error-ex@^1.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
|
error-stack-parser@^2.0.1:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.2.tgz#4ae8dbaa2bf90a8b450707b9149dcabca135520d"
|
||||||
|
integrity sha512-E1fPutRDdIj/hohG0UpT5mayXNCxXP9d+snxFsPU9X0XgccOumKraa3juDMwTUyi7+Bu5+mCGagjg4IYeNbOdw==
|
||||||
|
dependencies:
|
||||||
|
stackframe "^1.0.4"
|
||||||
|
|
||||||
es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0, es-abstract@^1.9.0:
|
es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0, es-abstract@^1.9.0:
|
||||||
version "1.13.0"
|
version "1.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
|
||||||
@ -7355,6 +7375,11 @@ fast-text-encoding@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz#3e5ce8293409cfaa7177a71b9ca84e1b1e6f25ef"
|
resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz#3e5ce8293409cfaa7177a71b9ca84e1b1e6f25ef"
|
||||||
integrity sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==
|
integrity sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==
|
||||||
|
|
||||||
|
fastest-stable-stringify@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028"
|
||||||
|
integrity sha1-kSLUBtTJ2YvqZEpraFPVh0uHsCg=
|
||||||
|
|
||||||
fastparse@^1.1.1:
|
fastparse@^1.1.1:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
|
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
|
||||||
@ -8837,6 +8862,11 @@ husky@1.3.1:
|
|||||||
run-node "^1.0.0"
|
run-node "^1.0.0"
|
||||||
slash "^2.0.0"
|
slash "^2.0.0"
|
||||||
|
|
||||||
|
hyphenate-style-name@^1.0.2:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
|
||||||
|
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
|
||||||
|
|
||||||
iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
||||||
version "0.4.24"
|
version "0.4.24"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||||
@ -9024,6 +9054,14 @@ init-package-json@^1.10.3:
|
|||||||
validate-npm-package-license "^3.0.1"
|
validate-npm-package-license "^3.0.1"
|
||||||
validate-npm-package-name "^3.0.0"
|
validate-npm-package-name "^3.0.0"
|
||||||
|
|
||||||
|
inline-style-prefixer@^4.0.0:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-4.0.2.tgz#d390957d26f281255fe101da863158ac6eb60911"
|
||||||
|
integrity sha512-N8nVhwfYga9MiV9jWlwfdj1UDIaZlBFu4cJSJkIr7tZX7sHpHhGR5su1qdpW+7KPL8ISTvCIkcaFi/JdBknvPg==
|
||||||
|
dependencies:
|
||||||
|
bowser "^1.7.3"
|
||||||
|
css-in-js-utils "^2.0.0"
|
||||||
|
|
||||||
inquirer@6.2.1:
|
inquirer@6.2.1:
|
||||||
version "6.2.1"
|
version "6.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52"
|
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52"
|
||||||
@ -11565,6 +11603,20 @@ nan@^2.10.0, nan@^2.12.1, nan@^2.6.2:
|
|||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
||||||
integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
|
integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
|
||||||
|
|
||||||
|
nano-css@^5.1.0:
|
||||||
|
version "5.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.1.0.tgz#03c2b4ea2edefd445ac0c0e0f2565ea62e2aa81a"
|
||||||
|
integrity sha512-08F1rBmp0JuAteOR/uk/c40q/+UxWr224m/ZCHjjgy8dhkFQptvNwj/408KYQc13PIV9aGvqmtUD49PqBB5Ppg==
|
||||||
|
dependencies:
|
||||||
|
css-tree "^1.0.0-alpha.28"
|
||||||
|
csstype "^2.5.5"
|
||||||
|
fastest-stable-stringify "^1.0.1"
|
||||||
|
inline-style-prefixer "^4.0.0"
|
||||||
|
rtl-css-js "^1.9.0"
|
||||||
|
sourcemap-codec "^1.4.1"
|
||||||
|
stacktrace-js "^2.0.0"
|
||||||
|
stylis "3.5.0"
|
||||||
|
|
||||||
nanomatch@^1.2.9:
|
nanomatch@^1.2.9:
|
||||||
version "1.2.13"
|
version "1.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||||
@ -14100,7 +14152,7 @@ react-error-overlay@^5.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.5.tgz#884530fd055476c764eaa8ab13b8ecf1f57bbf2c"
|
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.5.tgz#884530fd055476c764eaa8ab13b8ecf1f57bbf2c"
|
||||||
integrity sha512-O9JRum1Zq/qCPFH5qVEvDDrVun8Jv9vbHtZXCR1EuRj9sKg1xJTlHxBzU6AkCzpvxRLuiY4OKImy3cDLQ+UTdg==
|
integrity sha512-O9JRum1Zq/qCPFH5qVEvDDrVun8Jv9vbHtZXCR1EuRj9sKg1xJTlHxBzU6AkCzpvxRLuiY4OKImy3cDLQ+UTdg==
|
||||||
|
|
||||||
react-fast-compare@^2.0.2:
|
react-fast-compare@^2.0.2, react-fast-compare@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||||
@ -14379,6 +14431,19 @@ react-transition-group@^2.2.1:
|
|||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
react-lifecycles-compat "^3.0.4"
|
react-lifecycles-compat "^3.0.4"
|
||||||
|
|
||||||
|
react-use@9.0.0:
|
||||||
|
version "9.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-use/-/react-use-9.0.0.tgz#142bec53fa465db2a6e43c68a8c9ef2acc000592"
|
||||||
|
integrity sha512-jlXJneB96yl4VvAXDKyE6cmdIeWk0cO7Gomh870Qu0vXZ9YM2JjjR09E9vIPPPI2M27RWo2dZKXspv44Wxtoog==
|
||||||
|
dependencies:
|
||||||
|
copy-to-clipboard "^3.1.0"
|
||||||
|
nano-css "^5.1.0"
|
||||||
|
react-fast-compare "^2.0.4"
|
||||||
|
react-wait "^0.3.0"
|
||||||
|
screenfull "^4.1.0"
|
||||||
|
throttle-debounce "^2.0.1"
|
||||||
|
ts-easing "^0.2.0"
|
||||||
|
|
||||||
react-virtualized@9.21.0:
|
react-virtualized@9.21.0:
|
||||||
version "9.21.0"
|
version "9.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.0.tgz#8267c40ffb48db35b242a36dea85edcf280a6506"
|
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.0.tgz#8267c40ffb48db35b242a36dea85edcf280a6506"
|
||||||
@ -14391,6 +14456,11 @@ react-virtualized@9.21.0:
|
|||||||
prop-types "^15.6.0"
|
prop-types "^15.6.0"
|
||||||
react-lifecycles-compat "^3.0.4"
|
react-lifecycles-compat "^3.0.4"
|
||||||
|
|
||||||
|
react-wait@^0.3.0:
|
||||||
|
version "0.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-wait/-/react-wait-0.3.0.tgz#0cdd4d919012451a5bc3ab0a16d00c6fd9a8c10b"
|
||||||
|
integrity sha512-kB5x/kMKWcn0uVr9gBdNz21/oGbQwEQnF3P9p6E9yLfJ9DRcKS0fagbgYMFI0YFOoyKDj+2q6Rwax0kTYJF37g==
|
||||||
|
|
||||||
react-window@1.7.1:
|
react-window@1.7.1:
|
||||||
version "1.7.1"
|
version "1.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.7.1.tgz#c1db640415b97b85bc0a1c66eb82dadabca39b86"
|
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.7.1.tgz#c1db640415b97b85bc0a1c66eb82dadabca39b86"
|
||||||
@ -15206,6 +15276,13 @@ rsvp@^4.8.4:
|
|||||||
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.4.tgz#b50e6b34583f3dd89329a2f23a8a2be072845911"
|
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.4.tgz#b50e6b34583f3dd89329a2f23a8a2be072845911"
|
||||||
integrity sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==
|
integrity sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==
|
||||||
|
|
||||||
|
rtl-css-js@^1.9.0:
|
||||||
|
version "1.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.11.0.tgz#a7151930ef9d54656607d754ebb172ddfc9ef836"
|
||||||
|
integrity sha512-YnZ6jWxZxlWlcQAGF9vOmiF9bEmoQmSHE+wsrsiILkdK9HqiRPAIll4SY/QDzbvEu2lB2h62+hfg3TYzjnldbA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.1.2"
|
||||||
|
|
||||||
run-async@^0.1.0:
|
run-async@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
|
resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
|
||||||
@ -15400,6 +15477,11 @@ schema-utils@^1.0.0:
|
|||||||
ajv-errors "^1.0.0"
|
ajv-errors "^1.0.0"
|
||||||
ajv-keywords "^3.1.0"
|
ajv-keywords "^3.1.0"
|
||||||
|
|
||||||
|
screenfull@^4.1.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-4.2.0.tgz#d5252a5a0f56504719abbed9ebbcd9208115da03"
|
||||||
|
integrity sha512-qpyI9XbwuMJElWRP5vTgxkFAl4k7HpyhIqBFOZEwX9QBXn0MAuRSpn7LOc6/4CeSwoz61oBu1VPV+2fbIWC+5Q==
|
||||||
|
|
||||||
scss-tokenizer@^0.2.3:
|
scss-tokenizer@^0.2.3:
|
||||||
version "0.2.3"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
|
resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
|
||||||
@ -15978,7 +16060,7 @@ source-map@^0.7.2, source-map@^0.7.3:
|
|||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||||
|
|
||||||
sourcemap-codec@^1.4.4:
|
sourcemap-codec@^1.4.1, sourcemap-codec@^1.4.4:
|
||||||
version "1.4.4"
|
version "1.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f"
|
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f"
|
||||||
integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==
|
integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==
|
||||||
@ -16093,6 +16175,13 @@ stable@^0.1.8, stable@~0.1.3, stable@~0.1.5:
|
|||||||
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
||||||
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
||||||
|
|
||||||
|
stack-generator@^2.0.1:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.3.tgz#bb74385c67ffc4ccf3c4dee5831832d4e509c8a0"
|
||||||
|
integrity sha512-kdzGoqrnqsMxOEuXsXyQTmvWXZmG0f3Ql2GDx5NtmZs59sT2Bt9Vdyq0XdtxUi58q/+nxtbF9KOQ9HkV1QznGg==
|
||||||
|
dependencies:
|
||||||
|
stackframe "^1.0.4"
|
||||||
|
|
||||||
stack-parser@^0.0.1:
|
stack-parser@^0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/stack-parser/-/stack-parser-0.0.1.tgz#7d3b63a17887e9e2c2bf55dbd3318fe34a39d1e7"
|
resolved "https://registry.yarnpkg.com/stack-parser/-/stack-parser-0.0.1.tgz#7d3b63a17887e9e2c2bf55dbd3318fe34a39d1e7"
|
||||||
@ -16103,6 +16192,28 @@ stack-utils@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
|
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
|
||||||
integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
|
integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
|
||||||
|
|
||||||
|
stackframe@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b"
|
||||||
|
integrity sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==
|
||||||
|
|
||||||
|
stacktrace-gps@^3.0.1:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.2.tgz#33f8baa4467323ab2bd1816efa279942ba431ccc"
|
||||||
|
integrity sha512-9o+nWhiz5wFnrB3hBHs2PTyYrS60M1vvpSzHxwxnIbtY2q9Nt51hZvhrG1+2AxD374ecwyS+IUwfkHRE/2zuGg==
|
||||||
|
dependencies:
|
||||||
|
source-map "0.5.6"
|
||||||
|
stackframe "^1.0.4"
|
||||||
|
|
||||||
|
stacktrace-js@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.0.tgz#776ca646a95bc6c6b2b90776536a7fc72c6ddb58"
|
||||||
|
integrity sha1-d2ymRqlbxsayuQd2U2p/xyxt21g=
|
||||||
|
dependencies:
|
||||||
|
error-stack-parser "^2.0.1"
|
||||||
|
stack-generator "^2.0.1"
|
||||||
|
stacktrace-gps "^3.0.1"
|
||||||
|
|
||||||
staged-git-files@1.1.2:
|
staged-git-files@1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b"
|
resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b"
|
||||||
@ -16410,6 +16521,11 @@ stylis-rule-sheet@^0.0.10:
|
|||||||
resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
|
resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
|
||||||
integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==
|
integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==
|
||||||
|
|
||||||
|
stylis@3.5.0:
|
||||||
|
version "3.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1"
|
||||||
|
integrity sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw==
|
||||||
|
|
||||||
stylis@^3.5.0:
|
stylis@^3.5.0:
|
||||||
version "3.5.4"
|
version "3.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
|
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
|
||||||
@ -16665,6 +16781,11 @@ throat@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
|
resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
|
||||||
integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=
|
integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=
|
||||||
|
|
||||||
|
throttle-debounce@^2.0.1:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5"
|
||||||
|
integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg==
|
||||||
|
|
||||||
throttleit@^1.0.0:
|
throttleit@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
|
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
|
||||||
|
Loading…
Reference in New Issue
Block a user