solidus_admin_insights 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +54 -0
- data/Gemfile +2 -0
- data/LICENSE +26 -0
- data/README.md +71 -0
- data/Rakefile +21 -0
- data/app/assets/javascripts/spree/backend/jquery.tablesorter.min.js +4 -0
- data/app/assets/javascripts/spree/backend/solidus_admin_insights.js +2 -0
- data/app/assets/javascripts/spree/backend/solidus_admin_insights/paginator.js +128 -0
- data/app/assets/javascripts/spree/backend/solidus_admin_insights/report_loader.js +265 -0
- data/app/assets/javascripts/spree/backend/solidus_admin_insights/searcher.js +72 -0
- data/app/assets/javascripts/spree/backend/solidus_admin_insights/table_sorter.js +47 -0
- data/app/assets/javascripts/spree/backend/tmpl.js +87 -0
- data/app/assets/javascripts/spree/frontend/solidus_admin_insights.js +2 -0
- data/app/assets/stylesheets/spree/backend/override_pdf.css +71 -0
- data/app/assets/stylesheets/spree/backend/solidus_admin_insights.css +132 -0
- data/app/assets/stylesheets/spree/frontend/solidus_admin_insights.css +4 -0
- data/app/controllers/spree/admin/insights_controller.rb +103 -0
- data/app/helpers/spree/admin/base_helper_decorator.rb +17 -0
- data/app/models/spree/app_configuration_decorator.rb +3 -0
- data/app/models/spree/product_decorator.rb +3 -0
- data/app/models/spree/promotion_action_decorator.rb +3 -0
- data/app/models/spree/return_authorization_decorator.rb +4 -0
- data/app/permissions/spree/permission_sets/insight_display.rb +9 -0
- data/app/reports/spree/best_selling_products_report.rb +42 -0
- data/app/reports/spree/cart_additions_report.rb +36 -0
- data/app/reports/spree/cart_removals_report.rb +36 -0
- data/app/reports/spree/cart_updations_report.rb +40 -0
- data/app/reports/spree/payment_method_transactions_conversion_rate_report.rb +74 -0
- data/app/reports/spree/payment_method_transactions_conversion_rate_report/payment_method_state_distribution_chart.rb +39 -0
- data/app/reports/spree/payment_method_transactions_report.rb +60 -0
- data/app/reports/spree/payment_method_transactions_report/payment_method_revenue_distribution_chart.rb +36 -0
- data/app/reports/spree/product_views_report.rb +46 -0
- data/app/reports/spree/product_views_to_cart_additions_report.rb +53 -0
- data/app/reports/spree/product_views_to_purchases_report.rb +54 -0
- data/app/reports/spree/promotional_cost_report.rb +84 -0
- data/app/reports/spree/promotional_cost_report/promotional_cost_chart.rb +37 -0
- data/app/reports/spree/promotional_cost_report/usage_count_chart.rb +41 -0
- data/app/reports/spree/report.rb +131 -0
- data/app/reports/spree/report/chart.rb +11 -0
- data/app/reports/spree/report/configuration.rb +40 -0
- data/app/reports/spree/report/date_slicer.rb +61 -0
- data/app/reports/spree/report/observation.rb +49 -0
- data/app/reports/spree/report/query_fragments.rb +45 -0
- data/app/reports/spree/report/query_time_scale.rb +19 -0
- data/app/reports/spree/report/result.rb +100 -0
- data/app/reports/spree/report/timed_observation.rb +47 -0
- data/app/reports/spree/report/timed_result.rb +48 -0
- data/app/reports/spree/returned_products_report.rb +37 -0
- data/app/reports/spree/sales_performance_report.rb +107 -0
- data/app/reports/spree/sales_performance_report/profit_loss_chart.rb +37 -0
- data/app/reports/spree/sales_performance_report/profit_loss_percent_chart.rb +36 -0
- data/app/reports/spree/sales_performance_report/sale_cost_price_chart.rb +48 -0
- data/app/reports/spree/sales_tax_report.rb +64 -0
- data/app/reports/spree/sales_tax_report/monthly_sales_tax_comparison_chart.rb +39 -0
- data/app/reports/spree/shipping_cost_report.rb +89 -0
- data/app/reports/spree/shipping_cost_report/shipping_cost_distribution_chart.rb +38 -0
- data/app/reports/spree/trending_search_report.rb +50 -0
- data/app/reports/spree/trending_search_report/frequency_distribution_pie_chart.rb +41 -0
- data/app/reports/spree/unique_purchases_report.rb +39 -0
- data/app/reports/spree/user_pool_report.rb +66 -0
- data/app/reports/spree/user_pool_report/distribution_column_chart.rb +65 -0
- data/app/reports/spree/users_not_converted_report.rb +48 -0
- data/app/reports/spree/users_who_recently_purchased_report.rb +69 -0
- data/app/services/spree/report_generation_service.rb +27 -0
- data/app/views/spree/admin/insights/_chart.html.erb +4 -0
- data/app/views/spree/admin/insights/download.pdf.erb +27 -0
- data/app/views/spree/admin/insights/index.html.erb +82 -0
- data/app/views/spree/admin/insights/search/_product_views_search.html.erb +13 -0
- data/app/views/spree/admin/insights/search/_search_form.html.erb +39 -0
- data/app/views/spree/admin/insights/search/_trending_searches_search.html.erb +13 -0
- data/app/views/spree/admin/insights/search/_users_not_converted_search.html.erb +13 -0
- data/app/views/spree/admin/insights/search/_users_who_have_not_purchased_recently_search.html.erb +13 -0
- data/app/views/spree/admin/insights/search/_users_who_recently_purchased_search.html.erb +13 -0
- data/app/views/spree/admin/shared/_insights_side_menu.html.erb +5 -0
- data/app/views/spree/admin/shared/sub_menu/_insight.html.erb +7 -0
- data/app/views/spree/admin/templates/insights/_paginator.template +11 -0
- data/app/views/spree/admin/templates/insights/_search.template +76 -0
- data/app/views/spree/admin/templates/insights/_show.template +49 -0
- data/app/views/spree/layouts/pdf.html.erb +9 -0
- data/bin/rails +7 -0
- data/config/initializers/add_to_sidebar.rb +14 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/mime_types.rb +2 -0
- data/config/initializers/wicked_pdf.rb +21 -0
- data/config/locales/en.yml +167 -0
- data/config/routes.rb +6 -0
- data/lib/generators/solidus_admin_insights/install/install_generator.rb +36 -0
- data/lib/generators/solidus_admin_insights/install/solidus_admin_insights.rb +22 -0
- data/lib/solidus_admin_insights.rb +14 -0
- data/lib/solidus_admin_insights/engine.rb +27 -0
- data/lib/solidus_admin_insights/factories.rb +6 -0
- data/solidus_admin_insights.gemspec +42 -0
- data/spec/spec_helper.rb +93 -0
- metadata +419 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
//= require spree/backend/solidus_admin_insights/paginator
|
2
|
+
|
3
|
+
function Searcher(inputs, reportLoader) {
|
4
|
+
this.$insightsTableList = inputs.insightsDiv;
|
5
|
+
this.$filters = inputs.filterDiv;
|
6
|
+
this.$quickSearchForm = this.$filters.find('#quick-search');
|
7
|
+
this.tableSorter = inputs.tableSorterObject;
|
8
|
+
this.reportLoader = reportLoader;
|
9
|
+
this.$filterForm = null;
|
10
|
+
this.$searchLabelsContainer = this.$filters.find('.table-active-filters');
|
11
|
+
}
|
12
|
+
|
13
|
+
Searcher.prototype.bindEvents = function(data) {
|
14
|
+
var _this = this;
|
15
|
+
this.$searchLabelsContainer.on("click", ".js-delete-filter", function() {
|
16
|
+
_this.$quickSearchForm[0].reset();
|
17
|
+
$(this).parent().hide();
|
18
|
+
});
|
19
|
+
};
|
20
|
+
|
21
|
+
Searcher.prototype.refreshSearcher = function($selectedInsight, data) {
|
22
|
+
var requestPath = $selectedInsight.data('url'),
|
23
|
+
_this = this;
|
24
|
+
|
25
|
+
_this.$filters.removeClass('hide');
|
26
|
+
_this.addSearchForm(data);
|
27
|
+
_this.setFormActions(_this.$quickSearchForm, requestPath);
|
28
|
+
_this.setFormActions(_this.$filterForm, requestPath);
|
29
|
+
|
30
|
+
_this.$filterForm.on('submit', function() {
|
31
|
+
var paginate = !_this.reportLoader.removePaginationButton.closest('span').hasClass('hide');
|
32
|
+
$.ajax({
|
33
|
+
type: "GET",
|
34
|
+
url: _this.$filterForm.attr('action'),
|
35
|
+
data: _this.$filterForm.serialize() + "&per_page=" + _this.reportLoader.pageSelector.find(':selected').attr('value') + '&paginate=' + paginate,
|
36
|
+
dataType: 'json',
|
37
|
+
success: function(data) {
|
38
|
+
_this.reportLoader.requestUrl = this.url;
|
39
|
+
_this.populateInsightsData(data);
|
40
|
+
_this.reportLoader.paginatorObject.refreshPaginator(data);
|
41
|
+
}
|
42
|
+
});
|
43
|
+
return false;
|
44
|
+
});
|
45
|
+
};
|
46
|
+
|
47
|
+
Searcher.prototype.addSearchForm = function(data) {
|
48
|
+
this.$filters.find('#table-filter').empty().append($(tmpl('search-tmpl', data)));
|
49
|
+
this.$filterForm = this.$filters.find('#filter-search');
|
50
|
+
this.$filters.find('.datepicker').datepicker({ dateFormat: 'yy-mm-dd' });
|
51
|
+
};
|
52
|
+
|
53
|
+
Searcher.prototype.setFormActions = function($form, path) {
|
54
|
+
$form.attr("method", "get");
|
55
|
+
$form.attr("action", path);
|
56
|
+
};
|
57
|
+
|
58
|
+
Searcher.prototype.populateInsightsData = function(data) {
|
59
|
+
this.reportLoader.populateInsightsData(data);
|
60
|
+
};
|
61
|
+
|
62
|
+
Searcher.prototype.fillFormFields = function(searchedFields) {
|
63
|
+
$.each(Object.keys(searchedFields), function() {
|
64
|
+
$('#search_' + this).val(searchedFields[this]);
|
65
|
+
});
|
66
|
+
};
|
67
|
+
|
68
|
+
Searcher.prototype.clearSearchFields = function() {
|
69
|
+
this.$quickSearchForm[0].reset();
|
70
|
+
var filtersContainer = $(".js-filters");
|
71
|
+
filtersContainer.empty();
|
72
|
+
};
|
@@ -0,0 +1,47 @@
|
|
1
|
+
//= require spree/backend/jquery.tablesorter.min
|
2
|
+
|
3
|
+
function TableSorter(inputs) {
|
4
|
+
this.$insightsTableList = inputs.$insightsTable;
|
5
|
+
this.reportLoader = inputs.reportLoader;
|
6
|
+
this.paginatorDiv = inputs.paginatorDiv;
|
7
|
+
}
|
8
|
+
|
9
|
+
TableSorter.prototype.bindEvents = function() {
|
10
|
+
var _this = this;
|
11
|
+
this.$insightsTableList.on('click', '#admin-insight .sortable-link', function() {
|
12
|
+
event.preventDefault();
|
13
|
+
var currentPage = _this.paginatorDiv.find('li.active a').html() - 1,
|
14
|
+
paginate = _this.reportLoader.removePaginationButton.closest('span').hasClass('hide'),
|
15
|
+
requestPath = $(event.target).attr('href') + '&' + $('#filter-search').serialize() + '&page=' + currentPage + "&per_page=" + _this.reportLoader.pageSelector.find(':selected').attr('value') + '&paginate=' + paginate;
|
16
|
+
_this.reportLoader.requestUrl = requestPath;
|
17
|
+
|
18
|
+
$.ajax({
|
19
|
+
type: 'GET',
|
20
|
+
url: requestPath,
|
21
|
+
dataType: 'json',
|
22
|
+
success: function(data) {
|
23
|
+
_this.populateInsightsData(data);
|
24
|
+
}
|
25
|
+
});
|
26
|
+
});
|
27
|
+
};
|
28
|
+
|
29
|
+
TableSorter.prototype.populateInsightsData = function(data) {
|
30
|
+
this.reportLoader.populateInsightsData(data);
|
31
|
+
};
|
32
|
+
|
33
|
+
TableSorter.prototype.fetchSortedAttribute = function() {
|
34
|
+
var attribute, sortOrder;
|
35
|
+
if (this.$insightsTableList.find('.asc').length) {
|
36
|
+
attribute = this.getSortedAttribute('asc');
|
37
|
+
sortOrder = 'asc';
|
38
|
+
} else if(this.$insightsTableList.find('.desc').length) {
|
39
|
+
attribute = this.getSortedAttribute('desc');
|
40
|
+
sortOrder = 'desc';
|
41
|
+
}
|
42
|
+
return [attribute, sortOrder];
|
43
|
+
};
|
44
|
+
|
45
|
+
TableSorter.prototype.getSortedAttribute = function(order) {
|
46
|
+
return this.$insightsTableList.find('.' + order).data('attribute');
|
47
|
+
};
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/*
|
2
|
+
* JavaScript Templates 2.4.1
|
3
|
+
* https://github.com/blueimp/JavaScript-Templates
|
4
|
+
*
|
5
|
+
* Copyright 2011, Sebastian Tschan
|
6
|
+
* https://blueimp.net
|
7
|
+
*
|
8
|
+
* Licensed under the MIT license:
|
9
|
+
* http://www.opensource.org/licenses/MIT
|
10
|
+
*
|
11
|
+
* Inspired by John Resig's JavaScript Micro-Templating:
|
12
|
+
* http://ejohn.org/blog/javascript-micro-templating/
|
13
|
+
*/
|
14
|
+
|
15
|
+
/*jslint evil: true, regexp: true, unparam: true */
|
16
|
+
/*global document, define */
|
17
|
+
|
18
|
+
(function ($) {
|
19
|
+
"use strict";
|
20
|
+
var tmpl = function (str, data) {
|
21
|
+
var f = !/[^\w\-\.:]/.test(str) ? tmpl.cache[str] = tmpl.cache[str] ||
|
22
|
+
tmpl(tmpl.load(str)) :
|
23
|
+
new Function(
|
24
|
+
tmpl.arg + ',tmpl',
|
25
|
+
"var _e=tmpl.encode" + tmpl.helper + ",_s='" +
|
26
|
+
str.replace(tmpl.regexp, tmpl.func) +
|
27
|
+
"';return _s;"
|
28
|
+
);
|
29
|
+
return data ? f(data, tmpl) : function (data) {
|
30
|
+
return f(data, tmpl);
|
31
|
+
};
|
32
|
+
};
|
33
|
+
tmpl.cache = {};
|
34
|
+
tmpl.load = function (id) {
|
35
|
+
return document.getElementById(id).innerHTML;
|
36
|
+
};
|
37
|
+
tmpl.regexp = /([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g;
|
38
|
+
tmpl.func = function (s, p1, p2, p3, p4, p5) {
|
39
|
+
if (p1) { // whitespace, quote and backspace in HTML context
|
40
|
+
return {
|
41
|
+
"\n": "\\n",
|
42
|
+
"\r": "\\r",
|
43
|
+
"\t": "\\t",
|
44
|
+
" " : " "
|
45
|
+
}[p1] || "\\" + p1;
|
46
|
+
}
|
47
|
+
if (p2) { // interpolation: {%=prop%}, or unescaped: {%#prop%}
|
48
|
+
if (p2 === "=") {
|
49
|
+
return "'+_e(" + p3 + ")+'";
|
50
|
+
}
|
51
|
+
return "'+(" + p3 + "==null?'':" + p3 + ")+'";
|
52
|
+
}
|
53
|
+
if (p4) { // evaluation start tag: {%
|
54
|
+
return "';";
|
55
|
+
}
|
56
|
+
if (p5) { // evaluation end tag: %}
|
57
|
+
return "_s+='";
|
58
|
+
}
|
59
|
+
};
|
60
|
+
tmpl.encReg = /[<>&"'\x00]/g;
|
61
|
+
tmpl.encMap = {
|
62
|
+
"<" : "<",
|
63
|
+
">" : ">",
|
64
|
+
"&" : "&",
|
65
|
+
"\"" : """,
|
66
|
+
"'" : "'"
|
67
|
+
};
|
68
|
+
tmpl.encode = function (s) {
|
69
|
+
/*jshint eqnull:true */
|
70
|
+
return (s == null ? "" : "" + s).replace(
|
71
|
+
tmpl.encReg,
|
72
|
+
function (c) {
|
73
|
+
return tmpl.encMap[c] || "";
|
74
|
+
}
|
75
|
+
);
|
76
|
+
};
|
77
|
+
tmpl.arg = "o";
|
78
|
+
tmpl.helper = ",print=function(s,e){_s+=e?(s==null?'':s):_e(s);}" +
|
79
|
+
",include=function(s,d){_s+=tmpl(s,d);}";
|
80
|
+
if (typeof define === "function" && define.amd) {
|
81
|
+
define(function () {
|
82
|
+
return tmpl;
|
83
|
+
});
|
84
|
+
} else {
|
85
|
+
$.tmpl = tmpl;
|
86
|
+
}
|
87
|
+
}(this));
|
@@ -0,0 +1,71 @@
|
|
1
|
+
.table {
|
2
|
+
border-collapse: collapse !important;
|
3
|
+
}
|
4
|
+
|
5
|
+
.table td {
|
6
|
+
background-color: #fff !important;
|
7
|
+
}
|
8
|
+
|
9
|
+
.table-bordered {
|
10
|
+
border: 1px solid #ddd;
|
11
|
+
}
|
12
|
+
.table-bordered > thead > tr > th,
|
13
|
+
.table-bordered > tbody > tr > th,
|
14
|
+
.table-bordered > tfoot > tr > th,
|
15
|
+
.table-bordered > thead > tr > td,
|
16
|
+
.table-bordered > tbody > tr > td,
|
17
|
+
.table-bordered > tfoot > tr > td {
|
18
|
+
border: 1px solid #ddd;
|
19
|
+
}
|
20
|
+
.table-bordered > thead > tr > th,
|
21
|
+
.table-bordered > thead > tr > td {
|
22
|
+
border-bottom-width: 2px;
|
23
|
+
}
|
24
|
+
|
25
|
+
table {
|
26
|
+
background-color: transparent;
|
27
|
+
}
|
28
|
+
|
29
|
+
th {
|
30
|
+
background-color: #f0f0f0 !important;
|
31
|
+
text-align: left;
|
32
|
+
}
|
33
|
+
.table {
|
34
|
+
width: 100%;
|
35
|
+
max-width: 100%;
|
36
|
+
margin-bottom: 20px;
|
37
|
+
}
|
38
|
+
.table > thead > tr > th,
|
39
|
+
.table > tbody > tr > th,
|
40
|
+
.table > tfoot > tr > th,
|
41
|
+
.table > thead > tr > td,
|
42
|
+
.table > tbody > tr > td,
|
43
|
+
.table > tfoot > tr > td {
|
44
|
+
padding: 8px;
|
45
|
+
line-height: 1.42857143;
|
46
|
+
vertical-align: top;
|
47
|
+
border-top: 1px solid #ddd;
|
48
|
+
}
|
49
|
+
.table > thead > tr > th {
|
50
|
+
vertical-align: bottom;
|
51
|
+
border-bottom: 2px solid #ddd;
|
52
|
+
}
|
53
|
+
|
54
|
+
.table > tbody + tbody {
|
55
|
+
border-top: 2px solid #ddd;
|
56
|
+
}
|
57
|
+
.table .table {
|
58
|
+
background-color: #fff;
|
59
|
+
}
|
60
|
+
.logo {
|
61
|
+
width: auto;
|
62
|
+
height: 20px;
|
63
|
+
}
|
64
|
+
|
65
|
+
.spree-head {
|
66
|
+
padding: 20px 0px 20px 20px;
|
67
|
+
width: 100%;
|
68
|
+
max-width: 100%;
|
69
|
+
background: #162e40;
|
70
|
+
height: 50;
|
71
|
+
}
|
@@ -0,0 +1,132 @@
|
|
1
|
+
/*
|
2
|
+
Placeholder manifest file.
|
3
|
+
the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
|
4
|
+
*/
|
5
|
+
|
6
|
+
#report-container .filter-well {
|
7
|
+
margin: 5px 0px 10px 0px;
|
8
|
+
}
|
9
|
+
|
10
|
+
.select-box-slide {
|
11
|
+
margin-left: 3px;
|
12
|
+
}
|
13
|
+
|
14
|
+
#page-selector {
|
15
|
+
margin-right: 5px;
|
16
|
+
}
|
17
|
+
|
18
|
+
#table-helpers .col-md-2 {
|
19
|
+
padding-left: 3px;
|
20
|
+
}
|
21
|
+
|
22
|
+
.chart-title {
|
23
|
+
padding-right: 5px;
|
24
|
+
}
|
25
|
+
|
26
|
+
.sortable-arrow {
|
27
|
+
color: #2F85D5;
|
28
|
+
}
|
29
|
+
|
30
|
+
.loss-indicator {
|
31
|
+
color: red;
|
32
|
+
}
|
33
|
+
|
34
|
+
.profit-indicator {
|
35
|
+
color: green;
|
36
|
+
}
|
37
|
+
|
38
|
+
.hide {
|
39
|
+
display: none !important;
|
40
|
+
}
|
41
|
+
|
42
|
+
.full-width,
|
43
|
+
.date-range-filter input.datepicker.full-width {
|
44
|
+
width: 100% !important;
|
45
|
+
}
|
46
|
+
|
47
|
+
.dropdown-menu {
|
48
|
+
position: relative;
|
49
|
+
}
|
50
|
+
|
51
|
+
.sub-menu {
|
52
|
+
display: none;
|
53
|
+
background-color: #ffffff;
|
54
|
+
z-index: 9999;
|
55
|
+
padding: 10px;
|
56
|
+
position: absolute;
|
57
|
+
border: 1px solid #adadad;
|
58
|
+
border-radius: 5px;
|
59
|
+
left: 0px;
|
60
|
+
top: 40px;
|
61
|
+
min-width: 75px
|
62
|
+
}
|
63
|
+
|
64
|
+
.sub-menu li {
|
65
|
+
list-style: none;
|
66
|
+
}
|
67
|
+
|
68
|
+
.toggle-btn.open + ul {
|
69
|
+
display: block;
|
70
|
+
}
|
71
|
+
|
72
|
+
.btn-link {
|
73
|
+
background-color: #ffffff;
|
74
|
+
border: 1px solid #adadad;
|
75
|
+
}
|
76
|
+
|
77
|
+
.button.btn-link .fa {
|
78
|
+
color: #333;
|
79
|
+
}
|
80
|
+
|
81
|
+
.btn-link:hover {
|
82
|
+
background-color: #e6e6e6;
|
83
|
+
}
|
84
|
+
|
85
|
+
.page-select {
|
86
|
+
background-color: #ffffff;
|
87
|
+
border: 1px solid #adadad;
|
88
|
+
padding: 0px 6px 0px 6px;
|
89
|
+
color: #333;
|
90
|
+
height: 36px;
|
91
|
+
}
|
92
|
+
.move-right {
|
93
|
+
float: right !important;
|
94
|
+
}
|
95
|
+
|
96
|
+
.button-group {
|
97
|
+
margin-left: 5px;
|
98
|
+
}
|
99
|
+
|
100
|
+
.report-select {
|
101
|
+
padding: 5px 10px;
|
102
|
+
background-color: #5498da;
|
103
|
+
border-radius: 3px;
|
104
|
+
border: 0;
|
105
|
+
color: white;
|
106
|
+
height: 40px;
|
107
|
+
width: 100%;
|
108
|
+
}
|
109
|
+
|
110
|
+
.report-select:hover {
|
111
|
+
border: 0;
|
112
|
+
border-radius: 3px;
|
113
|
+
background-color: #9fc820;
|
114
|
+
color: white;
|
115
|
+
}
|
116
|
+
|
117
|
+
.report-select option {
|
118
|
+
background-color: white;
|
119
|
+
color: black;
|
120
|
+
}
|
121
|
+
|
122
|
+
.report-select option:nth-child(1) {
|
123
|
+
background-color: #f0f0f0;
|
124
|
+
}
|
125
|
+
|
126
|
+
.text-center {
|
127
|
+
text-align: center;
|
128
|
+
}
|
129
|
+
|
130
|
+
.tab-with-icon {
|
131
|
+
font-size: 12px;
|
132
|
+
}
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Spree
|
2
|
+
module Admin
|
3
|
+
class InsightsController < Spree::Admin::BaseController
|
4
|
+
before_action :ensure_report_exists, :set_default_pagination, only: [:show, :download]
|
5
|
+
before_action :set_reporting_period, only: [:index, :show, :download]
|
6
|
+
before_action :load_reports, only: [:index, :show]
|
7
|
+
|
8
|
+
def index
|
9
|
+
respond_to do |format|
|
10
|
+
format.html
|
11
|
+
format.json { render json: {} }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def show
|
16
|
+
report = ReportGenerationService.generate_report(@report_name, params.merge(@pagination_hash))
|
17
|
+
|
18
|
+
@report_data = shared_data.merge(report.to_h)
|
19
|
+
respond_to do |format|
|
20
|
+
format.html { render :index }
|
21
|
+
format.json { render json: @report_data }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def download
|
26
|
+
@report = ReportGenerationService.generate_report(@report_name, params.merge(@pagination_hash))
|
27
|
+
|
28
|
+
respond_to do |format|
|
29
|
+
format.csv do
|
30
|
+
send_data ReportGenerationService.download(@report),
|
31
|
+
filename: "#{ @report_name.to_s }.csv"
|
32
|
+
end
|
33
|
+
format.xls do
|
34
|
+
send_data ReportGenerationService.download(@report, { col_sep: "\t" }),
|
35
|
+
filename: "#{ @report_name.to_s }.xls"
|
36
|
+
end
|
37
|
+
format.text do
|
38
|
+
send_data ReportGenerationService.download(@report),
|
39
|
+
filename: "#{ @report_name.to_s }.txt"
|
40
|
+
end
|
41
|
+
format.pdf do
|
42
|
+
render pdf: "#{ @report_name.to_s }",
|
43
|
+
disposition: 'attachment',
|
44
|
+
layout: 'spree/layouts/pdf.html'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def ensure_report_exists
|
51
|
+
@report_name = params[:id].to_sym
|
52
|
+
unless ReportGenerationService.report_exists?(get_report_category, @report_name)
|
53
|
+
redirect_to admin_insights_path, alert: Spree.t(:not_found, scope: [:reports])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_reports
|
58
|
+
@reports = ReportGenerationService.reports_for_category(get_report_category)
|
59
|
+
end
|
60
|
+
|
61
|
+
def shared_data
|
62
|
+
{
|
63
|
+
current_page: params[:page] || 0,
|
64
|
+
report_category: params[:report_category],
|
65
|
+
request_path: request.path,
|
66
|
+
url: request.url,
|
67
|
+
searched_fields: params[:search],
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_report_category
|
72
|
+
params[:report_category] = if params[:report_category]
|
73
|
+
params[:report_category].to_sym
|
74
|
+
else
|
75
|
+
session[:report_category].try(:to_sym) || ReportGenerationService.default_report_category
|
76
|
+
end
|
77
|
+
session[:report_category] = params[:report_category]
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_reporting_period
|
81
|
+
if params[:search].present?
|
82
|
+
params[:search][:start_date] = params[:search][:start_date].presence || session[:search_start_date]
|
83
|
+
params[:search][:end_date] = params[:search][:end_date].presence || session[:search_end_date]
|
84
|
+
else
|
85
|
+
params[:search] = {}
|
86
|
+
params[:search][:start_date] = session[:search_start_date]
|
87
|
+
params[:search][:end_date] = session[:search_end_date]
|
88
|
+
end
|
89
|
+
session[:search_start_date] = params[:search][:start_date]
|
90
|
+
session[:search_end_date] = params[:search][:end_date]
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_default_pagination
|
94
|
+
@pagination_hash = { paginate: false }
|
95
|
+
unless params[:paginate] == 'false'
|
96
|
+
@pagination_hash[:paginate] = true
|
97
|
+
@pagination_hash[:records_per_page] = params[:per_page].try(:to_i) || Spree::Config[:records_per_page]
|
98
|
+
@pagination_hash[:offset] = params[:page].to_i * @pagination_hash[:records_per_page]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|