gooddata 0.6.24 → 0.6.25

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.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +54 -0
  3. data/CHANGELOG.md +3 -0
  4. data/DEPENDENCIES.md +155 -154
  5. data/README.md +15 -6
  6. data/Rakefile +5 -3
  7. data/dependency_decisions.yml +2 -0
  8. data/gooddata.gemspec +2 -3
  9. data/lib/gooddata/cli/cli.rb +1 -3
  10. data/lib/gooddata/cli/commands/auth_cmd.rb +16 -7
  11. data/lib/gooddata/cli/commands/project_cmd.rb +16 -178
  12. data/lib/gooddata/cli/shared.rb +46 -44
  13. data/lib/gooddata/commands/auth.rb +4 -0
  14. data/lib/gooddata/commands/project.rb +7 -24
  15. data/lib/gooddata/exceptions/object_migration.rb +4 -0
  16. data/lib/gooddata/exceptions/segment_not_empty.rb +18 -0
  17. data/lib/gooddata/extensions/object.rb +12 -0
  18. data/lib/gooddata/goodzilla/goodzilla.rb +56 -9
  19. data/lib/gooddata/helpers/global_helpers.rb +92 -0
  20. data/lib/gooddata/mixins/md_finders.rb +2 -8
  21. data/lib/gooddata/mixins/md_grantees.rb +42 -0
  22. data/lib/gooddata/mixins/md_id_to_uri.rb +1 -8
  23. data/lib/gooddata/mixins/md_object_id.rb +1 -1
  24. data/lib/gooddata/mixins/md_object_indexer.rb +5 -8
  25. data/lib/gooddata/mixins/md_object_query.rb +2 -2
  26. data/lib/gooddata/mixins/not_group.rb +17 -0
  27. data/lib/gooddata/mixins/rest_getters.rb +2 -2
  28. data/lib/gooddata/mixins/rest_resource.rb +1 -0
  29. data/lib/gooddata/mixins/to_json.rb +11 -0
  30. data/lib/gooddata/mixins/uri_getter.rb +9 -0
  31. data/lib/gooddata/models/blueprint/anchor_field.rb +14 -0
  32. data/lib/gooddata/models/blueprint/project_blueprint.rb +15 -1
  33. data/lib/gooddata/models/blueprint/to_wire.rb +10 -0
  34. data/lib/gooddata/models/client.rb +178 -0
  35. data/lib/gooddata/models/client_synchronization_result.rb +31 -0
  36. data/lib/gooddata/models/client_synchronization_result_details.rb +41 -0
  37. data/lib/gooddata/models/datawarehouse.rb +1 -5
  38. data/lib/gooddata/models/domain.rb +85 -1
  39. data/lib/gooddata/models/execution.rb +0 -2
  40. data/lib/gooddata/models/execution_detail.rb +0 -2
  41. data/lib/gooddata/models/from_wire.rb +10 -0
  42. data/lib/gooddata/models/invitation.rb +1 -1
  43. data/lib/gooddata/models/links.rb +1 -1
  44. data/lib/gooddata/models/membership.rb +10 -6
  45. data/lib/gooddata/models/metadata.rb +98 -11
  46. data/lib/gooddata/models/metadata/attribute.rb +6 -7
  47. data/lib/gooddata/models/metadata/dashboard.rb +41 -75
  48. data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +20 -4
  49. data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +37 -0
  50. data/lib/gooddata/models/metadata/dashboard/filter_item.rb +49 -0
  51. data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +56 -0
  52. data/lib/gooddata/models/metadata/dashboard/headline_item.rb +56 -0
  53. data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +46 -0
  54. data/lib/gooddata/models/metadata/dashboard/report_item.rb +49 -8
  55. data/lib/gooddata/models/metadata/dashboard/text_item.rb +55 -0
  56. data/lib/gooddata/models/metadata/dashboard_tab.rb +83 -30
  57. data/lib/gooddata/models/metadata/dataset.rb +0 -2
  58. data/lib/gooddata/models/metadata/dimension.rb +1 -3
  59. data/lib/gooddata/models/metadata/fact.rb +1 -3
  60. data/lib/gooddata/models/metadata/label.rb +1 -3
  61. data/lib/gooddata/models/metadata/metric.rb +11 -42
  62. data/lib/gooddata/models/metadata/report.rb +7 -18
  63. data/lib/gooddata/models/metadata/report_definition.rb +21 -113
  64. data/lib/gooddata/models/metadata/scheduled_mail.rb +274 -0
  65. data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +62 -0
  66. data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +64 -0
  67. data/lib/gooddata/models/metadata/variable.rb +8 -2
  68. data/lib/gooddata/models/model.rb +2 -9
  69. data/lib/gooddata/models/process.rb +7 -29
  70. data/lib/gooddata/models/profile.rb +1 -1
  71. data/lib/gooddata/models/project.rb +131 -167
  72. data/lib/gooddata/models/project_creator.rb +2 -7
  73. data/lib/gooddata/models/project_metadata.rb +2 -10
  74. data/lib/gooddata/models/project_role.rb +4 -10
  75. data/lib/gooddata/models/report_data_result.rb +3 -5
  76. data/lib/gooddata/models/schedule.rb +4 -31
  77. data/lib/gooddata/models/segment.rb +192 -0
  78. data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +2 -2
  79. data/lib/gooddata/models/user_filters/user_filter_builder.rb +1 -1
  80. data/lib/gooddata/models/user_filters/variable_user_filter.rb +11 -0
  81. data/lib/gooddata/models/user_group.rb +241 -0
  82. data/lib/gooddata/rest/connection.rb +81 -16
  83. data/lib/gooddata/rest/object.rb +29 -0
  84. data/lib/gooddata/rest/object_factory.rb +6 -1
  85. data/lib/gooddata/rest/resource.rb +7 -1
  86. data/lib/gooddata/version.rb +1 -1
  87. data/spec/environment/default.rb +19 -16
  88. data/spec/environment/develop.rb +10 -10
  89. data/spec/environment/hotfix.rb +6 -6
  90. data/spec/environment/production.rb +14 -14
  91. data/spec/environment/release.rb +6 -6
  92. data/spec/environment/staging.rb +9 -9
  93. data/spec/environment/staging_3.rb +14 -15
  94. data/spec/integration/blueprint_with_grain_spec.rb +72 -0
  95. data/spec/integration/clients_spec.rb +135 -0
  96. data/spec/integration/date_dim_switch_spec.rb +142 -0
  97. data/spec/integration/full_project_spec.rb +3 -3
  98. data/spec/integration/project_spec.rb +20 -0
  99. data/spec/integration/segments_spec.rb +141 -0
  100. data/spec/integration/user_group_spec.rb +127 -0
  101. data/spec/spec_helper.rb +4 -0
  102. data/spec/unit/models/domain_spec.rb +7 -1
  103. data/spec/unit/models/metric_spec.rb +0 -8
  104. data/spec/unit/models/profile_spec.rb +1 -1
  105. data/spec/unit/models/report_result_data_spec.rb +6 -0
  106. metadata +38 -38
  107. data/lib/gooddata/cli/commands/api_cmd.rb +0 -34
  108. data/lib/gooddata/cli/commands/console_cmd.rb +0 -40
  109. data/lib/gooddata/cli/commands/domain_cmd.rb +0 -46
  110. data/lib/gooddata/cli/commands/process_cmd.rb +0 -145
  111. data/lib/gooddata/cli/commands/projects_cmd.rb +0 -23
  112. data/lib/gooddata/cli/commands/run_ruby_cmd.rb +0 -77
  113. data/lib/gooddata/cli/commands/scaffold_cmd.rb +0 -35
  114. data/lib/gooddata/cli/commands/user_cmd.rb +0 -24
