From e5062fd442c73b9718c6e9ac4dcc31869244a16d Mon Sep 17 00:00:00 2001 From: Boris Date: Thu, 19 Sep 2024 19:35:37 +0800 Subject: [PATCH 1/4] chore: update dashboard zh --- packages/common-i18n/src/locales/zh/dashboard.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/common-i18n/src/locales/zh/dashboard.json b/packages/common-i18n/src/locales/zh/dashboard.json index b5a2ae51d..7ee3840b8 100644 --- a/packages/common-i18n/src/locales/zh/dashboard.json +++ b/packages/common-i18n/src/locales/zh/dashboard.json @@ -1,16 +1,16 @@ { "empty": { - "title": "暂无仪表板", - "description": "看起来您还没有创建任何仪表板。仪表板可以帮助您更有效地可视化和管理数据。", - "create": "创建您的第一个仪表板" + "title": "暂无仪表盘", + "description": "看起来您还没有创建任何仪表盘。仪表盘可以帮助您更有效地可视化和管理数据。", + "create": "创建您的第一个仪表盘" }, "addPlugin": "添加插件", "createDashboard": { - "button": "创建仪表板", - "title": "创建新仪表板", - "placeholder": "输入仪表板名称" + "button": "创建仪表盘", + "title": "创建新仪表盘", + "placeholder": "输入仪表盘名称" }, - "findDashboard": "查找仪表板...", + "findDashboard": "查找仪表盘...", "pluginUrlEmpty": "插件未设置 URL", "install": "安装", "publisher": "发布者", From 219cae6be5cbc600d305c548dd195304924bb1f4 Mon Sep 17 00:00:00 2001 From: Boris Date: Thu, 19 Sep 2024 19:39:21 +0800 Subject: [PATCH 2/4] fix: query builder --- .../src/components/base-query/QueryBuilder.tsx | 18 ++++++++++++------ .../base-query/query-from/QueryFrom.tsx | 14 ++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/sdk/src/components/base-query/QueryBuilder.tsx b/packages/sdk/src/components/base-query/QueryBuilder.tsx index de9780851..5cee36e21 100644 --- a/packages/sdk/src/components/base-query/QueryBuilder.tsx +++ b/packages/sdk/src/components/base-query/QueryBuilder.tsx @@ -73,9 +73,17 @@ const QueryBuilderContainer = forwardRef< useEffect(() => { if (query) { - setFromType(typeof query.from === 'string' ? 'table' : 'query'); + if (query.from == undefined) { + setFromType(undefined); + return; + } + setFromType( + typeof query.from === 'string' && fromType !== 'query' && query.from ? 'table' : 'query' + ); + } else { + setFromType(undefined); } - }, [query]); + }, [query, fromType]); useImperativeHandle(ref, () => ({ validateQuery: () => { @@ -277,12 +285,10 @@ const QueryBuilderContainer = forwardRef< const onFromQueryChange = (query?: IBaseQuery) => { if (!query) { - onQueryChange('from', ''); + setChildContext([]); setFromType(undefined); // if tableId is undefined, clear from - onChange({ - from: '', - }); + onChange(undefined); return; } onQueryChange('from', query ?? ''); diff --git a/packages/sdk/src/components/base-query/query-from/QueryFrom.tsx b/packages/sdk/src/components/base-query/query-from/QueryFrom.tsx index 72e0a4eda..9efd618a7 100644 --- a/packages/sdk/src/components/base-query/query-from/QueryFrom.tsx +++ b/packages/sdk/src/components/base-query/query-from/QueryFrom.tsx @@ -38,11 +38,13 @@ export const QueryFrom = (props: { {maxDepth ? ( - tables.map((table) => ( - onClick?.('table', table.id)}> - {table.name} - - )) +
+ {tables.map((table) => ( + onClick?.('table', table.id)}> + {table.name} + + ))} +
) : ( <> @@ -50,7 +52,7 @@ export const QueryFrom = (props: { {t('baseQuery.from.fromTable')} - + {tables.map((table) => ( Date: Thu, 19 Sep 2024 19:40:55 +0800 Subject: [PATCH 3/4] fix: plugin chart refetch access token --- plugins/chart/src/hooks/useBaseQueryData.ts | 32 +++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/plugins/chart/src/hooks/useBaseQueryData.ts b/plugins/chart/src/hooks/useBaseQueryData.ts index a7a55694b..24c013c26 100644 --- a/plugins/chart/src/hooks/useBaseQueryData.ts +++ b/plugins/chart/src/hooks/useBaseQueryData.ts @@ -36,14 +36,42 @@ export const useBaseQueryData = (cellFormat?: CellFormat) => { accessToken = res.accessToken; } - return fetch(`/api${url}?${params.toString()}`, { + const res = await fetch(`/api${url}?${params.toString()}`, { method: 'GET', credentials: 'omit', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}`, }, - }).then((res) => res.json() as Promise); + }); + + if (res.status < 200 || res.status > 300) { + const error: HttpError = await res.json(); + if (res.status === 401) { + await fetchGetToken({ + pluginId, + baseId, + }).then((res) => { + accessToken = res.accessToken; + return accessToken; + }); + return fetch(`/api${url}?${params.toString()}`, { + method: 'GET', + credentials: 'omit', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + }).then((res) => res.json() as Promise); + } + onQueryError?.(error.message); + return { + rows: [], + columns: [], + } as IBaseQueryVo; + } + + return res.json() as Promise; }, useErrorBoundary(error: HttpError) { if (error.code === HttpErrorCode.UNAUTHORIZED) { From ca153b0e658a37baaca873ce5a84b19ab1ecd56c Mon Sep 17 00:00:00 2001 From: Boris Date: Thu, 19 Sep 2024 19:41:35 +0800 Subject: [PATCH 4/4] feat: plugin settings add padding --- .../features/app/dashboard/TestBaseQuery.tsx | 23 ++++++ .../chart-config/common/PaddingEditor.tsx | 77 +++++++++++++++++++ .../chart/chart-config/form/ComboForm.tsx | 15 ++++ .../chart-config/form/ComboYAxisEditor.tsx | 13 +++- .../chart/chart-config/form/PieForm.tsx | 21 ++++- .../chart/chart-show/combo/Combo.tsx | 43 +++++++---- .../components/chart/chart-show/pie/Pie.tsx | 32 ++++---- plugins/chart/src/components/types.ts | 15 +++- plugins/chart/src/locales/en.json | 9 ++- plugins/chart/src/locales/zh.json | 9 ++- 10 files changed, 218 insertions(+), 39 deletions(-) create mode 100644 apps/nextjs-app/src/features/app/dashboard/TestBaseQuery.tsx create mode 100644 plugins/chart/src/components/chart/chart-config/common/PaddingEditor.tsx diff --git a/apps/nextjs-app/src/features/app/dashboard/TestBaseQuery.tsx b/apps/nextjs-app/src/features/app/dashboard/TestBaseQuery.tsx new file mode 100644 index 000000000..81660d47c --- /dev/null +++ b/apps/nextjs-app/src/features/app/dashboard/TestBaseQuery.tsx @@ -0,0 +1,23 @@ +import type { IBaseQuery } from '@teable/openapi'; +import { BaseQueryBuilder } from '@teable/sdk/components'; +import { Button, Dialog, DialogContent, DialogTrigger } from '@teable/ui-lib/shadcn'; +import { useState } from 'react'; + +export const TestBaseQuery = () => { + const [query, setQuery] = useState(); + return ( + + + + + + + + + + ); +}; diff --git a/plugins/chart/src/components/chart/chart-config/common/PaddingEditor.tsx b/plugins/chart/src/components/chart/chart-config/common/PaddingEditor.tsx new file mode 100644 index 000000000..23ea3ab96 --- /dev/null +++ b/plugins/chart/src/components/chart/chart-config/common/PaddingEditor.tsx @@ -0,0 +1,77 @@ +import { Input, Label } from '@teable/ui-lib'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import type { IChartPadding } from '../../../types'; + +export const PaddingEditor = (props: { + value?: IChartPadding; + onChange: (value?: IChartPadding) => void; +}) => { + const { value, onChange } = props; + const { t } = useTranslation(); + const [padding, setPadding] = useState(value); + return ( +
+
+ + onChange(padding)} + onChange={(e) => { + setPadding({ + ...padding, + top: e.target.value ? parseFloat(e.target.value) : undefined, + }); + }} + /> +
+
+ + onChange(padding)} + onChange={(e) => { + setPadding({ + ...padding, + right: e.target.value ? parseFloat(e.target.value) : undefined, + }); + }} + /> +
+
+ + onChange(padding)} + onChange={(e) => { + setPadding({ + ...padding, + bottom: e.target.value ? parseFloat(e.target.value) : undefined, + }); + }} + /> +
+
+ + onChange(padding)} + onChange={(e) => { + setPadding({ + ...padding, + left: e.target.value ? parseFloat(e.target.value) : undefined, + }); + }} + /> +
+
+ ); +}; diff --git a/plugins/chart/src/components/chart/chart-config/form/ComboForm.tsx b/plugins/chart/src/components/chart/chart-config/form/ComboForm.tsx index 8e4509e93..f7815d009 100644 --- a/plugins/chart/src/components/chart/chart-config/form/ComboForm.tsx +++ b/plugins/chart/src/components/chart/chart-config/form/ComboForm.tsx @@ -18,6 +18,7 @@ import { ComboXAxisDisplayEditor } from '../common/ComboXAxisDisplayEditor'; import { ComboYAxisDisplayEditor } from '../common/ComboYAisxDisplayEditor'; import { ConfigItem } from '../common/ConfigItem'; import { GoalLineEditor } from '../common/GoalLineEditor'; +import { PaddingEditor } from '../common/PaddingEditor'; import { SwitchEditor } from '../common/SwitchEditor'; import { ComboXAxisEditor } from './ComboXAxisEditor'; import { ComboYAxisEditor } from './ComboYAxisEditor'; @@ -217,6 +218,20 @@ export const ComboForm = (props: { /> + + {t('form.padding.label')} + + { + onChange({ + ...config, + padding: val, + }); + }} + /> + + onChange({ ...value, decimal })} - onChange={(e) => setDecimal(e.target.value ? Number(e.target.value) : undefined)} + onBlur={() => { + const newValue = decimal ? Math.max(0, Math.min(decimal, 10)) : undefined; + onChange({ + ...value, + decimal: newValue, + }); + setDecimal(newValue); + }} + onChange={(e) => + setDecimal(e.target.value != undefined ? parseInt(e.target.value) : undefined) + } /> diff --git a/plugins/chart/src/components/chart/chart-config/form/PieForm.tsx b/plugins/chart/src/components/chart/chart-config/form/PieForm.tsx index 15363c480..11754f789 100644 --- a/plugins/chart/src/components/chart/chart-config/form/PieForm.tsx +++ b/plugins/chart/src/components/chart/chart-config/form/PieForm.tsx @@ -7,6 +7,7 @@ import { useFilterNumberColumns } from '../../../../hooks/useFilterNumberColumns import type { IPieConfig } from '../../../types'; import { ColumnSelector } from '../common/ColumnSelector'; import { ConfigItem } from '../common/ConfigItem'; +import { PaddingEditor } from '../common/PaddingEditor'; import { SwitchEditor } from '../common/SwitchEditor'; export const PieForm = (props: { config: IPieConfig; onChange: (config: IPieConfig) => void }) => { @@ -60,16 +61,21 @@ export const PieForm = (props: { config: IPieConfig; onChange: (config: IPieConf step={1} value={decimal ?? ''} onBlur={() => { + const newValue = decimal ? Math.max(0, Math.min(decimal, 10)) : undefined; + onChange({ ...config, measure: { ...config.measure!, - decimal, + decimal: newValue, }, }); + setDecimal(newValue); }} onChange={(e) => { - setDecimal(e.target.value ? parseInt(e.target.value) : undefined); + setDecimal( + e.target.value != undefined ? parseInt(e.target.value) : undefined + ); }} /> @@ -144,6 +150,17 @@ export const PieForm = (props: { config: IPieConfig; onChange: (config: IPieConf }); }} /> + + { + onChange({ + ...config, + padding: val, + }); + }} + /> + ); }; diff --git a/plugins/chart/src/components/chart/chart-show/combo/Combo.tsx b/plugins/chart/src/components/chart/chart-show/combo/Combo.tsx index 5ef9093b3..a9d434284 100644 --- a/plugins/chart/src/components/chart/chart-show/combo/Combo.tsx +++ b/plugins/chart/src/components/chart/chart-show/combo/Combo.tsx @@ -98,6 +98,19 @@ export const ChartCombo = (props: { config: IComboConfig; defaultType?: IComboTy const showGoalLine = defaultYAxisId && config.goalLine?.enabled; const xAxisConfig = config.xAxis?.[0]; + const defaultMargin = isExpand + ? { + top: 20, + left: 12, + right: 12, + bottom: 25, + } + : { + top: 10, + left: 10, + right: 4, + bottom: 25, + }; return (
@@ -139,7 +141,12 @@ export const ChartCombo = (props: { config: IComboConfig; defaultType?: IComboTy {Object.keys(chartConfig).map((column) => { const display = yAxisMap[column]?.display; + const { prefix, decimal, suffix } = yAxisMap[column]; const type = display.type || defaultType; const lineStyle = (display as IChartBaseAxisDisplayLine).lineStyle; const yAxisId = chartYAxis.find((axis) => axis.column === column) @@ -225,6 +233,9 @@ export const ChartCombo = (props: { config: IComboConfig; defaultType?: IComboTy offset={12} className="fill-foreground" fontSize={12} + formatter={(value: number) => { + return `${prefix ?? ''}${decimal ? value.toFixed(decimal) : value}${suffix ?? ''}`; + }} /> )} diff --git a/plugins/chart/src/components/chart/chart-show/pie/Pie.tsx b/plugins/chart/src/components/chart/chart-show/pie/Pie.tsx index c965a8f2e..a961552dd 100644 --- a/plugins/chart/src/components/chart/chart-show/pie/Pie.tsx +++ b/plugins/chart/src/components/chart/chart-show/pie/Pie.tsx @@ -51,6 +51,19 @@ export const ChartPie = (props: { config: IPieConfig }) => { }; const [totalRef, { width: totalWidth }] = useRefObserve(); + const defaultMargin = isExpand + ? { + top: 20, + right: 20, + bottom: 20, + left: 20, + } + : { + top: 0, + right: 0, + bottom: 0, + left: 0, + }; return (
{/* calculate total width */} @@ -71,21 +84,10 @@ export const ChartPie = (props: { config: IPieConfig }) => { ; + export type IGoalLine = z.infer; export const comboConfigSchema = z.object({ @@ -64,7 +73,7 @@ export const comboConfigSchema = z.object({ .extend({ prefix: z.string().optional(), suffix: z.string().optional(), - decimal: z.number().optional(), + decimal: z.number().max(10).min(0).optional(), }) .extend({ display: chartBaseAxisDisplaySchema }) ) @@ -72,6 +81,7 @@ export const comboConfigSchema = z.object({ yAxisDisplay: chartYAxisDisplaySchema.optional(), goalLine: goalLineSchema.optional(), showLabel: z.boolean().optional(), + padding: chartPaddingSchema.optional(), }); export type IComboConfig = z.infer; @@ -106,7 +116,7 @@ export const pieConfigSchema = z.object({ measure: z .object({ column: z.string(), - decimal: z.number().optional(), + decimal: z.number().max(10).min(0).optional(), prefix: z.string().optional(), suffix: z.string().optional(), }) @@ -114,6 +124,7 @@ export const pieConfigSchema = z.object({ showLabel: z.boolean().optional(), showTotal: z.boolean().optional(), showLegend: z.boolean().optional(), + padding: chartPaddingSchema.optional(), }); export type IPieConfig = z.infer; diff --git a/plugins/chart/src/locales/en.json b/plugins/chart/src/locales/en.json index b4a382abc..627c87331 100644 --- a/plugins/chart/src/locales/en.json +++ b/plugins/chart/src/locales/en.json @@ -77,7 +77,14 @@ "showLabel": "Show values label on chart", "showLegend": "Show legend", "value": "Value", - "label": "Label" + "label": "Label", + "padding": { + "label": "Padding", + "top": "Top", + "right": "Right", + "bottom": "Bottom", + "left": "Left" + } }, "reloadQuery": "Reload Query", "noStorage": "Please configure the chart plugin first", diff --git a/plugins/chart/src/locales/zh.json b/plugins/chart/src/locales/zh.json index e7873970c..f87e01b2f 100644 --- a/plugins/chart/src/locales/zh.json +++ b/plugins/chart/src/locales/zh.json @@ -77,7 +77,14 @@ "showLabel": "在图表上显示数值标签", "showLegend": "显示图例", "value": "数值", - "label": "标签" + "label": "标签", + "padding": { + "label": "内边距", + "top": "上", + "right": "右", + "bottom": "下", + "left": "左" + } }, "reloadQuery": "重新加载查询", "noStorage": "请先配置图表插件",