Skip to content

Commit

Permalink
feat: linked posts in news articles
Browse files Browse the repository at this point in the history
  • Loading branch information
alexgoff committed Feb 5, 2025
1 parent 76b6891 commit 7bce7f6
Show file tree
Hide file tree
Showing 38 changed files with 961 additions and 541 deletions.
14 changes: 9 additions & 5 deletions app/[locale]/gallery/collections/[gallery]/[asset]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { SupportedCantoAssetScheme } from "@/lib/api/galleries/schema";
import { isMainGallery } from "@/lib/api/galleries";
import { getMediaPolicyPage } from "@/lib/api/galleries/media-policy";
import { buildParentPath } from "@/lib/helpers/gallery";
import { addLocaleUriSegment } from "@/lib/i18n";
import CantoFigure from "@/components/organisms/gallery/CantoFigure";
import SingleMediaAsset from "@/components/templates/SingleMediaAsset";
import ImageSizes from "@/components/organisms/gallery/metadata/Sizes";
Expand All @@ -15,7 +16,7 @@ import CantoImage from "@/components/organisms/gallery/CantoImage";
import CantoVideo from "@/components/organisms/gallery/CantoVideo";
import CantoDocument from "@/components/organisms/gallery/CantoDocument";
import AssetMetadata from "@/components/organisms/gallery/metadata/Asset";
import { addLocaleUriSegment } from "@/lib/i18n";
import LinkedPosts from "@/components/organisms/gallery/metadata/LinkedPosts";

