diff --git a/api/src/school/application/mission-learner-controller.js b/api/src/school/application/mission-learner-controller.js
index c3a965fcee7..62a86997d05 100644
--- a/api/src/school/application/mission-learner-controller.js
+++ b/api/src/school/application/mission-learner-controller.js
@@ -11,6 +11,11 @@ const findPaginatedMissionLearners = async function (request) {
if (filter.results && !Array.isArray(filter.results)) {
filter.results = [filter.results];
}
+
+ if (filter.statuses && !Array.isArray(filter.statuses)) {
+ filter.statuses = [filter.statuses];
+ }
+
const result = await usecases.findPaginatedMissionLearners({ organizationId, missionId, page, filter });
return missionLearnerSerializer.serialize(result);
};
diff --git a/api/src/school/application/mission-learner-route.js b/api/src/school/application/mission-learner-route.js
index f337e26f9b8..07f75ba8ddf 100644
--- a/api/src/school/application/mission-learner-route.js
+++ b/api/src/school/application/mission-learner-route.js
@@ -27,6 +27,7 @@ const register = async function (server) {
filter: Joi.object({
divisions: [Joi.string(), Joi.array().items(Joi.string())],
results: [Joi.string(), Joi.array().items(Joi.string())],
+ statuses: [Joi.string(), Joi.array().items(Joi.string())],
name: Joi.string().empty(''),
}).default({}),
}),
diff --git a/api/src/school/domain/usecases/find-paginated-mission-learners.js b/api/src/school/domain/usecases/find-paginated-mission-learners.js
index 1f2c52025ee..24565a498a1 100644
--- a/api/src/school/domain/usecases/find-paginated-mission-learners.js
+++ b/api/src/school/domain/usecases/find-paginated-mission-learners.js
@@ -1,4 +1,4 @@
-export { filterByGlobalResult, findPaginatedMissionLearners };
+export { filterByGlobalResult, filterByStatuses, findPaginatedMissionLearners };
const findPaginatedMissionLearners = async function ({
missionLearnerRepository,
@@ -18,9 +18,25 @@ const findPaginatedMissionLearners = async function ({
missionLearners,
);
- return _paginateMissionLearner(filterByGlobalResult(missionLearnersWithStatus, filter.results), page);
+ const missionLearnerWithStatusFilteredByGlobalResult = filterByGlobalResult(
+ missionLearnersWithStatus,
+ filter.results,
+ );
+ const missionLearnerWithStatusFilteredByGlobalResultAndStatuses = filterByStatuses(
+ missionLearnerWithStatusFilteredByGlobalResult,
+ filter.statuses,
+ );
+ return _paginateMissionLearner(missionLearnerWithStatusFilteredByGlobalResultAndStatuses, page);
};
+function filterByStatuses(missionLearners, statusesFilter) {
+ console.log('YAF DEBUG !', statusesFilter);
+ if (!statusesFilter) {
+ return missionLearners;
+ }
+ return missionLearners.filter((missionLearner) => statusesFilter.includes(missionLearner.missionStatus));
+}
+
function filterByGlobalResult(missionLearners, resultFilter) {
if (!resultFilter) {
return missionLearners;
diff --git a/api/tests/school/unit/application/mission-learner-route_test.js b/api/tests/school/unit/application/mission-learner-route_test.js
index 42ab844347f..a15bcd5bef9 100644
--- a/api/tests/school/unit/application/mission-learner-route_test.js
+++ b/api/tests/school/unit/application/mission-learner-route_test.js
@@ -33,7 +33,7 @@ describe('Unit | Route | mission-learner-route', function () {
// when
const response = await httpTestServer.request(
'GET',
- `/api/organizations/4/missions/1/learners?filter[name]=Henry&filter[divisions][]=CM2-C&filter[divisions][]=CM2-B&page[number]=1&page[size]=25&filter[results][]=exceeded`,
+ `/api/organizations/4/missions/1/learners?filter[name]=Henry&filter[divisions][]=CM2-C&filter[divisions][]=CM2-B&page[number]=1&page[size]=25&filter[results][]=exceeded&filter[statuses][]=completed`,
);
// then
@@ -45,6 +45,7 @@ describe('Unit | Route | mission-learner-route', function () {
'filter',
sinon.match.has('divisions', ['CM2-C', 'CM2-B']),
sinon.match.has('results', ['exceeded']),
+ sinon.match.has('statuses', ['completed']),
sinon.match.has('name', 'Henry'),
),
sinon.match.has('page', sinon.match.has('number', '1'), sinon.match.has('size', '25')),
diff --git a/api/tests/school/unit/domain/usecases/find-paginated-mission-learners_test.js b/api/tests/school/unit/domain/usecases/find-paginated-mission-learners_test.js
index 837b6196ad4..9d0a4e49f04 100644
--- a/api/tests/school/unit/domain/usecases/find-paginated-mission-learners_test.js
+++ b/api/tests/school/unit/domain/usecases/find-paginated-mission-learners_test.js
@@ -1,8 +1,38 @@
import { MissionLearner } from '../../../../../src/school/domain/models/MissionLearner.js';
-import { filterByGlobalResult } from '../../../../../src/school/domain/usecases/find-paginated-mission-learners.js';
+import {
+ filterByGlobalResult,
+ filterByStatuses,
+} from '../../../../../src/school/domain/usecases/find-paginated-mission-learners.js';
import { expect } from '../../../../test-helper.js';
describe('Unit | Domain | Use Cases | find-paginated-mission-learners', function () {
+ context('filterByStatuses', function () {
+ it('with empty mission learners, returns empty filtered array', function () {
+ const filter = [];
+ const missionLearners = [];
+ const filteredMissionLearners = filterByStatuses(missionLearners, filter);
+
+ expect(filteredMissionLearners).to.deep.equals([]);
+ });
+
+ it('should returns mission learner corresponding to the status filter', function () {
+ const notStartedMissionAssessement = new MissionLearner({
+ missionStatus: 'not-started',
+ });
+ const completedMissionAssessement = new MissionLearner({
+ missionStatus: 'completed',
+ });
+ const startedMissionAssessement = new MissionLearner({
+ missionStatus: 'started',
+ });
+
+ const missionLearners = [notStartedMissionAssessement, completedMissionAssessement, startedMissionAssessement];
+ const statusFilter = ['completed'];
+ const filteredMissionLearners = filterByStatuses(missionLearners, statusFilter);
+
+ expect(filteredMissionLearners).to.deep.equals([completedMissionAssessement]);
+ });
+ });
context('filterByGlobalResult', function () {
it('with empty mission learners, returns empty filtered array', function () {
const filterGlobalResults = [];
diff --git a/orga/app/controllers/authenticated/missions/mission/activities.js b/orga/app/controllers/authenticated/missions/mission/activities.js
index 6c9e6884a39..7207ab7b32c 100644
--- a/orga/app/controllers/authenticated/missions/mission/activities.js
+++ b/orga/app/controllers/authenticated/missions/mission/activities.js
@@ -7,11 +7,22 @@ const DEFAULT_PAGE_NUMBER = 1;
export default class MissionActivitiesController extends Controller {
@service router;
+ @service intl;
@tracked pageNumber = DEFAULT_PAGE_NUMBER;
@tracked pageSize = 25;
@tracked divisions = [];
+ @tracked statuses = [];
+ @tracked statusOptions = [
+ { value: 'completed', label: this.translateResultOptionKey('completed') },
+ { value: 'started', label: this.translateResultOptionKey('started') },
+ { value: 'not-started', label: this.translateResultOptionKey('not-started') },
+ ];
@tracked name = '';
+ translateResultOptionKey(key) {
+ return this.intl.t(`pages.missions.mission.table.activities.filters.status.options.${key}`);
+ }
+
get learnersCount() {
return this.model.missionLearners.meta.rowCount;
}
@@ -27,6 +38,12 @@ export default class MissionActivitiesController extends Controller {
this.pageNumber = null;
}
+ @action
+ onSelectStatuses(status) {
+ this.statuses = status;
+ this.pageNumber = null;
+ }
+
@action
onFilter(inputText, value) {
this[inputText] = value;
@@ -35,6 +52,7 @@ export default class MissionActivitiesController extends Controller {
@action
onResetFilter() {
this.divisions = [];
+ this.statuses = [];
this.name = '';
}
diff --git a/orga/app/routes/authenticated/missions/mission/activities.js b/orga/app/routes/authenticated/missions/mission/activities.js
index 46412defe1f..9f3f3c9316e 100644
--- a/orga/app/routes/authenticated/missions/mission/activities.js
+++ b/orga/app/routes/authenticated/missions/mission/activities.js
@@ -10,6 +10,7 @@ export default class MissionActivitiesRoute extends Route {
queryParams = {
divisions: { refreshModel: true },
name: { refreshModel: true },
+ statuses: { refreshModel: true },
pageNumber: {
refreshModel: true,
},
@@ -38,6 +39,7 @@ export default class MissionActivitiesRoute extends Route {
filter: {
divisions: params.divisions,
name: params.name,
+ statuses: params.statuses,
},
page: {
number: params.pageNumber,
diff --git a/orga/app/templates/authenticated/missions/mission/activities.hbs b/orga/app/templates/authenticated/missions/mission/activities.hbs
index 11745381e13..bd20a099a7d 100644
--- a/orga/app/templates/authenticated/missions/mission/activities.hbs
+++ b/orga/app/templates/authenticated/missions/mission/activities.hbs
@@ -20,5 +20,16 @@
@triggerFiltering={{this.onFilter}}
/>
+
+ <:label>{{t "pages.missions.mission.table.activity.filters.status.label"}}
+ <:default as |option|>{{option.label}}
+
\ No newline at end of file
diff --git a/orga/translations/en.json b/orga/translations/en.json
index 3fb0dd012f0..9601386e13b 100644
--- a/orga/translations/en.json
+++ b/orga/translations/en.json
@@ -918,7 +918,15 @@
"caption": "List of students with their activity for the mission {missionName}",
"filters": {
"aria-label": "Filter on students",
- "learners-count": "{count, plural, =0 {No student} =1 {1 student} other {{count} students}}"
+ "learners-count": "{count, plural, =0 {No student} =1 {1 student} other {{count} students}}",
+ "status": {
+ "label": "Status de la mission",
+ "options": {
+ "completed": "Completed",
+ "not-started": "Not started",
+ "started": "Started"
+ }
+ }
},
"headers": {
"division": "Division",
diff --git a/orga/translations/fr.json b/orga/translations/fr.json
index 8dc0cd45b33..73b42ccba93 100644
--- a/orga/translations/fr.json
+++ b/orga/translations/fr.json
@@ -926,7 +926,15 @@
"caption": "Tableau des élèves avec leur participation à la mission {missionName}",
"filters": {
"aria-label": "Filtre sur les élèves",
- "learners-count": "{count, plural, =0 {Aucun élève} =1 {1 élève} other {{count} élèves}}"
+ "learners-count": "{count, plural, =0 {Aucun élève} =1 {1 élève} other {{count} élèves}}",
+ "status": {
+ "label": "Status de la mission",
+ "options": {
+ "completed": "Complété",
+ "not-started": "Non démarré",
+ "started": "Démmarré"
+ }
+ }
},
"headers": {
"division": "Classe",