forest_admin_agent 1.0.0.pre.beta.22 → 1.0.0.pre.beta.24

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5714273d6e7144f00eb531b7a93d0e908698bd1dac7984dc47affd15a7514f6
4
- data.tar.gz: 3b47af0daae4bc4e02b944f0d21be13aa18fe5e7abb9bfcfa03f2ea3272028bd
3
+ metadata.gz: 5366fcae628c5d313080f3218e187b1b5754b884d7e8cc38c85b905b4268e35e
4
+ data.tar.gz: b4778e1a8f354b96b9ce0be00afae2d3688b0565d73026be0b3c0e89425a7aaf
5
5
  SHA512:
6
- metadata.gz: 93044527fdfb1a06f49408044479258b1cccb6af15c8025cf26310f01c684ae6b5c4657bd25496eb69d911eaa77daae83ec82ec551469bd15cacea61a3b46687
7
- data.tar.gz: f93863c6d28342854e2e453795bca3c3892c6a09c0d91a44fcb42fae57b107c17f6daa3e9694d04e0862bb46e1f95ff2d14f04c199ab0c2a5436434ca5090ca4
6
+ metadata.gz: 1e150b17814b1d3d7bdf2a25cb4b9cfa9b88a80e29593a4307b452b5096d733360f264e4034da11e835c0c1c24534ea1b84feb7c0e4658dfd0f689ff3b9494bc
7
+ data.tar.gz: e626ef0f2022abc05884b5a529d77269c72bc2c8aa45f3e2d6484021fdd590fe6fc0fce8fdba30869a3ca18c434aad4a2ce614222096ad7e4bf4589848b6c191
@@ -34,6 +34,7 @@ admin work on any Ruby application."
34
34
  spec.require_paths = ["lib"]
35
35
 
36
36
  spec.add_dependency "activesupport", ">= 6.1"
37
+ spec.add_dependency "deepsort", "~> 0.4.5"
37
38
  spec.add_dependency "dry-container", "~> 0.11"
38
39
  spec.add_dependency "faraday", "~> 2.7"
39
40
  spec.add_dependency "filecache", "~> 1.0"
@@ -14,26 +14,31 @@ module ForestAdminAgent
14
14
  def setup(options)
15
15
  @options = options
16
16
  @has_env_secret = options.to_h.key?(:env_secret)
17
- @customizer = ForestAdminDatasourceToolkit::Datasource.new
17
+ @customizer = ForestAdminDatasourceCustomizer::DatasourceCustomizer.new
18
18
  build_container
19
19
  build_cache
20
20
  build_logger
21
21
  end
22
22
 
23
- def add_datasource(datasource)
24
- datasource.collections.each_value { |collection| @customizer.add_collection(collection) }
23
+ def add_datasource(datasource, options = {})
24
+ @customizer.add_datasource(datasource, options)
25
+
25
26
  self
26
27
  end
27
28
 
29
+ def customize_collection(name, handle)
30
+ @customizer.customize_collection(name, handle)
31
+ end
32
+
28
33
  def build
29
- @container.register(:datasource, @customizer)
34
+ @container.register(:datasource, @customizer.datasource)
30
35
  send_schema
31
36
  end
32
37
 
33
38
  def send_schema(force: false)
34
39
  return unless @has_env_secret
35
40
 
36
- schema = ForestAdminAgent::Utils::Schema::SchemaEmitter.get_serialized_schema(@customizer)
41
+ schema = ForestAdminAgent::Utils::Schema::SchemaEmitter.get_serialized_schema(@customizer.datasource)
37
42
  schema_is_know = @container.key?(:schema_file_hash) &&
38
43
  @container.resolve(:schema_file_hash).get('value') == schema[:meta][:schemaFileHash]
39
44
 
@@ -63,9 +68,7 @@ module ForestAdminAgent
63
68
  return unless @has_env_secret
64
69
 
65
70
  cache = @container.resolve(:cache)
66
- cache.get_or_set 'config' do
67
- @options.to_h
68
- end
71
+ cache.set('config', @options.to_h)
69
72
  end
70
73
 
71
74
  def build_logger
@@ -9,6 +9,7 @@ module ForestAdminAgent
9
9
  # api_charts_routes,
10
10
  System::HealthCheck.new.routes,
11
11
  Security::Authentication.new.routes,
12
+ Charts::Charts.new.routes,
12
13
  Resources::Count.new.routes,
13
14
  Resources::Delete.new.routes,
14
15
  Resources::List.new.routes,
@@ -14,7 +14,7 @@ module ForestAdminAgent
14
14
  record = args[:params][:data][:attributes]
15
15
 
16
16
  args[:params][:data][:relationships]&.map do |field, value|
17
- schema = @collection.fields[field]
17
+ schema = @collection.schema[:fields][field]
18
18
 
19
19
  record[schema.foreign_key] = value['data'][schema.foreign_key_target] if schema.type == 'ManyToOne'
20
20
  end
@@ -4,8 +4,8 @@ module ForestAdminAgent
4
4
  def build(args = {})
5
5
  super
6
6
 
7
- relation = @collection.fields[args[:params]['relation_name']]
8
- @child_collection = @datasource.collection(relation.foreign_collection)
7
+ relation = @collection.schema[:fields][args[:params]['relation_name']]
8
+ @child_collection = @datasource.get_collection(relation.foreign_collection)
9
9
  end
10
10
  end
11
11
  end
@@ -8,7 +8,7 @@ module ForestAdminAgent
8
8
 
9
9
  def build(args)
10
10
  @datasource = ForestAdminAgent::Facades::Container.datasource
11
- @collection = @datasource.collection(args[:params]['collection_name'])
11
+ @collection = @datasource.get_collection(args[:params]['collection_name'])
12
12
  end
13
13
 
14
14
  def routes
