Skip to content

Commit

Permalink
refactor: use native class for search-input
Browse files Browse the repository at this point in the history
  • Loading branch information
kennstenicht committed Aug 11, 2024
1 parent 0da9f43 commit 126835b
Show file tree
Hide file tree
Showing 8 changed files with 271 additions and 196 deletions.
3 changes: 2 additions & 1 deletion guidemaker-ember-template/babel.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
["babel-plugin-ember-template-compilation", {
"targetFormat": "hbs",
"transforms": []
}],
}],
"ember-concurrency/async-arrow-task-transform",
["module:decorator-transforms", { "runtime": { "import": "decorator-transforms/runtime" } }],
]
}
120 changes: 63 additions & 57 deletions guidemaker-ember-template/src/components/search-input.hbs
Original file line number Diff line number Diff line change
@@ -1,61 +1,67 @@
{{! template-lint-disable no-action }}
{{#if this.searchService.index}}
<input
id="search-input"
type="search"
value={{this.value}}
oninput={{perform this.search value="target.value"}}
placeholder="Search the guides"
autocomplete="off"
onfocus={{action "onfocus"}}
onblur={{action "onblur"}}
data-test-search-input
/>
<div class="search-input" ...attributes>
{{#if this.searchService.index}}
<input
id="search-input"
type="search"
value={{this.value}}
oninput={{perform this.search value="target.value"}}
placeholder="Search the guides"
autocomplete="off"
data-test-search-input
{{on "focus" this.onfocus}}
{{on "blur" (perform this.closeMenu)}}
/>

{{! Search results dropdown }}
<EmberTether
@target="#search-input"
@targetAttachment="bottom right"
@attachment="top right"
@constraints={{this._resultTetherConstraints}}
@class="ds-dropdown-results"
>
{{#if this.showDropdown}}
<div class="ds-suggestions ds-dropdown-menu">
<DropdownHeader>
Search Results
</DropdownHeader>

{{#each this.searchService.results as |result|}}
<SearchResult @result={{result}} />
{{else}}
<div class="algolia-docsearch-suggestion">
<div class="algolia-docsearch-suggestion--noresults">
<p>
No results found.
{{#if this.deprecationsGuideURL}}
Try searching the
<a href={{this.deprecationsGuideURL}} target="_deprecations">
deprecations guide
</a>.
{{/if}}
</p>
{{! Search results dropdown }}
<EmberTether
@target="#search-input"
@targetAttachment="bottom right"
@attachment="top right"
@constraints={{this._resultTetherConstraints}}
@class="ds-dropdown-results"
>
{{#if this.showDropdown}}
<div class="ds-suggestions ds-dropdown-menu" data-test-search-dropdown>
<DropdownHeader>
Search Results
</DropdownHeader>
{{#each this.searchService.results as |result|}}
<SearchResult @result={{result}} />
{{else}}
<div class="algolia-docsearch-suggestion">
<div
class="algolia-docsearch-suggestion--noresults"
data-test-search-noresults
>
<p>
No results found.
{{#if this.deprecationsGuideURL}}
Try searching the
<a
href={{this.deprecationsGuideURL}}
target="_deprecations"
>
deprecations guide
</a>.
{{/if}}
</p>
</div>
</div>
{{/each}}
<div class="powered-by-algolia">
<a
href="https://www.algolia.com/"
target="_blank"
rel="noopener noreferrer"
>
<img
src="/images/logos/search-by-algolia.svg"
alt="Search Powered by Algolia"
/>
</a>
</div>
{{/each}}
<div class="powered-by-algolia">
<a
href="https://www.algolia.com/"
target="_blank"
rel="noopener noreferrer"
>
<img
src="/images/logos/search-by-algolia.svg"
alt="Search Powered by Algolia"
/>
</a>
</div>
</div>
{{/if}}
</EmberTether>
{{/if}}
{{/if}}
</EmberTether>
{{/if}}
</div>
78 changes: 34 additions & 44 deletions guidemaker-ember-template/src/components/search-input.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,59 @@
/* eslint-disable ember/no-classic-components, ember/no-classic-classes, ember/require-tagless-components, prettier/prettier, ember/no-get, ember/no-actions-hash */
import { getOwner } from '@ember/application';
import Component from '@ember/component';
import { get, set } from '@ember/object';
import { and } from '@ember/object/computed';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { task, timeout } from 'ember-concurrency';
import config from 'ember-get-config';

const SEARCH_DEBOUNCE_PERIOD = 300;
const SEARCH_CLOSE_PERIOD = 200;

export default Component.extend({
export default class SearchInputComponent extends Component {
@service('search') searchService;

classNames: ['search-input'],

searchService: service('search'),

_resultTetherConstraints: Object.freeze([
_resultTetherConstraints = [
{
to: 'window',
pin: ['left','right']
}
]),

_focused: false,
pin: ['left', 'right'],
},
];

init() {
this._super(...arguments);
const config = getOwner(this).resolveRegistration('config:environment');
this.deprecationsGuideURL = config['deprecationsGuideURL'];
},
@tracked _focused = false;
@tracked query;
@tracked value = '';

showDropdown: and('query', '_focused'),
get deprecationsGuideURL() {
return config['deprecationsGuideURL'];
}

search: task(function * (query) {
get showDropdown() {
return this.query && this._focused;
}

yield timeout(SEARCH_DEBOUNCE_PERIOD);
search = task(async (query) => {
await timeout(SEARCH_DEBOUNCE_PERIOD);

set(this, 'query', query);
this.query = query;

// Hide and don't run query if there's no search query
if (!query) {
return set(this, '_focused', false);
return (this._focused = false);
}

// ensure search results are visible if the menu was previously closed above
set(this, '_focused', true);

yield get(this, 'searchService.search').perform(query, this.projectVersion);

}).restartable(),
this._focused = true;

closeMenu: task(function * () {
yield timeout(SEARCH_CLOSE_PERIOD);
await this.searchService.search.perform(query, this.args.projectVersion);
});

set(this, '_focused', false);
}),
closeMenu = task({ restartable: true }, async () => {
await timeout(SEARCH_CLOSE_PERIOD);

actions: {
onfocus() {
set(this, '_focused', true);
},

onblur() {
this.get('closeMenu').perform();
}
this._focused = false;
});

@action
onfocus() {
this._focused = true;
}
});
}
30 changes: 14 additions & 16 deletions guidemaker-ember-template/src/services/search.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
/* eslint-disable ember/no-classic-classes, prettier/prettier, ember/no-get */
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { task } from 'ember-concurrency';
import { get, set } from '@ember/object';
import { A as emberArray } from '@ember/array';
import algoliasearch from 'algoliasearch';
import { getOwner } from '@ember/application';

export default Service.extend({
export default class SearchServices extends Service {
@tracked results = [];
client = null;
index = null;

results: emberArray(),
constructor() {
super(...arguments);

init() {
this._super(...arguments);
const config = getOwner(this).resolveRegistration('config:environment');

const { algoliaId, algoliaKey, indexName } = config['algolia'] || {};

if (algoliaId && algoliaKey && indexName) {
this.client = algoliasearch(algoliaId, algoliaKey);
this.index = this.client.initIndex(indexName);
}
},
}

search: task(function * (query, projectVersion) {
search = task({ restartable: true }, async (query, projectVersion) => {
const searchObj = {
hitsPerPage: 15,
restrictSearchableAttributes: ['content'],
};

if(projectVersion && projectVersion.match(/\d+\.\d+\.\d+/)) {
if (projectVersion && projectVersion.match(/\d+\.\d+\.\d+/)) {
searchObj.facetFilters = [[`version:${projectVersion}`]];
}

return set(this, 'results', yield this.doSearch(query, searchObj));

}).restartable(),
return (this.results = await this.doSearch(query, searchObj));
});

doSearch(query, searchObj) {
return this.index.search(query, searchObj).then((results) => {
return get(results, 'hits');
return results.hits;
});
}
});
}
1 change: 1 addition & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"compilerOptions":{"target":"es6","experimentalDecorators":true},"exclude":["node_modules","bower_components","tmp","vendor",".git","dist"]}
Loading

0 comments on commit 126835b

Please sign in to comment.