diff --git a/app/components/seek-pagination.hbs b/app/components/seek-pagination.hbs
new file mode 100644
index 00000000000..4ae6e0a1650
--- /dev/null
+++ b/app/components/seek-pagination.hbs
@@ -0,0 +1,7 @@
+{{#if @pagination.nextPage}}
+
+{{/if}}
diff --git a/app/components/seek-pagination.module.css b/app/components/seek-pagination.module.css
new file mode 100644
index 00000000000..76cebb05f16
--- /dev/null
+++ b/app/components/seek-pagination.module.css
@@ -0,0 +1,5 @@
+.seek-pagination {
+ text-align: center;
+ font-size: 90%;
+ margin-bottom: 20px;
+}
diff --git a/app/controllers/me/pending-invites.js b/app/controllers/me/pending-invites.js
new file mode 100644
index 00000000000..19efd238c7d
--- /dev/null
+++ b/app/controllers/me/pending-invites.js
@@ -0,0 +1,10 @@
+import Controller from '@ember/controller';
+
+import { reads } from 'macro-decorators';
+
+import { pagination } from '../../utils/seek-pagination';
+
+export default class PendingInvitesController extends Controller {
+ @reads('model.meta.next_page') nextPage;
+ @pagination() pagination;
+}
diff --git a/app/routes/me/pending-invites.js b/app/routes/me/pending-invites.js
index af51d27432c..1cb57350c0d 100644
--- a/app/routes/me/pending-invites.js
+++ b/app/routes/me/pending-invites.js
@@ -5,7 +5,11 @@ import AuthenticatedRoute from '../-authenticated-route';
export default class PendingInvitesRoute extends AuthenticatedRoute {
@service store;
- model() {
- return this.store.findAll('crate-owner-invite');
+ queryParams = {
+ seek: { refreshModel: true },
+ };
+
+ model(params) {
+ return this.store.query('crate-owner-invite', params);
}
}
diff --git a/app/styles/me/pending-invites.module.css b/app/styles/me/pending-invites.module.css
index 19813a7a861..9c5d3d4379c 100644
--- a/app/styles/me/pending-invites.module.css
+++ b/app/styles/me/pending-invites.module.css
@@ -1,5 +1,6 @@
.list {
background: white;
+ margin-bottom: 2rem;
}
.row {
diff --git a/app/templates/me/pending-invites.hbs b/app/templates/me/pending-invites.hbs
index 7fcd2d84d50..b1c9c762841 100644
--- a/app/templates/me/pending-invites.hbs
+++ b/app/templates/me/pending-invites.hbs
@@ -9,3 +9,5 @@
You don't seem to have any pending invitations.
{{/each}}
+
+
diff --git a/app/utils/seek-pagination.js b/app/utils/seek-pagination.js
new file mode 100644
index 00000000000..23423dcccba
--- /dev/null
+++ b/app/utils/seek-pagination.js
@@ -0,0 +1,12 @@
+import macro from 'macro-decorators';
+
+export function pagination() {
+ return macro(function () {
+ const { nextPage } = this;
+ const nextPageParams = new URLSearchParams(nextPage);
+
+ return {
+ nextPage: nextPageParams.get('seek'),
+ };
+ });
+}
diff --git a/mirage/route-handlers/me.js b/mirage/route-handlers/me.js
index 2f130022034..3749a8ad551 100644
--- a/mirage/route-handlers/me.js
+++ b/mirage/route-handlers/me.js
@@ -1,6 +1,7 @@
import { Response } from 'miragejs';
import { getSession } from '../utils/session';
+import { pageParams } from './-utils';
export function register(server) {
server.get('/api/v1/me', function (schema) {
@@ -98,13 +99,20 @@ export function register(server) {
return { ok: true };
});
- server.get('/api/v1/me/crate_owner_invitations', function (schema) {
+ server.get('/api/v1/me/crate_owner_invitations', function (schema, request) {
let { user } = getSession(schema);
if (!user) {
return new Response(403, {}, { errors: [{ detail: 'must be logged in to perform that action' }] });
}
- return schema.crateOwnerInvitations.where({ inviteeId: user.id });
+ const { start, end } = pageParams(request);
+ const invites = schema.crateOwnerInvitations.where({ inviteeId: user.id });
+
+ let response = this.serialize(invites.slice(start, end));
+
+ response.meta = { total: invites.length };
+
+ return response;
});
server.put('/api/v1/me/crate_owner_invitations/:crate_id', (schema, request) => {
diff --git a/mirage/serializers/crate-owner-invitation.js b/mirage/serializers/crate-owner-invitation.js
index 85ec23bef00..3e356b0207f 100644
--- a/mirage/serializers/crate-owner-invitation.js
+++ b/mirage/serializers/crate-owner-invitation.js
@@ -24,7 +24,9 @@ export default BaseSerializer.extend({
delete hash.id;
delete hash.token;
- hash.crate_id = Number(hash.crate_id);
+ // TODO: Check this further, `crate_id` are strings in the current fixtures
+ // when attempting to parse into number we will get `NaN`s here.
+ // hash.crate_id = Number(hash.crate_id);
let crate = this.schema.crates.find(hash.crate_id);
hash.crate_name = crate.name;
diff --git a/src/controllers/crate_owner_invitation.rs b/src/controllers/crate_owner_invitation.rs
index 35ec3642fc0..b2d7c93a741 100644
--- a/src/controllers/crate_owner_invitation.rs
+++ b/src/controllers/crate_owner_invitation.rs
@@ -20,7 +20,9 @@ pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
let user_id = auth.user_id();
let PrivateListResponse {
- invitations, users, ..
+ invitations,
+ users,
+ meta,
} = prepare_list(req, auth, ListFilter::InviteeId(user_id))?;
// The schema for the private endpoints is converted to the schema used by v1 endpoints.
@@ -47,6 +49,7 @@ pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
Ok(req.json(&json!({
"crate_owner_invitations": crate_owner_invitations,
"users": users,
+ "meta": meta,
})))
}
diff --git a/tests/mirage/me/crate-owner-invitations/list-test.js b/tests/mirage/me/crate-owner-invitations/list-test.js
index 6e4116819f2..84c8f84c7c8 100644
--- a/tests/mirage/me/crate-owner-invitations/list-test.js
+++ b/tests/mirage/me/crate-owner-invitations/list-test.js
@@ -15,7 +15,7 @@ module('Mirage | GET /api/v1/me/crate_owner_invitations', function (hooks) {
let response = await fetch('/api/v1/me/crate_owner_invitations');
assert.equal(response.status, 200);
- assert.deepEqual(await response.json(), { crate_owner_invitations: [] });
+ assert.deepEqual(await response.json(), { crate_owner_invitations: [], meta: { total: 0 } });
});
test('returns the list of invitations for the authenticated user', async function (assert) {
@@ -47,6 +47,7 @@ module('Mirage | GET /api/v1/me/crate_owner_invitations', function (hooks) {
let response = await fetch('/api/v1/me/crate_owner_invitations');
assert.equal(response.status, 200);
assert.deepEqual(await response.json(), {
+ meta: { total: 0 },
crate_owner_invitations: [
{
crate_id: Number(nanomsg.id),