scrivito_sdk 1.2.0 → 1.3.0.rc1
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/app/controllers/scrivito/blobs_controller.rb +5 -3
- data/app/controllers/scrivito/obj_class_controller.rb +58 -0
- data/app/controllers/scrivito/objs_controller.rb +1 -6
- data/app/controllers/scrivito/proxy/objs_controller.rb +34 -0
- data/app/controllers/scrivito/resolve_paths_controller.rb +21 -0
- data/app/controllers/scrivito/sessions_controller.rb +7 -0
- data/app/controllers/scrivito/webservice_controller.rb +11 -0
- data/app/controllers/scrivito/workspaces_controller.rb +7 -9
- data/app/helpers/scrivito_helper.rb +1 -1
- data/app/views/scrivito/obj_class/defaults.json.jbuilder +1 -0
- data/app/views/scrivito/proxy/index.json.jbuilder +1 -0
- data/app/views/scrivito/resolve_paths/resolve.json.jbuilder +1 -0
- data/app/views/scrivito/sessions/update.json.jbuilder +1 -0
- data/app/views/scrivito/ui/index.html.erb +1 -0
- data/app/views/scrivito/webservice/_workspace.json.jbuilder +0 -2
- data/config/ca-bundle.crt +55 -669
- data/config/precedence_routes.rb +7 -1
- data/lib/assets/images/scrivito/image_placeholder.gif +0 -0
- data/lib/assets/javascripts/scrivito_ui.js +6259 -3918
- data/lib/assets/stylesheets/scrivito.css +1 -1
- data/lib/assets/stylesheets/scrivito_ui.css +1 -1
- data/lib/scrivito/attribute_content.rb +43 -8
- data/lib/scrivito/attribute_deserializer.rb +11 -1
- data/lib/scrivito/attribute_serializer.rb +44 -8
- data/lib/scrivito/basic_obj.rb +3 -3
- data/lib/scrivito/binary.rb +17 -3
- data/lib/scrivito/binary_param_verifier.rb +2 -2
- data/lib/scrivito/client_attribute_serializer.rb +11 -1
- data/lib/scrivito/client_error.rb +1 -1
- data/lib/scrivito/cms_field_tag.rb +2 -0
- data/lib/scrivito/cms_rest_api.rb +6 -13
- data/lib/scrivito/{date_attribute.rb → date_conversion.rb} +2 -4
- data/lib/scrivito/float_conversion.rb +29 -0
- data/lib/scrivito/image_tag.rb +1 -1
- data/lib/scrivito/integer_conversion.rb +29 -0
- data/lib/scrivito/obj_params_parser.rb +1 -1
- data/lib/scrivito/obj_search_builder.rb +1 -1
- data/lib/scrivito/obj_search_enumerator.rb +19 -99
- data/lib/scrivito/obj_search_enumerator/facet_query.rb +105 -0
- data/lib/scrivito/page_config.rb +1 -0
- data/lib/scrivito/session.rb +23 -0
- data/lib/scrivito/task.rb +1 -1
- data/lib/scrivito/ui_config.rb +6 -0
- data/lib/scrivito/user.rb +4 -3
- data/lib/scrivito/user_definition.rb +7 -7
- data/lib/scrivito/workspace.rb +14 -3
- data/lib/scrivito/workspace_data.rb +5 -0
- metadata +18 -6
- data/lib/assets/images/scrivito/image_placeholder.png +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
module Scrivito
|
2
2
|
|
3
3
|
# Adds support for string columns which contain ISO dates
|
4
|
-
module
|
4
|
+
module DateConversion
|
5
5
|
def self.deserialize_from_backend(iso_date_time)
|
6
6
|
return nil unless iso_date_time
|
7
7
|
|
@@ -18,9 +18,7 @@ module Scrivito
|
|
18
18
|
DateTime.iso8601(iso8601_date_time).in_time_zone
|
19
19
|
rescue ArgumentError
|
20
20
|
raise Scrivito::ClientError.new(
|
21
|
-
|
22
|
-
400
|
23
|
-
)
|
21
|
+
"The value is not a valid ISO 8601 date time: #{iso8601_date_time.inspect}")
|
24
22
|
end
|
25
23
|
|
26
24
|
def self.serialize_for_backend(attribute_value)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Scrivito
|
2
|
+
module FloatConversion
|
3
|
+
FLOAT_STRING_REGEX = /\A-?\d+(\.\d+)?\z/.freeze
|
4
|
+
DEFAULT_VALUE = 0.0
|
5
|
+
|
6
|
+
def self.deserialize_from_backend(backend_value)
|
7
|
+
case backend_value
|
8
|
+
when Integer, Float, FLOAT_STRING_REGEX
|
9
|
+
value = backend_value.to_f
|
10
|
+
value.finite? ? value : DEFAULT_VALUE
|
11
|
+
when nil, String
|
12
|
+
DEFAULT_VALUE
|
13
|
+
else
|
14
|
+
raise Scrivito::InternalError,
|
15
|
+
"invalid value #{backend_value} (class: #{backend_value.class})"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.serialize_for_backend(value, attr_name)
|
20
|
+
serialized_value = value.to_f
|
21
|
+
unless serialized_value.finite?
|
22
|
+
raise ClientError.new(
|
23
|
+
"Value #{value} for attribute #{attr_name} is not supported.")
|
24
|
+
end
|
25
|
+
|
26
|
+
value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/scrivito/image_tag.rb
CHANGED
@@ -13,7 +13,7 @@ class ImageTag < Struct.new(:view_context)
|
|
13
13
|
def src(obj_or_widget, attribute_name, editing_options)
|
14
14
|
path(obj_or_widget, attribute_name, editing_options) ||
|
15
15
|
editing_options[:placeholder] ||
|
16
|
-
view_context.image_path('scrivito/image_placeholder.
|
16
|
+
view_context.image_path('scrivito/image_placeholder.gif')
|
17
17
|
end
|
18
18
|
|
19
19
|
def alt(obj_or_widget, attribute_name)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Scrivito
|
2
|
+
module IntegerConversion
|
3
|
+
INTEGER_STRING_REGEX = /\A-?\d+\z/.freeze
|
4
|
+
DEFAULT_VALUE = 0
|
5
|
+
RANGE = Range.new(-(2**53 - 1), (2**53 - 1)).freeze
|
6
|
+
|
7
|
+
def self.deserialize_from_backend(backend_value)
|
8
|
+
case backend_value
|
9
|
+
when Integer, Float, INTEGER_STRING_REGEX
|
10
|
+
value = backend_value.to_i
|
11
|
+
RANGE.include?(value) ? value : DEFAULT_VALUE
|
12
|
+
when nil, String
|
13
|
+
DEFAULT_VALUE
|
14
|
+
else
|
15
|
+
raise Scrivito::InternalError,
|
16
|
+
"invalid value #{backend_value} (class: #{backend_value.class})"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.serialize_for_backend(value, attr_name)
|
21
|
+
unless RANGE.include?(value)
|
22
|
+
raise ClientError.new(
|
23
|
+
"Value #{value} for attribute #{attr_name} is out of range: #{RANGE}")
|
24
|
+
end
|
25
|
+
|
26
|
+
value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -19,7 +19,7 @@ module Scrivito
|
|
19
19
|
when 'link' then ContentConversion.convert_link(value, host, port)
|
20
20
|
when 'linklist' then ContentConversion.convert_linklist_urls(value, host, port)
|
21
21
|
when 'widgetlist' then parse_widgetlist_params(value)
|
22
|
-
when 'date' then
|
22
|
+
when 'date' then DateConversion.deserialize_from_client(value)
|
23
23
|
else value
|
24
24
|
end
|
25
25
|
end
|
@@ -149,8 +149,8 @@ module Scrivito
|
|
149
149
|
include Enumerable
|
150
150
|
|
151
151
|
attr_reader :workspace
|
152
|
-
|
153
152
|
attr_reader :query
|
153
|
+
|
154
154
|
def initialize(workspace, batch_size = nil)
|
155
155
|
@workspace = workspace
|
156
156
|
@batch_size = batch_size
|
@@ -288,7 +288,7 @@ module Scrivito
|
|
288
288
|
#
|
289
289
|
def batch_size(size)
|
290
290
|
@batch_size = size
|
291
|
-
@
|
291
|
+
@preload_batch = true
|
292
292
|
|
293
293
|
self
|
294
294
|
end
|
@@ -497,17 +497,16 @@ module Scrivito
|
|
497
497
|
# @raise [Scrivito::ClientError] If the maximum number of results has been exceeded.
|
498
498
|
# The number of results is limited to 100 with respect to the facets themselves and the included Objs.
|
499
499
|
#
|
500
|
-
def facet(*
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
end
|
500
|
+
def facet(*facet_params)
|
501
|
+
search_params = search_dsl_params
|
502
|
+
search_params[:size] = 0 unless @preload_batch
|
503
|
+
|
504
|
+
facet_query = FacetQuery.new(facet_params, search_params, workspace)
|
505
|
+
facet_query.execute!
|
506
|
+
|
507
|
+
@preloaded_batch = facet_query.batch if @preload_batch
|
508
|
+
|
509
|
+
facet_query.result
|
511
510
|
end
|
512
511
|
|
513
512
|
def fetch_batch(continuation=nil)
|
@@ -539,87 +538,16 @@ module Scrivito
|
|
539
538
|
end
|
540
539
|
|
541
540
|
def convert_single_value(value)
|
542
|
-
|
543
|
-
|
541
|
+
case value
|
542
|
+
when Time, Date
|
543
|
+
DateConversion.serialize_for_backend(value)
|
544
|
+
when Integer, Float
|
545
|
+
value
|
544
546
|
else
|
545
547
|
value.to_s
|
546
548
|
end
|
547
549
|
end
|
548
550
|
|
549
|
-
def create_facet_value_objs(facet_arrays, obj_collection)
|
550
|
-
result = []
|
551
|
-
facet_arrays.map do |facet|
|
552
|
-
included_objs = []
|
553
|
-
if included_ids = get_objs_facet_ids(facet)
|
554
|
-
obj_collection.each do |basic_obj|
|
555
|
-
if included_ids.include? basic_obj.id
|
556
|
-
included_objs << basic_obj unless included_objs.include? basic_obj
|
557
|
-
end
|
558
|
-
end
|
559
|
-
end
|
560
|
-
result << ObjFacetValue.new(facet["value"], facet["total"], included_objs)
|
561
|
-
end
|
562
|
-
result
|
563
|
-
end
|
564
|
-
|
565
|
-
def get_all_facets_ids(facet_array)
|
566
|
-
result = []
|
567
|
-
facet_array.map do |facet|
|
568
|
-
result += get_objs_facet_ids(facet)
|
569
|
-
end
|
570
|
-
result
|
571
|
-
end
|
572
|
-
|
573
|
-
def multiple_facet_params(facets)
|
574
|
-
facet_params = []
|
575
|
-
facets.first.map do |k, v|
|
576
|
-
facet_params << single_facet_params(k, v)
|
577
|
-
end
|
578
|
-
facet_params
|
579
|
-
end
|
580
|
-
|
581
|
-
def single_facet_params(attribute, options = {})
|
582
|
-
{ attribute: attribute }.merge!(options)
|
583
|
-
end
|
584
|
-
|
585
|
-
def get_objs_facet_ids(facet)
|
586
|
-
result = []
|
587
|
-
if included_ids = facet["results"]
|
588
|
-
included_ids.each { |obj| result << obj["id"] }
|
589
|
-
end
|
590
|
-
result
|
591
|
-
end
|
592
|
-
|
593
|
-
def get_facet_value_objs(facets_params, attributes_list = [])
|
594
|
-
result = attributes_list.each_with_object({}) { |v,h| h[v] = [] }
|
595
|
-
included_objs_ids = []
|
596
|
-
|
597
|
-
params = prepare_facet_search_params facets_params
|
598
|
-
|
599
|
-
batch = QueryExecutor.new(workspace).call(params)
|
600
|
-
@preloaded_batch = batch if @preload_search_result
|
601
|
-
|
602
|
-
batch.facets.each do |facets_array|
|
603
|
-
included_objs_ids += get_all_facets_ids(facets_array)
|
604
|
-
end
|
605
|
-
|
606
|
-
obj_collection = workspace.objs.find(included_objs_ids)
|
607
|
-
batch.facets.each_with_index do |facets_array, index|
|
608
|
-
result[result.keys[index]] += create_facet_value_objs(facets_array, obj_collection)
|
609
|
-
end
|
610
|
-
result
|
611
|
-
end
|
612
|
-
|
613
|
-
def prepare_facet_search_params(facet_params)
|
614
|
-
params = { facets: facet_params }
|
615
|
-
|
616
|
-
if query
|
617
|
-
params.merge! search_dsl_params
|
618
|
-
end
|
619
|
-
|
620
|
-
params.reverse_merge(size: 0)
|
621
|
-
end
|
622
|
-
|
623
551
|
def operator_mapping(operator)
|
624
552
|
case operator.to_sym
|
625
553
|
when :contains
|
@@ -640,17 +568,9 @@ module Scrivito
|
|
640
568
|
end
|
641
569
|
|
642
570
|
def search_dsl_params
|
643
|
-
patches = {
|
644
|
-
query: query,
|
645
|
-
}
|
571
|
+
patches = {query: query}
|
646
572
|
patches[:size] = @batch_size if @batch_size
|
647
|
-
|
648
|
-
if @include_deleted
|
649
|
-
patches[:options] = {
|
650
|
-
include_deleted: true
|
651
|
-
}
|
652
|
-
end
|
653
|
-
|
573
|
+
patches[:options] = {include_deleted: true} if @include_deleted
|
654
574
|
options.merge(patches)
|
655
575
|
end
|
656
576
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Scrivito
|
2
|
+
class ObjSearchEnumerator
|
3
|
+
#
|
4
|
+
# Response format (assuming we've requested facets for attributes "color" and "size"):
|
5
|
+
#
|
6
|
+
# [
|
7
|
+
# # Facets for attribute "color"
|
8
|
+
# [
|
9
|
+
# {value: "red", total: 2, results: [{id: "xxx"}, {id: "yyy"}]},
|
10
|
+
# {value: "blue", total: 1, results: [{id: "xxx"}]},
|
11
|
+
# {value: "green", total: 0, results: []},
|
12
|
+
# ],
|
13
|
+
#
|
14
|
+
# # Facets for attribute "size"
|
15
|
+
# [
|
16
|
+
# {value: "large", total: 2, results: [{id: "xxx"}, {id: "yyy"}]},
|
17
|
+
# {value: "medium", total: 1, results: [{id: "xxx"}]},
|
18
|
+
# {value: "small", total: 0, results: []},
|
19
|
+
# ]
|
20
|
+
# ]
|
21
|
+
#
|
22
|
+
#
|
23
|
+
class FacetQuery < Struct.new(:facet_params, :search_params, :workspace)
|
24
|
+
attr_reader :batch, :result
|
25
|
+
|
26
|
+
def execute!
|
27
|
+
@result = case
|
28
|
+
when facet_params.first.empty?
|
29
|
+
{}
|
30
|
+
when facet_params.one? && facet_params.first.is_a?(Hash)
|
31
|
+
fetch_result(multi_facet_params, facet_params.first.keys)
|
32
|
+
else
|
33
|
+
attribute_name = facet_params.first
|
34
|
+
fetch_result([single_facet_params(*facet_params)], [attribute_name])[attribute_name]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def fetch_result(params, attribute_names)
|
41
|
+
result = attribute_names.each_with_object({}) { |v, h| h[v] = [] }
|
42
|
+
|
43
|
+
@batch = QueryExecutor.new(workspace).call(build_search_params(params))
|
44
|
+
objs = workspace.objs.find(obj_ids_from_batch)
|
45
|
+
|
46
|
+
@batch.facets.each_with_index do |facets_per_attribute, i|
|
47
|
+
result[result.keys[i]] += obj_facet_values(facets_per_attribute, objs)
|
48
|
+
end
|
49
|
+
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
def obj_ids_from_batch
|
54
|
+
ids = []
|
55
|
+
|
56
|
+
@batch.facets.each do |facets_per_attribute|
|
57
|
+
facets_per_attribute.each do |facet_hash|
|
58
|
+
ids += obj_ids_from_facet_hash(facet_hash)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
ids
|
63
|
+
end
|
64
|
+
|
65
|
+
def multi_facet_params
|
66
|
+
facet_params.first.map do |attribute_name, options|
|
67
|
+
single_facet_params(attribute_name, options)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def single_facet_params(attribute, options = {})
|
72
|
+
{attribute: attribute}.merge!(options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def obj_facet_values(facets_per_attribute, objs)
|
76
|
+
results = []
|
77
|
+
|
78
|
+
facets_per_attribute.map do |facet_hash|
|
79
|
+
obj_ids = obj_ids_from_facet_hash(facet_hash)
|
80
|
+
included_objs = []
|
81
|
+
|
82
|
+
objs.each do |obj|
|
83
|
+
if obj_ids.include?(obj.id) && !included_objs.include?(obj)
|
84
|
+
included_objs << obj
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
results << ObjFacetValue.new(facet_hash['value'], facet_hash['total'], included_objs)
|
89
|
+
end
|
90
|
+
|
91
|
+
results
|
92
|
+
end
|
93
|
+
|
94
|
+
def obj_ids_from_facet_hash(facet_hash)
|
95
|
+
facet_hash['results'].map { |obj_hash| obj_hash['id'] }
|
96
|
+
end
|
97
|
+
|
98
|
+
def build_search_params(params)
|
99
|
+
params = {facets: params}
|
100
|
+
params.merge!(search_params) if search_params
|
101
|
+
params.reverse_merge(size: 0)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/scrivito/page_config.rb
CHANGED
@@ -24,6 +24,7 @@ class PageConfig < Struct.new(:obj, :editing_context, :lookup_context)
|
|
24
24
|
{
|
25
25
|
id: obj.id,
|
26
26
|
obj_class: obj.obj_class,
|
27
|
+
description_for_editor: obj.description_for_editor,
|
27
28
|
has_children: obj.children.any?,
|
28
29
|
has_conflict: obj.has_conflict?,
|
29
30
|
has_details_view: obj_has_details_view?,
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Scrivito
|
2
|
+
class Session
|
3
|
+
def self.renew(id, user)
|
4
|
+
payload = {
|
5
|
+
session: {
|
6
|
+
role: 'editor',
|
7
|
+
user_id: user.id,
|
8
|
+
permissions: permissions(user),
|
9
|
+
},
|
10
|
+
}
|
11
|
+
|
12
|
+
CmsRestApi.task_unaware_request(:put, "sessions/#{id}", payload)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.permissions(user)
|
16
|
+
Hash[user.explicit_rules.map do |permission, verb, _, _|
|
17
|
+
[verb, permission.to_s]
|
18
|
+
end]
|
19
|
+
end
|
20
|
+
|
21
|
+
private_class_method :permissions
|
22
|
+
end
|
23
|
+
end
|
data/lib/scrivito/task.rb
CHANGED
data/lib/scrivito/ui_config.rb
CHANGED
@@ -10,6 +10,7 @@ class UiConfig < Struct.new(:editing_context, :resource, :return_to, :app_extens
|
|
10
10
|
{
|
11
11
|
app_extension_tags: app_extension_tags,
|
12
12
|
editing_context: editing_context_config,
|
13
|
+
session: session_config,
|
13
14
|
i18n: i18n_config,
|
14
15
|
is_development_mode: Rails.env.development?,
|
15
16
|
resource_dialog: resource_dialog_config,
|
@@ -30,6 +31,10 @@ class UiConfig < Struct.new(:editing_context, :resource, :return_to, :app_extens
|
|
30
31
|
}
|
31
32
|
end
|
32
33
|
|
34
|
+
def session_config
|
35
|
+
Session.renew(SecureRandom.hex(8), editor)
|
36
|
+
end
|
37
|
+
|
33
38
|
def workspace_config(workspace)
|
34
39
|
{
|
35
40
|
id: workspace.id,
|
@@ -41,6 +46,7 @@ class UiConfig < Struct.new(:editing_context, :resource, :return_to, :app_extens
|
|
41
46
|
}
|
42
47
|
end,
|
43
48
|
outdated: workspace.outdated?,
|
49
|
+
auto_update: workspace.auto_update?,
|
44
50
|
title: workspace.title,
|
45
51
|
}
|
46
52
|
end
|