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.
- checksums.yaml +4 -4
- data/.rubocop.yml +54 -0
- data/CHANGELOG.md +3 -0
- data/DEPENDENCIES.md +155 -154
- data/README.md +15 -6
- data/Rakefile +5 -3
- data/dependency_decisions.yml +2 -0
- data/gooddata.gemspec +2 -3
- data/lib/gooddata/cli/cli.rb +1 -3
- data/lib/gooddata/cli/commands/auth_cmd.rb +16 -7
- data/lib/gooddata/cli/commands/project_cmd.rb +16 -178
- data/lib/gooddata/cli/shared.rb +46 -44
- data/lib/gooddata/commands/auth.rb +4 -0
- data/lib/gooddata/commands/project.rb +7 -24
- data/lib/gooddata/exceptions/object_migration.rb +4 -0
- data/lib/gooddata/exceptions/segment_not_empty.rb +18 -0
- data/lib/gooddata/extensions/object.rb +12 -0
- data/lib/gooddata/goodzilla/goodzilla.rb +56 -9
- data/lib/gooddata/helpers/global_helpers.rb +92 -0
- data/lib/gooddata/mixins/md_finders.rb +2 -8
- data/lib/gooddata/mixins/md_grantees.rb +42 -0
- data/lib/gooddata/mixins/md_id_to_uri.rb +1 -8
- data/lib/gooddata/mixins/md_object_id.rb +1 -1
- data/lib/gooddata/mixins/md_object_indexer.rb +5 -8
- data/lib/gooddata/mixins/md_object_query.rb +2 -2
- data/lib/gooddata/mixins/not_group.rb +17 -0
- data/lib/gooddata/mixins/rest_getters.rb +2 -2
- data/lib/gooddata/mixins/rest_resource.rb +1 -0
- data/lib/gooddata/mixins/to_json.rb +11 -0
- data/lib/gooddata/mixins/uri_getter.rb +9 -0
- data/lib/gooddata/models/blueprint/anchor_field.rb +14 -0
- data/lib/gooddata/models/blueprint/project_blueprint.rb +15 -1
- data/lib/gooddata/models/blueprint/to_wire.rb +10 -0
- data/lib/gooddata/models/client.rb +178 -0
- data/lib/gooddata/models/client_synchronization_result.rb +31 -0
- data/lib/gooddata/models/client_synchronization_result_details.rb +41 -0
- data/lib/gooddata/models/datawarehouse.rb +1 -5
- data/lib/gooddata/models/domain.rb +85 -1
- data/lib/gooddata/models/execution.rb +0 -2
- data/lib/gooddata/models/execution_detail.rb +0 -2
- data/lib/gooddata/models/from_wire.rb +10 -0
- data/lib/gooddata/models/invitation.rb +1 -1
- data/lib/gooddata/models/links.rb +1 -1
- data/lib/gooddata/models/membership.rb +10 -6
- data/lib/gooddata/models/metadata.rb +98 -11
- data/lib/gooddata/models/metadata/attribute.rb +6 -7
- data/lib/gooddata/models/metadata/dashboard.rb +41 -75
- data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +20 -4
- data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +37 -0
- data/lib/gooddata/models/metadata/dashboard/filter_item.rb +49 -0
- data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/headline_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +46 -0
- data/lib/gooddata/models/metadata/dashboard/report_item.rb +49 -8
- data/lib/gooddata/models/metadata/dashboard/text_item.rb +55 -0
- data/lib/gooddata/models/metadata/dashboard_tab.rb +83 -30
- data/lib/gooddata/models/metadata/dataset.rb +0 -2
- data/lib/gooddata/models/metadata/dimension.rb +1 -3
- data/lib/gooddata/models/metadata/fact.rb +1 -3
- data/lib/gooddata/models/metadata/label.rb +1 -3
- data/lib/gooddata/models/metadata/metric.rb +11 -42
- data/lib/gooddata/models/metadata/report.rb +7 -18
- data/lib/gooddata/models/metadata/report_definition.rb +21 -113
- data/lib/gooddata/models/metadata/scheduled_mail.rb +274 -0
- data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +62 -0
- data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +64 -0
- data/lib/gooddata/models/metadata/variable.rb +8 -2
- data/lib/gooddata/models/model.rb +2 -9
- data/lib/gooddata/models/process.rb +7 -29
- data/lib/gooddata/models/profile.rb +1 -1
- data/lib/gooddata/models/project.rb +131 -167
- data/lib/gooddata/models/project_creator.rb +2 -7
- data/lib/gooddata/models/project_metadata.rb +2 -10
- data/lib/gooddata/models/project_role.rb +4 -10
- data/lib/gooddata/models/report_data_result.rb +3 -5
- data/lib/gooddata/models/schedule.rb +4 -31
- data/lib/gooddata/models/segment.rb +192 -0
- data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +2 -2
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +1 -1
- data/lib/gooddata/models/user_filters/variable_user_filter.rb +11 -0
- data/lib/gooddata/models/user_group.rb +241 -0
- data/lib/gooddata/rest/connection.rb +81 -16
- data/lib/gooddata/rest/object.rb +29 -0
- data/lib/gooddata/rest/object_factory.rb +6 -1
- data/lib/gooddata/rest/resource.rb +7 -1
- data/lib/gooddata/version.rb +1 -1
- data/spec/environment/default.rb +19 -16
- data/spec/environment/develop.rb +10 -10
- data/spec/environment/hotfix.rb +6 -6
- data/spec/environment/production.rb +14 -14
- data/spec/environment/release.rb +6 -6
- data/spec/environment/staging.rb +9 -9
- data/spec/environment/staging_3.rb +14 -15
- data/spec/integration/blueprint_with_grain_spec.rb +72 -0
- data/spec/integration/clients_spec.rb +135 -0
- data/spec/integration/date_dim_switch_spec.rb +142 -0
- data/spec/integration/full_project_spec.rb +3 -3
- data/spec/integration/project_spec.rb +20 -0
- data/spec/integration/segments_spec.rb +141 -0
- data/spec/integration/user_group_spec.rb +127 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/unit/models/domain_spec.rb +7 -1
- data/spec/unit/models/metric_spec.rb +0 -8
- data/spec/unit/models/profile_spec.rb +1 -1
- data/spec/unit/models/report_result_data_spec.rb +6 -0
- metadata +38 -38
- data/lib/gooddata/cli/commands/api_cmd.rb +0 -34
- data/lib/gooddata/cli/commands/console_cmd.rb +0 -40
- data/lib/gooddata/cli/commands/domain_cmd.rb +0 -46
- data/lib/gooddata/cli/commands/process_cmd.rb +0 -145
- data/lib/gooddata/cli/commands/projects_cmd.rb +0 -23
- data/lib/gooddata/cli/commands/run_ruby_cmd.rb +0 -77
- data/lib/gooddata/cli/commands/scaffold_cmd.rb +0 -35
- data/lib/gooddata/cli/commands/user_cmd.rb +0 -24
|
@@ -10,9 +10,7 @@ require_relative 'metadata'
|
|
|
10
10
|
|
|
11
11
|
module GoodData
|
|
12
12
|
class Dimension < GoodData::MdObject
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
include GoodData::Mixin::IsDimension
|
|
13
|
+
include Mixin::IsDimension
|
|
16
14
|
|
|
17
15
|
class << self
|
|
18
16
|
# Method intended to get all objects of that type in a specified project
|
|
@@ -12,9 +12,7 @@ require_relative 'metadata'
|
|
|
12
12
|
|
|
13
13
|
module GoodData
|
|
14
14
|
class Fact < GoodData::MdObject
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
include GoodData::Mixin::IsFact
|
|
15
|
+
include Mixin::IsFact
|
|
18
16
|
|
|
19
17
|
# TODO: verify that we have all (which we do not right now)
|
|
20
18
|
FACT_BASE_AGGREGATIONS = [:sum, :min, :max, :avg, :median, :runsum, :runmin, :runmax, :runavg, :runstdev, :runstdevp, :runvar, :runvarp, :stdev, :stdevp, :var, :varp]
|
|
@@ -10,9 +10,7 @@ require_relative 'metadata'
|
|
|
10
10
|
|
|
11
11
|
module GoodData
|
|
12
12
|
class Label < GoodData::MdObject
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
include GoodData::Mixin::IsLabel
|
|
13
|
+
include Mixin::IsLabel
|
|
16
14
|
|
|
17
15
|
# Finds an attribute element URI for given value. This URI can be used by find_element_value to find the original value again
|
|
18
16
|
# @param [String] value value of an label you are looking for
|
|
@@ -12,12 +12,7 @@ require_relative 'metadata'
|
|
|
12
12
|
module GoodData
|
|
13
13
|
# Metric representation
|
|
14
14
|
class Metric < MdObject
|
|
15
|
-
include
|
|
16
|
-
|
|
17
|
-
alias_method :to_hash, :json
|
|
18
|
-
|
|
19
|
-
include GoodData::Mixin::RestResource
|
|
20
|
-
root_key :metric
|
|
15
|
+
include Mixin::Lockable
|
|
21
16
|
|
|
22
17
|
class << self
|
|
23
18
|
# Method intended to get all objects of that type in a specified project
|
|
@@ -34,14 +29,7 @@ module GoodData
|
|
|
34
29
|
end
|
|
35
30
|
|
|
36
31
|
def create(metric, options = { :client => GoodData.connection, :project => GoodData.project })
|
|
37
|
-
client = options
|
|
38
|
-
fail ArgumentError, 'No :client specified' if client.nil?
|
|
39
|
-
|
|
40
|
-
p = options[:project]
|
|
41
|
-
fail ArgumentError, 'No :project specified' if p.nil?
|
|
42
|
-
|
|
43
|
-
project = GoodData::Project[p, options]
|
|
44
|
-
fail ArgumentError, 'Wrong :project specified' if project.nil?
|
|
32
|
+
client, project = GoodData.get_client_and_project(options)
|
|
45
33
|
|
|
46
34
|
if metric.is_a?(String)
|
|
47
35
|
expression = metric || options[:expression]
|
|
@@ -119,14 +107,7 @@ module GoodData
|
|
|
119
107
|
end
|
|
120
108
|
|
|
121
109
|
def xexecute(expression, opts = { :client => GoodData.connection, :project => GoodData.project })
|
|
122
|
-
|
|
123
|
-
fail ArgumentError, 'No :client specified' if client.nil?
|
|
124
|
-
|
|
125
|
-
p = opts[:project]
|
|
126
|
-
fail ArgumentError, 'No :project specified' if p.nil?
|
|
127
|
-
|
|
128
|
-
project = GoodData::Project[p, opts]
|
|
129
|
-
fail ArgumentError, 'Wrong :project specified' if project.nil?
|
|
110
|
+
GoodData.get_client_and_project(opts)
|
|
130
111
|
|
|
131
112
|
execute(expression, opts.merge(:extended_notation => true))
|
|
132
113
|
end
|
|
@@ -175,27 +156,15 @@ module GoodData
|
|
|
175
156
|
contain?(uri)
|
|
176
157
|
end
|
|
177
158
|
|
|
178
|
-
# Method used for replacing
|
|
179
|
-
#
|
|
180
|
-
# @param [
|
|
159
|
+
# 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.
|
|
160
|
+
#
|
|
161
|
+
# @param [Array<Array>]Mapping specifying what should be exchanged for what. As mapping should be used output of GoodData::Helpers.prepare_mapping.
|
|
181
162
|
# @return [GoodData::Metric]
|
|
182
|
-
def replace(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
elsif what.is_a?(Array) && for_what.is_a?(Array)
|
|
188
|
-
whats.zip(to_whats)
|
|
189
|
-
else
|
|
190
|
-
[[what, for_what]]
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
pairs.each do |a, b|
|
|
194
|
-
uri_what = a.respond_to?(:uri) ? a.uri : a
|
|
195
|
-
uri_for_what = b.respond_to?(:uri) ? b.uri : b
|
|
196
|
-
self.expression = expression.gsub("[#{uri_what}]", "[#{uri_for_what}]")
|
|
197
|
-
end
|
|
198
|
-
self
|
|
163
|
+
def replace(mapping)
|
|
164
|
+
x = GoodData::MdObject.replace_quoted(self, mapping)
|
|
165
|
+
x = GoodData::MdObject.replace_bracketed(x, mapping)
|
|
166
|
+
vals = GoodData::MdObject.find_replaceable_values(x, mapping)
|
|
167
|
+
GoodData::MdObject.replace_bracketed(x, vals)
|
|
199
168
|
end
|
|
200
169
|
|
|
201
170
|
# Method used for replacing attribute element values. Looks up certain value of a label in the MAQL expression and exchanges it for a different value of the same label.
|
|
@@ -9,9 +9,7 @@ require_relative 'metadata'
|
|
|
9
9
|
|
|
10
10
|
module GoodData
|
|
11
11
|
class Report < GoodData::MdObject
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
include GoodData::Mixin::Lockable
|
|
12
|
+
include Mixin::Lockable
|
|
15
13
|
|
|
16
14
|
class << self
|
|
17
15
|
# Method intended to get all objects of that type in a specified project
|
|
@@ -24,14 +22,7 @@ module GoodData
|
|
|
24
22
|
end
|
|
25
23
|
|
|
26
24
|
def create(options = { :client => GoodData.connection, :project => GoodData.project })
|
|
27
|
-
client = options
|
|
28
|
-
fail ArgumentError, 'No :client specified' if client.nil?
|
|
29
|
-
|
|
30
|
-
p = options[:project]
|
|
31
|
-
fail ArgumentError, 'No :project specified' if p.nil?
|
|
32
|
-
|
|
33
|
-
project = client.projects(p)
|
|
34
|
-
fail ArgumentError, 'Wrong :project specified' if project.nil?
|
|
25
|
+
client, project = GoodData.get_client_and_project(options)
|
|
35
26
|
|
|
36
27
|
title = options[:title]
|
|
37
28
|
fail 'Report needs a title specified' unless title
|
|
@@ -208,15 +199,13 @@ module GoodData
|
|
|
208
199
|
self
|
|
209
200
|
end
|
|
210
201
|
|
|
211
|
-
#
|
|
212
|
-
# real work is done under the hood in report definition. This is just deferring to those
|
|
202
|
+
# 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.
|
|
213
203
|
#
|
|
214
|
-
# @param
|
|
215
|
-
# @
|
|
216
|
-
|
|
217
|
-
def replace(what, for_what)
|
|
204
|
+
# @param [Array<Array>]Mapping specifying what should be exchanged for what. As mapping should be used output of GoodData::Helpers.prepare_mapping.
|
|
205
|
+
# @return [GoodData::Report]
|
|
206
|
+
def replace(mapping)
|
|
218
207
|
new_defs = definitions.map do |rep_def|
|
|
219
|
-
rep_def.replace(
|
|
208
|
+
rep_def.replace(mapping)
|
|
220
209
|
end
|
|
221
210
|
new_defs.pmap(&:save)
|
|
222
211
|
self
|
|
@@ -12,8 +12,6 @@ module GoodData
|
|
|
12
12
|
# Report Definition
|
|
13
13
|
# TODO: Add more doc ...
|
|
14
14
|
class ReportDefinition < GoodData::MdObject
|
|
15
|
-
root_key :reportDefinition
|
|
16
|
-
|
|
17
15
|
class << self
|
|
18
16
|
# Method intended to get all objects of that type in a specified project
|
|
19
17
|
#
|
|
@@ -52,10 +50,16 @@ module GoodData
|
|
|
52
50
|
}
|
|
53
51
|
end
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
# Method creates the list of filter representaion suitable for posting on the api. It can currently recognize 2 types of filters. Variable filters and attribute filters. Method for internal usage
|
|
54
|
+
#
|
|
55
|
+
# @param filters [GoodData::Variable|Array<Array>]
|
|
56
|
+
# @param options [Hash] the options hash
|
|
57
|
+
# @return [Array<Hash>] Returns the structure that is stored internally in the report definition and later psted on the API
|
|
58
|
+
def create_filters_part(filters, options = {})
|
|
59
|
+
project = options[:project]
|
|
60
|
+
vars = filters.select { |f| f.is_a?(GoodData::Variable) }.map { |v| { expression: "[#{v.uri}]" } }
|
|
61
|
+
category = filters.select { |f| f.is_a?(Array) }.map { |v| GoodData::SmallGoodZilla.create_category_filter(v, project) }
|
|
62
|
+
vars + category
|
|
59
63
|
end
|
|
60
64
|
|
|
61
65
|
def create_part(stuff)
|
|
@@ -75,10 +79,7 @@ module GoodData
|
|
|
75
79
|
end
|
|
76
80
|
|
|
77
81
|
def find(stuff, opts = { :client => GoodData.connection, :project => GoodData.project })
|
|
78
|
-
|
|
79
|
-
project = opts[:project]
|
|
80
|
-
fail ArgumentError, 'No :client specified' if client.nil?
|
|
81
|
-
fail ArgumentError, 'No :project specified' if project.nil?
|
|
82
|
+
_client, project = GoodData.get_client_and_project(opts)
|
|
82
83
|
|
|
83
84
|
stuff.map do |item|
|
|
84
85
|
obj = if item.is_a?(String)
|
|
@@ -133,14 +134,7 @@ module GoodData
|
|
|
133
134
|
end
|
|
134
135
|
|
|
135
136
|
def create(options = { :client => GoodData.connection, :project => GoodData.project })
|
|
136
|
-
client = options
|
|
137
|
-
fail ArgumentError, 'No :client specified' if client.nil?
|
|
138
|
-
|
|
139
|
-
p = options[:project]
|
|
140
|
-
fail ArgumentError, 'No :project specified' if p.nil?
|
|
141
|
-
|
|
142
|
-
project = GoodData::Project[p, options]
|
|
143
|
-
fail ArgumentError, 'Wrong :project specified' if project.nil?
|
|
137
|
+
client, project = GoodData.get_client_and_project(options)
|
|
144
138
|
|
|
145
139
|
left = Array(options[:left])
|
|
146
140
|
top = Array(options[:top])
|
|
@@ -167,7 +161,7 @@ module GoodData
|
|
|
167
161
|
'rows' => ReportDefinition.create_part(left)
|
|
168
162
|
},
|
|
169
163
|
'format' => 'grid',
|
|
170
|
-
'filters' => ReportDefinition.create_filters_part(filters)
|
|
164
|
+
'filters' => ReportDefinition.create_filters_part(filters, :project => project)
|
|
171
165
|
},
|
|
172
166
|
'meta' => {
|
|
173
167
|
'tags' => '',
|
|
@@ -249,101 +243,15 @@ module GoodData
|
|
|
249
243
|
content['filters'].map { |f| f['expression'] }
|
|
250
244
|
end
|
|
251
245
|
|
|
252
|
-
#
|
|
246
|
+
# 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.
|
|
253
247
|
#
|
|
254
|
-
# @param
|
|
255
|
-
# @
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
whats.zip(to_whats)
|
|
262
|
-
elsif what.is_a?(Array) && for_what.is_a?(Array)
|
|
263
|
-
whats.zip(to_whats)
|
|
264
|
-
else
|
|
265
|
-
[[what, for_what]]
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
pairs.each do |pair|
|
|
269
|
-
what = pair[0]
|
|
270
|
-
for_what = pair[1]
|
|
271
|
-
|
|
272
|
-
uri_what = what.respond_to?(:uri) ? what.uri : what
|
|
273
|
-
uri_for_what = for_what.respond_to?(:uri) ? for_what.uri : for_what
|
|
274
|
-
|
|
275
|
-
content['grid']['metrics'] = metric_parts.map do |item|
|
|
276
|
-
GoodData::Helpers.deep_dup(item).tap do |i|
|
|
277
|
-
i['uri'].gsub!("[#{uri_what}]", "[#{uri_for_what}]")
|
|
278
|
-
end
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
cols = content['grid']['columns'] || []
|
|
282
|
-
content['grid']['columns'] = cols.map do |item|
|
|
283
|
-
if item.is_a?(Hash)
|
|
284
|
-
GoodData::Helpers.deep_dup(item).tap do |i|
|
|
285
|
-
i['attribute']['uri'].gsub!("[#{uri_what}]", "[#{uri_for_what}]")
|
|
286
|
-
end
|
|
287
|
-
else
|
|
288
|
-
item
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
rows = content['grid']['rows'] || []
|
|
293
|
-
content['grid']['rows'] = rows.map do |item|
|
|
294
|
-
if item.is_a?(Hash)
|
|
295
|
-
GoodData::Helpers.deep_dup(item).tap do |i|
|
|
296
|
-
i['attribute']['uri'].gsub!("[#{uri_what}]", "[#{uri_for_what}]")
|
|
297
|
-
end
|
|
298
|
-
else
|
|
299
|
-
item
|
|
300
|
-
end
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
widths = content['grid']['columnWidths'] || []
|
|
304
|
-
content['grid']['columnWidths'] = widths.map do |item|
|
|
305
|
-
if item.is_a?(Hash)
|
|
306
|
-
GoodData::Helpers.deep_dup(item).tap do |i|
|
|
307
|
-
if i['locator'].length > 0 && i['locator'][0].key?('attributeHeaderLocator')
|
|
308
|
-
i['locator'][0]['attributeHeaderLocator']['uri'].gsub!("[#{uri_what}]", "[#{uri_for_what}]")
|
|
309
|
-
end
|
|
310
|
-
end
|
|
311
|
-
else
|
|
312
|
-
item
|
|
313
|
-
end
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
sort = content['grid']['sort']['columns'] || []
|
|
317
|
-
content['grid']['sort']['columns'] = sort.map do |item|
|
|
318
|
-
if item.is_a?(Hash)
|
|
319
|
-
GoodData::Helpers.deep_dup(item).tap do |i|
|
|
320
|
-
next unless i.key?('metricSort')
|
|
321
|
-
next unless i['metricSort'].key?('locators')
|
|
322
|
-
next unless i['metricSort']['locators'][0].key?('attributeLocator2')
|
|
323
|
-
i['metricSort']['locators'][0]['attributeLocator2']['uri'].gsub!("[#{uri_what}]", "[#{uri_for_what}]")
|
|
324
|
-
i['metricSort']['locators'][0]['attributeLocator2']['element'].gsub!("[#{uri_what}]", "[#{uri_for_what}]")
|
|
325
|
-
end
|
|
326
|
-
else
|
|
327
|
-
item
|
|
328
|
-
end
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
if content.key?('chart')
|
|
332
|
-
content['chart']['buckets'] = content['chart']['buckets'].reduce({}) do |a, e|
|
|
333
|
-
key = e[0]
|
|
334
|
-
val = e[1]
|
|
335
|
-
a[key] = val.map do |item|
|
|
336
|
-
GoodData::Helpers.deep_dup(item).tap do |i|
|
|
337
|
-
i['uri'].gsub!("[#{uri_what}]", "[#{uri_for_what}]")
|
|
338
|
-
end
|
|
339
|
-
end
|
|
340
|
-
a
|
|
341
|
-
end
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
content['filters'] = filters.map { |filter_expression| { 'expression' => filter_expression.gsub("[#{uri_what}]", "[#{uri_for_what}]") } }
|
|
345
|
-
end
|
|
346
|
-
self
|
|
248
|
+
# @param [Array<Array>]Mapping specifying what should be exchanged for what. As mapping should be used output of GoodData::Helpers.prepare_mapping.
|
|
249
|
+
# @return [GoodData::ReportDefinition]
|
|
250
|
+
def replace(mapping)
|
|
251
|
+
x = GoodData::MdObject.replace_quoted(self, mapping)
|
|
252
|
+
x = GoodData::MdObject.replace_bracketed(x, mapping)
|
|
253
|
+
vals = GoodData::MdObject.find_replaceable_values(self, mapping)
|
|
254
|
+
GoodData::MdObject.replace_bracketed(x, vals)
|
|
347
255
|
end
|
|
348
256
|
|
|
349
257
|
# Return true if the report definition is a table
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
|
6
|
+
|
|
7
|
+
require_relative 'scheduled_mail/dashboard_attachment'
|
|
8
|
+
require_relative 'scheduled_mail/report_attachment'
|
|
9
|
+
|
|
10
|
+
require_relative '../../helpers/global_helpers'
|
|
11
|
+
|
|
12
|
+
require_relative '../../core/core'
|
|
13
|
+
require_relative '../metadata'
|
|
14
|
+
require_relative 'metadata'
|
|
15
|
+
require_relative 'report'
|
|
16
|
+
|
|
17
|
+
require 'multi_json'
|
|
18
|
+
|
|
19
|
+
module GoodData
|
|
20
|
+
class ScheduledMail < GoodData::MdObject
|
|
21
|
+
root_key :scheduledMail
|
|
22
|
+
|
|
23
|
+
include GoodData::Mixin::Lockable
|
|
24
|
+
|
|
25
|
+
DEFAULT_OPTS = {
|
|
26
|
+
# Meta options
|
|
27
|
+
:title => 'Scheduled report example',
|
|
28
|
+
:summary => 'Daily at 12:00pm PT',
|
|
29
|
+
:tags => '',
|
|
30
|
+
:deprecated => 0,
|
|
31
|
+
|
|
32
|
+
# Content When options
|
|
33
|
+
:recurrency => '0:0:0:12:0:0',
|
|
34
|
+
:startDate => '2012-06-05',
|
|
35
|
+
:timeZone => 'America/Los_Angeles',
|
|
36
|
+
|
|
37
|
+
# Content Email options
|
|
38
|
+
:to => [],
|
|
39
|
+
:bcc => [],
|
|
40
|
+
:subject => 'Scheduled Report',
|
|
41
|
+
:body => "Hey, I'm sending you new Reports and Dashboards!",
|
|
42
|
+
|
|
43
|
+
# Attachments
|
|
44
|
+
:attachments => []
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class << self
|
|
48
|
+
# Method intended to get all objects of that type in a specified project
|
|
49
|
+
#
|
|
50
|
+
# @param options [Hash] the options hash
|
|
51
|
+
# @option options [Boolean] :full if passed true the subclass can decide to pull in full objects. This is desirable from the usability POV but unfortunately has negative impact on performance so it is not the default
|
|
52
|
+
# @return [Array<GoodData::MdObject> | Array<Hash>] Return the appropriate metadata objects or their representation
|
|
53
|
+
def all(options = { :client => GoodData.connection, :project => GoodData.project })
|
|
54
|
+
query('scheduledMail', ScheduledMail, options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def convert_attachment(item, opts)
|
|
58
|
+
if item.is_a?(GoodData::Dashboard)
|
|
59
|
+
{
|
|
60
|
+
dashboardAttachment: GoodData::DashboardAttachment::DEFAULT_OPTS.merge(opts.merge(:uri => item.uri))
|
|
61
|
+
}
|
|
62
|
+
elsif item.is_a?(GoodData::Report)
|
|
63
|
+
{
|
|
64
|
+
reportAttachment: GoodData::ReportAttachment::DEFAULT_OPTS.merge(opts.merge(:uri => item.uri))
|
|
65
|
+
}
|
|
66
|
+
elsif item.is_a?(GoodData::DashboardAttachment)
|
|
67
|
+
item.json
|
|
68
|
+
elsif item.is_a?(GoodData::ReportAttachment)
|
|
69
|
+
item.json
|
|
70
|
+
elsif item.is_a?(Hash)
|
|
71
|
+
item
|
|
72
|
+
elsif item == 'dashboardAttachment'
|
|
73
|
+
{
|
|
74
|
+
dashboardAttachment: GoodData::DashboardAttachment::DEFAULT_OPTS.merge(opts)
|
|
75
|
+
}
|
|
76
|
+
elsif item == 'reportAttachment'
|
|
77
|
+
{
|
|
78
|
+
reportAttachment: GoodData::ReportAttachment::DEFAULT_OPTS.merge(opts)
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def create(options = { :client => GoodData.connection, :project => GoodData.project })
|
|
84
|
+
client = options[:client]
|
|
85
|
+
fail ArgumentError, 'No :client specified' if client.nil?
|
|
86
|
+
|
|
87
|
+
p = options[:project]
|
|
88
|
+
fail ArgumentError, 'No :project specified' if p.nil?
|
|
89
|
+
|
|
90
|
+
project = client.projects(p)
|
|
91
|
+
fail ArgumentError, 'Wrong :project specified' if project.nil?
|
|
92
|
+
|
|
93
|
+
opts = GoodData::ScheduledMail::DEFAULT_OPTS.merge(GoodData::Helpers.symbolize_keys(options))
|
|
94
|
+
|
|
95
|
+
scheduled_mail = {
|
|
96
|
+
:scheduledMail => {
|
|
97
|
+
:meta => {
|
|
98
|
+
:title => opts[:title],
|
|
99
|
+
:summary => opts[:summary],
|
|
100
|
+
:tags => opts[:tags],
|
|
101
|
+
:deprecated => opts[:deprecated]
|
|
102
|
+
},
|
|
103
|
+
:content => {
|
|
104
|
+
:when => {
|
|
105
|
+
:recurrency => opts[:recurrency],
|
|
106
|
+
:startDate => opts[:startDate] || opts[:start_date],
|
|
107
|
+
:timeZone => opts[:timeZone] || opts[:time_zone] || opts[:timezone]
|
|
108
|
+
},
|
|
109
|
+
:to => opts[:to].is_a?(Array) ? opts[:to] : [opts[:to]],
|
|
110
|
+
:bcc => opts[:bcc].is_a?(Array) ? opts[:bcc] : [opts[:bcc]],
|
|
111
|
+
:subject => opts[:subject],
|
|
112
|
+
:body => opts[:body]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
attachments = opts[:attachments].map do |attachment|
|
|
118
|
+
key = attachment.keys.first
|
|
119
|
+
body = attachment[key]
|
|
120
|
+
|
|
121
|
+
ScheduledMail.convert_attachment(key, body)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
scheduled_mail[:scheduledMail][:content][:attachments] = attachments
|
|
125
|
+
|
|
126
|
+
client.create(ScheduledMail, GoodData::Helpers.deep_stringify_keys(scheduled_mail), :project => project)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Add attachment
|
|
131
|
+
#
|
|
132
|
+
# @param [String | Object] item Schedule to add
|
|
133
|
+
# @param [Hash] opts Optional schedule options
|
|
134
|
+
# @return [Array] New list of attachments
|
|
135
|
+
def add_attachment(item, opts)
|
|
136
|
+
attachment = ScheduledMail.convert_attachment(item, opts)
|
|
137
|
+
fail ArgumentError unless attachment
|
|
138
|
+
|
|
139
|
+
content['attachments'] << attachment
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Add attachment and save
|
|
143
|
+
#
|
|
144
|
+
# @param [String | Object] item Schedule to add
|
|
145
|
+
# @param [Hash] opts Optional schedule options
|
|
146
|
+
# @return [Array] New list of attachments
|
|
147
|
+
def add_attachment!(item, opts)
|
|
148
|
+
add_attachment(item, opts)
|
|
149
|
+
save!
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Get attachments as objects
|
|
153
|
+
#
|
|
154
|
+
# @return [Array<GoodData::DashboardAttachment | GoodData::ReportAttachment>] Array of attachments
|
|
155
|
+
def attachments
|
|
156
|
+
content['attachments'].map do |attachment|
|
|
157
|
+
key = attachment.keys.first
|
|
158
|
+
|
|
159
|
+
if key == 'dashboardAttachment'
|
|
160
|
+
GoodData::DashboardAttachment.new(self, attachment)
|
|
161
|
+
elsif key == 'reportAttachment'
|
|
162
|
+
GoodData::ReportAttachment.new(self, attachment)
|
|
163
|
+
else
|
|
164
|
+
RuntimeError "Unsupported attachment type: #{key}"
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Get body
|
|
170
|
+
#
|
|
171
|
+
# @return [String] Scheduled email body
|
|
172
|
+
def body
|
|
173
|
+
content['body']
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Set body
|
|
177
|
+
#
|
|
178
|
+
# @param [String] new_body New body to be set
|
|
179
|
+
# @return [String] New body
|
|
180
|
+
def body=(new_body)
|
|
181
|
+
content['body'] = new_body
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Get recurrency string
|
|
185
|
+
#
|
|
186
|
+
# @return [String] Recurrency (cron) string
|
|
187
|
+
def recurrency
|
|
188
|
+
content['when']['recurrency']
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Set recurrency
|
|
192
|
+
#
|
|
193
|
+
# @param [String] new_recurrency New recurrency to be set
|
|
194
|
+
# @return [Hash] New recurrency
|
|
195
|
+
def recurrency=(new_recurrency)
|
|
196
|
+
content['when']['recurrency'] = new_recurrency
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Get start date
|
|
200
|
+
#
|
|
201
|
+
# @return [String] Start date
|
|
202
|
+
def start_date
|
|
203
|
+
content['when']['startDate']
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Set start date
|
|
207
|
+
#
|
|
208
|
+
# @param [String] new_start_date New start date to be set
|
|
209
|
+
# @return [String] New start date
|
|
210
|
+
def start_date=(new_start_date)
|
|
211
|
+
content['when']['startDate'] = new_start_date
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Get subject
|
|
215
|
+
#
|
|
216
|
+
# @return [String] Subject of scheduled email
|
|
217
|
+
def subject
|
|
218
|
+
content['subject']
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Set subject
|
|
222
|
+
#
|
|
223
|
+
# @param [String] new_subject New subject to be set
|
|
224
|
+
# @return [String] New subject
|
|
225
|
+
def subject=(new_subject)
|
|
226
|
+
content['subject'] = new_subject
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Get timezone
|
|
230
|
+
#
|
|
231
|
+
# @return [String] Timezone
|
|
232
|
+
def timezone
|
|
233
|
+
content['when']['timeZone']
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Set timezone
|
|
237
|
+
#
|
|
238
|
+
# @param [String] new_timezone New timezone string to be set
|
|
239
|
+
# @return [String] New timezone
|
|
240
|
+
def timezone=(new_timezone)
|
|
241
|
+
content['when']['timeZone'] = new_timezone
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Get recipients
|
|
245
|
+
#
|
|
246
|
+
# @return [String] Recipients of email
|
|
247
|
+
def to
|
|
248
|
+
content['to']
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Set recipients
|
|
252
|
+
#
|
|
253
|
+
# @param [String|Array<String>] new_to New recipients to be set
|
|
254
|
+
# @return [Array<String>] New recipient list
|
|
255
|
+
def to=(new_to)
|
|
256
|
+
content['to'] = new_to.is_a?(Array) ? new_to : [new_to]
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Get 'when' section
|
|
260
|
+
#
|
|
261
|
+
# @return [Hash] 'when' section from json
|
|
262
|
+
def when
|
|
263
|
+
content['when']
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Set 'when' section
|
|
267
|
+
#
|
|
268
|
+
# @param [Hash] new_when New 'when' section to be set
|
|
269
|
+
# @return [Hash] New 'when' section
|
|
270
|
+
def when=(new_when)
|
|
271
|
+
content['when'] = new_when
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|