diff --git a/frontend/api/holon.ts b/frontend/api/holon.ts index efb99be50..5a077e7ed 100644 --- a/frontend/api/holon.ts +++ b/frontend/api/holon.ts @@ -23,6 +23,10 @@ export async function getHolonDataSegments() { return await httpGet(`/api/dummy-kosten-baten`); } +export async function getHolonDataSegmentsDetail() { + return await httpGet(`/api/dummy-kosten-baten`); +} + export async function getHolonGraphColor() { return await httpGet(`${API_URL}/v1/graph-colors/`); } diff --git a/frontend/components/Blocks/ChallengeFeedbackModal/ChallengeFeedbackModal.tsx b/frontend/components/Blocks/ChallengeFeedbackModal/ChallengeFeedbackModal.tsx index 4f2d367a6..88ddc4d95 100644 --- a/frontend/components/Blocks/ChallengeFeedbackModal/ChallengeFeedbackModal.tsx +++ b/frontend/components/Blocks/ChallengeFeedbackModal/ChallengeFeedbackModal.tsx @@ -43,7 +43,7 @@ export default function ChallengeFeedbackModal({ conditionItem.type == "interactive_input_condition" ? content?.find( content => content.value.id == parseFloat(conditionItem.value.parameter) - ).currentValue + )?.currentValue : kpis[splittedParameter[0]][splittedParameter[1]]; const conditionValue = parseFloat(conditionItem.value.value); diff --git a/frontend/components/Blocks/HolarchyFeedbackImage/HolarchyFeedbackImage.tsx b/frontend/components/Blocks/HolarchyFeedbackImage/HolarchyFeedbackImage.tsx index 3deb19881..3451ab00c 100644 --- a/frontend/components/Blocks/HolarchyFeedbackImage/HolarchyFeedbackImage.tsx +++ b/frontend/components/Blocks/HolarchyFeedbackImage/HolarchyFeedbackImage.tsx @@ -45,7 +45,7 @@ export default function HolarchyFeedbackImage({ content, holarchyfeedbackimages //inputvalue is the vaule of the assessed validator const inputvalue = content?.find( content => content.value.id == parseFloat(conditionItem.value.parameter) - ).currentValue; + )?.currentValue; const conditionValue = parseFloat(conditionItem.value.value); diff --git a/frontend/components/Blocks/SectionBlock/ContentColumn.tsx b/frontend/components/Blocks/SectionBlock/ContentColumn.tsx index 6b4c890de..21edcddb0 100644 --- a/frontend/components/Blocks/SectionBlock/ContentColumn.tsx +++ b/frontend/components/Blocks/SectionBlock/ContentColumn.tsx @@ -37,8 +37,10 @@ export default function ContentColumn({ break; } }); - - handleContentChange([...contentArr]); + // Only trigger api-call when input has changed + if (JSON.stringify(content) !== JSON.stringify(contentArr)) { + handleContentChange([...contentArr]); + } }, [dataContent]); function getDefaultValue(content: InteractiveContent): string | number | string[] | undefined { diff --git a/frontend/components/Blocks/SectionBlock/CostBenefitModal/CostBenefitModal.tsx b/frontend/components/Blocks/SectionBlock/CostBenefitModal/CostBenefitModal.tsx index 186bab9fb..97e059709 100644 --- a/frontend/components/Blocks/SectionBlock/CostBenefitModal/CostBenefitModal.tsx +++ b/frontend/components/Blocks/SectionBlock/CostBenefitModal/CostBenefitModal.tsx @@ -1,15 +1,52 @@ -import KostenBatenChart from "@/components/Charts/KostenBatenChart"; +import { useState, useEffect } from "react"; +import CostBenefitChart from "@/components/CostBenefit/CostBenefitChart"; +import CostBenefitDetail from "@/components/CostBenefit/CostBenefitDetail"; import { Tab } from "@headlessui/react"; import { XMarkIcon } from "@heroicons/react/24/outline"; import classNames from "classnames"; -import CostBenefitTable from "@/components/Charts/CostBenefitTable"; +import { + getHolonDataSegments, + getHolonDataSegmentsDetail, + getHolonGraphColor, +} from "../../../../api/holon"; + +import CostBenefitTable from "@/components/CostBenefit/CostBenefitTable"; export default function CostBenefitModal({ handleClose }: { handleClose: () => void }) { + const [data, setData] = useState([]); + const [detailData, setDetailData] = useState([]); + const [dataColors, setDataColors] = useState([]); + const ignoredLabels = ["name", "Netto kosten"]; + const handleClick = (e: React.MouseEvent) => { e.preventDefault(); handleClose(); }; + const convertGraphData = data => { + const returnArr: unknown[] = []; + Object.entries(data).map(value => { + const constructObj = { ...value[1] }; + constructObj.name = value[0].replace(/['"]+/g, ""); + returnArr.push(constructObj); + }); + + return returnArr; + }; + + useEffect(() => { + getHolonDataSegments() + .then(data => setData(data)) + .catch(err => console.log(err)); + + getHolonDataSegmentsDetail() + .then(data => setDetailData(data)) + .catch(err => console.log(err)); + + getHolonGraphColor() + .then(result => setDataColors(result.items)) + .catch(err => console.log(err)); + }, []); const tabItems = ["Grafiek", "Tabel", "Detail"]; return ( @@ -22,7 +59,7 @@ export default function CostBenefitModal({ handleClose }: { handleClose: () => v {tabItems.map((tabItem, index) => ( classNames( "p-3 mr-px ", @@ -40,16 +77,29 @@ export default function CostBenefitModal({ handleClose }: { handleClose: () => v - - -

Kosten en baten per groep

- + + +

Kosten en baten per segment

+
- +

Kosten en baten per groep

- + +
+ + +

Kosten en baten per subtype huishouden

+
- Content 3
diff --git a/frontend/components/Blocks/SectionBlock/HolarchyTab.tsx b/frontend/components/Blocks/SectionBlock/HolarchyTab.tsx index a4c456dee..ad86e8878 100644 --- a/frontend/components/Blocks/SectionBlock/HolarchyTab.tsx +++ b/frontend/components/Blocks/SectionBlock/HolarchyTab.tsx @@ -39,14 +39,23 @@ export default function HolarchyTab({ {/*Interactive input - left column */} {levels.map((level, index) => { const cssClasses = [ - "row-start-1 bg-holon-blue-100 ", - "row-start-2 bg-holon-blue-200", - "row-start-3 bg-holon-blue-300", + "row-start-1 bg-holon-holarchy-national", + "row-start-2 bg-holon-holarchy-intermediate", + "row-start-3 bg-holon-holarchy-local", ]; return (
+ className={`${cssClasses[index]} p-4 overflow-auto row-span-1 col-start-1 col-span-1 md:col-start-1 md:col-span-1 md:row-span-1 `}> +

+ {level == "national" + ? textLabelNational + : level == "local" + ? textLabelLocal + : level == "intermediate" + ? textLabelIntermediate + : ""} +

{/*image - highest block*/} -
- - - -
+
{/*image - middle block showing image*/} -
+
{holarchyFeedbackImages.length > 0 && ( {/*image - lowest block*/} -
- - - -
+
{/* KPIs - right column */} {/*National KPIs */} diff --git a/frontend/components/Blocks/SectionBlock/SectionBlock.tsx b/frontend/components/Blocks/SectionBlock/SectionBlock.tsx index 4df676ff9..fb3f74eb5 100644 --- a/frontend/components/Blocks/SectionBlock/SectionBlock.tsx +++ b/frontend/components/Blocks/SectionBlock/SectionBlock.tsx @@ -54,7 +54,7 @@ export default function SectionBlock({ data, pagetype, feedbackmodals }: Props) const [costBenefitModal, setCostBenefitModal] = useState(false); const [holarchyModal, setHolarchyModal] = useState(false); - const myRef = useRef(null); + const sectionContainerRef = useRef(null); const backgroundFullcolor = data.value.background.size == "bg__full" ? data.value.background.color : ""; @@ -93,12 +93,14 @@ export default function SectionBlock({ data, pagetype, feedbackmodals }: Props) function openHolarchyModal() { setHolarchyModal(true); - myRef.current.classList.add("h-screen"); - myRef.current.scrollIntoView(); + sectionContainerRef.current.classList.add("h-screen"); + setTimeout(() => { + sectionContainerRef.current.scrollIntoView(); + }, 0); } function closeHolarchyModal() { - myRef.current.classList.remove("h-screen"); + sectionContainerRef.current.classList.remove("h-screen"); setHolarchyModal(false); } @@ -129,7 +131,7 @@ export default function SectionBlock({ data, pagetype, feedbackmodals }: Props) } return ( -
+
{feedbackmodals && ( )} diff --git a/frontend/components/Charts/CostBenefit.module.css b/frontend/components/Charts/CostBenefit.module.css deleted file mode 100644 index b8794dfcb..000000000 --- a/frontend/components/Charts/CostBenefit.module.css +++ /dev/null @@ -1,32 +0,0 @@ -.Table tfoot { - border-top-width: 4px; -} -.Table tfoot td { - background-color: transparent !important; - font-weight: bold; - border-top-width: 4px; -} - -.Table abbr + span { - opacity: 0; - pointer-events: none; -} -.Table th, -.Table td { - position: relative; - z-index: 0; -} -.Table th:hover, -.Table td:hover { - filter: brightness(0.9); - z-index: 1; -} -.Table abbr { - text-decoration: none; -} -.Table th:hover abbr + span, -.Table td:hover abbr + span { - opacity: 1; - transition: 0s all; - transition-delay: 0.3s; -} diff --git a/frontend/components/Charts/dummyData.tsx b/frontend/components/Charts/dummyData.tsx deleted file mode 100644 index 9408e4232..000000000 --- a/frontend/components/Charts/dummyData.tsx +++ /dev/null @@ -1,62 +0,0 @@ -export const dummyData = { - Huishouden: { - Afschrijving: "-60", - Huishouden: null, - "Commercieel bedrijf": "0", - Overheidsinstelling: "0", - Energieleverancier: "-200", - Netbeheerder: "-200", - Overheid: "125", - "Netto kosten": "-335", - }, - "Commercieel bedrijf": { - Afschrijving: "0", - Huishouden: "0", - "Commercieel bedrijf": null, - Overheidsinstelling: "0", - Energieleverancier: "-200", - Netbeheerder: "-100", - Overheid: "-50", - "Netto kosten": "-350", - }, - Overheidsinstelling: { - Afschrijving: "-20", - Huishouden: "0", - "Commercieel bedrijf": "0", - Overheidsinstelling: null, - Energieleverancier: "-100", - Netbeheerder: "-200", - Overheid: "-75", - "Netto kosten": "-395", - }, - Energieleverancier: { - Afschrijving: "0", - Huishouden: "200", - "Commercieel bedrijf": "200", - Overheidsinstelling: "100", - Energieleverancier: null, - Netbeheerder: "0", - Overheid: "0", - "Netto kosten": "500", - }, - Netbeheerder: { - Afschrijving: "-500", - Huishouden: "200", - "Commercieel bedrijf": "100", - Overheidsinstelling: "200", - Energieleverancier: "0", - Netbeheerder: null, - Overheid: "0", - "Netto kosten": "0", - }, - Overheid: { - Afschrijving: "0", - Huishouden: "-125", - "Commercieel bedrijf": "50", - Overheidsinstelling: "75", - Energieleverancier: "0", - Netbeheerder: "0", - Overheid: null, - "Netto kosten": "0", - }, -}; diff --git a/frontend/components/CostBenefit/CostBenefit.module.css b/frontend/components/CostBenefit/CostBenefit.module.css new file mode 100644 index 000000000..a3430b187 --- /dev/null +++ b/frontend/components/CostBenefit/CostBenefit.module.css @@ -0,0 +1,64 @@ +.Table tfoot { + border-top-width: 4px; +} +.Table tfoot td { + background-color: transparent !important; + font-weight: bold; + border-top-width: 4px; +} + +.Table abbr + span { + opacity: 0; + pointer-events: none; +} +.Table th, +.Table td { + position: relative; + z-index: 0; + padding: 1rem; +} + +.Table th:hover, +.Table td:hover { + filter: brightness(0.9); + z-index: 1; +} +.Table abbr { + text-decoration: none; +} +.Table th:hover abbr + span, +.Table td:hover abbr + span { + opacity: 1; + transition: 0s all; + transition-delay: 0.3s; +} + +@media (max-width: 1599px) { + .CompactTable th, + .CompactTable td { + padding-right: 0.25rem; + padding-left: 0.25rem; + font-size: 13px; + } + .CompactTable th + th span { + writing-mode: vertical-rl; + rotate: 180deg; + padding: 1rem 0; + } +} +@media (max-height: 800px) { + .CompactTable th, + .CompactTable td { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + font-size: 13px; + } +} + +@media (max-height: 1000px) { + .CompactTable th, + .CompactTable td { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + } +} diff --git a/frontend/components/Charts/KostenBatenChart.tsx b/frontend/components/CostBenefit/CostBenefitChart.tsx similarity index 54% rename from frontend/components/Charts/KostenBatenChart.tsx rename to frontend/components/CostBenefit/CostBenefitChart.tsx index e55e1a13c..a5a72997f 100644 --- a/frontend/components/Charts/KostenBatenChart.tsx +++ b/frontend/components/CostBenefit/CostBenefitChart.tsx @@ -1,5 +1,5 @@ -import React, { useState, useEffect } from "react"; -import { getHolonDataSegments, getHolonGraphColor } from "../../api/holon"; +import React from "react"; + import { Bar, XAxis, @@ -12,33 +12,13 @@ import { BarChart, ResponsiveContainer, } from "recharts"; +import { CostBenefitChartProps } from "./types"; -export default function KostenBatenChart() { - const [data, setData] = useState([]); - const [dataColors, setDataColors] = useState([]); - const ignoredLabels = ["name", "Netto kosten"]; - - const convertGraphData = (data: Record) => { - const returnArr: unknown[] = []; - Object.entries(data).map(value => { - const constructObj = { ...value[1] }; - constructObj.name = value[0].replace(/['"]+/g, ""); - returnArr.push(constructObj); - }); - - return returnArr; - }; - - useEffect(() => { - getHolonDataSegments() - .then(data => setData(convertGraphData(data))) - .catch(err => console.log(err)); - - getHolonGraphColor() - .then(result => setDataColors(result.items)) - .catch(err => console.log(err)); - }, []); - +export default function CostBenefitChart({ + chartdata, + dataColors, + ignoredLabels, +}: CostBenefitChartProps) { const CustomBarWithTarget = props => { const { fill, x, y, width } = props; @@ -49,26 +29,36 @@ export default function KostenBatenChart() { ); }; - const convertToPositiveEuro = tickItem => { + const convertToPositiveEuro = (tickItem: number) => { return "€ " + Math.abs(tickItem); }; - const tooltipFormatter = (value, name, props) => { - return [ - convertToPositiveEuro(value), - (value < 0 ? "betaalt aan " : "ontvangt van ") + props.dataKey, - ]; - }; - const tooltipLabelFormatter = tooltipItemLabel => { - return tooltipItemLabel + ":"; + let columnLabel: string; + const CustomTooltip = ({ active, payload, label }) => { + let activeItem = payload.find(label => label.dataKey === columnLabel); + if (payload.length === 1) { + // in case, the bar is 0 + activeItem = payload[0]; + } + if (active && activeItem) { + return ( +
+ {`${label}${ + activeItem.value < 0 + ? ` betaalt ${convertToPositiveEuro(activeItem.value)} aan ` + : ` ontvangt ${convertToPositiveEuro(activeItem.value)} van ` + } ${activeItem.name} `} +
+ ); + } + return null; }; - return ( - {data.length > 0 && ( + {chartdata.length > 0 && (
- + @@ -79,15 +69,11 @@ export default function KostenBatenChart() { offset={-25} /> - item.value} - formatter={tooltipFormatter} - labelFormatter={tooltipLabelFormatter} - /> + } itemSorter={item => item.value} /> - {Object.keys(data[0]).map((label, _index) => { + {Object.keys(chartdata[0]).map((label, index) => { const found = ignoredLabels.find(ilabel => ilabel == label); if (!found) { const color = dataColors.find(col => col.name == label) || { @@ -97,10 +83,12 @@ export default function KostenBatenChart() { return ( (columnLabel = label)} + onMouseLeave={() => (columnLabel = "")} /> ); } @@ -111,6 +99,8 @@ export default function KostenBatenChart() { dataKey="Netto kosten" shape={} fill="#FF1818" + onMouseOver={() => (columnLabel = "Netto kosten")} + onMouseLeave={() => (columnLabel = "")} /> diff --git a/frontend/components/CostBenefit/CostBenefitDetail.tsx b/frontend/components/CostBenefit/CostBenefitDetail.tsx new file mode 100644 index 000000000..e1251f0da --- /dev/null +++ b/frontend/components/CostBenefit/CostBenefitDetail.tsx @@ -0,0 +1,57 @@ +import classNames from "classnames"; +import React from "react"; +import { Tab } from "@headlessui/react"; +import { TableCellsIcon, ChartBarIcon } from "@heroicons/react/24/outline"; +import CostBenefitChart from "./CostBenefitChart"; +import CostBenefitTable from "./CostBenefitTable"; + +import { CostBenefitChartProps } from "./types"; + +export default function CostBenefitDetail({ + chartdata, + detailData, + dataColors, + ignoredLabels, +}: CostBenefitChartProps) { + const subTabItems = ["Grafiek", "Tabel"]; + + return ( + + + {subTabItems.map((tabItem, index) => ( + + classNames( + "p-1 border-b-4 bg-transparent ", + selected + ? "text-holon-blue-900 border-holon-blue-900" + : "border-transparent text-holon-blue-500" + ) + }> + + {tabItem == "Grafiek" ? ( + + ) : ( + + )} + {tabItem} + + + ))} + + + + + + + + + + + ); +} diff --git a/frontend/components/Charts/CostBenefitTable.tsx b/frontend/components/CostBenefit/CostBenefitTable.tsx similarity index 75% rename from frontend/components/Charts/CostBenefitTable.tsx rename to frontend/components/CostBenefit/CostBenefitTable.tsx index b246c32e4..b8fb55ce4 100644 --- a/frontend/components/Charts/CostBenefitTable.tsx +++ b/frontend/components/CostBenefit/CostBenefitTable.tsx @@ -1,9 +1,8 @@ import { ArrowDownIcon } from "@heroicons/react/24/outline"; -import { dummyData } from "./dummyData"; import styles from "./CostBenefit.module.css"; import React from "react"; -export default function CostBenefitTable() { +export default function CostBenefitTable({ tableData }: { tableData: Array }) { const backgroundCell = { pos: "bg-holon-light-green", neg: "bg-holon-light-red", @@ -24,7 +23,10 @@ export default function CostBenefitTable() { return Object.keys(data); }; - const headings = getHeadings(dummyData); + const headings = getHeadings(tableData); + + //when there are a lot of columns, show all columns more compact + const CompactTable = headings.length > 9 ? true : false; function valueCheck(value: number | undefined) { if (!value) { @@ -51,19 +53,19 @@ export default function CostBenefitTable() { return ( <> {titleItem == "Netto kosten" ? `Totaal` : titleItem} {headings.map((heading, index) => { const tableCellValue = - dummyData[headings[index]] && dummyData[headings[index]][titleItem]; + tableData[headings[index]] && tableData[headings[index]][titleItem]; return ( {!tableCellValue || tableCellValue == 0 || titleItem == "Netto kosten" @@ -85,11 +87,14 @@ export default function CostBenefitTable() { }; return ( -
- +
+
- {headings.map((heading, index) => ( - ))} diff --git a/frontend/components/CostBenefit/types.ts b/frontend/components/CostBenefit/types.ts new file mode 100644 index 000000000..46fcdf8a1 --- /dev/null +++ b/frontend/components/CostBenefit/types.ts @@ -0,0 +1,10 @@ + export type DataColorsProps = { + color: string; + name: string; + }; + export type CostBenefitChartProps = { + chartdata: Array; + detailData?: Array; + dataColors: DataColorsProps[]; + ignoredLabels: Array; + }; \ No newline at end of file diff --git a/frontend/components/InteractiveImage/ImageSlider.tsx b/frontend/components/InteractiveImage/ImageSlider.tsx index 8efae30f8..d35d1adb6 100644 --- a/frontend/components/InteractiveImage/ImageSlider.tsx +++ b/frontend/components/InteractiveImage/ImageSlider.tsx @@ -48,8 +48,8 @@ export default function ImageSlider({ className="flex text-base font-bold"> {label} - - {moreInformation || linkWikiPage ? ( + {/* if selectedLevel, then you are in the holarchy view and popover is not shown */} + {!selectedLevel && (moreInformation || linkWikiPage) ? ( ", () => { - describe("renders an Interactive input slider", () => { - beforeEach(() => { - render( - - ); - }); - - it("renders a interactive Input slider", () => { - // TODO: Fix this test - // const input = screen.getByTestId("test"); - // expect(input).toBeInTheDocument(); - }); - }); -}); diff --git a/frontend/components/InteractiveInputs/InteractiveInputs.tsx b/frontend/components/InteractiveInputs/InteractiveInputs.tsx index 2810501bf..7ee20f4a2 100644 --- a/frontend/components/InteractiveInputs/InteractiveInputs.tsx +++ b/frontend/components/InteractiveInputs/InteractiveInputs.tsx @@ -83,7 +83,8 @@ function InteractiveRadios({

{name}

- {moreInformation || linkWikiPage ? ( + {/* if selectedLevel, then you are in the holarchy view and popover is not shown */} + {!selectedLevel && (moreInformation || linkWikiPage) ? ( {inputItem.label || inputItem.option} - {inputItem.legalLimitation || inputItem.linkWikiPage ? ( + {/* if selectedLevel, then you are in the holarchy view and popover is not shown */} + {!selectedLevel && (inputItem.legalLimitation || inputItem.linkWikiPage) ? ( (

diff --git a/frontend/components/KPIDashboard/KPIItem.module.css b/frontend/components/KPIDashboard/KPIItem.module.css index 55da59ede..1166f259d 100644 --- a/frontend/components/KPIDashboard/KPIItem.module.css +++ b/frontend/components/KPIDashboard/KPIItem.module.css @@ -69,10 +69,13 @@ gap: 0.25rem; } .kpiHolarchy__title { - padding: 0rem 0.5rem 0; + padding: 0.5rem 0.5rem 0; flex: 1 1 100%; font-weight: 600; } +.kpiHolarchy__nodata { + padding: 0.5rem 0.5rem 0; +} .kpiHolarchy output { font-size: 1.1rem; @@ -105,6 +108,9 @@ .kpiHolarchy__title { padding: 0.5rem 1.5rem 0; } + .kpiHolarchy__nodata { + padding: 0rem 1.5rem; + } .kpiHolarchy [data-class="kpiIcon"] { width: 2.2rem; } diff --git a/frontend/components/KPIDashboard/KPIItems.tsx b/frontend/components/KPIDashboard/KPIItems.tsx index 32dde39fd..dab854454 100644 --- a/frontend/components/KPIDashboard/KPIItems.tsx +++ b/frontend/components/KPIDashboard/KPIItems.tsx @@ -1,6 +1,7 @@ import React from "react"; import KPIItem from "./KPIItem"; import { KPIData } from "./types"; +import styles from "./KPIItem.module.css"; type KPIItems = { view: string; @@ -32,32 +33,38 @@ export default function KPIItems({ view, data, level, loading }: KPIItems) { return ( - - - - + {data[level] ? ( + + + + + + + ) : ( + Er is geen data op dit niveau. + )} ); } diff --git a/frontend/pages/api/dummy-kosten-baten-2.ts b/frontend/pages/api/dummy-kosten-baten-2.ts new file mode 100644 index 000000000..ace098cf7 --- /dev/null +++ b/frontend/pages/api/dummy-kosten-baten-2.ts @@ -0,0 +1,27 @@ +export default function handler(req, res) { + const data = { + "Type A": { + Afschrijving: "-60", + Huishouden: null, + "Commercieel bedrijf": "50", + Overheidsinstelling: "70", + Energieleverancier: "-200", + Netbeheerder: "-200", + Overheid: "125", + "Netto kosten": "-335", + }, + "Type B": { + Afschrijving: "20", + Huishouden: "-40", + "Commercieel bedrijf": "25", + Overheidsinstelling: "15", + Energieleverancier: "-200", + Netbeheerder: "-100", + Overheid: "-50", + "Netto kosten": "-350", + }, + }; + + res.status(200).json(data); + } + \ No newline at end of file diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 1a0bf00f5..6096dc1ad 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -31,6 +31,9 @@ module.exports = { "holon-light-green": "#DEF3DE", "holon-red": "#c51700", "holon-light-red": "#FFCCCC", + "holon-holarchy-national": "#DAE5F5", + "holon-holarchy-intermediate": "#B9CAE2", + "holon-holarchy-local": "#9DB2CF", }, backgroundImage: { "split-white-blue": "linear-gradient(-18deg, #051E3F 40% , white 30%)", diff --git a/src/main/blocks/feedbackmodals.py b/src/main/blocks/feedbackmodals.py index 7fd0be11d..3bad52ed2 100644 --- a/src/main/blocks/feedbackmodals.py +++ b/src/main/blocks/feedbackmodals.py @@ -54,7 +54,12 @@ class FeedbackModalInteractiveInputCondition(blocks.StructBlock): def get_interactive_inputs(): return [(ii.pk, ii.__str__) for ii in InteractiveInput.objects.all()] - parameter = blocks.ChoiceBlock(choices=get_interactive_inputs) + parameter = blocks.ChoiceBlock( + choices=get_interactive_inputs, + help_text=_( + "Please make sure the parameter is present in this section. Otherwise you assert something that doesn't exist" + ), + ) operator = blocks.ChoiceBlock( max_length=50, diff --git a/src/main/migrations/0047_alter_challengemodepage_feedbackmodals_and_more.py b/src/main/migrations/0047_alter_challengemodepage_feedbackmodals_and_more.py new file mode 100644 index 000000000..cf729cbfe --- /dev/null +++ b/src/main/migrations/0047_alter_challengemodepage_feedbackmodals_and_more.py @@ -0,0 +1,2125 @@ +# Generated by Django 4.1.7 on 2023-03-02 14:08 + +from django.db import migrations +import main.blocks.feedbackmodals +import main.blocks.holon_image_chooser +import main.blocks.page_chooser_block +import main.blocks.rich_text_block +import main.blocks.storyline_section +import wagtail.blocks +import wagtail.embeds.blocks +import wagtail.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ("main", "0046_merge_20230224_1027"), + ] + + operations = [ + migrations.AlterField( + model_name="challengemodepage", + name="feedbackmodals", + field=wagtail.fields.StreamField( + [ + ( + "feedbackmodals", + wagtail.blocks.StructBlock( + [ + ( + "modaltitle", + wagtail.blocks.CharBlock( + help_text="Set the title of the feedback modal", + max_length=255, + required=False, + ), + ), + ( + "modaltext", + wagtail.blocks.TextBlock( + help_text="Text of the modal", required=False + ), + ), + ( + "modaltheme", + wagtail.blocks.ChoiceBlock( + choices=[ + ("green", "Green"), + ( + "greenwithconfetti", + "Green with confetti", + ), + ("orange", "Orange"), + ("red", "Red"), + ], + help_text="Set the theme of this modal", + max_length=30, + ), + ), + ( + "image_selector", + main.blocks.holon_image_chooser.HolonImageChooserBlock(), + ), + ( + "conditions", + wagtail.blocks.StreamBlock( + [ + ( + "kpi_condition", + wagtail.blocks.StructBlock( + [ + ( + "parameter", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "local|costs", + "Local Costs", + ), + ( + "local|netload", + "Local Netload", + ), + ( + "local|self_sufficiency", + "Local Sufficiency", + ), + ( + "local|sustainability", + "Local Sustainability", + ), + ( + "national|costs", + "National Costs", + ), + ( + "national|netload", + "National Netload", + ), + ( + "national|self_sufficiency", + "National Sufficiency", + ), + ( + "national|sustainability", + "National Sustainability", + ), + ], + help_text="Set the parameter of this condition", + max_length=100, + ), + ), + ( + "operator", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bigger", + "Bigger", + ), + ( + "biggerequal", + "Bigger or Equal", + ), + ("equal", "Equal"), + ( + "notequal", + "Not Equal", + ), + ("lower", "Lower"), + ( + "lowerequal", + "Lower or Equal", + ), + ], + help_text="Set the operator of this condition", + max_length=50, + ), + ), + ( + "value", + wagtail.blocks.CharBlock( + help_text="Set the value of this condition to compare to", + max_length=255, + required=True, + ), + ), + ] + ), + ), + ( + "interactive_input_condition", + wagtail.blocks.StructBlock( + [ + ( + "parameter", + wagtail.blocks.ChoiceBlock( + choices=main.blocks.feedbackmodals.FeedbackModalInteractiveInputCondition.get_interactive_inputs, + help_text="Please make sure the parameter is present in this section. Otherwise you assert something that doesn't exist", + ), + ), + ( + "operator", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bigger", + "Bigger", + ), + ( + "biggerequal", + "Bigger or Equal", + ), + ("equal", "Equal"), + ( + "notequal", + "Not Equal", + ), + ("lower", "Lower"), + ( + "lowerequal", + "Lower or Equal", + ), + ], + help_text="Set the operator of this condition", + max_length=50, + ), + ), + ( + "value", + wagtail.blocks.CharBlock( + help_text="Set the value of this condition to compare to", + max_length=255, + required=True, + ), + ), + ] + ), + ), + ], + block_counts={}, + help_text="Feedback will only be shown when ALL conditions of a modal are true", + use_json_field=True, + ), + ), + ] + ), + ) + ], + blank=True, + null=True, + use_json_field=True, + ), + ), + migrations.AlterField( + model_name="challengemodepage", + name="storyline", + field=wagtail.fields.StreamField( + [ + ( + "header_full_image_block", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(required=True)), + ( + "size", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ("", "Select header size"), + ("h1", "H1"), + ("h2", "H2"), + ], + ), + ), + ( + "image_selector", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=True + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + help_text="Fill in this alt-text only when you want to describe the image (for screenreaders and SEO)", + required=False, + ), + ), + ] + ), + ), + ( + "text_and_media", + wagtail.blocks.StructBlock( + [ + ( + "grid_layout", + wagtail.blocks.StructBlock( + [ + ( + "grid", + wagtail.blocks.ChoiceBlock( + choices=[ + ("33_66", "33% - 66%"), + ("50_50", "50% - 50%"), + ("66_33", "66% - 33%"), + ] + ), + ) + ], + required=True, + ), + ), + ( + "column_order", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ("", "Default (Text left, Media right)"), + ( + "invert", + "Invert columns (Media left, Text right)", + ), + ], + required=False, + ), + ), + ( + "background", + wagtail.blocks.StructBlock( + [ + ( + "color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("block__bg-white", "White"), + ("block__bg-gray", "Pale gray"), + ( + "block__bg-purple", + "Pale purple", + ), + ] + ), + ), + ( + "size", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bg__full", + "Full backgroundcolor", + ), + ( + "bg__left", + "Only backgroundcolor in the left block", + ), + ] + ), + ), + ] + ), + ), + ( + "text", + main.blocks.rich_text_block.RichtextBlock( + help_text="Add your text", + required=True, + rows=15, + ), + ), + ( + "media", + wagtail.blocks.StreamBlock( + [ + ( + "image", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=False + ), + ), + ( + "video", + wagtail.embeds.blocks.EmbedBlock( + help_text="Youtube url of vimeo url", + required=False, + ), + ), + ], + help_text="Choose an image or paste an embed url", + max_num=1, + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + help_text="Fill in this alt-text only when you want to describe the image (for screenreaders and SEO)", + required=False, + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ( + "section", + wagtail.blocks.StructBlock( + [ + ( + "background", + wagtail.blocks.StructBlock( + [ + ( + "color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("block__bg-white", "White"), + ("block__bg-gray", "Pale gray"), + ( + "block__bg-purple", + "Pale purple", + ), + ] + ), + ), + ( + "size", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bg__full", + "Full backgroundcolor", + ), + ( + "bg__left", + "Only backgroundcolor in the left block", + ), + ] + ), + ), + ] + ), + ), + ( + "grid_layout", + wagtail.blocks.StructBlock( + [ + ( + "grid", + wagtail.blocks.ChoiceBlock( + choices=[ + ("33_66", "33% - 66%"), + ("50_50", "50% - 50%"), + ("66_33", "66% - 33%"), + ] + ), + ) + ], + required=True, + ), + ), + ( + "text_label_national", + wagtail.blocks.CharBlock( + default="Nationaal", required=True + ), + ), + ( + "text_label_intermediate", + wagtail.blocks.CharBlock( + default="Regionaal", required=True + ), + ), + ( + "text_label_local", + wagtail.blocks.CharBlock( + default="Lokaal", required=True + ), + ), + ( + "content", + wagtail.blocks.StreamBlock( + [ + ( + "text", + main.blocks.rich_text_block.RichtextBlock(), + ), + ( + "interactive_input", + wagtail.blocks.StructBlock( + [ + ( + "interactive_input", + wagtail.blocks.ChoiceBlock( + choices=main.blocks.storyline_section.get_interactive_inputs + ), + ), + ( + "display", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "checkbox_radio", + "Show as checkboxe(s) or radiobutton(s)", + ), + ( + "button", + "Show as button(s)", + ), + ], + help_text="Only applies if the interactive input is a Select type", + ), + ), + ( + "visible", + wagtail.blocks.BooleanBlock( + default=True, + required=False, + ), + ), + ( + "locked", + wagtail.blocks.BooleanBlock( + required=False + ), + ), + ( + "default_value", + wagtail.blocks.CharBlock( + help_text="Type the default value exactly as it's shown on the website page", + required=False, + ), + ), + ] + ), + ), + ( + "static_image", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=False + ), + ), + ( + "holarchy_feedback_image", + wagtail.blocks.StructBlock( + [ + ( + "image_selector", + main.blocks.holon_image_chooser.HolonImageChooserBlock(), + ), + ( + "conditions", + wagtail.blocks.StreamBlock( + [ + ( + "interactive_input_condition", + wagtail.blocks.StructBlock( + [ + ( + "parameter", + wagtail.blocks.ChoiceBlock( + choices=main.blocks.feedbackmodals.FeedbackModalInteractiveInputCondition.get_interactive_inputs, + help_text="Please make sure the parameter is present in this section. Otherwise you assert something that doesn't exist", + ), + ), + ( + "operator", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bigger", + "Bigger", + ), + ( + "biggerequal", + "Bigger or Equal", + ), + ( + "equal", + "Equal", + ), + ( + "notequal", + "Not Equal", + ), + ( + "lower", + "Lower", + ), + ( + "lowerequal", + "Lower or Equal", + ), + ], + help_text="Set the operator of this condition", + max_length=50, + ), + ), + ( + "value", + wagtail.blocks.CharBlock( + help_text="Set the value of this condition to compare to", + max_length=255, + required=True, + ), + ), + ] + ), + ) + ], + block_counts={}, + help_text="Image will only be shown when ALL conditions of a holarchy feedback image are true", + use_json_field=True, + ), + ), + ] + ), + ), + ], + block_counts={"static_image": {"max_num": 1}}, + ), + ), + ] + ), + ), + ( + "heroblock", + wagtail.blocks.StructBlock( + [ + ( + "background_color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("", "Default color"), + ("block__bg-gray", "Pale gray"), + ("block__bg-purple", "Pale purple"), + ], + required=False, + ), + ), + ( + "title", + wagtail.blocks.CharBlock( + form_classname="title", required=True + ), + ), + ( + "text", + main.blocks.rich_text_block.RichtextBlock( + required=True + ), + ), + ( + "media", + wagtail.blocks.StreamBlock( + [ + ( + "image", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=False + ), + ), + ( + "video", + wagtail.embeds.blocks.EmbedBlock( + required=False + ), + ), + ], + help_text="Choose an image or paste an embed url", + max_num=1, + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + help_text="Fill in this alt-text only when you want to describe the image (for screenreaders and SEO)", + required=False, + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ( + "title_block", + wagtail.blocks.StructBlock( + [ + ( + "background_color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("", "Default color"), + ("block__bg-gray", "Pale gray"), + ("block__bg-purple", "Pale purple"), + ], + required=False, + ), + ), + ("title", wagtail.blocks.CharBlock(required=True)), + ( + "size", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ("", "Select header size"), + ("h1", "H1"), + ("h2", "H2"), + ], + ), + ), + ( + "text", + main.blocks.rich_text_block.RichtextBlock( + required=False + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ( + "card_block", + wagtail.blocks.StructBlock( + [ + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + required=False + ), + ), + ( + "image_selector", + main.blocks.holon_image_chooser.HolonImageChooserBlock(), + ), + ( + "description", + wagtail.blocks.CharBlock( + max_length=255, required=False + ), + ), + ( + "card_color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("card__bg-gold", "Gold"), + ("card__bg-blue", "Blue"), + ("card__bg-gray", "Gray"), + ( + "card__bg-purple", + "Purple", + ), + ("card__bg-pink", "Pink"), + ( + "card__bg-orange", + "Orange", + ), + ], + required=False, + ), + ), + ( + "item_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the card to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the card should link externally", + required=False, + ), + ), + ], + help_text="Optional: add an internal or external link to the card", + max_num=1, + required=False, + ), + ), + ] + ) + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ], + use_json_field=True, + ), + ), + migrations.AlterField( + model_name="storylinepage", + name="storyline", + field=wagtail.fields.StreamField( + [ + ( + "header_full_image_block", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(required=True)), + ( + "size", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ("", "Select header size"), + ("h1", "H1"), + ("h2", "H2"), + ], + ), + ), + ( + "image_selector", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=True + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + help_text="Fill in this alt-text only when you want to describe the image (for screenreaders and SEO)", + required=False, + ), + ), + ] + ), + ), + ( + "text_and_media", + wagtail.blocks.StructBlock( + [ + ( + "grid_layout", + wagtail.blocks.StructBlock( + [ + ( + "grid", + wagtail.blocks.ChoiceBlock( + choices=[ + ("33_66", "33% - 66%"), + ("50_50", "50% - 50%"), + ("66_33", "66% - 33%"), + ] + ), + ) + ], + required=True, + ), + ), + ( + "column_order", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ("", "Default (Text left, Media right)"), + ( + "invert", + "Invert columns (Media left, Text right)", + ), + ], + required=False, + ), + ), + ( + "background", + wagtail.blocks.StructBlock( + [ + ( + "color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("block__bg-white", "White"), + ("block__bg-gray", "Pale gray"), + ( + "block__bg-purple", + "Pale purple", + ), + ] + ), + ), + ( + "size", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bg__full", + "Full backgroundcolor", + ), + ( + "bg__left", + "Only backgroundcolor in the left block", + ), + ] + ), + ), + ] + ), + ), + ( + "text", + main.blocks.rich_text_block.RichtextBlock( + help_text="Add your text", + required=True, + rows=15, + ), + ), + ( + "media", + wagtail.blocks.StreamBlock( + [ + ( + "image", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=False + ), + ), + ( + "video", + wagtail.embeds.blocks.EmbedBlock( + help_text="Youtube url of vimeo url", + required=False, + ), + ), + ], + help_text="Choose an image or paste an embed url", + max_num=1, + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + help_text="Fill in this alt-text only when you want to describe the image (for screenreaders and SEO)", + required=False, + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ( + "section", + wagtail.blocks.StructBlock( + [ + ( + "background", + wagtail.blocks.StructBlock( + [ + ( + "color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("block__bg-white", "White"), + ("block__bg-gray", "Pale gray"), + ( + "block__bg-purple", + "Pale purple", + ), + ] + ), + ), + ( + "size", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bg__full", + "Full backgroundcolor", + ), + ( + "bg__left", + "Only backgroundcolor in the left block", + ), + ] + ), + ), + ] + ), + ), + ( + "grid_layout", + wagtail.blocks.StructBlock( + [ + ( + "grid", + wagtail.blocks.ChoiceBlock( + choices=[ + ("33_66", "33% - 66%"), + ("50_50", "50% - 50%"), + ("66_33", "66% - 33%"), + ] + ), + ) + ], + required=True, + ), + ), + ( + "text_label_national", + wagtail.blocks.CharBlock( + default="Nationaal", required=True + ), + ), + ( + "text_label_intermediate", + wagtail.blocks.CharBlock( + default="Regionaal", required=True + ), + ), + ( + "text_label_local", + wagtail.blocks.CharBlock( + default="Lokaal", required=True + ), + ), + ( + "content", + wagtail.blocks.StreamBlock( + [ + ( + "text", + main.blocks.rich_text_block.RichtextBlock(), + ), + ( + "interactive_input", + wagtail.blocks.StructBlock( + [ + ( + "interactive_input", + wagtail.blocks.ChoiceBlock( + choices=main.blocks.storyline_section.get_interactive_inputs + ), + ), + ( + "display", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "checkbox_radio", + "Show as checkboxe(s) or radiobutton(s)", + ), + ( + "button", + "Show as button(s)", + ), + ], + help_text="Only applies if the interactive input is a Select type", + ), + ), + ( + "visible", + wagtail.blocks.BooleanBlock( + default=True, + required=False, + ), + ), + ( + "locked", + wagtail.blocks.BooleanBlock( + required=False + ), + ), + ( + "default_value", + wagtail.blocks.CharBlock( + help_text="Type the default value exactly as it's shown on the website page", + required=False, + ), + ), + ] + ), + ), + ( + "static_image", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=False + ), + ), + ( + "holarchy_feedback_image", + wagtail.blocks.StructBlock( + [ + ( + "image_selector", + main.blocks.holon_image_chooser.HolonImageChooserBlock(), + ), + ( + "conditions", + wagtail.blocks.StreamBlock( + [ + ( + "interactive_input_condition", + wagtail.blocks.StructBlock( + [ + ( + "parameter", + wagtail.blocks.ChoiceBlock( + choices=main.blocks.feedbackmodals.FeedbackModalInteractiveInputCondition.get_interactive_inputs, + help_text="Please make sure the parameter is present in this section. Otherwise you assert something that doesn't exist", + ), + ), + ( + "operator", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "bigger", + "Bigger", + ), + ( + "biggerequal", + "Bigger or Equal", + ), + ( + "equal", + "Equal", + ), + ( + "notequal", + "Not Equal", + ), + ( + "lower", + "Lower", + ), + ( + "lowerequal", + "Lower or Equal", + ), + ], + help_text="Set the operator of this condition", + max_length=50, + ), + ), + ( + "value", + wagtail.blocks.CharBlock( + help_text="Set the value of this condition to compare to", + max_length=255, + required=True, + ), + ), + ] + ), + ) + ], + block_counts={}, + help_text="Image will only be shown when ALL conditions of a holarchy feedback image are true", + use_json_field=True, + ), + ), + ] + ), + ), + ], + block_counts={"static_image": {"max_num": 1}}, + ), + ), + ] + ), + ), + ( + "heroblock", + wagtail.blocks.StructBlock( + [ + ( + "background_color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("", "Default color"), + ("block__bg-gray", "Pale gray"), + ("block__bg-purple", "Pale purple"), + ], + required=False, + ), + ), + ( + "title", + wagtail.blocks.CharBlock( + form_classname="title", required=True + ), + ), + ( + "text", + main.blocks.rich_text_block.RichtextBlock( + required=True + ), + ), + ( + "media", + wagtail.blocks.StreamBlock( + [ + ( + "image", + main.blocks.holon_image_chooser.HolonImageChooserBlock( + required=False + ), + ), + ( + "video", + wagtail.embeds.blocks.EmbedBlock( + required=False + ), + ), + ], + help_text="Choose an image or paste an embed url", + max_num=1, + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + help_text="Fill in this alt-text only when you want to describe the image (for screenreaders and SEO)", + required=False, + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ( + "title_block", + wagtail.blocks.StructBlock( + [ + ( + "background_color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("", "Default color"), + ("block__bg-gray", "Pale gray"), + ("block__bg-purple", "Pale purple"), + ], + required=False, + ), + ), + ("title", wagtail.blocks.CharBlock(required=True)), + ( + "size", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ("", "Select header size"), + ("h1", "H1"), + ("h2", "H2"), + ], + ), + ), + ( + "text", + main.blocks.rich_text_block.RichtextBlock( + required=False + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ( + "card_block", + wagtail.blocks.StructBlock( + [ + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + required=False + ), + ), + ( + "image_selector", + main.blocks.holon_image_chooser.HolonImageChooserBlock(), + ), + ( + "description", + wagtail.blocks.CharBlock( + max_length=255, required=False + ), + ), + ( + "card_color", + wagtail.blocks.ChoiceBlock( + choices=[ + ("card__bg-gold", "Gold"), + ("card__bg-blue", "Blue"), + ("card__bg-gray", "Gray"), + ( + "card__bg-purple", + "Purple", + ), + ("card__bg-pink", "Pink"), + ( + "card__bg-orange", + "Orange", + ), + ], + required=False, + ), + ), + ( + "item_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the card to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the card should link externally", + required=False, + ), + ), + ], + help_text="Optional: add an internal or external link to the card", + max_num=1, + required=False, + ), + ), + ] + ) + ), + ), + ( + "button_block", + wagtail.blocks.StreamBlock( + [ + ( + "buttons", + wagtail.blocks.StructBlock( + [ + ( + "buttons_align", + wagtail.blocks.ChoiceBlock( + choices=[ + ( + "btn-left", + "left", + ), + ( + "btn-center", + "center", + ), + ( + "btn-right", + "right", + ), + ], + required=False, + ), + ), + ( + "buttons", + wagtail.blocks.StreamBlock( + [ + ( + "button", + wagtail.blocks.StructBlock( + [ + ( + "button_style", + wagtail.blocks.ChoiceBlock( + blank=True, + choices=[ + ( + "dark", + "Default (Dark blue)", + ), + ( + "arrow", + "Dark blue with arrow", + ), + ( + "light", + "light", + ), + ], + required=False, + ), + ), + ( + "button_text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "button_link", + wagtail.blocks.StreamBlock( + [ + ( + "intern", + main.blocks.page_chooser_block.PageChooserBlock( + helptext="Choose if you want the button to link to a page internally", + required=False, + ), + ), + ( + "extern", + wagtail.blocks.URLBlock( + helptext="Fill in if the button should link externally", + required=False, + ), + ), + ], + help_text="Where do you want the button to link to", + max_num=1, + ), + ), + ], + required=True, + ), + ) + ], + help_text="Add a button", + min_num=1, + ), + ), + ], + required=False, + ), + ) + ], + required=False, + ), + ), + ] + ), + ), + ], + use_json_field=True, + ), + ), + ]

+ Transactie met @@ -98,8 +103,8 @@ export default function CostBenefitTable() { - {heading} + + {heading}