feat: add manual check count to collapsed view

This commit is contained in:
Muhammad Faraz Maqsood
2025-04-04 16:50:43 +05:00
committed by Muhammad Faraz Maqsood
parent 552ff395df
commit fdd8928f36
6 changed files with 69 additions and 11 deletions

View File

@@ -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%;

View File

@@ -30,7 +30,11 @@ const ScanResults: FC<Props> = ({ 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 <InfoCard text={intl.formatMessage(messages.noBrokenLinksCard)} />;
@@ -64,6 +68,9 @@ const ScanResults: FC<Props> = ({ 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) => (
<>

View File

@@ -13,11 +13,12 @@ interface Props {
children: React.ReactNode;
redItalics?: string;
yellowItalics?: string;
greenItalics?: string;
className?: string;
}
const SectionCollapsible: FC<Props> = ({
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<Props> = ({
<strong>{title}</strong>
<span className="red-italics">{redItalics}</span>
<span className="yellow-italics">{yellowItalics}</span>
<span className="green-italics">{greenItalics}</span>
</div>
);

View File

@@ -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.',

View File

@@ -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: [],
},
);
});
});

View File

@@ -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 };
};