mirror of
https://github.com/apache/superset.git
synced 2026-05-12 19:35:17 +00:00
chore: Upgrade to React 18 (#38563)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Evan Rusackas <evan@preset.io>
This commit is contained in:
committed by
GitHub
parent
28239c18d4
commit
41a22d7918
@@ -33,7 +33,7 @@
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -34,6 +34,6 @@
|
||||
"@apache-superset/core": "*",
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -36,6 +36,6 @@
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"@testing-library/jest-dom": "*",
|
||||
"@testing-library/react": "^12.1.5",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -39,6 +39,6 @@
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@apache-superset/core": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,6 @@
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"dayjs": "^1.11.19",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,14 +39,13 @@
|
||||
"@apache-superset/core": "*",
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@testing-library/dom": "^8.20.1",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/jest-dom": "*",
|
||||
"@testing-library/react": "^12.1.5",
|
||||
"@testing-library/react-hooks": "*",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "*",
|
||||
"@types/react": "*",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -247,7 +247,7 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
|
||||
[serverPagination, debouncedSearch, searchId],
|
||||
);
|
||||
|
||||
const handleColSort = (colId: string, sortDir: string) => {
|
||||
const handleColSort = (colId: string, sortDir: string | null) => {
|
||||
const isSortable = shouldSort({
|
||||
colId,
|
||||
sortDir,
|
||||
@@ -301,10 +301,12 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
|
||||
};
|
||||
|
||||
const handleColumnHeaderClick = useCallback(
|
||||
params => {
|
||||
(params: { column?: { colId?: string; sort?: string | null } }) => {
|
||||
const colId = params?.column?.colId;
|
||||
const sortDir = params?.column?.sort;
|
||||
handleColSort(colId, sortDir);
|
||||
if (colId && sortDir !== undefined) {
|
||||
handleColSort(colId, sortDir);
|
||||
}
|
||||
},
|
||||
[serverPagination, gridInitialState, percentMetrics, onSortChange],
|
||||
);
|
||||
|
||||
@@ -147,7 +147,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
|
||||
]);
|
||||
|
||||
const handleColumnStateChange = useCallback(
|
||||
agGridState => {
|
||||
(agGridState: Record<string, unknown>) => {
|
||||
if (onChartStateChange) {
|
||||
onChartStateChange(agGridState);
|
||||
}
|
||||
|
||||
@@ -70,5 +70,9 @@ export const TextCellRenderer = (params: CellRendererProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
return <div>{valueFormatted ?? value}</div>;
|
||||
return (
|
||||
<div>
|
||||
{valueFormatted ?? (value instanceof Date ? value.toISOString() : value)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ export const shouldSort = ({
|
||||
gridInitialState,
|
||||
}: {
|
||||
colId: string;
|
||||
sortDir: string;
|
||||
sortDir: string | null;
|
||||
percentMetrics: string[];
|
||||
serverPagination: boolean;
|
||||
gridInitialState: GridState;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { GenericDataType } from '@apache-superset/core/common';
|
||||
import {
|
||||
supersetTheme,
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"geostyler-wfs-parser": "^3.0.1",
|
||||
"ol": "^10.8.0",
|
||||
"polished": "*",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import Layer from 'ol/layer/Layer';
|
||||
import { FrameState } from 'ol/Map';
|
||||
import { apply as applyTransform } from 'ol/transform';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createRoot, Root } from 'react-dom/client';
|
||||
import { SupersetTheme } from '@apache-superset/core/theme';
|
||||
import { ChartConfig, ChartLayerOptions, ChartSizeValues } from '../types';
|
||||
import { createChartComponent } from '../util/chartUtil';
|
||||
@@ -31,7 +31,14 @@ import Loader from '../images/loading.gif';
|
||||
* Custom OpenLayers layer that displays charts on given locations.
|
||||
*/
|
||||
export class ChartLayer extends Layer {
|
||||
charts: any[] = [];
|
||||
charts: {
|
||||
htmlElement: HTMLDivElement;
|
||||
root: Root;
|
||||
coordinate: number[];
|
||||
width: number;
|
||||
height: number;
|
||||
feature: any;
|
||||
}[] = [];
|
||||
|
||||
chartConfigs: ChartConfig = {
|
||||
type: 'FeatureCollection',
|
||||
@@ -166,7 +173,7 @@ export class ChartLayer extends Layer {
|
||||
*/
|
||||
removeAllChartElements() {
|
||||
this.charts.forEach(chart => {
|
||||
ReactDOM.unmountComponentAtNode(chart.htmlElement);
|
||||
chart.root.unmount();
|
||||
chart.htmlElement.remove();
|
||||
});
|
||||
this.charts = [];
|
||||
@@ -191,10 +198,12 @@ export class ChartLayer extends Layer {
|
||||
this.theme,
|
||||
this.locale,
|
||||
);
|
||||
ReactDOM.render(chartComponent, container);
|
||||
const root = createRoot(container);
|
||||
root.render(chartComponent);
|
||||
|
||||
return {
|
||||
htmlElement: container,
|
||||
root,
|
||||
coordinate: getProjectedCoordinateFromPointGeoJson(feature.geometry),
|
||||
width: chartWidth,
|
||||
height: chartHeight,
|
||||
@@ -227,7 +236,7 @@ export class ChartLayer extends Layer {
|
||||
this.theme,
|
||||
this.locale,
|
||||
);
|
||||
ReactDOM.render(chartComponent, chart.htmlElement);
|
||||
chart.root.render(chartComponent);
|
||||
|
||||
return {
|
||||
...chart,
|
||||
|
||||
@@ -41,6 +41,11 @@ describe('ChartLayer', () => {
|
||||
chartLayer.charts = [
|
||||
{
|
||||
htmlElement: document.createElement('div'),
|
||||
root: { render: jest.fn(), unmount: jest.fn() } as any,
|
||||
coordinate: [0, 0],
|
||||
width: 100,
|
||||
height: 100,
|
||||
feature: {},
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"dayjs": "^1.11.19",
|
||||
"echarts": "*",
|
||||
"memoize-one": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function EchartsMixedTimeseries({
|
||||
);
|
||||
|
||||
const getCrossFilterDataMask = useCallback(
|
||||
(seriesName, seriesIndex) => {
|
||||
(seriesName: string, seriesIndex: number) => {
|
||||
const selected: string[] = Object.values(selectedValues || {});
|
||||
let values: string[];
|
||||
if (selected.includes(seriesName)) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
import { useCallback } from 'react';
|
||||
import Echart from '../components/Echart';
|
||||
import { NULL_STRING } from '../constants';
|
||||
import { EventHandlers } from '../types';
|
||||
import { EventHandlers, TreePathInfo } from '../types';
|
||||
import { extractTreePathInfo } from './constants';
|
||||
import { TreemapTransformedProps } from './types';
|
||||
import { formatSeriesName } from '../utils/series';
|
||||
@@ -46,7 +46,7 @@ export default function EchartsTreemap({
|
||||
coltypeMapping,
|
||||
}: TreemapTransformedProps) {
|
||||
const getCrossFilterDataMask = useCallback(
|
||||
(data, treePathInfo) => {
|
||||
(data: Record<string, unknown>, treePathInfo: TreePathInfo[]) => {
|
||||
if (data?.children) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ export default function EchartsTreemap({
|
||||
);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(data, treePathInfo) => {
|
||||
(data: Record<string, unknown>, treePathInfo: TreePathInfo[]) => {
|
||||
if (!emitCrossFilters || groupby.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@
|
||||
"handlebars": "^4.7.8",
|
||||
"lodash": "^4.18.1",
|
||||
"dayjs": "^1.11.19",
|
||||
"react": "^17.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-ace": "^10.1.0",
|
||||
"react-dom": "^17.0.2"
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^30.0.0",
|
||||
|
||||
@@ -45,10 +45,22 @@ const HandlebarsTemplateControl = (
|
||||
<div>
|
||||
<ControlHeader>
|
||||
<div>
|
||||
{props.label}
|
||||
{typeof props.label === 'function' ? null : props.label}
|
||||
<InfoTooltip
|
||||
iconStyle={{ marginLeft: theme.sizeUnit }}
|
||||
tooltip={<span>{t('See ')} <a href="https://superset.apache.org/docs/using-superset/handlebars-chart" target="_blank" rel="noopener noreferrer">{t('the Handlebars chart documentation')}</a> {t('for a list of available helpers.')}</span>}
|
||||
tooltip={
|
||||
<span>
|
||||
{t('See ')}{' '}
|
||||
<a
|
||||
href="https://superset.apache.org/docs/using-superset/handlebars-chart"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{t('the Handlebars chart documentation')}
|
||||
</a>{' '}
|
||||
{t('for a list of available helpers.')}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</ControlHeader>
|
||||
|
||||
@@ -49,7 +49,7 @@ const StyleControl = (props: CustomControlConfig<StyleCustomControlProps>) => {
|
||||
<div>
|
||||
<ControlHeader>
|
||||
<div>
|
||||
{props.label}
|
||||
{typeof props.label === 'function' ? null : props.label}
|
||||
{htmlSanitization && (
|
||||
<InfoTooltip
|
||||
iconStyle={{ marginLeft: theme.sizeUnit }}
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
"@superset-ui/core": "*",
|
||||
"lodash": "^4.18.1",
|
||||
"prop-types": "*",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.29.0",
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
"@apache-superset/core": "*",
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"react": "^17.0.2 || ^19.0.0",
|
||||
"react-dom": "^17.0.2 || ^19.0.0"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -39,15 +39,14 @@
|
||||
"@apache-superset/core": "*",
|
||||
"@superset-ui/chart-controls": "*",
|
||||
"@superset-ui/core": "*",
|
||||
"@testing-library/dom": "^8.20.1",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/jest-dom": "*",
|
||||
"@testing-library/react": "^12.1.5",
|
||||
"@testing-library/react-hooks": "*",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "*",
|
||||
"@types/react": "*",
|
||||
"match-sorter": "^8.2.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -533,7 +533,12 @@ export default function TableChart<D extends DataRecord = DataRecord>(
|
||||
// so that cross-filters work on the receiving chart
|
||||
const resolvedCol = columnLabelToNameMap[col] ?? col;
|
||||
const val = ensureIsArray(updatedFilters?.[col]);
|
||||
if (!val.length || val[0] === null || (val[0] instanceof DateWithFormatter && val[0].input === null))
|
||||
if (
|
||||
!val.length ||
|
||||
val[0] === null ||
|
||||
(val[0] instanceof DateWithFormatter &&
|
||||
val[0].input === null)
|
||||
)
|
||||
return {
|
||||
col: resolvedCol,
|
||||
op: 'IS NULL' as const,
|
||||
@@ -646,24 +651,22 @@ export default function TableChart<D extends DataRecord = DataRecord>(
|
||||
// DateWithFormatter objects wrap nulls, so we must check both
|
||||
if (
|
||||
dataRecordValue == null ||
|
||||
(dataRecordValue instanceof DateWithFormatter && dataRecordValue.input == null)
|
||||
(dataRecordValue instanceof DateWithFormatter &&
|
||||
dataRecordValue.input == null)
|
||||
) {
|
||||
drillToDetailFilters.push({
|
||||
col: col.key,
|
||||
op: 'IS NULL' as any,
|
||||
val: null,
|
||||
});
|
||||
|
||||
} else if (col.dataType === GenericDataType.Temporal && timeGrain) {
|
||||
const startTime =
|
||||
dataRecordValue instanceof Date
|
||||
? dataRecordValue
|
||||
: new Date(dataRecordValue as string | number);
|
||||
|
||||
const [rangeStartTime, rangeEndTime] = getTimeRangeFromGranularity(
|
||||
startTime,
|
||||
timeGrain,
|
||||
);
|
||||
const [rangeStartTime, rangeEndTime] =
|
||||
getTimeRangeFromGranularity(startTime, timeGrain);
|
||||
const timeRangeValue = `${rangeStartTime.toISOString()} : ${rangeEndTime.toISOString()}`;
|
||||
|
||||
drillToDetailFilters.push({
|
||||
@@ -696,7 +699,11 @@ export default function TableChart<D extends DataRecord = DataRecord>(
|
||||
filters: [
|
||||
{
|
||||
col: cellPoint.key,
|
||||
op: (cellPoint.value == null || (cellPoint.value instanceof DateWithFormatter && cellPoint.value.input == null) ? 'IS NULL' : '==') as any,
|
||||
op: (cellPoint.value == null ||
|
||||
(cellPoint.value instanceof DateWithFormatter &&
|
||||
cellPoint.value.input == null)
|
||||
? 'IS NULL'
|
||||
: '==') as any,
|
||||
val: extractTextFromHTML(cellPoint.value),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"@superset-ui/core": "*",
|
||||
"@types/lodash": "*",
|
||||
"@types/react": "*",
|
||||
"react": "^17.0.2"
|
||||
"react": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/d3-cloud": "^1.2.9"
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
"@superset-ui/core": "*",
|
||||
"dayjs": "^1.11.19",
|
||||
"mapbox-gl": ">=1.0.0",
|
||||
"react": "^17.0.2 || ^19.0.0",
|
||||
"react-dom": "^17.0.2 || ^19.0.0"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"mapbox-gl": {
|
||||
|
||||
@@ -139,7 +139,8 @@ const CategoricalDeckGLContainer = (props: CategoricalDeckGLContainerProps) => {
|
||||
const setTooltip = useCallback((tooltip: TooltipProps['tooltip']) => {
|
||||
const { current } = containerRef;
|
||||
if (current) {
|
||||
current.setTooltip(tooltip);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(current as any).setTooltip(tooltip);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -194,5 +194,5 @@ export const DeckGLContainerStyledWrapper = styled(DeckGLContainer)`
|
||||
`;
|
||||
|
||||
export type DeckGLContainerHandle = typeof DeckGLContainer & {
|
||||
setTooltip: (tooltip: ReactNode) => void;
|
||||
setTooltip: (tooltip: TooltipProps['tooltip']) => void;
|
||||
};
|
||||
|
||||
@@ -97,10 +97,10 @@ describe('getAggFunc', () => {
|
||||
});
|
||||
|
||||
describe('commonLayerProps', () => {
|
||||
const mockSetTooltip = jest.fn();
|
||||
const mockSetTooltip = jest.fn() as any;
|
||||
const mockSetTooltipContent = jest.fn(
|
||||
() => (o: JsonObject) => `Tooltip for ${o}`,
|
||||
);
|
||||
) as any;
|
||||
const mockOnSelect = jest.fn();
|
||||
|
||||
test('returns correct props when js_tooltip is provided', () => {
|
||||
|
||||
Reference in New Issue
Block a user