From 61b7076ff99c176733c328fee46acb825173d885 Mon Sep 17 00:00:00 2001 From: Leto Date: Thu, 2 Jan 2025 19:24:49 +0800 Subject: [PATCH 1/5] feat: add TimeQuerySwitch and related rules --- .../datasources/mm-info/metric-detail.ts | 8 ++- .../mm-info/metric-detail.types.ts | 4 ++ .../mm-info/metric-detail.utils.ts | 33 +++++++++++- .../link-metrics-to-time-and-step.tsx | 30 +++-------- .../edit-metric-query/time-query-switch.tsx | 54 +++++++++++++++++++ 5 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/time-query-switch.tsx diff --git a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.ts b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.ts index 5e84ad773..a178730d5 100644 --- a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.ts +++ b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.ts @@ -6,7 +6,7 @@ import { QueryFailureError } from '~/api-caller'; import { APIClient } from '~/api-caller/request'; import { DataSourceType } from '~/model'; import { postProcessWithDataSource, preProcessWithDataSource } from '~/utils'; -import { CombinedMetricCol, MetricDetail, MetricSourceCol } from './metric-detail.types'; +import { CombinedMetric, CombinedMetricCol, DerivedMetric, MetricDetail, MetricSourceCol } from './metric-detail.types'; import { makeFilterColOptions, makeGroupByColOptions, MetricGroupByColOption, parseData } from './metric-detail.utils'; function getURLByType(type: 'derived' | 'combined', id: string) { @@ -29,6 +29,8 @@ export const MetricDetailModel = types filters: types.optional(types.frozen>(), []), groupBys: types.optional(types.frozen>(), []), trendingDateCol: types.optional(types.frozen(), null), + supportTrending: types.optional(types.boolean, false), + requireTrendingReason: types.optional(types.string, ''), state: types.optional(types.enumeration(['idle', 'loading', 'error']), 'idle'), error: types.frozen(), }) @@ -106,10 +108,12 @@ export const MetricDetailModel = types ); const result = postProcessWithDataSource(self.mmInfo.dataSource, response); const data = _.cloneDeep(result.data); - const { filters, groupBys, trendingDateCol } = parseData(result.data); + const { filters, groupBys, trendingDateCol, supportTrending, requireTrendingReason } = parseData(result.data); self.data = data; self.filters = filters; self.groupBys = groupBys; + self.supportTrending = supportTrending; + self.requireTrendingReason = requireTrendingReason; self.trendingDateCol = trendingDateCol; self.state = 'idle'; self.error = null; diff --git a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.types.ts b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.types.ts index 88b093c70..9e78e3417 100644 --- a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.types.ts +++ b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.types.ts @@ -35,10 +35,12 @@ export type DimensionCol = { dimensionFieldId: string | null; metricSourceCol: MetricSourceCol; }; + export type DerivedMetric = { id: string; name: string; description: string; + calculation: 'accumulate' | 'percentage_total' | 'yoy_ratio' | 'step_ratio' | 'span_steps_calculation'; cols: DimensionCol[]; }; @@ -49,6 +51,8 @@ export type CombinedMetric = { description: string; filters: CombinedMetricCol[]; groupBys: CombinedMetricCol[]; + derivedMetrics: DerivedMetric[]; + supportTrending: boolean; }; export type MetricDetail = DerivedMetric | CombinedMetric; diff --git a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts index 9f9a7605e..1545e209f 100644 --- a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts +++ b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts @@ -8,20 +8,51 @@ import { MetricSourceCol, } from './metric-detail.types'; +const TrendingCalculationTypeSet = new Set(['yoy_ratio', 'step_ratio', 'span_steps_calculation']); +const DerivedCalculationLabelMap = { + accumulate: '累计计算', + yoy_ratio: '年同比率(yoy)', + step_ratio: '环比率', + span_steps_calculation: '移动计算', + percentage_total: '总占', +} as const; + export function parseData(data: MetricDetail) { if ('cols' in data) { const { cols } = data as DerivedMetric; + const trendingDateCol = cols.find((c) => c.type === 'trending_date_col')?.metricSourceCol ?? null; + const requireTrendingReason = TrendingCalculationTypeSet.has(data.calculation) + ? `当前指标涉及 ${_.get( + DerivedCalculationLabelMap, + data.calculation!, + data.calculation, + )},缺少时序则无法展示有效结果。 +` + : ''; return { filters: cols.filter((c) => c.type === 'filter').map((c) => c.metricSourceCol), groupBys: cols.filter((c) => c.type === 'group_by').map((c) => c.metricSourceCol), - trendingDateCol: cols.find((c) => c.type === 'trending_date_col')?.metricSourceCol ?? null, + trendingDateCol, + supportTrending: !!trendingDateCol, + requireTrendingReason, }; } + const calcs = _.uniq(data.derivedMetrics.map((it) => it.calculation)) + .filter((calc) => TrendingCalculationTypeSet.has(calc)) + .concat(['span_steps_calculation', 'step_ratio', 'yoy_ratio']); + const requireTrendingReason = data.supportTrending + ? `当前指标涉及 ${calcs + .map((it) => _.get(DerivedCalculationLabelMap, it, it)) + .join('、')},缺少时序则无法展示有效结果。` + : ''; + return { filters: data.filters, groupBys: data.groupBys, trendingDateCol: null, + supportTrending: data.supportTrending && calcs.length > 0, + requireTrendingReason, // supportTrending, then requireTrending }; } diff --git a/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/link-metrics-to-time-and-step.tsx b/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/link-metrics-to-time-and-step.tsx index bf972b71a..f1e0ccb58 100644 --- a/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/link-metrics-to-time-and-step.tsx +++ b/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/link-metrics-to-time-and-step.tsx @@ -1,4 +1,4 @@ -import { ActionIcon, Box, Group, Stack, Switch, Table, Text, Tooltip } from '@mantine/core'; +import { ActionIcon, Group, Stack, Table, Text, Tooltip } from '@mantine/core'; import { IconInfoCircle } from '@tabler/icons-react'; import { observer } from 'mobx-react-lite'; import { QueryModelInstance } from '~/dashboard-editor/model'; @@ -6,6 +6,7 @@ import { DataSourceModelInstance } from '~/dashboard-editor/model/datasources/da import { MericoMetricQueryMetaInstance } from '~/model'; import { RunByCheckbox } from './run-by-checkbox'; import { MetricTableStyles } from './table-styles'; +import { TimeQuerySwitch } from './time-query-switch'; import { VariableSelector } from './variable-selector'; import { VariableStat } from './variable-stats'; @@ -15,7 +16,7 @@ const TrendingDateSettings = observer(({ queryModel }: Props) => { const mmInfo = ds.mericoMetricInfo; const metric = mmInfo.metricDetail; const trendingDateCol = metric.trendingDateCol; - if (!config.timeQuery.enabled || !trendingDateCol) { + if (!config.timeQuery.enabled || !metric.supportTrending) { return null; } @@ -38,9 +39,9 @@ const TrendingDateSettings = observer(({ queryModel }: Props) => { - 时间维度: + 时间维度 - {trendingDateCol.name} + {trendingDateCol?.name ?? null} @@ -87,12 +88,6 @@ type Props = { queryModel: QueryModelInstance; }; export const LinkMetricsToTimeAndStep = observer(({ queryModel }: Props) => { - const config = queryModel.config as MericoMetricQueryMetaInstance; - const ds = queryModel.datasource as DataSourceModelInstance; - const mmInfo = ds.mericoMetricInfo; - const metric = mmInfo.metricDetail; - const trendingDateCol = metric.trendingDateCol; - return ( @@ -102,20 +97,7 @@ export const LinkMetricsToTimeAndStep = observer(({ queryModel }: Props) => { - {trendingDateCol ? ( - config.setTimeQueryEnabled(e.currentTarget.checked)} - /> - ) : ( - - - - - - )} + diff --git a/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/time-query-switch.tsx b/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/time-query-switch.tsx new file mode 100644 index 000000000..690501ad1 --- /dev/null +++ b/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/time-query-switch.tsx @@ -0,0 +1,54 @@ +import { Box, Switch, Tooltip } from '@mantine/core'; +import { observer } from 'mobx-react-lite'; +import { useEffect } from 'react'; +import { QueryModelInstance } from '~/dashboard-editor/model'; +import { DataSourceModelInstance } from '~/dashboard-editor/model/datasources/datasource'; +import { MericoMetricQueryMetaInstance } from '~/model'; + +type Props = { + queryModel: QueryModelInstance; +}; + +export const TimeQuerySwitch = observer(({ queryModel }: Props) => { + const config = queryModel.config as MericoMetricQueryMetaInstance; + const ds = queryModel.datasource as DataSourceModelInstance; + const mmInfo = ds.mericoMetricInfo; + const metric = mmInfo.metricDetail; + const trendingDateCol = metric.trendingDateCol; + + const enabled = config.timeQuery.enabled; + useEffect(() => { + if (!enabled && metric.requireTrendingReason) { + config.setTimeQueryEnabled(true); + return; + } + }, [metric.requireTrendingReason, enabled]); + + if (!metric.supportTrending) { + return ( + + + + + + ); + } + if (metric.requireTrendingReason) { + return ( + + + + + + ); + } + return ( + config.setTimeQueryEnabled(e.currentTarget.checked)} + styles={{ track: { cursor: 'pointer' } }} + /> + ); +}); From d3a07095b45649a48285d013d65de06190b67c0e Mon Sep 17 00:00:00 2001 From: Leto Date: Thu, 2 Jan 2025 19:25:04 +0800 Subject: [PATCH 2/5] fix(settings-form): misc --- settings-form/src/datasource/edit-data-source/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings-form/src/datasource/edit-data-source/index.tsx b/settings-form/src/datasource/edit-data-source/index.tsx index dd1623b29..59bfe6f52 100644 --- a/settings-form/src/datasource/edit-data-source/index.tsx +++ b/settings-form/src/datasource/edit-data-source/index.tsx @@ -33,6 +33,7 @@ function EditDataSourceForm({ dataSource, postSubmit, styles = defaultStyles }: title: t('common.state.successful'), message: t('datasource.state.updated'), color: 'green', + loading: false, autoClose: true, }); postSubmit(); @@ -42,6 +43,7 @@ function EditDataSourceForm({ dataSource, postSubmit, styles = defaultStyles }: title: t('common.state.failed'), message: error.message, color: 'red', + loading: false, autoClose: true, }); } From 49ca6716fa0d9c588a1b058dbb57f09447092fd9 Mon Sep 17 00:00:00 2001 From: Leto Date: Thu, 2 Jan 2025 19:25:32 +0800 Subject: [PATCH 3/5] chore: publish v14.4.0 --- api/package.json | 2 +- dashboard/package.json | 2 +- package.json | 2 +- settings-form/package.json | 2 +- website/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/package.json b/api/package.json index e0acce0ca..e9a26c923 100644 --- a/api/package.json +++ b/api/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/api", - "version": "14.3.6", + "version": "14.4.0", "description": "", "main": "index.js", "scripts": { diff --git a/dashboard/package.json b/dashboard/package.json index 039a56430..7efb85722 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/dashboard", - "version": "14.3.6", + "version": "14.4.0", "license": "Apache-2.0", "publishConfig": { "access": "public", diff --git a/package.json b/package.json index 514a08bb8..8ffb9ed81 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/root", - "version": "14.3.6", + "version": "14.4.0", "private": true, "workspaces": [ "api", diff --git a/settings-form/package.json b/settings-form/package.json index 02dc2f3d0..d67a3c058 100644 --- a/settings-form/package.json +++ b/settings-form/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/settings-form", - "version": "14.3.6", + "version": "14.4.0", "license": "Apache-2.0", "publishConfig": { "access": "public", diff --git a/website/package.json b/website/package.json index 24273e1d7..fd8b1f17d 100644 --- a/website/package.json +++ b/website/package.json @@ -2,7 +2,7 @@ "name": "@devtable/website", "private": true, "license": "Apache-2.0", - "version": "14.3.6", + "version": "14.4.0", "scripts": { "dev": "vite", "preview": "vite preview" From 10d13db4c2d59d0649555da55eb14d0c97cda878 Mon Sep 17 00:00:00 2001 From: Leto Date: Thu, 2 Jan 2025 19:40:40 +0800 Subject: [PATCH 4/5] fix: remove debug code --- .../model/datasources/mm-info/metric-detail.utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts index 1545e209f..4df09663b 100644 --- a/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts +++ b/dashboard/src/dashboard-editor/model/datasources/mm-info/metric-detail.utils.ts @@ -38,9 +38,9 @@ export function parseData(data: MetricDetail) { }; } - const calcs = _.uniq(data.derivedMetrics.map((it) => it.calculation)) - .filter((calc) => TrendingCalculationTypeSet.has(calc)) - .concat(['span_steps_calculation', 'step_ratio', 'yoy_ratio']); + const calcs = _.uniq(data.derivedMetrics.map((it) => it.calculation)).filter((calc) => + TrendingCalculationTypeSet.has(calc), + ); const requireTrendingReason = data.supportTrending ? `当前指标涉及 ${calcs .map((it) => _.get(DerivedCalculationLabelMap, it, it)) From d7197cefad01d5e7f5eed042ac0ade98acd11265 Mon Sep 17 00:00:00 2001 From: Leto Date: Thu, 2 Jan 2025 19:40:56 +0800 Subject: [PATCH 5/5] chore: publish v14.4.1 --- api/package.json | 2 +- dashboard/package.json | 2 +- package.json | 2 +- settings-form/package.json | 2 +- website/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/package.json b/api/package.json index e9a26c923..9c98e6761 100644 --- a/api/package.json +++ b/api/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/api", - "version": "14.4.0", + "version": "14.4.1", "description": "", "main": "index.js", "scripts": { diff --git a/dashboard/package.json b/dashboard/package.json index 7efb85722..f985890b6 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/dashboard", - "version": "14.4.0", + "version": "14.4.1", "license": "Apache-2.0", "publishConfig": { "access": "public", diff --git a/package.json b/package.json index 8ffb9ed81..f14d3522e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/root", - "version": "14.4.0", + "version": "14.4.1", "private": true, "workspaces": [ "api", diff --git a/settings-form/package.json b/settings-form/package.json index d67a3c058..9864ae4c6 100644 --- a/settings-form/package.json +++ b/settings-form/package.json @@ -1,6 +1,6 @@ { "name": "@devtable/settings-form", - "version": "14.4.0", + "version": "14.4.1", "license": "Apache-2.0", "publishConfig": { "access": "public", diff --git a/website/package.json b/website/package.json index fd8b1f17d..e48ea973f 100644 --- a/website/package.json +++ b/website/package.json @@ -2,7 +2,7 @@ "name": "@devtable/website", "private": true, "license": "Apache-2.0", - "version": "14.4.0", + "version": "14.4.1", "scripts": { "dev": "vite", "preview": "vite preview"