mirror of
https://github.com/apache/superset.git
synced 2026-04-20 00:24:38 +00:00
feat: add a theme CRUD page to manage themes (#34182)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
This commit is contained in:
committed by
GitHub
parent
5f11f9097a
commit
e741a3167f
@@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { PureComponent, MouseEvent, createRef } from 'react';
|
||||
import { useState, useEffect, useRef, MouseEvent } from 'react';
|
||||
import {
|
||||
t,
|
||||
getNumberFormatter,
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
BRAND_COLOR,
|
||||
styled,
|
||||
BinaryQueryObjectFilterClause,
|
||||
themeObject,
|
||||
useTheme,
|
||||
} from '@superset-ui/core';
|
||||
import Echart from '../components/Echart';
|
||||
import { BigNumberVizProps } from './types';
|
||||
@@ -44,82 +44,68 @@ const PROPORTION = {
|
||||
TRENDLINE: 0.3,
|
||||
};
|
||||
|
||||
type BigNumberVisState = {
|
||||
elementsRendered: boolean;
|
||||
recalculateTrigger: boolean;
|
||||
};
|
||||
function BigNumberVis({
|
||||
className = '',
|
||||
headerFormatter = defaultNumberFormatter,
|
||||
formatTime = getTimeFormatter(SMART_DATE_VERBOSE_ID),
|
||||
headerFontSize = PROPORTION.HEADER,
|
||||
kickerFontSize = PROPORTION.KICKER,
|
||||
metricNameFontSize = PROPORTION.METRIC_NAME,
|
||||
showMetricName = true,
|
||||
mainColor = BRAND_COLOR,
|
||||
showTimestamp = false,
|
||||
showTrendLine = false,
|
||||
startYAxisAtZero = true,
|
||||
subheader = '',
|
||||
subheaderFontSize = PROPORTION.SUBHEADER,
|
||||
subtitleFontSize = PROPORTION.SUBHEADER,
|
||||
timeRangeFixed = false,
|
||||
...props
|
||||
}: BigNumberVizProps) {
|
||||
const theme = useTheme();
|
||||
|
||||
class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
static defaultProps = {
|
||||
className: '',
|
||||
headerFormatter: defaultNumberFormatter,
|
||||
formatTime: getTimeFormatter(SMART_DATE_VERBOSE_ID),
|
||||
headerFontSize: PROPORTION.HEADER,
|
||||
kickerFontSize: PROPORTION.KICKER,
|
||||
metricNameFontSize: PROPORTION.METRIC_NAME,
|
||||
showMetricName: true,
|
||||
mainColor: BRAND_COLOR,
|
||||
showTimestamp: false,
|
||||
showTrendLine: false,
|
||||
startYAxisAtZero: true,
|
||||
subheader: '',
|
||||
subheaderFontSize: PROPORTION.SUBHEADER,
|
||||
timeRangeFixed: false,
|
||||
};
|
||||
// Convert state to hooks
|
||||
const [elementsRendered, setElementsRendered] = useState(false);
|
||||
|
||||
// Create refs for each component to measure heights
|
||||
metricNameRef = createRef<HTMLDivElement>();
|
||||
const metricNameRef = useRef<HTMLDivElement>(null);
|
||||
const kickerRef = useRef<HTMLDivElement>(null);
|
||||
const headerRef = useRef<HTMLDivElement>(null);
|
||||
const subheaderRef = useRef<HTMLDivElement>(null);
|
||||
const subtitleRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
kickerRef = createRef<HTMLDivElement>();
|
||||
|
||||
headerRef = createRef<HTMLDivElement>();
|
||||
|
||||
subheaderRef = createRef<HTMLDivElement>();
|
||||
|
||||
subtitleRef = createRef<HTMLDivElement>();
|
||||
|
||||
state = {
|
||||
elementsRendered: false,
|
||||
recalculateTrigger: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
// Convert componentDidMount
|
||||
useEffect(() => {
|
||||
// Wait for elements to render and then calculate heights
|
||||
setTimeout(() => {
|
||||
this.setState({ elementsRendered: true });
|
||||
const timeout = setTimeout(() => {
|
||||
setElementsRendered(true);
|
||||
}, 0);
|
||||
}
|
||||
return () => clearTimeout(timeout);
|
||||
}, []);
|
||||
|
||||
componentDidUpdate(prevProps: BigNumberVizProps) {
|
||||
if (
|
||||
prevProps.height !== this.props.height ||
|
||||
prevProps.showTrendLine !== this.props.showTrendLine
|
||||
) {
|
||||
this.setState(prevState => ({
|
||||
recalculateTrigger: !prevState.recalculateTrigger,
|
||||
}));
|
||||
}
|
||||
}
|
||||
// Convert componentDidUpdate - trigger re-render when height or trendline changes
|
||||
useEffect(() => {
|
||||
// Re-render when height or showTrendLine changes
|
||||
}, [props.height, showTrendLine]);
|
||||
|
||||
getClassName() {
|
||||
const { className, showTrendLine, bigNumberFallback } = this.props;
|
||||
const getClassName = () => {
|
||||
const names = `superset-legacy-chart-big-number ${className} ${
|
||||
bigNumberFallback ? 'is-fallback-value' : ''
|
||||
props.bigNumberFallback ? 'is-fallback-value' : ''
|
||||
}`;
|
||||
if (showTrendLine) return names;
|
||||
return `${names} no-trendline`;
|
||||
}
|
||||
};
|
||||
|
||||
createTemporaryContainer() {
|
||||
const createTemporaryContainer = () => {
|
||||
const container = document.createElement('div');
|
||||
container.className = this.getClassName();
|
||||
container.className = getClassName();
|
||||
container.style.position = 'absolute'; // so it won't disrupt page layout
|
||||
container.style.opacity = '0'; // and not visible
|
||||
return container;
|
||||
}
|
||||
};
|
||||
|
||||
renderFallbackWarning() {
|
||||
const { bigNumberFallback, formatTime, showTimestamp } = this.props;
|
||||
const renderFallbackWarning = () => {
|
||||
const { bigNumberFallback } = props;
|
||||
if (!formatTime || !bigNumberFallback || showTimestamp) return null;
|
||||
return (
|
||||
<span
|
||||
@@ -133,15 +119,15 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
{t('Not up to date')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderMetricName(maxHeight: number) {
|
||||
const { metricName, width, showMetricName } = this.props;
|
||||
const renderMetricName = (maxHeight: number) => {
|
||||
const { metricName, width } = props;
|
||||
if (!showMetricName || !metricName) return null;
|
||||
|
||||
const text = metricName;
|
||||
|
||||
const container = this.createTemporaryContainer();
|
||||
const container = createTemporaryContainer();
|
||||
document.body.append(container);
|
||||
const fontSize = computeMaxFontSize({
|
||||
text,
|
||||
@@ -154,7 +140,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.metricNameRef}
|
||||
ref={metricNameRef}
|
||||
className="metric-name"
|
||||
style={{
|
||||
fontSize,
|
||||
@@ -164,10 +150,10 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderKicker(maxHeight: number) {
|
||||
const { timestamp, showTimestamp, formatTime, width } = this.props;
|
||||
const renderKicker = (maxHeight: number) => {
|
||||
const { timestamp, width } = props;
|
||||
if (
|
||||
!formatTime ||
|
||||
!showTimestamp ||
|
||||
@@ -179,7 +165,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
|
||||
const text = timestamp === null ? '' : formatTime(timestamp);
|
||||
|
||||
const container = this.createTemporaryContainer();
|
||||
const container = createTemporaryContainer();
|
||||
document.body.append(container);
|
||||
const fontSize = computeMaxFontSize({
|
||||
text,
|
||||
@@ -192,7 +178,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.kickerRef}
|
||||
ref={kickerRef}
|
||||
className="kicker"
|
||||
style={{
|
||||
fontSize,
|
||||
@@ -202,18 +188,16 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderHeader(maxHeight: number) {
|
||||
const { bigNumber, headerFormatter, width, colorThresholdFormatters } =
|
||||
this.props;
|
||||
const renderHeader = (maxHeight: number) => {
|
||||
const { bigNumber, width, colorThresholdFormatters, onContextMenu } = props;
|
||||
// @ts-ignore
|
||||
const text = bigNumber === null ? t('No data') : headerFormatter(bigNumber);
|
||||
|
||||
const hasThresholdColorFormatter =
|
||||
Array.isArray(colorThresholdFormatters) &&
|
||||
colorThresholdFormatters.length > 0;
|
||||
const { theme } = themeObject;
|
||||
|
||||
let numberColor;
|
||||
if (hasThresholdColorFormatter) {
|
||||
@@ -229,7 +213,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
numberColor = theme.colorText;
|
||||
}
|
||||
|
||||
const container = this.createTemporaryContainer();
|
||||
const container = createTemporaryContainer();
|
||||
document.body.append(container);
|
||||
const fontSize = computeMaxFontSize({
|
||||
text,
|
||||
@@ -240,16 +224,16 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
});
|
||||
container.remove();
|
||||
|
||||
const onContextMenu = (e: MouseEvent<HTMLDivElement>) => {
|
||||
if (this.props.onContextMenu) {
|
||||
const handleContextMenu = (e: MouseEvent<HTMLDivElement>) => {
|
||||
if (onContextMenu) {
|
||||
e.preventDefault();
|
||||
this.props.onContextMenu(e.nativeEvent.clientX, e.nativeEvent.clientY);
|
||||
onContextMenu(e.nativeEvent.clientX, e.nativeEvent.clientY);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.headerRef}
|
||||
ref={headerRef}
|
||||
className="header-line"
|
||||
style={{
|
||||
display: 'flex',
|
||||
@@ -258,21 +242,21 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
height: 'auto',
|
||||
color: numberColor,
|
||||
}}
|
||||
onContextMenu={onContextMenu}
|
||||
onContextMenu={handleContextMenu}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
rendermetricComparisonSummary(maxHeight: number) {
|
||||
const { subheader, width } = this.props;
|
||||
const rendermetricComparisonSummary = (maxHeight: number) => {
|
||||
const { width } = props;
|
||||
let fontSize = 0;
|
||||
|
||||
const text = subheader;
|
||||
|
||||
if (text) {
|
||||
const container = this.createTemporaryContainer();
|
||||
const container = createTemporaryContainer();
|
||||
document.body.append(container);
|
||||
try {
|
||||
fontSize = computeMaxFontSize({
|
||||
@@ -288,7 +272,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.subheaderRef}
|
||||
ref={subheaderRef}
|
||||
className="subheader-line"
|
||||
style={{
|
||||
fontSize,
|
||||
@@ -300,10 +284,10 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
renderSubtitle(maxHeight: number) {
|
||||
const { subtitle, width, bigNumber, bigNumberFallback } = this.props;
|
||||
const renderSubtitle = (maxHeight: number) => {
|
||||
const { subtitle, width, bigNumber, bigNumberFallback } = props;
|
||||
let fontSize = 0;
|
||||
|
||||
const NO_DATA_OR_HASNT_LANDED = t(
|
||||
@@ -320,7 +304,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
}
|
||||
|
||||
if (text) {
|
||||
const container = this.createTemporaryContainer();
|
||||
const container = createTemporaryContainer();
|
||||
document.body.append(container);
|
||||
fontSize = computeMaxFontSize({
|
||||
text,
|
||||
@@ -334,7 +318,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
ref={this.subtitleRef}
|
||||
ref={subtitleRef}
|
||||
className="subtitle-line subheader-line"
|
||||
style={{
|
||||
fontSize: `${fontSize}px`,
|
||||
@@ -347,10 +331,18 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
renderTrendline(maxHeight: number) {
|
||||
const { width, trendLineData, echartOptions, refs } = this.props;
|
||||
const renderTrendline = (maxHeight: number) => {
|
||||
const {
|
||||
width,
|
||||
trendLineData,
|
||||
echartOptions,
|
||||
refs,
|
||||
onContextMenu,
|
||||
formData,
|
||||
xValueFormatter,
|
||||
} = props;
|
||||
|
||||
// if can't find any non-null values, no point rendering the trendline
|
||||
if (!trendLineData?.some(d => d[1] !== null)) {
|
||||
@@ -359,24 +351,22 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
|
||||
const eventHandlers: EventHandlers = {
|
||||
contextmenu: eventParams => {
|
||||
if (this.props.onContextMenu) {
|
||||
if (onContextMenu) {
|
||||
eventParams.event.stop();
|
||||
const { data } = eventParams;
|
||||
if (data) {
|
||||
const pointerEvent = eventParams.event.event;
|
||||
const drillToDetailFilters: BinaryQueryObjectFilterClause[] = [];
|
||||
drillToDetailFilters.push({
|
||||
col: this.props.formData?.granularitySqla,
|
||||
grain: this.props.formData?.timeGrainSqla,
|
||||
col: formData?.granularitySqla,
|
||||
grain: formData?.timeGrainSqla,
|
||||
op: '==',
|
||||
val: data[0],
|
||||
formattedVal: this.props.xValueFormatter?.(data[0]),
|
||||
formattedVal: xValueFormatter?.(data[0]),
|
||||
});
|
||||
onContextMenu(pointerEvent.clientX, pointerEvent.clientY, {
|
||||
drillToDetail: drillToDetailFilters,
|
||||
});
|
||||
this.props.onContextMenu(
|
||||
pointerEvent.clientX,
|
||||
pointerEvent.clientY,
|
||||
{ drillToDetail: drillToDetailFilters },
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -393,17 +383,17 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
getTotalElementsHeight() {
|
||||
const getTotalElementsHeight = () => {
|
||||
const marginPerElement = 8; // theme.sizeUnit = 4, so margin-bottom = 8px
|
||||
|
||||
const refs = [
|
||||
this.metricNameRef,
|
||||
this.kickerRef,
|
||||
this.headerRef,
|
||||
this.subheaderRef,
|
||||
this.subtitleRef,
|
||||
metricNameRef,
|
||||
kickerRef,
|
||||
headerRef,
|
||||
subheaderRef,
|
||||
subtitleRef,
|
||||
];
|
||||
|
||||
// Filter refs to only those with a current element
|
||||
@@ -416,108 +406,94 @@ class BigNumberVis extends PureComponent<BigNumberVizProps, BigNumberVisState> {
|
||||
}, 0);
|
||||
|
||||
return totalHeight;
|
||||
}
|
||||
};
|
||||
|
||||
shouldApplyOverflow(availableHeight: number) {
|
||||
if (!this.state.elementsRendered) return false;
|
||||
const totalHeight = this.getTotalElementsHeight();
|
||||
const shouldApplyOverflow = (availableHeight: number) => {
|
||||
if (!elementsRendered) return false;
|
||||
const totalHeight = getTotalElementsHeight();
|
||||
return totalHeight > availableHeight;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
showTrendLine,
|
||||
height,
|
||||
kickerFontSize,
|
||||
headerFontSize,
|
||||
subtitleFontSize,
|
||||
metricNameFontSize,
|
||||
subheaderFontSize,
|
||||
} = this.props;
|
||||
const className = this.getClassName();
|
||||
const { height } = props;
|
||||
const componentClassName = getClassName();
|
||||
|
||||
if (showTrendLine) {
|
||||
const chartHeight = Math.floor(PROPORTION.TRENDLINE * height);
|
||||
const allTextHeight = height - chartHeight;
|
||||
const shouldApplyOverflow = this.shouldApplyOverflow(allTextHeight);
|
||||
if (showTrendLine) {
|
||||
const chartHeight = Math.floor(PROPORTION.TRENDLINE * height);
|
||||
const allTextHeight = height - chartHeight;
|
||||
const overflow = shouldApplyOverflow(allTextHeight);
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div
|
||||
className="text-container"
|
||||
style={{
|
||||
height: allTextHeight,
|
||||
...(shouldApplyOverflow
|
||||
? {
|
||||
display: 'block',
|
||||
boxSizing: 'border-box',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
width: '100%',
|
||||
}
|
||||
: {}),
|
||||
}}
|
||||
>
|
||||
{this.renderFallbackWarning()}
|
||||
{this.renderMetricName(
|
||||
Math.ceil(
|
||||
(metricNameFontSize || 0) * (1 - PROPORTION.TRENDLINE) * height,
|
||||
),
|
||||
)}
|
||||
{this.renderKicker(
|
||||
Math.ceil(
|
||||
(kickerFontSize || 0) * (1 - PROPORTION.TRENDLINE) * height,
|
||||
),
|
||||
)}
|
||||
{this.renderHeader(
|
||||
Math.ceil(headerFontSize * (1 - PROPORTION.TRENDLINE) * height),
|
||||
)}
|
||||
{this.rendermetricComparisonSummary(
|
||||
Math.ceil(
|
||||
subheaderFontSize * (1 - PROPORTION.TRENDLINE) * height,
|
||||
),
|
||||
)}
|
||||
{this.renderSubtitle(
|
||||
Math.ceil(subtitleFontSize * (1 - PROPORTION.TRENDLINE) * height),
|
||||
)}
|
||||
</div>
|
||||
{this.renderTrendline(chartHeight)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const shouldApplyOverflow = this.shouldApplyOverflow(height);
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={{
|
||||
height,
|
||||
...(shouldApplyOverflow
|
||||
? {
|
||||
display: 'block',
|
||||
boxSizing: 'border-box',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
width: '100%',
|
||||
}
|
||||
: {}),
|
||||
}}
|
||||
>
|
||||
<div className="text-container">
|
||||
{this.renderFallbackWarning()}
|
||||
{this.renderMetricName((metricNameFontSize || 0) * height)}
|
||||
{this.renderKicker((kickerFontSize || 0) * height)}
|
||||
{this.renderHeader(Math.ceil(headerFontSize * height))}
|
||||
{this.rendermetricComparisonSummary(
|
||||
Math.ceil(subheaderFontSize * height),
|
||||
<div className={componentClassName}>
|
||||
<div
|
||||
className="text-container"
|
||||
style={{
|
||||
height: allTextHeight,
|
||||
...(overflow
|
||||
? {
|
||||
display: 'block',
|
||||
boxSizing: 'border-box',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
width: '100%',
|
||||
}
|
||||
: {}),
|
||||
}}
|
||||
>
|
||||
{renderFallbackWarning()}
|
||||
{renderMetricName(
|
||||
Math.ceil(
|
||||
(metricNameFontSize || 0) * (1 - PROPORTION.TRENDLINE) * height,
|
||||
),
|
||||
)}
|
||||
{renderKicker(
|
||||
Math.ceil(
|
||||
(kickerFontSize || 0) * (1 - PROPORTION.TRENDLINE) * height,
|
||||
),
|
||||
)}
|
||||
{renderHeader(
|
||||
Math.ceil(headerFontSize * (1 - PROPORTION.TRENDLINE) * height),
|
||||
)}
|
||||
{rendermetricComparisonSummary(
|
||||
Math.ceil(subheaderFontSize * (1 - PROPORTION.TRENDLINE) * height),
|
||||
)}
|
||||
{renderSubtitle(
|
||||
Math.ceil(subtitleFontSize * (1 - PROPORTION.TRENDLINE) * height),
|
||||
)}
|
||||
{this.renderSubtitle(Math.ceil(subtitleFontSize * height))}
|
||||
</div>
|
||||
{renderTrendline(chartHeight)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const overflow = shouldApplyOverflow(height);
|
||||
return (
|
||||
<div
|
||||
className={componentClassName}
|
||||
style={{
|
||||
height,
|
||||
...(overflow
|
||||
? {
|
||||
display: 'block',
|
||||
boxSizing: 'border-box',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
width: '100%',
|
||||
}
|
||||
: {}),
|
||||
}}
|
||||
>
|
||||
<div className="text-container">
|
||||
{renderFallbackWarning()}
|
||||
{renderMetricName((metricNameFontSize || 0) * height)}
|
||||
{renderKicker((kickerFontSize || 0) * height)}
|
||||
{renderHeader(Math.ceil(headerFontSize * height))}
|
||||
{rendermetricComparisonSummary(Math.ceil(subheaderFontSize * height))}
|
||||
{renderSubtitle(Math.ceil(subtitleFontSize * height))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default styled(BigNumberVis)`
|
||||
const StyledBigNumberVis = styled(BigNumberVis)`
|
||||
${({ theme }) => `
|
||||
font-family: ${theme.fontFamily};
|
||||
position: relative;
|
||||
@@ -584,3 +560,5 @@ export default styled(BigNumberVis)`
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
export default StyledBigNumberVis;
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
getMetricLabel,
|
||||
getNumberFormatter,
|
||||
tooltipHtml,
|
||||
themeObject,
|
||||
} from '@superset-ui/core';
|
||||
import { SankeyChartProps, SankeyTransformedProps } from './types';
|
||||
import { Refs } from '../types';
|
||||
@@ -40,7 +39,7 @@ export default function transformProps(
|
||||
chartProps: SankeyChartProps,
|
||||
): SankeyTransformedProps {
|
||||
const refs: Refs = {};
|
||||
const { formData, height, hooks, queriesData, width } = chartProps;
|
||||
const { formData, height, hooks, queriesData, width, theme } = chartProps;
|
||||
const { onLegendStateChanged } = hooks;
|
||||
const { colorScheme, metric, source, target, sliceId } = formData;
|
||||
const { data } = queriesData[0];
|
||||
@@ -63,7 +62,6 @@ export default function transformProps(
|
||||
value,
|
||||
});
|
||||
});
|
||||
const { theme } = themeObject;
|
||||
|
||||
const seriesData: NonNullable<SankeySeriesOption['data']> = Array.from(
|
||||
set,
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
getMetricLabel,
|
||||
DataRecordValue,
|
||||
tooltipHtml,
|
||||
themeObject,
|
||||
} from '@superset-ui/core';
|
||||
import type { EChartsCoreOption } from 'echarts/core';
|
||||
import type { TreeSeriesOption } from 'echarts/charts';
|
||||
@@ -57,7 +56,7 @@ export function formatTooltip({
|
||||
export default function transformProps(
|
||||
chartProps: EchartsTreeChartProps,
|
||||
): TreeTransformedProps {
|
||||
const { width, height, formData, queriesData } = chartProps;
|
||||
const { width, height, formData, queriesData, theme } = chartProps;
|
||||
const refs: Refs = {};
|
||||
const data: TreeDataRecord[] = queriesData[0].data || [];
|
||||
|
||||
@@ -182,7 +181,6 @@ export default function transformProps(
|
||||
}
|
||||
});
|
||||
}
|
||||
const { theme } = themeObject;
|
||||
const series: TreeSeriesOption[] = [
|
||||
{
|
||||
type: 'tree',
|
||||
|
||||
@@ -31,7 +31,7 @@ import { merge } from 'lodash';
|
||||
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { styled, themeObject } from '@superset-ui/core';
|
||||
import { styled, useTheme } from '@superset-ui/core';
|
||||
import { use, init, EChartsType, registerLocale } from 'echarts/core';
|
||||
import {
|
||||
SankeyChart,
|
||||
@@ -122,45 +122,6 @@ const loadLocale = async (locale: string) => {
|
||||
return lang?.default;
|
||||
};
|
||||
|
||||
const getTheme = (options: any) => {
|
||||
const token = themeObject.theme;
|
||||
const theme = {
|
||||
textStyle: {
|
||||
color: token.colorText,
|
||||
fontFamily: token.fontFamily,
|
||||
},
|
||||
title: {
|
||||
textStyle: { color: token.colorText },
|
||||
},
|
||||
legend: {
|
||||
textStyle: { color: token.colorTextSecondary },
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: token.colorBgContainer,
|
||||
textStyle: { color: token.colorText },
|
||||
},
|
||||
axisPointer: {
|
||||
lineStyle: { color: token.colorPrimary },
|
||||
label: { color: token.colorText },
|
||||
},
|
||||
} as any;
|
||||
if (options?.xAxis) {
|
||||
theme.xAxis = {
|
||||
axisLine: { lineStyle: { color: token.colorSplit } },
|
||||
axisLabel: { color: token.colorTextSecondary },
|
||||
splitLine: { lineStyle: { color: token.colorSplit } },
|
||||
};
|
||||
}
|
||||
if (options?.yAxis) {
|
||||
theme.yAxis = {
|
||||
axisLine: { lineStyle: { color: token.colorSplit } },
|
||||
axisLabel: { color: token.colorTextSecondary },
|
||||
splitLine: { lineStyle: { color: token.colorSplit } },
|
||||
};
|
||||
}
|
||||
return theme;
|
||||
};
|
||||
|
||||
function Echart(
|
||||
{
|
||||
width,
|
||||
@@ -173,6 +134,7 @@ function Echart(
|
||||
}: EchartsProps,
|
||||
ref: Ref<EchartsHandler>,
|
||||
) {
|
||||
const theme = useTheme();
|
||||
const divRef = useRef<HTMLDivElement>(null);
|
||||
if (refs) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
@@ -228,9 +190,48 @@ function Echart(
|
||||
chartRef.current?.getZr().on(name, handler);
|
||||
});
|
||||
|
||||
const getEchartsTheme = (options: any) => {
|
||||
const antdTheme = theme;
|
||||
const echartsTheme = {
|
||||
textStyle: {
|
||||
color: antdTheme.colorText,
|
||||
fontFamily: antdTheme.fontFamily,
|
||||
},
|
||||
title: {
|
||||
textStyle: { color: antdTheme.colorText },
|
||||
},
|
||||
legend: {
|
||||
textStyle: { color: antdTheme.colorTextSecondary },
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: antdTheme.colorBgContainer,
|
||||
textStyle: { color: antdTheme.colorText },
|
||||
},
|
||||
axisPointer: {
|
||||
lineStyle: { color: antdTheme.colorPrimary },
|
||||
label: { color: antdTheme.colorText },
|
||||
},
|
||||
} as any;
|
||||
if (options?.xAxis) {
|
||||
echartsTheme.xAxis = {
|
||||
axisLine: { lineStyle: { color: antdTheme.colorSplit } },
|
||||
axisLabel: { color: antdTheme.colorTextSecondary },
|
||||
splitLine: { lineStyle: { color: antdTheme.colorSplit } },
|
||||
};
|
||||
}
|
||||
if (options?.yAxis) {
|
||||
echartsTheme.yAxis = {
|
||||
axisLine: { lineStyle: { color: antdTheme.colorSplit } },
|
||||
axisLabel: { color: antdTheme.colorTextSecondary },
|
||||
splitLine: { lineStyle: { color: antdTheme.colorSplit } },
|
||||
};
|
||||
}
|
||||
return echartsTheme;
|
||||
};
|
||||
|
||||
const themedEchartOptions = merge(
|
||||
{},
|
||||
getTheme(echartOptions),
|
||||
getEchartsTheme(echartOptions),
|
||||
echartOptions,
|
||||
);
|
||||
chartRef.current?.setOption(themedEchartOptions, true);
|
||||
@@ -238,7 +239,7 @@ function Echart(
|
||||
// did mount
|
||||
handleSizeChange({ width, height });
|
||||
}
|
||||
}, [didMount, echartOptions, eventHandlers, zrEventHandlers]);
|
||||
}, [didMount, echartOptions, eventHandlers, zrEventHandlers, theme]);
|
||||
|
||||
useEffect(() => () => chartRef.current?.dispose(), []);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user