diff --git a/addon/components/pix-table-basic-column.hbs b/addon/components/pix-table-basic-column.hbs
index f0042c533..497cfa926 100644
--- a/addon/components/pix-table-basic-column.hbs
+++ b/addon/components/pix-table-basic-column.hbs
@@ -1,6 +1,7 @@
{{/if}}
diff --git a/addon/components/pix-table-column.js b/addon/components/pix-table-column.js
index e6911fa89..4df2cc77a 100644
--- a/addon/components/pix-table-column.js
+++ b/addon/components/pix-table-column.js
@@ -1,32 +1,56 @@
import Component from '@glimmer/component';
-import { action } from '@ember/object';
+import { warn } from '@ember/debug';
export default class PixTableColumn extends Component {
- id = crypto.randomUUID();
-
get displayHeader() {
- return this.args.context.type === 'header';
+ return this.args.context === 'header';
}
get sortable() {
- return Boolean(this.args.sort);
+ return Boolean(this.args.onSort);
+ }
+
+ get sortOrder() {
+ if (this.args.sortOrder === undefined) {
+ return undefined;
+ }
+ const correctSortOrders = ['asc', 'desc', null];
+ warn(
+ 'PixTableColumn: you need to provide a valid sortOrder',
+ correctSortOrders.includes(this.args.sortOrder),
+ {
+ id: 'pix-ui.table-column.sortOrder.not-valid',
+ },
+ );
+ return this.args.sortOrder;
}
get iconName() {
- if (this.args.context.currentSortedColumnId !== this.id) {
+ if (!this.sortOrder) {
return 'sort';
}
- if (this.args.context.sortOrder === 'asc') {
+ if (this.sortOrder === 'asc') {
return 'sortAsc';
}
return 'sortDesc';
}
get iconLabel() {
- if (this.args.context.currentSortedColumnId !== this.id) {
+ warn(
+ 'PixTableColumn: parameters `@ariaLabelDefaultSort`, `@ariaLabelSortDesc` and `@ariaLabelSortAsc` are required for sort buttons',
+ ![
+ this.args.ariaLabelDefaultSort,
+ this.args.ariaLabelSortDesc,
+ this.args.ariaLabelSortAsc,
+ ].includes(undefined),
+ {
+ id: 'pix-ui.pix-table-column.sortAriaLabels.required',
+ },
+ );
+ if (!this.sortOrder) {
return this.args.ariaLabelDefaultSort;
}
- if (this.args.context.sortOrder === 'asc') {
+ if (this.sortOrder === 'asc') {
return this.args.ariaLabelSortDesc;
}
return this.args.ariaLabelSortAsc;
@@ -36,17 +60,12 @@ export default class PixTableColumn extends Component {
if (!this.sortable) {
return undefined;
}
- if (this.args.context.currentSortedColumnId !== this.id) {
+ if (!this.sortOrder) {
return 'none';
}
- if (this.args.context.sortOrder === 'asc') {
+ if (this.sortOrder === 'asc') {
return 'ascending';
}
return 'descending';
}
-
- @action
- sort() {
- this.args.context.toggleSort(this.id, this.args.sort);
- }
}
diff --git a/addon/components/pix-table.hbs b/addon/components/pix-table.hbs
index 2d9b83fbd..938e5dc12 100644
--- a/addon/components/pix-table.hbs
+++ b/addon/components/pix-table.hbs
@@ -3,14 +3,13 @@
{{this.caption}}
- {{this.headerContext.date}}
- {{#each this.computedData as |row|}}
+ {{#each @data as |row|}}
- {{yield row this.cellContext to="columns"}}
+ {{yield row "cell" to="columns"}}
{{/each}}
diff --git a/addon/components/pix-table.js b/addon/components/pix-table.js
index c5a0bbc02..1ba350b89 100644
--- a/addon/components/pix-table.js
+++ b/addon/components/pix-table.js
@@ -1,17 +1,7 @@
import Component from '@glimmer/component';
import { warn } from '@ember/debug';
-import { tracked } from '@glimmer/tracking';
-import { action } from '@ember/object';
export default class PixTable extends Component {
- headerContext = new HeaderContext({
- type: 'header',
- toggleSort: this.toggleSort,
- });
-
- @tracked
- computedData = [...this.args.data];
-
get variant() {
const value = this.args.variant ?? 'primary';
warn(
@@ -35,41 +25,4 @@ export default class PixTable extends Component {
get headerClass() {
return `pix-table-header--${this.variant}`;
}
-
- get cellContext() {
- return {
- type: 'cell',
- };
- }
-
- @action
- toggleSort(id, sortFun) {
- this.headerContext.refresh(id);
- if (this.headerContext.sortOrder === 'asc') {
- this.computedData = this.computedData.sort(sortFun);
- return;
- }
- this.computedData = this.computedData.reverse();
- }
-}
-
-class HeaderContext {
- @tracked sortOrder;
- @tracked currentSortedColumnId;
-
- constructor({ type, toggleSort, sortOrder, currentSortedColumnId }) {
- this.type = type;
- this.toggleSort = toggleSort;
- this.sortOrder = sortOrder;
- this.currentSortedColumnId = currentSortedColumnId;
- }
-
- refresh(id) {
- if (id !== this.currentSortedColumnId) {
- this.sortOrder = 'asc';
- this.currentSortedColumnId = id;
- } else {
- this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
- }
- }
}
diff --git a/addon/styles/_pix-table-basic-column.scss b/addon/styles/_pix-table-basic-column.scss
index e72359777..2cb1aaebb 100644
--- a/addon/styles/_pix-table-basic-column.scss
+++ b/addon/styles/_pix-table-basic-column.scss
@@ -1,5 +1,5 @@
td.pix-table-basic-column {
- &--number{
+ &--number {
text-align: right;
}
}
diff --git a/tests/integration/components/pix-table-test.js b/tests/integration/components/pix-table-test.js
index 773dd1037..5975755da 100644
--- a/tests/integration/components/pix-table-test.js
+++ b/tests/integration/components/pix-table-test.js
@@ -126,28 +126,26 @@ module('Integration | Component | table', function (hooks) {
});
module('#sort', function () {
- test('it should sort properly when `@sort` is a custom sort function', async function (assert) {
- const arialLabelDefaultSort =
- "La table n'est pas triée par nom. Cliquer pour trier par ordre alphabétique";
+ test('it should call @onSort on click', async function (assert) {
+ // given
+ const sortStub = sinon.stub();
+ this.onSort = sortStub;
+
+ const arialLabelDefaultSort = 'default label sort';
this.arialLabelDefaultSort = arialLabelDefaultSort;
- const otherArialLabelDefaultSort = 'click sur un autre';
- this.otherArialLabelDefaultSort = otherArialLabelDefaultSort;
- const ariaLabelSortAsc = 'Cliquer pour trier en ordre ascendant';
- this.ariaLabelSortAsc = ariaLabelSortAsc;
- const ariaLabelSortDesc = 'Cliquer pour trier en ordre descendant';
- this.ariaLabelSortDesc = ariaLabelSortDesc;
- this.sort = (a, b) => a.name.localeCompare(b.name);
// when
+
const screen = await render(
hbs`
<:columns as |row context|>
<:header>
Nom
@@ -156,18 +154,81 @@ module('Integration | Component | table', function (hooks) {
{{row.name}}
+
+`,
+ );
+
+ // then
+ await click(await screen.getByRole('button', { name: arialLabelDefaultSort }));
+ assert.ok(sortStub.calledOnce);
+ });
+
+ test('it should display `ariaLabelSortAsc` when sortOrder is `desc`', async function (assert) {
+ // given
+ const sortStub = sinon.stub();
+ this.onSort = sortStub;
+
+ this.sortOrder = 'desc';
+
+ const ariaLabelSortAsc = "clicker pour trié dans l'ordre desc";
+ this.ariaLabelSortAsc = ariaLabelSortAsc;
+
+ // when
+
+ const screen = await render(
+ hbs`
+ <:columns as |row context|>
+ <:header>
+ Nom
+
+ <:cell>
+ {{row.name}}
+
+
+
+`,
+ );
+
+ // then
+ assert.ok(await screen.getByRole('button', { name: ariaLabelSortAsc }));
+ });
+
+ test('it should display `ariaLabelSortDesc` when sortOrder is `asc`', async function (assert) {
+ // given
+ const sortStub = sinon.stub();
+ this.onSort = sortStub;
+
+ this.sortOrder = 'asc';
+
+ const ariaLabelSortDesc = "clicker pour trié dans l'ordre asc";
+ this.ariaLabelSortDesc = ariaLabelSortDesc;
+
+ // when
+
+ const screen = await render(
+ hbs`
+ <:columns as |row context|>
+
<:header>
- Age
+ Nom
<:cell>
- {{row.age}}
+ {{row.name}}
@@ -175,27 +236,32 @@ module('Integration | Component | table', function (hooks) {
);
// then
- const names = screen.queryAllByText(/jean|brian|zoé/);
- assert.strictEqual(names.length, 3);
- assert.strictEqual(names[0].textContent.trim(), 'jean');
- assert.strictEqual(names[1].textContent.trim(), 'brian');
- assert.strictEqual(names[2].textContent.trim(), 'zoé');
+ assert.ok(await screen.getByRole('button', { name: ariaLabelSortDesc }));
+ });
- await click(await screen.getByRole('button', { name: arialLabelDefaultSort }));
- const namesAsc = screen.queryAllByText(/jean|brian|zoé/);
- assert.strictEqual(namesAsc[0].textContent.trim(), 'brian');
- assert.strictEqual(namesAsc[1].textContent.trim(), 'jean');
- assert.strictEqual(namesAsc[2].textContent.trim(), 'zoé');
-
- await click(await screen.getByRole('button', { name: ariaLabelSortDesc }));
- const namesDesc = screen.queryAllByText(/jean|brian|zoé/);
- assert.strictEqual(namesDesc[0].textContent.trim(), 'zoé');
- assert.strictEqual(namesDesc[1].textContent.trim(), 'jean');
- assert.strictEqual(namesDesc[2].textContent.trim(), 'brian');
- assert.ok(await screen.getByRole('button', { name: ariaLabelSortAsc }));
+ test('it should not display sortlabel when `@onSort` is not provided', async function (assert) {
+ // given
+ const arialLabelDefaultSort = 'default label sort';
+ this.arialLabelDefaultSort = arialLabelDefaultSort;
- await click(await screen.getByRole('button', { name: otherArialLabelDefaultSort }));
- assert.ok(await screen.getByRole('button', { name: arialLabelDefaultSort }));
+ // when
+ const screen = await render(
+ hbs`
+ <:columns as |row context|>
+
+ <:header>
+ Nom
+
+ <:cell>
+ {{row.name}}
+
+
+
+`,
+ );
+
+ // then
+ assert.notOk(await screen.queryByRole('button', { name: arialLabelDefaultSort }));
});
});
@@ -254,5 +320,89 @@ module('Integration | Component | table', function (hooks) {
}),
);
});
+
+ test('it should warn when @sortOrder is incorrect', async function (assert) {
+ // when
+ this.data = [];
+ this.onSort = () => {};
+ await render(
+ hbs`
+ <:columns as |row context|>
+
+
+`,
+ );
+
+ // then
+ assert.ok(
+ EmberDebug.warn
+ .getCalls()
+ .find((call) => {
+ return call.args[2].id === 'pix-ui.table-column.sortOrder.not-valid';
+ })
+ .calledWith('PixTableColumn: you need to provide a valid sortOrder', false, {
+ id: 'pix-ui.table-column.sortOrder.not-valid',
+ }),
+ );
+ });
+
+ [
+ {
+ ariaLabelDefaultSort: 'tri',
+ ariaLabelSortDesc: 'tri',
+ ariaLabelSortAsc: undefined,
+ },
+ {
+ ariaLabelDefaultSort: 'tri',
+ ariaLabelSortDesc: undefined,
+ ariaLabelSortAsc: 'tri',
+ },
+ {
+ ariaLabelDefaultSort: undefined,
+ ariaLabelSortDesc: 'tri',
+ ariaLabelSortAsc: 'tri',
+ },
+ ].forEach(function (sortAriaLabels) {
+ const [missingLabel] = Object.entries(sortAriaLabels).find(([, value]) => !value);
+ test(`it should warn when ${missingLabel} is not provided`, async function (assert) {
+ // when
+ this.data = [];
+ this.onSort = () => {};
+ this.ariaLabelDefaultSort = sortAriaLabels.ariaLabelDefaultSort;
+ this.ariaLabelSortDesc = sortAriaLabels.ariaLabelSortDesc;
+ this.ariaLabelSortAsc = sortAriaLabels.ariaLabelSortAsc;
+
+ await render(hbs`
+ <:columns as |row context|>
+
+
+`);
+
+ // then
+ assert.ok(
+ EmberDebug.warn
+ .getCalls()
+ .find((call) => {
+ return (
+ call.args[0] ===
+ 'PixTableColumn: parameters `@ariaLabelDefaultSort`, `@ariaLabelSortDesc` and `@ariaLabelSortAsc` are required for sort buttons'
+ );
+ })
+ .calledWith(
+ 'PixTableColumn: parameters `@ariaLabelDefaultSort`, `@ariaLabelSortDesc` and `@ariaLabelSortAsc` are required for sort buttons',
+ false,
+ {
+ id: 'pix-ui.pix-table-column.sortAriaLabels.required',
+ },
+ ),
+ );
+ });
+ });
});
});