Skip to content

Commit

Permalink
Merge pull request #23 from kevincobain2000/feature/mini
Browse files Browse the repository at this point in the history
add support for mini
  • Loading branch information
kevincobain2000 authored Jan 29, 2024
2 parents 47ea94e + 5ae296f commit 1f3ac6b
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 98 deletions.
64 changes: 39 additions & 25 deletions pkg/bar_chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,25 @@ func NewBarChart() *BarChart {
}

func (c *BarChart) GetVertical(xData []string, yData [][]float64, names []string, req *ChartRequest) ([]byte, error) {
isMini := IsMiniChart(req)
showLegend := true
paddings := GetPaddings(req)
titleSizes := GetTitleSizes(req)
if isMini {
showLegend = false
}
p, err := charts.BarRender(
yData,
charts.TitleOptionFunc(charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
SubtextFontSize: DEFAULT_SUBTITLE_FONT_SIZE,
Left: charts.PositionCenter,
SubtextFontColor: DEFAULT_SUBTITLE_COLOR,
}),
charts.TitleOptionFunc(titleSizes),
charts.HeightOptionFunc(req.Height),
charts.WidthOptionFunc(req.Width),
charts.PaddingOptionFunc(paddings),
charts.XAxisDataOptionFunc(xData),
charts.LegendOptionFunc(charts.LegendOption{
Orient: charts.OrientHorizontal,
Data: names,
Left: charts.PositionLeft,
Show: &showLegend,
}),
charts.MarkLineOptionFunc(0, charts.SeriesMarkDataTypeAverage),
charts.MarkPointOptionFunc(0, charts.SeriesMarkDataTypeMax,
Expand All @@ -47,7 +50,11 @@ func (c *BarChart) GetVertical(xData []string, yData [][]float64, names []string
Bottom: DEFAULT_PADDING_BOTTOM,
}
opt.ValueFormatter = func(f float64) string {
if isMini {
return "-"
}
return fmt.Sprintf("%s %s", NumberToK(&f), req.Metric)

}
idx := len(opt.SeriesList) - 1
if len(opt.SeriesList) > 1 {
Expand All @@ -57,9 +64,11 @@ func (c *BarChart) GetVertical(xData []string, yData [][]float64, names []string
charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin,
)
opt.SeriesList[idx].MarkLine = charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
)
if !isMini {
opt.SeriesList[idx].MarkLine = charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
)
}
},
)
if err != nil {
Expand Down Expand Up @@ -90,15 +99,9 @@ func (c *BarChart) GetStacked(xData []string, yData [][]float64, zData [][]float
}
series = append(series, s)
}

