old_sql 1.13.0 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +36 -7
- data/app/controllers/old_sql/report_controller.rb +42 -0
- data/app/views/old_sql/report/chart.html.erb +26 -0
- data/app/views/old_sql/report/index.html.erb +4 -2
- data/config/routes.rb +1 -0
- data/lib/generators/old_sql/install_generator.rb +1 -0
- data/lib/generators/old_sql/templates/reports.yml.example +29 -5
- data/lib/generators/old_sql/templates/user_old_sql_demo_chart_design.yml +8 -0
- data/lib/old_sql/report_design/chart.rb +24 -0
- data/lib/old_sql/report_design/chart_data.rb +29 -0
- data/lib/old_sql/report_design/chart_item.rb +23 -0
- data/lib/old_sql/report_design/chart_parser.rb +32 -0
- data/lib/old_sql/report_processor/base.rb +41 -2
- data/public/javascripts/old_sql/old_sql.js +14 -0
- metadata +9 -3
data/README.rdoc
CHANGED
@@ -10,7 +10,7 @@ Some features of Old SQL are:
|
|
10
10
|
- The design documents, which are nothing more than csv files, can also serve as documentation, and describe the layout of the report in an intuitive way.
|
11
11
|
- If you want more fine grained control and report processor can parse the SQL.
|
12
12
|
- This also makes it simple to convert legacy reports into Old SQL reports.
|
13
|
-
* Multiple report views (jqGrid, HTML table) that can be configured using the old_sql initializer.
|
13
|
+
* Multiple report views (jqGrid, HTML table, and chart) that can be configured using the old_sql initializer.
|
14
14
|
* Old SQL uses Devise for authentication, and will install it for you. It can
|
15
15
|
even add Devise support to an existing model (by default users).
|
16
16
|
* In the report design all data is rounded to a precision that can be set in the old_sql initializer. This feature can also be disabled in the initializer.
|
@@ -67,14 +67,35 @@ Configure your reports config/old_sql/report.yml. An example configuration is cr
|
|
67
67
|
# 'report_design' is also optional, and should point to a file in config/old_sql/report_design.
|
68
68
|
# See config/old_sql/report_design/user_old_sql_demo.csv for an example.
|
69
69
|
#
|
70
|
+
# 'report_view' is optional. It overrides the default_report_view defined in the initializer. It
|
71
|
+
# can be set to jqgrid, table, or chart.
|
72
|
+
#
|
70
73
|
# The 'fields' are the headers for the report.
|
71
74
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
user_jqgrid:
|
76
|
+
description: User jqGrid
|
77
|
+
report_sql: user_old_sql_demo
|
78
|
+
report_design: user_old_sql_demo.csv
|
79
|
+
report_view: jqgrid
|
80
|
+
fields:
|
81
|
+
- 'id'
|
82
|
+
- 'name'
|
83
|
+
|
84
|
+
user_table:
|
85
|
+
description: User HTML Table
|
86
|
+
report_sql: user_old_sql_demo
|
87
|
+
report_processor: User_Old_Sql_Demo_Processor
|
88
|
+
report_view: table
|
89
|
+
fields:
|
90
|
+
- 'id'
|
91
|
+
- 'name'
|
92
|
+
|
93
|
+
user_chart:
|
94
|
+
description: User Chart
|
95
|
+
report_sql: user_old_sql_demo
|
96
|
+
report_design: user_old_sql_demo.yml
|
97
|
+
report_view: chart
|
98
|
+
fields:
|
78
99
|
- 'id'
|
79
100
|
- 'name'
|
80
101
|
|
@@ -144,6 +165,14 @@ All css and html template files can be copied to your installation by executing:
|
|
144
165
|
|
145
166
|
Settings for Old SQL can be configured in config/initializers/old_sql.rb.
|
146
167
|
|
168
|
+
== Rake Examples
|
169
|
+
|
170
|
+
rake old_sql:print:range[user_table,'development','2011-03-01','2011-09-01']
|
171
|
+
|
172
|
+
rake old_sql:print:today[user_table,'development']
|
173
|
+
|
174
|
+
rake old_sql:print:week[user_table,'development']
|
175
|
+
|
147
176
|
== Contributing to old_sql
|
148
177
|
|
149
178
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
@@ -10,6 +10,9 @@ module OldSql
|
|
10
10
|
helper_method :jqgrid_col_model
|
11
11
|
helper_method :jqgrid_col_names
|
12
12
|
helper_method :strip_html
|
13
|
+
helper_method :chart_type
|
14
|
+
helper_method :chart_fields
|
15
|
+
helper_method :chart_data
|
13
16
|
|
14
17
|
layout "old_sql/report.html.erb"
|
15
18
|
|
@@ -50,6 +53,23 @@ module OldSql
|
|
50
53
|
render :template => "old_sql/report/table.html.erb"
|
51
54
|
end
|
52
55
|
|
56
|
+
def chart
|
57
|
+
@start_date = params[:start_date]
|
58
|
+
@end_date = params[:end_date]
|
59
|
+
@report_name = params[:report]
|
60
|
+
@report_sql = params[:report_sql].downcase
|
61
|
+
@report_sql_orig = params[:report_sql].downcase
|
62
|
+
|
63
|
+
@width = OldSql.report_width
|
64
|
+
@height = OldSql.report_height
|
65
|
+
|
66
|
+
processor = load_base_processor
|
67
|
+
@report = processor.execute_query(@report_sql,@start_date,@end_date,query_vars(@report_name),@reports[@report_name]['report_design'],
|
68
|
+
@reports[@report_name]['report_processor'])
|
69
|
+
|
70
|
+
render :template => "old_sql/report/chart.html.erb"
|
71
|
+
end
|
72
|
+
|
53
73
|
def query
|
54
74
|
@start_date = params[:start_date]
|
55
75
|
@end_date = params[:end_date]
|
@@ -173,6 +193,28 @@ module OldSql
|
|
173
193
|
def strip_html html
|
174
194
|
OldSql.strip_html html
|
175
195
|
end
|
196
|
+
|
197
|
+
def chart_fields
|
198
|
+
fields =[]
|
199
|
+
|
200
|
+
i=0
|
201
|
+
@reports[@report_name]['fields'].each do |field|
|
202
|
+
fields << {v:i, label:field}
|
203
|
+
i+=1
|
204
|
+
end
|
205
|
+
|
206
|
+
json = fields.to_json
|
207
|
+
json.html_safe
|
208
|
+
end
|
209
|
+
|
210
|
+
def chart_data
|
211
|
+
json = @report.values.first.to_json
|
212
|
+
json.html_safe
|
213
|
+
end
|
214
|
+
|
215
|
+
def chart_type
|
216
|
+
@report.keys.first
|
217
|
+
end
|
176
218
|
end
|
177
219
|
end
|
178
220
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= javascript_include_tag "old_sql/MochiKit-1.4.2/lib/MochiKit/MochiKit.js" %>
|
2
|
+
<%= javascript_include_tag "old_sql/plotkit-0.9.1/PlotKit/Base.js" %>
|
3
|
+
<%= javascript_include_tag "old_sql/plotkit-0.9.1/PlotKit/Layout.js" %>
|
4
|
+
<%= javascript_include_tag "old_sql/plotkit-0.9.1/PlotKit/Canvas.js" %>
|
5
|
+
<%= javascript_include_tag "old_sql/plotkit-0.9.1/PlotKit/SweetCanvas.js" %>
|
6
|
+
|
7
|
+
<script>
|
8
|
+
var options = {
|
9
|
+
"IECanvasHTC": "/plotkit/iecanvas.htc",
|
10
|
+
"colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),
|
11
|
+
"xTicks": <%=chart_fields%>,
|
12
|
+
"drawYAxis": true
|
13
|
+
};
|
14
|
+
|
15
|
+
function drawGraph() {
|
16
|
+
var layout = new PlotKit.Layout("<%=chart_type%>", options);
|
17
|
+
layout.addDataset("sqrt", <%=chart_data%>);
|
18
|
+
layout.evaluate();
|
19
|
+
var canvas = MochiKit.DOM.getElement("graph");
|
20
|
+
var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options);
|
21
|
+
plotter.render();
|
22
|
+
}
|
23
|
+
MochiKit.DOM.addLoadEvent(drawGraph);
|
24
|
+
</script>
|
25
|
+
|
26
|
+
<div><canvas id="graph" height="555" width="555"></canvas></div>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<script>
|
2
2
|
var host = "<%=@host%>";
|
3
3
|
var port = "<%=@port%>";
|
4
|
-
var
|
4
|
+
var default_report_view = "<%=@report_view%>";
|
5
5
|
</script>
|
6
6
|
|
7
7
|
<div class="os-block">
|
@@ -17,7 +17,9 @@ var report_view = "<%=@report_view%>";
|
|
17
17
|
onchange="report_selected()">
|
18
18
|
<option></option>
|
19
19
|
<% @reports.each do |report, data| %>
|
20
|
-
<option value="<%= data['name'] %>" report_sql="<%= data['report_sql'] %>"
|
20
|
+
<option value="<%= data['name'] %>" report_sql="<%= data['report_sql'] %>"
|
21
|
+
desc="<%= data['description'] %>" name="<%=report%>"
|
22
|
+
report_view="<%=data['report_view']%>"><%= data['description'] %></option>
|
21
23
|
<% end %>
|
22
24
|
</select>
|
23
25
|
</div>
|
data/config/routes.rb
CHANGED
@@ -6,6 +6,7 @@ Rails.application.routes.draw do
|
|
6
6
|
match "/query", :to => :query, :as => "query"
|
7
7
|
match "/jqgrid", :to => :jqgrid, :as => "jqgrid"
|
8
8
|
match "/table", :to => :table, :as => "table"
|
9
|
+
match "/chart", :to => :chart, :as => "chart"
|
9
10
|
match "/print", :to => :print, :as => "print"
|
10
11
|
end
|
11
12
|
end
|
@@ -59,6 +59,7 @@ module OldSql
|
|
59
59
|
copy_file "user.erb.example", "#{app_path}/config/old_sql/report_sql/user_old_sql_demo.erb"
|
60
60
|
copy_file "user_processor.rb.example", "#{app_path}/lib/old_sql/report_processor/user_old_sql_demo_processor.rb"
|
61
61
|
copy_file "user_design_template.csv", "#{app_path}/config/old_sql/report_design/user_old_sql_demo.csv"
|
62
|
+
copy_file "user_old_sql_demo_chart_design.yml", "#{app_path}/config/old_sql/report_design/user_old_sql_demo.yml"
|
62
63
|
end
|
63
64
|
|
64
65
|
def configure_initializer
|
@@ -15,13 +15,37 @@
|
|
15
15
|
# 'report_design' is also optional, and should point to a file in config/old_sql/report_design.
|
16
16
|
# See config/old_sql/report_design/user_old_sql_demo.csv for an example.
|
17
17
|
#
|
18
|
+
# 'report_view' is optional. It overrides the default_report_view defined in the initializer. It
|
19
|
+
# can be set to jqgrid, table, or chart.
|
20
|
+
#
|
18
21
|
# The 'fields' are the headers for the report.
|
19
22
|
|
20
|
-
|
21
|
-
description: User
|
23
|
+
user_jqgrid:
|
24
|
+
description: User jqGrid
|
25
|
+
report_sql: user_old_sql_demo
|
26
|
+
report_design: user_old_sql_demo.csv
|
27
|
+
report_view: jqgrid
|
28
|
+
fields:
|
29
|
+
- 'id'
|
30
|
+
- 'name'
|
31
|
+
|
32
|
+
user_table:
|
33
|
+
description: User HTML Table
|
22
34
|
report_sql: user_old_sql_demo
|
23
|
-
|
24
|
-
|
35
|
+
report_processor: User_Old_Sql_Demo_Processor
|
36
|
+
report_view: table
|
25
37
|
fields:
|
26
38
|
- 'id'
|
27
|
-
- 'name'
|
39
|
+
- 'name'
|
40
|
+
|
41
|
+
user_chart:
|
42
|
+
description: User Chart
|
43
|
+
report_sql: user_old_sql_demo
|
44
|
+
report_design: user_old_sql_demo.yml
|
45
|
+
report_view: chart
|
46
|
+
fields:
|
47
|
+
- 'zero'
|
48
|
+
- 'one'
|
49
|
+
- 'two'
|
50
|
+
- 'three'
|
51
|
+
- 'four'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module OldSql
|
2
|
+
module ReportDesign
|
3
|
+
class Chart
|
4
|
+
attr_accessor :type, :items
|
5
|
+
|
6
|
+
def initialize(value = [])
|
7
|
+
@items = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def type new_type = nil
|
11
|
+
@type = new_type unless new_type.nil?
|
12
|
+
@type
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(key, value)
|
16
|
+
@items << ChartItem.new(key, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def item(index)
|
20
|
+
@items[index]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module OldSql
|
2
|
+
module ReportDesign
|
3
|
+
class ChartData
|
4
|
+
attr_accessor :value, :type
|
5
|
+
|
6
|
+
COLUMN = 1
|
7
|
+
OPERATOR = 3
|
8
|
+
NUMERIC_LITERAL = 4
|
9
|
+
|
10
|
+
def initialize(value)
|
11
|
+
@value = value
|
12
|
+
set_type
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_type
|
18
|
+
@type = case @value[0]
|
19
|
+
when /[\/*+-\Q()]/
|
20
|
+
OPERATOR
|
21
|
+
when /[0-9]/
|
22
|
+
NUMERIC_LITERAL
|
23
|
+
else
|
24
|
+
COLUMN
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module OldSql
|
2
|
+
module ReportDesign
|
3
|
+
class ChartItem
|
4
|
+
attr_accessor :chart_data, :key
|
5
|
+
|
6
|
+
def initialize(key, value)
|
7
|
+
@key = key
|
8
|
+
@value = value
|
9
|
+
@chart_data = []
|
10
|
+
|
11
|
+
@value.split(" ").each {|chart_data| @chart_data << ChartData.new(chart_data)}
|
12
|
+
end
|
13
|
+
|
14
|
+
def expression?
|
15
|
+
if @chart_data.count>1
|
16
|
+
return true
|
17
|
+
else
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module OldSql
|
2
|
+
module ReportDesign
|
3
|
+
class ChartParser
|
4
|
+
def self.read_file file_to_read
|
5
|
+
raise ArgumentError, 'Argument file is null.' unless !file_to_read.nil?
|
6
|
+
full_path = "#{report_design_path}/#{file_to_read}"
|
7
|
+
raise ArgumentError, "File #{full_path} not found." unless File.exists?(full_path)
|
8
|
+
|
9
|
+
@chart = Chart.new
|
10
|
+
|
11
|
+
template = File.read("#{report_design_path}/#{file_to_read}")
|
12
|
+
design_template = YAML.load(Erubis::Eruby.new(template).result)
|
13
|
+
|
14
|
+
design_template.each do |type, i|
|
15
|
+
@chart.type = type
|
16
|
+
i.each do |key, value|
|
17
|
+
@chart.add(key, value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@chart
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.report_design_path
|
25
|
+
app_path = Rails.public_path.split("/")
|
26
|
+
app_path.delete_at(-1)
|
27
|
+
app_path = app_path.join("/")
|
28
|
+
app_path << "/config/old_sql/report_design"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -4,6 +4,11 @@ require 'old_sql/report_design/row'
|
|
4
4
|
require 'old_sql/report_design/cell'
|
5
5
|
require 'old_sql/report_design/cell_data'
|
6
6
|
|
7
|
+
require 'old_sql/report_design/chart_parser'
|
8
|
+
require 'old_sql/report_design/chart'
|
9
|
+
require 'old_sql/report_design/chart_item'
|
10
|
+
require 'old_sql/report_design/chart_data'
|
11
|
+
|
7
12
|
module OldSql
|
8
13
|
module ReportProcessor
|
9
14
|
class Base
|
@@ -35,7 +40,8 @@ module OldSql
|
|
35
40
|
end
|
36
41
|
|
37
42
|
if design
|
38
|
-
parse_design(design, @resultset)
|
43
|
+
parse_design(design, @resultset) if design =~ /csv/
|
44
|
+
parse_chart_design(design, @resultset) if design =~ /yml/
|
39
45
|
else
|
40
46
|
loaded_sub_processor = load_sub_processor(sub_processor)
|
41
47
|
|
@@ -73,7 +79,7 @@ module OldSql
|
|
73
79
|
|
74
80
|
return nil if @rec.nil?
|
75
81
|
|
76
|
-
model = OldSql::ReportDesign::Parser.read_file("#{design}
|
82
|
+
model = OldSql::ReportDesign::Parser.read_file("#{design}")
|
77
83
|
|
78
84
|
init(resultset)
|
79
85
|
|
@@ -108,6 +114,39 @@ module OldSql
|
|
108
114
|
end
|
109
115
|
end
|
110
116
|
|
117
|
+
def parse_chart_design(design, resultset)
|
118
|
+
report_row = []
|
119
|
+
@rec = resultset[0]
|
120
|
+
|
121
|
+
chart = OldSql::ReportDesign::ChartParser.read_file("#{design}")
|
122
|
+
|
123
|
+
chart.items.each do |item|
|
124
|
+
key = item.key
|
125
|
+
expression = ""
|
126
|
+
item.chart_data.each do |data|
|
127
|
+
if item.expression?
|
128
|
+
if data.type == OldSql::ReportDesign::ChartData::COLUMN
|
129
|
+
expression << @rec[data.value].to_s
|
130
|
+
elsif data.type == OldSql::ReportDesign::ChartData::OPERATOR ||
|
131
|
+
data.type == OldSql::ReportDesign::ChartData::NUMERIC_LITERAL
|
132
|
+
expression << data.value
|
133
|
+
end
|
134
|
+
else
|
135
|
+
if data.type == OldSql::ReportDesign::ChartData::COLUMN
|
136
|
+
result = @rec[data.value]
|
137
|
+
if OldSql.round_report_values
|
138
|
+
result = round(result.to_f, OldSql.rounding_precision)
|
139
|
+
end
|
140
|
+
report_row << [key,result]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
report_row << [key,eval_expression(expression)] unless expression.length==0
|
145
|
+
end
|
146
|
+
|
147
|
+
@data = {chart.type=>report_row}
|
148
|
+
end
|
149
|
+
|
111
150
|
def eval_expression expression
|
112
151
|
result = 0.0
|
113
152
|
begin
|
@@ -2,6 +2,7 @@ function load_report()
|
|
2
2
|
{
|
3
3
|
report_name = jQuery("#report option:selected").attr('name');
|
4
4
|
report_sql = jQuery("#report option:selected").attr('report_sql');
|
5
|
+
report_view = get_report_view();
|
5
6
|
|
6
7
|
if (!reported_selected(report_name)) return;
|
7
8
|
|
@@ -18,6 +19,7 @@ function print_report()
|
|
18
19
|
{
|
19
20
|
report_name = jQuery("#report option:selected").attr('name');
|
20
21
|
report_sql = jQuery("#report option:selected").attr('report_sql');
|
22
|
+
report_view = get_report_view();
|
21
23
|
|
22
24
|
if (!reported_selected(report_name)) return;
|
23
25
|
|
@@ -31,6 +33,7 @@ function export_report_to_excel()
|
|
31
33
|
{
|
32
34
|
report_name = jQuery("#report option:selected").attr('name');
|
33
35
|
report_sql = jQuery("#report option:selected").attr('report_sql');
|
36
|
+
report_view = get_report_view();
|
34
37
|
|
35
38
|
if (!reported_selected(report_name)) return;
|
36
39
|
|
@@ -50,6 +53,17 @@ function reported_selected(report_name)
|
|
50
53
|
}
|
51
54
|
}
|
52
55
|
|
56
|
+
function get_report_view()
|
57
|
+
{
|
58
|
+
report_view = jQuery("#report option:selected").attr('report_view');
|
59
|
+
|
60
|
+
if (report_view) {
|
61
|
+
return report_view;
|
62
|
+
} else {
|
63
|
+
return default_report_view;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
53
67
|
jQuery(document).ready(function($){
|
54
68
|
jQuery("#datepicker-start").datetimepicker();
|
55
69
|
jQuery("#datepicker-start").datetimepicker( "option", "dateFormat", "yy/mm/dd" );
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: old_sql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: 1.14.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Eddie Gonzales
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-14 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: devise
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- app/controllers/old_sql/report_controller.rb
|
52
52
|
- app/views/layouts/old_sql/report.html.erb
|
53
53
|
- app/views/old_sql/errors/401.html.erb
|
54
|
+
- app/views/old_sql/report/chart.html.erb
|
54
55
|
- app/views/old_sql/report/datagrid.html.erb
|
55
56
|
- app/views/old_sql/report/index.html.erb
|
56
57
|
- app/views/old_sql/report/print.html.erb
|
@@ -71,11 +72,16 @@ files:
|
|
71
72
|
- lib/generators/old_sql/templates/reports.yml.example
|
72
73
|
- lib/generators/old_sql/templates/user.erb.example
|
73
74
|
- lib/generators/old_sql/templates/user_design_template.csv
|
75
|
+
- lib/generators/old_sql/templates/user_old_sql_demo_chart_design.yml
|
74
76
|
- lib/generators/old_sql/templates/user_processor.rb.example
|
75
77
|
- lib/old_sql.rb
|
76
78
|
- lib/old_sql/engine.rb
|
77
79
|
- lib/old_sql/report_design/cell.rb
|
78
80
|
- lib/old_sql/report_design/cell_data.rb
|
81
|
+
- lib/old_sql/report_design/chart.rb
|
82
|
+
- lib/old_sql/report_design/chart_data.rb
|
83
|
+
- lib/old_sql/report_design/chart_item.rb
|
84
|
+
- lib/old_sql/report_design/chart_parser.rb
|
79
85
|
- lib/old_sql/report_design/model.rb
|
80
86
|
- lib/old_sql/report_design/parser.rb
|
81
87
|
- lib/old_sql/report_design/row.rb
|
@@ -447,7 +453,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
447
453
|
requirements:
|
448
454
|
- - ">="
|
449
455
|
- !ruby/object:Gem::Version
|
450
|
-
hash:
|
456
|
+
hash: 1769007801397558054
|
451
457
|
segments:
|
452
458
|
- 0
|
453
459
|
version: "0"
|