- Explicitly set maskImage=undefined for rectangle mode
- Force re-mount EChartsBase on wordcloud shape change via React key
- Prevents stale mask from previous shape persisting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Select '自定义图片' from shape dropdown
- Upload any silhouette image (black=words, white=empty)
- Image preview with delete button
- maskImage passed to echarts-wordcloud with keepAspect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dynamic import was async and wordcloud plugin wasn't loaded before
setOption was called. Now uses synchronous require() guarded by
typeof window check to avoid SSR crash.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
echarts-wordcloud accesses window at import time, causing 500 error
during server-side rendering. Moved to dynamic import() inside
useEffect which only runs on the client.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- shrinkToFit: true — auto-shrink words that don't fit
- width/height: 95% — use nearly full container
- keepAspect: false — let shape stretch to fill container
- Combined with ellipse mask radii, all words should now display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Changed from square min(w,h) radius to separate rx/ry that use
the full width and height of the container. Shapes now fill the
entire chart area instead of being constrained to a small square.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previous 512x512 square mask was too small, causing most words to
be excluded. Now uses 1024x700 (16:11 ratio) to match typical chart
containers, with r=48% fill for maximum word area.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shape presets (circle/heart/diamond/triangle/star/pentagon) now
render correctly using dynamically generated canvas mask images.
Added rectangle option. Mask images are cached for performance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same bug as chartSlice - the builder's ensureStyle was stripping
custom properties like wordcloud. Now preserves all non-standard keys.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Without this import, the wordCloud series type is not registered
with echarts, causing wordcloud charts to render blank.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ensureStyle() was stripping unknown properties like 'wordcloud'.
Now collects and preserves all non-standard style keys so chart-type
specific configs survive Redux state updates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- WordcloudOptionBuilder: shape, font size range, rotation range,
grid size, font family/weight, 3 color modes (palette/random/gradient)
- WordcloudConfig panel: full UI for all wordcloud settings
- StyleConfig: conditionally shows wordcloud/axis/legend panels
based on chart type (wordcloud hides axes, KPI hides legend, etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Percent label format: calculate actual % from total instead of {d}
- Value labels: use toLocaleString for thousand separators
- Background opacity: convert hex+opacity to rgba
- Border radius: apply to ECharts container div
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Typing axis title text auto-sets titleVisible=true
- Added switches for: show axis, show axis title, show grid lines
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legend moves below title when both are at top. Grid top adjusts
dynamically based on title/legend presence to prevent overlap.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each bar gets a different color from the palette, making color
palette changes immediately visible for all chart configurations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Typing title text now auto-sets visible=true so the title appears
immediately. Also added a Switch to toggle title visibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use JSON.stringify as useMemo key to detect deep changes in chart
config. Also removed redundant ensureStyle (now handled in Redux).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All style sub-objects (title, legend, xAxis, yAxis, dataLabel,
background, border, animation) are guaranteed to exist in Redux.
This fixes:
- Style config panels showing blank (returned null for missing fields)
- Style changes not applying (updateStyle now deep-merges sub-objects)
- Color palette changes not persisting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ensureStyle: handle empty colors array (use defaults)
- barOptionBuilder: set option.color = style.colors globally
so ECharts auto-assigns palette colors to all series
- Changing palette in style panel now updates chart colors immediately
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a field is dragged to the 'label' slot, data labels are
automatically shown on top of each bar with the value.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dragging a field to the 'color' slot now creates separate colored bars
per category value, with auto-generated legend. Also aggregates
multiple rows per category (sum) instead of taking first match only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Metric name (column name) as title
- Large formatted number with 万/亿 abbreviation
- Auto-detect 同比/环比 columns, show as colored trend badges
- Group label showing dimension info
- SVG sparkline for trend visualization
- Clean layout matching Tableau/Power BI KPI card patterns
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: backend returns minimal style object without title/legend/axis
sub-objects, causing TypeError 'Cannot read properties of undefined'.
Fix: normalize style with full defaults at the builder entry point,
protecting ALL chart type builders uniformly.
Also fix antd deprecation warnings (destroyOnClose -> destroyOnHidden).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- DropZone: log actual error message instead of generic text
- KPICard: aggregate all rows, auto-detect 同比/环比 columns,
show proper formatting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All 17 chart types now show Chinese names (柱状图, 折线图, 饼图, etc.)
and use specific Ant Design icons instead of generic BarChartOutlined.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When creating a chart, automatically assign first text column to X axis
and first number column to Y axis (varies by chart type).
Charts now show data immediately instead of blank.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All 4 API clients now consistently use /api/v1/ prefix on all routes
- ChartRenderer fills missing style fields with defaults to prevent
undefined property crashes when backend returns minimal style
- KPICard uses safe defaults for background/border/title
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
react-grid-layout v2 removed WidthProvider. Use ResizeObserver to
track container width and pass it directly to Responsive component.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
Clicking a chart type card now calls useCreateChart to create
a chart instance on the backend and add it to the canvas.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
WidthProvider is not available during SSR. Use dynamic import
inside useEffect to load it only on the client side.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously excluded due to nested .git from create-next-app.
Includes all Clean Architecture layers, API client integration,
and full UI component suite.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>