switched to bindings + validators for forms
This commit is contained in:
parent
de64cd6aab
commit
18449ed0a5
6 changed files with 81 additions and 151 deletions
75
main.go
75
main.go
|
@ -42,6 +42,7 @@ func (web Web) createWatch(c *gin.Context) {
|
||||||
errMap, err := bindAndValidateWatch(&watch, c)
|
errMap, err := bindAndValidateWatch(&watch, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(http.StatusBadRequest, "500", errMap)
|
c.HTML(http.StatusBadRequest, "500", errMap)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
web.db.Create(&watch)
|
web.db.Create(&watch)
|
||||||
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", watch.ID))
|
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", watch.ID))
|
||||||
|
@ -74,83 +75,37 @@ func (web Web) createURL(c *gin.Context) {
|
||||||
c.HTML(http.StatusInternalServerError, "500", errMap)
|
c.HTML(http.StatusInternalServerError, "500", errMap)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
web.db.Create(url)
|
web.db.Create(&url)
|
||||||
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", url.WatchID))
|
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", url.WatchID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web Web) createQuery(c *gin.Context) {
|
func (web Web) createQuery(c *gin.Context) {
|
||||||
watch_id, err := strconv.ParseUint(c.PostForm("watch_id"), 10, 64)
|
watch_id, err := strconv.ParseUint(c.PostForm("w_id"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
log.Print(err)
|
||||||
return // TODO response
|
c.HTML(http.StatusInternalServerError, "500", gin.H{})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
url_id, err := strconv.ParseUint(c.PostForm("url_id"), 10, 64)
|
var query Query
|
||||||
|
errMap, err := bindAndValidateQuery(&query, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
c.HTML(http.StatusBadRequest, "500", errMap)
|
||||||
return // TODO response
|
|
||||||
}
|
|
||||||
name := c.PostForm("name")
|
|
||||||
if name == "" {
|
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
typ := c.PostForm("type")
|
web.db.Create(&query)
|
||||||
if typ == "" {
|
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
query := c.PostForm("query")
|
|
||||||
if query == "" {
|
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
query_model := &Query{
|
|
||||||
URLID: uint(url_id),
|
|
||||||
Name: name,
|
|
||||||
Type: typ,
|
|
||||||
Query: query,
|
|
||||||
}
|
|
||||||
web.db.Create(query_model)
|
|
||||||
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", watch_id))
|
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", watch_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web Web) createFilter(c *gin.Context) {
|
func (web Web) createFilter(c *gin.Context) {
|
||||||
query_id, err := strconv.ParseUint(c.PostForm("query_id"), 10, 64)
|
var filter Filter
|
||||||
|
errMap, err := bindAndValidateFilter(&filter, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
c.HTML(http.StatusBadRequest, "500", errMap)
|
||||||
return // TODO response
|
|
||||||
}
|
|
||||||
name := c.PostForm("name")
|
|
||||||
if name == "" {
|
|
||||||
log.Print(name)
|
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
typ := c.PostForm("type")
|
web.db.Create(&filter)
|
||||||
if typ == "" {
|
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/query/edit/%d", filter.QueryID))
|
||||||
log.Print(typ)
|
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
from := c.PostForm("from")
|
|
||||||
if from == "" {
|
|
||||||
log.Print(from)
|
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
to := c.PostForm("to")
|
|
||||||
log.Print("To:", to)
|
|
||||||
filter_model := &Filter{
|
|
||||||
QueryID: uint(query_id),
|
|
||||||
Name: name,
|
|
||||||
Type: typ,
|
|
||||||
From: from,
|
|
||||||
To: to,
|
|
||||||
}
|
|
||||||
web.db.Create(filter_model)
|
|
||||||
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/query/edit/%d", query_id))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web Web) editQuery(c *gin.Context) {
|
func (web Web) editQuery(c *gin.Context) {
|
||||||
|
|
24
models.go
24
models.go
|
@ -6,36 +6,36 @@ import (
|
||||||
|
|
||||||
type Watch struct {
|
type Watch struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string `form:"name" yaml:"name" binding:"required" validate:"min=1"`
|
Name string `form:"watch_name" yaml:"watch_name" binding:"required" validate:"min=1"`
|
||||||
Interval int `form:"interval" yaml:"interval" binding:"required"`
|
Interval int `form:"interval" yaml:"interval" binding:"required"`
|
||||||
URLs []URL
|
URLs []URL
|
||||||
}
|
}
|
||||||
|
|
||||||
type URL struct {
|
type URL struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
WatchID uint `form:"watch_id" yaml:"watch_id" binding:"required"`
|
WatchID uint `form:"url_watch_id" yaml:"url_watch_id" binding:"required"`
|
||||||
Watch *Watch `form:"watch" yaml:"watch" validate:"omitempty"`
|
Watch *Watch `form:"watch" yaml:"watch" validate:"omitempty"`
|
||||||
Name string `form:"name" yaml:"name" binding:"required"`
|
Name string `form:"url_name" yaml:"url_name" binding:"required" validate:"min=1"`
|
||||||
URL string `form:"url" yaml:"url" binding:"required,url"`
|
URL string `form:"url" yaml:"url" binding:"required,url" validate:"min=1"`
|
||||||
Queries []Query
|
Queries []Query
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query struct {
|
type Query struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
URLID uint `form:"url_id" yaml:"url_id" binding:"required"`
|
URLID uint `form:"query_url_id" yaml:"query_url_id" binding:"required"`
|
||||||
URL URL
|
URL *URL
|
||||||
Name string `form:"name" yaml:"name" binding:"required"`
|
Name string `form:"query_name" yaml:"query_name" binding:"required" validate:"min=1"`
|
||||||
Type string `form:"type" yaml:"type" binding:"required"`
|
Type string `form:"query_type" yaml:"query_type" binding:"required" validate:"oneof=css xpath regex json"`
|
||||||
Query string `form:"query" yaml:"query" binding:"required"`
|
Query string `form:"query" yaml:"query" binding:"required"`
|
||||||
Filters []Filter
|
Filters []Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
QueryID uint `form:"query_id" yaml:"query_id" binding:"required"`
|
QueryID uint `form:"filter_query_id" yaml:"filter_query_id" binding:"required"`
|
||||||
Query Query
|
Query *Query
|
||||||
Name string `form:"name" yaml:"name" binding:"required"`
|
Name string `form:"filter_name" yaml:"filter_name" binding:"required" validate:"min=1"`
|
||||||
Type string `form:"type" yaml:"type" binding:"required"`
|
Type string `form:"filter_type" yaml:"filter_type" binding:"required" validate:"oneof=replace regex substring"`
|
||||||
From string `form:"from" yaml:"from" binding:"required"`
|
From string `form:"from" yaml:"from" binding:"required"`
|
||||||
To string `form:"to" yaml:"to" binding:"required"`
|
To string `form:"to" yaml:"to" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,21 +75,18 @@
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link" id="substring-tab" data-bs-toggle="tab" data-bs-target="#substring-tab-pane" type="button" role="tab" aria-controls="contact-tab-pane" aria-selected="false">Substring</button>
|
<button class="nav-link" id="substring-tab" data-bs-toggle="tab" data-bs-target="#substring-tab-pane" type="button" role="tab" aria-controls="contact-tab-pane" aria-selected="false">Substring</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<button class="nav-link" id="lua-tab" data-bs-toggle="tab" data-bs-target="#lua-tab-pane" type="button" role="tab" aria-selected="false">Lua</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content" id="newFilterTabsContent">
|
<div class="tab-content" id="newFilterTabsContent">
|
||||||
<div class="tab-pane fade show active" id="replace-tab-pane" role="tabpanel" aria-labelledby="replace-tab" tabindex="0">
|
<div class="tab-pane fade show active" id="replace-tab-pane" role="tabpanel" aria-labelledby="replace-tab" tabindex="0">
|
||||||
|
|
||||||
<form action="/filter/create" method="post">
|
<form action="/filter/create" method="post">
|
||||||
<div class="mb-3 m-3 row">
|
<div class="mb-3 m-3 row">
|
||||||
<input type="hidden" name="query_id" value="{{ .Query.ID }}" >
|
<input type="hidden" name="filter_query_id" value="{{ .Query.ID }}" >
|
||||||
<input type="hidden" name="type" value="replace" >
|
<input type="hidden" name="filter_type" value="replace" >
|
||||||
|
|
||||||
<label for="nameInput" class="col-sm-2 col-form-label">Name:</label>
|
<label for="nameInput" class="col-sm-2 col-form-label">Name:</label>
|
||||||
<div class="col-sm-10 p-2">
|
<div class="col-sm-10 p-2">
|
||||||
<input type="text" class="form-control" name="name" id="nameInput" placeholder="Name">
|
<input type="text" class="form-control" name="filter_name" id="nameInput" placeholder="Name">
|
||||||
</div>
|
</div>
|
||||||
<label for="fromInput" class="col-sm-2 col-form-label">From:</label>
|
<label for="fromInput" class="col-sm-2 col-form-label">From:</label>
|
||||||
<div class="col-sm-10 p-2">
|
<div class="col-sm-10 p-2">
|
||||||
|
@ -106,12 +103,12 @@
|
||||||
<div class="tab-pane fade" id="regex-tab-pane" role="tabpanel" aria-labelledby="regex-tab" tabindex="0">
|
<div class="tab-pane fade" id="regex-tab-pane" role="tabpanel" aria-labelledby="regex-tab" tabindex="0">
|
||||||
<form action="/filter/create" method="post">
|
<form action="/filter/create" method="post">
|
||||||
<div class="mb-3 m-3 row">
|
<div class="mb-3 m-3 row">
|
||||||
<input type="hidden" name="query_id" value="{{ .Query.ID }}" >
|
<input type="hidden" name="filter_query_id" value="{{ .Query.ID }}" >
|
||||||
<input type="hidden" name="type" value="regex" >
|
<input type="hidden" name="filter_type" value="regex" >
|
||||||
|
|
||||||
<label for="nameInput" class="col-sm-2 col-form-label">Name:</label>
|
<label for="nameInput" class="col-sm-2 col-form-label">Name:</label>
|
||||||
<div class="col-sm-10 p-2">
|
<div class="col-sm-10 p-2">
|
||||||
<input type="text" class="form-control" name="name" id="nameInput" placeholder="Name">
|
<input type="text" class="form-control" name="filter_name" id="nameInput" placeholder="Name">
|
||||||
</div>
|
</div>
|
||||||
<label for="fromInput" class="col-sm-2 col-form-label">From:</label>
|
<label for="fromInput" class="col-sm-2 col-form-label">From:</label>
|
||||||
<div class="col-sm-10 p-2">
|
<div class="col-sm-10 p-2">
|
||||||
|
@ -128,13 +125,13 @@
|
||||||
<div class="tab-pane fade" id="substring-tab-pane" role="tabpanel" aria-labelledby="substring-tab" tabindex="0">
|
<div class="tab-pane fade" id="substring-tab-pane" role="tabpanel" aria-labelledby="substring-tab" tabindex="0">
|
||||||
<form action="/filter/create" method="post">
|
<form action="/filter/create" method="post">
|
||||||
<div class="mb-3 m-3 row">
|
<div class="mb-3 m-3 row">
|
||||||
<input type="hidden" name="query_id" value="{{ .Query.ID }}" >
|
<input type="hidden" name="filter_query_id" value="{{ .Query.ID }}" >
|
||||||
<input type="hidden" name="type" value="substring" >
|
<input type="hidden" name="filter_type" value="substring" >
|
||||||
<input type="hidden" name="to" value="-" >
|
<input type="hidden" name="to" value="-" >
|
||||||
|
|
||||||
<label for="nameInput" class="col-sm-2 col-form-label">Name:</label>
|
<label for="nameInput" class="col-sm-2 col-form-label">Name:</label>
|
||||||
<div class="col-sm-10 p-2">
|
<div class="col-sm-10 p-2">
|
||||||
<input type="text" class="form-control" name="name" id="nameInput" placeholder="Name">
|
<input type="text" class="form-control" name="filter_name" id="nameInput" placeholder="Name">
|
||||||
</div>
|
</div>
|
||||||
<label for="fromInput" class="col-sm-2 col-form-label">From:</label>
|
<label for="fromInput" class="col-sm-2 col-form-label">From:</label>
|
||||||
<div class="col-sm-10 p-2">
|
<div class="col-sm-10 p-2">
|
||||||
|
@ -144,27 +141,6 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="lua-tab-pane" role="tabpanel" aria-labelledby="lua-tab" tabindex="0">
|
|
||||||
<form action="/filter/create" method="post">
|
|
||||||
<div class="mb-3 m-3 row">
|
|
||||||
<input type="hidden" name="query_id" value="{{ .Query.ID }}" >
|
|
||||||
<input type="hidden" name="type" value="lua" >
|
|
||||||
<input type="hidden" name="to" value="-" >
|
|
||||||
|
|
||||||
<label for="nameInput" class="col-sm-2 col-form-label">Name:</label>
|
|
||||||
<div class="col-sm-10 p-2">
|
|
||||||
<input type="text" class="form-control" name="name" id="nameInput" placeholder="Name">
|
|
||||||
</div>
|
|
||||||
<label for="fromInput" class="col-sm-2 col-form-label">From:</label>
|
|
||||||
<select name="from" class="form-select"> <!-- TODO Lua stuff -->
|
|
||||||
<option>lua_func1</option>
|
|
||||||
<option>lua_func2</option>
|
|
||||||
<option>lua_func3</option>
|
|
||||||
</select>
|
|
||||||
<button class="btn btn-primary mt-4">Add Filter</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<form action="/watch/create" method="post">
|
<form action="/watch/create" method="post">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="name" class="form-label">Watch Name</label>
|
<label for="name" class="form-label">Watch Name</label>
|
||||||
<input name="name" type="text" class="form-control" id="name" placeholder="Watch">
|
<input name="watch_name" type="text" class="form-control" id="name" placeholder="Watch">
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="interval" class="form-label">Interval (seconds) - TODO </label>
|
<label for="interval" class="form-label">Interval (seconds) - TODO </label>
|
||||||
|
@ -10,5 +10,4 @@
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="btn btn-primary mb-3" value="Create">
|
<input type="submit" class="btn btn-primary mb-3" value="Create">
|
||||||
</form>
|
</form>
|
||||||
{{ . }}
|
|
||||||
{{end}}
|
{{end}}
|
|
@ -26,13 +26,16 @@
|
||||||
<div class="col h4 text-center" >{{ .Name }}</div>
|
<div class="col h4 text-center" >{{ .Name }}</div>
|
||||||
<div class="col h5 text-end"><a class="btn btn-success btn-sm" href="/query/edit/{{ .ID }}">Edit</a></div>
|
<div class="col h5 text-end"><a class="btn btn-success btn-sm" href="/query/edit/{{ .ID }}">Edit</a></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="text-center text-muted">
|
||||||
|
{{ .Query }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="/filter/create" method="post">
|
|
||||||
<input type="hidden" name="query_id" value="{{ .ID }}" >
|
<input type="hidden" name="query_id" value="{{ .ID }}" >
|
||||||
<input type="hidden" name="watch_id" value="{{ $.ID }}" >
|
<input type="hidden" name="w_id" value="{{ $.ID }}" >
|
||||||
<table class="table table-hover caption-top">
|
<table class="table table-hover caption-top">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{{ if .Filters }}
|
||||||
{{ range .Filters }}
|
{{ range .Filters }}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ .Name }}</td>
|
<td>{{ .Name }}</td>
|
||||||
|
@ -42,48 +45,35 @@
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
<tr>
|
<tr>
|
||||||
<td><input type="text" class="form-control" name="name" placeholder="Filter Name"></td>
|
<td class="text-center h3">No filters yet, click "Edit" to add</td>
|
||||||
<td>
|
|
||||||
<select class="form-control" id="type" name="type">
|
|
||||||
<option>Replace</option>
|
|
||||||
<option>Regex Replace</option>
|
|
||||||
<option>Substring</option>
|
|
||||||
<option>Lua</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
<td><input type="text" class="form-control" name="from" placeholder="From"></td>
|
|
||||||
<td><input type="text" class="form-control" name="to" placeholder="To"></td>
|
|
||||||
<td><button class="btn btn-primary">Add Filter</button></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
{{ end }}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="row">
|
|
||||||
<div class="col-2">{{ .Type }}</div>
|
|
||||||
<div class="col-8">{{ .Query }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<form action="/query/create" method="post">
|
<form action="/query/create" method="post">
|
||||||
<input type="hidden" name="url_id" value="{{ .ID }}" >
|
<input type="hidden" name="query_url_id" value="{{ .ID }}" >
|
||||||
<input type="hidden" name="watch_id" value="{{ $.ID }}" >
|
<input type="hidden" name="w_id" value="{{ $.ID }}" >
|
||||||
<table class="table table-hover caption-top">
|
<table class="table table-hover caption-top">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" class="form-control" name="name" placeholder="Query Name">
|
<input type="text" class="form-control" name="query_name" placeholder="Query Name">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select class="form-control" id="type" name="type">
|
<select class="form-control" id="query_type" name="query_type">
|
||||||
<option>CSS Selector</option>
|
<option value="css">CSS Selector</option>
|
||||||
<option>XPath</option>
|
<option value="xpath">XPath</option>
|
||||||
<option>Regex</option>
|
<option value="regex">Regex</option>
|
||||||
<option>JSON</option>
|
<option value="json">JSON</option>
|
||||||
<option>Lua</option>
|
<!-- additions/changes should also be added to Query.Type oneof validator -->
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -106,13 +96,13 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="/url/create" method="post">
|
<form action="/url/create" method="post">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<input type="text" class="form-control" name="name" id="urlName" placeholder="URL Name">
|
<input type="text" class="form-control" name="url_name" id="urlName" placeholder="URL Name">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<input type="url" class="form-control" name="url" id="url" placeholder="URL">
|
<input type="url" class="form-control" name="url" id="url" placeholder="URL">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="watch_id" value="{{ .ID }}" >
|
<input type="hidden" name="url_watch_id" value="{{ .ID }}" >
|
||||||
<input class="btn btn-primary" type="submit" value="Create URL">
|
<input class="btn btn-primary" type="submit" value="Create URL">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
10
util.go
10
util.go
|
@ -17,6 +17,16 @@ func bindAndValidateURL(url *URL, c *gin.Context) (map[string]string, error) {
|
||||||
return validate(err), err
|
return validate(err), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func bindAndValidateQuery(query *Query, c *gin.Context) (map[string]string, error) {
|
||||||
|
err := c.ShouldBind(query)
|
||||||
|
return validate(err), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindAndValidateFilter(filter *Filter, c *gin.Context) (map[string]string, error) {
|
||||||
|
err := c.ShouldBind(filter)
|
||||||
|
return validate(err), err
|
||||||
|
}
|
||||||
|
|
||||||
func prettyError(fieldError validator.FieldError) string {
|
func prettyError(fieldError validator.FieldError) string {
|
||||||
switch fieldError.Tag() {
|
switch fieldError.Tag() {
|
||||||
case "required":
|
case "required":
|
||||||
|
|
Loading…
Add table
Reference in a new issue