Skip to content

Commit

Permalink
Merge pull request #1 from kevincobain2000/feature/api
Browse files Browse the repository at this point in the history
(docs) adds frontend LP
  • Loading branch information
kevincobain2000 authored Jun 3, 2024
2 parents 44ad89d + efeed65 commit 0fd7e40
Show file tree
Hide file tree
Showing 46 changed files with 9,062 additions and 190 deletions.
45 changes: 45 additions & 0 deletions .air.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# .air.conf
# Config file for [Air](https://github.com/cosmtrek/air) in TOML format

# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"

[build]
# Just plain old shell command. You could use `make` as well.
cmd = "go mod tidy && go build -o ./tmp/main api/main.go"
# Binary file yields from `cmd`.
bin = "tmp/main"
# Customize binary.
# allow cors for astro
full_bin = "PP_USER=air ./tmp/main --cors=4321"
# Watch these filename extensions.
include_ext = ["go", "tpl", "tmpl", "html", "env", "conf"]
# Ignore these filename extensions or directories.
exclude_dir = ["assets", "tmp", "vendor", "dist", "api/pkg/frontend"]
# Watch these directories if you specified.
include_dir = []
# Exclude files.
exclude_file = []
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 1000 # ms
# Stop to run old binary when build errors occur.
stop_on_error = true
# This log file places in your tmp_dir.
log = "air_errors.log"

[log]
# Show log time
time = false

