This commit is contained in:
Daniel Ponte 2024-11-25 09:44:12 -05:00
parent 638b4df0e7
commit 53ccf1715b
5 changed files with 90 additions and 6 deletions

View file

@ -24,7 +24,7 @@ func makeExportRequest(ej *xport.ExportJob, url string) *http.Request {
perr(body.WriteField("systemID", strconv.Itoa(int(ej.SystemID)))) perr(body.WriteField("systemID", strconv.Itoa(int(ej.SystemID))))
perr(body.WriteField("talkgroups", "3,4")) perr(body.WriteField("talkgroups", "[197:3,4]"))
w, err := body.CreateFormFile("template", ej.TemplateFileName) w, err := body.CreateFormFile("template", ej.TemplateFileName)
perr(err) perr(err)

View file

@ -1,6 +1,7 @@
package forms package forms
import ( import (
"encoding"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -104,6 +105,7 @@ func (o *options) parseDuration(s string) (v time.Duration, set bool, err error)
var typeOfByteSlice = reflect.TypeOf([]byte(nil)) var typeOfByteSlice = reflect.TypeOf([]byte(nil))
func (o *options) unmIterFields(r *http.Request, destStruct reflect.Value) error { func (o *options) unmIterFields(r *http.Request, destStruct reflect.Value) error {
textUnmarshaler := reflect.TypeFor[encoding.TextUnmarshaler]()
structType := destStruct.Type() structType := destStruct.Type()
for i := 0; i < destStruct.NumField(); i++ { for i := 0; i < destStruct.NumField(); i++ {
destFieldVal := destStruct.Field(i) destFieldVal := destStruct.Field(i)
@ -175,6 +177,8 @@ func (o *options) unmIterFields(r *http.Request, destStruct reflect.Value) error
ff := r.Form.Get(formField) ff := r.Form.Get(formField)
destFieldType := destFieldVal.Type()
switch v := destFieldIntf.(type) { switch v := destFieldIntf.(type) {
case string, *string: case string, *string:
setVal(destFieldVal, ff != "" || o.acceptBlank, ff) setVal(destFieldVal, ff != "" || o.acceptBlank, ff)
@ -223,11 +227,34 @@ func (o *options) unmIterFields(r *http.Request, destStruct reflect.Value) error
} }
destFieldVal.Set(reflect.ValueOf(ar)) destFieldVal.Set(reflect.ValueOf(ar))
default: default:
dvt := destFieldVal.Type() if destFieldType.Kind() == reflect.Slice && reflect.PointerTo(destFieldType.Elem()).Implements(textUnmarshaler) {
if dvt.Kind() == reflect.Ptr { val := strings.Trim(ff, "[]")
dvt = dvt.Elem() if val == "" && o.acceptBlank {
continue
}
vals := strings.Split(val, ",")
elemType := destFieldType.Elem()
sliceVal := reflect.MakeSlice(destFieldType, len(vals), len(vals))
for i, tElem := range vals {
newElem := reflect.New(elemType)
tum := newElem.Interface().(encoding.TextUnmarshaler)
err := tum.UnmarshalText([]byte(tElem))
if err != nil {
return err
}
sliceVal.Index(i).Set(newElem.Elem())
}
destFieldVal.Set(sliceVal)
continue
} }
if reflect.ValueOf(ff).CanConvert(dvt) { if destFieldType.Kind() == reflect.Ptr {
destFieldType = destFieldType.Elem()
}
if reflect.ValueOf(ff).CanConvert(destFieldType) {
setVal(destFieldVal, ff != "" || o.acceptBlank, ff) setVal(destFieldVal, ff != "" || o.acceptBlank, ff)
} else { } else {
panic(fmt.Errorf("unsupported type %T", v)) panic(fmt.Errorf("unsupported type %T", v))

View file

@ -137,7 +137,7 @@ var (
TalkgroupFilter: filter.TalkgroupFilter{ TalkgroupFilter: filter.TalkgroupFilter{
Talkgroups: []talkgroups.ID{ Talkgroups: []talkgroups.ID{
talkgroups.TG(197, 3), talkgroups.TG(197, 3),
talkgroups.TG(197, 4), talkgroups.TG(0, 4),
}, },
}, },
} }

View file

@ -1,8 +1,12 @@
package talkgroups package talkgroups
import ( import (
"encoding"
"encoding/json"
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings"
"dynatron.me/x/stillbox/pkg/database" "dynatron.me/x/stillbox/pkg/database"
) )
@ -32,6 +36,54 @@ type ID struct {
Talkgroup uint32 `json:"tg"` Talkgroup uint32 `json:"tg"`
} }
var _ encoding.TextUnmarshaler = (*ID)(nil)
var ErrBadTG = errors.New("bad talkgroup format")
func (tid *ID) UnmarshalJSON(j []byte) error {
// this is a dirty hack since we cannot implement both TextUnmarshaler
// and json.Unmarshaler at the same time. sigh.
v := &struct{
System uint32 `json:"sys"`
Talkgroup uint32 `json:"tg"`
}{}
if tid != nil {
v.System, v.Talkgroup = tid.System, tid.Talkgroup
}
err := json.Unmarshal(j, v)
if err != nil {
return err
}
tid.System, tid.Talkgroup = v.System, v.Talkgroup
return nil
}
func (tid *ID) UnmarshalText(txt []byte) error {
ar := strings.Split(string(txt), ":")
switch len(ar) {
case 2:
sys, err := strconv.Atoi(ar[0])
if err != nil {
return err
}
tid.System = uint32(sys)
fallthrough
case 1:
tg, err := strconv.Atoi(ar[len(ar)-1])
if err != nil {
return err
}
tid.Talkgroup = uint32(tg)
default:
return ErrBadTG
}
return nil
}
type IDs []ID type IDs []ID
func (t IDs) Tuples() database.TGTuples { func (t IDs) Tuples() database.TGTuples {

View file

@ -34,6 +34,11 @@ func (ej *ExportJob) Export(ctx context.Context, w io.Writer) error {
return err return err
} }
} else { } else {
for i, v := range ej.TalkgroupFilter.Talkgroups {
if v.System == 0 {
ej.TalkgroupFilter.Talkgroups[i].System = uint32(ej.SystemID)
}
}
ids, err := ej.TalkgroupFilter.TGs(ctx) ids, err := ej.TalkgroupFilter.TGs(ctx)
if err != nil { if err != nil {
return err return err