Commit 514f2bea by kay delaney Committed by GitHub

Chore: Remove several instances of non-strict null usage (#20563)

parent 665079dc
...@@ -18,8 +18,8 @@ export interface LocationUpdate { ...@@ -18,8 +18,8 @@ export interface LocationUpdate {
replace?: boolean; replace?: boolean;
} }
export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[]; export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[] | undefined;
export type UrlQueryMap = { [s: string]: UrlQueryValue }; export type UrlQueryMap = Record<string, UrlQueryValue>;
export interface LocationSrv { export interface LocationSrv {
update(options: LocationUpdate): void; update(options: LocationUpdate): void;
......
...@@ -83,7 +83,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({ ...@@ -83,7 +83,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({
})); }));
interface Props { interface Props {
isOpen: boolean; isOpen?: boolean;
label: string; label: string;
loading?: boolean; loading?: boolean;
collapsible?: boolean; collapsible?: boolean;
......
...@@ -14,7 +14,7 @@ export interface GraphProps { ...@@ -14,7 +14,7 @@ export interface GraphProps {
children?: JSX.Element | JSX.Element[]; children?: JSX.Element | JSX.Element[];
series: GraphSeriesXY[]; series: GraphSeriesXY[];
timeRange: TimeRange; // NOTE: we should aim to make `time` a property of the axis, not force it for all graphs timeRange: TimeRange; // NOTE: we should aim to make `time` a property of the axis, not force it for all graphs
timeZone: TimeZone; // NOTE: we should aim to make `time` a property of the axis, not force it for all graphs timeZone?: TimeZone; // NOTE: we should aim to make `time` a property of the axis, not force it for all graphs
showLines?: boolean; showLines?: boolean;
showPoints?: boolean; showPoints?: boolean;
showBars?: boolean; showBars?: boolean;
...@@ -246,7 +246,7 @@ export class Graph extends PureComponent<GraphProps, GraphState> { ...@@ -246,7 +246,7 @@ export class Graph extends PureComponent<GraphProps, GraphState> {
label: 'Datetime', label: 'Datetime',
ticks: ticks, ticks: ticks,
timeformat: timeFormat(ticks, min, max), timeformat: timeFormat(ticks, min, max),
timezone: timeZone ? timeZone : DefaultTimeZone, timezone: timeZone ?? DefaultTimeZone,
}, },
yaxes, yaxes,
grid: { grid: {
......
...@@ -16,7 +16,7 @@ export interface Props extends Themeable { ...@@ -16,7 +16,7 @@ export interface Props extends Themeable {
logRows?: LogRowModel[]; logRows?: LogRowModel[];
deduplicatedRows?: LogRowModel[]; deduplicatedRows?: LogRowModel[];
dedupStrategy: LogsDedupStrategy; dedupStrategy: LogsDedupStrategy;
highlighterExpressions: string[]; highlighterExpressions?: string[];
showTime: boolean; showTime: boolean;
timeZone: TimeZone; timeZone: TimeZone;
rowLimit?: number; rowLimit?: number;
......
...@@ -37,7 +37,7 @@ export interface Props { ...@@ -37,7 +37,7 @@ export interface Props {
export class RefreshPickerBase extends PureComponent<Props> { export class RefreshPickerBase extends PureComponent<Props> {
static offOption = { label: 'Off', value: '' }; static offOption = { label: 'Off', value: '' };
static liveOption = { label: 'Live', value: 'LIVE' }; static liveOption = { label: 'Live', value: 'LIVE' };
static isLive = (refreshInterval: string): boolean => refreshInterval === RefreshPicker.liveOption.value; static isLive = (refreshInterval?: string): boolean => refreshInterval === RefreshPicker.liveOption.value;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
......
...@@ -42,7 +42,7 @@ export const LogLevelColor = { ...@@ -42,7 +42,7 @@ export const LogLevelColor = {
}; };
const isoDateRegexp = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-6]\d[,\.]\d+([+-][0-2]\d:[0-5]\d|Z)/g; const isoDateRegexp = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-6]\d[,\.]\d+([+-][0-2]\d:[0-5]\d|Z)/g;
function isDuplicateRow(row: LogRowModel, other: LogRowModel, strategy: LogsDedupStrategy): boolean { function isDuplicateRow(row: LogRowModel, other: LogRowModel, strategy?: LogsDedupStrategy): boolean {
switch (strategy) { switch (strategy) {
case LogsDedupStrategy.exact: case LogsDedupStrategy.exact:
// Exact still strips dates // Exact still strips dates
...@@ -59,7 +59,7 @@ function isDuplicateRow(row: LogRowModel, other: LogRowModel, strategy: LogsDedu ...@@ -59,7 +59,7 @@ function isDuplicateRow(row: LogRowModel, other: LogRowModel, strategy: LogsDedu
} }
} }
export function dedupLogRows(rows: LogRowModel[], strategy: LogsDedupStrategy): LogRowModel[] { export function dedupLogRows(rows: LogRowModel[], strategy?: LogsDedupStrategy): LogRowModel[] {
if (strategy === LogsDedupStrategy.none) { if (strategy === LogsDedupStrategy.none) {
return rows; return rows;
} }
...@@ -68,7 +68,7 @@ export function dedupLogRows(rows: LogRowModel[], strategy: LogsDedupStrategy): ...@@ -68,7 +68,7 @@ export function dedupLogRows(rows: LogRowModel[], strategy: LogsDedupStrategy):
const rowCopy = { ...row }; const rowCopy = { ...row };
const previous = result[result.length - 1]; const previous = result[result.length - 1];
if (index > 0 && isDuplicateRow(row, previous, strategy)) { if (index > 0 && isDuplicateRow(row, previous, strategy)) {
previous.duplicates++; previous.duplicates!++;
} else { } else {
rowCopy.duplicates = 0; rowCopy.duplicates = 0;
result.push(rowCopy); result.push(rowCopy);
......
...@@ -202,20 +202,20 @@ describe('hasNonEmptyQuery', () => { ...@@ -202,20 +202,20 @@ describe('hasNonEmptyQuery', () => {
describe('hasRefId', () => { describe('hasRefId', () => {
describe('when called with a null value', () => { describe('when called with a null value', () => {
it('then it should return null', () => { it('then it should return undefined', () => {
const input: any = null; const input: any = null;
const result = getValueWithRefId(input); const result = getValueWithRefId(input);
expect(result).toBeNull(); expect(result).toBeUndefined();
}); });
}); });
describe('when called with a non object value', () => { describe('when called with a non object value', () => {
it('then it should return null', () => { it('then it should return undefined', () => {
const input = 123; const input = 123;
const result = getValueWithRefId(input); const result = getValueWithRefId(input);
expect(result).toBeNull(); expect(result).toBeUndefined();
}); });
}); });
...@@ -249,11 +249,11 @@ describe('hasRefId', () => { ...@@ -249,11 +249,11 @@ describe('hasRefId', () => {
describe('getFirstQueryErrorWithoutRefId', () => { describe('getFirstQueryErrorWithoutRefId', () => {
describe('when called with a null value', () => { describe('when called with a null value', () => {
it('then it should return null', () => { it('then it should return undefined', () => {
const errors: DataQueryError[] = null; const errors: DataQueryError[] = null;
const result = getFirstQueryErrorWithoutRefId(errors); const result = getFirstQueryErrorWithoutRefId(errors);
expect(result).toBeNull(); expect(result).toBeUndefined();
}); });
}); });
......
...@@ -418,13 +418,9 @@ export const getTimeRangeFromUrl = (range: RawTimeRange, timeZone: TimeZone): Ti ...@@ -418,13 +418,9 @@ export const getTimeRangeFromUrl = (range: RawTimeRange, timeZone: TimeZone): Ti
}; };
}; };
export const getValueWithRefId = (value: any): any | null => { export const getValueWithRefId = (value?: any): any => {
if (!value) { if (!value || typeof value !== 'object') {
return null; return undefined;
}
if (typeof value !== 'object') {
return null;
} }
if (value.refId) { if (value.refId) {
...@@ -440,12 +436,12 @@ export const getValueWithRefId = (value: any): any | null => { ...@@ -440,12 +436,12 @@ export const getValueWithRefId = (value: any): any | null => {
} }
} }
return null; return undefined;
}; };
export const getFirstQueryErrorWithoutRefId = (errors: DataQueryError[]) => { export const getFirstQueryErrorWithoutRefId = (errors?: DataQueryError[]) => {
if (!errors) { if (!errors) {
return null; return undefined;
} }
return errors.filter(error => (error && error.refId ? false : true))[0]; return errors.filter(error => (error && error.refId ? false : true))[0];
...@@ -503,7 +499,7 @@ export enum SortOrder { ...@@ -503,7 +499,7 @@ export enum SortOrder {
Ascending = 'Ascending', Ascending = 'Ascending',
} }
export const refreshIntervalToSortOrder = (refreshInterval: string) => export const refreshIntervalToSortOrder = (refreshInterval?: string) =>
RefreshPicker.isLive(refreshInterval) ? SortOrder.Ascending : SortOrder.Descending; RefreshPicker.isLive(refreshInterval) ? SortOrder.Ascending : SortOrder.Descending;
export const sortLogsResult = (logsResult: LogsModel, sortOrder: SortOrder): LogsModel => { export const sortLogsResult = (logsResult: LogsModel, sortOrder: SortOrder): LogsModel => {
......
...@@ -36,6 +36,11 @@ export const AdHocFilter: React.FunctionComponent<Props> = props => { ...@@ -36,6 +36,11 @@ export const AdHocFilter: React.FunctionComponent<Props> = props => {
const onChange = (changeType: ChangeType) => (item: SelectableValue<string>) => { const onChange = (changeType: ChangeType) => (item: SelectableValue<string>) => {
const { onKeyChanged, onValueChanged, onOperatorChanged } = props; const { onKeyChanged, onValueChanged, onOperatorChanged } = props;
if (!item.value) {
return;
}
switch (changeType) { switch (changeType) {
case ChangeType.Key: case ChangeType.Key:
onKeyChanged(item.value); onKeyChanged(item.value);
...@@ -54,13 +59,13 @@ export const AdHocFilter: React.FunctionComponent<Props> = props => { ...@@ -54,13 +59,13 @@ export const AdHocFilter: React.FunctionComponent<Props> = props => {
const { keys, initialKey, keysPlaceHolder, initialOperator, values, initialValue, valuesPlaceHolder } = props; const { keys, initialKey, keysPlaceHolder, initialOperator, values, initialValue, valuesPlaceHolder } = props;
const operators = ['=', '!=']; const operators = ['=', '!='];
const keysAsOptions = keys ? keys.map(stringToOption) : []; const keysAsOptions = keys ? keys.map(stringToOption) : [];
const selectedKey = initialKey ? keysAsOptions.filter(option => option.value === initialKey) : null; const selectedKey = initialKey ? keysAsOptions.filter(option => option.value === initialKey) : undefined;
const valuesAsOptions = values ? values.map(stringToOption) : []; const valuesAsOptions = values ? values.map(stringToOption) : [];
const selectedValue = initialValue ? valuesAsOptions.filter(option => option.value === initialValue) : null; const selectedValue = initialValue ? valuesAsOptions.filter(option => option.value === initialValue) : undefined;
const operatorsAsOptions = operators.map(stringToOption); const operatorsAsOptions = operators.map(stringToOption);
const selectedOperator = initialOperator const selectedOperator = initialOperator
? operatorsAsOptions.filter(option => option.value === initialOperator) ? operatorsAsOptions.filter(option => option.value === initialOperator)
: null; : undefined;
return ( return (
<div className={cx([styles.keyValueContainer])}> <div className={cx([styles.keyValueContainer])}>
......
...@@ -174,11 +174,11 @@ describe('AdHocFilterField', () => { ...@@ -174,11 +174,11 @@ describe('AdHocFilterField', () => {
const { instance } = setup(); const { instance } = setup();
const pairs: KeyValuePair[] = []; const pairs: KeyValuePair[] = [];
const index = 0; const index = 0;
const key: string = undefined; const key: undefined = undefined;
const keys: string[] = ['key 1', 'key 2']; const keys: string[] = ['key 1', 'key 2'];
const value: string = undefined; const value: undefined = undefined;
const values: string[] = undefined; const values: undefined = undefined;
const operator: string = undefined; const operator: undefined = undefined;
const result = instance.updatePairs(pairs, index, { key, keys, value, values, operator }); const result = instance.updatePairs(pairs, index, { key, keys, value, values, operator });
......
...@@ -131,7 +131,7 @@ export class AdHocFilterField< ...@@ -131,7 +131,7 @@ export class AdHocFilterField<
return allPairs; return allPairs;
} }
return allPairs.concat(pair); return allPairs.concat(pair);
}, []); }, [] as KeyValuePair[]);
this.setState({ pairs }); this.setState({ pairs });
}; };
......
...@@ -4,7 +4,7 @@ import { FadeIn } from 'app/core/components/Animations/FadeIn'; ...@@ -4,7 +4,7 @@ import { FadeIn } from 'app/core/components/Animations/FadeIn';
import { getFirstQueryErrorWithoutRefId, getValueWithRefId } from 'app/core/utils/explore'; import { getFirstQueryErrorWithoutRefId, getValueWithRefId } from 'app/core/utils/explore';
interface Props { interface Props {
queryErrors: DataQueryError[]; queryErrors?: DataQueryError[];
} }
export const ErrorContainer: FunctionComponent<Props> = props => { export const ErrorContainer: FunctionComponent<Props> = props => {
......
...@@ -203,9 +203,10 @@ export class Explore extends React.PureComponent<ExploreProps> { ...@@ -203,9 +203,10 @@ export class Explore extends React.PureComponent<ExploreProps> {
onModifyQueries = (action: any, index?: number) => { onModifyQueries = (action: any, index?: number) => {
const { datasourceInstance } = this.props; const { datasourceInstance } = this.props;
if (datasourceInstance && datasourceInstance.modifyQuery) { if (datasourceInstance?.modifyQuery) {
const modifier = (queries: DataQuery, modification: any) => datasourceInstance.modifyQuery(queries, modification); const modifier = (queries: DataQuery, modification: any) =>
this.props.modifyQueries(this.props.exploreId, action, index, modifier); datasourceInstance.modifyQuery!(queries, modification);
this.props.modifyQueries(this.props.exploreId, action, modifier, index);
} }
}; };
...@@ -277,7 +278,7 @@ export class Explore extends React.PureComponent<ExploreProps> { ...@@ -277,7 +278,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
{datasourceInstance && ( {datasourceInstance && (
<div className="explore-container"> <div className="explore-container">
<QueryRows exploreEvents={this.exploreEvents} exploreId={exploreId} queryKeys={queryKeys} /> <QueryRows exploreEvents={this.exploreEvents} exploreId={exploreId} queryKeys={queryKeys} />
<ErrorContainer queryErrors={[queryResponse.error]} /> <ErrorContainer queryErrors={queryResponse.error ? [queryResponse.error] : undefined} />
<AutoSizer onResize={this.onResize} disableHeight> <AutoSizer onResize={this.onResize} disableHeight>
{({ width }) => { {({ width }) => {
if (width === 0) { if (width === 0) {
...@@ -287,7 +288,7 @@ export class Explore extends React.PureComponent<ExploreProps> { ...@@ -287,7 +288,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
return ( return (
<main className={`m-t-2 ${styles.logsMain}`} style={{ width }}> <main className={`m-t-2 ${styles.logsMain}`} style={{ width }}>
<ErrorBoundaryAlert> <ErrorBoundaryAlert>
{showingStartPage && ( {showingStartPage && StartPage && (
<div className="grafana-info-box grafana-info-box--max-lg"> <div className="grafana-info-box grafana-info-box--max-lg">
<StartPage <StartPage
onClickExample={this.onClickExample} onClickExample={this.onClickExample}
...@@ -377,7 +378,7 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia ...@@ -377,7 +378,7 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia
const initialQueries: DataQuery[] = ensureQueriesMemoized(queries); const initialQueries: DataQuery[] = ensureQueriesMemoized(queries);
const initialRange = urlRange ? getTimeRangeFromUrlMemoized(urlRange, timeZone).raw : DEFAULT_RANGE; const initialRange = urlRange ? getTimeRangeFromUrlMemoized(urlRange, timeZone).raw : DEFAULT_RANGE;
let newMode: ExploreMode; let newMode: ExploreMode | undefined;
if (supportedModes.length) { if (supportedModes.length) {
const urlModeIsValid = supportedModes.includes(urlMode); const urlModeIsValid = supportedModes.includes(urlMode);
...@@ -391,7 +392,7 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia ...@@ -391,7 +392,7 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia
newMode = supportedModes[0]; newMode = supportedModes[0];
} }
} else { } else {
newMode = [ExploreMode.Metrics, ExploreMode.Logs].includes(urlMode) ? urlMode : null; newMode = [ExploreMode.Metrics, ExploreMode.Logs].includes(urlMode) ? urlMode : undefined;
} }
const initialUI = ui || DEFAULT_UI_STATE; const initialUI = ui || DEFAULT_UI_STATE;
......
...@@ -39,17 +39,17 @@ const getStyles = (theme: GrafanaTheme) => ({ ...@@ -39,17 +39,17 @@ const getStyles = (theme: GrafanaTheme) => ({
}); });
interface Props extends Themeable { interface Props extends Themeable {
series: GraphSeriesXY[]; series?: GraphSeriesXY[];
width: number; width: number;
absoluteRange: AbsoluteTimeRange; absoluteRange: AbsoluteTimeRange;
loading: boolean; loading?: boolean;
showPanel: boolean; showPanel: boolean;
showBars: boolean; showBars: boolean;
showLines: boolean; showLines: boolean;
isStacked: boolean; isStacked: boolean;
showingGraph: boolean; showingGraph?: boolean;
showingTable: boolean; showingTable?: boolean;
timeZone: TimeZone; timeZone?: TimeZone;
onUpdateTimeRange: (absoluteRange: AbsoluteTimeRange) => void; onUpdateTimeRange: (absoluteRange: AbsoluteTimeRange) => void;
onToggleGraph?: (showingGraph: boolean) => void; onToggleGraph?: (showingGraph: boolean) => void;
onHiddenSeriesChanged?: (hiddenSeries: string[]) => void; onHiddenSeriesChanged?: (hiddenSeries: string[]) => void;
...@@ -75,7 +75,7 @@ class UnThemedExploreGraphPanel extends PureComponent<Props, State> { ...@@ -75,7 +75,7 @@ class UnThemedExploreGraphPanel extends PureComponent<Props, State> {
onClickGraphButton = () => { onClickGraphButton = () => {
const { onToggleGraph, showingGraph } = this.props; const { onToggleGraph, showingGraph } = this.props;
if (onToggleGraph) { if (onToggleGraph) {
onToggleGraph(showingGraph); onToggleGraph(showingGraph ?? false);
} }
}; };
......
...@@ -73,7 +73,7 @@ export class ExploreTimeControls extends Component<Props> { ...@@ -73,7 +73,7 @@ export class ExploreTimeControls extends Component<Props> {
render() { render() {
const { range, timeZone, splitted, syncedTimes, onChangeTimeSync, hideText } = this.props; const { range, timeZone, splitted, syncedTimes, onChangeTimeSync, hideText } = this.props;
const timeSyncButton = splitted ? <TimeSyncButton onClick={onChangeTimeSync} isSynced={syncedTimes} /> : null; const timeSyncButton = splitted ? <TimeSyncButton onClick={onChangeTimeSync} isSynced={syncedTimes} /> : undefined;
const timePickerCommonProps = { const timePickerCommonProps = {
value: range, value: range,
onChange: this.onChangeTimePicker, onChange: this.onChangeTimePicker,
......
...@@ -54,18 +54,18 @@ interface StateProps { ...@@ -54,18 +54,18 @@ interface StateProps {
loading: boolean; loading: boolean;
range: TimeRange; range: TimeRange;
timeZone: TimeZone; timeZone: TimeZone;
selectedDatasource: DataSourceSelectItem; selectedDatasource?: DataSourceSelectItem;
splitted: boolean; splitted: boolean;
syncedTimes: boolean; syncedTimes: boolean;
refreshInterval: string; refreshInterval?: string;
supportedModes: ExploreMode[]; supportedModes: ExploreMode[];
selectedMode: ExploreMode; selectedMode: ExploreMode;
hasLiveOption: boolean; hasLiveOption: boolean;
isLive: boolean; isLive: boolean;
isPaused: boolean; isPaused: boolean;
originPanelId: number; originPanelId?: number;
queries: DataQuery[]; queries: DataQuery[];
datasourceLoading: boolean | null; datasourceLoading?: boolean;
containerWidth: number; containerWidth: number;
} }
...@@ -163,7 +163,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props> { ...@@ -163,7 +163,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props> {
} = this.props; } = this.props;
const styles = getStyles(); const styles = getStyles();
const originDashboardIsEditable = Number.isInteger(originPanelId); const originDashboardIsEditable = originPanelId && Number.isInteger(originPanelId);
const panelReturnClasses = classNames('btn', 'navbar-button', { const panelReturnClasses = classNames('btn', 'navbar-button', {
'btn--radius-right-0': originDashboardIsEditable, 'btn--radius-right-0': originDashboardIsEditable,
'navbar-button navbar-button--border-right-0': originDashboardIsEditable, 'navbar-button navbar-button--border-right-0': originDashboardIsEditable,
...@@ -234,7 +234,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props> { ...@@ -234,7 +234,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props> {
</div> </div>
) : null} ) : null}
{Number.isInteger(originPanelId) && !splitted && ( {originPanelId && Number.isInteger(originPanelId) && !splitted && (
<div className="explore-toolbar-content-item"> <div className="explore-toolbar-content-item">
<Tooltip content={'Return to panel'} placement="bottom"> <Tooltip content={'Return to panel'} placement="bottom">
<button className={panelReturnClasses} onClick={() => this.returnToPanel()}> <button className={panelReturnClasses} onClick={() => this.returnToPanel()}>
......
...@@ -63,7 +63,7 @@ interface State { ...@@ -63,7 +63,7 @@ interface State {
} }
class LiveLogs extends PureComponent<Props, State> { class LiveLogs extends PureComponent<Props, State> {
private liveEndDiv: HTMLDivElement = null; private liveEndDiv: HTMLDivElement | null = null;
private scrollContainerRef = React.createRef<HTMLDivElement>(); private scrollContainerRef = React.createRef<HTMLDivElement>();
private lastScrollPos: number | null = null; private lastScrollPos: number | null = null;
...@@ -77,7 +77,7 @@ class LiveLogs extends PureComponent<Props, State> { ...@@ -77,7 +77,7 @@ class LiveLogs extends PureComponent<Props, State> {
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: Props) {
if (!prevProps.isPaused && this.props.isPaused) { if (!prevProps.isPaused && this.props.isPaused) {
// So we paused the view and we changed the content size, but we want to keep the relative offset from the bottom. // So we paused the view and we changed the content size, but we want to keep the relative offset from the bottom.
if (this.lastScrollPos) { if (this.lastScrollPos && this.scrollContainerRef.current) {
// There is last scroll pos from when user scrolled up a bit so go to that position. // There is last scroll pos from when user scrolled up a bit so go to that position.
const { clientHeight, scrollHeight } = this.scrollContainerRef.current; const { clientHeight, scrollHeight } = this.scrollContainerRef.current;
const scrollTop = scrollHeight - (this.lastScrollPos + clientHeight); const scrollTop = scrollHeight - (this.lastScrollPos + clientHeight);
...@@ -123,7 +123,7 @@ class LiveLogs extends PureComponent<Props, State> { ...@@ -123,7 +123,7 @@ class LiveLogs extends PureComponent<Props, State> {
rowsToRender = () => { rowsToRender = () => {
const { isPaused } = this.props; const { isPaused } = this.props;
let rowsToRender: LogRowModel[] = this.state.logRowsToRender; let { logRowsToRender: rowsToRender = [] } = this.state;
if (!isPaused) { if (!isPaused) {
// A perf optimisation here. Show just 100 rows when streaming and full length when the streaming is paused. // A perf optimisation here. Show just 100 rows when streaming and full length when the streaming is paused.
rowsToRender = rowsToRender.slice(-100); rowsToRender = rowsToRender.slice(-100);
......
...@@ -37,7 +37,7 @@ interface Props { ...@@ -37,7 +37,7 @@ interface Props {
dedupedRows?: LogRowModel[]; dedupedRows?: LogRowModel[];
width: number; width: number;
highlighterExpressions: string[]; highlighterExpressions?: string[];
loading: boolean; loading: boolean;
absoluteRange: AbsoluteTimeRange; absoluteRange: AbsoluteTimeRange;
timeZone: TimeZone; timeZone: TimeZone;
......
...@@ -30,7 +30,7 @@ import { LiveTailControls } from './useLiveTailControls'; ...@@ -30,7 +30,7 @@ import { LiveTailControls } from './useLiveTailControls';
import { getLinksFromLogsField } from '../panel/panellinks/linkSuppliers'; import { getLinksFromLogsField } from '../panel/panellinks/linkSuppliers';
interface LogsContainerProps { interface LogsContainerProps {
datasourceInstance: DataSourceApi | null; datasourceInstance?: DataSourceApi;
exploreId: ExploreId; exploreId: ExploreId;
loading: boolean; loading: boolean;
...@@ -80,7 +80,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> { ...@@ -80,7 +80,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
getLogRowContext = async (row: LogRowModel, options?: any): Promise<any> => { getLogRowContext = async (row: LogRowModel, options?: any): Promise<any> => {
const { datasourceInstance } = this.props; const { datasourceInstance } = this.props;
if (datasourceInstance) { if (datasourceInstance?.getLogRowContext) {
return datasourceInstance.getLogRowContext(row, options); return datasourceInstance.getLogRowContext(row, options);
} }
......
...@@ -45,13 +45,13 @@ export default class QueryEditor extends PureComponent<QueryEditorProps, any> { ...@@ -45,13 +45,13 @@ export default class QueryEditor extends PureComponent<QueryEditorProps, any> {
target, target,
refresh: () => { refresh: () => {
setTimeout(() => { setTimeout(() => {
this.props.onQueryChange(target); this.props.onQueryChange?.(target);
this.props.onExecuteQuery(); this.props.onExecuteQuery?.();
}, 1); }, 1);
}, },
onQueryChange: () => { onQueryChange: () => {
setTimeout(() => { setTimeout(() => {
this.props.onQueryChange(target); this.props.onQueryChange?.(target);
}, 1); }, 1);
}, },
events: exploreEvents, events: exploreEvents,
...@@ -64,8 +64,8 @@ export default class QueryEditor extends PureComponent<QueryEditorProps, any> { ...@@ -64,8 +64,8 @@ export default class QueryEditor extends PureComponent<QueryEditorProps, any> {
this.angularScope = scopeProps.ctrl; this.angularScope = scopeProps.ctrl;
setTimeout(() => { setTimeout(() => {
this.props.onQueryChange(target); this.props.onQueryChange?.(target);
this.props.onExecuteQuery(); this.props.onExecuteQuery?.();
}, 1); }, 1);
} }
......
...@@ -134,12 +134,12 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> { ...@@ -134,12 +134,12 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
const queryErrors = queryResponse.error && queryResponse.error.refId === query.refId ? [queryResponse.error] : []; const queryErrors = queryResponse.error && queryResponse.error.refId === query.refId ? [queryResponse.error] : [];
let QueryField; let QueryField;
if (mode === ExploreMode.Metrics && datasourceInstance.components.ExploreMetricsQueryField) { if (mode === ExploreMode.Metrics && datasourceInstance.components?.ExploreMetricsQueryField) {
QueryField = datasourceInstance.components.ExploreMetricsQueryField; QueryField = datasourceInstance.components.ExploreMetricsQueryField;
} else if (mode === ExploreMode.Logs && datasourceInstance.components.ExploreLogsQueryField) { } else if (mode === ExploreMode.Logs && datasourceInstance.components?.ExploreLogsQueryField) {
QueryField = datasourceInstance.components.ExploreLogsQueryField; QueryField = datasourceInstance.components.ExploreLogsQueryField;
} else { } else {
QueryField = datasourceInstance.components.ExploreQueryField; QueryField = datasourceInstance.components?.ExploreQueryField;
} }
return ( return (
......
...@@ -2,7 +2,7 @@ import React from 'react'; ...@@ -2,7 +2,7 @@ import React from 'react';
export type Props = { export type Props = {
canToggleEditorModes: boolean; canToggleEditorModes: boolean;
isDisabled: boolean; isDisabled?: boolean;
isNotStarted: boolean; isNotStarted: boolean;
onClickToggleEditorMode: () => void; onClickToggleEditorMode: () => void;
onClickToggleDisabled: () => void; onClickToggleDisabled: () => void;
......
...@@ -21,7 +21,7 @@ type Props = { ...@@ -21,7 +21,7 @@ type Props = {
splitted: boolean; splitted: boolean;
loading: boolean; loading: boolean;
onRun: () => void; onRun: () => void;
refreshInterval: string; refreshInterval?: string;
onChangeRefreshInterval: (interval: string) => void; onChangeRefreshInterval: (interval: string) => void;
showDropdown: boolean; showDropdown: boolean;
}; };
......
...@@ -28,7 +28,7 @@ export default class Table extends PureComponent<TableProps> { ...@@ -28,7 +28,7 @@ export default class Table extends PureComponent<TableProps> {
if (link.className === 'link') { if (link.className === 'link') {
const columnKey = column.Header().props.title; const columnKey = column.Header().props.title;
const rowValue = rowInfo.row[columnKey]; const rowValue = rowInfo.row[columnKey];
this.props.onClickCell(columnKey, rowValue); this.props.onClickCell?.(columnKey, rowValue);
} }
} }
}, },
......
...@@ -118,7 +118,7 @@ export interface LoadDatasourceReadyPayload { ...@@ -118,7 +118,7 @@ export interface LoadDatasourceReadyPayload {
export interface ModifyQueriesPayload { export interface ModifyQueriesPayload {
exploreId: ExploreId; exploreId: ExploreId;
modification: QueryFixAction; modification: QueryFixAction;
index: number; index?: number;
modifier: (query: DataQuery, modification: QueryFixAction) => DataQuery; modifier: (query: DataQuery, modification: QueryFixAction) => DataQuery;
} }
......
...@@ -162,7 +162,7 @@ export function changeQuery( ...@@ -162,7 +162,7 @@ export function changeQuery(
exploreId: ExploreId, exploreId: ExploreId,
query: DataQuery, query: DataQuery,
index: number, index: number,
override: boolean override = false
): ThunkResult<void> { ): ThunkResult<void> {
return (dispatch, getState) => { return (dispatch, getState) => {
// Null query means reset // Null query means reset
...@@ -389,8 +389,8 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi, or ...@@ -389,8 +389,8 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi, or
export function modifyQueries( export function modifyQueries(
exploreId: ExploreId, exploreId: ExploreId,
modification: QueryFixAction, modification: QueryFixAction,
index: number, modifier: any,
modifier: any index?: number
): ThunkResult<void> { ): ThunkResult<void> {
return dispatch => { return dispatch => {
dispatch(modifyQueriesAction({ exploreId, modification, index, modifier })); dispatch(modifyQueriesAction({ exploreId, modification, index, modifier }));
......
...@@ -59,7 +59,7 @@ const state: any = { ...@@ -59,7 +59,7 @@ const state: any = {
describe('Deduplication selector', () => { describe('Deduplication selector', () => {
it('returns the same rows if no deduplication', () => { it('returns the same rows if no deduplication', () => {
const dedups = deduplicatedRowsSelector(state as ExploreItemState); const dedups = deduplicatedRowsSelector(state as ExploreItemState);
expect(dedups.length).toBe(11); expect(dedups?.length).toBe(11);
expect(dedups).toBe(state.logsResult.rows); expect(dedups).toBe(state.logsResult.rows);
}); });
...@@ -68,7 +68,7 @@ describe('Deduplication selector', () => { ...@@ -68,7 +68,7 @@ describe('Deduplication selector', () => {
...state, ...state,
dedupStrategy: LogsDedupStrategy.numbers, dedupStrategy: LogsDedupStrategy.numbers,
} as ExploreItemState); } as ExploreItemState);
expect(dedups.length).toBe(2); expect(dedups?.length).toBe(2);
expect(dedups).not.toBe(state.logsResult.rows); expect(dedups).not.toBe(state.logsResult.rows);
}); });
...@@ -77,7 +77,7 @@ describe('Deduplication selector', () => { ...@@ -77,7 +77,7 @@ describe('Deduplication selector', () => {
...state, ...state,
hiddenLogLevels: [LogLevel.debug], hiddenLogLevels: [LogLevel.debug],
} as ExploreItemState); } as ExploreItemState);
expect(dedups.length).toBe(2); expect(dedups?.length).toBe(2);
expect(dedups).not.toBe(state.logsResult.rows); expect(dedups).not.toBe(state.logsResult.rows);
dedups = deduplicatedRowsSelector({ dedups = deduplicatedRowsSelector({
...@@ -86,7 +86,7 @@ describe('Deduplication selector', () => { ...@@ -86,7 +86,7 @@ describe('Deduplication selector', () => {
hiddenLogLevels: [LogLevel.debug], hiddenLogLevels: [LogLevel.debug],
} as ExploreItemState); } as ExploreItemState);
expect(dedups.length).toBe(2); expect(dedups?.length).toBe(2);
expect(dedups).not.toBe(state.logsResult.rows); expect(dedups).not.toBe(state.logsResult.rows);
}); });
}); });
...@@ -14,7 +14,7 @@ export class ResultProcessor { ...@@ -14,7 +14,7 @@ export class ResultProcessor {
private timeZone: TimeZone private timeZone: TimeZone
) {} ) {}
getGraphResult(): GraphSeriesXY[] { getGraphResult(): GraphSeriesXY[] | null {
if (this.state.mode !== ExploreMode.Metrics) { if (this.state.mode !== ExploreMode.Metrics) {
return null; return null;
} }
...@@ -34,7 +34,7 @@ export class ResultProcessor { ...@@ -34,7 +34,7 @@ export class ResultProcessor {
); );
} }
getTableResult(): TableModel { getTableResult(): TableModel | null {
if (this.state.mode !== ExploreMode.Metrics) { if (this.state.mode !== ExploreMode.Metrics) {
return null; return null;
} }
...@@ -78,7 +78,7 @@ export class ResultProcessor { ...@@ -78,7 +78,7 @@ export class ResultProcessor {
return mergeTablesIntoModel(new TableModel(), ...tables); return mergeTablesIntoModel(new TableModel(), ...tables);
} }
getLogsResult(): LogsModel { getLogsResult(): LogsModel | null {
if (this.state.mode !== ExploreMode.Logs) { if (this.state.mode !== ExploreMode.Logs) {
return null; return null;
} }
......
...@@ -65,7 +65,7 @@ export interface ExploreItemState { ...@@ -65,7 +65,7 @@ export interface ExploreItemState {
/** /**
* Datasource instance that has been selected. Datasource-specific logic can be run on this object. * Datasource instance that has been selected. Datasource-specific logic can be run on this object.
*/ */
datasourceInstance: DataSourceApi | null; datasourceInstance?: DataSourceApi;
/** /**
* Current data source name or null if default * Current data source name or null if default
*/ */
...@@ -73,7 +73,7 @@ export interface ExploreItemState { ...@@ -73,7 +73,7 @@ export interface ExploreItemState {
/** /**
* True if the datasource is loading. `null` if the loading has not started yet. * True if the datasource is loading. `null` if the loading has not started yet.
*/ */
datasourceLoading: boolean | null; datasourceLoading?: boolean;
/** /**
* True if there is no datasource to be selected. * True if there is no datasource to be selected.
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment