Skip to content

Commit

Permalink
feat: add paginator to collection page (#526)
Browse files Browse the repository at this point in the history
* feat: created simple paginator for collection root component WIP

* chore: added extra test objects

* fix: adjusted styling of paginator WIP

* chore: move paginator to shared components package

* chore: import new paginator component in manage WIP

* feat: add paginator to presentation

* test: coverage
  • Loading branch information
lem-onade authored Dec 1, 2021
1 parent a992be9 commit ae4a700
Show file tree
Hide file tree
Showing 17 changed files with 1,125 additions and 21 deletions.
2 changes: 2 additions & 0 deletions packages/solid-crs-components/lib/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { LargeCardComponent } from './collections/large-card.component';
import { DemoLargeCardComponent } from './demo/demo-large-card.component';
import { ProgressBarComponent } from './loading/progress-bar-component';
import { PopupComponent } from './alerts/popup.component';
import { PaginatorComponent } from './paginator/paginator.component';

/**
* Register tags for components.
Expand All @@ -40,3 +41,4 @@ customElements.define('nde-demo-svg', DemoSVGComponent);
customElements.define('nde-sidebar-item', SidebarItemComponent);
customElements.define('nde-progress-bar', ProgressBarComponent);
customElements.define('nde-popup', PopupComponent);
customElements.define('nde-paginator', PaginatorComponent);
1 change: 1 addition & 0 deletions packages/solid-crs-components/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export * from './state/schema';
export * from './state/state';
export * from './header/content-header.component';
export * from './loading/progress-bar-component';
export * from './paginator/paginator.component';
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* eslint-disable @typescript-eslint/dot-notation */
import { PaginatorComponent } from './paginator.component';

describe('PaginatorComponent', () => {

let component: PaginatorComponent;

beforeEach(() => {

component = window.document.createElement('nde-paginator') as PaginatorComponent;
component.pageIndex = 0;
component.objectsPerPage = 18;
component.objectsAmount = 40;

component.translator = {
translate: () => 'page 1 of 10',
} as any;

});

afterEach(() => {

document.getElementsByTagName('html')[0].innerHTML = '';

});

it('should be correctly instantiated', async () => {

window.document.body.appendChild(component);
await component.updateComplete;
expect(component).toBeTruthy();

});

describe('HTML', () => {

beforeEach(async () => {

window.document.body.appendChild(component);
await component.updateComplete;

});

it('should disable previous button when on first page', async () => {

component.pageIndex = 0;
await component.updateComplete;
expect(component.shadowRoot.querySelector<HTMLButtonElement>('button.previous').disabled).toBeTruthy();

});

it('should disable next button when on last page', async () => {

// 40 objects, 18 per page, on page 3 (index 2)
component.pageIndex = 2;
await component.updateComplete;
expect(component.shadowRoot.querySelector<HTMLButtonElement>('button.next').disabled).toBeTruthy();

});

});

describe('onNext', () => {

it('should dispatch next CustomEvent', async (done) => {

component.addEventListener('next', () => done());
component['onNext']();

});

});

describe('onPrevious', () => {

it('should dispatch previous CustomEvent', async (done) => {

component.addEventListener('previous', () => done());
component['onPrevious']();

});

});

});
132 changes: 132 additions & 0 deletions packages/solid-crs-components/lib/paginator/paginator.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { css, CSSResult, html, property, TemplateResult, unsafeCSS } from 'lit-element';
import { RxLitElement } from 'rx-lit';
import { Dropdown, Theme } from '@netwerk-digitaal-erfgoed/solid-crs-theme';
import { unsafeSVG } from 'lit-html/directives/unsafe-svg';
import { Translator } from '@netwerk-digitaal-erfgoed/solid-crs-core';

/**
* A component for paginator controls.
*/
export class PaginatorComponent extends RxLitElement {

/**
* The index of the page curently being viewed.
*/
@property({ type: Object })
public translator: Translator;

/**
* The index of the page curently being viewed.
*/
@property({ type: Number })
public pageIndex: number;

/**
* The amount of objects to show per page.
*/
@property({ type: Number })
public objectsPerPage: number;

/**
* The total amount of objects.
*/
@property({ type: Number })
public objectsAmount: number;

/**
* Emits a custom next event.
*/
private onNext(): void {

this.dispatchEvent(new CustomEvent('next'));

}

/**
* Emits a custom previous event.
*/
private onPrevious(): void {

this.dispatchEvent(new CustomEvent('previous'));

}

/**
* Renders the component as HTML.
*
* @returns The rendered HTML of the component.
*/
render(): TemplateResult {

return html`
<!-- e.g. page 1 of 10 -->
<p>${this.translator.translate('common.paginator.page-counter')
.replace('{CURRENT}', (this.pageIndex+1).toString())
.replace('{TOTAL}', Math.ceil(this.objectsAmount / this.objectsPerPage).toString())}
</p>
<!-- previous button -->
<button
.disabled="${this.pageIndex < 1}"
class="previous"
@click="${this.onPrevious}">
${ unsafeSVG(Dropdown) }
</button>
<!-- next button -->
<button
.disabled="${(this.pageIndex + 1) * this.objectsPerPage >= this.objectsAmount}"
class="next"
@click="${this.onNext}">
${ unsafeSVG(Dropdown) }
</button>
<!-- </div> -->
`;

}

/**
* The styles associated with the component.
*/
static get styles(): CSSResult[] {

return [
unsafeCSS(Theme),
css`
:host {
display: flex;
justify-content: flex-end;
gap: var(--gap-normal);
height: var(--gap-normal);
}
:host[hidden] {
display: none;
}
:host > * {
margin: 0;
padding: 0;
display: block;
background-color: unset;
font-size: var(--font-size-small);
line-height: var(--gap-normal);
min-width: var(--gap-normal);
}
:host svg {
fill: var(--colors-primary-dark);
}
button:disabled svg {
fill: var(--colors-foreground-light);
}
.previous svg {
transform: rotate(90deg);
}
.next svg {
transform: rotate(270deg);
}
`,
];

}

}
4 changes: 2 additions & 2 deletions packages/solid-crs-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@
"coverageThreshold": {
"global": {
"branches": 93.17,
"functions": 98.97,
"functions": 99.01,
"lines": 100,
"statements": 99.69
"statements": 99.7
}
},
"coveragePathIgnorePatterns": [
Expand Down
2 changes: 2 additions & 0 deletions packages/solid-crs-components/tests/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { SidebarListComponent } from '../lib/sidebar/sidebar-list.component';
import { SidebarListItemComponent } from '../lib/sidebar/sidebar-list-item.component';
import { FormElementComponent } from '../lib/forms/form-element.component';
import { AlertComponent } from '../lib/alerts/alert.component';
import { PaginatorComponent } from '../lib/paginator/paginator.component';

/**
* Enable mocks for fetch.
Expand All @@ -50,3 +51,4 @@ customElements.define('nde-card', CardComponent);
customElements.define('nde-large-card', LargeCardComponent);
customElements.define('nde-progress-bar', ProgressBarComponent);
customElements.define('nde-popup', PopupComponent);
customElements.define('nde-paginator', PaginatorComponent);
2 changes: 1 addition & 1 deletion packages/solid-crs-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@
"preset": "@digita-ai/jest-config",
"maxWorkers": 6
}
}
}
3 changes: 2 additions & 1 deletion packages/solid-crs-manage/lib/app.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AlertComponent, CardComponent, CollectionCardComponent, ContentHeaderComponent, FormElementComponent, LargeCardComponent, ObjectCardComponent, SidebarComponent, SidebarItemComponent, SidebarListComponent, SidebarListItemComponent, ProgressBarComponent } from '@netwerk-digitaal-erfgoed/solid-crs-components';
import { AlertComponent, CardComponent, CollectionCardComponent, ContentHeaderComponent, FormElementComponent, LargeCardComponent, ObjectCardComponent, SidebarComponent, SidebarItemComponent, SidebarListComponent, SidebarListItemComponent, ProgressBarComponent, PaginatorComponent } from '@netwerk-digitaal-erfgoed/solid-crs-components';
import { inspect } from '@xstate/inspect';
import { SearchRootComponent } from './features/search/search-root.component';
import { AppRootComponent } from './app-root.component';
Expand Down Expand Up @@ -44,3 +44,4 @@ customElements.define('nde-sidebar-list', SidebarListComponent);
customElements.define('nde-sidebar-item', SidebarItemComponent);
customElements.define('nde-progress-bar', ProgressBarComponent);
customElements.define('nde-term-search', TermSearchComponent);
customElements.define('nde-paginator', PaginatorComponent);
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ describe('CollectionRootComponent', () => {
component = window.document.createElement('nde-collection-root') as CollectionRootComponent;

component.actor = machine;

component.formActor = machine.children.get(FormActors.FORM_MACHINE);

component.translator = new MockTranslator('nl-NL');

});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,44 @@ export class CollectionRootComponent extends RxLitElement {
* Indicates if the form is being submitted.
*/
@internalProperty()
isSubmitting? = false;
isSubmitting = false;

/**
* Indicates if if the form validation passed.
*/
@internalProperty()
isValid? = false;
isValid = false;

/**
* Indicates if one the form fields has changed.
*/
@internalProperty()
isDirty? = false;
isDirty = false;

/**
* Indicates if one the form fields has changed.
*/
@internalProperty()
objectsPerPage = 18;

/**
* Indicates if one the form fields has changed.
*/
@internalProperty()
pageIndex = 0;

/**
* The popup component shown when the delete icon is clicked
*/
@query('nde-popup#delete-popup')
deletePopup: PopupComponent;

/**
* The element containing the grid of collection objects.
*/
@query('.content')
pageContent: HTMLElement;

/**
* Hook called on at every update after connection to the DOM.
*/
Expand Down Expand Up @@ -228,9 +246,33 @@ export class CollectionRootComponent extends RxLitElement {
: html`
${this.objects?.length
? html`
<div class='three-column-content-grid'>
${this.objects.map((object) => html`<nde-object-card @click="${() => this.actor.send(ObjectEvents.SELECTED_OBJECT, { object })}" .translator=${this.translator} .object=${object}></nde-object-card>`)}
<nde-paginator
?hidden="${this.objects.length <= this.objectsPerPage}"
@next="${() => { this.pageIndex++; this.pageContent.scrollTo(0, 0); }}"
@previous="${() => { this.pageIndex--; this.pageContent.scrollTo(0, 0); }}"
.translator="${this.translator}"
.pageIndex="${this.pageIndex}"
.objectsPerPage="${this.objectsPerPage}"
.objectsAmount="${this.objects.length}">
</nde-paginator>
<div class="three-column-content-grid">
${this.objects
.slice(this.pageIndex * this.objectsPerPage, this.pageIndex * this.objectsPerPage + this.objectsPerPage)
.map((object) =>
html`<nde-object-card @click="${() => this.actor.send(ObjectEvents.SELECTED_OBJECT, { object })}" .translator=${this.translator} .object=${object}></nde-object-card>`)}
</div>
<nde-paginator
?hidden="${this.objects.length <= this.objectsPerPage}"
@next="${() => { this.pageIndex++; this.pageContent.scrollTo(0, 0); }}"
@previous="${() => { this.pageIndex--; this.pageContent.scrollTo(0, 0); }}"
.translator="${this.translator}"
.pageIndex="${this.pageIndex}"
.objectsPerPage="${this.objectsPerPage}"
.objectsAmount="${this.objects.length}">
</nde-paginator>
`
: html`
<div class="empty-container">
Expand Down Expand Up @@ -305,6 +347,7 @@ export class CollectionRootComponent extends RxLitElement {
overflow-y: auto;
display:flex;
flex-direction: column;
gap: var(--gap-large);
}
nde-progress-bar {
position: absolute;
Expand Down
3 changes: 3 additions & 0 deletions packages/solid-crs-manage/lib/public/nl-NL.json
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@
"months-ago": "maanden geleden",
"year-ago": "jaar geleden",
"years-ago": "jaar geleden"
},
"paginator": {
"page-counter": "Pagina {CURRENT} van {TOTAL}"
}
},
"search": {
Expand Down
Loading

0 comments on commit ae4a700

Please sign in to comment.