@@ -5,33 +5,17 @@ import {
55 CompActionTypes ,
66 wrapChildAction ,
77} from "openblocks-core" ;
8- import {
9- AxisFormatterComp ,
10- calcXYConfig ,
11- EchartsAxisType ,
12- } from "./chartConfigs/cartesianAxisConfig" ;
13- import { getPieRadiusAndCenter } from "./chartConfigs/pieChartConfig" ;
14- import {
15- CharOptionCompType ,
16- chartChildrenMap ,
17- ChartCompPropsType ,
18- ChartSize ,
19- getDataKeys ,
20- noDataAxisConfig ,
21- noDataPieChartConfig ,
22- } from "./chartConstants" ;
8+ import { AxisFormatterComp , EchartsAxisType } from "./chartConfigs/cartesianAxisConfig" ;
9+ import { chartChildrenMap , ChartSize , getDataKeys } from "./chartConstants" ;
2310import { chartPropertyView } from "./chartPropertyView" ;
24- import { EChartsOption } from "echarts" ;
2511import _ from "lodash" ;
2612import { useEffect , useMemo , useRef , useState } from "react" ;
2713import ReactResizeDetector from "react-resize-detector" ;
2814import ReactECharts from "./reactEcharts" ;
2915import {
30- chartColorPalette ,
3116 childrenToProps ,
3217 depsConfig ,
3318 genRandomKey ,
34- isNumeric ,
3519 JSONObject ,
3620 JSONValue ,
3721 NameConfig ,
@@ -42,230 +26,12 @@ import {
4226 withViewFn ,
4327} from "openblocks-sdk" ;
4428import { getEchartsLocale , trans } from "i18n/comps" ;
45-
46- function transformData ( originData : JSONObject [ ] , xAxis : string , seriesColumnNames : string [ ] ) {
47- // aggregate data by x-axis
48- const transformedData : JSONObject [ ] = [ ] ;
49- originData . reduce ( ( prev , cur ) => {
50- if ( cur === null || cur === undefined ) {
51- return prev ;
52- }
53- const groupValue = cur [ xAxis ] as string ;
54- if ( ! prev [ groupValue ] ) {
55- // init as 0
56- const initValue : any = { } ;
57- seriesColumnNames . forEach ( ( name ) => {
58- initValue [ name ] = 0 ;
59- } ) ;
60- prev [ groupValue ] = initValue ;
61- transformedData . push ( prev [ groupValue ] ) ;
62- }
63- // remain the x-axis data
64- prev [ groupValue ] [ xAxis ] = groupValue ;
65- seriesColumnNames . forEach ( ( key ) => {
66- if ( key === xAxis ) {
67- return ;
68- } else if ( isNumeric ( cur [ key ] ) ) {
69- prev [ groupValue ] [ key ] += Number ( cur [ key ] ) ;
70- } else {
71- prev [ groupValue ] [ key ] += 1 ;
72- }
73- } ) ;
74- return prev ;
75- } , { } as any ) ;
76- return transformedData ;
77- }
78-
79- const notAxisChartSet : Set < CharOptionCompType > = new Set ( [ "pie" ] as const ) ;
80- const echartsConfigOmitChildren = [ "hidden" , "selectedPoints" , "onEvent" ] as const ;
81- type EchartsConfigProps = Omit < ChartCompPropsType , typeof echartsConfigOmitChildren [ number ] > ;
82-
83- function isAxisChart ( type : CharOptionCompType ) {
84- return ! notAxisChartSet . has ( type ) ;
85- }
86-
87- function getSeriesConfig ( props : EchartsConfigProps ) {
88- const visibleSeries = props . series . filter ( ( s ) => ! s . getView ( ) . hide ) ;
89- const seriesLength = visibleSeries . length ;
90- return visibleSeries . map ( ( s , index ) => {
91- if ( isAxisChart ( props . chartConfig . type ) ) {
92- let encodeX : string , encodeY : string ;
93- const horizontalX = props . xAxisDirection === "horizontal" ;
94- let itemStyle = props . chartConfig . itemStyle ;
95- // FIXME: need refactor... chartConfig returns a function with paramters
96- if ( props . chartConfig . type === "bar" ) {
97- // barChart's border radius, depend on x-axis direction and stack state
98- const borderRadius = horizontalX ? [ 2 , 2 , 0 , 0 ] : [ 0 , 2 , 2 , 0 ] ;
99- if ( props . chartConfig . stack && index === visibleSeries . length - 1 ) {
100- itemStyle = { ...itemStyle , borderRadius : borderRadius } ;
101- } else if ( ! props . chartConfig . stack ) {
102- itemStyle = { ...itemStyle , borderRadius : borderRadius } ;
103- }
104- }
105- if ( horizontalX ) {
106- encodeX = props . xAxisKey ;
107- encodeY = s . getView ( ) . columnName ;
108- } else {
109- encodeX = s . getView ( ) . columnName ;
110- encodeY = props . xAxisKey ;
111- }
112- return {
113- name : s . getView ( ) . seriesName ,
114- selectedMode : "single" ,
115- select : {
116- itemStyle : {
117- borderColor : "#000" ,
118- } ,
119- } ,
120- encode : {
121- x : encodeX ,
122- y : encodeY ,
123- } ,
124- // each type of chart's config
125- ...props . chartConfig ,
126- itemStyle : itemStyle ,
127- label : {
128- ...props . chartConfig . label ,
129- ...( ! horizontalX && { position : "outside" } ) ,
130- } ,
131- } ;
132- } else {
133- // pie
134- const radiusAndCenter = getPieRadiusAndCenter ( seriesLength , index , props . chartConfig ) ;
135- return {
136- ...props . chartConfig ,
137- radius : radiusAndCenter . radius ,
138- center : radiusAndCenter . center ,
139- name : s . getView ( ) . seriesName ,
140- selectedMode : "single" ,
141- encode : {
142- itemName : props . xAxisKey ,
143- value : s . getView ( ) . columnName ,
144- } ,
145- } ;
146- }
147- } ) ;
148- }
149-
150- // https://echarts.apache.org/en/option.html
151- function getEchartsConfig ( props : EchartsConfigProps , chartSize ?: ChartSize ) : EChartsOption {
152- if ( props . mode === "json" ) {
153- return props . echartsOption ? props . echartsOption : { } ;
154- }
155- // axisChart
156- const axisChart = isAxisChart ( props . chartConfig . type ) ;
157- const gridPos = {
158- left : 20 ,
159- right : props . legendConfig . left === "right" ? "10%" : 20 ,
160- top : 50 ,
161- bottom : 35 ,
162- } ;
163- let config : EChartsOption = {
164- color : chartColorPalette ,
165- title : { text : props . title , left : "center" } ,
166- backgroundColor : "#fff" ,
167- tooltip : {
168- confine : true ,
169- trigger : axisChart ? "axis" : "item" ,
170- } ,
171- legend : props . legendConfig ,
172- grid : {
173- ...gridPos ,
174- containLabel : true ,
175- } ,
176- } ;
177- if ( props . data . length <= 0 ) {
178- // no data
179- return {
180- ...config ,
181- ...( axisChart ? noDataAxisConfig : noDataPieChartConfig ) ,
182- } ;
183- }
184- const yAxisConfig = props . yConfig ( ) ;
185- const seriesColumnNames = props . series
186- . filter ( ( s ) => ! s . getView ( ) . hide )
187- . map ( ( s ) => s . getView ( ) . columnName ) ;
188- // y-axis is category and time, data doesn't need to aggregate
189- const transformedData =
190- yAxisConfig . type === "category" || yAxisConfig . type === "time"
191- ? props . data
192- : transformData ( props . data , props . xAxisKey , seriesColumnNames ) ;
193- config = {
194- ...config ,
195- dataset : [
196- {
197- source : transformedData ,
198- sourceHeader : false ,
199- } ,
200- ] ,
201- series : getSeriesConfig ( props ) ,
202- } ;
203- if ( axisChart ) {
204- // pure chart's size except the margin around
205- let chartRealSize ;
206- if ( chartSize ) {
207- const rightSize =
208- typeof gridPos . right === "number"
209- ? gridPos . right
210- : ( chartSize . w * parseFloat ( gridPos . right ) ) / 100.0 ;
211- chartRealSize = {
212- // actually it's self-adaptive with the x-axis label on the left, not that accurate but work
213- w : chartSize . w - gridPos . left - rightSize ,
214- // also self-adaptive on the bottom
215- h : chartSize . h - gridPos . top - gridPos . bottom ,
216- right : rightSize ,
217- } ;
218- }
219- const finalXyConfig = calcXYConfig (
220- props . xConfig ,
221- yAxisConfig ,
222- props . xAxisDirection ,
223- transformedData . map ( ( d ) => d [ props . xAxisKey ] ) ,
224- chartRealSize
225- ) ;
226- config = {
227- ...config ,
228- // @ts -ignore
229- xAxis : finalXyConfig . xConfig ,
230- // @ts -ignore
231- yAxis : finalXyConfig . yConfig ,
232- } ;
233- }
234- // log.log("Echarts transformedData and config", transformedData, config);
235- return config ;
236- }
237-
238- function getSelectedPoints ( param : any , option : any ) {
239- const series = option . series ;
240- const dataSource = _ . isArray ( option . dataset ) && option . dataset [ 0 ] ?. source ;
241- if ( series && dataSource ) {
242- return param . selected . flatMap ( ( selectInfo : any ) => {
243- const seriesInfo = series [ selectInfo . seriesIndex ] ;
244- if ( ! seriesInfo || ! seriesInfo . encode ) {
245- return [ ] ;
246- }
247- return selectInfo . dataIndex . map ( ( index : any ) => {
248- const commonResult = {
249- seriesName : seriesInfo . name ,
250- } ;
251- if ( seriesInfo . encode . itemName && seriesInfo . encode . value ) {
252- return {
253- ...commonResult ,
254- itemName : dataSource [ index ] [ seriesInfo . encode . itemName ] ,
255- value : dataSource [ index ] [ seriesInfo . encode . value ] ,
256- } ;
257- } else {
258- return {
259- ...commonResult ,
260- x : dataSource [ index ] [ seriesInfo . encode . x ] ,
261- y : dataSource [ index ] [ seriesInfo . encode . y ] ,
262- } ;
263- }
264- } ) ;
265- } ) ;
266- }
267- return [ ] ;
268- }
29+ import { ItemColorComp } from "comps/chartComp/chartConfigs/lineChartConfig" ;
30+ import {
31+ echartsConfigOmitChildren ,
32+ getEchartsConfig ,
33+ getSelectedPoints ,
34+ } from "comps/chartComp/chartUtils" ;
26935
27036let ChartTmpComp = ( function ( ) {
27137 return new UICompBuilder ( chartChildrenMap , ( ) => null )
@@ -353,6 +119,52 @@ function getYAxisFormatContextValue(
353119
354120ChartTmpComp = class extends ChartTmpComp {
355121 private lastYAxisFormatContextVal ?: JSONValue ;
122+ private lastColorContext ?: JSONObject ;
123+
124+ updateContext ( comp : this) {
125+ // the context value of axis format
126+ let resultComp = comp ;
127+ const data = comp . children . data . getView ( ) ;
128+ const sampleSeries = comp . children . series . getView ( ) . find ( ( s ) => ! s . getView ( ) . hide ) ;
129+ const yAxisContextValue = getYAxisFormatContextValue (
130+ data ,
131+ comp . children . yConfig . children . yAxisType . getView ( ) ,
132+ sampleSeries ?. children . columnName . getView ( )
133+ ) ;
134+ if ( yAxisContextValue !== comp . lastYAxisFormatContextVal ) {
135+ comp . lastYAxisFormatContextVal = yAxisContextValue ;
136+ resultComp = comp . setChild (
137+ "yConfig" ,
138+ comp . children . yConfig . reduce (
139+ wrapChildAction (
140+ "formatter" ,
141+ AxisFormatterComp . changeContextDataAction ( { value : yAxisContextValue } )
142+ )
143+ )
144+ ) ;
145+ }
146+ // item color context
147+ const colorContextVal = {
148+ seriesName : sampleSeries ?. children . seriesName . getView ( ) ,
149+ value : yAxisContextValue ,
150+ } ;
151+ if (
152+ comp . children . chartConfig . children . comp . children . hasOwnProperty ( "itemColor" ) &&
153+ ! _ . isEqual ( colorContextVal , comp . lastColorContext )
154+ ) {
155+ comp . lastColorContext = colorContextVal ;
156+ resultComp = resultComp . setChild (
157+ "chartConfig" ,
158+ comp . children . chartConfig . reduce (
159+ wrapChildAction (
160+ "comp" ,
161+ wrapChildAction ( "itemColor" , ItemColorComp . changeContextDataAction ( colorContextVal ) )
162+ )
163+ )
164+ ) ;
165+ }
166+ return resultComp ;
167+ }
356168
357169 override reduce ( action : CompAction ) : this {
358170 const comp = super . reduce ( action ) ;
@@ -370,25 +182,7 @@ ChartTmpComp = class extends ChartTmpComp {
370182 comp . children . series . dispatchDataChanged ( newData ) ;
371183 } , 0 ) ;
372184 }
373- // the context value of axis format
374- const sampleSeries = comp . children . series . getView ( ) . find ( ( s ) => ! s . getView ( ) . hide ) ;
375- const contextValue = getYAxisFormatContextValue (
376- newData ,
377- comp . children . yConfig . children . yAxisType . getView ( ) ,
378- sampleSeries ?. children . columnName . getView ( )
379- ) ;
380- if ( contextValue !== comp . lastYAxisFormatContextVal ) {
381- comp . lastYAxisFormatContextVal = contextValue ;
382- return comp . setChild (
383- "yConfig" ,
384- comp . children . yConfig . reduce (
385- wrapChildAction (
386- "formatter" ,
387- AxisFormatterComp . changeContextDataAction ( { value : contextValue } )
388- )
389- )
390- ) ;
391- }
185+ return this . updateContext ( comp ) ;
392186 }
393187 return comp ;
394188 }
0 commit comments