diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index bd751b2d4e..0e9c6e55b1 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -84,6 +84,17 @@ def welcome_my_journey_into_teaching render_page("welcome/my-journey-into-teaching") end + def authenticate? + # restrict the /values page to any user who has a login + %w[values].include?(action_name) || super + end + + def values + # restrict the /values page to any user who has a login + render_forbidden if session[:user].blank? + render template: "pages/values", layout: "content" + end + private def adviser_sign_up_url diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 3e44c811c1..dea14d134c 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -8,4 +8,9 @@ def article_classes(front_matter) def display_content_errors? Rails.application.config.x.display_content_errors end + + def value(key) + Value.data[key.to_s] + end + alias_method :v, :value end diff --git a/app/models/value.rb b/app/models/value.rb new file mode 100644 index 0000000000..6ecf81399b --- /dev/null +++ b/app/models/value.rb @@ -0,0 +1,36 @@ +class Value + PATH = "config/values/**/*.yml".freeze + attr_reader :data + + def self.data + # the value data will rarely change, so OK to cache in a class variable + @@data ||= new.data + end + + def initialize(path = nil) + @data = load_values(path || Rails.root.join(PATH)) + end + +private + + def load_values(dir_spec) + {}.tap do |data| + Dir[dir_spec].each do |filename| + data.merge!(flatten_hash(YAML.load_file(filename))) + end + end + end + + def flatten_hash(hash) + # based on https://stackoverflow.com/questions/23521230/flattening-nested-hash-to-a-single-hash-with-ruby-rails + hash.each_with_object({}) do |(k, v), h| + if v.is_a? Hash + flatten_hash(v).map do |h_k, h_v| + h["#{k}_#{h_k}"] = h_v + end + else + h[k] = v + end + end + end +end diff --git a/app/views/pages/values.md b/app/views/pages/values.md new file mode 100644 index 0000000000..c2e39bb987 --- /dev/null +++ b/app/views/pages/values.md @@ -0,0 +1,6 @@ +--- +title: Values +noindex: true +content: + - pages/values/table +--- diff --git a/app/views/pages/values/_table.html.erb b/app/views/pages/values/_table.html.erb new file mode 100644 index 0000000000..ecb3595cb2 --- /dev/null +++ b/app/views/pages/values/_table.html.erb @@ -0,0 +1,26 @@ +
+ Key + | ++ Value + | +
---|---|
+
+ $<%= key %>$
+
+ |
+ + <%= value %> + | +
+ The opening date for applications is <%= v :dates_example_opening %>. +
+``` + +A list of the current values available on the site can be viewed at the `/values` endpoint. + ## Creating a Blog Post Blog posts should be written in Markdown format using the following template as a guide: @@ -574,4 +610,4 @@ You can find everywhere a page is linked to by: ## Resolving comments People can add comments to pull requests in Github which makes it easier to see feedback and keep track of changes. You can also tag people and reply to their comments. -Once you've addressed a comment click on resolve. This hides it from the conversation making it easier to keep track of what's been updated. \ No newline at end of file +Once you've addressed a comment click on resolve. This hides it from the conversation making it easier to keep track of what's been updated. diff --git a/lib/template_handlers/markdown.rb b/lib/template_handlers/markdown.rb index 887c57397d..cfbbcb4297 100644 --- a/lib/template_handlers/markdown.rb +++ b/lib/template_handlers/markdown.rb @@ -57,7 +57,7 @@ def markdown # entire placeholder to the arg (including dollar symbols) but we only # want what's inside the capture group parsed.content.gsub(COMPONENT_PLACEHOLDER_REGEX) do - safe_join([cta_component($1), content_component($1), image($1)].compact).strip + safe_join([cta_component($1), content_component($1), image($1), value($1)].compact).strip end end # rubocop:enable Style/PerlBackrefs @@ -95,6 +95,10 @@ def image(placeholder) ApplicationController.render(component, layout: false) end + def value(placeholder) + Value.data[placeholder] + end + def front_matter @front_matter ||= self.class.global_front_matter.deep_merge(parsed.front_matter) end diff --git a/spec/fixtures/files/example_values/data1.yml b/spec/fixtures/files/example_values/data1.yml new file mode 100644 index 0000000000..a1cfb4f44e --- /dev/null +++ b/spec/fixtures/files/example_values/data1.yml @@ -0,0 +1,5 @@ +data1: + example: + date: 01/02/2003 + +data1_example_amount: £1,234.56 diff --git a/spec/fixtures/files/example_values/data2.yml b/spec/fixtures/files/example_values/data2.yml new file mode 100644 index 0000000000..c94094ffdc --- /dev/null +++ b/spec/fixtures/files/example_values/data2.yml @@ -0,0 +1,5 @@ +data2: + example: + string: Hello World! + +data2_example_number: 0.01 diff --git a/spec/lib/template_handlers/markdown_spec.rb b/spec/lib/template_handlers/markdown_spec.rb index 5a08f25bbc..b2a76ae123 100644 --- a/spec/lib/template_handlers/markdown_spec.rb +++ b/spec/lib/template_handlers/markdown_spec.rb @@ -262,4 +262,38 @@ is_expected.to have_css("ol.steps") end end + + describe "injecting values" do + let(:front_matter) { { "title": "Page with view components" } } + + let :markdown do + <<~MARKDOWN + # Some page + + data1_example_amount: $data1_example_amount$ + + Some text + + data2_example_string: $data2_example_string$ + MARKDOWN + end + + let(:value_data) { Value.new("spec/fixtures/files/example_values/**/*.yml").data } + + before do + allow(described_class).to receive(:global_front_matter).and_return(front_matter) + allow(Value).to receive(:data).and_return(value_data) + stub_template "page_with_rich_content.md" => markdown + render template: "page_with_rich_content" + end + + subject { rendered } + + it "contains the specified view components" do + is_expected.to have_text("Some page") + is_expected.to have_text("data1_example_amount: £1,234.56") + is_expected.to have_text("Some text") + is_expected.to have_text("data2_example_string: Hello World!") + end + end end diff --git a/spec/models/value_spec.rb b/spec/models/value_spec.rb new file mode 100644 index 0000000000..3a98ce30bf --- /dev/null +++ b/spec/models/value_spec.rb @@ -0,0 +1,36 @@ +require "rails_helper" + +describe Value do + describe "##data (class method)" do + subject { described_class.data } + + it { is_expected.to be_a Hash } + end + + describe "#data" do + subject { instance.data } + + let(:instance) { described_class.new(path) } + + context "with default path" do + let(:path) { nil } + + it { is_expected.to be_a Hash } + end + + context "with specific file path" do + let(:path) { "spec/fixtures/files/example_values/**/*.yml" } + + it { + is_expected.to eql( + { + "data1_example_amount" => "£1,234.56", + "data1_example_date" => "01/02/2003", + "data2_example_number" => 0.01, + "data2_example_string" => "Hello World!", + }, + ) + } + end + end +end