Skip to content

Commit 963bbdf

Browse files
authored
Merge pull request #222 from ember-learn/69/update-search-indexer
Update search indexer
2 parents d666025 + 935af55 commit 963bbdf

File tree

18 files changed

+189
-127
lines changed

18 files changed

+189
-127
lines changed

addon/components/docs-header/search-box/component.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@ import Component from '@ember/component';
22
import layout from './template';
33
import { EKMixin, keyUp } from 'ember-keyboard';
44
import { on } from '@ember/object/evented';
5+
import { task } from 'ember-concurrency';
6+
import config from 'dummy/config/environment';
7+
import { inject as service } from '@ember/service';
8+
9+
const projectName = config['ember-cli-addon-docs'].projectName;
510

611
export default Component.extend(EKMixin, {
712
layout,
13+
store: service(),
14+
815
classNames: 'ad-ml-auto',
916

1017
query: null,
@@ -13,8 +20,18 @@ export default Component.extend(EKMixin, {
1320
this._super();
1421

1522
this.set('keyboardActivated', true);
23+
this.get('fetchProject').perform();
1624
},
1725

26+
// TODO: The searchbox doesn't work without the project being fetched.
27+
// We should move this logic (and everywhere else in the code that's fetching
28+
// the project) within a new addonDocs service that wires all that up together.
29+
// I think it's fine if our Docs-* components assume there is a single global
30+
// project.
31+
fetchProject: task(function*() {
32+
yield this.get('store').findRecord('project', projectName);
33+
}),
34+
1835
focusSearch: on(keyUp('Slash'), function() {
1936
this.element.querySelector('input').focus();
2037
}),

addon/components/docs-header/search-box/styles.scss

Lines changed: 0 additions & 71 deletions
This file was deleted.

addon/components/docs-header/search-box/template.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<input oninput={{action on-input value='target.value'}}
1111
value={{query}}
1212
type="text"
13+
disabled={{fetchProject.isRunning}}
1314
placeholder='Search'
1415
class='ad-w-24 ad-text-xs ad-p-2 ad-pl-6 ad-rounded focus:ad-bg-grey-lighter outline-none'
1516
data-search-box-input

addon/components/docs-header/search-result/component.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ export default Component.extend({
1414
let type = this.get('result.document.type');
1515
if (type === 'template') {
1616
args = [ this.get('result.document.route') ];
17-
} else if (type === 'class') {
18-
args = [ 'docs.api.class', this.get('result.document.class.id') ];
17+
18+
} else {
19+
args = [ 'docs.api.item', this.get('result.model.routingId') ];
1920
}
2021

2122
return args;
@@ -32,7 +33,7 @@ export default Component.extend({
3233
if (this.get('result.document.type') === 'template') {
3334
return 'guide';
3435
} else {
35-
return 'class';
36+
return 'api-item';
3637
}
3738
}),
3839

@@ -80,7 +81,7 @@ export default Component.extend({
8081
}),
8182

8283
_highlight(text, start, length) {
83-
return `${text.slice(0, start)}<em class='docs-viewer-search__result-item__text--emphasis'>${text.slice(start, start + length)}</em>${text.slice(start + length)}`;
84+
return `${text.slice(0, start)}<em class='ad-bg-yellow'>${text.slice(start, start + length)}</em>${text.slice(start + length)}`;
8485
},
8586

8687
'data-test-search-result': true,
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
{{#link-to
22
params=linkArgs
33
class=(concat
4-
"docs-viewer-search__result-item "
5-
(if selected "docs-viewer-search__result-item--selected")
4+
"ad-block ad-py-2 ad-px-3 ad-text-black ad-no-underline hover:ad-bg-grey-lighter "
5+
(if selected "ad-bg-grey-lighter")
66
)
77
}}
8-
<div class="docs-viewer-search__result-item__label">
9-
{{svg-jar icon height=28 width=28 class="docs-viewer-search__result-icon"}}
10-
{{result.document.title}}
8+
<div class="ad-flex ad-items-center">
9+
{{svg-jar icon height=28 width=28 class="ad-mr-2 ad-flex-no-shrink"}}
10+
<span class='ad-truncate'>
11+
{{result.document.title}}
12+
</span>
1113
</div>
12-
<small class='docs-viewer-search__result-item__text'>
14+
<small class='ad-text-grey-dark ad-inline-block'>
1315
{{{matches}}}
1416
</small>
1517
{{/link-to}}

addon/components/docs-header/search-results/component.js

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ import { EKMixin, keyUp, keyDown } from 'ember-keyboard';
55
import { on } from '@ember/object/evented';
66
import { computed } from '@ember/object';
77
import { task } from 'ember-concurrency';
8+
import config from 'dummy/config/environment';
9+
10+
const projectName = config['ember-cli-addon-docs'].projectName;
811

912
export default Component.extend(EKMixin, {
1013
layout,
1114

1215
docsSearch: service(),
1316
router: service(),
17+
store: service(),
1418

1519
query: null, // passed in
1620
selectedIndex: null,
@@ -30,6 +34,10 @@ export default Component.extend(EKMixin, {
3034
this.get('search').perform();
3135
},
3236

37+
project: computed(function() {
38+
return this.get('store').peekRecord('project', projectName);
39+
}),
40+
3341
trimmedQuery: computed('query', function() {
3442
return this.get('query').trim();
3543
}),
@@ -51,17 +59,44 @@ export default Component.extend(EKMixin, {
5159
let routerMicrolib = router._router._routerMicrolib || router._router.router;
5260

5361
if (rawSearchResults) {
54-
let filteredSearchResults = this.get('rawSearchResults')
62+
return this.get('rawSearchResults')
63+
// If the doc has a route, ensure it exists
5564
.filter(({ document }) => {
56-
let routeExists = routerMicrolib.recognizer.names[document.route];
57-
return routeExists && document.route !== 'not-found';
65+
if (document.route) {
66+
let routeExists = routerMicrolib.recognizer.names[document.route];
67+
68+
return routeExists && document.route !== 'not-found' && document.route !== 'application';
69+
} else {
70+
return true;
71+
}
5872
})
73+
74+
// Filter out the templates of the API items' pages, since we handle them separately
5975
.filter(({ document }) => {
60-
let isClassTemplate = (document.route === 'docs.api.class' && document.type === 'template');
61-
return !isClassTemplate;
62-
});
76+
let isApiItemTemplate = (document.route === 'docs.api.item' && document.type === 'template');
77+
return !isApiItemTemplate;
78+
})
79+
80+
// Filter out modules that are not in the navigationIndex
81+
.filter(({ document }) => {
82+
if (document.type === 'module') {
83+
let navigableModules = this.get('project.navigationIndex.modules').map(x => x.name);
84+
return navigableModules.includes(document.title);
85+
} else {
86+
return true;
87+
}
88+
})
89+
90+
// Add a reference to the Ember Data model to each API item search result
91+
.map(searchResult => {
92+
let { document } = searchResult;
93+
if (document.type !== 'template') {
94+
let store = this.get('store');
95+
searchResult.model = store.peekRecord(document.type, document.item.id)
96+
}
6397

64-
return filteredSearchResults;
98+
return searchResult;
99+
});
65100
}
66101
}),
67102

@@ -70,8 +105,8 @@ export default Component.extend(EKMixin, {
70105
let selectedResult = this.get('searchResults')[this.get('selectedIndex')];
71106
if (selectedResult.document.type === 'template') {
72107
this.get('router').transitionTo(selectedResult.document.route);
73-
} else if (selectedResult.document.type === 'class') {
74-
this.get('router').transitionTo('docs.api.class', selectedResult.document.class.id);
108+
} else {
109+
this.get('router').transitionTo('docs.api.item', selectedResult.model.get('routingId'));
75110
}
76111
}
77112

addon/components/docs-header/search-results/template.hbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
onClose=(action 'clearSearch')
77
targetAttachment='bottom left'
88
constraints=(array (hash to='window' attachment='together' pin=true))}}
9-
<ul class="docs-viewer-search__result-list" data-test-search-result-list>
9+
10+
<ul class="ad-w-76 ad-bg-white ad-shadow-md ad-list-reset" data-test-search-result-list>
1011
{{#each (take 5 searchResults) as |result index|}}
1112
<li>
1213
{{docs-header/search-result
@@ -17,10 +18,11 @@
1718
on-click=(action 'clearSearch')}}
1819
</li>
1920
{{else}}
20-
<li class='docs-viewer-search__result-item docs-viewer-search__result-item--disabled'>
21+
<li class='ad-block ad-py-1 ad-px-3 ad-text-grey-dark ad-no-underline'>
2122
No results.
2223
</li>
2324
{{/each}}
2425
</ul>
26+
2527
{{/modal-dialog}}
2628
{{/if}}

addon/models/component.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import DS from 'ember-data';
22
import { filterBy, or } from '@ember/object/computed';
3+
import { dasherize } from '@ember/string';
4+
import { computed } from '@ember/object';
35

46
import Class from './class';
57
import { memberUnion, hasMemberType } from '../utils/computed';
@@ -61,5 +63,17 @@ export default Class.extend({
6163
function(member) {
6264
return member.tags && member.tags.find(t => t.name === 'deprecated');
6365
}
64-
)
66+
),
67+
68+
/*
69+
This gives us a way to link to a model, since we don't always link by the actual ID:
70+
71+
{{link-to 'item' model.routingId}}
72+
73+
Possible refactoring is to always link by actual ID, and implement redirects.
74+
*/
75+
routingId: computed('name', function() {
76+
return `components/${dasherize(this.get('name'))}`;
77+
})
78+
6579
});

addon/models/module.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import DS from 'ember-data';
2+
import { computed } from '@ember/object';
23

34
const { attr, hasMany } = DS;
45

@@ -8,5 +9,17 @@ export default DS.Model.extend({
89
functions: attr(),
910

1011
classes: hasMany('class', { async: false, }),
11-
components: hasMany('class', { async: false, })
12+
components: hasMany('class', { async: false, }),
13+
14+
/*
15+
This gives us a way to link to a model, since we don't always link by the actual ID:
16+
17+
{{link-to 'item' model.routingId}}
18+
19+
Possible refactoring is to always link by actual ID, and implement redirects.
20+
*/
21+
routingId: computed('id', function() {
22+
return `modules/${this.get('id')}`;
23+
})
24+
1225
});

addon/tailwind/config/width.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export default {
3434
'32': '8rem',
3535
'48': '12rem',
3636
'64': '16rem',
37+
'76': '19rem',
3738
'1/2': '50%',
3839
'1/3': '33.33333%',
3940
'2/3': '66.66667%',

0 commit comments

Comments
 (0)