forest_admin_datasource_toolkit 1.0.0.pre.beta.21 → 1.0.0.pre.beta.23
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/lib/forest_admin_datasource_toolkit/collection.rb +6 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/chart.rb +11 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/leaderboard_chart.rb +24 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/line_chart.rb +24 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/objective_chart.rb +22 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/percentage_chart.rb +18 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/pie_chart.rb +24 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/smart_chart.rb +18 -0
- data/lib/forest_admin_datasource_toolkit/components/charts/value_chart.rb +19 -0
- data/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb +168 -0
- data/lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_equivalent.rb +11 -11
- data/lib/forest_admin_datasource_toolkit/exceptions/forest_exception.rb +1 -1
- data/lib/forest_admin_datasource_toolkit/utils/collection.rb +17 -0
- data/lib/forest_admin_datasource_toolkit/validations/chart_validator.rb +15 -0
- data/lib/forest_admin_datasource_toolkit/version.rb +1 -1
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 786b58c3bc21c7187d7a95025aae6229de6c04bac42549cede55f060be797d86
|
4
|
+
data.tar.gz: 477ffdc3ed1eba5e5240e641741f9f7cbd311373e35594438ccc452584a75830
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46282da2e6d7221c853d234d382a3712a4fcb0e0340c06f93ba97f2a9ca26967a0adc0e153e6b904dfe39c4aaadcb31ffe0a3731ae6a097e3520120dbdaa0e16
|
7
|
+
data.tar.gz: 52c33562da9679ea958fec285158dc6c12f5fb7ff9a3076f2724951bae500e99debb10925a562add7daeab4d749102494b46c6a33eaaaee22e54c5fb4c861984
|
@@ -46,5 +46,11 @@ module ForestAdminDatasourceToolkit
|
|
46
46
|
add_field(name, field)
|
47
47
|
end
|
48
48
|
end
|
49
|
+
|
50
|
+
def add_action(name, action)
|
51
|
+
raise Exceptions::ForestException, "Action #{name} already defined in collection" if @actions[key]
|
52
|
+
|
53
|
+
@actions[name] = action
|
54
|
+
end
|
49
55
|
end
|
50
56
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ForestAdminDatasourceToolkit
|
2
|
+
module Components
|
3
|
+
module Charts
|
4
|
+
class LeaderboardChart
|
5
|
+
include ForestAdminDatasourceToolkit::Validations
|
6
|
+
|
7
|
+
attr_reader :data
|
8
|
+
|
9
|
+
def initialize(data)
|
10
|
+
super()
|
11
|
+
@data = data
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize
|
15
|
+
data.each do |item|
|
16
|
+
ChartValidator.validate?(!item.key?(:key) || !item.key?(:value), item, "'key', 'value'")
|
17
|
+
end
|
18
|
+
|
19
|
+
data
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ForestAdminDatasourceToolkit
|
2
|
+
module Components
|
3
|
+
module Charts
|
4
|
+
class LineChart
|
5
|
+
include ForestAdminDatasourceToolkit::Validations
|
6
|
+
|
7
|
+
attr_reader :data
|
8
|
+
|
9
|
+
def initialize(data)
|
10
|
+
super()
|
11
|
+
@data = data
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize
|
15
|
+
data.each do |item|
|
16
|
+
ChartValidator.validate?(!item.key?(:label) || !item.key?(:values), item, "'label', 'values'")
|
17
|
+
end
|
18
|
+
|
19
|
+
data
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ForestAdminDatasourceToolkit
|
2
|
+
module Components
|
3
|
+
module Charts
|
4
|
+
class ObjectiveChart
|
5
|
+
attr_reader :value, :objective
|
6
|
+
|
7
|
+
def initialize(value, objective = nil)
|
8
|
+
super()
|
9
|
+
@value = value
|
10
|
+
@objective = objective
|
11
|
+
end
|
12
|
+
|
13
|
+
def serialize
|
14
|
+
result = { value: value }
|
15
|
+
result[:objective] = objective if objective
|
16
|
+
|
17
|
+
result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ForestAdminDatasourceToolkit
|
2
|
+
module Components
|
3
|
+
module Charts
|
4
|
+
class PieChart
|
5
|
+
include ForestAdminDatasourceToolkit::Validations
|
6
|
+
|
7
|
+
attr_reader :data
|
8
|
+
|
9
|
+
def initialize(data)
|
10
|
+
super()
|
11
|
+
@data = data
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize
|
15
|
+
data.each do |item|
|
16
|
+
ChartValidator.validate?(!item.key?(:key) || !item.key?(:value), item, "'key', 'value'")
|
17
|
+
end
|
18
|
+
|
19
|
+
data
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ForestAdminDatasourceToolkit
|
2
|
+
module Components
|
3
|
+
module Charts
|
4
|
+
class ValueChart
|
5
|
+
attr_reader :value, :previous_value
|
6
|
+
|
7
|
+
def initialize(value, previous_value = nil)
|
8
|
+
super()
|
9
|
+
@value = value
|
10
|
+
@previous_value = previous_value
|
11
|
+
end
|
12
|
+
|
13
|
+
def serialize
|
14
|
+
{ countCurrent: value, countPrevious: previous_value }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require 'active_support/core_ext/numeric/time'
|
3
|
+
|
1
4
|
module ForestAdminDatasourceToolkit
|
2
5
|
module Components
|
3
6
|
module Query
|
@@ -17,6 +20,171 @@ module ForestAdminDatasourceToolkit
|
|
17
20
|
|
18
21
|
raise ForestException, "Aggregate operation #{operation} not allowed"
|
19
22
|
end
|
23
|
+
|
24
|
+
def projection
|
25
|
+
aggregate_fields = []
|
26
|
+
aggregate_fields << field if field
|
27
|
+
|
28
|
+
groups.each do |group|
|
29
|
+
aggregate_fields << group[:field]
|
30
|
+
end
|
31
|
+
|
32
|
+
Projection.new(aggregate_fields)
|
33
|
+
end
|
34
|
+
|
35
|
+
def replace_fields(handler)
|
36
|
+
result = clone
|
37
|
+
result.field = handler.call(result.field) if result.field
|
38
|
+
result.groups = result.groups.map do |group|
|
39
|
+
{
|
40
|
+
field: handler.call(group[:field]),
|
41
|
+
operation: group[:operation] || nil
|
42
|
+
}
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def override(**args)
|
48
|
+
Aggregation.new(**to_h.merge(args))
|
49
|
+
end
|
50
|
+
|
51
|
+
def apply(records, timezone, limit = nil)
|
52
|
+
rows = format_summaries(create_summaries(records, timezone))
|
53
|
+
rows.sort do |r1, r2|
|
54
|
+
if r1[:value] == r2[:value]
|
55
|
+
0
|
56
|
+
else
|
57
|
+
r1[:value] < r2[:value] ? 1 : -1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
rows = rows[0..limit - 1] if limit && rows.size > limit
|
62
|
+
|
63
|
+
rows
|
64
|
+
end
|
65
|
+
|
66
|
+
def nest(prefix = nil)
|
67
|
+
return self unless prefix
|
68
|
+
|
69
|
+
nested_field = nil
|
70
|
+
nested_groups = []
|
71
|
+
nested_field = "#{prefix}:#{field}" if field
|
72
|
+
|
73
|
+
if groups.size.positive?
|
74
|
+
nested_groups = groups.map do |item|
|
75
|
+
{
|
76
|
+
field: "#{prefix}:#{item[:field]}",
|
77
|
+
operation: item[:operation]
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
self.class.new(operation: operation, field: nested_field, groups: nested_groups)
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_h
|
86
|
+
{
|
87
|
+
operation: operation,
|
88
|
+
field: field,
|
89
|
+
groups: groups
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def create_summaries(records, timezone)
|
96
|
+
grouping_map = {}
|
97
|
+
|
98
|
+
records.each do |record|
|
99
|
+
group = create_group(record, timezone)
|
100
|
+
unique_key = Digest::SHA1.hexdigest(group.to_json)
|
101
|
+
summary = grouping_map[unique_key] || create_summary(group)
|
102
|
+
|
103
|
+
update_summary_in_place(summary, record)
|
104
|
+
|
105
|
+
grouping_map[unique_key] = summary
|
106
|
+
end
|
107
|
+
|
108
|
+
grouping_map.values
|
109
|
+
end
|
110
|
+
|
111
|
+
def format_summaries(summaries)
|
112
|
+
if operation == 'Avg'
|
113
|
+
summaries
|
114
|
+
.select { |summary| (summary['Count']).positive? }
|
115
|
+
.map do |summary|
|
116
|
+
{
|
117
|
+
group: summary['group'],
|
118
|
+
value: summary['Sum'] / summary['Count']
|
119
|
+
}
|
120
|
+
end
|
121
|
+
else
|
122
|
+
summaries.map do |summary|
|
123
|
+
{
|
124
|
+
group: summary['group'],
|
125
|
+
value: operation == 'Count' && !field ? summary['starCount'] : summary[operation]
|
126
|
+
}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def create_group(record, timezone)
|
132
|
+
group = {}
|
133
|
+
|
134
|
+
groups.each do |value|
|
135
|
+
group_value = record[value[:field]]
|
136
|
+
group[value[:field]] = apply_date_operation(group_value, value[:operation], timezone)
|
137
|
+
end
|
138
|
+
|
139
|
+
group
|
140
|
+
end
|
141
|
+
|
142
|
+
def apply_date_operation(value, operation, timezone)
|
143
|
+
return value unless operation
|
144
|
+
|
145
|
+
case operation
|
146
|
+
when 'Year'
|
147
|
+
DateTime.parse(value).in_time_zone(timezone).strftime('%Y-01-01')
|
148
|
+
when 'Month'
|
149
|
+
DateTime.parse(value).in_time_zone(timezone).strftime('%Y-%m-01')
|
150
|
+
when 'Day'
|
151
|
+
DateTime.parse(value).in_time_zone(timezone).strftime('%Y-%m-%d')
|
152
|
+
when 'Week'
|
153
|
+
DateTime.parse(value).in_time_zone(timezone).beginning_of_month.strftime('%Y-%m-%d')
|
154
|
+
else
|
155
|
+
value
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def create_summary(group)
|
160
|
+
{
|
161
|
+
'group' => group,
|
162
|
+
'starCount' => 0,
|
163
|
+
'Count' => 0,
|
164
|
+
'Sum' => 0,
|
165
|
+
'Min' => nil,
|
166
|
+
'Max' => nil
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
def update_summary_in_place(summary, record)
|
171
|
+
summary['starCount'] += 1
|
172
|
+
|
173
|
+
return unless field
|
174
|
+
|
175
|
+
value = ForestAdminDatasourceToolkit::Utils::Record.field_value(record, field)
|
176
|
+
|
177
|
+
if value
|
178
|
+
min = summary['Min']
|
179
|
+
max = summary['Max']
|
180
|
+
|
181
|
+
summary['Count'] += 1
|
182
|
+
summary['Min'] = value if min.nil? || value < min
|
183
|
+
summary['Max'] = value if max.nil? || value < max
|
184
|
+
end
|
185
|
+
|
186
|
+
summary['Sum'] += value if value.is_a?(Numeric)
|
187
|
+
end
|
20
188
|
end
|
21
189
|
end
|
22
190
|
end
|
@@ -41,18 +41,18 @@ module ForestAdminDatasourceToolkit
|
|
41
41
|
depends_on = alt[:depends_on]
|
42
42
|
valid = alt[:for_types].nil? || alt[:for_types].include?(column_type)
|
43
43
|
|
44
|
-
|
45
|
-
depends_replacers = depends_on.map do |replacement|
|
46
|
-
get_replacer(replacement, filter_operators, column_type, visited + [alt])
|
47
|
-
end
|
44
|
+
next unless valid && !visited.include?(alt)
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
46
|
+
depends_replacers = depends_on.map do |replacement|
|
47
|
+
get_replacer(replacement, filter_operators, column_type, visited + [alt])
|
48
|
+
end
|
49
|
+
|
50
|
+
if depends_replacers.all? { |r| !r.nil? }
|
51
|
+
return lambda { |leaf, timezone|
|
52
|
+
replacer.call(leaf).replace_leafs do |sub_leaf|
|
53
|
+
depends_replacers[depends_on.index(sub_leaf.operator)].call(sub_leaf, timezone)
|
54
|
+
end
|
55
|
+
}
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -106,6 +106,23 @@ module ForestAdminDatasourceToolkit
|
|
106
106
|
nil
|
107
107
|
end
|
108
108
|
|
109
|
+
def self.get_through_origin(collection, relation_name)
|
110
|
+
relation = collection.fields[relation_name]
|
111
|
+
raise ForestException, 'Relation must be many to many' unless relation.is_a?(ManyToManySchema)
|
112
|
+
|
113
|
+
through_collection = collection.datasource.collection(relation.through_collection)
|
114
|
+
through_collection.fields.select do |field_name, field|
|
115
|
+
if field.is_a?(ManyToOneSchema) &&
|
116
|
+
field.foreign_collection == collection.name &&
|
117
|
+
field.foreign_key == relation.origin_key &&
|
118
|
+
field.foreign_key_target == relation.origin_key_target
|
119
|
+
return field_name
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
|
109
126
|
def self.list_relation(collection, id, relation_name, caller, foreign_filter, projection)
|
110
127
|
relation = collection.fields[relation_name]
|
111
128
|
foreign_collection = collection.datasource.collection(relation.foreign_collection)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ForestAdminDatasourceToolkit
|
2
|
+
module Validations
|
3
|
+
class ChartValidator
|
4
|
+
def self.validate?(condition, result, key_names)
|
5
|
+
if condition
|
6
|
+
result_keys = result.keys.join(',')
|
7
|
+
raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
|
8
|
+
"The result columns must be named '#{key_names}' instead of '#{result_keys}'"
|
9
|
+
end
|
10
|
+
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forest_admin_datasource_toolkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.beta.
|
4
|
+
version: 1.0.0.pre.beta.23
|
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
|
+
date: 2023-12-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -56,6 +56,14 @@ files:
|
|
56
56
|
- lib/forest_admin_datasource_toolkit.rb
|
57
57
|
- lib/forest_admin_datasource_toolkit/collection.rb
|
58
58
|
- lib/forest_admin_datasource_toolkit/components/caller.rb
|
59
|
+
- lib/forest_admin_datasource_toolkit/components/charts/chart.rb
|
60
|
+
- lib/forest_admin_datasource_toolkit/components/charts/leaderboard_chart.rb
|
61
|
+
- lib/forest_admin_datasource_toolkit/components/charts/line_chart.rb
|
62
|
+
- lib/forest_admin_datasource_toolkit/components/charts/objective_chart.rb
|
63
|
+
- lib/forest_admin_datasource_toolkit/components/charts/percentage_chart.rb
|
64
|
+
- lib/forest_admin_datasource_toolkit/components/charts/pie_chart.rb
|
65
|
+
- lib/forest_admin_datasource_toolkit/components/charts/smart_chart.rb
|
66
|
+
- lib/forest_admin_datasource_toolkit/components/charts/value_chart.rb
|
59
67
|
- lib/forest_admin_datasource_toolkit/components/contracts/collection_contract.rb
|
60
68
|
- lib/forest_admin_datasource_toolkit/components/contracts/datasource_contract.rb
|
61
69
|
- lib/forest_admin_datasource_toolkit/components/query/aggregation.rb
|
@@ -85,6 +93,7 @@ files:
|
|
85
93
|
- lib/forest_admin_datasource_toolkit/utils/collection.rb
|
86
94
|
- lib/forest_admin_datasource_toolkit/utils/record.rb
|
87
95
|
- lib/forest_admin_datasource_toolkit/utils/schema.rb
|
96
|
+
- lib/forest_admin_datasource_toolkit/validations/chart_validator.rb
|
88
97
|
- lib/forest_admin_datasource_toolkit/version.rb
|
89
98
|
- sig/forest_admin_datasource_toolkit.rbs
|
90
99
|
- sig/forest_admin_datasource_toolkit/collection.rbs
|