scrivito_sdk 1.8.1 → 1.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/scrivito/binary_redirect_controller.rb +0 -1
  3. data/app/controllers/scrivito/obj_class_controller.rb +18 -0
  4. data/app/controllers/scrivito/objs_controller.rb +6 -6
  5. data/app/controllers/scrivito/workspaces_controller.rb +2 -18
  6. data/app/views/scrivito/obj_class/thumbnails.json.jbuilder +1 -0
  7. data/app/views/scrivito/objs/valid_page_classes.json.jbuilder +1 -0
  8. data/config/ca-bundle.crt +1 -1
  9. data/config/precedence_routes.rb +7 -12
  10. data/lib/assets/javascripts/scrivito.js +101 -10
  11. data/lib/assets/javascripts/scrivito_ui_redirect.js +85 -6
  12. data/lib/assets/javascripts/scrivito_with_js_sdk.js +22205 -18338
  13. data/lib/assets/stylesheets/scrivito.css +1 -1
  14. data/lib/generators/scrivito/install/templates/app/models/image.rb +0 -5
  15. data/lib/scrivito/attribute_content.rb +5 -4
  16. data/lib/scrivito/base_widget_tag.rb +1 -0
  17. data/lib/scrivito/basic_obj.rb +21 -41
  18. data/lib/scrivito/basic_widget.rb +1 -21
  19. data/lib/scrivito/binary.rb +0 -7
  20. data/lib/scrivito/binary_routing.rb +5 -6
  21. data/lib/scrivito/child_list_tag.rb +8 -1
  22. data/lib/scrivito/cms_env.rb +6 -2
  23. data/lib/scrivito/cms_field_tag.rb +2 -0
  24. data/lib/scrivito/cms_routing.rb +25 -13
  25. data/lib/scrivito/configuration.rb +1 -4
  26. data/lib/scrivito/disable_browser_cache_for_ui_middleware.rb +19 -0
  27. data/lib/scrivito/editing_context.rb +4 -0
  28. data/lib/scrivito/editing_context_middleware.rb +5 -1
  29. data/lib/scrivito/obj_collection.rb +4 -0
  30. data/lib/scrivito/page_config.rb +1 -1
  31. data/lib/scrivito/preset_routes.rb +1 -1
  32. data/lib/scrivito/revision.rb +1 -1
  33. data/lib/scrivito/sdk_engine.rb +1 -0
  34. data/lib/scrivito/ui_config.rb +6 -42
  35. data/lib/scrivito/ui_obj_classes_json_formatter.rb +48 -0
  36. data/lib/scrivito/user.rb +3 -0
  37. data/lib/scrivito/user_definition.rb +1 -1
  38. data/lib/scrivito/workspace.rb +1 -1
  39. metadata +8 -10
  40. data/app/controllers/scrivito/completion_controller.rb +0 -12
  41. data/app/views/scrivito/completion/suggest.json.jbuilder +0 -1
  42. data/app/views/scrivito/objs/show.json.jbuilder +0 -2
  43. data/app/views/scrivito/webservice/workspaces.json.jbuilder +0 -1
  44. data/app/views/scrivito/workspaces/show.json.jbuilder +0 -1
  45. data/lib/assets/images/scrivito/source_type_invalid.png +0 -0
@@ -1,9 +1,4 @@
1
1
  class Image < Obj
2
2
  attribute :blob, :binary
3
3
  attribute :tags, :stringlist
4
-
5
- # activate image resizing and optimization
6
- def apply_image_transformation?
7
- true
8
- end
9
4
  end
@@ -4,7 +4,7 @@ module Scrivito
4
4
  # default values, restricting the types of widgets that may be added to a +widgetlist+
5
5
  # attribute, plus a couple of convenience methods.
6
6
  # @api public
7
- # @see http://scrivito.com/attribute-types Attributes and their type
7
+ # @see https://scrivito.com/attribute-types Attributes and their type
8
8
  #
9
9
  module AttributeContent
