Add search branding option (#20902)
* Add search branding option * Change search test
This commit is contained in:
parent
7890944a9d
commit
1287c343b6
14 changed files with 37 additions and 17 deletions
3
app/assets/images/algolia.svg
Normal file
3
app/assets/images/algolia.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 500 500.34">
|
||||
<defs><style>.cls-1{fill:#003dff;}</style></defs><path class="cls-1" d="M250,0C113.38,0,2,110.16,.03,246.32c-2,138.29,110.19,252.87,248.49,253.67,42.71,.25,83.85-10.2,120.38-30.05,3.56-1.93,4.11-6.83,1.08-9.52l-23.39-20.74c-4.75-4.22-11.52-5.41-17.37-2.92-25.5,10.85-53.21,16.39-81.76,16.04-111.75-1.37-202.04-94.35-200.26-206.1,1.76-110.33,92.06-199.55,202.8-199.55h202.83V407.68l-115.08-102.25c-3.72-3.31-9.43-2.66-12.43,1.31-18.47,24.46-48.56,39.67-81.98,37.36-46.36-3.2-83.92-40.52-87.4-86.86-4.15-55.28,39.65-101.58,94.07-101.58,49.21,0,89.74,37.88,93.97,86.01,.38,4.28,2.31,8.28,5.53,11.13l29.97,26.57c3.4,3.01,8.8,1.17,9.63-3.3,2.16-11.55,2.92-23.6,2.07-35.95-4.83-70.39-61.84-127.01-132.26-131.35-80.73-4.98-148.23,58.18-150.37,137.35-2.09,77.15,61.12,143.66,138.28,145.36,32.21,.71,62.07-9.42,86.2-26.97l150.36,133.29c6.45,5.71,16.62,1.14,16.62-7.48V9.49C500,4.25,495.75,0,490.51,0H250Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1,009 B |
|
|
@ -110,7 +110,7 @@ export class Search extends Component {
|
|||
searchBox.select();
|
||||
};
|
||||
|
||||
render({ searchTerm }) {
|
||||
render({ searchTerm, branding }) {
|
||||
return (
|
||||
<Fragment>
|
||||
<KeyboardShortcuts
|
||||
|
|
@ -122,6 +122,7 @@ export class Search extends Component {
|
|||
<SearchForm
|
||||
searchTerm={searchTerm}
|
||||
onSubmitSearch={this.submit}
|
||||
branding={branding}
|
||||
ref={this.searchInputRef}
|
||||
/>
|
||||
</Fragment>
|
||||
|
|
@ -132,4 +133,5 @@ export class Search extends Component {
|
|||
Search.propTypes = {
|
||||
searchTerm: PropTypes.string.isRequired,
|
||||
setSearchTerm: PropTypes.func.isRequired,
|
||||
branding: PropTypes.string,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ import { forwardRef } from 'preact/compat';
|
|||
import { locale } from '../utilities/locale';
|
||||
import { ButtonNew as Button } from '@crayons';
|
||||
import SearchIcon from '@images/search.svg';
|
||||
import AlgoliaIcon from '@images/algolia.svg'
|
||||
|
||||
export const SearchForm = forwardRef(({ searchTerm, onSubmitSearch }, ref) => (
|
||||
export const SearchForm = forwardRef(({ searchTerm, onSubmitSearch, branding }, ref) => (
|
||||
<form
|
||||
action="/search"
|
||||
acceptCharset="UTF-8"
|
||||
|
|
@ -21,14 +22,14 @@ export const SearchForm = forwardRef(({ searchTerm, onSubmitSearch }, ref) => (
|
|||
className="crayons-header--search-input crayons-textfield"
|
||||
type="text"
|
||||
name="q"
|
||||
placeholder={`${locale('core.search')}...`}
|
||||
placeholder={`${locale(branding === 'algolia' ? 'core.algolia_search' : 'core.search')}...`}
|
||||
autoComplete="off"
|
||||
aria-label="Search term"
|
||||
value={searchTerm}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
icon={SearchIcon}
|
||||
icon={branding === 'algolia' ? AlgoliaIcon : SearchIcon}
|
||||
className="absolute inset-px left-auto mt-0 py-0"
|
||||
aria-label="Search"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -67,9 +67,11 @@ export function SearchFormSync() {
|
|||
};
|
||||
});
|
||||
|
||||
const branding = document.body.dataset.algoliaDisplay === 'true' ? 'algolia' : 'default';
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Search searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
|
||||
<Search searchTerm={searchTerm} setSearchTerm={setSearchTerm} branding={branding} />
|
||||
{mobileSearchContainer &&
|
||||
createPortal(
|
||||
<Search searchTerm={searchTerm} setSearchTerm={setSearchTerm} />,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ describe('<Search />', () => {
|
|||
const props = {
|
||||
searchTerm: 'fish',
|
||||
setSearchTerm: jest.fn(),
|
||||
branding: 'dark',
|
||||
};
|
||||
const { container } = render(<Search {...props} />);
|
||||
|
||||
|
|
@ -34,6 +35,7 @@ describe('<Search />', () => {
|
|||
const props = {
|
||||
searchTerm: 'fish',
|
||||
setSearchTerm: jest.fn(),
|
||||
branding: 'dark',
|
||||
};
|
||||
|
||||
const { getByRole } = render(<Search {...props} />);
|
||||
|
|
@ -49,6 +51,7 @@ describe('<Search />', () => {
|
|||
const props = {
|
||||
searchTerm: 'fish',
|
||||
setSearchTerm: jest.fn(),
|
||||
branding: 'dark',
|
||||
};
|
||||
const { getByRole, findByRole } = render(<Search {...props} />);
|
||||
|
||||
|
|
@ -67,6 +70,7 @@ describe('<Search />', () => {
|
|||
const props = {
|
||||
searchTerm: '',
|
||||
setSearchTerm: jest.fn(),
|
||||
branding: 'light',
|
||||
};
|
||||
const { getByRole } = render(<Search {...props} />);
|
||||
|
||||
|
|
@ -87,6 +91,7 @@ describe('<Search />', () => {
|
|||
searchTerm: '',
|
||||
setSearchTerm: jest.fn(),
|
||||
onSubmitSearch: jest.fn(),
|
||||
branding: 'minimal',
|
||||
};
|
||||
const { getByRole, findByRole } = render(<Search {...props} />);
|
||||
|
||||
|
|
@ -107,13 +112,12 @@ describe('<Search />', () => {
|
|||
});
|
||||
|
||||
it('should be listening for history state changes', async () => {
|
||||
// This is an implementation detail, but I want to make sure that this
|
||||
// listener is registered as it affects the UI.
|
||||
jest.spyOn(window, 'addEventListener');
|
||||
|
||||
const props = {
|
||||
searchTerm: '',
|
||||
setSearchTerm: jest.fn(),
|
||||
branding: 'default',
|
||||
};
|
||||
render(<Search {...props} />);
|
||||
|
||||
|
|
@ -125,13 +129,12 @@ describe('<Search />', () => {
|
|||
});
|
||||
|
||||
it('should stop listening for history state changes when the component is destroyed', async () => {
|
||||
// This is an implementation detail, but I want to make sure that this
|
||||
// listener is unregistered as it affects the UI.
|
||||
jest.spyOn(window, 'removeEventListener');
|
||||
|
||||
const props = {
|
||||
searchTerm: '',
|
||||
setSearchTerm: jest.fn(),
|
||||
branding: 'classic',
|
||||
};
|
||||
const { unmount } = render(<Search {...props} />);
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ function algoliaSearch(searchParams) {
|
|||
const {algoliaId, algoliaSearchKey} = document.body.dataset;
|
||||
console.log(paramsObj) /* eslint-disable-line */
|
||||
const client = algoliasearch(algoliaId, algoliaSearchKey);
|
||||
const indexName = paramsObj.sort_by ? `${paramsObj.class_name}_timestamp_${paramsObj.sort_direction}_${env}` : `${paramsObj.class_name}_${env}`;
|
||||
const indexName = paramsObj.sort_by ? `${paramsObj.class_name || 'Article'}_timestamp_${paramsObj.sort_direction}_${env}` : `${paramsObj.class_name || 'Article'}_${env}`;
|
||||
const index = client.initIndex(indexName); // Hardcoded to user for now
|
||||
console.log(index) /* eslint-disable-line */
|
||||
// This is where we will add the functionality to get search results directly from index with client:
|
||||
|
|
|
|||
|
|
@ -10,12 +10,15 @@ module AlgoliaSearchable
|
|||
{ name: user.name, username: user.username, profile_image: user.profile_image_90 }
|
||||
end
|
||||
|
||||
attribute :title, :tag_list, :reading_time, :score, :featured, :featured_number, :comments_count,
|
||||
:reaction_counts, :positive_reaction_counts, :path, :main_image
|
||||
attribute :title, :tag_list, :reading_time, :score, :featured, :comments_count,
|
||||
:positive_reactions_count, :path, :main_image
|
||||
|
||||
add_attribute(:published_at) { published_at.to_i }
|
||||
add_attribute(:timestamp) { published_at.to_i }
|
||||
|
||||
add_replica("Article_timestamp_desc", per_environment: true) { customRanking ["desc(timestamp)"] }
|
||||
add_replica("Article_timestamp_asc", per_environment: true) { customRanking ["asc(timestamp)"] }
|
||||
|
||||
attribute :published_at do
|
||||
published_at.to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ module Settings
|
|||
setting :algolia_application_id, type: :string, default: ApplicationConfig["ALGOLIA_APPLICATION_ID"]
|
||||
setting :algolia_api_key, type: :string, default: ApplicationConfig["ALGOLIA_API_KEY"]
|
||||
setting :algolia_search_only_api_key, type: :string, default: ApplicationConfig["ALGOLIA_SEARCH_ONLY_API_KEY"]
|
||||
setting :display_algolia_branding, type: :boolean, default: ApplicationConfig["ALGOLIA_DISPLAY_BRANDING"] == "true"
|
||||
|
||||
def self.algolia_search_enabled?
|
||||
algolia_application_id.present? && algolia_search_only_api_key.present? && algolia_api_key.present?
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@
|
|||
<form accept-charset="UTF-8" method="get" action="<%= search_path %>" role="search">
|
||||
<div class="crayons-fields crayons-fields--horizontal">
|
||||
<div class="crayons-field flex-1 relative">
|
||||
<input class="crayons-header--search-input crayons-textfield js-search-input" type="text" id="nav-search" name="q" placeholder="<%= t("views.search.placeholder") %>" autocomplete="off" />
|
||||
<input class="crayons-header--search-input crayons-textfield js-search-input" type="text" id="nav-search" name="q" placeholder="<%= t(Settings::General.display_algolia_branding ? "views.search.algolia_placeholder" : "views.search.placeholder") %>" autocomplete="off" />
|
||||
<button type="submit" aria-label="<%= t("views.search.icon.aria_label") %>" class="c-btn c-btn--icon-alone absolute inset-px left-auto mt-0 py-0">
|
||||
<%= crayons_icon_tag(:search, aria_hidden: true, title: t("views.search.icon.title")) %>
|
||||
<%= crayons_icon_tag(Settings::General.display_algolia_branding ? :algolia : :search, aria_hidden: true, title: t("views.search.icon.title")) %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
data-cookie-banner-platform-context="<%= j(Settings::General.coolie_banner_platform_context) %>"
|
||||
data-algolia-id="<%= j(Settings::General.algolia_application_id) %>"
|
||||
data-algolia-search-key="<%= j(Settings::General.algolia_search_only_api_key) %>"
|
||||
data-algolia-display="<%= j(Settings::General.display_algolia_branding) %>"
|
||||
data-ga4-tracking-id="<%= j(Settings::General.ga_analytics_4_id) %>">
|
||||
<%# Repeat of stylesheets in <head> to fix rendering glitch: https://github.com/forem/forem/issues/12377 %>
|
||||
<%= render "layouts/styles", qualifier: "secondary" %>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ en:
|
|||
reaction: Reaction
|
||||
report_abuse: Report abuse
|
||||
search: Search
|
||||
algolia_search: Search powered by Algolia
|
||||
success_settings: Successfully updated settings.
|
||||
counted_organization:
|
||||
one: "%{count} organization"
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ fr:
|
|||
reaction: Réaction
|
||||
report_abuse: Signaler un abus
|
||||
search: Recherche
|
||||
algolia_search: Recherche par Algolia
|
||||
success_settings: Successfully updated settings.
|
||||
counted_organization:
|
||||
one: "%{count} organisation"
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ en:
|
|||
heading: Search results%{for}
|
||||
for: " for %{query}"
|
||||
placeholder: Search...
|
||||
algolia_placeholder: Search powered by Algolia...
|
||||
icon:
|
||||
aria_label: Search
|
||||
title: Search
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ fr:
|
|||
heading: Search results%{for}
|
||||
for: " for %{query}"
|
||||
placeholder: Recherche...
|
||||
algolia_placeholder: Recherche par Algolia
|
||||
icon:
|
||||
aria_label: Search
|
||||
title: Search
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue