[TASK] response available as json or svg template
This commit is contained in:
parent
9b10999cde
commit
21859eec82
|
@ -26,6 +26,7 @@ func main() {
|
|||
|
||||
// load config
|
||||
config = models.ReadConfigFile(configFile)
|
||||
web.GoodAvailablityTemplate = config.GoodAvailablityTemplate
|
||||
|
||||
log.Log.Info("Starting rezension monolith")
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
webserver_bind = ":8080"
|
||||
|
||||
good_availablity_template = "contrib/good_availablity.svg"
|
||||
|
||||
[database]
|
||||
type = "sqlite3"
|
||||
# logging = true
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g class="arcs">
|
||||
<circle cx="50" cy="50" r="40" fill="#fff" stroke="#aaa" stroke-width="5"/>
|
||||
<circle cx="50" cy="50" r="40" fill="none" stroke="#26b" stroke-width="5" stroke-dasharray="251.33" stroke-dashoffset="{{process_radius .Count 10 40}}"/>
|
||||
</g>
|
||||
<text x="50" y="58" fill="#555" text-anchor="middle" style="font: 500 20px Roboto,Verdana,sans-serif;">{{procent .Count 10}}%</text>
|
||||
</svg>
|
After Width: | Height: | Size: 495 B |
40
http/good.go
40
http/good.go
|
@ -4,6 +4,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
logrus "github.com/Sirupsen/logrus"
|
||||
"goji.io/pat"
|
||||
|
||||
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
||||
|
@ -31,3 +32,42 @@ func listGoods(w http.ResponseWriter, r *http.Request) {
|
|||
lib.Write(w, list)
|
||||
log.Info("done")
|
||||
}
|
||||
|
||||
func getGoodAvailablityCount(w http.ResponseWriter, r *http.Request) (int, *logrus.Entry) {
|
||||
log := logger.HTTP(r)
|
||||
id, err := strconv.ParseInt(pat.Param(r, "productid"), 10, 64)
|
||||
if err != nil {
|
||||
log.Warn("wrong productid format")
|
||||
http.Error(w, "wrong productid", http.StatusNotAcceptable)
|
||||
return -1, log
|
||||
}
|
||||
log = log.WithField("productid", id)
|
||||
product := models.Product{ID: id}
|
||||
ok, err := product.Exists()
|
||||
if err != nil {
|
||||
log.Warn("product could not verified on other microservice")
|
||||
http.Error(w, "product could not verified on other microservice", http.StatusGatewayTimeout)
|
||||
}
|
||||
if !ok {
|
||||
log.Warn("product did not exists anymore")
|
||||
http.Error(w, "product did not exists anymore", http.StatusNotFound)
|
||||
return -1, log
|
||||
}
|
||||
var count float64
|
||||
(&models.Good{}).FilterAvailable(database.Read.Where("product_id = ?", product.ID)).Count(&count)
|
||||
return int(count), log
|
||||
}
|
||||
func getGoodAvailablity(w http.ResponseWriter, r *http.Request) {
|
||||
count, log := getGoodAvailablityCount(w, r)
|
||||
if count < 0 {
|
||||
return
|
||||
}
|
||||
log = log.WithField("type", r.Header.Get("Content-Type"))
|
||||
switch r.Header.Get("Content-Type") {
|
||||
case "application/json":
|
||||
lib.Write(w, count)
|
||||
default:
|
||||
getGoodAvailablitySVG(w, count)
|
||||
}
|
||||
log.Info("done")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var GoodAvailablityTemplate string
|
||||
|
||||
func tempProcent(value, max int) int {
|
||||
return value * 100 / max
|
||||
}
|
||||
|
||||
func tempProcessRadius(value, max, radius int) float64 {
|
||||
return (1 - float64(value)/float64(max)) * float64(radius) * 2 * 3.14
|
||||
}
|
||||
|
||||
func getGoodAvailablitySVG(w http.ResponseWriter, count int) {
|
||||
|
||||
t := template.New("some")
|
||||
t = t.Funcs(template.FuncMap{"procent": tempProcent,
|
||||
"process_radius": tempProcessRadius,
|
||||
})
|
||||
buf := bytes.NewBuffer(nil)
|
||||
f, _ := os.Open(GoodAvailablityTemplate) // Error handling elided for brevity.
|
||||
io.Copy(buf, f) // Error handling elided for brevity.
|
||||
f.Close()
|
||||
|
||||
s := string(buf.Bytes())
|
||||
t.Parse(s)
|
||||
|
||||
w.Header().Set("Content-Type", "image/svg+xml")
|
||||
t.Execute(w, map[string]interface{}{"Count": count})
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTempFuncs(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
resultInt := tempProcent(3, 9)
|
||||
assert.Equal(33, resultInt)
|
||||
|
||||
// TODO is there a other way to calc this?
|
||||
resultFloat := tempProcessRadius(3, 9, 0)
|
||||
assert.Equal(float64(0), resultFloat)
|
||||
}
|
|
@ -2,7 +2,9 @@ package http
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
||||
"github.com/genofire/hs_master-kss-monolith/models"
|
||||
|
@ -10,7 +12,7 @@ import (
|
|||
"github.com/genofire/hs_master-kss-monolith/test"
|
||||
)
|
||||
|
||||
func TestGood(t *testing.T) {
|
||||
func TestListGood(t *testing.T) {
|
||||
assertion, router := test.Init(t)
|
||||
|
||||
BindAPI(router)
|
||||
|
@ -33,3 +35,45 @@ func TestGood(t *testing.T) {
|
|||
|
||||
test.Close()
|
||||
}
|
||||
|
||||
func TestGetGoodAvailable(t *testing.T) {
|
||||
now := time.Now()
|
||||
assertion, router := test.Init(t)
|
||||
|
||||
BindAPI(router)
|
||||
session := test.NewSession(router)
|
||||
|
||||
result, w := session.JSONRequest("GET", "/api/good/availablity/a", nil)
|
||||
assertion.Equal(http.StatusNotAcceptable, w.StatusCode)
|
||||
|
||||
result, w = session.JSONRequest("GET", "/api/good/availablity/1", nil)
|
||||
assertion.Equal(http.StatusOK, w.StatusCode)
|
||||
assertion.Equal(float64(0), result)
|
||||
|
||||
database.Write.Create(&models.Good{
|
||||
ProductID: 3,
|
||||
Comment: "blub",
|
||||
LockedAt: &now,
|
||||
LockedSecret: "hidden",
|
||||
})
|
||||
database.Write.Create(&models.Good{
|
||||
ProductID: 3,
|
||||
Comment: "blub",
|
||||
})
|
||||
database.Write.Create(&models.Good{
|
||||
ProductID: 3,
|
||||
Comment: "blub",
|
||||
})
|
||||
|
||||
result, w = session.JSONRequest("GET", "/api/good/availablity/3", nil)
|
||||
assertion.Equal(http.StatusOK, w.StatusCode)
|
||||
assertion.Equal(float64(2), result)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/api/good/availablity/3", nil)
|
||||
req.Header.Set("Content-Type", "image/svg+xml")
|
||||
rec := httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, req)
|
||||
assertion.Equal(http.StatusOK, w.StatusCode)
|
||||
|
||||
test.Close()
|
||||
}
|
||||
|
|
|
@ -8,4 +8,5 @@ import (
|
|||
func BindAPI(router *goji.Mux) {
|
||||
router.HandleFunc(pat.Get("/api/status"), status)
|
||||
router.HandleFunc(pat.Get("/api/good/:productid"), listGoods)
|
||||
router.HandleFunc(pat.Get("/api/good/availablity/:productid"), getGoodAvailablity)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
|
||||
var Log *logger.Logger
|
||||
|
||||
type Logger logger.Entry
|
||||
|
||||
func init() {
|
||||
Log = logger.New()
|
||||
// Enable fallback if core logger is used:
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
type Config struct {
|
||||
WebserverBind string `toml:"webserver_bind"`
|
||||
Database database.Config `toml:"database"`
|
||||
GoodAvailablityTemplate string `toml:"good_availablity_template"`
|
||||
GoodRelease struct {
|
||||
After Duration `toml:"after"`
|
||||
Timer Duration `toml:"timer"`
|
||||
|
|
|
@ -11,11 +11,13 @@ func TestDuration(t *testing.T) {
|
|||
assert := assert.New(t)
|
||||
|
||||
var tests = []struct {
|
||||
input string
|
||||
input interface{}
|
||||
err string
|
||||
duration time.Duration
|
||||
}{
|
||||
{3, "invalid duration: \"%!s(int=3)\"", 0},
|
||||
{"", "invalid duration: \"\"", 0},
|
||||
{"am", "unable to parse duration am: strconv.Atoi: parsing \"a\": invalid syntax", 0},
|
||||
{"1x", "invalid duration unit: x", 0},
|
||||
{"1s", "", time.Second},
|
||||
{"73s", "", time.Second * 73},
|
||||
|
|
|
@ -26,7 +26,7 @@ type Good struct {
|
|||
}
|
||||
|
||||
func (g *Good) FilterAvailable(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("locked_secret is NULL deleted_at is NULL and send_at is NULL")
|
||||
return db.Model(g).Where("locked_secret == '' OR locked_secret is NULL")
|
||||
}
|
||||
|
||||
func (g *Good) Lock(secret string) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package models
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -21,4 +22,7 @@ func TestGood(t *testing.T) {
|
|||
|
||||
good.Unlock("blub_secret")
|
||||
assert.False(good.IsLock())
|
||||
|
||||
assert.NotNil(good.FilterAvailable(database.Read))
|
||||
|
||||
}
|
||||
|
|
Reference in New Issue