From da3791ad3daa209631a588394600d1a8b635e814 Mon Sep 17 00:00:00 2001 From: Geido <60598000+geido@users.noreply.github.com> Date: Wed, 15 Mar 2023 18:48:03 +0100 Subject: [PATCH] fix: Table sorting reset (#23318) --- superset-frontend/package-lock.json | 67 +++++++++++ .../packages/superset-ui-core/package.json | 1 + .../superset-ui-core/src/hooks/index.ts | 25 ++++ .../src/hooks/useChangeEffect/index.ts | 0 .../useChangeEffect/useChangeEffect.test.ts | 0 .../hooks/useChangeEffect/useChangeEffect.ts | 0 .../src/hooks/useComponentDidMount/index.ts | 0 .../useComponentDidMount.test.ts | 0 .../useComponentDidMount.ts | 0 .../src/hooks/useComponentDidUpdate/index.ts | 0 .../useComponentDidUpdate.test.ts | 0 .../useComponentDidUpdate.ts | 0 .../src/hooks/useElementOnScreen/index.ts | 20 ++++ .../useElementOnScreen.test.ts | 111 ++++++++++++++++++ .../useElementOnScreen/useElementOnScreen.ts} | 0 .../src/hooks/usePrevious/index.ts | 0 .../src/hooks/usePrevious/usePrevious.test.ts | 0 .../src/hooks/usePrevious/usePrevious.ts | 0 .../src/hooks/useTruncation/index.ts | 0 .../useCSSTextTruncation.test.tsx | 62 ++++++++++ .../useTruncation/useCSSTextTruncation.ts | 0 .../useChildElementTruncation.test.ts | 102 ++++++++++++++++ .../useChildElementTruncation.ts | 0 .../packages/superset-ui-core/src/index.ts | 1 + .../plugins/plugin-chart-table/package.json | 1 + .../src/DataTable/DataTable.tsx | 6 +- .../components/AceEditorWrapper/index.tsx | 3 +- .../src/SqlLab/components/ResultSet/index.tsx | 2 +- .../components/DropdownContainer/index.tsx | 3 +- .../src/components/FaveStar/index.tsx | 3 +- .../src/components/FlashProvider/index.tsx | 2 +- .../src/components/ListView/CrossLinks.tsx | 3 +- .../HeaderReportDropdown/index.tsx | 2 +- .../src/components/Select/CustomTag.tsx | 3 +- .../src/components/TruncatedList/index.tsx | 3 +- .../DashboardBuilder/DashboardBuilder.tsx | 2 +- .../DashboardBuilder/DashboardContainer.tsx | 2 +- .../components/FiltersBadge/index.tsx | 8 +- .../FilterBar/CrossFilters/CrossFilterTag.tsx | 9 +- .../CrossFilters/CrossFilterTitle.tsx | 9 +- .../FilterControls/FilterControl.tsx | 3 +- .../FilterControls/FilterDivider.tsx | 8 +- .../nativeFilters/FilterBar/index.tsx | 2 +- .../FilterCard/DependenciesRow.tsx | 3 +- .../nativeFilters/FilterCard/NameRow.tsx | 3 +- .../nativeFilters/FilterCard/ScopeRow.tsx | 3 +- .../FiltersConfigForm/ColumnSelect.tsx | 3 +- .../FilterScope/FilterScope.tsx | 8 +- .../nativeFilters/FiltersConfigModal/state.ts | 3 +- .../src/explore/components/Control.tsx | 8 +- .../components/ControlPanelsContainer.tsx | 2 +- .../components/ExploreViewContainer/index.jsx | 14 ++- .../ConditionalFormattingControl.tsx | 9 +- .../DateFilterControl/DateFilterLabel.tsx | 2 +- .../controls/MetricControl/MetricsControl.jsx | 3 +- 55 files changed, 471 insertions(+), 53 deletions(-) create mode 100644 superset-frontend/packages/superset-ui-core/src/hooks/index.ts rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useChangeEffect/index.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useChangeEffect/useChangeEffect.test.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useChangeEffect/useChangeEffect.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useComponentDidMount/index.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useComponentDidMount/useComponentDidMount.test.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useComponentDidMount/useComponentDidMount.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useComponentDidUpdate/index.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useComponentDidUpdate/useComponentDidUpdate.ts (100%) create mode 100644 superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/index.ts create mode 100644 superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/useElementOnScreen.test.ts rename superset-frontend/{src/hooks/useElementOnScreen/index.ts => packages/superset-ui-core/src/hooks/useElementOnScreen/useElementOnScreen.ts} (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/usePrevious/index.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/usePrevious/usePrevious.test.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/usePrevious/usePrevious.ts (100%) rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useTruncation/index.ts (100%) create mode 100644 superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useCSSTextTruncation.test.tsx rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useTruncation/useCSSTextTruncation.ts (100%) create mode 100644 superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useChildElementTruncation.test.ts rename superset-frontend/{ => packages/superset-ui-core}/src/hooks/useTruncation/useChildElementTruncation.ts (100%) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 2d3d67aa74..c8a9e8234d 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -59940,6 +59940,7 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.1.2", + "@testing-library/react-hooks": "^8.0.1", "@types/d3-format": "^1.3.0", "@types/d3-interpolate": "^1.3.1", "@types/d3-scale": "^2.1.1", @@ -59993,6 +59994,50 @@ "tinycolor2": "*" } }, + "packages/superset-ui-core/node_modules/@testing-library/react-hooks": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", + "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "react-error-boundary": "^3.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-test-renderer": "^16.9.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-test-renderer": { + "optional": true + } + } + }, + "packages/superset-ui-core/node_modules/@testing-library/react-hooks/node_modules/react-error-boundary": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", + "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "packages/superset-ui-core/node_modules/@types/d3-time": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", @@ -61420,6 +61465,7 @@ "@types/react-table": "^7.0.29", "classnames": "^2.3.2", "d3-array": "^2.4.0", + "lodash": "^4.17.21", "match-sorter": "^6.3.0", "memoize-one": "^5.1.1", "react-table": "^7.6.3", @@ -76247,6 +76293,7 @@ "requires": { "@babel/runtime": "^7.1.2", "@emotion/styled": "^11.3.0", + "@testing-library/react-hooks": "*", "@types/d3-format": "^1.3.0", "@types/d3-interpolate": "^1.3.1", "@types/d3-scale": "^2.1.1", @@ -76286,6 +76333,25 @@ "whatwg-fetch": "^3.0.0" }, "dependencies": { + "@testing-library/react-hooks": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", + "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", + "requires": { + "@babel/runtime": "^7.12.5", + "react-error-boundary": "^3.1.0" + }, + "dependencies": { + "react-error-boundary": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", + "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "requires": { + "@babel/runtime": "^7.12.5" + } + } + } + }, "@types/d3-time": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", @@ -77286,6 +77352,7 @@ "@types/react-table": "^7.0.29", "classnames": "^2.3.2", "d3-array": "^2.4.0", + "lodash": "^4.17.21", "match-sorter": "^6.3.0", "memoize-one": "^5.1.1", "react-table": "^7.6.3", diff --git a/superset-frontend/packages/superset-ui-core/package.json b/superset-frontend/packages/superset-ui-core/package.json index 2ccb9877fd..6107945900 100644 --- a/superset-frontend/packages/superset-ui-core/package.json +++ b/superset-frontend/packages/superset-ui-core/package.json @@ -24,6 +24,7 @@ ], "dependencies": { "@babel/runtime": "^7.1.2", + "@testing-library/react-hooks": "^8.0.1", "@types/d3-format": "^1.3.0", "@types/d3-interpolate": "^1.3.1", "@types/d3-scale": "^2.1.1", diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/index.ts new file mode 100644 index 0000000000..b27759b492 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/hooks/index.ts @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './useChangeEffect'; +export * from './useComponentDidMount'; +export * from './useComponentDidUpdate'; +export * from './useElementOnScreen'; +export * from './usePrevious'; +export * from './useTruncation'; diff --git a/superset-frontend/src/hooks/useChangeEffect/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/index.ts similarity index 100% rename from superset-frontend/src/hooks/useChangeEffect/index.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/index.ts diff --git a/superset-frontend/src/hooks/useChangeEffect/useChangeEffect.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.test.ts similarity index 100% rename from superset-frontend/src/hooks/useChangeEffect/useChangeEffect.test.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.test.ts diff --git a/superset-frontend/src/hooks/useChangeEffect/useChangeEffect.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.ts similarity index 100% rename from superset-frontend/src/hooks/useChangeEffect/useChangeEffect.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useChangeEffect/useChangeEffect.ts diff --git a/superset-frontend/src/hooks/useComponentDidMount/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/index.ts similarity index 100% rename from superset-frontend/src/hooks/useComponentDidMount/index.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/index.ts diff --git a/superset-frontend/src/hooks/useComponentDidMount/useComponentDidMount.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.test.ts similarity index 100% rename from superset-frontend/src/hooks/useComponentDidMount/useComponentDidMount.test.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.test.ts diff --git a/superset-frontend/src/hooks/useComponentDidMount/useComponentDidMount.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.ts similarity index 100% rename from superset-frontend/src/hooks/useComponentDidMount/useComponentDidMount.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidMount/useComponentDidMount.ts diff --git a/superset-frontend/src/hooks/useComponentDidUpdate/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/index.ts similarity index 100% rename from superset-frontend/src/hooks/useComponentDidUpdate/index.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/index.ts diff --git a/superset-frontend/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts similarity index 100% rename from superset-frontend/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.test.ts diff --git a/superset-frontend/src/hooks/useComponentDidUpdate/useComponentDidUpdate.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.ts similarity index 100% rename from superset-frontend/src/hooks/useComponentDidUpdate/useComponentDidUpdate.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useComponentDidUpdate/useComponentDidUpdate.ts diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/index.ts new file mode 100644 index 0000000000..389d85eedf --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/index.ts @@ -0,0 +1,20 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './useElementOnScreen'; diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/useElementOnScreen.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/useElementOnScreen.test.ts new file mode 100644 index 0000000000..ef105208e0 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/useElementOnScreen.test.ts @@ -0,0 +1,111 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { renderHook } from '@testing-library/react-hooks'; +import React from 'react'; +import { useElementOnScreen } from './useElementOnScreen'; + +const observeMock = jest.fn(); +const unobserveMock = jest.fn(); +const IntersectionObserverMock = jest.fn(); +IntersectionObserverMock.prototype.observe = observeMock; +IntersectionObserverMock.prototype.unobserve = unobserveMock; + +beforeEach(() => { + window.IntersectionObserver = IntersectionObserverMock; +}); + +afterEach(() => { + IntersectionObserverMock.mockClear(); + jest.clearAllMocks(); +}); + +test('should return null and false on first render', () => { + const hook = renderHook(() => + useElementOnScreen({ rootMargin: '-50px 0px 0px 0px' }), + ); + expect(hook.result.current).toEqual([{ current: null }, false]); +}); + +test('should return isSticky as true when intersectionRatio < 1', async () => { + const hook = renderHook(() => + useElementOnScreen({ rootMargin: '-50px 0px 0px 0px' }), + ); + const callback = IntersectionObserverMock.mock.calls[0][0]; + const callBack = callback([{ isIntersecting: true, intersectionRatio: 0.5 }]); + const observer = new IntersectionObserverMock(callBack, {}); + const newDiv = document.createElement('div'); + observer.observe(newDiv); + expect(hook.result.current[1]).toEqual(true); +}); + +test('should return isSticky as false when intersectionRatio >= 1', async () => { + const hook = renderHook(() => + useElementOnScreen({ rootMargin: '-50px 0px 0px 0px' }), + ); + const callback = IntersectionObserverMock.mock.calls[0][0]; + const callBack = callback([{ isIntersecting: true, intersectionRatio: 1 }]); + const observer = new IntersectionObserverMock(callBack, {}); + const newDiv = document.createElement('div'); + observer.observe(newDiv); + expect(hook.result.current[1]).toEqual(false); +}); + +test('should observe and unobserve element with IntersectionObserver', async () => { + jest.spyOn(React, 'useRef').mockReturnValue({ current: 'test' }); + const options = { threshold: 0.5 }; + const { result, unmount } = renderHook(() => useElementOnScreen(options)); + const [elementRef] = result.current; + + expect(IntersectionObserverMock).toHaveBeenCalledWith( + expect.any(Function), + options, + ); + + expect(elementRef).not.toBe(null); + expect(observeMock).toHaveBeenCalledWith(elementRef.current); + + unmount(); + + expect(unobserveMock).toHaveBeenCalledWith(elementRef.current); +}); + +test('should not observe an element if it is null', () => { + jest.spyOn(React, 'useRef').mockReturnValue({ current: null }); + const options = {}; + const { result } = renderHook(() => useElementOnScreen(options)); + const [ref, isSticky] = result.current; + expect(ref.current).toBe(null); + expect(isSticky).toBe(false); + + expect(observeMock).not.toHaveBeenCalled(); +}); + +test('should not unobserve the element if it is null', () => { + jest.spyOn(React, 'useRef').mockReturnValue({ current: null }); + const options = {}; + const { result, unmount } = renderHook(() => useElementOnScreen(options)); + const [ref, isSticky] = result.current; + + expect(ref.current).toBe(null); + expect(isSticky).toBe(false); + + unmount(); + + expect(unobserveMock).not.toHaveBeenCalled(); +}); diff --git a/superset-frontend/src/hooks/useElementOnScreen/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/useElementOnScreen.ts similarity index 100% rename from superset-frontend/src/hooks/useElementOnScreen/index.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useElementOnScreen/useElementOnScreen.ts diff --git a/superset-frontend/src/hooks/usePrevious/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/usePrevious/index.ts similarity index 100% rename from superset-frontend/src/hooks/usePrevious/index.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/usePrevious/index.ts diff --git a/superset-frontend/src/hooks/usePrevious/usePrevious.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/usePrevious/usePrevious.test.ts similarity index 100% rename from superset-frontend/src/hooks/usePrevious/usePrevious.test.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/usePrevious/usePrevious.test.ts diff --git a/superset-frontend/src/hooks/usePrevious/usePrevious.ts b/superset-frontend/packages/superset-ui-core/src/hooks/usePrevious/usePrevious.ts similarity index 100% rename from superset-frontend/src/hooks/usePrevious/usePrevious.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/usePrevious/usePrevious.ts diff --git a/superset-frontend/src/hooks/useTruncation/index.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/index.ts similarity index 100% rename from superset-frontend/src/hooks/useTruncation/index.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/index.ts diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useCSSTextTruncation.test.tsx b/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useCSSTextTruncation.test.tsx new file mode 100644 index 0000000000..96a46734d7 --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useCSSTextTruncation.test.tsx @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { renderHook } from '@testing-library/react-hooks'; +import React from 'react'; +import useCSSTextTruncation from './useCSSTextTruncation'; + +afterEach(() => { + jest.clearAllMocks(); +}); + +test('should be false by default', () => { + const { result } = renderHook(() => + useCSSTextTruncation(), + ); + const [paragraphRef, isTruncated] = result.current; + expect(paragraphRef.current).toBe(null); + expect(isTruncated).toBe(false); +}); + +test('should not truncate', () => { + const ref = { current: document.createElement('p') }; + Object.defineProperty(ref.current, 'offsetWidth', { get: () => 100 }); + Object.defineProperty(ref.current, 'scrollWidth', { get: () => 50 }); + jest.spyOn(React, 'useRef').mockReturnValue({ current: ref.current }); + + const { result } = renderHook(() => + useCSSTextTruncation(), + ); + const [, isTruncated] = result.current; + + expect(isTruncated).toBe(false); +}); + +test('should truncate', () => { + const ref = { current: document.createElement('p') }; + Object.defineProperty(ref.current, 'offsetWidth', { get: () => 50 }); + Object.defineProperty(ref.current, 'scrollWidth', { get: () => 100 }); + jest.spyOn(React, 'useRef').mockReturnValue({ current: ref.current }); + + const { result } = renderHook(() => + useCSSTextTruncation(), + ); + const [, isTruncated] = result.current; + + expect(isTruncated).toBe(true); +}); diff --git a/superset-frontend/src/hooks/useTruncation/useCSSTextTruncation.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useCSSTextTruncation.ts similarity index 100% rename from superset-frontend/src/hooks/useTruncation/useCSSTextTruncation.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useCSSTextTruncation.ts diff --git a/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useChildElementTruncation.test.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useChildElementTruncation.test.ts new file mode 100644 index 0000000000..ee3e95139f --- /dev/null +++ b/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useChildElementTruncation.test.ts @@ -0,0 +1,102 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { renderHook } from '@testing-library/react-hooks'; +import { RefObject } from 'react'; +import useChildElementTruncation from './useChildElementTruncation'; + +const genElements = ( + scrollWidth: number, + clientWidth: number, + offsetWidth: number | undefined, + childNodes: any = [], +) => { + const elementRef: RefObject> = { + current: { scrollWidth, clientWidth, childNodes }, + }; + const plusRef: RefObject> = { + current: { offsetWidth }, + }; + return [elementRef, plusRef]; +}; +const useTruncation = (elementRef: any, plusRef: any) => + useChildElementTruncation( + elementRef as RefObject, + plusRef as RefObject, + ); + +test('should return [0, false] when elementRef.current is not defined', () => { + const { result } = renderHook(() => + useTruncation({ current: undefined }, { current: undefined }), + ); + + expect(result.current).toEqual([0, false]); +}); + +test('should not recompute when previousEffectInfo is the same as previous', () => { + const elementRef = { current: document.createElement('div') }; + const plusRef = { current: document.createElement('div') }; + const { result, rerender } = renderHook(() => + useTruncation(elementRef, plusRef), + ); + const previousEffectInfo = result.current; + + rerender(); + + expect(result.current).toEqual(previousEffectInfo); +}); + +test('should return [0, false] when there are no truncated/hidden elements', () => { + const [elementRef, plusRef] = genElements(100, 100, 10); + const { result } = renderHook(() => useTruncation(elementRef, plusRef)); + expect(result.current).toEqual([0, false]); +}); + +test('should return [1, false] when there is only one truncated element', () => { + const [elementRef, plusRef] = genElements(150, 100, 10); + const { result } = renderHook(() => useTruncation(elementRef, plusRef)); + expect(result.current).toEqual([1, false]); +}); + +test('should return [1, true] with one truncated and hidden elements', () => { + const [elementRef, plusRef] = genElements(150, 100, 10, [ + { offsetWidth: 150 } as HTMLElement, + { offsetWidth: 150 } as HTMLElement, + ]); + const { result } = renderHook(() => useTruncation(elementRef, plusRef)); + expect(result.current).toEqual([1, true]); +}); + +test('should return [2, true] with 2 truncated and hidden elements', () => { + const [elementRef, plusRef] = genElements(150, 100, 10, [ + { offsetWidth: 150 } as HTMLElement, + { offsetWidth: 150 } as HTMLElement, + { offsetWidth: 150 } as HTMLElement, + ]); + const { result } = renderHook(() => useTruncation(elementRef, plusRef)); + expect(result.current).toEqual([2, true]); +}); + +test('should return [1, true] with plusSize offsetWidth undefined', () => { + const [elementRef, plusRef] = genElements(150, 100, undefined, [ + { offsetWidth: 150 } as HTMLElement, + { offsetWidth: 150 } as HTMLElement, + ]); + const { result } = renderHook(() => useTruncation(elementRef, plusRef)); + expect(result.current).toEqual([1, true]); +}); diff --git a/superset-frontend/src/hooks/useTruncation/useChildElementTruncation.ts b/superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useChildElementTruncation.ts similarity index 100% rename from superset-frontend/src/hooks/useTruncation/useChildElementTruncation.ts rename to superset-frontend/packages/superset-ui-core/src/hooks/useTruncation/useChildElementTruncation.ts diff --git a/superset-frontend/packages/superset-ui-core/src/index.ts b/superset-frontend/packages/superset-ui-core/src/index.ts index 4d3c4b7c95..5ee5acbce4 100644 --- a/superset-frontend/packages/superset-ui-core/src/index.ts +++ b/superset-frontend/packages/superset-ui-core/src/index.ts @@ -35,3 +35,4 @@ export * from './chart-composition'; export * from './components'; export * from './math-expression'; export * from './ui-overrides'; +export * from './hooks'; diff --git a/superset-frontend/plugins/plugin-chart-table/package.json b/superset-frontend/plugins/plugin-chart-table/package.json index 293413805d..738c143e9d 100644 --- a/superset-frontend/plugins/plugin-chart-table/package.json +++ b/superset-frontend/plugins/plugin-chart-table/package.json @@ -32,6 +32,7 @@ "@types/react-table": "^7.0.29", "classnames": "^2.3.2", "d3-array": "^2.4.0", + "lodash": "^4.17.21", "match-sorter": "^6.3.0", "memoize-one": "^5.1.1", "react-table": "^7.6.3", diff --git a/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx b/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx index 85580e7b63..6c5123806f 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/DataTable/DataTable.tsx @@ -37,7 +37,8 @@ import { Row, } from 'react-table'; import { matchSorter, rankings } from 'match-sorter'; -import { typedMemo } from '@superset-ui/core'; +import { typedMemo, usePrevious } from '@superset-ui/core'; +import { isEqual } from 'lodash'; import GlobalFilter, { GlobalFilterProps } from './components/GlobalFilter'; import SelectPageSize, { SelectPageSizeProps, @@ -108,6 +109,8 @@ export default typedMemo(function DataTable({ doSticky ? useSticky : [], hooks || [], ].flat(); + const columnNames = Object.keys(data?.[0] || {}); + const previousColumnNames = usePrevious(columnNames); const resultsSize = serverPagination ? rowCount : data.length; const sortByRef = useRef([]); // cache initial `sortby` so sorting doesn't trigger page reset const pageSizeRef = useRef([initialPageSize, resultsSize]); @@ -187,6 +190,7 @@ export default typedMemo(function DataTable({ getTableSize: defaultGetTableSize, globalFilter: defaultGlobalFilter, sortTypes, + autoResetSortBy: !isEqual(columnNames, previousColumnNames), ...moreUseTableOptions, }, ...tableHooks, diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx index 0dd3385ea5..32d17340fb 100644 --- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx +++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx @@ -18,9 +18,8 @@ */ import React, { useState, useEffect, useRef } from 'react'; import { useDispatch } from 'react-redux'; -import { css, styled } from '@superset-ui/core'; +import { css, styled, usePrevious } from '@superset-ui/core'; -import { usePrevious } from 'src/hooks/usePrevious'; import { areArraysShallowEqual } from 'src/reduxUtils'; import sqlKeywords from 'src/SqlLab/utils/sqlKeywords'; import { diff --git a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx index fad6c98bc9..f41d27650b 100644 --- a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx +++ b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx @@ -28,8 +28,8 @@ import { styled, t, useTheme, + usePrevious, } from '@superset-ui/core'; -import { usePrevious } from 'src/hooks/usePrevious'; import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace'; import { ISaveableDatasource, diff --git a/superset-frontend/src/components/DropdownContainer/index.tsx b/superset-frontend/src/components/DropdownContainer/index.tsx index c90372973e..f2504c66ff 100644 --- a/superset-frontend/src/components/DropdownContainer/index.tsx +++ b/superset-frontend/src/components/DropdownContainer/index.tsx @@ -30,9 +30,8 @@ import React, { ReactNode, } from 'react'; import { Global } from '@emotion/react'; -import { css, t, useTheme } from '@superset-ui/core'; +import { css, t, useTheme, usePrevious } from '@superset-ui/core'; import { useResizeDetector } from 'react-resize-detector'; -import { usePrevious } from 'src/hooks/usePrevious'; import Badge from '../Badge'; import Icons from '../Icons'; import Button from '../Button'; diff --git a/superset-frontend/src/components/FaveStar/index.tsx b/superset-frontend/src/components/FaveStar/index.tsx index 8a6f4eca1f..c7b605243a 100644 --- a/superset-frontend/src/components/FaveStar/index.tsx +++ b/superset-frontend/src/components/FaveStar/index.tsx @@ -18,9 +18,8 @@ */ import React, { useCallback } from 'react'; -import { css, t, styled } from '@superset-ui/core'; +import { css, t, styled, useComponentDidMount } from '@superset-ui/core'; import { Tooltip } from 'src/components/Tooltip'; -import { useComponentDidMount } from 'src/hooks/useComponentDidMount'; import Icons from 'src/components/Icons'; export interface FaveStarProps { diff --git a/superset-frontend/src/components/FlashProvider/index.tsx b/superset-frontend/src/components/FlashProvider/index.tsx index 5e00af5fc5..f2bef9cf57 100644 --- a/superset-frontend/src/components/FlashProvider/index.tsx +++ b/superset-frontend/src/components/FlashProvider/index.tsx @@ -17,7 +17,7 @@ * under the License. */ import { useToasts } from 'src/components/MessageToasts/withToasts'; -import { useComponentDidMount } from 'src/hooks/useComponentDidMount'; +import { useComponentDidMount } from '@superset-ui/core'; type FlashMessageType = 'info' | 'alert' | 'danger' | 'warning' | 'success'; export type FlashMessage = [FlashMessageType, string]; diff --git a/superset-frontend/src/components/ListView/CrossLinks.tsx b/superset-frontend/src/components/ListView/CrossLinks.tsx index 653e97b06e..e315750674 100644 --- a/superset-frontend/src/components/ListView/CrossLinks.tsx +++ b/superset-frontend/src/components/ListView/CrossLinks.tsx @@ -17,9 +17,8 @@ * under the License. */ import React, { useMemo, useRef } from 'react'; -import { styled } from '@superset-ui/core'; +import { styled, useTruncation } from '@superset-ui/core'; import { Link } from 'react-router-dom'; -import { useTruncation } from 'src/hooks/useTruncation'; import CrossLinksTooltip from './CrossLinksTooltip'; export type CrossLinkProps = { diff --git a/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx b/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx index f7bb9ba55c..e8426641d6 100644 --- a/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx +++ b/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx @@ -17,7 +17,6 @@ * under the License. */ import React, { useState, useEffect } from 'react'; -import { usePrevious } from 'src/hooks/usePrevious'; import { useSelector, useDispatch } from 'react-redux'; import { t, @@ -28,6 +27,7 @@ import { FeatureFlag, isFeatureEnabled, getExtensionsRegistry, + usePrevious, } from '@superset-ui/core'; import Icons from 'src/components/Icons'; import { Switch } from 'src/components/Switch'; diff --git a/superset-frontend/src/components/Select/CustomTag.tsx b/superset-frontend/src/components/Select/CustomTag.tsx index a7ffe10f6d..ce837706da 100644 --- a/superset-frontend/src/components/Select/CustomTag.tsx +++ b/superset-frontend/src/components/Select/CustomTag.tsx @@ -18,8 +18,7 @@ */ import React from 'react'; import { Tag as AntdTag } from 'antd'; -import { styled } from '@superset-ui/core'; -import { useCSSTextTruncation } from 'src/hooks/useTruncation'; +import { styled, useCSSTextTruncation } from '@superset-ui/core'; import { Tooltip } from '../Tooltip'; import { CustomTagProps } from './types'; import { SELECT_ALL_VALUE } from './utils'; diff --git a/superset-frontend/src/components/TruncatedList/index.tsx b/superset-frontend/src/components/TruncatedList/index.tsx index 37d4fe0436..00e0acc0c3 100644 --- a/superset-frontend/src/components/TruncatedList/index.tsx +++ b/superset-frontend/src/components/TruncatedList/index.tsx @@ -18,8 +18,7 @@ */ import React, { ReactNode, useMemo, useRef } from 'react'; -import { styled, t } from '@superset-ui/core'; -import { useTruncation } from 'src/hooks/useTruncation'; +import { styled, t, useTruncation } from '@superset-ui/core'; import { Tooltip } from '../Tooltip'; export type TruncatedListProps = { diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx index 99360801c5..3c64c2ef1e 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx @@ -33,6 +33,7 @@ import { styled, t, useTheme, + useElementOnScreen, } from '@superset-ui/core'; import { Global } from '@emotion/react'; import { useDispatch, useSelector } from 'react-redux'; @@ -56,7 +57,6 @@ import { setDirectPathToChild, setEditMode, } from 'src/dashboard/actions/dashboardState'; -import { useElementOnScreen } from 'src/hooks/useElementOnScreen'; import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags'; import { deleteTopLevelTabs, diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx index 386d96266a..fc1570a975 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx @@ -27,6 +27,7 @@ import { getCategoricalSchemeRegistry, isFeatureEnabled, SupersetClient, + useComponentDidUpdate, } from '@superset-ui/core'; import { ParentSize } from '@visx/responsive'; import pick from 'lodash/pick'; @@ -48,7 +49,6 @@ import findTabIndexByComponentId from 'src/dashboard/util/findTabIndexByComponen import { setInScopeStatusOfFilters } from 'src/dashboard/actions/nativeFilters'; import { dashboardInfoChanged } from 'src/dashboard/actions/dashboardInfo'; import { setColorScheme } from 'src/dashboard/actions/dashboardState'; -import { useComponentDidUpdate } from 'src/hooks/useComponentDidUpdate/useComponentDidUpdate'; import jsonStringify from 'json-stringify-pretty-compact'; import { NATIVE_FILTER_DIVIDER_PREFIX } from '../nativeFilters/FiltersConfigModal/utils'; import { findTabsWithChartsInScope } from '../nativeFilters/utils'; diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx index f2d102ad8d..866fde94be 100644 --- a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx +++ b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx @@ -20,9 +20,13 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { uniqWith } from 'lodash'; import cx from 'classnames'; -import { DataMaskStateWithId, Filters, styled } from '@superset-ui/core'; +import { + DataMaskStateWithId, + Filters, + styled, + usePrevious, +} from '@superset-ui/core'; import Icons from 'src/components/Icons'; -import { usePrevious } from 'src/hooks/usePrevious'; import { setDirectPathToChild } from 'src/dashboard/actions/dashboardState'; import Badge from 'src/components/Badge'; import DetailsPanelPopover from './DetailsPanel'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTag.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTag.tsx index 3a1145c7db..d4b0789919 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTag.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTag.tsx @@ -18,11 +18,16 @@ */ import React from 'react'; -import { styled, css, useTheme, getColumnLabel } from '@superset-ui/core'; +import { + styled, + css, + useTheme, + getColumnLabel, + useCSSTextTruncation, +} from '@superset-ui/core'; import { CrossFilterIndicator } from 'src/dashboard/components/nativeFilters/selectors'; import { Tag } from 'src/components'; import { Tooltip } from 'src/components/Tooltip'; -import useCSSTextTruncation from 'src/hooks/useTruncation/useCSSTextTruncation'; import { FilterBarOrientation } from 'src/dashboard/types'; import { ellipsisCss } from './styles'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTitle.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTitle.tsx index 70f0ad2cd9..9221bffe15 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTitle.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/CrossFilterTitle.tsx @@ -18,9 +18,14 @@ */ import React from 'react'; -import { t, css, styled, useTheme } from '@superset-ui/core'; +import { + t, + css, + styled, + useTheme, + useCSSTextTruncation, +} from '@superset-ui/core'; import { Tooltip } from 'src/components/Tooltip'; -import useCSSTextTruncation from 'src/hooks/useTruncation/useCSSTextTruncation'; import { FilterBarOrientation } from 'src/dashboard/types'; import Icons from 'src/components/Icons'; import { ellipsisCss } from './styles'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx index 218603f74d..b7f2ba04f2 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx @@ -22,11 +22,10 @@ import { InPortal, OutPortal, } from 'react-reverse-portal'; -import { styled, SupersetTheme } from '@superset-ui/core'; +import { styled, SupersetTheme, truncationCSS } from '@superset-ui/core'; import { FormItem as StyledFormItem, Form } from 'src/components/Form'; import { Tooltip } from 'src/components/Tooltip'; import { FilterBarOrientation } from 'src/dashboard/types'; -import { truncationCSS } from 'src/hooks/useTruncation'; import { checkIsMissingRequiredValue } from '../utils'; import FilterValue from './FilterValue'; import { FilterCard } from '../../FilterCard'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterDivider.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterDivider.tsx index e06a56ac7b..6efe2c4515 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterDivider.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterDivider.tsx @@ -17,12 +17,16 @@ * under the License. */ -import { css, useTheme } from '@superset-ui/core'; +import { + css, + useTheme, + useCSSTextTruncation, + truncationCSS, +} from '@superset-ui/core'; import React from 'react'; import Icons from 'src/components/Icons'; import { Tooltip } from 'src/components/Tooltip'; import { FilterBarOrientation } from 'src/dashboard/types'; -import { useCSSTextTruncation, truncationCSS } from 'src/hooks/useTruncation'; import { FilterDividerProps } from './types'; const VerticalDivider = ({ title, description }: FilterDividerProps) => ( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx index d82c128bf8..5b2ce29326 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx @@ -27,9 +27,9 @@ import { DataMask, SLOW_DEBOUNCE, isNativeFilter, + usePrevious, } from '@superset-ui/core'; import { useHistory } from 'react-router-dom'; -import { usePrevious } from 'src/hooks/usePrevious'; import { updateDataMask, clearDataMask } from 'src/dataMask/actions'; import { useImmer } from 'use-immer'; import { isEmpty, isEqual, debounce } from 'lodash'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx index 0d0907a6eb..253ce4649d 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/DependenciesRow.tsx @@ -18,9 +18,8 @@ */ import React, { useCallback, useMemo, useRef } from 'react'; import { useDispatch } from 'react-redux'; -import { css, t, useTheme } from '@superset-ui/core'; +import { css, t, useTheme, useTruncation } from '@superset-ui/core'; import Icons from 'src/components/Icons'; -import { useTruncation } from 'src/hooks/useTruncation'; import { setDirectPathToChild } from 'src/dashboard/actions/dashboardState'; import { DependencyItem, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/NameRow.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/NameRow.tsx index 6f42b05e08..37f18eda29 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/NameRow.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/NameRow.tsx @@ -18,9 +18,8 @@ */ import React, { useRef } from 'react'; import { useSelector } from 'react-redux'; -import { css, SupersetTheme, useTheme } from '@superset-ui/core'; +import { css, SupersetTheme, useTheme, useTruncation } from '@superset-ui/core'; import Icons from 'src/components/Icons'; -import { useTruncation } from 'src/hooks/useTruncation'; import { RootState } from 'src/dashboard/types'; import { Row, FilterName, InternalRow } from './Styles'; import { FilterCardRowProps } from './types'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/ScopeRow.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/ScopeRow.tsx index 0c07040891..ff5c1142a5 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/ScopeRow.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterCard/ScopeRow.tsx @@ -17,8 +17,7 @@ * under the License. */ import React, { useMemo, useRef } from 'react'; -import { t } from '@superset-ui/core'; -import { useTruncation } from 'src/hooks/useTruncation'; +import { t, useTruncation } from '@superset-ui/core'; import { useFilterScope } from './useFilterScope'; import { Row, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx index 4fb2b21469..761817843b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx @@ -17,8 +17,7 @@ * under the License. */ import React, { useCallback, useState, useMemo, useEffect } from 'react'; -import { Column, ensureIsArray, t } from '@superset-ui/core'; -import { useChangeEffect } from 'src/hooks/useChangeEffect'; +import { Column, ensureIsArray, t, useChangeEffect } from '@superset-ui/core'; import { Select, FormInstance } from 'src/components'; import { useToasts } from 'src/components/MessageToasts/withToasts'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx index 059e202905..ce1a510e20 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx @@ -18,10 +18,14 @@ */ import React, { FC, useCallback, useState } from 'react'; -import { NativeFilterScope, styled, t } from '@superset-ui/core'; +import { + NativeFilterScope, + styled, + t, + useComponentDidUpdate, +} from '@superset-ui/core'; import { Radio } from 'src/components/Radio'; import { AntdForm, Typography } from 'src/components'; -import { useComponentDidUpdate } from 'src/hooks/useComponentDidUpdate/useComponentDidUpdate'; import { ScopingType } from './types'; import ScopingTree from './ScopingTree'; import { getDefaultScopeValue, isScopingAll } from './utils'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts index e9b9ec17c6..65c4af3b04 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts @@ -1,6 +1,5 @@ import { useEffect } from 'react'; -import { usePrevious } from 'src/hooks/usePrevious'; -import { NativeFilterType } from '@superset-ui/core'; +import { NativeFilterType, usePrevious } from '@superset-ui/core'; import { FilterRemoval } from './types'; /** diff --git a/superset-frontend/src/explore/components/Control.tsx b/superset-frontend/src/explore/components/Control.tsx index 5e202fdf10..b7a1587dd8 100644 --- a/superset-frontend/src/explore/components/Control.tsx +++ b/superset-frontend/src/explore/components/Control.tsx @@ -22,8 +22,12 @@ import { ControlType, ControlComponentProps as BaseControlComponentProps, } from '@superset-ui/chart-controls'; -import { styled, JsonValue, QueryFormData } from '@superset-ui/core'; -import { usePrevious } from 'src/hooks/usePrevious'; +import { + styled, + JsonValue, + QueryFormData, + usePrevious, +} from '@superset-ui/core'; import ErrorBoundary from 'src/components/ErrorBoundary'; import { ExploreActions } from 'src/explore/actions/exploreActions'; import controlMap from './controls'; diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx index 8a456619f4..7d0ceea50c 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx @@ -39,6 +39,7 @@ import { isDefined, JsonValue, NO_TIME_RANGE, + usePrevious, } from '@superset-ui/core'; import { ControlPanelSectionConfig, @@ -59,7 +60,6 @@ import { PluginContext } from 'src/components/DynamicPlugins'; import Loading from 'src/components/Loading'; import Modal from 'src/components/Modal'; -import { usePrevious } from 'src/hooks/usePrevious'; import { getSectionsToRender } from 'src/explore/controlUtils'; import { ExploreActions } from 'src/explore/actions/exploreActions'; import { ChartState, ExplorePageState } from 'src/explore/types'; diff --git a/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx b/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx index 66eed14a6c..0550ba2b29 100644 --- a/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx +++ b/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx @@ -21,15 +21,21 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -import { styled, t, css, useTheme, logging } from '@superset-ui/core'; +import { + styled, + t, + css, + useTheme, + logging, + useChangeEffect, + useComponentDidMount, + usePrevious, +} from '@superset-ui/core'; import { debounce, pick } from 'lodash'; import { Resizable } from 're-resizable'; -import { useChangeEffect } from 'src/hooks/useChangeEffect'; import { usePluginContext } from 'src/components/DynamicPlugins'; import { Global } from '@emotion/react'; import { Tooltip } from 'src/components/Tooltip'; -import { usePrevious } from 'src/hooks/usePrevious'; -import { useComponentDidMount } from 'src/hooks/useComponentDidMount'; import Icons from 'src/components/Icons'; import { getItem, diff --git a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx index 478a395448..8fb9b27453 100644 --- a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx +++ b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx @@ -17,10 +17,15 @@ * under the License. */ import React, { useCallback, useEffect, useState } from 'react'; -import { styled, css, t, useTheme } from '@superset-ui/core'; +import { + styled, + css, + t, + useTheme, + useComponentDidUpdate, +} from '@superset-ui/core'; import Icons from 'src/components/Icons'; import ControlHeader from 'src/explore/components/ControlHeader'; -import { useComponentDidUpdate } from 'src/hooks/useComponentDidUpdate'; import { FormattingPopover } from './FormattingPopover'; import { COMPARATOR, diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx index 55adbfe44e..a3d44eb570 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx +++ b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx @@ -24,6 +24,7 @@ import { useTheme, NO_TIME_RANGE, SupersetTheme, + useCSSTextTruncation, } from '@superset-ui/core'; import Button from 'src/components/Button'; import ControlHeader from 'src/explore/components/ControlHeader'; @@ -35,7 +36,6 @@ import { Tooltip } from 'src/components/Tooltip'; import { useDebouncedEffect } from 'src/explore/exploreUtils'; import { SLOW_DEBOUNCE } from 'src/constants'; import { noOp } from 'src/utils/common'; -import { useCSSTextTruncation } from 'src/hooks/useTruncation'; import ControlPopover from '../ControlPopover/ControlPopover'; import { DateFilterControlProps, FrameType } from './types'; diff --git a/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx b/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx index 617be7112b..62005910cb 100644 --- a/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx +++ b/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx @@ -18,7 +18,7 @@ */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; -import { ensureIsArray, t, useTheme } from '@superset-ui/core'; +import { ensureIsArray, t, useTheme, usePrevious } from '@superset-ui/core'; import { isEqual } from 'lodash'; import ControlHeader from 'src/explore/components/ControlHeader'; import Icons from 'src/components/Icons'; @@ -28,7 +28,6 @@ import { HeaderContainer, LabelsContainer, } from 'src/explore/components/controls/OptionControls'; -import { usePrevious } from 'src/hooks/usePrevious'; import columnType from './columnType'; import MetricDefinitionValue from './MetricDefinitionValue'; import AdhocMetric from './AdhocMetric';