Skip to content

Commit

Permalink
frontend: change logic of when doc links are shown in search results
Browse files Browse the repository at this point in the history
The crate version page uses a fallback to handle crates that don't
define `documentation` keys in their manifests: if docs.rs has
documentation for that crate version, that those docs are used.

The search results do not implement the same logic, so crates that don't
have `documentation` keys don't get the handy documentation link in the
crate row.

This copies the logic from the version model into the crate model, using
the default crate version as the version to look for on docs.rs.

I strongly suspect there is a better way to do this than copying a bunch
of code, and would welcome suggestions from those more familiar with
Ember.

This would eventually fix rust-lang#1484.
  • Loading branch information
LawnGnome committed Sep 19, 2024
1 parent 2baaf0b commit cc0a011
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
6 changes: 3 additions & 3 deletions app/components/crate-row.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@
{{#if @crate.homepage}}
<li><a href="{{@crate.homepage}}">Homepage</a></li>
{{/if}}
{{#if @crate.documentation}}
<li><a href="{{@crate.documentation}}">Documentation</a></li>
{{#if @crate.documentationLink}}
<li><a href="{{@crate.documentationLink}}">Documentation</a></li>
{{/if}}
{{#if @crate.repository}}
<li><a href="{{@crate.repository}}">Repository</a></li>
{{/if}}
</ul>

</div>
</div>
21 changes: 19 additions & 2 deletions app/controllers/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';

import { restartableTask } from 'ember-concurrency';
import { all, restartableTask } from 'ember-concurrency';
import { bool, reads } from 'macro-decorators';

import { AjaxError } from '../utils/ajax';
import { pagination } from '../utils/pagination';
import { CATEGORY_PREFIX, processSearchQuery } from '../utils/search';

Expand Down Expand Up @@ -73,6 +74,22 @@ export default class SearchController extends Controller {
? { page, per_page, sort, q: query, all_keywords }
: { page, per_page, sort, ...processSearchQuery(query) };

return await this.store.query('crate', searchOptions);
const crates = await this.store.query('crate', searchOptions);

// Prime the docs for the most recent versions of each crate.
const docTasks = [];
for (const crate of crates) {
docTasks.push(crate.loadDocsStatusTask.perform());
}
try {
await all(docTasks);
} catch (e) {
// report unexpected errors to Sentry and ignore `ajax()` errors
if (!didCancel(error) && !(error instanceof AjaxError)) {
this.sentry.captureException(error);
}
}

return crates;
});
}
42 changes: 42 additions & 0 deletions app/models/crate.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import Model, { attr, hasMany } from '@ember-data/model';
import { waitForPromise } from '@ember/test-waiters';

import { task } from 'ember-concurrency';
import { apiAction } from '@mainmatter/ember-api-actions';
import { cached } from 'tracked-toolbox';

import ajax from '../utils/ajax';

export default class Crate extends Model {
@attr name;
@attr downloads;
Expand Down Expand Up @@ -42,6 +45,45 @@ export default class Crate extends Model {
}
}

get documentationLink() {
let crateDocsLink = this.documentation;

// if this is *not* a docs.rs link we'll return it directly
if (crateDocsLink && !crateDocsLink.startsWith('https://docs.rs/')) {
return crateDocsLink;
}

// if we know about a successful docs.rs build, we'll return a link to that
let { docsRsLink } = this;
if (docsRsLink) {
return docsRsLink;
}

// finally, we'll return the specified documentation link, whatever it is
if (crateDocsLink) {
return crateDocsLink;
}

return null;
}

loadDocsStatusTask = task(async () => {
if (!this.documentation) {
return await ajax(`https://docs.rs/crate/${this.name}/=${this.defaultVersion}/status.json`);
}
});

get hasDocsRsLink() {
let docsStatus = this.loadDocsStatusTask.lastSuccessful?.value;
return docsStatus?.doc_status === true;
}

get docsRsLink() {
if (this.hasDocsRsLink) {
return `https://docs.rs/${this.name}`;
}
}

@cached get versionIdsBySemver() {
let versions = this.versions.toArray() ?? [];
return versions.sort(compareVersionBySemver).map(v => v.id);
Expand Down

0 comments on commit cc0a011

Please sign in to comment.