diff --git a/app/components/version-list/row.hbs b/app/components/version-list/row.hbs
index 7446250208d..11ce1dcc151 100644
--- a/app/components/version-list/row.hbs
+++ b/app/components/version-list/row.hbs
@@ -128,6 +128,18 @@
+
+
+
diff --git a/app/components/version-list/row.js b/app/components/version-list/row.js
index 82ee537993c..15deed1253a 100644
--- a/app/components/version-list/row.js
+++ b/app/components/version-list/row.js
@@ -4,9 +4,12 @@ import { htmlSafe } from '@ember/template';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
+import { keepLatestTask } from 'ember-concurrency';
+
import styles from './row.module.css';
export default class VersionRow extends Component {
+ @service notifications;
@service session;
@tracked focused = false;
@@ -59,4 +62,16 @@ export default class VersionRow extends Component {
@action setFocused(value) {
this.focused = value;
}
+
+ rebuildDocsTask = keepLatestTask(async () => {
+ let { version } = this.args;
+ try {
+ await version.rebuildDocs();
+ this.notifications.success('Docs rebuild task was enqueued successfully!');
+ } catch (error) {
+ let reason = error?.errors?.[0]?.detail ?? 'Failed to equeue docs rebuild task.';
+ let msg = `Error: ${reason}`;
+ this.notifications.error(msg);
+ }
+ });
}
diff --git a/app/models/version.js b/app/models/version.js
index 1a89cbf1706..c07e781e1ed 100644
--- a/app/models/version.js
+++ b/app/models/version.js
@@ -200,4 +200,8 @@ export default class Version extends Model {
this.store.pushPayload(payload);
await waitForPromise(this.releaseTracks.refreshTask.perform(this.crateName, false));
});
+
+ async rebuildDocs() {
+ return await waitForPromise(apiAction(this, { method: 'POST', path: 'rebuild_docs' }));
+ }
}
diff --git a/e2e/acceptance/versions.spec.ts b/e2e/acceptance/versions.spec.ts
index c61d297a6b0..c895a34f7b6 100644
--- a/e2e/acceptance/versions.spec.ts
+++ b/e2e/acceptance/versions.spec.ts
@@ -68,4 +68,31 @@ test.describe('Acceptance | crate versions page', { tag: '@acceptance' }, () =>
await expect(v020).not.toHaveClass(/.*latest/);
await expect(v020).not.toHaveClass(/.yanked/);
});
+
+ test('triggers a rebuild for crate documentation', async ({ page, msw }) => {
+ let user = msw.db.user.create();
+ await msw.authenticateAs(user);
+
+ let crate = msw.db.crate.create({ name: 'nanomsg' });
+ msw.db.crateOwnership.create({ crate, user });
+
+ msw.db.version.create({ crate, num: '0.1.0', created_at: '2017-01-01' });
+ msw.db.version.create({ crate, num: '0.2.0', created_at: '2018-01-01' });
+ msw.db.version.create({ crate, num: '0.3.0', created_at: '2019-01-01', rust_version: '1.69' });
+ msw.db.version.create({ crate, num: '0.2.1', created_at: '2020-01-01' });
+
+ await page.goto('/crates/nanomsg/versions');
+ await expect(page).toHaveURL('/crates/nanomsg/versions');
+
+ await expect(page.locator('[data-test-version]')).toHaveCount(4);
+ let versions = await page.locator('[data-test-version]').evaluateAll(el => el.map(it => it.dataset.testVersion));
+ expect(versions).toEqual(['0.2.1', '0.3.0', '0.2.0', '0.1.0']);
+
+ let v021 = page.locator('[data-test-version="0.2.1"]');
+ await v021.locator('[data-test-actions-toggle]').click();
+ await v021.getByRole('button', { name: 'Rebuild Docs' }).click();
+
+ let message = 'Docs rebuild task was enqueued successfully!';
+ await expect(page.locator('[data-test-notification-message="success"]')).toHaveText(message);
+ });
});
diff --git a/tests/acceptance/versions-test.js b/tests/acceptance/versions-test.js
index cff0df2e9b2..5cc09f13169 100644
--- a/tests/acceptance/versions-test.js
+++ b/tests/acceptance/versions-test.js
@@ -81,4 +81,29 @@ module('Acceptance | crate versions page', function (hooks) {
.hasNoClass(/.*latest/)
.hasNoClass(/.yanked/);
});
+
+ test('triggers a rebuild for crate documentation', async function (assert) {
+ let user = this.db.user.create();
+ this.authenticateAs(user);
+
+ let crate = this.db.crate.create({ name: 'nanomsg' });
+ this.db.crateOwnership.create({ crate, user });
+
+ this.db.version.create({ crate, num: '0.1.0', created_at: '2017-01-01' });
+ this.db.version.create({ crate, num: '0.2.0', created_at: '2018-01-01' });
+ this.db.version.create({ crate, num: '0.3.0', created_at: '2019-01-01', rust_version: '1.69' });
+ this.db.version.create({ crate, num: '0.2.1', created_at: '2020-01-01' });
+
+ await visit('/crates/nanomsg/versions');
+ assert.strictEqual(currentURL(), '/crates/nanomsg/versions');
+
+ let versions = findAll('[data-test-version]').map(it => it.dataset.testVersion);
+ assert.deepEqual(versions, ['0.2.1', '0.3.0', '0.2.0', '0.1.0']);
+
+ await click('[data-test-version="0.2.1"] [data-test-actions-toggle]');
+ await click('[data-test-version="0.2.1"] [data-test-id="btn-rebuild-docs"]');
+
+ let message = 'Docs rebuild task was enqueued successfully!';
+ assert.dom('[data-test-notification-message="success"]').hasText(message);
+ });
});