Skip to content

Commit

Permalink
Merge pull request #4343 from owid/breadcrumbs
Browse files Browse the repository at this point in the history
🎉 automatic breadcrumbs from the tag graph
  • Loading branch information
ikesau authored Jan 16, 2025
2 parents 0e7e76d + a65c4b3 commit 5d3fb41
Show file tree
Hide file tree
Showing 27 changed files with 611 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ export const BreadcrumbLine = ({
item,
setItem,
removeItem,
isLastBreadcrumbItem,
labelError,
hrefError,
}: {
item: BreadcrumbItem
setItem: (item: BreadcrumbItem) => void
removeItem: () => void
isLastBreadcrumbItem?: boolean
labelError?: OwidGdocErrorMessage
hrefError?: OwidGdocErrorMessage
}) => {
Expand All @@ -30,15 +28,10 @@ export const BreadcrumbLine = ({
<Col span={11}>
<Input
addonBefore="URL"
value={
isLastBreadcrumbItem
? "The last breadcrumb isn't clickable"
: item.href
}
value={item.href}
onChange={(e) =>
setItem({ ...item, href: e.target.value })
}
disabled={isLastBreadcrumbItem}
status={hrefError?.type}
placeholder="e.g. /poverty"
/>
Expand All @@ -51,11 +44,7 @@ export const BreadcrumbLine = ({
onChange={(e) =>
setItem({ ...item, label: e.target.value })
}
placeholder={
isLastBreadcrumbItem
? "Concise version of the article's title"
: undefined
}
placeholder={"A topic name"}
status={labelError?.type}
/>
{labelError && <GdocsErrorHelp error={labelError} />}
Expand All @@ -70,7 +59,7 @@ export const BreadcrumbLine = ({
)
}

export const GdocsBreadcrumbsInput = ({
export const GdocsManualBreadcrumbsInput = ({
gdoc,
setCurrentGdoc,
errors,
Expand All @@ -79,62 +68,76 @@ export const GdocsBreadcrumbsInput = ({
setCurrentGdoc: (gdoc: OwidGdocPostInterface) => void
errors?: OwidGdocErrorMessage[]
}) => {
const setBreadcrumbs = (breadcrumbs: BreadcrumbItem[] | undefined) => {
if (breadcrumbs?.length) {
// The last breadcrumb is not clickable, so we don't need a URL
breadcrumbs[breadcrumbs.length - 1].href = undefined
} else breadcrumbs = undefined

setCurrentGdoc({ ...gdoc, breadcrumbs: breadcrumbs ?? null })
const setBreadcrumbs = (breadcrumbs: BreadcrumbItem[] | null) => {
setCurrentGdoc({ ...gdoc, manualBreadcrumbs: breadcrumbs })
}

const setItemAtIndex = (item: BreadcrumbItem, i: number) => {
const breadcrumbs = [...(gdoc.breadcrumbs ?? [])]
if (!gdoc.manualBreadcrumbs) return

const breadcrumbs = [...gdoc.manualBreadcrumbs]
breadcrumbs[i] = item
setBreadcrumbs(breadcrumbs)
}

const removeItemAtIndex = (i: number) => {
const breadcrumbs = [...(gdoc.breadcrumbs ?? [])]
if (!gdoc.manualBreadcrumbs) return

const breadcrumbs = [...gdoc.manualBreadcrumbs]
breadcrumbs.splice(i, 1)
setBreadcrumbs(breadcrumbs)

setBreadcrumbs(breadcrumbs.length ? breadcrumbs : null)
}

return (
<div className="form-group">
<div className="d-flex justify-content-between">
Breadcrumbs
<Button
type="dashed"
onClick={() =>
setBreadcrumbs([
{ label: "" },
...(gdoc.breadcrumbs ?? []),
])
}
>
<FontAwesomeIcon icon={faPlus} className="mr-1" /> Add
breadcrumb
</Button>
</div>
{gdoc.breadcrumbs?.map((item, i) => (
<div className="d-flex justify-content-between">Breadcrumbs</div>
{!!gdoc.breadcrumbs?.length && !gdoc.manualBreadcrumbs?.length ? (
<div>
<p>
The breadcrumbs for this article will be automatically
generated, based on this article's tags and the tag
graph.
</p>
<p>
If you want to override these breadcrumbs, you can do so
here:
</p>
</div>
) : (
<strong>
Unless you are editing an SDG page, each breadcrumb should
have a URL and label.
</strong>
)}
<Button
type="dashed"
onClick={() =>
setBreadcrumbs([
{ href: "", label: "" },
...(gdoc.manualBreadcrumbs || []),
])
}
>
<FontAwesomeIcon icon={faPlus} className="mr-1" /> Add
breadcrumb
</Button>
{gdoc.manualBreadcrumbs?.map((item, i) => (
<BreadcrumbLine
item={item}
setItem={(item) => setItemAtIndex(item, i)}
removeItem={() => removeItemAtIndex(i)}
key={i}
labelError={getPropertyMostCriticalError(
`breadcrumbs[${i}].label`,
`manualBreadcrumbs[${i}].label`,
errors
)}
hrefError={getPropertyMostCriticalError(
`breadcrumbs[${i}].href`,
`manualBreadcrumbs[${i}].href`,
errors
)}
isLastBreadcrumbItem={i === gdoc.breadcrumbs!.length - 1}
/>
))}
{!gdoc.breadcrumbs?.length && <i>No breadcrumbs</i>}
</div>
)
}
5 changes: 0 additions & 5 deletions adminSiteClient/GdocsPreviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,6 @@ export const GdocsPreviewPage = ({ match, history }: GdocsMatchProps) => {
size="large"
onClose={onSettingsClose}
open={isSettingsOpen}
extra={
<Button type="primary" onClick={onSettingsClose}>
Done
</Button>
}
>
{tsMatch(currentGdoc)
.with(
Expand Down
4 changes: 2 additions & 2 deletions adminSiteClient/GdocsSettingsForms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { GdocsPublishedAt } from "./GdocsDateline.js"
import { GdocsPublicationContext } from "./GdocsPublicationContext.js"
import { Alert } from "antd"
import { GdocsBreadcrumbsInput } from "./GdocsBreadcrumbsInput.js"
import { GdocsManualBreadcrumbsInput } from "./GdocsManualBreadcrumbsInput.js"

const GdocCommonErrors = ({
errors,
Expand Down Expand Up @@ -155,7 +155,7 @@ export const GdocPostSettings = ({
errors={errors}
description="An optional property to override the excerpt of this post in our atom feed, which is used for the newsletter"
/>
<GdocsBreadcrumbsInput
<GdocsManualBreadcrumbsInput
gdoc={gdoc}
errors={errors}
setCurrentGdoc={setCurrentGdoc}
Expand Down
3 changes: 2 additions & 1 deletion adminSiteClient/gdocsDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ export const checkIsLightningUpdate = (
Exclude<keyof OwidGdocBaseInterface, "content">,
boolean
> = {
breadcrumbs: true,
breadcrumbs: true, // automatically generated, not actually possible to change via the admin preview
manualBreadcrumbs: true,
errors: true,
linkedAuthors: false,
linkedCharts: true,
Expand Down
10 changes: 5 additions & 5 deletions adminSiteClient/gdocsValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ function validateExcerpt(
}
}

function validateBreadcrumbs(
function validateManualBreadcrumbs(
gdoc: OwidGdocPostInterface,
errors: OwidGdocErrorMessage[]
) {
if (gdoc.breadcrumbs) {
for (const [i, breadcrumb] of gdoc.breadcrumbs.entries()) {
if (gdoc.manualBreadcrumbs) {
for (const [i, breadcrumb] of gdoc.manualBreadcrumbs.entries()) {
if (!breadcrumb.label) {
errors.push({
property: `breadcrumbs[${i}].label`,
Expand All @@ -155,7 +155,7 @@ function validateBreadcrumbs(
}

// Last item can be missing a href
if (!breadcrumb.href && i !== gdoc.breadcrumbs.length - 1) {
if (!breadcrumb.href && i !== gdoc.manualBreadcrumbs.length - 1) {
errors.push({
property: `breadcrumbs[${i}].href`,
type: OwidGdocErrorMessageType.Error,
Expand Down Expand Up @@ -292,7 +292,7 @@ export const getErrors = (gdoc: OwidGdoc): OwidGdocErrorMessage[] => {
if (checkIsGdocPost(gdoc)) {
validateRefs(gdoc, errors)
validateExcerpt(gdoc, errors)
validateBreadcrumbs(gdoc, errors)
validateManualBreadcrumbs(gdoc, errors)
validateAtomFields(gdoc, errors)
} else if (checkIsDataInsight(gdoc)) {
validateApprovedBy(gdoc, errors)
Expand Down
5 changes: 2 additions & 3 deletions adminSiteServer/apiRoutes/gdocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,10 @@ export async function createOrUpdateGdoc(
: GdocLinkUpdateMode.DeleteOnly
)

await upsertGdoc(trx, nextGdoc)

const upserted = await upsertGdoc(trx, nextGdoc)
await indexAndBakeGdocIfNeccesary(trx, res.locals.user, prevGdoc, nextGdoc)

return nextGdoc
return upserted
}

async function validateTombstoneRelatedLinkUrl(
Expand Down
Loading

0 comments on commit 5d3fb41

Please sign in to comment.