titleSizes := GetTitleSizes(req)
opt := charts.ChartOption{
Title: charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
SubtextFontSize: DEFAULT_SUBTITLE_FONT_SIZE,
SubtextFontColor: DEFAULT_SUBTITLE_COLOR,
Left: charts.PositionCenter,
},
Title: titleSizes,
XAxis: charts.NewXAxisOption(xData),
Legend: charts.NewLegendOption(names),
YAxisOptions: []charts.YAxisOption{
Expand Down Expand Up @@ -154,22 +157,33 @@ func (c *BarChart) GetStacked(xData []string, yData [][]float64, zData [][]float
}

func (c *BarChart) GetHorizontal(xData []string, yData [][]float64, names []string, req *ChartRequest) ([]byte, error) {
isMini := IsMiniChart(req)
showLegend := true
paddings := GetPaddings(req)
titleSizes := GetTitleSizes(req)
if isMini {
showLegend = false
}
p, err := charts.HorizontalBarRender(
yData,
charts.TitleOptionFunc(charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
SubtextFontSize: DEFAULT_SUBTITLE_FONT_SIZE,
SubtextFontColor: DEFAULT_SUBTITLE_COLOR,
Left: charts.PositionCenter,
}),
charts.TitleOptionFunc(titleSizes),
charts.HeightOptionFunc(req.Height),
charts.WidthOptionFunc(req.Width),
charts.PaddingOptionFunc(paddings),
charts.YAxisDataOptionFunc(xData),
charts.LegendOptionFunc(charts.LegendOption{
Orient: charts.OrientHorizontal,
Data: names,
Left: charts.PositionLeft,
Show: &showLegend,
}),
func(opt *charts.ChartOption) {
opt.Theme = req.Theme
opt.Type = req.Output
opt.ValueFormatter = func(f float64) string {
if isMini {
return "-"
}
return fmt.Sprintf("%s %s", NumberToK(&f), req.Metric)
}
},
Expand Down
102 changes: 41 additions & 61 deletions pkg/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ package pkg
import (
"errors"
"net/http"
"net/url"
"os"
"strconv"
"strings"

"github.com/imroc/req/v3"
charts "github.com/vicanso/go-charts/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
)

Expand All @@ -17,7 +14,10 @@ const (
DEFAULT_PADDING_RIGHT = 20
DEFAULT_PADDING_BOTTOM = 20
DEFAULT_PADDING_LEFT = 20
DEFAULT_SUBTITLE_FONT_SIZE = 11
DEFAULT_TITLE_FONT_SIZE = 12
DEFAULT_SUBTITLE_FONT_SIZE = 10
MINI_CHART_WIDTH = 300
MINI_CHART_HEIGHT = 300

BAR_STYLE_VERTICAL = "vertical"
BAR_STYLE_HORIZONTAL = "horizontal"
Expand Down Expand Up @@ -88,44 +88,6 @@ func SetHeadersResponseTxt(header http.Header) {
header.Set("X-XSS-Protection", "1; mode=block")
}

func IsURL(urlStr string) bool {
parsedURL, err := url.ParseRequestURI(urlStr)
return err == nil && parsedURL.Scheme != "" && parsedURL.Host != ""
}

func IsAllowedDomain(urlStr string, allowedDomains string) bool {
if allowedDomains == "" {
return false // default do not allow any urls
}

// Parse the URL to extract the domain
parsedURL, err := url.Parse(urlStr)
if err != nil {
return false // If the URL is invalid, do not allow
}
domain := parsedURL.Hostname()

// Split the allowedDomains into a slice
domains := strings.Split(allowedDomains, ",")

// Check if the domain is in the list of allowed domains
for _, d := range domains {
if domain == d {
return true
}
}

return false
}

func GetURL(urlStr string) (string, error) {
resp, err := req.Get(urlStr)
if err != nil {
return "", err
}
return resp.ToString()
}

func SetDataIfRemoteURL(req *ChartRequest) error {
allowedRemoteDomains := os.Getenv("ALLOWED_REMOTE_DOMAINS")
if allowedRemoteDomains == "" {
Expand All @@ -144,28 +106,46 @@ func SetDataIfRemoteURL(req *ChartRequest) error {
return nil
}

// NumberToK converts a number to a string with 'k' for thousands and 'm' for millions.
func NumberToK(num *float64) string {
if num == nil {
return "0"
}
func IsMiniChart(req *ChartRequest) bool {
return req.Width <= MINI_CHART_WIDTH && req.Height <= MINI_CHART_HEIGHT
}

formatNumber := func(n float64) string {
if n == float64(int64(n)) {
// If n is an integer, format without decimal places.
return strconv.FormatFloat(n, 'f', 0, 64)
func GetPaddings(req *ChartRequest) charts.Box {
paddings := charts.Box{
Top: 10,
Bottom: 10,
Left: 10,
Right: 10,
}
if IsMiniChart(req) {
paddings = charts.Box{
Top: 10,
Bottom: -20,
Left: -10,
Right: 10,
}
// Otherwise, format with one decimal place.
return strconv.FormatFloat(n, 'f', 1, 64)
}
return paddings
}

if *num < 1000 {
return formatNumber(*num)
func GetTitleSizes(req *ChartRequest) charts.TitleOption {
titleSizes := charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
FontSize: DEFAULT_TITLE_FONT_SIZE,
SubtextFontSize: DEFAULT_SUBTITLE_FONT_SIZE,
Left: charts.PositionCenter,
SubtextFontColor: DEFAULT_SUBTITLE_COLOR,
}

if *num < 1000000 {
return formatNumber(*num/1000) + "k"
if IsMiniChart(req) {
titleSizes = charts.TitleOption{
Text: Truncate(req.ChartTitle, 17),
Subtext: Truncate(req.ChartSubtitle, 17),
FontSize: DEFAULT_TITLE_FONT_SIZE,
SubtextFontSize: DEFAULT_SUBTITLE_FONT_SIZE,
Left: charts.PositionCenter,
SubtextFontColor: DEFAULT_SUBTITLE_COLOR,
}
}

return formatNumber(*num/1000000) + "m"
return titleSizes
}
35 changes: 23 additions & 12 deletions pkg/line_chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,40 @@ func (c *LineChart) Get(xData []string, yData [][]float64, names []string, req *
if req.Line == "fill" {
fill = true
}
isMini := IsMiniChart(req)

showLegend := true
paddings := GetPaddings(req)
titleSizes := GetTitleSizes(req)
if isMini {
showLegend = false
}
p, err := charts.LineRender(
yData,
charts.HeightOptionFunc(req.Height),
charts.WidthOptionFunc(req.Width),
charts.TitleOptionFunc(charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
SubtextFontSize: DEFAULT_SUBTITLE_FONT_SIZE,
Left: charts.PositionCenter,
SubtextFontColor: DEFAULT_SUBTITLE_COLOR,
}),
charts.PaddingOptionFunc(paddings),
charts.TitleOptionFunc(titleSizes),
charts.XAxisDataOptionFunc(xData),
charts.LegendOptionFunc(charts.LegendOption{
Orient: charts.OrientHorizontal,
Data: names,
Left: charts.PositionLeft,
Show: &showLegend,
}),
func(opt *charts.ChartOption) {
opt.Type = req.Output
opt.Theme = req.Theme
opt.Legend.Padding = charts.Box{
Top: DEFAULT_PADDING_TOP,
Bottom: DEFAULT_PADDING_BOTTOM * 2,
Top: DEFAULT_PADDING_TOP * 2,
Bottom: DEFAULT_PADDING_BOTTOM,
}
opt.ValueFormatter = func(f float64) string {
if isMini {
return "-"
}
return fmt.Sprintf("%s %s", NumberToK(&f), req.Metric)

}
opt.FillArea = fill

Expand All @@ -58,9 +66,12 @@ func (c *LineChart) Get(xData []string, yData [][]float64, names []string, req *
charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin,
)
opt.SeriesList[idx].MarkLine = charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
)
if !isMini {
opt.SeriesList[idx].MarkLine = charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
)
}

},
)
if err != nil {
Expand Down
Loading

0 comments on commit 1f3ac6b

Please sign in to comment.