3
0

Allow default values

This commit is contained in:
Tomaž Jerman
2019-09-12 13:12:09 +02:00
parent dacc855944
commit c8e04f1919
7 changed files with 134 additions and 8 deletions
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
ALTER TABLE `compose_module_field`
ADD `default_value` JSON DEFAULT NULL COMMENT 'Default value as a record value set.'
AFTER `options`;
+1 -1
View File
@@ -230,7 +230,7 @@ func (r module) FindFields(moduleIDs ...uint64) (ff types.ModuleFieldSet, err er
query := `SELECT id, rel_module, place,
kind, name, label, options,
is_private, is_required, is_visible, is_multi,
is_private, is_required, is_visible, is_multi, default_value,
created_at, updated_at, deleted_at
FROM %s
WHERE rel_module IN (?)
+24
View File
@@ -305,6 +305,10 @@ func (svc record) Create(mod *types.Record) (r *types.Record, err error) {
CreatedAt: time.Now(),
}
if err = svc.setDefaultValues(m, mod); err != nil {
return
}
if err = svc.copyChanges(m, mod, r); err != nil {
return
}
@@ -463,6 +467,26 @@ func (svc record) copyChanges(m *types.Module, mod, r *types.Record) (err error)
return err
}
func (svc record) setDefaultValues(module *types.Module, mod *types.Record) (err error) {
err = module.Fields.Walk(func(field *types.ModuleField) error {
if field.DefaultValue == nil {
return nil
}
return field.DefaultValue.Walk(func(value *types.RecordValue) error {
if !mod.Values.Has(value.Name, value.Place) {
mod.Values = mod.Values.Set(value)
}
return nil
})
return nil
})
mod.Values, err = svc.sanitizeValues(module, mod.Values)
return err
}
// Validates and filters record values
func (svc record) sanitizeValues(module *types.Module, values types.RecordValueSet) (out types.RecordValueSet, err error) {
// Make sure there are no multi values in a non-multi value fields
+7 -6
View File
@@ -17,16 +17,17 @@ type (
ModuleID uint64 `json:"moduleID,string" db:"rel_module"`
Place int `json:"-" db:"place"`
Kind string `json:"kind" db:"kind"`
Name string `json:"name" db:"name"`
Kind string `json:"kind" db:"kind"`
Name string `json:"name" db:"name"`
Label string `json:"label" db:"label"`
Options types.JSONText `json:"options" db:"options"`
Private bool `json:"isPrivate" db:"is_private"`
Required bool `json:"isRequired" db:"is_required"`
Visible bool `json:"isVisible" db:"is_visible"`
Multi bool `json:"isMulti" db:"is_multi"`
Private bool `json:"isPrivate" db:"is_private"`
Required bool `json:"isRequired" db:"is_required"`
Visible bool `json:"isVisible" db:"is_visible"`
Multi bool `json:"isMulti" db:"is_multi"`
DefaultValue RecordValueSet `json:"defaultValue" db:"default_value"`
CreatedAt time.Time `db:"created_at" json:"createdAt,omitempty"`
UpdatedAt *time.Time `db:"updated_at" json:"updatedAt,omitempty"`
+56
View File
@@ -1,7 +1,11 @@
package types
import (
"database/sql/driver"
"encoding/json"
"time"
"github.com/pkg/errors"
)
type (
@@ -35,3 +39,55 @@ func (set RecordValueSet) FilterByRecordID(recordID uint64) (vv RecordValueSet)
return
}
// Set updates existing value or creates a new one
func (set RecordValueSet) Set(v *RecordValue) RecordValueSet {
for i := range set {
if set[i].Name != v.Name {
continue
}
if set[i].Place != v.Place {
continue
}
// Update existing entry
return append(append(set[:i], v), set[i+1:]...)
}
// Append new value
return append(set, v)
}
// Has value set?
func (set RecordValueSet) Has(name string, place uint) bool {
for i := range set {
if set[i].Name != name {
continue
}
if set[i].Place != place {
continue
}
return true
}
return false
}
func (meta *RecordValueSet) Scan(value interface{}) error {
//lint:ignore S1034 This typecast is intentional, we need to get []byte out of a []uint8
switch value.(type) {
case nil:
*meta = RecordValueSet{}
case []uint8:
if err := json.Unmarshal(value.([]byte), meta); err != nil {
return errors.Wrapf(err, "Can not scan '%v' into RecordValueSet", value)
}
}
return nil
}
func (meta RecordValueSet) Value() (driver.Value, error) {
return json.Marshal(meta)
}
+42
View File
@@ -0,0 +1,42 @@
package types
import (
"reflect"
"testing"
)
func TestRecordValueSet_Set(t *testing.T) {
tests := []struct {
name string
set RecordValueSet
new RecordValue
want RecordValueSet
}{
{
name: "simple add on empty",
set: RecordValueSet{},
new: RecordValue{Name: "n", Value: "v"},
want: RecordValueSet{{Name: "n", Value: "v"}},
},
{
name: "update existing",
set: RecordValueSet{{Name: "a", Value: "b"}, {Name: "n", Value: "v"}, {Name: "x", Value: "y"}},
new: RecordValue{Name: "n", Value: "v2"},
want: RecordValueSet{{Name: "a", Value: "b"}, {Name: "n", Value: "v2"}, {Name: "x", Value: "y"}},
},
{
name: "multi-value",
set: RecordValueSet{{Name: "n", Value: "v"}},
new: RecordValue{Name: "n", Value: "v", Place: 1},
want: RecordValueSet{{Name: "n", Value: "v", Place: 0}, {Name: "n", Value: "v", Place: 1}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.set.Set(&tt.new); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Set() = %v, want %v", got, tt.want)
}
})
}
}