From fdd8928f36d0dfa9b99726a39f4dbafb5aca567b Mon Sep 17 00:00:00 2001 From: Muhammad Faraz Maqsood Date: Fri, 4 Apr 2025 16:50:43 +0500 Subject: [PATCH] feat: add manual check count to collapsed view --- .../scan-results/ScanResults.scss | 10 +++++- .../scan-results/ScanResults.tsx | 9 +++++- .../scan-results/SectionCollapsible.tsx | 4 ++- src/optimizer-page/scan-results/messages.js | 4 +++ src/optimizer-page/utils.test.js | 32 ++++++++++++++++--- src/optimizer-page/utils.ts | 21 +++++++++--- 6 files changed, 69 insertions(+), 11 deletions(-) diff --git a/src/optimizer-page/scan-results/ScanResults.scss b/src/optimizer-page/scan-results/ScanResults.scss index b17b3cbaa..e5b1978eb 100644 --- a/src/optimizer-page/scan-results/ScanResults.scss +++ b/src/optimizer-page/scan-results/ScanResults.scss @@ -12,7 +12,15 @@ } .yellow-italics { - color: $warning-800;; + color: $warning-800; + margin-left: 2rem; + font-weight: 400; + font-size: 80%; + font-style: italic; + } + + .green-italics { + color: $green; margin-left: 2rem; font-weight: 400; font-size: 80%; diff --git a/src/optimizer-page/scan-results/ScanResults.tsx b/src/optimizer-page/scan-results/ScanResults.tsx index a409b1249..c0c32b98c 100644 --- a/src/optimizer-page/scan-results/ScanResults.tsx +++ b/src/optimizer-page/scan-results/ScanResults.tsx @@ -30,7 +30,11 @@ const ScanResults: FC = ({ data }) => { const intl = useIntl(); const [showLockedLinks, setShowLockedLinks] = useState(true); - const { brokenLinksCounts, lockedLinksCounts } = useMemo(() => countBrokenLinks(data), [data?.sections]); + const { + brokenLinksCounts, + lockedLinksCounts, + externalForbiddenLinksCounts, + } = useMemo(() => countBrokenLinks(data), [data?.sections]); if (!data?.sections) { return ; @@ -64,6 +68,9 @@ const ScanResults: FC = ({ data }) => { title={section.displayName} redItalics={intl.formatMessage(messages.brokenLinksNumber, { count: brokenLinksCounts[index] })} yellowItalics={!showLockedLinks ? '' : intl.formatMessage(messages.lockedLinksNumber, { count: lockedLinksCounts[index] })} + greenItalics={ + intl.formatMessage(messages.externalForbiddenLinksNumber, { count: externalForbiddenLinksCounts[index] }) + } > {section.subsections.map((subsection) => ( <> diff --git a/src/optimizer-page/scan-results/SectionCollapsible.tsx b/src/optimizer-page/scan-results/SectionCollapsible.tsx index 077f747cc..80c40bf97 100644 --- a/src/optimizer-page/scan-results/SectionCollapsible.tsx +++ b/src/optimizer-page/scan-results/SectionCollapsible.tsx @@ -13,11 +13,12 @@ interface Props { children: React.ReactNode; redItalics?: string; yellowItalics?: string; + greenItalics?: string; className?: string; } const SectionCollapsible: FC = ({ - title, children, redItalics = '', yellowItalics = '', className = '', + title, children, redItalics = '', yellowItalics = '', greenItalics = '', className = '', }) => { const [isOpen, setIsOpen] = useState(false); const styling = 'card-lg'; @@ -27,6 +28,7 @@ const SectionCollapsible: FC = ({ {title} {redItalics} {yellowItalics} + {greenItalics} ); diff --git a/src/optimizer-page/scan-results/messages.js b/src/optimizer-page/scan-results/messages.js index 3368fda57..e3b0c88d3 100644 --- a/src/optimizer-page/scan-results/messages.js +++ b/src/optimizer-page/scan-results/messages.js @@ -29,6 +29,10 @@ const messages = defineMessages({ id: 'course-authoring.course-optimizer.lockedLinksNumber', defaultMessage: '{count} locked links', }, + externalForbiddenLinksNumber: { + id: 'course-authoring.course-optimizer.externalForbiddenLinksNumber', + defaultMessage: '{count} manual check', + }, lockedInfoTooltip: { id: 'course-authoring.course-optimizer.lockedInfoTooltip', defaultMessage: 'These course files are "locked", so we cannot verify if the link can access the file.', diff --git a/src/optimizer-page/utils.test.js b/src/optimizer-page/utils.test.js index 0af97a146..dccd820b8 100644 --- a/src/optimizer-page/utils.test.js +++ b/src/optimizer-page/utils.test.js @@ -4,7 +4,13 @@ import { countBrokenLinks } from './utils'; describe('countBrokenLinks', () => { it('should return the count of broken links', () => { const data = mockApiResponse.LinkCheckOutput; - expect(countBrokenLinks(data)).toStrictEqual({ brokenLinksCounts: [5, 2], lockedLinksCounts: [5, 2] }); + expect(countBrokenLinks(data)).toStrictEqual( + { + brokenLinksCounts: [5, 2], + lockedLinksCounts: [5, 2], + externalForbiddenLinksCounts: [1, 1], + }, + ); }); it('should return 0 if there are no broken links', () => { @@ -27,18 +33,36 @@ describe('countBrokenLinks', () => { }, ], }; - expect(countBrokenLinks(data)).toStrictEqual({ brokenLinksCounts: [0], lockedLinksCounts: [0] }); + expect(countBrokenLinks(data)).toStrictEqual( + { + brokenLinksCounts: [0], + lockedLinksCounts: [0], + externalForbiddenLinksCounts: [0], + }, + ); }); it('should return [] if there is no data', () => { const data = {}; - expect(countBrokenLinks(data)).toStrictEqual({ brokenLinksCounts: [], lockedLinksCounts: [] }); + expect(countBrokenLinks(data)).toStrictEqual( + { + brokenLinksCounts: [], + lockedLinksCounts: [], + externalForbiddenLinksCounts: [], + }, + ); }); it('should return [] if there are no sections', () => { const data = { sections: [], }; - expect(countBrokenLinks(data)).toStrictEqual({ brokenLinksCounts: [], lockedLinksCounts: [] }); + expect(countBrokenLinks(data)).toStrictEqual( + { + brokenLinksCounts: [], + lockedLinksCounts: [], + externalForbiddenLinksCounts: [], + }, + ); }); }); diff --git a/src/optimizer-page/utils.ts b/src/optimizer-page/utils.ts index 712cf61eb..ee151ab0c 100644 --- a/src/optimizer-page/utils.ts +++ b/src/optimizer-page/utils.ts @@ -1,26 +1,39 @@ /* eslint-disable import/prefer-default-export */ import { LinkCheckResult } from './types'; -export const countBrokenLinks = (data: LinkCheckResult | null): -{ brokenLinksCounts: number[], lockedLinksCounts: number[] } => { +export const countBrokenLinks = ( + data: LinkCheckResult | null, +): { + brokenLinksCounts: number[]; + lockedLinksCounts: number[]; + externalForbiddenLinksCounts: number[]; +} => { if (!data?.sections) { - return { brokenLinksCounts: [], lockedLinksCounts: [] }; + return { + brokenLinksCounts: [], + lockedLinksCounts: [], + externalForbiddenLinksCounts: [], + }; } const brokenLinksCounts: number[] = []; const lockedLinksCounts: number[] = []; + const externalForbiddenLinksCounts: number[] = []; data.sections.forEach((section) => { let brokenLinks = 0; let lockedLinks = 0; + let externalForbiddenLinks = 0; section.subsections.forEach((subsection) => { subsection.units.forEach((unit) => { unit.blocks.forEach((block) => { brokenLinks += block.brokenLinks?.length || 0; lockedLinks += block.lockedLinks?.length || 0; + externalForbiddenLinks += block.externalForbiddenLinks?.length || 0; }); }); }); brokenLinksCounts.push(brokenLinks); lockedLinksCounts.push(lockedLinks); + externalForbiddenLinksCounts.push(externalForbiddenLinks); }); - return { brokenLinksCounts, lockedLinksCounts }; + return { brokenLinksCounts, lockedLinksCounts, externalForbiddenLinksCounts }; };