@@ -12,8 +12,6 @@ module GoodData
12
12
  attr_reader :dirty, :json
13
13
 
14
14
  alias_method :data, :json
15
- alias_method :raw_data, :json
16
- alias_method :to_hash, :json
17
15
 
18
16
  # Initializes object instance from raw wire JSON
19
17
  #
@@ -12,8 +12,6 @@ module GoodData
12
12
  attr_reader :dirty, :json
13
13
 
14
14
  alias_method :data, :json
15
- alias_method :raw_data, :json
16
- alias_method :to_hash, :json
17
15
 
18
16
  # Initializes object instance from raw wire JSON
19
17
  #
@@ -74,6 +74,16 @@ module GoodData
74
74
  a[:title] = attribute['title']
75
75
  a[:description] = attribute['description']
76
76
  a[:folder] = attribute['folder']
77
+ if attribute['grain']
78
+ a[:grain] = attribute['grain'].map do |g|
79
+ case g.keys.first.to_sym
80
+ when :dateDimension
81
+ { date: g.values.first }
82
+ else
83
+ Helpers.symbolize_keys(g)
84
+ end
85
+ end
86
+ end
77
87
  end
78
88
  [attribute] + pl + rl
79
89
  end
@@ -7,7 +7,7 @@
7
7
  require_relative '../rest/rest'
