Skip to content

Commit

Permalink
Merge branch 'content-api-homepage-stories' into top-stories-content-api
Browse files Browse the repository at this point in the history
  • Loading branch information
davidpmccormick committed Nov 12, 2024
2 parents 6ec51f0 + 480a818 commit 9573684
Show file tree
Hide file tree
Showing 30 changed files with 927 additions and 937 deletions.
2 changes: 1 addition & 1 deletion .buildkite/urls/expected_200_urls.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/search/stories?query=human
/search/images?query=human
/search/works?query=human
/concepts/n4fvtc49
/concepts/cza334ke
# A works search page where some results contain thumbnails
# https://wellcome.slack.com/archives/C8X9YKM5X/p1657191146272169
/search/works?subjects.label=Liliaceae
Expand Down
6 changes: 0 additions & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ updates:
update-types: ['version-update:semver-patch'] # Ignore all patch updates for version updates only
# We are looking at updating Chromatic, so don't tell us about it. Remove this once we've upgraded.
- dependency-name: 'chromatic*'
# Bigger piece, has a ticket to upgrade. Remove this once it's done.
- dependency-name: 'next'
- dependency-name: '@next*'
# Needs to be done carefully, has its own ticket. Remove this once it's done.
- dependency-name: 'slice-machine-ui'
- dependency-name: '@slicemachine'
# Needs more work, has its own ticket. Remove this once it's done.
- dependency-name: 'eslint*'
# Needs untangling, has its own ticket. Remove this once it's done.
Expand Down
2 changes: 1 addition & 1 deletion cardigan/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@storybook/theming": "^8.3.5",
"chromatic": "^6.21.1",
"husky": "^4.3.0",
"next": "13.5.7",
"next": "14.2.10",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "^5.6.2",
Expand Down
2 changes: 1 addition & 1 deletion common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"jest-environment-jsdom": "^29.5.0",
"koa-compose": "^4.1.0",
"lodash.debounce": "^4.0.8",
"next": "13.2.3",
"next": "14.2.10",
"nprogress": "^0.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
13 changes: 11 additions & 2 deletions common/views/components/UserProvider/UserProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ import {
export type State = 'initial' | 'loading' | 'signedin' | 'signedout' | 'failed';

type Props = {
user: UserInfo | undefined;
user?: UserInfo;
userIsStaffWithRestricted: boolean;
state: State;
reload: (abortSignal?: AbortSignal) => Promise<void>;
};

const defaultUserContext: Props = {
user: undefined,
userIsStaffWithRestricted: false,
state: 'initial',
reload: async () => undefined,
};
Expand All @@ -36,6 +38,8 @@ export function useUser(): Props {

const UserProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
const [user, setUser] = useState<UserInfo>();
const [userIsStaffWithRestricted, setUserIsStaffWithRestricted] =
useState(false);
const [state, setState] = useState<State>('initial');

const fetchUser = async (abortSignal?: AbortSignal, refetch = false) => {
Expand All @@ -59,7 +63,11 @@ const UserProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
// There is a race condition here where the cancel can happen
// after the fetch has finished but before the response has been deserialised
if (!abortSignal?.aborted) {
setUser(auth0UserProfileToUserInfo(data));
const userData = auth0UserProfileToUserInfo(data);
setUser(userData);
setUserIsStaffWithRestricted(
userData?.role === 'StaffWithRestricted'
);
setState('signedin');
}
} else {
Expand Down Expand Up @@ -92,6 +100,7 @@ const UserProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
<UserContext.Provider
value={{
user,
userIsStaffWithRestricted,
state,
reload: (abortSignal?: AbortSignal) => fetchUser(abortSignal, true),
}}
Expand Down
10 changes: 9 additions & 1 deletion content/webapp/components/CardGrid/CardGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ import ExhibitionGuidePromo from '@weco/content/components/ExhibitionGuidePromo/
import ExhibitionPromo from '@weco/content/components/ExhibitionPromo/ExhibitionPromo';
import MoreLink from '@weco/content/components/MoreLink/MoreLink';
import StoryPromo from '@weco/content/components/StoryPromo/StoryPromo';
import StoryPromoContentApi from '@weco/content/components/StoryPromo/StoryPromoContentApi';
import { Article } from '@weco/content/services/wellcome/content/types/api';
import { convertItemToCardProps } from '@weco/content/types/card';
import { Link } from '@weco/content/types/link';
import { MultiContent } from '@weco/content/types/multi-content';

import DailyTourPromo from './DailyTourPromo';

type Props = {
items: readonly MultiContent[];
items: readonly MultiContent[] | Article[];
hidePromoText?: boolean;
itemsPerRow: number;
itemsHaveTransparentBackground?: boolean;
Expand Down Expand Up @@ -65,6 +67,12 @@ const CardGrid: FunctionComponent<Props> = ({
{item.id !== 'tours' && item.type === 'events' && (
<EventPromo event={item} position={i} fromDate={fromDate} />
)}
{item.type === 'Article' && (
<StoryPromoContentApi
article={item}
hidePromoText={hidePromoText}
/>
)}
{item.type === 'articles' && (
<StoryPromo article={item} hidePromoText={hidePromoText} />
)}
Expand Down
5 changes: 2 additions & 3 deletions content/webapp/components/IIIFViewer/IIIFCanvasThumbnail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ const IIIFCanvasThumbnail: FunctionComponent<IIIFCanvasThumbnailProps> = ({
highlightImage,
}: IIIFCanvasThumbnailProps) => {
const [thumbnailLoaded, setThumbnailLoaded] = useState(false);
const { user } = useUser();
const role = user?.role;
const { userIsStaffWithRestricted } = useUser();
const isRestricted = canvas.hasRestrictedImage;
const urlTemplate = canvas.imageServiceId
? iiifImageTemplate(canvas.imageServiceId)
Expand All @@ -90,7 +89,7 @@ const IIIFCanvasThumbnail: FunctionComponent<IIIFCanvasThumbnailProps> = ({
{!thumbnailLoaded && !isRestricted && (
<LL $small={true} $lighten={true} />
)}
{isRestricted && role !== 'StaffWithRestricted' ? (
{isRestricted && !userIsStaffWithRestricted ? (
<>
<Padlock />
<span className="visually-hidden">
Expand Down
5 changes: 2 additions & 3 deletions content/webapp/components/IIIFViewer/MainViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ const ItemRenderer = memo(({ style, index, data }: ItemRendererProps) => {
const { scrollVelocity, canvases, externalAccessService } = data;
const [mainLoaded, setMainLoaded] = useState(false);
const currentCanvas = canvases[index];
const { user } = useUser();
const role = user?.role;
const { userIsStaffWithRestricted } = useUser();
const urlTemplateMain = currentCanvas.imageServiceId
? iiifImageTemplate(currentCanvas.imageServiceId)
: undefined;
Expand Down Expand Up @@ -276,7 +275,7 @@ const ItemRenderer = memo(({ style, index, data }: ItemRendererProps) => {
<div style={{ display: 'flex', justifyContent: 'center' }}>
<LL $lighten={true} />
</div>
) : isRestricted && role !== 'StaffWithRestricted' ? (
) : isRestricted && !userIsStaffWithRestricted ? (
// We always want to show the restricted message to users without a role of 'StaffWithRestricted'
// If the user has the correct role then officially we should check the probe service repsonse before trying to load the image.
// https://iiif.io/api/auth/2.0/#probe-service
Expand Down
4 changes: 2 additions & 2 deletions content/webapp/components/IIIFViewer/ViewerSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ const ViewerSidebar: FunctionComponent<ViewerSidebarProps> = ({
const { authV2 } = useToggles();
const { work, transformedManifest, parentManifest } =
useContext(ItemViewerContext);
const { user } = useUser();
const { userIsStaffWithRestricted } = useUser();

const matchingManifest =
parentManifest &&
Expand Down Expand Up @@ -194,7 +194,7 @@ const ViewerSidebar: FunctionComponent<ViewerSidebarProps> = ({

const isWorkVisibleWithPermission =
digitalLocationInfo?.accessCondition === 'restricted' &&
user?.role === 'StaffWithRestricted';
userIsStaffWithRestricted;

const authServices = getAuthServices({ auth, authV2 });

Expand Down
90 changes: 90 additions & 0 deletions content/webapp/components/StoryPromo/StoryPromoContentApi.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { FunctionComponent } from 'react';
import styled from 'styled-components';

import linkResolver from '@weco/common/services/prismic/link-resolver';
import { transformImage } from '@weco/common/services/prismic/transformers/images';
import { font } from '@weco/common/utils/classnames';
import { isNotUndefined } from '@weco/common/utils/type-guards';
import PrismicImage from '@weco/common/views/components/PrismicImage/PrismicImage';
import {
CardBody,
CardImageWrapper,
CardLabels,
CardOuter,
CardPostBody,
CardTitle,
} from '@weco/content/components/Card/Card';
import { Article } from '@weco/content/services/wellcome/content/types/api';

const Caption = styled.p.attrs({
className: font('intr', 5),
})`
display: inline-block;
margin: 0;
`;

const PartOf = styled.div.attrs({
className: font('intb', 6),
})`
margin: 0;
`;

type Props = {
article: Article;
hidePromoText?: boolean;
sizesQueries?: string;
};

const StoryPromoContentApi: FunctionComponent<Props> = ({
article,
hidePromoText = false,
}) => {
const { title, caption, seriesTitle, format, uid } = article;
const rawImage = article.image?.['16:9'] || article.image;
const image = transformImage(rawImage);
const url = linkResolver({ uid, type: 'articles' });

const labels = format?.label ? [{ text: format.label }] : [];

return (
<CardOuter href={url}>
<CardImageWrapper>
{isNotUndefined(image) && (
<PrismicImage
// We intentionally omit the alt text on promos, so screen reader
// users don't have to listen to the alt text before hearing the
// title of the item in the list.
//
// See https://github.com/wellcomecollection/wellcomecollection.org/issues/6007
image={{ ...image, alt: '' }}
sizes={{
xlarge: 1 / 3,
large: 1 / 3,
medium: 1 / 2,
small: 1,
}}
quality="low"
/>
)}

{labels.length > 0 && <CardLabels labels={labels} />}
</CardImageWrapper>

<CardBody>
<div>
<CardTitle>{title}</CardTitle>
{!hidePromoText && caption && <Caption>{caption}</Caption>}
</div>
</CardBody>
{seriesTitle && (
<CardPostBody>
<PartOf>
<span className={font('intr', 6)}>Part of</span> {seriesTitle}
</PartOf>
</CardPostBody>
)}
</CardOuter>
);
};

export default StoryPromoContentApi;
4 changes: 3 additions & 1 deletion content/webapp/components/Tags/Tags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ type PartWithSeparatorProps = {
$isLast: boolean;
};

const nbsp = '\\00a0';

const PartWithSeparator = styled.span.attrs({
className: font('intr', 5),
})<PartWithSeparatorProps>`
&::after {
display: ${props => (props.$isLast ? 'none' : 'inline')};
/* non-breaking space (\u00A0) keeps characters that would otherwise break (e.g. hyphens) stuck to the preceding text */
content: '\u00A0${props => props.$separator}\u00A0';
content: '${nbsp}${props => props.$separator}${nbsp}';
}
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ const ItemPageLink = ({
digitalLocationInfo,
authServices,
}) => {
const { user } = useUser();
const { userIsStaffWithRestricted } = useUser();

const isDownloadable =
digitalLocationInfo?.accessCondition !== 'open-with-advisory' &&
downloadOptions.length > 0;

const isWorkVisibleWithPermission =
digitalLocationInfo?.accessCondition === 'restricted' &&
user?.role === 'StaffWithRestricted';
userIsStaffWithRestricted;

const manifestNeedsRegeneration =
authServices?.external?.id ===
Expand Down Expand Up @@ -271,8 +271,8 @@ const WorkDetailsAvailableOnline = ({
locationOfWork,
transformedManifest,
}: Props) => {
const { user } = useUser();
const role = user?.role;
const { userIsStaffWithRestricted } = useUser();

const { authV2 } = useToggles();
const {
collectionManifestsCount,
Expand All @@ -287,7 +287,7 @@ const WorkDetailsAvailableOnline = ({
const [origin, setOrigin] = useState<string | undefined>();

const tokenService = getIframeTokenSrc({
role,
userIsStaffWithRestricted,
workId: work.id,
origin,
auth,
Expand Down
4 changes: 2 additions & 2 deletions content/webapp/components/WorkDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const WorkDetails: FunctionComponent<Props> = ({
digitalLocationInfo,
transformedManifest,
}: Props) => {
const { user } = useUser();
const { userIsStaffWithRestricted } = useUser();
const isArchive = useContext(IsArchiveContext);
const transformedIIIFImage = useTransformedIIIFImage(toWorkBasic(work));
const { canvases, rendering, bornDigitalStatus } = {
Expand Down Expand Up @@ -158,7 +158,7 @@ const WorkDetails: FunctionComponent<Props> = ({

const treatAsRestricted =
digitalLocationInfo?.accessCondition === 'restricted' &&
user?.role !== 'StaffWithRestricted';
!userIsStaffWithRestricted;

const showAvailableOnlineSection =
((digitalLocation && shouldShowItemLink) ||
Expand Down
2 changes: 1 addition & 1 deletion content/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"koa-router": "^7.4.0",
"lodash.flattendeep": "^4.4.0",
"lodash.throttle": "^4.1.1",
"next": "13.2.3",
"next": "14.2.10",
"next-router-mock": "^0.9.3",
"openseadragon": "^4.0.0",
"react": "^18.3.1",
Expand Down
16 changes: 6 additions & 10 deletions content/webapp/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,11 @@ import { fetchPage } from '@weco/content/services/prismic/fetch/pages';
import { transformContentListSlice } from '@weco/content/services/prismic/transformers/body';
import { transformEventBasic } from '@weco/content/services/prismic/transformers/events';
import { transformExhibitionsQuery } from '@weco/content/services/prismic/transformers/exhibitions';
import { articleLd } from '@weco/content/services/prismic/transformers/json-ld';
import { articleLdContentApi } from '@weco/content/services/prismic/transformers/json-ld';
import { transformPage } from '@weco/content/services/prismic/transformers/pages';
import { transformQuery } from '@weco/content/services/prismic/transformers/paginated-results';
import { getArticles } from '@weco/content/services/wellcome/content/articles';
import { transformArticle } from '@weco/content/services/wellcome/transformers/articles';
import { transformPaginatedResults } from '@weco/content/services/wellcome/transformers/paginated-results';
import { ArticleBasic } from '@weco/content/types/articles';
import { Article } from '@weco/content/services/wellcome/content/types/api';
import {
ContentListProps,
isContentList,
Expand All @@ -71,7 +69,7 @@ type Props = {
pageId: string;
exhibitions: ExhibitionBasic[];
nextSevenDaysEvents: EventBasic[];
articles: ArticleBasic[];
articles: Article[];
jsonLd: JsonLdObj[];
untransformedStandfirst?: RawStandfirstSlice;
transformedHeaderList: Slice<'contentList', ContentListProps> | null;
Expand Down Expand Up @@ -120,12 +118,10 @@ export const getServerSideProps: GetServerSideProps<
// The homepage should always exist in Prismic.
const page = transformPage(pageDocument as RawPagesDocument);

const articles = transformPaginatedResults(
articlesResponse,
transformArticle
).results;
const articles =
articlesResponse.type === 'ResultList' ? articlesResponse.results : [];

const jsonLd = articles.map(articleLd);
const jsonLd = articles.map(articleLdContentApi);

const events = transformQuery(eventsQuery, transformEventBasic).results;
const nextSevenDaysEvents = orderEventsByNextAvailableDate(
Expand Down
Loading

0 comments on commit 9573684

Please sign in to comment.