From a27767db3c74a777fba2547b8577766e693d23f4 Mon Sep 17 00:00:00 2001 From: Rowan Seymour Date: Tue, 5 Mar 2024 13:49:14 -0500 Subject: [PATCH] Instead of supporting both variables and components in send_msg actions, add 13.4 migration --- flows/actions/send_msg.go | 28 +-- flows/actions/testdata/_assets.json | 6 +- flows/actions/testdata/send_msg.json | 134 +------------ flows/definition/flow.go | 2 +- flows/definition/migrations/13_x.go | 43 ++++ .../definition/migrations/primitives_test.go | 1 + .../migrations/specdata/templates.json | 90 ++++++++- .../testdata/migrations/13.4.0.json | 184 ++++++++++++++++++ ...ChangeLanguage_change_language_to_ara.snap | 2 +- ...ChangeLanguage_change_language_to_kin.snap | 2 +- ...ChangeLanguage_change_language_to_spa.snap | 2 +- .../definition/testdata/change_language.json | 2 +- 12 files changed, 341 insertions(+), 155 deletions(-) create mode 100644 flows/definition/migrations/testdata/migrations/13.4.0.json diff --git a/flows/actions/send_msg.go b/flows/actions/send_msg.go index c27b587e7..421d8239d 100644 --- a/flows/actions/send_msg.go +++ b/flows/actions/send_msg.go @@ -72,7 +72,6 @@ func (c *TemplatingComponent) LocalizationUUID() uuids.UUID { return c.UUID } type Templating struct { UUID uuids.UUID `json:"uuid" validate:"required,uuid4"` Template *assets.TemplateReference `json:"template" validate:"required"` - Variables []string `json:"variables,omitempty" engine:"localized,evaluated"` Components []*TemplatingComponent `json:"components,omitempty"` } @@ -148,29 +147,16 @@ func (a *SendMsgAction) Execute(run flows.Run, step flows.Step, logModifier flow func (a *SendMsgAction) getTemplateMsg(run flows.Run, urn urns.URN, channelRef *assets.ChannelReference, translation *flows.TemplateTranslation, unsendableReason flows.UnsendableReason, logEvent flows.EventCallback) *flows.MsgOut { evaluatedParams := make(map[string][]string) - // start by localizing and evaluating either the legacy variables or per-component params - if len(a.Templating.Variables) > 0 { - localizedVariables, _ := run.GetTextArray(uuids.UUID(a.Templating.UUID), "variables", a.Templating.Variables, nil) - - evaluatedVariables := make([]string, len(localizedVariables)) - for i, variable := range localizedVariables { + // start by localizing and evaluating either the per-component params + for _, comp := range a.Templating.Components { + localizedCompParams, _ := run.GetTextArray(comp.UUID, "params", comp.Params, nil) + evaluatedCompParams := make([]string, len(localizedCompParams)) + for i, variable := range localizedCompParams { sub, _ := run.EvaluateTemplate(variable, logEvent) - evaluatedVariables[i] = sub + evaluatedCompParams[i] = sub } - evaluatedParams["body"] = evaluatedVariables - - } else if len(a.Templating.Components) > 0 { - for _, comp := range a.Templating.Components { - localizedCompParams, _ := run.GetTextArray(comp.UUID, "params", comp.Params, nil) - evaluatedCompParams := make([]string, len(localizedCompParams)) - for i, variable := range localizedCompParams { - sub, _ := run.EvaluateTemplate(variable, logEvent) - evaluatedCompParams[i] = sub - } - - evaluatedParams[comp.Name] = evaluatedCompParams - } + evaluatedParams[comp.Name] = evaluatedCompParams } // next we cross reference with params defined in the template translation to get types diff --git a/flows/actions/testdata/_assets.json b/flows/actions/testdata/_assets.json index 06984f663..a28b56665 100644 --- a/flows/actions/testdata/_assets.json +++ b/flows/actions/testdata/_assets.json @@ -3,7 +3,7 @@ { "uuid": "bead76f5-dac4-4c9d-996c-c62b326e8c0a", "name": "Action Tester", - "spec_version": "13.3.0", + "spec_version": "13.4.0", "language": "eng", "type": "messaging", "revision": 123, @@ -23,7 +23,7 @@ { "uuid": "7a84463d-d209-4d3e-a0ff-79f977cd7bd0", "name": "Voice Action Tester", - "spec_version": "13.2", + "spec_version": "13.4.0", "language": "eng", "type": "voice", "revision": 123, @@ -43,7 +43,7 @@ { "uuid": "b7cf0d83-f1c9-411c-96fd-c511a4cfa86d", "name": "Collect Age", - "spec_version": "13.2", + "spec_version": "13.4.0", "revision": 123, "language": "eng", "type": "messaging", diff --git a/flows/actions/testdata/send_msg.json b/flows/actions/testdata/send_msg.json index a13d4d0d7..67905edfd 100644 --- a/flows/actions/testdata/send_msg.json +++ b/flows/actions/testdata/send_msg.json @@ -351,9 +351,15 @@ "uuid": "b620b463-8d15-427f-b2e3-4f44f9f071ec", "name": "missing" }, - "variables": [ - "@contact.name", - "boy" + "components": [ + { + "uuid": "aa304c85-c14f-4f94-b97c-ec59c07a3f39", + "name": "body", + "params": [ + "@contact.name", + "boy" + ] + } ] } }, @@ -959,127 +965,5 @@ "waiting_exits": [], "parent_refs": [] } - }, - { - "description": "Use template translation with legacy variables", - "action": { - "type": "send_msg", - "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", - "text": "Hey Ryan Lewis, your gender is saved as boy.", - "templating": { - "uuid": "9c4bf5b5-3aa4-48ec-9bb9-424a9cbc6785", - "template": { - "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", - "name": "gender_update" - }, - "variables": [ - "@contact.name", - "boy" - ] - } - }, - "localization": { - "spa": { - "ad154980-7bf7-4ab8-8728-545fd6378912": { - "text": [ - "Hola!" - ], - "attachments": [ - "http://example.com/rojo.jpg" - ], - "quick_replies": [ - "Si", - "No" - ] - }, - "9c4bf5b5-3aa4-48ec-9bb9-424a9cbc6785": { - "variables": [ - "@contact.name", - "niño" - ] - } - } - }, - "events": [ - { - "type": "msg_created", - "created_on": "2018-10-18T14:20:30.000123456Z", - "step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c", - "msg": { - "uuid": "9688d21d-95aa-4bed-afc7-f31b35731a3d", - "urn": "tel:+12065551212?channel=57f1078f-88aa-46f4-a59a-948a5739c03d&id=123", - "channel": { - "uuid": "57f1078f-88aa-46f4-a59a-948a5739c03d", - "name": "My Android Phone" - }, - "text": "Hola, Ryan Lewis, tu género está guardado como niño.", - "quick_replies": [ - "", - "No" - ], - "templating": { - "template": { - "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", - "name": "gender_update" - }, - "params": { - "body": [ - { - "type": "text", - "value": "Ryan Lewis" - }, - { - "type": "text", - "value": "niño" - } - ], - "button.0": [ - { - "type": "text", - "value": "" - } - ], - "header": [ - { - "type": "image", - "value": "" - } - ] - }, - "namespace": "" - }, - "locale": "spa" - } - } - ], - "templates": [ - "Hey Ryan Lewis, your gender is saved as boy.", - "Hola!", - "http://example.com/rojo.jpg", - "Si", - "No", - "@contact.name", - "boy", - "@contact.name", - "niño" - ], - "localizables": [ - "Hey Ryan Lewis, your gender is saved as boy.", - "@contact.name", - "boy" - ], - "inspection": { - "dependencies": [ - { - "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", - "name": "gender_update", - "type": "template" - } - ], - "issues": [], - "results": [], - "waiting_exits": [], - "parent_refs": [] - } } ] \ No newline at end of file diff --git a/flows/definition/flow.go b/flows/definition/flow.go index fb18df8c5..c9bd5d26b 100644 --- a/flows/definition/flow.go +++ b/flows/definition/flow.go @@ -19,7 +19,7 @@ import ( ) // CurrentSpecVersion is the flow spec version supported by this library -var CurrentSpecVersion = semver.MustParse("13.3.0") +var CurrentSpecVersion = semver.MustParse("13.4.0") // IsVersionSupported checks the given version is supported func IsVersionSupported(v *semver.Version) bool { diff --git a/flows/definition/migrations/13_x.go b/flows/definition/migrations/13_x.go index d2e69b1a0..3a68b86f3 100644 --- a/flows/definition/migrations/13_x.go +++ b/flows/definition/migrations/13_x.go @@ -7,11 +7,54 @@ import ( ) func init() { + registerMigration(semver.MustParse("13.4.0"), Migrate13_4) registerMigration(semver.MustParse("13.3.0"), Migrate13_3) registerMigration(semver.MustParse("13.2.0"), Migrate13_2) registerMigration(semver.MustParse("13.1.0"), Migrate13_1) } +// Migrate13_4 converts the `templating` object in [action:send_msg] actions to use a list of components. +// +// @version 13_4 "13.4" +func Migrate13_4(f Flow, cfg *Config) (Flow, error) { + localization := f.Localization() + + for _, node := range f.Nodes() { + for _, action := range node.Actions() { + if action.Type() == "send_msg" { + templating, _ := action["templating"].(map[string]any) + if templating != nil { + templatingUUID := GetObjectUUID(templating) + bodyCompUUID := uuids.New() + variables, _ := templating["variables"].([]any) + if variables == nil { + variables = []any{} + } + templating["components"] = []map[string]any{ + {"uuid": bodyCompUUID, "name": "body", "params": variables}, + } + + if localization != nil { + for _, lang := range localization.Languages() { + langTrans := localization.GetLanguageTranslation(lang) + if langTrans != nil { + vars := langTrans.GetTranslation(templatingUUID, "variables") + if vars != nil { + langTrans.SetTranslation(bodyCompUUID, "params", vars) + langTrans.DeleteTranslation(templatingUUID, "variables") + } + } + } + } + + delete(templating, "variables") + } + } + } + } + return f, nil +} + // Migrate13_3 refactors template expressions that reference @webhook to use @webhook.json // // @version 13_3 "13.3" diff --git a/flows/definition/migrations/primitives_test.go b/flows/definition/migrations/primitives_test.go index d620cd8d0..eefc2ebc9 100644 --- a/flows/definition/migrations/primitives_test.go +++ b/flows/definition/migrations/primitives_test.go @@ -118,6 +118,7 @@ func TestLocalizationPrimitives(t *testing.T) { spa.DeleteTranslation("8eebd020-1af5-431c-b943-aa670fc74da9", "text") spa.DeleteTranslation("8eebd020-1af5-431c-b943-aa670fc74da9", "empty") + spa.DeleteTranslation("8eebd020-1af5-431c-b943-aa670fc74da9", "foo") // doesn't exist spa.DeleteTranslation("6f865930-e783-4fde-8e28-34b93b3a17c6", "text") test.AssertEqualJSON(t, []byte(`{ diff --git a/flows/definition/migrations/specdata/templates.json b/flows/definition/migrations/specdata/templates.json index b825af354..f52834cb4 100644 --- a/flows/definition/migrations/specdata/templates.json +++ b/flows/definition/migrations/specdata/templates.json @@ -1,5 +1,5 @@ { - "13.3.0": { + "13.4.0": { "actions": { "add_contact_groups": [ ".groups[*].name_match" @@ -51,6 +51,94 @@ ".attachments[*]", ".quick_replies[*]", ".templating.components[*].params[*]", + ".text" + ], + "set_contact_channel": [], + "set_contact_field": [ + ".value" + ], + "set_contact_language": [ + ".language" + ], + "set_contact_name": [ + ".name" + ], + "set_contact_status": [], + "set_contact_timezone": [ + ".timezone" + ], + "set_run_result": [ + ".value" + ], + "start_session": [ + ".contact_query", + ".groups[*].name_match", + ".legacy_vars[*]" + ], + "transfer_airtime": [] + }, + "routers": { + "random": [ + ".operand", + ".cases[*].arguments[*]" + ], + "switch": [ + ".operand", + ".cases[*].arguments[*]" + ] + } + }, + "13.3.0": { + "actions": { + "add_contact_groups": [ + ".groups[*].name_match" + ], + "add_contact_urn": [ + ".path" + ], + "add_input_labels": [ + ".labels[*].name_match" + ], + "call_classifier": [ + ".input" + ], + "call_resthook": [], + "call_webhook": [ + ".body", + ".headers.*", + ".url" + ], + "enter_flow": [], + "open_ticket": [ + ".assignee.email_match", + ".body" + ], + "play_audio": [ + ".audio_url" + ], + "remove_contact_groups": [ + ".groups[*].name_match" + ], + "request_optin": [], + "say_msg": [ + ".text" + ], + "send_broadcast": [ + ".attachments[*]", + ".contact_query", + ".groups[*].name_match", + ".legacy_vars[*]", + ".quick_replies[*]", + ".text" + ], + "send_email": [ + ".addresses[*]", + ".body", + ".subject" + ], + "send_msg": [ + ".attachments[*]", + ".quick_replies[*]", ".templating.variables[*]", ".text" ], diff --git a/flows/definition/migrations/testdata/migrations/13.4.0.json b/flows/definition/migrations/testdata/migrations/13.4.0.json new file mode 100644 index 000000000..856a04448 --- /dev/null +++ b/flows/definition/migrations/testdata/migrations/13.4.0.json @@ -0,0 +1,184 @@ +[ + { + "description": "flow with localization", + "original": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.3.0", + "language": "eng", + "type": "messaging", + "localization": { + "spa": { + "8eebd020-1af5-431c-b943-aa670fc74da9": { + "text": [ + "Hola" + ] + }, + "9c4bf5b5-3aa4-48ec-9bb9-424a9cbc6785": { + "variables": [ + "@contact" + ] + } + } + }, + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "templating": { + "uuid": "9c4bf5b5-3aa4-48ec-9bb9-424a9cbc6785", + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "variables": [ + "@contact.name" + ] + } + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + }, + "migrated": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.4.0", + "language": "eng", + "type": "messaging", + "localization": { + "spa": { + "8eebd020-1af5-431c-b943-aa670fc74da9": { + "text": [ + "Hola" + ] + }, + "d2f852ec-7b4e-457f-ae7f-f8b243c49ff5": { + "params": [ + "@contact" + ] + } + } + }, + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "templating": { + "uuid": "9c4bf5b5-3aa4-48ec-9bb9-424a9cbc6785", + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "components": [ + { + "uuid": "d2f852ec-7b4e-457f-ae7f-f8b243c49ff5", + "name": "body", + "params": [ + "@contact.name" + ] + } + ] + } + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + } + }, + { + "description": "flow without localization", + "original": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.3.0", + "language": "eng", + "type": "messaging", + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "templating": { + "uuid": "9c4bf5b5-3aa4-48ec-9bb9-424a9cbc6785", + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "variables": [ + "@contact.name" + ] + } + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + }, + "migrated": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.4.0", + "language": "eng", + "type": "messaging", + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "templating": { + "uuid": "9c4bf5b5-3aa4-48ec-9bb9-424a9cbc6785", + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "components": [ + { + "uuid": "d2f852ec-7b4e-457f-ae7f-f8b243c49ff5", + "name": "body", + "params": [ + "@contact.name" + ] + } + ] + } + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap b/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap index b86e10cef..1525c9c5d 100644 --- a/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap +++ b/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap @@ -1,7 +1,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.3.0", + "spec_version": "13.4.0", "language": "ara", "type": "messaging", "revision": 16, diff --git a/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap b/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap index 465bf1555..2efb24214 100644 --- a/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap +++ b/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap @@ -1,7 +1,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.3.0", + "spec_version": "13.4.0", "language": "kin", "type": "messaging", "revision": 16, diff --git a/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap b/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap index b89a182e9..5e5e28c93 100644 --- a/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap +++ b/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap @@ -1,7 +1,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.3.0", + "spec_version": "13.4.0", "language": "spa", "type": "messaging", "revision": 16, diff --git a/flows/definition/testdata/change_language.json b/flows/definition/testdata/change_language.json index 31c81e06f..d2a8c476c 100644 --- a/flows/definition/testdata/change_language.json +++ b/flows/definition/testdata/change_language.json @@ -3,7 +3,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.3.0", + "spec_version": "13.4.0", "language": "eng", "type": "messaging", "revision": 16,