spree_dash 0.70.7 → 1.0.0.rc1

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 (34) hide show
  1. data/LICENSE +2 -2
  2. data/README.md +1 -1
  3. data/app/assets/images/analytics_dashboard_preview.png +0 -0
  4. data/app/controllers/spree/admin/overview_controller.rb +15 -0
  5. data/app/controllers/spree/base_controller_decorator.rb +3 -0
  6. data/app/helpers/spree/analytics_helper.rb +69 -0
  7. data/app/models/spree/dash_configuration.rb +11 -0
  8. data/app/overrides/analytics_header.rb +4 -0
  9. data/app/views/spree/admin/overview/_form.html.erb +23 -0
  10. data/app/views/spree/admin/overview/index.html.erb +37 -0
  11. data/app/views/spree/analytics/_header.html.erb +12 -0
  12. data/config/locales/en.yml +1 -0
  13. data/config/routes.rb +2 -2
  14. data/lib/spree/dash.rb +9 -0
  15. data/lib/spree/dash/engine.rb +24 -0
  16. data/lib/spree_dash.rb +1 -7
  17. metadata +33 -32
  18. data/app/assets/javascripts/admin/dashboard.js +0 -144
  19. data/app/assets/javascripts/admin/spree_dash.js +0 -15
  20. data/app/assets/javascripts/store/spree_dash.js +0 -1
  21. data/app/assets/stylesheets/admin/dashboard.css.erb +0 -143
  22. data/app/assets/stylesheets/admin/spree_dash.css +0 -4
  23. data/app/assets/stylesheets/store/spree_dash.css +0 -3
  24. data/app/controllers/admin/overview_controller.rb +0 -152
  25. data/app/views/admin/overview/index.html.erb +0 -164
  26. data/vendor/assets/javascripts/jqPlot/excanvas.min.js +0 -1
  27. data/vendor/assets/javascripts/jqPlot/jquery.jqplot.min.js +0 -14
  28. data/vendor/assets/javascripts/jqPlot/plugins/jqplot.canvasAxisLabelRenderer.min.js +0 -14
  29. data/vendor/assets/javascripts/jqPlot/plugins/jqplot.canvasAxisTickRenderer.min.js +0 -14
  30. data/vendor/assets/javascripts/jqPlot/plugins/jqplot.canvasTextRenderer.min.js +0 -14
  31. data/vendor/assets/javascripts/jqPlot/plugins/jqplot.categoryAxisRenderer.min.js +0 -14
  32. data/vendor/assets/javascripts/jqPlot/plugins/jqplot.dateAxisRenderer.min.js +0 -14
  33. data/vendor/assets/javascripts/jqPlot/plugins/jqplot.highlighter.min.js +0 -14
  34. data/vendor/assets/javascripts/jqPlot/plugins/jqplot.pieRenderer.min.js +0 -14
