workarea-classic_search_autocomplete 1.0.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.
- checksums.yaml +7 -0
- data/.editorconfig +20 -0
- data/.eslintrc +35 -0
- data/.eslintrc.json +35 -0
- data/.github/workflows/ci.yml +60 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +2 -0
- data/.stylelintrc +8 -0
- data/.stylelintrc.json +8 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +17 -0
- data/LICENSE +52 -0
- data/README.md +45 -0
- data/Rakefile +60 -0
- data/app/assets/javascripts/jquery_ui/storefront/categorized_autocomplete.js +53 -0
- data/app/assets/javascripts/workarea/storefront/modules/search_fields.js +69 -0
- data/app/assets/javascripts/workarea/storefront/templates/ui_menu_heading.jst.ejs +1 -0
- data/app/assets/javascripts/workarea/storefront/templates/ui_menu_item.jst.ejs +8 -0
- data/app/assets/stylesheets/jquery_ui/storefront/_ui_autocomplete.scss +17 -0
- data/app/assets/stylesheets/jquery_ui/storefront/_ui_menu.scss +40 -0
- data/app/controllers/.keep +0 -0
- data/app/controllers/workarea/storefront/searches_controller.decorator +14 -0
- data/app/queries/workarea/search/search_suggestions.rb +45 -0
- data/app/view_models/workarea/storefront/search_suggestion_view_model.rb +85 -0
- data/app/views/workarea/storefront/searches/index.json.jbuilder +1 -0
- data/bin/rails +25 -0
- data/config/initializers/appends.rb +26 -0
- data/config/initializers/workarea.rb +2 -0
- data/config/routes.rb +5 -0
- data/lib/workarea/classic_search_autocomplete.rb +11 -0
- data/lib/workarea/classic_search_autocomplete/engine.rb +10 -0
- data/lib/workarea/classic_search_autocomplete/version.rb +5 -0
- data/package.json +9 -0
- data/script/admin_ci +9 -0
- data/script/ci +11 -0
- data/script/core_ci +9 -0
- data/script/plugins_ci +9 -0
- data/script/storefront_ci +9 -0
- data/test/dummy/.ruby-version +1 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +14 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +15 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +25 -0
- data/test/dummy/bin/update +25 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +34 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +52 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +45 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/test/dummy/config/initializers/assets.rb +12 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/content_security_policy.rb +25 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +34 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/db/seeds.rb +2 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/integration/workarea/storefront/search_autocomplete_integration_test.rb +43 -0
- data/test/queries/workarea/search/search_suggestions_test.rb +77 -0
- data/test/system/workarea/storefront/search_autocomplete_analytics_system_test.rb +46 -0
- data/test/teaspoon_env.rb +6 -0
- data/test/test_helper.rb +10 -0
- data/test/view_models/workarea/storefront/search_suggestion_view_model_test.rb +42 -0
- data/workarea-classic_search_autocomplete.gemspec +25 -0
- data/yarn.lock +3265 -0
- metadata +156 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
/**
|
2
|
+
* @namespace WORKAREA.searchFields
|
3
|
+
*/
|
4
|
+
WORKAREA.registerModule('searchFields', (function () {
|
5
|
+
'use strict';
|
6
|
+
|
7
|
+
var getSource = function (request, response) {
|
8
|
+
var endpoint = WORKAREA.routes.storefront.searchesPath();
|
9
|
+
|
10
|
+
$.getJSON(endpoint, { q: request.term }, function (data) {
|
11
|
+
response(data.results);
|
12
|
+
});
|
13
|
+
},
|
14
|
+
|
15
|
+
openSelected = function (event, ui) {
|
16
|
+
if (ui.item.type === "Products") {
|
17
|
+
WORKAREA.analytics.fireCallback(
|
18
|
+
'productClick',
|
19
|
+
ui.item.analytics
|
20
|
+
);
|
21
|
+
}
|
22
|
+
|
23
|
+
if (WORKAREA.analytics.domEventsDisabled()) { return; }
|
24
|
+
window.location = ui.item.url;
|
25
|
+
},
|
26
|
+
|
27
|
+
/**
|
28
|
+
* iOS touch devices treat touch events as mouseenter unless there is no
|
29
|
+
* change in the UI, like a menu-selected state. By unbinding the
|
30
|
+
* mouseenter event we force those devices to treat the touch event as a
|
31
|
+
* click. This prevents the user having to tap twice to open a search
|
32
|
+
* autocomplete result.
|
33
|
+
*/
|
34
|
+
openOnTouchDevices = function () {
|
35
|
+
$('.ui-autocomplete').off('mouseenter');
|
36
|
+
},
|
37
|
+
|
38
|
+
getConfig = function () {
|
39
|
+
var config = WORKAREA.config.searchFieldsAutocomplete || {
|
40
|
+
minLength: 2
|
41
|
+
};
|
42
|
+
|
43
|
+
return _.assign({}, config, {
|
44
|
+
source: getSource,
|
45
|
+
select: openSelected,
|
46
|
+
open: openOnTouchDevices
|
47
|
+
});
|
48
|
+
},
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Queries the DOM for either a `data-search-field` or
|
52
|
+
* `[id=storefront_search] attribute to hook onto, selecting the first
|
53
|
+
* that is found, before initializing the customized jQuery UI
|
54
|
+
* Autocomplete method `categorizedAutocomplete`.
|
55
|
+
*
|
56
|
+
* @method
|
57
|
+
* @name init
|
58
|
+
* @memberof WORKAREA.searchFields
|
59
|
+
*/
|
60
|
+
init = function ($scope) {
|
61
|
+
$('[data-search-field], #storefront_search', $scope)
|
62
|
+
.first()
|
63
|
+
.categorizedAutocomplete(getConfig());
|
64
|
+
};
|
65
|
+
|
66
|
+
return {
|
67
|
+
init: init
|
68
|
+
};
|
69
|
+
}()));
|
@@ -0,0 +1 @@
|
|
1
|
+
<li class="ui-menu-heading"><%= categoryName %></li>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/*------------------------------------*\
|
2
|
+
#UI-AUTOCOMPLETE
|
3
|
+
\*------------------------------------*/
|
4
|
+
|
5
|
+
$ui-autocomplete-bg-color: $white !default;
|
6
|
+
|
7
|
+
$ui-autocomplete-width: 190px !default;
|
8
|
+
|
9
|
+
|
10
|
+
.ui-autocomplete {
|
11
|
+
@extend %list-reset;
|
12
|
+
position: absolute;
|
13
|
+
z-index: index($components, ui-autocomplete);
|
14
|
+
padding: $spacing-unit;
|
15
|
+
width: $ui-autocomplete-width;
|
16
|
+
background: $ui-autocomplete-bg-color;
|
17
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/*------------------------------------*\
|
2
|
+
#UI-MENU
|
3
|
+
\*------------------------------------*/
|
4
|
+
|
5
|
+
$ui-menu-item-selected-color: $highlight-color !default;
|
6
|
+
|
7
|
+
|
8
|
+
/**
|
9
|
+
* 1. default menu item state
|
10
|
+
* 2. hovered menu item state
|
11
|
+
* 3. the displayed result image
|
12
|
+
* 4. menu headings
|
13
|
+
*/
|
14
|
+
|
15
|
+
.ui-menu {
|
16
|
+
.ui-menu-item { /* [1] */
|
17
|
+
@extend %clearfix;
|
18
|
+
padding: ($spacing-unit / 2) 0;
|
19
|
+
cursor: pointer;
|
20
|
+
|
21
|
+
&:hover { /* [2] */
|
22
|
+
background: $ui-menu-item-selected-color;
|
23
|
+
}
|
24
|
+
|
25
|
+
img { /* [3] */
|
26
|
+
margin: 0 ($spacing-unit / 2) 0 0;
|
27
|
+
float: left;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
.ui-menu-heading { /* [4] */
|
32
|
+
margin: ($spacing-unit / 2) 0;
|
33
|
+
padding: ($spacing-unit / 2) 0;
|
34
|
+
font-weight: bold;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
.ui-menu-item-wrapper {
|
39
|
+
display: block;
|
40
|
+
}
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Storefront::SearchesController, with: :classic_search_autocomplete do
|
3
|
+
def index
|
4
|
+
render nothing: true and return if search_query.blank?
|
5
|
+
autocomplete_params = params.permit(:q)
|
6
|
+
|
7
|
+
search = Search::SearchSuggestions.new(autocomplete_params)
|
8
|
+
|
9
|
+
@results = search.results.map do |result|
|
10
|
+
Storefront::SearchSuggestionViewModel.new(result).to_h
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Search
|
3
|
+
class SearchSuggestions
|
4
|
+
include Query
|
5
|
+
include ProductDisplayRules
|
6
|
+
|
7
|
+
document Search::Storefront
|
8
|
+
|
9
|
+
def results
|
10
|
+
response['hits']['hits']
|
11
|
+
end
|
12
|
+
|
13
|
+
def sanitized_string
|
14
|
+
@sanitized_query ||= QueryString.new(params[:q]).sanitized
|
15
|
+
end
|
16
|
+
|
17
|
+
def query
|
18
|
+
{
|
19
|
+
bool: {
|
20
|
+
must: [
|
21
|
+
{
|
22
|
+
match_phrase_prefix: {
|
23
|
+
'content.name': {
|
24
|
+
query: sanitized_string,
|
25
|
+
max_expansions: 10
|
26
|
+
}
|
27
|
+
}
|
28
|
+
},
|
29
|
+
active_for_segments_clause,
|
30
|
+
preview_current_release_clause
|
31
|
+
]
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def sort
|
37
|
+
{ type: :desc }
|
38
|
+
end
|
39
|
+
|
40
|
+
def size
|
41
|
+
Workarea.config.search_suggestions
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
class SearchSuggestionViewModel < ApplicationViewModel
|
4
|
+
include I18n::DefaultUrlOptions
|
5
|
+
include Storefront::Engine.routes.url_helpers
|
6
|
+
include Search::LoadProductResults
|
7
|
+
include AnalyticsHelper
|
8
|
+
|
9
|
+
def to_h
|
10
|
+
{
|
11
|
+
value: name,
|
12
|
+
type: type,
|
13
|
+
image: image,
|
14
|
+
url: url,
|
15
|
+
analytics: analytics
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def source
|
20
|
+
model['_source']
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
source['content']['name']
|
25
|
+
end
|
26
|
+
|
27
|
+
def type
|
28
|
+
t("workarea.storefront.searches.#{suggestion_type.pluralize}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def image
|
32
|
+
return if source['cache']['image'].blank?
|
33
|
+
|
34
|
+
image_url = URI.parse(source['cache']['image'])
|
35
|
+
|
36
|
+
if asset_host.present?
|
37
|
+
image_url.scheme = asset_host.scheme
|
38
|
+
image_url.host = asset_host.host
|
39
|
+
end
|
40
|
+
|
41
|
+
image_url.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
def asset_host
|
45
|
+
URI.parse(Rails.application.config.action_controller.asset_host)
|
46
|
+
rescue URI::InvalidURIError
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def suggestion_type
|
51
|
+
source['type']
|
52
|
+
end
|
53
|
+
|
54
|
+
def analytics
|
55
|
+
return unless suggestion_type == 'product'
|
56
|
+
|
57
|
+
product_analytics_data(product)
|
58
|
+
end
|
59
|
+
|
60
|
+
def product
|
61
|
+
@product ||=
|
62
|
+
begin
|
63
|
+
loaded = load_model_from(model)
|
64
|
+
|
65
|
+
Storefront::ProductViewModel.wrap(
|
66
|
+
loaded[:model],
|
67
|
+
loaded.slice(:inventory, :pricing)
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def url
|
73
|
+
if suggestion_type == 'product'
|
74
|
+
product_path(product)
|
75
|
+
elsif suggestion_type == 'search'
|
76
|
+
search_path(q: name)
|
77
|
+
elsif suggestion_type == 'category'
|
78
|
+
category_path(source['slug'])
|
79
|
+
elsif suggestion_type == 'page'
|
80
|
+
page_path(source['slug'])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
json.results @results
|
data/bin/rails
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails gems
|
3
|
+
# installed from the root of your application.
|
4
|
+
|
5
|
+
ENGINE_ROOT = File.expand_path('..', __dir__)
|
6
|
+
ENGINE_PATH = File.expand_path('../lib/workarea/classic_search_autocomplete/engine', __dir__)
|
7
|
+
APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
|
8
|
+
|
9
|
+
# Set up gems listed in the Gemfile.
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
11
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
12
|
+
|
13
|
+
require "rails"
|
14
|
+
# Pick the frameworks you want:
|
15
|
+
require "active_model/railtie"
|
16
|
+
require "active_job/railtie"
|
17
|
+
# require "active_record/railtie"
|
18
|
+
# require "active_storage/engine"
|
19
|
+
require "action_controller/railtie"
|
20
|
+
require "action_mailer/railtie"
|
21
|
+
require "action_view/railtie"
|
22
|
+
# require "action_cable/engine"
|
23
|
+
require "sprockets/railtie"
|
24
|
+
require "rails/test_unit/railtie"
|
25
|
+
require 'rails/engine/commands'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Workarea.append_javascripts(
|
2
|
+
'storefront.dependencies',
|
3
|
+
'jquery-ui/widgets/autocomplete'
|
4
|
+
)
|
5
|
+
|
6
|
+
Workarea.append_javascripts(
|
7
|
+
'storefront.templates',
|
8
|
+
'workarea/storefront/templates/ui_menu_heading',
|
9
|
+
'workarea/storefront/templates/ui_menu_item'
|
10
|
+
)
|
11
|
+
|
12
|
+
Workarea.append_javascripts(
|
13
|
+
'storefront.extensions',
|
14
|
+
'jquery_ui/storefront/categorized_autocomplete'
|
15
|
+
)
|
16
|
+
|
17
|
+
Workarea.append_javascripts(
|
18
|
+
'storefront.modules',
|
19
|
+
'workarea/storefront/modules/search_fields'
|
20
|
+
)
|
21
|
+
|
22
|
+
Workarea.append_stylesheets(
|
23
|
+
'storefront.dependencies',
|
24
|
+
'jquery_ui/storefront/ui_menu',
|
25
|
+
'jquery_ui/storefront/ui_autocomplete'
|
26
|
+
)
|
data/config/routes.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'workarea'
|
2
|
+
require 'workarea/storefront'
|
3
|
+
require 'workarea/admin'
|
4
|
+
|
5
|
+
require 'workarea/classic_search_autocomplete/engine'
|
6
|
+
require 'workarea/classic_search_autocomplete/version'
|
7
|
+
|
8
|
+
module Workarea
|
9
|
+
module ClassicSearchAutocomplete
|
10
|
+
end
|
11
|
+
end
|
data/package.json
ADDED
data/script/admin_ci
ADDED
data/script/ci
ADDED
data/script/core_ci
ADDED