-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement basic share images #30
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,8 @@ | |
"repl": "yarn run-script scripts/repl/repl.ts", | ||
"hello": "yarn run-script scripts/hello/index.ts", | ||
"generate-data-snapshot": "yarn run-script scripts/data/generate-snapshot.ts", | ||
"create-share-page": "plop share-page" | ||
"create-share-page": "plop share-page", | ||
"create-component": "plop component" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will we port this plop to the template? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, actually I didn't really use it, but I will test & port! |
||
}, | ||
"lint-staged": { | ||
"*.{ts,tsx}": "eslint --max-warnings=0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ import { | |
|
||
import { RegionSearch } from "@actnowcoalition/actnow.js"; | ||
|
||
import { regions } from "src/utils/regions"; | ||
import { regions } from "../../utils/regions"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm actually okay with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, cool. When I tried to do |
||
|
||
interface AppBarItem { | ||
href: string; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Box } from "@mui/material"; | ||
|
||
import { styled } from "../../styles"; | ||
|
||
export const ratio = 16 / 9; | ||
export const width = 900; | ||
export const height = width / ratio; | ||
|
||
export const ShareImageContainer = styled(Box)` | ||
padding: ${({ theme }) => theme.spacing(4, 5)}; | ||
width: ${width}px; | ||
height: ${height}px; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import React from "react"; | ||
|
||
import { ComponentMeta, ComponentStory } from "@storybook/react"; | ||
|
||
import { ShareImageHomepage } from "."; | ||
|
||
export default { | ||
title: "Components/ShareImageHomepage", | ||
component: ShareImageHomepage, | ||
} as ComponentMeta<typeof ShareImageHomepage>; | ||
|
||
const Template: ComponentStory<typeof ShareImageHomepage> = () => ( | ||
<ShareImageHomepage /> | ||
); | ||
|
||
export const Home = Template.bind({}); | ||
Home.args = {}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from "react"; | ||
|
||
import { Box, Stack, Typography } from "@mui/material"; | ||
|
||
import { MetricWorldMap } from "@actnowcoalition/actnow.js"; | ||
|
||
import { MetricId } from "../../utils/metrics"; | ||
import { regions } from "../../utils/regions"; | ||
import { ShareImageContainer } from "./ShareImage.styles"; | ||
|
||
export const ShareImageHomepage = () => ( | ||
<ShareImageContainer sx={{ background: "linear-gradient(#00bfa5, #0091ea)" }}> | ||
<Stack spacing={2} alignItems="center"> | ||
<Typography variant="h1" sx={{ mt: 0 }} color="white"> | ||
World Happiness Report 2022 | ||
</Typography> | ||
<Box | ||
sx={{ | ||
width: 700, | ||
backgroundColor: (theme) => theme.palette.common.white, | ||
borderRadius: 2, | ||
}} | ||
> | ||
<MetricWorldMap regionDB={regions} metric={MetricId.HAPPINESS} /> | ||
</Box> | ||
<Typography variant="labelLarge" color="white"> | ||
By Act Now Coalition | ||
</Typography> | ||
</Stack> | ||
</ShareImageContainer> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from "react"; | ||
|
||
import { ComponentMeta, ComponentStory } from "@storybook/react"; | ||
|
||
import { ShareImageLocation } from "."; | ||
import { regions } from "../../utils/regions"; | ||
|
||
export default { | ||
title: "Components/ShareImageLocation", | ||
component: ShareImageLocation, | ||
} as ComponentMeta<typeof ShareImageLocation>; | ||
|
||
const Template: ComponentStory<typeof ShareImageLocation> = () => ( | ||
<ShareImageLocation region={regions.findByRegionIdStrict("NOR")} /> | ||
); | ||
|
||
export const Home = Template.bind({}); | ||
Home.args = {}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from "react"; | ||
|
||
import { Box, Stack, Typography } from "@mui/material"; | ||
|
||
import { MetricWorldMap, Region } from "@actnowcoalition/actnow.js"; | ||
|
||
import { MetricId } from "../../utils/metrics"; | ||
import { regions } from "../../utils/regions"; | ||
import { ShareImageContainer } from "./ShareImage.styles"; | ||
|
||
export const ShareImageLocation = ({ region }: { region: Region }) => ( | ||
<ShareImageContainer sx={{ background: "linear-gradient(#00bfa5, #0091ea)" }}> | ||
<Stack spacing={2} alignItems="center"> | ||
<Typography variant="h1" sx={{ mt: 0 }} color="white"> | ||
{`Happiness in ${region.shortName}`} | ||
</Typography> | ||
<Box | ||
sx={{ | ||
width: 700, | ||
backgroundColor: (theme) => theme.palette.common.white, | ||
borderRadius: 2, | ||
}} | ||
> | ||
<MetricWorldMap regionDB={regions} metric={MetricId.HAPPINESS} /> | ||
</Box> | ||
<Typography variant="labelLarge" color="white"> | ||
By Act Now Coalition | ||
</Typography> | ||
</Stack> | ||
</ShareImageContainer> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "./ShareImageHomepage"; | ||
export * from "./ShareImageLocation"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { useRef, useState } from "react"; | ||
|
||
import { Box } from "@mui/material"; | ||
import { NextPage } from "next"; | ||
|
||
import { useMutationObserver } from "@actnowcoalition/actnow.js"; | ||
|
||
import { ScreenshotWrapper } from "components/Containers"; | ||
import { ShareImageHomepage } from "components/ShareImages"; | ||
import { searchDomForClass } from "src/utils/share-pages"; | ||
|
||
// http://localhost:3000/internal/share-image/homepage | ||
const HomeSharePage: NextPage = () => { | ||
const ref = useRef<Element>(null); | ||
|
||
const [isLoaded, setIsLoaded] = useState<boolean>(false); | ||
const handleMutations: MutationCallback = (mutations: MutationRecord[]) => { | ||
for (const mutation of mutations) { | ||
if (mutation.type === "childList") { | ||
searchDomForClass(mutation.target as Element, setIsLoaded); | ||
} | ||
} | ||
}; | ||
useMutationObserver(ref, handleMutations, { childList: true, subtree: true }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW- Repeating all of this in every share page seems non-ideal. I'm also not entirely understanding how it works (it seems like we are waiting for "act-now-component-loaded" class and then adding a different "screenshot-ready" class; why not just have the screenshot capture use the "act-now-component-loaded" class directly? I may be missing something...) I'll throw a topic on the standup discussion to discuss with Sean on Monday. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, maybe we can create a hook that handles all that in one go There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this got really messy and is overcomplicated for most use cases. The problem that the mutation observer is trying to solve is the situation where you have a share page with two components that use the "act-now-component-loaded" class upon load. If one component typically loads more slowly than the other (e.g. a Using the mutation observer to wait until the "slow to load" component is ready sort-of resolves this (it's not a guarantee that the map will always load more slowly), but it is clunky. I think it's worth exploring ways to clean it up There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not 100% sure if this would work, but maybe we could have components add a act-now-component-loading class while they're loading and a act-now-component-loaded class when they're done loading. And then the screenshot capturer could look for at least one act-now-component-loaded and no act-now-component-loading elements or something. Anyway, thanks for the details! We can discuss more at standup. |
||
|
||
return ( | ||
<ScreenshotWrapper className="screenshot"> | ||
<Box ref={ref} className={isLoaded ? "screenshot-ready" : undefined}> | ||
<ShareImageHomepage /> | ||
</Box> | ||
</ScreenshotWrapper> | ||
); | ||
}; | ||
export default HomeSharePage; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { useRef, useState } from "react"; | ||
|
||
import { Box } from "@mui/material"; | ||
import isEmpty from "lodash/isEmpty"; | ||
import { NextPage } from "next"; | ||
import { useRouter } from "next/router"; | ||
|
||
import { | ||
Region, | ||
assert, | ||
useMutationObserver, | ||
} from "@actnowcoalition/actnow.js"; | ||
|
||
import { regions } from "../../../utils/regions"; | ||
import { ScreenshotWrapper } from "components/Containers"; | ||
import { ShareImageLocation } from "components/ShareImages"; | ||
import { searchDomForClass } from "src/utils/share-pages"; | ||
|
||
// http://localhost:3000/internal/share-image/location?regionId=CAN | ||
const LocationSharePage: NextPage = () => { | ||
const router = useRouter(); | ||
const ref = useRef<Element>(null); | ||
|
||
const [isLoaded, setIsLoaded] = useState<boolean>(false); | ||
const handleMutations: MutationCallback = (mutations: MutationRecord[]) => { | ||
for (const mutation of mutations) { | ||
if (mutation.type === "childList") { | ||
searchDomForClass(mutation.target as Element, setIsLoaded); | ||
} | ||
} | ||
}; | ||
useMutationObserver(ref, handleMutations, { childList: true, subtree: true }); | ||
|
||
if (isEmpty(router.query)) { | ||
return ( | ||
<span> | ||
Page loading or no query params were provided. Expects params: regionId | ||
</span> | ||
); | ||
} | ||
|
||
const { regionId } = router.query; | ||
const region = regions.findByRegionIdStrict(regionId as string); | ||
assert(region instanceof Region, `Region with ID ${regionId} not found`); | ||
|
||
return ( | ||
<ScreenshotWrapper className="screenshot"> | ||
<Box ref={ref} className={isLoaded ? "screenshot-ready" : undefined}> | ||
<ShareImageLocation region={region} /> | ||
</Box> | ||
</ScreenshotWrapper> | ||
); | ||
}; | ||
export default LocationSharePage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need the
MetricCatalogProvider
to make metrics available to components in Storybook (will port this to the template)