scrivito_sdk 1.2.0 → 1.3.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/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
|