diff --git a/lib/biz/spreadsheet/charts.v b/lib/biz/spreadsheet/charts.v new file mode 100644 index 00000000..14e933d6 --- /dev/null +++ b/lib/biz/spreadsheet/charts.v @@ -0,0 +1,138 @@ +module spreadsheet + +import freeflowuniverse.herolib.data.markdownparser.elements +import freeflowuniverse.herolib.ui.console +import freeflowuniverse.herolib.web.echarts + +pub fn (s Sheet) title_chart(args RowGetArgs) echarts.EChartsOption { + return echarts.EChartsOption{ + title: echarts.Title{ + text: args.title + subtext: args.title_sub + left: 'center' + } + } +} + +pub fn (s Sheet) line_chart(args_ RowGetArgs) !echarts.EChartsOption { + mut args := args_ + + rownames := s.rownames_get(args)! + header := s.header_get_as_string(args.period_type)! + mut series := []echarts.Series{} + + for rowname in rownames { + data := s.data_get_as_string(RowGetArgs{ + ...args + rowname: rowname + })! + series << echarts.Series{ + name: rowname + type_: 'line' + stack: 'Total' + data: data.split(',') + } + } + + return echarts.EChartsOption{ + title: s.title_chart(args).title + tooltip: echarts.Tooltip{ + trigger: 'axis' + } + legend: echarts.Legend{ + data: rownames + } + grid: echarts.Grid{ + left: '3%' + right: '4%' + bottom: '3%' + contain_label: true + } + toolbox: echarts.Toolbox{ + feature: echarts.ToolboxFeature{ + save_as_image: {} + } + } + x_axis: echarts.XAxis{ + type_: 'category' + boundary_gap: false + data: header.split(',') + } + y_axis: echarts.YAxis{ + type_: 'value' + } + series: series + } +} + +pub fn (s Sheet) bar_chart(args_ RowGetArgs) !echarts.EChartsOption { + mut args := args_ + args.rowname = s.rowname_get(args)! + header := s.header_get_as_list(args.period_type)! + data := s.data_get_as_list(args)! + + return echarts.EChartsOption{ + title: s.title_chart(args).title + x_axis: echarts.XAxis{ + type_: 'category' + data: header + } + y_axis: echarts.YAxis{ + type_: 'value' + } + series: [ + echarts.Series{ + name: args.rowname + type_: 'bar' + data: data + stack: '' + }, + ] + } +} + +pub fn (s Sheet) pie_chart(args_ RowGetArgs) !echarts.EChartsOption { + mut args := args_ + args.rowname = s.rowname_get(args)! + header := s.header_get_as_list(args.period_type)! + data := s.data_get_as_list(args)! + + if header.len != data.len { + return error('Data and header lengths must match.') + } + + mut pie_data := []map[string]string{} + for i, _ in data { + pie_data << { + 'value': data[i].trim_space().trim("'") + 'name': header[i].trim_space().trim("'") + } + } + + return echarts.EChartsOption{ + title: s.title_chart(args).title + tooltip: echarts.Tooltip{ + trigger: 'item' + } + legend: echarts.Legend{ + data: header + orient: 'vertical' + left: 'left' + } + series: [ + echarts.Series{ + name: 'Data' + type_: 'pie' + radius: args.size.int() + data: pie_data.map(it.str()) + emphasis: echarts.Emphasis{ + item_style: echarts.ItemStyle{ + shadow_blur: 10 + shadow_offset_x: 0 + shadow_color: 'rgba(0, 0, 0, 0.5)' + } + } + }, + ] + } +} diff --git a/lib/biz/spreadsheet/charts_test.v b/lib/biz/spreadsheet/charts_test.v new file mode 100644 index 00000000..acb8be64 --- /dev/null +++ b/lib/biz/spreadsheet/charts_test.v @@ -0,0 +1,77 @@ +module spreadsheet + +import freeflowuniverse.herolib.data.markdownparser.elements +import freeflowuniverse.herolib.ui.console +import freeflowuniverse.herolib.web.echarts + +fn test_title_chart() { + mut s := sheet_new() or { panic(err) } + mut nrnodes := s.row_new( + name: 'nrnodes' + growth: '5:100,55:1000' + tags: 'cat:nodes color:yellow urgent' + )! + args := RowGetArgs{ + rowname: 'nrnodes' + title: 'Main Title' + title_sub: 'Subtitle' + } + title := s.title_chart(args).title + assert title.text == 'Main Title' + assert title.subtext == 'Subtitle' + assert title.left == 'center' +} + +fn test_line_chart() { + mut s := sheet_new() or { panic(err) } + mut nrnodes := s.row_new( + name: 'nrnodes' + growth: '5:100,55:1000' + tags: 'cat:nodes color:yellow urgent' + )! + args := RowGetArgs{ + rowname: 'nrnodes' + title: 'Line Chart' + period_type: .month + } + option := s.line_chart(args) or { panic(err) } + assert option.title.text == 'Line Chart' + assert option.tooltip.trigger == 'axis' + assert option.grid.contain_label == true +} + +fn test_bar_chart() { + mut s := sheet_new() or { panic(err) } + mut nrnodes := s.row_new( + name: 'nrnodes' + growth: '5:100,55:1000' + tags: 'cat:nodes color:yellow urgent' + )! + args := RowGetArgs{ + rowname: 'nrnodes' + title: 'Bar Chart' + period_type: .year + } + option := s.bar_chart(args) or { panic(err) } + assert option.title.text == 'Bar Chart' + assert option.x_axis.type_ == 'category' + assert option.y_axis.type_ == 'value' +} + +fn test_pie_chart() { + mut s := sheet_new() or { panic(err) } + mut nrnodes := s.row_new( + name: 'nrnodes' + growth: '5:100,55:1000' + tags: 'cat:nodes color:yellow urgent' + )! + args := RowGetArgs{ + rowname: 'nrnodes' + title: 'Pie Chart' + period_type: .quarter + } + option := s.pie_chart(args) or { panic(err) } + assert option.title.text == 'Pie Chart' + assert option.tooltip.trigger == 'item' + assert option.legend.data.len > 0 +}