From 526a76dd714240449c1233231fe4e9c2f357112b Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Thu, 26 Mar 2020 19:58:56 +0100 Subject: [PATCH] Add output formatter for record values --- compose/service/record.go | 8 ++- compose/service/values/formatter.go | 92 +++++++++++++++++++++++++++++ compose/service/values/sanitizer.go | 6 +- 3 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 compose/service/values/formatter.go diff --git a/compose/service/record.go b/compose/service/record.go index 9d47e5aeb..1979f39f0 100644 --- a/compose/service/record.go +++ b/compose/service/record.go @@ -40,10 +40,15 @@ type ( moduleRepo repository.ModuleRepository nsRepo repository.NamespaceRepository + formatter recordValuesFormatter sanitizer recordValuesSanitizer validator recordValuesValidator } + recordValuesFormatter interface { + Run(*types.Module, types.RecordValueSet) types.RecordValueSet + } + recordValuesSanitizer interface { Run(*types.Module, types.RecordValueSet) types.RecordValueSet } @@ -176,6 +181,7 @@ func (svc record) With(ctx context.Context) RecordService { moduleRepo: repository.Module(ctx, db), nsRepo: repository.Namespace(ctx, db), + formatter: values.Formatter(), sanitizer: values.Sanitizer(), validator: validator, } @@ -1022,7 +1028,7 @@ func (svc record) preloadValues(m *types.Module, rr ...*types.Record) error { return err } else { return types.RecordSet(rr).Walk(func(r *types.Record) error { - r.Values = rvs.FilterByRecordID(r.ID) + r.Values = svc.formatter.Run(m, rvs.FilterByRecordID(r.ID)) return nil }) } diff --git a/compose/service/values/formatter.go b/compose/service/values/formatter.go new file mode 100644 index 000000000..ed181732e --- /dev/null +++ b/compose/service/values/formatter.go @@ -0,0 +1,92 @@ +package values + +import ( + "github.com/cortezaproject/corteza-server/compose/types" + "strings" + "time" +) + +type ( + formatter struct{} +) + +// Formatter initializes formatter +// +// Not really needed, following pattern in the package +func Formatter() *formatter { + return &formatter{} +} + +func (f formatter) Run(m *types.Module, vv types.RecordValueSet) types.RecordValueSet { + for _, v := range vv { + fld := m.Fields.FindByName(v.Name) + if fld == nil { + // Unknown field, + // if it is not handled before, + // formatter does not care about it + continue + } + + // Per field type validators + switch strings.ToLower(fld.Kind) { + case "bool": + v = f.fBool(v) + case "datetime": + v = f.fDatetime(v, fld) + } + } + + return vv +} + +// Boolean values are outputed as "1" (true) and "" (false) +func (formatter) fBool(v *types.RecordValue) *types.RecordValue { + if v.Value != strBoolTrue { + v.Value = "" + } + + return v +} + +func (formatter) fDatetime(v *types.RecordValue, f *types.ModuleField) *types.RecordValue { + var ( + // database formats + dbFormats []string + + // output format + internalFormat string + ) + + if f.Options.Bool("onlyDate") { + internalFormat = datetimeInternalFormatDate + dbFormats = []string{ + datetimeInternalFormatDate, + } + } else if f.Options.Bool("onlyTime") { + internalFormat = datetimeIntenralFormatTime + dbFormats = []string{ + datetimeIntenralFormatTime, + "15:04", + } + } else { + internalFormat = datetimeInternalFormatFull + // date & time + dbFormats = []string{ + datetimeInternalFormatFull, + "2006-01-02 15:04:05", + "2006-01-02 15:04", + } + } + + for _, format := range dbFormats { + parsed, err := time.Parse(format, v.Value) + if err == nil { + v.Value = parsed.UTC().Format(internalFormat) + return v + } + } + + v.Value = "" + return v + +} diff --git a/compose/service/values/sanitizer.go b/compose/service/values/sanitizer.go index 67e9415ab..c98ba16c4 100644 --- a/compose/service/values/sanitizer.go +++ b/compose/service/values/sanitizer.go @@ -138,7 +138,7 @@ func (sanitizer) sDatetime(v *types.RecordValue, f *types.ModuleField, m *types. "02 Jan 06", "Monday, 02-Jan-06", "Mon, 02 Jan 2006", - "2019/_1/_2", + "2006/_1/_2", } } else if f.Options.Bool("onlyTime") { internalFormat = datetimeIntenralFormatTime @@ -166,8 +166,8 @@ func (sanitizer) sDatetime(v *types.RecordValue, f *types.ModuleField, m *types. time.RubyDate, time.UnixDate, time.ANSIC, - "2019/_1/_2 15:04:05", - "2019/_1/_2 15:04", + "2006/_1/_2 15:04:05", + "2006/_1/_2 15:04", } // if string looks like a RFC 3330 (ISO 8601), see if we need to suffix it with Z