@@ -0,0 +1,214 @@
1
+ require 'jsonapi-serializers'
2
+ require 'active_support/inflector'
3
+
4
+ module ForestAdminAgent
5
+ module Routes
6
+ module Charts
7
+ class Charts < AbstractAuthenticatedRoute
8
+ include ForestAdminAgent::Builder
9
+ include ForestAdminAgent::Utils
10
+ include ForestAdminDatasourceToolkit::Components::Query
11
+ include ForestAdminDatasourceToolkit::Components::Query::ConditionTree
12
+ include ForestAdminDatasourceToolkit::Components::Charts
13
+
14
+ attr_reader :filter
15
+
16
+ FORMAT = {
17
+ Day: '%d/%m/%Y',
18
+ Week: 'W%W-%Y',
19
+ Month: '%b %y',
20
+ Year: '%Y'
21
+ }.freeze
22
+
23
+ def setup_routes
24
+ add_route('forest_chart', 'post', '/stats/:collection_name', lambda { |args|
25
+ handle_request(args)
26
+ })
27
+ self
28
+ end
29
+
30
+ def handle_request(args = {})
31
+ build(args)
32
+ @permissions.can_chart?(args[:params])
33
+ @args = args
34
+ self.type = args[:params][:type]
35
+ @filter = Filter.new(
36
+ condition_tree: ConditionTreeFactory.intersect(
37
+ [
38
+ @permissions.get_scope(@collection),
39
+ ForestAdminAgent::Utils::QueryStringParser.parse_condition_tree(
40
+ @collection, args
41
+ )
42
+ ]
43
+ )
44
+ )
45
+
46
+ inject_context_variables
47
+
48
+ { content: Serializer::ForestChartSerializer.serialize(send(:"make_#{@type}")) }
49
+ end
50
+
51
+ private
52
+
53
+ def type=(type)
54
+ chart_types = %w[Value Objective Pie Line Leaderboard]
55
+ unless chart_types.include?(type)
56
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException, "Invalid Chart type #{type}"
57
+ end
58
+
59
+ @type = type.downcase
60
+ end
61
+
62
+ def inject_context_variables
63
+ user = @permissions.get_user_data(@caller.id)
64
+ team = @permissions.get_team(@caller.rendering_id)
65
+
66
+ context_variables = ForestAdminAgent::Utils::ContextVariables.new(team, user,
67
+ @args[:params][:contextVariables])
68
+ return unless @args[:params][:filter]
69
+
70
+ @filter = @filter.override(condition_tree: ContextVariablesInjector.inject_context_in_filter(
71
+ @filter.condition_tree, context_variables
72
+ ))
73
+ end
74
+
75
+ def make_value
76
+ value = compute_value(@filter)
77
+ previous_value = nil
78
+ is_and_aggregator = @filter.condition_tree&.try(:aggregator) == 'And'
79
+ with_count_previous = @filter.condition_tree&.some_leaf(&:use_interval_operator)
80
+
81
+ if with_count_previous && !is_and_aggregator
82
+ previous_value = compute_value(FilterFactory.get_previous_period_filter(@filter, @caller.timezone))
83
+ end
84
+
85
+ ValueChart.new(value, previous_value)
86
+ end
87
+
88
+ def make_objective
89
+ ObjectiveChart.new(compute_value(@filter))
90
+ end
91
+
92
+ def make_pie
93
+ group_field = @args[:params][:groupByFieldName]
94
+ aggregation = Aggregation.new(
95
+ operation: @args[:params][:aggregator],
96
+ field: @args[:params][:aggregateFieldName],
97
+ groups: group_field ? [{ field: group_field }] : []
98
+ )
99
+
100
+ result = @collection.aggregate(@caller, @filter, aggregation)
101
+
102
+ PieChart.new(result.map { |row| { key: row[:group][group_field], value: row[:value] } })
103
+ end
104
+
105
+ def make_line
106
+ group_by_field_name = @args[:params][:groupByFieldName]
107
+ time_range = @args[:params][:timeRange]
108
+ filter_only_with_values = @filter.override(
109
+ condition_tree: ConditionTree::ConditionTreeFactory.intersect(
110
+ [
111
+ @filter.condition_tree,
112
+ ConditionTree::Nodes::ConditionTreeLeaf.new(group_by_field_name, ConditionTree::Operators::PRESENT)
113
+ ]
114
+ )
115
+ )
116
+ rows = @collection.aggregate(
117
+ @caller,
118
+ filter_only_with_values,
119
+ Aggregation.new(
120
+ operation: @args[:params][:aggregator],
121
+ field: @args[:params][:aggregateField],
122
+ groups: [{ field: group_by_field_name, operation: time_range }]
123
+ )
124
+ )
125
+
126
+ values = {}
127
+ rows.each { |row| values[row[:group][group_by_field_name]] = row[:value] }
128
+ dates = values.keys.sort
129
+ current = dates[0]
130
+ last = dates.last
131
+ result = []
132
+ while current <= last
133
+ result << {
134
+ label: current.strftime(FORMAT[time_range.to_sym]),
135
+ values: { value: values[current] || 0 }
136
+ }
137
+ current += 1.send(time_range.downcase.pluralize.to_sym)
138
+ end
139
+
140
+ LineChart.new(result)
141
+ end
142
+
143
+ def make_leaderboard
144
+ field = @collection.schema[:fields][@args[:params][:relationshipFieldName]]
145
+
146
+ if field && field.type == 'OneToMany'
147
+ inverse = ForestAdminDatasourceToolkit::Utils::Collection.get_inverse_relation(
148
+ @collection,
149
+ @args[:params][:relationshipFieldName]
150
+ )
151
+ if inverse
152
+ collection = field.foreign_collection
153
+ filter = @filter.nest(inverse)
154
+ aggregation = Aggregation.new(
155
+ operation: @args[:params][:aggregator],
156
+ field: @args[:params][:aggregateFieldName],
157
+ groups: [{ field: "#{inverse}:#{@args[:params][:labelFieldName]}" }]
158
+ )
159
+ end
160
+ end
161
+
162
+ if field && field.type == 'ManyToMany'
163
+ origin = ForestAdminDatasourceToolkit::Utils::Collection.get_through_origin(
164
+ @collection,
165
+ @args[:params][:relationshipFieldName]
166
+ )
167
+ target = ForestAdminDatasourceToolkit::Utils::Collection.get_through_target(
168
+ @collection,
169
+ @args[:params][:relationshipFieldName]
170
+ )
171
+ if origin && target
172
+ collection = field.through_collection
173
+ filter = @filter.nest(origin)
174
+ aggregation = Aggregation.new(
175
+ operation: @args[:params][:aggregator],
176
+ field: @args[:params][:aggregateFieldName] ? "#{target}:#{@args[:params][:aggregateFieldName]}" : nil,
177
+ groups: [{ field: "#{origin}:#{@args[:params][:labelFieldName]}" }]
178
+ )
179
+ end
180
+ end
181
+
182
+ if collection && filter && aggregation
183
+ rows = @datasource.get_collection(collection).aggregate(
184
+ @caller,
185
+ filter,
186
+ aggregation,
187
+ @args[:params][:limit]
188
+ )
189
+
190
+ result = rows.map do |row|
191
+ {
192
+ key: row[:group][aggregation.groups[0][:field]],
193
+ value: row[:value]
194
+ }
195
+ end
196
+
197
+ return LeaderboardChart.new(result)
198
+ end
199
+
200
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
201
+ 'Failed to generate leaderboard chart: parameters do not match pre-requisites'
202
+ end
203
+
204
+ def compute_value(filter)
205
+ aggregation = Aggregation.new(operation: @args[:params][:aggregator],
206
+ field: @args[:params][:aggregateFieldName])
207
+ result = @collection.aggregate(@caller, filter, aggregation)
208
+
209
+ result[0][:value] || 0
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
@@ -26,7 +26,7 @@ module ForestAdminAgent
26
26
  return {
27
27
  name: args[:params]['collection_name'],
28
28
  content: {
29
- count: result[0][:value]
29
+ count: result.empty? ? 0 : result[0][:value]
30
30
  }
31
31
  }
