diff --git a/apps/trustlab/src/components/ReportCard/ReportCard.js b/apps/trustlab/src/components/ReportCard/ReportCard.js new file mode 100644 index 000000000..54eaac2fe --- /dev/null +++ b/apps/trustlab/src/components/ReportCard/ReportCard.js @@ -0,0 +1,145 @@ +import { Link } from "@commons-ui/next"; +import { LexicalRichText } from "@commons-ui/payload"; +import { + Box, + Card, + CardContent, + CardMedia, + Divider, + Typography, +} from "@mui/material"; +import { forwardRef } from "react"; + +const ReportCard = forwardRef(function ReportCard(props, ref) { + const { + image, + title, + description, + link, + actionLabel = "Download Report", + condensed = false, + date = "Jul 28, 2025", + sx, + ...other + } = props; + + return ( + + {image?.src && !condensed && ( + + )} + + + {title} + + + {date} + + {description && !condensed && ( + <> + + + {/* TODO: Remove link?.href integration is done */} + + + {actionLabel} + + + + )} + {description && condensed && ( + + + + + + {actionLabel} + + + + )} + + + ); +}); + +export default ReportCard; diff --git a/apps/trustlab/src/components/ReportCard/ReportCard.snap.js b/apps/trustlab/src/components/ReportCard/ReportCard.snap.js new file mode 100644 index 000000000..d135056c3 --- /dev/null +++ b/apps/trustlab/src/components/ReportCard/ReportCard.snap.js @@ -0,0 +1,201 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders in condensed mode 1`] = ` +
+
+

+ Test Report +

+
+ Jul 28, 2025 +
+
+
+
+ + This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations. + +
+
+
+ + Download Report + +
+
+
+
+`; + +exports[` renders unchanged 1`] = ` +
+ Test image +
+

+ Test Report +

+
+ Jul 28, 2025 +
+
+
+ + This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations. + +
+
+
+ + + Download Report + + +
+
+`; + +exports[` renders without image 1`] = ` +
+
+

+ Test Report +

+
+ Jul 28, 2025 +
+
+
+ + This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations. + +
+
+
+
+ + Download Report + +
+
+
+`; + +exports[` renders without link 1`] = ` +
+ Test image +
+

+ Test Report +

