mirror of
https://github.com/Bornholm/formidable.git
synced 2025-07-22 05:21:33 +02:00
feat: aggregate defaults and values
- Output merged defaults and values - Add "check" command
This commit is contained in:
49
internal/command/check.go
Normal file
49
internal/command/check.go
Normal file
@ -0,0 +1,49 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/santhosh-tekuri/jsonschema/v5"
|
||||
_ "github.com/santhosh-tekuri/jsonschema/v5/httploader"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func Check() *cli.Command {
|
||||
flags := []cli.Flag{}
|
||||
|
||||
flags = append(flags, commonFlags()...)
|
||||
|
||||
return &cli.Command{
|
||||
Name: "check",
|
||||
Usage: "Check values with the given schema",
|
||||
Flags: flags,
|
||||
Action: func(ctx *cli.Context) error {
|
||||
schema, err := loadSchema(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load schema")
|
||||
}
|
||||
|
||||
_, values, err := loadData(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load data")
|
||||
}
|
||||
|
||||
if err := schema.Validate(values); err != nil {
|
||||
if _, ok := err.(*jsonschema.ValidationError); ok {
|
||||
fmt.Printf("%#v\n", err)
|
||||
|
||||
return errors.New("invalid values")
|
||||
}
|
||||
|
||||
return errors.Wrap(err, "could not validate values")
|
||||
}
|
||||
|
||||
if err := outputValues(ctx, values); err != nil {
|
||||
return errors.Wrap(err, "could not output updated values")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
87
internal/command/check_test.go
Normal file
87
internal/command/check_test.go
Normal file
@ -0,0 +1,87 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type ExpectFunc func(t *testing.T, cmd *cli.Command, err error)
|
||||
|
||||
type checkCommandTestCase struct {
|
||||
Name string
|
||||
SchemaFile string
|
||||
DefaultFile string
|
||||
ValuesFile string
|
||||
Expect ExpectFunc
|
||||
}
|
||||
|
||||
var checkCommandTestCases = []checkCommandTestCase{
|
||||
{
|
||||
Name: "ok",
|
||||
SchemaFile: "file://testdata/check/schema.json",
|
||||
DefaultFile: "file://testdata/check/defaults.json",
|
||||
ValuesFile: "file://testdata/check/values-ok.json",
|
||||
Expect: expectNoError,
|
||||
},
|
||||
{
|
||||
Name: "nok",
|
||||
SchemaFile: "file://testdata/check/schema.json",
|
||||
DefaultFile: "file://testdata/check/defaults.json",
|
||||
ValuesFile: "file://testdata/check/values-nok.json",
|
||||
Expect: expectError,
|
||||
},
|
||||
}
|
||||
|
||||
func TestCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range checkCommandTestCases {
|
||||
func(tc *checkCommandTestCase) {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
flags := flag.NewFlagSet("", flag.ExitOnError)
|
||||
cmd := Check()
|
||||
|
||||
for _, f := range cmd.Flags {
|
||||
if err := f.Apply(flags); err != nil {
|
||||
t.Fatal(errors.WithStack(err))
|
||||
}
|
||||
}
|
||||
|
||||
err := flags.Parse([]string{
|
||||
"check",
|
||||
"--schema", tc.SchemaFile,
|
||||
"--defaults", tc.DefaultFile,
|
||||
"--values", tc.ValuesFile,
|
||||
"--output", "null://local?format=json",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(errors.WithStack(err))
|
||||
}
|
||||
|
||||
app := cli.NewApp()
|
||||
ctx := cli.NewContext(app, flags, nil)
|
||||
|
||||
err = cmd.Run(ctx)
|
||||
|
||||
tc.Expect(t, cmd, err)
|
||||
})
|
||||
}(&tc)
|
||||
}
|
||||
}
|
||||
|
||||
func expectNoError(t *testing.T, cmd *cli.Command, err error) {
|
||||
if err != nil {
|
||||
t.Error(errors.Wrap(err, "the command result in an unexpected error"))
|
||||
}
|
||||
}
|
||||
|
||||
func expectError(t *testing.T, cmd *cli.Command, err error) {
|
||||
if err == nil {
|
||||
t.Error(errors.New("an error should have been returned"))
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
encjson "encoding/json"
|
||||
|
||||
@ -20,6 +21,7 @@ import (
|
||||
"forge.cadoles.com/wpetit/formidable/internal/data/updater/null"
|
||||
"forge.cadoles.com/wpetit/formidable/internal/data/updater/stdout"
|
||||
"forge.cadoles.com/wpetit/formidable/internal/def"
|
||||
"forge.cadoles.com/wpetit/formidable/internal/merge"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/santhosh-tekuri/jsonschema/v5"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -113,6 +115,46 @@ func loadDefaults(ctx *cli.Context) (interface{}, error) {
|
||||
return defaults, nil
|
||||
}
|
||||
|
||||
func loadData(ctx *cli.Context) (defaults interface{}, values interface{}, err error) {
|
||||
values, err = loadValues(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not load values")
|
||||
}
|
||||
|
||||
defaults, err = loadDefaults(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not load defaults")
|
||||
}
|
||||
|
||||
merged, err := getMatchingZeroValue(values)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if defaults != nil {
|
||||
if err := merge.Merge(&merged, defaults, values); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not merge values")
|
||||
}
|
||||
|
||||
values = merged
|
||||
}
|
||||
|
||||
return defaults, values, nil
|
||||
}
|
||||
|
||||
func getMatchingZeroValue(values interface{}) (interface{}, error) {
|
||||
valuesKind := reflect.TypeOf(values).Kind()
|
||||
|
||||
switch valuesKind {
|
||||
case reflect.Map:
|
||||
return make(map[string]interface{}, 0), nil
|
||||
case reflect.Slice:
|
||||
return make([]interface{}, 0), nil
|
||||
default:
|
||||
return nil, errors.Errorf("unexpected type '%T'", values)
|
||||
}
|
||||
}
|
||||
|
||||
func loadSchema(ctx *cli.Context) (*jsonschema.Schema, error) {
|
||||
schemaFlag := ctx.String("schema")
|
||||
|
||||
|
@ -55,14 +55,9 @@ func Edit() *cli.Command {
|
||||
return errors.Wrap(err, "could not load schema")
|
||||
}
|
||||
|
||||
values, err := loadValues(ctx)
|
||||
defaults, values, err := loadData(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load values")
|
||||
}
|
||||
|
||||
defaults, err := loadDefaults(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load defaults")
|
||||
return errors.Wrap(err, "could not load data")
|
||||
}
|
||||
|
||||
srvCtx, srvCancel := context.WithCancel(ctx.Context)
|
||||
|
@ -26,9 +26,9 @@ func Get() *cli.Command {
|
||||
return errors.Wrap(err, "could not load schema")
|
||||
}
|
||||
|
||||
values, err := loadValues(ctx)
|
||||
_, values, err := loadData(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load values")
|
||||
return errors.Wrap(err, "could not load data")
|
||||
}
|
||||
|
||||
if err := schema.Validate(values); err != nil {
|
||||
|
@ -8,5 +8,6 @@ func Root() []*cli.Command {
|
||||
Set(),
|
||||
Get(),
|
||||
Delete(),
|
||||
Check(),
|
||||
}
|
||||
}
|
||||
|
@ -33,9 +33,9 @@ func Set() *cli.Command {
|
||||
return errors.Wrap(err, "could not load schema")
|
||||
}
|
||||
|
||||
values, err := loadValues(ctx)
|
||||
_, values, err := loadData(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load values")
|
||||
return errors.Wrap(err, "could not load data")
|
||||
}
|
||||
|
||||
rawPointer := ctx.Args().Get(0)
|
||||
|
5
internal/command/testdata/check/defaults.json
vendored
Normal file
5
internal/command/testdata/check/defaults.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"foo": {
|
||||
"bar": "test"
|
||||
}
|
||||
}
|
17
internal/command/testdata/check/schema.json
vendored
Normal file
17
internal/command/testdata/check/schema.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bar": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["bar"]
|
||||
}
|
||||
},
|
||||
"required": ["foo"],
|
||||
"additionalProperties": true
|
||||
}
|
5
internal/command/testdata/check/values-nok.json
vendored
Normal file
5
internal/command/testdata/check/values-nok.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"foo": {
|
||||
"bar": false
|
||||
}
|
||||
}
|
3
internal/command/testdata/check/values-ok.json
vendored
Normal file
3
internal/command/testdata/check/values-ok.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"test": 1
|
||||
}
|
@ -33,7 +33,12 @@ func TestPointerDelete(t *testing.T) {
|
||||
{
|
||||
"nestedObject": {
|
||||
"foo": [
|
||||
"bar"
|
||||
"bar",
|
||||
{
|
||||
"prop1": {
|
||||
"subProp": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
@ -45,7 +50,8 @@ func TestPointerDelete(t *testing.T) {
|
||||
{
|
||||
"nestedObject": {
|
||||
"foo": [
|
||||
"bar"
|
||||
"bar",
|
||||
0
|
||||
]
|
||||
}
|
||||
}`,
|
||||
|
@ -14,7 +14,9 @@ import (
|
||||
type pointerSetTestCase struct {
|
||||
DocPath string
|
||||
Pointer string
|
||||
Force bool
|
||||
Value interface{}
|
||||
ExpectedError error
|
||||
ExpectedRawDocument string
|
||||
}
|
||||
|
||||
@ -37,7 +39,12 @@ func TestPointerSet(t *testing.T) {
|
||||
"nestedObject": {
|
||||
"foo": [
|
||||
"bar",
|
||||
"test"
|
||||
"test",
|
||||
{
|
||||
"prop1": {
|
||||
"subProp": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
@ -52,11 +59,44 @@ func TestPointerSet(t *testing.T) {
|
||||
"foo": [
|
||||
"bar",
|
||||
0,
|
||||
{
|
||||
"prop1": {
|
||||
"subProp": 1
|
||||
}
|
||||
},
|
||||
"baz"
|
||||
]
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
DocPath: "./testdata/set/nested.json",
|
||||
Pointer: "/nestedObject/foo/2/prop2",
|
||||
Value: "baz",
|
||||
Force: true,
|
||||
ExpectedRawDocument: `
|
||||
{
|
||||
"nestedObject": {
|
||||
"foo": [
|
||||
"bar",
|
||||
0,
|
||||
{
|
||||
"prop2": "baz",
|
||||
"prop1": {
|
||||
"subProp": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
DocPath: "./testdata/set/nested.json",
|
||||
Pointer: "/nestedObject/foo/2/prop2",
|
||||
Value: "baz",
|
||||
Force: false,
|
||||
ExpectedError: ErrNotFound,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
@ -77,8 +117,19 @@ func TestPointerSet(t *testing.T) {
|
||||
|
||||
pointer := New(tc.Pointer)
|
||||
|
||||
updatedDoc, err := pointer.Set(baseDoc, tc.Value)
|
||||
if err != nil {
|
||||
var updatedDoc interface{}
|
||||
|
||||
if tc.Force {
|
||||
updatedDoc, err = pointer.Force(baseDoc, tc.Value)
|
||||
} else {
|
||||
updatedDoc, err = pointer.Set(baseDoc, tc.Value)
|
||||
}
|
||||
|
||||
if tc.ExpectedError != nil && !errors.Is(err, tc.ExpectedError) {
|
||||
t.Fatalf("Expected error '%v', got '%v'", tc.ExpectedError, errors.Cause(err))
|
||||
}
|
||||
|
||||
if tc.ExpectedError == nil && err != nil {
|
||||
t.Fatal(errors.WithStack(err))
|
||||
}
|
||||
|
||||
@ -89,12 +140,20 @@ func TestPointerSet(t *testing.T) {
|
||||
|
||||
var expectedDoc interface{}
|
||||
|
||||
if tc.ExpectedRawDocument == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(tc.ExpectedRawDocument), &expectedDoc); err != nil {
|
||||
t.Fatal(errors.WithStack(err))
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expectedDoc, updatedDoc) {
|
||||
t.Errorf("Set pointer '%s' -> '%v': expected document '%s', got '%s'", tc.Pointer, tc.Value, strings.TrimSpace(tc.ExpectedRawDocument), rawDoc)
|
||||
command := "Set"
|
||||
if tc.Force {
|
||||
command = "Force"
|
||||
}
|
||||
t.Errorf("%s pointer '%s' -> '%v': expected document '%s', got '%s'", command, tc.Pointer, tc.Value, strings.TrimSpace(tc.ExpectedRawDocument), rawDoc)
|
||||
}
|
||||
})
|
||||
}(i, tc)
|
||||
|
@ -2,7 +2,12 @@
|
||||
"nestedObject": {
|
||||
"foo": [
|
||||
"bar",
|
||||
0
|
||||
0,
|
||||
{
|
||||
"prop1": {
|
||||
"subProp": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
91
internal/merge/merge.go
Normal file
91
internal/merge/merge.go
Normal file
@ -0,0 +1,91 @@
|
||||
package merge
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNonPointerDst = errors.New("dst is not a pointer")
|
||||
ErrUnsupportedMerge = errors.New("unsupported merge")
|
||||
ErrUnexpectedFailedCast = errors.New("unexpected failed cast")
|
||||
)
|
||||
|
||||
func Merge(dst interface{}, sources ...interface{}) error {
|
||||
if reflect.TypeOf(dst).Kind() != reflect.Ptr {
|
||||
return errors.WithStack(ErrNonPointerDst)
|
||||
}
|
||||
|
||||
dstPointedKind := reflect.Indirect(reflect.ValueOf(dst)).Elem().Kind()
|
||||
|
||||
for _, src := range sources {
|
||||
srcKind := reflect.ValueOf(src).Kind()
|
||||
|
||||
switch dstPointedKind {
|
||||
case reflect.Map:
|
||||
if srcKind != dstPointedKind {
|
||||
return errors.WithStack(unsupportedMergeError(dstPointedKind, srcKind))
|
||||
}
|
||||
|
||||
if err := mergeMaps(dst, src); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
case reflect.Slice:
|
||||
if srcKind != dstPointedKind {
|
||||
return errors.WithStack(unsupportedMergeError(dstPointedKind, srcKind))
|
||||
}
|
||||
|
||||
if err := mergeSlices(dst, src); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
default:
|
||||
return errors.WithStack(unsupportedMergeError(dstPointedKind, srcKind))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func unsupportedMergeError(dstKind reflect.Kind, defaultsKind reflect.Kind) error {
|
||||
return errors.Wrapf(ErrUnsupportedMerge, "could not merge '%s' with defaults '%s'", dstKind, defaultsKind)
|
||||
}
|
||||
|
||||
func mergeMaps(dst interface{}, defaults interface{}) error {
|
||||
dstMap, ok := reflect.Indirect(reflect.ValueOf(dst)).Elem().Interface().(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.WithStack(ErrUnexpectedFailedCast)
|
||||
}
|
||||
|
||||
defaultsMap, ok := defaults.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.WithStack(ErrUnexpectedFailedCast)
|
||||
}
|
||||
|
||||
if err := mergo.Merge(&dstMap, defaultsMap, mergo.WithOverride); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergeSlices(dst interface{}, defaults interface{}) error {
|
||||
dstSlice, ok := reflect.Indirect(reflect.ValueOf(dst)).Elem().Interface().([]interface{})
|
||||
if !ok {
|
||||
return errors.WithStack(ErrUnexpectedFailedCast)
|
||||
}
|
||||
|
||||
defaultsSlice, ok := defaults.([]interface{})
|
||||
if !ok {
|
||||
return errors.WithStack(ErrUnexpectedFailedCast)
|
||||
}
|
||||
|
||||
if err := mergo.Merge(&dstSlice, defaultsSlice, mergo.WithOverride); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
69
internal/merge/merge_test.go
Normal file
69
internal/merge/merge_test.go
Normal file
@ -0,0 +1,69 @@
|
||||
package merge
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
type mergeTestCase struct {
|
||||
Name string
|
||||
Dst interface{}
|
||||
Dflts interface{}
|
||||
ExpectedResult interface{}
|
||||
ShouldFail bool
|
||||
}
|
||||
|
||||
var mergeTestCases = []mergeTestCase{
|
||||
{
|
||||
Name: "simple-maps",
|
||||
Dst: map[string]interface{}{
|
||||
"foo": map[string]interface{}{
|
||||
"bar": "test",
|
||||
},
|
||||
},
|
||||
Dflts: map[string]interface{}{
|
||||
"other": true,
|
||||
"foo": map[string]interface{}{
|
||||
"bar": true,
|
||||
"baz": 1,
|
||||
},
|
||||
},
|
||||
ExpectedResult: map[string]interface{}{
|
||||
"foo": map[string]interface{}{
|
||||
"bar": "test",
|
||||
"baz": 1,
|
||||
},
|
||||
"other": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "string-slices",
|
||||
Dst: []string{"foo"},
|
||||
Dflts: []string{"bar"},
|
||||
ExpectedResult: []string{"foo"},
|
||||
},
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range mergeTestCases {
|
||||
func(tc *mergeTestCase) {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := Merge(&tc.Dst, tc.Dflts)
|
||||
|
||||
if tc.ShouldFail && err == nil {
|
||||
t.Error("merge should have failed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tc.Dst, tc.ExpectedResult) {
|
||||
t.Errorf("tc.Dst should have been the same as tc.ExpectedResult. Expected: %s, got %s", spew.Sdump(tc.ExpectedResult), spew.Sdump(tc.Dst))
|
||||
}
|
||||
})
|
||||
}(&tc)
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ func (s *Server) handleFormReq(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
} else {
|
||||
values, err = handleForm(r.Form, s.schema, values)
|
||||
values, err = handleForm(r.Form, s.schema, s.values)
|
||||
if err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
@ -57,7 +57,7 @@ func (s *Server) handleFormReq(w http.ResponseWriter, r *http.Request) {
|
||||
data.Values = values
|
||||
}
|
||||
|
||||
if err := s.schema.Validate(data.Values); err != nil {
|
||||
if err := s.schema.Validate(values); err != nil {
|
||||
validationErr, ok := err.(*jsonschema.ValidationError)
|
||||
if !ok {
|
||||
panic(errors.Wrap(err, "could not validate values"))
|
||||
@ -68,7 +68,7 @@ func (s *Server) handleFormReq(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if data.Error == nil {
|
||||
if s.onUpdate != nil {
|
||||
if err := s.onUpdate(data.Values); err != nil {
|
||||
if err := s.onUpdate(values); err != nil {
|
||||
panic(errors.Wrap(err, "could not update values"))
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{ define "form_input_array" }}
|
||||
{{ $root := . }}
|
||||
{{ $fullProperty := getFullProperty .Parent .Property }}
|
||||
{{ $values := getValue .Defaults .Values $fullProperty }}
|
||||
{{ $values := getValue .Values $fullProperty }}
|
||||
<table width="100%">
|
||||
<tbody>
|
||||
{{ range $index, $value := $values }}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{{define "form_input_boolean"}}
|
||||
{{ $fullProperty := getFullProperty .Parent .Property }}
|
||||
{{ $checked := getValue .Defaults .Values $fullProperty }}
|
||||
{{ $checked := getValue .Values $fullProperty }}
|
||||
<label for="yes:{{ $fullProperty }}" class="inline-flex items-center mt-3">
|
||||
<input type="radio"
|
||||
class="h-5 w-5 text-gray-600"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{{define "form_input_number"}}
|
||||
{{ $fullProperty := getFullProperty .Parent .Property }}
|
||||
{{ $value := getValue .Defaults .Values $fullProperty }}
|
||||
{{ $value := getValue .Values $fullProperty }}
|
||||
<input type="number"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
name="num:{{ $fullProperty }}"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{{define "form_input_string"}}
|
||||
{{ $fullProperty := getFullProperty .Parent .Property }}
|
||||
{{ $value := getValue .Defaults .Values $fullProperty }}
|
||||
{{ $value := getValue .Values $fullProperty }}
|
||||
{{/* <input type="text"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
name="{{ $fullProperty }}"
|
||||
|
@ -162,11 +162,7 @@ func customHelpers(tpl *template.Template) template.FuncMap {
|
||||
|
||||
return fullProperty
|
||||
},
|
||||
"getValue": func(defaults, values interface{}, path string) (interface{}, error) {
|
||||
if defaults == nil {
|
||||
defaults = make(map[string]interface{})
|
||||
}
|
||||
|
||||
"getValue": func(values interface{}, path string) (interface{}, error) {
|
||||
if values == nil {
|
||||
values = make(map[string]interface{})
|
||||
}
|
||||
@ -178,13 +174,6 @@ func customHelpers(tpl *template.Template) template.FuncMap {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if errors.Is(err, jsonpointer.ErrNotFound) {
|
||||
val, err = pointer.Get(defaults)
|
||||
if err != nil && !errors.Is(err, jsonpointer.ErrNotFound) {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
return val, nil
|
||||
},
|
||||
"getItemSchema": func(arraySchema *jsonschema.Schema) (*jsonschema.Schema, error) {
|
||||
|
Reference in New Issue
Block a user