mirror of
https://github.com/apache/superset.git
synced 2026-04-24 18:44:53 +00:00
Co-authored-by: Fardin Mustaque <fardinmustaque@Fardins-Mac-mini.local>
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { PureComponent, MouseEvent } from 'react';
|
||||
import { PureComponent, MouseEvent, createRef } from 'react';
|
||||
import {
|
||||
t,
|
||||
getNumberFormatter,
|
||||
@@ -35,6 +35,7 @@ const defaultNumberFormatter = getNumberFormatter();
|
||||
|
||||
const PROPORTION = {
|
||||
// text size: proportion of the chart container sans trendline
|
||||
METRIC_NAME: 0.125,
|
||||
KICKER: 0.1,
|
||||
HEADER: 0.3,
|
||||
SUBHEADER: 0.125,
|
||||
@@ -42,13 +43,20 @@ const PROPORTION = {
|
||||
TRENDLINE: 0.3,
|
||||
};
|
||||
|
||||
class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
type BigNumberVisState = {
|
||||
elementsRendered: boolean;
|
||||
recalculateTrigger: boolean;
|
||||
};
|
||||
|
||||
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,
|
||||
@@ -58,6 +66,40 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
timeRangeFixed: false,
|
||||
};
|
||||
|
||||
// Create refs for each component to measure heights
|
||||
metricNameRef = createRef<HTMLDivElement>();
|
||||
|
||||
kickerRef = createRef<HTMLDivElement>();
|
||||
|
||||
headerRef = createRef<HTMLDivElement>();
|
||||
|
||||
subheaderRef = createRef<HTMLDivElement>();
|
||||
|
||||
subtitleRef = createRef<HTMLDivElement>();
|
||||
|
||||
state = {
|
||||
elementsRendered: false,
|
||||
recalculateTrigger: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
// Wait for elements to render and then calculate heights
|
||||
setTimeout(() => {
|
||||
this.setState({ elementsRendered: true });
|
||||
}, 0);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: BigNumberVizProps) {
|
||||
if (
|
||||
prevProps.height !== this.props.height ||
|
||||
prevProps.showTrendLine !== this.props.showTrendLine
|
||||
) {
|
||||
this.setState(prevState => ({
|
||||
recalculateTrigger: !prevState.recalculateTrigger,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
getClassName() {
|
||||
const { className, showTrendLine, bigNumberFallback } = this.props;
|
||||
const names = `superset-legacy-chart-big-number ${className} ${
|
||||
@@ -92,6 +134,37 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
);
|
||||
}
|
||||
|
||||
renderMetricName(maxHeight: number) {
|
||||
const { metricName, width, showMetricName } = this.props;
|
||||
if (!showMetricName || !metricName) return null;
|
||||
|
||||
const text = metricName;
|
||||
|
||||
const container = this.createTemporaryContainer();
|
||||
document.body.append(container);
|
||||
const fontSize = computeMaxFontSize({
|
||||
text,
|
||||
maxWidth: width,
|
||||
maxHeight,
|
||||
className: 'metric-name',
|
||||
container,
|
||||
});
|
||||
container.remove();
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.metricNameRef}
|
||||
className="metric-name"
|
||||
style={{
|
||||
fontSize,
|
||||
height: 'auto',
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderKicker(maxHeight: number) {
|
||||
const { timestamp, showTimestamp, formatTime, width } = this.props;
|
||||
if (
|
||||
@@ -118,6 +191,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.kickerRef}
|
||||
className="kicker"
|
||||
style={{
|
||||
fontSize,
|
||||
@@ -173,6 +247,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.headerRef}
|
||||
className="header-line"
|
||||
style={{
|
||||
display: 'flex',
|
||||
@@ -211,6 +286,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={this.subheaderRef}
|
||||
className="subheader-line"
|
||||
style={{
|
||||
fontSize,
|
||||
@@ -256,6 +332,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
ref={this.subtitleRef}
|
||||
className="subtitle-line subheader-line"
|
||||
style={{
|
||||
fontSize: `${fontSize}px`,
|
||||
@@ -316,6 +393,35 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
);
|
||||
}
|
||||
|
||||
getTotalElementsHeight() {
|
||||
const marginPerElement = 8; // theme.gridUnit = 4, so margin-bottom = 8px
|
||||
|
||||
const refs = [
|
||||
this.metricNameRef,
|
||||
this.kickerRef,
|
||||
this.headerRef,
|
||||
this.subheaderRef,
|
||||
this.subtitleRef,
|
||||
];
|
||||
|
||||
// Filter refs to only those with a current element
|
||||
const visibleRefs = refs.filter(ref => ref.current);
|
||||
|
||||
const totalHeight = visibleRefs.reduce((sum, ref, index) => {
|
||||
const height = ref.current?.offsetHeight || 0;
|
||||
const margin = index < visibleRefs.length - 1 ? marginPerElement : 0;
|
||||
return sum + height + margin;
|
||||
}, 0);
|
||||
|
||||
return totalHeight;
|
||||
}
|
||||
|
||||
shouldApplyOverflow(availableHeight: number) {
|
||||
if (!this.state.elementsRendered) return false;
|
||||
const totalHeight = this.getTotalElementsHeight();
|
||||
return totalHeight > availableHeight;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
showTrendLine,
|
||||
@@ -323,6 +429,7 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
kickerFontSize,
|
||||
headerFontSize,
|
||||
subtitleFontSize,
|
||||
metricNameFontSize,
|
||||
subheaderFontSize,
|
||||
} = this.props;
|
||||
const className = this.getClassName();
|
||||
@@ -330,11 +437,31 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
if (showTrendLine) {
|
||||
const chartHeight = Math.floor(PROPORTION.TRENDLINE * height);
|
||||
const allTextHeight = height - chartHeight;
|
||||
const shouldApplyOverflow = this.shouldApplyOverflow(allTextHeight);
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="text-container" style={{ height: allTextHeight }}>
|
||||
<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,
|
||||
@@ -356,16 +483,33 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const shouldApplyOverflow = this.shouldApplyOverflow(height);
|
||||
return (
|
||||
<div className={className} style={{ height }}>
|
||||
{this.renderFallbackWarning()}
|
||||
{this.renderKicker((kickerFontSize || 0) * height)}
|
||||
{this.renderHeader(Math.ceil(headerFontSize * height))}
|
||||
{this.rendermetricComparisonSummary(
|
||||
Math.ceil(subheaderFontSize * height),
|
||||
)}
|
||||
{this.renderSubtitle(Math.ceil(subtitleFontSize * height))}
|
||||
<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),
|
||||
)}
|
||||
{this.renderSubtitle(Math.ceil(subtitleFontSize * height))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -400,7 +544,12 @@ export default styled(BigNumberVis)`
|
||||
|
||||
.kicker {
|
||||
line-height: 1em;
|
||||
padding-bottom: 2em;
|
||||
margin-bottom: ${theme.gridUnit * 2}px;
|
||||
}
|
||||
|
||||
.metric-name {
|
||||
line-height: 1em;
|
||||
margin-bottom: ${theme.gridUnit * 2}px;
|
||||
}
|
||||
|
||||
.header-line {
|
||||
@@ -416,12 +565,12 @@ export default styled(BigNumberVis)`
|
||||
|
||||
.subheader-line {
|
||||
line-height: 1em;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: ${theme.gridUnit * 2}px;
|
||||
}
|
||||
|
||||
.subtitle-line {
|
||||
line-height: 1em;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: ${theme.gridUnit * 2}px;
|
||||
}
|
||||
|
||||
&.is-fallback-value {
|
||||
|
||||
Reference in New Issue
Block a user