This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new f8fe780f52 chore: replace Lodash usage with native JS implementation
(#31907)
f8fe780f52 is described below
commit f8fe780f52604dd83aa6cdf2e6c9cec01dc09852
Author: Đỗ Trọng Hải <[email protected]>
AuthorDate: Wed Jan 22 01:33:31 2025 +0700
chore: replace Lodash usage with native JS implementation (#31907)
Signed-off-by: hainenber <[email protected]>
---
.../src/operators/utils/timeOffset.ts | 5 +++--
.../superset-ui-core/src/components/SafeMarkdown.tsx | 4 ++--
.../superset-ui-core/src/query/normalizeOrderBy.ts | 4 ++--
.../plugins/legacy-preset-chart-deckgl/src/utils.ts | 3 +--
.../plugins/plugin-chart-echarts/src/utils/forecast.ts | 5 ++---
.../plugin-chart-echarts/src/utils/treeBuilder.ts | 4 ++--
.../plugins/plugin-chart-table/src/TableChart.tsx | 6 ++++--
.../src/SqlLab/components/SaveDatasetModal/index.tsx | 4 ++--
.../src/SqlLab/components/SqlEditor/index.tsx | 9 +++++----
.../src/components/Chart/DrillBy/DrillByModal.test.tsx | 4 ++--
.../src/explore/components/DatasourcePanel/index.tsx | 3 +--
.../src/explore/components/controls/BoundsControl.tsx | 4 ++--
.../components/controls/ColorSchemeControl/index.tsx | 8 ++++----
.../components/controls/DatasourceControl/index.jsx | 3 +--
.../DateFilterControl/components/CustomFrame.tsx | 3 +--
.../databases/UploadDataModel/UploadDataModal.test.tsx | 13 ++++++-------
superset-frontend/src/reduxUtils.ts | 17 +++++------------
17 files changed, 45 insertions(+), 54 deletions(-)
diff --git
a/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/timeOffset.ts
b/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/timeOffset.ts
index 8a7d9a964f..852b4eb1ab 100644
---
a/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/timeOffset.ts
+++
b/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/timeOffset.ts
@@ -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,
diff --git
a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
index 02db7dadbc..d35c2160e9 100644
---
a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
+++
b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
@@ -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,
);
}
diff --git
a/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts
b/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts
index b07338781c..840cf4c1a1 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts
@@ -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;
}
diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/utils.ts
b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/utils.ts
index aac2a739e6..55d05fe5b6 100644
--- a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/utils.ts
+++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/utils.ts
@@ -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(
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts
index c7244baf48..1f92390113 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts
@@ -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
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts
index cda78da93a..919d6e6db6 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts
@@ -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(
diff --git a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx
b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx
index b9cc335a34..77905ea562 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx
+++ b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx
@@ -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"
diff --git a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx
b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx
index 98dcd34862..5df4d0c304 100644
--- a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx
@@ -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) {
diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
index cab82cd02f..4d1aded5be 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
@@ -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),
diff --git
a/superset-frontend/src/components/Chart/DrillBy/DrillByModal.test.tsx
b/superset-frontend/src/components/Chart/DrillBy/DrillByModal.test.tsx
index 2299f091b6..a57dd675e7 100644
--- a/superset-frontend/src/components/Chart/DrillBy/DrillByModal.test.tsx
+++ b/superset-frontend/src/components/Chart/DrillBy/DrillByModal.test.tsx
@@ -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: [
diff --git a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
index d15df0a2f4..2d2c0783df 100644
--- a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
+++ b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
@@ -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({
diff --git
a/superset-frontend/src/explore/components/controls/BoundsControl.tsx
b/superset-frontend/src/explore/components/controls/BoundsControl.tsx
index 10b355d176..87914d04b0 100644
--- a/superset-frontend/src/explore/components/controls/BoundsControl.tsx
+++ b/superset-frontend/src/explore/components/controls/BoundsControl.tsx
@@ -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;
}
diff --git
a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
index fd9dc85f0f..b479c4f3d9 100644
---
a/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
+++
b/superset-frontend/src/explore/components/controls/ColorSchemeControl/index.tsx
@@ -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];
diff --git
a/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx
b/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx
index d4ed74a019..cc8474b6dc 100644
---
a/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx
+++
b/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx
@@ -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
diff --git
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
index ec558c0909..378956c645 100644
---
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
+++
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
@@ -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,
diff --git
a/superset-frontend/src/features/databases/UploadDataModel/UploadDataModal.test.tsx
b/superset-frontend/src/features/databases/UploadDataModel/UploadDataModal.test.tsx
index 54b8176546..7347e13bd5 100644
---
a/superset-frontend/src/features/databases/UploadDataModel/UploadDataModal.test.tsx
+++
b/superset-frontend/src/features/databases/UploadDataModel/UploadDataModal.test.tsx
@@ -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',
diff --git a/superset-frontend/src/reduxUtils.ts
b/superset-frontend/src/reduxUtils.ts
index 20153cb0d3..ea87285cb8 100644
--- a/superset-frontend/src/reduxUtils.ts
+++ b/superset-frontend/src/reduxUtils.ts
@@ -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);