Skip to content

Commit

Permalink
wip: add link to author page in article header
Browse files Browse the repository at this point in the history
  • Loading branch information
mlbrgl committed May 21, 2024
1 parent eb2966e commit ed5675d
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 31 deletions.
54 changes: 52 additions & 2 deletions db/model/Gdoc/GdocBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,19 @@ import {
getVariableOfDatapageIfApplicable,
} from "../Variable.js"
import { createLinkFromUrl } from "../Link.js"
import { OwidGdoc, OwidGdocContent, OwidGdocType } from "@ourworldindata/types"
import {
OwidGdoc,
OwidGdocContent,
OwidGdocType,
DbRawAuthor,
DbEnrichedAuthor,
} from "@ourworldindata/types"
import { KnexReadonlyTransaction } from "../../db"

export class GdocBase implements OwidGdocBaseInterface {
id!: string
slug: string = ""
authors: DbEnrichedAuthor[] = []
content!: OwidGdocContent
published: boolean = false
createdAt: Date = new Date()
Expand Down Expand Up @@ -178,6 +185,10 @@ export class GdocBase implements OwidGdocBaseInterface {
return [...details]
}

async loadAuthors(knex: db.KnexReadonlyTransaction): Promise<void> {
this.authors = await getMinimalAuthorByNames(knex, this.content.authors)
}

get links(): DbInsertPostGdocLink[] {
const links: DbInsertPostGdocLink[] = []

Expand Down Expand Up @@ -643,8 +654,17 @@ export class GdocBase implements OwidGdocBaseInterface {
}

async loadLinkedDocuments(knex: db.KnexReadonlyTransaction): Promise<void> {
if (!this.authors.length) await this.loadAuthors(knex)

const authorIds = excludeNullish(
this.authors.map((author) => author.id)
)

const linkedDocuments: OwidGdocMinimalPostInterface[] =
await getMinimalGdocPostsByIds(knex, this.linkedDocumentIds)
await getMinimalGdocPostsByIds(knex, [
...this.linkedDocumentIds,
...authorIds,
])

this.linkedDocuments = keyBy(linkedDocuments, "id")
}
Expand Down Expand Up @@ -792,6 +812,8 @@ export class GdocBase implements OwidGdocBaseInterface {
}

async loadState(knex: db.KnexReadonlyTransaction): Promise<void> {
// TODO explain why we're loading authors first
await this.loadAuthors(knex)
await this.loadLinkedDocuments(knex)
await this.loadImageMetadataFromDB(knex)
await this.loadLinkedCharts(knex)
Expand Down Expand Up @@ -868,3 +890,31 @@ export async function getMinimalGdocPostsByIds(
} satisfies OwidGdocMinimalPostInterface
})
}