32
32
  end
@@ -62,7 +62,7 @@ module ForestAdminAgent
62
62
  origin_value = Collection.get_value(@collection, @caller, parent_id, id)
63
63
  record = { relation.origin_key => origin_value, relation.foreign_key => foreign_value }
64
64
 
65
- through_collection = @datasource.collection(relation.through_collection)
65
+ through_collection = @datasource.get_collection(relation.through_collection)
66
66
  through_collection.create(@caller, record)
67
67
  end
68
68
  end
@@ -52,7 +52,7 @@ module ForestAdminAgent
52
52
  end
53
53
 
54
54
  def dissociate_or_delete_many_to_many(relation, relation_name, parent_id, is_delete_mode, filter)
55
- through_collection = @datasource.collection(relation.through_collection)
55
+ through_collection = @datasource.get_collection(relation.through_collection)
56
56
 
57
57
  if is_delete_mode
58
58
  # Generate filters _BEFORE_ deleting stuff, otherwise things break.
@@ -23,7 +23,7 @@ module ForestAdminAgent
23
23
  build(args)
24
24
  @permissions.can?(:edit, @collection)
25
25
 
26
- relation = @collection.fields[args[:params]['relation_name']]
26
+ relation = @collection.schema[:fields][args[:params]['relation_name']]
27
27
  parent_id = Utils::Id.unpack_id(@collection, args[:params]['id'])
28
28
 
29
29
  linked_id = if (id = args.dig(:params, :data, :id))
@@ -32,18 +32,18 @@ module ForestAdminAgent
32
32
 
33
33
  def link_one_to_one_relations(args, record)
34
34
  args[:params][:data][:relationships]&.map do |field, value|
35
- schema = @collection.fields[field]
36
- if schema.type == 'OneToOne'
37
- id = Utils::Id.unpack_id(@collection, value['data']['id'], with_key: true)
38
- foreign_collection = @datasource.collection(schema.foreign_collection)
39
- # Load the value that will be used as origin_key
40
- origin_value = record[schema.origin_key_target]
35
+ schema = @collection.schema[:fields][field]
36
+ next unless schema.type == 'OneToOne'
41
37
 
42
- # update new relation (may update zero or one records).
43
- condition_tree = ConditionTree::ConditionTreeFactory.match_records(foreign_collection, [id])
44
- filter = Filter.new(condition_tree: condition_tree)
45
- foreign_collection.update(@caller, filter, { schema.origin_key => origin_value })
46
- end
38
+ id = Utils::Id.unpack_id(@collection, value['data']['id'], with_key: true)
39
+ foreign_collection = @datasource.get_collection(schema.foreign_collection)
40
+ # Load the value that will be used as origin_key
41
+ origin_value = record[schema.origin_key_target]
42
+
43
+ # update new relation (may update zero or one records).
44
+ condition_tree = ConditionTree::ConditionTreeFactory.match_records(foreign_collection, [id])
45
+ filter = Filter.new(condition_tree: condition_tree)
46
+ foreign_collection.update(@caller, filter, { schema.origin_key => origin_value })
47
47
  end
