Add pagination component

This commit is contained in:
Stanislav Romanov 2022-03-25 14:23:53 +03:00
parent 2251443c10
commit 3c9a0b0d95
8 changed files with 169 additions and 2 deletions

View file

@ -0,0 +1,46 @@
{{#if (gt this.totalPages 1)}}
<nav class="flex justify-center relative z-0 my-4" aria-label="Pagination">
{{#let "inline-flex items-center justify-center px-2 mx-1 font-display text-lg" as |commonClasses|}}
{{#if this.previousPage}}
<LinkTo
@route={{this.router.currentRouteName}}
@models={{if @model (array @model) (array)}}
@query={{hash page=this.previousPage}}
class={{commonClasses}}
title="Previous page"
>
<MdIcon @icon="chevron-left" />
</LinkTo>
{{/if}}
{{#each this.availablePages as |i|}}
{{#if (eq @current i)}}
<span class="{{commonClasses}} border rounded">{{i}}</span>
{{else if (eq "..." i)}}
<span class={{commonClasses}}>{{i}}</span>
{{else}}
<LinkTo
@route={{this.router.currentRouteName}}
@models={{if @model (array @model) (array)}}
@query={{hash page=i}}
class={{commonClasses}}
>
{{i}}
</LinkTo>
{{/if}}
{{/each}}
{{#if this.nextPage}}
<LinkTo
@route={{this.router.currentRouteName}}
@models={{if @model (array @model) (array)}}
@query={{hash page=this.nextPage}}
class={{commonClasses}}
title="Next page"
>
<MdIcon @icon="chevron-right" />
</LinkTo>
{{/if}}
{{/let}}
</nav>
{{/if}}

View file

@ -0,0 +1,65 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class PaginationComponent extends Component {
@service router;
numberPagesToShow = 2;
get availablePages() {
const availablePages = [];
for (let i = 1; i <= this.totalPages; i++) {
if (i === this.args.current) {
availablePages.push(i);
} else if (
i < this.args.current &&
i >= this.args.current - this.numberPagesToShow
) {
availablePages.push(i);
} else if (
i > this.args.current &&
i <= this.args.current + this.numberPagesToShow
) {
availablePages.push(i);
} else if (
this.args.current > this.totalPages &&
i <= this.args.current + this.numberPagesToShow
) {
availablePages.push(i);
}
}
const firstPage = availablePages[0];
if (firstPage > 1) {
if (firstPage - 1 > 1) {
availablePages.unshift('...');
}
availablePages.unshift(1);
}
const lastPage = availablePages[availablePages.length - 1];
if (lastPage < this.totalPages) {
if (lastPage + 1 < this.totalPages) {
availablePages.push('...');
}
availablePages.push(this.totalPages);
}
return availablePages;
}
get totalPages() {
return Math.ceil(this.args.count / this.args.perPage);
}
get previousPage() {
return this.args.current > 1 ? this.args.current - 1 : null;
}
get nextPage() {
return this.args.current < this.totalPages ? this.args.current + 1 : null;
}
}

View file

@ -5,6 +5,8 @@ import { trackedFunction } from 'ember-resources';
export default class AdminIndexesItemDataController extends Controller {
@tracked searchText = 'hello';
@tracked offset = 0;
@tracked page = 0;
request = trackedFunction(this, async () => {
if (typeof this.searchText !== 'string' || this.searchText.length < 1) {

View file

@ -3,7 +3,6 @@ import Route from '@ember/routing/route';
export default class AdminIndexesRoute extends Route {
// @service meilisearch;
// async model() {
// return this.modelFor('admin');
// }

View file

@ -21,7 +21,7 @@
<h2 class="text-xl mb-4">Results:</h2>
<div class=" ">
{{#each this.data.hits as |item|}}
<div class="mb-8 rounded-md overflow-hidden shadow">
<div class="mb-8 rounded-md border overflow-hidden shadow">
{{#each-in item as |key value|}}
<div class="grid grid-cols-3 gap-4 p-4 odd:bg-gray-50">
<div>{{key}}</div>
@ -32,4 +32,10 @@
{{/each}}
</div>
</div>
<Pagination
@count={{this.data.nbHits}}
@current={{this.page}}
@perPage={{this.data.limit}}
/>
{{/if}}

22
package-lock.json generated
View file

@ -54,6 +54,7 @@
"ember-resources": "^4.4.0",
"ember-source": "~4.2.0",
"ember-template-lint": "^4.2.0",
"ember-truth-helpers": "^3.0.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.4.0",
"eslint-plugin-ember": "^10.5.9",
@ -13442,6 +13443,18 @@
"node": ">=8.17.0"
}
},
"node_modules/ember-truth-helpers": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ember-truth-helpers/-/ember-truth-helpers-3.0.0.tgz",
"integrity": "sha512-hPKG9QqruAELh0li5xaiLZtr88ioWYxWCXisAWHWE0qCP4a2hgtuMzKUPpiTCkltvKjuqpzTZCU4VhQ+IlRmew==",
"dev": true,
"dependencies": {
"ember-cli-babel": "^7.22.1"
},
"engines": {
"node": "10.* || >= 12.*"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -35053,6 +35066,15 @@
}
}
},
"ember-truth-helpers": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ember-truth-helpers/-/ember-truth-helpers-3.0.0.tgz",
"integrity": "sha512-hPKG9QqruAELh0li5xaiLZtr88ioWYxWCXisAWHWE0qCP4a2hgtuMzKUPpiTCkltvKjuqpzTZCU4VhQ+IlRmew==",
"dev": true,
"requires": {
"ember-cli-babel": "^7.22.1"
}
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",

View file

@ -74,6 +74,7 @@
"ember-resources": "^4.4.0",
"ember-source": "~4.2.0",
"ember-template-lint": "^4.2.0",
"ember-truth-helpers": "^3.0.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.4.0",
"eslint-plugin-ember": "^10.5.9",

View file

@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | pagination', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Pagination />`);
assert.dom(this.element).hasText('');
// Template block usage:
await render(hbs`
<Pagination>
template block text
</Pagination>
`);
assert.dom(this.element).hasText('template block text');
});
});