export async function getMinimalAuthorByNames(
knex: KnexReadonlyTransaction,
names: string[]
): Promise<DbEnrichedAuthor[]> {
if (names.length === 0) return []
const rows = await db.knexRaw<DbRawAuthor>(
knex,
`-- sql
SELECT
id,
content ->> '$.title' as title
FROM posts_gdocs
WHERE type = 'author'
AND content->>"$.title" in (:names)
AND published = 1`,
{ names }
)

const rowsByName = keyBy(rows, "title")

return names.map((name) => {
return {
id: rowsByName[name]?.id || null,
title: name,
}
})
}
4 changes: 4 additions & 0 deletions db/model/Gdoc/GdocFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export async function getGdocBaseObjectById(
const enrichedRow = parsePostsGdocsRow(row)
const gdoc: OwidGdocBaseInterface = {
...enrichedRow,
authors: [],
tags: null,
} satisfies OwidGdocBaseInterface
if (fetchLinkedTags) {
Expand Down Expand Up @@ -244,6 +245,7 @@ export async function getGdocBaseObjectBySlug(
const enrichedRow = parsePostsGdocsRow(row)
const gdoc: OwidGdocBaseInterface = {
...enrichedRow,
authors: [],
tags: null,
} satisfies OwidGdocBaseInterface
if (fetchLinkedTags) {
Expand Down Expand Up @@ -387,6 +389,7 @@ export async function getAndLoadPublishedDataInsights(
const enrichedRows = rows.map((row) => {
return {
...parsePostsGdocsRow(row),
authors: [],
tags: groupedTags[row.id] ? groupedTags[row.id] : null,
} satisfies OwidGdocBaseInterface
})
Expand Down Expand Up @@ -507,6 +510,7 @@ export function getDbEnrichedGdocFromOwidGdoc(
gdoc: OwidGdoc | GdocBase
): DbEnrichedPostGdoc {
const enrichedGdoc = {
authors: gdoc.authors,
breadcrumbs: gdoc.breadcrumbs,
content: gdoc.content,
createdAt: gdoc.createdAt,
Expand Down
16 changes: 12 additions & 4 deletions packages/@ourworldindata/types/src/dbTypes/PostsGdocs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DbEnrichedAuthor } from "../domainTypes/Author.js"
import { BreadcrumbItem } from "../domainTypes/Site.js"
import { JsonString } from "../domainTypes/Various.js"
import {
Expand Down Expand Up @@ -25,6 +26,7 @@ export type DbEnrichedPostGdoc = Omit<
DbRawPostGdoc,
"content" | "breadcrumbs" | "published"
> & {
authors: DbEnrichedAuthor[]
content: OwidGdocContent
breadcrumbs: BreadcrumbItem[] | null
published: boolean
Expand Down Expand Up @@ -61,6 +63,7 @@ export function serializePostsGdocsBreadcrumbs(
export function parsePostsGdocsRow(row: DbRawPostGdoc): DbEnrichedPostGdoc {
return {
...row,
authors: [],
content: parsePostGdocContent(row.content),
breadcrumbs: parsePostsGdocsBreadcrumbs(row.breadcrumbs),
published: !!row.published,
Expand All @@ -72,15 +75,20 @@ export function parsePostsGdocsWithTagsRow(
): DBEnrichedPostGdocWithTags {
return {
...parsePostsGdocsRow(row),
authors: [],
tags: JSON.parse(row.tags),
}
}

export function serializePostsGdocsRow(row: DbEnrichedPostGdoc): DbRawPostGdoc {
const { authors: _authors, ...rowWithoutAuthors } = row

return {
...row,
content: serializePostGdocContent(row.content),
breadcrumbs: serializePostsGdocsBreadcrumbs(row.breadcrumbs),
published: row.published ? 1 : 0,
...rowWithoutAuthors,
content: serializePostGdocContent(rowWithoutAuthors.content),
breadcrumbs: serializePostsGdocsBreadcrumbs(
rowWithoutAuthors.breadcrumbs
),
published: rowWithoutAuthors.published ? 1 : 0,
}
}
10 changes: 10 additions & 0 deletions packages/@ourworldindata/types/src/domainTypes/Author.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
export interface DbRawAuthor {
id: string
title: string
}

export interface DbEnrichedAuthor {
id: string | null
title: string
}

export interface DbRawLatestWork {
id: string
slug: string
Expand Down
6 changes: 5 additions & 1 deletion packages/@ourworldindata/types/src/gdocTypes/Gdoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import {
} from "./ArchieMlComponents.js"
import { DbChartTagJoin } from "../dbTypes/ChartTags.js"
import { MinimalTag } from "../dbTypes/Tags.js"
import { DbEnrichedLatestWork } from "../domainTypes/Author.js"
import {
DbEnrichedAuthor,
DbEnrichedLatestWork,
} from "../domainTypes/Author.js"

export enum OwidGdocPublicationContext {
unlisted = "unlisted",
Expand Down Expand Up @@ -59,6 +62,7 @@ export interface OwidGdocBaseInterface {
id: string
slug: string
// TODO: should we type this as a union of the possible content types instead?
authors: DbEnrichedAuthor[]
content: OwidGdocContent
published: boolean
createdAt: Date
Expand Down
2 changes: 2 additions & 0 deletions packages/@ourworldindata/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,8 @@ export { RedirectCode, type DbPlainRedirect } from "./dbTypes/Redirects.js"
export type { Nominal } from "./NominalType.js"

export {
type DbRawAuthor,
type DbEnrichedAuthor,
type DbRawLatestWork,
type DbEnrichedLatestWork,
parseLatestWork,
Expand Down
24 changes: 24 additions & 0 deletions site/gdocs/components/Byline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { DbEnrichedAuthor } from "@ourworldindata/types"
import React from "react"
import { useLinkedDocument } from "../utils.js"

export const Byline = ({ authors }: { authors: DbEnrichedAuthor[] }) => {
return (
<>
By:{" "}
{authors.map((author) => (
<LinkedAuthor key={author.title} author={author} />
))}
</>
)
}

const LinkedAuthor = ({ author }: { author: DbEnrichedAuthor }) => {
const gdocUrl = `https://docs.google.com/document/d/${author.id}`
const { linkedDocument } = useLinkedDocument(gdocUrl)

if (linkedDocument && linkedDocument.published && linkedDocument.slug) {
return <a href={`/${linkedDocument.slug}`}>{author.title}</a>
}
return <>{author.title}</>
}
32 changes: 9 additions & 23 deletions site/gdocs/components/OwidGdocHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import React from "react"
import cx from "classnames"
import {
BreadcrumbItem,
DbEnrichedAuthor,
OwidGdocPostContent,
OwidGdocType,
formatDate,
} from "@ourworldindata/utils"
import { formatAuthors } from "../../clientFormatting.js"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js"
import { faBook } from "@fortawesome/free-solid-svg-icons"
import { faCreativeCommons } from "@fortawesome/free-brands-svg-icons"
import Image from "./Image.js"
import { Breadcrumbs } from "../../Breadcrumb/Breadcrumb.js"
import { breadcrumbColorForCoverColor } from "../utils.js"
import { Byline } from "./Byline.js"

function OwidArticleHeader({
content,
Expand All @@ -21,7 +22,7 @@ function OwidArticleHeader({
breadcrumbs,
}: {
content: OwidGdocPostContent
authors: string[]
authors: DbEnrichedAuthor[]
publishedAt: Date | null
breadcrumbs?: BreadcrumbItem[]
}) {
Expand Down Expand Up @@ -79,12 +80,7 @@ function OwidArticleHeader({
<div className="centered-article-header__meta-container col-start-2 span-cols-6 span-md-cols-10 col-md-start-2 grid grid-cols-2 ">
<div className="span-cols-1 span-sm-cols-2">
<div className="centered-article-header__byline">
{"By: "}
<a href="/team">
{formatAuthors({
authors,
})}
</a>
<Byline authors={authors} />
</div>
<div className="centered-article-header__dateline body-3-medium-italic">
{content.dateline ||
Expand Down Expand Up @@ -121,7 +117,7 @@ function OwidTopicPageHeader({
authors,
}: {
content: OwidGdocPostContent
authors: string[]
authors: DbEnrichedAuthor[]
}) {
return (
<header className="topic-page-header grid span-cols-14 grid-cols-12-full-width">
Expand All @@ -132,12 +128,7 @@ function OwidTopicPageHeader({
{content.subtitle}
</p>
<p className="topic-page-header__byline col-start-2 span-cols-8 col-sm-start-2 span-sm-cols-12">
{"By "}
<a href="/team">
{formatAuthors({
authors,
})}
</a>
<Byline authors={authors} />
</p>
</header>
)
Expand All @@ -148,7 +139,7 @@ function OwidLinearTopicPageHeader({
authors,
}: {
content: OwidGdocPostContent
authors: string[]
authors: DbEnrichedAuthor[]
}) {
return (
<header className="topic-page-header grid span-cols-14 grid-cols-12-full-width">
Expand All @@ -159,12 +150,7 @@ function OwidLinearTopicPageHeader({
{content.subtitle}
</p>
<p className="topic-page-header__byline col-start-5 span-cols-6 col-md-start-3 span-md-cols-10 span-sm-cols-12 col-sm-start-2">
{"By "}
<a href="/team">
{formatAuthors({
authors,
})}
</a>
<Byline authors={authors} />
</p>
<p className="topic-page-header__dateline body-3-medium-italic col-start-5 span-cols-6 col-md-start-3 span-md-cols-10 span-sm-cols-12 col-sm-start-2">
{content.dateline}
Expand All @@ -175,7 +161,7 @@ function OwidLinearTopicPageHeader({

export function OwidGdocHeader(props: {
content: OwidGdocPostContent
authors: string[]
authors: DbEnrichedAuthor[]
publishedAt: Date | null
breadcrumbs?: BreadcrumbItem[]
}) {
Expand Down
3 changes: 2 additions & 1 deletion site/gdocs/pages/GdocPost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const citationDescriptionsByArticleType: Record<
}

export function GdocPost({
authors,
content,
publishedAt,
slug,
Expand Down Expand Up @@ -83,7 +84,7 @@ export function GdocPost({
>
<OwidGdocHeader
content={content}
authors={content.authors}
authors={authors}
publishedAt={publishedAt}
breadcrumbs={breadcrumbs ?? undefined}
/>
Expand Down
2 changes: 2 additions & 0 deletions site/gdocs/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export const useLinkedDocument = (
} else if (!linkedDocument.published) {
errorMessage = `Article with slug "${linkedDocument.slug}" isn't published.`
}

//todo replace with getCanonicalUrl
const subdirectory =
linkedDocument.type === OwidGdocType.DataInsight ? "data-insights/" : ""
return {
Expand Down

0 comments on commit ed5675d

Please sign in to comment.