48
48
  end
49
49
  end
@@ -0,0 +1,19 @@
1
+ require 'securerandom'
2
+
3
+ module ForestAdminAgent
4
+ module Serializer
5
+ class ForestChartSerializer
6
+ def self.serialize(chart)
7
+ {
8
+ data: {
9
+ id: SecureRandom.uuid,
10
+ type: 'stats',
11
+ attributes: {
12
+ value: chart.serialize
13
+ }
14
+ }
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -41,8 +41,8 @@ module ForestAdminAgent
41
41
  end
42
42
 
43
43
  def attributes
44
- forest_collection = ForestAdminAgent::Facades::Container.datasource.collection(object.class.name.demodulize.underscore)
45
- fields = forest_collection.fields.select { |_field_name, field| field.type == 'Column' }
44
+ forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(object.class.name.demodulize.underscore)
45
+ fields = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'Column' }
46
46
  fields.each { |field_name, _field| add_attribute(field_name) }
47
47
  return {} if attributes_map.nil?
48
48
  attributes = {}
@@ -104,9 +104,9 @@ module ForestAdminAgent
104
104
  end
105
105
 
106
106
  def relationships
107
- forest_collection = ForestAdminAgent::Facades::Container.datasource.collection(object.class.name.demodulize.underscore)
108
- relations_to_many = forest_collection.fields.select { |_field_name, field| field.type == 'OneToMany' || field.type == 'ManyToMany' }
109
- relations_to_one = forest_collection.fields.select { |_field_name, field| field.type == 'OneToOne' || field.type == 'ManyToOne' }
107
+ forest_collection = ForestAdminAgent::Facades::Container.datasource.get_collection(object.class.name.demodulize.underscore)
108
+ relations_to_many = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'OneToMany' || field.type == 'ManyToMany' }
109
+ relations_to_one = forest_collection.schema[:fields].select { |_field_name, field| field.type == 'OneToOne' || field.type == 'ManyToOne' }
110
110
 
111
111
  relations_to_one.each { |field_name, _field| add_to_one_association(field_name) }
112
112
 
@@ -1,4 +1,5 @@
1
1
  require 'filecache'
2
+ require 'deepsort'
2
3
 
3
4
  module ForestAdminAgent
4
5
  module Services
@@ -56,7 +57,7 @@ module ForestAdminAgent
56
57
  end
57
58
 
58
59
  def can_chart?(parameters)
59
- attributes = sanitize_chart_parameters(parameters)
60
+ attributes = sanitize_chart_parameters(parameters.deep_symbolize_keys)
60
61
  hash_request = "#{attributes[:type]}:#{array_hash(attributes)}"
61
62
  is_allowed = get_chart_data(caller.rendering_id).include?(hash_request)
62
63
 
@@ -99,8 +100,6 @@ module ForestAdminAgent
99
100
  def get_scope(collection)
100
101
  permissions = get_scope_and_team_data(caller.rendering_id)
101
102
  scope = permissions[:scopes][collection.name.to_sym]
102
- team = permissions[:team]
103
- user = get_user_data(caller.id)
104
103
 
105
104
  return nil if scope.nil?
106
105
 
@@ -170,16 +169,21 @@ module ForestAdminAgent
170
169
  end
171
170
 
172
171
  def sanitize_chart_parameters(parameters)
173
- # parameters = parameters.to_h
174
172
  parameters.delete(:timezone)
175
173
  parameters.delete(:collection)
176
174
  parameters.delete(:contextVariables)
175
+ # rails
176
+ parameters.delete(:route_alias)
177
+ parameters.delete(:controller)
178
+ parameters.delete(:action)
179
+ parameters.delete(:collection_name)
180
+ parameters.delete(:forest)
177
181
 
178
182
  parameters.select { |_, value| !value.nil? && value != '' }
179
183
  end
180
184
 
181
185
  def array_hash(data)
182
- Digest::SHA1.hexdigest(data.sort.to_h.to_s)
186
+ Digest::SHA1.hexdigest(data.deep_sort.to_h.to_s)
183
187
  end
184
188
 
185
189
  def get_scope_and_team_data(rendering_id)
