editmode 1.1.7 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a278337d6551c478182ab117612d042fdd8e2ff02f4cebbcb7acad50f453d90
4
- data.tar.gz: 94f704ae1f80a190424b24019dffe3ae2aedb20cb092f89e56b2382f64540ced
3
+ metadata.gz: 2beab37962d65855d3ecfd66b6d9731fd4f1826eac260d97a30d8c1b022b9ff8
4
+ data.tar.gz: b05b7f2425a796262ec31e2d8cc447405d9bb2ed339b37a6f71cc2d52cd10ad7
5
5
  SHA512:
6
- metadata.gz: 8238f3fa1c5e60c0277dee06e02691e833a858a525d6d4d00ddef62cba336699015309f4b75e31b4a1a98239ad12badae6f314cc2f6a5810c7376a59282eb5ca
7
- data.tar.gz: 538ed505b343dce47388922818fc297b67b111297538be1035248b0007f3691afa1324e233b438bbdc6c811d2065c0652b846376bb3d12616836dc2bf10ed6f6
6
+ metadata.gz: 75944607fde64c8da7a99751a421d43fbc473b7f0c0c7ce34297b16d70869d2d393de8731fed85dfd6387ba22977ef3e92ae892370b07a13a9ed41bad7d6472b
7
+ data.tar.gz: c2109b7ca239fce3ddb025348bc534201002d6396a18e4eec9357fdc992f64489efed095e4568db984148e5ff45aafad70b1026cf93111d9c04aa20bed329924
data/README.md CHANGED
@@ -47,6 +47,7 @@ Editmode provides helper methods for use in your rails views and controllers.
47
47
  ```erb
48
48
  <%= E('cnk_x4ts............') %> # Using a chunk identifier
49
49
  <%= E('marketing_page_headline') %> # Using a content key
50
+ <%= E('cnk_x4ts...', class: "a-css-class") %> # Render a chunk with inline css class
50
51
  ```
51
52
 
52
53
  ### Content can also be accessed in Controllers
@@ -79,23 +80,23 @@ e("cnk_16e04a02d577afb610ce", "Email Content", variables: variable_values)
79
80
 
80
81
  ### Use collections for repeatable content
81
82
  ```erb
82
- <%= c('col_j8fbs...') do |chunk| %>
83
- <div class="user-profile">
84
- <h3 class="name">
85
- <%= F("Name") %>
86
- </h3>
87
- <p class="description">
88
- <%= f("Description") %>
89
- </p>
90
- </div>
83
+ <%= c('col_j8fbs...', class: "profiles-container", item_class: "profile-item") do %>
84
+ <h3 class="name">
85
+ <%= F("Name", class: "profile-name") %>
86
+ </h3>
87
+ <p class="description">
88
+ <%= f("Description"), class: "profile-description" %>
89
+ </p>
91
90
  <% end %>
92
91
  ```
93
92
 
94
93
  |Parameter|Type|Description|
95
94
  |---|---|---|
96
95
  | identifier | string | The first argument of `c` takes the id of the collection you want to loop through |
97
- | limit | int |`optional` The number of collection items you want to display |
96
+ | limit | int/string |`optional` The number of collection items you want to display |
98
97
  | tags | array |`optional` Filter collection items based on tags listed in this parameter |
98
+ | class | string | `optional` Class name(s) that will be added along with "chunks-collection-wrapper" to the main collection `<div>` element |
99
+ | item_class | string | `optional` Class name(s) that will be added along with "chunks-collection-item--wrapper" to all collection items |
99
100
 
100
101
 
101
102
  ## Caching
@@ -13,8 +13,7 @@ class EditmodeController < ApplicationController
13
13
  Rails.cache.delete("chunk_#{project_id}_variables")
14
14
  render status: 200, json: {:response => "success"}
15
15
  elsif params[:identifier]
16
- Rails.cache.delete("chunk_#{params[:identifier]}")
17
- Rails.cache.delete("chunk_#{params[:identifier]}_type")
16
+ Rails.cache.delete_matched("#{params[:identifier]}")
18
17
  render status: 200, json: {:response => "success"}
19
18
  else
20
19
  render status: 404, json: {:response => "no identifier specified"}
@@ -36,7 +36,7 @@ module Editmode
36
36
  begin
