From c8cee22dfc16364f5fdd7a270660226575b96206 Mon Sep 17 00:00:00 2001 From: Alexandre Monney Date: Fri, 13 Dec 2024 11:57:13 +0100 Subject: [PATCH 1/2] feat(orga): add filter on statistics page Co-authored-by: Vincent Hardouin --- orga/app/components/statistics/index.gjs | 74 +++++++++++++++++-- orga/app/styles/components/statistics.scss | 7 ++ .../components/statistics/index-test.gjs | 60 ++++++++++++++- orga/translations/en.json | 4 +- orga/translations/fr.json | 4 +- orga/translations/nl.json | 2 + 6 files changed, 140 insertions(+), 11 deletions(-) diff --git a/orga/app/components/statistics/index.gjs b/orga/app/components/statistics/index.gjs index 037caa49e06..137871def56 100644 --- a/orga/app/components/statistics/index.gjs +++ b/orga/app/components/statistics/index.gjs @@ -1,6 +1,9 @@ +import PixButton from '@1024pix/pix-ui/components/pix-button'; import PixPagination from '@1024pix/pix-ui/components/pix-pagination'; +import PixSelect from '@1024pix/pix-ui/components/pix-select'; import { service } from '@ember/service'; import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; import dayjs from 'dayjs'; import { t } from 'ember-intl'; @@ -11,12 +14,48 @@ import TagLevel from './tag-level'; export default class Statistics extends Component { @service router; + @tracked currentDomainFilter = null; + get analysisByTubes() { return this.args.model.data.sort( (a, b) => a.competence_code.localeCompare(b.competence_code) || a.sujet.localeCompare(b.sujet), ); } + get analysisByDomains() { + return this.analysisByTubes.reduce((acc, line) => { + const domain = line.domaine; + if (acc[domain]) { + acc[domain].push(line); + } else { + acc[domain] = [line]; + } + return acc; + }, {}); + } + + get currentAnalysis() { + if (this.currentDomainFilter !== null) { + return this.analysisByDomains[this.currentDomainFilter]; + } + return this.analysisByTubes; + } + + get currentVisibleAnalysis() { + const start = this.pageSize * (this.page - 1); + const end = this.pageSize * this.page; + return this.currentAnalysis.slice(start, end); + } + + get domainsName() { + return Object.keys(this.analysisByDomains).map((value) => { + return { + label: value, + value, + }; + }); + } + get pageSize() { return Number(this.router.currentRoute?.queryParams?.pageSize) || 10; } @@ -29,16 +68,20 @@ export default class Statistics extends Component { return { page: this.page, pageSize: this.pageSize, - rowCount: this.analysisByTubes.length, - pageCount: Math.ceil(this.analysisByTubes.length / this.pageSize), + rowCount: this.currentAnalysis.length, + pageCount: Math.ceil(this.currentAnalysis.length / this.pageSize), }; } - get visibleAnalysisByTubes() { - const start = this.pageSize * (this.page - 1); - const end = this.pageSize * this.page; - return this.analysisByTubes.slice(start, end); - } + handleDomainFilter = (domain) => { + this.currentDomainFilter = domain; + this.router.replaceWith({ queryParams: { pageNumber: 1 } }); + }; + + removeFilter = () => { + this.currentDomainFilter = null; + this.router.replaceWith({ queryParams: { pageNumber: 1 } }); + }; get extractedDate() { return dayjs(this.analysisByTubes[0]?.extraction_date).format('D MMM YYYY'); @@ -51,6 +94,21 @@ export default class Statistics extends Component { {{this.extractedDate}} +
+ + <:label>{{t "pages.statistics.select-label"}} + + {{t + "common.filters.actions.clear" + }} +
+
@@ -67,7 +125,7 @@ export default class Statistics extends Component { - {{#each this.visibleAnalysisByTubes as |line|}} + {{#each this.currentVisibleAnalysis as |line|}} diff --git a/orga/app/styles/components/statistics.scss b/orga/app/styles/components/statistics.scss index 998806bea08..07e5bf0719e 100644 --- a/orga/app/styles/components/statistics.scss +++ b/orga/app/styles/components/statistics.scss @@ -16,3 +16,10 @@ } } } + +.statistics-page__filter { + display: flex; + gap: var(--pix-spacing-4x); + align-items: end; + margin-bottom: var(--pix-spacing-8x); +} diff --git a/orga/tests/integration/components/statistics/index-test.gjs b/orga/tests/integration/components/statistics/index-test.gjs index ae09c07810f..278d65369bb 100644 --- a/orga/tests/integration/components/statistics/index-test.gjs +++ b/orga/tests/integration/components/statistics/index-test.gjs @@ -1,5 +1,6 @@ -import { render } from '@1024pix/ember-testing-library'; +import { clickByName, render } from '@1024pix/ember-testing-library'; import Service from '@ember/service'; +import { click } from '@ember/test-helpers'; import dayjs from 'dayjs'; import { t } from 'ember-intl/test-support'; import Statistics from 'pix-orga/components/statistics/index'; @@ -55,6 +56,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { const model = { data: [ { + domaine: '2. Communication et collaboration', competence_code: '2.1', competence: 'Interagir', sujet: 'Gérer ses contacts', @@ -79,6 +81,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { const model = { data: [ { + domaine: '2. Communication et collaboration', competence_code: '2.1', competence: 'Interagir', sujet: 'Gérer ses contacts', @@ -86,6 +89,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { niveau_par_sujet: '1.50', }, { + domaine: '2. Communication et collaboration', competence_code: '2.1', competence: 'Interagir', sujet: 'Gérer ses contacts', @@ -117,6 +121,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { const model = { data: [ { + domaine: '2. Communication et collaboration', competence_code: '2.1', competence: 'Interagir', sujet: 'Gérer ses contacts', @@ -124,6 +129,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { niveau_par_sujet: '1.50', }, { + domaine: '2. Communication et collaboration', competence_code: '2.1', competence: 'Interagir', sujet: 'Gérer ses contacts', @@ -154,6 +160,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { const model = { data: [ { + domaine: '2. Communication et collaboration', competence_code: '2.1', competence: 'Foo', sujet: 'Gérer ses contacts', @@ -161,6 +168,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { niveau_par_sujet: '1.50', }, { + domaine: '2. Communication et collaboration', competence_code: '2.1', competence: 'Interagir', sujet: 'Gérer ses contacts', @@ -187,4 +195,54 @@ module('Integration | Component | Statistics | Index', function (hooks) { assert.ok(screen.getByRole('cell', { name: t('pages.statistics.level.novice') })); }); }); + + module('filter', function () { + test('should filtered analysis', async function (assert) { + //given + const model = { + data: [ + { + domaine: '1. Information et données', + competence_code: '1.1 ', + competence: 'Mener une recherche et une veille d’information', + sujet: "Indices de qualité d'une page web", + niveau_par_user: '1.30', + niveau_par_sujet: '1.50', + }, + { + domaine: '2. Communication et collaboration', + competence_code: '2.1', + competence: 'Interagir', + sujet: 'Gérer ses contacts', + niveau_par_user: '1.30', + niveau_par_sujet: '1.50', + }, + ], + }; + + //when + const screen = await render(); + + //then + assert.ok(screen.getByText(t('common.pagination.page-results', { total: 2 }))); + + // when + const select = screen.getByRole('button', { name: t('pages.statistics.select-label') }); + await click(select); + const option = await screen.findByRole('option', { name: '2. Communication et collaboration' }); + await click(option); + + // then + assert.ok(screen.getByText(t('common.pagination.page-results', { total: 1 }))); + assert.ok(screen.getByRole('cell', { name: '2.1 Interagir' })); + assert.ok(screen.getByRole('cell', { name: 'Gérer ses contacts' })); + assert.ok(screen.getByRole('cell', { name: t('pages.statistics.level.novice') })); + + // when + await clickByName(t('common.filters.actions.clear')); + + // then + assert.ok(screen.getByText(t('common.pagination.page-results', { total: 2 }))); + }); + }); }); diff --git a/orga/translations/en.json b/orga/translations/en.json index f369afdc9a2..75a7c47c6e1 100644 --- a/orga/translations/en.json +++ b/orga/translations/en.json @@ -228,7 +228,8 @@ "label": "Search by last name and first name", "placeholder": "Last name, first name" }, - "loading": "Loading..." + "loading": "Loading...", + "placeholder": "-- Select --" }, "form": { "mandatory-all-fields": "All fields are required.", @@ -1473,6 +1474,7 @@ "independent": "independent", "novice": "novice" }, + "select-label": "Domain", "table": { "caption": "This table displays the analysis of all participants' results by topic. For each line, it shows the skill, the topic, the coverage rate and the level achieved.", "headers": { diff --git a/orga/translations/fr.json b/orga/translations/fr.json index afc61303408..ba8213d16e4 100644 --- a/orga/translations/fr.json +++ b/orga/translations/fr.json @@ -228,7 +228,8 @@ "label": "Recherche sur le nom et prénom", "placeholder": "Nom, prénom" }, - "loading": "Chargement..." + "loading": "Chargement...", + "placeholder": "-- Sélectionner --" }, "form": { "mandatory-all-fields": "Tous les champs sont obligatoires.", @@ -1479,6 +1480,7 @@ "independent": "indépendant", "novice": "novice" }, + "select-label": "Domaine", "table": { "caption": "Ce tableau affiche l'analyse des résultats de tous les participants par sujets. Il indique pour chaque ligne la compétence, le sujet, le taux de couverture ainsi que le niveau atteint", "headers": { diff --git a/orga/translations/nl.json b/orga/translations/nl.json index 8bfdef2f218..92152c6e15a 100644 --- a/orga/translations/nl.json +++ b/orga/translations/nl.json @@ -228,6 +228,7 @@ "placeholder": "Achternaam, voornaam" }, "loading": "Laden...", + "placeholder": "-- Selecteer --", "title": "Filters" }, "form": { @@ -1462,6 +1463,7 @@ "title": "{count, plural, =0 {Studenten} =1 {Studenten ({count})} other {studenten ({count})}}" }, "statistics": { + "select-label": "Domein", "title": "Statistieken", "before-date": "op", "gauge": { From abcc9a3200b0b4b5bdc1cf1b1eb421619965f54b Mon Sep 17 00:00:00 2001 From: Alexandre Monney Date: Fri, 13 Dec 2024 15:25:27 +0100 Subject: [PATCH 2/2] refactor(orga): use common placeholder translation --- orga/app/components/attestations/sixth-grade.gjs | 2 +- .../components/attestations/sixth-grade-test.gjs | 2 +- .../components/statistics/index-test.gjs | 16 ++++++++++++++-- orga/translations/en.json | 1 - orga/translations/fr.json | 1 - orga/translations/nl.json | 1 - 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/orga/app/components/attestations/sixth-grade.gjs b/orga/app/components/attestations/sixth-grade.gjs index 88a2e7b5841..3fa85a3ed77 100644 --- a/orga/app/components/attestations/sixth-grade.gjs +++ b/orga/app/components/attestations/sixth-grade.gjs @@ -38,7 +38,7 @@ export default class AttestationsSixthGrade extends Component { @options={{@divisions}} @values={{this.selectedDivisions}} @onChange={{this.onSelectDivision}} - @placeholder={{t "pages.attestations.placeholder"}} + @placeholder={{t "common.filters.placeholder"}} > <:label>{{t "pages.attestations.select-label"}} <:default as |option|>{{option.label}} diff --git a/orga/tests/integration/components/attestations/sixth-grade-test.gjs b/orga/tests/integration/components/attestations/sixth-grade-test.gjs index ff076bdeecb..d7bacc68743 100644 --- a/orga/tests/integration/components/attestations/sixth-grade-test.gjs +++ b/orga/tests/integration/components/attestations/sixth-grade-test.gjs @@ -21,7 +21,7 @@ module('Integration | Component | Attestations | Sixth-grade', function (hooks) assert.ok(screen.getByRole('heading', { name: t('pages.attestations.title') })); assert.ok(screen.getByText(t('pages.attestations.description'))); assert.ok(screen.getByRole('textbox', { name: t('pages.attestations.select-label') })); - assert.ok(screen.getByPlaceholderText(t('pages.attestations.placeholder'))); + assert.ok(screen.getByPlaceholderText(t('common.filters.placeholder'))); assert.ok(screen.getByRole('button', { name: t('pages.attestations.download-attestations-button') })); }); diff --git a/orga/tests/integration/components/statistics/index-test.gjs b/orga/tests/integration/components/statistics/index-test.gjs index 278d65369bb..40459b160c2 100644 --- a/orga/tests/integration/components/statistics/index-test.gjs +++ b/orga/tests/integration/components/statistics/index-test.gjs @@ -219,12 +219,24 @@ module('Integration | Component | Statistics | Index', function (hooks) { }, ], }; + class Router extends Service { + currentRoute = { + queryParams: { + pageSize: 1, + pageNumber: 2, + }, + }; + replaceWith = ({ queryParams }) => { + this.currentRoute.queryParams.pageNumber = queryParams.pageNumber; + }; + } + this.owner.register('service:router', Router); //when const screen = await render(); //then - assert.ok(screen.getByText(t('common.pagination.page-results', { total: 2 }))); + assert.ok(screen.getByText(t('common.pagination.page-info', { start: 2, end: 2, total: 2 }))); // when const select = screen.getByRole('button', { name: t('pages.statistics.select-label') }); @@ -242,7 +254,7 @@ module('Integration | Component | Statistics | Index', function (hooks) { await clickByName(t('common.filters.actions.clear')); // then - assert.ok(screen.getByText(t('common.pagination.page-results', { total: 2 }))); + assert.ok(screen.getByText(t('common.pagination.page-info', { start: 1, end: 1, total: 2 }))); }); }); }); diff --git a/orga/translations/en.json b/orga/translations/en.json index 75a7c47c6e1..d64171bbe46 100644 --- a/orga/translations/en.json +++ b/orga/translations/en.json @@ -421,7 +421,6 @@ "description": "Select the class for which you wish to export attestations in PDF format.", "download-attestations-button": "Download", "no-attestations": "No attestation available", - "placeholder": "-- Select --", "select-label": "Select one or more classes" }, "campaign": { diff --git a/orga/translations/fr.json b/orga/translations/fr.json index ba8213d16e4..6bbfb2479f7 100644 --- a/orga/translations/fr.json +++ b/orga/translations/fr.json @@ -427,7 +427,6 @@ "description": "Sélectionnez la classe pour laquelle vous souhaitez exporter les attestations au format PDF.", "download-attestations-button": "Télécharger", "no-attestations": "Aucune attestation disponible pour votre sélection", - "placeholder": "-- Sélectionner --", "select-label": "Sélectionnez une ou plusieurs classes" }, "campaign": { diff --git a/orga/translations/nl.json b/orga/translations/nl.json index 92152c6e15a..fac6c1e0834 100644 --- a/orga/translations/nl.json +++ b/orga/translations/nl.json @@ -421,7 +421,6 @@ "title": "Certificaten", "description": "Selecteer de klas waarvoor je de attesten in PDF-formaat wilt exporteren.", "download-attestations-button": "Downloaden", - "placeholder": "-- Selecteer --", "select-label": "Selecteer een of meer klassen" }, "campaign-activity": {
{{t "pages.statistics.table.caption"}}
{{line.competence_code}} {{line.competence}} {{line.sujet}}