locomotivecms_steam 1.5.0.beta1 → 1.5.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +8 -6
- data/lib/locomotive/steam/adapters/filesystem.rb +5 -1
- data/lib/locomotive/steam/adapters/filesystem/sanitizer.rb +2 -0
- data/lib/locomotive/steam/adapters/filesystem/sanitizers/content_entry.rb +3 -0
- data/lib/locomotive/steam/adapters/filesystem/sanitizers/page.rb +22 -1
- data/lib/locomotive/steam/adapters/filesystem/sanitizers/section.rb +7 -2
- data/lib/locomotive/steam/adapters/filesystem/yaml_loader.rb +19 -7
- data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb +5 -1
- data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_type.rb +1 -1
- data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/page.rb +107 -26
- data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/site.rb +8 -0
- data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/translation.rb +8 -4
- data/lib/locomotive/steam/adapters/memory/condition.rb +1 -1
- data/lib/locomotive/steam/entities/content_entry.rb +21 -11
- data/lib/locomotive/steam/errors.rb +14 -0
- data/lib/locomotive/steam/liquid/drops/content_entry_collection.rb +26 -1
- data/lib/locomotive/steam/liquid/drops/section_block.rb +3 -7
- data/lib/locomotive/steam/liquid/tags/concerns/section.rb +10 -8
- data/lib/locomotive/steam/liquid/tags/consume.rb +1 -1
- data/lib/locomotive/steam/middlewares/section.rb +0 -4
- data/lib/locomotive/steam/middlewares/thread_safe.rb +4 -4
- data/lib/locomotive/steam/models/i18n_field.rb +4 -0
- data/lib/locomotive/steam/repositories/content_type_field_repository.rb +2 -2
- data/lib/locomotive/steam/repositories/content_type_field_select_option_repository.rb +4 -0
- data/lib/locomotive/steam/repositories/page_repository.rb +1 -1
- data/lib/locomotive/steam/services/content_entry_service.rb +19 -7
- data/lib/locomotive/steam/version.rb +1 -1
- data/locomotivecms_steam.gemspec +1 -0
- data/spec/fixtures/default/data/production/pages/fr/index.json +4 -0
- data/spec/fixtures/default/data/production/pages/fr/music.json +8 -0
- data/spec/fixtures/default/data/production/pages/fr/unknown.json +8 -0
- data/spec/fixtures/default/data/production/site.json +3 -0
- data/spec/fixtures/default/data/production/translations.json +6 -0
- data/spec/fixtures/default/data/staging/pages/fr/index.json +3 -0
- data/spec/unit/adapters/filesystem/sanitizers/section_spec.rb +1 -1
- data/spec/unit/adapters/filesystem/yaml_loaders/content_type_spec.rb +5 -1
- data/spec/unit/adapters/filesystem/yaml_loaders/page_spec.rb +23 -1
- data/spec/unit/adapters/filesystem/yaml_loaders/site_spec.rb +10 -0
- data/spec/unit/adapters/filesystem/yaml_loaders/translation_spec.rb +12 -0
- data/spec/unit/entities/content_entry_spec.rb +43 -5
- data/spec/unit/liquid/tags/consume_spec.rb +24 -0
- data/spec/unit/liquid/tags/sections_dropzone_spec.rb +0 -21
- data/spec/unit/repositories/content_entry_repository_spec.rb +9 -9
- data/spec/unit/repositories/content_type_field_repository_spec.rb +18 -0
- data/spec/unit/repositories/page_repository_spec.rb +1 -1
- metadata +28 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 612050310b274060e06a38a72ec026c69b071f3166d6453e2d7f4a8242a3cda1
|
4
|
+
data.tar.gz: 5d92a727d6a162872eddd102d560e0c7840a7fc5142a12907f19411e07793955
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9be228b111d043a33b745dcc7bdf7408cf3651d377183394d7c779067186c0e064f0fed97e66cceceeb791b8b1eeebc61af4e959342b0c6975e5720cf8a7ea7
|
7
|
+
data.tar.gz: cc472030e4d96fcd1ca0ef278fb8f9d4a58a502db6a06fad8d1ea1f733272329e057cbe57effa8d18cdb78ffa3bc14d1113181d7ed276d8266d97a65885ffd29
|
data/Gemfile.lock
CHANGED
@@ -12,7 +12,7 @@ GIT
|
|
12
12
|
PATH
|
13
13
|
remote: .
|
14
14
|
specs:
|
15
|
-
locomotivecms_steam (1.5.0.
|
15
|
+
locomotivecms_steam (1.5.0.beta2)
|
16
16
|
RedCloth (~> 4.3.2)
|
17
17
|
autoprefixer-rails (~> 8.0.0)
|
18
18
|
bcrypt (~> 3.1.11)
|
@@ -29,6 +29,7 @@ PATH
|
|
29
29
|
mimetype-fu (~> 0.1.2)
|
30
30
|
moneta (~> 1.0.0)
|
31
31
|
morphine (~> 0.1.1)
|
32
|
+
multi_json (~> 1.13.1)
|
32
33
|
nokogiri (~> 1.8.2)
|
33
34
|
pony (~> 1.12)
|
34
35
|
rack-cache (~> 1.7.0)
|
@@ -56,7 +57,7 @@ GEM
|
|
56
57
|
bcrypt (3.1.12)
|
57
58
|
bson (4.3.0)
|
58
59
|
chronic (0.10.2)
|
59
|
-
chunky_png (1.3.
|
60
|
+
chunky_png (1.3.11)
|
60
61
|
codeclimate-test-reporter (0.4.8)
|
61
62
|
simplecov (>= 0.7.1, < 1.0.0)
|
62
63
|
coffee-script (2.4.1)
|
@@ -97,7 +98,8 @@ GEM
|
|
97
98
|
haml (5.0.4)
|
98
99
|
temple (>= 0.8.0)
|
99
100
|
tilt
|
100
|
-
httparty (0.16.
|
101
|
+
httparty (0.16.3)
|
102
|
+
mime-types (~> 3.0)
|
101
103
|
multi_xml (>= 0.5.2)
|
102
104
|
i18n (1.1.0)
|
103
105
|
concurrent-ruby (~> 1.0)
|
@@ -113,7 +115,7 @@ GEM
|
|
113
115
|
locomotivecms-liquid (4.0.0)
|
114
116
|
locomotivecms-solid (4.0.1)
|
115
117
|
locomotivecms-liquid (~> 4.0.0)
|
116
|
-
mail (2.7.
|
118
|
+
mail (2.7.1)
|
117
119
|
mini_mime (>= 0.1.1)
|
118
120
|
memory_profiler (0.9.11)
|
119
121
|
mime-types (3.1)
|
@@ -129,7 +131,7 @@ GEM
|
|
129
131
|
morphine (0.1.1)
|
130
132
|
multi_json (1.13.1)
|
131
133
|
multi_xml (0.6.0)
|
132
|
-
nokogiri (1.8.
|
134
|
+
nokogiri (1.8.5)
|
133
135
|
mini_portile2 (~> 2.3.0)
|
134
136
|
nokogumbo (1.5.0)
|
135
137
|
nokogiri
|
@@ -190,7 +192,7 @@ GEM
|
|
190
192
|
tins (1.16.3)
|
191
193
|
tzinfo (1.2.5)
|
192
194
|
thread_safe (~> 0.1)
|
193
|
-
uglifier (4.1.
|
195
|
+
uglifier (4.1.20)
|
194
196
|
execjs (>= 0.3.0, < 3)
|
195
197
|
|
196
198
|
PLATFORMS
|
@@ -116,7 +116,7 @@ module Locomotive::Steam
|
|
116
116
|
|
117
117
|
def build_yaml_loaders
|
118
118
|
%i(sites pages content_types content_entries snippets sections translations theme_assets).inject({}) do |memo, name|
|
119
|
-
memo[name] = build_klass('YAMLLoaders', name).new(site_path)
|
119
|
+
memo[name] = build_klass('YAMLLoaders', name).new(site_path, env)
|
120
120
|
memo
|
121
121
|
end
|
122
122
|
end
|
@@ -137,5 +137,9 @@ module Locomotive::Steam
|
|
137
137
|
def site_path
|
138
138
|
options.respond_to?(:has_key?) ? options[:path] : options
|
139
139
|
end
|
140
|
+
|
141
|
+
def env
|
142
|
+
(options.respond_to?(:has_key?) ? options[:env] : nil) || :local
|
143
|
+
end
|
140
144
|
end
|
141
145
|
end
|
@@ -47,6 +47,9 @@ module Locomotive::Steam
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def set_id(entity)
|
50
|
+
# don't override the id if it was set from a MongoDB dump
|
51
|
+
return if entity._id =~ /[a-z0-9]{12,}/
|
52
|
+
|
50
53
|
if (slug = entity[:_slug]).respond_to?(:translations)
|
51
54
|
entity[:_id] = slug[locale]
|
52
55
|
else
|
@@ -20,6 +20,7 @@ module Locomotive::Steam
|
|
20
20
|
record_id(entity) # required to get the parent_id
|
21
21
|
|
22
22
|
locales.each do |locale|
|
23
|
+
set_automatic_translations(entity, locale)
|
23
24
|
set_default_redirect_type(entity, locale)
|
24
25
|
end
|
25
26
|
|
@@ -38,6 +39,7 @@ module Locomotive::Steam
|
|
38
39
|
|
39
40
|
use_default_locale_template_path(page, locale)
|
40
41
|
|
42
|
+
# make sure we'll deal with a Hash and not a string
|
41
43
|
transform_sections_content(page, locale)
|
42
44
|
end
|
43
45
|
end
|
@@ -88,6 +90,20 @@ module Locomotive::Steam
|
|
88
90
|
page[:fullpath][locale] = fullpath
|
89
91
|
end
|
90
92
|
|
93
|
+
def set_automatic_translations(page, locale)
|
94
|
+
return if locale == self.locale
|
95
|
+
|
96
|
+
if page[:template_path][locale].blank?
|
97
|
+
%i(
|
98
|
+
title slug fullpath template_path redirect_url
|
99
|
+
sections_content sections_dropzone_content
|
100
|
+
seo_title meta_description meta_keywords
|
101
|
+
).each do |name|
|
102
|
+
page[name][locale] ||= page[name][default_locale]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
91
107
|
def depth(page)
|
92
108
|
return page.depth if page.depth
|
93
109
|
|
@@ -143,7 +159,12 @@ module Locomotive::Steam
|
|
143
159
|
[:sections_dropzone_content, :sections_content].each do |name|
|
144
160
|
if content = page[name][locale]
|
145
161
|
return unless content.is_a?(String)
|
146
|
-
|
162
|
+
|
163
|
+
begin
|
164
|
+
page[name][locale] = MultiJson.load(content)
|
165
|
+
rescue MultiJson::ParseError => e
|
166
|
+
raise Locomotive::Steam::JsonParsingError.new(e, page.template_path[locale], content)
|
167
|
+
end
|
147
168
|
end
|
148
169
|
end
|
149
170
|
end
|
@@ -21,8 +21,13 @@ module Locomotive::Steam
|
|
21
21
|
|
22
22
|
json, template = match[:json], match[:template]
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
begin
|
25
|
+
entity.definition = MultiJson.load(json)
|
26
|
+
rescue MultiJson::ParseError => e
|
27
|
+
raise Locomotive::Steam::JsonParsingError.new(e, entity.template_path, json)
|
28
|
+
end
|
29
|
+
|
30
|
+
entity.template = template
|
26
31
|
end
|
27
32
|
|
28
33
|
def raise_parsing_error(entity, content)
|
@@ -4,20 +4,20 @@ module Locomotive::Steam
|
|
4
4
|
|
5
5
|
module YAMLLoader
|
6
6
|
|
7
|
-
|
7
|
+
extend Forwardable
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
def_delegators :@scope, :locales, :default_locale
|
10
|
+
|
11
|
+
attr_reader :site_path, :env
|
12
|
+
|
13
|
+
def initialize(site_path, env = :local)
|
14
|
+
@site_path, @env = site_path, env
|
11
15
|
end
|
12
16
|
|
13
17
|
def load(scope = nil)
|
14
18
|
@scope = scope
|
15
19
|
end
|
16
20
|
|
17
|
-
def default_locale
|
18
|
-
@scope.default_locale
|
19
|
-
end
|
20
|
-
|
21
21
|
def _load(path, frontmatter = false, &block)
|
22
22
|
if File.exists?(path)
|
23
23
|
yaml = File.open(path).read.force_encoding('utf-8')
|
@@ -46,6 +46,18 @@ module Locomotive::Steam
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
def safe_json_load(path)
|
50
|
+
return {} unless File.exists?(path)
|
51
|
+
|
52
|
+
json = File.read(path)
|
53
|
+
|
54
|
+
begin
|
55
|
+
MultiJson.load(json)
|
56
|
+
rescue MultiJson::ParseError => e
|
57
|
+
raise Locomotive::Steam::JsonParsingError.new(e, path, json)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
49
61
|
def template_extensions
|
50
62
|
@extensions ||= %w(liquid haml)
|
51
63
|
end
|
@@ -110,7 +110,11 @@ module Locomotive
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def path
|
113
|
-
|
113
|
+
return @path if @path # memoization
|
114
|
+
|
115
|
+
path = File.join(site_path, 'data', env.to_s, 'content_entries')
|
116
|
+
|
117
|
+
@path = File.exists?(path) ? path : File.join(site_path, 'data') # allow the legacy folder
|
114
118
|
end
|
115
119
|
|
116
120
|
def content_type
|
@@ -65,7 +65,7 @@ module Locomotive
|
|
65
65
|
options.each do |locale, values|
|
66
66
|
values.each_with_index do |name, position|
|
67
67
|
if (option = list.at(position)).nil?
|
68
|
-
list << { _id: position, name: { locale => name }, position: position }
|
68
|
+
list << { _id: position.to_s, name: { locale => name }, position: position }
|
69
69
|
else
|
70
70
|
option[:name][locale] = name
|
71
71
|
end
|
@@ -8,40 +8,107 @@ module Locomotive
|
|
8
8
|
|
9
9
|
include Adapters::Filesystem::YAMLLoader
|
10
10
|
|
11
|
+
# Basically Load all the pages from both the app/views/pages and data/<env>/pages folders
|
12
|
+
#
|
13
|
+
# The process of loading locally all the pages is pretty complex. Of course, it handles localized pages.
|
14
|
+
# It involves 2 main steps.
|
15
|
+
#
|
16
|
+
# 1/ load all the pages/layouts under app/views/pages. Because of legacy support,
|
17
|
+
# we still grab the data from the YAML header.
|
18
|
+
#
|
19
|
+
# 2/ load the localized content from the data/<env>/pages folder. The content is fetched
|
20
|
+
# from the Wagon sync command. 2 kind of pages are stored in this folder:
|
21
|
+
# - pages with a not null handle property. We call them core pages. They are not aimed
|
22
|
+
# to be deleted. When found, we merge their content with the original page found by process #1
|
23
|
+
# - pages without a handle and created from a layout. These pages don't own a liquid template.
|
24
|
+
# We just use the liquid template of the layout they belong to.
|
25
|
+
#
|
11
26
|
def load(scope)
|
12
27
|
super
|
28
|
+
|
29
|
+
@pages_by_fullpath = {}
|
30
|
+
@pages_by_handle = {}
|
31
|
+
|
32
|
+
# step #1 (cf description of the method)
|
13
33
|
load_tree
|
34
|
+
|
35
|
+
# step #2 (cf description of the method)
|
36
|
+
load_data
|
37
|
+
|
38
|
+
@pages_by_fullpath.values
|
14
39
|
end
|
15
40
|
|
16
41
|
private
|
17
42
|
|
18
|
-
def
|
19
|
-
|
43
|
+
def load_tree
|
44
|
+
# load the core pages and layouts from the app/views/pages folder
|
45
|
+
each_file do |filepath, fullpath, locale|
|
46
|
+
if leaf = @pages_by_fullpath[fullpath]
|
47
|
+
update(leaf, filepath, fullpath, locale)
|
48
|
+
else
|
49
|
+
leaf = build(filepath, fullpath, locale)
|
50
|
+
end
|
51
|
+
|
52
|
+
@pages_by_fullpath[fullpath] = leaf
|
53
|
+
@pages_by_handle[leaf[:handle]] = leaf if leaf[:handle].present?
|
54
|
+
end
|
55
|
+
|
56
|
+
each_directory do |filepath, fullpath, locale|
|
57
|
+
@pages_by_fullpath[fullpath] ||= build(filepath, fullpath, locale)
|
58
|
+
end
|
20
59
|
end
|
21
60
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
61
|
+
def load_data
|
62
|
+
Dir.glob(File.join(data_path, '**', '*.json')).each do |filepath|
|
63
|
+
filepath =~ /#{data_path}\/([a-z]+)\//
|
64
|
+
data = safe_json_load(filepath)
|
65
|
+
locale = $1.to_sym
|
25
66
|
|
26
|
-
|
27
|
-
update(leaf, filepath, fullpath, locale)
|
28
|
-
else
|
29
|
-
leaf = build(filepath, fullpath, locale)
|
30
|
-
end
|
67
|
+
next unless locales.include?($1.to_sym)
|
31
68
|
|
32
|
-
|
69
|
+
if data['handle'].present? # yeah, core page found!
|
70
|
+
attributes = @pages_by_handle[data['handle']]
|
71
|
+
else
|
72
|
+
@pages_by_fullpath[data['fullpath']] ||= {}
|
73
|
+
attributes = @pages_by_fullpath[data['fullpath']]
|
33
74
|
end
|
34
75
|
|
35
|
-
|
36
|
-
|
76
|
+
complete_attributes_from_data(attributes, data, locale)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def complete_attributes_from_data(attributes, data, locale)
|
81
|
+
return if attributes.nil? # shouldn't happen (undeleted page? local files out of date?)
|
82
|
+
|
83
|
+
# this is super important to handle correctly url type settings in sections
|
84
|
+
attributes[:_id] = data['id']
|
85
|
+
|
86
|
+
# required by pages which are not present locally
|
87
|
+
attributes[:_fullpath] = data['fullpath']
|
88
|
+
|
89
|
+
# set the attributes
|
90
|
+
%i(
|
91
|
+
title slug redirect_url seo_title meta_description meta_keywords
|
92
|
+
listed published position
|
93
|
+
sections_content sections_dropzone_content editable_elements raw_template
|
94
|
+
).each do |name|
|
95
|
+
next if (value = data[name.to_s]).nil?
|
96
|
+
|
97
|
+
if name == :editable_elements
|
98
|
+
update_editable_elements(attributes, value, locale)
|
99
|
+
elsif %i(listed published position).include?(name)
|
100
|
+
attributes[name] = value
|
101
|
+
elsif name != :raw_template || (name == :raw_template && data['handle'].blank?)
|
102
|
+
(attributes[name] ||= {})[locale] = value
|
37
103
|
end
|
38
|
-
end
|
104
|
+
end
|
39
105
|
end
|
40
106
|
|
41
107
|
def build(filepath, fullpath, locale)
|
42
|
-
slug
|
43
|
-
attributes
|
108
|
+
slug = fullpath.split('/').last
|
109
|
+
attributes = get_attributes(filepath, fullpath)
|
44
110
|
|
111
|
+
# use first the attributes of the liquid template
|
45
112
|
_attributes = {
|
46
113
|
title: { locale => attributes.delete(:title) || (default_locale == locale ? slug.humanize : nil) },
|
47
114
|
slug: { locale => attributes.delete(:slug) || slug.dasherize },
|
@@ -50,7 +117,10 @@ module Locomotive
|
|
50
117
|
_fullpath: fullpath
|
51
118
|
}
|
52
119
|
|
53
|
-
|
120
|
+
%i(
|
121
|
+
redirect_url seo_title meta_description meta_keywords
|
122
|
+
sections_content sections_dropzone_content
|
123
|
+
).each do |name|
|
54
124
|
_attributes[name] = { locale => attributes.delete(name) }
|
55
125
|
end
|
56
126
|
|
@@ -58,19 +128,22 @@ module Locomotive
|
|
58
128
|
end
|
59
129
|
|
60
130
|
def update(leaf, filepath, fullpath, locale)
|
61
|
-
slug
|
62
|
-
attributes
|
131
|
+
slug = fullpath.split('/').last
|
132
|
+
attributes = get_attributes(filepath, fullpath)
|
63
133
|
|
64
|
-
leaf[:title][locale]
|
65
|
-
leaf[:slug][locale]
|
134
|
+
leaf[:title][locale] ||= attributes.delete(:title) || slug.humanize
|
135
|
+
leaf[:slug][locale] ||= attributes.delete(:slug) || slug.dasherize
|
66
136
|
leaf[:template_path][locale] = template_path(filepath, attributes, locale)
|
67
137
|
|
68
|
-
[:redirect_url, :seo_title, :meta_description, :meta_keywords].each do |name|
|
69
|
-
leaf[name][locale] = attributes.delete(name)
|
70
|
-
end
|
71
|
-
|
72
138
|
update_editable_elements(leaf, attributes.delete(:editable_elements), locale)
|
73
139
|
|
140
|
+
%i(
|
141
|
+
redirect_url seo_title meta_description meta_keywords
|
142
|
+
sections_content sections_dropzone_content
|
143
|
+
).each do |name|
|
144
|
+
leaf[name][locale] ||= attributes.delete(name)
|
145
|
+
end
|
146
|
+
|
74
147
|
leaf.merge!(attributes)
|
75
148
|
end
|
76
149
|
|
@@ -148,7 +221,7 @@ module Locomotive
|
|
148
221
|
|
149
222
|
list.each do |name, content|
|
150
223
|
if el = find_editable_element(leaf, name)
|
151
|
-
el[:content][locale]
|
224
|
+
el[:content][locale] ||= content
|
152
225
|
else
|
153
226
|
leaf[:editable_elements] << build_editable_element(name, content, locale)
|
154
227
|
end
|
@@ -175,6 +248,14 @@ module Locomotive
|
|
175
248
|
attributes[:published] = false
|
176
249
|
end
|
177
250
|
|
251
|
+
def data_path
|
252
|
+
File.join(self.site_path, 'data', env.to_s, 'pages')
|
253
|
+
end
|
254
|
+
|
255
|
+
def path
|
256
|
+
@path ||= File.join(site_path, 'app', 'views', 'pages')
|
257
|
+
end
|
258
|
+
|
178
259
|
end
|
179
260
|
|
180
261
|
end
|
@@ -17,11 +17,19 @@ module Locomotive
|
|
17
17
|
|
18
18
|
attributes[:metafields_schema] = load_metafields_schema
|
19
19
|
|
20
|
+
attributes.merge!(load_from_env)
|
21
|
+
|
20
22
|
[attributes]
|
21
23
|
end
|
22
24
|
|
23
25
|
private
|
24
26
|
|
27
|
+
def load_from_env
|
28
|
+
return {} if env == :local
|
29
|
+
|
30
|
+
safe_json_load(File.join(site_path, 'data', env.to_s, 'site.json')).symbolize_keys
|
31
|
+
end
|
32
|
+
|
25
33
|
def load_metafields_schema
|
26
34
|
_load(File.join(site_path, 'config', 'metafields_schema.yml'))
|
27
35
|
end
|
@@ -16,15 +16,19 @@ module Locomotive
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def load_array
|
19
|
+
all = env == :local ? _load(path) : _load_from_env
|
20
|
+
|
19
21
|
[].tap do |array|
|
20
|
-
|
21
|
-
|
22
|
-
array << { key: key.to_s, values: HashConverter.to_string(values) }
|
23
|
-
end
|
22
|
+
(all || {}).each do |key, values|
|
23
|
+
array << { key: key.to_s, values: HashConverter.to_string(values) }
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
def _load_from_env
|
29
|
+
safe_json_load(File.join(site_path, 'data', env.to_s, 'translations.json'))
|
30
|
+
end
|
31
|
+
|
28
32
|
def path
|
29
33
|
File.join(site_path, 'config', 'translations.yml')
|
30
34
|
end
|
@@ -48,7 +48,7 @@ module Locomotive::Steam
|
|
48
48
|
protected
|
49
49
|
|
50
50
|
def entry_value(entry)
|
51
|
-
value = entry.send(@field) rescue nil # not
|
51
|
+
value = entry.send(@field) rescue nil # TODO: not safe to rely on rescue (hidden errors)
|
52
52
|
|
53
53
|
if value.respond_to?(:translations)
|
54
54
|
value[@locale]
|
@@ -95,7 +95,7 @@ module Locomotive::Steam
|
|
95
95
|
_attributes += content_type.persisted_field_names
|
96
96
|
|
97
97
|
_attributes.each do |name|
|
98
|
-
hash[name.to_s] = send(name)
|
98
|
+
hash[name.to_s] = send(name)
|
99
99
|
end
|
100
100
|
|
101
101
|
# errors?
|
@@ -121,6 +121,7 @@ module Locomotive::Steam
|
|
121
121
|
_cast_value(field)
|
122
122
|
rescue Exception => e
|
123
123
|
Locomotive::Common::Logger.info "[#{content_type.slug}][#{_label}] Unable to cast the \"#{name}\" field, reason: #{e.message}".yellow
|
124
|
+
puts e.message
|
124
125
|
nil
|
125
126
|
end
|
126
127
|
end
|
@@ -190,19 +191,28 @@ module Locomotive::Steam
|
|
190
191
|
end
|
191
192
|
|
192
193
|
def _cast_select(field)
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
194
|
+
options = field.select_options
|
195
|
+
|
196
|
+
if (_value = @attributes[:"#{field.name}_id"]).respond_to?(:translations)
|
197
|
+
# the field is localized, so get the labels in all the locales
|
198
|
+
# (2 different locales might point to different options)
|
199
|
+
if _value.default
|
200
|
+
# unique value for all the locales, so grab the option
|
201
|
+
name = options.by_id_or_name(_value.default)&.name
|
202
|
+
name&.duplicate(field.name)
|
203
|
+
else
|
204
|
+
@attributes[field.name] = _value.duplicate(field.name)
|
205
|
+
|
206
|
+
_cast_convertor(field.name, true) do |value, locale|
|
207
|
+
name = options.by_id_or_name(value)&.name
|
208
|
+
name.try(:[], locale)
|
209
|
+
end
|
201
210
|
end
|
202
211
|
else
|
203
|
-
# the field is not localized, we only have the id of the option
|
212
|
+
# the field is not localized, we only have the id of the option (or its name if a
|
213
|
+
# contact form submission in Wagon for instance),
|
204
214
|
# so just copy the labels (in all the locales) of the matching select option
|
205
|
-
if name =
|
215
|
+
if name = options.by_id_or_name(_value)&.name # this should either return an i18nField or nil
|
206
216
|
attributes[field.name] = name.dup
|
207
217
|
end
|
208
218
|
end
|
@@ -55,6 +55,20 @@ module Locomotive::Steam
|
|
55
55
|
|
56
56
|
end
|
57
57
|
|
58
|
+
class JsonParsingError < ParsingRenderingError
|
59
|
+
|
60
|
+
def initialize(error, file, source)
|
61
|
+
line = if error.message =~ /at line ([0-9]+)/
|
62
|
+
$1.to_i
|
63
|
+
else
|
64
|
+
0
|
65
|
+
end
|
66
|
+
|
67
|
+
super(error.message, file, source, line, error.backtrace)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
58
72
|
class ActionError < ParsingRenderingError
|
59
73
|
|
60
74
|
attr_accessor :action
|
@@ -82,13 +82,38 @@ module Locomotive
|
|
82
82
|
|
83
83
|
(content_type_repository.select_options(@content_type, name) || []).map do |option|
|
84
84
|
_option = Locomotive::Steam::Decorators::I18nDecorator.new(option, locale, default_locale)
|
85
|
-
_option
|
85
|
+
ContentTypeFieldSelectOption.new(_option)
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
89
|
end
|
90
90
|
|
91
91
|
end
|
92
|
+
|
93
|
+
class ContentTypeFieldSelectOption < ::Liquid::Drop
|
94
|
+
|
95
|
+
def initialize(option)
|
96
|
+
@option = option
|
97
|
+
end
|
98
|
+
|
99
|
+
def id
|
100
|
+
@option._id.to_s
|
101
|
+
end
|
102
|
+
|
103
|
+
def name
|
104
|
+
@option.name
|
105
|
+
end
|
106
|
+
|
107
|
+
def ==(other_object)
|
108
|
+
self.name == other_object
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_s
|
112
|
+
self.name
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
92
117
|
end
|
93
118
|
end
|
94
119
|
end
|
@@ -12,7 +12,7 @@ module Locomotive
|
|
12
12
|
@index = index
|
13
13
|
@definition = section.definition['blocks'].find do |block|
|
14
14
|
block['type'] == type
|
15
|
-
end
|
15
|
+
end || {}
|
16
16
|
end
|
17
17
|
|
18
18
|
def id
|
@@ -31,12 +31,8 @@ module Locomotive
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def locomotive_attributes
|
34
|
-
|
35
|
-
|
36
|
-
%(data-locomotive-block="#{value}")
|
37
|
-
else
|
38
|
-
''
|
39
|
-
end
|
34
|
+
value = "section-#{@context['section'].id}-block-#{id}"
|
35
|
+
%(data-locomotive-block="#{value}")
|
40
36
|
end
|
41
37
|
|
42
38
|
end
|
@@ -29,16 +29,18 @@ module Locomotive::Steam::Liquid::Tags::Concerns
|
|
29
29
|
editor_settings_lookup(template.root)
|
30
30
|
end
|
31
31
|
|
32
|
-
context
|
33
|
-
|
34
|
-
|
32
|
+
html = template.render(context)
|
33
|
+
section = context['section']
|
34
|
+
css_class = context['section_css_class']
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
tag_data = %(data-locomotive-section-type="#{section.type}")
|
36
|
+
# we need the section_css_class once
|
37
|
+
context.scopes.last.delete('section_css_class')
|
39
38
|
|
40
|
-
|
41
|
-
|
39
|
+
tag_id = %(id="locomotive-section-#{section.id}")
|
40
|
+
tag_class = %(class="#{['locomotive-section', section.css_class, css_class].compact.join(' ')}")
|
41
|
+
tag_data = %(data-locomotive-section-type="#{section.type}")
|
42
|
+
|
43
|
+
%(<div #{tag_id} #{tag_class} #{tag_data}>#{html}</div>)
|
42
44
|
end
|
43
45
|
|
44
46
|
# in order to enable string/text synchronization with the editor:
|
@@ -18,10 +18,6 @@ module Locomotive::Steam
|
|
18
18
|
request.get_header('HTTP_LOCOMOTIVE_SECTION_TYPE')
|
19
19
|
end
|
20
20
|
|
21
|
-
def section_finder
|
22
|
-
services.section_finder
|
23
|
-
end
|
24
|
-
|
25
21
|
def render(section_type)
|
26
22
|
document = Liquid::Template.parse(liquid_source(section_type))
|
27
23
|
document.render(liquid_context)
|
@@ -53,10 +53,6 @@ module Locomotive::Steam::Middlewares
|
|
53
53
|
@locale ||= env.fetch('steam.locale')
|
54
54
|
end
|
55
55
|
|
56
|
-
def liquid_assigns
|
57
|
-
@liquid_assigns ||= env.fetch('steam.liquid_assigns')
|
58
|
-
end
|
59
|
-
|
60
56
|
def locales
|
61
57
|
site.locales
|
62
58
|
end
|
@@ -83,6 +79,10 @@ module Locomotive::Steam::Middlewares
|
|
83
79
|
env['rack.session']
|
84
80
|
end
|
85
81
|
|
82
|
+
def liquid_assigns
|
83
|
+
@liquid_assigns ||= env.fetch('steam.liquid_assigns')
|
84
|
+
end
|
85
|
+
|
86
86
|
def live_editing?
|
87
87
|
!!env['steam.live_editing']
|
88
88
|
end
|
@@ -61,9 +61,9 @@ module Locomotive
|
|
61
61
|
query { where(required: true) }.all
|
62
62
|
end
|
63
63
|
|
64
|
-
def localized_names
|
64
|
+
def localized_names(include_select_field_id: true)
|
65
65
|
query { where(localized: true) }.all.map do |field|
|
66
|
-
field.type == :select ? [field.name, "#{field.name}_id"] : field.name
|
66
|
+
field.type == :select && include_select_field_id ? [field.name, "#{field.name}_id"] : field.name
|
67
67
|
end.flatten
|
68
68
|
end
|
69
69
|
|
@@ -8,7 +8,7 @@ module Locomotive
|
|
8
8
|
# Entity mapping
|
9
9
|
mapping :pages, entity: Page do
|
10
10
|
localized_attributes :title, :slug, :permalink,
|
11
|
-
:source, :raw_template, :template_path, :redirect_url, :fullpath,
|
11
|
+
:source, :raw_template, :template_path, :data_path, :redirect_url, :fullpath,
|
12
12
|
:sections_content, :sections_dropzone_content,
|
13
13
|
:seo_title, :meta_description, :meta_keywords
|
14
14
|
|
@@ -27,7 +27,9 @@ module Locomotive
|
|
27
27
|
# Warning: do not work with localized and file fields
|
28
28
|
def create(type_slug, attributes, as_json = false)
|
29
29
|
with_repository(type_slug) do |_repository|
|
30
|
-
|
30
|
+
_attributes = prepare_attributes(_repository.content_type, attributes)
|
31
|
+
|
32
|
+
entry = _repository.build(_attributes)
|
31
33
|
|
32
34
|
yield(entry) if block_given?
|
33
35
|
|
@@ -46,8 +48,10 @@ module Locomotive
|
|
46
48
|
# Warning: do not work with localized and file fields
|
47
49
|
def update(type_slug, id_or_slug, attributes, as_json = false)
|
48
50
|
with_repository(type_slug) do |_repository|
|
49
|
-
entry
|
50
|
-
|
51
|
+
entry = _repository.by_slug(id_or_slug) || _repository.find(id_or_slug)
|
52
|
+
_attributes = prepare_attributes(_repository.content_type, attributes)
|
53
|
+
|
54
|
+
decorated_entry = i18n_decorate { entry.change(_attributes) }
|
51
55
|
|
52
56
|
if validate(_repository, decorated_entry)
|
53
57
|
_repository.update(entry)
|
@@ -61,9 +65,10 @@ module Locomotive
|
|
61
65
|
|
62
66
|
def update_decorated_entry(decorated_entry, attributes)
|
63
67
|
with_repository(decorated_entry.content_type) do |_repository|
|
64
|
-
entry
|
68
|
+
entry = decorated_entry.__getobj__
|
69
|
+
_attributes = prepare_attributes(_repository.content_type, attributes)
|
65
70
|
|
66
|
-
entry.change(
|
71
|
+
entry.change(_attributes)
|
67
72
|
|
68
73
|
_repository.update(entry)
|
69
74
|
|
@@ -117,12 +122,19 @@ module Locomotive
|
|
117
122
|
as_json ? entry.as_json : entry
|
118
123
|
end
|
119
124
|
|
120
|
-
def
|
125
|
+
def prepare_attributes(content_type, attributes)
|
126
|
+
select_field_names = content_type.fields.selects.map(&:name)
|
127
|
+
|
121
128
|
attributes.each do |key, value|
|
122
129
|
next unless value.is_a?(String)
|
123
130
|
attributes[key] = Sanitize.clean(value, Sanitize::Config::BASIC)
|
124
131
|
end
|
125
|
-
|
132
|
+
|
133
|
+
# special case: select fields. <name> becomes <name>_id
|
134
|
+
attributes.map do |key, value|
|
135
|
+
_key = select_field_names.include?(key.to_s) ? "#{key}_id" : key
|
136
|
+
[_key, value]
|
137
|
+
end.to_h
|
126
138
|
end
|
127
139
|
|
128
140
|
def validate(_repository, entry)
|
data/locomotivecms_steam.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_dependency 'httparty', '~> 0.16.0'
|
28
28
|
spec.add_dependency 'chronic', '~> 0.10.2'
|
29
29
|
spec.add_dependency 'bcrypt', '~> 3.1.11'
|
30
|
+
spec.add_dependency 'multi_json', '~> 1.13.1'
|
30
31
|
|
31
32
|
spec.add_dependency 'rack-rewrite', '~> 1.5.1'
|
32
33
|
spec.add_dependency 'rack-cache', '~> 1.7.0'
|
@@ -57,7 +57,7 @@ LIQUID
|
|
57
57
|
let(:template_path) { 'spec/fixtures/errors/section_bad_json_content.liquid' }
|
58
58
|
|
59
59
|
it 'should throw an error' do
|
60
|
-
expect { subject }.to raise_error(
|
60
|
+
expect { subject }.to raise_error(Locomotive::Steam::JsonParsingError)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -29,7 +29,11 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentType do
|
|
29
29
|
|
30
30
|
subject { loader.send(:build_select_options_from_hash, options) }
|
31
31
|
|
32
|
-
it { is_expected.to eq [
|
32
|
+
it { is_expected.to eq [
|
33
|
+
{ _id: '0', name: { en: 'General', fr: 'Général' }, position: 0 },
|
34
|
+
{ _id: '1', name: { en: 'Gigs', fr: 'Concerts' }, position: 1 },
|
35
|
+
{ _id: '2', name: { en: 'Bands', fr: 'Groupes' }, position: 2 }]
|
36
|
+
}
|
33
37
|
|
34
38
|
end
|
35
39
|
|
@@ -10,7 +10,7 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::Page do
|
|
10
10
|
|
11
11
|
describe '#load' do
|
12
12
|
|
13
|
-
let(:scope) { instance_double('Scope', locale: :fr, default_locale: :en) }
|
13
|
+
let(:scope) { instance_double('Scope', locale: :fr, default_locale: :en, locales: [:en, :fr]) }
|
14
14
|
|
15
15
|
subject { loader.load(scope).sort { |a, b| a[:_fullpath] <=> b[:_fullpath] } }
|
16
16
|
|
@@ -25,6 +25,28 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::Page do
|
|
25
25
|
expect(subject[25][:template_path]).to eq(en: false)
|
26
26
|
end
|
27
27
|
|
28
|
+
context 'a different environment' do
|
29
|
+
|
30
|
+
let(:env) { :production }
|
31
|
+
let(:loader) { described_class.new(site_path, env) }
|
32
|
+
|
33
|
+
it 'completes the data with the ones from the production environment' do
|
34
|
+
expect(subject.size).to eq 36
|
35
|
+
expect(subject[21][:title]).to eq(en: 'Home page', fr: "Ma page d'accueil en production")
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'invalid json' do
|
39
|
+
|
40
|
+
let(:env) { :staging }
|
41
|
+
|
42
|
+
it 'raises a parsing exception' do
|
43
|
+
expect { subject }.to raise_exception(Locomotive::Steam::JsonParsingError)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
28
50
|
end
|
29
51
|
|
30
52
|
end
|
@@ -24,6 +24,16 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::Site do
|
|
24
24
|
|
25
25
|
end
|
26
26
|
|
27
|
+
context 'a different environment' do
|
28
|
+
|
29
|
+
let(:loader) { described_class.new(site_path, :production) }
|
30
|
+
|
31
|
+
it 'completes the data with the ones from the production environment' do
|
32
|
+
expect(subject[:name]).to eq('My awesome site')
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
27
37
|
end
|
28
38
|
|
29
39
|
end
|
@@ -20,6 +20,18 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::Translation do
|
|
20
20
|
expect(subject.first[:values]).to eq({ 'en' => 'Powered by', 'fr' => 'Propulsé par' })
|
21
21
|
end
|
22
22
|
|
23
|
+
context 'a different environment' do
|
24
|
+
|
25
|
+
let(:loader) { described_class.new(site_path, :production) }
|
26
|
+
|
27
|
+
it 'replaces the data with the ones from the production environment' do
|
28
|
+
expect(subject.size).to eq 1
|
29
|
+
expect(subject.first[:key]).to eq('hello_world')
|
30
|
+
expect(subject.first[:values]).to eq('en' => 'Hello world', 'fr' => 'Bonjour le monde')
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
23
35
|
end
|
24
36
|
|
25
37
|
end
|
@@ -230,11 +230,49 @@ describe Locomotive::Steam::ContentEntry do
|
|
230
230
|
end
|
231
231
|
|
232
232
|
context 'a select' do
|
233
|
-
let(:
|
234
|
-
let(:
|
235
|
-
let(:
|
236
|
-
|
237
|
-
|
233
|
+
let(:translations) { instance_double('Translations', translations: { en: 'Category #1', fr: 'Categorie #1' }) }
|
234
|
+
let(:option) { instance_double('SelectOption', name: translations) }
|
235
|
+
let(:options) { instance_double('SelectOptions') }
|
236
|
+
let(:field) { instance_double('Field', name: :my_field, type: :select, select_options: options) }
|
237
|
+
let(:attributes) { { my_field_id: attribute } }
|
238
|
+
|
239
|
+
context 'the attribute is not localized' do
|
240
|
+
|
241
|
+
let(:option) { instance_double('SelectOption', name: 'Category #1') }
|
242
|
+
let(:attribute) { 42 }
|
243
|
+
|
244
|
+
before { expect(options).to receive(:by_id_or_name).with(42).and_return(option) }
|
245
|
+
|
246
|
+
it { expect(subject).to eq('Category #1') }
|
247
|
+
end
|
248
|
+
|
249
|
+
context 'the attribute is localized' do
|
250
|
+
|
251
|
+
context 'the attribute has values in all the locales' do
|
252
|
+
|
253
|
+
let(:attribute) { instance_double('FieldValue', default: nil, translations: true) }
|
254
|
+
|
255
|
+
before do
|
256
|
+
expect(attribute).to receive(:duplicate).with(:my_field).and_return(translations)
|
257
|
+
expect(translations).to receive(:apply).and_return(translations)
|
258
|
+
end
|
259
|
+
|
260
|
+
it { expect(subject.translations).to eq({ en: 'Category #1', fr: 'Categorie #1' }) }
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'the attribute has the same value in all the locales' do
|
265
|
+
|
266
|
+
let(:attribute) { instance_double('FieldValue', default: 42, translations: true) }
|
267
|
+
|
268
|
+
before { expect(translations).to receive(:duplicate).with(:my_field).and_return(translations) }
|
269
|
+
before { expect(options).to receive(:by_id_or_name).with(42).and_return(option) }
|
270
|
+
|
271
|
+
it { expect(subject.translations).to eq({ en: 'Category #1', fr: 'Categorie #1' }) }
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
238
276
|
end
|
239
277
|
|
240
278
|
context 'a json' do
|
@@ -80,6 +80,30 @@ describe Locomotive::Steam::Liquid::Tags::Consume do
|
|
80
80
|
|
81
81
|
end
|
82
82
|
|
83
|
+
describe 'with an expires_in option' do
|
84
|
+
|
85
|
+
let(:assigns) { { 'secret_password' => 'bar' } }
|
86
|
+
let(:source) { "{% consume blog from \"http://blog.locomotiveapp.org/api/read\", username: 'foo', password: secret_password, expires_in: #{expires_in} %}{{ blog.title }}{% endconsume %}" }
|
87
|
+
let(:expires_in) { 42 }
|
88
|
+
|
89
|
+
it 'passes the expires_in value to the cache' do
|
90
|
+
expect(services.cache).to receive(:fetch).with('Steam-consume-d1249cd56af82e108d383f981ad953347dbb94dc', { expires_in: 42 }).and_return('Locomotive rocks!')
|
91
|
+
is_expected.to eq 'Locomotive rocks!'
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'expires_in set to 0 (so basically, meaning non cache at all)' do
|
95
|
+
|
96
|
+
let(:expires_in) { 0 }
|
97
|
+
|
98
|
+
it "doesn't pass the expires_in value to the cache" do
|
99
|
+
expect(services.cache).to receive(:fetch).with('Steam-consume-d1249cd56af82e108d383f981ad953347dbb94dc', { force: true }).and_return('Locomotive rocks!')
|
100
|
+
is_expected.to eq 'Locomotive rocks!'
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
83
107
|
describe 'timeout' do
|
84
108
|
|
85
109
|
let(:response) { { 'title' => 'first response' } }
|
@@ -80,27 +80,6 @@ describe Locomotive::Steam::Liquid::Tags::SectionsDropzone do
|
|
80
80
|
.strip.gsub(/\n\s+/, '')
|
81
81
|
end
|
82
82
|
|
83
|
-
context 'live editing is off' do
|
84
|
-
|
85
|
-
let(:live_editing) { false }
|
86
|
-
|
87
|
-
it 'renders the list of sections' do
|
88
|
-
is_expected.to eq <<-HTML
|
89
|
-
<div class="locomotive-sections">
|
90
|
-
<div id="locomotive-section-dropzone-0" class="locomotive-section" data-locomotive-section-type="hero">
|
91
|
-
<h1>Hello world</h1>
|
92
|
-
</div>
|
93
|
-
<div id="locomotive-section-dropzone-1" class="locomotive-section" data-locomotive-section-type="slideshow">
|
94
|
-
<div ><p>Slide 1</p></div>
|
95
|
-
<div ><p>Slide 2</p></div>
|
96
|
-
</div>
|
97
|
-
</div>
|
98
|
-
HTML
|
99
|
-
.strip.gsub(/\n\s+/, '')
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
83
|
end
|
105
84
|
|
106
85
|
end
|
@@ -248,27 +248,27 @@ describe Locomotive::Steam::ContentEntryRepository do
|
|
248
248
|
|
249
249
|
let(:options) {
|
250
250
|
[
|
251
|
-
instance_double('SelectOption1', _id: 0, name: instance_double('I18nField', :[] => 'cooking', translations: { 'en' => 'cooking' })),
|
252
|
-
instance_double('SelectOption2', _id: 1, name: instance_double('I18nField', :[] => 'wine', translations: { 'en' => 'wine' })),
|
253
|
-
instance_double('SelectOption3', _id: 2, name: instance_double('I18nField', :[] => 'bread', translations: { 'en' => 'bread' }))
|
251
|
+
instance_double('SelectOption1', _id: '0', name: instance_double('I18nField', :[] => 'cooking', translations: { 'en' => 'cooking' })),
|
252
|
+
instance_double('SelectOption2', _id: '1', name: instance_double('I18nField', :[] => 'wine', translations: { 'en' => 'wine' })),
|
253
|
+
instance_double('SelectOption3', _id: '2', name: instance_double('I18nField', :[] => 'bread', translations: { 'en' => 'bread' }))
|
254
254
|
]
|
255
255
|
}
|
256
256
|
|
257
257
|
let(:entries) do
|
258
258
|
[
|
259
|
-
{ content_type_id: 1, _position: 0, _label: 'Recipe #1', category_id: { 'en' => 0 } },
|
260
|
-
{ content_type_id: 1, _position: 1, _label: 'Recipe #2', category_id: { 'en' => 2 } },
|
261
|
-
{ content_type_id: 1, _position: 2, _label: 'Recipe #3', category_id: { 'en' => 2 } },
|
262
|
-
{ content_type_id: 1, _position: 3, _label: 'Recipe #4', category_id: { 'en' => 42 } } # unknown category
|
259
|
+
{ content_type_id: 1, _position: 0, _label: 'Recipe #1', category_id: { 'en' => '0' } },
|
260
|
+
{ content_type_id: 1, _position: 1, _label: 'Recipe #2', category_id: { 'en' => '2' } },
|
261
|
+
{ content_type_id: 1, _position: 2, _label: 'Recipe #3', category_id: { 'en' => '2' } },
|
262
|
+
{ content_type_id: 1, _position: 3, _label: 'Recipe #4', category_id: { 'en' => '42' } } # unknown category
|
263
263
|
]
|
264
264
|
end
|
265
265
|
|
266
266
|
before {
|
267
267
|
allow(content_type_repository).to receive(:select_options).and_return(options)
|
268
268
|
%w(cooking wine bread).each_with_index do |name, position|
|
269
|
-
allow(fields[:category].select_options).to receive(:
|
269
|
+
allow(fields[:category].select_options).to receive(:by_id_or_name).with(position.to_s).and_return(options.at(position))
|
270
270
|
end
|
271
|
-
allow(fields[:category].select_options).to receive(:
|
271
|
+
allow(fields[:category].select_options).to receive(:by_id_or_name).with('42').and_return(nil)
|
272
272
|
}
|
273
273
|
|
274
274
|
it { expect(subject.size).to eq 4 }
|
@@ -80,4 +80,22 @@ describe Locomotive::Steam::ContentTypeFieldRepository do
|
|
80
80
|
|
81
81
|
end
|
82
82
|
|
83
|
+
describe '#localized_names' do
|
84
|
+
|
85
|
+
let(:collection) { [{ name: 'name', type: 'string', localized: true }, { name: 'picture', type: 'file' }, { name: 'category', type: 'select', localized: true }] }
|
86
|
+
|
87
|
+
subject { repository.localized_names }
|
88
|
+
|
89
|
+
it { expect(subject).to eq(['name', 'category', 'category_id']) }
|
90
|
+
|
91
|
+
context 'without the select field id' do
|
92
|
+
|
93
|
+
subject { repository.localized_names(include_select_field_id: false) }
|
94
|
+
|
95
|
+
it { expect(subject).to eq(['name', 'category']) }
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
83
101
|
end
|
@@ -71,7 +71,7 @@ describe Locomotive::Steam::PageRepository do
|
|
71
71
|
it { expect(subject.templatized?).to eq true }
|
72
72
|
it { expect(subject.content_type_id).to eq 'articles' }
|
73
73
|
it { expect(subject.slug[:en]).to eq 'comments' }
|
74
|
-
it { expect(subject.slug[:fr]).to eq
|
74
|
+
it { expect(subject.slug[:fr]).to eq 'comments' }
|
75
75
|
it { expect(subject.fullpath[:en]).to eq 'articles/content_type_template/comments' }
|
76
76
|
|
77
77
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: locomotivecms_steam
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.0.
|
4
|
+
version: 1.5.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Didier Lafforgue
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2018-
|
14
|
+
date: 2018-12-10 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -153,6 +153,20 @@ dependencies:
|
|
153
153
|
- - "~>"
|
154
154
|
- !ruby/object:Gem::Version
|
155
155
|
version: 3.1.11
|
156
|
+
- !ruby/object:Gem::Dependency
|
157
|
+
name: multi_json
|
158
|
+
requirement: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - "~>"
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: 1.13.1
|
163
|
+
type: :runtime
|
164
|
+
prerelease: false
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - "~>"
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: 1.13.1
|
156
170
|
- !ruby/object:Gem::Dependency
|
157
171
|
name: rack-rewrite
|
158
172
|
requirement: !ruby/object:Gem::Requirement
|
@@ -709,7 +723,13 @@ files:
|
|
709
723
|
- spec/fixtures/default/data/bands.yml
|
710
724
|
- spec/fixtures/default/data/events.yml
|
711
725
|
- spec/fixtures/default/data/messages.yml
|
726
|
+
- spec/fixtures/default/data/production/pages/fr/index.json
|
727
|
+
- spec/fixtures/default/data/production/pages/fr/music.json
|
728
|
+
- spec/fixtures/default/data/production/pages/fr/unknown.json
|
729
|
+
- spec/fixtures/default/data/production/site.json
|
730
|
+
- spec/fixtures/default/data/production/translations.json
|
712
731
|
- spec/fixtures/default/data/songs.yml
|
732
|
+
- spec/fixtures/default/data/staging/pages/fr/index.json
|
713
733
|
- spec/fixtures/default/data/updates.yml
|
714
734
|
- spec/fixtures/default/public/fonts/chunkfive-webfont.eot
|
715
735
|
- spec/fixtures/default/public/fonts/chunkfive-webfont.svg
|
@@ -1007,7 +1027,13 @@ test_files:
|
|
1007
1027
|
- spec/fixtures/default/data/bands.yml
|
1008
1028
|
- spec/fixtures/default/data/events.yml
|
1009
1029
|
- spec/fixtures/default/data/messages.yml
|
1030
|
+
- spec/fixtures/default/data/production/pages/fr/index.json
|
1031
|
+
- spec/fixtures/default/data/production/pages/fr/music.json
|
1032
|
+
- spec/fixtures/default/data/production/pages/fr/unknown.json
|
1033
|
+
- spec/fixtures/default/data/production/site.json
|
1034
|
+
- spec/fixtures/default/data/production/translations.json
|
1010
1035
|
- spec/fixtures/default/data/songs.yml
|
1036
|
+
- spec/fixtures/default/data/staging/pages/fr/index.json
|
1011
1037
|
- spec/fixtures/default/data/updates.yml
|
1012
1038
|
- spec/fixtures/default/public/fonts/chunkfive-webfont.eot
|
1013
1039
|
- spec/fixtures/default/public/fonts/chunkfive-webfont.svg
|