From ca57ccd0aa99939433624e14d81884b88ff2a8ef Mon Sep 17 00:00:00 2001 From: Eric Newcomer Date: Wed, 5 Jul 2017 16:10:06 -0500 Subject: [PATCH 1/6] Use arrays for localization, include category_original where appropriate --- flows/actions/save_flow_result.go | 9 +++++++-- flows/definition/legacy.go | 30 ++++++++++++++++-------------- flows/definition/localization.go | 17 ++++++++++++++--- flows/engine/engine.go | 12 +++++++++--- flows/events/save_flow_result.go | 13 +++++++------ flows/interfaces.go | 2 ++ flows/results.go | 28 ++++++++++++++++------------ flows/routers/switch.go | 4 +++- flows/runs/run.go | 7 +++++++ 9 files changed, 81 insertions(+), 41 deletions(-) diff --git a/flows/actions/save_flow_result.go b/flows/actions/save_flow_result.go index d8931db9c..217737e0d 100644 --- a/flows/actions/save_flow_result.go +++ b/flows/actions/save_flow_result.go @@ -61,11 +61,16 @@ func (a *SaveFlowResultAction) Execute(run flows.FlowRun, step flows.Step) error } // log our event - event := events.NewSaveFlowResult(step.NodeUUID(), a.ResultName, value, category) + var categoryOriginal string + if template != a.Category { + categoryOriginal = a.Category + } + + event := events.NewSaveFlowResult(step.NodeUUID(), a.ResultName, value, category, categoryOriginal) run.AddEvent(step, event) // and save our result - run.Results().Save(step.NodeUUID(), a.ResultName, value, a.Category, *event.CreatedOn()) + run.Results().Save(step.NodeUUID(), a.ResultName, value, a.Category, categoryOriginal, *event.CreatedOn()) return nil } diff --git a/flows/definition/legacy.go b/flows/definition/legacy.go index 37b1f8e5e..8a5c012eb 100644 --- a/flows/definition/legacy.go +++ b/flows/definition/legacy.go @@ -14,7 +14,8 @@ import ( "github.com/satori/go.uuid" ) -type legacyFlow struct { +// LegacyFlow imports an old-world flow so it can be exported anew +type LegacyFlow struct { flow envelope legacyFlowEnvelope } @@ -130,8 +131,8 @@ type stringTest struct { type localizations map[utils.Language]flows.Action // ReadLegacyFlows reads in legacy formatted flows -func ReadLegacyFlows(data json.RawMessage) ([]legacyFlow, error) { - var flows []legacyFlow +func ReadLegacyFlows(data json.RawMessage) ([]LegacyFlow, error) { + var flows []LegacyFlow err := json.Unmarshal(data, &flows) return flows, err } @@ -142,7 +143,7 @@ func addTranslationMap(baseLanguage utils.Language, translations *flowTranslatio for language, translation := range mapped { items := itemTranslations{} expression, _ := excellent.TranslateTemplate(translation) - items[key] = expression + items[key] = []string{expression} if language != baseLanguage { addTranslation(baseLanguage, translations, language, uuid, items) } @@ -253,17 +254,16 @@ func createAction(baseLanguage utils.Language, a legacyAction, fieldMap map[stri addTranslationMap(baseLanguage, translations, msg, flows.UUID(a.UUID), "text") // TODO translations for each attachment? - - text_expression, _ := excellent.TranslateTemplate(msg[baseLanguage]) - attachment_expression, _ := excellent.TranslateTemplate(media[baseLanguage]) + textExpression, _ := excellent.TranslateTemplate(msg[baseLanguage]) + attachmentExpression, _ := excellent.TranslateTemplate(media[baseLanguage]) attachments := []string{} - if attachment_expression != "" { - attachments = append(attachments, attachment_expression) + if attachmentExpression != "" { + attachments = append(attachments, attachmentExpression) } return &actions.ReplyAction{ - Text: text_expression, + Text: textExpression, Attachments: attachments, BaseAction: actions.BaseAction{ UUID: a.UUID, @@ -419,7 +419,7 @@ func parseRules(baseLanguage utils.Language, r legacyRuleSet, translations *flow exits := make([]flows.Exit, len(categoryMap)) exitMap := make(map[string]flows.Exit) for k, category := range categoryMap { - addTranslationMap(baseLanguage, translations, category.translations, flows.UUID(category.uuid), "label") + addTranslationMap(baseLanguage, translations, category.translations, flows.UUID(category.uuid), "name") exits[category.order] = &exit{ name: k, @@ -559,13 +559,14 @@ func createActionNode(lang utils.Language, a legacyActionSet, fieldMap map[strin node.exits = make([]flows.Exit, 1) node.exits[0] = &exit{ destination: a.Destination, - uuid: flows.ExitUUID(a.UUID), + uuid: flows.ExitUUID(uuid.NewV4().String()), } return node } -func (f *legacyFlow) UnmarshalJSON(data []byte) error { +// UnmarshalJSON imports our JSON into a LegacyFlow object +func (f *LegacyFlow) UnmarshalJSON(data []byte) error { var envelope legacyFlowEnvelope var err error @@ -611,7 +612,8 @@ func (f *legacyFlow) UnmarshalJSON(data []byte) error { return err } -func (f *legacyFlow) MarshalJSON() ([]byte, error) { +// MarshalJSON sends turns our legacy flow into bytes +func (f *LegacyFlow) MarshalJSON() ([]byte, error) { var fe = flowEnvelope{} fe.Name = f.name diff --git a/flows/definition/localization.go b/flows/definition/localization.go index 8bebb63b7..acd1de92b 100644 --- a/flows/definition/localization.go +++ b/flows/definition/localization.go @@ -5,13 +5,13 @@ import ( "github.com/nyaruka/goflow/utils" ) -// itemTranslations map a key for a node to a key - say "text" to "je suis francais!" -type itemTranslations map[string]string +// itemTranslations map a key for a node to a key - say "text" to "[je suis francais!]" +type itemTranslations map[string][]string // languageTranslations map a node uuid to item_translations - say "node1-asdf" to { "text": "je suis francais!" } type languageTranslations map[flows.UUID]itemTranslations -func (t *languageTranslations) GetText(uuid flows.UUID, key string, backdown string) string { +func (t *languageTranslations) GetTranslations(uuid flows.UUID, key string, backdown []string) []string { item, found := (*t)[uuid] if found { translation, found := item[key] @@ -22,6 +22,17 @@ func (t *languageTranslations) GetText(uuid flows.UUID, key string, backdown str return backdown } +func (t *languageTranslations) GetText(uuid flows.UUID, key string, backdown string) string { + item, found := (*t)[uuid] + if found { + translation, found := item[key] + if found && len(translation) > 0 { + return translation[0] + } + } + return backdown +} + // flowTranslations are our top level container for all the translations for a language type flowTranslations map[utils.Language]*languageTranslations diff --git a/flows/engine/engine.go b/flows/engine/engine.go index e23ba88bd..3a0f342fa 100644 --- a/flows/engine/engine.go +++ b/flows/engine/engine.go @@ -239,6 +239,7 @@ func pickNodeExit(run flows.FlowRun, node flows.Node, step flows.Step) (flows.No var exitUUID flows.ExitUUID var exit flows.Exit var exitName string + var exitOriginal string route := flows.NoRoute router := node.Router() @@ -265,7 +266,8 @@ func pickNodeExit(run flows.FlowRun, node flows.Node, step flows.Step) (flows.No // find our exit for _, e := range node.Exits() { if e.UUID() == exitUUID { - exitName = e.Name() + // exitName = e.Name() + exitName = run.GetText(flows.UUID(exitUUID), "name", e.Name()) exit = e break } @@ -277,9 +279,13 @@ func pickNodeExit(run flows.FlowRun, node flows.Node, step flows.Step) (flows.No // save our results if appropriate if router != nil && router.ResultName() != "" { - event := events.NewSaveFlowResult(node.UUID(), router.ResultName(), route.Match(), exitName) + if exit != nil && exit.Name() != exitName { + exitOriginal = exit.Name() + } + + event := events.NewSaveFlowResult(node.UUID(), router.ResultName(), route.Match(), exitName, exitOriginal) run.AddEvent(step, event) - run.Results().Save(node.UUID(), router.ResultName(), route.Match(), exitName, *event.CreatedOn()) + run.Results().Save(node.UUID(), router.ResultName(), route.Match(), exitName, exitOriginal, *event.CreatedOn()) } // log any error we received diff --git a/flows/events/save_flow_result.go b/flows/events/save_flow_result.go index a6e588c7c..da76e4e6a 100644 --- a/flows/events/save_flow_result.go +++ b/flows/events/save_flow_result.go @@ -24,15 +24,16 @@ const TypeSaveFlowResult string = "save_flow_result" // @event save_flow_result type SaveFlowResultEvent struct { BaseEvent - NodeUUID flows.NodeUUID `json:"node_uuid" validate:"required"` - ResultName string `json:"result_name" validate:"required"` - Value string `json:"value"` - Category string `json:"category"` + NodeUUID flows.NodeUUID `json:"node_uuid" validate:"required"` + ResultName string `json:"result_name" validate:"required"` + Value string `json:"value"` + Category string `json:"category"` + CategoryOriginal string `json:"category_original,omitempty"` } // NewSaveFlowResult returns a new save result event for the passed in values -func NewSaveFlowResult(node flows.NodeUUID, name string, value string, category string) *SaveFlowResultEvent { - return &SaveFlowResultEvent{NodeUUID: node, ResultName: name, Value: value, Category: category} +func NewSaveFlowResult(node flows.NodeUUID, name string, value string, exitName string, exitOriginal string) *SaveFlowResultEvent { + return &SaveFlowResultEvent{NodeUUID: node, ResultName: name, Value: value, Category: exitName, CategoryOriginal: exitOriginal} } // Type returns the type of this event diff --git a/flows/interfaces.go b/flows/interfaces.go index f62cc6f86..61c7dc978 100644 --- a/flows/interfaces.go +++ b/flows/interfaces.go @@ -154,6 +154,7 @@ type FlowTranslations interface { // Translations provide a way to get the translation for a specific language for a uuid/key pair type Translations interface { GetText(uuid UUID, key string, backdown string) string + GetTranslations(uuid UUID, key string, backdown []string) []string } type Context interface { @@ -249,6 +250,7 @@ type FlowRun interface { SetLanguage(utils.Language) SetFlowTranslations(FlowTranslations) GetText(uuid UUID, key string, backdown string) string + GetTranslations(uuid UUID, key string, backdown []string) []string Webhook() *utils.RequestResponse SetWebhook(*utils.RequestResponse) diff --git a/flows/results.go b/flows/results.go index cb4209396..dd3588761 100644 --- a/flows/results.go +++ b/flows/results.go @@ -20,8 +20,8 @@ type Results struct { } // Save saves a new result in our map. The key is saved in a snakified format -func (r *Results) Save(node NodeUUID, name string, value string, category string, createdOn time.Time) { - result := Result{node, name, value, category, createdOn} +func (r *Results) Save(node NodeUUID, name string, value string, category string, categoryOriginal string, createdOn time.Time) { + result := Result{node, name, value, category, categoryOriginal, createdOn} r.results[utils.Snakify(name)] = &result } @@ -55,11 +55,12 @@ var _ utils.VariableResolver = (*Results)(nil) // Result represents a result value in our flow run. Results have a name for which they are the result for, // the value itself of the result, optional category and the date and node the result was collected on type Result struct { - node NodeUUID - name string - value string - category string - createdOn time.Time + node NodeUUID + name string + value string + category string + categoryOriginal string + createdOn time.Time } // Resolve resolves the passed in key to a value. Result values have a name, value, category, node and created_on @@ -129,11 +130,12 @@ func (r *Results) MarshalJSON() ([]byte, error) { } type resultEnvelope struct { - Node NodeUUID `json:"node_uuid"` - Name string `json:"result_name"` - Value string `json:"value"` - Category string `json:"category,omitempty"` - CreatedOn time.Time `json:"created_on"` + Node NodeUUID `json:"node_uuid"` + Name string `json:"result_name"` + Value string `json:"value"` + Category string `json:"category,omitempty"` + CategoryOriginal string `json:"category_original,omitempty"` + CreatedOn time.Time `json:"created_on"` } // UnmarshalJSON is our custom unmarshalling of a Result object @@ -146,6 +148,7 @@ func (r *Result) UnmarshalJSON(data []byte) error { r.name = re.Name r.value = re.Value r.category = re.Category + r.categoryOriginal = re.CategoryOriginal r.createdOn = re.CreatedOn return err @@ -159,6 +162,7 @@ func (r *Result) MarshalJSON() ([]byte, error) { re.Name = r.name re.Value = r.value re.Category = r.category + re.CategoryOriginal = r.categoryOriginal re.CreatedOn = r.createdOn return json.Marshal(re) diff --git a/flows/routers/switch.go b/flows/routers/switch.go index d1072f553..d30aaa850 100644 --- a/flows/routers/switch.go +++ b/flows/routers/switch.go @@ -75,8 +75,10 @@ func (r *SwitchRouter) PickRoute(run flows.FlowRun, exits []flows.Exit, step flo // build our argument list args := make([]interface{}, len(c.Arguments)+1) args[0] = operand + + localizedArgs := run.GetTranslations(c.UUID, "arguments", c.Arguments) for i := range c.Arguments { - test := run.GetText(c.UUID, fmt.Sprintf("args.%d", i), c.Arguments[i]) + test := localizedArgs[i] args[i+1], err = excellent.EvaluateTemplate(env, run.Context(), test) if err != nil { run.AddError(step, err) diff --git a/flows/runs/run.go b/flows/runs/run.go index 1316c2f62..eec521d02 100644 --- a/flows/runs/run.go +++ b/flows/runs/run.go @@ -219,6 +219,13 @@ func (r *flowRun) GetText(uuid flows.UUID, key string, backdown string) string { return r.translations.GetText(uuid, key, backdown) } +func (r *flowRun) GetTranslations(uuid flows.UUID, key string, backdown []string) []string { + if r.translations == nil { + return backdown + } + return r.translations.GetTranslations(uuid, key, backdown) +} + // NewRun initializes a new context and flow run for the passed in flow and contact func NewRun(env flows.FlowEnvironment, flow flows.Flow, contact *flows.Contact, parent flows.FlowRun) flows.FlowRun { now := time.Now().UTC() From 093d68415def9100a53df26bf5f17324d540f115 Mon Sep 17 00:00:00 2001 From: Eric Newcomer Date: Wed, 5 Jul 2017 16:14:41 -0500 Subject: [PATCH 2/6] Remove duplicative code --- flows/definition/localization.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/flows/definition/localization.go b/flows/definition/localization.go index acd1de92b..4b4f9b445 100644 --- a/flows/definition/localization.go +++ b/flows/definition/localization.go @@ -23,14 +23,7 @@ func (t *languageTranslations) GetTranslations(uuid flows.UUID, key string, back } func (t *languageTranslations) GetText(uuid flows.UUID, key string, backdown string) string { - item, found := (*t)[uuid] - if found { - translation, found := item[key] - if found && len(translation) > 0 { - return translation[0] - } - } - return backdown + return t.GetTranslations(uuid, key, []string{backdown})[0] } // flowTranslations are our top level container for all the translations for a language From 3a5b285e3fa8b1d436469044f40b17da93580058 Mon Sep 17 00:00:00 2001 From: Eric Newcomer Date: Wed, 5 Jul 2017 16:18:41 -0500 Subject: [PATCH 3/6] Revert translation lookup, remove comment --- flows/definition/localization.go | 9 ++++++++- flows/engine/engine.go | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/flows/definition/localization.go b/flows/definition/localization.go index 4b4f9b445..acd1de92b 100644 --- a/flows/definition/localization.go +++ b/flows/definition/localization.go @@ -23,7 +23,14 @@ func (t *languageTranslations) GetTranslations(uuid flows.UUID, key string, back } func (t *languageTranslations) GetText(uuid flows.UUID, key string, backdown string) string { - return t.GetTranslations(uuid, key, []string{backdown})[0] + item, found := (*t)[uuid] + if found { + translation, found := item[key] + if found && len(translation) > 0 { + return translation[0] + } + } + return backdown } // flowTranslations are our top level container for all the translations for a language diff --git a/flows/engine/engine.go b/flows/engine/engine.go index 3a0f342fa..266ce6382 100644 --- a/flows/engine/engine.go +++ b/flows/engine/engine.go @@ -266,7 +266,6 @@ func pickNodeExit(run flows.FlowRun, node flows.Node, step flows.Step) (flows.No // find our exit for _, e := range node.Exits() { if e.UUID() == exitUUID { - // exitName = e.Name() exitName = run.GetText(flows.UUID(exitUUID), "name", e.Name()) exit = e break From 44863d479acdb8a13200e07f88f87050b99d71c2 Mon Sep 17 00:00:00 2001 From: Eric Newcomer Date: Wed, 5 Jul 2017 16:24:49 -0500 Subject: [PATCH 4/6] Update test flow to new localization format --- .../testdata/flows/two_questions.json | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/cmd/flowrunner/testdata/flows/two_questions.json b/cmd/flowrunner/testdata/flows/two_questions.json index f0567cca6..aab97e225 100644 --- a/cmd/flowrunner/testdata/flows/two_questions.json +++ b/cmd/flowrunner/testdata/flows/two_questions.json @@ -6,43 +6,69 @@ "localization": { "fra": { "e97cd6d5-3354-4dbd-85bc-6c1f87849eec": { - "text": "Quelle est votres couleur preferee? (rouge/blue)" + "text": [ + "Quelle est votres couleur preferee? (rouge/blue)" + ] }, "98503572-25bf-40ce-ad72-8836b6549a38": { - "test": "rouge" + "test": [ + "rouge" + ] }, "a51e5c8c-c891-401d-9c62-15fc37278c94": { - "test": "blue" + "test": [ + "blue" + ] }, "598ae7a5-2f81-48f1-afac-595262514aa1": { - "label": "Rouge" + "name": [ + "Rouge" + ] }, "c70fe86c-9aac-4cc2-a5cb-d35cbe3fed6e": { - "label": "Blue" + "name": [ + "Blue" + ] }, "78ae8f05-f92e-43b2-a886-406eaea1b8e0": { - "label": "Autres" + "name": [ + "Autres" + ] }, "d2a4052a-3fa9-4608-ab3e-5b9631440447": { - "text": "@(TITLE(input.text))! Bien sur! Quelle est votes soda preferee? (pepsi/coke)" + "text": [ + "@(TITLE(input.text))! Bien sur! Quelle est votes soda preferee? (pepsi/coke)" + ] }, "e27c3bce-1095-4d08-9164-dc4530a0688a": { - "test": "pepsi" + "test": [ + "pepsi" + ] }, "4a6c3b0b-0658-4a93-ae37-bee68f6a6a87": { - "test": "coke" + "test": [ + "coke" + ] }, "2ab9b033-77a8-4e56-a558-b568c00c9492": { - "label": "Pepsi" + "label": [ + "Pepsi" + ] }, "c7bca181-0cb3-4ec6-8555-f7e5644238ad": { - "label": "Coke" + "label": [ + "Coke" + ] }, "5ce6c69a-fdfe-4594-ab71-26be534d31c3": { - "label": "Autres" + "label": [ + "Autres" + ] }, "0a8467eb-911a-41db-8101-ccf415c48e6a": { - "text": "Parfait, vous avez finis et tu aimes @run.results.soda.category" + "text": [ + "Parfait, vous avez finis et tu aimes @run.results.soda.category" + ] } } }, From 2931ecdc6a1289b65e414c13ee56504ac330e211 Mon Sep 17 00:00:00 2001 From: Eric Newcomer Date: Thu, 6 Jul 2017 10:44:34 -0500 Subject: [PATCH 5/6] Migrate @flow.blerg.category to @run.results.blerg.category_localized --- excellent/legacy.go | 24 +++++++++++++++---- excellent/legacy_test.go | 2 +- flows/actions/save_flow_result.go | 12 ++++------ flows/engine/engine.go | 15 ++++++------ flows/events/save_flow_result.go | 14 +++++------ flows/results.go | 40 ++++++++++++++++++------------- 6 files changed, 63 insertions(+), 44 deletions(-) diff --git a/excellent/legacy.go b/excellent/legacy.go index 6130b1a06..6477be4fa 100644 --- a/excellent/legacy.go +++ b/excellent/legacy.go @@ -40,22 +40,33 @@ func (v vars) String() string { } type arbitraryVars struct { - vars vars - base string - nesting string + vars vars + base string + nesting string + nestedVars vars } func (v arbitraryVars) Resolve(key string) interface{} { + value, ok := v.vars[key] if ok { return fmt.Sprintf("%s.%s", v.base, value) } + prefix := v.base if v.nesting != "" { - return fmt.Sprintf("%s.%s.%s", v.base, v.nesting, key) + prefix = fmt.Sprintf("%s.%s", v.base, v.nesting) + } + + if v.nestedVars != nil { + return &arbitraryVars{ + base: fmt.Sprintf("%s.%s", prefix, key), + vars: v.nestedVars, + } } - return fmt.Sprintf("%s.%s", v.base, key) + return fmt.Sprintf("%s.%s", prefix, key) + } func (v arbitraryVars) Default() interface{} { @@ -140,6 +151,9 @@ func newVars() vars { }, "flow": arbitraryVars{ base: "run.results", + nestedVars: map[string]interface{}{ + "category": "category_localized", + }, }, "step": vars{ "value": "input.text", diff --git a/excellent/legacy_test.go b/excellent/legacy_test.go index 04b85f6e1..93d1aba1c 100644 --- a/excellent/legacy_test.go +++ b/excellent/legacy_test.go @@ -51,7 +51,7 @@ func TestTranslate(t *testing.T) { {old: "@contact.uuid", new: "@contact.uuid"}, {old: "@contact.blerg", new: "@contact.fields.blerg"}, {old: "@flow.blerg", new: "@run.results.blerg"}, - {old: "@flow.blerg.category", new: "@run.results.blerg.category"}, + {old: "@flow.blerg.category", new: "@run.results.blerg.category_localized"}, {old: "@step.value", new: "@input.text"}, {old: "@step.contact", new: "@step.contact"}, {old: "@date.now", new: "@(now())"}, diff --git a/flows/actions/save_flow_result.go b/flows/actions/save_flow_result.go index 217737e0d..04650ce8a 100644 --- a/flows/actions/save_flow_result.go +++ b/flows/actions/save_flow_result.go @@ -55,22 +55,20 @@ func (a *SaveFlowResultAction) Execute(run flows.FlowRun, step flows.Step) error } template = run.GetText(flows.UUID(a.UUID), "category", a.Category) - category, err := excellent.EvaluateTemplateAsString(run.Environment(), run.Context(), template) + categoryLocalized, err := excellent.EvaluateTemplateAsString(run.Environment(), run.Context(), template) if err != nil { run.AddError(step, err) } - // log our event - var categoryOriginal string - if template != a.Category { - categoryOriginal = a.Category + if a.Category == categoryLocalized { + categoryLocalized = "" } - event := events.NewSaveFlowResult(step.NodeUUID(), a.ResultName, value, category, categoryOriginal) + event := events.NewSaveFlowResult(step.NodeUUID(), a.ResultName, value, a.Category, categoryLocalized) run.AddEvent(step, event) // and save our result - run.Results().Save(step.NodeUUID(), a.ResultName, value, a.Category, categoryOriginal, *event.CreatedOn()) + run.Results().Save(step.NodeUUID(), a.ResultName, value, a.Category, categoryLocalized, *event.CreatedOn()) return nil } diff --git a/flows/engine/engine.go b/flows/engine/engine.go index 266ce6382..4456a228b 100644 --- a/flows/engine/engine.go +++ b/flows/engine/engine.go @@ -239,7 +239,6 @@ func pickNodeExit(run flows.FlowRun, node flows.Node, step flows.Step) (flows.No var exitUUID flows.ExitUUID var exit flows.Exit var exitName string - var exitOriginal string route := flows.NoRoute router := node.Router() @@ -266,7 +265,11 @@ func pickNodeExit(run flows.FlowRun, node flows.Node, step flows.Step) (flows.No // find our exit for _, e := range node.Exits() { if e.UUID() == exitUUID { - exitName = run.GetText(flows.UUID(exitUUID), "name", e.Name()) + + localizedName := run.GetText(flows.UUID(exitUUID), "name", e.Name()) + if localizedName != e.Name() { + exitName = localizedName + } exit = e break } @@ -278,13 +281,9 @@ func pickNodeExit(run flows.FlowRun, node flows.Node, step flows.Step) (flows.No // save our results if appropriate if router != nil && router.ResultName() != "" { - if exit != nil && exit.Name() != exitName { - exitOriginal = exit.Name() - } - - event := events.NewSaveFlowResult(node.UUID(), router.ResultName(), route.Match(), exitName, exitOriginal) + event := events.NewSaveFlowResult(node.UUID(), router.ResultName(), route.Match(), exit.Name(), exitName) run.AddEvent(step, event) - run.Results().Save(node.UUID(), router.ResultName(), route.Match(), exitName, exitOriginal, *event.CreatedOn()) + run.Results().Save(node.UUID(), router.ResultName(), route.Match(), exit.Name(), exitName, *event.CreatedOn()) } // log any error we received diff --git a/flows/events/save_flow_result.go b/flows/events/save_flow_result.go index da76e4e6a..fb94fa97f 100644 --- a/flows/events/save_flow_result.go +++ b/flows/events/save_flow_result.go @@ -24,16 +24,16 @@ const TypeSaveFlowResult string = "save_flow_result" // @event save_flow_result type SaveFlowResultEvent struct { BaseEvent - NodeUUID flows.NodeUUID `json:"node_uuid" validate:"required"` - ResultName string `json:"result_name" validate:"required"` - Value string `json:"value"` - Category string `json:"category"` - CategoryOriginal string `json:"category_original,omitempty"` + NodeUUID flows.NodeUUID `json:"node_uuid" validate:"required"` + ResultName string `json:"result_name" validate:"required"` + Value string `json:"value"` + Category string `json:"category"` + CategoryLocalized string `json:"category_localized,omitempty"` } // NewSaveFlowResult returns a new save result event for the passed in values -func NewSaveFlowResult(node flows.NodeUUID, name string, value string, exitName string, exitOriginal string) *SaveFlowResultEvent { - return &SaveFlowResultEvent{NodeUUID: node, ResultName: name, Value: value, Category: exitName, CategoryOriginal: exitOriginal} +func NewSaveFlowResult(node flows.NodeUUID, name string, value string, categoryName string, categoryLocalized string) *SaveFlowResultEvent { + return &SaveFlowResultEvent{NodeUUID: node, ResultName: name, Value: value, Category: categoryName, CategoryLocalized: categoryLocalized} } // Type returns the type of this event diff --git a/flows/results.go b/flows/results.go index dd3588761..1f0c6a713 100644 --- a/flows/results.go +++ b/flows/results.go @@ -20,8 +20,8 @@ type Results struct { } // Save saves a new result in our map. The key is saved in a snakified format -func (r *Results) Save(node NodeUUID, name string, value string, category string, categoryOriginal string, createdOn time.Time) { - result := Result{node, name, value, category, categoryOriginal, createdOn} +func (r *Results) Save(node NodeUUID, name string, value string, category string, categoryLocalized string, createdOn time.Time) { + result := Result{node, name, value, category, categoryLocalized, createdOn} r.results[utils.Snakify(name)] = &result } @@ -55,20 +55,28 @@ var _ utils.VariableResolver = (*Results)(nil) // Result represents a result value in our flow run. Results have a name for which they are the result for, // the value itself of the result, optional category and the date and node the result was collected on type Result struct { - node NodeUUID - name string - value string - category string - categoryOriginal string - createdOn time.Time + node NodeUUID + name string + value string + category string + categoryLocalized string + createdOn time.Time } // Resolve resolves the passed in key to a value. Result values have a name, value, category, node and created_on func (r *Result) Resolve(key string) interface{} { switch key { case "category": + if r.categoryLocalized != "" { + return r.categoryLocalized + } return r.category + case "category_localized": + if r.categoryLocalized == "" { + return r.category + } + return r.categoryLocalized case "created_on": return r.createdOn @@ -130,12 +138,12 @@ func (r *Results) MarshalJSON() ([]byte, error) { } type resultEnvelope struct { - Node NodeUUID `json:"node_uuid"` - Name string `json:"result_name"` - Value string `json:"value"` - Category string `json:"category,omitempty"` - CategoryOriginal string `json:"category_original,omitempty"` - CreatedOn time.Time `json:"created_on"` + Node NodeUUID `json:"node_uuid"` + Name string `json:"result_name"` + Value string `json:"value"` + Category string `json:"category,omitempty"` + CategoryLocalized string `json:"category_localized,omitempty"` + CreatedOn time.Time `json:"created_on"` } // UnmarshalJSON is our custom unmarshalling of a Result object @@ -148,7 +156,7 @@ func (r *Result) UnmarshalJSON(data []byte) error { r.name = re.Name r.value = re.Value r.category = re.Category - r.categoryOriginal = re.CategoryOriginal + r.categoryLocalized = re.CategoryLocalized r.createdOn = re.CreatedOn return err @@ -162,7 +170,7 @@ func (r *Result) MarshalJSON() ([]byte, error) { re.Name = r.name re.Value = r.value re.Category = r.category - re.CategoryOriginal = r.categoryOriginal + re.CategoryLocalized = r.categoryLocalized re.CreatedOn = r.createdOn return json.Marshal(re) From 6a848923e44576edfa2fa7702ebeda253996970d Mon Sep 17 00:00:00 2001 From: Eric Newcomer Date: Thu, 6 Jul 2017 11:02:02 -0500 Subject: [PATCH 6/6] Make category not return localized value --- flows/results.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/flows/results.go b/flows/results.go index 1f0c6a713..3ea3a2665 100644 --- a/flows/results.go +++ b/flows/results.go @@ -67,9 +67,6 @@ type Result struct { func (r *Result) Resolve(key string) interface{} { switch key { case "category": - if r.categoryLocalized != "" { - return r.categoryLocalized - } return r.category case "category_localized":