10
10
  ATTRIBUTE_TYPES = %w[
@@ -128,7 +128,8 @@ module AttributeContent
128
128
  # @api public
129
129
  # @param [String] field_name Name of the widget attribute.
130
130
  # @return [nil, Array<Class>]
131
- # @see http://scrivito.com/limiting-widget-and-page-types Limiting available widget and page types
131
+ # @see
132
+ # https://scrivito.com/limiting-widget-and-page-types Limiting available widget and page types
132
133
  #
133
134
  def valid_widget_classes_for(field_name)
134
135
  end
@@ -451,7 +452,7 @@ module AttributeContent
451
452
  # ImageWidget.attribute_definitions[:my_reference2].valid_classes
452
453
  # #=> [Image, Video]
453
454
  #
454
- # @see http://scrivito.com/default-attribute-values Specifying default attribute values
455
+ # @see https://scrivito.com/default-attribute-values Specifying default attribute values
455
456
  #
456
457
  def attribute(name, type, options = {})
457
458
  name, type, options = name.to_s, type.to_s, options
@@ -562,7 +563,7 @@ module AttributeContent
562
563
  # my_page = MyPage.create({_path: '/en/test'}, bob)
563
564
  # my_page.title # => 'Hier den Titel eingeben'
564
565
  #
565
- # @see http://scrivito.com/default-attribute-values Specifying default attribute values
566
+ # @see https://scrivito.com/default-attribute-values Specifying default attribute values
566
567
  #
567
568
  def default_for(attribute_name, &block)
568
569
  attribute_name = attribute_name.to_s
@@ -23,6 +23,7 @@ class BaseWidgetTag < Struct.new(
23
23
  options = {}
24
24
 
25
25
  if inplace_editing_allowed?
26
+ options['private-widget'] = true
26
27
  options['private-widget-id'] = widget.id
27
28
  options['widget-obj-class'] = widget.obj_class
28
29
  options['private-widget-description-for-editor'] = description_for_editor
@@ -16,7 +16,7 @@ module Scrivito
16
16
  # @note Please do not use {Scrivito::BasicObj} directly
17
17
  # as it is intended as an abstract class.
18
18
  # Always use {Obj} or a subclass of {Obj}.
19
- # @see http://scrivito.com/objects-widgets-classes CMS objects, widgets, and classes
19
+ # @see https://scrivito.com/objects-widgets-classes CMS objects, widgets, and classes
20
20
  # @api public
21
21
  #
22
22
  class BasicObj
@@ -581,21 +581,13 @@ module Scrivito
581
581
  blob_attribute_definition.present? && blob_attribute_definition.type == 'binary'
582
582
  end
583
583
 
584
- #
585
- # When delivering binary objects, this method decides whether the image transformations should
586
- # be applied by default.
587
584
  #
588
585
  # @api public
589
- #
590
- # By default, this method returns +false+.
591
- # Override it in subclasses to fit your needs.
592
- #
593
- # @note Only relevant for binary objects
594
- # @see Scrivito::Configuration.default_image_transformation=
595
- # @see Scrivito::Binary#transform
586
+ # @deprecated Has no effect anymore: Image transformation will be applied if possible.
596
587
  #
597
588
  def apply_image_transformation?
598
- false
589
+ Scrivito::Deprecation.warn(
590
+ 'Scrivito::BasicObj#apply_image_transformation? is deprecated and has no effect anymore.')
599
591
  end
600
592
 
601
593
  # Returns true if this Obj is the root Obj.
@@ -623,11 +615,11 @@ module Scrivito
623
615
  #
624
616
  # @return [Array<Obj>]
625
617
  def sorted_toclist
626
- if sortable_toclist?
627
- (child_order & toclist) + (toclist - child_order).sort_by(&:id)
628
- else
629
- toclist
630
- end
618
+ sort_toclist(toclist)
619
+ end
620
+
621
+ def sorted_toclist_including_deleted
622
+ sort_toclist(children_including_deleted.reject(&:binary?))
631
623
  end
632
624
 
633
625
  def sortable_toclist?
@@ -908,30 +900,6 @@ module Scrivito
908
900
  end
909
901
  end
910
902
 
911
- def restore_widget(widget_id)
912
- Workspace.current.assert_revertable
913
-
914
- return if modification == Modification::UNMODIFIED
915
- if modification == Modification::DELETED
916
- raise ScrivitoError, 'Can not restore a widget inside a deleted obj'
917
- end
918
-
919
- unless widget = in_revision(Workspace.current.base_revision).widgets[widget_id]
920
- raise ResourceNotFound, "Could not find widget with id #{widget_id}"
921
- end
922
-
923
- container = widget.container
924
- if container.kind_of?(BasicWidget) && !widgets[container.id]
925
- raise ScrivitoError, 'Can not restore a widget inside a deleted widget'
926
- end
927
-
928
- widget_copy = widget.copy_for_restore(read_widget_pool.keys)
929
- attribute_name = widget.container_attribute_name
930
- current_container = widgets[container.id] || self
931
- current_container.update(attribute_name =>
932
- current_container[attribute_name].insert(widget.container_attribute_index, widget_copy))
933
- end
934
-
935
903
  def mark_resolved
936
904
  workspace.api_request(:put, "/objs/#{id}", obj: {_conflicts: nil})
937
905
  reload
@@ -995,6 +963,18 @@ module Scrivito
995
963
 
996
964
  private
997
965
 
966
+ def children_including_deleted
967
+ workspace.objs.find_by_parent_path_including_deleted(path)
968
+ end
969
+
970
+ def sort_toclist(unsorted_toclist)
971
+ if sortable_toclist?
972
+ (child_order & unsorted_toclist) + (unsorted_toclist - child_order).sort_by(&:id)
973
+ else
974
+ unsorted_toclist
975
+ end
976
+ end
977
+
998
978
  def cms_data_for_revision(revision)
999
979
  return nil unless revision
1000
980
 
@@ -4,7 +4,7 @@ module Scrivito
4
4
  # of content editors want to place on pages or into widgets. All widget classes are based on
5
5
  # subclasses of {Scrivito::BasicWidget Widget}. As with CMS objects, the content of a widget
6
6
  # is stored in its attributes.
7
- # @see http://scrivito.com/page-with-widgets Creating a page type with widgets
7
+ # @see https://scrivito.com/page-with-widgets Creating a page type with widgets
8
8
  # @api public
9
9
  class BasicWidget
10
10
  extend AttributeContent::ClassMethods
@@ -204,22 +204,6 @@ class BasicWidget
204
204
  self.class.new(attributes)
205
205
  end
206
206
 
207
- def copy_for_restore(referenced_ids)
208
- attributes = {}
209
- attribute_definitions.each do |attribute_definition|
210
- attribute_name = attribute_definition.name
211
- attribute_value = read_attribute(attribute_name)
212
- if attribute_definition.widgetlist?
213
- attribute_value = attribute_value
214
- .reject { |widget| referenced_ids.include?(widget.id) }
215
- .map { |widget| widget.copy_for_restore(referenced_ids) }
216
- end
217
- attributes[attribute_name] = attribute_value
218
- end
219
- attributes['_id'] = id
220
- self.class.new(attributes)
221
- end
222
-
223
207
  def clone
224
208
  raise "The method `clone' was removed. Please use `copy' instead"
225
209
  end
@@ -347,10 +331,6 @@ class BasicWidget
347
331
  container_attribute_name
348
332
  end
349
333
 
350
- def container_attribute_index
351
- container[container_attribute_name].index(self)
352
- end
353
-
354
334
  def has_attribute?(key)
355
335
  key.to_s == '_obj_class' || super
356
336
  end
@@ -283,13 +283,6 @@ class Binary
283
283
  # Otherwise +self+.
284
284
  #
285
285
  # @return [Scrivito::Binary] original binary
286
- #
287
- # @example
288
- # @obj.blob.id # => "abc123"
289
- # @obj.blob.original.id # => "abc123"
290
- # @obj.blob.transform(width: 50).original.id # => "abc123"
291
- # @obj.blob.transform(width: 50).transform(height: 50).original.id # => "abc123"
292
- #
293
286
  def original
294
287
  @original || self
295
288
  end
@@ -9,13 +9,13 @@ class BinaryRouting < Struct.new(:request, :scrivito_engine)
9
9
  binary = if image_options.key?(:transform)
10
10
  apply_custom_transformation(binary, image_options[:transform])
11
11
  else
12
- apply_default_transformation(binary, obj)
12
+ apply_default_transformation(binary)
13
13
  end
14
14
  binary_url(binary)
15
15
  end
16
16
 
17
17
  def resolved_binary_obj_url(obj, binary)
18
- apply_default_transformation(binary, obj).url
18
+ BinaryRewrite.call(request, apply_default_transformation(binary).url)
19
19
  end
20
20
 
21
21
  private
@@ -39,10 +39,9 @@ class BinaryRouting < Struct.new(:request, :scrivito_engine)
39
39
  end
40
40
  end
41
41
 
42
- def apply_default_transformation(binary, obj)
43
- if (transformation_definition = Scrivito::Configuration.default_image_transformation) &&
44
- obj.apply_image_transformation?
45
- binary.transform(transformation_definition)
42
+ def apply_default_transformation(binary)
43
+ if Scrivito::Configuration.default_image_transformation
44
+ binary.transform(Scrivito::Configuration.default_image_transformation)
46
45
  else
47
46
  binary
48
47
  end
@@ -37,8 +37,15 @@ class ChildListTag < Struct.new(:tag_name, :obj, :field_name, :view)
37
37
  def content(&block)
38
38
  return unless block_given?
39
39
 
40
+ toclist =
41
+ if EditingContextMiddleware.from_request(view.request).include_deleted_objs?
42
+ obj.sorted_toclist_including_deleted
43
+ else
44
+ obj.sorted_toclist
45
+ end
46
+
40
47
  is_sortable = obj.sortable_toclist? && user_present?
41
- rendered_children = obj.sorted_toclist.map do |child|
48
+ rendered_children = toclist.map do |child|
42
49
  obj_tag = ObjTag.new(child, is_sortable, comparison.modification(child), view)
43
50
  yield obj_tag, child
44
51
  obj_tag.rendered
@@ -28,8 +28,12 @@ module Scrivito
28
28
 
29
29
  def find_obj
30
30
  found_obj =
31
- if params[:id]
32
- Obj.find(params[:id])
31
+ if id = params[:id]
32
+ if EditingContextMiddleware.from_env(env).include_deleted_objs?
33
+ Obj.find_including_deleted(id)
34
+ else
35
+ Obj.find(id)
36
+ end
33
37
  elsif params[:permalink].present?
34
38
  permalink = Array(params[:permalink]).join("/")
35
39
  Obj.find_by_permalink!(permalink)
@@ -149,6 +149,8 @@ class CmsFieldTag < Struct.new(:view, :tag_name, :obj_or_widget, :editing_option
149
149
  if %w[
150
150
  binary
151
151
  date
152
+ enum
153
+ multienum
152
154
  reference
153
155
  referencelist
154
156
  ].include?(field_type)
@@ -76,21 +76,33 @@ class CmsRouting < Struct.new(:request, :context, :scrivito_engine, :image_optio
76
76
  end
77
77
 
78
78
  def path_or_url_for_objs(obj, path_or_url, options)
79
- permalink = obj.permalink
80
- if permalink && (route = find_route(:permalink)) && permalink.split('/').first != 'scrivito'
81
- route.generate(path_or_url, options.merge(:permalink => permalink))
82
- elsif homepage?(obj) && route = find_route(:homepage)
83
- route.generate(path_or_url, options)
84
- elsif obj.binary?
85
- binary_obj_url(obj) || LINK_TO_EMPTY_BLOB
86
- elsif route = find_route(:slug_id)
79
+ if permalink_route_applicable?(obj) && route = find_route(:permalink)
80
+ return route.generate(path_or_url, options.merge(permalink: obj.permalink))
81
+ end
82
+
83
+ if homepage?(obj) && route = find_route(:homepage)
84
+ return route.generate(path_or_url, options)
85
+ end
86
+
87
+ if obj.binary?
88
+ return binary_obj_url(obj) || LINK_TO_EMPTY_BLOB
89
+ end
90
+
91
+ if route = find_route(:slug_id)
87
92
  slug = obj.slug.present? ? obj.slug.sub(/^\//, '') : nil
88
- route.generate(path_or_url, options.merge(id: obj.id, slug: slug))
89
- else
90
- raise ScrivitoError, "The required scrivito route 'slug_id' is not defined. "\
91
- "Please add a 'slug_id' definition to your routes.rb. See the documentation"\
92
- " of 'scrivito_route' for further details."
93
+
94
+ return route.generate(path_or_url, options.merge(id: obj.id, slug: slug))
93
95
  end
96
+
97
+ raise ScrivitoError, "The required scrivito route 'slug_id' is not defined. "\
98
+ "Please add a 'slug_id' definition to your routes.rb. See the documentation"\
99
+ " of 'scrivito_route' for further details."
100
+ end
101
+
102
+ def permalink_route_applicable?(obj)
103
+ permalink = obj.permalink
104
+
105
+ permalink && permalink.split('/').first != 'scrivito' && !obj.deleted?
94
106
  end
95
107
 
96
108
  def find_route(name)
@@ -323,9 +323,7 @@ Please use the new scrivito_route api to replicate the legacy routes:
323
323
  #
324
324
  # @api public
325
325
  #
326
- # When delivering binary Objs, the default image transformation will be applied if
327
- # {Scrivito::BasicObj#apply_image_transformation? Obj#apply_image_transformation?} returns
328
- # +true+.
326
+ # When delivering binary Objs, the default image transformation will be applied.
329
327
  #
330
328
  # If not changed the default image transformation is an empty transformation (an empty
331
329
  # +Hash+). Set it to +false+ to disabled the default image transformation completely.
@@ -333,7 +331,6 @@ Please use the new scrivito_route api to replicate the legacy routes:
333
331
  # @param [Hash] value the {Scrivito::Binary#transform transformation definition}
334
332
  #
335
333
  # @see Scrivito::Binary#transform
336
- # @see Scrivito::BasicObj#apply_image_transformation?
337
334
  #
338
335
  attr_writer :default_image_transformation
339
336
 
@@ -0,0 +1,19 @@
1
+ module Scrivito
2
+ class DisableBrowserCacheForUiMiddleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ status, headers, response = @app.call(env)
9
+
10
+ editing_context = EditingContextMiddleware.from_env(env)
11
+
12
+ if editing_context.authenticated_editor?
13
+ headers['Cache-Control'] = 'no-store, must-revalidate'
14
+ end
15
+
16
+ [status, headers, response]
17
+ end
18
+ end
19
+ end
@@ -80,6 +80,10 @@ class EditingContext
80
80
  display_mode == 'editing'
81
81
  end
82
82
 
83
+ def include_deleted_objs?
84
+ display_mode == 'diff'
85
+ end
86
+
83
87
  def to_params
84
88
  {
85
89
  _scrivito_display_mode: display_mode,
@@ -6,7 +6,11 @@ class EditingContextMiddleware
6
6
  ENVKEY = 'SCRIVITO_EDITING_CONTEXT'
7
7
 
8
8
  def self.from_request(request)
9
- request.env[ENVKEY] || EditingContext.new
9
+ from_env(request.env)
10
+ end
11
+
12
+ def self.from_env(env)
13
+ env[ENVKEY] || EditingContext.new
10
14
  end
11
15
 
12
16
  def initialize(app)
@@ -102,6 +102,10 @@ module Scrivito
102
102
  find_by(:ppath, [path]).first
103
103
  end
104
104
 
105
+ def find_by_parent_path_including_deleted(path)
106
+ find_by_including_deleted(:ppath, [path]).first
107
+ end
108
+
105
109
  def find_by_id(id)
106
110
  find_by(:id, [id]).first.first
107
111
  end
@@ -41,7 +41,7 @@ class PageConfig < Struct.new(:obj, :editing_context, :lookup_context)
41
41
  has_details_view: obj_has_details_view?,
42
42
  modification: modification(obj),
43
43
  parent_path: obj.parent_path,
44
- restriction_messages: editor.restriction_messages_for(obj),
44
+ is_restricted: editor.restriction_messages_for(obj).any?,
45
45
  }
46
46
  end
47
47
 
@@ -13,7 +13,7 @@ module Scrivito
13
13
  scrivito_route '(/)(*slug-):id', using: "slug_id", via: :all
14
14
 
15
15
  match ':id(/*slug)', to: 'scrivito/legacy_redirect#index', via: :all, constraints: {
16
- id: /[a-z0-9]{16}/
16
+ id: /[a-f0-9]{16}/
17
17
  }
18
18
  end
19
19
 
@@ -40,7 +40,7 @@ class Revision < Struct.new(:id, :workspace, :base)
40
40
  def internal_obj_search(query, result, continuation=nil, tentative=false)
41
41
  response = workspace.api_request(:get, "/objs/search",
42
42
  query: query,
43
- include_deleted: true,
43
+ options: {include_deleted: true},
44
44
  size: 100,
45
45
  continuation: continuation,
46
46
  consistent_with: content_state_id
@@ -69,6 +69,7 @@ module ::Scrivito
69
69
  config.app_middleware.use Scrivito::EditingContextMiddleware
70
70
  config.app_middleware.use Scrivito::CacheMiddleware
71
71
  config.app_middleware.use Scrivito::WorkspaceSelectionMiddleware
72
+ config.app_middleware.use Scrivito::DisableBrowserCacheForUiMiddleware
72
73
  end
73
74
  end
74
75
 
@@ -9,59 +9,33 @@ class UiConfig < Struct.new(:editing_context, :resource, :return_to, :app_extens
9
9
  def to_json
10
10
  {
11
11
  app_extension_tags: app_extension_tags,
12
- editing_context: editing_context_config,
13
12
  backend_endpoint: Configuration.endpoint,
14
13
  tenant: Configuration.tenant,
15
14
  i18n: i18n_config,
16
15
  is_development_mode: Rails.env.development?,
17
16
  resource_dialog: resource_dialog_config,
18
- revision: revision_config,
19
17
  user: user_config,
20
18
  user_permissions: user_permissions_config,
21
- obj_class: obj_class_config,
22
- widget_class: widget_class_config,
19
+ class_datas: obj_class_config + widget_class_config,
20
+ useRailsEngine: true,
23
21
  }.to_json
24
22
  end
25
23
 
26
24
  private
27
25
 
28
- def editing_context_config
29
- {
30
- display_mode: editing_context.display_mode,
31
- selected_workspace: workspace_config(selected_workspace),
32
- visible_workspace: workspace_config(visible_workspace),
33
- }
34
- end
35
-
36
- def workspace_config(workspace)
37
- {
38
- id: workspace.id,
39
- memberships: workspace.memberships.map do |membership|
40
- {
41
- user_id: membership.user_id,
42
- role: membership.role,
43
- description: membership.user.description
44
- }
45
- end,
46
- outdated: workspace.outdated?,
47
- auto_update: workspace.auto_update?,
48
- title: workspace.title,
49
- }
50
- end
51
-
52
26
  def i18n_config
53
27
  {locale: Scrivito::Configuration.ui_locale || I18n.locale}
54
28
  end
55
29
 
56
30
  def obj_class_config
57
31
  obj_models.map do |obj_class|
58
- obj_class.as_json.merge(hasDetailsView: details_view?(obj_class.name))
32
+ obj_class_formatter.format(obj_class)
59
33
  end
60
34
  end
61
35
 
62
36
  def widget_class_config
63
37
  widget_models.map do |widget_class|
64
- widget_class.as_json.merge(hasDetailsView: details_view?(widget_class.name))
38
+ obj_class_formatter.format(widget_class)
65
39
  end
66
40
  end
67
41
 
@@ -90,10 +64,6 @@ class UiConfig < Struct.new(:editing_context, :resource, :return_to, :app_extens
90
64
  }
91
65
  end
92
66
 
93
- def revision_config
94
- {published_revision_id: Workspace.published.revision_id}
95
- end
96
-
97
67
  def editor
98
68
  editing_context.editor
99
69
  end
@@ -102,14 +72,8 @@ class UiConfig < Struct.new(:editing_context, :resource, :return_to, :app_extens
102
72
  editing_context.selected_workspace
103
73
  end
104
74
 
105
- def visible_workspace
106
- editing_context.visible_workspace
107
- end
108
-
109
- def details_view?(obj_class_name)
110
- lookup_context.find("#{obj_class_name.underscore}/details").present?
111
- rescue ActionView::MissingTemplate
112
- false
75
+ def obj_class_formatter
76
+ @obj_class_formatter ||= UiObjClassesJsonFormatter.new(lookup_context)
113
77
  end
114
78
  end
115
79
 
@@ -0,0 +1,48 @@
1
+ module Scrivito
2
+ class UiObjClassesJsonFormatter < Struct.new(:lookup_context)
3
+ def format(obj_class)
4
+ data = base_obj_class_data(obj_class)
5
+ if obj_class.ancestors.include?(Scrivito::BasicWidget)
6
+ data[:embeds] = obj_class.embeds?
7
+ data[:embeddingAttribute] =
8
+ obj_class.embeds? ? obj_class.embedding_attribute.name.camelcase(:lower) : nil
9
+
10
+ data[:validContainerClasses] = convert_classes_array(obj_class.valid_container_classes)
11
+ end
12
+
13
+ data[:hasServerDetailsTemplate] = details_view?(obj_class.name)
14
+ data
15
+ end
16
+
17
+ private
18
+
19
+ def base_obj_class_data(obj_class)
20
+ {
21
+ name: obj_class.name,
22
+ type: obj_class.ancestors.include?(Scrivito::BasicWidget) ? 'Widget' : 'Obj',
23
+ title: obj_class.description_for_editor,
24
+ attributes: obj_class.attribute_definitions.map { |attr| convert_attribute(attr) },
25
+ usesServerCallbacks: true,
26
+ hideFromEditor: obj_class.hide_from_editor?,
27
+ }
28
+ end
29
+
30
+ def convert_attribute(attribute)
31
+ attribute_json = attribute.as_json
32
+ attribute_json[:name] = attribute_json[:name].camelcase(:lower)
33
+ attribute_json
34
+ end
35
+
36
+ def details_view?(obj_class_name)
37
+ lookup_context.find("#{obj_class_name.underscore}/details").present?
38
+ rescue ActionView::MissingTemplate
39
+ false
40
+ end
41
+
42
+ def convert_classes_array(arr)
43
+ if arr
44
+ arr.map(&:name)
45
+ end
46
+ end
47
+ end
48
+ end
data/lib/scrivito/user.rb CHANGED
@@ -26,6 +26,9 @@ module Scrivito
26
26
 
27
27
  # Permits the user to publish the working copy.
28
28
  :publish,
29
+
30
+ # Permits the user to access the publishing history
31
+ :read_history,
29
32
  ].freeze
30
33
 
31
34
  class << self
@@ -18,7 +18,7 @@ module Scrivito
18
18
  # perform a specific action. This method lets you add an exception to this logic and thus
19
19
  # should be used carefully.
20
20
  # @note By default, all users are allowed to create a new workspace.
21
- # @see http://scrivito.com/user-permissions Defining users and their permissions
21
+ # @see https://scrivito.com/user-permissions Defining users and their permissions
22
22
  #
23
23
  # @param [Symbol] verb the verb of the action (see {Scrivito::User::VERBS}).
24
24
  # @param [Symbol] subject the subject of the action. Currently, only +:workspace+ is supported.
@@ -6,7 +6,7 @@ module Scrivito
6
6
  # This class represents a CMS workspace, called "working copy" in the UI. A working copy lets
7
7
  # editors create and modify content independently of the published content or other working copies.
8
8
  # On creation, a working copy is based on the currently published content.
9
- # @see http://scrivito.com/about-working-copies About working copies
9
+ # @see https://scrivito.com/about-working-copies About working copies
10
10
 
11
11
  class Workspace
12
12
  extend ActiveModel::Naming