[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
# Delete tmp directory on exit
clean_on_exit = true
18 changes: 18 additions & 0 deletions .github/workflows/coveritup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ jobs:
- uses: kevincobain2000/action-gobrew@v2
with:
version: ${{ matrix.go-version }}
- name: Setup Node.js ${{ matrix.node-versions }}
uses: actions/setup-node@v2
with:
node-version: 20

- name: Install Tools
run: |
Expand All @@ -31,6 +35,20 @@ jobs:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
curl -sLk https://raw.githubusercontent.com/kevincobain2000/cover-totalizer/master/install.sh | sh
- name: NPM Install
uses: kevincobain2000/action-coveritup@v2
with:
type: npm-install-time
command: cd api/pkg/frontend; npm install
record: runtime

- name: NPM Build
uses: kevincobain2000/action-coveritup@v2
with:
type: npm-build-time
command: cd api/pkg/frontend; npm run build
record: runtime

- run: go mod tidy
- name: Lint Errors
uses: kevincobain2000/action-coveritup@v2
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ bin/
main
.DS_Store
output.svg
node_modules/
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h1 align="center">
SVG - Circle & Bar Progress generator
SVG - Circle, Bar & Battery progress generator
<br>
in Golang.
<br>
Expand All @@ -24,6 +24,8 @@

**Bar Progress:** Generate pure SVG bar progress bar.

**Battery Progress:** Generate pure SVG battery progress bar.

**Supports Captions:** Add captions horizontally or vertically.

**Customizable:** Customize with various color, width, height, background and caption options.
Expand Down Expand Up @@ -66,14 +68,13 @@ import (
func main() {
circular, _ := gps.NewCircular(func(o *gps.CircularOptions) error {
o.Progress = 97
o.Size = 200
o.CircleSize = 200
o.CircleWidth = 16
o.ProgressWidth = 16
o.CircleColor = "#e0e0e0"
o.ProgressColor = "#76e5b1"
o.TextColor = "#6bdba7"
o.TextSize = 52
o.ShowPercentage = true
o.TextSize = 52true
o.BackgroundColor = ""
o.Caption = ""
o.CaptionPos = "bottom"
Expand Down Expand Up @@ -104,8 +105,7 @@ func main() {
o.Height = 50
o.ProgressColor = "#76e5b1"
o.TextColor = "#6bdba7"
o.TextSize = 20
o.ShowPercentage = true
o.TextSize = 20true
o.Caption = ""
o.CaptionSize = 16
o.CaptionColor = "#000000"
Expand Down
30 changes: 30 additions & 0 deletions api/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package main

import (
"flag"

"github.com/kevincobain2000/go-progress-svg/api/pkg"
)

type Flags struct {
host string
port string
cors string
baseUrl string
}

var f Flags

func main() {
SetupFlags()
pkg.StartEcho(pkg.NewEcho(f.baseUrl, f.cors), f.host, f.port)
}

func SetupFlags() {
flag.StringVar(&f.host, "host", "localhost", "host to serve")
flag.StringVar(&f.port, "port", "3003", "port to serve")
flag.StringVar(&f.cors, "cors", "", "cors port to allow")
flag.StringVar(&f.baseUrl, "base-url", "/", "base url with slash")
flag.Parse()

}
134 changes: 134 additions & 0 deletions api/pkg/api_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package pkg

import (
"net/http"

gps "github.com/kevincobain2000/go-progress-svg"
"github.com/labstack/echo/v4"
"github.com/mcuadros/go-defaults"
)

type APIHandler struct {
}

func NewAPIHandler() *APIHandler {
return &APIHandler{}
}

type APIRequest struct {
Style string `json:"style" query:"style" default:"circle" validate:"required,ascii,oneof=circle battery bar" message:"style is required"`

// common on all styles
Progress int `json:"progress" query:"progress" default:"1" validate:"required,min=0,max=100" message:"progress is required"`

// only circle style
CircleSize int `json:"size" query:"size" default:"100" validate:"required,min=50,max=500" message:"size is required"`
CircleWidth int `json:"circle_width" query:"circle_width" default:"15" validate:"required,min=1,max=200" message:"circle_width is required"`
ProgressWidth int `json:"progress_width" query:"progress_width" default:"15" validate:"required,min=1,max=50" message:"progress_width is required"`
CircleColor string `json:"circle_color" query:"circle_color" default:"e0e0e0" validate:"required" message:"circle_color is required"`

// circle style
ProgressColor string `json:"progress_color" query:"progress_color" default:"76e5b1" validate:"required" message:"progress_color is required"`
TextColor string `json:"text_color" query:"text_color" default:"6bdba7" validate:"required" message:"text_color is required"`
TextSize int `json:"text_size" query:"text_size" default:"52" validate:"required,min=10,max=100" message:"text_size is required"`

BackgroundColor string `json:"background_color" query:"background_color" default:"e0e0e0" validate:"required" message:"background_color is required"`
CaptionSize int `json:"caption_size" query:"caption_size" default:"25" validate:"required,min=2,max=100" message:"caption_size is required"`
CaptionColor string `json:"caption_color" query:"caption_color" default:"000000" validate:"required" message:"caption_color is required"`
SegmentCount int `json:"segment_count" query:"segment_count" default:"1" validate:"min=0,max=100" message:"segment_count min 0 and max 100"`
SegmentGap int `json:"segment_gap" query:"segment_gap" default:"0" validate:"min=0,max=10" message:"segment_gap min 0 and max 10"`
Caption string `json:"caption" query:"caption" default:"" validate:"ascii,min=0,max=20" message:"caption min 0 and max 20"`
CornerRadius int `json:"corner_radius" query:"corner_radius" default:"10" validate:"required,min=1,max=50" message:"corner_radius is required"`

// only bar style
Width int `json:"width" query:"width" default:"200" validate:"required,min=50,max=500" message:"width is required"`
Height int `json:"height" query:"height" default:"20" validate:"required,min=20,max=500" message:"height is required"`
}

func (h *APIHandler) Get(c echo.Context) error {
req := new(APIRequest)
if err := BindRequest(c, req); err != nil {
return echo.NewHTTPError(http.StatusUnprocessableEntity, err)
}
defaults.SetDefaults(req)
msgs, err := ValidateRequest(req)
if err != nil {
return echo.NewHTTPError(http.StatusUnprocessableEntity, msgs)
}

if req.Style == "circle" {
circular, err := gps.NewCircular(func(o *gps.CircularOptions) error {
o.Progress = req.Progress
o.CircleSize = req.CircleSize
o.CircleWidth = req.CircleWidth
o.ProgressWidth = req.ProgressWidth
o.CircleColor = "#" + req.CircleColor
o.ProgressColor = "#" + req.ProgressColor
o.TextColor = "#" + req.TextColor
o.TextSize = req.TextSize
o.BackgroundColor = "#" + req.BackgroundColor
o.Caption = req.Caption
o.CaptionSize = req.CaptionSize
o.CaptionColor = "#" + req.CaptionColor
o.SegmentCount = req.SegmentCount
o.SegmentGap = float64(req.SegmentGap)

return nil
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err)
}
content := circular.SVG()
SetHeadersResponseSvg(c.Response().Header())
return c.Blob(http.StatusOK, "image/svg+xml", []byte(content))
}

if req.Style == "bar" {
bar, err := gps.NewBar(func(o *gps.BarOptions) error {
o.Progress = req.Progress
o.Caption = req.Caption
o.Width = req.Width
o.Height = req.Height
o.ProgressColor = "#" + req.ProgressColor
o.TextColor = "#" + req.TextColor
o.TextSize = req.TextSize
o.Caption = req.Caption
o.CaptionSize = req.CaptionSize
o.CaptionColor = "#" + req.CaptionColor
o.BackgroundColor = "#" + req.BackgroundColor
o.CornerRadius = req.CornerRadius
return nil
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err)
}
content := bar.SVG()
SetHeadersResponseSvg(c.Response().Header())
return c.Blob(http.StatusOK, "image/svg+xml", []byte(content))
}

if req.Style == "battery" {
battery, err := gps.NewBattery(func(o *gps.BatteryOptions) error {
o.Progress = req.Progress
o.Caption = req.Caption
o.Width = req.Width
o.Height = req.Height
o.ProgressColor = "#" + req.ProgressColor
o.TextColor = "#" + req.TextColor
o.TextSize = req.TextSize
o.Caption = req.Caption
o.CaptionSize = req.CaptionSize
o.CaptionColor = "#" + req.CaptionColor
o.BackgroundColor = "#" + req.BackgroundColor
o.CornerRadius = req.CornerRadius
return nil
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err)
}
content := battery.SVG()
SetHeadersResponseSvg(c.Response().Header())
return c.Blob(http.StatusOK, "image/svg+xml", []byte(content))
}
return nil
}
49 changes: 49 additions & 0 deletions api/pkg/assets_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package pkg

import (
"embed"
"fmt"
"net/http"
"os"

"github.com/labstack/echo/v4"
)

type AssetsHandler struct {
filename string
publicDir embed.FS
}

func NewAssetsHandler(publicDir embed.FS, filename string) *AssetsHandler {
return &AssetsHandler{
publicDir: publicDir,
filename: filename,
}
}

func (h *AssetsHandler) GetPlain(c echo.Context) error {
filename := fmt.Sprintf("%s/%s", DIST_DIR, h.filename)
content, err := h.publicDir.ReadFile(filename)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not Found")
}
return ResponsePlain(c, content, "0")
}
func (h *AssetsHandler) GetICO(c echo.Context) error {
filename := fmt.Sprintf("%s/%s", DIST_DIR, h.filename)
content, err := h.publicDir.ReadFile(filename)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not Found")
}
SetHeadersResponsePNG(c.Response().Header())
return c.Blob(http.StatusOK, "image/x-icon", content)
}

func (h *AssetsHandler) GetHTML(c echo.Context) error {
filename := fmt.Sprintf("%s/%s", DIST_DIR, h.filename)
content, err := h.publicDir.ReadFile(filename)
if err != nil {
return c.String(http.StatusOK, os.Getenv("VERSION"))
}
return ResponseHTML(c, content, "0")
}
Loading

0 comments on commit 0fd7e40

Please sign in to comment.