feat: add manual check links section separately for 403 links (#1751)
This commit is contained in:
@@ -143,6 +143,7 @@ describe('CourseOptimizerPage', () => {
|
||||
await waitFor(() => {
|
||||
expect(getAllByText(scanResultsMessages.brokenLinkStatus.defaultMessage)[0]).toBeInTheDocument();
|
||||
expect(queryAllByText(scanResultsMessages.lockedLinkStatus.defaultMessage)[0]).toBeInTheDocument();
|
||||
expect(queryAllByText(scanResultsMessages.recommendedManualCheckText.defaultMessage)[0]).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ const mockApiResponse = {
|
||||
url: 'https://example.com/intro-guide',
|
||||
brokenLinks: ['https://example.com/broken-link-algo'],
|
||||
lockedLinks: ['https://example.com/locked-link-algo'],
|
||||
externalForbiddenLinks: ['https://outsider.com/forbidden-link-algo'],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -92,6 +93,7 @@ const mockApiResponse = {
|
||||
url: 'https://example.com/broken-link-algo',
|
||||
brokenLinks: ['https://example.com/broken-link-algo'],
|
||||
lockedLinks: ['https://example.com/locked-link-algo'],
|
||||
externalForbiddenLinks: ['https://outsider.com/forbidden-link-algo'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { Icon, Table } from '@openedx/paragon';
|
||||
import { OpenInNew, Lock, LinkOff } from '@openedx/paragon/icons';
|
||||
import {
|
||||
Card, Icon, OverlayTrigger, Table, Tooltip,
|
||||
} from '@openedx/paragon';
|
||||
import {
|
||||
OpenInNew, Lock, LinkOff, InfoOutline,
|
||||
} from '@openedx/paragon/icons';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { FC } from 'react';
|
||||
import { Unit } from '../types';
|
||||
@@ -23,6 +27,26 @@ const GoToBlock: FC<{ block: { url: string } }> = ({ block }) => (
|
||||
</span>
|
||||
);
|
||||
|
||||
const RecommendedManualCheckHeading = () => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<span className="d-flex align-items-center font-weight-bold py-2">
|
||||
{intl.formatMessage(messages.recommendedManualCheckText)}
|
||||
<OverlayTrigger
|
||||
key="top"
|
||||
placement="top"
|
||||
overlay={(
|
||||
<Tooltip id="tooltip-top">
|
||||
{intl.formatMessage(messages.recommendedManualCheckTooltip)}
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
<Icon className="ml-1 pl-1" src={InfoOutline} />
|
||||
</OverlayTrigger>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
interface BrokenLinkTableProps {
|
||||
unit: Unit;
|
||||
showLockedLinks: boolean;
|
||||
@@ -40,7 +64,7 @@ const BrokenLinkTable: FC<BrokenLinkTableProps> = ({
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<>
|
||||
<Card className="unit-card rounded-sm pt-2 pl-3 pr-4 mb-2.5">
|
||||
<p className="unit-header">{unit.displayName}</p>
|
||||
<Table
|
||||
data={unit.blocks.reduce(
|
||||
@@ -62,23 +86,42 @@ const BrokenLinkTable: FC<BrokenLinkTableProps> = ({
|
||||
),
|
||||
}));
|
||||
acc.push(...blockBrokenLinks);
|
||||
if (!showLockedLinks) {
|
||||
return acc;
|
||||
|
||||
if (showLockedLinks) {
|
||||
const blockLockedLinks = block.lockedLinks.map((link) => ({
|
||||
blockLink: <GoToBlock block={block} />,
|
||||
blockDisplayName: block.displayName || '',
|
||||
brokenLink: <BrokenLinkHref href={link} />,
|
||||
status: (
|
||||
<span className="link-status-text">
|
||||
<Icon src={Lock} className="lock-icon" />
|
||||
{intl.formatMessage(messages.lockedLinkStatus)}{' '}
|
||||
<LockedInfoIcon />
|
||||
</span>
|
||||
),
|
||||
}));
|
||||
|
||||
acc.push(...blockLockedLinks);
|
||||
}
|
||||
|
||||
if (block.externalForbiddenLinks?.length > 0) {
|
||||
const recommendedManualCheckHeading = {
|
||||
blockLink: <div />,
|
||||
blockDisplayName: <RecommendedManualCheckHeading />,
|
||||
brokenLink: <div />,
|
||||
status: <div />,
|
||||
};
|
||||
const externalForbiddenLinks = block.externalForbiddenLinks.map((link) => ({
|
||||
blockLink: <GoToBlock block={block} />,
|
||||
blockDisplayName: block.displayName || '',
|
||||
brokenLink: <BrokenLinkHref href={link} />,
|
||||
status: <div />,
|
||||
}));
|
||||
|
||||
acc.push(recommendedManualCheckHeading);
|
||||
acc.push(...externalForbiddenLinks);
|
||||
}
|
||||
|
||||
const blockLockedLinks = block.lockedLinks.map((link) => ({
|
||||
blockLink: <GoToBlock block={block} />,
|
||||
blockDisplayName: block.displayName || '',
|
||||
brokenLink: <BrokenLinkHref href={link} />,
|
||||
status: (
|
||||
<span className="link-status-text">
|
||||
<Icon src={Lock} className="lock-icon" />
|
||||
{intl.formatMessage(messages.lockedLinkStatus)}{' '}
|
||||
<LockedInfoIcon />
|
||||
</span>
|
||||
),
|
||||
}));
|
||||
acc.push(...blockLockedLinks);
|
||||
return acc;
|
||||
},
|
||||
[],
|
||||
@@ -110,7 +153,7 @@ const BrokenLinkTable: FC<BrokenLinkTableProps> = ({
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,15 @@
|
||||
background-color: $dark-100;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:not(:first-child){
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.unit-card{
|
||||
border: 1px solid #BCBCBC;
|
||||
box-shadow: 0 1px 2px rgb(0 0 0 / .15);
|
||||
}
|
||||
|
||||
/* Subsection Header */
|
||||
@@ -49,7 +58,7 @@
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: .75rem;
|
||||
color: $primary-500;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,14 @@ const messages = defineMessages({
|
||||
id: 'course-authoring.course-optimizer.lockedLinkStatus',
|
||||
defaultMessage: 'Status: Locked',
|
||||
},
|
||||
recommendedManualCheckText: {
|
||||
id: 'course-authoring.course-optimizer.recommendedManualCheckText',
|
||||
defaultMessage: 'Recommended Manual Check',
|
||||
},
|
||||
recommendedManualCheckTooltip: {
|
||||
id: 'course-authoring.course-optimizer.recommendedManualCheckTooltip',
|
||||
defaultMessage: 'For websites returning 403, websites often show 403 because they don\'t want bots accessing their content',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface Unit {
|
||||
url: string;
|
||||
brokenLinks: string[];
|
||||
lockedLinks: string[];
|
||||
externalForbiddenLinks: string[];
|
||||
}[];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user