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 +4 -4
- data/README.md +11 -10
- data/app/controllers/editmode_controller.rb +1 -2
- data/lib/editmode.rb +1 -1
- data/lib/editmode/action_view_extensions/editmode_helper.rb +49 -73
- data/lib/editmode/chunk_value.rb +76 -25
- data/lib/editmode/helper.rb +4 -4
- data/lib/editmode/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2beab37962d65855d3ecfd66b6d9731fd4f1826eac260d97a30d8c1b022b9ff8
|
4
|
+
data.tar.gz: b05b7f2425a796262ec31e2d8cc447405d9bb2ed339b37a6f71cc2d52cd10ad7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
83
|
-
<
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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.
|
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"}
|
data/lib/editmode.rb
CHANGED
@@ -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
|
-
|
58
|
+
concat(content_tag(:div, class: "chunks-collection-item--wrapper #{item_class}") do
|
59
|
+
yield
|
60
|
+
end)
|
56
61
|
end
|
57
|
-
|
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, " ".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
|
-
|
71
|
-
|
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
|
-
|
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
|
-
|
109
|
-
|
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
|
-
|
152
|
-
|
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
|
-
|
155
|
-
|
156
|
-
|
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
|
data/lib/editmode/chunk_value.rb
CHANGED
@@ -1,29 +1,42 @@
|
|
1
1
|
module Editmode
|
2
2
|
class ChunkValue
|
3
|
-
include
|
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
|
-
|
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
|
23
|
-
|
24
|
-
|
25
|
-
result =
|
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
|
47
|
+
raise "undefined method 'field` for chunk_type: #{chunk_type} \n"
|
35
48
|
end
|
36
|
-
result
|
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
|
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
|
55
|
-
|
56
|
-
|
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
|
-
|
59
|
-
|
101
|
+
content
|
102
|
+
end
|
60
103
|
|
61
|
-
|
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 !
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
data/lib/editmode/helper.rb
CHANGED
@@ -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
|
-
|
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
|
|
data/lib/editmode/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2020-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|