mirror of https://github.com/buster-so/buster.git
update server shared to include new types
This commit is contained in:
parent
7364f328d4
commit
4cdde9203f
|
@ -1,77 +0,0 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { GoalLineSchema, TrendlineSchema } from './annotationInterfaces';
|
||||
import { ColumnSettingsSchema } from './columnInterfaces';
|
||||
import { IColumnLabelFormatSchema } from './columnLabelInterfaces';
|
||||
import { ChartTypeSchema } from './enum';
|
||||
import { ShowLegendHeadlineSchema } from './etcInterfaces';
|
||||
import {
|
||||
CategoryAxisStyleConfigSchema,
|
||||
XAxisConfigSchema,
|
||||
Y2AxisConfigSchema,
|
||||
YAxisConfigSchema
|
||||
} from './tickInterfaces';
|
||||
import { DEFAULT_CHART_THEME } from './configColors';
|
||||
import { BarChartPropsSchema } from './barChartProps';
|
||||
import { LineChartPropsSchema } from './lineChartProps';
|
||||
import { ScatterChartPropsSchema } from './scatterChartProps';
|
||||
import { PieChartPropsSchema } from './pieChartProps';
|
||||
import { TableChartPropsSchema } from './tableChartProps';
|
||||
import { ComboChartPropsSchema } from './comboChartProps';
|
||||
import { MetricChartPropsSchema, DerivedMetricTitleSchema } from './metricChartProps';
|
||||
|
||||
export const BusterChartConfigPropsSchema = z.object({
|
||||
selectedChartType: ChartTypeSchema,
|
||||
// COLUMN SETTINGS
|
||||
// OPTIONAL because the defaults will be determined by the UI
|
||||
columnSettings: z.record(z.string(), z.optional(ColumnSettingsSchema)).default({}),
|
||||
columnLabelFormats: z.record(z.string(), z.optional(IColumnLabelFormatSchema)).default({}),
|
||||
// OPTIONAL: default is the buster color palette
|
||||
colors: z.array(z.string()).default(DEFAULT_CHART_THEME),
|
||||
// OPTIONAL: default is null and will be true if there are multiple Y axes or if a category axis is used
|
||||
showLegend: z.nullable(z.boolean()).default(null),
|
||||
// OPTIONAL: default: true
|
||||
gridLines: z.boolean().default(true),
|
||||
// OPTIONAL
|
||||
showLegendHeadline: ShowLegendHeadlineSchema,
|
||||
// OPTIONAL: default is no goal lines
|
||||
goalLines: z.array(GoalLineSchema).default([]),
|
||||
// OPTIONAL: default is no trendlines
|
||||
trendlines: z.array(TrendlineSchema).default([]),
|
||||
// OPTIONAL: default is false
|
||||
disableTooltip: z.boolean().default(false),
|
||||
// Spread the shape properties from all schemas
|
||||
...YAxisConfigSchema.shape,
|
||||
...XAxisConfigSchema.shape,
|
||||
...CategoryAxisStyleConfigSchema.shape,
|
||||
...Y2AxisConfigSchema.shape,
|
||||
...BarChartPropsSchema.shape,
|
||||
...LineChartPropsSchema.shape,
|
||||
...ScatterChartPropsSchema.shape,
|
||||
...PieChartPropsSchema.shape,
|
||||
...TableChartPropsSchema.shape,
|
||||
...ComboChartPropsSchema.shape,
|
||||
...MetricChartPropsSchema.shape
|
||||
});
|
||||
|
||||
// Re-export schemas for backward compatibility
|
||||
export {
|
||||
BarChartPropsSchema,
|
||||
LineChartPropsSchema,
|
||||
ScatterChartPropsSchema,
|
||||
PieChartPropsSchema,
|
||||
TableChartPropsSchema,
|
||||
ComboChartPropsSchema,
|
||||
MetricChartPropsSchema,
|
||||
DerivedMetricTitleSchema
|
||||
};
|
||||
|
||||
// Export original types for backward compatibility
|
||||
export type BusterChartConfigProps = z.infer<typeof BusterChartConfigPropsSchema>;
|
||||
export type DerivedMetricTitle = z.infer<typeof DerivedMetricTitleSchema>;
|
||||
export type MetricChartProps = z.infer<typeof MetricChartPropsSchema>;
|
||||
export type BarChartProps = z.infer<typeof BarChartPropsSchema>;
|
||||
export type LineChartProps = z.infer<typeof LineChartPropsSchema>;
|
||||
export type ScatterChartProps = z.infer<typeof ScatterChartPropsSchema>;
|
||||
export type PieChartProps = z.infer<typeof PieChartPropsSchema>;
|
||||
export type TableChartProps = z.infer<typeof TableChartPropsSchema>;
|
||||
export type ComboChartProps = z.infer<typeof ComboChartPropsSchema>;
|
|
@ -1,125 +0,0 @@
|
|||
import { DEFAULT_CHART_THEME } from './configColors';
|
||||
import { BusterChartConfigPropsSchema, type BusterChartConfigProps } from './chartConfigProps';
|
||||
import { z } from 'zod/v4';
|
||||
|
||||
/**
|
||||
* Extracts all default values from a Zod schema.
|
||||
* This function creates a partial version of the schema where all fields are optional,
|
||||
* then parses an empty object to get all the default values.
|
||||
*/
|
||||
function getDefaults<T extends z.ZodObject<z.ZodRawShape>>(schema: T): z.infer<T> {
|
||||
// Create a partial version of the schema where all fields are optional
|
||||
const partialSchema = schema.partial();
|
||||
|
||||
// Parse an empty object through the partial schema
|
||||
// This will apply all default values without throwing on missing required fields
|
||||
const defaults = partialSchema.parse({});
|
||||
|
||||
// Now try to parse the defaults through the original schema
|
||||
// This ensures we get the correct type and validates the defaults
|
||||
try {
|
||||
return schema.parse(defaults);
|
||||
} catch {
|
||||
// If the original schema fails (missing required fields without defaults),
|
||||
// return what we have as a partial
|
||||
return defaults as z.infer<T>;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative implementation that only returns fields with explicit defaults.
|
||||
* This is useful when you want to know which fields have defaults vs which are undefined.
|
||||
*/
|
||||
function getDefaultsPartial<T extends z.ZodObject<z.ZodRawShape>>(schema: T): Partial<z.infer<T>> {
|
||||
// Make all fields optional and parse an empty object
|
||||
const partialSchema = schema.partial();
|
||||
return partialSchema.parse({}) as Partial<z.infer<T>>;
|
||||
}
|
||||
|
||||
export const DEFAULT_CHART_CONFIG: BusterChartConfigProps = getDefaults(
|
||||
BusterChartConfigPropsSchema
|
||||
);
|
||||
|
||||
// export const DEFAULT_CHART_CONFIG: BusterChartConfigProps = {
|
||||
// colors: DEFAULT_CHART_THEME,
|
||||
// selectedChartType: 'table',
|
||||
// yAxisShowAxisLabel: true,
|
||||
// yAxisShowAxisTitle: true,
|
||||
// yAxisAxisTitle: null,
|
||||
// yAxisStartAxisAtZero: null,
|
||||
// yAxisScaleType: 'linear',
|
||||
// y2AxisShowAxisLabel: true,
|
||||
// y2AxisAxisTitle: null,
|
||||
// y2AxisShowAxisTitle: true,
|
||||
// y2AxisStartAxisAtZero: true,
|
||||
// y2AxisScaleType: 'linear',
|
||||
// xAxisTimeInterval: null,
|
||||
// xAxisShowAxisLabel: true,
|
||||
// xAxisShowAxisTitle: true,
|
||||
// xAxisAxisTitle: null,
|
||||
// xAxisLabelRotation: 'auto',
|
||||
// xAxisDataZoom: false,
|
||||
// categoryAxisTitle: null,
|
||||
// showLegend: null,
|
||||
// gridLines: true,
|
||||
// goalLines: [],
|
||||
// trendlines: [],
|
||||
// showLegendHeadline: false,
|
||||
// disableTooltip: false,
|
||||
// barAndLineAxis: {
|
||||
// x: [],
|
||||
// y: [],
|
||||
// category: [],
|
||||
// tooltip: null
|
||||
// },
|
||||
// scatterAxis: {
|
||||
// x: [],
|
||||
// y: [],
|
||||
// size: [],
|
||||
// tooltip: null
|
||||
// },
|
||||
// comboChartAxis: {
|
||||
// x: [],
|
||||
// y: [],
|
||||
// y2: [],
|
||||
// tooltip: null
|
||||
// },
|
||||
// pieChartAxis: {
|
||||
// x: [],
|
||||
// y: [],
|
||||
// tooltip: null
|
||||
// },
|
||||
// //LINE
|
||||
// lineGroupType: null,
|
||||
// //SCATTER
|
||||
// scatterDotSize: [3, 15],
|
||||
// //BAR
|
||||
// barSortBy: [],
|
||||
// barLayout: 'vertical',
|
||||
// barGroupType: 'group',
|
||||
// barShowTotalAtTop: false,
|
||||
// //PIE
|
||||
// pieShowInnerLabel: true,
|
||||
// pieInnerLabelAggregate: 'sum',
|
||||
// pieInnerLabelTitle: 'Total',
|
||||
// pieLabelPosition: null,
|
||||
// pieDonutWidth: 40,
|
||||
// pieMinimumSlicePercentage: 0,
|
||||
// pieDisplayLabelAs: 'number',
|
||||
// pieSortBy: 'value',
|
||||
// //METRIC
|
||||
// metricColumnId: '',
|
||||
// metricValueAggregate: 'sum',
|
||||
// metricHeader: null,
|
||||
// metricSubHeader: null,
|
||||
// metricValueLabel: null,
|
||||
// //TABLE
|
||||
// tableColumnOrder: null,
|
||||
// tableColumnWidths: null,
|
||||
// tableHeaderBackgroundColor: null,
|
||||
// tableHeaderFontColor: null,
|
||||
// tableColumnFontColor: null,
|
||||
// //MUST LOOP THROUGH ALL COLUMNS
|
||||
// columnSettings: {},
|
||||
// columnLabelFormats: {}
|
||||
// };
|
|
@ -1,69 +0,0 @@
|
|||
import { z } from 'zod/v4';
|
||||
|
||||
export const IColumnLabelFormatSchema = z.object({
|
||||
columnType: z.enum(['number', 'text', 'date'] as const),
|
||||
style: z.enum(['currency', 'percent', 'number', 'date', 'string']),
|
||||
// All other properties from ColumnLabelFormat
|
||||
// OPTIONAL: if this is not specifically requested by the user, then you should ignore this and the columnId will be used and formatted
|
||||
displayName: z.optional(z.string()),
|
||||
// OPTIONAL: default is ','. You should add this style if the column type requires a unique separator style. This will only apply if the format is set to 'number'.
|
||||
numberSeparatorStyle: z.optional(z.nullable(z.literal(','))),
|
||||
// OPTIONAL: default is 0. This is essentially used to set a minimum number of decimal places. This will only apply if the format is set to 'number'.
|
||||
minimumFractionDigits: z.optional(
|
||||
z
|
||||
.number()
|
||||
.check(
|
||||
z.gte(0, 'Minimum fraction digits must be at least 0'),
|
||||
z.lte(20, 'Minimum fraction digits must be at most 20')
|
||||
)
|
||||
),
|
||||
// OPTIONAL: default is 2. This is essentially used to set a maximum number of decimal places. This will only apply if the format is set to 'number'.
|
||||
maximumFractionDigits: z.optional(
|
||||
z
|
||||
.number()
|
||||
.check(
|
||||
z.gte(0, 'Maximum fraction digits must be at least 0'),
|
||||
z.lte(20, 'Maximum fraction digits must be at most 20')
|
||||
)
|
||||
),
|
||||
// OPTIONAL: default is 1. This will only apply if the format is set to 'number', 'currency', or 'percent'.
|
||||
multiplier: z.optional(
|
||||
z
|
||||
.number()
|
||||
.check(
|
||||
z.gte(0.001, 'Multiplier must be at least 0.001'),
|
||||
z.lte(1000000, 'Multiplier must be at most 1,000,000')
|
||||
)
|
||||
),
|
||||
// OPTIONAL: default is ''. This sets a prefix to go in front of each value found within the column. This will only apply if the format is set to 'number' or 'percent'.
|
||||
prefix: z.optional(z.string()),
|
||||
// OPTIONAL: default is ''. This sets a suffix to go after each value found within the column. This will only apply if the format is set to 'number' or 'percent'.
|
||||
suffix: z.optional(z.string()),
|
||||
// OPTIONAL: default is 0. This will only apply if the format is set to 'number'. This will replace missing data with the specified value.
|
||||
replaceMissingDataWith: z.optional(z.union([z.literal(0), z.null(), z.string()])),
|
||||
useRelativeTime: z.optional(z.boolean()),
|
||||
isUTC: z.optional(z.boolean()),
|
||||
makeLabelHumanReadable: z.optional(z.boolean()),
|
||||
// DO NOT SHARE WITH LLM
|
||||
compactNumbers: z.optional(z.boolean()),
|
||||
// Currency-specific properties
|
||||
// OPTIONAL: default is 'USD'. This will only apply if the format is set to 'currency'. It should be the ISO 4217 currency code.
|
||||
currency: z.optional(z.string()),
|
||||
// Date-specific properties
|
||||
// OPTIONAL: default is 'LL'. This will only apply if the format is set to 'date'. This will convert the date to the specified format. This MUST BE IN dayjs format. If you determine that a column type is a date column, you should specify it's date format here.
|
||||
dateFormat: z.optional(z.union([z.literal('auto'), z.string()])),
|
||||
// OPTIONAL: default is null. This will only apply if the format is set to 'number'. This will convert the number to a specified date unit. For example, if month_of_year is selected, then the number 0 will be converted to January.
|
||||
convertNumberTo: z.optional(
|
||||
z.nullable(z.enum(['day_of_week', 'month_of_year', 'quarter', 'number']))
|
||||
)
|
||||
});
|
||||
|
||||
// Create ColumnLabelFormatSchema by extending IColumnLabelFormatSchema with optional columnType and style
|
||||
export const ColumnLabelFormatSchema = IColumnLabelFormatSchema.extend({
|
||||
columnType: z.optional(z.enum(['number', 'text', 'date'] as const)),
|
||||
style: z.optional(z.enum(['currency', 'percent', 'number', 'date', 'string']))
|
||||
});
|
||||
|
||||
// Export inferred types
|
||||
export type ColumnLabelFormat = z.infer<typeof ColumnLabelFormatSchema>;
|
||||
export type IColumnLabelFormat = z.infer<typeof IColumnLabelFormatSchema>;
|
|
@ -1,10 +1 @@
|
|||
export * from './annotationInterfaces';
|
||||
export * from './axisInterfaces';
|
||||
export * from './chartBaseInterfaces';
|
||||
export * from './chartConfigProps';
|
||||
export * from './columnInterfaces';
|
||||
export * from './columnLabelInterfaces';
|
||||
export * from './enum';
|
||||
export * from './etcInterfaces';
|
||||
export * from './interfaces';
|
||||
export * from './tickInterfaces';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { Chart, ChartType, DefaultDataPoint } from 'chart.js';
|
||||
import type { ColumnMetaData } from '../interfaces';
|
||||
import type { BusterChartConfigProps } from './chartConfigProps';
|
||||
import type { ColumnMetaData, ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
|
||||
export type BusterChartProps = {
|
||||
data: Record<string, string | number | null | Date>[] | null;
|
||||
|
@ -15,7 +14,7 @@ export type BusterChartProps = {
|
|||
readOnly?: boolean;
|
||||
onInitialAnimationEnd?: () => void;
|
||||
onChartMounted?: (chart?: ChartJSOrUndefined) => void;
|
||||
} & BusterChartConfigProps;
|
||||
} & ChartConfigProps;
|
||||
|
||||
type ChartJSOrUndefined<
|
||||
TType extends ChartType = ChartType,
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { PieChartAxisSchema } from './axisInterfaces';
|
||||
import { PieSortBySchema } from './etcInterfaces';
|
||||
|
||||
export const PieChartPropsSchema = z.object({
|
||||
// OPTIONAL: default: value
|
||||
pieSortBy: PieSortBySchema,
|
||||
// Required for Pie
|
||||
pieChartAxis: PieChartAxisSchema,
|
||||
// OPTIONAL: default: number
|
||||
pieDisplayLabelAs: z.enum(['percent', 'number']).default('number'),
|
||||
// OPTIONAL: default true if donut width is set. If the data contains a percentage, set this as false.
|
||||
pieShowInnerLabel: z.boolean().default(true),
|
||||
// OPTIONAL: default: sum
|
||||
pieInnerLabelAggregate: z
|
||||
.enum(['sum', 'average', 'median', 'max', 'min', 'count'])
|
||||
.default('sum'),
|
||||
// OPTIONAL: default is null and will be the name of the pieInnerLabelAggregate
|
||||
pieInnerLabelTitle: z.string().optional(),
|
||||
// OPTIONAL: default: outside
|
||||
pieLabelPosition: z.nullable(z.enum(['inside', 'outside', 'none'])).default(null),
|
||||
// OPTIONAL: default: 55 | range 0-65 | range represents percent size of the donut hole. If user asks for a pie this should be 0
|
||||
pieDonutWidth: z
|
||||
.number()
|
||||
.min(0, 'Donut width must be at least 0')
|
||||
.max(65, 'Donut width must be at most 65')
|
||||
.default(40),
|
||||
// OPTIONAL: default: 2.5 | range 0-100 | If there are items that are less than this percentage of the pie, they combine to form a single slice.
|
||||
pieMinimumSlicePercentage: z
|
||||
.number()
|
||||
.min(0, 'Minimum slice percentage must be at least 0')
|
||||
.max(100, 'Minimum slice percentage must be at most 100')
|
||||
.default(0)
|
||||
});
|
||||
|
||||
export type PieChartProps = z.infer<typeof PieChartPropsSchema>;
|
|
@ -1,70 +0,0 @@
|
|||
import { z } from 'zod/v4';
|
||||
|
||||
/**
|
||||
* Configuration options for the Y-axis of a chart.
|
||||
*/
|
||||
export const YAxisConfigSchema = z.object({
|
||||
// Whether to show the axis label. Defaults to true.
|
||||
yAxisShowAxisLabel: z.boolean().default(true),
|
||||
// Whether to show the axis title. Defaults to true.
|
||||
yAxisShowAxisTitle: z.boolean().default(true),
|
||||
// The title of the Y-axis. @default null - Uses the name of the first column plotted on the Y-axis
|
||||
yAxisAxisTitle: z.nullable(z.string()).default(null),
|
||||
// Whether to start the axis at zero. Defaults to null.
|
||||
yAxisStartAxisAtZero: z.nullable(z.boolean()).default(null),
|
||||
// The scale type for the Y-axis. @default "linear"
|
||||
yAxisScaleType: z.enum(['log', 'linear']).default('linear')
|
||||
});
|
||||
|
||||
//The y2 (or right axis) Y-axis is used for secondary Y-axes in a combo chart.
|
||||
/**
|
||||
* Configuration options for the secondary Y-axis (Y2) in a combo chart.
|
||||
*/
|
||||
export const Y2AxisConfigSchema = z.object({
|
||||
// Whether to show the axis label. Defaults to true.
|
||||
y2AxisShowAxisLabel: z.boolean().default(true),
|
||||
// Whether to show the axis title. Defaults to true.
|
||||
y2AxisShowAxisTitle: z.boolean().default(true),
|
||||
// The title of the secondary Y-axis. @default null - Uses the name of the first column plotted on the Y2-axis
|
||||
y2AxisAxisTitle: z.nullable(z.string()).default(null),
|
||||
// Whether to start the axis at zero. Defaults to true.
|
||||
y2AxisStartAxisAtZero: z.boolean().default(true),
|
||||
// The scale type for the secondary Y-axis. @default "linear"
|
||||
y2AxisScaleType: z.enum(['log', 'linear']).default('linear')
|
||||
});
|
||||
|
||||
/**
|
||||
* Configuration options for the X-axis of a chart.
|
||||
*/
|
||||
export const XAxisConfigSchema = z.object({
|
||||
// The time interval for the X-axis. Only applies to combo and line charts. @default null
|
||||
xAxisTimeInterval: z.nullable(z.enum(['day', 'week', 'month', 'quarter', 'year'])).default(null),
|
||||
// Whether to show the axis label. Defaults to true.
|
||||
xAxisShowAxisLabel: z.boolean().default(true),
|
||||
// Whether to show the axis title. Defaults to true.
|
||||
xAxisShowAxisTitle: z.boolean().default(true),
|
||||
// The title of the X-axis. @default null - Uses a concatenation of all X columns applied to the axis
|
||||
xAxisAxisTitle: z.nullable(z.string()).default(null),
|
||||
// The rotation angle for the X-axis labels. @default "auto"
|
||||
xAxisLabelRotation: z
|
||||
.union([z.literal(0), z.literal(45), z.literal(90), z.literal('auto')])
|
||||
.default('auto'),
|
||||
// Whether to enable data zooming on the X-axis. Should only be set to true by the user. @default false
|
||||
xAxisDataZoom: z.boolean().default(false)
|
||||
});
|
||||
|
||||
//The category axis works differently than the other axes. It is used to color and group the data.
|
||||
/**
|
||||
* Configuration options for styling the category axis.
|
||||
* The category axis is used to color and group the data.
|
||||
*/
|
||||
export const CategoryAxisStyleConfigSchema = z.object({
|
||||
// The title of the category axis. @default null
|
||||
categoryAxisTitle: z.nullable(z.string()).default(null)
|
||||
});
|
||||
|
||||
// Export inferred types
|
||||
export type YAxisConfig = z.infer<typeof YAxisConfigSchema>;
|
||||
export type Y2AxisConfig = z.infer<typeof Y2AxisConfigSchema>;
|
||||
export type XAxisConfig = z.infer<typeof XAxisConfigSchema>;
|
||||
export type CategoryAxisStyleConfig = z.infer<typeof CategoryAxisStyleConfigSchema>;
|
|
@ -1,187 +0,0 @@
|
|||
import { ShareRole } from '../share/shareInterfaces';
|
||||
import { VerificationStatus } from '../share/verificationInterfaces';
|
||||
import { type ColumnLabelFormat, type ColumnSettings } from './charts';
|
||||
import { DEFAULT_CHART_THEME } from './charts/configColors';
|
||||
import type { ColumnMetaData } from './interfaces';
|
||||
import type { IBusterMetric, IBusterMetricChartConfig } from './requireInterfaces';
|
||||
|
||||
export const DEFAULT_CHART_CONFIG: IBusterMetricChartConfig = {
|
||||
colors: DEFAULT_CHART_THEME,
|
||||
selectedChartType: 'table',
|
||||
yAxisShowAxisLabel: true,
|
||||
yAxisShowAxisTitle: true,
|
||||
yAxisAxisTitle: null,
|
||||
yAxisStartAxisAtZero: null,
|
||||
yAxisScaleType: 'linear',
|
||||
y2AxisShowAxisLabel: true,
|
||||
y2AxisAxisTitle: null,
|
||||
y2AxisShowAxisTitle: true,
|
||||
y2AxisStartAxisAtZero: true,
|
||||
y2AxisScaleType: 'linear',
|
||||
xAxisTimeInterval: null,
|
||||
xAxisShowAxisLabel: true,
|
||||
xAxisShowAxisTitle: true,
|
||||
xAxisAxisTitle: null,
|
||||
xAxisLabelRotation: 'auto',
|
||||
xAxisDataZoom: false,
|
||||
categoryAxisTitle: null,
|
||||
showLegend: null,
|
||||
gridLines: true,
|
||||
goalLines: [],
|
||||
trendlines: [],
|
||||
showLegendHeadline: false,
|
||||
disableTooltip: false,
|
||||
barAndLineAxis: {
|
||||
x: [],
|
||||
y: [],
|
||||
category: [],
|
||||
tooltip: null
|
||||
},
|
||||
scatterAxis: {
|
||||
x: [],
|
||||
y: [],
|
||||
category: [],
|
||||
size: [],
|
||||
tooltip: null
|
||||
},
|
||||
comboChartAxis: {
|
||||
x: [],
|
||||
y: [],
|
||||
y2: [],
|
||||
category: [],
|
||||
tooltip: null
|
||||
},
|
||||
pieChartAxis: {
|
||||
x: [],
|
||||
y: [],
|
||||
tooltip: null
|
||||
},
|
||||
//LINE
|
||||
lineGroupType: null,
|
||||
//SCATTER
|
||||
scatterDotSize: [3, 15],
|
||||
//BAR
|
||||
barSortBy: [],
|
||||
barLayout: 'vertical',
|
||||
barGroupType: 'group',
|
||||
barShowTotalAtTop: false,
|
||||
//PIE
|
||||
pieShowInnerLabel: true,
|
||||
pieInnerLabelAggregate: 'sum',
|
||||
pieInnerLabelTitle: 'Total',
|
||||
pieLabelPosition: null,
|
||||
pieDonutWidth: 40,
|
||||
pieMinimumSlicePercentage: 0,
|
||||
pieDisplayLabelAs: 'number',
|
||||
pieSortBy: 'value',
|
||||
//METRIC
|
||||
metricColumnId: '',
|
||||
metricValueAggregate: 'sum',
|
||||
metricHeader: null,
|
||||
metricSubHeader: null,
|
||||
metricValueLabel: null,
|
||||
//TABLE
|
||||
tableColumnOrder: null,
|
||||
tableColumnWidths: null,
|
||||
tableHeaderBackgroundColor: null,
|
||||
tableHeaderFontColor: null,
|
||||
tableColumnFontColor: null,
|
||||
//MUST LOOP THROUGH ALL COLUMNS
|
||||
columnSettings: {},
|
||||
columnLabelFormats: {}
|
||||
};
|
||||
|
||||
export const DEFAULT_COLUMN_SETTINGS: Required<ColumnSettings> = {
|
||||
showDataLabels: false,
|
||||
columnVisualization: 'bar',
|
||||
lineWidth: 2,
|
||||
lineStyle: 'line',
|
||||
lineType: 'normal',
|
||||
lineSymbolSize: 0,
|
||||
barRoundness: 8,
|
||||
showDataLabelsAsPercentage: false
|
||||
};
|
||||
|
||||
export const DEFAULT_COLUMN_LABEL_FORMAT: Required<ColumnLabelFormat> = {
|
||||
style: 'string',
|
||||
compactNumbers: false,
|
||||
columnType: 'text',
|
||||
displayName: '',
|
||||
numberSeparatorStyle: ',',
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
currency: 'USD',
|
||||
convertNumberTo: null,
|
||||
dateFormat: 'auto',
|
||||
useRelativeTime: false,
|
||||
isUTC: false,
|
||||
multiplier: 1,
|
||||
prefix: '',
|
||||
suffix: '',
|
||||
replaceMissingDataWith: 0,
|
||||
makeLabelHumanReadable: true
|
||||
};
|
||||
|
||||
export const ENABLED_DOTS_ON_LINE = 3.5;
|
||||
export const DEFAULT_CHART_CONFIG_ENTRIES = Object.entries(DEFAULT_CHART_CONFIG);
|
||||
export const DEFAULT_BAR_ROUNDNESS = DEFAULT_COLUMN_SETTINGS.barRoundness;
|
||||
export const MIN_DONUT_WIDTH = 15;
|
||||
|
||||
export const DEFAULT_DAY_OF_WEEK_FORMAT = 'ddd';
|
||||
export const DEFAULT_DATE_FORMAT_DAY_OF_WEEK = 'dddd';
|
||||
export const DEFAULT_DATE_FORMAT_MONTH_OF_YEAR = 'MMMM';
|
||||
export const DEFAULT_DATE_FORMAT_QUARTER = 'YYYY [Q]Q';
|
||||
|
||||
export const ENABLED_DOTS_ON_LINE_SIZE = 4;
|
||||
export const DEFAULT_COLUMN_METADATA: ColumnMetaData[] = [];
|
||||
|
||||
export const DEFAULT_IBUSTER_METRIC: Required<IBusterMetric> = {
|
||||
id: 'DEFAULT_ID',
|
||||
type: 'metric',
|
||||
name: '',
|
||||
version_number: 1,
|
||||
description: '',
|
||||
time_frame: '',
|
||||
sql: null,
|
||||
dataset_id: '',
|
||||
dataset_name: null,
|
||||
error: null,
|
||||
data_metadata: null,
|
||||
status: VerificationStatus.NOT_REQUESTED,
|
||||
evaluation_score: 'Moderate',
|
||||
evaluation_summary: '',
|
||||
file_name: '',
|
||||
file: '',
|
||||
data_source_id: '',
|
||||
created_at: '',
|
||||
updated_at: '',
|
||||
sent_by_id: '',
|
||||
sent_by_name: '',
|
||||
permission: ShareRole.CAN_VIEW,
|
||||
sent_by_avatar_url: null,
|
||||
dashboards: [],
|
||||
collections: [],
|
||||
chart_config: DEFAULT_CHART_CONFIG,
|
||||
individual_permissions: null,
|
||||
public_expiry_date: null,
|
||||
public_enabled_by: null,
|
||||
publicly_accessible: false,
|
||||
public_password: null,
|
||||
versions: []
|
||||
};
|
||||
|
||||
export const DEFAULT_TRENDLINE_CONFIG: Required<IBusterMetricChartConfig['trendlines'][number]> = {
|
||||
id: 'DEFAULT_ID',
|
||||
columnId: '',
|
||||
show: true,
|
||||
showTrendlineLabel: false,
|
||||
trendlineLabel: null,
|
||||
type: 'linear_regression',
|
||||
trendLineColor: '#FF0000',
|
||||
trendlineLabelPositionOffset: 85,
|
||||
projection: true,
|
||||
lineStyle: 'solid',
|
||||
polynomialOrder: 2,
|
||||
aggregateAllCategories: true,
|
||||
offset: 0
|
||||
};
|
|
@ -1,6 +1,4 @@
|
|||
export * from './charts';
|
||||
export * from './defaults';
|
||||
export * from './interfaces';
|
||||
export * from './listInterfaces';
|
||||
export * from './metricDataInterfaces';
|
||||
export * from './requireInterfaces';
|
||||
|
|
|
@ -1,88 +1,3 @@
|
|||
import type { BusterShare, VerificationStatus } from '../share';
|
||||
import type { BusterChartConfigProps } from './charts';
|
||||
import type { Metric } from '@buster/server-shared/metrics';
|
||||
|
||||
export type BusterMetric = {
|
||||
id: string;
|
||||
type: 'metric';
|
||||
name: string;
|
||||
version_number: number;
|
||||
description: string | null;
|
||||
file_name: string;
|
||||
time_frame: string;
|
||||
dataset_id: string;
|
||||
data_source_id: string;
|
||||
dataset_name: string | null;
|
||||
error: string | null;
|
||||
chart_config?: BusterChartConfigProps;
|
||||
data_metadata: DataMetadata;
|
||||
status: VerificationStatus;
|
||||
evaluation_score: 'Moderate' | 'High' | 'Low';
|
||||
evaluation_summary: string;
|
||||
file: string; //yaml file
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
sent_by_id: string;
|
||||
sent_by_name: string;
|
||||
sent_by_avatar_url: string | null;
|
||||
sql: string | null;
|
||||
dashboards: {
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
collections: {
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
versions: {
|
||||
version_number: number;
|
||||
updated_at: string;
|
||||
}[];
|
||||
} & BusterShare;
|
||||
|
||||
export type DataMetadata = {
|
||||
column_count: number;
|
||||
column_metadata: ColumnMetaData[];
|
||||
row_count: number;
|
||||
} | null;
|
||||
|
||||
export type ColumnMetaData = {
|
||||
name: string;
|
||||
min_value: number | string;
|
||||
max_value: number | string;
|
||||
unique_values: number;
|
||||
simple_type: 'text' | 'number' | 'date';
|
||||
type:
|
||||
| 'text'
|
||||
| 'float'
|
||||
| 'integer'
|
||||
| 'date'
|
||||
| 'float8'
|
||||
| 'timestamp'
|
||||
| 'timestamptz'
|
||||
| 'bool'
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'boolean'
|
||||
| 'json'
|
||||
| 'jsonb'
|
||||
| 'int8'
|
||||
| 'int4'
|
||||
| 'int2'
|
||||
| 'decimal'
|
||||
| 'char'
|
||||
| 'character varying'
|
||||
| 'character'
|
||||
| 'varchar'
|
||||
| 'text'
|
||||
| 'number'
|
||||
| 'numeric'
|
||||
| 'tinytext'
|
||||
| 'mediumtext'
|
||||
| 'longtext'
|
||||
| 'nchar'
|
||||
| 'nvarchat'
|
||||
| 'ntext'
|
||||
| 'float4';
|
||||
};
|
||||
|
||||
export type IDataResult = Record<string, null | string | number>[] | null;
|
||||
export type BusterMetric = Metric;
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
import type { VerificationStatus } from '../share';
|
||||
import type { MetricListItem } from '@buster/server-shared/metrics';
|
||||
|
||||
export type BusterMetricListItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
last_edited: string;
|
||||
dataset_name: string;
|
||||
dataset_uuid: string;
|
||||
created_by_id: string;
|
||||
created_by_name: string;
|
||||
created_by_email: string;
|
||||
created_by_avatar: string;
|
||||
status: VerificationStatus;
|
||||
is_shared: boolean;
|
||||
};
|
||||
export type BusterMetricListItem = MetricListItem;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import type { DataMetadata, IDataResult } from './interfaces';
|
||||
import type { DataMetadata, DataResult } from '@buster/server-shared/metrics';
|
||||
|
||||
export type BusterMetricData = {
|
||||
data: IDataResult | null;
|
||||
data: DataResult | null;
|
||||
data_metadata: DataMetadata;
|
||||
metricId: string;
|
||||
};
|
||||
|
||||
export type IBusterMetricData = {
|
||||
data: IDataResult | null;
|
||||
dataFromRerun?: IDataResult; //this is actually only used in the UI. maybe move this to ?
|
||||
export type BusterMetricDataExtended = {
|
||||
data: DataResult | null;
|
||||
dataFromRerun?: DataResult; //this is actually only used in the UI. maybe move this to ?
|
||||
data_metadata: DataMetadata;
|
||||
runRunDataMetadata?: DataMetadata;
|
||||
metricId: string;
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import type { BusterChartConfigProps, ColumnSettings, IColumnLabelFormat } from './charts';
|
||||
import type { BusterMetric } from './interfaces';
|
||||
|
||||
export type IBusterMetricChartConfig = Required<
|
||||
Omit<BusterChartConfigProps, 'columnLabelFormats'>
|
||||
> & {
|
||||
columnLabelFormats: Record<string, Required<IColumnLabelFormat>>;
|
||||
columnSettings: Required<Record<string, Required<ColumnSettings>>>;
|
||||
};
|
||||
|
||||
export interface IBusterMetric extends Required<BusterMetric> {
|
||||
chart_config: IBusterMetricChartConfig;
|
||||
}
|
|
@ -6,9 +6,9 @@ import {
|
|||
} from '@tanstack/react-query';
|
||||
import last from 'lodash/last';
|
||||
import type {
|
||||
BusterMetric,
|
||||
BusterMetricData,
|
||||
IBusterMetric,
|
||||
IBusterMetricData
|
||||
BusterMetricDataExtended
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import { metricsQueryKeys } from '@/api/query_keys/metric';
|
||||
import { useBusterAssetsContextSelector } from '@/context/Assets/BusterAssetsProvider';
|
||||
|
@ -19,7 +19,7 @@ import type { RustApiError } from '../errors';
|
|||
import { useGetMetricVersionNumber, useMetricQueryStore } from './metricQueryStore';
|
||||
import { getMetric, getMetricData } from './requests';
|
||||
|
||||
export const useGetMetric = <TData = IBusterMetric>(
|
||||
export const useGetMetric = <TData = BusterMetric>(
|
||||
{
|
||||
id,
|
||||
versionNumber: versionNumberProp
|
||||
|
@ -27,7 +27,7 @@ export const useGetMetric = <TData = IBusterMetric>(
|
|||
id: string | undefined;
|
||||
versionNumber?: number | null; //if null it will not use a params from the query params
|
||||
},
|
||||
params?: Omit<UseQueryOptions<IBusterMetric, RustApiError, TData>, 'queryKey' | 'queryFn'>
|
||||
params?: Omit<UseQueryOptions<BusterMetric, RustApiError, TData>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
const setOriginalMetric = useOriginalMetricStore((x) => x.setOriginalMetric);
|
||||
|
@ -108,7 +108,7 @@ export const usePrefetchGetMetricClient = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export const useGetMetricData = <TData = IBusterMetricData>(
|
||||
export const useGetMetricData = <TData = BusterMetricDataExtended>(
|
||||
{
|
||||
id,
|
||||
versionNumber: versionNumberProp
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import type {
|
||||
BusterChartConfigProps,
|
||||
BusterMetric,
|
||||
BusterMetricData,
|
||||
BusterMetricListItem
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
import type { VerificationStatus } from '@/api/asset_interfaces/share';
|
||||
import type {
|
||||
ShareDeleteRequest,
|
||||
|
@ -72,7 +72,7 @@ export const updateMetric = async (params: {
|
|||
/** SQL query associated with the metric */
|
||||
sql?: string;
|
||||
/** chart_config to update */
|
||||
chart_config?: BusterChartConfigProps;
|
||||
chart_config?: ChartConfigProps;
|
||||
/** file in yaml format to update */
|
||||
file?: string;
|
||||
/** update the version number of the metric - default is true */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { create } from 'mutative';
|
||||
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { collectionQueryKeys } from '@/api/query_keys/collection';
|
||||
import { metricsQueryKeys } from '@/api/query_keys/metric';
|
||||
import { useOriginalMetricStore } from '@/context/Metrics/useOriginalMetricStore';
|
||||
|
@ -225,9 +225,9 @@ export const useShareMetric = () => {
|
|||
variables.id,
|
||||
selectedVersionNumber
|
||||
).queryKey;
|
||||
queryClient.setQueryData(queryKey, (previousData: IBusterMetric | undefined) => {
|
||||
queryClient.setQueryData(queryKey, (previousData: BusterMetric | undefined) => {
|
||||
if (!previousData) return previousData;
|
||||
return create(previousData, (draft: IBusterMetric) => {
|
||||
return create(previousData, (draft: BusterMetric) => {
|
||||
draft.individual_permissions = [
|
||||
...variables.params,
|
||||
...(draft.individual_permissions || [])
|
||||
|
@ -260,9 +260,9 @@ export const useUnshareMetric = () => {
|
|||
variables.id,
|
||||
selectedVersionNumber
|
||||
).queryKey;
|
||||
queryClient.setQueryData(queryKey, (previousData: IBusterMetric | undefined) => {
|
||||
queryClient.setQueryData(queryKey, (previousData: BusterMetric | undefined) => {
|
||||
if (!previousData) return previousData;
|
||||
return create(previousData, (draft: IBusterMetric) => {
|
||||
return create(previousData, (draft: BusterMetric) => {
|
||||
draft.individual_permissions =
|
||||
draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || [];
|
||||
});
|
||||
|
@ -293,9 +293,9 @@ export const useUpdateMetricShare = () => {
|
|||
variables.id,
|
||||
selectedVersionNumber
|
||||
).queryKey;
|
||||
queryClient.setQueryData(queryKey, (previousData: IBusterMetric | undefined) => {
|
||||
queryClient.setQueryData(queryKey, (previousData: BusterMetric | undefined) => {
|
||||
if (!previousData) return previousData;
|
||||
return create(previousData, (draft: IBusterMetric) => {
|
||||
return create(previousData, (draft: BusterMetric) => {
|
||||
draft.individual_permissions =
|
||||
draft.individual_permissions?.map((t) => {
|
||||
const found = variables.params.users?.find((v) => v.email === t.email);
|
||||
|
@ -330,7 +330,7 @@ export const useUpdateMetric = (params: {
|
|||
const { selectedVersionNumber } = useGetMetricVersionNumber();
|
||||
|
||||
const saveMetricToServer = useMemoizedFn(
|
||||
async (newMetric: IBusterMetric, prevMetric: IBusterMetric) => {
|
||||
async (newMetric: BusterMetric, prevMetric: BusterMetric) => {
|
||||
const changedValues = prepareMetricUpdateMetric(newMetric, prevMetric);
|
||||
if (changedValues) {
|
||||
await saveMetric({ ...changedValues, update_version: updateVersion });
|
||||
|
@ -342,7 +342,7 @@ export const useUpdateMetric = (params: {
|
|||
({
|
||||
id: metricId,
|
||||
...newMetricPartial
|
||||
}: Omit<Partial<IBusterMetric>, 'status'> & { id: string }) => {
|
||||
}: Omit<Partial<BusterMetric>, 'status'> & { id: string }) => {
|
||||
const options = metricsQueryKeys.metricsGetMetric(metricId, selectedVersionNumber);
|
||||
const prevMetric = getOriginalMetric(metricId);
|
||||
const newMetric = create(prevMetric, (draft) => {
|
||||
|
@ -358,7 +358,7 @@ export const useUpdateMetric = (params: {
|
|||
);
|
||||
|
||||
const mutationFn = useMemoizedFn(
|
||||
async (newMetricPartial: Omit<Partial<IBusterMetric>, 'status'> & { id: string }) => {
|
||||
async (newMetricPartial: Omit<Partial<BusterMetric>, 'status'> & { id: string }) => {
|
||||
const { newMetric, prevMetric } = combineAndSaveMetric(newMetricPartial);
|
||||
|
||||
if (newMetric && prevMetric && saveToServer) {
|
||||
|
@ -389,13 +389,13 @@ export const useBulkUpdateMetricVerificationStatus = () => {
|
|||
onMutate: (variables) => {
|
||||
for (const metric of variables) {
|
||||
const latestVersionNumber = getLatestMetricVersion(metric.id);
|
||||
const foundMetric = queryClient.getQueryData<IBusterMetric>(
|
||||
const foundMetric = queryClient.getQueryData<BusterMetric>(
|
||||
metricsQueryKeys.metricsGetMetric(metric.id, latestVersionNumber).queryKey
|
||||
);
|
||||
if (foundMetric) {
|
||||
queryClient.setQueryData(
|
||||
metricsQueryKeys.metricsGetMetric(metric.id, latestVersionNumber).queryKey,
|
||||
create(foundMetric, (draft: IBusterMetric) => {
|
||||
create(foundMetric, (draft: BusterMetric) => {
|
||||
draft.status = metric.status;
|
||||
})
|
||||
);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { queryOptions } from '@tanstack/react-query';
|
||||
import type {
|
||||
BusterMetricListItem,
|
||||
IBusterMetric,
|
||||
IBusterMetricData
|
||||
BusterMetric,
|
||||
BusterMetricDataExtended
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import type { listMetrics } from '../buster_rest/metrics';
|
||||
|
||||
export const metricsGetMetric = (metricId: string, version_number: number | null) => {
|
||||
return queryOptions<IBusterMetric>({
|
||||
return queryOptions<BusterMetric>({
|
||||
queryKey: ['metrics', 'get', metricId, version_number || 'INITIAL'] as const,
|
||||
staleTime: 60 * 1000
|
||||
});
|
||||
|
@ -27,7 +27,7 @@ export const metricsGetList = (
|
|||
});
|
||||
|
||||
export const metricsGetData = (id: string, version_number: number) =>
|
||||
queryOptions<IBusterMetricData>({
|
||||
queryOptions<BusterMetricDataExtended>({
|
||||
queryKey: ['metrics', 'data', id, version_number || 'INITIAL'] as const,
|
||||
staleTime: 3 * 60 * 60 * 1000 // 3 hours,
|
||||
});
|
||||
|
|
|
@ -2,11 +2,11 @@ import type {
|
|||
BusterCollection,
|
||||
BusterDashboardResponse,
|
||||
BusterShare,
|
||||
IBusterMetric
|
||||
BusterMetric
|
||||
} from '@/api/asset_interfaces';
|
||||
|
||||
export const getShareAssetConfig = (
|
||||
message: IBusterMetric | BusterDashboardResponse | BusterCollection | null
|
||||
message: BusterMetric | BusterDashboardResponse | BusterCollection | null
|
||||
): BusterShare | null => {
|
||||
if (!message) return null;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import type React from 'react';
|
||||
import { useEffect, useMemo, useState, useTransition } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import type {
|
||||
BusterChartProps,
|
||||
ChartEncodes,
|
||||
|
@ -28,7 +28,7 @@ interface UseBusterChartJSLegendProps {
|
|||
selectedChartType: ChartType;
|
||||
chartMounted: boolean;
|
||||
selectedAxis: ChartEncodes | undefined;
|
||||
showLegendHeadline: IBusterMetricChartConfig['showLegendHeadline'] | undefined;
|
||||
showLegendHeadline: BusterMetricChartConfig['showLegendHeadline'] | undefined;
|
||||
columnLabelFormats: NonNullable<BusterChartProps['columnLabelFormats']>;
|
||||
loading: boolean;
|
||||
lineGroupType: BusterChartProps['lineGroupType'];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useMemo } from 'react';
|
||||
import type { BusterChartConfigProps } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
import { formatLabel } from '@/lib/columnFormatter';
|
||||
import { AXIS_TITLE_SEPARATOR } from '../../../../commonHelpers/axisHelper';
|
||||
import { truncateWithEllipsis } from '../../../../commonHelpers/titleHelpers';
|
||||
|
@ -12,10 +12,10 @@ export const useY2AxisTitle = ({
|
|||
y2AxisShowAxisTitle
|
||||
}: {
|
||||
y2Axis: string[];
|
||||
columnLabelFormats: NonNullable<BusterChartConfigProps['columnLabelFormats']>;
|
||||
columnLabelFormats: NonNullable<ChartConfigProps['columnLabelFormats']>;
|
||||
isSupportedChartForAxisTitles: boolean;
|
||||
y2AxisAxisTitle: BusterChartConfigProps['y2AxisAxisTitle'];
|
||||
y2AxisShowAxisTitle: BusterChartConfigProps['y2AxisShowAxisTitle'];
|
||||
y2AxisAxisTitle: ChartConfigProps['y2AxisAxisTitle'];
|
||||
y2AxisShowAxisTitle: ChartConfigProps['y2AxisShowAxisTitle'];
|
||||
}) => {
|
||||
const y2AxisColumnLabelFormats = useMemo(() => {
|
||||
return y2Axis.map((y) => columnLabelFormats[y]);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import type { CoreInteractionOptions } from 'chart.js';
|
||||
import { useMemo } from 'react';
|
||||
import type { DeepPartial } from 'utility-types'; // Add this import
|
||||
import type { BusterChartConfigProps } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
|
||||
interface UseInteractionsProps {
|
||||
selectedChartType: BusterChartConfigProps['selectedChartType'];
|
||||
barLayout: BusterChartConfigProps['barLayout'];
|
||||
selectedChartType: ChartConfigProps['selectedChartType'];
|
||||
barLayout: ChartConfigProps['barLayout'];
|
||||
}
|
||||
|
||||
export const useInteractions = ({ selectedChartType, barLayout }: UseInteractionsProps) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Chart, ChartTypeRegistry, TooltipItem } from 'chart.js';
|
||||
import type { BusterChartConfigProps } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
import { formatLabel } from '@/lib';
|
||||
import type { ITooltipItem } from '../../../../BusterChartTooltip/interfaces';
|
||||
import { getPercentage } from './helpers';
|
||||
|
@ -7,7 +7,7 @@ import { getPercentage } from './helpers';
|
|||
export const barAndLineTooltipHelper = (
|
||||
dataPoints: TooltipItem<keyof ChartTypeRegistry>[],
|
||||
chart: Chart,
|
||||
columnLabelFormats: NonNullable<BusterChartConfigProps['columnLabelFormats']>,
|
||||
columnLabelFormats: NonNullable<ChartConfigProps['columnLabelFormats']>,
|
||||
keyToUsePercentage: string[],
|
||||
hasMultipleShownDatasets: boolean,
|
||||
percentageMode: undefined | 'stacked'
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import type { ChartTypeRegistry, TooltipItem } from 'chart.js';
|
||||
import type { BusterChartConfigProps } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
import { formatLabel } from '@/lib/columnFormatter';
|
||||
import type { ITooltipItem } from '../../../../BusterChartTooltip/interfaces';
|
||||
|
||||
export const scatterTooltipHelper = (
|
||||
dataPoints: TooltipItem<keyof ChartTypeRegistry>[],
|
||||
columnLabelFormats: NonNullable<BusterChartConfigProps['columnLabelFormats']>
|
||||
columnLabelFormats: NonNullable<ChartConfigProps['columnLabelFormats']>
|
||||
): ITooltipItem[] => {
|
||||
return dataPoints.slice(0, 1).flatMap<ITooltipItem>((dataPoint) => {
|
||||
const dataPointDataset = dataPoint.dataset;
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import type { Scale, ScaleChartOptions } from 'chart.js';
|
||||
import { useMemo } from 'react';
|
||||
import type { DeepPartial } from 'utility-types';
|
||||
import { DEFAULT_CHART_CONFIG, DEFAULT_COLUMN_LABEL_FORMAT } from '@/api/asset_interfaces/metric';
|
||||
import {
|
||||
type BusterChartConfigProps,
|
||||
type BusterChartProps,
|
||||
type ChartEncodes,
|
||||
ChartType,
|
||||
type ComboChartAxis,
|
||||
type IColumnLabelFormat
|
||||
} from '@/api/asset_interfaces/metric/charts';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { formatYAxisLabel, yAxisSimilar } from '../../../commonHelpers';
|
||||
import { useY2AxisTitle } from './axisHooks/useY2AxisTitle';
|
||||
import {
|
||||
DEFAULT_CHART_CONFIG,
|
||||
DEFAULT_COLUMN_LABEL_FORMAT,
|
||||
type ChartConfigProps,
|
||||
type ChartEncodes,
|
||||
type ChartType,
|
||||
type ColumnLabelFormat,
|
||||
type ComboChartAxis
|
||||
} from '@buster/server-shared/metrics';
|
||||
import type { BusterChartProps } from '@/api/asset_interfaces';
|
||||
|
||||
export const useY2Axis = ({
|
||||
columnLabelFormats,
|
||||
|
@ -24,7 +25,7 @@ export const useY2Axis = ({
|
|||
y2AxisStartAxisAtZero,
|
||||
y2AxisScaleType
|
||||
}: {
|
||||
columnLabelFormats: NonNullable<BusterChartConfigProps['columnLabelFormats']>;
|
||||
columnLabelFormats: NonNullable<ChartConfigProps['columnLabelFormats']>;
|
||||
selectedAxis: ChartEncodes;
|
||||
selectedChartType: ChartType;
|
||||
y2AxisAxisTitle: BusterChartProps['y2AxisAxisTitle'];
|
||||
|
@ -64,10 +65,10 @@ export const useY2Axis = ({
|
|||
return y2AxisScaleType === 'log' ? 'logarithmic' : 'linear';
|
||||
}, [y2AxisScaleType, isSupportedType]);
|
||||
|
||||
const y2AxisColumnFormats: Record<string, IColumnLabelFormat> = useMemo(() => {
|
||||
const y2AxisColumnFormats: Record<string, ColumnLabelFormat> = useMemo(() => {
|
||||
if (!isSupportedType) return {};
|
||||
|
||||
return y2AxisKeys.reduce<Record<string, IColumnLabelFormat>>((acc, y) => {
|
||||
return y2AxisKeys.reduce<Record<string, ColumnLabelFormat>>((acc, y) => {
|
||||
acc[y] = columnLabelFormats[y] || DEFAULT_COLUMN_LABEL_FORMAT;
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterChartProps, ShowLegendHeadline } from '@/api/asset_interfaces/metric/charts';
|
||||
import { formatLabel } from '@/lib/columnFormatter';
|
||||
import { ArrayOperations } from '@/lib/math';
|
||||
|
@ -11,7 +11,7 @@ export const addLegendHeadlines = (
|
|||
showLegendHeadline: ShowLegendHeadline,
|
||||
columnMetadata: NonNullable<BusterChartProps['columnMetadata']>,
|
||||
columnLabelFormats: NonNullable<BusterChartProps['columnLabelFormats']>,
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'],
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'],
|
||||
xAxisKeys: string[]
|
||||
) => {
|
||||
const isScatterChart = selectedChartType === 'scatter';
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, { useCallback } from 'react';
|
|||
import {
|
||||
type BusterChartPropsBase,
|
||||
DEFAULT_CHART_CONFIG,
|
||||
type IBusterMetricChartConfig
|
||||
type BusterMetricChartConfig
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import { AppDataGrid } from '@/components/ui/table/AppDataGrid';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
|
@ -30,7 +30,7 @@ const BusterTableChartBase: React.FC<BusterTableChartProps> = ({
|
|||
}) => {
|
||||
const { onUpdateMetricChartConfig, onInitializeTableColumnWidths } = useUpdateMetricChart();
|
||||
|
||||
const onChangeConfig = useMemoizedFn((config: Partial<IBusterMetricChartConfig>) => {
|
||||
const onChangeConfig = useMemoizedFn((config: Partial<BusterMetricChartConfig>) => {
|
||||
if (readOnly) return;
|
||||
onUpdateMetricChartConfig({ chartConfig: config });
|
||||
if (
|
||||
|
@ -42,7 +42,7 @@ const BusterTableChartBase: React.FC<BusterTableChartProps> = ({
|
|||
});
|
||||
|
||||
const onUpdateTableColumnOrder = useMemoizedFn((columns: string[]) => {
|
||||
const config: Partial<IBusterMetricChartConfig> = {
|
||||
const config: Partial<BusterMetricChartConfig> = {
|
||||
tableColumnOrder: columns
|
||||
};
|
||||
|
||||
|
@ -51,7 +51,7 @@ const BusterTableChartBase: React.FC<BusterTableChartProps> = ({
|
|||
|
||||
const onUpdateTableColumnSize = useMemoizedFn((columns: { key: string; size: number }[]) => {
|
||||
if (readOnly) return;
|
||||
const config: Partial<IBusterMetricChartConfig> = {
|
||||
const config: Partial<BusterMetricChartConfig> = {
|
||||
tableColumnWidths: columns.reduce<Record<string, number>>((acc, { key, size }) => {
|
||||
acc[key] = Number(size.toFixed(1));
|
||||
return acc;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { BusterChartConfigProps } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
|
||||
export const InnerLabelTitleRecord: Record<
|
||||
NonNullable<BusterChartConfigProps['pieInnerLabelAggregate']>,
|
||||
NonNullable<ChartConfigProps['pieInnerLabelAggregate']>,
|
||||
string
|
||||
> = {
|
||||
sum: 'Total',
|
||||
|
@ -13,8 +13,8 @@ export const InnerLabelTitleRecord: Record<
|
|||
};
|
||||
|
||||
export const getPieInnerLabelTitle = (
|
||||
pieInnerLabelTitle: BusterChartConfigProps['pieInnerLabelTitle'],
|
||||
pieInnerLabelAggregate: BusterChartConfigProps['pieInnerLabelAggregate'] = 'sum'
|
||||
pieInnerLabelTitle: ChartConfigProps['pieInnerLabelTitle'],
|
||||
pieInnerLabelAggregate: ChartConfigProps['pieInnerLabelAggregate'] = 'sum'
|
||||
) => {
|
||||
return pieInnerLabelTitle ?? InnerLabelTitleRecord[pieInnerLabelAggregate];
|
||||
};
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
'use client';
|
||||
|
||||
import type { BusterDashboardResponse } from '@/api/asset_interfaces/dashboard';
|
||||
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { HydrationBoundaryDashboardStore } from '../Dashboards/useOriginalDashboardStore';
|
||||
import { HydrationBoundaryMetricStore } from '../Metrics/useOriginalMetricStore';
|
||||
|
||||
export const HydrationBoundaryAssetStore: React.FC<{
|
||||
children: React.ReactNode;
|
||||
asset: IBusterMetric | BusterDashboardResponse | undefined;
|
||||
asset: BusterMetric | BusterDashboardResponse | undefined;
|
||||
}> = ({ children, asset }) => {
|
||||
if (!asset) return <>{children}</>;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import type { IBusterMetric, IBusterMetricData } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetric, BusterMetricDataExtended } from '@/api/asset_interfaces/metric';
|
||||
import { useGetMetricVersionNumber } from '@/api/buster_rest/metrics';
|
||||
import { queryKeys } from '@/api/query_keys';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
|
@ -9,7 +9,7 @@ export const useGetMetricMemoized = () => {
|
|||
const queryClient = useQueryClient();
|
||||
const { selectedVersionNumber } = useGetMetricVersionNumber();
|
||||
const getMetricMemoized = useMemoizedFn(
|
||||
(metricId: string, versionNumberProp?: number): IBusterMetric => {
|
||||
(metricId: string, versionNumberProp?: number): BusterMetric => {
|
||||
const options = queryKeys.metricsGetMetric(
|
||||
metricId,
|
||||
versionNumberProp || selectedVersionNumber
|
||||
|
@ -25,7 +25,7 @@ export const useGetMetricDataMemoized = () => {
|
|||
const queryClient = useQueryClient();
|
||||
const { selectedVersionNumber, latestVersionNumber } = useGetMetricVersionNumber();
|
||||
const getMetricDataMemoized = useMemoizedFn(
|
||||
(metricId: string, versionNumberProp?: number): IBusterMetricData | undefined => {
|
||||
(metricId: string, versionNumberProp?: number): BusterMetricDataExtended | undefined => {
|
||||
const versionNumber = versionNumberProp ?? selectedVersionNumber ?? latestVersionNumber;
|
||||
if (versionNumber == null) return undefined;
|
||||
const options = queryKeys.metricsGetData(metricId, versionNumber);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { act, renderHook } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { DEFAULT_CHART_CONFIG } from '@/api/asset_interfaces/metric/defaults';
|
||||
import { VerificationStatus } from '@/api/asset_interfaces/share';
|
||||
import { ShareRole } from '@/api/asset_interfaces/share/shareInterfaces';
|
||||
|
@ -13,7 +13,7 @@ describe('useOriginalMetricStore', () => {
|
|||
});
|
||||
|
||||
it('should correctly set and get a metric', () => {
|
||||
const mockMetric: IBusterMetric = {
|
||||
const mockMetric: BusterMetric = {
|
||||
id: 'test-metric-1',
|
||||
type: 'metric' as const,
|
||||
name: 'Test Metric',
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
'use client';
|
||||
|
||||
import { create } from 'zustand';
|
||||
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { useMount } from '@/hooks';
|
||||
|
||||
type OriginalMetricStore = {
|
||||
originalMetrics: Record<string, IBusterMetric>;
|
||||
bulkAddOriginalMetrics: (metrics: Record<string, IBusterMetric>) => void;
|
||||
setOriginalMetric: (metric: IBusterMetric) => void;
|
||||
getOriginalMetric: (metricId: string | undefined) => IBusterMetric | undefined;
|
||||
originalMetrics: Record<string, BusterMetric>;
|
||||
bulkAddOriginalMetrics: (metrics: Record<string, BusterMetric>) => void;
|
||||
setOriginalMetric: (metric: BusterMetric) => void;
|
||||
getOriginalMetric: (metricId: string | undefined) => BusterMetric | undefined;
|
||||
removeOriginalMetric: (metricId: string) => void;
|
||||
};
|
||||
|
||||
export const useOriginalMetricStore = create<OriginalMetricStore>((set, get) => ({
|
||||
originalMetrics: {},
|
||||
bulkAddOriginalMetrics: (metrics: Record<string, IBusterMetric>) =>
|
||||
bulkAddOriginalMetrics: (metrics: Record<string, BusterMetric>) =>
|
||||
set((prev) => ({
|
||||
originalMetrics: {
|
||||
...prev.originalMetrics,
|
||||
...metrics
|
||||
}
|
||||
})),
|
||||
setOriginalMetric: (metric: IBusterMetric) =>
|
||||
setOriginalMetric: (metric: BusterMetric) =>
|
||||
set((state) => ({
|
||||
originalMetrics: {
|
||||
...state.originalMetrics,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useState } from 'react';
|
|||
import {
|
||||
type ColumnSettings,
|
||||
DEFAULT_CHART_CONFIG,
|
||||
type IBusterMetricChartConfig,
|
||||
type BusterMetricChartConfig,
|
||||
type IColumnLabelFormat
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import { useUpdateMetric } from '@/api/buster_rest/metrics';
|
||||
|
@ -39,7 +39,7 @@ export const useUpdateMetricChart = (props?: { metricId?: string; chatId?: strin
|
|||
chartConfig,
|
||||
ignoreUndoRedo
|
||||
}: {
|
||||
chartConfig: Partial<IBusterMetricChartConfig>;
|
||||
chartConfig: Partial<BusterMetricChartConfig>;
|
||||
ignoreUndoRedo?: boolean;
|
||||
}) => {
|
||||
const currentMetric = getMetricMemoized(metricId);
|
||||
|
@ -52,7 +52,7 @@ export const useUpdateMetricChart = (props?: { metricId?: string; chatId?: strin
|
|||
// });
|
||||
}
|
||||
|
||||
const newChartConfig: IBusterMetricChartConfig = {
|
||||
const newChartConfig: BusterMetricChartConfig = {
|
||||
...DEFAULT_CHART_CONFIG,
|
||||
...currentMetric.chart_config,
|
||||
...chartConfig
|
||||
|
@ -129,10 +129,10 @@ export const useUpdateMetricChart = (props?: { metricId?: string; chatId?: strin
|
|||
});
|
||||
|
||||
const onInitializeTableColumnWidths = useMemoizedFn(
|
||||
(tableColumnWidths: IBusterMetricChartConfig['tableColumnWidths']) => {
|
||||
(tableColumnWidths: BusterMetricChartConfig['tableColumnWidths']) => {
|
||||
const originalMetric = getOriginalMetric(metricId);
|
||||
if (originalMetric) {
|
||||
const newChartConfig: IBusterMetricChartConfig = {
|
||||
const newChartConfig: BusterMetricChartConfig = {
|
||||
...DEFAULT_CHART_CONFIG,
|
||||
...originalMetric.chart_config,
|
||||
tableColumnWidths
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { Button, type ButtonProps } from '@/components/ui/buttons';
|
||||
import {
|
||||
CircleCheck,
|
||||
|
@ -9,7 +9,7 @@ import {
|
|||
import { Popover } from '@/components/ui/popover/Popover';
|
||||
|
||||
export const MetricChartEvaluation: React.FC<{
|
||||
evaluationScore: IBusterMetric['evaluation_score'] | undefined;
|
||||
evaluationScore: BusterMetric['evaluation_score'] | undefined;
|
||||
evaluationSummary: string | undefined;
|
||||
}> = React.memo(({ evaluationScore, evaluationSummary }) => {
|
||||
const text = useMemo(() => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { AppSegmented, type SegmentedItem } from '@/components/ui/segmented';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
@ -8,7 +8,7 @@ import { MetricStylingAppSegments } from './config';
|
|||
export const MetricStylingAppSegment: React.FC<{
|
||||
segment: MetricStylingAppSegments;
|
||||
setSegment: (segment: MetricStylingAppSegments) => void;
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
className?: string;
|
||||
}> = React.memo(({ segment, setSegment, selectedChartType, className = '' }) => {
|
||||
const isTable = selectedChartType === 'table';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import isEqual from 'lodash/isEqual';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import type { IColorTheme } from '../Common';
|
||||
import { ThemeList } from '../Common/ThemeList';
|
||||
|
@ -8,8 +8,8 @@ import { ColorStyleSegments } from './ColorStyleSegments';
|
|||
import { COLORFUL_THEMES, ColorAppSegments, MONOCHROME_THEMES } from './config';
|
||||
|
||||
export const ColorsApp: React.FC<{
|
||||
colors: IBusterMetricChartConfig['colors'];
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
colors: BusterMetricChartConfig['colors'];
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = ({ colors, onUpdateChartConfig }) => {
|
||||
const initialSelectedSegment = useMemo(() => {
|
||||
const isFromColorfulThemes = COLORFUL_THEMES.some((theme) => isEqual(theme.colors, colors));
|
||||
|
@ -44,7 +44,7 @@ export const ColorsApp: React.FC<{
|
|||
|
||||
const ColorPicker: React.FC<{
|
||||
selectedSegmentColors: IColorTheme[];
|
||||
colors: IBusterMetricChartConfig['colors'];
|
||||
colors: BusterMetricChartConfig['colors'];
|
||||
onChangeColorTheme: (theme: IColorTheme) => void;
|
||||
}> = React.memo(({ selectedSegmentColors, colors, onChangeColorTheme }) => {
|
||||
const themes = useMemo(() => {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { DEFAULT_CHART_THEME } from '@/api/asset_interfaces/metric/charts/configColors';
|
||||
import {
|
||||
BLUE_THEME,
|
||||
BLUE_TO_ORANGE_GRADIENT,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
|
||||
export const PaletteApp: React.FC<{
|
||||
colors: IBusterMetricChartConfig['colors'];
|
||||
colors: BusterMetricChartConfig['colors'];
|
||||
}> = React.memo(({ colors }) => {
|
||||
return (
|
||||
<div className="flex h-full min-h-[200px] items-center justify-center">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import React, { useState } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
|
@ -11,13 +11,13 @@ import { PaletteApp } from './PaletteApp';
|
|||
|
||||
export const StylingAppColors: React.FC<{
|
||||
className: string;
|
||||
colors: IBusterMetricChartConfig['colors'];
|
||||
colors: BusterMetricChartConfig['colors'];
|
||||
}> = React.memo(({ className, colors }) => {
|
||||
const [selectedTab, setSelectedTab] = useState<StylingAppColorsTab>(StylingAppColorsTab.Colors);
|
||||
|
||||
const { onUpdateMetricChartConfig } = useUpdateMetricChart();
|
||||
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<IBusterMetricChartConfig>) => {
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<BusterMetricChartConfig>) => {
|
||||
onUpdateMetricChartConfig({ chartConfig });
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BarSortBy } from '@/api/asset_interfaces/metric/charts';
|
||||
import { BarChartSortNoneIcon } from '@/components/ui/icons/customIcons/BarChart_NoSort';
|
||||
import { BarChartSortAscIcon } from '@/components/ui/icons/customIcons/BarChartSortAscIcon';
|
||||
|
@ -27,8 +27,8 @@ const options: SegmentedItem<BarSortBy[0]>[] = [
|
|||
];
|
||||
|
||||
export const EditBarSorting: React.FC<{
|
||||
barSortBy: IBusterMetricChartConfig['barSortBy'];
|
||||
onUpdateChartConfig: (v: Partial<IBusterMetricChartConfig>) => void;
|
||||
barSortBy: BusterMetricChartConfig['barSortBy'];
|
||||
onUpdateChartConfig: (v: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ barSortBy, onUpdateChartConfig }) => {
|
||||
const selectedOption = useMemo(() => {
|
||||
return (
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnSettings } from '@/api/asset_interfaces/metric/charts';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { EditBarRoundness } from '../StylingAppVisualize/SelectAxis/SelectAxisColumnContent/EditBarRoundness';
|
||||
|
||||
export const EditBarRoundnessGlobal: React.FC<{
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings'];
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
columnSettings: BusterMetricChartConfig['columnSettings'];
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ columnSettings, onUpdateChartConfig }) => {
|
||||
const mostPermissiveBarRoundness = useMemo(() => {
|
||||
return Object.values(columnSettings).reduce((acc, curr) => {
|
||||
|
@ -15,9 +15,9 @@ export const EditBarRoundnessGlobal: React.FC<{
|
|||
}, []);
|
||||
|
||||
const onUpdateBarRoundness = useMemoizedFn((v: Partial<ColumnSettings>) => {
|
||||
const newColumnSettings: IBusterMetricChartConfig['columnSettings'] = Object.keys(
|
||||
const newColumnSettings: BusterMetricChartConfig['columnSettings'] = Object.keys(
|
||||
columnSettings
|
||||
).reduce<IBusterMetricChartConfig['columnSettings']>((acc, curr) => {
|
||||
).reduce<BusterMetricChartConfig['columnSettings']>((acc, curr) => {
|
||||
acc[curr] = { ...columnSettings[curr], ...v };
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { ENABLED_DOTS_ON_LINE } from '@/api/asset_interfaces';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
export const EditDotsOnLineGlobal: React.FC<{
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
columnSettings: BusterMetricChartConfig['columnSettings'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ columnSettings, onUpdateChartConfig }) => {
|
||||
const allDotsOnLine = useMemo(() => {
|
||||
return Object.values(columnSettings).some((column) => column.lineSymbolSize > 0);
|
||||
|
@ -15,12 +15,13 @@ export const EditDotsOnLineGlobal: React.FC<{
|
|||
|
||||
const onChangeAllSmooth = useMemoizedFn((value: boolean) => {
|
||||
onUpdateChartConfig({
|
||||
columnSettings: Object.keys(columnSettings).reduce<
|
||||
IBusterMetricChartConfig['columnSettings']
|
||||
>((acc, curr) => {
|
||||
acc[curr] = { ...columnSettings[curr], lineSymbolSize: value ? ENABLED_DOTS_ON_LINE : 0 };
|
||||
return acc;
|
||||
}, {})
|
||||
columnSettings: Object.keys(columnSettings).reduce<BusterMetricChartConfig['columnSettings']>(
|
||||
(acc, curr) => {
|
||||
acc[curr] = { ...columnSettings[curr], lineSymbolSize: value ? ENABLED_DOTS_ON_LINE : 0 };
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
export const EditGridLines: React.FC<{
|
||||
gridLines: IBusterMetricChartConfig['gridLines'];
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
gridLines: BusterMetricChartConfig['gridLines'];
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ gridLines, onUpdateChartConfig }) => {
|
||||
return (
|
||||
<LabelAndInput label={'Grid lines'}>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useMemo, useState } from 'react';
|
||||
import {
|
||||
DEFAULT_CHART_CONFIG,
|
||||
type IBusterMetricChartConfig,
|
||||
type BusterMetricChartConfig,
|
||||
MIN_DONUT_WIDTH
|
||||
} from '@/api/asset_interfaces';
|
||||
import { AppSegmented, type SegmentedItem } from '@/components/ui/segmented';
|
||||
|
@ -23,9 +23,9 @@ export const EditPieAppearance = React.memo(
|
|||
onUpdateChartConfig,
|
||||
pieChartAxis
|
||||
}: {
|
||||
pieDonutWidth: IBusterMetricChartConfig['pieDonutWidth'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieChartAxis: IBusterMetricChartConfig['pieChartAxis'];
|
||||
pieDonutWidth: BusterMetricChartConfig['pieDonutWidth'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
pieChartAxis: BusterMetricChartConfig['pieChartAxis'];
|
||||
}) => {
|
||||
const [showDonutWidthSelector, setShowDonutWidthSelector] = useState(pieDonutWidth > 0);
|
||||
const [value, setValue] = useState(pieDonutWidth);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Input } from '@/components/ui/inputs';
|
||||
import { Select, type SelectItem } from '@/components/ui/select';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
@ -10,9 +10,9 @@ export const EditPieInnerLabel = React.memo(
|
|||
pieInnerLabelTitle,
|
||||
onUpdateChartConfig
|
||||
}: {
|
||||
pieInnerLabelAggregate: IBusterMetricChartConfig['pieInnerLabelAggregate'];
|
||||
pieInnerLabelTitle: IBusterMetricChartConfig['pieInnerLabelTitle'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieInnerLabelAggregate: BusterMetricChartConfig['pieInnerLabelAggregate'];
|
||||
pieInnerLabelTitle: BusterMetricChartConfig['pieInnerLabelTitle'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
|
@ -31,7 +31,7 @@ export const EditPieInnerLabel = React.memo(
|
|||
);
|
||||
EditPieInnerLabel.displayName = 'EditPieInnerLabel';
|
||||
|
||||
const options: SelectItem<IBusterMetricChartConfig['pieInnerLabelAggregate']>[] = [
|
||||
const options: SelectItem<BusterMetricChartConfig['pieInnerLabelAggregate']>[] = [
|
||||
{ label: 'Sum', value: 'sum' },
|
||||
{ label: 'Average', value: 'average' },
|
||||
{ label: 'Median', value: 'median' },
|
||||
|
@ -41,8 +41,8 @@ const options: SelectItem<IBusterMetricChartConfig['pieInnerLabelAggregate']>[]
|
|||
];
|
||||
|
||||
const EditPieInnerLabelAggregate: React.FC<{
|
||||
pieInnerLabelAggregate: IBusterMetricChartConfig['pieInnerLabelAggregate'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieInnerLabelAggregate: BusterMetricChartConfig['pieInnerLabelAggregate'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = ({ pieInnerLabelAggregate, onUpdateChartConfig }) => {
|
||||
const selectedOption = useMemo(() => {
|
||||
return options.find((option) => option.value === pieInnerLabelAggregate) || options[0];
|
||||
|
@ -56,7 +56,7 @@ const EditPieInnerLabelAggregate: React.FC<{
|
|||
onChange={(value) => {
|
||||
const label = options.find((option) => option.value === value)?.label;
|
||||
onUpdateChartConfig({
|
||||
pieInnerLabelAggregate: value as IBusterMetricChartConfig['pieInnerLabelAggregate'],
|
||||
pieInnerLabelAggregate: value as BusterMetricChartConfig['pieInnerLabelAggregate'],
|
||||
pieInnerLabelTitle: label as string
|
||||
});
|
||||
}}
|
||||
|
@ -66,8 +66,8 @@ const EditPieInnerLabelAggregate: React.FC<{
|
|||
};
|
||||
|
||||
const EditPieInnerLabelTitle: React.FC<{
|
||||
pieInnerLabelTitle: IBusterMetricChartConfig['pieInnerLabelTitle'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieInnerLabelTitle: BusterMetricChartConfig['pieInnerLabelTitle'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = ({ pieInnerLabelTitle, onUpdateChartConfig }) => {
|
||||
return (
|
||||
<LabelAndInput label="Title">
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Select, type SelectItem } from '@/components/ui/select';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
const options: SelectItem<NonNullable<IBusterMetricChartConfig['pieLabelPosition']>>[] = [
|
||||
const options: SelectItem<NonNullable<BusterMetricChartConfig['pieLabelPosition']>>[] = [
|
||||
{ label: 'Outside', value: 'outside' },
|
||||
{ label: 'Inside', value: 'inside' }
|
||||
];
|
||||
|
@ -15,15 +15,15 @@ export const EditPieLabelLocation = React.memo(
|
|||
pieLabelPosition,
|
||||
onUpdateChartConfig
|
||||
}: {
|
||||
pieLabelPosition: IBusterMetricChartConfig['pieLabelPosition'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieLabelPosition: BusterMetricChartConfig['pieLabelPosition'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}) => {
|
||||
const selectedLabelPosition = useMemo(() => {
|
||||
return options.find((option) => option.value === pieLabelPosition)?.value || 'outside';
|
||||
}, [pieLabelPosition]);
|
||||
const hideLabel = pieLabelPosition === 'none' || !pieLabelPosition;
|
||||
|
||||
const onChangeSelect = useMemoizedFn((value: IBusterMetricChartConfig['pieLabelPosition']) => {
|
||||
const onChangeSelect = useMemoizedFn((value: BusterMetricChartConfig['pieLabelPosition']) => {
|
||||
onUpdateChartConfig({ pieLabelPosition: value });
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { SliderWithInputNumber } from '@/components/ui/slider';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
@ -9,8 +9,8 @@ export const EditPieMinimumSlicePercentage = React.memo(
|
|||
pieMinimumSlicePercentage: initialValue,
|
||||
onUpdateChartConfig
|
||||
}: {
|
||||
pieMinimumSlicePercentage: IBusterMetricChartConfig['pieMinimumSlicePercentage'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieMinimumSlicePercentage: BusterMetricChartConfig['pieMinimumSlicePercentage'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}) => {
|
||||
const [pieMinimumSlicePercentage, setIntermediateValue] = useState(initialValue);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
|
@ -8,8 +8,8 @@ export const EditPieShowInnerLabel = React.memo(
|
|||
pieShowInnerLabel,
|
||||
onUpdateChartConfig
|
||||
}: {
|
||||
pieShowInnerLabel: IBusterMetricChartConfig['pieShowInnerLabel'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieShowInnerLabel: BusterMetricChartConfig['pieShowInnerLabel'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}) => {
|
||||
return (
|
||||
<LabelAndInput label="Show inner label">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { PieSortBy } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Empty, SortAlphaAscending, SortNumAscending } from '@/components/ui/icons';
|
||||
import { AppSegmented, type SegmentedItem } from '@/components/ui/segmented';
|
||||
|
@ -25,8 +25,8 @@ const options: SegmentedItem<NonNullable<PieSortBy> | 'none'>[] = [
|
|||
];
|
||||
|
||||
export const EditPieSorting: React.FC<{
|
||||
pieSortBy: IBusterMetricChartConfig['pieSortBy'];
|
||||
onUpdateChartConfig: (v: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieSortBy: BusterMetricChartConfig['pieSortBy'];
|
||||
onUpdateChartConfig: (v: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ pieSortBy, onUpdateChartConfig }) => {
|
||||
const selectedOption = useMemo(() => {
|
||||
return (
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { IColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { EditReplaceMissingData } from '../StylingAppVisualize/SelectAxis/SelectAxisColumnContent/EditReplaceMissingData';
|
||||
|
||||
export const EditReplaceMissingValuesWithGlobal: React.FC<{
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ columnLabelFormats, onUpdateChartConfig }) => {
|
||||
const mostPermissiveMissingWith = useMemo(() => {
|
||||
return Object.values(columnLabelFormats).some(
|
||||
|
@ -17,9 +17,9 @@ export const EditReplaceMissingValuesWithGlobal: React.FC<{
|
|||
}, [columnLabelFormats]);
|
||||
|
||||
const onUpdateColumnLabel = useMemoizedFn((config: Partial<IColumnLabelFormat>) => {
|
||||
const newColumnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'] = Object.entries(
|
||||
const newColumnLabelFormats: BusterMetricChartConfig['columnLabelFormats'] = Object.entries(
|
||||
columnLabelFormats
|
||||
).reduce<IBusterMetricChartConfig['columnLabelFormats']>((acc, [key, value]) => {
|
||||
).reduce<BusterMetricChartConfig['columnLabelFormats']>((acc, [key, value]) => {
|
||||
acc[key] = { ...value, ...config };
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import isEmpty from 'lodash/isEmpty';
|
||||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ChartEncodes, ScatterAxis } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Slider } from '@/components/ui/slider';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
export const EditScatterDotSize: React.FC<{
|
||||
scatterDotSize: IBusterMetricChartConfig['scatterDotSize'];
|
||||
scatterDotSize: BusterMetricChartConfig['scatterDotSize'];
|
||||
selectedAxis: ChartEncodes;
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ scatterDotSize, selectedAxis, onUpdateChartConfig }) => {
|
||||
const hasSize = !isEmpty((selectedAxis as ScatterAxis).size);
|
||||
const defaultValue = hasSize ? scatterDotSize : scatterDotSize[0];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import React, { useState } from 'react';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { ColumnMetaData, IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnMetaData, BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ChartEncodes, GoalLine } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { ColorPicker } from '@/components/ui/color-picker';
|
||||
|
@ -18,8 +18,8 @@ interface LoopGoalLine extends GoalLine {
|
|||
}
|
||||
|
||||
export const EditGoalLine: React.FC<{
|
||||
goalLines: IBusterMetricChartConfig['goalLines'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
goalLines: BusterMetricChartConfig['goalLines'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
columnMetadata: ColumnMetaData[] | undefined;
|
||||
selectedAxis: ChartEncodes;
|
||||
}> = React.memo(({ goalLines, onUpdateChartConfig, columnMetadata, selectedAxis }) => {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import first from 'lodash/first';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Select, type SelectItem } from '@/components/ui/select';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
const options: SelectItem<IBusterMetricChartConfig['showLegendHeadline'] | 'false'>[] = [
|
||||
const options: SelectItem<BusterMetricChartConfig['showLegendHeadline'] | 'false'>[] = [
|
||||
{ label: 'None', value: 'false' },
|
||||
{ label: 'Total', value: 'total' },
|
||||
{ label: 'Average', value: 'average' },
|
||||
|
@ -21,11 +21,11 @@ const pieOptions: SelectItem<'false' | 'current'>[] = [
|
|||
];
|
||||
|
||||
export const EditShowHeadline: React.FC<{
|
||||
showLegendHeadline: IBusterMetricChartConfig['showLegendHeadline'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
showLegendHeadline: BusterMetricChartConfig['showLegendHeadline'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
}> = React.memo(
|
||||
({ showLegendHeadline, onUpdateChartConfig, lineGroupType, barGroupType, selectedChartType }) => {
|
||||
const isStackPercentage =
|
||||
|
@ -56,7 +56,7 @@ export const EditShowHeadline: React.FC<{
|
|||
|
||||
onUpdateChartConfig({
|
||||
showLegend: true,
|
||||
showLegendHeadline: transformedValue as IBusterMetricChartConfig['showLegendHeadline']
|
||||
showLegendHeadline: transformedValue as BusterMetricChartConfig['showLegendHeadline']
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { AppSegmented, type SegmentedItem } from '@/components/ui/segmented';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
@ -14,8 +14,8 @@ export const EditShowLabelPieAsPercentage = React.memo(
|
|||
pieDisplayLabelAs,
|
||||
onUpdateChartConfig
|
||||
}: {
|
||||
pieDisplayLabelAs: IBusterMetricChartConfig['pieDisplayLabelAs'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
pieDisplayLabelAs: BusterMetricChartConfig['pieDisplayLabelAs'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}) => {
|
||||
const selectedValue = useMemo(() => {
|
||||
return options.find((option) => option.value === pieDisplayLabelAs)?.value || 'number';
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ChartEncodes, ScatterAxis } from '@/api/asset_interfaces/metric/charts';
|
||||
import { useLegendAutoShow } from '@/components/ui/charts/BusterChartLegend';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
export const EditShowLegend: React.FC<{
|
||||
showLegend: IBusterMetricChartConfig['showLegend'];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
showLegend: BusterMetricChartConfig['showLegend'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
selectedAxis: ChartEncodes;
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(
|
||||
({ showLegend: showLegendProp, selectedAxis, selectedChartType, onUpdateChartConfig }) => {
|
||||
const categoryAxisColumnNames = (selectedAxis as ScatterAxis)?.category;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../Common';
|
||||
|
||||
export const EditSmoothLinesGlobal: React.FC<{
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
columnSettings: BusterMetricChartConfig['columnSettings'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ columnSettings, onUpdateChartConfig }) => {
|
||||
const allSmooth = useMemo(() => {
|
||||
return Object.values(columnSettings).every((column) => column.lineType === 'smooth');
|
||||
|
@ -14,12 +14,13 @@ export const EditSmoothLinesGlobal: React.FC<{
|
|||
|
||||
const onChangeAllSmooth = useMemoizedFn((value: boolean) => {
|
||||
onUpdateChartConfig({
|
||||
columnSettings: Object.keys(columnSettings).reduce<
|
||||
IBusterMetricChartConfig['columnSettings']
|
||||
>((acc, curr) => {
|
||||
acc[curr] = { ...columnSettings[curr], lineType: value ? 'smooth' : 'normal' };
|
||||
return acc;
|
||||
}, {})
|
||||
columnSettings: Object.keys(columnSettings).reduce<BusterMetricChartConfig['columnSettings']>(
|
||||
(acc, curr) => {
|
||||
acc[curr] = { ...columnSettings[curr], lineType: value ? 'smooth' : 'normal' };
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import isEqual from 'lodash/isEqual';
|
|||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { ColumnMetaData } from '@/api/asset_interfaces';
|
||||
import { DEFAULT_TRENDLINE_CONFIG, type IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { DEFAULT_TRENDLINE_CONFIG, type BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ChartEncodes, ScatterAxis, Trendline } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { JOIN_CHARACTER } from '@/components/ui/charts/commonHelpers';
|
||||
|
@ -30,13 +30,13 @@ export interface LoopTrendline extends Trendline {
|
|||
}
|
||||
|
||||
export const EditTrendline: React.FC<{
|
||||
trendlines: IBusterMetricChartConfig['trendlines'];
|
||||
trendlines: BusterMetricChartConfig['trendlines'];
|
||||
colors: string[];
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
selectedAxis: ChartEncodes;
|
||||
columnMetadata: ColumnMetaData[];
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
}> = React.memo(
|
||||
({
|
||||
trendlines,
|
||||
|
@ -189,12 +189,12 @@ const EditTrendlineItem: React.FC<{
|
|||
trend: LoopTrendline;
|
||||
isNewTrend: boolean;
|
||||
columnMetadata: ColumnMetaData[];
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
yAxisEncodes: string[];
|
||||
xAxisEncodes: string[];
|
||||
categoryEncodes: string[] | null | undefined;
|
||||
colors: string[];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
onUpdateExistingTrendline: (trend: LoopTrendline) => void;
|
||||
onDeleteTrendline: (id: string) => void;
|
||||
}> = React.memo(
|
||||
|
@ -254,8 +254,8 @@ const TrendlineItemContent: React.FC<{
|
|||
xAxisEncodes: string[];
|
||||
colors: string[];
|
||||
categoryEncodes: string[] | null | undefined;
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
onUpdateExistingTrendline: (trend: LoopTrendline) => void;
|
||||
}> = React.memo(
|
||||
({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { ColumnMetaData, IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnMetaData, BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Select, type SelectItem } from '@/components/ui/select';
|
||||
import { formatLabel } from '@/lib';
|
||||
import { LabelAndInput } from '../../Common';
|
||||
|
@ -15,7 +15,7 @@ export const TrendlineColumnId = React.memo(
|
|||
}: {
|
||||
trend: LoopTrendline;
|
||||
columnMetadata: ColumnMetaData[];
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
onUpdateExistingTrendline: (trend: LoopTrendline) => void;
|
||||
yAxisEncodes: string[];
|
||||
}) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ChartType, Trendline } from '@/api/asset_interfaces/metric/charts';
|
||||
import { TriangleWarning } from '@/components/ui/icons';
|
||||
import { Select, type SelectItem } from '@/components/ui/select';
|
||||
|
@ -22,7 +22,7 @@ export const EditTrendlineOption = React.memo(
|
|||
onUpdateExistingTrendline: (trend: LoopTrendline) => void;
|
||||
yAxisEncodes: string[];
|
||||
xAxisEncodes: string[];
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
selectedChartType: ChartType;
|
||||
}) => {
|
||||
const { type } = trend;
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { EditAxisScale } from '../StylingAppVisualize/SelectAxis/SelectAxisSettingsContent/EditAxisScale';
|
||||
|
||||
export const EditYAxisScaleGlobal: React.FC<{
|
||||
yAxisScaleType: IBusterMetricChartConfig['yAxisScaleType'];
|
||||
y2AxisScaleType: IBusterMetricChartConfig['y2AxisScaleType'];
|
||||
onUpdateChartConfig: (config: Partial<IBusterMetricChartConfig>) => void;
|
||||
yAxisScaleType: BusterMetricChartConfig['yAxisScaleType'];
|
||||
y2AxisScaleType: BusterMetricChartConfig['y2AxisScaleType'];
|
||||
onUpdateChartConfig: (config: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ yAxisScaleType, y2AxisScaleType, onUpdateChartConfig }) => {
|
||||
const mostPermissiveScale = useMemo(() => {
|
||||
return yAxisScaleType === y2AxisScaleType ? yAxisScaleType : 'linear';
|
||||
}, [yAxisScaleType, y2AxisScaleType]);
|
||||
|
||||
const onChangeAxisScale = useMemoizedFn((value: IBusterMetricChartConfig['yAxisScaleType']) => {
|
||||
const onChangeAxisScale = useMemoizedFn((value: BusterMetricChartConfig['yAxisScaleType']) => {
|
||||
onUpdateChartConfig({
|
||||
yAxisScaleType: value,
|
||||
y2AxisScaleType: value
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import { type BarAndLineAxis, ChartType } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Separator } from '@/components/ui/seperator';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
|
@ -78,16 +78,16 @@ export const StylingAppStyling: React.FC<
|
|||
const { onUpdateMetricChartConfig } = useUpdateMetricChart();
|
||||
|
||||
const onUpdateDataLabel = useMemoizedFn((v: boolean) => {
|
||||
const newColumnSettings: IBusterMetricChartConfig['columnSettings'] = Object.keys(
|
||||
const newColumnSettings: BusterMetricChartConfig['columnSettings'] = Object.keys(
|
||||
columnSettings
|
||||
).reduce<IBusterMetricChartConfig['columnSettings']>((acc, curr) => {
|
||||
).reduce<BusterMetricChartConfig['columnSettings']>((acc, curr) => {
|
||||
acc[curr] = { ...columnSettings[curr], showDataLabels: v };
|
||||
return acc;
|
||||
}, {});
|
||||
onUpdateChartConfig({ columnSettings: newColumnSettings });
|
||||
});
|
||||
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<IBusterMetricChartConfig>) => {
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<BusterMetricChartConfig>) => {
|
||||
onUpdateMetricChartConfig({ chartConfig });
|
||||
});
|
||||
|
||||
|
@ -185,9 +185,9 @@ export const StylingAppStyling: React.FC<
|
|||
const GlobalSettings: React.FC<
|
||||
{
|
||||
className: string;
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings'];
|
||||
yAxisShowAxisTitle: IBusterMetricChartConfig['yAxisShowAxisTitle'];
|
||||
yAxisShowAxisLabel: IBusterMetricChartConfig['yAxisShowAxisLabel'];
|
||||
columnSettings: BusterMetricChartConfig['columnSettings'];
|
||||
yAxisShowAxisTitle: BusterMetricChartConfig['yAxisShowAxisTitle'];
|
||||
yAxisShowAxisLabel: BusterMetricChartConfig['yAxisShowAxisLabel'];
|
||||
} & Parameters<typeof EditShowLegend>[0] &
|
||||
Parameters<typeof EditGridLines>[0] &
|
||||
Omit<Parameters<typeof EditHideYAxis>[0], 'hideYAxis'> &
|
||||
|
@ -294,9 +294,9 @@ const GlobalSettings: React.FC<
|
|||
const ChartSpecificSettings: React.FC<
|
||||
{
|
||||
className: string;
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings'];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnSettings: BusterMetricChartConfig['columnSettings'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
} & Parameters<typeof EditBarRoundnessGlobal>[0] &
|
||||
Parameters<typeof EditBarSorting>[0] &
|
||||
Parameters<typeof EditPieSorting>[0] &
|
||||
|
@ -567,7 +567,7 @@ const EtcSettings: React.FC<
|
|||
const PieSettings: React.FC<
|
||||
{
|
||||
className: string;
|
||||
pieDonutWidth: IBusterMetricChartConfig['pieDonutWidth'];
|
||||
pieDonutWidth: BusterMetricChartConfig['pieDonutWidth'];
|
||||
} & Parameters<typeof EditPieShowInnerLabel>[0] &
|
||||
Parameters<typeof EditPieInnerLabel>[0]
|
||||
> = React.memo(
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { ChartType } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
|
||||
export const StylingAppStylingNotSupported = React.memo(
|
||||
({ selectedChartType }: { selectedChartType: IBusterMetricChartConfig['selectedChartType'] }) => {
|
||||
({ selectedChartType }: { selectedChartType: BusterMetricChartConfig['selectedChartType'] }) => {
|
||||
const title = useMemo(() => {
|
||||
if (selectedChartType === 'table') {
|
||||
return 'Styling for tables charts is coming soon';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import isEmpty from 'lodash/isEmpty';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type {
|
||||
CategoryAxisStyleConfig,
|
||||
ChartEncodes,
|
||||
|
@ -46,7 +46,7 @@ export const SelectAxis: React.FC<
|
|||
return Object.assign(acc, { [axis]: zone.items });
|
||||
}, {} as ChartEncodes);
|
||||
|
||||
const newChartConfig: Partial<IBusterMetricChartConfig> = {
|
||||
const newChartConfig: Partial<BusterMetricChartConfig> = {
|
||||
[selectedAxisToEdit]: newChartEncodes
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { ChartType, type ColumnSettings } from '@/api/asset_interfaces/metric/charts';
|
||||
import { ChartBarAxisX, ChartLine, ChartScatter } from '@/components/ui/icons';
|
||||
import { AppSegmented, type SegmentedItem } from '@/components/ui/segmented';
|
||||
|
@ -40,7 +40,7 @@ const options = [
|
|||
export const EditDisplayAs: React.FC<{
|
||||
columnVisualization: Required<ColumnSettings>['columnVisualization'];
|
||||
onUpdateColumnSettingConfig: (columnSettings: Partial<ColumnSettings>) => void;
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
}> = React.memo(({ columnVisualization, onUpdateColumnSettingConfig, selectedChartType }) => {
|
||||
const selectedOption = useMemo(() => {
|
||||
if (selectedChartType === 'bar') return 'bar';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { type ChartEncodes, type ColumnSettings } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { IColumnLabelFormat } from '@/api/asset_interfaces/metric/charts/columnLabelInterfaces';
|
||||
import { useGetCurrencies } from '@/api/buster_rest/currency';
|
||||
|
@ -28,14 +28,14 @@ import { EditSuffix } from './EditSuffix';
|
|||
import { EditTitle } from './EditTitle';
|
||||
|
||||
export const SelectAxisDropdownContent: React.FC<{
|
||||
columnSetting: IBusterMetricChartConfig['columnSettings'][string];
|
||||
columnSetting: BusterMetricChartConfig['columnSettings'][string];
|
||||
columnLabelFormat: IColumnLabelFormat;
|
||||
selectedAxis: ChartEncodes | null;
|
||||
id: string;
|
||||
className?: string;
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
zoneId: SelectAxisContainerId;
|
||||
hideTitle?: boolean;
|
||||
classNames?: {
|
||||
|
@ -115,13 +115,13 @@ const ColumnSettingComponent: React.FC<{
|
|||
formattedTitle: string;
|
||||
onUpdateColumnConfig: (columnLabelFormat: Partial<IColumnLabelFormat>) => void;
|
||||
onUpdateColumnSettingConfig: (columnSetting: Partial<ColumnSettings>) => void;
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
selectedAxis: ChartEncodes | null;
|
||||
columnSetting: IBusterMetricChartConfig['columnSettings'][string];
|
||||
columnSetting: BusterMetricChartConfig['columnSettings'][string];
|
||||
columnLabelFormat: IColumnLabelFormat;
|
||||
zoneId: SelectAxisContainerId;
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
rowCount: number;
|
||||
}> = ({
|
||||
formattedTitle,
|
||||
|
@ -274,7 +274,7 @@ const LabelSettings: React.FC<{
|
|||
onUpdateColumnConfig: (columnLabelFormat: Partial<IColumnLabelFormat>) => void;
|
||||
id: string;
|
||||
zoneId: SelectAxisContainerId;
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
}> = ({
|
||||
columnLabelFormat,
|
||||
onUpdateColumnConfig,
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { HttpResponse, http } from 'msw';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { type IColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Button } from '@/components/ui/buttons/Button';
|
||||
import { SelectAxisContainerId } from './config';
|
||||
import {
|
||||
SelectAxisColumnPopover,
|
||||
type SelectAxisColumnPopoverProps
|
||||
} from './SelectAxisColumnPopover';
|
||||
import type { ColumnLabelFormat } from '@buster/server-shared/metrics';
|
||||
|
||||
const meta: Meta<typeof SelectAxisColumnPopover> = {
|
||||
title: 'Controllers/EditMetricController/SelectAxisColumnPopover',
|
||||
|
@ -60,7 +60,7 @@ const mockProps: SelectAxisColumnPopoverProps = {
|
|||
replaceMissingDataWith: null,
|
||||
makeLabelHumanReadable: true,
|
||||
compactNumbers: false
|
||||
} satisfies IColumnLabelFormat,
|
||||
} satisfies ColumnLabelFormat,
|
||||
columnSetting: {
|
||||
showDataLabels: false,
|
||||
showDataLabelsAsPercentage: false,
|
||||
|
@ -70,7 +70,7 @@ const mockProps: SelectAxisColumnPopoverProps = {
|
|||
lineType: 'normal' as const,
|
||||
lineSymbolSize: 0,
|
||||
barRoundness: 8
|
||||
} satisfies IBusterMetricChartConfig['columnSettings'][string],
|
||||
} satisfies BusterMetricChartConfig['columnSettings'][string],
|
||||
id: 'test-id',
|
||||
selectedChartType: 'bar',
|
||||
barGroupType: 'group',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ChartEncodes, IColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Popover } from '@/components/ui/popover/Popover';
|
||||
import type { SelectAxisContainerId } from './config';
|
||||
|
@ -7,12 +7,12 @@ import { SelectAxisDropdownContent } from './SelectAxisColumnContent';
|
|||
|
||||
export interface SelectAxisColumnPopoverProps {
|
||||
columnLabelFormat: IColumnLabelFormat;
|
||||
columnSetting: IBusterMetricChartConfig['columnSettings'][string];
|
||||
columnSetting: BusterMetricChartConfig['columnSettings'][string];
|
||||
children: React.ReactNode;
|
||||
id: string;
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
zoneId: SelectAxisContainerId;
|
||||
selectedAxis: ChartEncodes | null;
|
||||
rowCount: number;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { DraggableAttributes } from '@dnd-kit/core';
|
||||
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';
|
||||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ChartEncodes, IColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { DotsVertical } from '@/components/ui/icons';
|
||||
|
@ -59,10 +59,10 @@ export const SelectAxisItemAvailableContainer = React.memo(
|
|||
const ThreeDotMenu: React.FC<{
|
||||
isDragging?: boolean;
|
||||
columnLabelFormat: IColumnLabelFormat;
|
||||
columnSetting: IBusterMetricChartConfig['columnSettings'][string];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
columnSetting: BusterMetricChartConfig['columnSettings'][string];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
zoneId: SelectAxisContainerId;
|
||||
selectedAxis: ChartEncodes | null;
|
||||
id: string;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import type { DraggableAttributes } from '@dnd-kit/core';
|
||||
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { ChartEncodes, IColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import { ErrorBoundary } from '@/components/ui/error';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
|
@ -10,6 +9,7 @@ import { chartTypeToAxis, type SelectAxisContainerId, zoneIdToAxis } from './con
|
|||
import { SelectAxisDropdownContent } from './SelectAxisColumnContent';
|
||||
import { SelectAxisItemLabel } from './SelectAxisItemLabel';
|
||||
import { useSelectAxisContextSelector } from './useSelectAxisContext';
|
||||
import type { ChartEncodes, ColumnLabelFormat } from '@buster/server-shared/metrics';
|
||||
|
||||
interface SelectAxisItemContainerProps {
|
||||
id: string;
|
||||
|
@ -25,7 +25,7 @@ interface SelectAxisItemContainerProps {
|
|||
export const SelectAxisItemContainer = React.memo(
|
||||
React.forwardRef<HTMLDivElement, SelectAxisItemContainerProps>(
|
||||
({ id, zoneId, isPlaceholder, ...draggingProps }, ref) => {
|
||||
const columnLabelFormat: undefined | IColumnLabelFormat = useSelectAxisContextSelector(
|
||||
const columnLabelFormat: undefined | ColumnLabelFormat = useSelectAxisContextSelector(
|
||||
(x) => x.columnLabelFormats[id]
|
||||
);
|
||||
const selectedAxis = useSelectAxisContextSelector((x) => x.selectedAxis);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useSelectAxisContextSelector } from '../useSelectAxisContext';
|
||||
|
@ -18,7 +18,7 @@ export const CategoryAxisSettingContent: React.FC = React.memo(() => {
|
|||
contextOnUpdateMetricChartConfig({ chartConfig: { categoryAxisTitle: value } });
|
||||
});
|
||||
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<IBusterMetricChartConfig>) => {
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<BusterMetricChartConfig>) => {
|
||||
contextOnUpdateMetricChartConfig({ chartConfig });
|
||||
});
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { AppSegmented, type SegmentedItem } from '@/components/ui/segmented';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../../../Common/LabelAndInput';
|
||||
|
||||
const options: SegmentedItem<IBusterMetricChartConfig['xAxisLabelRotation']>[] = [
|
||||
const options: SegmentedItem<BusterMetricChartConfig['xAxisLabelRotation']>[] = [
|
||||
{ label: 'Auto', value: 'auto' },
|
||||
{ label: '0°', value: 0 },
|
||||
{ label: '45°', value: 45 },
|
||||
|
@ -12,17 +12,17 @@ const options: SegmentedItem<IBusterMetricChartConfig['xAxisLabelRotation']>[] =
|
|||
];
|
||||
|
||||
export const EditAxisLabelRotation: React.FC<{
|
||||
xAxisLabelRotation: IBusterMetricChartConfig['xAxisLabelRotation'];
|
||||
onChangeLabelRotation: (value: IBusterMetricChartConfig['xAxisLabelRotation']) => void;
|
||||
xAxisLabelRotation: BusterMetricChartConfig['xAxisLabelRotation'];
|
||||
onChangeLabelRotation: (value: BusterMetricChartConfig['xAxisLabelRotation']) => void;
|
||||
}> = React.memo(({ xAxisLabelRotation, onChangeLabelRotation }) => {
|
||||
const selectedOption: IBusterMetricChartConfig['xAxisLabelRotation'] = useMemo(() => {
|
||||
const selectedOption: BusterMetricChartConfig['xAxisLabelRotation'] = useMemo(() => {
|
||||
return (
|
||||
options.find((option) => option.value === xAxisLabelRotation)?.value ?? options[0]?.value
|
||||
);
|
||||
}, [xAxisLabelRotation]);
|
||||
|
||||
const onChange = useMemoizedFn((value: SegmentedItem<string>) => {
|
||||
onChangeLabelRotation(value.value as IBusterMetricChartConfig['xAxisLabelRotation']);
|
||||
onChangeLabelRotation(value.value as BusterMetricChartConfig['xAxisLabelRotation']);
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
import React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Select } from '@/components/ui/select';
|
||||
import { LabelAndInput } from '../../../Common/LabelAndInput';
|
||||
|
||||
const options: { label: string; value: IBusterMetricChartConfig['yAxisScaleType'] }[] = [
|
||||
const options: { label: string; value: BusterMetricChartConfig['yAxisScaleType'] }[] = [
|
||||
{ label: 'Linear', value: 'linear' },
|
||||
{ label: 'Logarithmic', value: 'log' }
|
||||
];
|
||||
|
||||
export const EditAxisScale: React.FC<{
|
||||
scaleType:
|
||||
| IBusterMetricChartConfig['yAxisScaleType']
|
||||
| IBusterMetricChartConfig['y2AxisScaleType'];
|
||||
onChangeAxisScale: (value: IBusterMetricChartConfig['yAxisScaleType']) => void;
|
||||
scaleType: BusterMetricChartConfig['yAxisScaleType'] | BusterMetricChartConfig['y2AxisScaleType'];
|
||||
onChangeAxisScale: (value: BusterMetricChartConfig['yAxisScaleType']) => void;
|
||||
}> = React.memo(({ scaleType, onChangeAxisScale }) => {
|
||||
return (
|
||||
<LabelAndInput label="Scale">
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
import React, { useMemo, useState } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Select, type SelectItem } from '@/components/ui/select';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../../../Common/LabelAndInput';
|
||||
|
||||
const barGroupingOptions: SelectItem<NonNullable<IBusterMetricChartConfig['barGroupType']>>[] = [
|
||||
const barGroupingOptions: SelectItem<NonNullable<BusterMetricChartConfig['barGroupType']>>[] = [
|
||||
{ label: 'Grouped', value: 'group' },
|
||||
{ label: 'Stacked', value: 'stack' }
|
||||
];
|
||||
|
||||
const lineGroupingOptions: SelectItem<
|
||||
NonNullable<IBusterMetricChartConfig['lineGroupType']> | 'default'
|
||||
NonNullable<BusterMetricChartConfig['lineGroupType']> | 'default'
|
||||
>[] = [
|
||||
{ label: 'Default', value: 'default' },
|
||||
{ label: 'Stacked', value: 'stack' }
|
||||
];
|
||||
|
||||
export const EditGrouping: React.FC<{
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
onUpdateChartConfig: (value: Partial<IBusterMetricChartConfig>) => void;
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
barShowTotalAtTop: IBusterMetricChartConfig['barShowTotalAtTop'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
onUpdateChartConfig: (value: Partial<BusterMetricChartConfig>) => void;
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
barShowTotalAtTop: BusterMetricChartConfig['barShowTotalAtTop'];
|
||||
}> = React.memo(
|
||||
({ selectedChartType, onUpdateChartConfig, lineGroupType, barGroupType, barShowTotalAtTop }) => {
|
||||
const isBarChart = selectedChartType === 'bar';
|
||||
|
@ -30,9 +30,7 @@ export const EditGrouping: React.FC<{
|
|||
isBarChart ? barGroupType === 'stack' : lineGroupType === 'stack'
|
||||
);
|
||||
const [value, setValue] = useState<
|
||||
| IBusterMetricChartConfig['lineGroupType']
|
||||
| 'default'
|
||||
| IBusterMetricChartConfig['barGroupType']
|
||||
BusterMetricChartConfig['lineGroupType'] | 'default' | BusterMetricChartConfig['barGroupType']
|
||||
>(isBarChart ? barGroupType : lineGroupType);
|
||||
|
||||
const showTotal = useMemo(() => {
|
||||
|
@ -62,21 +60,21 @@ export const EditGrouping: React.FC<{
|
|||
|
||||
const onChangeGroupType = useMemoizedFn(
|
||||
(
|
||||
value: IBusterMetricChartConfig['lineGroupType'] | IBusterMetricChartConfig['barGroupType']
|
||||
value: BusterMetricChartConfig['lineGroupType'] | BusterMetricChartConfig['barGroupType']
|
||||
) => {
|
||||
if (selectedChartType === 'bar') {
|
||||
const barGroupType = value as IBusterMetricChartConfig['barGroupType'];
|
||||
const barGroupType = value as BusterMetricChartConfig['barGroupType'];
|
||||
onUpdateChartConfig({ barGroupType });
|
||||
} else {
|
||||
const lineGroupType = value as IBusterMetricChartConfig['lineGroupType'];
|
||||
const lineGroupType = value as BusterMetricChartConfig['lineGroupType'];
|
||||
onUpdateChartConfig({ lineGroupType });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const onChangeGrouping = (value: string) => {
|
||||
setValue(value as IBusterMetricChartConfig['barGroupType']);
|
||||
onChangeGroupType(value as IBusterMetricChartConfig['barGroupType']);
|
||||
setValue(value as BusterMetricChartConfig['barGroupType']);
|
||||
onChangeGroupType(value as BusterMetricChartConfig['barGroupType']);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import React, { useState } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Input } from '@/components/ui/inputs';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../../../Common/LabelAndInput';
|
||||
|
||||
export const EditShowAxisTitle: React.FC<{
|
||||
axisTitle:
|
||||
| IBusterMetricChartConfig['xAxisAxisTitle']
|
||||
| IBusterMetricChartConfig['yAxisAxisTitle'];
|
||||
axisTitle: BusterMetricChartConfig['xAxisAxisTitle'] | BusterMetricChartConfig['yAxisAxisTitle'];
|
||||
showAxisTitle: boolean;
|
||||
formattedColumnTitle: string;
|
||||
onChangeAxisTitle: (value: string | null) => void;
|
||||
|
@ -64,9 +62,9 @@ const EditToggleAxisTitle: React.FC<{
|
|||
export const EditAxisTitle: React.FC<{
|
||||
label?: string;
|
||||
axisTitle:
|
||||
| IBusterMetricChartConfig['xAxisAxisTitle']
|
||||
| IBusterMetricChartConfig['yAxisAxisTitle']
|
||||
| IBusterMetricChartConfig['categoryAxisTitle'];
|
||||
| BusterMetricChartConfig['xAxisAxisTitle']
|
||||
| BusterMetricChartConfig['yAxisAxisTitle']
|
||||
| BusterMetricChartConfig['categoryAxisTitle'];
|
||||
onChangeTitle: (v: string | null) => void;
|
||||
formattedColumnTitle: string;
|
||||
}> = ({ axisTitle, onChangeTitle, formattedColumnTitle, label = 'Axis title' }) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import { AXIS_TITLE_SEPARATOR } from '@/components/ui/charts/commonHelpers/axisHelper';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
|
@ -60,7 +60,7 @@ export const XAxisSettingContent: React.FC = React.memo(() => {
|
|||
});
|
||||
|
||||
const onChangeLabelRotation = useMemoizedFn(
|
||||
(xAxisLabelRotation: IBusterMetricChartConfig['xAxisLabelRotation']) => {
|
||||
(xAxisLabelRotation: BusterMetricChartConfig['xAxisLabelRotation']) => {
|
||||
onUpdateMetricChartConfig({
|
||||
chartConfig: {
|
||||
xAxisLabelRotation
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnLabelFormat, ComboChartAxis } from '@/api/asset_interfaces/metric/charts';
|
||||
import { AXIS_TITLE_SEPARATOR } from '@/components/ui/charts/commonHelpers/axisHelper';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
|
@ -52,7 +52,7 @@ export const Y2AxisSettingContent: React.FC = React.memo(() => {
|
|||
});
|
||||
|
||||
const onChangeAxisScale = useMemoizedFn(
|
||||
(y2AxisScaleType: IBusterMetricChartConfig['y2AxisScaleType']) => {
|
||||
(y2AxisScaleType: BusterMetricChartConfig['y2AxisScaleType']) => {
|
||||
onUpdateMetricChartConfig({
|
||||
chartConfig: {
|
||||
y2AxisScaleType
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import { AXIS_TITLE_SEPARATOR } from '@/components/ui/charts/commonHelpers/axisHelper';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
|
@ -52,7 +52,7 @@ export const YAxisSettingContent: React.FC = React.memo(() => {
|
|||
});
|
||||
|
||||
const onChangeAxisScale = useMemoizedFn(
|
||||
(yAxisScaleType: IBusterMetricChartConfig['yAxisScaleType']) => {
|
||||
(yAxisScaleType: BusterMetricChartConfig['yAxisScaleType']) => {
|
||||
onUpdateMetricChartConfig({
|
||||
chartConfig: {
|
||||
yAxisScaleType
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import isEmpty from 'lodash/isEmpty';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { ChartType } from '@/api/asset_interfaces/metric/charts';
|
||||
import { SelectAxisContainerId } from './config';
|
||||
import type { DropZone } from './SelectAxisDragContainer/interfaces';
|
||||
|
@ -60,11 +60,11 @@ const makeY2AxisDropZone = (y2Items: string[] | null | undefined): DropZone =>
|
|||
makeDropZone(SelectAxisContainerId.Y2Axis, y2Items ?? EMPTY_ARRAY);
|
||||
|
||||
export const chartTypeToDropZones: Record<
|
||||
IBusterMetricChartConfig['selectedChartType'],
|
||||
BusterMetricChartConfig['selectedChartType'],
|
||||
(selectedAxis: Parameters<typeof getChartTypeDropZones>[0]['selectedAxis']) => DropZone[]
|
||||
> = {
|
||||
['bar']: (selectedAxis) => {
|
||||
const _selectedAxis = selectedAxis as IBusterMetricChartConfig['barAndLineAxis'];
|
||||
const _selectedAxis = selectedAxis as BusterMetricChartConfig['barAndLineAxis'];
|
||||
return [
|
||||
makeXAxisDropZone(_selectedAxis.x),
|
||||
makeYAxisDropZone(_selectedAxis.y),
|
||||
|
@ -73,7 +73,7 @@ export const chartTypeToDropZones: Record<
|
|||
];
|
||||
},
|
||||
['line']: (selectedAxis) => {
|
||||
const _selectedAxis = selectedAxis as IBusterMetricChartConfig['barAndLineAxis'];
|
||||
const _selectedAxis = selectedAxis as BusterMetricChartConfig['barAndLineAxis'];
|
||||
return [
|
||||
makeXAxisDropZone(_selectedAxis.x),
|
||||
makeYAxisDropZone(_selectedAxis.y),
|
||||
|
@ -82,7 +82,7 @@ export const chartTypeToDropZones: Record<
|
|||
];
|
||||
},
|
||||
['scatter']: (selectedAxis) => {
|
||||
const _selectedAxis = selectedAxis as IBusterMetricChartConfig['scatterAxis'];
|
||||
const _selectedAxis = selectedAxis as BusterMetricChartConfig['scatterAxis'];
|
||||
return [
|
||||
makeXAxisDropZone(_selectedAxis.x),
|
||||
makeYAxisDropZone(_selectedAxis.y),
|
||||
|
@ -92,7 +92,7 @@ export const chartTypeToDropZones: Record<
|
|||
];
|
||||
},
|
||||
['pie']: (selectedAxis) => {
|
||||
const _selectedAxis = selectedAxis as IBusterMetricChartConfig['pieChartAxis'];
|
||||
const _selectedAxis = selectedAxis as BusterMetricChartConfig['pieChartAxis'];
|
||||
return [
|
||||
makeXAxisDropZone(_selectedAxis.x),
|
||||
makeYAxisDropZone(_selectedAxis.y),
|
||||
|
@ -100,7 +100,7 @@ export const chartTypeToDropZones: Record<
|
|||
];
|
||||
},
|
||||
['combo']: (selectedAxis) => {
|
||||
const _selectedAxis = selectedAxis as IBusterMetricChartConfig['comboChartAxis'];
|
||||
const _selectedAxis = selectedAxis as BusterMetricChartConfig['comboChartAxis'];
|
||||
return [
|
||||
makeXAxisDropZone(_selectedAxis.x),
|
||||
makeYComboAxisDropZone(_selectedAxis.y),
|
||||
|
@ -122,12 +122,12 @@ export const getChartTypeDropZones = ({
|
|||
chartType,
|
||||
selectedAxis
|
||||
}: {
|
||||
chartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
chartType: BusterMetricChartConfig['selectedChartType'];
|
||||
selectedAxis:
|
||||
| IBusterMetricChartConfig['comboChartAxis']
|
||||
| IBusterMetricChartConfig['pieChartAxis']
|
||||
| IBusterMetricChartConfig['scatterAxis']
|
||||
| IBusterMetricChartConfig['barAndLineAxis'];
|
||||
| BusterMetricChartConfig['comboChartAxis']
|
||||
| BusterMetricChartConfig['pieChartAxis']
|
||||
| BusterMetricChartConfig['scatterAxis']
|
||||
| BusterMetricChartConfig['barAndLineAxis'];
|
||||
}): DropZone[] => {
|
||||
return chartTypeToDropZones[chartType](selectedAxis);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type React from 'react';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { createContext, useContextSelector } from 'use-context-selector';
|
||||
import type { ColumnMetaData, IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnMetaData, BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type {
|
||||
CategoryAxisStyleConfig,
|
||||
ChartEncodes,
|
||||
|
@ -16,19 +16,19 @@ export interface ISelectAxisContext
|
|||
Required<Omit<XAxisConfig, 'xAxisTimeInterval'>>,
|
||||
Required<CategoryAxisStyleConfig> {
|
||||
selectedAxis: ChartEncodes | null;
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
columnMetadata: ColumnMetaData[];
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings'];
|
||||
selectedChartType: IBusterMetricChartConfig['selectedChartType'];
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
showLegend: IBusterMetricChartConfig['showLegend'];
|
||||
showLegendHeadline: IBusterMetricChartConfig['showLegendHeadline'];
|
||||
gridLines: IBusterMetricChartConfig['gridLines'];
|
||||
goalLines: IBusterMetricChartConfig['goalLines'];
|
||||
trendlines: IBusterMetricChartConfig['trendlines'];
|
||||
barShowTotalAtTop: IBusterMetricChartConfig['barShowTotalAtTop'];
|
||||
disableTooltip: IBusterMetricChartConfig['disableTooltip'];
|
||||
columnSettings: BusterMetricChartConfig['columnSettings'];
|
||||
selectedChartType: BusterMetricChartConfig['selectedChartType'];
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
showLegend: BusterMetricChartConfig['showLegend'];
|
||||
showLegendHeadline: BusterMetricChartConfig['showLegendHeadline'];
|
||||
gridLines: BusterMetricChartConfig['gridLines'];
|
||||
goalLines: BusterMetricChartConfig['goalLines'];
|
||||
trendlines: BusterMetricChartConfig['trendlines'];
|
||||
barShowTotalAtTop: BusterMetricChartConfig['barShowTotalAtTop'];
|
||||
disableTooltip: BusterMetricChartConfig['disableTooltip'];
|
||||
rowCount: number;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type React from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import {
|
||||
type CategoryAxisStyleConfig,
|
||||
type ChartEncodes,
|
||||
|
@ -17,11 +17,11 @@ import { StylingMetric } from './StylingMetric';
|
|||
|
||||
export const StylingAppVisualize: React.FC<
|
||||
{
|
||||
barLayout: IBusterMetricChartConfig['barLayout'];
|
||||
barLayout: BusterMetricChartConfig['barLayout'];
|
||||
selectedAxis: ChartEncodes;
|
||||
className?: string;
|
||||
colors: string[];
|
||||
disableTooltip: IBusterMetricChartConfig['disableTooltip'];
|
||||
disableTooltip: BusterMetricChartConfig['disableTooltip'];
|
||||
} & Required<YAxisConfig> &
|
||||
Required<CategoryAxisStyleConfig> &
|
||||
Required<Y2AxisConfig> &
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import React, { useEffect, useRef } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Input } from '@/components/ui/inputs';
|
||||
import { LabelAndInput } from '../../Common';
|
||||
|
||||
export const EditHeaderTitle: React.FC<{
|
||||
value: string | undefined;
|
||||
type: 'header' | 'subHeader';
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ value, onUpdateChartConfig, type }) => {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const key: keyof IBusterMetricChartConfig =
|
||||
type === 'header' ? 'metricHeader' : 'metricSubHeader';
|
||||
const key: keyof BusterMetricChartConfig = type === 'header' ? 'metricHeader' : 'metricSubHeader';
|
||||
const title = type === 'header' ? 'Header' : 'Sub-header';
|
||||
const placeholder = type === 'header' ? 'Enter header' : 'Enter sub-header';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { DEFAULT_COLUMN_SETTINGS } from '@/api/asset_interfaces';
|
||||
import { ChartType, type DerivedMetricTitle } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
|
@ -15,15 +15,15 @@ import type { createColumnFieldOptions } from './helpers';
|
|||
|
||||
export const EditMetricField: React.FC<{
|
||||
label?: string;
|
||||
columnId: IBusterMetricChartConfig['metricColumnId'];
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnId: BusterMetricChartConfig['metricColumnId'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
columnFieldOptions: ReturnType<typeof createColumnFieldOptions>;
|
||||
rowCount: number;
|
||||
onUpdateMetricField: (config: {
|
||||
metricColumnId: string;
|
||||
metricValueAggregate?: DerivedMetricTitle['aggregate'];
|
||||
}) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(
|
||||
({
|
||||
columnId,
|
||||
|
@ -82,9 +82,9 @@ export const EditMetricField: React.FC<{
|
|||
EditMetricField.displayName = 'EditMetricField';
|
||||
|
||||
const StylingPopover: React.FC<{
|
||||
metricColumnId: IBusterMetricChartConfig['metricColumnId'];
|
||||
columnLabelFormat: IBusterMetricChartConfig['columnLabelFormats'][string];
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
metricColumnId: BusterMetricChartConfig['metricColumnId'];
|
||||
columnLabelFormat: BusterMetricChartConfig['columnLabelFormats'][string];
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
rowCount: number;
|
||||
}> = React.memo(({ metricColumnId, columnLabelFormat, rowCount }) => {
|
||||
return (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { Select, type SelectItem } from '@/components/ui/select';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { LabelAndInput } from '../../Common';
|
||||
|
@ -26,11 +26,11 @@ const allOptions: SelectItem<'custom' | 'columnTitle' | 'columnValue' | 'none'>[
|
|||
const onlyCustomOptions = [allOptions[0], allOptions[1]];
|
||||
|
||||
export const EditMetricHeader: React.FC<{
|
||||
header: IBusterMetricChartConfig['metricHeader'] | IBusterMetricChartConfig['metricSubHeader'];
|
||||
header: BusterMetricChartConfig['metricHeader'] | BusterMetricChartConfig['metricSubHeader'];
|
||||
type: 'header' | 'subHeader';
|
||||
firstColumnId: string;
|
||||
hideDerivedMetricOption: boolean;
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = React.memo(({ header, type, firstColumnId, hideDerivedMetricOption, onUpdateChartConfig }) => {
|
||||
const selectedOption = useMemo(() => {
|
||||
if (header === null) return 'none';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import last from 'lodash/last';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnLabelFormat } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { SelectItem } from '@/components/ui/select';
|
||||
import { Select } from '@/components/ui/select';
|
||||
|
@ -8,7 +8,7 @@ import { useMemoizedFn } from '@/hooks';
|
|||
import { isNumericColumnStyle, isNumericColumnType } from '@/lib';
|
||||
import { LabelAndInput } from '../../Common';
|
||||
|
||||
export const AGGREGATE_OPTIONS: SelectItem<IBusterMetricChartConfig['metricValueAggregate']>[] = [
|
||||
export const AGGREGATE_OPTIONS: SelectItem<BusterMetricChartConfig['metricValueAggregate']>[] = [
|
||||
{ label: 'Sum', value: 'sum' },
|
||||
{ label: 'Average', value: 'average' },
|
||||
{ label: 'Median', value: 'median' },
|
||||
|
@ -19,9 +19,9 @@ export const AGGREGATE_OPTIONS: SelectItem<IBusterMetricChartConfig['metricValue
|
|||
];
|
||||
|
||||
export const EditMetricAggregate: React.FC<{
|
||||
aggregate: IBusterMetricChartConfig['metricValueAggregate'];
|
||||
aggregate: BusterMetricChartConfig['metricValueAggregate'];
|
||||
columnId?: string;
|
||||
onUpdateAggregate: (aggregate: IBusterMetricChartConfig['metricValueAggregate']) => void;
|
||||
onUpdateAggregate: (aggregate: BusterMetricChartConfig['metricValueAggregate']) => void;
|
||||
columnLabelFormat: ColumnLabelFormat | undefined;
|
||||
}> = React.memo(({ aggregate, onUpdateAggregate, columnId, columnLabelFormat }) => {
|
||||
const isNumberColumn = columnLabelFormat?.columnType
|
||||
|
@ -38,7 +38,7 @@ export const EditMetricAggregate: React.FC<{
|
|||
}, [aggregate, disableOptions]);
|
||||
|
||||
const onUpdateMetricValueAggregate = useMemoizedFn((value: string) => {
|
||||
onUpdateAggregate(value as IBusterMetricChartConfig['metricValueAggregate']);
|
||||
onUpdateAggregate(value as BusterMetricChartConfig['metricValueAggregate']);
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { ColumnMetaData, IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnMetaData, BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { DerivedMetricTitle } from '@/api/asset_interfaces/metric/charts';
|
||||
import { Separator } from '@/components/ui/seperator';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
|
@ -12,12 +12,12 @@ import { createColumnFieldOptions } from './helpers';
|
|||
|
||||
export const StylingMetric: React.FC<{
|
||||
className?: string;
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
metricHeader: IBusterMetricChartConfig['metricHeader'];
|
||||
metricSubHeader: IBusterMetricChartConfig['metricSubHeader'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
metricHeader: BusterMetricChartConfig['metricHeader'];
|
||||
metricSubHeader: BusterMetricChartConfig['metricSubHeader'];
|
||||
rowCount: number;
|
||||
metricValueAggregate: IBusterMetricChartConfig['metricValueAggregate'];
|
||||
metricColumnId: IBusterMetricChartConfig['metricColumnId'];
|
||||
metricValueAggregate: BusterMetricChartConfig['metricValueAggregate'];
|
||||
metricColumnId: BusterMetricChartConfig['metricColumnId'];
|
||||
columnMetadata: ColumnMetaData[];
|
||||
}> = ({
|
||||
className,
|
||||
|
@ -31,7 +31,7 @@ export const StylingMetric: React.FC<{
|
|||
}) => {
|
||||
const { onUpdateMetricChartConfig } = useUpdateMetricChart();
|
||||
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<IBusterMetricChartConfig>) => {
|
||||
const onUpdateChartConfig = useMemoizedFn((chartConfig: Partial<BusterMetricChartConfig>) => {
|
||||
onUpdateMetricChartConfig({ chartConfig });
|
||||
});
|
||||
|
||||
|
@ -82,12 +82,12 @@ export const StylingMetric: React.FC<{
|
|||
};
|
||||
|
||||
const PrimaryMetricStyling: React.FC<{
|
||||
metricColumnId: IBusterMetricChartConfig['metricColumnId'];
|
||||
metricValueAggregate: IBusterMetricChartConfig['metricValueAggregate'];
|
||||
metricColumnId: BusterMetricChartConfig['metricColumnId'];
|
||||
metricValueAggregate: BusterMetricChartConfig['metricValueAggregate'];
|
||||
columnFieldOptions: ReturnType<typeof createColumnFieldOptions>;
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
rowCount: number;
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = ({
|
||||
metricColumnId,
|
||||
columnLabelFormats,
|
||||
|
@ -104,7 +104,7 @@ const PrimaryMetricStyling: React.FC<{
|
|||
metricColumnId: string;
|
||||
metricValueAggregate?: DerivedMetricTitle['aggregate'];
|
||||
}) => {
|
||||
const newConfig: Partial<IBusterMetricChartConfig> = {
|
||||
const newConfig: Partial<BusterMetricChartConfig> = {
|
||||
metricColumnId
|
||||
};
|
||||
if (metricValueAggregate) {
|
||||
|
@ -116,7 +116,7 @@ const PrimaryMetricStyling: React.FC<{
|
|||
);
|
||||
|
||||
const onUpdateAggregate = useMemoizedFn(
|
||||
(aggregate: IBusterMetricChartConfig['metricValueAggregate']) => {
|
||||
(aggregate: BusterMetricChartConfig['metricValueAggregate']) => {
|
||||
onUpdateChartConfig({ metricValueAggregate: aggregate });
|
||||
}
|
||||
);
|
||||
|
@ -142,12 +142,12 @@ const PrimaryMetricStyling: React.FC<{
|
|||
};
|
||||
|
||||
const HeaderMetricStyling: React.FC<{
|
||||
header: IBusterMetricChartConfig['metricHeader'] | IBusterMetricChartConfig['metricSubHeader'];
|
||||
header: BusterMetricChartConfig['metricHeader'] | BusterMetricChartConfig['metricSubHeader'];
|
||||
columnFieldOptions: ReturnType<typeof createColumnFieldOptions>;
|
||||
rowCount: number;
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'];
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'];
|
||||
type: 'header' | 'subHeader';
|
||||
onUpdateChartConfig: (chartConfig: Partial<IBusterMetricChartConfig>) => void;
|
||||
onUpdateChartConfig: (chartConfig: Partial<BusterMetricChartConfig>) => void;
|
||||
}> = ({ header, type, columnFieldOptions, rowCount, columnLabelFormats, onUpdateChartConfig }) => {
|
||||
const isStringHeader = typeof header === 'string';
|
||||
const isObjectHeader = typeof header === 'object';
|
||||
|
@ -187,7 +187,7 @@ const HeaderMetricStyling: React.FC<{
|
|||
);
|
||||
|
||||
const onUpdateAggregate = useMemoizedFn(
|
||||
(aggregate: IBusterMetricChartConfig['metricValueAggregate']) => {
|
||||
(aggregate: BusterMetricChartConfig['metricValueAggregate']) => {
|
||||
const key = type === 'header' ? 'metricHeader' : 'metricSubHeader';
|
||||
const newConfig: DerivedMetricTitle = {
|
||||
columnId: (header as DerivedMetricTitle)?.columnId,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import type { ColumnMetaData, IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { ColumnMetaData, BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { SelectItem } from '@/components/ui/select';
|
||||
import { formatLabel } from '@/lib';
|
||||
import { ColumnTypeIcon } from '../SelectAxis/config';
|
||||
|
||||
export const createColumnFieldOptions = (
|
||||
columnMetadata: ColumnMetaData[],
|
||||
columnLabelFormats: IBusterMetricChartConfig['columnLabelFormats'],
|
||||
columnLabelFormats: BusterMetricChartConfig['columnLabelFormats'],
|
||||
iconClass: string
|
||||
): SelectItem<string>[] => {
|
||||
return columnMetadata.map<SelectItem<string>>((column) => {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { BusterMetricData, DataMetadata, IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { ChartType } from '@/api/asset_interfaces/metric/charts';
|
||||
import type { BusterMetricData, BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { DataMetadata } from '@buster/server-shared/metrics';
|
||||
import { BusterChart } from '@/components/ui/charts';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import { METRIC_CHART_CONTAINER_ID } from './config';
|
||||
|
||||
interface MetricViewChartContentProps {
|
||||
className?: string;
|
||||
chartConfig: IBusterMetric['chart_config'];
|
||||
chartConfig: BusterMetric['chart_config'];
|
||||
metricData: BusterMetricData['data'];
|
||||
dataMetadata: DataMetadata | undefined;
|
||||
fetchedData: boolean;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type {
|
||||
ColumnMetaData,
|
||||
IBusterMetric,
|
||||
IBusterMetricChartConfig
|
||||
BusterMetric,
|
||||
BusterMetricChartConfig
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import type {
|
||||
BusterChartConfigProps,
|
||||
|
@ -57,9 +57,9 @@ export const didColumnDataChange = (
|
|||
* @returns A new chart configuration suitable for the changed SQL data
|
||||
*/
|
||||
export const simplifyChatConfigForSQLChange = (
|
||||
chartConfig: IBusterMetricChartConfig,
|
||||
data_metadata: IBusterMetric['data_metadata']
|
||||
): IBusterMetricChartConfig => {
|
||||
chartConfig: BusterMetricChartConfig,
|
||||
data_metadata: BusterMetric['data_metadata']
|
||||
): BusterMetricChartConfig => {
|
||||
// Create a new mapping of column name to format settings
|
||||
// This preserves existing format settings only when the column type hasn't changed
|
||||
const columnLabelFormats = data_metadata?.column_metadata?.reduce<
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useRef } from 'react';
|
||||
import type { BusterMetricData, IBusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import type { ChartConfigProps } from '@buster/server-shared/metrics';
|
||||
import type { BusterMetricData } from '@/api/asset_interfaces/metric';
|
||||
import type { RunSQLResponse } from '@/api/asset_interfaces/sql';
|
||||
import { useRunSQL as useRunSQLQuery } from '@/api/buster_rest';
|
||||
import { useGetLatestMetricVersionMemoized, useUpdateMetric } from '@/api/buster_rest/metrics';
|
||||
|
@ -38,7 +39,7 @@ export const useMetricRunSQL = () => {
|
|||
const getLatestMetricVersion = useGetLatestMetricVersionMemoized();
|
||||
|
||||
const originalConfigs = useRef<{
|
||||
chartConfig: IBusterMetricChartConfig;
|
||||
chartConfig: ChartConfigProps;
|
||||
sql: string;
|
||||
data: BusterMetricData['data'];
|
||||
dataMetadata: BusterMetricData['data_metadata'];
|
||||
|
@ -88,7 +89,7 @@ export const useMetricRunSQL = () => {
|
|||
const newColumnData = data_metadata?.column_metadata;
|
||||
|
||||
const didDataMetadataChange = didColumnDataChange(oldColumnData, newColumnData);
|
||||
const totallyDefaultChartConfig: IBusterMetricChartConfig = didDataMetadataChange
|
||||
const totallyDefaultChartConfig: ChartConfigProps = didDataMetadataChange
|
||||
? simplifyChatConfigForSQLChange(metricMessage.chart_config, data_metadata)
|
||||
: metricMessage.chart_config;
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import type { ColumnLabelFormat } from '@buster/server-shared/metrics';
|
||||
import {
|
||||
type ColumnLabelFormat,
|
||||
DEFAULT_COLUMN_LABEL_FORMAT,
|
||||
DEFAULT_DATE_FORMAT_DAY_OF_WEEK,
|
||||
DEFAULT_DATE_FORMAT_MONTH_OF_YEAR,
|
||||
DEFAULT_DATE_FORMAT_QUARTER
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
} from '@buster/server-shared/metrics';
|
||||
import { formatDate } from './date';
|
||||
import { formatNumber, roundNumber } from './numbers';
|
||||
import { makeHumanReadble } from './text';
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import type React from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import type { BusterMetricData, IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetricData, BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { downloadImageData, exportElementToImage } from './exportUtils';
|
||||
import { timeout } from './timeout';
|
||||
|
||||
export const generateChartDownloadImage = async (
|
||||
message: IBusterMetric,
|
||||
message: BusterMetric,
|
||||
messageData: NonNullable<BusterMetricData['data']>,
|
||||
isDark = false
|
||||
) => {
|
||||
|
@ -61,7 +61,7 @@ export const generateChartDownloadImage = async (
|
|||
|
||||
export const generateChartPreviewImage = async (
|
||||
message: {
|
||||
chart_config: IBusterMetric['chart_config'];
|
||||
chart_config: BusterMetric['chart_config'];
|
||||
} | null,
|
||||
messageData: BusterMetricData,
|
||||
isDark = true
|
||||
|
@ -77,7 +77,7 @@ export const generateChartPreviewImage = async (
|
|||
|
||||
const container = (
|
||||
<PreviewImageReactComponent
|
||||
message={message as IBusterMetric}
|
||||
message={message as BusterMetric}
|
||||
messageData={messageData}
|
||||
isDark={isDark}
|
||||
/>
|
||||
|
@ -149,7 +149,7 @@ const ChartPreviewImage = ({
|
|||
message,
|
||||
messageData
|
||||
}: {
|
||||
message: IBusterMetric;
|
||||
message: BusterMetric;
|
||||
messageData: BusterMetricData;
|
||||
}) => {
|
||||
const data = messageData?.data || [];
|
||||
|
@ -174,7 +174,7 @@ const ChartPreviewImage = ({
|
|||
|
||||
export const PreviewImageReactComponent: React.FC<{
|
||||
message: {
|
||||
chart_config: IBusterMetric['chart_config'];
|
||||
chart_config: BusterMetric['chart_config'];
|
||||
} | null;
|
||||
messageData: BusterMetricData;
|
||||
isDark: boolean;
|
||||
|
@ -210,7 +210,7 @@ export const PreviewImageReactComponent: React.FC<{
|
|||
}`}>
|
||||
{BusterLogo}
|
||||
{hasData && message?.chart_config ? (
|
||||
<ChartPreviewImage message={message as IBusterMetric} messageData={messageData} />
|
||||
<ChartPreviewImage message={message as BusterMetric} messageData={messageData} />
|
||||
) : (
|
||||
<div
|
||||
className={`${isDark ? 'text-stone-400' : 'text-stone-700'}`}
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
type ColumnLabelFormat,
|
||||
type ColumnMetaData,
|
||||
DEFAULT_COLUMN_LABEL_FORMAT,
|
||||
type IBusterMetricChartConfig,
|
||||
type BusterMetricChartConfig,
|
||||
type IColumnLabelFormat,
|
||||
type SimplifiedColumnType
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
|
@ -12,7 +12,7 @@ import { isDateColumnType, isNumericColumnType, simplifyColumnType } from '@/lib
|
|||
export const createDefaultColumnLabelFormats = (
|
||||
columnLabelFormats: Record<string, IColumnLabelFormat> | undefined,
|
||||
columnsMetaData: ColumnMetaData[] | undefined
|
||||
): IBusterMetricChartConfig['columnLabelFormats'] => {
|
||||
): BusterMetricChartConfig['columnLabelFormats'] => {
|
||||
if (!columnsMetaData) return {};
|
||||
|
||||
return columnsMetaData.reduce(
|
||||
|
@ -25,7 +25,7 @@ export const createDefaultColumnLabelFormats = (
|
|||
});
|
||||
return acc;
|
||||
},
|
||||
{} as IBusterMetricChartConfig['columnLabelFormats']
|
||||
{} as BusterMetricChartConfig['columnLabelFormats']
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -2,17 +2,17 @@ import { create } from 'mutative';
|
|||
import {
|
||||
type ColumnMetaData,
|
||||
DEFAULT_COLUMN_SETTINGS,
|
||||
type IBusterMetricChartConfig
|
||||
type BusterMetricChartConfig
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import type { ColumnSettings } from '@/api/asset_interfaces/metric/charts';
|
||||
|
||||
export const createDefaultColumnSettings = (
|
||||
existingColumnSettings: Record<string, ColumnSettings> | undefined,
|
||||
columnsMetaData: ColumnMetaData[] | undefined
|
||||
): IBusterMetricChartConfig['columnSettings'] => {
|
||||
): BusterMetricChartConfig['columnSettings'] => {
|
||||
if (!columnsMetaData) return {};
|
||||
|
||||
return create({} as IBusterMetricChartConfig['columnSettings'], (draft) => {
|
||||
return create({} as BusterMetricChartConfig['columnSettings'], (draft) => {
|
||||
for (const column of columnsMetaData) {
|
||||
draft[column.name] = create(DEFAULT_COLUMN_SETTINGS, (settingsDraft) => {
|
||||
if (existingColumnSettings?.[column.name]) {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import isEmpty from 'lodash/isEmpty';
|
||||
import { create } from 'mutative';
|
||||
import { type BusterMetric, type BusterMetricChartConfig } from '@/api/asset_interfaces/metric';
|
||||
import {
|
||||
type BusterMetric,
|
||||
type DataMetadata,
|
||||
DEFAULT_CHART_CONFIG,
|
||||
DEFAULT_CHART_CONFIG_ENTRIES,
|
||||
type IBusterMetricChartConfig
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import type { BusterChartConfigProps } from '@/api/asset_interfaces/metric/charts';
|
||||
type ChartConfigProps,
|
||||
type DataMetadata
|
||||
} from '@buster/server-shared/metrics';
|
||||
import {
|
||||
createDefaultBarAndLineAxis,
|
||||
createDefaultPieAxis,
|
||||
|
@ -18,27 +17,27 @@ import { createDefaultColumnSettings } from './createDefaultColumnSettings';
|
|||
|
||||
const keySpecificHandlers: Partial<
|
||||
Record<
|
||||
keyof IBusterMetricChartConfig,
|
||||
keyof BusterMetricChartConfig,
|
||||
(
|
||||
value: unknown,
|
||||
dataMetadata: DataMetadata | undefined,
|
||||
pieChartAxis: IBusterMetricChartConfig['pieChartAxis'] | undefined
|
||||
pieChartAxis: BusterMetricChartConfig['pieChartAxis'] | undefined
|
||||
) => unknown
|
||||
>
|
||||
> = {
|
||||
colors: (value: unknown) => {
|
||||
const colors = value as IBusterMetricChartConfig['colors'];
|
||||
const colors = value as BusterMetricChartConfig['colors'];
|
||||
if (isEmpty(colors)) return DEFAULT_CHART_CONFIG.colors;
|
||||
if (colors.length >= 3) return colors; //we need at least 3 colors for the chart icons
|
||||
return Array.from({ length: 3 }, (_, index) => colors[index % colors.length]);
|
||||
},
|
||||
scatterDotSize: (value: unknown) => {
|
||||
const scatterDotSize = value as IBusterMetricChartConfig['scatterDotSize'];
|
||||
const scatterDotSize = value as BusterMetricChartConfig['scatterDotSize'];
|
||||
if (isEmpty(scatterDotSize)) return DEFAULT_CHART_CONFIG.scatterDotSize;
|
||||
return scatterDotSize;
|
||||
},
|
||||
barAndLineAxis: (value: unknown, dataMetadata) => {
|
||||
const barAndLineAxis = value as IBusterMetricChartConfig['barAndLineAxis'];
|
||||
const barAndLineAxis = value as BusterMetricChartConfig['barAndLineAxis'];
|
||||
if (isEmpty(barAndLineAxis)) {
|
||||
return createDefaultBarAndLineAxis(dataMetadata?.column_metadata);
|
||||
}
|
||||
|
@ -50,7 +49,7 @@ const keySpecificHandlers: Partial<
|
|||
};
|
||||
},
|
||||
pieChartAxis: (value: unknown, dataMetadata) => {
|
||||
const pieChartAxis = value as IBusterMetricChartConfig['pieChartAxis'];
|
||||
const pieChartAxis = value as BusterMetricChartConfig['pieChartAxis'];
|
||||
if (isEmpty(pieChartAxis)) return createDefaultPieAxis(dataMetadata?.column_metadata);
|
||||
return {
|
||||
x: pieChartAxis.x || DEFAULT_CHART_CONFIG.pieChartAxis.x,
|
||||
|
@ -59,7 +58,7 @@ const keySpecificHandlers: Partial<
|
|||
};
|
||||
},
|
||||
scatterAxis: (value: unknown, dataMetadata) => {
|
||||
const scatterAxis = value as IBusterMetricChartConfig['scatterAxis'];
|
||||
const scatterAxis = value as BusterMetricChartConfig['scatterAxis'];
|
||||
if (isEmpty(scatterAxis)) return createDefaultScatterAxis(dataMetadata?.column_metadata);
|
||||
return {
|
||||
x: scatterAxis.x || DEFAULT_CHART_CONFIG.scatterAxis.x,
|
||||
|
@ -70,7 +69,7 @@ const keySpecificHandlers: Partial<
|
|||
};
|
||||
},
|
||||
comboChartAxis: (value: unknown, dataMetadata) => {
|
||||
const comboChartAxis = value as IBusterMetricChartConfig['comboChartAxis'];
|
||||
const comboChartAxis = value as BusterMetricChartConfig['comboChartAxis'];
|
||||
if (isEmpty(comboChartAxis)) return createDefaultBarAndLineAxis(dataMetadata?.column_metadata);
|
||||
return {
|
||||
x: comboChartAxis.x || DEFAULT_CHART_CONFIG.comboChartAxis.x,
|
||||
|
@ -81,7 +80,7 @@ const keySpecificHandlers: Partial<
|
|||
};
|
||||
},
|
||||
metricColumnId: (value: unknown, dataMetadata) => {
|
||||
const metricColumnId = value as IBusterMetricChartConfig['metricColumnId'];
|
||||
const metricColumnId = value as BusterMetricChartConfig['metricColumnId'];
|
||||
if (isEmpty(metricColumnId)) {
|
||||
const firstNumberColumn = dataMetadata?.column_metadata?.find(
|
||||
(m) => m.simple_type === 'number'
|
||||
|
@ -91,25 +90,25 @@ const keySpecificHandlers: Partial<
|
|||
return metricColumnId;
|
||||
},
|
||||
metricHeader: (value: unknown) => {
|
||||
const metricHeader = value as IBusterMetricChartConfig['metricHeader'];
|
||||
const metricHeader = value as BusterMetricChartConfig['metricHeader'];
|
||||
if (isEmpty(metricHeader)) return DEFAULT_CHART_CONFIG.metricHeader;
|
||||
return metricHeader;
|
||||
},
|
||||
metricSubHeader: (value: unknown) => {
|
||||
const metricSubHeader = value as IBusterMetricChartConfig['metricSubHeader'];
|
||||
const metricSubHeader = value as BusterMetricChartConfig['metricSubHeader'];
|
||||
if (isEmpty(metricSubHeader)) return DEFAULT_CHART_CONFIG.metricSubHeader;
|
||||
return metricSubHeader;
|
||||
},
|
||||
columnLabelFormats: (value: unknown, dataMetadata) => {
|
||||
const columnLabelFormats = value as IBusterMetricChartConfig['columnLabelFormats'];
|
||||
const columnLabelFormats = value as BusterMetricChartConfig['columnLabelFormats'];
|
||||
return createDefaultColumnLabelFormats(columnLabelFormats, dataMetadata?.column_metadata);
|
||||
},
|
||||
columnSettings: (value: unknown, dataMetadata) => {
|
||||
const columnSettings = value as IBusterMetricChartConfig['columnSettings'];
|
||||
const columnSettings = value as BusterMetricChartConfig['columnSettings'];
|
||||
return createDefaultColumnSettings(columnSettings, dataMetadata?.column_metadata);
|
||||
},
|
||||
pieLabelPosition: (value: unknown, dataMetadata, pieChartAxis) => {
|
||||
const pieLabelPosition = value as IBusterMetricChartConfig['pieLabelPosition'];
|
||||
const pieLabelPosition = value as BusterMetricChartConfig['pieLabelPosition'];
|
||||
// if (isEmpty(pieLabelPosition)) {
|
||||
// const firstPieColumn = pieChartAxis?.x?.[0];
|
||||
// const firstPieColumnMetaData = dataMetadata?.column_metadata?.find(
|
||||
|
@ -124,14 +123,14 @@ const keySpecificHandlers: Partial<
|
|||
|
||||
export const createDefaultChartConfig = (
|
||||
message: Pick<BusterMetric, 'chart_config' | 'data_metadata'>
|
||||
): IBusterMetricChartConfig => {
|
||||
const chartConfig: BusterChartConfigProps | undefined = message.chart_config;
|
||||
): BusterMetricChartConfig => {
|
||||
const chartConfig: ChartConfigProps | undefined = message.chart_config;
|
||||
const dataMetadata = message.data_metadata;
|
||||
const pieChartAxis = chartConfig?.pieChartAxis;
|
||||
|
||||
const newChartConfig = create(DEFAULT_CHART_CONFIG, (draft) => {
|
||||
for (const [_key, defaultValue] of DEFAULT_CHART_CONFIG_ENTRIES) {
|
||||
const key = _key as keyof IBusterMetricChartConfig;
|
||||
const key = _key as keyof BusterMetricChartConfig;
|
||||
const chartConfigValue = chartConfig?.[key];
|
||||
|
||||
const handler = keySpecificHandlers[key];
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { DEFAULT_IBUSTER_METRIC, type IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { DEFAULT_IBUSTER_METRIC, type BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
|
||||
export const resolveEmptyMetric = (
|
||||
metric: IBusterMetric | undefined,
|
||||
metric: BusterMetric | undefined,
|
||||
metricId: string
|
||||
): IBusterMetric => {
|
||||
): BusterMetric => {
|
||||
if (!metric || !metric?.id) {
|
||||
return { ...DEFAULT_IBUSTER_METRIC, ...metric, id: metricId };
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import isEqual from 'lodash/isEqual';
|
||||
import type { DataMetadata, IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { DataMetadata, BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import {
|
||||
DEFAULT_CHART_CONFIG_ENTRIES,
|
||||
DEFAULT_COLUMN_LABEL_FORMAT,
|
||||
DEFAULT_COLUMN_SETTINGS,
|
||||
type IBusterMetricChartConfig
|
||||
type BusterMetricChartConfig
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import type {
|
||||
BarAndLineAxis,
|
||||
|
@ -23,15 +23,15 @@ const DEFAULT_COLUMN_SETTINGS_ENTRIES = Object.entries(DEFAULT_COLUMN_SETTINGS);
|
|||
const DEFAULT_COLUMN_LABEL_FORMATS_ENTRIES = Object.entries(DEFAULT_COLUMN_LABEL_FORMAT);
|
||||
|
||||
export const getChangedTopLevelMessageValues = (
|
||||
newMetric: IBusterMetric,
|
||||
oldMetric: IBusterMetric
|
||||
newMetric: BusterMetric,
|
||||
oldMetric: BusterMetric
|
||||
) => {
|
||||
const changes = getChangedValues(oldMetric, newMetric, ['name', 'status', 'sql', 'file']);
|
||||
return changes;
|
||||
};
|
||||
|
||||
const keySpecificHandlers: Partial<
|
||||
Record<keyof IBusterMetricChartConfig, (value: unknown) => unknown>
|
||||
Record<keyof BusterMetricChartConfig, (value: unknown) => unknown>
|
||||
> = {
|
||||
barAndLineAxis: (value: unknown) => value as BarAndLineAxis,
|
||||
scatterAxis: (value: unknown) => value as ScatterAxis,
|
||||
|
@ -97,14 +97,14 @@ const keySpecificHandlers: Partial<
|
|||
}
|
||||
};
|
||||
|
||||
export const getChangesFromDefaultChartConfig = (newMetric: IBusterMetric) => {
|
||||
export const getChangesFromDefaultChartConfig = (newMetric: BusterMetric) => {
|
||||
const chartConfig = newMetric.chart_config;
|
||||
if (!chartConfig) return {} as BusterChartConfigProps;
|
||||
|
||||
const diff: Partial<IBusterMetricChartConfig> = {};
|
||||
const diff: Partial<BusterMetricChartConfig> = {};
|
||||
|
||||
for (const [_key, defaultValue] of DEFAULT_CHART_CONFIG_ENTRIES) {
|
||||
const key = _key as keyof IBusterMetricChartConfig;
|
||||
const key = _key as keyof BusterMetricChartConfig;
|
||||
const chartConfigValue = chartConfig[key];
|
||||
const handler = keySpecificHandlers[key];
|
||||
|
||||
|
@ -127,7 +127,7 @@ export const getChangesFromDefaultChartConfig = (newMetric: IBusterMetric) => {
|
|||
};
|
||||
|
||||
export const combineChangeFromDefaultChartConfig = (
|
||||
newMetric: IBusterMetric,
|
||||
newMetric: BusterMetric,
|
||||
dataMetadata: DataMetadata
|
||||
) => {
|
||||
const chartConfig = createDefaultChartConfig({
|
||||
|
@ -138,8 +138,8 @@ export const combineChangeFromDefaultChartConfig = (
|
|||
};
|
||||
|
||||
export const prepareMetricUpdateMetric = (
|
||||
newMetric: IBusterMetric,
|
||||
prevMetric: IBusterMetric
|
||||
newMetric: BusterMetric,
|
||||
prevMetric: BusterMetric
|
||||
): Parameters<typeof updateMetric>[0] | null => {
|
||||
const changedTopLevelValues = getChangedTopLevelMessageValues(
|
||||
newMetric,
|
||||
|
|
|
@ -2,16 +2,16 @@ import {
|
|||
ChartEncodes,
|
||||
ChartType,
|
||||
ColumnMetaData,
|
||||
IBusterMetricChartConfig
|
||||
BusterMetricChartConfig
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
|
||||
export interface SelectChartTypeProps {
|
||||
selectedChartType: ChartType;
|
||||
lineGroupType: IBusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: IBusterMetricChartConfig['barGroupType'];
|
||||
barLayout: IBusterMetricChartConfig['barLayout'];
|
||||
lineGroupType: BusterMetricChartConfig['lineGroupType'];
|
||||
barGroupType: BusterMetricChartConfig['barGroupType'];
|
||||
barLayout: BusterMetricChartConfig['barLayout'];
|
||||
colors: string[];
|
||||
columnMetadata: ColumnMetaData[];
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings'];
|
||||
columnSettings: BusterMetricChartConfig['columnSettings'];
|
||||
selectedAxis: ChartEncodes;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import omit from 'lodash/omit';
|
||||
import type { IBusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import type { BusterMetricChartConfig } from '@/api/asset_interfaces';
|
||||
import { ChartType } from '@/api/asset_interfaces/metric/charts';
|
||||
import { CHART_ICON_LIST, ChartIconType, DETERMINE_SELECTED_CHART_TYPE_ORDER } from './config';
|
||||
import type { SelectChartTypeProps } from './chartIcon.types';
|
||||
|
@ -37,7 +37,7 @@ export const getSelectedChartTypeConfig = (
|
|||
|
||||
const chartTypeMethod: Record<
|
||||
ChartIconType,
|
||||
() => Partial<IBusterMetricChartConfig> & {
|
||||
() => Partial<BusterMetricChartConfig> & {
|
||||
hasAreaStyle?: boolean;
|
||||
}
|
||||
> = {
|
||||
|
@ -130,14 +130,14 @@ export const disableTypeMethod: Record<
|
|||
|
||||
export const selectedChartTypeMethod = (
|
||||
chartIconType: ChartIconType,
|
||||
columnSettings: IBusterMetricChartConfig['columnSettings']
|
||||
): Partial<IBusterMetricChartConfig> => {
|
||||
columnSettings: BusterMetricChartConfig['columnSettings']
|
||||
): Partial<BusterMetricChartConfig> => {
|
||||
const fullRes = chartTypeMethod[chartIconType]();
|
||||
const hasAreaStyle = !!fullRes.hasAreaStyle;
|
||||
const resOmitted = omit(fullRes, 'hasAreaStyle');
|
||||
|
||||
if (resOmitted.selectedChartType === 'line') {
|
||||
const newColumnSettings: IBusterMetricChartConfig['columnSettings'] = Object.fromEntries(
|
||||
const newColumnSettings: BusterMetricChartConfig['columnSettings'] = Object.fromEntries(
|
||||
Object.entries(columnSettings).map(([key, value]) => [
|
||||
key,
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import type { BusterMetric, IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetric, BusterMetric } from '@/api/asset_interfaces/metric';
|
||||
import { createDefaultChartConfig } from './messageAutoChartHandler';
|
||||
|
||||
export const upgradeMetricToIMetric = (
|
||||
metric: BusterMetric,
|
||||
oldMetric: IBusterMetric | null | undefined
|
||||
): IBusterMetric => {
|
||||
oldMetric: BusterMetric | null | undefined
|
||||
): BusterMetric => {
|
||||
const chart_config = createDefaultChartConfig(metric);
|
||||
return {
|
||||
...oldMetric,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import {
|
||||
type BusterMetricListItem,
|
||||
ChartType,
|
||||
type DataMetadata,
|
||||
DEFAULT_CHART_CONFIG,
|
||||
type IBusterMetric,
|
||||
type IBusterMetricChartConfig
|
||||
type BusterMetric,
|
||||
type BusterMetricChartConfig
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import { ShareRole, VerificationStatus } from '@/api/asset_interfaces/share';
|
||||
import type { DataMetadata } from '@buster/server-shared/metrics';
|
||||
|
||||
// Utility functions for predictable mock data generation
|
||||
const CHART_TYPES: ChartType[] = ['bar', 'table', 'line', 'pie', 'scatter', 'metric'];
|
||||
|
@ -62,7 +62,7 @@ const generatePredictableEmail = (id: string): string => {
|
|||
return `${name}.${hash % 100}@${domain}`;
|
||||
};
|
||||
|
||||
const createMockChartConfig = (id: string): IBusterMetricChartConfig => {
|
||||
const createMockChartConfig = (id: string): BusterMetricChartConfig => {
|
||||
const hash = Array.from(id).reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
||||
const chartType: ChartType = CHART_TYPES[hash % CHART_TYPES.length];
|
||||
|
||||
|
@ -126,7 +126,7 @@ const dataMetadata: DataMetadata = {
|
|||
row_count: 10
|
||||
};
|
||||
|
||||
export const createMockMetric = (id: string): IBusterMetric => {
|
||||
export const createMockMetric = (id: string): BusterMetric => {
|
||||
const chart_config = createMockChartConfig(id);
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { BusterMetricData, DataMetadata } from '@/api/asset_interfaces/metric';
|
||||
import type { BusterMetricData } from '@/api/asset_interfaces/metric';
|
||||
import type { DataMetadata } from '@buster/server-shared/metrics';
|
||||
|
||||
const PRODUCTS = [
|
||||
'Laptop',
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue