diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index aa378789d6..2c853d6f9b 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -734,6 +734,32 @@ export const GET_HISTORICAL_ORG_SUMMARIES = gql` ${Summary.fragments.requiredFields} ` +export const ORG_NEGATIVE_FINDINGS = gql` + query OrgAggregatedNegativeGuidance($orgSlug: Slug!) { + findOrganizationBySlug(orgSlug: $orgSlug) { + summaries { + negativeFindings(orderBy: { direction: DESC, field: TAG_COUNT }) { + guidanceTags { + tagId + tagName + guidance + refLinks { + description + refLink + } + refLinksTech { + description + refLink + } + count + } + totalCount + } + } + } + } +` + export const PAGINATED_ORG_DOMAINS = gql` query OrgDomainsNext( $slug: Slug! diff --git a/frontend/src/guidance/GuidanceTagDetails.js b/frontend/src/guidance/GuidanceTagDetails.js index fa708d50b9..e4c7c942ce 100644 --- a/frontend/src/guidance/GuidanceTagDetails.js +++ b/frontend/src/guidance/GuidanceTagDetails.js @@ -21,6 +21,16 @@ export function GuidanceTagDetails({ guidanceTag, tagType }) { negative: t`Negative`, } + const tagTypeColor = { + positive: 'strong', + informative: 'info', + negative: 'weak', + } + + const getTagCategoryFromId = (tagId) => { + return tagId.split(/[0-9]/)[0].toUpperCase() + } + const cccsGuidance = guidanceTag.refLinks[0]?.description !== null && guidanceTag.refLinks.length !== 0 ? ( @@ -67,17 +77,16 @@ export function GuidanceTagDetails({ guidanceTag, tagType }) { return ( - + {tagIcon()} - {guidanceTag.tagName} + + {guidanceTag?.count && `${getTagCategoryFromId(guidanceTag.tagId)}: `} + {guidanceTag.tagName} + - {tagTypeList[tagType]?.toUpperCase()} + + {guidanceTag?.count ? {guidanceTag?.count} Findings : tagTypeList[tagType]?.toUpperCase()} + diff --git a/frontend/src/locales/en.po b/frontend/src/locales/en.po index 72c892d79f..4c2c480537 100644 --- a/frontend/src/locales/en.po +++ b/frontend/src/locales/en.po @@ -21,6 +21,10 @@ msgstr ", and" msgid ". Personal information will not be disclosed by Treasury Board Secretariat of Canada (TBS) except in accordance with the" msgstr ". Personal information will not be disclosed by Treasury Board Secretariat of Canada (TBS) except in accordance with the" +#: src/guidance/GuidanceTagDetails.js:84 +msgid "{0} Findings" +msgstr "{0} Findings" + #: src/admin/AdminDomainModal.js:63 msgid "{0} was added to {orgSlug}" msgstr "{0} was added to {orgSlug}" @@ -173,7 +177,7 @@ msgstr "404 - Page Not Found" #~ msgid "6.2.3 All remaining websites and web services must be accessible through a secure connection, as outlined in Section 6.1, by December 31, 2019." #~ msgstr "6.2.3 All remaining websites and web services must be accessible through a secure connection, as outlined in Section 6.1, by December 31, 2019." -#: src/guidance/GuidancePage.js:211 +#: src/guidance/GuidancePage.js:210 msgid "A DNS request for this service has resulted in the following error code:" msgstr "A DNS request for this service has resulted in the following error code:" @@ -296,7 +300,7 @@ msgstr "Add User" #: src/guidance/AdditionalFindings.js:52 #: src/guidance/AdditionalFindings.js:416 -#: src/guidance/GuidancePage.js:255 +#: src/guidance/GuidancePage.js:254 msgid "Additional Findings" msgstr "Additional Findings" @@ -409,7 +413,7 @@ msgid "An error occurred when you attempted to sign out" msgstr "An error occurred when you attempted to sign out" #: src/domains/DomainCard.js:38 -#: src/guidance/GuidancePage.js:99 +#: src/guidance/GuidancePage.js:98 msgid "An error occurred while favouriting a domain." msgstr "An error occurred while favouriting a domain." @@ -580,7 +584,7 @@ msgstr "Asset State" msgid "Asset States" msgstr "Asset States" -#: src/admin/AdminPage.js:200 +#: src/admin/AdminPage.js:199 #: src/admin/AuditLogTable.js:95 msgid "Audit Logs" msgstr "Audit Logs" @@ -597,7 +601,7 @@ msgstr "Authenticate" #: src/auth/ForgotPasswordPage.js:101 #: src/createOrganization/CreateOrganizationPage.js:228 #: src/guidance/CveIgnorer.js:131 -#: src/userOnboarding/components/TourComponent.js:63 +#: src/userOnboarding/components/TourComponent.js:74 msgid "Back" msgstr "Back" @@ -1211,8 +1215,8 @@ msgstr "DMARC Implementation Phase: {0}" #~ msgid "DMARC phase summary" #~ msgstr "DMARC phase summary" -#: src/organizationDetails/OrganizationDetails.js:135 -#: src/organizationDetails/OrganizationDetails.js:173 +#: src/organizationDetails/OrganizationDetails.js:137 +#: src/organizationDetails/OrganizationDetails.js:178 #: src/user/MyTrackerPage.js:81 msgid "DMARC Phases" msgstr "DMARC Phases" @@ -1233,7 +1237,7 @@ msgstr "DMARC policy of quarantine or reject, and all messages from non-mail dom #: src/dmarc/DmarcReportPage.js:94 #: src/domains/DomainCard.js:241 -#: src/guidance/GuidancePage.js:334 +#: src/guidance/GuidancePage.js:333 msgid "DMARC Report" msgstr "DMARC Report" @@ -1344,7 +1348,7 @@ msgstr "Domain:" #: src/app/FloatingMenu.js:116 #: src/domains/DomainsPage.js:208 #: src/domains/DomainsPage.js:272 -#: src/organizationDetails/OrganizationDetails.js:138 +#: src/organizationDetails/OrganizationDetails.js:140 #: src/organizationDetails/OrganizationDomains.js:125 #: src/summaries/Doughnut.js:53 #: src/summaries/Doughnut.js:74 @@ -1435,7 +1439,7 @@ msgid "Email cannot be empty" msgstr "Email cannot be empty" #: src/domains/ScanDomain.js:245 -#: src/guidance/GuidancePage.js:252 +#: src/guidance/GuidancePage.js:251 msgid "Email Guidance" msgstr "Email Guidance" @@ -1597,7 +1601,7 @@ msgstr "Error while retrieving DMARC data for {domainSlug}. <0/>This could be du #~ msgid "Error while retrieving scan data for {domainName}. <0/>This could be due to insufficient user privileges or the domain does not exist in the system." #~ msgstr "Error while retrieving scan data for {domainName}. <0/>This could be due to insufficient user privileges or the domain does not exist in the system." -#: src/guidance/GuidancePage.js:186 +#: src/guidance/GuidancePage.js:185 msgid "Error while retrieving scan data for {domainName}. <0/>This could be due to insufficient user privileges or the Domain does not exist in the system. You can request access to an Organization below to view the Domain results" msgstr "Error while retrieving scan data for {domainName}. <0/>This could be due to insufficient user privileges or the Domain does not exist in the system. You can request access to an Organization below to view the Domain results" @@ -1667,7 +1671,7 @@ msgstr "Fake email domain blocks (reject + quarantine):" #~ msgstr "FAQ" #: src/domains/DomainCard.js:48 -#: src/guidance/GuidancePage.js:109 +#: src/guidance/GuidancePage.js:108 msgid "Favourited Domain" msgstr "Favourited Domain" @@ -1712,7 +1716,7 @@ msgstr "Filtered" msgid "Filters:" msgstr "Filters:" -#: src/userOnboarding/components/TourComponent.js:66 +#: src/userOnboarding/components/TourComponent.js:77 msgid "Finish" msgstr "Finish" @@ -1868,7 +1872,7 @@ msgstr "Graph direction:" msgid "Guidance" msgstr "Guidance" -#: src/guidance/GuidancePage.js:122 +#: src/guidance/GuidancePage.js:121 msgid "Guidance results" msgstr "Guidance results" @@ -2120,7 +2124,7 @@ msgstr "If at any time you or your representatives wish to adjust or cancel thes msgid "If available, please use a managed device provided by your organization." msgstr "If available, please use a managed device provided by your organization." -#: src/guidance/GuidancePage.js:216 +#: src/guidance/GuidancePage.js:215 msgid "If you believe this could be the result of an issue with the scan, rescan the service using the refresh button. If you believe this is because the service no longer exists (NXDOMAIN), this domain should be removed from all affiliated organizations." msgstr "If you believe this could be the result of an issue with the scan, rescan the service using the refresh button. If you believe this is because the service no longer exists (NXDOMAIN), this domain should be removed from all affiliated organizations." @@ -2351,7 +2355,7 @@ msgstr "Information shared with TBS, or acquired via systems hosted by TBS, may msgid "Informative" msgstr "Informative" -#: src/guidance/GuidanceTagDetails.js:93 +#: src/guidance/GuidanceTagDetails.js:98 msgid "Informative tags highlight relevant configuration details, but are not addressed within policy requirements and have no impact on scoring." msgstr "Informative tags highlight relevant configuration details, but are not addressed within policy requirements and have no impact on scoring." @@ -2648,6 +2652,10 @@ msgstr "More details" msgid "More info" msgstr "More info" +#: src/summaries/AggregatedGuidanceSummary.js:44 +msgid "Most Common Negative Findings" +msgstr "Most Common Negative Findings" + #: src/app/ReadGuidancePage.js:535 msgid "Mozilla SSL Configuration Generator" msgstr "Mozilla SSL Configuration Generator" @@ -2767,7 +2775,7 @@ msgstr "New Phone Number:" msgid "New Value:" msgstr "New Value:" -#: src/userOnboarding/components/TourComponent.js:64 +#: src/userOnboarding/components/TourComponent.js:75 msgid "Next" msgstr "Next" @@ -2895,7 +2903,11 @@ msgstr "No known weak protocols used." msgid "No MX records found. Is the domain parked?" msgstr "No MX records found. Is the domain parked?" -#: src/guidance/GuidancePage.js:136 +#: src/summaries/AggregatedGuidanceSummary.js:51 +msgid "No negative findings to show." +msgstr "No negative findings to show." + +#: src/guidance/GuidancePage.js:135 #: src/organizations/Organizations.js:112 msgid "No Organizations" msgstr "No Organizations" @@ -2912,7 +2924,7 @@ msgstr "No response headers found" msgid "No scan data for this organization." msgstr "No scan data for this organization." -#: src/guidance/GuidancePage.js:231 +#: src/guidance/GuidancePage.js:230 msgid "No scan data is currently available for this service. You may request a scan using the refresh button, or wait up to 24 hours for data to refresh." msgstr "No scan data is currently available for this service. You may request a scan using the refresh button, or wait up to 24 hours for data to refresh." @@ -3042,7 +3054,7 @@ msgstr "Organization" msgid "Organization created" msgstr "Organization created" -#: src/organizationDetails/OrganizationDetails.js:67 +#: src/organizationDetails/OrganizationDetails.js:69 msgid "Organization Details" msgstr "Organization Details" @@ -3082,15 +3094,15 @@ msgstr "Organization owns this domain, but it is outside the allowed scope" msgid "Organization:" msgstr "Organization:" -#: src/guidance/GuidancePage.js:341 +#: src/guidance/GuidancePage.js:340 msgid "Organization(s):" msgstr "Organization(s):" -#: src/admin/AdminPage.js:198 +#: src/admin/AdminPage.js:197 #: src/app/App.js:134 #: src/app/App.js:236 #: src/app/FloatingMenu.js:103 -#: src/guidance/GuidancePage.js:194 +#: src/guidance/GuidancePage.js:193 #: src/organizations/Organizations.js:103 #: src/organizations/Organizations.js:187 msgid "Organizations" @@ -3271,7 +3283,7 @@ msgstr "Pointer to a DKIM public key record in DNS." #~ msgid "Policy" #~ msgstr "Policy" -#: src/guidance/GuidanceTagDetails.js:28 +#: src/guidance/GuidanceTagDetails.js:34 msgid "Policy guidance:" msgstr "Policy guidance:" @@ -3470,8 +3482,8 @@ msgstr "Report an Issue" msgid "Request a domain to be scanned:" msgstr "Request a domain to be scanned:" -#: src/guidance/GuidancePage.js:159 -#: src/organizationDetails/OrganizationDetails.js:112 +#: src/guidance/GuidancePage.js:158 +#: src/organizationDetails/OrganizationDetails.js:114 #: src/organizations/Organizations.js:133 #: src/organizations/RequestOrgInviteModal.js:62 msgid "Request Invite" @@ -3617,7 +3629,7 @@ msgstr "Scan of domain successfully requested" #: src/admin/AdminDomains.js:183 #: src/domains/DomainCard.js:161 #: src/domains/DomainsPage.js:134 -#: src/guidance/GuidancePage.js:302 +#: src/guidance/GuidancePage.js:301 #: src/organizationDetails/OrganizationDomains.js:110 msgid "Scan Pending" msgstr "Scan Pending" @@ -3718,7 +3730,7 @@ msgstr "Select a state that best describes the asset in relation to your organiz msgid "Select an organization" msgstr "Select an organization" -#: src/admin/AdminPage.js:162 +#: src/admin/AdminPage.js:161 msgid "Select an organization to view admin options" msgstr "Select an organization to view admin options" @@ -3997,7 +4009,7 @@ msgstr "Sign Out." msgid "Signature Hash:" msgstr "Signature Hash:" -#: src/userOnboarding/components/TourComponent.js:65 +#: src/userOnboarding/components/TourComponent.js:76 msgid "Skip" msgstr "Skip" @@ -4110,7 +4122,7 @@ msgstr "Staging" msgid "STAGING" msgstr "STAGING" -#: src/userOnboarding/components/TourButton.js:53 +#: src/userOnboarding/components/TourButton.js:59 msgid "Start Tour" msgstr "Start Tour" @@ -4192,7 +4204,7 @@ msgstr "Successfully removed user {0}." msgid "Successfully stopped ignoring CVE for domain \"{0}\". New ignored CVEs: \"{1}\"." msgstr "Successfully stopped ignoring CVE for domain \"{0}\". New ignored CVEs: \"{1}\"." -#: src/organizationDetails/OrganizationDetails.js:132 +#: src/organizationDetails/OrganizationDetails.js:134 msgid "Summaries" msgstr "Summaries" @@ -4208,7 +4220,7 @@ msgstr "Summary of your tracker" msgid "Summary Tier:" msgstr "Summary Tier:" -#: src/admin/AdminPage.js:195 +#: src/admin/AdminPage.js:194 msgid "Super Admin Menu:" msgstr "Super Admin Menu:" @@ -4301,7 +4313,7 @@ msgstr "TBS be identified as the source; and" msgid "TBS reserves the right to refuse service, and may reject your application for an account, or cancel an existing account, for any reason, at our sole discretion." msgstr "TBS reserves the right to refuse service, and may reject your application for an account, or cancel an existing account, for any reason, at our sole discretion." -#: src/guidance/GuidanceTagDetails.js:47 +#: src/guidance/GuidanceTagDetails.js:53 msgid "Technical implementation guidance:" msgstr "Technical implementation guidance:" @@ -4943,9 +4955,9 @@ msgstr "User removed." msgid "User:" msgstr "User:" -#: src/admin/AdminPage.js:199 +#: src/admin/AdminPage.js:198 #: src/admin/AdminPanel.js:22 -#: src/organizationDetails/OrganizationDetails.js:142 +#: src/organizationDetails/OrganizationDetails.js:144 msgid "Users" msgstr "Users" @@ -5094,7 +5106,7 @@ msgid "Web Connections Summary" msgstr "Web Connections Summary" #: src/domains/ScanDomain.js:242 -#: src/guidance/GuidancePage.js:249 +#: src/guidance/GuidancePage.js:248 msgid "Web Guidance" msgstr "Web Guidance" @@ -5190,7 +5202,7 @@ msgstr "Wiki" #: src/admin/AdminDomains.js:182 #: src/domains/DomainCard.js:149 #: src/domains/DomainsPage.js:133 -#: src/guidance/GuidancePage.js:309 +#: src/guidance/GuidancePage.js:308 #: src/organizationDetails/OrganizationDomains.js:109 msgid "Wildcard" msgstr "Wildcard" @@ -5261,7 +5273,7 @@ msgstr "You can modify the results of the domain list using these filters" msgid "You can search for an organization here" msgstr "You can search for an organization here" -#: src/guidance/GuidancePage.js:110 +#: src/guidance/GuidancePage.js:109 msgid "You have successfully added {domainName} to myTracker." msgstr "You have successfully added {domainName} to myTracker." diff --git a/frontend/src/locales/fr.po b/frontend/src/locales/fr.po index 8ba061de3f..96fadbefa1 100644 --- a/frontend/src/locales/fr.po +++ b/frontend/src/locales/fr.po @@ -21,6 +21,10 @@ msgstr ", et" msgid ". Personal information will not be disclosed by Treasury Board Secretariat of Canada (TBS) except in accordance with the" msgstr ". Les renseignements personnels ne seront pas divulgués par le Secrétariat du Conseil du Trésor du Canada (SCT), sauf en conformité avec les dispositions du" +#: src/guidance/GuidanceTagDetails.js:84 +msgid "{0} Findings" +msgstr "{0} Constatations" + #: src/admin/AdminDomainModal.js:63 msgid "{0} was added to {orgSlug}" msgstr "{0} a été ajouté à {orgSlug}" @@ -169,7 +173,7 @@ msgstr "404 - Page non trouvée" #~ msgid "6.2.3 All remaining websites and web services must be accessible through a secure connection, as outlined in Section 6.1, by December 31, 2019." #~ msgstr "6.2.3 Tous les sites web et services web restants doivent être accessibles par une connexion sécurisée, comme indiqué à la section 6.1, d'ici le 31 décembre 2019." -#: src/guidance/GuidancePage.js:211 +#: src/guidance/GuidancePage.js:210 msgid "A DNS request for this service has resulted in the following error code:" msgstr "Une requête DNS pour ce service a donné lieu au code d'erreur suivant :" @@ -288,7 +292,7 @@ msgstr "Ajouter un utilisateur" #: src/guidance/AdditionalFindings.js:52 #: src/guidance/AdditionalFindings.js:416 -#: src/guidance/GuidancePage.js:255 +#: src/guidance/GuidancePage.js:254 msgid "Additional Findings" msgstr "Constatations supplémentaires" @@ -397,7 +401,7 @@ msgid "An error occurred when you attempted to sign out" msgstr "Une erreur s'est produite lorsque vous avez tenté de vous déconnecter" #: src/domains/DomainCard.js:38 -#: src/guidance/GuidancePage.js:99 +#: src/guidance/GuidancePage.js:98 msgid "An error occurred while favouriting a domain." msgstr "Une erreur s'est produite lors de la mise en favori d'un domaine." @@ -568,7 +572,7 @@ msgstr "État des actifs" msgid "Asset States" msgstr "Estados del activo" -#: src/admin/AdminPage.js:200 +#: src/admin/AdminPage.js:199 #: src/admin/AuditLogTable.js:95 msgid "Audit Logs" msgstr "Journaux d'audit" @@ -585,7 +589,7 @@ msgstr "Authentifier" #: src/auth/ForgotPasswordPage.js:101 #: src/createOrganization/CreateOrganizationPage.js:228 #: src/guidance/CveIgnorer.js:131 -#: src/userOnboarding/components/TourComponent.js:63 +#: src/userOnboarding/components/TourComponent.js:74 msgid "Back" msgstr "Retour" @@ -1199,8 +1203,8 @@ msgstr "Phase de mise en œuvre de DMARC: {0}" #~ msgid "DMARC phase summary" #~ msgstr "Résumé de la phase DMARC" -#: src/organizationDetails/OrganizationDetails.js:135 -#: src/organizationDetails/OrganizationDetails.js:173 +#: src/organizationDetails/OrganizationDetails.js:137 +#: src/organizationDetails/OrganizationDetails.js:178 #: src/user/MyTrackerPage.js:81 msgid "DMARC Phases" msgstr "Phases DMARC" @@ -1221,7 +1225,7 @@ msgstr "Politique DMARC de mise en quarantaine ou de rejet, et rejet de tous les #: src/dmarc/DmarcReportPage.js:94 #: src/domains/DomainCard.js:241 -#: src/guidance/GuidancePage.js:334 +#: src/guidance/GuidancePage.js:333 msgid "DMARC Report" msgstr "Rapport DMARC " @@ -1332,7 +1336,7 @@ msgstr "Domaine:" #: src/app/FloatingMenu.js:116 #: src/domains/DomainsPage.js:208 #: src/domains/DomainsPage.js:272 -#: src/organizationDetails/OrganizationDetails.js:138 +#: src/organizationDetails/OrganizationDetails.js:140 #: src/organizationDetails/OrganizationDomains.js:125 #: src/summaries/Doughnut.js:53 #: src/summaries/Doughnut.js:74 @@ -1415,7 +1419,7 @@ msgid "Email cannot be empty" msgstr "Le courriel ne peut être vide" #: src/domains/ScanDomain.js:245 -#: src/guidance/GuidancePage.js:252 +#: src/guidance/GuidancePage.js:251 msgid "Email Guidance" msgstr "Conseils par courriel" @@ -1569,7 +1573,7 @@ msgstr "Erreur lors de la récupération des données DMARC pour {domainSlug}. < #~ msgid "Error while retrieving scan data for {domainName}. <0/>This could be due to insufficient user privileges or the domain does not exist in the system." #~ msgstr "Erreur lors de la récupération des données d'analyse pour {domainName}. This could be due to insufficient user privileges or the Domain does not exist in the system. You can request access to an Organization below to view the Domain results" msgstr "Erreur lors de la récupération des données d'analyse pour {domainName}. <0/>Cela peut être dû à des privilèges d'utilisateur insuffisants ou au fait que le domaine n'existe pas dans le système. Vous pouvez demander l'accès à une organisation ci-dessous pour voir les résultats du domaine." @@ -1639,7 +1643,7 @@ msgstr "Blocs de domaines de faux e-mails (rejet + quarantaine) :" #~ msgstr "FAQ" #: src/domains/DomainCard.js:48 -#: src/guidance/GuidancePage.js:109 +#: src/guidance/GuidancePage.js:108 msgid "Favourited Domain" msgstr "Domaine favori" @@ -1680,7 +1684,7 @@ msgstr "Filtré" msgid "Filters:" msgstr "Filtres :" -#: src/userOnboarding/components/TourComponent.js:66 +#: src/userOnboarding/components/TourComponent.js:77 msgid "Finish" msgstr "Terminer" @@ -1828,7 +1832,7 @@ msgstr "Direction du graphique :" msgid "Guidance" msgstr "Orientation" -#: src/guidance/GuidancePage.js:122 +#: src/guidance/GuidancePage.js:121 msgid "Guidance results" msgstr "Résultats de l'orientation" @@ -2080,7 +2084,7 @@ msgstr "Si, à tout moment, vous ou vos représentants souhaitez ajuster ou annu msgid "If available, please use a managed device provided by your organization." msgstr "Si disponible, veuillez utiliser un dispositif géré fourni par votre organisation." -#: src/guidance/GuidancePage.js:216 +#: src/guidance/GuidancePage.js:215 msgid "If you believe this could be the result of an issue with the scan, rescan the service using the refresh button. If you believe this is because the service no longer exists (NXDOMAIN), this domain should be removed from all affiliated organizations." msgstr "Si vous pensez que cela peut être le résultat d'un problème avec l'analyse, réanalysez le service en utilisant le bouton d'actualisation. Si vous pensez que c'est parce que le service n'existe plus (NXDOMAIN), ce domaine doit être supprimé de toutes les organisations affiliées." @@ -2311,7 +2315,7 @@ msgstr "Les renseignements partagés avec le SCT ou acquis par l'entremise de sy msgid "Informative" msgstr "Informatif" -#: src/guidance/GuidanceTagDetails.js:93 +#: src/guidance/GuidanceTagDetails.js:98 msgid "Informative tags highlight relevant configuration details, but are not addressed within policy requirements and have no impact on scoring." msgstr "Les balises informatives mettent en évidence des détails de configuration pertinents, mais ne sont pas traitées dans le cadre des exigences de la politique et n'ont aucun impact sur la notation." @@ -2608,6 +2612,10 @@ msgstr "Plus de détails" msgid "More info" msgstr "Plus d'informations" +#: src/summaries/AggregatedGuidanceSummary.js:44 +msgid "Most Common Negative Findings" +msgstr "Résultats négatifs les plus fréquents" + #: src/app/ReadGuidancePage.js:535 msgid "Mozilla SSL Configuration Generator" msgstr "Générateur de configuration SSL de Mozilla" @@ -2719,7 +2727,7 @@ msgstr "Nouveau numéro de téléphone:" msgid "New Value:" msgstr "Nouvelle valeur :" -#: src/userOnboarding/components/TourComponent.js:64 +#: src/userOnboarding/components/TourComponent.js:75 msgid "Next" msgstr "Suivant" @@ -2847,7 +2855,11 @@ msgstr "Aucun protocole faible connu n'a été utilisé." msgid "No MX records found. Is the domain parked?" msgstr "Aucun enregistrement MX n'a été trouvé. Le domaine est-il parqué ?" -#: src/guidance/GuidancePage.js:136 +#: src/summaries/AggregatedGuidanceSummary.js:51 +msgid "No negative findings to show." +msgstr "Aucun résultat négatif à signaler." + +#: src/guidance/GuidancePage.js:135 #: src/organizations/Organizations.js:112 msgid "No Organizations" msgstr "Aucune organisation" @@ -2864,7 +2876,7 @@ msgstr "Aucun en-tête de réponse n'a été trouvé" msgid "No scan data for this organization." msgstr "Aucune donnée d'analyse pour cette organisation." -#: src/guidance/GuidancePage.js:231 +#: src/guidance/GuidancePage.js:230 msgid "No scan data is currently available for this service. You may request a scan using the refresh button, or wait up to 24 hours for data to refresh." msgstr "Aucune donnée de balayage n'est actuellement disponible pour ce service. Vous pouvez demander un scan en utilisant le bouton d'actualisation, ou attendre jusqu'à 24 heures pour que les données soient actualisées." @@ -2994,7 +3006,7 @@ msgstr "Organisation" msgid "Organization created" msgstr "Organisation créée" -#: src/organizationDetails/OrganizationDetails.js:67 +#: src/organizationDetails/OrganizationDetails.js:69 msgid "Organization Details" msgstr "Détails de l'organisation" @@ -3034,15 +3046,15 @@ msgstr "L'organisation possède ce domaine, mais il est en dehors du champ d'app msgid "Organization:" msgstr "Organisation:" -#: src/guidance/GuidancePage.js:341 +#: src/guidance/GuidancePage.js:340 msgid "Organization(s):" msgstr "Organisation(s) :" -#: src/admin/AdminPage.js:198 +#: src/admin/AdminPage.js:197 #: src/app/App.js:134 #: src/app/App.js:236 #: src/app/FloatingMenu.js:103 -#: src/guidance/GuidancePage.js:194 +#: src/guidance/GuidancePage.js:193 #: src/organizations/Organizations.js:103 #: src/organizations/Organizations.js:187 msgid "Organizations" @@ -3223,7 +3235,7 @@ msgstr "Pointeur vers un enregistrement de clé publique DKIM dans le DNS." #~ msgid "Policy" #~ msgstr "Politique" -#: src/guidance/GuidanceTagDetails.js:28 +#: src/guidance/GuidanceTagDetails.js:34 msgid "Policy guidance:" msgstr "Orientation politique :" @@ -3418,8 +3430,8 @@ msgstr "Signaler un problème" msgid "Request a domain to be scanned:" msgstr "Demander qu'un domaine soit scanné:" -#: src/guidance/GuidancePage.js:159 -#: src/organizationDetails/OrganizationDetails.js:112 +#: src/guidance/GuidancePage.js:158 +#: src/organizationDetails/OrganizationDetails.js:114 #: src/organizations/Organizations.js:133 #: src/organizations/RequestOrgInviteModal.js:62 msgid "Request Invite" @@ -3565,7 +3577,7 @@ msgstr "Scan du domaine demandé avec succès" #: src/admin/AdminDomains.js:183 #: src/domains/DomainCard.js:161 #: src/domains/DomainsPage.js:134 -#: src/guidance/GuidancePage.js:302 +#: src/guidance/GuidancePage.js:301 #: src/organizationDetails/OrganizationDomains.js:110 msgid "Scan Pending" msgstr "Scan en attente" @@ -3662,7 +3674,7 @@ msgstr "Sélectionnez l'état qui décrit le mieux l'actif par rapport à votre msgid "Select an organization" msgstr "Sélectionnez une organisation" -#: src/admin/AdminPage.js:162 +#: src/admin/AdminPage.js:161 msgid "Select an organization to view admin options" msgstr "Sélectionnez une organisation pour voir les options d'administration" @@ -3947,7 +3959,7 @@ msgstr "Déconnexion." msgid "Signature Hash:" msgstr "Signature Hash :" -#: src/userOnboarding/components/TourComponent.js:65 +#: src/userOnboarding/components/TourComponent.js:76 msgid "Skip" msgstr "Sauter" @@ -4060,7 +4072,7 @@ msgstr "Dév" msgid "STAGING" msgstr "DÉV" -#: src/userOnboarding/components/TourButton.js:53 +#: src/userOnboarding/components/TourButton.js:59 msgid "Start Tour" msgstr "Début de la visite" @@ -4134,7 +4146,7 @@ msgstr "L'utilisateur {0} a été supprimé." msgid "Successfully stopped ignoring CVE for domain \"{0}\". New ignored CVEs: \"{1}\"." msgstr "Arrêt réussi de l'ignorance des CVE pour le domaine « {0} ». Nouvelles CVE ignorées : « {1} »." -#: src/organizationDetails/OrganizationDetails.js:132 +#: src/organizationDetails/OrganizationDetails.js:134 msgid "Summaries" msgstr "Résumés" @@ -4150,7 +4162,7 @@ msgstr "Résumé de votre tracker" msgid "Summary Tier:" msgstr "Résumé Tier :" -#: src/admin/AdminPage.js:195 +#: src/admin/AdminPage.js:194 msgid "Super Admin Menu:" msgstr "Super Admin Menu :" @@ -4243,7 +4255,7 @@ msgstr "le SCT soit identifié comme la source; et" msgid "TBS reserves the right to refuse service, and may reject your application for an account, or cancel an existing account, for any reason, at our sole discretion." msgstr "TBS se réserve le droit de refuser le service, de rejeter votre demande de compte ou d'annuler un compte existant, pour quelque raison que ce soit, à sa seule discrétion." -#: src/guidance/GuidanceTagDetails.js:47 +#: src/guidance/GuidanceTagDetails.js:53 msgid "Technical implementation guidance:" msgstr "Conseils techniques de mise en œuvre :" @@ -4861,9 +4873,9 @@ msgstr "Utilisateur supprimé." msgid "User:" msgstr "Utilisateur:" -#: src/admin/AdminPage.js:199 +#: src/admin/AdminPage.js:198 #: src/admin/AdminPanel.js:22 -#: src/organizationDetails/OrganizationDetails.js:142 +#: src/organizationDetails/OrganizationDetails.js:144 msgid "Users" msgstr "Utilisateurs" @@ -5008,7 +5020,7 @@ msgid "Web Connections Summary" msgstr "Résumé des connexions web" #: src/domains/ScanDomain.js:242 -#: src/guidance/GuidancePage.js:249 +#: src/guidance/GuidancePage.js:248 msgid "Web Guidance" msgstr "Conseils sur le Web" @@ -5096,7 +5108,7 @@ msgstr "Wiki" #: src/admin/AdminDomains.js:182 #: src/domains/DomainCard.js:149 #: src/domains/DomainsPage.js:133 -#: src/guidance/GuidancePage.js:309 +#: src/guidance/GuidancePage.js:308 #: src/organizationDetails/OrganizationDomains.js:109 msgid "Wildcard" msgstr "Wildcard" @@ -5163,7 +5175,7 @@ msgstr "Vous pouvez modifier les résultats de la liste des domaines à l'aide d msgid "You can search for an organization here" msgstr "Vous pouvez rechercher une organisation ici" -#: src/guidance/GuidancePage.js:110 +#: src/guidance/GuidancePage.js:109 msgid "You have successfully added {domainName} to myTracker." msgstr "Vous avez ajouté avec succès {domainName} à myTracker." diff --git a/frontend/src/organizationDetails/OrganizationDetails.js b/frontend/src/organizationDetails/OrganizationDetails.js index 912344f88e..c0929604af 100644 --- a/frontend/src/organizationDetails/OrganizationDetails.js +++ b/frontend/src/organizationDetails/OrganizationDetails.js @@ -4,6 +4,7 @@ import { Trans } from '@lingui/macro' import { Box, Button, + Divider, Flex, Heading, IconButton, @@ -33,6 +34,7 @@ import { RequestOrgInviteModal } from '../organizations/RequestOrgInviteModal' import { useUserVar } from '../utilities/userState' import { HistoricalSummariesGraph } from '../summaries/HistoricalSummariesGraph' import { ABTestVariant, ABTestWrapper } from '../app/ABTestWrapper' +import { AggregatedGuidanceSummary } from '../summaries/AggregatedGuidanceSummary' import { bool } from 'prop-types' export default function OrganizationDetails({ loginRequired }) { @@ -150,6 +152,7 @@ export default function OrganizationDetails({ loginRequired }) { + {orgSummariesLoading ? ( @@ -164,6 +167,10 @@ export default function OrganizationDetails({ loginRequired }) { /> )} + + + + diff --git a/frontend/src/summaries/AggregatedGuidanceSummary.js b/frontend/src/summaries/AggregatedGuidanceSummary.js new file mode 100644 index 0000000000..59a4873dd8 --- /dev/null +++ b/frontend/src/summaries/AggregatedGuidanceSummary.js @@ -0,0 +1,82 @@ +import React, { useState } from 'react' +import { Accordion, Box, Heading, Text } from '@chakra-ui/react' +import { string } from 'prop-types' +import { ORG_NEGATIVE_FINDINGS } from '../graphql/queries' +import { ErrorFallbackMessage } from '../components/ErrorFallbackMessage' +import { RelayPaginationControls } from '../components/RelayPaginationControls' +import { LoadingMessage } from '../components/LoadingMessage' +import { ListOf } from '../components/ListOf' +import { Trans } from '@lingui/macro' +import { ErrorBoundary } from 'react-error-boundary' +import { GuidanceTagDetails } from '../guidance/GuidanceTagDetails' +import { useQuery } from '@apollo/client' + +export function AggregatedGuidanceSummary({ orgSlug, ...props }) { + const [tagsPerPage, setTagsPerPage] = useState(10) + const [currentPage, setCurrentPage] = useState(1) + const { loading, error, data } = useQuery(ORG_NEGATIVE_FINDINGS, { variables: { orgSlug } }) + + if (loading) return + if (error) return + + const handleNext = () => { + setCurrentPage(currentPage + 1) + } + + const handlePrevious = () => { + setCurrentPage(currentPage - 1) + } + + const resetToFirstPage = () => { + setCurrentPage(1) + } + + const handleItemsPerPageChange = (newItemsPerPage) => { + setTagsPerPage(newItemsPerPage) + } + + const { guidanceTags, totalCount } = data?.findOrganizationBySlug?.summaries?.negativeFindings + const paginatedData = guidanceTags.slice((currentPage - 1) * tagsPerPage, currentPage * tagsPerPage) + + return ( + + + Most Common Negative Findings + + + ( + + No negative findings to show. + + )} + mb="4" + > + {(guidanceTag, index) => ( + + + + + + )} + + + 1} + previous={handlePrevious} + setSelectedDisplayLimit={handleItemsPerPageChange} + resetToFirstPage={resetToFirstPage} + displayLimitOptions={[5, 10, 20]} + /> + + ) +} + +AggregatedGuidanceSummary.propTypes = { + orgSlug: string.isRequired, +} diff --git a/frontend/src/summaries/__tests__/AggregatedGuidanceSummary.test.js b/frontend/src/summaries/__tests__/AggregatedGuidanceSummary.test.js new file mode 100644 index 0000000000..498596a127 --- /dev/null +++ b/frontend/src/summaries/__tests__/AggregatedGuidanceSummary.test.js @@ -0,0 +1,198 @@ +import React from 'react' +import { render, waitFor } from '@testing-library/react' +import { MockedProvider } from '@apollo/client/testing' +import { MemoryRouter, Route } from 'react-router-dom' +import { theme, ChakraProvider } from '@chakra-ui/react' +import { I18nProvider } from '@lingui/react' +import { setupI18n } from '@lingui/core' +import { makeVar } from '@apollo/client' +import { en } from 'make-plural/plurals' + +import { AggregatedGuidanceSummary } from '../AggregatedGuidanceSummary' + +import { UserVarProvider } from '../../utilities/userState' +import { ORG_NEGATIVE_FINDINGS } from '../../graphql/queries' + +const i18n = setupI18n({ + locale: 'en', + messages: { + en: {}, + }, + localeData: { + en: { plurals: en }, + }, +}) + +describe('', () => { + const mocks = [ + { + request: { + query: ORG_NEGATIVE_FINDINGS, + variables: { orgSlug: 'tbs-sct-gc-ca' }, + }, + result: { + data: { + findOrganizationBySlug: { + id: 'fgwsgwsf', + summaries: { + negativeFindings: { + totalCount: 2, + guidanceTags: [ + { + tagId: 'tag2', + tagName: 'TAG-short-age', + guidance: 'Hello World', + refLinks: [ + { + description: 'Aut autem consequatur ipsam aliquam sunt et at pariatur suscipit.', + refLink: 'http://zita.com', + }, + ], + refLinksTech: [ + { + description: 'Recusandae dolor quidem et repellendus iure sit aliquam.', + refLink: 'http://audie.org', + }, + ], + count: 10, + }, + + { + tagId: 'tag9', + tagName: 'TAG-certificate-expired', + guidance: 'Hello World', + refLinks: [ + { + description: 'Vitae cum molestias veritatis.', + refLink: 'https://michaela.com', + }, + ], + refLinksTech: [ + { + description: 'Voluptatem repudiandae accusantium ratione ea sed.', + refLink: 'https://dennis.name', + }, + ], + count: 5, + }, + ], + }, + }, + }, + }, + }, + }, + ] + it('renders correctly', async () => { + const { getByText } = render( + + + + + + + + + + + + + , + ) + await waitFor(() => { + expect(getByText(/TAG-short-age/i)).toBeInTheDocument() + }) + }) + + it('displays error message on error', async () => { + const errorMocks = [ + { + request: { + query: ORG_NEGATIVE_FINDINGS, + variables: { orgSlug: 'tbs-sct-gc-ca' }, + }, + error: new Error('An error occurred'), + }, + ] + + const { getByText } = render( + + + + + + + + + + + + + , + ) + await waitFor(() => { + expect(getByText(/An error occurred/i)).toBeInTheDocument() + }) + }) + + it('displays no findings message when there are no negative findings', async () => { + const noFindingsMocks = [ + { + request: { + query: ORG_NEGATIVE_FINDINGS, + variables: { orgSlug: 'tbs-sct-gc-ca' }, + }, + result: { + data: { + findOrganizationBySlug: { + id: 'fgwsgwsf', + summaries: { + negativeFindings: { + totalCount: 0, + guidanceTags: [], + }, + }, + }, + }, + }, + }, + ] + + const { getByText } = render( + + + + + + + + + + + + + , + ) + await waitFor(() => { + expect(getByText(/No negative findings to show/i)).toBeInTheDocument() + }) + }) +})