chore: replace Lodash usage with native JS implementation (#31907)
Signed-off-by: hainenber <dotronghai96@gmail.com>
This commit is contained in:
parent
eec374426f
commit
f8fe780f52
|
|
@ -18,7 +18,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { JsonObject } from '@superset-ui/core';
|
||||
import { isString } from 'lodash';
|
||||
|
||||
export const getTimeOffset = (
|
||||
series: JsonObject,
|
||||
|
|
@ -36,7 +35,9 @@ export const hasTimeOffset = (
|
|||
series: JsonObject,
|
||||
timeCompare: string[],
|
||||
): boolean =>
|
||||
isString(series.name) ? !!getTimeOffset(series, timeCompare) : false;
|
||||
typeof series.name === 'string'
|
||||
? !!getTimeOffset(series, timeCompare)
|
||||
: false;
|
||||
|
||||
export const getOriginalSeries = (
|
||||
seriesName: string,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
import { useEffect, useMemo, useState } from 'react';
|
||||
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { mergeWith, isArray } from 'lodash';
|
||||
import { mergeWith } from 'lodash';
|
||||
import { FeatureFlag, isFeatureEnabled } from '../utils';
|
||||
|
||||
interface SafeMarkdownProps {
|
||||
|
|
@ -33,7 +33,7 @@ export function getOverrideHtmlSchema(
|
|||
htmlSchemaOverrides: SafeMarkdownProps['htmlSchemaOverrides'],
|
||||
) {
|
||||
return mergeWith(originalSchema, htmlSchemaOverrides, (objValue, srcValue) =>
|
||||
isArray(objValue) ? objValue.concat(srcValue) : undefined,
|
||||
Array.isArray(objValue) ? objValue.concat(srcValue) : undefined,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { isEmpty, isBoolean } from 'lodash';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import { QueryObject } from './types';
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ export default function normalizeOrderBy(
|
|||
Array.isArray(orderbyClause) &&
|
||||
orderbyClause.length === 2 &&
|
||||
!isEmpty(orderbyClause[0]) &&
|
||||
isBoolean(orderbyClause[1])
|
||||
typeof orderbyClause[1] === 'boolean'
|
||||
) {
|
||||
return queryObject;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import {
|
|||
QueryFormData,
|
||||
SequentialScheme,
|
||||
} from '@superset-ui/core';
|
||||
import { isNumber } from 'lodash';
|
||||
import { hexToRGB } from './utils/colors';
|
||||
|
||||
const DEFAULT_NUM_BUCKETS = 10;
|
||||
|
|
@ -140,7 +139,7 @@ export function getBreakPointColorScaler(
|
|||
} else {
|
||||
// interpolate colors linearly
|
||||
const linearScaleDomain = extent(features, accessor);
|
||||
if (!linearScaleDomain.some(isNumber)) {
|
||||
if (!linearScaleDomain.some(i => typeof i === 'number')) {
|
||||
scaler = colorScheme.createLinearScale();
|
||||
} else {
|
||||
scaler = colorScheme.createLinearScale(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { isNumber } from 'lodash';
|
||||
import { DataRecord, DTTM_ALIAS, ValueFormatter } from '@superset-ui/core';
|
||||
import type { OptionName } from 'echarts/types/src/util/types';
|
||||
import type { TooltipMarker } from 'echarts/types/src/util/format';
|
||||
|
|
@ -64,7 +63,7 @@ export const extractForecastValuesFromTooltipParams = (
|
|||
const { marker, seriesId, value } = param;
|
||||
const context = extractForecastSeriesContext(seriesId);
|
||||
const numericValue = isHorizontal ? value[0] : value[1];
|
||||
if (isNumber(numericValue)) {
|
||||
if (typeof numericValue === 'number') {
|
||||
if (!(context.name in values))
|
||||
values[context.name] = {
|
||||
marker: marker || '',
|
||||
|
|
@ -97,7 +96,7 @@ export const formatForecastTooltipSeries = ({
|
|||
formatter: ValueFormatter;
|
||||
}): string[] => {
|
||||
const name = `${marker}${sanitizeHtml(seriesName)}`;
|
||||
let value = isNumber(observation) ? formatter(observation) : '';
|
||||
let value = typeof observation === 'number' ? formatter(observation) : '';
|
||||
if (forecastTrend || forecastLower || forecastUpper) {
|
||||
// forecast values take the form of "20, y = 30 (10, 40)"
|
||||
// where the first part is the observation, the second part is the forecast trend
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { DataRecord, DataRecordValue } from '@superset-ui/core';
|
||||
import { groupBy as _groupBy, isNumber, transform } from 'lodash';
|
||||
import { groupBy as _groupBy, transform } from 'lodash';
|
||||
|
||||
export type TreeNode = {
|
||||
name: DataRecordValue;
|
||||
|
|
@ -28,7 +28,7 @@ export type TreeNode = {
|
|||
};
|
||||
|
||||
function getMetricValue(datum: DataRecord, metric: string) {
|
||||
return isNumber(datum[metric]) ? (datum[metric] as number) : 0;
|
||||
return typeof datum[metric] === 'number' ? (datum[metric] as number) : 0;
|
||||
}
|
||||
|
||||
export function treeBuilder(
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ import {
|
|||
PlusCircleOutlined,
|
||||
TableOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { isEmpty, isNumber } from 'lodash';
|
||||
import { isEmpty } from 'lodash';
|
||||
import {
|
||||
ColorSchemeEnum,
|
||||
DataColumnMeta,
|
||||
|
|
@ -899,7 +899,9 @@ export default function TableChart<D extends DataRecord = DataRecord>(
|
|||
/* The following classes are added to support custom CSS styling */
|
||||
className={cx(
|
||||
'cell-bar',
|
||||
isNumber(value) && value < 0 ? 'negative' : 'positive',
|
||||
typeof value === 'number' && value < 0
|
||||
? 'negative'
|
||||
: 'positive',
|
||||
)}
|
||||
css={cellBarStyles}
|
||||
role="presentation"
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ import { mountExploreUrl } from 'src/explore/exploreUtils';
|
|||
import { postFormData } from 'src/explore/exploreUtils/formData';
|
||||
import { URL_PARAMS } from 'src/constants';
|
||||
import { SelectValue } from 'antd/lib/select';
|
||||
import { isEmpty, isString } from 'lodash';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
interface QueryDatabase {
|
||||
id?: number;
|
||||
|
|
@ -280,7 +280,7 @@ export const SaveDatasetModal = ({
|
|||
// Remove the special filters entry from the templateParams
|
||||
// before saving the dataset.
|
||||
let templateParams;
|
||||
if (isString(datasource?.templateParams)) {
|
||||
if (typeof datasource?.templateParams === 'string') {
|
||||
const p = JSON.parse(datasource.templateParams);
|
||||
/* eslint-disable-next-line no-underscore-dangle */
|
||||
if (p._filters) {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ import type {
|
|||
CursorPosition,
|
||||
} from 'src/SqlLab/types';
|
||||
import type { DatabaseObject } from 'src/features/databases/types';
|
||||
import { debounce, throttle, isBoolean, isEmpty } from 'lodash';
|
||||
import { debounce, throttle, isEmpty } from 'lodash';
|
||||
import Modal from 'src/components/Modal';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import Button from 'src/components/Button';
|
||||
|
|
@ -281,9 +281,10 @@ const SqlEditor: FC<Props> = ({
|
|||
if (unsavedQueryEditor?.id === queryEditor.id) {
|
||||
dbId = unsavedQueryEditor.dbId || dbId;
|
||||
latestQueryId = unsavedQueryEditor.latestQueryId || latestQueryId;
|
||||
hideLeftBar = isBoolean(unsavedQueryEditor.hideLeftBar)
|
||||
? unsavedQueryEditor.hideLeftBar
|
||||
: hideLeftBar;
|
||||
hideLeftBar =
|
||||
typeof unsavedQueryEditor.hideLeftBar === 'boolean'
|
||||
? unsavedQueryEditor.hideLeftBar
|
||||
: hideLeftBar;
|
||||
}
|
||||
return {
|
||||
hasSqlStatement: Boolean(queryEditor.sql?.trim().length > 0),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import { useState } from 'react';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { omit, isUndefined, omitBy } from 'lodash';
|
||||
import { omit, omitBy } from 'lodash';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { waitFor, within } from '@testing-library/react';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
|
|
@ -166,7 +166,7 @@ test('should generate Explore url', async () => {
|
|||
form_data: {
|
||||
...omitBy(
|
||||
omit(formData, ['slice_id', 'slice_name', 'dashboards']),
|
||||
isUndefined,
|
||||
i => i === undefined,
|
||||
),
|
||||
groupby: ['name'],
|
||||
adhoc_filters: [
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import { ControlConfig } from '@superset-ui/chart-controls';
|
|||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import { FixedSizeList as List } from 'react-window';
|
||||
|
||||
import { isArray } from 'lodash';
|
||||
import { matchSorter, rankings } from 'match-sorter';
|
||||
import Alert from 'src/components/Alert';
|
||||
import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal';
|
||||
|
|
@ -142,7 +141,7 @@ export default function DataSourcePanel({
|
|||
|
||||
const allowedColumns = useMemo(() => {
|
||||
const validators = Object.values(dropzones);
|
||||
if (!isArray(_columns)) return [];
|
||||
if (!Array.isArray(_columns)) return [];
|
||||
return _columns.filter(column =>
|
||||
validators.some(validator =>
|
||||
validator({
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
import { useEffect, useRef, useState } from 'react';
|
||||
import { InputNumber } from 'src/components/Input';
|
||||
import { t, styled } from '@superset-ui/core';
|
||||
import { debounce, parseInt } from 'lodash';
|
||||
import { debounce } from 'lodash';
|
||||
import ControlHeader from 'src/explore/components/ControlHeader';
|
||||
|
||||
type ValueType = (number | null)[];
|
||||
|
|
@ -47,7 +47,7 @@ const parseNumber = (value: undefined | number | string | null) => {
|
|||
if (
|
||||
value === null ||
|
||||
value === undefined ||
|
||||
(typeof value === 'string' && Number.isNaN(parseInt(value)))
|
||||
(typeof value === 'string' && Number.isNaN(Number.parseInt(value, 10)))
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import {
|
|||
CategoricalColorNamespace,
|
||||
} from '@superset-ui/core';
|
||||
import AntdSelect from 'antd/lib/select';
|
||||
import { isFunction, sortBy } from 'lodash';
|
||||
import { sortBy } from 'lodash';
|
||||
import ControlHeader from 'src/explore/components/ControlHeader';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import Icons from 'src/components/Icons';
|
||||
|
|
@ -163,7 +163,7 @@ const ColorSchemeControl = ({
|
|||
}
|
||||
let result = value || defaultScheme;
|
||||
if (result === 'SUPERSET_DEFAULT') {
|
||||
const schemesObject = isFunction(schemes) ? schemes() : schemes;
|
||||
const schemesObject = typeof schemes === 'function' ? schemes() : schemes;
|
||||
result = schemesObject?.SUPERSET_DEFAULT?.id;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -179,8 +179,8 @@ const ColorSchemeControl = ({
|
|||
</Option>,
|
||||
];
|
||||
}
|
||||
const schemesObject = isFunction(schemes) ? schemes() : schemes;
|
||||
const controlChoices = isFunction(choices) ? choices() : choices;
|
||||
const schemesObject = typeof schemes === 'function' ? schemes() : schemes;
|
||||
const controlChoices = typeof choices === 'function' ? choices() : choices;
|
||||
const allColorOptions: string[] = [];
|
||||
const filteredColorOptions = controlChoices.filter(o => {
|
||||
const option = o[0];
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ import ViewQueryModalFooter from 'src/explore/components/controls/ViewQueryModal
|
|||
import ViewQuery from 'src/explore/components/controls/ViewQuery';
|
||||
import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal';
|
||||
import { safeStringify } from 'src/utils/safeStringify';
|
||||
import { isString } from 'lodash';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const propTypes = {
|
||||
|
|
@ -383,7 +382,7 @@ class DatasourceControl extends PureComponent {
|
|||
|
||||
let extra;
|
||||
if (datasource?.extra) {
|
||||
if (isString(datasource.extra)) {
|
||||
if (typeof datasource.extra === 'string') {
|
||||
try {
|
||||
extra = JSON.parse(datasource.extra);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { isInteger } from 'lodash';
|
||||
import { t, customTimeRangeDecode } from '@superset-ui/core';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
import { Col, Row } from 'src/components';
|
||||
|
|
@ -76,7 +75,7 @@ export function CustomFrame(props: FrameComponentProps) {
|
|||
value: string | number,
|
||||
) {
|
||||
// only positive values in grainValue controls
|
||||
if (isInteger(value) && value > 0) {
|
||||
if (typeof value === 'number' && Number.isInteger(value) && value > 0) {
|
||||
props.onChange(
|
||||
customTimeRangeEncode({
|
||||
...customRange,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import { render, screen } from 'spec/helpers/testing-library';
|
|||
import userEvent from '@testing-library/user-event';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import { UploadFile } from 'antd/lib/upload/interface';
|
||||
import { forEach } from 'lodash';
|
||||
|
||||
fetchMock.post('glob:*api/v1/database/1/csv_upload/', {});
|
||||
fetchMock.post('glob:*api/v1/database/1/excel_upload/', {});
|
||||
|
|
@ -782,7 +781,7 @@ test('Columnar, form post', async () => {
|
|||
|
||||
test('CSV, validate file extension returns false', () => {
|
||||
const invalidFileNames = ['out', 'out.exe', 'out.csv.exe', '.csv', 'out.xls'];
|
||||
forEach(invalidFileNames, fileName => {
|
||||
invalidFileNames.forEach(fileName => {
|
||||
const file: UploadFile<any> = {
|
||||
name: fileName,
|
||||
uid: 'xp',
|
||||
|
|
@ -795,7 +794,7 @@ test('CSV, validate file extension returns false', () => {
|
|||
|
||||
test('Excel, validate file extension returns false', () => {
|
||||
const invalidFileNames = ['out', 'out.exe', 'out.xls.exe', '.csv', 'out.csv'];
|
||||
forEach(invalidFileNames, fileName => {
|
||||
invalidFileNames.forEach(fileName => {
|
||||
const file: UploadFile<any> = {
|
||||
name: fileName,
|
||||
uid: 'xp',
|
||||
|
|
@ -814,7 +813,7 @@ test('Columnar, validate file extension returns false', () => {
|
|||
'.parquet',
|
||||
'out.excel',
|
||||
];
|
||||
forEach(invalidFileNames, fileName => {
|
||||
invalidFileNames.forEach(fileName => {
|
||||
const file: UploadFile<any> = {
|
||||
name: fileName,
|
||||
uid: 'xp',
|
||||
|
|
@ -827,7 +826,7 @@ test('Columnar, validate file extension returns false', () => {
|
|||
|
||||
test('CSV, validate file extension returns true', () => {
|
||||
const invalidFileNames = ['out.csv', 'out.tsv', 'out.exe.csv', 'out a.csv'];
|
||||
forEach(invalidFileNames, fileName => {
|
||||
invalidFileNames.forEach(fileName => {
|
||||
const file: UploadFile<any> = {
|
||||
name: fileName,
|
||||
uid: 'xp',
|
||||
|
|
@ -840,7 +839,7 @@ test('CSV, validate file extension returns true', () => {
|
|||
|
||||
test('Excel, validate file extension returns true', () => {
|
||||
const invalidFileNames = ['out.xls', 'out.xlsx', 'out.exe.xls', 'out a.xls'];
|
||||
forEach(invalidFileNames, fileName => {
|
||||
invalidFileNames.forEach(fileName => {
|
||||
const file: UploadFile<any> = {
|
||||
name: fileName,
|
||||
uid: 'xp',
|
||||
|
|
@ -858,7 +857,7 @@ test('Columnar, validate file extension returns true', () => {
|
|||
'out.exe.zip',
|
||||
'out a.parquet',
|
||||
];
|
||||
forEach(invalidFileNames, fileName => {
|
||||
invalidFileNames.forEach(fileName => {
|
||||
const file: UploadFile<any> = {
|
||||
name: fileName,
|
||||
uid: 'xp',
|
||||
|
|
|
|||
|
|
@ -19,14 +19,7 @@
|
|||
import { nanoid } from 'nanoid';
|
||||
import { compose } from 'redux';
|
||||
import persistState, { StorageAdapter } from 'redux-localstorage';
|
||||
import {
|
||||
isEqual,
|
||||
omitBy,
|
||||
omit,
|
||||
isUndefined,
|
||||
isNull,
|
||||
isEqualWith,
|
||||
} from 'lodash';
|
||||
import { isEqual, omitBy, omit, isEqualWith } from 'lodash';
|
||||
import { ensureIsArray } from '@superset-ui/core';
|
||||
|
||||
export function addToObject(
|
||||
|
|
@ -195,12 +188,12 @@ export function areObjectsEqual(
|
|||
let comp1 = obj1;
|
||||
let comp2 = obj2;
|
||||
if (opts.ignoreUndefined) {
|
||||
comp1 = omitBy(comp1, isUndefined);
|
||||
comp2 = omitBy(comp2, isUndefined);
|
||||
comp1 = omitBy(comp1, i => i === undefined);
|
||||
comp2 = omitBy(comp2, i => i === undefined);
|
||||
}
|
||||
if (opts.ignoreNull) {
|
||||
comp1 = omitBy(comp1, isNull);
|
||||
comp2 = omitBy(comp2, isNull);
|
||||
comp1 = omitBy(comp1, i => i === null);
|
||||
comp2 = omitBy(comp2, i => i === null);
|
||||
}
|
||||
if (opts.ignoreFields?.length) {
|
||||
const ignoreFields = ensureIsArray(opts.ignoreFields);
|
||||
|
|
|
|||
Loading…
Reference in New Issue