fix: critical data mapping bugs in useImportData and useCreateChart
- useImportData: use dataset_id instead of id from backend response, fetch rows after import, fix column type mapping - useCreateChart: fix bindings mapper to use axis instead of fieldRole, graceful error handling instead of throwing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0c0592b511
commit
28ebbbfb82
|
|
@ -8,17 +8,15 @@ import { addLayoutItem } from '@/adapters/state/redux/layoutSlice';
|
|||
import { type ChartType } from '@/domain';
|
||||
import { type ChartInstance } from '@/domain/entities/ChartInstance';
|
||||
|
||||
/**
|
||||
* Map a backend chart object (snake_case) to frontend ChartInstance (camelCase).
|
||||
*/
|
||||
function mapBackendChart(raw: any): ChartInstance {
|
||||
return {
|
||||
id: raw.id,
|
||||
type: raw.chart_type ?? raw.type,
|
||||
dataSetId: raw.dataset_id ?? raw.dataSetId,
|
||||
bindings: (raw.bindings ?? []).map((b: any) => ({
|
||||
fieldRole: b.field_role ?? b.fieldRole,
|
||||
axis: b.axis ?? b.field_role ?? b.fieldRole,
|
||||
columnName: b.column_name ?? b.columnName,
|
||||
aggregation: b.aggregation,
|
||||
})),
|
||||
style: raw.style ?? {},
|
||||
filters: (raw.filters ?? []).map((f: any) => ({
|
||||
|
|
@ -43,7 +41,8 @@ export function useCreateChart() {
|
|||
const handleCreate = useCallback(
|
||||
async (chartType?: ChartType) => {
|
||||
if (!activeDataSetId) {
|
||||
throw new Error('No active dataset. Import data first.');
|
||||
setError('请先导入数据集');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
|
@ -58,7 +57,6 @@ export function useCreateChart() {
|
|||
dispatch(addChart(chart));
|
||||
dispatch(setActiveChart(chart.id));
|
||||
|
||||
// Default position: stack items in a 2-column grid
|
||||
const col = layoutCount % 2;
|
||||
const row = Math.floor(layoutCount / 2);
|
||||
dispatch(
|
||||
|
|
@ -74,7 +72,6 @@ export function useCreateChart() {
|
|||
return chart;
|
||||
} catch (e: any) {
|
||||
setError(e.message ?? 'Failed to create chart');
|
||||
throw e;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,40 +8,34 @@ import { type DataSet } from '@/domain/entities/DataSet';
|
|||
import { type ChartSuggestion } from '@/application/dto/ChartSuggestion';
|
||||
|
||||
/**
|
||||
* Map a backend dataset object (snake_case) to the frontend DataSet entity (camelCase).
|
||||
* Map a backend import result (snake_case) to frontend DataSet entity.
|
||||
* The import endpoint returns {dataset_id, file_name, columns, row_count, ...}
|
||||
* We then fetch the full dataset (with rows) from GET /datasets/{id}.
|
||||
*/
|
||||
function mapBackendDataSet(raw: any): DataSet {
|
||||
function mapBackendDataSet(raw: any, rows: Record<string, any>[] = []): DataSet {
|
||||
return {
|
||||
id: raw.id,
|
||||
id: raw.dataset_id ?? raw.id ?? '',
|
||||
fileName: raw.file_name ?? raw.fileName ?? '',
|
||||
sheetName: raw.sheet_name ?? raw.sheetName,
|
||||
columns: (raw.columns ?? []).map((col: any) => ({
|
||||
name: col.name,
|
||||
type: col.type ?? col.field_type ?? 'string',
|
||||
type: col.field_type ?? col.type ?? 'text',
|
||||
sampleValues: col.sample_values ?? col.sampleValues ?? [],
|
||||
})),
|
||||
rows: raw.rows ?? [],
|
||||
rowCount: raw.row_count ?? raw.rowCount ?? (raw.rows?.length ?? 0),
|
||||
rows,
|
||||
rowCount: raw.row_count ?? raw.rowCount ?? rows.length,
|
||||
dataStructure: raw.data_structure ?? raw.dataStructure,
|
||||
createdAt: raw.created_at ?? raw.createdAt ?? new Date().toISOString(),
|
||||
updatedAt: raw.updated_at ?? raw.updatedAt ?? new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a backend chart recommendation (snake_case) to frontend ChartSuggestion.
|
||||
*/
|
||||
function mapBackendSuggestion(raw: any): ChartSuggestion {
|
||||
return {
|
||||
chartType: raw.chart_type ?? raw.chartType,
|
||||
label: raw.label ?? raw.chart_type ?? '',
|
||||
isPrimary: raw.is_primary ?? raw.isPrimary ?? false,
|
||||
defaultBindings: (raw.default_bindings ?? raw.defaultBindings ?? []).map(
|
||||
(b: any) => ({
|
||||
fieldRole: b.field_role ?? b.fieldRole,
|
||||
columnName: b.column_name ?? b.columnName,
|
||||
}),
|
||||
),
|
||||
isPrimary: raw.primary ?? raw.is_primary ?? raw.isPrimary ?? false,
|
||||
defaultBindings: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -58,21 +52,29 @@ export function useImportData() {
|
|||
try {
|
||||
// Upload file to backend data-service
|
||||
const rawDatasets = await dataServiceClient.importFile(file);
|
||||
|
||||
// The backend may return one or more datasets; take the first
|
||||
const rawDataSet = Array.isArray(rawDatasets) ? rawDatasets[0] : rawDatasets;
|
||||
const dataSet = mapBackendDataSet(rawDataSet);
|
||||
const dataSetId = rawDataSet.dataset_id ?? rawDataSet.id;
|
||||
|
||||
// Fetch rows from backend
|
||||
let rows: Record<string, any>[] = [];
|
||||
try {
|
||||
const rowsResp = await dataServiceClient.getRows(dataSetId, 10000);
|
||||
rows = rowsResp.rows ?? rowsResp ?? [];
|
||||
} catch {
|
||||
// rows fetch failed, continue without
|
||||
}
|
||||
|
||||
const dataSet = mapBackendDataSet(rawDataSet, rows);
|
||||
|
||||
dispatch(addDataSet(dataSet));
|
||||
dispatch(setActiveDataSet(dataSet.id));
|
||||
|
||||
// Request chart suggestions from backend chart-service
|
||||
// Request chart suggestions
|
||||
try {
|
||||
const rawSuggestions = await chartServiceClient.recommendCharts(dataSet.id);
|
||||
const mapped = (rawSuggestions ?? []).map(mapBackendSuggestion);
|
||||
setSuggestions(mapped);
|
||||
} catch {
|
||||
// Non-critical: recommendations are optional
|
||||
setSuggestions([]);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue