solidus_admin_insights 2.1.0

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +54 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +26 -0
  5. data/README.md +71 -0
  6. data/Rakefile +21 -0
  7. data/app/assets/javascripts/spree/backend/jquery.tablesorter.min.js +4 -0
  8. data/app/assets/javascripts/spree/backend/solidus_admin_insights.js +2 -0
  9. data/app/assets/javascripts/spree/backend/solidus_admin_insights/paginator.js +128 -0
  10. data/app/assets/javascripts/spree/backend/solidus_admin_insights/report_loader.js +265 -0
  11. data/app/assets/javascripts/spree/backend/solidus_admin_insights/searcher.js +72 -0
  12. data/app/assets/javascripts/spree/backend/solidus_admin_insights/table_sorter.js +47 -0
  13. data/app/assets/javascripts/spree/backend/tmpl.js +87 -0
  14. data/app/assets/javascripts/spree/frontend/solidus_admin_insights.js +2 -0
  15. data/app/assets/stylesheets/spree/backend/override_pdf.css +71 -0
  16. data/app/assets/stylesheets/spree/backend/solidus_admin_insights.css +132 -0
  17. data/app/assets/stylesheets/spree/frontend/solidus_admin_insights.css +4 -0
  18. data/app/controllers/spree/admin/insights_controller.rb +103 -0
  19. data/app/helpers/spree/admin/base_helper_decorator.rb +17 -0
  20. data/app/models/spree/app_configuration_decorator.rb +3 -0
  21. data/app/models/spree/product_decorator.rb +3 -0
  22. data/app/models/spree/promotion_action_decorator.rb +3 -0
  23. data/app/models/spree/return_authorization_decorator.rb +4 -0
  24. data/app/permissions/spree/permission_sets/insight_display.rb +9 -0
  25. data/app/reports/spree/best_selling_products_report.rb +42 -0
  26. data/app/reports/spree/cart_additions_report.rb +36 -0
  27. data/app/reports/spree/cart_removals_report.rb +36 -0
  28. data/app/reports/spree/cart_updations_report.rb +40 -0
  29. data/app/reports/spree/payment_method_transactions_conversion_rate_report.rb +74 -0
  30. data/app/reports/spree/payment_method_transactions_conversion_rate_report/payment_method_state_distribution_chart.rb +39 -0
  31. data/app/reports/spree/payment_method_transactions_report.rb +60 -0
  32. data/app/reports/spree/payment_method_transactions_report/payment_method_revenue_distribution_chart.rb +36 -0
  33. data/app/reports/spree/product_views_report.rb +46 -0
  34. data/app/reports/spree/product_views_to_cart_additions_report.rb +53 -0
  35. data/app/reports/spree/product_views_to_purchases_report.rb +54 -0
  36. data/app/reports/spree/promotional_cost_report.rb +84 -0
  37. data/app/reports/spree/promotional_cost_report/promotional_cost_chart.rb +37 -0
  38. data/app/reports/spree/promotional_cost_report/usage_count_chart.rb +41 -0
  39. data/app/reports/spree/report.rb +131 -0
  40. data/app/reports/spree/report/chart.rb +11 -0
  41. data/app/reports/spree/report/configuration.rb +40 -0
  42. data/app/reports/spree/report/date_slicer.rb +61 -0
  43. data/app/reports/spree/report/observation.rb +49 -0
  44. data/app/reports/spree/report/query_fragments.rb +45 -0
  45. data/app/reports/spree/report/query_time_scale.rb +19 -0
  46. data/app/reports/spree/report/result.rb +100 -0
  47. data/app/reports/spree/report/timed_observation.rb +47 -0
  48. data/app/reports/spree/report/timed_result.rb +48 -0
  49. data/app/reports/spree/returned_products_report.rb +37 -0
  50. data/app/reports/spree/sales_performance_report.rb +107 -0
  51. data/app/reports/spree/sales_performance_report/profit_loss_chart.rb +37 -0
  52. data/app/reports/spree/sales_performance_report/profit_loss_percent_chart.rb +36 -0
  53. data/app/reports/spree/sales_performance_report/sale_cost_price_chart.rb +48 -0
  54. data/app/reports/spree/sales_tax_report.rb +64 -0
  55. data/app/reports/spree/sales_tax_report/monthly_sales_tax_comparison_chart.rb +39 -0
  56. data/app/reports/spree/shipping_cost_report.rb +89 -0
  57. data/app/reports/spree/shipping_cost_report/shipping_cost_distribution_chart.rb +38 -0
  58. data/app/reports/spree/trending_search_report.rb +50 -0
  59. data/app/reports/spree/trending_search_report/frequency_distribution_pie_chart.rb +41 -0
  60. data/app/reports/spree/unique_purchases_report.rb +39 -0
  61. data/app/reports/spree/user_pool_report.rb +66 -0
  62. data/app/reports/spree/user_pool_report/distribution_column_chart.rb +65 -0
  63. data/app/reports/spree/users_not_converted_report.rb +48 -0
  64. data/app/reports/spree/users_who_recently_purchased_report.rb +69 -0
  65. data/app/services/spree/report_generation_service.rb +27 -0
  66. data/app/views/spree/admin/insights/_chart.html.erb +4 -0
  67. data/app/views/spree/admin/insights/download.pdf.erb +27 -0
  68. data/app/views/spree/admin/insights/index.html.erb +82 -0
  69. data/app/views/spree/admin/insights/search/_product_views_search.html.erb +13 -0
  70. data/app/views/spree/admin/insights/search/_search_form.html.erb +39 -0
  71. data/app/views/spree/admin/insights/search/_trending_searches_search.html.erb +13 -0
  72. data/app/views/spree/admin/insights/search/_users_not_converted_search.html.erb +13 -0
  73. data/app/views/spree/admin/insights/search/_users_who_have_not_purchased_recently_search.html.erb +13 -0
  74. data/app/views/spree/admin/insights/search/_users_who_recently_purchased_search.html.erb +13 -0
  75. data/app/views/spree/admin/shared/_insights_side_menu.html.erb +5 -0
  76. data/app/views/spree/admin/shared/sub_menu/_insight.html.erb +7 -0
  77. data/app/views/spree/admin/templates/insights/_paginator.template +11 -0
  78. data/app/views/spree/admin/templates/insights/_search.template +76 -0
  79. data/app/views/spree/admin/templates/insights/_show.template +49 -0
  80. data/app/views/spree/layouts/pdf.html.erb +9 -0
  81. data/bin/rails +7 -0
  82. data/config/initializers/add_to_sidebar.rb +14 -0
  83. data/config/initializers/assets.rb +1 -0
  84. data/config/initializers/mime_types.rb +2 -0
  85. data/config/initializers/wicked_pdf.rb +21 -0
  86. data/config/locales/en.yml +167 -0
  87. data/config/routes.rb +6 -0
  88. data/lib/generators/solidus_admin_insights/install/install_generator.rb +36 -0
  89. data/lib/generators/solidus_admin_insights/install/solidus_admin_insights.rb +22 -0
  90. data/lib/solidus_admin_insights.rb +14 -0
  91. data/lib/solidus_admin_insights/engine.rb +27 -0
  92. data/lib/solidus_admin_insights/factories.rb +6 -0
  93. data/solidus_admin_insights.gemspec +42 -0
  94. data/spec/spec_helper.rb +93 -0
  95. metadata +419 -0
@@ -0,0 +1,39 @@
1
+ module Spree
2
+ class UniquePurchasesReport < Spree::Report
3
+ DEFAULT_SORTABLE_ATTRIBUTE = :product_name
4
+ HEADERS = { sku: :string, product_name: :string, sold_count: :integer, users: :integer }
5
+ SEARCH_ATTRIBUTES = { start_date: :orders_completed_from, end_date: :orders_completed_till }
6
+ SORTABLE_ATTRIBUTES = [:product_name, :sku, :sold_count, :users]
7
+
8
+ deeplink product_name: { template: %Q{<a href="/admin/products/{%# o.product_slug %}" target="_blank">{%# o.product_name %}</a>} }
9
+
10
+ class Result < Spree::Report::Result
11
+ class Observation < Spree::Report::Observation
12
+ observation_fields [:product_name, :product_slug, :sku, :sold_count, :users]
13
+
14
+ def sku
15
+ @sku.presence || @product_name
16
+ end
17
+ end
18
+ end
19
+
20
+ def report_query
21
+ user_count_sql = '(COUNT(DISTINCT(spree_orders.user_id)) + COUNT(spree_orders.id) - COUNT(spree_orders.user_id))'
22
+ purchases_by_variant =
23
+ Spree::LineItem
24
+ .joins(:order)
25
+ .joins(:variant)
26
+ .joins(:product)
27
+ .where(spree_orders: { state: 'complete', completed_at: reporting_period })
28
+ .group('variant_id', 'spree_variants.sku', 'spree_products.slug', 'spree_products.name')
29
+ .select(
30
+ 'spree_variants.sku as sku',
31
+ 'spree_products.slug as product_slug',
32
+ 'spree_products.name as product_name',
33
+ 'SUM(quantity) as sold_count',
34
+ "#{ user_count_sql } as users"
35
+ )
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,66 @@
1
+ module Spree
2
+ class UserPoolReport < Spree::Report
3
+ HEADERS = { guest_users: :integer, active_users: :integer, new_sign_ups: :integer }
4
+ SEARCH_ATTRIBUTES = { start_date: :users_created_from, end_date: :users_created_till }
5
+ SORTABLE_ATTRIBUTES = []
6
+
7
+ class Result < Spree::Report::TimedResult
8
+ charts DistributionColumnChart
9
+
10
+ class Observation < Spree::Report::TimedObservation
11
+ observation_fields active_users: 0, guest_users: 0, new_sign_ups: 0
12
+ end
13
+ end
14
+
15
+ def report_query
16
+ Report::QueryFragments
17
+ .from_union(grouped_sign_ups, grouped_visitors)
18
+ .group(*time_scale_columns)
19
+ .order(*time_scale_columns_to_s)
20
+ .project(
21
+ *time_scale_columns,
22
+ 'SUM(active_users) as active_users',
23
+ 'SUM(guest_users) as guest_users',
24
+ 'SUM(new_sign_ups) as new_sign_ups'
25
+ )
26
+ end
27
+
28
+ private def grouped_sign_ups
29
+ sign_ups = Spree::User.where(created_at: reporting_period).select(:id, *time_scale_selects)
30
+
31
+ Report::QueryFragments.from_subquery(sign_ups)
32
+ .group(*time_scale_columns, 'guest_users', 'active_users')
33
+ .order(*time_scale_columns_to_s)
34
+ .project(
35
+ *time_scale_columns,
36
+ '0 as guest_users',
37
+ '0 as active_users',
38
+ 'COUNT(id) as new_sign_ups'
39
+ )
40
+ end
41
+
42
+ private def grouped_visitors
43
+ guest_count_sql = '(COUNT(DISTINCT(session)) - COUNT(DISTINCT(user)))'
44
+ Report::QueryFragments.from_subquery(visitors)
45
+ .group(*time_scale_columns, 'new_sign_ups')
46
+ .order(*time_scale_columns_to_s)
47
+ .project(
48
+ *time_scale_columns,
49
+ "#{ guest_count_sql } as guest_users",
50
+ 'COUNT(DISTINCT(user)) as active_users',
51
+ '0 as new_sign_ups'
52
+ )
53
+ end
54
+
55
+ private def visitors
56
+ Spree::PageEvent
57
+ .where(created_at: reporting_period)
58
+ .select(
59
+ *time_scale_selects,
60
+ 'actor_id as user',
61
+ 'session_id as session'
62
+ )
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,65 @@
1
+ class Spree::UserPoolReport::DistributionColumnChart
2
+ def initialize(result)
3
+ @chart_data = {
4
+ active_users: [],
5
+ guest_users: [],
6
+ new_sign_ups: []
7
+ }
8
+ @time_dimension = result.time_dimension
9
+ @chart_data[@time_dimension] = []
10
+ @result = result
11
+ process_chart_data
12
+ end
13
+
14
+ def process_chart_data
15
+ chart_keys = @chart_data.keys
16
+ @result.observations.each do |observation|
17
+ chart_keys.each do |key|
18
+ @chart_data[key] << observation.public_send(key)
19
+ end
20
+ end
21
+ end
22
+
23
+ def to_h
24
+ {
25
+ id: 'user-pool',
26
+ json: {
27
+ chart: { type: 'column' },
28
+ title: {
29
+ useHTML: true,
30
+ text: %Q(
31
+ <span class="chart-title">User Pool</span>
32
+ <span class="fa fa-question-circle"
33
+ data-toggle="tooltip"
34
+ title=" Keep a track of different type of users such as guest users, registered users and newly signed up users">
35
+ </span>
36
+ )
37
+ },
38
+ xAxis: { categories: @chart_data[@time_dimension] },
39
+ yAxis: {
40
+ title: { text: 'Count' }
41
+ },
42
+ legend: {
43
+ layout: 'vertical',
44
+ align: 'right',
45
+ verticalAlign: 'middle',
46
+ borderWidth: 0
47
+ },
48
+ series: [
49
+ {
50
+ name: Spree.t('user_pool.new_sign_ups'),
51
+ data: @chart_data[:new_sign_ups].map(&:to_i)
52
+ },
53
+ {
54
+ name: Spree.t('user_pool.active_users'),
55
+ data: @chart_data[:active_users].map(&:to_i)
56
+ },
57
+ {
58
+ name: Spree.t('user_pool.guest_users'),
59
+ data: @chart_data[:guest_users].map(&:to_i)
60
+ }
61
+ ]
62
+ }
63
+ }
64
+ end
65
+ end
@@ -0,0 +1,48 @@
1
+ module Spree
2
+ class UsersNotConvertedReport < Spree::Report
3
+ DEFAULT_SORTABLE_ATTRIBUTE = :user_email
4
+ HEADERS = { user_email: :string, signup_date: :date }
5
+ SEARCH_ATTRIBUTES = { start_date: :users_created_from, end_date: :users_created_till, email_cont: :email }
6
+ SORTABLE_ATTRIBUTES = [:user_email, :signup_date]
7
+
8
+ def paginated?
9
+ true
10
+ end
11
+
12
+ class Result < Spree::Report::Result
13
+ class Observation < Spree::Report::Observation
14
+ observation_fields [:user_email, :signup_date]
15
+
16
+ def signup_date
17
+ @signup_date.to_date.strftime("%B %d, %Y")
18
+ end
19
+ end
20
+ end
21
+
22
+ def paginated_report_query
23
+ report_query
24
+ .limit(records_per_page)
25
+ .offset(current_page)
26
+ end
27
+
28
+ def record_count_query
29
+ Spree::Report::QueryFragments.from_subquery(report_query).project(Arel.star.count)
30
+ end
31
+
32
+ def report_query
33
+ Spree::User
34
+ .where(created_at: reporting_period)
35
+ .where(Spree::User.arel_table[:email].matches(email_search))
36
+ .left_joins(:spree_orders)
37
+ .where(spree_orders: { completed_at: nil, number: nil })
38
+ .select(
39
+ "spree_users.email as user_email",
40
+ "spree_users.created_at as signup_date")
41
+ end
42
+
43
+ private def email_search
44
+ search[:email_cont].present? ? "%#{ search[:email_cont] }%" : '%'
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,69 @@
1
+ module Spree
2
+ class UsersWhoRecentlyPurchasedReport < Spree::Report
3
+ DEFAULT_SORTABLE_ATTRIBUTE = :user_email
4
+ HEADERS = { user_email: :string, purchase_count: :integer, last_purchase_date: :date, last_purchased_order_number: :string }
5
+ SEARCH_ATTRIBUTES = { start_date: :start_date, end_date: :end_date, email_cont: :email }
6
+ SORTABLE_ATTRIBUTES = [:user_email, :purchase_count, :last_purchase_date]
7
+
8
+ def paginated?
9
+ true
10
+ end
11
+
12
+ class Result < Spree::Report::Result
13
+ class Observation < Spree::Report::Observation
14
+ observation_fields [:user_email, :last_purchased_order_number, :last_purchase_date, :purchase_count]
15
+
16
+ def last_purchase_date
17
+ @last_purchase_date.to_date.strftime("%B %d, %Y")
18
+ end
19
+ end
20
+ end
21
+
22
+ def record_count_query
23
+ Spree::Report::QueryFragments.from_subquery(report_query).project(Arel.star.count)
24
+ end
25
+
26
+ def report_query
27
+ Spree::Report::QueryFragments
28
+ .from_subquery(all_orders_with_users)
29
+ .project(
30
+ "user_email",
31
+ "last_purchased_order_number",
32
+ "last_purchase_date",
33
+ "COUNT(user_email) as purchase_count")
34
+ .group(
35
+ "user_email",
36
+ "last_purchased_order_number",
37
+ "last_purchase_date"
38
+ )
39
+ end
40
+
41
+
42
+ def paginated_report_query
43
+ report_query
44
+ .take(records_per_page)
45
+ .skip(current_page)
46
+ end
47
+
48
+ private def all_orders_with_users
49
+ Spree::User
50
+ .where(Spree::User.arel_table[:email].matches(email_search))
51
+ .left_joins(:spree_orders)
52
+ .where(spree_orders: { completed_at: reporting_period })
53
+ .order("spree_orders.completed_at desc")
54
+ .select(
55
+ "spree_users.email as user_email",
56
+ "spree_orders.number as last_purchased_order_number",
57
+ "spree_orders.completed_at as last_purchase_date"
58
+ ).group(
59
+ 'user_email',
60
+ "spree_orders.number",
61
+ "spree_orders.completed_at"
62
+ )
63
+ end
64
+
65
+ private def email_search
66
+ search[:email_cont].present? ? "%#{ search[:email_cont] }%" : '%'
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,27 @@
1
+ module Spree
2
+ class ReportGenerationService
3
+
4
+ class << self
5
+ delegate :reports, :report_exists?, :reports_for_category, :default_report_category, to: :configuration
6
+ delegate :configuration, to: SolidusAdminInsights::Config
7
+ end
8
+
9
+ def self.generate_report(report_name, options)
10
+ klass = Spree.const_get((report_name.to_s + '_report').classify)
11
+ resource = klass.new(options)
12
+ dataset = resource.generate
13
+ end
14
+
15
+ def self.download(report, options = {})
16
+ headers = report.headers
17
+ stats = report.observations
18
+ ::CSV.generate(options) do |csv|
19
+ csv << headers.map { |head| head[:name] }
20
+ stats.each do |record|
21
+ csv << headers.map { |head| record.public_send(head[:value]) }
22
+ end
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,4 @@
1
+ <script src="https://code.highcharts.com/highcharts.js"></script>
2
+ <script src="https://code.highcharts.com/modules/exporting.js"></script>
3
+
4
+ <div id="chart-container" style="margin: 0 auto" class='hidden'></div>
@@ -0,0 +1,27 @@
1
+ <div class='spree-head'>
2
+ <figure>
3
+ <%= pdf_logo %>
4
+ </figure>
5
+ </div>
6
+ <h3 id="report-head">
7
+ <%= Spree.t(@report_name) %>
8
+ </h3>
9
+
10
+ <table class="table table-bordered" id="admin-insight" data-hook>
11
+ <thead>
12
+ <tr>
13
+ <% @report.headers.each do |_header_| %>
14
+ <th><%= Spree.t(_header_[:value], scope: [:insight, @report_name], default: _header_[:name]) %></th>
15
+ <% end %>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <% @report.observations.each do |stat| %>
20
+ <tr>
21
+ <% @report.headers.each do |head|%>
22
+ <td><%= stat.public_send(head[:value]) %></td>
23
+ <% end %>
24
+ </tr>
25
+ <% end %>
26
+ </tbody>
27
+ </table>
@@ -0,0 +1,82 @@
1
+ <%= render :partial => 'spree/admin/shared/sub_menu/insight' %>
2
+ <% content_for :page_title do %>
3
+ <%= Spree.t(:heading, type: params[:type].to_s.titleize, scope: :insight) %>
4
+ <% end %>
5
+
6
+ <% content_for :title do %>
7
+ <%= Spree.t(:heading, type: params[:type].to_s.titleize, scope: :insight) %>
8
+ <% end %>
9
+
10
+ <div id='insights-div' class='container-fluid' data-hook="admin-insights">
11
+ <div class="row">
12
+ <%= select_tag :reports, options_for_select(@reports.map { |report_name| [ Spree.t(:title, scope: [:insight, report_name]), report_name, data: { url: admin_insight_url(report_name, report_category: params[:report_category]) }] }.unshift(['Select a report', '', data: { url: admin_insights_url(report_category: params[:report_category]) }, disabled: true]), @report_name || ''), class: 'report-select' %>
13
+ </div>
14
+ </div>
15
+ <%= content_tag :div, class: 'hidden report-data', data: { report_data: @report_data_json } {} %>
16
+
17
+ <div id='report-container'>
18
+ <div id='search-div' class='hide'>
19
+ <div class="filter-wrap row">
20
+ <div class="col-sm-12">
21
+ <div id="table-filter" data-hook class="well filter-well">
22
+ </div>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="table-active-filters js-filters"></div>
27
+ </div>
28
+
29
+ <%= render 'chart' %>
30
+
31
+ <div id="table-helpers" class="row move-right hide">
32
+ <span id="page-selector">
33
+ <span class="select-box-slide move-right button-group">
34
+ <%= select_tag :per_page, options_for_select(page_selector_options, params[:per_page] || Spree::Config[:records_per_page]), class: 'form-control text-right move-right page-select' %>
35
+ </span>
36
+ <span title="apply pagination" class="button-group hide move-right">
37
+ <%= link_to '#', class: 'button btn-link', id: 'apply-pagination' do %>
38
+ <span class="fa fa-eye"></span>
39
+ <% end %>
40
+ </span>
41
+ <span title="remove pagination" class="button-group move-right">
42
+ <%= link_to '#', class: 'button btn-link', id: 'remove-pagination' do %>
43
+ <span class="fa fa-eye-slash"></span>
44
+ <% end %>
45
+ </span>
46
+ </span>
47
+ <span id='page-helpers'>
48
+ <span title="reset" class="button-group move-right">
49
+ <%= link_to '#', class: 'button btn-link', id: 'reset' do %>
50
+ <span class="fa fa-undo"></span>
51
+ <% end %>
52
+ </span>
53
+ <span title="refresh" class="button-group move-right">
54
+ <%= link_to '#', class: 'button btn-link', id: 'refresh' do %>
55
+ <span class="fa fa-refresh"></span>
56
+ <% end %>
57
+ </span>
58
+ <span title="download" class="dropdown move-right button-group">
59
+ <%= link_to "javascript:void(0)", class: "toggle-btn button btn-link", data: { toggle: 'dropdown' } do %>
60
+ <span class="fa fa-download"></span>
61
+ <% end %>
62
+ <ul class="sub-menu">
63
+ <li class="dropdown-item"><%= link_to 'CSV', admin_insights_download_path(format: 'csv'), class: 'download-link', data: { url: admin_insights_download_path(format: 'csv') } %></li>
64
+ <li class="dropdown-item"><%= link_to 'Excel', admin_insights_download_path(format: 'xls'), class: 'download-link', data: { url: admin_insights_download_path(format: 'xls') }%></li>
65
+ <li class="dropdown-item"><%= link_to 'Text', admin_insights_download_path(format: 'text'), class: 'download-link', data: { url: admin_insights_download_path(format: 'text') }%></li>
66
+ <li class="dropdown-item"><%= link_to 'PDF', admin_insights_download_path(format: 'pdf'), class: 'download-link', data: { url: admin_insights_download_path(format: 'pdf') }%></li>
67
+ </ul>
68
+ </span>
69
+ </div>
70
+ </div>
71
+
72
+ <input id="narrow-down-report-data" name="narrow-down-report-data" type="text" value="" class="form-control input-lg" placeholder="Start typing to filter data"/>
73
+ <div id='report-div'>
74
+ </div>
75
+
76
+ <div id='paginator-div'>
77
+ </div>
78
+ </div>
79
+
80
+ <%= render partial: 'spree/admin/templates/insights/show', formats: [:template] %>
81
+ <%= render partial: 'spree/admin/templates/insights/paginator', formats: [:template] %>
82
+ <%= render partial: 'spree/admin/templates/insights/search', formats: [:template] %>
@@ -0,0 +1,13 @@
1
+ <% content_for :quick_search_form do %>
2
+ <div class="row">
3
+ <div class="col col-md-6">
4
+ <div data-hook="admin_property_index_search" class="form-group">
5
+ <%= label_tag :search_name, Spree.t(:name) %>
6
+ <%= text_field_tag 'search[name]', params.fetch(:search, {})[:name], class: "form-control js-quick-search-target js-filterable" %>
7
+ </div>
8
+ </div>
9
+
10
+ <div class="col-md-6">
11
+ </div>
12
+ </div>
13
+ <% end %>