ecoportal-api-v2 0.8.5 → 0.8.9
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/CHANGELOG.md +60 -25
- data/bin/console +1 -1
- data/ecoportal-api-v2.gemspec +5 -5
- data/lib/ecoportal/api-v2.rb +2 -2
- data/lib/ecoportal/api/common.v2.rb +8 -0
- data/lib/ecoportal/api/common/content.rb +1 -0
- data/lib/ecoportal/api/common/content/array_model.rb +8 -6
- data/lib/ecoportal/api/common/content/collection_model.rb +10 -4
- data/lib/ecoportal/api/common/content/double_model.rb +15 -4
- data/lib/ecoportal/api/common/content/hash_diff_patch.rb +31 -19
- data/lib/ecoportal/api/common/content/model_helpers.rb +36 -0
- data/lib/ecoportal/api/v2/page.rb +2 -0
- data/lib/ecoportal/api/v2/page/component.rb +33 -3
- data/lib/ecoportal/api/v2/page/component/action.rb +13 -5
- data/lib/ecoportal/api/v2/page/component/action_field.rb +37 -2
- data/lib/ecoportal/api/v2/page/component/chart_field.rb +43 -5
- data/lib/ecoportal/api/v2/page/component/chart_field/benchmark.rb +30 -0
- data/lib/ecoportal/api/v2/page/component/chart_field/config.rb +23 -0
- data/lib/ecoportal/api/v2/page/component/chart_field/frequency.rb +3 -4
- data/lib/ecoportal/api/v2/page/component/chart_field/heatmap.rb +1 -3
- data/lib/ecoportal/api/v2/page/component/chart_field/indicator.rb +4 -5
- data/lib/ecoportal/api/v2/page/component/chart_field/multiseries.rb +3 -5
- data/lib/ecoportal/api/v2/page/component/chart_field/sankey.rb +1 -3
- data/lib/ecoportal/api/v2/page/component/chart_field/serie.rb +3 -4
- data/lib/ecoportal/api/v2/page/component/chart_field/series_config.rb +5 -7
- data/lib/ecoportal/api/v2/page/component/chart_fr_field.rb +7 -5
- data/lib/ecoportal/api/v2/page/component/checklist_field.rb +1 -1
- data/lib/ecoportal/api/v2/page/component/checklist_item.rb +3 -2
- data/lib/ecoportal/api/v2/page/component/date_field.rb +71 -4
- data/lib/ecoportal/api/v2/page/component/file.rb +3 -2
- data/lib/ecoportal/api/v2/page/component/gauge_field.rb +2 -2
- data/lib/ecoportal/api/v2/page/component/geo_coordinates.rb +13 -0
- data/lib/ecoportal/api/v2/page/component/geo_field.rb +4 -1
- data/lib/ecoportal/api/v2/page/component/images_field.rb +57 -1
- data/lib/ecoportal/api/v2/page/component/people_field.rb +104 -6
- data/lib/ecoportal/api/v2/page/component/plain_text_field.rb +34 -2
- data/lib/ecoportal/api/v2/page/component/reference_field.rb +32 -3
- data/lib/ecoportal/api/v2/page/component/selection_field.rb +71 -4
- data/lib/ecoportal/api/v2/page/component/selection_option.rb +12 -2
- data/lib/ecoportal/api/v2/page/component/tag_field.rb +31 -1
- data/lib/ecoportal/api/v2/page/components.rb +8 -3
- data/lib/ecoportal/api/v2/page/permission_flags.rb +67 -0
- data/lib/ecoportal/api/v2/page/permit.rb +14 -0
- data/lib/ecoportal/api/v2/page/section.rb +65 -5
- data/lib/ecoportal/api/v2/page/sections.rb +64 -6
- data/lib/ecoportal/api/v2/page/stage.rb +11 -3
- data/lib/ecoportal/api/v2/page/stages.rb +7 -7
- data/lib/ecoportal/api/v2/pages/page_stage.rb +3 -3
- data/lib/ecoportal/api/v2_version.rb +5 -0
- metadata +16 -10
- data/lib/ecoportal/api/common.rb +0 -18
- data/lib/ecoportal/api/v2/version.rb +0 -7
@@ -4,11 +4,22 @@ module Ecoportal
|
|
4
4
|
class Page
|
5
5
|
class Component
|
6
6
|
class SelectionField < Page::Component
|
7
|
-
|
8
|
-
passthrough :
|
7
|
+
passboolean :multiple, :flat, :other
|
8
|
+
passthrough :other_desc
|
9
|
+
passthrough :data_type
|
9
10
|
|
10
11
|
embeds_many :options, klass: "Ecoportal::API::V2::Page::Component::SelectionOption", order_key: :weight
|
11
12
|
|
13
|
+
def numeric!(&block)
|
14
|
+
ordered_options.each {|opt| opt.numeric!(&block)}
|
15
|
+
self.data_type = "num"
|
16
|
+
end
|
17
|
+
|
18
|
+
def text!(&block)
|
19
|
+
ordered_options.each {|opt| opt.text!(&block)}
|
20
|
+
self.data_type = "str"
|
21
|
+
end
|
22
|
+
|
12
23
|
def select(value)
|
13
24
|
opt = options.find {|opt| opt.value == value}
|
14
25
|
sel = selected
|
@@ -33,8 +44,8 @@ module Ecoportal
|
|
33
44
|
end
|
34
45
|
end
|
35
46
|
|
36
|
-
def add_option(
|
37
|
-
opt_doc = options.items_class.new_doc
|
47
|
+
def add_option(value:, name: nil, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
48
|
+
opt_doc = options.items_class.new_doc
|
38
49
|
options.upsert!(opt_doc, pos: pos, before: before, after: after) do |option|
|
39
50
|
option.name = name
|
40
51
|
option.value = value
|
@@ -52,8 +63,64 @@ module Ecoportal
|
|
52
63
|
end.map(&:first)
|
53
64
|
end
|
54
65
|
|
66
|
+
# Quick config helper
|
67
|
+
# @param conf [Symbol, Array<Symbol>]
|
68
|
+
# - `:flat` to display in flat mode
|
69
|
+
# - `:multiple` to allow multiple selection
|
70
|
+
# - `:single` to set to singular selection
|
71
|
+
# - `:other` to enable `other` button
|
72
|
+
# - `:options` to add options (`Hash<value, name>`)
|
73
|
+
# - `:type` to define the type
|
74
|
+
# - `:num`
|
75
|
+
# - `:str`
|
76
|
+
def configure(*conf)
|
77
|
+
conf.each_with_object([]) do |cnf, unused|
|
78
|
+
case cnf
|
79
|
+
when :flat
|
80
|
+
self.flat = true
|
81
|
+
when :multiple
|
82
|
+
self.multiple = true
|
83
|
+
when :single
|
84
|
+
self.multiple = false
|
85
|
+
when :other
|
86
|
+
self.other = true
|
87
|
+
when Hash
|
88
|
+
supported = [:flat, :options, :type]
|
89
|
+
unless (rest = hash_except(cnf.dup, *supported)).empty?
|
90
|
+
unused.push(rest)
|
91
|
+
end
|
92
|
+
|
93
|
+
if cnf.key?(:flat) then self.flat = cnf[:flat] end
|
94
|
+
if cnf.key?(:options)
|
95
|
+
if opts = cnf[:options]
|
96
|
+
configure_options opts
|
97
|
+
end
|
98
|
+
end
|
99
|
+
if cnf.key?(:type)
|
100
|
+
if cnf[:type] == :str
|
101
|
+
self.text!
|
102
|
+
elsif cnf[:type] == :num
|
103
|
+
self.numeric!
|
104
|
+
else
|
105
|
+
# Unknown type
|
106
|
+
end
|
107
|
+
end
|
108
|
+
else
|
109
|
+
unused.push(cnf)
|
110
|
+
end
|
111
|
+
end.yield_self do |unused|
|
112
|
+
super(*unused)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
55
116
|
private
|
56
117
|
|
118
|
+
def configure_options(opts)
|
119
|
+
opts.each do |val, nm|
|
120
|
+
add_option(value: val, name: nm)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
57
124
|
def fix_option_weights!
|
58
125
|
ordered_options.each_with_index do |option, index|
|
59
126
|
option.weight = index
|
@@ -4,7 +4,7 @@ module Ecoportal
|
|
4
4
|
class Page
|
5
5
|
class Component
|
6
6
|
class SelectionOption < Common::Content::DoubleModel
|
7
|
-
|
7
|
+
|
8
8
|
class << self
|
9
9
|
def new_doc
|
10
10
|
{
|
@@ -16,7 +16,17 @@ module Ecoportal
|
|
16
16
|
|
17
17
|
passkey :id
|
18
18
|
passthrough :patch_ver, :name, :value
|
19
|
-
passthrough :weight
|
19
|
+
passthrough :weight
|
20
|
+
passboolean :selected
|
21
|
+
|
22
|
+
def numeric!
|
23
|
+
self.value = block_given?? yield(value) : value.to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
def text!
|
27
|
+
self.value = block_given?? yield(value) : value.to_s
|
28
|
+
end
|
29
|
+
|
20
30
|
end
|
21
31
|
end
|
22
32
|
end
|
@@ -4,8 +4,38 @@ module Ecoportal
|
|
4
4
|
class Page
|
5
5
|
class Component
|
6
6
|
class TagField < Page::Component
|
7
|
-
|
7
|
+
passboolean :single_select, :use_defaults
|
8
8
|
passthrough :tag_tree_id, :button_text
|
9
|
+
|
10
|
+
# Quick config helper
|
11
|
+
# @param conf [Symbol, Array<Symbol>]
|
12
|
+
# - `:multiple` to allow multiple selection
|
13
|
+
# - `:single` to set to singular selection
|
14
|
+
# - `:default_tag` to prepopulate using users's `default_tag`
|
15
|
+
# - `:button_text` to define the button description
|
16
|
+
def configure(*conf)
|
17
|
+
conf.each_with_object([]) do |cnf, unused|
|
18
|
+
case cnf
|
19
|
+
when :single
|
20
|
+
self.single_select = true
|
21
|
+
when :multiple
|
22
|
+
self.single_select = false
|
23
|
+
when :default_tag
|
24
|
+
self.use_defaults = true
|
25
|
+
when Hash
|
26
|
+
supported = [:button_text]
|
27
|
+
unless (rest = hash_except(cnf.dup, *supported)).empty?
|
28
|
+
unused.push(rest)
|
29
|
+
end
|
30
|
+
if cnf.key?(:button_text) then self.button_text = cnf[:button_text] end
|
31
|
+
else
|
32
|
+
unused.push(cnf)
|
33
|
+
end
|
34
|
+
end.yield_self do |unused|
|
35
|
+
super(*unused)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
9
39
|
end
|
10
40
|
end
|
11
41
|
end
|
@@ -13,6 +13,12 @@ module Ecoportal
|
|
13
13
|
|
14
14
|
order_matters = true
|
15
15
|
|
16
|
+
def get_by_id(id)
|
17
|
+
self.find do |comp|
|
18
|
+
comp.id == id
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
16
22
|
def get_by_type(type)
|
17
23
|
self.select do |comp|
|
18
24
|
comp.type.downcase == type.to_s.strip.downcase
|
@@ -21,10 +27,9 @@ module Ecoportal
|
|
21
27
|
|
22
28
|
def get_by_name(name, type: nil)
|
23
29
|
pool = type ? get_by_type(type) : self
|
24
|
-
|
25
30
|
pool.select do |comp|
|
26
|
-
comp.label
|
27
|
-
end
|
31
|
+
same_string?(comp.label, name)
|
32
|
+
end
|
28
33
|
end
|
29
34
|
|
30
35
|
def add(label:, type:)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Ecoportal
|
2
|
+
module API
|
3
|
+
class V2
|
4
|
+
class Page
|
5
|
+
class PermissionFlags < Common::Content::DoubleModel
|
6
|
+
class << self
|
7
|
+
def new_doc
|
8
|
+
{
|
9
|
+
"can_restructure" => false,
|
10
|
+
"can_configure" => false,
|
11
|
+
"can_permission" => false,
|
12
|
+
"can_create_actions" => false,
|
13
|
+
"can_administrate_actions" => false,
|
14
|
+
"subscribed" => false,
|
15
|
+
"subscribed_to_tasks" => false
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
passboolean :can_restructure, :can_configure
|
21
|
+
passboolean :can_permission, :can_create_actions, :can_administrate_actions
|
22
|
+
passboolean :subscribed, :subscribed_to_tasks
|
23
|
+
|
24
|
+
def reset!
|
25
|
+
doc.merge!(self.class.new_doc)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Quick config helper
|
29
|
+
# @param conf [Symbol, Array<Symbol>]
|
30
|
+
# - `:restructure`
|
31
|
+
# - `:configure`
|
32
|
+
# - `:can_permission`
|
33
|
+
# - `:create_actions`
|
34
|
+
# - `:admin_actions`
|
35
|
+
# - `:subscribed`
|
36
|
+
# - `:subscribed_to_tasks`
|
37
|
+
def configure(*conf)
|
38
|
+
conf.each_with_object([]) do |cnf, unused|
|
39
|
+
case cnf
|
40
|
+
when :restructure
|
41
|
+
self.can_restructure = true
|
42
|
+
when :configure
|
43
|
+
self.can_configure = true
|
44
|
+
when :can_permission
|
45
|
+
self.can_permission = true
|
46
|
+
when :create_actions
|
47
|
+
self.can_create_actions = true
|
48
|
+
when :admin_actions
|
49
|
+
self.can_administrate_actions = true
|
50
|
+
when :subscribed
|
51
|
+
self.subscribed = true
|
52
|
+
when :subscribed_to_tasks
|
53
|
+
self.subscribed_to_tasks = true
|
54
|
+
else
|
55
|
+
unused.push(cnf)
|
56
|
+
end
|
57
|
+
end.yield_self do |unused|
|
58
|
+
raise "Unknown configuaration options #{unused}" unless unused.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -8,7 +8,7 @@ module Ecoportal
|
|
8
8
|
{
|
9
9
|
"id" => new_uuid,
|
10
10
|
"type" => split ? "split" : "content",
|
11
|
-
"weight" =>
|
11
|
+
"weight" => 800
|
12
12
|
}.tap do |out|
|
13
13
|
component_ids = if split
|
14
14
|
{
|
@@ -44,10 +44,70 @@ module Ecoportal
|
|
44
44
|
all_component_ids.include?(id)
|
45
45
|
end
|
46
46
|
|
47
|
-
def components
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
def components(side: nil)
|
48
|
+
case side
|
49
|
+
when :right
|
50
|
+
components_right
|
51
|
+
when :left
|
52
|
+
components_left
|
53
|
+
when NilClass
|
54
|
+
components_by_id(*all_component_ids)
|
55
|
+
else
|
56
|
+
raise "Side should be one of [nil, :right, :left]. Given: #{side}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def components_left
|
61
|
+
raise "You are trying to retrieve side components in a Split Section" unless split?
|
62
|
+
components_by_id(*left_component_ids)
|
63
|
+
end
|
64
|
+
|
65
|
+
def components_right
|
66
|
+
raise "You are trying to retrieve side components in a Split Section" unless split?
|
67
|
+
components_by_id(*right_component_ids)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Adds `field` to the section
|
71
|
+
# @note
|
72
|
+
# - To the specified `side`, when split section (default `:left`)
|
73
|
+
# - To the end if `after` is not specified
|
74
|
+
# - If `after` is specified, it searches field
|
75
|
+
# - On the specific `side`, if specified (and split section)
|
76
|
+
# - And adds the `field` after it, when found, or at the end if `after` is not found
|
77
|
+
# @param field [Ecoportal::API::V2::Page::Component] the field to be added.
|
78
|
+
def add_component(field, after: nil, side: nil)
|
79
|
+
raise "field should be a Ecoportal::API::V2::Page::Component. Given: #{field.class}" unless field.is_a?(Ecoportal::API::V2::Page::Component)
|
80
|
+
if field.section == self
|
81
|
+
raise "Field with id '#{field.id}' already belongs to this section"
|
82
|
+
elsif sec = field.section
|
83
|
+
# Field belongs to another section
|
84
|
+
raise "Field with id '#{field.id}' belongs to section '#{sec.heading || "Unnamed"}' (id: '#{sec.id}')"
|
85
|
+
end
|
86
|
+
|
87
|
+
if split?
|
88
|
+
ids_ary = side == :right ? right_component_ids : left_component_ids
|
89
|
+
fields = components(side: side || :left)
|
90
|
+
else
|
91
|
+
ids_ary = component_ids
|
92
|
+
fields = components
|
93
|
+
end
|
94
|
+
if after
|
95
|
+
after_fld = fields.find do |fld|
|
96
|
+
found = nil
|
97
|
+
found ||= !!after if after.is_a?(Ecoportal::API::V2::Page::Component)
|
98
|
+
found ||= fld.id == after
|
99
|
+
found ||= same_string?(fld.label, after)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
ids_ary.insert_one(field.id, after: after_fld&.id)
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def components_by_id(*ids)
|
109
|
+
root.components.values_at(*ids).select.with_index do |fld, i|
|
110
|
+
puts "Warning: field id #{ids[i]} points to missing field" if !fld
|
51
111
|
fld && (!block_given? || yield(fld))
|
52
112
|
end
|
53
113
|
end
|
@@ -7,26 +7,84 @@ module Ecoportal
|
|
7
7
|
|
8
8
|
self.klass = :section_class
|
9
9
|
|
10
|
+
# Creates a new `section`
|
10
11
|
def add(name: nil, split: false, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
11
12
|
sec_doc = section_class.new_doc(split: split)
|
12
|
-
upsert!(sec_doc
|
13
|
+
upsert!(sec_doc) do |section| #, pos: pos, before: before, after: after) do |section|
|
13
14
|
section.heading = name
|
14
|
-
if
|
15
|
-
section.weight =
|
15
|
+
if weight = scope_weight(pos: pos, before: before, after: after)
|
16
|
+
section.weight = weight
|
16
17
|
end
|
18
|
+
fix_weights!
|
17
19
|
yield(section) if block_given?
|
18
|
-
#fix_weights! # a server bug prevents to set the weight of existing sections
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
def get_by_type(type)
|
24
|
+
ordered.select do |sec|
|
25
|
+
sec.type == type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_by_heading(heading)
|
30
|
+
ordered.select do |sec|
|
31
|
+
value = heading == :unnamed ? nil : heading
|
32
|
+
same_string?(sec.heading, value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Gets all the sections between `sec1` and `sec2`
|
37
|
+
def between(sec1, sec2, included: false)
|
38
|
+
sorted_secs = ordered
|
39
|
+
pos1 = (sec1 = to_section(sec1)) && sorted_secs.index(sec1)
|
40
|
+
pos2 = (sec2 = to_section(sec2)) && sorted_secs.index(sec2)
|
41
|
+
if included
|
42
|
+
pos1 = pos1 ? pos1 : 0
|
43
|
+
pos2 = pos2 ? pos2 : -1
|
44
|
+
else
|
45
|
+
pos1 = pos1 ? (pos1 + 1) : 0
|
46
|
+
pos2 = pos2 ? (pos2 - 1) : -1
|
47
|
+
end
|
48
|
+
sorted_secs[pos1..pos2]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Gets the sections ordered by `weight` (as they appear in the page)
|
22
52
|
def ordered
|
23
|
-
|
53
|
+
self.sort_by.with_index do |section, index|
|
24
54
|
(section.weight >= 9999) ? [index, index] : [section.weight, index]
|
25
|
-
end
|
55
|
+
end
|
26
56
|
end
|
27
57
|
|
28
58
|
private
|
29
59
|
|
60
|
+
def scope_weight(pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
61
|
+
case
|
62
|
+
when used_param?(pos)
|
63
|
+
if pos = to_section(pos)
|
64
|
+
pos.weight - 1
|
65
|
+
end
|
66
|
+
when used_param?(before)
|
67
|
+
if before = to_section(before)
|
68
|
+
before.weight - 1
|
69
|
+
end
|
70
|
+
when used_param?(after)
|
71
|
+
if after = to_section(after)
|
72
|
+
after.weight
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_section(value)
|
78
|
+
case value
|
79
|
+
when Ecoportal::API::V2::Page::Section
|
80
|
+
value
|
81
|
+
when Numeric
|
82
|
+
ordered[value]
|
83
|
+
else
|
84
|
+
get_by_heading(value).first
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
30
88
|
def fix_weights!
|
31
89
|
ordered.each_with_index do |section, index|
|
32
90
|
section.weight = index
|