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]

Reply via email to