codeant-ai-for-open-source[bot] commented on code in PR #37794:
URL: https://github.com/apache/superset/pull/37794#discussion_r3501315529
##########
superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx:
##########
@@ -125,455 +100,167 @@ function BigNumberVis({
const { metricName, width } = props;
if (!showMetricName || !metricName) return null;
- const text = metricName;
-
const container = createTemporaryContainer();
document.body.append(container);
+
const fontSize = computeMaxFontSize({
- text,
+ text: metricName,
maxWidth: width,
maxHeight,
className: 'metric-name',
container,
});
+
container.remove();
return (
- <div
- ref={metricNameRef}
- className="metric-name"
- style={{
- fontSize,
- height: 'auto',
- }}
- >
- {text}
+ <div ref={metricNameRef} className="metric-name" style={{ fontSize }}>
+ {metricName}
</div>
);
};
const renderKicker = (maxHeight: number) => {
const { timestamp, width } = props;
- if (
- !formatTime ||
- !showTimestamp ||
- typeof timestamp === 'string' ||
- typeof timestamp === 'bigint' ||
- typeof timestamp === 'boolean'
- )
- return null;
+ if (!formatTime || !showTimestamp || timestamp == null) return null;
- const text = timestamp === null ? '' : formatTime(timestamp);
+ const text = formatTime(timestamp as number | Date);
const container = createTemporaryContainer();
document.body.append(container);
+
const fontSize = computeMaxFontSize({
text,
maxWidth: width,
maxHeight,
className: 'kicker',
container,
});
+
container.remove();
return (
- <div
- ref={kickerRef}
- className="kicker"
- style={{
- fontSize,
- height: 'auto',
- }}
- >
+ <div ref={kickerRef} className="kicker" style={{ fontSize }}>
{text}
</div>
);
};
const renderHeader = (maxHeight: number) => {
- const { bigNumber, width, colorThresholdFormatters, onContextMenu } =
props;
- // Format bigNumber based on its type: null/undefined -> "No data", number
-> format, else -> string
- let text: string;
- if (bigNumber === null || bigNumber === undefined) {
- text = t('No data');
- } else if (typeof bigNumber === 'number') {
- text = headerFormatter(bigNumber);
- } else {
- // For string/boolean/Date values, convert to number if possible, else
show as string
- const numValue = Number(bigNumber);
- text = Number.isNaN(numValue)
- ? String(bigNumber)
- : headerFormatter(numValue);
- }
+ const { bigNumber, width } = props;
- const hasThresholdColorFormatter =
- Array.isArray(colorThresholdFormatters) &&
- colorThresholdFormatters.length > 0;
-
- let numberColor;
- if (hasThresholdColorFormatter) {
- colorThresholdFormatters!.forEach(formatter => {
- const formatterResult = bigNumber
- ? formatter.getColorFromValue(bigNumber as number)
- : false;
- if (formatterResult) {
- numberColor = formatterResult;
- }
- });
- } else {
- numberColor = theme.colorText;
- }
+ const text =
+ bigNumber == null
+ ? t('No data')
+ : typeof bigNumber === 'number'
+ ? headerFormatter(bigNumber)
+ : String(bigNumber);
const container = createTemporaryContainer();
document.body.append(container);
+
const fontSize = computeMaxFontSize({
text,
- maxWidth: width * 0.9, // reduced it's max width
+ maxWidth: width * 0.9,
maxHeight,
className: 'header-line',
container,
});
- container.remove();
- const handleContextMenu = (e: MouseEvent<HTMLDivElement>) => {
- if (onContextMenu) {
- e.preventDefault();
- onContextMenu(e.nativeEvent.clientX, e.nativeEvent.clientY);
- }
- };
+ container.remove();
return (
- <div
- ref={headerRef}
- className="header-line"
- style={{
- display: 'flex',
- alignItems: 'center',
- fontSize,
- height: 'auto',
- color: numberColor,
- }}
- onContextMenu={handleContextMenu}
- >
+ <div ref={headerRef} className="header-line" style={{ fontSize }}>
{text}
</div>
Review Comment:
**Suggestion:** The right-click drill-to-detail callback is no longer wired
to the rendered metric text, so context menus will not open for Big Number
values even though `onContextMenu` is still provided by `transformProps`. Add
an `onContextMenu` handler (prevent default + call the callback with cursor
coordinates and filters) on the clickable text container/header like before.
[api mismatch]
<details>
<summary><b>Severity Level:</b> Critical π¨</summary>
```mdx
- β Big Number drill-to-detail never calls plugin hook.
- β οΈ Right-click on metric text bypasses filters-aware context menu.
- β οΈ Behavior.DrillToDetail metadata unused for Big Number.
```
</details>
<details>
<summary><b>Steps of Reproduction β
</b></summary>
```mdx
1. Big Number viz props include an `onContextMenu` callback:
`BigNumberVizProps` in
`superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts:76-118`
defines an
optional `onContextMenu(clientX, clientY, filters?: ContextMenuFilters)`
field (lines
114-118), so the visual component is expected to invoke this when it wants
to open the
drill-to-detail context menu.
2. Both Big Number plugins wire the ChartRenderer hook into this prop: in
`BigNumberTotal/transformProps.ts:58-60,119-22`, the returned props object
includes
`onContextMenu` taken from `hooks` (line 58, then returned at line 15);
similarly
`BigNumberWithTrendline/transformProps.ts:64-75,166-188` returns
`onContextMenu:
hooks.onContextMenu` (line 187). These plugins are registered with
`Behavior.DrillToDetail` in `BigNumberTotal/index.ts:33-55` and
`BigNumberWithTrendline/index.ts:34-52`, so drill-to-detail relies on this
hook path.
3. The visual component `BigNumberVis` never uses this callback: in
`BigNumberViz.tsx:149-177` the header is rendered as
`return (` (line 172) followed by
`<div ref={headerRef} className="header-line" style={{ fontSize }}>` (line
173), `{text}`
(line 174), and `</div>` (line 175). A repo-wide grep for `onContextMenu` in
this file
returns no matches (`Grep` on `BigNumberViz.tsx`), so `props.onContextMenu`
is never bound
to the header or any other clickable element.
4. At runtime, ChartRenderer exposes the context-menu hook but the Big
Number viz does not
call it: `ChartRenderer` builds `hooks` with `onContextMenu` pointing to
`this.handleOnContextMenu` when `this.state.showContextMenu` is true
(`src/components/Chart/ChartRenderer.tsx:10-15`), and passes these hooks
into the plugin
via `SuperChart` props (`ChartRenderer.tsx:25-27, 56-58, 71-78, 525-37`).
Because
`BigNumberWithTrendline` and `BigNumberTotal` both pass this hook through to
`BigNumberViz`, but `BigNumberViz` never invokes it on the header or text
container,
right-clicking the main metric text will not trigger the plugin-specific
`onContextMenu`
callback. Instead only the generic fallback on the outer chart container
(`onContextMenuFallback` in `ChartRenderer.tsx:19-25, 515-39`) can fire, and
that path
explicitly calls `handleOnContextMenu(event.clientX, event.clientY)` with no
filters. As a
result, the intended drill-to-detail behavior for Big Number (which depends
on the viz
invoking `onContextMenu` with appropriate coordinates/filters) is
effectively broken for
the metric text element.
```
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=9125b2b782e9470abdae0a4bd74e9d06&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=9125b2b782e9470abdae0a4bd74e9d06&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent π€ </b></summary>
```mdx
This is a comment left during a code review.
**Path:**
superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx
**Line:** 173:175
**Comment:**
*Api Mismatch: The right-click drill-to-detail callback is no longer
wired to the rendered metric text, so context menus will not open for Big
Number values even though `onContextMenu` is still provided by
`transformProps`. Add an `onContextMenu` handler (prevent default + call the
callback with cursor coordinates and filters) on the clickable text
container/header like before.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37794&comment_hash=97cfaf72b24f27c9fa53ed262fc59a555e7793b58ac33d446528baed67bd2b0a&reaction=like'>π</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37794&comment_hash=97cfaf72b24f27c9fa53ed262fc59a555e7793b58ac33d446528baed67bd2b0a&reaction=dislike'>π</a>
##########
superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx:
##########
@@ -125,455 +100,167 @@ function BigNumberVis({
const { metricName, width } = props;
if (!showMetricName || !metricName) return null;
- const text = metricName;
-
const container = createTemporaryContainer();
document.body.append(container);
+
const fontSize = computeMaxFontSize({
- text,
+ text: metricName,
maxWidth: width,
maxHeight,
className: 'metric-name',
container,
});
+
container.remove();
return (
- <div
- ref={metricNameRef}
- className="metric-name"
- style={{
- fontSize,
- height: 'auto',
- }}
- >
- {text}
+ <div ref={metricNameRef} className="metric-name" style={{ fontSize }}>
+ {metricName}
</div>
);
};
const renderKicker = (maxHeight: number) => {
const { timestamp, width } = props;
- if (
- !formatTime ||
- !showTimestamp ||
- typeof timestamp === 'string' ||
- typeof timestamp === 'bigint' ||
- typeof timestamp === 'boolean'
- )
- return null;
+ if (!formatTime || !showTimestamp || timestamp == null) return null;
- const text = timestamp === null ? '' : formatTime(timestamp);
+ const text = formatTime(timestamp as number | Date);
const container = createTemporaryContainer();
document.body.append(container);
+
const fontSize = computeMaxFontSize({
text,
maxWidth: width,
maxHeight,
className: 'kicker',
container,
});
+
container.remove();
return (
- <div
- ref={kickerRef}
- className="kicker"
- style={{
- fontSize,
- height: 'auto',
- }}
- >
+ <div ref={kickerRef} className="kicker" style={{ fontSize }}>
{text}
</div>
);
};
const renderHeader = (maxHeight: number) => {
- const { bigNumber, width, colorThresholdFormatters, onContextMenu } =
props;
- // Format bigNumber based on its type: null/undefined -> "No data", number
-> format, else -> string
- let text: string;
- if (bigNumber === null || bigNumber === undefined) {
- text = t('No data');
- } else if (typeof bigNumber === 'number') {
- text = headerFormatter(bigNumber);
- } else {
- // For string/boolean/Date values, convert to number if possible, else
show as string
- const numValue = Number(bigNumber);
- text = Number.isNaN(numValue)
- ? String(bigNumber)
- : headerFormatter(numValue);
- }
+ const { bigNumber, width } = props;
- const hasThresholdColorFormatter =
- Array.isArray(colorThresholdFormatters) &&
- colorThresholdFormatters.length > 0;
-
- let numberColor;
- if (hasThresholdColorFormatter) {
- colorThresholdFormatters!.forEach(formatter => {
- const formatterResult = bigNumber
- ? formatter.getColorFromValue(bigNumber as number)
- : false;
- if (formatterResult) {
- numberColor = formatterResult;
- }
- });
- } else {
- numberColor = theme.colorText;
- }
+ const text =
+ bigNumber == null
+ ? t('No data')
+ : typeof bigNumber === 'number'
+ ? headerFormatter(bigNumber)
+ : String(bigNumber);
const container = createTemporaryContainer();
document.body.append(container);
+
const fontSize = computeMaxFontSize({
text,
- maxWidth: width * 0.9, // reduced it's max width
+ maxWidth: width * 0.9,
maxHeight,
className: 'header-line',
container,
});
- container.remove();
- const handleContextMenu = (e: MouseEvent<HTMLDivElement>) => {
- if (onContextMenu) {
- e.preventDefault();
- onContextMenu(e.nativeEvent.clientX, e.nativeEvent.clientY);
- }
- };
+ container.remove();
return (
- <div
- ref={headerRef}
- className="header-line"
- style={{
- display: 'flex',
- alignItems: 'center',
- fontSize,
- height: 'auto',
- color: numberColor,
- }}
- onContextMenu={handleContextMenu}
- >
+ <div ref={headerRef} className="header-line" style={{ fontSize }}>
{text}
</div>
);
};
- const rendermetricComparisonSummary = (maxHeight: number) => {
- const { width } = props;
- let fontSize = 0;
-
- const text = subheader;
-
- if (text) {
- const container = createTemporaryContainer();
- document.body.append(container);
- try {
- fontSize = computeMaxFontSize({
- text,
- maxWidth: width * 0.9,
- maxHeight,
- className: 'subheader-line',
- container,
- });
- } finally {
- container.remove();
- }
-
- return (
- <div
- ref={subheaderRef}
- className="subheader-line"
- style={{
- fontSize,
- height: maxHeight,
- }}
- >
- {text}
- </div>
- );
- }
- return null;
- };
-
- const renderSubtitle = (maxHeight: number) => {
- const { subtitle, width, bigNumber, bigNumberFallback } = props;
- let fontSize = 0;
-
- const NO_DATA_OR_HASNT_LANDED = t(
- 'No data after filtering or data is NULL for the latest time record',
- );
- const NO_DATA = t(
- 'Try applying different filters or ensuring your datasource has data',
- );
-
- let text = subtitle;
- if (bigNumber === null) {
- text =
- subtitle || (bigNumberFallback ? NO_DATA : NO_DATA_OR_HASNT_LANDED);
- }
-
- if (text) {
- const container = createTemporaryContainer();
- document.body.append(container);
- fontSize = computeMaxFontSize({
- text,
- maxWidth: width * 0.9,
- maxHeight,
- className: 'subtitle-line',
- container,
- });
- container.remove();
-
- return (
- <>
- <div
- ref={subtitleRef}
- className="subtitle-line subheader-line"
- style={{
- fontSize: `${fontSize}px`,
- height: maxHeight,
- }}
- >
- {text}
- </div>
- </>
- );
- }
- return null;
- };
-
- 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)) {
- return null;
- }
-
- const eventHandlers: EventHandlers = {
- contextmenu: eventParams => {
- if (onContextMenu) {
- eventParams.event.stop();
- const { data } = eventParams;
- if (data) {
- const pointerEvent = eventParams.event.event;
- const drillToDetailFilters: BinaryQueryObjectFilterClause[] = [];
- drillToDetailFilters.push({
- col:
- formData?.xAxis === DTTM_ALIAS
- ? formData?.granularitySqla
- : formData?.xAxis,
- grain: formData?.timeGrainSqla,
- op: '==',
- val: data[0],
- formattedVal: xValueFormatter?.(data[0]),
- });
- onContextMenu(pointerEvent.clientX, pointerEvent.clientY, {
- drillToDetail: drillToDetailFilters,
- });
- }
- }
- },
- };
-
- return (
- echartOptions && (
- <Echart
- refs={refs}
- width={Math.floor(width)}
- height={maxHeight}
- echartOptions={echartOptions}
- eventHandlers={eventHandlers}
- vizType={formData?.vizType}
- />
- )
- );
- };
-
- const getTotalElementsHeight = () => {
- const marginPerElement = 8; // theme.sizeUnit = 4, so margin-bottom = 8px
-
- const refs = [
- metricNameRef,
- kickerRef,
- headerRef,
- subheaderRef,
- subtitleRef,
- ];
-
- // Filter refs to only those with a current element
- const visibleRefs = refs.filter(ref => ref.current);
+ const renderSubheader = (maxHeight: number) =>
+ subheader ? (
+ <div
+ ref={subheaderRef}
+ className="subheader-line"
+ style={{ fontSize: `${maxHeight}px` }}
+ >
+ {subheader}
+ </div>
+ ) : null;
- 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);
+ const renderSubtitle = (maxHeight: number) =>
+ props.subtitle ? (
+ <div
+ ref={subtitleRef}
+ className="subtitle-line"
+ style={{ fontSize: `${maxHeight}px` }}
+ >
+ {props.subtitle}
+ </div>
+ ) : null;
- return totalHeight;
- };
+ const { height } = props;
- const shouldApplyOverflow = (availableHeight: number) => {
- if (!elementsRendered) return false;
- const totalHeight = getTotalElementsHeight();
- return totalHeight > availableHeight;
+ const alignmentStyles = {
+ alignItems:
+ alignment === 'center'
+ ? 'center'
+ : alignment === 'right'
+ ? 'flex-end'
+ : 'flex-start',
+ textAlign: alignment as 'left' | 'center' | 'right',
};
- const { height } = props;
- const componentClassName = getClassName();
-
if (showTrendLine) {
const chartHeight = Math.floor(PROPORTION.TRENDLINE * height);
const allTextHeight = height - chartHeight;
- const overflow = shouldApplyOverflow(allTextHeight);
return (
- <div className={componentClassName}>
+ <div className={getClassName()}>
<div
className="text-container"
- style={{
- height: allTextHeight,
- ...(overflow
- ? {
- display: 'block',
- boxSizing: 'border-box',
- overflowX: 'hidden',
- overflowY: 'auto',
- width: '100%',
- }
- : {}),
- }}
+ style={{ height: allTextHeight, ...alignmentStyles }}
>
{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),
- )}
+ {renderMetricName(metricNameFontSize * height)}
+ {renderKicker(kickerFontSize * height)}
+ {renderHeader(headerFontSize * height)}
+ {renderSubheader(subheaderFontSize * height)}
+ {renderSubtitle(subtitleFontSize * height)}
Review Comment:
**Suggestion:** In the trendline layout, text font sizing is still computed
against full chart height instead of the reduced text area height
(`allTextHeight`), which can oversize text and cause clipping/overlap when the
trendline is shown. Use the text container height for these calculations in
this branch. [logic error]
<details>
<summary><b>Severity Level:</b> Major β οΈ</summary>
```mdx
- β οΈ Trendline Big Number text can overlap or be clipped.
- β οΈ Default KPI layout mis-sizes text in trendline mode.
- β οΈ Visual regressions in Big Number with Trendline.
```
</details>
<details>
<summary><b>Steps of Reproduction β
</b></summary>
```mdx
1. The Big Number with Trendline transform computes font-size proportions
relative to the
overall chart `height`: `BigNumberWithTrendline/transformProps.ts:77-94`
reads
`headerFontSize`, `metricNameFontSize`, `subtitleFontSize`, and
`subheaderFontSize` from
`formData`, which are configured via shared font-size controls in
`sharedControls.ts:59-80` with defaults like `headerFontSize` 0.4,
`subtitleFontSize`
0.15, `subheaderFontSize` 0.15, and `metricNameFontSize` 0.15. The transform
then returns
these values unscaled as part of `BigNumberVizProps`
(`transformProps.ts:166-179`).
2. In the viz component, the trendline layout explicitly reduces the text
area height:
`BigNumberViz.tsx:213-216` checks `if (showTrendLine)` and computes `const
chartHeight =
Math.floor(PROPORTION.TRENDLINE * height);` and `const allTextHeight =
height -
chartHeight;`. The text container `div` inside this branch
(`BigNumberViz.tsx:219-221`) is
rendered with `style={{ height: allTextHeight, ...alignmentStyles }}`, so
the vertical
space available for the big-number text is `allTextHeight`, not the full
`height`.
3. Despite that reduced text area, font sizing for each text line still
multiplies by the
full `height`: inside the same `showTrendLine` branch, the component calls
the text render
helpers as `{renderMetricName(metricNameFontSize * height)}`,
`{renderKicker(kickerFontSize * height)}`, `{renderHeader(headerFontSize *
height)}`,
`{renderSubheader(subheaderFontSize * height)}`, and
`{renderSubtitle(subtitleFontSize *
height)}` (`BigNumberViz.tsx:223-228`). These values are passed as the
`maxHeight`
argument into `computeMaxFontSize` in `renderMetricName`, `renderKicker`, and
`renderHeader` (`BigNumberViz.tsx:99-113, 123-138, 149-168`), determining
each lineβs font
size.
4. With the default Big Number font controls and trendline enabled, the
summed per-line
heights exceed the available text container: using the defaults from
`sharedControls.ts`
(header 0.4, subtitle 0.15, subheader 0.15, metric name 0.15), the total
proportion used
for text becomes roughly `0.4 + 0.15 + 0.15 + 0.15 = 0.85` of the full chart
`height`,
while `allTextHeight` is `height - PROPORTION.TRENDLINE * height = 0.7 *
height`
(`PROPORTION.TRENDLINE` is 0.3 in `BigNumberViz.tsx:34-40`). Because the
helper calls
still multiply by `height`, text lines are sized for up to `0.85 * height`
of stacked
vertical space but are forced into a container only `0.7 * height` tall,
leading to
clipping or overlap when the trendline is shown. Using `allTextHeight`
instead (e.g.,
`metricNameFontSize * allTextHeight`) would align font sizing with the
actual text
container height and prevent this overflow.
```
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=015662662ba34283ad871e5edb8d9d9f&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=015662662ba34283ad871e5edb8d9d9f&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent π€ </b></summary>
```mdx
This is a comment left during a code review.
**Path:**
superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx
**Line:** 224:228
**Comment:**
*Logic Error: In the trendline layout, text font sizing is still
computed against full chart height instead of the reduced text area height
(`allTextHeight`), which can oversize text and cause clipping/overlap when the
trendline is shown. Use the text container height for these calculations in
this branch.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37794&comment_hash=865198124228a79800b9dbd1dfadfeb5c471e298f9d0f1607b51b7323a7a74be&reaction=like'>π</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37794&comment_hash=865198124228a79800b9dbd1dfadfeb5c471e298f9d0f1607b51b7323a7a74be&reaction=dislike'>π</a>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]