@@ -1,15 +0,0 @@
1
- // This is a manifest file that'll be compiled into including all the files listed below.
2
- // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
- // be included in the compiled file accessible from http://example.com/assets/application.js
4
- // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
- // the compiled file.
6
- //
7
- //= require_tree .
8
- //= require admin/spree_core
9
- //= require jqPlot/jquery.jqplot.min
10
- //= require jqPlot/plugins/jqplot.dateAxisRenderer.min
11
- //= require jqPlot/plugins/jqplot.highlighter.min
12
- //= require jqPlot/plugins/jqplot.canvasAxisTickRenderer.min
13
- //= require jqPlot/plugins/jqplot.canvasTextRenderer.min
14
- //= require jqPlot/plugins/jqplot.canvasAxisLabelRenderer.min
15
- //= require jqPlot/plugins/jqplot.pieRenderer.min
@@ -1 +0,0 @@
1
- //= require store/spree_core
@@ -1,143 +0,0 @@
1
- .dashboard h2{
2
- padding-bottom:5px;
3
- color: #476D9B;
4
- clear:both;
5
- }
6
-
7
- .dashboard_left{
8
- width:25%;
9
- float:left;
10
- }
11
-
12
- .dashboard_main{
13
- width:55%;
14
- float:left;
15
- }
16
-
17
- .dashboard_main #orders_by_day_options{
18
- background-color:#0095DA;
19
- -moz-border-radius-bottomleft:10px;
20
- -moz-border-radius-bottomright:10px;
21
- -moz-border-radius-topleft:10px;
22
- -moz-border-radius-topright:10px;
23
- -webkit-border-bottom-left-radius: 10px 10px;
24
- -webkit-border-bottom-right-radius: 10px 10px;
25
- -webkit-border-top-left-radius: 10px 10px;
26
- -webkit-border-top-right-radius: 10px 10px;
27
- color:#fff;
28
- margin-top:10px;
29
- padding:5px;
30
- text-align:center;
31
- }
32
-
33
- #order_by_day_title{
34
- padding-bottom:5px;
35
- color: #476D9B;
36
- clear:both;
37
- }
38
-
39
- #order_totals{
40
- background:#154E8C url(<%= asset_path("admin/bg/admin_tab_back.png") %>) repeat-x scroll left top;
41
- -moz-border-radius-bottomleft:10px;
42
- -moz-border-radius-bottomright:10px;
43
- -moz-border-radius-topleft:10px;
44
- -moz-border-radius-topright:10px;
45
- -webkit-border-bottom-left-radius: 10px 10px;
46
- -webkit-border-bottom-right-radius: 10px 10px;
47
- -webkit-border-top-left-radius: 10px 10px;
48
- -webkit-border-top-right-radius: 10px 10px;
49
- color:#fff;
50
- height:62px;
51
- padding:0 10px;
52
- margin-bottom:20px;
53
- }
54
-
55
- #order_totals hr{
56
- background-color:#fff;
57
- clear:none;
58
- float:left;
59
- height:80%;
60
- margin-top:6px;
61
- width:3px;
62
- }
63
-
64
- #order_totals .spacer{
65
- padding: 0px 10px;
66
- font-size: 50px;
67
- line-height: 60px;
68
- color: #476D9B;
69
- }
70
-
71
- #order_totals p{
72
- float:left;
73
- font-size:420%;
74
- font-weight:bold;
75
- line-height:60px;
76
- margin:0 5px 0 0;
77
- }
78
-
79
- #order_totals label{
80
- font-size:200%;
81
- line-height:50px;
82
- }
83
-
84
- #order_totals span{
85
- display:block;
86
- font-size:90%;
87
- font-weight:bold;
88
- margin-top: -10px;
89
- }
90
-
91
- .dashboard_main #orders_by_day_options label{
92
- padding: 0px 10px;
93
- }
94
-
95
- .dashboard_right{
96
- width:20%;
97
- float:left;
98
- }
99
-
100
- .dashboard table th{
101
- background-color: #0095DA;
102
- color: #fff;
103
- }
104
-
105
- .dashboard_small_wrapper{
106
- padding: 0px 20px 0px 0px;
107
- }
108
-
109
- .dashboard_main_wrapper{
110
- padding: 0px 30px 10px 30px;
111
- margin-left: auto;
112
- margin-right: auto;
113
- }
114
-
115
- #pie_legend{
116
- width:50%;
117
- float:left;
118
- font-size: 80%;
119
- }
120
-
121
- #pie_legend span{
122
- line-height:15px;
123
- width:15px;
124
- float:left;
125
- }
126
-
127
- #pie_legend label{
128
- margin-left:5px;
129
- float:left;
130
- }
131
-
132
- #pie_legend div{
133
- clear:both;
134
- text-align:right;
135
- }
136
-
137
- .text-right{
138
- text-align:right;
139
- }
140
-
141
- .jqplot-table-legend{
142
- width:60px;
143
- }
@@ -1,4 +0,0 @@
1
- /*
2
- *= require admin/spree_core
3
- *= require admin/dashboard
4
- */
@@ -1,3 +0,0 @@
1
- /*
2
- *= require store/spree_core
3
- */
@@ -1,152 +0,0 @@
1
- # this clas was inspired (heavily) from the mephisto admin architecture
2
-
3
- class Admin::OverviewController < Admin::BaseController
4
- before_filter :check_json_authenticity, :only => :get_report_data
5
- #todo, add rss feed of information that is happening
6
-
7
- def index
8
- @show_dashboard = show_dashboard
9
- return unless @show_dashboard
10
-
11
- p = {:from => (Time.new().to_date - 1.week).to_s(:db), :value => "Count"}
12
- @orders_by_day = orders_by_day(p)
13
- @orders_line_total = orders_line_total(p)
14
- @orders_total = orders_total(p)
15
- @orders_adjustment_total = orders_adjustment_total(p)
16
- @orders_credit_total = orders_credit_total(p)
17
-
18
- @best_selling_variants = best_selling_variants
19
- @top_grossing_variants = top_grossing_variants
20
- @last_five_orders = last_five_orders
21
- @biggest_spenders = biggest_spenders
22
- @out_of_stock_products = out_of_stock_products
23
- @best_selling_taxons = best_selling_taxons
24
-
25
- @pie_colors = [ "#0093DA", "#FF3500", "#92DB00", "#1AB3FF", "#FFB800"]
26
- end
27
-
28
- def get_report_data
29
- opts = case params[:name]
30
- when "7_days" then {:from => (Time.new().to_date - 1.week).to_s(:db)}
31
- when "14_days" then {:from => (Time.new().to_date - 2.week).to_s(:db)}
32
- when "this_month" then {:from => Date.new(Time.now.year, Time.now.month, 1).to_s(:db), :to => Date.new(Time.now.year, Time.now.month, -1).to_s(:db)}
33
- when "last_month" then {:from => (Date.new(Time.now.year, Time.now.month, 1) - 1.month).to_s(:db), :to => (Date.new(Time.now.year, Time.now.month, -1) - 1.month).to_s(:db)}
34
- when "this_year" then {:from => Date.new(Time.now.year, 1, 1).to_s(:db)}
35
- when "last_year" then {:from => Date.new(Time.now.year - 1, 1, 1).to_s(:db), :to => Date.new(Time.now.year - 1, 12, -1).to_s(:db)}
36
- end
37
-
38
- case params[:report]
39
- when "orders_by_day"
40
- opts[:value] = params[:value]
41
-
42
- render :js => "[[" + orders_by_day(opts).map { |day| "['#{day[0]}',#{day[1]}]" }.join(",") + "]]"
43
- when "orders_totals"
44
- render :js => [:orders_total => orders_total(opts).to_i, :orders_line_total => orders_line_total(opts).to_i,
45
- :orders_adjustment_total => orders_adjustment_total(opts).to_i, :orders_credit_total => orders_credit_total(opts).to_i ].to_json
46
- end
47
- end
48
-
49
- private
50
- def show_dashboard
51
- Order.count > 50
52
- end
53
-
54
- def conditions(params)
55
- if params.key? :to
56
- ["completed_at >= ? AND completed_at <= ? AND state <> 'canceled'", params[:from], params[:to]]
57
- else
58
- ["completed_at >= ? AND state <> 'canceled'", params[:from]]
59
- end
60
- end
61
-
62
- def fill_empty_entries(orders, params)
63
- from_date = params[:from].to_date
64
- to_date = (params[:to] || Time.now).to_date
65
- (from_date..to_date).each do |date|
66
- orders[date] ||= []
67
- end
68
- end
69
-
70
- def orders_by_day(params)
71
-
72
- if params[:value] == "Count"
73
- orders = Order.select(:created_at).where(conditions(params))
74
- orders = orders.group_by { |o| o.created_at.to_date }
75
- fill_empty_entries(orders, params)
76
- orders.keys.sort.map {|key| [key.strftime('%Y-%m-%d'), orders[key].size ]}
77
- else
78
- orders = Order.select([:created_at, :total]).where(conditions(params))
79
- orders = orders.group_by { |o| o.created_at.to_date }
80
- fill_empty_entries(orders, params)
81
- orders.keys.sort.map {|key| [key.strftime('%Y-%m-%d'), orders[key].inject(0){|s,o| s += o.total} ]}
82
- end
83
- end
84
-
85
- def orders_line_total(params)
86
- Order.sum(:item_total, :conditions => conditions(params))
87
- end
88
-
89
- def orders_total(params)
90
- Order.sum(:total, :conditions => conditions(params))
91
- end
92
-
93
- def orders_adjustment_total(params)
94
- Order.sum(:adjustment_total, :conditions => conditions(params))
95
- end
96
-
97
- def orders_credit_total(params)
98
- Order.sum(:credit_total, :conditions => conditions(params))
99
- end
100
-
101
- def best_selling_variants
102
- li = LineItem.includes(:order).where("orders.state = 'complete'").sum(:quantity, :group => :variant_id, :order => 'sum(quantity) desc', :limit => 5)
103
- variants = li.map do |v|
104
- variant = Variant.find(v[0])
105
- [variant.name, v[1] ]
106
- end
107
- variants.sort { |x,y| y[1] <=> x[1] }
108
- end
109
-
110
- def top_grossing_variants
111
- prices = LineItem.includes(:order).where("orders.state = 'complete'").sum(:price, :group => :variant_id, :order => 'sum(price) desc', :limit => 5)
112
- variants = prices.map do |v|
113
- variant = Variant.find(v[0])
114
- [variant.name, v[1] * prices[v[0]]]
115
- end
116
-
117
- variants.sort { |x,y| y[1] <=> x[1] }
118
- end
119
-
120
- def best_selling_taxons
121
- taxonomy = Taxonomy.last
122
- taxons = Taxon.connection.select_rows("select t.name, count(li.quantity) from line_items li inner join variants v on
123
- li.variant_id = v.id inner join products p on v.product_id = p.id inner join products_taxons pt on p.id = pt.product_id
124
- inner join taxons t on pt.taxon_id = t.id where t.taxonomy_id = #{taxonomy.id} group by t.name order by count(li.quantity) desc limit 5;")
125
- end
126
-
127
- def last_five_orders
128
- orders = Order.includes(:line_items).where("completed_at IS NOT NULL AND state <> 'canceled'").order("completed_at DESC").limit(5)
129
- orders.map do |o|
130
- qty = o.line_items.inject(0) {|sum,li| sum + li.quantity}
131
-
132
- [o.email, qty, o.total]
133
- end
134
- end
135
-
136
- def biggest_spenders
137
- spenders = Order.sum(:total, :group => :user_id, :limit => 5, :order => "sum(total) desc", :conditions => "completed_at is not null and state <> 'canceled' and user_id is not null")
138
- spenders = spenders.map do |o|
139
- orders = User.find(o[0]).orders
140
- qty = orders.size
141
-
142
- [orders.first.email, qty, o[1]]
143
-
144
- end
145
-
146
- spenders.sort { |x,y| y[2] <=> x[2] }
147
- end
148
-
149
- def out_of_stock_products
150
- Product.where(:count_on_hand => 0).limit(5)
151
- end
152
- end
@@ -1,164 +0,0 @@
1
- <h1><%= t(:overview) %></h1>
2
-
3
- <div data-hook="admin_dashboard">
4
- <% if @show_dashboard %>
5
- <div class="dashboard">
6
- <div class="dashboard_left">
7
- <div data-hook="admin_dashboard_left">
8
- <div class="dashboard_small_wrapper">
9
- <h2><%= t(:best_selling_products) %></h2>
10
- <div id="best_selling_products" style="width:50%; height:170px; float:left;"></div>
11
- <div id="pie_legend">
12
- <% @best_selling_variants.each_with_index do |v,i| %>
13
- <span style="background-color:<%= @pie_colors[i] %>">&nbsp;</span>
14
- <label><%= truncate v[0], :length => 27 %></label>
15
- <div><%= number_with_delimiter v[1] %> <%= t(:units) %></div>
16
- <% end %>
17
- </div>
18
-
19
- <h2><%= t(:top_grossing_products) %></h2>
20
- <div id="top_grossing_products" style="width:50%; height:170px; float:left;"></div>
21
- <div id="pie_legend">
22
- <% @top_grossing_variants.each_with_index do |v,i| %>
23
- <span style="background-color:<%= @pie_colors[i] %>">&nbsp;</span>
24
- <label><%= truncate v[0], :length => 27 %></label>
25
- <div><%= number_to_currency v[1], :precision => 0 %></div>
26
- <% end %>
27
- </div>
28
-
29
- <h2><%= t(:best_selling_taxons) %></h2>
30
- <div id="best_selling_taxons" style="width:50%; height:170px; float:left;"></div>
31
- <div id="pie_legend">
32
- <% @best_selling_taxons.each_with_index do |t,i| %>
33
- <span style="background-color:<%= @pie_colors[i] %>">&nbsp;</span>
34
- <label><%= truncate t[0], :length => 27 %></label>
35
- <div><%= number_with_delimiter t[1] %> <%= t(:units) %></div>
36
- <% end %>
37
- </div>
38
-
39
- </div>
40
- </div>
41
- </div>
42
- <div data-hook="admin_dashboard_center">
43
- <div class="dashboard_main">
44
- <div class="dashboard_main_wrapper">
45
- <h2 id="order_by_day_title"><%= t('orders') %> <%= t('count') %> <%= t('by_day') %> (<%= t('last_7_days') %>)</h2>
46
-
47
- <table id="order_totals">
48
- <tr>
49
- <td style="width:23%;">
50
- <p><%= t("number.currency.format.unit") %></p>
51
- <label id="orders_total"><%= number_with_delimiter @orders_total.to_i %></label>
52
- <span><%= t('order') %> <%= t('total') %></span>
53
- </td>
54
- <td class="spacer">|</td>
55
- <td style="width:23%;">
56
- <p><%= t("number.currency.format.unit") %></p>
57
- <label id="orders_line_total"><%= number_with_delimiter @orders_line_total.to_i %></label>
58
- <span><%= t('item') %> <%= t('total') %></span>
59
- </td>
60
- <td class="spacer">|</td>
61
- <td style="width:23%;">
62
- <p><%= t("number.currency.format.unit") %></p>
63
- <label id="orders_adjustment_total"><%= number_with_delimiter @orders_adjustment_total.to_i %></label>
64
- <span><%= t('adjustments') %></span>
65
- </td>
66
- <td class="spacer">|</td>
67
- <td style="width:22%">
68
- <p><%= t("number.currency.format.unit") %></p>
69
- <label id="orders_adjustment_total"><%= number_with_delimiter @orders_credit_total.to_i %></label>
70
- <span><%= t('credits') %></span>
71
- </td>
72
- </tr>
73
- </table>
74
-
75
- <div id="orders_by_day" style="width:100%;height:240px;"></div>
76
-
77
- <div id="orders_by_day_options">
78
- <label><%= t('range') %>:</label>
79
- <%= select_tag "orders_by_day_reports", options_for_select([[t('last_7_days'), "7_days"], [t('last_14_days'), "14_days"], [t('this_month'), "this_month"],
80
- [t('last_month'), "last_month"], [t('this_year'), "this_year"], [t('last_year'), "last_year"] ], "7_days") %>
81
- <label><%= t('value') %>:</label>
82
- <%= select_tag "orders_by_day_value", options_for_select({t('count') => 'Count', t('value') => 'Value'}, 'Count') %>
83
- </div>
84
- </div>
85
- </div>
86
- </div>
87
- <div data-hook="admin_dashboard_right">
88
- <div class="dashboard_right">
89
- <h2><%= t('last_5_orders') %></h2>
90
- <table>
91
- <thead>
92
- <tr>
93
- <th><%= t('name') %></th>
94
- <th class="text-right"><%= t('items') %></th>
95
- <th class="text-right"><%= t('total') %></th>
96
- </tr>
97
- </thead>
98
- <% @last_five_orders.each do |order| %>
99
- <tr>
100
- <td><%= truncate order[0], :length => 18 %></td>
101
- <td class="text-right"><%= order[1] %></td>
102
- <td class="text-right"><%= number_to_currency order[2] %></td>
103
- </tr>
104
- <% end %>
105
- </table>
106
-
107
- <h2><%= t('5_biggest_spenders') %></h2>
108
- <table>
109
- <thead>
110
- <tr>
111
- <th><%= t('name') %></th>
112
- <th class="text-right"><%= t('ord_qty') %></th>
113
- <th class="text-right"><%= t('ord_total') %></th>
114
- </tr>
115
- </thead>
116
- <% @biggest_spenders.each do |order| %>
117
- <tr>
118
- <td><%= truncate order[0], :length => 18 %></td>
119
- <td class="text-right"><%= order[1] %></td>
120
- <td class="text-right"><%= number_to_currency order[2] %></td>
121
- </tr>
122
- <% end %>
123
- </table>
124
-
125
- <h2><%= t('out_of_stock_products') %></h2>
126
- <table>
127
- <thead>
128
- <tr>
129
- <th><%= t('name') %></th>
130
- </tr>
131
- </thead>
132
- <% @out_of_stock_products.each do |product| %>
133
- <tr>
134
- <td><%= product.name %></td>
135
- </tr>
136
- <% end %>
137
- </table>
138
- </div>
139
- </div>
140
- </div>
141
- <p style="clear:both;">&nbsp;</p>
142
- <% else %>
143
- <div data-hook="admin_dashboard_welcome">
144
- <%== t('overview_welcome') %>
145
- </div>
146
- <% end %>
147
- </div>
148
-
149
- <% content_for :head do %>
150
- <% if @show_dashboard %>
151
- <%= javascript_tag do -%>
152
- var orders_by_day_points = [[<%== @orders_by_day.map { |day| "[\"#{day[0]}\",#{day[1]}]" }.join(",") %>]];
153
- var best_selling_variants_points = [<%== @best_selling_variants.map { |v| "[\"#{h(v[0])}\",#{v[1]}]" }.join(",") %>];
154
- var top_grossing_variants_points = [<%== @top_grossing_variants.map { |v| "[\"#{h(v[0])}\",#{v[1]}]" }.join(",") %>];
155
- var best_selling_taxons_points = [<%== @best_selling_taxons.map { |t| "[\"#{h(t[0])}\",#{t[1]}]" }.join(",") %>];
156
-
157
- var orders = "<%= t(:orders) %>";
158
- var by_day = "<%= t(:by_day) %>";
159
-
160
- var pie_colors = [<%== @pie_colors.map{|c| "'#{c}'"}.join(",") %>];
161
- <% end -%>
162
- <!--[if IE]><%= javascript_include_tag 'jqPlot/excanvas.min.js' %><![endif]-->
163
- <% end %>
164
- <% end %>