@@ -197,7 +201,7 @@ module ForestAdminAgent
197
201
  def permission_system?
198
202
  cache.get_or_set('forest.has_permission') do
199
203
  response = fetch('/liana/v4/permissions/environment')
200
- { enable: !response.nil? }
204
+ { enable: response != true }
201
205
  end[:enable]
202
206
  end
203
207
 
@@ -11,7 +11,7 @@ module ForestAdminAgent
11
11
  end
12
12
 
13
13
  result = primary_keys.map.with_index do |pk_name, index|
14
- field = collection.fields[pk_name]
14
+ field = collection.schema[:fields][pk_name]
15
15
  value = primary_key_values[index]
16
16
  casted_value = field.column_type == 'Number' ? value.to_i : value
17
17
  # TODO: call FieldValidator::validateValue($value, $field, $castedValue);
@@ -1,4 +1,5 @@
1
1
  require 'jwt'
2
+ require 'active_support'
2
3
  require 'active_support/time'
3
4
 
4
5
  module ForestAdminAgent
@@ -56,7 +57,7 @@ module ForestAdminAgent
56
57
  return ProjectionFactory.all(collection) unless fields != '' && !fields.nil?
57
58
 
58
59
  fields = fields.split(',').map do |field_name|
59
- column = collection.fields[field_name.strip]
60
+ column = collection.schema[:fields][field_name.strip]
60
61
  column.type == 'Column' ? field_name.strip : "#{field_name.strip}:#{args[:params][:fields][field_name.strip]}"
61
62
  end
62
63
 
@@ -10,7 +10,7 @@ module ForestAdminAgent
10
10
  fields: build_fields(collection),
11
11
  icon: nil,
12
12
  integration: nil,
13
- isReadOnly: collection.fields.all? { |_k, field| field.type != 'Column' || field.is_read_only },
13
+ isReadOnly: collection.schema[:fields].all? { |_k, field| field.type != 'Column' || field.is_read_only },
14
14
  isSearchable: true,
15
15
  isVirtual: false,
16
16
  name: collection.name,
@@ -21,7 +21,7 @@ module ForestAdminAgent
21
21
  end
22
22
 
23
23
  def self.build_fields(collection)
24
- fields = collection.fields.select do |name, _field|
24
+ fields = collection.schema[:fields].select do |name, _field|
25
25
  !ForestAdminDatasourceToolkit::Utils::Schema.foreign_key?(collection, name) ||
26
26
  ForestAdminDatasourceToolkit::Utils::Schema.primary_key?(collection, name)
27
27
  end
@@ -10,7 +10,7 @@ module ForestAdminAgent
10
10
  }.freeze
11
11
 
12
12
  def self.build_schema(collection, name)
13
- type = collection.fields[name].type
13
+ type = collection.schema[:fields][name].type
14
14
 
15
15
  case type
16
16
  when 'Column'
@@ -26,7 +26,7 @@ module ForestAdminAgent
26
26
  private
27
27
 
28
28
  def build_column_schema(collection, name)
29
- column = collection.fields[name]
29
+ column = collection.schema[:fields][name]
30
30
  is_foreign_key = ForestAdminDatasourceToolkit::Utils::Schema.foreign_key?(collection, name)
31
31
 
