2022-08-27 17:03:05 +02:00

285 lines
10 KiB
TypeScript

import { GetStaticProps } from "next";
import { useMemo } from "react";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Chip } from "components/Chip";
import { Button } from "components/Inputs/Button";
import {
ContentPanel,
ContentPanelWidthSizes,
} from "components/Panels/ContentPanel";
import { ToolTip } from "components/ToolTip";
import { DevGetContentsQuery } from "graphql/generated";
import { getReadySdk } from "graphql/sdk";
import { filterDefined, filterHasAttributes } from "helpers/others";
import { Report, Severity } from "helpers/types/Report";
import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
/*
* ╭────────╮
* ──────────────────────────────────────────╯ PAGE ╰─────────────────────────────────────────────
*/
interface Props extends AppLayoutRequired {
contents: DevGetContentsQuery;
}
const CheckupContents = ({ contents, ...otherProps }: Props): JSX.Element => {
const testReport = useMemo(() => testingContent(contents), [contents]);
const contentPanel = useMemo(
() => (
<ContentPanel width={ContentPanelWidthSizes.Full}>
{<h2 className="text-2xl">{testReport.title}</h2>}
<div className="my-4 grid grid-cols-[2em,3em,2fr,1fr,0.5fr,0.5fr,2fr] items-center gap-2">
<p></p>
<p></p>
<p className="font-headers">Ref</p>
<p className="font-headers">Name</p>
<p className="font-headers">Type</p>
<p className="font-headers">Severity</p>
<p className="font-headers">Description</p>
</div>
{testReport.lines
.sort((a, b) => a.name.localeCompare(b.name))
.sort((a, b) => b.severity - a.severity)
.map((line, index) => (
<div
key={index}
className="mb-2 grid grid-cols-[2em,3em,2fr,1fr,0.5fr,0.5fr,2fr] items-center
justify-items-start gap-2"
>
<Button
href={line.frontendUrl}
className="w-4 text-xs"
text="F"
alwaysNewTab
/>
<Button
href={line.backendUrl}
className="w-4 text-xs"
text="B"
alwaysNewTab
/>
<p>{line.subitems.join(" -> ")}</p>
<p>{line.name}</p>
<Chip text={line.type} />
<Chip
className={
line.severity === Severity.VeryHigh
? "bg-[#f00] font-bold !opacity-100"
: line.severity === Severity.High
? "bg-[#ff6600] font-bold !opacity-100"
: line.severity === Severity.Medium
? "bg-[#fff344] !opacity-100"
: ""
}
text={Severity[line.severity]}
/>
<ToolTip content={line.recommandation} placement="left">
<p>{line.description}</p>
</ToolTip>
</div>
))}
</ContentPanel>
),
[testReport.lines, testReport.title]
);
return <AppLayout contentPanel={contentPanel} {...otherProps} />;
};
export default CheckupContents;
/*
* ╭──────────────────────╮
* ───────────────────────────────────╯ NEXT DATA FETCHING ╰──────────────────────────────────────
*/
export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk();
const langui = getLangui(context.locale);
const contents = await sdk.devGetContents();
const props: Props = {
contents: contents,
openGraph: getOpenGraph(langui, "Checkup Contents"),
};
return {
props: props,
};
};
/*
* ╭───────────────────╮
* ─────────────────────────────────────╯ PRIVATE METHODS ╰───────────────────────────────────────
*/
const testingContent = (contents: Props["contents"]): Report => {
const report: Report = {
title: "Contents",
lines: [],
};
filterHasAttributes(contents.contents?.data, ["attributes"] as const).map(
(content) => {
const backendUrl = `${process.env.NEXT_PUBLIC_URL_CMS}/admin/content-manager/collectionType/api::content.content/${content.id}`;
const frontendUrl = `${process.env.NEXT_PUBLIC_URL_SELF}/contents/${content.attributes.slug}`;
if (content.attributes.categories?.data.length === 0) {
report.lines.push({
subitems: [content.attributes.slug],
name: "No Category",
type: "Missing",
severity: Severity.High,
description: "The Content has no Category.",
recommandation: "Select a Category in relation with the Content",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
if (!content.attributes.type?.data?.id) {
report.lines.push({
subitems: [content.attributes.slug],
name: "No Type",
type: "Missing",
severity: Severity.High,
description: "The Content has no Type.",
recommandation: 'If unsure, use the "Other" Type.',
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
if (content.attributes.ranged_contents?.data.length === 0) {
report.lines.push({
subitems: [content.attributes.slug],
name: "No Ranged Content",
type: "Improvement",
severity: Severity.Low,
description: "The Content has no Ranged Content.",
recommandation:
"If this Content is available in one or multiple Library Item(s), create a Range Content to connect the Content to its Library Item(s).",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
if (!content.attributes.thumbnail?.data?.id) {
report.lines.push({
subitems: [content.attributes.slug],
name: "No Thumbnail",
type: "Missing",
severity: Severity.High,
description: "The Content has no Thumbnail.",
recommandation: "",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
if (content.attributes.translations?.length === 0) {
report.lines.push({
subitems: [content.attributes.slug],
name: "No Titles",
type: "Missing",
severity: Severity.High,
description: "The Content has no Titles.",
recommandation: "",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
} else {
const titleLanguages: string[] = [];
if (
content.attributes.translations &&
content.attributes.translations.length > 0
) {
filterDefined(content.attributes.translations).map(
(translation, titleIndex) => {
if (translation.language?.data?.id) {
if (translation.language.data.id in titleLanguages) {
report.lines.push({
subitems: [
content.attributes.slug,
`Title ${titleIndex.toString()}`,
],
name: "Duplicate Language",
type: "Error",
severity: Severity.High,
description: "",
recommandation: "",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
} else {
titleLanguages.push(translation.language.data.id);
}
} else {
report.lines.push({
subitems: [
content.attributes.slug,
`Title ${titleIndex.toString()}`,
],
name: "No Language",
type: "Error",
severity: Severity.VeryHigh,
description: "",
recommandation: "",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
if (!translation.description) {
report.lines.push({
subitems: [
content.attributes.slug,
`Title ${titleIndex.toString()}`,
],
name: "No Description",
type: "Missing",
severity: Severity.Medium,
description: "",
recommandation: "",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
if (!translation.text_set) {
report.lines.push({
subitems: [
content.attributes.slug,
translation.language?.data?.attributes?.code ?? "",
],
name: "No Text Set",
type: "Missing",
severity: Severity.High,
description: "The Content has no Text Set.",
recommandation: "",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
}
);
} else {
report.lines.push({
subitems: [content.attributes.slug],
name: "No Translations",
type: "Missing",
severity: Severity.High,
description: "The Content has no Translations.",
recommandation: "",
backendUrl: backendUrl,
frontendUrl: frontendUrl,
});
}
}
}
);
return report;
};