Performance: Standardize lodash imports to use destructured members (#33040)

* Performance: Standardize lodash imports to use destructured members
Changes lodash imports of the form `import x from 'lodash/x'` to
`import { x } from 'lodash'` to reduce bundle size.

* Remove unnecessary _ import from Graph component

* Enforce lodash import style

* Fix remaining lodash imports
This commit is contained in:
kay delaney 2021-04-21 08:38:00 +01:00 committed by GitHub
parent 2bb7eb18d1
commit bad048b7ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
299 changed files with 1135 additions and 1137 deletions

View File

@ -1,11 +1,12 @@
{ {
"extends": ["@grafana/eslint-config"], "extends": ["@grafana/eslint-config"],
"root": true, "root": true,
"plugins": ["no-only-tests", "@emotion"], "plugins": ["no-only-tests", "@emotion", "lodash"],
"rules": { "rules": {
"no-only-tests/no-only-tests": "error", "no-only-tests/no-only-tests": "error",
"react/prop-types": "off", "react/prop-types": "off",
"@emotion/jsx-import": "error" "@emotion/jsx-import": "error",
"lodash/import-scope": [2, "member"]
}, },
"overrides": [ "overrides": [
{ {

View File

@ -146,6 +146,7 @@
"eslint": "7.21.0", "eslint": "7.21.0",
"eslint-config-prettier": "7.2.0", "eslint-config-prettier": "7.2.0",
"eslint-plugin-jsdoc": "31.6.1", "eslint-plugin-jsdoc": "31.6.1",
"eslint-plugin-lodash": "^7.2.0",
"eslint-plugin-no-only-tests": "2.4.0", "eslint-plugin-no-only-tests": "2.4.0",
"eslint-plugin-prettier": "3.3.1", "eslint-plugin-prettier": "3.3.1",
"eslint-plugin-react": "7.22.0", "eslint-plugin-react": "7.22.0",

View File

@ -1,7 +1,7 @@
import { Field, DataFrame, DataFrameDTO, FieldDTO, FieldType } from '../types/dataFrame'; import { Field, DataFrame, DataFrameDTO, FieldDTO, FieldType } from '../types/dataFrame';
import { QueryResultMeta } from '../types/data'; import { QueryResultMeta } from '../types/data';
import { guessFieldTypeFromValue, guessFieldTypeForField, toDataFrameDTO } from './processDataFrame'; import { guessFieldTypeFromValue, guessFieldTypeForField, toDataFrameDTO } from './processDataFrame';
import isString from 'lodash/isString'; import { isString } from 'lodash';
import { makeFieldParser } from '../utils/fieldParser'; import { makeFieldParser } from '../utils/fieldParser';
import { MutableVector, Vector } from '../types/vector'; import { MutableVector, Vector } from '../types/vector';
import { ArrayVector } from '../vector/ArrayVector'; import { ArrayVector } from '../vector/ArrayVector';

View File

@ -1,5 +1,5 @@
import sinon, { SinonFakeTimers } from 'sinon'; import sinon, { SinonFakeTimers } from 'sinon';
import each from 'lodash/each'; import { each } from 'lodash';
import * as dateMath from './datemath'; import * as dateMath from './datemath';
import { dateTime, DurationUnit, DateTime } from './moment_wrapper'; import { dateTime, DurationUnit, DateTime } from './moment_wrapper';

View File

@ -1,5 +1,4 @@
import includes from 'lodash/includes'; import { includes, isDate } from 'lodash';
import isDate from 'lodash/isDate';
import { DateTime, dateTime, dateTimeForTimeZone, ISO_8601, isDateTime, DurationUnit } from './moment_wrapper'; import { DateTime, dateTime, dateTimeForTimeZone, ISO_8601, isDateTime, DurationUnit } from './moment_wrapper';
import { TimeZone } from '../types/index'; import { TimeZone } from '../types/index';

View File

@ -1,6 +1,4 @@
import each from 'lodash/each'; import { each, groupBy, has } from 'lodash';
import groupBy from 'lodash/groupBy';
import has from 'lodash/has';
import { RawTimeRange, TimeRange, TimeZone, IntervalValues } from '../types/time'; import { RawTimeRange, TimeRange, TimeZone, IntervalValues } from '../types/time';

View File

@ -1,5 +1,5 @@
// Libraries // Libraries
import _ from 'lodash'; import { toString, toNumber as _toNumber, isEmpty, isBoolean } from 'lodash';
// Types // Types
import { Field, FieldType } from '../types/dataFrame'; import { Field, FieldType } from '../types/dataFrame';
@ -36,7 +36,7 @@ const timeFormats: KeyValue<boolean> = {
}; };
export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayProcessor { export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayProcessor {
if (!options || _.isEmpty(options) || !options.field) { if (!options || isEmpty(options) || !options.field) {
return toStringProcessor; return toStringProcessor;
} }
@ -65,7 +65,7 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP
value = dateTime(value).valueOf(); value = dateTime(value).valueOf();
} }
let text = _.toString(value); let text = toString(value);
let numeric = isStringUnit ? NaN : toNumber(value); let numeric = isStringUnit ? NaN : toNumber(value);
let prefix: string | undefined = undefined; let prefix: string | undefined = undefined;
let suffix: string | undefined = undefined; let suffix: string | undefined = undefined;
@ -87,7 +87,7 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP
} }
if (!isNaN(numeric)) { if (!isNaN(numeric)) {
if (shouldFormat && !_.isBoolean(value)) { if (shouldFormat && !isBoolean(value)) {
const v = formatFunc(numeric, config.decimals, null, options.timeZone); const v = formatFunc(numeric, config.decimals, null, options.timeZone);
text = v.text; text = v.text;
suffix = v.suffix; suffix = v.suffix;
@ -123,11 +123,11 @@ function toNumber(value: any): number {
if (typeof value === 'boolean') { if (typeof value === 'boolean') {
return value ? 1 : 0; return value ? 1 : 0;
} }
return _.toNumber(value); return _toNumber(value);
} }
function toStringProcessor(value: any): DisplayValue { function toStringProcessor(value: any): DisplayValue {
return { text: _.toString(value), numeric: toNumber(value) }; return { text: toString(value), numeric: toNumber(value) };
} }
export function getRawDisplayProcessor(): DisplayProcessor { export function getRawDisplayProcessor(): DisplayProcessor {

View File

@ -1,7 +1,7 @@
import { Field, FieldType } from '../types/dataFrame'; import { Field, FieldType } from '../types/dataFrame';
import { Vector } from '../types/vector'; import { Vector } from '../types/vector';
import { dateTime } from '../datetime'; import { dateTime } from '../datetime';
import isNumber from 'lodash/isNumber'; import { isNumber } from 'lodash';
type IndexComparer = (a: number, b: number) => number; type IndexComparer = (a: number, b: number) => number;

View File

@ -1,4 +1,4 @@
import merge from 'lodash/merge'; import { merge } from 'lodash';
import { getFieldDisplayValues, GetFieldDisplayValuesOptions } from './fieldDisplay'; import { getFieldDisplayValues, GetFieldDisplayValuesOptions } from './fieldDisplay';
import { toDataFrame } from '../dataframe/processDataFrame'; import { toDataFrame } from '../dataframe/processDataFrame';
import { ReducerID } from '../transformations/fieldReducer'; import { ReducerID } from '../transformations/fieldReducer';

View File

@ -1,5 +1,4 @@
import toString from 'lodash/toString'; import { toString, isEmpty } from 'lodash';
import isEmpty from 'lodash/isEmpty';
import { getDisplayProcessor } from './displayProcessor'; import { getDisplayProcessor } from './displayProcessor';
import { import {

View File

@ -19,10 +19,7 @@ import {
} from '../types'; } from '../types';
import { fieldMatchers, reduceField, ReducerID } from '../transformations'; import { fieldMatchers, reduceField, ReducerID } from '../transformations';
import { FieldMatcher } from '../types/transformations'; import { FieldMatcher } from '../types/transformations';
import isNumber from 'lodash/isNumber'; import { isNumber, set, unset, get } from 'lodash';
import set from 'lodash/set';
import unset from 'lodash/unset';
import get from 'lodash/get';
import { getDisplayProcessor, getRawDisplayProcessor } from './displayProcessor'; import { getDisplayProcessor, getRawDisplayProcessor } from './displayProcessor';
import { guessFieldTypeForField } from '../dataframe'; import { guessFieldTypeForField } from '../dataframe';
import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry'; import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry';

View File

@ -1,4 +1,4 @@
import toNumber from 'lodash/toNumber'; import { toNumber } from 'lodash';
import { DataFrame, DisplayValue, GrafanaTheme, TimeZone } from '../types'; import { DataFrame, DisplayValue, GrafanaTheme, TimeZone } from '../types';
import { getDisplayProcessor } from './displayProcessor'; import { getDisplayProcessor } from './displayProcessor';
import { formattedValueToString } from '../valueFormats'; import { formattedValueToString } from '../valueFormats';

View File

@ -11,7 +11,7 @@ import {
} from '../types'; } from '../types';
import { FieldConfigEditorBuilder, PanelOptionsEditorBuilder } from '../utils/OptionsUIBuilders'; import { FieldConfigEditorBuilder, PanelOptionsEditorBuilder } from '../utils/OptionsUIBuilders';
import { ComponentClass, ComponentType } from 'react'; import { ComponentClass, ComponentType } from 'react';
import set from 'lodash/set'; import { set } from 'lodash';
import { deprecationWarning } from '../utils'; import { deprecationWarning } from '../utils';
import { FieldConfigOptionsRegistry } from '../field'; import { FieldConfigOptionsRegistry } from '../field';
import { createFieldConfigRegistry } from './registryFactories'; import { createFieldConfigRegistry } from './registryFactories';

View File

@ -1,4 +1,4 @@
import difference from 'lodash/difference'; import { difference } from 'lodash';
import { fieldReducers, ReducerID, reduceField } from './fieldReducer'; import { fieldReducers, ReducerID, reduceField } from './fieldReducer';

View File

@ -1,5 +1,5 @@
// Libraries // Libraries
import isNumber from 'lodash/isNumber'; import { isNumber } from 'lodash';
import { NullValueMode, Field, FieldState, FieldCalcs, FieldType } from '../types/index'; import { NullValueMode, Field, FieldState, FieldCalcs, FieldType } from '../types/index';
import { Registry, RegistryItem } from '../utils/Registry'; import { Registry, RegistryItem } from '../utils/Registry';

View File

@ -9,7 +9,7 @@ import { RowVector } from '../../vector/RowVector';
import { ArrayVector, BinaryOperationVector, ConstantVector } from '../../vector'; import { ArrayVector, BinaryOperationVector, ConstantVector } from '../../vector';
import { AsNumberVector } from '../../vector/AsNumberVector'; import { AsNumberVector } from '../../vector/AsNumberVector';
import { getTimeField } from '../../dataframe/processDataFrame'; import { getTimeField } from '../../dataframe/processDataFrame';
import defaults from 'lodash/defaults'; import { defaults } from 'lodash';
import { BinaryOperationID, binaryOperators } from '../../utils/binaryOperators'; import { BinaryOperationID, binaryOperators } from '../../utils/binaryOperators';
import { ensureColumnsTransformer } from './ensureColumns'; import { ensureColumnsTransformer } from './ensureColumns';
import { getFieldDisplayName } from '../../field'; import { getFieldDisplayName } from '../../field';

View File

@ -1,6 +1,6 @@
// Libraries // Libraries
import Papa, { ParseConfig, Parser, ParseResult } from 'papaparse'; import Papa, { ParseConfig, Parser, ParseResult } from 'papaparse';
import defaults from 'lodash/defaults'; import { defaults } from 'lodash';
// Types // Types
import { DataFrame, Field, FieldConfig, FieldType } from '../types'; import { DataFrame, Field, FieldConfig, FieldType } from '../types';

View File

@ -1,4 +1,4 @@
import flatten from 'lodash/flatten'; import { flatten } from 'lodash';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { GrafanaTheme, GrafanaThemeType } from '../types/theme'; import { GrafanaTheme, GrafanaThemeType } from '../types/theme';

View File

@ -2,7 +2,7 @@
* @preserve jquery-param (c) 2015 KNOWLEDGECODE | MIT * @preserve jquery-param (c) 2015 KNOWLEDGECODE | MIT
*/ */
import _ from 'lodash'; import { toNumber } from 'lodash';
import { ExploreUrlState } from '../types/explore'; import { ExploreUrlState } from '../types/explore';
/** /**
@ -156,7 +156,7 @@ export function parseKeyValue(keyValue: string) {
let parsedVal: any; let parsedVal: any;
if (typeof val === 'string' && val !== '') { if (typeof val === 'string' && val !== '') {
parsedVal = val === 'true' || val === 'false' ? val === 'true' : _.toNumber(val); parsedVal = val === 'true' || val === 'false' ? val === 'true' : toNumber(val);
} else { } else {
parsedVal = val; parsedVal = val;
} }

View File

@ -1,4 +1,4 @@
import merge from 'lodash/merge'; import { merge } from 'lodash';
import { getTheme } from '@grafana/ui'; import { getTheme } from '@grafana/ui';
import { import {
BuildInfo, BuildInfo,

View File

@ -1,8 +1,6 @@
// @ts-ignore import { difference, sortBy } from 'lodash';
import * as _ from 'lodash';
import { Task } from './task'; import { Task } from './task';
import GithubClient from '../utils/githubClient'; import GithubClient from '../utils/githubClient';
import difference from 'lodash/difference';
import chalk from 'chalk'; import chalk from 'chalk';
import { useSpinner } from '../utils/useSpinner'; import { useSpinner } from '../utils/useSpinner';
@ -26,8 +24,8 @@ const getPackageChangelog = (packageName: string, issues: any[]) => {
} }
let markdown = chalk.bold.yellow(`\n\n/*** ${packageName} changelog ***/\n\n`); let markdown = chalk.bold.yellow(`\n\n/*** ${packageName} changelog ***/\n\n`);
const bugs = _.sortBy(issues.filter(filterBugs), 'title'); const bugs = sortBy(issues.filter(filterBugs), 'title');
const notBugs = _.sortBy(difference(issues, bugs), 'title'); const notBugs = sortBy(difference(issues, bugs), 'title');
if (notBugs.length > 0) { if (notBugs.length > 0) {
markdown += '### Features / Enhancements\n'; markdown += '### Features / Enhancements\n';
@ -89,7 +87,7 @@ const changelogTaskRunner = ({ milestone }: ChangelogOptions) =>
mergedIssues.push(item); mergedIssues.push(item);
} }
} }
const issues = _.sortBy(mergedIssues, 'title'); const issues = sortBy(mergedIssues, 'title');
const toolkitIssues = issues.filter((item: any) => const toolkitIssues = issues.filter((item: any) =>
item.labels.find((label: any) => label.name === 'area/grafana/toolkit') item.labels.find((label: any) => label.name === 'area/grafana/toolkit')

View File

@ -1,6 +1,6 @@
import { Task, TaskRunner } from './task'; import { Task, TaskRunner } from './task';
import fs from 'fs'; import fs from 'fs';
import _ from 'lodash'; import { template as _template } from 'lodash';
import { prompt } from 'inquirer'; import { prompt } from 'inquirer';
import { pascalCase } from '../utils/pascalCase'; import { pascalCase } from '../utils/pascalCase';
import { promptConfirm, promptInput, promptList } from '../utils/prompt'; import { promptConfirm, promptInput, promptList } from '../utils/prompt';
@ -53,7 +53,7 @@ export const promptDetails = () => {
export const generateComponents: ComponentGenerator = async ({ details, path }) => { export const generateComponents: ComponentGenerator = async ({ details, path }) => {
const name = pascalCase(details.name); const name = pascalCase(details.name);
const getCompiled = (template: string) => { const getCompiled = (template: string) => {
return _.template(template)({ ...details, name }); return _template(template)({ ...details, name });
}; };
const filePath = `${path}/${name}`; const filePath = `${path}/${name}`;
let paths = []; let paths = [];

View File

@ -2,7 +2,7 @@ import chalk from 'chalk';
import commandExists from 'command-exists'; import commandExists from 'command-exists';
import { promises as fs, readFileSync } from 'fs'; import { promises as fs, readFileSync } from 'fs';
import { prompt } from 'inquirer'; import { prompt } from 'inquirer';
import kebabCase from 'lodash/kebabCase'; import { kebabCase } from 'lodash';
import path from 'path'; import path from 'path';
import gitPromise from 'simple-git/promise'; import gitPromise from 'simple-git/promise';
import { promptConfirm, promptInput } from '../../utils/prompt'; import { promptConfirm, promptInput } from '../../utils/prompt';

View File

@ -1,3 +1,3 @@
import _ from 'lodash'; import { flow, camelCase, upperFirst } from 'lodash';
export const pascalCase = _.flow(_.camelCase, _.upperFirst); export const pascalCase = flow(camelCase, upperFirst);

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import debounce from 'lodash/debounce'; import { debounce } from 'lodash';
import { ColorPickerProps } from './ColorPickerPopover'; import { ColorPickerProps } from './ColorPickerPopover';
import { Input } from '../Forms/Legacy/Input/Input'; import { Input } from '../Forms/Legacy/Input/Input';

View File

@ -1,5 +1,4 @@
import React, { Component, createRef } from 'react'; import React, { Component, createRef } from 'react';
import omit from 'lodash/omit';
import { PopoverController } from '../Tooltip/PopoverController'; import { PopoverController } from '../Tooltip/PopoverController';
import { Popover } from '../Tooltip/Popover'; import { Popover } from '../Tooltip/Popover';
import { ColorPickerPopover, ColorPickerProps, ColorPickerChangeHandler } from './ColorPickerPopover'; import { ColorPickerPopover, ColorPickerProps, ColorPickerChangeHandler } from './ColorPickerPopover';
@ -43,7 +42,7 @@ export const colorPickerFactory = <T extends ColorPickerProps>(
const { theme, children } = this.props; const { theme, children } = this.props;
const styles = getStyles(theme); const styles = getStyles(theme);
const popoverElement = React.createElement(popover, { const popoverElement = React.createElement(popover, {
...omit(this.props, 'children'), ...{ ...this.props, children: null },
onChange: this.onColorChange, onChange: this.onColorChange,
}); });

View File

@ -2,7 +2,7 @@ import React from 'react';
import { mount, ReactWrapper } from 'enzyme'; import { mount, ReactWrapper } from 'enzyme';
import { ColorPickerPopover } from './ColorPickerPopover'; import { ColorPickerPopover } from './ColorPickerPopover';
import { ColorSwatch } from './NamedColorsGroup'; import { ColorSwatch } from './NamedColorsGroup';
import flatten from 'lodash/flatten'; import { flatten } from 'lodash';
import { getNamedColorPalette, getColorFromHexRgbOrName } from '@grafana/data'; import { getNamedColorPalette, getColorFromHexRgbOrName } from '@grafana/data';
const allColors = flatten(Array.from(getNamedColorPalette().values())); const allColors = flatten(Array.from(getNamedColorPalette().values()));

View File

@ -2,8 +2,7 @@ import React, { FunctionComponent } from 'react';
import { Themeable } from '../../types'; import { Themeable } from '../../types';
import { ColorDefinition } from '@grafana/data'; import { ColorDefinition } from '@grafana/data';
import { Color } from 'csstype'; import { Color } from 'csstype';
import upperFirst from 'lodash/upperFirst'; import { upperFirst, find } from 'lodash';
import find from 'lodash/find';
type ColorChangeHandler = (color: ColorDefinition) => void; type ColorChangeHandler = (color: ColorDefinition) => void;

View File

@ -1,5 +1,5 @@
import React, { FC, useCallback, useEffect, useRef } from 'react'; import React, { FC, useCallback, useEffect, useRef } from 'react';
import isNil from 'lodash/isNil'; import { isNil } from 'lodash';
import classNames from 'classnames'; import classNames from 'classnames';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import Scrollbars from 'react-custom-scrollbars'; import Scrollbars from 'react-custom-scrollbars';

View File

@ -1,7 +1,7 @@
import { ThemeContext } from '../../index'; import { ThemeContext } from '../../index';
import { GrafanaTheme, VariableSuggestion } from '@grafana/data'; import { GrafanaTheme, VariableSuggestion } from '@grafana/data';
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import _ from 'lodash'; import { groupBy, capitalize } from 'lodash';
import React, { useRef, useContext, useMemo } from 'react'; import React, { useRef, useContext, useMemo } from 'react';
import useClickAway from 'react-use/lib/useClickAway'; import useClickAway from 'react-use/lib/useClickAway';
import { List } from '../index'; import { List } from '../index';
@ -70,7 +70,7 @@ export const DataLinkSuggestions: React.FC<DataLinkSuggestionsProps> = ({ sugges
}); });
const groupedSuggestions = useMemo(() => { const groupedSuggestions = useMemo(() => {
return _.groupBy(suggestions, (s) => s.origin); return groupBy(suggestions, (s) => s.origin);
}, [suggestions]); }, [suggestions]);
const styles = getStyles(theme); const styles = getStyles(theme);
@ -91,7 +91,7 @@ export const DataLinkSuggestions: React.FC<DataLinkSuggestionsProps> = ({ sugges
<DataLinkSuggestionsList <DataLinkSuggestionsList
{...otherProps} {...otherProps}
suggestions={groupedSuggestions[key]} suggestions={groupedSuggestions[key]}
label={`${_.capitalize(key)}`} label={`${capitalize(key)}`}
activeIndex={otherProps.activeIndex} activeIndex={otherProps.activeIndex}
activeIndexOffset={indexOffset} activeIndexOffset={indexOffset}
key={key} key={key}

View File

@ -2,7 +2,7 @@ import { DataFrame, DataLink, GrafanaTheme, VariableSuggestion } from '@grafana/
import React, { useState } from 'react'; import React, { useState } from 'react';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { Button } from '../../Button/Button'; import { Button } from '../../Button/Button';
import cloneDeep from 'lodash/cloneDeep'; import { cloneDeep } from 'lodash';
import { Modal } from '../../Modal/Modal'; import { Modal } from '../../Modal/Modal';
import { stylesFactory, useTheme } from '../../../themes'; import { stylesFactory, useTheme } from '../../../themes';
import { DataLinksListItem } from './DataLinksListItem'; import { DataLinksListItem } from './DataLinksListItem';

View File

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import uniqueId from 'lodash/uniqueId'; import { uniqueId } from 'lodash';
import { DataSourceSettings } from '@grafana/data'; import { DataSourceSettings } from '@grafana/data';
import { Button } from '../Button'; import { Button } from '../Button';
import { FormField } from '../FormField/FormField'; import { FormField } from '../FormField/FormField';

View File

@ -1,5 +1,5 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import uniqueId from 'lodash/uniqueId'; import { uniqueId } from 'lodash';
import { Placement } from '@popperjs/core'; import { Placement } from '@popperjs/core';
import { Tooltip } from '../../../Tooltip/Tooltip'; import { Tooltip } from '../../../Tooltip/Tooltip';
import { Icon } from '../../..'; import { Icon } from '../../..';

View File

@ -1,6 +1,6 @@
import React, { useCallback, useRef } from 'react'; import React, { useCallback, useRef } from 'react';
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import uniqueId from 'lodash/uniqueId'; import { uniqueId } from 'lodash';
import { GrafanaTheme, SelectableValue } from '@grafana/data'; import { GrafanaTheme, SelectableValue } from '@grafana/data';
import { RadioButtonSize, RadioButton } from './RadioButton'; import { RadioButtonSize, RadioButton } from './RadioButton';
import { Icon } from '../../Icon/Icon'; import { Icon } from '../../Icon/Icon';

View File

@ -1,10 +1,9 @@
// Libraries // Libraries
import $ from 'jquery'; import $ from 'jquery';
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import uniqBy from 'lodash/uniqBy'; import { uniqBy } from 'lodash';
// Types // Types
import { TimeRange, GraphSeriesXY, TimeZone, createDimension } from '@grafana/data'; import { TimeRange, GraphSeriesXY, TimeZone, createDimension } from '@grafana/data';
import _ from 'lodash';
import { FlotPosition, FlotItem } from './types'; import { FlotPosition, FlotItem } from './types';
import { VizTooltipProps, VizTooltipContentProps, ActiveDimensions, VizTooltip } from '../VizTooltip'; import { VizTooltipProps, VizTooltipContentProps, ActiveDimensions, VizTooltip } from '../VizTooltip';
import { GraphTooltip } from './GraphTooltip/GraphTooltip'; import { GraphTooltip } from './GraphTooltip/GraphTooltip';

View File

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import { GraphSeriesXY } from '@grafana/data'; import { GraphSeriesXY } from '@grafana/data';
import difference from 'lodash/difference'; import { difference, isEqual } from 'lodash';
import isEqual from 'lodash/isEqual';
export interface GraphSeriesTogglerAPI { export interface GraphSeriesTogglerAPI {
onSeriesToggle: (label: string, event: React.MouseEvent<HTMLElement>) => void; onSeriesToggle: (label: string, event: React.MouseEvent<HTMLElement>) => void;

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import isNumber from 'lodash/isNumber'; import { isNumber } from 'lodash';
import { GraphNGLegendEventMode, XYFieldMatchers } from './types'; import { GraphNGLegendEventMode, XYFieldMatchers } from './types';
import { import {
ArrayVector, ArrayVector,

View File

@ -3,7 +3,7 @@
import { isObject, getObjectName, getType, getValuePreview, cssClass, createElement } from './helpers'; import { isObject, getObjectName, getType, getValuePreview, cssClass, createElement } from './helpers';
import _ from 'lodash'; import { isNumber } from 'lodash';
const DATE_STRING_REGEX = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/; const DATE_STRING_REGEX = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/;
const PARTIAL_DATE_REGEX = /\d{2}:\d{2}:\d{2} GMT-\d{4}/; const PARTIAL_DATE_REGEX = /\d{2}:\d{2}:\d{2} GMT-\d{4}/;
@ -222,7 +222,7 @@ export class JsonExplorer {
} }
isNumberArray() { isNumberArray() {
return this.json.length > 0 && this.json.length < 4 && (_.isNumber(this.json[0]) || _.isNumber(this.json[1])); return this.json.length > 0 && this.json.length < 4 && (isNumber(this.json[0]) || isNumber(this.json[1]));
} }
renderArray() { renderArray() {

View File

@ -1,5 +1,5 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import _ from 'lodash'; import { isEqual } from 'lodash';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { LogRowModel, findHighlightChunksInText, GrafanaTheme } from '@grafana/data'; import { LogRowModel, findHighlightChunksInText, GrafanaTheme } from '@grafana/data';
@ -76,7 +76,7 @@ class UnThemedLogRowMessage extends PureComponent<Props> {
const style = getLogRowStyles(theme, row.logLevel); const style = getLogRowStyles(theme, row.logLevel);
const { entry, hasAnsi, raw } = row; const { entry, hasAnsi, raw } = row;
const previewHighlights = highlighterExpressions?.length && !_.isEqual(highlighterExpressions, row.searchWords); const previewHighlights = highlighterExpressions?.length && !isEqual(highlighterExpressions, row.searchWords);
const highlights = previewHighlights ? highlighterExpressions : row.searchWords; const highlights = previewHighlights ? highlighterExpressions : row.searchWords;
const needsHighlighter = const needsHighlighter =
highlights && highlights.length > 0 && highlights[0] && highlights[0].length > 0 && entry.length < MAX_CHARACTERS; highlights && highlights.length > 0 && highlights[0] && highlights[0].length > 0 && entry.length < MAX_CHARACTERS;

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { debounce } from 'lodash';
import React, { Context } from 'react'; import React, { Context } from 'react';
import { Value, Editor as CoreEditor } from 'slate'; import { Value, Editor as CoreEditor } from 'slate';
@ -64,7 +64,7 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
constructor(props: QueryFieldProps, context: Context<any>) { constructor(props: QueryFieldProps, context: Context<any>) {
super(props, context); super(props, context);
this.runOnChangeDebounced = _.debounce(this.runOnChange, 500); this.runOnChangeDebounced = debounce(this.runOnChange, 500);
const { onTypeahead, cleanText, portalOrigin, onWillApplySuggestion } = props; const { onTypeahead, cleanText, portalOrigin, onWillApplySuggestion } = props;

View File

@ -1,4 +1,4 @@
import omit from 'lodash/omit'; import { omit } from 'lodash';
import React, { InputHTMLAttributes, FunctionComponent } from 'react'; import React, { InputHTMLAttributes, FunctionComponent } from 'react';
import { FormField } from '../FormField/FormField'; import { FormField } from '../FormField/FormField';
import { Button } from '../Button/Button'; import { Button } from '../Button/Button';

View File

@ -1,6 +1,6 @@
import React, { HTMLProps } from 'react'; import React, { HTMLProps } from 'react';
import { cx } from '@emotion/css'; import { cx } from '@emotion/css';
import _ from 'lodash'; import { isObject } from 'lodash';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
import { SegmentSelect, useExpandableLabel, SegmentProps } from './'; import { SegmentSelect, useExpandableLabel, SegmentProps } from './';
import { getSegmentStyles } from './styles'; import { getSegmentStyles } from './styles';
@ -28,7 +28,7 @@ export function Segment<T>({
const styles = useStyles(getSegmentStyles); const styles = useStyles(getSegmentStyles);
if (!expanded) { if (!expanded) {
const label = _.isObject(value) ? value.label : value; const label = isObject(value) ? value.label : value;
return ( return (
<Label <Label
@ -56,7 +56,7 @@ export function Segment<T>({
return ( return (
<SegmentSelect <SegmentSelect
{...rest} {...rest}
value={value && !_.isObject(value) ? { value } : value} value={value && !isObject(value) ? { value } : value}
options={options} options={options}
width={width} width={width}
onClickOutside={() => setExpanded(false)} onClickOutside={() => setExpanded(false)}

View File

@ -1,6 +1,6 @@
import React, { HTMLProps } from 'react'; import React, { HTMLProps } from 'react';
import { cx } from '@emotion/css'; import { cx } from '@emotion/css';
import _ from 'lodash'; import { isObject } from 'lodash';
import { SegmentSelect } from './SegmentSelect'; import { SegmentSelect } from './SegmentSelect';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
import { useExpandableLabel, SegmentProps } from '.'; import { useExpandableLabel, SegmentProps } from '.';
@ -34,7 +34,7 @@ export function SegmentAsync<T>({
const styles = useStyles(getSegmentStyles); const styles = useStyles(getSegmentStyles);
if (!expanded) { if (!expanded) {
const label = _.isObject(value) ? value.label : value; const label = isObject(value) ? value.label : value;
return ( return (
<Label <Label
@ -63,7 +63,7 @@ export function SegmentAsync<T>({
return ( return (
<SegmentSelect <SegmentSelect
{...rest} {...rest}
value={value && !_.isObject(value) ? { value } : value} value={value && !isObject(value) ? { value } : value}
options={state.value ?? []} options={state.value ?? []}
width={width} width={width}
noOptionsMessage={noOptionMessageHandler(state)} noOptionsMessage={noOptionMessageHandler(state)}

View File

@ -4,7 +4,7 @@ import { SelectableValue } from '@grafana/data';
import { Icon, Select, AsyncSelect, MultiSelect, AsyncMultiSelect } from '@grafana/ui'; import { Icon, Select, AsyncSelect, MultiSelect, AsyncMultiSelect } from '@grafana/ui';
import { getAvailableIcons, IconName } from '../../types'; import { getAvailableIcons, IconName } from '../../types';
import { select, boolean, number } from '@storybook/addon-knobs'; import { select, boolean, number } from '@storybook/addon-knobs';
import kebabCase from 'lodash/kebabCase'; import { kebabCase } from 'lodash';
import { generateOptions } from './mockOptions'; import { generateOptions } from './mockOptions';
import mdx from './Select.mdx'; import mdx from './Select.mdx';

View File

@ -1,7 +1,7 @@
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import { interval, Subscription, Subject, of, NEVER } from 'rxjs'; import { interval, Subscription, Subject, of, NEVER } from 'rxjs';
import { tap, switchMap } from 'rxjs/operators'; import { tap, switchMap } from 'rxjs/operators';
import _ from 'lodash'; import { isEqual } from 'lodash';
import { stringToMs, SelectableValue } from '@grafana/data'; import { stringToMs, SelectableValue } from '@grafana/data';
import { RefreshPicker } from '../RefreshPicker/RefreshPicker'; import { RefreshPicker } from '../RefreshPicker/RefreshPicker';
@ -63,7 +63,7 @@ export class SetInterval extends PureComponent<Props> {
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: Props) {
if ( if (
(RefreshPicker.isLive(prevProps.interval) && RefreshPicker.isLive(this.props.interval)) || (RefreshPicker.isLive(prevProps.interval) && RefreshPicker.isLive(this.props.interval)) ||
_.isEqual(prevProps, this.props) isEqual(prevProps, this.props)
) { ) {
return; return;
} }

View File

@ -1,5 +1,4 @@
import cloneDeep from 'lodash/cloneDeep'; import { cloneDeep, omit } from 'lodash';
import omit from 'lodash/omit';
import { import {
fieldReducers, fieldReducers,

View File

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import difference from 'lodash/difference'; import { difference } from 'lodash';
import { Select } from '../Select/Select'; import { Select } from '../Select/Select';

View File

@ -1,6 +1,6 @@
import React, { HTMLProps, useRef } from 'react'; import React, { HTMLProps, useRef } from 'react';
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import uniqueId from 'lodash/uniqueId'; import { uniqueId } from 'lodash';
import { GrafanaTheme, deprecationWarning } from '@grafana/data'; import { GrafanaTheme, deprecationWarning } from '@grafana/data';
import { stylesFactory, useTheme } from '../../themes'; import { stylesFactory, useTheme } from '../../themes';
import { focusCss, getMouseFocusStyles } from '../../themes/mixins'; import { focusCss, getMouseFocusStyles } from '../../themes/mixins';

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import debounce from 'lodash/debounce'; import { debounce } from 'lodash';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { GrafanaTheme, DataFrame, CSVConfig, readCSV } from '@grafana/data'; import { GrafanaTheme, DataFrame, CSVConfig, readCSV } from '@grafana/data';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';

View File

@ -7,7 +7,7 @@ import { TimeZoneDescription } from '../TimeZonePicker/TimeZoneDescription';
import { TimeZoneOffset } from '../TimeZonePicker/TimeZoneOffset'; import { TimeZoneOffset } from '../TimeZonePicker/TimeZoneOffset';
import { Button } from '../../Button'; import { Button } from '../../Button';
import { TimeZonePicker } from '../TimeZonePicker'; import { TimeZonePicker } from '../TimeZonePicker';
import isString from 'lodash/isString'; import { isString } from 'lodash';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
interface Props { interface Props {

View File

@ -2,7 +2,7 @@ import React, { PropsWithChildren } from 'react';
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { GrafanaTheme, TimeZone, dateTimeFormat } from '@grafana/data'; import { GrafanaTheme, TimeZone, dateTimeFormat } from '@grafana/data';
import { useTheme, stylesFactory } from '../../../themes'; import { useTheme, stylesFactory } from '../../../themes';
import isString from 'lodash/isString'; import { isString } from 'lodash';
interface Props { interface Props {
timestamp: number; timestamp: number;

View File

@ -7,7 +7,7 @@ import { Icon } from '../../Icon/Icon';
import { TimeZoneOffset } from './TimeZoneOffset'; import { TimeZoneOffset } from './TimeZoneOffset';
import { TimeZoneDescription } from './TimeZoneDescription'; import { TimeZoneDescription } from './TimeZoneDescription';
import { TimeZoneTitle } from './TimeZoneTitle'; import { TimeZoneTitle } from './TimeZoneTitle';
import isString from 'lodash/isString'; import { isString } from 'lodash';
interface Props { interface Props {
isFocused: boolean; isFocused: boolean;

View File

@ -1,6 +1,6 @@
import React, { createRef } from 'react'; import React, { createRef } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import _ from 'lodash'; import { isEqual } from 'lodash';
import { FixedSizeList } from 'react-window'; import { FixedSizeList } from 'react-window';
import { TypeaheadInfo } from './TypeaheadInfo'; import { TypeaheadInfo } from './TypeaheadInfo';
@ -83,7 +83,7 @@ export class Typeahead extends React.PureComponent<Props, State> {
this.listRef.current.scrollToItem(this.state.typeaheadIndex); this.listRef.current.scrollToItem(this.state.typeaheadIndex);
} }
if (_.isEqual(prevProps.groupedItems, this.props.groupedItems) === false) { if (isEqual(prevProps.groupedItems, this.props.groupedItems) === false) {
const allItems = flattenGroupItems(this.props.groupedItems); const allItems = flattenGroupItems(this.props.groupedItems);
const longestLabel = calculateLongestLabel(allItems); const longestLabel = calculateLongestLabel(allItems);
const { listWidth, listHeight, itemHeight } = calculateListSizes(this.context, allItems, longestLabel); const { listWidth, listHeight, itemHeight } = calculateListSizes(this.context, allItems, longestLabel);

View File

@ -2,7 +2,7 @@ import React from 'react';
import { InlineList } from '../List/InlineList'; import { InlineList } from '../List/InlineList';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { DisplayValue, formattedValueToString } from '@grafana/data'; import { DisplayValue, formattedValueToString } from '@grafana/data';
import capitalize from 'lodash/capitalize'; import { capitalize } from 'lodash';
import { useStyles } from '../../themes/ThemeContext'; import { useStyles } from '../../themes/ThemeContext';
/** /**

View File

@ -3,8 +3,7 @@ import { css, cx } from '@emotion/css';
import { VizLegendTableProps } from './types'; import { VizLegendTableProps } from './types';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
import { useStyles } from '../../themes/ThemeContext'; import { useStyles } from '../../themes/ThemeContext';
import union from 'lodash/union'; import { union, sortBy } from 'lodash';
import sortBy from 'lodash/sortBy';
import { LegendTableItem } from './VizLegendTableItem'; import { LegendTableItem } from './VizLegendTableItem';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';

View File

@ -4,6 +4,12 @@ import { SuggestionsPlugin } from './suggestions';
import { Plugin as SlatePlugin } from '@grafana/slate-react'; import { Plugin as SlatePlugin } from '@grafana/slate-react';
import { SearchFunctionType } from '../utils'; import { SearchFunctionType } from '../utils';
import { CompletionItemGroup, SuggestionsState } from '../types'; import { CompletionItemGroup, SuggestionsState } from '../types';
// eslint-disable-next-line lodash/import-scope
import _ from 'lodash';
jest.spyOn(_, 'debounce').mockImplementation((func: (...args: any) => any) => {
return Object.assign(func, { cancel: jest.fn(), flush: jest.fn() });
});
jest.mock('../utils/searchFunctions', () => ({ jest.mock('../utils/searchFunctions', () => ({
// @ts-ignore // @ts-ignore
@ -26,10 +32,6 @@ jest.mock('../components/Typeahead/Typeahead', () => {
}; };
}); });
jest.mock('lodash/debounce', () => {
return (func: () => any) => func;
});
describe('SuggestionsPlugin', () => { describe('SuggestionsPlugin', () => {
let plugin: SlatePlugin, nextMock: any, suggestions: CompletionItemGroup[], editorMock: any, eventMock: any; let plugin: SlatePlugin, nextMock: any, suggestions: CompletionItemGroup[], editorMock: any, eventMock: any;

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import debounce from 'lodash/debounce'; import { debounce, sortBy } from 'lodash';
import sortBy from 'lodash/sortBy';
import { Editor as CoreEditor } from 'slate'; import { Editor as CoreEditor } from 'slate';
import { Plugin as SlatePlugin } from '@grafana/slate-react'; import { Plugin as SlatePlugin } from '@grafana/slate-react';

View File

@ -1,8 +1,4 @@
import map from 'lodash/map'; import { map, sortBy, flattenDeep, chunk, zip } from 'lodash';
import sortBy from 'lodash/sortBy';
import flattenDeep from 'lodash/flattenDeep';
import chunk from 'lodash/chunk';
import zip from 'lodash/zip';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import lightTheme from '../themes/light'; import lightTheme from '../themes/light';
import darkTheme from '../themes/dark'; import darkTheme from '../themes/dark';

View File

@ -1,4 +1,4 @@
import throttle from 'lodash/throttle'; import { throttle } from 'lodash';
/** /**
* @internal * @internal

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _range from 'lodash/range'; import { range as _range } from 'lodash';
import renderIntoCanvas, { import renderIntoCanvas, {
BG_COLOR, BG_COLOR,

View File

@ -13,9 +13,7 @@
// limitations under the License. // limitations under the License.
import * as React from 'react'; import * as React from 'react';
import _get from 'lodash/get'; import { get as _get, maxBy as _maxBy, values as _values } from 'lodash';
import _maxBy from 'lodash/maxBy';
import _values from 'lodash/values';
import MdKeyboardArrowRight from 'react-icons/lib/md/keyboard-arrow-right'; import MdKeyboardArrowRight from 'react-icons/lib/md/keyboard-arrow-right';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import cx from 'classnames'; import cx from 'classnames';

View File

@ -14,7 +14,7 @@
import cx from 'classnames'; import cx from 'classnames';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import _groupBy from 'lodash/groupBy'; import { groupBy as _groupBy } from 'lodash';
import React from 'react'; import React from 'react';
import { compose, onlyUpdateForKeys, withProps, withState } from 'recompose'; import { compose, onlyUpdateForKeys, withProps, withState } from 'recompose';
import { autoColor, createStyle, Theme } from '../Theme'; import { autoColor, createStyle, Theme } from '../Theme';

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import * as React from 'react'; import * as React from 'react';
import _sortBy from 'lodash/sortBy'; import { sortBy as _sortBy } from 'lodash';
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down'; import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right'; import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right';
import { css } from '@emotion/css'; import { css } from '@emotion/css';

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import React from 'react'; import React from 'react';
import _get from 'lodash/get'; import { get as _get } from 'lodash';
import IoChevronRight from 'react-icons/lib/io/chevron-right'; import IoChevronRight from 'react-icons/lib/io/chevron-right';
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down'; import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
import { css } from '@emotion/css'; import { css } from '@emotion/css';

View File

@ -14,12 +14,15 @@
import * as React from 'react'; import * as React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import debounceMock from 'lodash/debounce'; // eslint-disable-next-line lodash/import-scope
import _ from 'lodash';
import UiFindInput from './UiFindInput'; import UiFindInput from './UiFindInput';
import { UIInput } from '../uiElementsContext'; import { UIInput } from '../uiElementsContext';
jest.mock('lodash/debounce'); const debounceMock = jest.spyOn(_, 'debounce').mockImplementation((func) => {
return Object.assign(func, { cancel: jest.fn(), flush: jest.fn() });
});
describe('UiFindInput', () => { describe('UiFindInput', () => {
const flushMock = jest.fn(); const flushMock = jest.fn();

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _uniq from 'lodash/uniq'; import { uniq as _uniq } from 'lodash';
import memoize from 'lru-memoize'; import memoize from 'lru-memoize';
import { getConfigValue } from '../utils/config/get-config'; import { getConfigValue } from '../utils/config/get-config';
import { getParent } from './span'; import { getParent } from './span';

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _isEqual from 'lodash/isEqual'; import { isEqual as _isEqual } from 'lodash';
// @ts-ignore // @ts-ignore
import { getTraceSpanIdsAsTree } from '../selectors/trace'; import { getTraceSpanIdsAsTree } from '../selectors/trace';

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _values from 'lodash/values'; import { values as _values } from 'lodash';
import { followsFromRef } from './trace.fixture'; import { followsFromRef } from './trace.fixture';
import { import {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _get from 'lodash/get'; import { get as _get } from 'lodash';
import EUpdateTypes from './EUpdateTypes'; import EUpdateTypes from './EUpdateTypes';
import { DraggableBounds, DraggingUpdate } from './types'; import { DraggableBounds, DraggingUpdate } from './types';

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _get from 'lodash/get'; import { get as _get } from 'lodash';
import defaultConfig from '../../constants/default-config'; import defaultConfig from '../../constants/default-config';

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import _round from 'lodash/round'; import { round as _round } from 'lodash';
import { toFloatPrecision } from './number'; import { toFloatPrecision } from './number';

View File

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import _find from 'lodash/find'; import { find as _find, get as _get } from 'lodash';
import _get from 'lodash/get';
import { TNil } from '../types'; import { TNil } from '../types';
import { TraceSpan } from '../types/trace'; import { TraceSpan } from '../types/trace';

View File

@ -8,6 +8,7 @@ import 'file-saver';
import 'jquery'; import 'jquery';
import '@grafana/ui/src/components/Icon/iconBundle'; import '@grafana/ui/src/components/Icon/iconBundle';
// eslint-disable-next-line lodash/import-scope
import _ from 'lodash'; import _ from 'lodash';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import React from 'react'; import React from 'react';

View File

@ -1,5 +1,5 @@
import React, { useMemo, useCallback, FC } from 'react'; import React, { useMemo, useCallback, FC } from 'react';
import _ from 'lodash'; import { flatten } from 'lodash';
import { LegacyForms } from '@grafana/ui'; import { LegacyForms } from '@grafana/ui';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
@ -60,7 +60,7 @@ const useSelectOptions = ({ variables = [], options }: Props): Array<SelectableV
const useSelectedOption = (options: Array<SelectableValue<string>>, value: string): SelectableValue<string> => { const useSelectedOption = (options: Array<SelectableValue<string>>, value: string): SelectableValue<string> => {
return useMemo(() => { return useMemo(() => {
const allOptions = options.every((o) => o.options) ? _.flatten(options.map((o) => o.options)) : options; const allOptions = options.every((o) => o.options) ? flatten(options.map((o) => o.options)) : options;
return allOptions.find((option) => option.value === value); return allOptions.find((option) => option.value === value);
}, [options, value]); }, [options, value]);
}; };

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import _, { debounce } from 'lodash'; import { debounce, isNil } from 'lodash';
import { AsyncSelect } from '@grafana/ui'; import { AsyncSelect } from '@grafana/ui';
import { getBackendSrv } from '@grafana/runtime'; import { getBackendSrv } from '@grafana/runtime';
@ -36,7 +36,7 @@ export class TeamPicker extends Component<Props, State> {
search(query?: string) { search(query?: string) {
this.setState({ isLoading: true }); this.setState({ isLoading: true });
if (_.isNil(query)) { if (isNil(query)) {
query = ''; query = '';
} }

View File

@ -1,6 +1,6 @@
// Libraries // Libraries
import React, { Component } from 'react'; import React, { Component } from 'react';
import _, { debounce } from 'lodash'; import { debounce, isNil } from 'lodash';
// Components // Components
import { AsyncSelect } from '@grafana/ui'; import { AsyncSelect } from '@grafana/ui';
@ -37,7 +37,7 @@ export class UserPicker extends Component<Props, State> {
search(query?: string) { search(query?: string) {
this.setState({ isLoading: true }); this.setState({ isLoading: true });
if (_.isNil(query)) { if (isNil(query)) {
query = ''; query = '';
} }

View File

@ -24,7 +24,7 @@ import {
ReduceOptions, ReduceOptions,
} from '@grafana/data/src/transformations/transformers/calculateField'; } from '@grafana/data/src/transformations/transformers/calculateField';
import defaults from 'lodash/defaults'; import { defaults } from 'lodash';
interface CalculateFieldTransformerEditorProps extends TransformerUIProps<CalculateFieldTransformerOptions> {} interface CalculateFieldTransformerEditorProps extends TransformerUIProps<CalculateFieldTransformerOptions> {}

View File

@ -13,7 +13,7 @@ import {
valueMatchers, valueMatchers,
} from '@grafana/data'; } from '@grafana/data';
import { Button, RadioButtonGroup, stylesFactory } from '@grafana/ui'; import { Button, RadioButtonGroup, stylesFactory } from '@grafana/ui';
import cloneDeep from 'lodash/cloneDeep'; import { cloneDeep } from 'lodash';
import { import {
FilterByValueFilter, FilterByValueFilter,
FilterByValueMatch, FilterByValueMatch,

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { debounce, find, indexOf, map, isObject, escape, unescape } from 'lodash';
import coreModule from '../../core_module'; import coreModule from '../../core_module';
import { ISCEService } from 'angular'; import { ISCEService } from 'angular';
import { promiseToDigest } from 'app/core/utils/promiseToDigest'; import { promiseToDigest } from 'app/core/utils/promiseToDigest';
@ -81,7 +81,7 @@ export class FormDropdownCtrl {
}; };
if (this.debounce) { if (this.debounce) {
typeahead.lookup = _.debounce(typeahead.lookup, 500, { leading: true }); typeahead.lookup = debounce(typeahead.lookup, 500, { leading: true });
} }
this.linkElement.keydown((evt) => { this.linkElement.keydown((evt) => {
@ -115,13 +115,13 @@ export class FormDropdownCtrl {
} }
modelChanged() { modelChanged() {
if (_.isObject(this.model)) { if (isObject(this.model)) {
this.updateDisplay((this.model as any).text); this.updateDisplay((this.model as any).text);
} else { } else {
// if we have text use it // if we have text use it
if (this.lookupText) { if (this.lookupText) {
this.getOptionsInternal('').then((options: any) => { this.getOptionsInternal('').then((options: any) => {
const item: any = _.find(options, { value: this.model }); const item: any = find(options, { value: this.model });
this.updateDisplay(item ? item.text : this.model); this.updateDisplay(item ? item.text : this.model);
}); });
} else { } else {
@ -135,13 +135,13 @@ export class FormDropdownCtrl {
this.optionCache = options; this.optionCache = options;
// extract texts // extract texts
const optionTexts = _.map(options, (op: any) => { const optionTexts = map(options, (op: any) => {
return _.escape(op.text); return escape(op.text);
}); });
// add custom values // add custom values
if (this.allowCustom && this.text !== '') { if (this.allowCustom && this.text !== '') {
if (_.indexOf(optionTexts, this.text) === -1) { if (indexOf(optionTexts, this.text) === -1) {
optionTexts.unshift(this.text); optionTexts.unshift(this.text);
} }
} }
@ -182,24 +182,24 @@ export class FormDropdownCtrl {
} }
updateValue(text: string) { updateValue(text: string) {
text = _.unescape(text); text = unescape(text);
if (text === '' || this.text === text) { if (text === '' || this.text === text) {
return; return;
} }
this.$scope.$apply(() => { this.$scope.$apply(() => {
const option: any = _.find(this.optionCache, { text: text }); const option: any = find(this.optionCache, { text: text });
if (option) { if (option) {
if (_.isObject(this.model)) { if (isObject(this.model)) {
this.model = option; this.model = option;
} else { } else {
this.model = option.value; this.model = option.value;
} }
this.text = option.text; this.text = option.text;
} else if (this.allowCustom) { } else if (this.allowCustom) {
if (_.isObject(this.model)) { if (isObject(this.model)) {
(this.model as any).text = (this.model as any).value = text; (this.model as any).text = (this.model as any).value = text;
} else { } else {
this.model = text; this.model = text;

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { each } from 'lodash';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
// @ts-ignore // @ts-ignore
import Drop from 'tether-drop'; import Drop from 'tether-drop';
@ -28,7 +28,7 @@ export function infoPopover() {
const content = document.createElement('div'); const content = document.createElement('div');
content.className = 'markdown-html'; content.className = 'markdown-html';
_.each(clone, (node) => { each(clone, (node) => {
content.appendChild(node); content.appendChild(node);
}); });

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { clone, each, map } from 'lodash';
export class QueryPartDef { export class QueryPartDef {
type: string; type: string;
@ -31,7 +31,7 @@ export class QueryPart {
throw { message: 'Could not find query part ' + part.type }; throw { message: 'Could not find query part ' + part.type };
} }
part.params = part.params || _.clone(this.def.defaultParams); part.params = part.params || clone(this.def.defaultParams);
this.params = part.params; this.params = part.params;
this.text = ''; this.text = '';
this.updateText(); this.updateText();
@ -53,7 +53,7 @@ export class QueryPart {
// handle optional parameters // handle optional parameters
// if string contains ',' and next param is optional, split and update both // if string contains ',' and next param is optional, split and update both
if (this.hasMultipleParamsInString(strValue, index)) { if (this.hasMultipleParamsInString(strValue, index)) {
_.each(strValue.split(','), (partVal, idx) => { each(strValue.split(','), (partVal, idx) => {
this.updateParam(partVal.trim(), idx); this.updateParam(partVal.trim(), idx);
}); });
return; return;
@ -84,7 +84,7 @@ export class QueryPart {
export function functionRenderer(part: any, innerExpr: string) { export function functionRenderer(part: any, innerExpr: string) {
const str = part.def.type + '('; const str = part.def.type + '(';
const parameters = _.map(part.params, (value, index) => { const parameters = map(part.params, (value, index) => {
const paramType = part.def.params[index]; const paramType = part.def.params[index];
if (paramType.type === 'time') { if (paramType.type === 'time') {
if (value === 'auto') { if (value === 'auto') {

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { debounce, each, map, partial, escape, unescape } from 'lodash';
import $ from 'jquery'; import $ from 'jquery';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import { promiseToDigest } from '../../utils/promiseToDigest'; import { promiseToDigest } from '../../utils/promiseToDigest';
@ -90,7 +90,7 @@ export function queryPartEditorDirective(templateSrv: any) {
if (param.options) { if (param.options) {
let options = param.options; let options = param.options;
if (param.type === 'int') { if (param.type === 'int') {
options = _.map(options, (val) => { options = map(options, (val) => {
return val.toString(); return val.toString();
}); });
} }
@ -99,8 +99,8 @@ export function queryPartEditorDirective(templateSrv: any) {
$scope.$apply(() => { $scope.$apply(() => {
$scope.handleEvent({ $event: { name: 'get-param-options' } }).then((result: any) => { $scope.handleEvent({ $event: { name: 'get-param-options' } }).then((result: any) => {
const dynamicOptions = _.map(result, (op) => { const dynamicOptions = map(result, (op) => {
return _.escape(op.value); return escape(op.value);
}); });
callback(dynamicOptions); callback(dynamicOptions);
}); });
@ -114,7 +114,7 @@ export function queryPartEditorDirective(templateSrv: any) {
minLength: 0, minLength: 0,
items: 1000, items: 1000,
updater: (value: string) => { updater: (value: string) => {
value = _.unescape(value); value = unescape(value);
setTimeout(() => { setTimeout(() => {
inputBlur.call($input[0], paramIndex); inputBlur.call($input[0], paramIndex);
}, 0); }, 0);
@ -130,7 +130,7 @@ export function queryPartEditorDirective(templateSrv: any) {
}; };
if (debounceLookup) { if (debounceLookup) {
typeahead.lookup = _.debounce(typeahead.lookup, 500, { leading: true }); typeahead.lookup = debounce(typeahead.lookup, 500, { leading: true });
} }
} }
@ -147,7 +147,7 @@ export function queryPartEditorDirective(templateSrv: any) {
}; };
function addElementsAndCompile() { function addElementsAndCompile() {
_.each(partDef.params, (param: any, index: number) => { each(partDef.params, (param: any, index: number) => {
if (param.optional && part.params.length <= index) { if (param.optional && part.params.length <= index) {
return; return;
} }
@ -163,10 +163,10 @@ export function queryPartEditorDirective(templateSrv: any) {
$paramLink.appendTo($paramsContainer); $paramLink.appendTo($paramsContainer);
$input.appendTo($paramsContainer); $input.appendTo($paramsContainer);
$input.blur(_.partial(inputBlur, index)); $input.blur(partial(inputBlur, index));
$input.keyup(inputKeyDown); $input.keyup(inputKeyDown);
$input.keypress(_.partial(inputKeyPress, index)); $input.keypress(partial(inputKeyPress, index));
$paramLink.click(_.partial(clickFuncParam, index)); $paramLink.click(partial(clickFuncParam, index));
addTypeahead($input, param, index); addTypeahead($input, param, index);
}); });

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import { cloneDeep, find } from 'lodash';
import { SignIn } from './SignIn'; import { SignIn } from './SignIn';
import BottomNavLinks from './BottomNavLinks'; import BottomNavLinks from './BottomNavLinks';
import { contextSrv } from 'app/core/services/context_srv'; import { contextSrv } from 'app/core/services/context_srv';
@ -7,13 +7,13 @@ import config from '../../config';
import { NavModelItem } from '@grafana/data'; import { NavModelItem } from '@grafana/data';
export default function BottomSection() { export default function BottomSection() {
const navTree: NavModelItem[] = _.cloneDeep(config.bootData.navTree); const navTree: NavModelItem[] = cloneDeep(config.bootData.navTree);
const bottomNav: NavModelItem[] = navTree.filter((item) => item.hideFromMenu); const bottomNav: NavModelItem[] = navTree.filter((item) => item.hideFromMenu);
const isSignedIn = contextSrv.isSignedIn; const isSignedIn = contextSrv.isSignedIn;
const user = contextSrv.user; const user = contextSrv.user;
if (user && user.orgCount > 1) { if (user && user.orgCount > 1) {
const profileNode: any = _.find(bottomNav, { id: 'profile' }); const profileNode: any = find(bottomNav, { id: 'profile' });
if (profileNode) { if (profileNode) {
profileNode.showOrgSwitcher = true; profileNode.showOrgSwitcher = true;
} }

View File

@ -1,5 +1,5 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import _ from 'lodash'; import { filter } from 'lodash';
import DropDownChild from './DropDownChild'; import DropDownChild from './DropDownChild';
import { NavModelItem } from '@grafana/data'; import { NavModelItem } from '@grafana/data';
import { Link } from '@grafana/ui'; import { Link } from '@grafana/ui';
@ -13,7 +13,7 @@ const SideMenuDropDown: FC<Props> = (props) => {
const { link, onHeaderClick } = props; const { link, onHeaderClick } = props;
let childrenLinks: NavModelItem[] = []; let childrenLinks: NavModelItem[] = [];
if (link.children) { if (link.children) {
childrenLinks = _.filter(link.children, (item) => !item.hideFromMenu); childrenLinks = filter(link.children, (item) => !item.hideFromMenu);
} }
const linkContent = <span className="sidemenu-item-text">{link.text}</span>; const linkContent = <span className="sidemenu-item-text">{link.text}</span>;

View File

@ -1,12 +1,12 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import _ from 'lodash'; import { cloneDeep, filter } from 'lodash';
import TopSectionItem from './TopSectionItem'; import TopSectionItem from './TopSectionItem';
import config from '../../config'; import config from '../../config';
import { locationService } from '@grafana/runtime'; import { locationService } from '@grafana/runtime';
const TopSection: FC<any> = () => { const TopSection: FC<any> = () => {
const navTree = _.cloneDeep(config.bootData.navTree); const navTree = cloneDeep(config.bootData.navTree);
const mainLinks = _.filter(navTree, (item) => !item.hideFromMenu); const mainLinks = filter(navTree, (item) => !item.hideFromMenu);
const searchLink = { const searchLink = {
text: 'Search', text: 'Search',
icon: 'search', icon: 'search',

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { clone } from 'lodash';
export class SqlPartDef { export class SqlPartDef {
type: string; type: string;
@ -57,7 +57,7 @@ export class SqlPart {
this.label = def.label; this.label = def.label;
} }
part.params = part.params || _.clone(this.def.defaultParams); part.params = part.params || clone(this.def.defaultParams);
this.params = part.params; this.params = part.params;
} }

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { debounce, each, indexOf, map, partial, escape, unescape } from 'lodash';
import $ from 'jquery'; import $ from 'jquery';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
@ -95,7 +95,7 @@ export function sqlPartEditorDirective(templateSrv: any) {
if (param.options) { if (param.options) {
let options = param.options; let options = param.options;
if (param.type === 'int') { if (param.type === 'int') {
options = _.map(options, (val) => { options = map(options, (val) => {
return val.toString(); return val.toString();
}); });
} }
@ -104,13 +104,13 @@ export function sqlPartEditorDirective(templateSrv: any) {
$scope.$apply(() => { $scope.$apply(() => {
$scope.handleEvent({ $event: { name: 'get-param-options', param: param } }).then((result: any) => { $scope.handleEvent({ $event: { name: 'get-param-options', param: param } }).then((result: any) => {
const dynamicOptions = _.map(result, (op) => { const dynamicOptions = map(result, (op) => {
return _.escape(op.value); return escape(op.value);
}); });
// add current value to dropdown if it's not in dynamicOptions // add current value to dropdown if it's not in dynamicOptions
if (_.indexOf(dynamicOptions, part.params[paramIndex]) === -1) { if (indexOf(dynamicOptions, part.params[paramIndex]) === -1) {
dynamicOptions.unshift(_.escape(part.params[paramIndex])); dynamicOptions.unshift(escape(part.params[paramIndex]));
} }
callback(dynamicOptions); callback(dynamicOptions);
@ -125,7 +125,7 @@ export function sqlPartEditorDirective(templateSrv: any) {
minLength: 0, minLength: 0,
items: 1000, items: 1000,
updater: (value: string) => { updater: (value: string) => {
value = _.unescape(value); value = unescape(value);
if (value === part.params[paramIndex]) { if (value === part.params[paramIndex]) {
clearTimeout(cancelBlur); clearTimeout(cancelBlur);
$input.focus(); $input.focus();
@ -143,7 +143,7 @@ export function sqlPartEditorDirective(templateSrv: any) {
}; };
if (debounceLookup) { if (debounceLookup) {
typeahead.lookup = _.debounce(typeahead.lookup, 500, { leading: true }); typeahead.lookup = debounce(typeahead.lookup, 500, { leading: true });
} }
} }
@ -158,7 +158,7 @@ export function sqlPartEditorDirective(templateSrv: any) {
}; };
function addElementsAndCompile() { function addElementsAndCompile() {
_.each(partDef.params, (param: any, index: number) => { each(partDef.params, (param: any, index: number) => {
if (param.optional && part.params.length <= index) { if (param.optional && part.params.length <= index) {
return; return;
} }
@ -174,10 +174,10 @@ export function sqlPartEditorDirective(templateSrv: any) {
$paramLink.appendTo($paramsContainer); $paramLink.appendTo($paramsContainer);
$input.appendTo($paramsContainer); $input.appendTo($paramsContainer);
$input.blur(_.partial(inputBlur, $input, index)); $input.blur(partial(inputBlur, $input, index));
$input.keyup(inputKeyDown); $input.keyup(inputKeyDown);
$input.keypress(_.partial(inputKeyPress, index)); $input.keypress(partial(inputKeyPress, index));
$paramLink.click(_.partial(clickFuncParam, index)); $paramLink.click(partial(clickFuncParam, index));
addTypeahead($input, param, index); addTypeahead($input, param, index);
}); });

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { isArray } from 'lodash';
import coreModule from '../core_module'; import coreModule from '../core_module';
export function arrayJoin() { export function arrayJoin() {
@ -13,7 +13,7 @@ export function arrayJoin() {
} }
function join_array(text: string) { function join_array(text: string) {
if (_.isArray(text)) { if (isArray(text)) {
return ((text || '') as any).join(','); return ((text || '') as any).join(',');
} else { } else {
return text; return text;

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { each, reduce } from 'lodash';
import $ from 'jquery'; import $ from 'jquery';
import coreModule from '../core_module'; import coreModule from '../core_module';
@ -32,8 +32,8 @@ export function dropdownTypeahead($compile: any) {
if (attrs.ngModel) { if (attrs.ngModel) {
$scope.$watch('model', (newValue: any) => { $scope.$watch('model', (newValue: any) => {
_.each($scope.menuItems, (item) => { each($scope.menuItems, (item) => {
_.each(item.submenu, (subItem) => { each(item.submenu, (subItem) => {
if (subItem.value === newValue) { if (subItem.value === newValue) {
$button.html(subItem.text); $button.html(subItem.text);
} }
@ -42,14 +42,14 @@ export function dropdownTypeahead($compile: any) {
}); });
} }
const typeaheadValues = _.reduce( const typeaheadValues = reduce(
$scope.menuItems, $scope.menuItems,
(memo: any[], value, index) => { (memo: any[], value, index) => {
if (!value.submenu) { if (!value.submenu) {
value.click = 'menuItemSelected(' + index + ')'; value.click = 'menuItemSelected(' + index + ')';
memo.push(value.text); memo.push(value.text);
} else { } else {
_.each(value.submenu, (item, subIndex) => { each(value.submenu, (item, subIndex) => {
item.click = 'menuItemSelected(' + index + ',' + subIndex + ')'; item.click = 'menuItemSelected(' + index + ',' + subIndex + ')';
memo.push(value.text + ' ' + item.text); memo.push(value.text + ' ' + item.text);
}); });
@ -84,8 +84,8 @@ export function dropdownTypeahead($compile: any) {
items: 10, items: 10,
updater: (value: string) => { updater: (value: string) => {
const result: any = {}; const result: any = {};
_.each($scope.menuItems, (menuItem) => { each($scope.menuItems, (menuItem) => {
_.each(menuItem.submenu, (submenuItem) => { each(menuItem.submenu, (submenuItem) => {
if (value === menuItem.text + ' ' + submenuItem.text) { if (value === menuItem.text + ' ' + submenuItem.text) {
result.$subItem = submenuItem; result.$subItem = submenuItem;
result.$item = menuItem; result.$item = menuItem;
@ -172,8 +172,8 @@ export function dropdownTypeahead2($compile: any) {
if (attrs.ngModel) { if (attrs.ngModel) {
$scope.$watch('model', (newValue: any) => { $scope.$watch('model', (newValue: any) => {
_.each($scope.menuItems, (item) => { each($scope.menuItems, (item) => {
_.each(item.submenu, (subItem) => { each(item.submenu, (subItem) => {
if (subItem.value === newValue) { if (subItem.value === newValue) {
$button.html(subItem.text); $button.html(subItem.text);
} }
@ -182,14 +182,14 @@ export function dropdownTypeahead2($compile: any) {
}); });
} }
const typeaheadValues = _.reduce( const typeaheadValues = reduce(
$scope.menuItems, $scope.menuItems,
(memo: any[], value, index) => { (memo: any[], value, index) => {
if (!value.submenu) { if (!value.submenu) {
value.click = 'menuItemSelected(' + index + ')'; value.click = 'menuItemSelected(' + index + ')';
memo.push(value.text); memo.push(value.text);
} else { } else {
_.each(value.submenu, (item, subIndex) => { each(value.submenu, (item, subIndex) => {
item.click = 'menuItemSelected(' + index + ',' + subIndex + ')'; item.click = 'menuItemSelected(' + index + ',' + subIndex + ')';
memo.push(value.text + ' ' + item.text); memo.push(value.text + ' ' + item.text);
}); });
@ -224,8 +224,8 @@ export function dropdownTypeahead2($compile: any) {
items: 10, items: 10,
updater: (value: string) => { updater: (value: string) => {
const result: any = {}; const result: any = {};
_.each($scope.menuItems, (menuItem) => { each($scope.menuItems, (menuItem) => {
_.each(menuItem.submenu, (submenuItem) => { each(menuItem.submenu, (submenuItem) => {
if (value === menuItem.text + ' ' + submenuItem.text) { if (value === menuItem.text + ' ' + submenuItem.text) {
result.$subItem = submenuItem; result.$subItem = submenuItem;
result.$item = menuItem; result.$item = menuItem;

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { debounce, find, indexOf, map, escape, unescape } from 'lodash';
import $ from 'jquery'; import $ from 'jquery';
import coreModule from '../core_module'; import coreModule from '../core_module';
import { TemplateSrv } from 'app/features/templating/template_srv'; import { TemplateSrv } from 'app/features/templating/template_srv';
@ -43,7 +43,7 @@ export function metricSegment($compile: any, $sce: any, templateSrv: TemplateSrv
} }
$scope.$apply(() => { $scope.$apply(() => {
const selected: any = _.find($scope.altSegments, { value: value }); const selected: any = find($scope.altSegments, { value: value });
if (selected) { if (selected) {
segment.value = selected.value; segment.value = selected.value;
segment.html = selected.html || $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(selected.value)); segment.html = selected.html || $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(selected.value));
@ -87,14 +87,14 @@ export function metricSegment($compile: any, $sce: any, templateSrv: TemplateSrv
$scope.$apply(() => { $scope.$apply(() => {
$scope.getOptions({ $query: query }).then((altSegments: any) => { $scope.getOptions({ $query: query }).then((altSegments: any) => {
$scope.altSegments = altSegments; $scope.altSegments = altSegments;
options = _.map($scope.altSegments, (alt) => { options = map($scope.altSegments, (alt) => {
return _.escape(alt.value); return escape(alt.value);
}); });
// add custom values // add custom values
if (segment.custom !== 'false') { if (segment.custom !== 'false') {
if (!segment.fake && _.indexOf(options, segment.value) === -1) { if (!segment.fake && indexOf(options, segment.value) === -1) {
options.unshift(_.escape(segment.value)); options.unshift(escape(segment.value));
} }
} }
@ -104,7 +104,7 @@ export function metricSegment($compile: any, $sce: any, templateSrv: TemplateSrv
}; };
$scope.updater = (value: string) => { $scope.updater = (value: string) => {
value = _.unescape(value); value = unescape(value);
if (value === segment.value) { if (value === segment.value) {
clearTimeout(cancelBlur); clearTimeout(cancelBlur);
$input.focus(); $input.focus();
@ -152,7 +152,7 @@ export function metricSegment($compile: any, $sce: any, templateSrv: TemplateSrv
}; };
if (debounceLookup) { if (debounceLookup) {
typeahead.lookup = _.debounce(typeahead.lookup, 500, { leading: true }); typeahead.lookup = debounce(typeahead.lookup, 500, { leading: true });
} }
$button.keydown((evt) => { $button.keydown((evt) => {
@ -203,7 +203,7 @@ export function metricSegmentModel(uiSegmentSrv: any) {
let cachedOptions: any; let cachedOptions: any;
$scope.valueToSegment = (value: any) => { $scope.valueToSegment = (value: any) => {
const option: any = _.find($scope.options, { value: value }); const option: any = find($scope.options, { value: value });
const segment = { const segment = {
cssClass: attrs.cssClass, cssClass: attrs.cssClass,
custom: attrs.custom, custom: attrs.custom,
@ -218,14 +218,14 @@ export function metricSegmentModel(uiSegmentSrv: any) {
if ($scope.options) { if ($scope.options) {
cachedOptions = $scope.options; cachedOptions = $scope.options;
return Promise.resolve( return Promise.resolve(
_.map($scope.options, (option) => { map($scope.options, (option) => {
return { value: option.text }; return { value: option.text };
}) })
); );
} else { } else {
return $scope.getOptions().then((options: any) => { return $scope.getOptions().then((options: any) => {
cachedOptions = options; cachedOptions = options;
return _.map(options, (option) => { return map(options, (option) => {
if (option.html) { if (option.html) {
return option; return option;
} }
@ -237,7 +237,7 @@ export function metricSegmentModel(uiSegmentSrv: any) {
$scope.onSegmentChange = () => { $scope.onSegmentChange = () => {
if (cachedOptions) { if (cachedOptions) {
const option: any = _.find(cachedOptions, { text: $scope.segment.value }); const option: any = find(cachedOptions, { text: $scope.segment.value });
if (option && option.value !== $scope.property) { if (option && option.value !== $scope.property) {
$scope.property = option.value; $scope.property = option.value;
} else if (attrs.custom !== 'false') { } else if (attrs.custom !== 'false') {

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { isArray, isNull, isObject, isUndefined } from 'lodash';
import angular from 'angular'; import angular from 'angular';
import coreModule from '../core_module'; import coreModule from '../core_module';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv'; import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
@ -12,7 +12,7 @@ coreModule.filter('stringSort', () => {
coreModule.filter('slice', () => { coreModule.filter('slice', () => {
return (arr: any[], start: any, end: any) => { return (arr: any[], start: any, end: any) => {
if (!_.isUndefined(arr)) { if (!isUndefined(arr)) {
return arr.slice(start, end); return arr.slice(start, end);
} }
return arr; return arr;
@ -21,10 +21,10 @@ coreModule.filter('slice', () => {
coreModule.filter('stringify', () => { coreModule.filter('stringify', () => {
return (arr: any[]) => { return (arr: any[]) => {
if (_.isObject(arr) && !_.isArray(arr)) { if (isObject(arr) && !isArray(arr)) {
return angular.toJson(arr); return angular.toJson(arr);
} else { } else {
return _.isNull(arr) ? null : arr.toString(); return isNull(arr) ? null : arr.toString();
} }
}; };
}); });

View File

@ -1,6 +1,6 @@
import $ from 'jquery'; import $ from 'jquery';
import angular from 'angular'; import angular from 'angular';
import _ from 'lodash'; import { extend } from 'lodash';
const $win = $(window); const $win = $(window);
@ -30,7 +30,7 @@ $.fn.place_tt = (() => {
'$rootScope', '$rootScope',
($compile, $rootScope) => { ($compile, $rootScope) => {
const tmpScope = $rootScope.$new(true); const tmpScope = $rootScope.$new(true);
_.extend(tmpScope, opts.scopeData); extend(tmpScope, opts.scopeData);
$compile($tooltip)(tmpScope); $compile($tooltip)(tmpScope);
tmpScope.$digest(); tmpScope.$digest();

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line lodash/import-scope
import _ from 'lodash'; import _ from 'lodash';
/* /*

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { size } from 'lodash';
import { colors, ansicolor } from '@grafana/ui'; import { colors, ansicolor } from '@grafana/ui';
import { import {
@ -399,7 +399,7 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi
// Meta data to display in status // Meta data to display in status
const meta: LogsMetaItem[] = []; const meta: LogsMetaItem[] = [];
if (_.size(commonLabels) > 0) { if (size(commonLabels) > 0) {
meta.push({ meta.push({
label: 'Common labels', label: 'Common labels',
value: commonLabels, value: commonLabels,

View File

@ -1,6 +1,6 @@
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import config from 'app/core/config'; import config from 'app/core/config';
import _ from 'lodash'; import { find, isNumber } from 'lodash';
import { NavModel } from '@grafana/data'; import { NavModel } from '@grafana/data';
export class NavModelSrv { export class NavModelSrv {
@ -12,7 +12,7 @@ export class NavModelSrv {
} }
getCfgNode() { getCfgNode() {
return _.find(this.navItems, { id: 'cfg' }); return find(this.navItems, { id: 'cfg' });
} }
getNav(...args: Array<string | number>) { getNav(...args: Array<string | number>) {
@ -23,12 +23,12 @@ export class NavModelSrv {
for (const id of args) { for (const id of args) {
// if its a number then it's the index to use for main // if its a number then it's the index to use for main
if (_.isNumber(id)) { if (isNumber(id)) {
nav.main = nav.breadcrumbs[id]; nav.main = nav.breadcrumbs[id];
break; break;
} }
const node: any = _.find(children, { id: id }); const node: any = find(children, { id: id });
nav.breadcrumbs.push(node); nav.breadcrumbs.push(node);
nav.node = node; nav.node = node;
nav.main = node; nav.main = node;

View File

@ -1,6 +1,6 @@
import angular from 'angular'; import angular from 'angular';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import _ from 'lodash'; import { assign } from 'lodash';
import { import {
AngularComponent, AngularComponent,
@ -16,7 +16,7 @@ export class AngularLoader implements AngularLoaderInterface {
load(elem: any, scopeProps: any, template: string): AngularComponent { load(elem: any, scopeProps: any, template: string): AngularComponent {
const scope = this.$rootScope.$new(); const scope = this.$rootScope.$new();
_.assign(scope, scopeProps); assign(scope, scopeProps);
const compiledElem = this.$compile(template)(scope); const compiledElem = this.$compile(template)(scope);
const rootNode = angular.element(elem); const rootNode = angular.element(elem);

View File

@ -1,5 +1,5 @@
import config from '../../core/config'; import config from '../../core/config';
import _ from 'lodash'; import { extend } from 'lodash';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import { rangeUtil } from '@grafana/data'; import { rangeUtil } from '@grafana/data';
import { AccessControlAction, AccessControlScope, UserPermission } from 'app/types'; import { AccessControlAction, AccessControlScope, UserPermission } from 'app/types';
@ -35,7 +35,7 @@ export class User {
this.hasEditPermissionInFolders = false; this.hasEditPermissionInFolders = false;
this.email = undefined; this.email = undefined;
if (config.bootData.user) { if (config.bootData.user) {
_.extend(this, config.bootData.user); extend(this, config.bootData.user);
} }
} }
} }

View File

@ -1,5 +1,5 @@
import store from 'app/core/store'; import store from 'app/core/store';
import _ from 'lodash'; import { filter, isArray, isNumber } from 'lodash';
import config from 'app/core/config'; import config from 'app/core/config';
export class ImpressionSrv { export class ImpressionSrv {
@ -10,7 +10,7 @@ export class ImpressionSrv {
let impressions = []; let impressions = [];
if (store.exists(impressionsKey)) { if (store.exists(impressionsKey)) {
impressions = JSON.parse(store.get(impressionsKey)); impressions = JSON.parse(store.get(impressionsKey));
if (!_.isArray(impressions)) { if (!isArray(impressions)) {
impressions = []; impressions = [];
} }
} }
@ -32,8 +32,8 @@ export class ImpressionSrv {
impressions = JSON.parse(impressions); impressions = JSON.parse(impressions);
impressions = _.filter(impressions, (el) => { impressions = filter(impressions, (el) => {
return _.isNumber(el); return isNumber(el);
}); });
return impressions; return impressions;

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { extend } from 'lodash';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
// @ts-ignore // @ts-ignore
import Drop from 'tether-drop'; import Drop from 'tether-drop';
@ -20,7 +20,7 @@ function popoverSrv(this: any, $compile: any, $rootScope: GrafanaRootScope, $tim
openDrop = null; openDrop = null;
} }
const scope = _.extend($rootScope.$new(true), options.model); const scope = extend($rootScope.$new(true), options.model);
let drop: any; let drop: any;
const cleanUp = () => { const cleanUp = () => {

View File

@ -1,4 +1,4 @@
import _ from 'lodash'; import { clone, keys, sortBy, take, values } from 'lodash';
import impressionSrv from 'app/core/services/impression_srv'; import impressionSrv from 'app/core/services/impression_srv';
import store from 'app/core/store'; import store from 'app/core/store';
@ -29,7 +29,7 @@ export class SearchSrv {
} }
private queryForRecentDashboards(): Promise<DashboardSearchHit[]> { private queryForRecentDashboards(): Promise<DashboardSearchHit[]> {
const dashIds: number[] = _.take(impressionSrv.getDashboardOpened(), 30); const dashIds: number[] = take(impressionSrv.getDashboardOpened(), 30);
if (dashIds.length === 0) { if (dashIds.length === 0) {
return Promise.resolve([]); return Promise.resolve([]);
} }
@ -63,7 +63,7 @@ export class SearchSrv {
search(options: any) { search(options: any) {
const sections: any = {}; const sections: any = {};
const promises = []; const promises = [];
const query = _.clone(options); const query = clone(options);
const filters = hasFilters(options) || query.folderIds?.length > 0; const filters = hasFilters(options) || query.folderIds?.length > 0;
query.folderIds = query.folderIds || []; query.folderIds = query.folderIds || [];
@ -93,7 +93,7 @@ export class SearchSrv {
); );
return Promise.all(promises).then(() => { return Promise.all(promises).then(() => {
return _.sortBy(_.values(sections), 'score'); return sortBy(values(sections), 'score');
}); });
} }
@ -113,7 +113,7 @@ export class SearchSrv {
items: [], items: [],
url: hit.url, url: hit.url,
icon: 'folder', icon: 'folder',
score: _.keys(sections).length, score: keys(sections).length,
type: hit.type, type: hit.type,
}; };
} }
@ -134,7 +134,7 @@ export class SearchSrv {
url: hit.folderUrl, url: hit.folderUrl,
items: [], items: [],
icon: 'folder-open', icon: 'folder-open',
score: _.keys(sections).length, score: keys(sections).length,
type: DashboardSearchItemType.DashFolder, type: DashboardSearchItemType.DashFolder,
}; };
} else { } else {
@ -143,7 +143,7 @@ export class SearchSrv {
title: 'General', title: 'General',
items: [], items: [],
icon: 'folder-open', icon: 'folder-open',
score: _.keys(sections).length, score: keys(sections).length,
type: DashboardSearchItemType.DashFolder, type: DashboardSearchItemType.DashFolder,
}; };
} }

Some files were not shown because too many files have changed in this diff Show More