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("talkgroups", "3,4"))
perr(body.WriteField("talkgroups", "[197:3,4]"))
w, err := body.CreateFormFile("template", ej.TemplateFileName)
perr(err)

View file

@ -1,6 +1,7 @@
package forms
import (
"encoding"
"encoding/json"
"fmt"
"io"
@ -104,6 +105,7 @@ func (o *options) parseDuration(s string) (v time.Duration, set bool, err error)
var typeOfByteSlice = reflect.TypeOf([]byte(nil))
func (o *options) unmIterFields(r *http.Request, destStruct reflect.Value) error {
textUnmarshaler := reflect.TypeFor[encoding.TextUnmarshaler]()
structType := destStruct.Type()
for i := 0; i < destStruct.NumField(); 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)
destFieldType := destFieldVal.Type()
switch v := destFieldIntf.(type) {
case string, *string:
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))
default:
dvt := destFieldVal.Type()
if dvt.Kind() == reflect.Ptr {
dvt = dvt.Elem()
if destFieldType.Kind() == reflect.Slice && reflect.PointerTo(destFieldType.Elem()).Implements(textUnmarshaler) {
val := strings.Trim(ff, "[]")
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)
} else {
panic(fmt.Errorf("unsupported type %T", v))

View file

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

View file

@ -1,8 +1,12 @@
package talkgroups
import (
"encoding"
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
"dynatron.me/x/stillbox/pkg/database"
)
@ -32,6 +36,54 @@ type ID struct {
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
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
}
} 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)
if err != nil {
return err