diff --git a/lib/custom_wizard/liquid_extensions/first_non_empty.rb b/lib/custom_wizard/liquid_extensions/first_non_empty.rb new file mode 100644 index 00000000..bd4dec01 --- /dev/null +++ b/lib/custom_wizard/liquid_extensions/first_non_empty.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module ::CustomWizard + module LiquidFilter + module FirstNonEmpty + def first_non_empty(*multiple) + multiple.find { |var| var.present? } + end + end + end +end diff --git a/lib/custom_wizard/mapper.rb b/lib/custom_wizard/mapper.rb index df49c538..c1187b0f 100644 --- a/lib/custom_wizard/mapper.rb +++ b/lib/custom_wizard/mapper.rb @@ -213,7 +213,7 @@ class CustomWizard::Mapper end end - def interpolate(string, opts = { user: true, wizard: true, value: true }) + def interpolate(string, opts = { user: true, wizard: true, value: true, template: false }) return string if string.blank? if opts[:user] @@ -248,6 +248,11 @@ class CustomWizard::Mapper end end + if opts[:template] + template = Liquid::Template.parse(string) + string = template.render(data) + end + string end diff --git a/plugin.rb b/plugin.rb index 0a272aed..169f6ff6 100644 --- a/plugin.rb +++ b/plugin.rb @@ -6,6 +6,7 @@ # url: https://github.com/paviliondev/discourse-custom-wizard # contact emails: angus@thepavilion.io +gem 'liquid', '5.0.1', require: true register_asset 'stylesheets/common/wizard-admin.scss' register_asset 'stylesheets/common/wizard-mapper.scss' register_asset 'lib/jquery.timepicker.min.js' @@ -73,6 +74,7 @@ after_initialize do ../lib/custom_wizard/api/authorization.rb ../lib/custom_wizard/api/endpoint.rb ../lib/custom_wizard/api/log_entry.rb + ../lib/custom_wizard/liquid_extensions/first_non_empty.rb ../serializers/custom_wizard/api/authorization_serializer.rb ../serializers/custom_wizard/api/basic_endpoint_serializer.rb ../serializers/custom_wizard/api/endpoint_serializer.rb @@ -97,6 +99,8 @@ after_initialize do load File.expand_path(path, __FILE__) end + Liquid::Template.register_filter(::CustomWizard::LiquidFilter::FirstNonEmpty) + add_class_method(:wizard, :user_requires_completion?) do |user| wizard_result = self.new(user).requires_completion? return wizard_result if wizard_result diff --git a/spec/components/custom_wizard/mapper_spec.rb b/spec/components/custom_wizard/mapper_spec.rb index 3b993b4b..aa34f9f1 100644 --- a/spec/components/custom_wizard/mapper_spec.rb +++ b/spec/components/custom_wizard/mapper_spec.rb @@ -41,6 +41,39 @@ describe CustomWizard::Mapper do "#{Rails.root}/plugins/discourse-custom-wizard/spec/fixtures/mapper/data.json" ).read) } + let(:template_params) { + { + "step_1_field_1" => "Hello" + } + } + let(:template_params_empty) { + { + "step_1_field_1" => nil, + "step_1_field_2" => nil, + "step_1_field_3" => "" + } + } + let(:template_params_non_empty) { + { + "step_1_field_1" => nil, + "step_1_field_2" => "", + "step_1_field_3" => "Value" + } + } + let(:template_params_multiple_non_empty) { + { + "step_1_field_1" => nil, + "step_1_field_2" => "Value1", + "step_1_field_3" => "Value" + } + } + + def create_template_mapper(data, user) + CustomWizard::Mapper.new( + data: data, + user: user + ) + end it "maps values" do expect(CustomWizard::Mapper.new( @@ -88,7 +121,7 @@ describe CustomWizard::Mapper do it "does not map when one of multiple conditions are not met" do user1.email = "angus@other-email.com" user1.save - + expect(CustomWizard::Mapper.new( inputs: inputs['conditional_multiple_pairs'], data: data, @@ -250,4 +283,128 @@ describe CustomWizard::Mapper do user: user1 ).perform).to eq(false) end + + context "output templating" do + it "passes the correct values to the template" do + template = "w{step_1_field_1}" + mapper = create_template_mapper(template_params, user1) + result = mapper.interpolate( + template.dup, + template: true, + user: true, + wizard: true, + value: true + ) + expect(result).to eq(template_params["step_1_field_1"]) + end + + it "treats replaced values as string literals" do + template = '{{ "w{step_1_field_1}" | size }}' + mapper = create_template_mapper(template_params, user1) + result = mapper.interpolate( + template.dup, + template: true, + user: true, + wizard: true, + value: true + ) + expect(result).to eq(template_params["step_1_field_1"].size.to_s) + end + + it "allows the wizard values to be used inside conditionals" do + template = <<-LIQUID + {%- if "w{step_1_field_1}" contains "ello" -%} + Correct + {%- else -%} + Incorrect + {%-endif-%} + LIQUID + mapper = create_template_mapper(template_params, user1) + result = mapper.interpolate( + template.dup, + template: true, + user: true, + wizard: true, + value: true + ) + expect(result).to eq("Correct") + end + + it "can access data passed to render method as variable" do + template = "{{step_1_field_1.size}}" + mapper = create_template_mapper(template_params, user1) + result = mapper.interpolate( + template.dup, + template: true, + user: true, + wizard: true, + value: true + ) + expect(result).to eq(template_params["step_1_field_1"].size.to_s) + end + + it "doesn't parse the template when template param is false" do + template = <<-LIQUID.strip + {{ "w{step_1_field_1}" | size}} + LIQUID + mapper = create_template_mapper(template_params, user1) + result = mapper.interpolate( + template.dup, + template: false, + ) + expect(result).to eq(template) + end + + context "custom filter: 'first_non_empty'" do + it "gives first non empty element from list" do + template = <<-LIQUID.strip + {%- assign entry = "" | first_non_empty: step_1_field_1, step_1_field_2, step_1_field_3 -%} + {{ entry }} + LIQUID + mapper = create_template_mapper(template_params_non_empty, user1) + result = mapper.interpolate( + template.dup, + template: true, + user: true, + wizard: true, + value: true + ) + expect(result).to eq(template_params_non_empty["step_1_field_3"]) + end + + it "gives first non empty element from list when multiple non empty values present" do + template = <<-LIQUID.strip + {%- assign entry = "" | first_non_empty: step_1_field_1, step_1_field_2, step_1_field_3 -%} + {{ entry }} + LIQUID + mapper = create_template_mapper(template_params_multiple_non_empty, user1) + result = mapper.interpolate( + template.dup, + template: true, + user: true, + wizard: true, + value: true + ) + expect(result).to eq(template_params_multiple_non_empty["step_1_field_2"]) + end + + it "gives empty if all elements are empty" do + template = <<-LIQUID.strip + {%- assign entry = "" | first_non_empty: step_1_field_1, step_1_field_2, step_1_field_3 -%} + {%- if entry -%} + {{ entry }} + {%- endif -%} + LIQUID + mapper = create_template_mapper(template_params_empty, user1) + result = mapper.interpolate( + template.dup, + template: true, + user: true, + wizard: true, + value: true + ) + expect(result).to eq("") + end + end + end end