diff --git a/backend/api/cms/page/blocks/communities_section.py b/backend/api/cms/page/blocks/communities_section.py new file mode 100644 index 0000000000..5849b8b95c --- /dev/null +++ b/backend/api/cms/page/blocks/communities_section.py @@ -0,0 +1,62 @@ +from typing import Self +import strawberry +from api.cms.page.registry import register_page_block + + +@strawberry.type +class Community: + name: str + description: str + logo: str | None + banner_photo: str | None + banner_background_color: str | None + + mastodon_url: str | None + facebook_url: str | None + instagram_url: str | None + linkedin_url: str | None + twitter_url: str | None + + @classmethod + def from_block(cls, block) -> Self: + logo_url = None + if block["logo"]: + logo_url = block["logo"].get_rendition("width-300|jpegquality-60").full_url + + banner_photo_url = None + if block["banner_photo"]: + banner_photo_url = ( + block["banner_photo"].get_rendition("width-300|jpegquality-60").full_url + ) + + return cls( + name=block["name"], + description=block["description"], + logo=logo_url, + banner_photo=banner_photo_url, + banner_background_color=block["banner_background_color"], + mastodon_url=block["mastodon_url"], + facebook_url=block["facebook_url"], + instagram_url=block["instagram_url"], + linkedin_url=block["linkedin_url"], + twitter_url=block["twitter_url"], + ) + + +@register_page_block() +@strawberry.type +class CommunitiesSection: + id: strawberry.ID + title: str + communities: list[Community] + + @classmethod + def from_block(cls, block) -> Self: + return cls( + id=block.id, + title=block.value["title"], + communities=[ + Community.from_block(community) + for community in block.value["communities"] + ], + ) diff --git a/backend/api/cms/page/blocks/dynamic_content_display_section.py b/backend/api/cms/page/blocks/dynamic_content_display_section.py index 072803a2a9..e989149164 100644 --- a/backend/api/cms/page/blocks/dynamic_content_display_section.py +++ b/backend/api/cms/page/blocks/dynamic_content_display_section.py @@ -9,6 +9,7 @@ class DynamicContentDisplaySectionSource(enum.Enum): speakers = "speakers" keynoters = "keynoters" proposals = "proposals" + local_communities = "local_communities" @register_page_block() diff --git a/backend/cms/components/page/blocks/communities_section.py b/backend/cms/components/page/blocks/communities_section.py new file mode 100644 index 0000000000..0aa62c22ca --- /dev/null +++ b/backend/cms/components/page/blocks/communities_section.py @@ -0,0 +1,25 @@ +from wagtail.images.blocks import ImageChooserBlock +from wagtail import blocks + + +class Community(blocks.StructBlock): + name = blocks.CharBlock(required=True) + description = blocks.RichTextBlock(required=True) + logo = ImageChooserBlock(required=True) + banner_photo = ImageChooserBlock(required=False) + banner_background_color = blocks.CharBlock(required=False) + + mastodon_url = blocks.URLBlock(required=False) + facebook_url = blocks.URLBlock(required=False) + instagram_url = blocks.URLBlock(required=False) + linkedin_url = blocks.URLBlock(required=False) + twitter_url = blocks.URLBlock(required=False) + + +class CommunitiesSection(blocks.StructBlock): + title = blocks.CharBlock(required=True) + communities = blocks.ListBlock(Community) + + class Meta: + label = "Communities Section" + icon = "crosshairs" diff --git a/backend/cms/components/page/blocks/dynamic_content_display_section.py b/backend/cms/components/page/blocks/dynamic_content_display_section.py index fc87d47799..27a9945aeb 100644 --- a/backend/cms/components/page/blocks/dynamic_content_display_section.py +++ b/backend/cms/components/page/blocks/dynamic_content_display_section.py @@ -7,5 +7,6 @@ class DynamicContentDisplaySection(blocks.StructBlock): ("speakers", "Speakers"), ("keynoters", "Keynoters"), ("proposals", "Proposals"), + ("local_communities", "Local Communities"), ], ) diff --git a/backend/cms/components/page/models.py b/backend/cms/components/page/models.py index b3bf3e9a2f..8316bf3d38 100644 --- a/backend/cms/components/page/models.py +++ b/backend/cms/components/page/models.py @@ -1,3 +1,4 @@ +from cms.components.page.blocks.communities_section import CommunitiesSection from cms.components.page.blocks.dynamic_content_display_section import ( DynamicContentDisplaySection, ) @@ -41,6 +42,7 @@ class BodyBlock(blocks.StreamBlock): live_streaming_section = LiveStreamingSection() homepage_hero = HomepageHero() dynamic_content_display_section = DynamicContentDisplaySection() + communities_section = CommunitiesSection() class GenericPage(CustomHeadlessMixin, Page): diff --git a/frontend/src/components/blocks-renderer/index.tsx b/frontend/src/components/blocks-renderer/index.tsx index f3a3d6ddf5..721d6a6e0d 100644 --- a/frontend/src/components/blocks-renderer/index.tsx +++ b/frontend/src/components/blocks-renderer/index.tsx @@ -5,6 +5,7 @@ import { TextSection } from "~/components/blocks/text-section"; import type { Block } from "~/types"; import { CheckoutSection } from "../blocks/checkout-section"; +import { CommunitiesSection } from "../blocks/communities-section"; import { DynamicContentDisplaySection } from "../blocks/dynamic-content-display-section"; import { HomeIntroSection } from "../blocks/home-intro-section"; import { HomepageHero } from "../blocks/homepage-hero"; @@ -38,6 +39,7 @@ const REGISTRY: Registry = { LiveStreamingSection, HomepageHero, DynamicContentDisplaySection, + CommunitiesSection, }; type Props = { diff --git a/frontend/src/components/blocks/communities-section.tsx b/frontend/src/components/blocks/communities-section.tsx new file mode 100644 index 0000000000..92dc7e9623 --- /dev/null +++ b/frontend/src/components/blocks/communities-section.tsx @@ -0,0 +1,86 @@ +import { + CardPart, + Grid, + Heading, + MultiplePartsCard, + MultiplePartsCardCollection, + SocialLinks, + Spacer, + StyledHTMLText, + Text, + VerticalStack, +} from "@python-italia/pycon-styleguide"; +import { Section } from "@python-italia/pycon-styleguide"; +import type { Community } from "~/types"; + +type Props = { + title: string; + communities: Community[]; +}; + +export const CommunitiesSection = ({ title, communities }: Props) => { + return ( +
+ + {communities.map((community) => { + const socialLinks = []; + if (community.mastodonUrl) { + socialLinks.push({ + icon: "mastodon", + link: community.mastodonUrl, + }); + } + if (community.facebookUrl) { + socialLinks.push({ + icon: "facebook", + link: community.facebookUrl, + }); + } + if (community.instagramUrl) { + socialLinks.push({ + icon: "instagram", + link: community.instagramUrl, + }); + } + if (community.linkedinUrl) { + socialLinks.push({ + icon: "linkedin", + link: community.linkedinUrl, + }); + } + if (community.twitterUrl) { + socialLinks.push({ + icon: "twitter", + link: community.twitterUrl, + }); + } + + return ( + + + {community.name} + + + {community.logo && ( + <> + + {community.name} + + + + )} + + + + + + + + + + ); + })} + +
+ ); +}; diff --git a/frontend/src/components/blocks/dynamic-content-display-section/index.tsx b/frontend/src/components/blocks/dynamic-content-display-section/index.tsx index 37f9bb3fa1..4187bf5ac4 100644 --- a/frontend/src/components/blocks/dynamic-content-display-section/index.tsx +++ b/frontend/src/components/blocks/dynamic-content-display-section/index.tsx @@ -5,6 +5,7 @@ import { queryKeynotesSection, } from "~/types"; import { KeynotersContent } from "./keynoters-content"; +import { LocalCommunitiesContent } from "./local-communities-content"; import { ProposalsContent } from "./proposals-content"; import { SpeakersContent } from "./speakers-content"; @@ -24,6 +25,9 @@ export const DynamicContentDisplaySection = ({ {source === DynamicContentDisplaySectionSource.Proposals && ( )} + {source === DynamicContentDisplaySectionSource.LocalCommunities && ( + + )} ); }; @@ -56,6 +60,9 @@ DynamicContentDisplaySection.dataFetching = (client, language, block) => { }), ]; } + case DynamicContentDisplaySectionSource.LocalCommunities: { + return []; + } } return []; diff --git a/frontend/src/components/blocks/dynamic-content-display-section/local-communities-content.tsx b/frontend/src/components/blocks/dynamic-content-display-section/local-communities-content.tsx new file mode 100644 index 0000000000..339974e619 --- /dev/null +++ b/frontend/src/components/blocks/dynamic-content-display-section/local-communities-content.tsx @@ -0,0 +1,85 @@ +import { + CardPart, + Grid, + Heading, + MultiplePartsCard, + MultiplePartsCardCollection, + SocialLinks, + Spacer, + Text, + VerticalStack, +} from "@python-italia/pycon-styleguide"; +import { Section } from "@python-italia/pycon-styleguide"; + +export const LocalCommunitiesContent = () => { + return ( +
+ + {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((item) => ( + + + test + + + + Python Bari + + + + Python Bari + + + + Python Bari è una community di Python che si occupa di + sviluppare software per la città di Bari. + + + + + + + + + ))} + +
+ ); +}; diff --git a/frontend/src/pages/schedule/fragments/blocks.graphql b/frontend/src/pages/schedule/fragments/blocks.graphql index d96579185f..54ba628288 100644 --- a/frontend/src/pages/schedule/fragments/blocks.graphql +++ b/frontend/src/pages/schedule/fragments/blocks.graphql @@ -135,6 +135,23 @@ fragment Blocks on Block { id source } + + ... on CommunitiesSection { + id + title + communities { + name + description + logo + bannerPhoto + bannerBackgroundColor + mastodonUrl + facebookUrl + instagramUrl + linkedinUrl + twitterUrl + } + } } fragment CTAInfo on CTA { diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 4dcdb1cd32..0e481c04b3 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -13,7 +13,7 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "baseUrl": ".", "paths": { "~/*": ["./src/*"],