Skip to content

Commit

Permalink
Ajoute des filtres sur le niveau de conformité pendant la génération (#…
Browse files Browse the repository at this point in the history
…479)

* add compliance level filter

* add content if there are no results with active filters

* revert compliance filters usage

* fix counters update

* Update AuditGenerationFilters.vue

* fix filtering order in store

* update no results message depending on reason: compliance filter, search or evaluated criteria checkbox

* update compliance filters main label

* use getter to get results

* update wording when no results from search

* handle complex filtering cases

* update changelog
  • Loading branch information
bellangerq authored Nov 2, 2023
1 parent e153215 commit 102c655
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 42 deletions.
6 changes: 6 additions & 0 deletions confiture-web-app/src/assets/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Tous les changements notables de Ara sont documentés ici avec leur date, leur catégorie (nouvelle fonctionnalité, correction de bug ou autre changement) et leur pull request (PR) associée.

## 02/11/2023

### Nouvelles fonctionnalités 🚀

- Ajout de filtres sur la conformité lors du remplissage de l’audit ([#479](https://github.com/DISIC/Ara/pull/479))

## 25/10/2023

### Autres changements ⚙️
Expand Down
81 changes: 80 additions & 1 deletion confiture-web-app/src/components/AuditGenerationFilters.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<script setup lang="ts">
import { computed, watch, nextTick } from "vue";
import { ref } from "vue";
import { useAuditStore, useFiltersStore, useResultsStore } from "../store";
import { pluralize } from "../utils";
import { CriteriumResultStatus } from "../types";
defineProps<{
topics: { title: string; number: number; value: number }[];
Expand Down Expand Up @@ -65,6 +67,25 @@ watch(
() => filterStore.hideEvaluatedCriteria,
() => filterStore.updateEvaluatedCriteria()
);
const compliantCount = computed(
() =>
resultStore.allResults?.filter(
(r) => r.status === CriteriumResultStatus.COMPLIANT
).length
);
const notCompliantCount = computed(
() =>
resultStore.allResults?.filter(
(r) => r.status === CriteriumResultStatus.NOT_COMPLIANT
).length
);
const notApplicableCount = computed(
() =>
resultStore.allResults?.filter(
(r) => r.status === CriteriumResultStatus.NOT_APPLICABLE
).length
);
</script>

<template>
Expand All @@ -90,7 +111,11 @@ watch(
</button>
</div>
<button
v-if="filterStore.search || filterStore.hideEvaluatedCriteria"
v-if="
filterStore.search ||
filterStore.hideEvaluatedCriteria ||
filterStore.complianceLevels.length
"
class="fr-btn fr-btn--tertiary-no-outline fr-icon-refresh-line fr-btn--icon-right fr-mb-4w"
@click="onGlobalReset"
>
Expand Down Expand Up @@ -171,6 +196,60 @@ watch(
</div>
</div>

<fieldset
id="checkboxes"
class="fr-fieldset"
aria-labelledby="complianceLevel"
>
<legend
id="complianceLevel"
class="fr-fieldset__legend--regular fr-fieldset__legend fr-text--bold"
>
Critères
</legend>
<div class="fr-fieldset__element">
<div class="fr-checkbox-group">
<input
id="compliance-level-compliant"
v-model="filterStore.complianceLevels"
:value="CriteriumResultStatus.COMPLIANT"
type="checkbox"
/>
<label class="fr-label" for="compliance-level-compliant">
Conforme ({{ compliantCount }})
</label>
</div>
</div>
<div class="fr-fieldset__element">
<div class="fr-checkbox-group">
<input
id="compliance-level-not-compliant"
v-model="filterStore.complianceLevels"
:value="CriteriumResultStatus.NOT_COMPLIANT"
type="checkbox"
/>
<label class="fr-label" for="compliance-level-not-compliant">
Non conforme ({{ notCompliantCount }})
</label>
</div>
</div>
<div class="fr-fieldset__element">
<div class="fr-checkbox-group">
<input
id="compliance-level-not-applicable"
v-model="filterStore.complianceLevels"
:value="CriteriumResultStatus.NOT_APPLICABLE"
type="checkbox"
/>
<label class="fr-label" for="compliance-level-not-applicable">
Non applicable ({{ notApplicableCount }})
</label>
</div>
</div>
</fieldset>

<hr />

<div class="fr-form-group">
<p id="anchor-nav-title" class="fr-text--regular fr-text--bold fr-mb-1w">
Thématiques de critères
Expand Down
115 changes: 87 additions & 28 deletions confiture-web-app/src/components/AuditGenerationPageCriteria.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { computed } from "vue";
import { AuditPage } from "../types";
import AuditGenerationCriterium from "./AuditGenerationCriterium.vue";
Expand All @@ -11,6 +13,34 @@ defineProps<{
}>();
const store = useFiltersStore();
const noResults = computed(() => {
if (store.hasNoResultsFromEvaluated) {
return {
title: "Tous les critères évalués ont été masqués",
description:
'Veuillez décocher le filtre "Masquer critères évalués" pour afficher de nouveau les critères.',
};
} else if (store.hasNoResultsFromComplianceLevel) {
return {
title: "Aucun résultat ne correspond à votre recherche",
description:
'Veuillez sélectionner un filtre "Critères" comportant au moins un critère.',
};
} else if (store.hasNoResultsFromSearch && !store.hideEvaluatedCriteria) {
return {
title: "Aucun résultat ne correspond à votre recherche",
description:
"Le système de recherche par mots clés s'applique uniquement à l’intitulé des critères.",
};
} else {
return {
title: "Tous les critères évalués ont été masqués",
description:
'Veuillez décocher le filtre "Masquer critères évalués" pour afficher de nouveau les critères.',
};
}
});
</script>

<template>
Expand All @@ -21,35 +51,64 @@ const store = useFiltersStore();
</a>
</div>

<section
v-for="topic in store.filteredTopics"
:key="topic.number"
class="fr-mb-6w"
>
<div class="fr-mb-3w topic-header">
<h3 :id="topic.number" class="fr-m-0 topic-heading">
{{ topic.number }}. {{ topic.topic }}
</h3>
<NotApplicableSwitch :page-id="page.id" :topic-number="topic.number" />
</div>
<ol class="fr-p-0 fr-m-0">
<AuditGenerationCriterium
v-for="criterium in topic.criteria"
:key="criterium.criterium.number"
:page="page"
class="fr-mb-3w"
:criterium="criterium.criterium"
:topic-number="topic.number"
:audit-unique-id="auditUniqueId"
/>
</ol>
<template v-if="store.filteredTopics.length">
<section
v-for="topic in store.filteredTopics"
:key="topic.number"
class="fr-mb-6w"
>
<div class="fr-mb-3w topic-header">
<h3 :id="topic.number" class="fr-m-0 topic-heading">
{{ topic.number }}. {{ topic.topic }}
</h3>
<NotApplicableSwitch :page-id="page.id" :topic-number="topic.number" />
</div>
<ol class="fr-p-0 fr-m-0">
<AuditGenerationCriterium
v-for="criterium in topic.criteria"
:key="criterium.criterium.number"
:page="page"
class="fr-mb-3w"
:criterium="criterium.criterium"
:topic-number="topic.number"
:audit-unique-id="auditUniqueId"
/>
</ol>

<div class="fr-grid-row fr-grid-row--right">
<a
class="fr-link fr-icon-arrow-up-fill fr-link--icon-left"
href="#main"
>
Haut de page
</a>
</div>
</section>
</template>

<div class="fr-grid-row fr-grid-row--right">
<a class="fr-link fr-icon-arrow-up-fill fr-link--icon-left" href="#main">
Haut de page
</a>
</div>
</section>
<div aria-live="polite" role="alert">
<section v-if="!store.filteredTopics.length">
<h2 class="fr-h6 fr-mb-1w">
{{ noResults.title }}
</h2>
<p>{{ noResults.description }}</p>

<template
v-if="
store.hasNoResultsFromSearch &&
!store.hideEvaluatedCriteria &&
!store.hasNoResultsFromEvaluated &&
!store.hasNoResultsFromComplianceLevel
"
>
<p><strong>Suggestions :</strong></p>
<ul>
<li>Vérifiez l’orthographe des termes de recherche</li>
<li>Essayez un autre mot</li>
</ul>
</template>
</section>
</div>
</template>

<style scoped>
Expand Down
99 changes: 86 additions & 13 deletions confiture-web-app/src/store/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface FiltersStoreState {
hideEvaluatedCriteria: boolean;
hideTestsAndReferences: boolean;
newEvaluatedCriteria: string[];
complianceLevels: CriteriumResultStatus[];
}

export const useFiltersStore = defineStore("filters", {
Expand All @@ -18,6 +19,7 @@ export const useFiltersStore = defineStore("filters", {
hideEvaluatedCriteria: false,
hideTestsAndReferences: false,
newEvaluatedCriteria: [],
complianceLevels: [],
}),
getters: {
/** Filter topics by topic name and by search. */
Expand Down Expand Up @@ -64,30 +66,101 @@ export const useFiltersStore = defineStore("filters", {
* - topic title ("Images")
* - criteria title ("Dans chaque page web, l’ouverture...")
* - audit type (fast, complementary, full)
* - result (compliant, not compliant, not applicable)
*/
filteredTopics = filteredTopics.map((t) => {
return {
...t,
criteria: t.criteria.filter(
(c: any) =>
// audit type filter
!!CRITERIA_BY_AUDIT_TYPE[auditType].find(
(fc) =>
fc.criterium === c.criterium.number && fc.topic === t.number
) &&
// search filter
(c.criterium.title
.toLowerCase()
.includes(this.search.toLowerCase()) ||
t.topic.toLowerCase().includes(this.search.toLocaleLowerCase()))
),
criteria: t.criteria
.map((c: any) => {
return {
...c,
status:
resultStore.data?.[auditStore.currentPageId!]?.[t.number]?.[
c.criterium.number
]?.status,
};
})
.filter(
(c: any) =>
// audit type filter
!!CRITERIA_BY_AUDIT_TYPE[auditType].find(
(fc) =>
fc.criterium === c.criterium.number && fc.topic === t.number
) &&
// status
(this.complianceLevels.length
? this.complianceLevels.includes(c.status)
: !this.complianceLevels.includes(c.status)) &&
// search filter
(c.criterium.title
.toLowerCase()
.includes(this.search.toLowerCase()) ||
t.topic
.toLowerCase()
.includes(this.search.toLocaleLowerCase()))
),
};
});

filteredTopics = filteredTopics.filter((t) => t.criteria.length);

return filteredTopics;
},
hasNoResultsFromSearch(): boolean {
if (!this.search) {
return false;
}

return !this.filteredTopics.some((t) => {
return (
t.topic.toLowerCase().includes(this.search.toLocaleLowerCase()) ||
t.criteria.some((c: any) => {
return c.criterium.title
.toLowerCase()
.includes(this.search.toLowerCase());
})
);
});
},
hasNoResultsFromComplianceLevel(): boolean {
if (!this.complianceLevels.length) {
return false;
}

const auditStore = useAuditStore();
const resultStore = useResultsStore();

const pageResults = resultStore.data?.[auditStore.currentPageId!];

return Object.values(pageResults!)
.map((topic) => {
return Object.values(topic).map((c) => c.status);
})
.flat(2)
.every((status) => {
return !this.complianceLevels.includes(status);
});
},
hasNoResultsFromEvaluated(): boolean {
if (!this.hideEvaluatedCriteria) {
return false;
}

const auditStore = useAuditStore();
const resultStore = useResultsStore();

const pageResults = resultStore.data?.[auditStore.currentPageId!];

return Object.values(pageResults!)
.map((topic) => {
return Object.values(topic).map((c) => c.status);
})
.flat(2)
.every((status) => {
return status !== CriteriumResultStatus.NOT_TESTED;
});
},
},
actions: {
updateEvaluatedCriteria() {
Expand Down

0 comments on commit 102c655

Please sign in to comment.