scrivito_sdk 0.30.0 → 0.40.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/scrivito/objs_controller.rb +29 -20
- data/app/controllers/scrivito/ui_controller.rb +18 -0
- data/app/helpers/scrivito_helper.rb +21 -4
- data/app/views/scrivito/objs/obj.json.jbuilder +1 -0
- data/app/views/scrivito/objs/update.json.jbuilder +1 -1
- data/app/views/scrivito/ui/index.html.erb +13 -0
- data/config/ca-bundle.crt +565 -3
- data/config/routes.rb +4 -0
- data/lib/assets/javascripts/scrivito_sdk.js +28 -19545
- data/lib/assets/javascripts/scrivito_ui.js +30398 -0
- data/lib/assets/stylesheets/scrivito_sdk.css +228 -232
- data/lib/assets/stylesheets/scrivito_ui.css +3148 -0
- data/lib/generators/scrivito/install/install_generator.rb +4 -0
- data/lib/generators/scrivito/install/templates/app/views/layouts/scrivito_dialog.html.erb +13 -0
- data/lib/generators/scrivito/page/templates/details.html.erb +1 -1
- data/lib/generators/scrivito/widget/templates/details.html.erb +1 -1
- data/lib/generators/scrivito/widget/templates/show.html.erb +1 -1
- data/lib/generators/scrivito/widget/templates/thumbnail.html.erb +2 -2
- data/lib/generators/scrivito/widget/widget_generator.rb +12 -0
- data/lib/scrivito/attribute_content.rb +4 -5
- data/lib/scrivito/basic_obj.rb +47 -8
- data/lib/scrivito/basic_widget.rb +41 -14
- data/lib/scrivito/cache.rb +2 -0
- data/lib/scrivito/child_list_tag.rb +1 -1
- data/lib/scrivito/client_config.rb +9 -11
- data/lib/scrivito/cms_backend.rb +5 -4
- data/lib/scrivito/cms_field_tag.rb +6 -2
- data/lib/scrivito/cms_rest_api/attribute_serializer.rb +2 -0
- data/lib/scrivito/cms_rest_api/widget_extractor.rb +5 -5
- data/lib/scrivito/connection_manager.rb +1 -0
- data/lib/scrivito/controller_actions.rb +24 -3
- data/lib/scrivito/image_tag_helper.rb +0 -12
- data/lib/scrivito/layout_tags.rb +1 -8
- data/lib/scrivito/link_parser.rb +5 -0
- data/lib/scrivito/{memberships_collection.rb → membership_collection.rb} +2 -2
- data/lib/scrivito/obj_class.rb +3 -6
- data/lib/scrivito/{objs_collection.rb → obj_collection.rb} +1 -1
- data/lib/scrivito/obj_create_params_parser.rb +15 -0
- data/lib/scrivito/obj_params_parser.rb +37 -45
- data/lib/scrivito/obj_update_params_parser.rb +25 -0
- data/lib/scrivito/revision.rb +6 -2
- data/lib/scrivito/sdk_engine.rb +6 -1
- data/lib/scrivito/test_request.rb +4 -0
- data/lib/scrivito/uploaded_binary.rb +4 -0
- data/lib/scrivito/user.rb +8 -0
- data/lib/scrivito/widget_collection.rb +22 -0
- data/lib/scrivito/workspace.rb +11 -6
- metadata +17 -11
- data/app/views/scrivito/objs/copy.json.jbuilder +0 -1
- data/app/views/scrivito/objs/create.json.jbuilder +0 -1
- data/app/views/scrivito/objs/details.json.jbuilder +0 -1
- data/lib/scrivito/widget_field_params.rb +0 -61
@@ -22,6 +22,10 @@ module Scrivito
|
|
22
22
|
copy_file 'app/controllers/cms_controller.rb'
|
23
23
|
end
|
24
24
|
|
25
|
+
def copy_dialog_layout
|
26
|
+
copy_file 'app/views/layouts/scrivito_dialog.html.erb'
|
27
|
+
end
|
28
|
+
|
25
29
|
def copy_migration
|
26
30
|
migration_template 'scrivito/migrate/install_scrivito_migration.rb',
|
27
31
|
File.join(Scrivito::Configuration.migration_path, 'install_scrivito_migration.rb')
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<%= scrivito_head_tags %>
|
5
|
+
<%= stylesheet_link_tag 'application', media: 'all' %>
|
6
|
+
<%= csrf_meta_tags %>
|
7
|
+
</head>
|
8
|
+
<body class="scrivito_dialog">
|
9
|
+
<%= scrivito_body_tags %>
|
10
|
+
<%= yield %>
|
11
|
+
<%= javascript_include_tag 'application' %>
|
12
|
+
</body>
|
13
|
+
</html>
|
@@ -1 +1 @@
|
|
1
|
-
<%= scrivito_tag :div, @obj, :title %>
|
1
|
+
<b>Title:</b> <%= scrivito_tag :div, @obj, :title %>
|
@@ -1,2 +1,2 @@
|
|
1
|
-
This is the details view of the <%=
|
1
|
+
This is the details view of the <%= human_name %>.
|
2
2
|
Edit "app/views/<%= file_name %>/details.html.erb" to change its appearance.
|
@@ -1,2 +1,2 @@
|
|
1
|
-
This is the show view of the <%=
|
1
|
+
This is the show view of the <%= human_name %>.
|
2
2
|
Edit "app/views/<%= file_name %>/show.html.erb" to change its appearance.
|
@@ -1,3 +1,3 @@
|
|
1
|
-
<%%= scrivito_thumbnail '<%=
|
2
|
-
|
1
|
+
<%%= scrivito_thumbnail '<%= human_name %>' do %>
|
2
|
+
<!-- Add the detailed description of the widget here. -->
|
3
3
|
<%% end %>
|
@@ -23,6 +23,18 @@ module Scrivito
|
|
23
23
|
migration_template 'migration.erb',
|
24
24
|
File.join(Scrivito::Configuration.migration_path, "create_#{file_name}_migration.rb")
|
25
25
|
end
|
26
|
+
|
27
|
+
def file_name
|
28
|
+
super.ends_with?('_widget') ? super : "#{super}_widget"
|
29
|
+
end
|
30
|
+
|
31
|
+
def class_name
|
32
|
+
super.ends_with?('Widget') ? super : "#{super}Widget"
|
33
|
+
end
|
34
|
+
|
35
|
+
def human_name
|
36
|
+
class_name.underscore.humanize
|
37
|
+
end
|
26
38
|
end
|
27
39
|
end
|
28
40
|
end
|
@@ -59,16 +59,15 @@ module AttributeContent
|
|
59
59
|
has_attribute?(key) ? read_attribute(key) : nil
|
60
60
|
end
|
61
61
|
|
62
|
-
# Hook method to control which widget classes should be available for this page
|
63
|
-
# Override it to allow only certain classes or none.
|
62
|
+
# Hook method to control which widget classes should be available for this page
|
63
|
+
# or widget. Override it to allow only certain classes or none.
|
64
64
|
# Must return either +NilClass+, or +Array+.
|
65
65
|
#
|
66
|
-
# If +nil+ is returned (default), then all widget classes will be available for this page.
|
66
|
+
# If +nil+ is returned (default), then all widget classes will be available for this page or widget.
|
67
67
|
#
|
68
68
|
# If +Array+ is returned, then it should include desired class names.
|
69
69
|
# Each class name must be either a +String+ or a +Symbol+.
|
70
|
-
# Only
|
71
|
-
# Order of the class names will be preserved.
|
70
|
+
# Only these class names will be available and their order will be preserved.
|
72
71
|
#
|
73
72
|
# @param [String] field_name Name of the widget field.
|
74
73
|
# @return [nil, Array<Symbol, String>]
|
data/lib/scrivito/basic_obj.rb
CHANGED
@@ -76,12 +76,12 @@ module Scrivito
|
|
76
76
|
# @example Arrays of {String Strings} allow you to set multi enum fields
|
77
77
|
# Obj.create(:tags => ["ruby", "rails"])
|
78
78
|
#
|
79
|
-
# @example Simply pass an Array of {Scrivito::BasicWidget Widgets} to change a widget field. See {Scrivito::BasicWidget#
|
79
|
+
# @example Simply pass an Array of {Scrivito::BasicWidget Widgets} to change a widget field. See {Scrivito::BasicWidget#copy Widget#copy} on how to copy a widget.
|
80
80
|
# # Add new widgets
|
81
81
|
# Obj.create(:widgets => [Widget.new(_obj_class: 'TitleWidget', title: 'My Title')])
|
82
82
|
#
|
83
|
-
# # Add a widget
|
84
|
-
# Obj.create(:widgets => [another_obj.widgets.first.
|
83
|
+
# # Add a widget copy
|
84
|
+
# Obj.create(:widgets => [another_obj.widgets.first.copy])
|
85
85
|
#
|
86
86
|
# # Changing a widget field
|
87
87
|
# obj.update(:widgets => [obj.widgets.first])
|
@@ -304,7 +304,7 @@ module Scrivito
|
|
304
304
|
self
|
305
305
|
end
|
306
306
|
|
307
|
-
#
|
307
|
+
# Creates a copy of the +Obj+.
|
308
308
|
# @api public
|
309
309
|
# @param [Hash] options
|
310
310
|
# @option options [String,Symbol] :_path (nil) the path of the copy.
|
@@ -315,7 +315,7 @@ module Scrivito
|
|
315
315
|
# @example Copy a blog post.
|
316
316
|
# blog_post = Obj.find_by_path('/blog/first_post')
|
317
317
|
# blog_post.copy(_path: '/blog/second_post')
|
318
|
-
def copy(options)
|
318
|
+
def copy(options={})
|
319
319
|
options = options.stringify_keys.assert_valid_keys('_path', '_id', '_permalink')
|
320
320
|
json = workspace.api_request(:post, '/objs', obj: copyable_attributes.merge(options))
|
321
321
|
self.class.find(json['_id'])
|
@@ -390,7 +390,7 @@ module Scrivito
|
|
390
390
|
BasicObj.find_by_path('/') or raise ResourceNotFound,
|
391
391
|
'"Obj.root" not found: There is no "Obj" with path "/". '\
|
392
392
|
'Maybe you forgot the migration when setting up your Scrivito application? '\
|
393
|
-
'Try "rake scrivito:migrate
|
393
|
+
'Try "bundle exec rake scrivito:migrate scrivito:migrate:publish".'
|
394
394
|
end
|
395
395
|
|
396
396
|
# Returns the homepage obj. This can be overwritten in your application's +Obj+.
|
@@ -720,6 +720,17 @@ module Scrivito
|
|
720
720
|
instantiate_widget(widget_id, widget_data) if widget_data
|
721
721
|
end
|
722
722
|
|
723
|
+
# @api public
|
724
|
+
# Allows accessing the {Scrivito::BasicWidget Widgets} of this Obj
|
725
|
+
#
|
726
|
+
# @example Access a widget by its id
|
727
|
+
# obj.widgets['widget_id']
|
728
|
+
#
|
729
|
+
# @return [Scrivito::WidgetCollection]
|
730
|
+
def widgets
|
731
|
+
@widgets ||= WidgetCollection.new(self)
|
732
|
+
end
|
733
|
+
|
723
734
|
# for internal testing purposes only
|
724
735
|
def blob_id
|
725
736
|
find_blob.try(:id)
|
@@ -756,6 +767,30 @@ module Scrivito
|
|
756
767
|
end
|
757
768
|
end
|
758
769
|
|
770
|
+
def restore_widget(widget_id)
|
771
|
+
Workspace.current.assert_revertable
|
772
|
+
|
773
|
+
return if modification == Modification::UNMODIFIED
|
774
|
+
if modification == Modification::DELETED
|
775
|
+
raise ScrivitoError, 'Can not restore a widget inside a deleted obj'
|
776
|
+
end
|
777
|
+
|
778
|
+
unless widget = in_revision(Workspace.current.base_revision).widgets[widget_id]
|
779
|
+
raise ResourceNotFound, "Could not find widget with id #{widget_id}"
|
780
|
+
end
|
781
|
+
|
782
|
+
container = widget.container
|
783
|
+
if container.kind_of?(BasicWidget) && !widgets[container.id]
|
784
|
+
raise ScrivitoError, 'Can not restore a widget inside a deleted widget'
|
785
|
+
end
|
786
|
+
|
787
|
+
widget_copy = widget.copy_for_restore(read_widget_pool.keys)
|
788
|
+
field_name = widget.container_field_name
|
789
|
+
current_container = widgets[container.id] || self
|
790
|
+
current_container.update(field_name =>
|
791
|
+
current_container[field_name].insert(widget.container_field_index, widget_copy))
|
792
|
+
end
|
793
|
+
|
759
794
|
def mark_resolved
|
760
795
|
workspace.api_request(:put, "/objs/#{id}", obj: {_conflicts: nil})
|
761
796
|
reload
|
@@ -802,10 +837,13 @@ module Scrivito
|
|
802
837
|
raise ScrivitoError.new('Could not generate a new unused widget id')
|
803
838
|
end
|
804
839
|
|
840
|
+
#
|
805
841
|
# Generates a +Hash+ containing all public attributes. The hash will _not_ include attributes,
|
806
842
|
# which are read-only or used for internal purpose.
|
807
|
-
#
|
843
|
+
#
|
844
|
+
# @api private
|
808
845
|
# @return [Hash] a hash containing all public attributes.
|
846
|
+
#
|
809
847
|
# @example
|
810
848
|
# old_obj = Obj.homepage
|
811
849
|
# attrs = old_obj.to_h
|
@@ -816,12 +854,13 @@ module Scrivito
|
|
816
854
|
# new_obj = Obj.create(attrs)
|
817
855
|
# puts new_obj == old_obj
|
818
856
|
# #=> true
|
857
|
+
#
|
819
858
|
def to_h
|
820
859
|
data_from_cms.to_h.except(*GENERATED_ATTRIBUTES)
|
821
860
|
end
|
822
861
|
|
823
862
|
def parent_path
|
824
|
-
unless root?
|
863
|
+
unless root? || path.nil?
|
825
864
|
path.gsub(/\/[^\/]+$/, '').presence || '/'
|
826
865
|
end
|
827
866
|
end
|
@@ -66,25 +66,42 @@ class BasicWidget
|
|
66
66
|
container.update(container_field_name => new_widget_list)
|
67
67
|
end
|
68
68
|
|
69
|
-
# Clones the {Scrivito::BasicWidget Widget}. The clone gets all
|
70
|
-
# attributes of the original widget except nested widget attributes.
|
71
|
-
# The clone is not attached to an {Scrivito::BasicObj Obj} initially.
|
72
|
-
# It only becomes usable by assigning it to a widget attribute of an Obj.
|
73
69
|
#
|
74
|
-
#
|
75
|
-
# # From another_obj, take the first widget in my_widgets,
|
76
|
-
# # and put a clone in obj's my_widgets.
|
77
|
-
# obj.update(my_widgets: [another_obj.my_widgets.first.clone])
|
70
|
+
# Create a copy of a {Scrivito::BasicWidget Widget}.
|
78
71
|
#
|
79
72
|
# @api public
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
73
|
+
#
|
74
|
+
# The copy will have all attributes of the original widget including its widgets.
|
75
|
+
# Its attributes can be accessed only after it has been stored in a widget field of an
|
76
|
+
# {Scrivito::BasicObj Obj}, since initially the copy is not stored in any widget field.
|
77
|
+
#
|
78
|
+
# @example Duplicate the first widget in field +my_widget+
|
79
|
+
# obj.update(my_widgets: obj.my_widgets.push(obj.my_widgets.first.copy))
|
80
|
+
#
|
81
|
+
def copy
|
82
|
+
attrs = {}
|
83
|
+
each_custom_attribute do |attr_name, attr_value, attr_type|
|
84
|
+
attrs[attr_name] = attr_type == 'widget' ? attr_value.map(&:copy) : attr_value
|
85
|
+
end
|
86
|
+
self.class.new(attrs)
|
87
|
+
end
|
88
|
+
|
89
|
+
def copy_for_restore(referenced_ids)
|
90
|
+
attrs = {}
|
91
|
+
each_custom_attribute do |attr_name, attr_value, attr_type|
|
92
|
+
attrs[attr_name] = if attr_type == 'widget'
|
93
|
+
attr_value.reject { |widget| referenced_ids.include?(widget.id) }
|
94
|
+
.map { |widget| widget.copy_for_restore(referenced_ids) }
|
95
|
+
else
|
96
|
+
attr_value
|
85
97
|
end
|
86
98
|
end
|
87
|
-
|
99
|
+
attrs['_id'] = id
|
100
|
+
self.class.new(attrs)
|
101
|
+
end
|
102
|
+
|
103
|
+
def clone
|
104
|
+
raise "The method `clone' was removed. Please use `copy' instead"
|
88
105
|
end
|
89
106
|
|
90
107
|
def id
|
@@ -193,6 +210,10 @@ class BasicWidget
|
|
193
210
|
@container_field_name || cache_container_and_field_name_for_widget.second
|
194
211
|
end
|
195
212
|
|
213
|
+
def container_field_index
|
214
|
+
container[container_field_name].index(self)
|
215
|
+
end
|
216
|
+
|
196
217
|
def has_attribute?(key)
|
197
218
|
key.to_s == '_obj_class' || super
|
198
219
|
end
|
@@ -265,6 +286,12 @@ class BasicWidget
|
|
265
286
|
def cache_container_and_field_name_for_widget
|
266
287
|
@cache_container_and_field_name_for_widget ||= obj.container_and_field_name_for_widget(id)
|
267
288
|
end
|
289
|
+
|
290
|
+
def each_custom_attribute
|
291
|
+
data_from_cms.all_custom_attributes.each do |attr_name|
|
292
|
+
yield attr_name, read_attribute(attr_name), type_of_attribute(attr_name)
|
293
|
+
end
|
294
|
+
end
|
268
295
|
end
|
269
296
|
|
270
297
|
end
|
data/lib/scrivito/cache.rb
CHANGED
@@ -11,7 +11,7 @@ class ChildListTag < Struct.new(:tag_name, :obj, :field_name, :view)
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def options
|
14
|
-
return {} unless user_present?
|
14
|
+
return {} unless user_present? || obj.path.nil?
|
15
15
|
|
16
16
|
options = {
|
17
17
|
'private-child-list-allowed-classes' => Obj.valid_page_classes_beneath(obj.path).to_json,
|
@@ -7,9 +7,9 @@ class ClientConfig < Struct.new(:obj, :editing_context, :lookup_context, :resour
|
|
7
7
|
|
8
8
|
def to_json
|
9
9
|
config = {}
|
10
|
+
config[:current_page] = current_page_config
|
10
11
|
config[:editing_context] = editing_context_config
|
11
12
|
config[:i18n] = i18n_config
|
12
|
-
config[:obj] = obj_config
|
13
13
|
config[:resource_dialog] = resource_dialog_config
|
14
14
|
config[:user] = user_config
|
15
15
|
config[:user_permissions] = user_permissions_config
|
@@ -39,18 +39,16 @@ class ClientConfig < Struct.new(:obj, :editing_context, :lookup_context, :resour
|
|
39
39
|
{locale: I18n.locale}
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
42
|
+
def current_page_config
|
43
43
|
if obj
|
44
44
|
{
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
restriction_messages: editor.restriction_messages_for(obj),
|
53
|
-
}
|
45
|
+
id: obj.id,
|
46
|
+
obj_class_name: obj.obj_class_name,
|
47
|
+
has_children: obj.children.any?,
|
48
|
+
has_conflict: obj.has_conflict?,
|
49
|
+
has_details_view: obj_has_details_view?,
|
50
|
+
modification: modification(obj),
|
51
|
+
restriction_messages: editor.restriction_messages_for(obj),
|
54
52
|
}
|
55
53
|
else
|
56
54
|
{}
|
data/lib/scrivito/cms_backend.rb
CHANGED
@@ -246,7 +246,7 @@ module Scrivito
|
|
246
246
|
end
|
247
247
|
|
248
248
|
def blob_metadata_cache_key(id)
|
249
|
-
"blob_metadata/#{
|
249
|
+
"blob_metadata/#{id}"
|
250
250
|
end
|
251
251
|
|
252
252
|
def find_obj_data_filtering_deleted_by(revision, index, keys, include_deleted)
|
@@ -312,9 +312,10 @@ module Scrivito
|
|
312
312
|
include_deleted: true
|
313
313
|
}
|
314
314
|
|
315
|
-
#
|
316
|
-
#
|
317
|
-
|
315
|
+
# A base revision doesn't have a directly corresponding workspace. Instead it uses its
|
316
|
+
# derivative workspace as fallback to access the contents. Thus fallback workspace of a base
|
317
|
+
# revision may not be used for backend requests.
|
318
|
+
params[:workspace_id] = revision.workspace.id unless revision.base?
|
318
319
|
|
319
320
|
params
|
320
321
|
end
|
@@ -43,7 +43,7 @@ class CmsFieldTag < Struct.new(
|
|
43
43
|
|
44
44
|
if FIELD_TYPES_WITH_ORIGINAL_CONTENT.include?(field_type)
|
45
45
|
original_value = view.scrivito_value(current_value)
|
46
|
-
original_content = original_content(field_type, original_value)
|
46
|
+
original_content = original_content(field_type, original_value, current_value)
|
47
47
|
encoded_content = Base64.strict_encode64(MultiJson.encode(original_content))
|
48
48
|
options['private-field-original-content'] = encoded_content
|
49
49
|
end
|
@@ -99,6 +99,8 @@ class CmsFieldTag < Struct.new(
|
|
99
99
|
referencelist
|
100
100
|
string
|
101
101
|
text
|
102
|
+
binary
|
103
|
+
date
|
102
104
|
]
|
103
105
|
|
104
106
|
def authenticated_editor?
|
@@ -109,10 +111,12 @@ class CmsFieldTag < Struct.new(
|
|
109
111
|
EditingContextMiddleware.from_request(view.request)
|
110
112
|
end
|
111
113
|
|
112
|
-
def original_content(field_type, field_value)
|
114
|
+
def original_content(field_type, field_value, raw_value)
|
113
115
|
case field_type
|
114
116
|
when 'reference' then field_value.try(:id)
|
115
117
|
when 'referencelist' then field_value.map(&:id)
|
118
|
+
when 'binary' then field_value && {}
|
119
|
+
when 'date' then raw_value.try(:utc).try(:iso8601)
|
116
120
|
else field_value
|
117
121
|
end
|
118
122
|
end
|
@@ -31,11 +31,7 @@ module Scrivito
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.attach_widget_to_obj(widget, obj)
|
34
|
-
widget.id =
|
35
|
-
obj.generate_widget_pool_id
|
36
|
-
else
|
37
|
-
BasicObj.generate_widget_pool_id
|
38
|
-
end
|
34
|
+
widget.id = widget.attributes_to_be_saved.delete('_id') || generate_widget_pool_id(obj)
|
39
35
|
widget.obj = obj
|
40
36
|
end
|
41
37
|
|
@@ -47,6 +43,10 @@ module Scrivito
|
|
47
43
|
end
|
48
44
|
end
|
49
45
|
end
|
46
|
+
|
47
|
+
def self.generate_widget_pool_id(obj)
|
48
|
+
obj.presence ? obj.generate_widget_pool_id : BasicObj.generate_widget_pool_id
|
49
|
+
end
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|