8
8
 
9
9
  module GoodData
10
- class Invitation < GoodData::Rest::Object
10
+ class Invitation < Rest::Resource
11
11
  def initialize(json)
12
12
  @json = json
13
13
  end
@@ -7,7 +7,7 @@
7
7
  require_relative '../rest/object'
8
8
 
9
9
  module GoodData
10
- class Links < GoodData::Rest::Object
10
+ class Links < Rest::Resource
11
11
  attr_reader :data
12
12
 
13
13
  def initialize(items)
@@ -13,7 +13,7 @@ require_relative 'project_role'
13
13
  require_relative '../rest/object'
14
14
 
15
15
  module GoodData
16
- class Membership < GoodData::Rest::Object
16
+ class Membership < Rest::Resource
17
17
  attr_reader :json
18
18
 
19
19
  ASSIGNABLE_MEMBERS = [
@@ -109,7 +109,7 @@ module GoodData
109
109
  def contributor
110
110
  url = @json['user']['meta']['contributor']
111
111
  data = client.get url
112
- client.factory.create(GoodData::Membership, data)
112
+ client.create(GoodData::Membership, data)
113
113
  end
114
114
 
115
115
  # Gets date when created
@@ -242,7 +242,7 @@ module GoodData
242
242
  # Gets profile of this membership
243
243
  def profile
244
244
  raw = client.get @json['user']['links']['self']
245
- client.factory.create(GoodData::Profile, raw)
245
+ client.create(GoodData::Profile, raw)
246
246
  end
247
247
 
248
248
  # Gets URL of profile membership
@@ -253,7 +253,7 @@ module GoodData
253
253
  # # Gets project which this membership relates to
254
254
  # def project
255
255
  # raw = client.get project_url
256
- # client.factory.create(GoodData::Project, raw)
256
+ # client.create(GoodData::Project, raw)
257
257
  # end
258
258
 
259
259
  # Gets project id
@@ -274,7 +274,7 @@ module GoodData
274
274
  tmp['projects'].map do |project_meta|
275
275
  project_uri = project_meta['project']['links']['self']
276
276
  project = client.get project_uri
277
- client.factory.create(GoodData::Project, project)
277
+ client.create(GoodData::Project, project)
278
278
  end
279
279
  end
280
280
 
@@ -294,7 +294,7 @@ module GoodData
294
294
  tmp = client.get roles_link
295
295
  tmp['associatedRoles']['roles'].pmap do |role_uri|
296
296
  role = client.get role_uri
297
- client.factory.create(GoodData::ProjectRole, role)
297
+ client.create(GoodData::ProjectRole, role)
298
298
  end
299
299
  end
300
300
 
@@ -401,6 +401,10 @@ module GoodData
401
401
  tmp
402
402
  end
403
403
 
404
+ def user_groups
405
+ project.user_groups(:all, user: obj_id)
406
+ end
407
+
404
408
  private
405
409
 
406
410
  # Sets status to 'ENABLED' or 'DISABLED'
@@ -4,34 +4,102 @@
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
+ require 'multi_json'
8
+
7
9
  require_relative '../core/project'
8
10
 
9
11
  require_relative '../mixins/mixins'
10
12
  require_relative '../rest/object'
11
13
 
12
14
  module GoodData
13
- class MdObject < GoodData::Rest::Object
15
+ class MdObject < Rest::Resource
14
16
  MD_OBJ_CTG = 'obj'
15
17
  IDENTIFIERS_CFG = 'instance-identifiers'
16
18
 
17
- attr_accessor :json
19
+ extend Mixin::MdIdToUri
20
+ extend Mixin::MdObjectIndexer
21
+ extend Mixin::MdObjectQuery
18
22
 
19
- alias_method :raw_data, :json
20
- alias_method :to_hash, :json
23
+ extend Mixin::MdFinders
24
+ extend Mixin::MdObjId
21
25
 
22
- include GoodData::Mixin::RestResource
26
+ include Mixin::Links
27
+ include Mixin::ObjId
28
+ include Mixin::MdRelations
29
+ include Mixin::MdGrantees
23
30
 
24
31
  class << self
25
- def metadata_property_reader(*props)
26
- props.each do |prop|
27
- define_method prop, proc { meta[prop.to_s] }
32
+ # Method used for replacing objects like Attribute, Fact or Metric. It takes the object. Scans its JSON
33
+ # representation and returns a new one with object references changed according to mapping. The references an be found either in the object structure or in the MAQL in bracketed form. This implementation takes care only of those in bracketed form.
34
+ #
35
+ # @param obj [GoodData::MdObject] what Object that should be replaced
36
+ # @param mapping [Array[Array]] Array of mapping pairs.
37
+ # @return [GoodData::MdObject]
38
+ def replace_bracketed(obj, mapping)
39
+ replace(obj, mapping) { |e, a, b| e.gsub("[#{a}]", "[#{b}]") }
40
+ end
41
+
42
+ # Method used for replacing objects like Attribute, Fact or Metric. It takes the object. Scans its JSON
43
+ # representation and returns a new one with object references changed according to mapping. The references an be found either in the object structure or in the MAQL in bracketed form. This implementation takes care only of those in object structure where they are as a string in JSON.
44
+ #
45
+ # @param obj [GoodData::MdObject] Object that should be replaced
46
+ # @param mapping [Array[Array]] Array of mapping pairs.
47
+ # @return [GoodData::MdObject]
48
+ def replace_quoted(obj, mapping)
49
+ replace(obj, mapping) do |e, a, b|
50
+ e.gsub("\"#{a}\"", "\"#{b}\"")
28
51
  end
29
52
  end
30
53
 
31
- def metadata_property_writer(*props)
32
- props.each do |prop|
33
- define_method "#{prop}=", proc { |val| meta[prop.to_s] = val }
54
+ # Helper method used for replacing objects like Attribute, Fact or Metric. It takes the object. Scans its JSON
55
+ # representation yields for a client to perform replacement for each mapping pair and returns a new one
56
+ # with object of the same type as obj.
57
+ #
58
+ # @param obj [GoodData::MdObject] Object that should be replaced
59
+ # @param mapping [Array[Array]] Array of mapping pairs.
60
+ # @param block [Proc] Block that receives the object state as a JSON string and mapping pair and expects a new object state as a JSON string back
61
+ # @return [GoodData::MdObject]
62
+ def replace(obj, mapping, &block)
63
+ json = mapping.reduce(obj.to_json) do |a, e|
64
+ obj_a, obj_b = e
65
+ uri_what = obj_a.respond_to?(:uri) ? obj_a.uri : obj_a
66
+ uri_for_what = obj_b.respond_to?(:uri) ? obj_b.uri : obj_b
67
+ block.call(a, uri_what, uri_for_what)
68
+ end
69
+ client = obj.client
70
+ client.create(obj.class, MultiJson.load(json), :project => obj.project)
71
+ end
72
+
73
+ # Helper method used for finding attribute elements that are interesting becuase they can be possibly
74
+ # replaced according to mapping specification. This walks through all the attribute elemets. Picks only those
75
+ # whose attribute is mentioned in the mapping. Walks through all the labels of that particular attribute and
76
+ # tries to find a value from one to be translated into a label in second. Obviously this is not guaranteed to
77
+ # find any results or in some cases can yield to incorrect results.
78
+ #
79
+ # @param obj [GoodData::MdObject] Object that should be replaced
80
+ # @param mapping [Array[Array]] Array of mapping pairs.
81
+ # @param block [Proc] Block that receives the object state as a JSON string and mapping pair and expects a new object state as a JSON string back
82
+ # @return [GoodData::MdObject]
83
+ def find_replaceable_values(obj, mapping)
84
+ values_to_replace = GoodData::SmallGoodZilla.extract_element_uri_pairs(MultiJson.dump(obj.to_json))
85
+ values_from_mapping = values_to_replace.select { |i| mapping.map { |a, _| a.uri }.include?(i.first) }
86
+ replaceable_vals = values_from_mapping.map do |a_uri, id|
87
+ from_attribute, to_attribute = mapping.find { |k, _| k.uri == a_uri }
88
+ vals = from_attribute.values_for(id)
89
+ labels = to_attribute.labels
90
+ results = labels.to_enum.mapcat do |l|
91
+ vals.map do |v|
92
+ begin
93
+ l.find_value_uri(v)
94
+ rescue
95
+ nil
96
+ end
97
+ end
98
+ end
99
+ fail "Unable to find replacement for #{a_uri}" if results.compact.empty?
100
+ [a_uri, id, results.compact.first]
34
101
  end
102
+ replaceable_vals.map { |a, id, r| ["#{a}/elements?id=#{id}", r] }
35
103
  end
36
104
  end
37
105
 
@@ -88,6 +156,25 @@ module GoodData
88
156
  @project ||= Project[uri.gsub(%r{\/obj\/\d+$}, ''), :client => client]
89
157
  end
90
158
 
159
+ # Method used for replacing objects like Attribute, Fact or Metric. Returns new object of the same type.
160
+ #
161
+ # @param [GoodData::MdObject] what Object that should be replaced
162
+ # @param [GoodData::MdObject] for_what Object it is replaced with
163
+ # @return [GoodData::Metric]
164
+ def replace(mapping)
165
+ GoodData::MdObject.replace_quoted(self, mapping)
166
+ end
167
+
168
+ # Method used for replacing objects like Attribute, Fact or Metric. Returns itself mutated.
169
+ # @param [GoodData::MdObject] what Object that should be replaced
170
+ # @param [GoodData::MdObject] for_what Object it is replaced with
171
+ # @return [GoodData::Metric]
172
+ def replace!(mapping)
173
+ x = replace(mapping)
174
+ @json = x.json
175
+ self
176
+ end
177
+
91
178
  def remove_tag(a_tag)
92
179
  self.tags = tag_set.delete(a_tag).to_a.join(' ')
93
180
  self
@@ -12,9 +12,7 @@ require_relative '../../mixins/is_attribute'
12
12
 
13
13
  module GoodData
14
14
  class Attribute < MdObject
15
- root_key :attribute
16
-
17
- include GoodData::Mixin::IsAttribute
15
+ include Mixin::IsAttribute
18
16
 
19
17
  ATTRIBUTE_BASE_AGGREGATIONS = [:count]
20
18
 
@@ -32,16 +30,17 @@ module GoodData
32
30
  #
33
31
  # @param uri [String] Uri of the element. in the form of /gdc/md/PID/obj/OBJ_ID/elements?id=21
34
32
  # @return [String] Textual representation of a particular attribute element
35
- def find_element_value(uri, opts = { :client => @client, :project => @project })
36
- matches = uri.match(%r{(.*)/elements\?id=(\d+)$})
37
- opts[:project].attributes(matches[1]).primary_label.find_element_value(uri)
33
+ def find_element_value(stuff, opts = { :project => GoodData.project })
34
+ stuff.scan(%r{([^\[\]]*)\/elements\?id=(\d+)}).pmap do |a, id|
35
+ opts[:project].attributes(a).primary_label.find_element_value(id.to_i)
36
+ end.first
38
37
  end
39
38
  end
40
39
 
41
40
  # Returns the labels of an attribute
42
41
  # @return [Array<GoodData::Label>]
43
42
  def display_forms
44
- content['displayForms'].map { |df| GoodData::Label[df['meta']['uri'], :client => client, :project => project] }
43
+ content['displayForms'].pmap { |df| project.labels(df['meta']['uri']) }
45
44
  end
46
45
  alias_method :labels, :display_forms
47
46
 
@@ -9,6 +9,7 @@ require_relative 'dashboard/filter_item'
9
9
  require_relative 'dashboard/report_item'
10
10
 
11
11
  require_relative '../../core/core'
12
+ require_relative '../../helpers/global_helpers'
12
13
  require_relative '../metadata'
13
14
  require_relative 'metadata'
14
15
  require_relative 'report'
@@ -17,9 +18,29 @@ require 'multi_json'
17
18
 
18
19
  module GoodData
19
20
  class Dashboard < GoodData::MdObject
20
- root_key :projectDashboard
21
+ include Mixin::Lockable
22
+
23
+ EMPTY_OBJECT = {
24
+ 'projectDashboard' => {
25
+ 'content' => {
26
+ 'tabs' => [],
27
+ 'filters' => []
28
+ },
29
+ 'meta' => {
30
+ 'tags' => '',
31
+ 'summary' => '',
32
+ 'title' => ''
33
+ }
34
+ }
35
+ }
21
36
 
22
- include GoodData::Mixin::Lockable
37
+ ASSIGNABLE_MEMBERS = [
38
+ :filters,
39
+ :tabs,
40
+ :tags,
41
+ :summary,
42
+ :title
43
+ ]
23
44
 
24
45
  class << self
25
46
  # Method intended to get all objects of that type in a specified project
@@ -31,84 +52,19 @@ module GoodData
31
52
  query('projectDashboard', Dashboard, options)
32
53
  end
33
54
 
34
- def create_report_tab(tab, options = { :client => GoodData.client, :project => GoodData.project })
35
- title = tab[:title]
36
- {
37
- :title => title,
38
- :items => tab[:items].map { |i| GoodData::Dashboard.create_report_tab_item(i, options) }
39
- }
40
- end
41
-
42
- def create_report_tab_item(item, options = { :client => GoodData.client, :project => GoodData.project })
43
- title = item[:title]
44
-
45
- report = GoodData::Report.find_first_by_title(title, options)
46
- {
47
- :reportItem => {
48
- :obj => report.uri,
49
- :sizeY => item[:size_y] || 200,
50
- :sizeX => item[:size_x] || 300,
51
- :style => {
52
- :displayTitle => 1,
53
- :background => {
54
- :opacity => 0
55
- }
56
- },
57
- :visualization => {
58
- :grid => {
59
- :columnWidths => []
60
- },
61
- :oneNumber => {
62
- :labels => {}
63
- }
64
- },
65
- :positionY => item[:position_y] || 0,
66
- :filters => [],
67
- :positionX => item[:position_x] || 0
68
- }
69
- }
70
- end
71
-
72
- def create(dashboard = { :tabs => [] }, options = { :client => GoodData.client, :project => GoodData.project })
73
- client = options[:client]
74
- fail ArgumentError, 'No :client specified' if client.nil?
75
-
76
- p = options[:project]
77
- fail ArgumentError, 'No :project specified' if p.nil?
78
-
79
- project = GoodData::Project[p, options]
80
- fail ArgumentError, 'Wrong :project specified' if project.nil?
81
-
82
- tabs = dashboard[:tabs] || []
83
-
84
- stuff = {
85
- 'projectDashboard' => {
86
- 'content' => {
87
- 'tabs' => tabs.map { |t| GoodData::Dashboard.create_report_tab(t, options) },
88
- 'filters' => []
89
- },
90
- 'meta' => {
91
- 'tags' => dashboard[:tags],
92
- 'summary' => dashboard[:summary],
93
- 'title' => dashboard[:title]
94
- }
95
- }
96
- }
55
+ def create(dashboard = {}, options = { :client => GoodData.client, :project => GoodData.project })
56
+ client, project = GoodData.get_client_and_project(options)
97
57
 
98
- client.create(Dashboard, stuff, :project => project)
58
+ res = client.create(Dashboard, GoodData::Helpers.deep_dup(GoodData::Helpers.deep_stringify_keys(EMPTY_OBJECT)), :project => project)
59
+ dashboard.each do |k, v|
60
+ res.send("#{k}=", v) if ASSIGNABLE_MEMBERS.include? k
61
+ end
62
+ res
99
63
  end
100
64
  end
101
65
 
102
66
  def add_tab(tab)
103
- title = tab[:title] || 'Default Tab Title'
104
- items = tab[:items] || []
105
-
106
- new_tab_json = {
107
- :title => title,
108
- :items => items.map { |i| GoodData::Dashboard.create_report_tab_item(i, options) }
109
- }
110
-
111
- new_tab = GoodData::DashboardTab.new(self, GoodData::Helpers.deep_stringify_keys(new_tab_json))
67
+ new_tab = GoodData::DashboardTab.create(self, tab)
112
68
  content['tabs'] << new_tab.json
113
69
  new_tab
114
70
  end
@@ -129,6 +85,16 @@ module GoodData
129
85
  client.poll_on_code(x['asyncTask']['link']['poll'], options.merge(process: false))
130
86
  end
131
87
 
88
+ # Method used for replacing values in their state according to mapping. Can be used to replace any values but it is typically used to replace the URIs. Returns a new object of the same type.
89
+ #
90
+ # @param [Array<Array>]Mapping specifying what should be exchanged for what. As mapping should be used output of GoodData::Helpers.prepare_mapping.
91
+ # @return [GoodData::Dashboard]
92
+ def replace(mapping)
93
+ x = GoodData::MdObject.replace_quoted(self, mapping)
94
+ vals = GoodData::MdObject.find_replaceable_values(self, mapping)
95
+ GoodData::MdObject.replace_quoted(x, vals)
96
+ end
97
+
132
98
  def tabs
133
99
  content['tabs'].map do |tab|
134
100
  GoodData::DashboardTab.new(self, tab)
@@ -4,19 +4,35 @@
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
- module GoodData
8
- class DashboardItem
9
- include GoodData::Mixin::RootKeyGetter
10
- include GoodData::Mixin::DataGetter
7
+ require_relative '../../../rest/resource'
11
8
 
9
+ module GoodData
10
+ class DashboardItem < Rest::Resource
12
11
  attr_reader :tab
13
12
  attr_accessor :json
14
13
 
14
+ ASSIGNABLE_MEMBERS = [
15
+ :pos_x,
16
+ :pos_y,
17
+ :position_x,
18
+ :position_y,
19
+ :size_x,
20
+ :size_y
21
+ ]
22
+
15
23
  def initialize(tab, json)
16
24
  @tab = tab
17
25
  @json = json
18
26
  end
19
27
 
28
+ def filters
29
+ data['filters']
30
+ end
31
+
32
+ def filters=(new_filters)
33
+ data['filters'] = new_filters
34
+ end
35
+
20
36
  def position_x
21
37
  data['positionX']
22
38
  end