diff --git a/CHANGELOG.md b/CHANGELOG.md index b4e42bcf..7270087a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. +## 17/10/2024 + +### Nouvelles fonctionnalités 🚀 + +- Modifie la gestion des éléments transverses : l’interrupteur "Sur toutes les pages" est remplacé par l’onglet "Éléments transverses" qui permet d’évaluer les éléments communs à toutes les pages : en-tête, pied de page... ([#758](https://github.com/DISIC/Ara/pull/758)) + ## 09/10/2024 ### Corrections 🐛 diff --git a/confiture-rest-api/prisma/migrations/20240911153613_add_transverse_elements_page/migration.sql b/confiture-rest-api/prisma/migrations/20240911153613_add_transverse_elements_page/migration.sql new file mode 100644 index 00000000..7e68796c --- /dev/null +++ b/confiture-rest-api/prisma/migrations/20240911153613_add_transverse_elements_page/migration.sql @@ -0,0 +1,25 @@ +-- AlterTable +ALTER TABLE "Audit" ADD COLUMN "transverseElementsPageId" INTEGER; + +-- Create one transverse elements page for each existing audit and link it +DO $$ +DECLARE temprow RECORD; +DECLARE transversePageId "AuditedPage"."id"%TYPE; +BEGIN FOR temprow IN + SELECT * FROM "Audit" WHERE "transverseElementsPageId" IS NULL + LOOP + -- Crée la page élément transverse + INSERT INTO "AuditedPage"("name", "url", "order") VALUES ('Éléments transverses (optionnel)', '', -1) RETURNING "id" INTO transversePageId; + -- Lie la page à l'audit + UPDATE "Audit" SET "transverseElementsPageId" = transversePageId WHERE "id" = "temprow"."id"; + END LOOP; +END $$; + +-- Make transverseElementsPageId not nullable +ALTER TABLE "Audit" ALTER COLUMN "transverseElementsPageId" SET NOT NULL; + +-- CreateIndex +CREATE UNIQUE INDEX "Audit_transverseElementsPageId_key" ON "Audit"("transverseElementsPageId"); + +-- AddForeignKey +ALTER TABLE "Audit" ADD CONSTRAINT "Audit_transverseElementsPageId_fkey" FOREIGN KEY ("transverseElementsPageId") REFERENCES "AuditedPage"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/confiture-rest-api/prisma/schema.prisma b/confiture-rest-api/prisma/schema.prisma index 7edb012f..cbf4388e 100644 --- a/confiture-rest-api/prisma/schema.prisma +++ b/confiture-rest-api/prisma/schema.prisma @@ -49,7 +49,10 @@ model Audit { auditType AuditType procedureName String /// @DtoEntityHidden - pages AuditedPage[] + pages AuditedPage[] @relation("UserPages") + // single page for transverse elements + transverseElementsPage AuditedPage @relation("TransversePage", fields: [transverseElementsPageId], references: [id]) + transverseElementsPageId Int @unique auditorName String? auditorEmail String? showAuditorEmailInReport Boolean @default(false) @@ -111,9 +114,14 @@ model AuditedPage { name String url String - audit Audit? @relation(fields: [auditUniqueId], references: [editUniqueId], onDelete: Cascade) + // parent audit when the page is a user made page + audit Audit? @relation(name: "UserPages", fields: [auditUniqueId], references: [editUniqueId], onDelete: Cascade) auditUniqueId String? + // parent audit when the page is a transverse page + auditTransverse Audit? @relation(name: "TransversePage") + + results CriterionResult[] } diff --git a/confiture-rest-api/src/audits/audit-export.service.ts b/confiture-rest-api/src/audits/audit-export.service.ts index 3f8a21a0..d3258985 100644 --- a/confiture-rest-api/src/audits/audit-export.service.ts +++ b/confiture-rest-api/src/audits/audit-export.service.ts @@ -38,7 +38,11 @@ export class AuditExportService { const data = []; // Column headers - data.push(["Critères", ...audit.pages.map((p) => p.name)]); + data.push([ + "Critères", + "Éléments transverses", + ...audit.pages.map((p) => p.name) + ]); const resultsByCriteria = groupBy( results, @@ -50,6 +54,13 @@ export class AuditExportService { // Tests results criteria.forEach((c) => { const criterionKey = c.topic + "." + c.criterium; + + const transverseStatus = + CRITERIUM_STATUS[ + resultsByCriteria[criterionKey].find( + (r) => r.pageId === audit.transverseElementsPageId + ).status + ]; const criteriumStatuses = audit.pages.map( (p) => CRITERIUM_STATUS[ @@ -57,7 +68,7 @@ export class AuditExportService { .status ] ); - data.push([criterionKey, ...criteriumStatuses]); + data.push([criterionKey, transverseStatus, ...criteriumStatuses]); }); // compile data to CSV buffer diff --git a/confiture-rest-api/src/audits/audit.service.ts b/confiture-rest-api/src/audits/audit.service.ts index a95c8c10..2a092679 100644 --- a/confiture-rest-api/src/audits/audit.service.ts +++ b/confiture-rest-api/src/audits/audit.service.ts @@ -1,14 +1,11 @@ import { Injectable } from "@nestjs/common"; import { Audit, - AuditedPage, CriterionResult, CriterionResultStatus, CriterionResultUserImpact, - AuditFile, Prisma, - StoredFile, - TestEnvironment + StoredFile } from "@prisma/client"; import { nanoid } from "nanoid"; import sharp from "sharp"; @@ -24,9 +21,10 @@ import { UpdateAuditDto } from "./dto/update-audit.dto"; import { UpdateResultsDto } from "./dto/update-results.dto"; import { PatchAuditDto } from "./dto/patch-audit.dto"; -const AUDIT_EDIT_INCLUDE: Prisma.AuditInclude = { +const AUDIT_EDIT_INCLUDE = { recipients: true, environments: true, + transverseElementsPage: true, pages: true, sourceAudit: { select: { @@ -34,7 +32,22 @@ const AUDIT_EDIT_INCLUDE: Prisma.AuditInclude = { } }, notesFiles: true -}; +} as const; + +const isCompliant = (c: CriterionResult) => + c.status === CriterionResultStatus.COMPLIANT; + +const isNotCompliant = (c: CriterionResult) => + c.status === CriterionResultStatus.NOT_COMPLIANT; + +const isNotApplicable = (c: CriterionResult) => + c.status === CriterionResultStatus.NOT_APPLICABLE; + +const isNotTested = (c: CriterionResult) => + c.status === CriterionResultStatus.NOT_TESTED; + +const isTransverse = (c: CriterionResult, transversePageId: number) => + c.pageId === transversePageId; @Injectable() export class AuditService { @@ -61,10 +74,17 @@ export class AuditService { auditorEmail: data.auditorEmail, auditorName: data.auditorName, + transverseElementsPage: { + create: { + name: "Éléments transverses", + url: "", + order: -1 + } + }, pages: { createMany: { data: data.pages.map((p, i) => { - return { ...p, order: i }; + return { ...p, order: i + 1 }; }) } }, @@ -130,6 +150,9 @@ export class AuditService { > { const [audit, pages, existingResults] = await Promise.all([ this.prisma.audit.findUnique({ + include: { + transverseElementsPage: true + }, where: { editUniqueId: uniqueId } @@ -140,9 +163,18 @@ export class AuditService { this.prisma.criterionResult.findMany({ where: { page: { - audit: { - editUniqueId: uniqueId - } + OR: [ + { + audit: { + editUniqueId: uniqueId + } + }, + { + auditTransverse: { + editUniqueId: uniqueId + } + } + ] } }, include: { @@ -153,7 +185,7 @@ export class AuditService { // We do not create every empty criterion result rows in the db when creating pages. // Instead we return the results in the database and fill missing criteria with placeholder data. - return pages.flatMap((page) => + return [audit.transverseElementsPage, ...pages].flatMap((page) => CRITERIA_BY_AUDIT_TYPE[audit.auditType].map((criterion) => { const existingResult = existingResults.find( (result) => @@ -750,14 +782,10 @@ export class AuditService { async getAuditReportData( consultUniqueId: string ): Promise { - const audit = (await this.prisma.audit.findUnique({ + const audit = await this.prisma.audit.findUnique({ where: { consultUniqueId }, include: AUDIT_EDIT_INCLUDE - })) as Audit & { - environments: TestEnvironment[]; - pages: AuditedPage[]; - notesFiles: AuditFile[]; - }; + }); if (!audit) { return; @@ -766,14 +794,21 @@ export class AuditService { const results = await this.prisma.criterionResult.findMany({ where: { page: { - auditUniqueId: audit.editUniqueId - }, - criterium: { - in: CRITERIA_BY_AUDIT_TYPE[audit.auditType].map((c) => c.criterium) + OR: [ + { + auditUniqueId: audit.editUniqueId + }, + { + auditTransverse: { + editUniqueId: audit.editUniqueId + } + } + ] }, - topic: { - in: CRITERIA_BY_AUDIT_TYPE[audit.auditType].map((c) => c.topic) - } + OR: CRITERIA_BY_AUDIT_TYPE[audit.auditType].map((c) => ({ + criterium: c.criterium, + topic: c.topic + })) }, include: { exampleImages: true @@ -794,25 +829,36 @@ export class AuditService { ); const applicableCriteria = Object.values(groupedCriteria).filter( - (criteria) => - criteria.some((c) => c.status !== CriterionResultStatus.NOT_APPLICABLE) + (criteria) => criteria.some((c) => isCompliant(c) || isNotCompliant(c)) ); - const notApplicableCriteria = Object.values(groupedCriteria).filter( - (criteria) => - criteria.every((c) => c.status === CriterionResultStatus.NOT_APPLICABLE) - ); - - const compliantCriteria = applicableCriteria.filter((criteria) => - criteria.every( + const compliantCriteria = applicableCriteria.filter((criteria) => { + // remove untested transverse criterion + const withoutUntestedTrans = criteria.filter( (c) => - c.status === CriterionResultStatus.COMPLIANT || - c.status === CriterionResultStatus.NOT_APPLICABLE - ) - ); + !(isTransverse(c, audit.transverseElementsPageId) && isNotTested(c)) + ); + + return ( + withoutUntestedTrans.some((c) => isCompliant(c)) && + withoutUntestedTrans.every((c) => isCompliant(c) || isNotApplicable(c)) + ); + }); - const notCompliantCriteria = applicableCriteria.filter((criteria) => - criteria.some((c) => c.status === CriterionResultStatus.NOT_COMPLIANT) + const notCompliantCriteria = applicableCriteria.filter((criteria) => { + return criteria.some((c) => isNotCompliant(c)); + }); + + const notApplicableCriteria = Object.values(groupedCriteria).filter( + (criteria) => { + // remove untested transverse criterion + const withoutUntestedTrans = criteria.filter( + (c) => + !isTransverse(c, audit.transverseElementsPageId) && isNotTested(c) + ); + + return withoutUntestedTrans.every((c) => isNotApplicable(c)); + } ); const accessibilityRate = @@ -878,7 +924,7 @@ export class AuditService { browser: e.browser })), referencial: "RGAA Version 4.1", - samples: audit.pages + samples: [audit.transverseElementsPage, ...audit.pages] .map((p, i) => ({ name: p.name, order: p.order, @@ -891,53 +937,56 @@ export class AuditService { technologies: audit.technologies }, - pageDistributions: audit.pages.map((p) => ({ - name: p.name, - compliant: { - raw: results.filter( - (r) => - r.pageId === p.id && r.status === CriterionResultStatus.COMPLIANT - ).length, - percentage: - (results.filter( + pageDistributions: [audit.transverseElementsPage, ...audit.pages].map( + (p) => ({ + name: p.name, + compliant: { + raw: results.filter( (r) => r.pageId === p.id && r.status === CriterionResultStatus.COMPLIANT - ).length / - totalCriteriaCount) * - 100 - }, - notApplicable: { - raw: results.filter( - (r) => - r.pageId === p.id && - r.status === CriterionResultStatus.NOT_APPLICABLE - ).length, - percentage: - (results.filter( + ).length, + percentage: + (results.filter( + (r) => + r.pageId === p.id && + r.status === CriterionResultStatus.COMPLIANT + ).length / + totalCriteriaCount) * + 100 + }, + notApplicable: { + raw: results.filter( (r) => r.pageId === p.id && r.status === CriterionResultStatus.NOT_APPLICABLE - ).length / - totalCriteriaCount) * - 100 - }, - notCompliant: { - raw: results.filter( - (r) => - r.pageId === p.id && - r.status === CriterionResultStatus.NOT_COMPLIANT - ).length, - percentage: - (results.filter( + ).length, + percentage: + (results.filter( + (r) => + r.pageId === p.id && + r.status === CriterionResultStatus.NOT_APPLICABLE + ).length / + totalCriteriaCount) * + 100 + }, + notCompliant: { + raw: results.filter( (r) => r.pageId === p.id && r.status === CriterionResultStatus.NOT_COMPLIANT - ).length / - totalCriteriaCount) * - 100 - } - })), + ).length, + percentage: + (results.filter( + (r) => + r.pageId === p.id && + r.status === CriterionResultStatus.NOT_COMPLIANT + ).length / + totalCriteriaCount) * + 100 + } + }) + ), resultDistribution: { compliant: { @@ -1050,6 +1099,15 @@ export class AuditService { where: { editUniqueId: sourceUniqueId, isHidden: false }, include: { environments: true, + transverseElementsPage: { + include: { + results: { + include: { + exampleImages: true + } + } + } + }, pages: { include: { results: { @@ -1182,7 +1240,12 @@ export class AuditService { const newAudit = await this.prisma.audit.create({ data: { - ...omit(originalAudit, ["id", "auditTraceId", "sourceAuditId"]), + ...omit(originalAudit, [ + "id", + "auditTraceId", + "sourceAuditId", + "transverseElementsPageId" + ]), // link new audit with the original sourceAudit: { @@ -1208,6 +1271,25 @@ export class AuditService { } }, + transverseElementsPage: { + create: { + ...originalAudit.transverseElementsPage, + results: { + create: originalAudit.transverseElementsPage.results.map((r) => ({ + ...omit(r, ["id", "pageId"]), + exampleImages: { + create: r.exampleImages.map( + (e) => + imagesCreateData[originalAudit.transverseElementsPage.id][ + r.id + ][e.id] + ) + } + })) + } + } + }, + pages: { create: originalAudit.pages.map((p) => ({ name: p.name, @@ -1267,16 +1349,25 @@ export class AuditService { editUniqueId: true, consultUniqueId: true, initiator: true, + transverseElementsPageId: true, pages: { select: { results: true } + }, + transverseElementsPage: { + select: { + results: true + } } } }); return audits.map((a) => { - const results = a.pages.flatMap((p) => p.results); + const results = [ + ...a.transverseElementsPage.results, + ...a.pages.flatMap((p) => p.results) + ]; const progress = results.filter((r) => r.status !== CriterionResultStatus.NOT_TESTED) @@ -1302,21 +1393,24 @@ export class AuditService { (c) => resultsGroupedById[`${c.topic}.${c.criterium}`] ?? null ); - const applicableCriteria = results2.filter( - (criteria) => - criteria && - criteria.some( - (c) => c.status !== CriterionResultStatus.NOT_APPLICABLE - ) + const applicableCriteria = results2.filter((criteria) => + criteria.some((c) => isCompliant(c) || isNotCompliant(c)) ); - const compliantCriteria = applicableCriteria.filter((criteria) => - criteria.every( + const compliantCriteria = applicableCriteria.filter((criteria) => { + // remove untested transverse criterion + const withoutUntestedTrans = criteria.filter( (c) => - c.status === CriterionResultStatus.COMPLIANT || - c.status === CriterionResultStatus.NOT_APPLICABLE - ) - ); + !(isTransverse(c, a.transverseElementsPageId) && isNotTested(c)) + ); + + return ( + withoutUntestedTrans.some((c) => isCompliant(c)) && + withoutUntestedTrans.every( + (c) => isCompliant(c) || isNotApplicable(c) + ) + ); + }); complianceLevel = Math.round( (compliantCriteria.length / applicableCriteria.length) * 100 diff --git a/confiture-rest-api/src/audits/audits.controller.ts b/confiture-rest-api/src/audits/audits.controller.ts index 17f239a6..d2a7c92a 100644 --- a/confiture-rest-api/src/audits/audits.controller.ts +++ b/confiture-rest-api/src/audits/audits.controller.ts @@ -88,6 +88,7 @@ export class AuditsController { async getAudit(@Param("uniqueId") uniqueId: string) { const audit = await this.auditService.findAuditWithEditUniqueId(uniqueId, { environments: true, + transverseElementsPage: true, pages: true, sourceAudit: { select: { diff --git a/confiture-web-app/src/components/audit/AraTabs.vue b/confiture-web-app/src/components/audit/AraTabs.vue index c2d0a67e..e58468a3 100644 --- a/confiture-web-app/src/components/audit/AraTabs.vue +++ b/confiture-web-app/src/components/audit/AraTabs.vue @@ -8,9 +8,10 @@ import { ref, watch } from "vue"; import { useUniqueId } from "../../composables/useUniqueId"; +import LayoutIcon from "../icons/LayoutIcon.vue"; const props = defineProps<{ - tabs: { label: string; data: T; icon?: string }[]; + tabs: { label: string; data: T }[]; stickyTop: string; }>(); @@ -74,18 +75,13 @@ watch(currentTab, (currentTab) => { :aria-controls="panelId(i)" :aria-selected="i === currentTab ? 'true' : 'false'" :tabindex="i === currentTab ? undefined : '-1'" - :class="{ - 'fr-tabs__tab--icon-left': !!tab.icon, - ...(!!tab.icon && { - [`fr-icon-${tab.icon}`]: !!tab.icon - }) - }" @click="currentTab = i" @keydown.right.down.prevent="selectNextTab" @keydown.left.up.prevent="selectPreviousTab" @keydown.home.prevent="selectFirstTab" @keydown.end.prevent="selectLastTab" > + {{ tab.label }} diff --git a/confiture-web-app/src/components/audit/AuditGenerationCriterium.vue b/confiture-web-app/src/components/audit/AuditGenerationCriterium.vue index 3fce3ec5..0d167eac 100644 --- a/confiture-web-app/src/components/audit/AuditGenerationCriterium.vue +++ b/confiture-web-app/src/components/audit/AuditGenerationCriterium.vue @@ -20,7 +20,9 @@ import { handleFileDeleteError, handleFileUploadError } from "../../utils"; -import RadioGroup, { RadioColor } from "../ui/RadioGroup.vue"; +import MarkdownRenderer from "../ui/MarkdownRenderer.vue"; +import { RadioColor } from "../ui/Radio.vue"; +import RadioGroup from "../ui/RadioGroup.vue"; import CriteriumCompliantAccordion from "./CriteriumCompliantAccordion.vue"; import CriteriumNotApplicableAccordion from "./CriteriumNotApplicableAccordion.vue"; import CriteriumNotCompliantAccordion from "./CriteriumNotCompliantAccordion.vue"; @@ -48,19 +50,19 @@ const statuses: Array<{ { label: formatStatus(CriteriumResultStatus.COMPLIANT), value: CriteriumResultStatus.COMPLIANT, - color: "green" + color: RadioColor.GREEN }, { label: formatStatus(CriteriumResultStatus.NOT_COMPLIANT), extraLabel: "Le focus se déplacera dans le champ « Erreur et recommandation »", value: CriteriumResultStatus.NOT_COMPLIANT, - color: "red" + color: RadioColor.RED }, { label: formatStatus(CriteriumResultStatus.NOT_APPLICABLE), value: CriteriumResultStatus.NOT_APPLICABLE, - color: "grey" + color: RadioColor.GREY } ]; @@ -73,6 +75,48 @@ const result = computed( )! ); +const transversePageId = computed(() => { + return auditStore.currentAudit?.transverseElementsPage.id; +}); + +const transverseStatus = computed((): CriteriumResultStatus | null => { + if (store.data && transversePageId.value) { + return store.data?.[transversePageId.value][props.topicNumber][ + props.criterium.number + ].status; + } + + return null; +}); + +const transverseComment = computed((): string | null => { + if (store.data && transversePageId.value) { + const result = + store.data?.[transversePageId.value][props.topicNumber][ + props.criterium.number + ]; + + switch (transverseStatus.value) { + case CriteriumResultStatus.COMPLIANT: + return result.compliantComment; + case CriteriumResultStatus.NOT_COMPLIANT: + return result.notCompliantComment; + case CriteriumResultStatus.NOT_APPLICABLE: + return result.notApplicableComment; + default: + return null; + } + } + + return null; +}); + +const showTransverseComment = ref(false); + +function toggleTransverseComment() { + showTransverseComment.value = !showTransverseComment.value; +} + const notify = useNotifications(); const errorMessage: Ref = ref(null); @@ -185,13 +229,6 @@ function updateResultImpact(userImpact: CriterionResultUserImpact | null) { .catch(handleUpdateResultError); } -function updateTransverseStatus(e: Event) { - const transverse = (e.target as HTMLInputElement).checked; - store - .updateResults(props.auditUniqueId, [{ ...result.value, transverse }]) - .catch(handleUpdateResultError); -} - function updateQuickWin(quickWin: boolean) { store .updateResults(props.auditUniqueId, [{ ...result.value, quickWin }]) @@ -219,14 +256,7 @@ const isOffline = useIsOffline(); -
+
+
-
- -
diff --git a/confiture-web-app/src/store/results.ts b/confiture-web-app/src/store/results.ts index ee398931..709064eb 100644 --- a/confiture-web-app/src/store/results.ts +++ b/confiture-web-app/src/store/results.ts @@ -115,13 +115,17 @@ export const useResultsStore = defineStore("results", { }, /** - * @returns True when every criterium in the audit have been tested (status is different from NOT_TESTED) + * @returns True when every criterium (transverse excluded) in the audit have been tested (status is different from NOT_TESTED) */ everyCriteriumAreTested(): boolean { + const auditStore = useAuditStore(); + const transversePageId = + auditStore.currentAudit?.transverseElementsPage.id; + return ( - !this.allResults?.some( - (r) => r.status === CriteriumResultStatus.NOT_TESTED - ) ?? false + !this.allResults + ?.filter((r) => r.pageId !== transversePageId) + .some((r) => r.status === CriteriumResultStatus.NOT_TESTED) ?? false ); }, @@ -144,6 +148,7 @@ export const useResultsStore = defineStore("results", { /** * Ratio of tested criteria over total number of criteria. + * Transverse criteria are excluded. * * `0.5` means half of the audit criteria have been tested. */ @@ -151,9 +156,15 @@ export const useResultsStore = defineStore("results", { if (!this.data) { return 0; } + + const auditStore = useAuditStore(); + const transversePageId = + auditStore.currentAudit?.transverseElementsPage.id; + const r = Object.values(this.data) .flatMap(Object.values) - .flatMap(Object.values) as CriteriumResult[]; + .flatMap(Object.values) + .filter((cr) => cr.pageId !== transversePageId) as CriteriumResult[]; const total = r.length; @@ -211,37 +222,6 @@ export const useResultsStore = defineStore("results", { // Update UI immediately, rollbacks later if update fails. this.data[update.pageId][update.topic][update.criterium] = update; - - // Apply `transverse` result update to every pages - if (update.transverse) { - Object.keys(this.data) - .map(Number) // this.data requires a number index - .filter((pageId) => pageId !== update.pageId) // Ignore current page - .forEach((pageId) => { - if (!this.data) { - return; - } - - const target = this.data[pageId][update.topic][update.criterium]; - - target.status = update.status; - target.transverse = true; - - if (update.status === CriteriumResultStatus.COMPLIANT) { - target.compliantComment = update.compliantComment; - } - - if (update.status === CriteriumResultStatus.NOT_COMPLIANT) { - target.notCompliantComment = update.notCompliantComment; - target.userImpact = update.userImpact; - target.quickWin = update.quickWin; - } - - if (update.status === CriteriumResultStatus.NOT_APPLICABLE) { - target.notApplicableComment = update.notApplicableComment; - } - }); - } }); // update the edition date of the local audit. It will not be the same diff --git a/confiture-web-app/src/types/types.ts b/confiture-web-app/src/types/types.ts index 514b37dc..9da7167c 100644 --- a/confiture-web-app/src/types/types.ts +++ b/confiture-web-app/src/types/types.ts @@ -44,6 +44,7 @@ export interface Audit { // Audit creation auditType: AuditType; procedureName: string; + transverseElementsPage: AuditPage; pages: AuditPage[]; auditorEmail: string; auditorName: string | null; diff --git a/confiture-web-app/src/utils.ts b/confiture-web-app/src/utils.ts index 00c4f7e6..31c3bdcb 100644 --- a/confiture-web-app/src/utils.ts +++ b/confiture-web-app/src/utils.ts @@ -79,15 +79,20 @@ export function getCriteriaCount(auditType: AuditType): number { /** * Return the audit status based on: - * - the number of results (criteria count * number of pages) + * - the number of results excluding transverse (criteria count * number of pages) * - the status of each criteria * - the completion of a11y statement */ export function getAuditStatus(report: AuditReport): string { + const transversePageId = report.context.samples[0].id; + if ( - report.results.length !== - getCriteriaCount(report.auditType) * report.pageDistributions.length || - report?.results.some((r) => r.status === CriteriumResultStatus.NOT_TESTED) + report.results.filter((r) => r.pageId !== transversePageId).length !== + getCriteriaCount(report.auditType) * + (report.context.samples.length - 1) || + report?.results + .filter((r) => r.pageId !== transversePageId) + .some((r) => r.status === CriteriumResultStatus.NOT_TESTED) ) { return AuditStatus.IN_PROGRESS; }