GitHub user user1500177 added a comment to the discussion: Superset Genral
Doubt version 6
@dosu , can u help me out ?
Hi @dosu ,
i have added a new echart completely called theme river (code as attached ;
apart fro mit i did make edit in the viztype , index.ts , Mainprest.js)
```
--- FILE: buildQuery.ts ---
import { buildQueryContext, getColumnLabel } from '@superset-ui/core';
import { ThemeRiverFormData } from './types';
export default function buildQuery(formData: ThemeRiverFormData) {
const { dateColumn, seriesColumn } = formData;
return buildQueryContext(formData, baseQueryObject => [
{
...baseQueryObject,
columns: [getColumnLabel(dateColumn), getColumnLabel(seriesColumn)],
},
]);
}
--- FILE: controlPanel.tsx ---
import { t, validateNonEmpty } from '@superset-ui/core';
import { ControlPanelConfig, sharedControls } from
'@superset-ui/chart-controls';
const requiredEntity = {
...sharedControls.entity,
clearable: false,
validators: [validateNonEmpty],
};
const config: ControlPanelConfig = {
controlPanelSections: [
{
label: t('Query'),
expanded: true,
controlSetRows: [
[
{
name: 'dateColumn',
config: {
...requiredEntity,
label: t('Date column'),
description: t('Time column used for the horizontal axis'),
},
},
],
[
{
name: 'seriesColumn',
config: {
...requiredEntity,
label: t('Series column'),
description: t(
'Column whose distinct values become the individual river
streams',
),
},
},
],
['metric'],
['adhoc_filters'],
['row_limit'],
],
},
{
label: t('Chart Options'),
expanded: true,
controlSetRows: [
['color_scheme'],
[
{
name: 'show_legend',
config: {
type: 'CheckboxControl',
label: t('Legend'),
renderTrigger: true,
default: true,
description: t('Whether to display the legend'),
},
},
],
],
},
],
};
export default config;
--- FILE: index.ts ---
import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
import buildQuery from './buildQuery';
import controlPanel from './controlPanel';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
import example1 from './images/example1.png';
const metadata = new ChartMetadata({
category: t('Trend'),
credits: ['https://echarts.apache.org'],
description: t(
'Displays how multiple categories evolve over time as flowing, ' +
'stacked streams. Useful for showing volume trends across ' +
'several groups at once.',
),
exampleGallery: [{ url: example1 }],
name: t('Theme River'),
tags: [t('ECharts'), t('Time'), t('Trend'), t('Stacked')],
thumbnail,
});
export default class EchartsThemeRiverChartPlugin extends ChartPlugin {
constructor() {
super({
buildQuery,
controlPanel,
loadChart: () => import('./ThemeRiver'),
metadata,
transformProps,
});
}
}
--- FILE: ThemeRiver.tsx ---
import { ThemeRiverTransformedProps } from './types';
import Echart from '../components/Echart';
export default function ThemeRiver(props: ThemeRiverTransformedProps) {
const { height, width, echartOptions, refs } = props;
return (
<Echart
refs={refs}
height={height}
width={width}
echartOptions={echartOptions}
/>
);
}
--- FILE: transformProps.ts ---
import {
CategoricalColorNamespace,
GenericDataType,
getColumnLabel,
getMetricLabel,
getTimeFormatter,
tooltipHtml, // Superset's shared tooltip HTML builder — used instead of
// a raw string formatter, same fix you called out for
candlestick
} from '@superset-ui/core';
import type { EChartsCoreOption } from 'echarts/core';
import type { ThemeRiverSeriesOption } from 'echarts/charts';
import { ThemeRiverChartProps, ThemeRiverTransformedProps } from './types';
import { getDefaultTooltip } from '../utils/tooltip';
import { getColtypesMapping } from '../utils/series';
import { Refs } from '../types';
// themeRiver's data format wants "YYYY/MM/DD" (per the official example),
// so we build a dedicated formatter for it rather than reusing the
// "YYYY-MM-DD" one from CalendarPie.
const dayFormatter = getTimeFormatter('%Y/%m/%d');
export default function transformProps(
chartProps: ThemeRiverChartProps,
): ThemeRiverTransformedProps {
const refs: Refs = {};
const { width, height, formData, queriesData } = chartProps;
const { dateColumn, seriesColumn, metric, colorScheme, showLegend } =
formData;
// Dashboards can mount this chart's container at a transient 0-size
// before the grid layout settles. Bail out with an empty option instead
// of handing ECharts a time axis / river layout with a zero-pixel box —
// same guard as CalendarPie, needed by any chart using a computed axis
// layout rather than a plain category axis.
if (!width || !height) {
return { refs, echartOptions: { series: [] }, width, height, formData };
}
const dateLabel = getColumnLabel(dateColumn);
const seriesLabel = getColumnLabel(seriesColumn);
const metricLabel = getMetricLabel(metric);
const data = queriesData[0].data || [];
const coltypeMapping = getColtypesMapping(queriesData[0]);
const dateColType = coltypeMapping[dateLabel];
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
// Same standard normalization used in CalendarPie: only trust epoch-based
// parsing when coltypes confirms the column is actually Temporal; never
// hand a raw un-normalized string straight to an ECharts time-based field.
const toDateString = (raw: unknown): string | null => {
if (raw === null || raw === undefined) {
return null;
}
if (dateColType === GenericDataType.Temporal) {
const epoch = typeof raw === 'string' ? Number.parseInt(raw, 10) : raw;
if (typeof epoch === 'number' && !Number.isNaN(epoch)) {
return dayFormatter(epoch);
}
}
return String(raw).split(' ')[0].split('T')[0].replaceAll('-', '/');
};
// themeRiver series data shape is a flat array of [date, value, seriesName]
// triples — build it directly from query rows.
const riverData: [string, number, string][] = [];
const seriesNames = new Set<string>();
data.forEach(row => {
const date = toDateString(row[dateLabel]);
if (!date) {
return; // skip rows with an unparseable date rather than breaking layout
}
const seriesName = String(row[seriesLabel]);
const value = Number(row[metricLabel]) || 0;
seriesNames.add(seriesName);
riverData.push([date, value, seriesName]);
});
const seriesList = [...seriesNames];
const series: ThemeRiverSeriesOption[] = [
{
type: 'themeRiver',
emphasis: {
itemStyle: { shadowBlur: 20, shadowColor: 'rgba(0, 0, 0, 0.8)' },
},
data: riverData,
color: seriesList.map(name => colorFn(name)),
},
];
const echartOptions: EChartsCoreOption = {
tooltip: {
...getDefaultTooltip(refs),
trigger: 'axis',
// themeRiver has exactly ONE echarts series containing every
// stream's points together, so `p.seriesName` is always the same
// generic value (hence "series0" for every row). The real stream
// name and value live inside each hovered point's own data tuple:
// [date, value, name]. We also drop any point whose value is 0,
// since axis-trigger tooltips otherwise list every stream at every
// timestamp even when a given stream had no data that day.
formatter: (params: any) => {
const arr = Array.isArray(params) ? params : [params];
const rows: [string, string][] = arr
.filter((p: any) => Number(p.value?.[1]) > 0)
.map((p: any) => [String(p.value?.[2] ?? ''), String(p.value?.[1] ??
'')]);
const title = arr[0]?.value?.[0] ?? '';
return tooltipHtml(rows, title);
},
},
legend: {
show: showLegend,
data: seriesList,
top: 15,
},
singleAxis: {
top: 50,
bottom: 50,
type: 'time',
axisPointer: { animation: true, label: { show: true } },
splitLine: { show: true, lineStyle: { type: 'dashed', opacity: 0.2 } },
},
series,
};
return {
refs,
echartOptions,
width,
height,
formData,
};
}
--- FILE: types.ts ---
import { QueryFormColumn, QueryFormData, QueryFormMetric } from
'@superset-ui/core';
import { BaseChartProps, BaseTransformedProps } from '../types';
// theme river needs: a date column (x axis, time-typed), a series/category
// column (the "DQ", "TY", "SS" streams), and a metric (the stream's value)
export interface ThemeRiverFormData extends QueryFormData {
dateColumn: QueryFormColumn;
seriesColumn: QueryFormColumn;
metric: QueryFormMetric;
colorScheme?: string;
showLegend?: boolean;
}
export interface ThemeRiverChartProps
extends BaseChartProps<ThemeRiverFormData> {
formData: ThemeRiverFormData;
}
// BaseTransformedProps already requires: refs, echartOptions, width,
// height, formData — this is the contract dashboards rely on, same as
// every other working chart (Heatmap, Histogram, Graph, CalendarPie).
export type ThemeRiverTransformedProps =
BaseTransformedProps<ThemeRiverFormData>;
```
ONE ISSUE I AM SEEING - Should i be adding something more - as at times if i
use these charts on dashboards they are not visible - but at times rarely they
are (like if i click on edit chart and then take dashboards all the charts like
themerive , calendar pie etc which i added will work but else NOT what is the
reason ? )
or the way by which i should have done
also can u tell me the reason for this:
return (
<Echart
refs={refs}
height={height}
width={width}
echartOptions={echartOptions}
eventHandlers={eventHandlers}
selectedValues={selectedValues}
/>
);
should i be retunrning more things from the chartname.tsx ?
what is the use of the event handlers which is one thign i missed on : also is
there any other data that i should have retrned from the chartname.tsx - could
ou in detial go on about hte use of each file and any concpet if i have missed
how to add them ?
GitHub link:
https://github.com/apache/superset/discussions/41663#discussioncomment-17796490
----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]