37
37
  Editmode::ChunkValue.new(identifier, **options )
38
38
  rescue => er
39
- raise er
39
+ puts er
40
40
  end
41
41
  end
42
42
  end
@@ -19,6 +19,9 @@ module Editmode
19
19
  branch_id = params[:em_branch_id].presence
20
20
  tags = options[:tags].presence || []
21
21
  limit = options[:limit].presence
22
+
23
+ parent_class = options[:class] || ""
24
+ item_class = options[:item_class] || ""
22
25
 
23
26
  begin
24
27
  url_params = {
@@ -49,12 +52,22 @@ module Editmode
49
52
  end
50
53
 
51
54
  if chunks.any?
52
- content_tag :div, class: "chunks-collection-wrapper", data: {chunk_collection_identifier: collection_identifier} do
55
+ content_tag :div, class: "chunks-collection-wrapper #{parent_class}", data: {chunk_collection_identifier: collection_identifier} do
53
56
  chunks.each do |chunk|
54
57
  @custom_field_chunk = chunk
55
- yield
58
+ concat(content_tag(:div, class: "chunks-collection-item--wrapper #{item_class}") do
59
+ yield
60
+ end)
56
61
  end
57
- end
62
+
63
+ # Placeholder element for new collection item
64
+ @custom_field_chunk = chunks.first.merge!({placeholder: true})
65
+ concat(content_tag(:div, class: "chunks-hide chunks-col-placeholder-wrapper") do
66
+ yield
67
+ end)
68
+ end
69
+ else
70
+ content_tag(:span, "&nbsp".html_safe)
58
71
  end
59
72
  end
60
73
  rescue => error
@@ -67,18 +80,22 @@ module Editmode
67
80
  def chunk_field_value(parent_chunk_object, custom_field_identifier, options = {})
68
81
  begin
69
82
  chunk_identifier = parent_chunk_object["identifier"]
70
- custom_field_item = parent_chunk_object["content"].detect do |f|
71
- f["custom_field_identifier"].try(:downcase) == custom_field_identifier.try(:downcase) || f["custom_field_name"].try(:downcase) == custom_field_identifier.try(:downcase)
72
- end
83
+ chunk_value = Editmode::ChunkValue.new(parent_chunk_object["identifier"], options.merge({response: parent_chunk_object}))
84
+ custom_field_item = chunk_value.field_chunk(custom_field_identifier)
73
85
 
74
86
  options[:field] = custom_field_identifier
75
87
 
88
+ if parent_chunk_object[:placeholder]
89
+ custom_field_item["identifier"] = ""
90
+ custom_field_item["content"] = ""
91
+ end
92
+
76
93
  if custom_field_item.present?
77
94
  render_chunk_content(
78
95
  custom_field_item["identifier"],
79
- custom_field_item["content"],
96
+ chunk_value.field(custom_field_identifier),
80
97
  custom_field_item["chunk_type"],
81
- { parent_identifier: chunk_identifier }.merge(options)
98
+ { parent_identifier: chunk_identifier, custom_field_identifier: custom_field_identifier}.merge(options)
82
99
  )
83
100
  end
84
101
  rescue => errors
@@ -88,13 +105,9 @@ module Editmode
88
105
  end
89
106
 
90
107
  def render_chunk_content(chunk_identifier, chunk_content, chunk_type,options = {})
91
-
92
108
  begin
93
- # Always sanitize the content!!
94
- chunk_content = ActionController::Base.helpers.sanitize(chunk_content) unless chunk_type == 'rich_text'
95
- chunk_content = variable_parse!(chunk_content, options[:variable_fallbacks], options[:variable_values])
96
-
97
109
  css_class = options[:class]
110
+ cache_id = options[:cache_identifier]
98
111
 
99
112
  if chunk_type == "image"
100
113
  display_type = "image"
@@ -104,11 +117,12 @@ module Editmode
104
117
 
105
118
  chunk_data = { :chunk => chunk_identifier, :chunk_editable => false, :chunk_type => chunk_type }
106
119
 
107
- if options[:parent_identifier].present?
108
- chunk_data.merge!({parent_identifier: options[:parent_identifier]})
109
- end
110
-
111
-
120
+ chunk_data.merge!({parent_identifier: options[:parent_identifier]}) if options[:parent_identifier].present?
121
+ chunk_data.merge!({custom_field_identifier: options[:custom_field_identifier]}) if options[:custom_field_identifier].present?
122
+ chunk_data.merge!({chunk_cache_id: cache_id}) if cache_id.present?
123
+ chunk_data.merge!({chunk_collection_identifier: options[:collection_id]}) if options[:collection_id].present?
124
+ chunk_data.merge!({chunk_content_key: options[:content_key]}) if options[:content_key].present?
125
+
112
126
  case display_type
113
127
  when "span"
114
128
  if chunk_type == "rich_text"
@@ -117,10 +131,11 @@ module Editmode
117
131
  end
118
132
  else
119
133
  content_tag("em-span", :class => css_class, :data => chunk_data.merge!({:chunk_editable => true}) ) do
120
- chunk_content
134
+ chunk_content.html_safe
121
135
  end
122
136
  end
123
137
  when "image"
138
+ chunk_content = chunk_content.blank? || chunk_content == "/images/original/missing.png" ? 'https://www.editmode.com/upload.png' : chunk_content
124
139
  image_tag(chunk_content, :data => chunk_data, :class => css_class)
125
140
  end
126
141
  rescue => errors
@@ -131,54 +146,31 @@ module Editmode
131
146
  end
132
147
 
133
148
  def chunk_display(label, identifier, options = {}, &block)
134
- branch_id = params[:em_branch_id]
149
+ options[:branch_id] = params[:em_branch_id] if params[:em_branch_id].present?
135
150
  # This method should never show an error.
136
151
  # If anything goes wrong fetching content
137
152
  # We should just show blank content, not
138
153
  # prevent the page from loading.
139
154
  begin
140
- branch_params = branch_id.present? ? "branch_id=#{branch_id}" : ""
141
155
  field = options[:field].presence || ""
142
- cache_identifier = "chunk_#{identifier}#{branch_id}#{field}"
143
- url = "#{api_root_url}/chunks/#{identifier}?project_id=#{Editmode.project_id}&#{branch_params}"
144
- cached_content_present = Rails.cache.exist?(cache_identifier)
145
-
146
- if !cached_content_present
147
- response = HTTParty.get(url)
148
- response_received = true if response.code == 200
149
- end
150
156
 
151
- if !cached_content_present && !response_received
152
- raise "No response received"
157
+ chunk_value = Editmode::ChunkValue.new(identifier, options)
158
+
159
+ if field.present? && chunk_value.chunk_type == 'collection_item'
160
+ chunk_content = chunk_value.field(field)
161
+ identifier = chunk_value.field_chunk(field)["identifier"]
162
+ chunk_type = chunk_value.field_chunk(field)["chunk_type"]
163
+ options[:collection_id] = chunk_value.collection_id
153
164
  else
154
- if field.present? && response.present?
155
- field_content = response["content"].detect {|f| f["custom_field_identifier"].downcase == field.downcase || f["custom_field_name"].downcase == field.downcase }
156
- if field_content
157
- content = field_content["content"]
158
- type = field_content["chunk_type"]
159
- identifier = field_content["identifier"]
160
- end
161
- end
162
-
163
- variable_fallbacks = Rails.cache.fetch("#{cache_identifier}_variables") do
164
- response['variable_fallbacks'].presence || {}
165
- end
166
-
167
- chunk_content = Rails.cache.fetch(cache_identifier) do
168
- content.presence || response["content"]
169
- end
170
-
171
- chunk_type = Rails.cache.fetch("#{cache_identifier}_type") do
172
- type.presence || response['chunk_type']
173
- end
174
-
175
- options[:variable_fallbacks] = variable_fallbacks
176
- options[:variable_values] = options[:variables].presence || {}
177
-
178
- render_chunk_content(identifier,chunk_content,chunk_type, options)
179
-
165
+ chunk_content = chunk_value.content
166
+ chunk_type = chunk_value.chunk_type
167
+ identifier = chunk_value.response["identifier"] unless identifier.include? "cnk_"
180
168
  end
181
169
 
170
+ options[:cache_identifier] = chunk_value.identifier
171
+ options[:content_key] = chunk_value.response.try(:[], "content_key")
172
+ render_chunk_content(identifier, chunk_content, chunk_type, options)
173
+
182
174
  rescue => error
183
175
  # Show fallback content by default
184
176
  return content_tag("em-span", &block) if block_given?
@@ -205,22 +197,6 @@ module Editmode
205
197
  end
206
198
  alias_method :E, :render_chunk
207
199
 
208
-
209
- def variable_parse!(content, variables = {}, values = {})
210
- tokens = content.scan(/\{{(.*?)\}}/)
211
- if tokens.any?
212
- tokens.flatten!
213
- tokens.each do |token|
214
- token_value = values[token.to_sym] || variables[token] || ""
215
- sanitized_value = ActionController::Base.helpers.sanitize(token_value)
216
-
217
- content.gsub!("{{#{token}}}", sanitized_value)
218
- end
219
- end
220
-
221
- content
222
- end
223
-
224
200
  def no_response_received(id = "")
225
201
  "Sorry, we can't find a chunk using this identifier: \"#{id}\". This can happen if you've deleted a chunk on editmode.com or if your local cache is out of date. If it persists, try running Rails.cache clear."
226
202
  end
@@ -1,29 +1,42 @@
1
1
  module Editmode
2
2
  class ChunkValue
3
- include Editmode::ActionViewExtensions::EditmodeHelper
3
+ include ActionView::Helpers::TagHelper
4
+ include ActionView::Context
4
5
 
5
6
  attr_accessor :identifier, :variable_values, :branch_id,
6
7
  :variable_fallbacks, :chunk_type, :project_id,
8
+ :url, :collection_id, :cache_identifier,
7
9
  :response
8
-
10
+
9
11
  attr_writer :content
10
12
 
11
13
  def initialize(identifier, **options)
12
14
  @identifier = identifier
13
15
  @branch_id = options[:branch_id].presence
16
+ @project_id = Editmode.project_id
14
17
  @variable_values = options[:variables].presence || {}
15
- get_content
18
+ @raw = options[:raw].present?
19
+
20
+ branch_params = branch_id.present? ? "branch_id=#{branch_id}" : ""
21
+ @url = "#{api_root_url}/chunks/#{identifier}?project_id=#{project_id}&#{branch_params}"
22
+ @cache_identifier = set_cache_identifier(identifier)
23
+
24
+ if options[:response].present?
25
+ @response = options[:response]
26
+ set_response_attributes!
27
+ else
28
+ get_content
29
+ end
16
30
  end
17
31
 
18
- def field(field = nil)
32
+ def field(field = nil)
19
33
  # Field ID can be a slug or field_name
20
34
  if chunk_type == 'collection_item'
21
35
  if field.present?
22
- field.downcase!
23
- field_content = @content.detect {|f| f["custom_field_identifier"].downcase == field || f["custom_field_name"].downcase == field }
24
- if field_content.present?
25
- result = field_content['content']
26
- result = variable_parse!(result, variable_fallbacks, variable_values)
36
+ field_chunk = field_chunk(field)
37
+ if field_chunk.present?
38
+ result = field_chunk['content']
39
+ result = variable_parse!(result, variable_fallbacks, variable_values, @raw)
27
40
  else
28
41
  raise no_response_received(field)
29
42
  end
@@ -31,18 +44,33 @@ module Editmode
31
44
  raise require_field_id
32
45
  end
33
46
  else
34
- raise NoMethodError.new "undefined method 'field` for chunk_type: #{chunk_type} \n"
47
+ raise "undefined method 'field` for chunk_type: #{chunk_type} \n"
35
48
  end
36
- result || @content
49
+ result ||= @content
50
+ result.try(:html_safe)
51
+ end
52
+
53
+ def field_chunk(field)
54
+ field.downcase!
55
+ @content.detect {|f| f["custom_field_identifier"].downcase == field || f["custom_field_name"].downcase == field }
37
56
  end
38
57
 
39
58
  def content
40
- raise NoMethodError.new "undefined method 'content` for chunk_type: collection_item \nDid you mean? field" if chunk_type == 'collection_item'
59
+ raise "undefined method 'content` for chunk_type: collection_item \nDid you mean? field" if chunk_type == 'collection_item'
41
60
 
42
- variable_parse!(@content, variable_fallbacks, variable_values)
61
+ result = variable_parse!(@content, variable_fallbacks, variable_values, @raw)
62
+ result.try(:html_safe)
43
63
  end
44
64
 
45
65
  private
66
+ # Todo: Transfer to helper utils
67
+ def api_root_url
68
+ ENV["EDITMODE_OVERRIDE_API_URL"] || "https://api.editmode.com"
69
+ end
70
+
71
+ def set_cache_identifier(id)
72
+ "chunk_#{project_id}#{branch_id}#{id}"
73
+ end
46
74
 
47
75
  def json?(json)
48
76
  JSON.parse(json)
@@ -51,19 +79,39 @@ module Editmode
51
79
  return false
52
80
  end
53
81
 
54
- def get_content
55
- branch_params = branch_id.present? ? "branch_id=#{branch_id}" : ""
56
- url = "#{api_root_url}/chunks/#{identifier}?project_id=#{Editmode.project_id}&#{branch_params}"
82
+ def variable_parse!(content, variables = {}, values = {}, raw = true)
83
+ content = ActionController::Base.helpers.sanitize(content)
84
+ tokens = content.scan(/\{{(.*?)\}}/)
85
+ if tokens.any?
86
+ tokens.flatten!
87
+ tokens.each do |token|
88
+ token_value = values[token.to_sym] || variables[token] || ""
89
+ sanitized_value = ActionController::Base.helpers.sanitize(token_value)
90
+
91
+ unless raw
92
+ sanitized_value = content_tag("em-var", :data => {chunk_variable: token, chunk_variable_value: sanitized_value}) do
93
+ sanitized_value
94
+ end
95
+ end
96
+
97
+ content.gsub!("{{#{token}}}", sanitized_value)
98
+ end
99
+ end
57
100
 
58
- cache_identifier = "chunk_value_#{identifier}#{branch_id}"
59
- cached_content_present = Rails.cache.exist?(cache_identifier)
101
+ content
102
+ end
60
103
 
61
- if !cached_content_present
104
+ def cached?
105
+ Rails.cache.exist?(cache_identifier)
106
+ end
107
+
108
+ def get_content
109
+ if !cached?
62
110
  http_response = HTTParty.get(url)
63
111
  response_received = true if http_response.code == 200
64
112
  end
65
113
 
66
- if !cached_content_present && !response_received
114
+ if !cached? && !response_received
67
115
  raise no_response_received(identifier)
68
116
  else
69
117
  cached_response = Rails.cache.fetch(cache_identifier) do
@@ -71,12 +119,15 @@ module Editmode
71
119
  end
72
120
 
73
121
  @response = json?(cached_response) ? JSON.parse(cached_response) : cached_response
122
+ set_response_attributes!
123
+ end
124
+ end
74
125
 
75
- @content = response['content']
76
- @chunk_type = response['chunk_type']
77
- @project_id = response['project_id']
78
- @variable_fallbacks = response['variable_fallbacks']
79
- end
126
+ def set_response_attributes!
127
+ @content = response['content']
128
+ @chunk_type = response['chunk_type']
129
+ @variable_fallbacks = response['variable_fallbacks'].presence || {}
130
+ @collection_id = response["collection"]["identifier"] if chunk_type == 'collection_item'
80
131
  end
81
132
 
82
133
  end
@@ -4,20 +4,20 @@ module Editmode
4
4
  def e(identifier, *args)
5
5
  field, options = parse_arguments(args)
6
6
  begin
7
- chunk = Editmode::ChunkValue.new(identifier, options)
8
-
7
+ chunk = Editmode::ChunkValue.new(identifier, options.merge({raw: true}))
8
+
9
9
  if chunk.chunk_type == 'collection_item'
10
10
  chunk.field(field)
11
11
  else
12
12
  chunk.content
13
13
  end
14
14
  rescue => er
15
- raise er
15
+ puts er
16
16
  end
17
17
  end
18
18
 
19
19
  def render_custom_field_raw(label, options={})
20
- e(@custom_field_chunk["identifier"], label, options)
20
+ e(@custom_field_chunk["identifier"], label, options.merge({response: @custom_field_chunk}))
21
21
  end
22
22
  alias_method :f, :render_custom_field_raw
23
23
 
@@ -1,3 +1,3 @@
1
1
  module Editmode
2
- VERSION = "1.1.7"
2
+ VERSION = "1.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: editmode
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.7
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Ennis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-03 00:00:00.000000000 Z
11
+ date: 2020-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler