From 7e7cb076d3b6e7229ab2457eb1676c0b2b008c14 Mon Sep 17 00:00:00 2001 From: Cory Loken Date: Tue, 17 Sep 2024 17:54:33 -0400 Subject: [PATCH] Add more types or turn off checker for later work --- .../src/components/chart/bar.gts | 1 + .../src/components/chart/pie.gts | 1 + .../src/modifiers/bar-chart.ts | 124 ++++++++++--- .../src/modifiers/graph-chart.ts | 5 + .../src/modifiers/tree-chart.ts | 171 +++++++++++------- .../src/utils/chart/parse-axis-label.ts | 2 +- .../src/utils/create-lookup.ts | 2 +- .../src/utils/data/compute-statistic.ts | 9 +- .../src/utils/data/get-series-data.ts | 7 +- .../src/utils/data/get-series-totals.ts | 12 +- .../utils/data/get-unique-dataset-values.ts | 6 +- .../src/utils/data/rotate-data-series.ts | 6 +- .../src/utils/layout/compute-inner-box.ts | 1 + .../utils/layout/compute-max-text-metrics.ts | 3 +- .../src/utils/layout/compute-text-height.ts | 1 + .../src/utils/layout/layout-cells.ts | 9 +- ember-apache-echarts/src/utils/merge-at.ts | 6 +- .../src/utils/on-element-resize.ts | 2 +- .../src/utils/style/format-css-style-value.ts | 6 +- .../app/components/chart-graph-example.js | 2 - test-app/app/components/chart-tree-example.js | 4 - 21 files changed, 265 insertions(+), 115 deletions(-) diff --git a/ember-apache-echarts/src/components/chart/bar.gts b/ember-apache-echarts/src/components/chart/bar.gts index 1ce6924fd..edeb6e881 100644 --- a/ember-apache-echarts/src/components/chart/bar.gts +++ b/ember-apache-echarts/src/components/chart/bar.gts @@ -1,3 +1,4 @@ +// @ts-nocheck import { action } from '@ember/object'; import { htmlSafe } from '@ember/template'; import { or } from 'ember-truth-helpers'; diff --git a/ember-apache-echarts/src/components/chart/pie.gts b/ember-apache-echarts/src/components/chart/pie.gts index 774c4d6db..e98372446 100644 --- a/ember-apache-echarts/src/components/chart/pie.gts +++ b/ember-apache-echarts/src/components/chart/pie.gts @@ -1,3 +1,4 @@ +// @ts-nocheck import { pick } from 'lodash-es'; import { action } from '@ember/object'; import Component from '@glimmer/component'; diff --git a/ember-apache-echarts/src/modifiers/bar-chart.ts b/ember-apache-echarts/src/modifiers/bar-chart.ts index c50110290..f40fd675f 100644 --- a/ember-apache-echarts/src/modifiers/bar-chart.ts +++ b/ember-apache-echarts/src/modifiers/bar-chart.ts @@ -1,7 +1,6 @@ import { tracked } from '@glimmer/tracking'; -import { compact } from 'lodash-es'; -import { countBy } from 'lodash-es'; -import { flatten } from 'lodash-es'; +// @ts-expect-error +import { compact, countBy, flatten } from 'lodash-es'; import * as echarts from 'echarts'; import mergeAtPaths from '../utils/merge-at-paths.ts'; import parseAxisLabel from '../utils/chart/parse-axis-label.ts'; @@ -14,13 +13,24 @@ import computeMaxTextMetrics from '../utils/layout/compute-max-text-metrics.ts'; import computeTextMetrics from '../utils/layout/compute-text-metrics.ts'; import resolveStyle from '../utils/style/resolve-style.ts'; import AbstractChartModifier from './abstract-chart.ts'; +import type { ECharts, SelectChangedPayload } from 'echarts'; + +type Variant = 'bar' | 'line' | 'area' | 'groupedBar' | 'groupedLine' | 'stackedBar' | 'stackedArea'; + +type AxisConfig = { + type: string; + axisLabel?: { + showMinLabel?: boolean; + showMaxLabel?: boolean; + }; +}; const DEFAULT_CATEGORY_PROPERTY = 'name'; const DEFAULT_VALUE_PROPERTY = 'value'; // TODO: Import only the required components to keep the bundle size small. See // https://echarts.apache.org/handbook/en/basics/import/ [twl 6.Apr.22] - +// @ts-expect-error const setItemColor = (colorMap, item, color) => !colorMap?.[color] ? item @@ -31,23 +41,44 @@ const setItemColor = (colorMap, item, color) => }, }; -const isShowingAxisLabel = (axisConfig, labelType) => +const isShowingAxisLabel = (axisConfig: AxisConfig, labelType: 'Min' | 'Max') => axisConfig.axisLabel?.[`show${labelType}Label`] === false || (axisConfig.type === 'time' && axisConfig.axisLabel?.[`show${labelType}Label`] !== true); - +// @ts-expect-error const computeData = (data, categories, args) => { const { categoryProperty = DEFAULT_CATEGORY_PROPERTY } = args; const { categoryAxisType, orientation } = args; + // @ts-expect-error - not sure what the 4th arg should be const series = getSeriesData(data, categories, categoryProperty); return categoryAxisType !== 'time' ? series + // @ts-expect-error : series.map((item) => ({ ...item, value: orientation === 'horizontal' ? [item.value, item.name] : [item.name, item.value], })); }; +type ChartArgs = { + tooltipFormatter?: (params: unknown) => string; + onSelect?: (name: string | null) => void; + data: unknown[]; + series?: unknown[]; + rotateData?: boolean; + categoryProperty?: string; + valueProperty?: string; + variant?: Variant; + categoryAxisScale?: 'shared' | 'separate'; + valueAxisScale?: 'shared' | 'separate'; + categoryAxisType?: 'category' | 'time'; + categoryAxisSort?: 'firstSeries' | 'asc' | 'desc' | ((a: string, b: string) => number); + missingCategoryFormat?: string; + missingValueFormat?: string; + drillUpButtonText?: string; + title?: string; +}; + /** * Renders one or more bar charts. * @@ -321,25 +352,26 @@ export default class BarChartModifier extends AbstractChartModifier { }; } - isGroupedVariant(variant) { + isGroupedVariant(variant: Variant) { return ['groupedBar', 'groupedLine'].includes(variant); } - isStackedVariant(variant) { + isStackedVariant(variant: Variant) { return ['stackedArea', 'stackedBar'].includes(variant); } - isBarVariant(variant) { + isBarVariant(variant: Variant) { return ['bar', 'groupedBar', 'stackedBar'].includes(variant ?? 'bar'); } - isAreaVariant(variant) { + isAreaVariant(variant: Variant) { return ['area', 'stackedArea'].includes(variant); } /** * Returns the categories used within the data series in render order. */ + // @ts-expect-error getCategories(args, series) { const { categoryAxisSort = 'firstSeries', categoryAxisType } = args; const { categoryProperty = DEFAULT_CATEGORY_PROPERTY } = args; @@ -366,6 +398,7 @@ export default class BarChartModifier extends AbstractChartModifier { * Formats the `name` and `value` within `params` when a category or value * formatter are defined, respectively. */ + // @ts-expect-error formatTooltipParams(args, params, elementType) { const { valueAxisFormatter = echarts.format.addCommas } = args; const { categoryAxisType, categoryAxisFormatter, orientation } = args; @@ -397,7 +430,7 @@ export default class BarChartModifier extends AbstractChartModifier { }; } - configureChart(args, chart) { + configureChart(args: ChartArgs, chart: ECharts) { const allSeries = args.series ?? [{ data: args.data }]; const { categoryAxisScale, tooltipFormatter, onSelect } = args; const { config, context } = this.buildLayout(args, chart); @@ -408,11 +441,12 @@ export default class BarChartModifier extends AbstractChartModifier { tooltip: { trigger: 'item', ...(tooltipFormatter && { - formatter: (params) => + formatter: (params: unknown[]) => tooltipFormatter( params.length != null ? params.map((param) => this.formatTooltipParams(args, param, 'axisTooltip')) : this.formatTooltipParams(args, params, 'itemTooltip'), + // @ts-expect-error context.data.dataset ), }), @@ -423,23 +457,26 @@ export default class BarChartModifier extends AbstractChartModifier { } ); - chart.handle('selectchanged', (event) => { - const { fromAction, fromActionPayload, isFromClick } = event; + chart.on('selectchanged', (event) => { + const { fromAction, fromActionPayload, isFromClick } = event as SelectChangedPayload; if (!isFromClick) { return; } - const seriesIndex = fromActionPayload.seriesIndex; - const dataIndex = fromActionPayload.dataIndexInside; + const seriesIndex = fromActionPayload['seriesIndex']; + const dataIndex = fromActionPayload['dataIndexInside']; const series = allSeries[seriesIndex]; // NOTE: `dataIndex` isn't actually the data index. It's the index of the // category on the X axis. Thus we need to look up the value based // on how the axis is being rendered. [twl 20.Jul.22] const name = categoryAxisScale === 'shared' + // @ts-expect-error: until the abstract is typed this needs to wait ? context.data.categories[dataIndex] + // @ts-expect-error: TypeScript doesn't know about the structure of `series.data` : series.data[dataIndex] + // @ts-expect-error: TypeScript doesn't know about the structure of `series.data` ? series.data[dataIndex][args.categoryProperty ?? DEFAULT_CATEGORY_PROPERTY] : null; @@ -454,7 +491,8 @@ export default class BarChartModifier extends AbstractChartModifier { }); // Change the default behavior of how selections work on the legend - chart.handle('legendselectchanged', ({ name, selected }) => { + // @ts-expect-error + chart.on('legendselectchanged', ({ name, selected }) => { const selections = Object.values(selected); const counts = countBy(selections); @@ -468,8 +506,10 @@ export default class BarChartModifier extends AbstractChartModifier { }); // Handle the drill in action - chart.handle('dblclick', ({ seriesIndex }) => { + chart.on('dblclick', ({ seriesIndex }) => { + // @ts-expect-error if (context.data.dataset[seriesIndex].series) { + // @ts-expect-error this.drillPath.pushObject(seriesIndex); } }); @@ -478,8 +518,9 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Generates the `data` section of the context used to construct this chart. */ - createContextData(args, chart) { - const context = super.createContextData(args, chart); + // @ts-expect-error + createContextData(args, chart: ECharts) { + const context = super.createContextData(args); const { rotateData, categoryAxisScale, valueAxisScale } = args; const { categoryProperty = DEFAULT_CATEGORY_PROPERTY } = args; const { valueProperty = DEFAULT_VALUE_PROPERTY } = args; @@ -518,6 +559,7 @@ export default class BarChartModifier extends AbstractChartModifier { * Adds the title to `config` as defined in the data or by `args` and returns * the new context layout. */ + // @ts-expect-error addTitle(context, config) { const buttonLayout = this.addDrillUpButton(context, config); const buttonWidth = context.layout.width - buttonLayout.width; @@ -556,6 +598,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Adds the drill up button to `config` and returns the new context layout. */ + // @ts-expect-error addDrillUpButton(context, config) { if (!this.drillPath.length) { return context.layout; @@ -575,22 +618,23 @@ export default class BarChartModifier extends AbstractChartModifier { const buttonConfig = this.generateDrillUpButtonConfig(drillUpButtonText, layout, style); mergeAtPaths(config, [buttonConfig]); - + // @ts-expect-error const buttonBox = buttonConfig['graphic.elements'][0].children[0].shape; return { ...layout, - width: layout.width - buttonBox.width - xMargins, - height: layout.height - buttonBox.height - yMargins, - x: layout.x + buttonBox.width + xMargins, - y: layout.y + buttonBox.height + yMargins, + width: layout.width - (buttonBox?.width ?? 0) - xMargins, + height: layout.height - (buttonBox?.height ?? 0) - yMargins, + x: layout.x + (buttonBox?.width ?? 0) + xMargins, + y: layout.y + (buttonBox?.height ?? 0) + yMargins }; } /** * Generates the configuration for the drill up button. */ - generateDrillUpButtonConfig(text, layout, style) { + // @ts-expect-error + generateDrillUpButtonConfig(text: string, layout, style) { const textMetrics = computeTextMetrics(text, style); return { @@ -634,6 +678,7 @@ export default class BarChartModifier extends AbstractChartModifier { }, }, ], + // @ts-expect-error onclick: () => this.drillPath.popObject(), }, ], @@ -643,18 +688,21 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Returns the labels for the legend. */ + // @ts-expect-error getLegendLabels(series, args) { if (!this.isStackedVariant(args.variant) && !this.isGroupedVariant(args.variant)) { return super.getLegendLabels(series, args); } // Grouped and stacked datasets may have a dummy root node + // @ts-expect-error return series[0].data.map((info) => info.label ?? info.name); } /** * Calculate the categories and range used for the category axis. */ + // @ts-expect-error computeCategoryInfo(series, context) { const { args, data } = context; const { variant, categoryAxisScale } = args; @@ -674,6 +722,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Calculate the values and stats used for the value axis. */ + // @ts-expect-error computeValueInfo(series, context, categories) { const { args, data } = context; const { variant, valueAxisScale } = args; @@ -688,6 +737,7 @@ export default class BarChartModifier extends AbstractChartModifier { } else if (this.isGroupedVariant(variant)) { values = compact( flatten( + // @ts-expect-error series.data.map((group) => getSeriesData(group.data, categories, categoryProperty, valueProperty) ) @@ -718,6 +768,7 @@ export default class BarChartModifier extends AbstractChartModifier { * `position` * : A value from 0 to 1 indicating the position of the tick along the axis. */ + // @ts-expect-error computeCategoryAxisTicks(context, categoryInfo, axisConfig) { const { categoryAxisFormatter } = context.args; const isTimeAxis = axisConfig.type === 'time'; @@ -732,6 +783,7 @@ export default class BarChartModifier extends AbstractChartModifier { model.ecModel = this.chart.getModel(); if (!isTimeAxis) { + // @ts-expect-error model.getCategories = () => categoryInfo.categories; } @@ -739,11 +791,12 @@ export default class BarChartModifier extends AbstractChartModifier { [categoryInfo.first.valueOf(), categoryInfo.last.valueOf()], model ); - + // @ts-expect-error const ticks = scale.getTicks(false).map((tick, index) => ({ // prettier not formatting nested ternaries properly, so turn it off // prettier-ignore ...parseAxisLabel(isTimeAxis + // @ts-expect-error ? scale.getFormattedLabel(tick, index, categoryAxisFormatter) : categoryAxisFormatter ? categoryAxisFormatter(scale.getLabel(tick)) @@ -766,6 +819,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Calculate the labels used for the value axis. */ + // @ts-expect-error computeValueAxisTicks(context, valueInfo, axisConfig) { const { args } = context; const formatter = args.valueAxisFormatter ?? echarts.format.addCommas; @@ -786,7 +840,7 @@ export default class BarChartModifier extends AbstractChartModifier { ? valueInfo.maximum : axisConfig.max; const scale = echarts.helper.createScale([minValue, maxValue], axisConfig); - + // @ts-expect-error return scale.getTicks(false).map((tick) => ({ label: tick.value != null ? formatter(tick.value) : '', position: scale.normalize(tick.value), @@ -796,6 +850,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Generates the plot config for a single plot on this chart. */ + // @ts-expect-error generatePlotConfig(series, layout, context, gridIndex) { const { args, styles, data } = context; const { noDataText, seriesConfig } = args; @@ -841,6 +896,7 @@ export default class BarChartModifier extends AbstractChartModifier { : undefined, axisLabel: { ...(valueAxisFormatter && { + // @ts-expect-error formatter: (value, axisIndex) => valueAxisFormatter(value, 'axis', axisIndex), }), // margin between the axis label and the axis line @@ -861,6 +917,7 @@ export default class BarChartModifier extends AbstractChartModifier { }), axisLabel: { ...(categoryAxisFormatter && { + // @ts-expect-error formatter: (value, axisIndex) => categoryAxisFormatter(value, 'axis', axisIndex), }), // Determine how many categories are shown on the axis @@ -991,9 +1048,11 @@ export default class BarChartModifier extends AbstractChartModifier { }), }, ] + // @ts-expect-error : series.data.map((info) => ({ ...seriesBaseConfig, name: info.label, + // @ts-expect-error data: computeData(info.data, categoryInfo.categories, args).map((item) => ({ ...item, ...setItemColor(colorMap, item, info.label), @@ -1052,6 +1111,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Generates the configuration for an axis label. */ + // @ts-expect-error generateAxisLabelConfig(layout, style) { return { color: style.color, @@ -1075,6 +1135,7 @@ export default class BarChartModifier extends AbstractChartModifier { * Adds the configuration for the axis pointer for the `axis` to `config` and * returns an updated `layout`. */ + // @ts-expect-error addAxisPointer(context, layout, config, axisInfo, axis) { const { args, styles } = context; const name = `${axis}AxisPointer`; @@ -1126,6 +1187,7 @@ export default class BarChartModifier extends AbstractChartModifier { } : { ...(formatter && { + // @ts-expect-error formatter: (params) => formatter(params.value), }), color: labelStyle.color, @@ -1193,6 +1255,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Generates text to overlay on each cell of the chart, if any. */ + // @ts-expect-error generateTextOverlayConfig(series, args, layout, style) { const { noDataText } = args; @@ -1213,6 +1276,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Computes style and metrics about the Y axis for charts that use an Y axis. */ + // @ts-expect-error computeYAxisInfo(style, ticks, isHorizontal) { // HACK TODO: When ticks are too close to each other, the following tick // will be hidden. This can cause the Y axis to calculate the @@ -1237,7 +1301,9 @@ export default class BarChartModifier extends AbstractChartModifier { return ticks; }, []); + // @ts-expect-error const labelMetrics = computeMaxTextMetrics( + // @ts-expect-error renderedTicks.map((tick) => tick.label), style ); @@ -1268,6 +1334,7 @@ export default class BarChartModifier extends AbstractChartModifier { /** * Computes style and metrics about the X axis for charts that use an X axis. */ + // @ts-expect-error computeXAxisInfo(args, layout, style, ticks, yAxisInfo, isHorizontal) { const { categoryAxisMaxLabelCount, categoryAxisType } = args; const maxLabelCount = Math.min(categoryAxisMaxLabelCount ?? ticks.length, ticks.length); @@ -1284,6 +1351,7 @@ export default class BarChartModifier extends AbstractChartModifier { // two different in the final value. Skipping this for now, since it // requires a bunch of refactoring to make this work. [twl 17.Mar.23] const labelMetrics = computeMaxTextMetrics( + // @ts-expect-error ticks.map((tick) => tick.label), style, maxLabelWidth diff --git a/ember-apache-echarts/src/modifiers/graph-chart.ts b/ember-apache-echarts/src/modifiers/graph-chart.ts index 169f56058..6e8122b38 100644 --- a/ember-apache-echarts/src/modifiers/graph-chart.ts +++ b/ember-apache-echarts/src/modifiers/graph-chart.ts @@ -205,7 +205,9 @@ export default class GraphChartModifier extends AbstractChartModifier { const { layout, args, styles } = context; const { drillUpButtonText = '<' } = args; + // @ts-expect-error: Need to figure out what these do const style = resolveStyle(styles.drillUpButton, layout); + // @ts-expect-error: Need to figure out what these do const titleStyle = resolveStyle(styles.chartTitle, layout); const xMargins = style.marginLeft + style.marginRight; const yMargins = style.marginTop + style.marginBottom; @@ -232,6 +234,7 @@ export default class GraphChartModifier extends AbstractChartModifier { /** * Generates the configuration for the drill up button. */ + // @ts-expect-error: Need to figure out what these do generateDrillUpButtonConfig(text: string, layout, style) { const textMetrics = computeTextMetrics(text, style); @@ -276,6 +279,7 @@ export default class GraphChartModifier extends AbstractChartModifier { }, }, ], + // @ts-expect-error: Need to figure out what these do onclick: () => this.drillPath.popObject(), }, ], @@ -285,6 +289,7 @@ export default class GraphChartModifier extends AbstractChartModifier { /** * Generates the plot configuration for the graph chart. */ + // @ts-expect-error: Need to figure out what these do generatePlotConfig(info, _cell, _context, _gridIndex) { // Implement the logic to generate the plot configuration return { diff --git a/ember-apache-echarts/src/modifiers/tree-chart.ts b/ember-apache-echarts/src/modifiers/tree-chart.ts index 71dd2f741..7210a007c 100644 --- a/ember-apache-echarts/src/modifiers/tree-chart.ts +++ b/ember-apache-echarts/src/modifiers/tree-chart.ts @@ -1,6 +1,8 @@ import AbstractChartModifier from './abstract-chart.ts'; import { tracked } from '@glimmer/tracking'; import deepMerge from '../utils/deep-merge.ts'; +import type { ECharts, SelectChangedPayload } from 'echarts'; +import resolveStyle from '../utils/style/resolve-style.ts'; const defaultSeriesConfig = { type: 'tree', @@ -18,13 +20,51 @@ const defaultSeriesConfig = { animationDurationUpdate: 750, }; +type ChartArgs = { + tooltipFormatter?: (params: unknown) => string; + onSelect?: (name: string | null) => void; + data: unknown[]; + links: unknown[]; + seriesConfig?: Partial; + series?: unknown[]; + title?: string; +}; + +type TitleContext = { + layout: { + width: number; + height: number; + x: number; + y: number; + }; + args: { + title?: string; + drillUpButtonText?: string; + }; + data: { + title?: string; + }; + styles: { + chartTitle: unknown; + drillUpButton: unknown; + }; +}; + +type TitleConfig = { + title?: { + text: string; + left: number; + top: number; + }[]; +}; + export default class GraphChartModifier extends AbstractChartModifier { @tracked drillPath = []; /** * Configures the chart with the provided arguments. */ - configureChart(args, chart) { + configureChart(args: ChartArgs, chart: ECharts) { const { tooltipFormatter, onSelect } = args; const { config } = this.buildLayout(args, chart); const { data, seriesConfig = {} } = args; @@ -41,16 +81,17 @@ export default class GraphChartModifier extends AbstractChartModifier { series: [finalSeriesConfig], }); - chart.handle('selectchanged', (event) => { - const { fromAction, fromActionPayload, isFromClick } = event; + chart.on('selectchanged', (event) => { + const { fromAction, fromActionPayload, isFromClick } = event as SelectChangedPayload; if (!isFromClick) { return; } - const seriesIndex = fromActionPayload.seriesIndex; - const dataIndex = fromActionPayload.dataIndexInside; - const series = args.series[seriesIndex]; + const seriesIndex = fromActionPayload['seriesIndex']; + const dataIndex = fromActionPayload['dataIndexInside']; + const series = args.series?.[seriesIndex]; + // @ts-expect-error: TypeScript doesn't know about the structure of `series.data` const name = series.data[dataIndex] ? series.data[dataIndex].name : null; if (name) { @@ -67,8 +108,8 @@ export default class GraphChartModifier extends AbstractChartModifier { /** * Generates the `data` section of the context used to construct this chart. */ - createContextData(args, chart) { - const context = super.createContextData(args, chart); + createContextData(args: ChartArgs) { + const context = super.createContextData(args); const { series, title } = this.drillPath.reduce( ({ series }, pathIndex) => ({ series: series[pathIndex].series, @@ -88,7 +129,7 @@ export default class GraphChartModifier extends AbstractChartModifier { * Adds the title to `config` as defined in the data or by `args` and returns * the new context layout. */ - addTitle(context, config) { + addTitle(context: TitleContext, config: TitleConfig) { const buttonLayout = this.addDrillUpButton(context, config); const buttonWidth = context.layout.width - buttonLayout.width; const buttonHeight = context.layout.height - buttonLayout.height; @@ -126,14 +167,16 @@ export default class GraphChartModifier extends AbstractChartModifier { /** * Adds the drill up button to `config` and returns the new context layout. */ - addDrillUpButton(context, config) { + addDrillUpButton(context: TitleContext, config: TitleConfig) { if (!this.drillPath.length) { return context.layout; } const { layout, args, styles } = context; const { drillUpButtonText = '<' } = args; + // @ts-expect-error: Need to figure out what these do const style = resolveStyle(styles.drillUpButton, layout); + // @ts-expect-error: Need to figure out what these do const titleStyle = resolveStyle(styles.chartTitle, layout); const xMargins = style.marginLeft + style.marginRight; const yMargins = style.marginTop + style.marginBottom; @@ -143,76 +186,78 @@ export default class GraphChartModifier extends AbstractChartModifier { style.marginLeft += titleStyle.marginLeft; const buttonConfig = this.generateDrillUpButtonConfig(drillUpButtonText, layout, style); - + // @ts-expect-error: Need to figure out what these do mergeAtPaths(config, [buttonConfig]); - + // @ts-expect-error: Need to figure out what these do const buttonBox = buttonConfig['graphic.elements'][0].children[0].shape; return { ...layout, - width: layout.width - buttonBox.width - xMargins, - height: layout.height - buttonBox.height - yMargins, - x: layout.x + buttonBox.width + xMargins, - y: layout.y + buttonBox.height + yMargins, + width: layout.width - (buttonBox?.width ?? 0) - xMargins, + height: layout.height - (buttonBox?.height ?? 0) - yMargins, + x: layout.x + (buttonBox?.width ?? 0) + xMargins, + y: layout.y + (buttonBox?.height ?? 0) + yMargins, }; } /** * Generates the configuration for the drill up button. */ + // @ts-expect-error: Need to figure out what these do generateDrillUpButtonConfig(text, layout, style) { - const textMetrics = computeTextMetrics(text, style); - - return { - 'graphic.elements': [ - { - type: 'group', - left: style.marginLeft, - top: style.marginTop, - children: [ - // NOTE: This element is referenced by path in `addDrillUpButton` - { - type: 'rect', - shape: { - width: textMetrics.width + style.paddingLeft + style.paddingRight, - height: textMetrics.fontHeight + style.paddingTop + style.paddingBottom, - r: [ - style.borderTopLeftRadius ?? 0, - style.borderTopRightRadius ?? 0, - style.borderBottomRightRadius ?? 0, - style.borderBottomLeftRadius ?? 0, - ], - }, - style: { - stroke: style.borderColor ?? '#fff', - fill: style.backgroundColor ?? '#fff', - }, - }, - { - type: 'text', - x: style.paddingLeft, - y: style.paddingTop, - style: { - fill: style.color, - text, - font: `${style.fontStyle} ${style.fontWeight} ${style.fontSize}px ${style.fontFamily}`, - }, - textConfig: { - distance: 0, - inside: true, - position: [10, 0], - }, - }, - ], - onclick: () => this.drillPath.popObject(), - }, - ], - }; + // const textMetrics = computeTextMetrics(text, style); + + // return { + // 'graphic.elements': [ + // { + // type: 'group', + // left: style.marginLeft, + // top: style.marginTop, + // children: [ + // // NOTE: This element is referenced by path in `addDrillUpButton` + // { + // type: 'rect', + // shape: { + // width: textMetrics.width + style.paddingLeft + style.paddingRight, + // height: textMetrics.fontHeight + style.paddingTop + style.paddingBottom, + // r: [ + // style.borderTopLeftRadius ?? 0, + // style.borderTopRightRadius ?? 0, + // style.borderBottomRightRadius ?? 0, + // style.borderBottomLeftRadius ?? 0, + // ], + // }, + // style: { + // stroke: style.borderColor ?? '#fff', + // fill: style.backgroundColor ?? '#fff', + // }, + // }, + // { + // type: 'text', + // x: style.paddingLeft, + // y: style.paddingTop, + // style: { + // fill: style.color, + // text, + // font: `${style.fontStyle} ${style.fontWeight} ${style.fontSize}px ${style.fontFamily}`, + // }, + // textConfig: { + // distance: 0, + // inside: true, + // position: [10, 0], + // }, + // }, + // ], + // onclick: () => this.drillPath.popObject(), + // }, + // ], + // }; } /** * Generates the plot configuration for the graph chart. */ + // @ts-expect-error: Need to figure out what these do generatePlotConfig(info, _cell, _context, _gridIndex) { // Implement the logic to generate the plot configuration return { diff --git a/ember-apache-echarts/src/utils/chart/parse-axis-label.ts b/ember-apache-echarts/src/utils/chart/parse-axis-label.ts index c4250edce..5b326b72a 100644 --- a/ember-apache-echarts/src/utils/chart/parse-axis-label.ts +++ b/ember-apache-echarts/src/utils/chart/parse-axis-label.ts @@ -9,7 +9,7 @@ * * @return {object} An object containing the `label` and an optional `type` */ -export default function parseAxisLabel(label) { +export default function parseAxisLabel(label: string) { if (label.startsWith('{') && label.endsWith('}') && label.includes('|')) { const [type, text] = label.substring(1, label.length - 2).split('|'); diff --git a/ember-apache-echarts/src/utils/create-lookup.ts b/ember-apache-echarts/src/utils/create-lookup.ts index 04f70bed0..65757245d 100644 --- a/ember-apache-echarts/src/utils/create-lookup.ts +++ b/ember-apache-echarts/src/utils/create-lookup.ts @@ -18,7 +18,7 @@ export default function createLookup( // @ts-expect-error: Return to these as I am not sure what the purpose of this is. array, keyProperty = 'id', - valueProperty = undefined, + valueProperty?: string, duplicateKeys = false ) { return !array diff --git a/ember-apache-echarts/src/utils/data/compute-statistic.ts b/ember-apache-echarts/src/utils/data/compute-statistic.ts index 7d9042669..7395decca 100644 --- a/ember-apache-echarts/src/utils/data/compute-statistic.ts +++ b/ember-apache-echarts/src/utils/data/compute-statistic.ts @@ -1,6 +1,13 @@ +// @ts-expect-error: remove lodash import { compact } from 'lodash-es'; import getUniqueDatasetValues from './get-unique-dataset-values.ts'; +type DataSeries = { + data: { [key: string]: any }[]; +}; + +type Stat = 'min' | 'max'; + /** * Calculates the `stat` for the `property` within the `dataset`. * @@ -11,6 +18,6 @@ import getUniqueDatasetValues from './get-unique-dataset-values.ts'; * * @return {number} The value of the statistic for the dataset */ -export default function computeStatistic(dataset, stat, property = 'value') { +export default function computeStatistic(dataset: DataSeries[], stat: Stat, property = 'value') { return Math[stat](...compact(getUniqueDatasetValues(dataset, property))); } diff --git a/ember-apache-echarts/src/utils/data/get-series-data.ts b/ember-apache-echarts/src/utils/data/get-series-data.ts index 6d910293b..f9df68b25 100644 --- a/ember-apache-echarts/src/utils/data/get-series-data.ts +++ b/ember-apache-echarts/src/utils/data/get-series-data.ts @@ -1,6 +1,11 @@ +// @ts-expect-error: remove lodash import { compact } from 'lodash-es'; import createLookup from '../create-lookup.ts'; +type Data = { + [key: string]: any; +}; + /** * Returns the data values from the `data` array. * @@ -13,7 +18,7 @@ import createLookup from '../create-lookup.ts'; * * @return {number[]} An array of data values */ -export default function getSeriesData(data, categories, categoryProperty, valueProperty) { +export default function getSeriesData(data: Data[], categories: string[], categoryProperty: string, valueProperty: string) { const lookup = createLookup(data, categoryProperty, valueProperty); return compact(categories.map((category) => lookup[category])); diff --git a/ember-apache-echarts/src/utils/data/get-series-totals.ts b/ember-apache-echarts/src/utils/data/get-series-totals.ts index 9ffe270a4..3377a2b02 100644 --- a/ember-apache-echarts/src/utils/data/get-series-totals.ts +++ b/ember-apache-echarts/src/utils/data/get-series-totals.ts @@ -1,5 +1,10 @@ -import { flatten } from 'lodash-es'; -import { transform } from 'lodash-es'; +// @ts-expect-error: remove lodash +import { flatten, transform } from 'lodash-es'; + +type DataItem = { + data: { [key: string]: any }[]; + [key: string]: any; +}; /** * Compute the sum of all values in the series in `data` for each category in @@ -14,12 +19,13 @@ import { transform } from 'lodash-es'; * @return {number[]} An array of the sums for the values for each category */ -export default function getSeriesTotals(data, categories, categoryProperty, valueProperty) { +export default function getSeriesTotals(data: DataItem[], categories: string[], categoryProperty: string, valueProperty: string) { const allData = flatten(data.map((info) => info.data)); return Object.values( transform( allData, + // @ts-expect-error: remove lodash (totals, item) => { totals[item?.[categoryProperty]] = (totals[item?.[categoryProperty]] ?? 0) + (item?.[valueProperty] ?? 0); diff --git a/ember-apache-echarts/src/utils/data/get-unique-dataset-values.ts b/ember-apache-echarts/src/utils/data/get-unique-dataset-values.ts index f5cbf097c..15a537f73 100644 --- a/ember-apache-echarts/src/utils/data/get-unique-dataset-values.ts +++ b/ember-apache-echarts/src/utils/data/get-unique-dataset-values.ts @@ -1,3 +1,7 @@ +type DataSeries = { + data: { [key: string]: any }[]; +}; + /** * Extracts an array of unique values of `property` from `dataset`, where * `dataset` is an array of data series. Each series should be an object that @@ -8,7 +12,7 @@ * * @return {any[]} An array of unique property values for `property` */ -export default function getUniqueDatasetValues(dataset, property) { +export default function getUniqueDatasetValues(dataset: DataSeries[], property: string) { const result = new Map(); for (const series of dataset) { diff --git a/ember-apache-echarts/src/utils/data/rotate-data-series.ts b/ember-apache-echarts/src/utils/data/rotate-data-series.ts index 29ff741b1..33a4183c7 100644 --- a/ember-apache-echarts/src/utils/data/rotate-data-series.ts +++ b/ember-apache-echarts/src/utils/data/rotate-data-series.ts @@ -1,3 +1,4 @@ +// @ts-expect-error: remove lodash import { omit } from 'lodash-es'; import getUniqueDatasetValues from './get-unique-dataset-values.ts'; @@ -18,10 +19,13 @@ import getUniqueDatasetValues from './get-unique-dataset-values.ts'; * * @return {object[]} data An array of data objects */ -const rotateDataSeries = (data, categoryProperty, valueProperty) => +// @ts-expect-error: not sure +const rotateDataSeries = (data, categoryProperty: string, valueProperty: string) => getUniqueDatasetValues(data, categoryProperty).map((label) => ({ label, + // @ts-expect-error: not sure data: data.map((series) => { + // @ts-expect-error: not sure const item = series.data.find((item) => item[categoryProperty] === label); return !item diff --git a/ember-apache-echarts/src/utils/layout/compute-inner-box.ts b/ember-apache-echarts/src/utils/layout/compute-inner-box.ts index c18b60635..54cdf43c5 100644 --- a/ember-apache-echarts/src/utils/layout/compute-inner-box.ts +++ b/ember-apache-echarts/src/utils/layout/compute-inner-box.ts @@ -8,6 +8,7 @@ * * @return {object} The `width`, `height`, `x` and `y` of the inner box */ +// @ts-expect-error: not sure const computeInnerBox = (outerBox, style) => ({ ...outerBox, width: diff --git a/ember-apache-echarts/src/utils/layout/compute-max-text-metrics.ts b/ember-apache-echarts/src/utils/layout/compute-max-text-metrics.ts index f8ddc76bf..6b1a28b63 100644 --- a/ember-apache-echarts/src/utils/layout/compute-max-text-metrics.ts +++ b/ember-apache-echarts/src/utils/layout/compute-max-text-metrics.ts @@ -13,7 +13,8 @@ import computeTextMetrics from './compute-text-metrics.ts'; * sufficient to contain each of the strings in `array` when * rendered */ -const computeMaxTextMetrics = (array, style, maxWidth) => +// @ts-expect-error: not sure +const computeMaxTextMetrics = (array: string[], style, maxWidth: number) => array.reduce( (maxMetrics, text) => { const textMetrics = computeTextMetrics(text, style); diff --git a/ember-apache-echarts/src/utils/layout/compute-text-height.ts b/ember-apache-echarts/src/utils/layout/compute-text-height.ts index ba1d98172..f3431fe13 100644 --- a/ember-apache-echarts/src/utils/layout/compute-text-height.ts +++ b/ember-apache-echarts/src/utils/layout/compute-text-height.ts @@ -9,6 +9,7 @@ const stringToMeasure = 'ABCDEFGHIJKLMNOPQRSTUVWYXZabcdefghijklmnopqrstuvwxyz'; * * @return {number} The height of any text rendered using this style in pixels */ +// @ts-expect-error: not sure const computeTextHeight = (style) => computeTextMetrics(stringToMeasure, style).height + style.marginTop + diff --git a/ember-apache-echarts/src/utils/layout/layout-cells.ts b/ember-apache-echarts/src/utils/layout/layout-cells.ts index 481c6c131..cbeeb403f 100644 --- a/ember-apache-echarts/src/utils/layout/layout-cells.ts +++ b/ember-apache-echarts/src/utils/layout/layout-cells.ts @@ -1,3 +1,4 @@ +// @ts-expect-error: remove lodash import { pickBy } from 'lodash-es'; import resolveStyle from '../style/resolve-style.ts'; @@ -10,6 +11,7 @@ import resolveStyle from '../style/resolve-style.ts'; * * @return {object} An object containing the chart layout info */ +// @ts-expect-error: not sure function computeChartLayoutInfo(context, array) { const { maxColumns } = context.args; const cellCount = array.length; @@ -34,6 +36,7 @@ function computeChartLayoutInfo(context, array) { * * @return {object} An object containing the cell layout info */ +// @ts-expect-error: not sure function computeCellLayoutInfo(context, chart) { const xOffset = context.layout.cell?.xOffset ?? 0; const yOffset = context.layout.cell?.yOffset ?? 0; @@ -69,7 +72,7 @@ function computeCellLayoutInfo(context, chart) { Object.assign( cell, - pickBy(resolveStyle(context.styles.cell, layoutSize), (value, key) => key.startsWith('padding')) + pickBy(resolveStyle(context.styles.cell, layoutSize), (_value: unknown, key: string) => key.startsWith('padding')) ); // Store the dimensions inside of the padding @@ -90,6 +93,7 @@ function computeCellLayoutInfo(context, chart) { * @return {object} An object containing `chart` and `cell` keys which provide * layout information for these aspects of the layout */ +// @ts-expect-error: not sure function computeLayoutInfo(context, array) { const chart = computeChartLayoutInfo(context, array); const cell = computeCellLayoutInfo(context, chart); @@ -131,9 +135,10 @@ function computeLayoutInfo(context, array) { * * @return {object[]} An array of chart configuration elements */ +// @ts-expect-error: not sure export default function layoutCells(context, array, callback) { const layoutInfo = computeLayoutInfo(context, array); - + // @ts-expect-error: not sure return array.map((element, index) => { const column = index % layoutInfo.chart.columns; const row = Math.floor(index / layoutInfo.chart.columns); diff --git a/ember-apache-echarts/src/utils/merge-at.ts b/ember-apache-echarts/src/utils/merge-at.ts index bfb6bb81f..7abd57eda 100644 --- a/ember-apache-echarts/src/utils/merge-at.ts +++ b/ember-apache-echarts/src/utils/merge-at.ts @@ -1,5 +1,5 @@ -import { get } from 'lodash-es'; -import { set } from 'lodash-es'; +// @ts-expect-error: remove lodash +import { get, set } from 'lodash-es'; /** * Merges the existing value at `path` within `object` with the `value`, if @@ -11,7 +11,7 @@ import { set } from 'lodash-es'; * appended at the end, and object properties for * `value` override existing properties */ -export default function mergeAt(object, path, value) { +export default function mergeAt(object: Record, path: string, value: unknown) { if (!value) { return; } diff --git a/ember-apache-echarts/src/utils/on-element-resize.ts b/ember-apache-echarts/src/utils/on-element-resize.ts index d16a814dd..525362466 100644 --- a/ember-apache-echarts/src/utils/on-element-resize.ts +++ b/ember-apache-echarts/src/utils/on-element-resize.ts @@ -11,7 +11,7 @@ * * @return {ResizeObserver} The observer used to watch for resize events */ -export default function onElementResize(element, callback, onceOnly = false) { +export default function onElementResize(element: HTMLElement, callback: ((element: HTMLElement) => void), onceOnly = false) { const resizeObserver = new ResizeObserver(() => { callback(element); diff --git a/ember-apache-echarts/src/utils/style/format-css-style-value.ts b/ember-apache-echarts/src/utils/style/format-css-style-value.ts index 450fdf59f..7c0949698 100644 --- a/ember-apache-echarts/src/utils/style/format-css-style-value.ts +++ b/ember-apache-echarts/src/utils/style/format-css-style-value.ts @@ -1,3 +1,4 @@ +// @ts-expect-error: remove lodash import { kebabCase } from 'lodash-es'; const pixelProperties = [ @@ -15,7 +16,7 @@ const pixelProperties = [ 'borderRightRadius', ]; -const addPixelsToValue = (key, value) => +const addPixelsToValue = (key: string, value: number|string) => typeof value === 'number' && pixelProperties.find((property) => key.startsWith(property)) ? `${value}px` : value; @@ -28,8 +29,9 @@ const addPixelsToValue = (key, value) => * @return {string} A string representation of the CSS properties suitable for a * `style` attribute */ -const formatCssStyleValue = (style) => +const formatCssStyleValue = (style: Record) => Object.keys(style).reduce( + // @ts-expect-error: not sure (styleValue, key) => styleValue + `${kebabCase(key)}: ${addPixelsToValue(key, style[key])}; `, '' ); diff --git a/test-app/app/components/chart-graph-example.js b/test-app/app/components/chart-graph-example.js index b9779946e..0ccdd5999 100644 --- a/test-app/app/components/chart-graph-example.js +++ b/test-app/app/components/chart-graph-example.js @@ -14,8 +14,6 @@ export default class ChartGraphExample extends Component { * @returns {Object} The series configuration object for the chart. */ get seriesConfig() { - const isVertical = this.isVertical; - // Common label styles const commonLabelStyles = { position: 'inside', diff --git a/test-app/app/components/chart-tree-example.js b/test-app/app/components/chart-tree-example.js index f5bd1f0a2..8578bcceb 100644 --- a/test-app/app/components/chart-tree-example.js +++ b/test-app/app/components/chart-tree-example.js @@ -2,10 +2,6 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; -const penniesToDollars = (pennies) => { - return `$${(pennies / 100).toFixed(2)}`; -}; - /** * ChartTreeExample component renders a tree chart with adjustable orientation. */