32
32
  {
@@ -74,10 +74,10 @@ module ForestAdminAgent
74
74
 
75
75
  def build_many_to_many_schema(relation, collection, foreign_collection, base_schema)
76
76
  target_name = relation.foreign_key_target
77
- target_field = foreign_collection.fields[target_name]
78
- through_schema = collection.datasource.collection(relation.through_collection)
79
- foreign_schema = through_schema.fields[relation.foreign_key]
80
- origin_key = through_schema.fields[relation.origin_key]
77
+ target_field = foreign_collection.schema[:fields][target_name]
78
+ through_schema = collection.datasource.get_collection(relation.through_collection)
79
+ foreign_schema = through_schema.schema[:fields][relation.foreign_key]
80
+ origin_key = through_schema.schema[:fields][relation.origin_key]
81
81
 
82
82
  base_schema.merge(
83
83
  {
@@ -96,8 +96,8 @@ module ForestAdminAgent
96
96
 
97
97
  def build_one_to_many_schema(relation, collection, foreign_collection, base_schema)
98
98
  target_name = relation.origin_key_target
99
- target_field = collection.fields[target_name]
100
- origin_key = foreign_collection.fields[relation.origin_key]
99
+ target_field = collection.schema[:fields][target_name]
100
+ origin_key = foreign_collection.schema[:fields][relation.origin_key]
101
101
 
102
102
  base_schema.merge(
103
103
  {
@@ -115,8 +115,8 @@ module ForestAdminAgent
115
115
  end
116
116
 
117
117
  def build_one_to_one_schema(relation, collection, foreign_collection, base_schema)
118
- target_field = collection.fields[relation.origin_key_target]
119
- key_field = foreign_collection.fields[relation.origin_key]
118
+ target_field = collection.schema[:fields][relation.origin_key_target]
119
+ key_field = foreign_collection.schema[:fields][relation.origin_key]
120
120
 
121
121
  base_schema.merge(
122
122
  {
@@ -134,7 +134,7 @@ module ForestAdminAgent
134
134
  end
135
135
 
136
136
  def build_many_to_one_schema(relation, collection, foreign_collection, base_schema)
137
- key_field = collection.fields[relation.foreign_key]
137
+ key_field = collection.schema[:fields][relation.foreign_key]
138
138
 
139
139
  base_schema.merge(
140
140
  {
@@ -152,8 +152,8 @@ module ForestAdminAgent
152
152
  end
153
153
 
154
154
  def build_relation_schema(collection, name)
155
- relation = collection.fields[name]
156
- foreign_collection = collection.datasource.collection(relation.foreign_collection)
155
+ relation = collection.schema[:fields][name]
156
+ foreign_collection = collection.datasource.get_collection(relation.foreign_collection)
157
157
 
158
158
  relation_schema = {
159
159
  field: name,
@@ -7,7 +7,7 @@ module ForestAdminAgent
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "forest-rails"
9
9
 
10
- LIANA_VERSION = "1.0.0-beta.22"
10
+ LIANA_VERSION = "1.0.0-beta.24"
11
11
 
12
12
  def self.get_serialized_schema(datasource)
13
13
  schema_path = Facades::Container.cache(:schema_path)
@@ -1,3 +1,3 @@
1
1
  module ForestAdminAgent
2
- VERSION = "1.0.0-beta.22"
2
+ VERSION = "1.0.0-beta.24"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_admin_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.beta.22
4
+ version: 1.0.0.pre.beta.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-12-08 00:00:00.000000000 Z
12
+ date: 2023-12-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '6.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: deepsort
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.4.5
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.4.5
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: dry-container
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -204,7 +218,6 @@ extensions: []
204
218
  extra_rdoc_files: []
205
219
  files:
206
220
  - ".rspec"
207
- - CHANGELOG.md
208
221
  - README.md
209
222
  - Rakefile
210
223
  - forest_admin
@@ -229,6 +242,7 @@ files:
229
242
  - lib/forest_admin_agent/routes/abstract_authenticated_route.rb
230
243
  - lib/forest_admin_agent/routes/abstract_related_route.rb
231
244
  - lib/forest_admin_agent/routes/abstract_route.rb
245
+ - lib/forest_admin_agent/routes/charts/charts.rb
232
246
  - lib/forest_admin_agent/routes/resources/count.rb
233
247
  - lib/forest_admin_agent/routes/resources/delete.rb
234
248
  - lib/forest_admin_agent/routes/resources/list.rb
@@ -242,6 +256,7 @@ files:
242
256
  - lib/forest_admin_agent/routes/resources/update.rb
243
257
  - lib/forest_admin_agent/routes/security/authentication.rb
244
258
  - lib/forest_admin_agent/routes/system/health_check.rb
259
+ - lib/forest_admin_agent/serializer/forest_chart_serializer.rb
245
260
  - lib/forest_admin_agent/serializer/forest_serializer.rb
246
261
  - lib/forest_admin_agent/serializer/forest_serializer_override.rb
247
262
  - lib/forest_admin_agent/services/ip_whitelist.rb
data/CHANGELOG.md DELETED
@@ -1,5 +0,0 @@
1
- ## [Unreleased]
2
-
3
- ## [0.1.0] - 2023-08-28
4
-
5
- - Initial release