Allow default values
This commit is contained in:
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`;
|
||||
@@ -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 (?)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user