export async function generateMetadata({
params: { locale, gallery, asset: id },
Expand Down Expand Up @@ -121,10 +122,13 @@ const GalleryAsset: FunctionComponent<GalleryAssetProps> = async ({
/>
}
metadataBlocks={
<AssetMetadata
size={parseInt(size)}
{...{ scheme, width, height, dateCreated }}
/>
<>
<AssetMetadata
size={parseInt(size)}
{...{ scheme, width, height, dateCreated }}
/>
<LinkedPosts {...{ id, scheme }} />
</>
}
metadataLinks={links[scheme]}
/>
Expand Down
1 change: 1 addition & 0 deletions components/auth/AuthorizePage/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import PropTypes from "prop-types";
import { Trans, useTranslation } from "react-i18next";
import { useAuthModal } from "@/hooks";
Expand Down
3 changes: 2 additions & 1 deletion components/dynamic/NewsList/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
import { Grid } from "@rubin-epo/epo-react-lib";
import Grid from "@rubin-epo/epo-react-lib/Grid";
import DataList from "@/dynamic/DataList";
import Tile from "@/atomic/Tile";
import {
Expand Down
1 change: 1 addition & 0 deletions components/factories/ContentBlockFactory.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import PropTypes from "prop-types";
import {
Image,
Expand Down
1 change: 1 addition & 0 deletions components/layout/InvestigationHero/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import PropTypes from "prop-types";
import * as Styled from "./styles";
import { Button, Image, IconComposer } from "@rubin-epo/epo-react-lib";
Expand Down
1 change: 1 addition & 0 deletions components/layout/NavButtons/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
Expand Down
Empty file.
1 change: 1 addition & 0 deletions components/layout/StepNavigation/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import { useState, useEffect } from "react";
import PropTypes from "prop-types";
import { ExpandToggle, Container } from "@rubin-epo/epo-react-lib";
Expand Down
53 changes: 53 additions & 0 deletions components/molecules/Aside/Image/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { FC } from "react";
import classNames from "classnames";
import Link, { LinkProps } from "next/link";
import { type ImageShape } from "@rubin-epo/epo-react-lib/Image";
import ResponsiveImage from "@rubin-epo/epo-react-lib/ResponsiveImage";
import Figure from "@rubin-epo/epo-react-lib/Figure";
import styles from "./styles.module.css";

interface AsideImageProps {
link?: LinkProps;
image: ImageShape;
caption?: string;
className?: string;
}

const AsideImage: FC<AsideImageProps> = ({
link,
image,
caption,
className,
}) => {
return (
<Figure
className={classNames(styles.figure, className)}
caption={
caption &&
(link ? (
<Link
prefetch={false}
{...link}
className={styles.captionLink}
dangerouslySetInnerHTML={{ __html: caption }}
/>
) : (
<div
className={styles.caption}
dangerouslySetInnerHTML={{ __html: caption }}
/>
))
}
>
<ResponsiveImage
className={styles.image}
image={image}
aspectRatio="8:5"
/>
</Figure>
);
};

AsideImage.displayName = "Molecule.Aside.Image";

export default AsideImage;
42 changes: 42 additions & 0 deletions components/molecules/Aside/Image/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.figure {
--figure-padding: 0;

position: relative;

&:has(a:focus-visible),
&:has(a:hover) {
& .image {
filter: invert(25%) sepia(80%) saturate(102%) hue-rotate(130deg)
brightness(100%) contrast(100%);
opacity: 0.7;
}
}
}

.image {
background-color: var(--color-background-tile-light);
opacity: 1;
transition: filter 0.2s ease 0s, opacity 0.2s ease 0s;
}

.caption {
display: block;
margin-block-start: var(--size-spacing-2xs);
}

.captionLink {
composes: caption;

color: var(--color-background-accent-aside);
text-decoration: none;

&:focus-visible {
outline: none;
}

&::after {
content: "";
position: absolute;
inset: 0;
}
}
25 changes: 25 additions & 0 deletions components/molecules/Aside/Section/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FC, PropsWithChildren } from "react";
import classNames from "classnames";
import styles from "./styles.module.css";

interface AsideSectionProps {
title?: string;
className?: string;
}

const AsideSection: FC<PropsWithChildren<AsideSectionProps>> = ({
title,
children,
className,
}) => {
return (
<section className={classNames(styles.section, className)}>
{title && <h3 className={styles.title}>{title}</h3>}
{children}
</section>
);
};

AsideSection.displayName = "Page.Aside.Section";

export default AsideSection;
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import styled from "styled-components";
.section {
flex: 1 0 270px;

export const Title = styled.h3`
& > * + * {
margin-block-start: var(--size-spacing-2xs);
}
}

.title {
position: relative;
padding-right: 1em;
padding-bottom: 0.5em;
margin-bottom: 0.5em;
padding-right: var(--size-spacing-s);
padding-bottom: var(--size-spacing-2xs);
border-bottom: 8px solid var(--color-background-accent-aside);

& svg {
Expand All @@ -20,4 +25,4 @@ export const Title = styled.h3`
border-radius: 50%;
fill: var(--white);
}
`;
}
14 changes: 14 additions & 0 deletions components/molecules/Aside/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import PropTypes from "prop-types";
import * as Styled from "./styles";

const Aside = ({ children }) => {
return <Styled.Aside>{children}</Styled.Aside>;
};

Aside.displayName = "Page.Aside";

Aside.propTypes = {
children: PropTypes.node,
};

export default Aside;
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import { fluidScale, token } from "@rubin-epo/epo-react-lib";
"use client";
import { token } from "@rubin-epo/epo-react-lib";
import styled from "styled-components";

export const Aside = styled.aside`
--size-width-aside: 270px;
--size-gap-aside: ${fluidScale("50px", token("PADDING_SMALL"))};
--size-gap-aside: var(--size-spacing-xs);
--color-font-link-aside: var(--turquoise60);
--color-background-accent-aside: var(--turquoise55, #009fa1);
display: flex;
flex-shrink: 0;
flex-basis: 270px;
flex-wrap: wrap;
gap: var(--size-gap-aside);
padding: 0;
margin: 0;
font-size: 0.875rem;
& a {
font-size: 14px;
color: var(--color-background-accent-aside);
text-decoration: none;
& img {
opacity: 1;
transition: filter 0.2s ease 0s, opacity 0.2s ease 0s;
Expand All @@ -38,12 +34,12 @@ export const Aside = styled.aside`
}
@media screen and (min-width: ${token("BREAK_DESKTOP_SMALL")}) {
flex-direction: column;
gap: 0;
padding: var(--PADDING_LARGE) 0 var(--PADDING_LARGE) 10px;
padding: var(--size-spacing-l) 0 var(--size-spacing-l)
var(--size-spacing-xs);
> * + * {
margin-block-start: 1em;
margin-block-start: var(--size-spacing-2xs);
}
}
`;
48 changes: 48 additions & 0 deletions components/organisms/MediaAside/GalleryAsset/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import AsideImage from "@/components/molecules/Aside/Image";
import { cantoToImageShape } from "@/lib/api/canto";
import { assetTitle } from "@/lib/api/canto/metadata";
import { getGalleryForAsset } from "@/lib/api/galleries/asset";
import { addLocaleUriSegment } from "@/lib/i18n";
import { getLocale } from "@/lib/i18n/server";
import { type ImageShape } from "@rubin-epo/epo-react-lib/Image";
import { FC, Suspense } from "react";

interface GalleryAssetProps {
asset: any;
}

interface GalleryAssetContentProps {
id: string;
image: ImageShape;
caption?: string;
}

const GalleryAssetContent: FC<GalleryAssetContentProps> = async ({
id,
image,
caption,
}) => {
const uri = await getGalleryForAsset(id);
const link = uri
? { href: addLocaleUriSegment(getLocale(), `${uri}/${id}`) }
: undefined;

return <AsideImage {...{ image, caption }} link={link} />;
};

const GalleryAsset: FC<GalleryAssetProps> = ({ asset }) => {
const image = cantoToImageShape(asset, 240);
const caption = assetTitle(asset.metadata);

if (!image) return null;

return (
<Suspense fallback={<AsideImage {...{ image, caption }} />}>
<GalleryAssetContent id={asset.id} {...{ image, caption }} />
</Suspense>
);
};

GalleryAsset.displayName = "Organism.MediaAside.GalleryAsset";

export default GalleryAsset;
Loading

0 comments on commit 7bce7f6

Please sign in to comment.