Skip to content

Commit

Permalink
✨ feat: filter mission assessement on activities
Browse files Browse the repository at this point in the history
  • Loading branch information
yaf committed Oct 10, 2024
1 parent 7bf178d commit c488ced
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 6 deletions.
5 changes: 5 additions & 0 deletions api/src/school/application/mission-learner-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand Down
1 change: 1 addition & 0 deletions api/src/school/application/mission-learner-route.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({}),
}),
Expand Down
20 changes: 18 additions & 2 deletions api/src/school/domain/usecases/find-paginated-mission-learners.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { filterByGlobalResult, findPaginatedMissionLearners };
export { filterByGlobalResult, filterByStatuses, findPaginatedMissionLearners };

const findPaginatedMissionLearners = async function ({
missionLearnerRepository,
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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')),
Expand Down
Original file line number Diff line number Diff line change
@@ -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 = [];
Expand Down
18 changes: 18 additions & 0 deletions orga/app/controllers/authenticated/missions/mission/activities.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -35,6 +52,7 @@ export default class MissionActivitiesController extends Controller {
@action
onResetFilter() {
this.divisions = [];
this.statuses = [];
this.name = '';
}

Expand Down
2 changes: 2 additions & 0 deletions orga/app/routes/authenticated/missions/mission/activities.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default class MissionActivitiesRoute extends Route {
queryParams = {
divisions: { refreshModel: true },
name: { refreshModel: true },
statuses: { refreshModel: true },
pageNumber: {
refreshModel: true,
},
Expand Down Expand Up @@ -38,6 +39,7 @@ export default class MissionActivitiesRoute extends Route {
filter: {
divisions: params.divisions,
name: params.name,
statuses: params.statuses,
},
page: {
number: params.pageNumber,
Expand Down
11 changes: 11 additions & 0 deletions orga/app/templates/authenticated/missions/mission/activities.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,16 @@
@triggerFiltering={{this.onFilter}}
/>

<PixMultiSelect
@options={{this.statusOptions}}
@values={{this.statuses}}
@placeholder={{t "pages.missions.mission.table.activities.filters.status.label"}}
@onChange={{this.onSelectStatuses}}
@isSearchable={{false}}
@screenReaderOnly={{true}}
>
<:label>{{t "pages.missions.mission.table.activity.filters.status.label"}}</:label>
<:default as |option|>{{option.label}}</:default>
</PixMultiSelect>
</PixFilterBanner>
<Mission::ActivityTable @missionLearners={{this.model.missionLearners}} @mission={{this.model.mission.mission}} />
10 changes: 9 additions & 1 deletion orga/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 9 additions & 1 deletion orga/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit c488ced

Please sign in to comment.