Skip to content

Commit

Permalink
(feat) allow x axis to be string on line
Browse files Browse the repository at this point in the history
  • Loading branch information
kevincobain2000 committed Dec 26, 2023
1 parent 920d3fc commit 5893b32
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 41 deletions.
72 changes: 56 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

- [API](#api)
- [`GET /line`](#get-line)
- [Line Chart Simple](#line-chart-simple)
- [Single Line Series](#single-line-series)
- [Multiple Line Series](#multiple-line-series)
- [Continuous Series](#continuous-series)
Expand All @@ -46,16 +47,17 @@

## [`GET /line`](https://instachart.coveritup.app/line?title=Single+Line+series&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22]],%20%22y%22:%20[[1,2,3]]%20})

| Query | Required | Description | Example |
| :-------- | :------- | :---------- | :--------------------------------------------------------- |
| `data` || JSON | `?data={ "x": [["2022-12-23","2023-12-25"]],"y": [[1,2]]}` |
| `title` | | string | |
| `fill` | | boolean | |
| `x_label` | | string | |
| `y_label` | | string | |
| `height` | | int | |
| `width` | | int | |
| `color` | | string | `blue`,`red`,`green`,`yellow`,`cyan`,`orange` |
| Query | Required | Description | Example |
| :--------- | :------- | :---------- | :--------------------------------------------------------- |
| `data` || JSON | `?data={ "x": [["2022-12-23","2023-12-25"]],"y": [[1,2]]}` |
| `title` | | string | |
| `fill` | | boolean | |
| `x_label` | | string | |
| `y_label` | | string | |
| `subtitle` | | string | |
| `height` | | int | |
| `width` | | int | |
| `color` | | string | `blue`,`red`,`green`,`yellow`,`cyan`,`orange` |


| `data` | Required | Description | Example |
Expand All @@ -64,6 +66,44 @@
| `y` || []Array (int) | `"y": [[1,2],[3,4]]` |
| `names` | | Array | `"names": ["Series A", "Series B"]` |


### Line Chart Simple

<details>
<summary><b>REQUEST URL</b></summary>

```sh
https://instachart.coveritup.app/line?title=Line+Chart+Simple&subtitle=Sleeping+Hours&data={
"x": [["Mon","Tue","Wed"]],
"y": [[4,8,7], [10,20,24]],
"names": ["Sleeping", "Awake"]
}
```

</details>

<br>

![Line chart area](https://instachart.coveritup.app/line?title=Line+Chart&subtitle=Sleeping+Hours&fill=truedata={%20"x":%20[["Mon","Tue","Wed"]],%20"y":%20[[4,8,7],%20[10,20,24]],%20"names":%20["Sleeping",%20"Awake"]%20})

<details>
<summary><b>REQUEST URL</b></summary>

```sh
https://instachart.coveritup.app/line?title=Line+Chart+Simple&subtitle=Sleeping+Hours&fill=true&data={
"x": [["Mon","Tue","Wed"]],
"y": [[4,8,7], [10,20,24]],
"names": ["Sleeping", "Awake"]
}
```

</details>

<br>


![Continuous area series](https://instachart.coveritup.app/line?title=Line+Chart+Area&subtitle=Sleeping+Hours&fill=truedata={%20"x":%20[["Mon","Tue","Wed"]],%20"y":%20[[4,8,7],%20[10,20,24]],%20"names":%20["Sleeping",%20"Awake"]%20})

### Single Line Series

<details>
Expand All @@ -79,7 +119,7 @@ https://instachart.coveritup.app/line?title=Single+Line+Series&x_label=dates&y_l

<br>

![Line single](https://instachart.coveritup.app/line?title=Single+Line&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22]],%20%22y%22:%20[[1,2,3]],%20%22names%22:%20[%22Series%20A%22]%20})
![Line single](https://instachart.coveritup.app/line?title=Single+Line+Series&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22]],%20%22y%22:%20[[1,2,3]],%20%22names%22:%20[%22Series%20A%22]%20})

<details>
<summary><b>REQUEST URL</b></summary>
Expand All @@ -94,7 +134,7 @@ https://instachart.coveritup.app/line?title=Single+Line+Series&fill=true&x_label

<br>

![Area single](https://instachart.coveritup.app/line?title=Single+Area&fill=true&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22]],%20%22y%22:%20[[1,2,3]],%20%22names%22:%20[%22Series%20A%22]%20})
![Area single](https://instachart.coveritup.app/line?title=Single+Area+Series&fill=true&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22]],%20%22y%22:%20[[1,2,3]],%20%22names%22:%20[%22Series%20A%22]%20})

### Multiple Line Series

Expand All @@ -112,7 +152,7 @@ https://instachart.coveritup.app/line?title=Multi+Line+Series&x_label=dates&y_la

<br>

![Multi line series](https://instachart.coveritup.app/line?title=Multi+Lines&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22],%20[%222022-12-23%22,%222022-12-28%22,%222023-12-30%22]],%20%22y%22:%20[[1,2,3],%20[1,5,10]],%20%22names%22:%20[%22Series%20A%22,%20%22Series%20B%22]%20})
![Multi line series](https://instachart.coveritup.app/line?title=Multi+Lines+Series&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22],%20[%222022-12-23%22,%222022-12-28%22,%222023-12-30%22]],%20%22y%22:%20[[1,2,3],%20[1,5,10]],%20%22names%22:%20[%22Series%20A%22,%20%22Series%20B%22]%20})

<details>
<summary><b>REQUEST URL</b></summary>
Expand All @@ -126,7 +166,7 @@ https://instachart.coveritup.app/line?title=Single+Line+Series&fill=true&x_label
</details>
<br>

![Multi area series](https://instachart.coveritup.app/line?title=Multi+Areas&fill=true&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22],%20[%222022-12-23%22,%222022-12-28%22,%222023-12-30%22]],%20%22y%22:%20[[1,2,3],%20[1,5,10]],%20%22names%22:%20[%22Series%20A%22,%20%22Series%20B%22]%20})
![Multi area series](https://instachart.coveritup.app/line?title=Multi+Areas+Series&fill=true&x_label=dates&y_label=amount&data={%20%22x%22:%20[[%222022-12-23%22,%222022-12-24%22,%222023-12-25%22],%20[%222022-12-23%22,%222022-12-28%22,%222023-12-30%22]],%20%22y%22:%20[[1,2,3],%20[1,5,10]],%20%22names%22:%20[%22Series%20A%22,%20%22Series%20B%22]%20})


### Continuous Series
Expand All @@ -146,7 +186,7 @@ https://instachart.coveritup.app/line?title=Continuous+Series&x_label=No+of+peop

<br>

![Continuous line series](https://instachart.coveritup.app/line?title=Continuous+Lines&x_label=No+of+people&y_label=amount&data={%20"x":%20[["10","20","30"],%20["10","20","30"],%20["10","20","30"]],%20"y":%20[[1,2,3],%20[10,20,30],%20[6,3,9]]%20})
![Continuous line series](https://instachart.coveritup.app/line?title=Continuous+Lines+Series&x_label=No+of+people&y_label=amount&data={%20"x":%20[["10","20","30"],%20["10","20","30"],%20["10","20","30"]],%20"y":%20[[1,2,3],%20[10,20,30],%20[6,3,9]]%20})

<details>
<summary><b>REQUEST URL</b></summary>
Expand All @@ -164,7 +204,7 @@ https://instachart.coveritup.app/line?title=Continuous+Series&fill=true&x_label=
<br>


![Continuous area series](https://instachart.coveritup.app/line?title=Continuous+Areas&x_label=No+of+people&y_label=amount&fill=true&data={%20"x":%20[["10","20","30"],%20["10","20","30"],%20["10","20","30"]],%20"y":%20[[1,2,3],%20[10,20,30],%20[6,3,9]]%20})
![Continuous area series](https://instachart.coveritup.app/line?title=Continuous+Areas+Series&x_label=No+of+people&y_label=amount&fill=true&data={%20"x":%20[["10","20","30"],%20["10","20","30"],%20["10","20","30"]],%20"y":%20[[1,2,3],%20[10,20,30],%20[6,3,9]]%20})



Expand Down
19 changes: 19 additions & 0 deletions pkg/line_chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@ func (c *LineChart) GetYValues(data []float64) []float64 {
return yValues
}

func (c *LineChart) ContainsDateOrFloat(xData [][]string) bool {
for _, xSlice := range xData {
for _, x := range xSlice {
if c.IsTimeseries(x) {
return true
}
}
}
for _, xSlice := range xData {
for _, x := range xSlice {
if _, err := strconv.ParseFloat(x, 32); err == nil {
return true
} else {
return false
}
}
}
return false
}
func (c *LineChart) GetSeries(xData [][]string, yData [][]float64, names []string, color string, fill bool) []chart.Series {
var series []chart.Series
isTimeSeries := c.IsTimeseries(xData[0][0])
Expand Down
92 changes: 67 additions & 25 deletions pkg/line_chart_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"

"github.com/labstack/echo/v4"
charts "github.com/vicanso/go-charts/v2"
"github.com/wcharczuk/go-chart/v2"
)

Expand All @@ -20,14 +21,15 @@ func NewLineChartHandler() *LineChartHandler {
}

type LineChartRequest struct {
ChartData string `json:"data" query:"data" form:"data" validate:"required" message:"data is required"`
XAxisLabel string `json:"x_label" query:"x_label" form:"x_label"`
YAxisLabel string `json:"y_label" query:"y_label" form:"y_label"`
ChartTitle string `json:"title" query:"title" form:"title"`
Fill bool `json:"fill" query:"fill" form:"fill"`
Color string `json:"color" query:"color" form:"color"`
Height int `json:"height" query:"height" form:"height"`
Width int `json:"width" query:"width" form:"width"`
ChartData string `json:"data" query:"data" form:"data" validate:"required" message:"data is required"`
XAxisLabel string `json:"x_label" query:"x_label" form:"x_label"`
YAxisLabel string `json:"y_label" query:"y_label" form:"y_label"`
ChartTitle string `json:"title" query:"title" form:"title"`
ChartSubtitle string `json:"subtitle" query:"subtitle" form:"subtitle"`
Fill bool `json:"fill" query:"fill" form:"fill"`
Color string `json:"color" query:"color" form:"color"`
Height int `json:"height" query:"height" form:"height"`
Width int `json:"width" query:"width" form:"width"`
}

type LineChartData struct {
Expand All @@ -47,26 +49,66 @@ func (h *LineChartHandler) Get(c echo.Context) ([]byte, error) {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}

if len(data.XData) == 0 || len(data.XData) != len(data.YData) {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, "data provided is invalid")
}
isSeries := h.chart.ContainsDateOrFloat(data.XData)

graph := chart.Chart{
Title: req.ChartTitle,
Height: req.Height,
Width: req.Width,
Background: h.chart.GetBackground(),
XAxis: h.chart.GetXAxis(req.XAxisLabel),
YAxis: h.chart.GetYAxis(req.YAxisLabel),
Series: h.chart.GetSeries(data.XData, data.YData, data.Names, req.Color, req.Fill),
}
graph.Elements = []chart.Renderable{
chart.Legend(&graph),
if isSeries {
if len(data.XData) == 0 || len(data.XData) != len(data.YData) {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, "data provided is invalid")
}
graph := chart.Chart{
Title: req.ChartTitle,
Height: req.Height,
Width: req.Width,
Background: h.chart.GetBackground(),
XAxis: h.chart.GetXAxis(req.XAxisLabel),
YAxis: h.chart.GetYAxis(req.YAxisLabel),
Series: h.chart.GetSeries(data.XData, data.YData, data.Names, req.Color, req.Fill),
}
graph.Elements = []chart.Renderable{
chart.Legend(&graph),
}
buffer := bytes.NewBuffer([]byte{})
err := graph.Render(chart.PNG, buffer)
if err != nil {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}
return buffer.Bytes(), err
}
buffer := bytes.NewBuffer([]byte{})
err := graph.Render(chart.PNG, buffer)
p, err := charts.LineRender(
data.YData,
charts.HeightOptionFunc(req.Height),
charts.WidthOptionFunc(req.Width),
charts.TitleOptionFunc(charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
SubtextFontSize: 9,
Left: charts.PositionCenter,
}),
charts.XAxisDataOptionFunc(data.XData[0]),
charts.LegendOptionFunc(charts.LegendOption{
Orient: charts.OrientVertical,
Data: data.Names,
Left: charts.PositionLeft,
}),
func(opt *charts.ChartOption) {
opt.FillArea = req.Fill
opt.SeriesList[1].MarkPoint = charts.NewMarkPoint(
charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin,
)
opt.SeriesList[1].MarkLine = charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
)
},
)

if err != nil {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}
return buffer.Bytes(), err

buf, err := p.Bytes()
if err != nil {
return nil, err
}
return buf, err
}

0 comments on commit 5893b32

Please sign in to comment.