+
+ Jul 28, 2025 +
+
+
+ + This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations. + +
+
+
+
+ + Download Report + +
+
+
+`; diff --git a/apps/trustlab/src/components/ReportCard/ReportCard.test.js b/apps/trustlab/src/components/ReportCard/ReportCard.test.js new file mode 100644 index 000000000..224a26082 --- /dev/null +++ b/apps/trustlab/src/components/ReportCard/ReportCard.test.js @@ -0,0 +1,116 @@ +import { createRender } from "@commons-ui/testing-library"; +import React from "react"; + +import ReportCard from "./ReportCard"; + +import theme from "@/trustlab/theme"; + +const render = createRender({ theme }); + +const mockDescription = { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: "normal", + style: "", + text: "This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations.", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + textFormat: 0, + textStyle: "", + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, +}; + +describe("", () => { + it("renders unchanged", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders without image", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders in condensed mode", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders without link", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders with custom action label", () => { + const { getByText } = render( + , + ); + expect(getByText("View Full Report")).toBeInTheDocument(); + }); + + it("renders with default action label", () => { + const { getByText } = render( + , + ); + expect(getByText("Download Report")).toBeInTheDocument(); + }); +}); diff --git a/apps/trustlab/src/components/ReportCard/index.js b/apps/trustlab/src/components/ReportCard/index.js new file mode 100644 index 000000000..7a34db2da --- /dev/null +++ b/apps/trustlab/src/components/ReportCard/index.js @@ -0,0 +1,3 @@ +import ReportCard from "./ReportCard"; + +export default ReportCard; diff --git a/apps/trustlab/src/components/ReportsList/ReportsList.js b/apps/trustlab/src/components/ReportsList/ReportsList.js new file mode 100644 index 000000000..28319bf9d --- /dev/null +++ b/apps/trustlab/src/components/ReportsList/ReportsList.js @@ -0,0 +1,37 @@ +import { Section } from "@commons-ui/core"; +import { Grid2 as Grid, Box } from "@mui/material"; +import { forwardRef } from "react"; + +import ReportCard from "@/trustlab/components/ReportCard"; + +const ReportsList = forwardRef(function ReportsList(props, ref) { + const { reports = [], condensed, ...other } = props; + + if (!reports.length) { + return null; + } + + return ( + +
+ + {reports.map((report, index) => ( + + + + ))} + +
+
+ ); +}); + +export default ReportsList; diff --git a/apps/trustlab/src/components/ReportsList/ReportsList.snap.js b/apps/trustlab/src/components/ReportsList/ReportsList.snap.js new file mode 100644 index 000000000..543a5edbd --- /dev/null +++ b/apps/trustlab/src/components/ReportsList/ReportsList.snap.js @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders unchanged 1`] = `null`; diff --git a/apps/trustlab/src/components/ReportsList/ReportsList.test.js b/apps/trustlab/src/components/ReportsList/ReportsList.test.js new file mode 100644 index 000000000..2f9ac6bd5 --- /dev/null +++ b/apps/trustlab/src/components/ReportsList/ReportsList.test.js @@ -0,0 +1,149 @@ +import { createRender } from "@commons-ui/testing-library"; +import React from "react"; + +import ReportsList from "./ReportsList"; + +import theme from "@/trustlab/theme"; + +const render = createRender({ theme }); + +const mockCategories = [ + { + id: "1", + title: "Research Category 1", + description: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: "normal", + style: "", + text: "This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations.", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + textFormat: 0, + textStyle: "", + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, + }, + image: { + src: "/test-image-1.jpg", + alt: "Test image 1", + }, + link: { + href: "/category-1", + }, + }, + { + id: "2", + title: "Research Category 2", + description: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: "normal", + style: "", + text: "This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations.", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + textFormat: 0, + textStyle: "", + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, + }, + image: { + src: "/test-image-2.jpg", + alt: "Test image 2", + }, + link: { + href: "/category-2", + }, + }, + { + id: "3", + title: "Research Category 3", + description: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: "normal", + style: "", + text: "This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations.", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + textFormat: 0, + textStyle: "", + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, + }, + image: { + src: "/test-image-3.jpg", + alt: "Test image 3", + }, + link: { + href: "/category-3", + }, + }, +]; + +describe("", () => { + it("renders unchanged", () => { + const { container } = render(); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders empty list when no categories", () => { + const { container } = render(); + expect(container.firstChild).toBeNull(); + }); +}); diff --git a/apps/trustlab/src/components/ReportsList/index.js b/apps/trustlab/src/components/ReportsList/index.js new file mode 100644 index 000000000..99971a1e2 --- /dev/null +++ b/apps/trustlab/src/components/ReportsList/index.js @@ -0,0 +1,3 @@ +import ReportsList from "./ReportsList"; + +export default ReportsList; diff --git a/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.js b/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.js new file mode 100644 index 000000000..6dddcae71 --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.js @@ -0,0 +1,92 @@ +import { Link } from "@commons-ui/next"; +import { LexicalRichText } from "@commons-ui/payload"; +import { + Box, + Button, + Card, + CardContent, + CardMedia, + Typography, +} from "@mui/material"; +import { forwardRef } from "react"; + +const ResearchCategoryCard = forwardRef( + function ResearchCategoryCard(props, ref) { + const { + image, + title, + description, + link, + readMoreLabel = "Read More", + ...other + } = props; + + return ( + + {image?.src && ( + + )} + + + {title} + + {description && ( + + )} + {link?.href && ( + + + + )} + + + ); + }, +); + +export default ResearchCategoryCard; diff --git a/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.snap.js b/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.snap.js new file mode 100644 index 000000000..f67232f25 --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.snap.js @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders unchanged 1`] = ` + + Test image +
+

+ Test Research Category +

+
+
+

+ This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations. +

+
+
+
+ +
+
+
+`; + +exports[` renders without image 1`] = ` +
+
+

+ Test Research Category +

+
+
+

+ This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations. +

+
+
+
+
+`; + +exports[` renders without link 1`] = ` +
+ Test image +
+

+ Test Research Category +

+
+
+

+ This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations. +

+
+
+
+
+`; diff --git a/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.test.js b/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.test.js new file mode 100644 index 000000000..24cb43aa2 --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryCard/ResearchCategoryCard.test.js @@ -0,0 +1,141 @@ +import { createRender } from "@commons-ui/testing-library"; +import React from "react"; + +import ResearchCategoryCard from "./ResearchCategoryCard"; + +import theme from "@/trustlab/theme"; + +const render = createRender({ theme }); + +describe("", () => { + it("renders unchanged", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders without image", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders without link", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/apps/trustlab/src/components/ResearchCategoryCard/index.js b/apps/trustlab/src/components/ResearchCategoryCard/index.js new file mode 100644 index 000000000..efc06b207 --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryCard/index.js @@ -0,0 +1,3 @@ +import ResearchCategoryCard from "./ResearchCategoryCard"; + +export default ResearchCategoryCard; diff --git a/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.js b/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.js new file mode 100644 index 000000000..f4371af22 --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.js @@ -0,0 +1,29 @@ +import { Section } from "@commons-ui/core"; +import { Grid2 as Grid } from "@mui/material"; +import { forwardRef } from "react"; + +import ResearchCategoryCard from "@/trustlab/components/ResearchCategoryCard"; + +const ResearchCategoryList = forwardRef( + function ResearchCategoryList(props, ref) { + const { categories = [], ...other } = props; + + if (!categories.length) { + return null; + } + + return ( +
+ + {categories.map((category, index) => ( + + + + ))} + +
+ ); + }, +); + +export default ResearchCategoryList; diff --git a/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.snap.js b/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.snap.js new file mode 100644 index 000000000..78fd532f4 --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.snap.js @@ -0,0 +1,159 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders unchanged 1`] = ` + +`; diff --git a/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.test.js b/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.test.js new file mode 100644 index 000000000..634f56b1d --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryList/ResearchCategoryList.test.js @@ -0,0 +1,159 @@ +import { createRender } from "@commons-ui/testing-library"; +import React from "react"; + +import ResearchCategoryList from "./ResearchCategoryList"; + +import theme from "@/trustlab/theme"; + +const render = createRender({ theme }); + +const mockCategories = [ + { + id: "1", + title: "Research Category 1", + description: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: "normal", + style: "", + text: "This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations.", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + textFormat: 0, + textStyle: "", + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, + }, + image: { + src: "/test-image-1.jpg", + alt: "Test image 1", + }, + link: { + href: "/category-1", + }, + }, + { + id: "2", + title: "Research Category 2", + description: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: "normal", + style: "", + text: "This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations.", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + textFormat: 0, + textStyle: "", + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, + }, + image: { + src: "/test-image-2.jpg", + alt: "Test image 2", + }, + link: { + href: "/category-2", + }, + }, + { + id: "3", + title: "Research Category 3", + description: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: "normal", + style: "", + text: "This report is a baseline Information Ecosystem Assessment (IEA) of online communities in Kenya, mapping digital harms and malign actors, using the DISARM and D-RAIL frameworks for analysing weaponised hate speech, information manipulation and other forms of illicit influence operations.", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + textFormat: 0, + textStyle: "", + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, + }, + image: { + src: "/test-image-3.jpg", + alt: "Test image 3", + }, + link: { + href: "/category-3", + }, + }, +]; + +describe("", () => { + it("renders unchanged", () => { + const { container } = render( + , + ); + expect(container.firstChild).toMatchSnapshot(); + }); + + it("renders empty list when no categories", () => { + const { container } = render(); + expect(container.firstChild).toBeNull(); + }); + + it("renders correct number of cards", () => { + const { getAllByRole } = render( + , + ); + const cards = getAllByRole("heading", { level: 3 }); + expect(cards).toHaveLength(mockCategories.length); + }); +}); diff --git a/apps/trustlab/src/components/ResearchCategoryList/index.js b/apps/trustlab/src/components/ResearchCategoryList/index.js new file mode 100644 index 000000000..965714bfe --- /dev/null +++ b/apps/trustlab/src/components/ResearchCategoryList/index.js @@ -0,0 +1,3 @@ +import ResearchCategoryList from "./ResearchCategoryList"; + +export default ResearchCategoryList;