Skip to content

Commit

Permalink
🎉 make tags editable on the DI index page
Browse files Browse the repository at this point in the history
  • Loading branch information
sophiamersmann committed Feb 14, 2025
1 parent 491ce5b commit a862c68
Showing 1 changed file with 55 additions and 20 deletions.
75 changes: 55 additions & 20 deletions adminSiteClient/DataInsightIndexPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { useContext, useEffect, useMemo, useState } from "react"
import * as React from "react"
import {
useContext,
useEffect,
useMemo,
useState,
useCallback,
createContext,
Fragment,
} from "react"
import {
Button,
Card,
Expand Down Expand Up @@ -34,10 +41,10 @@ import {
import {
ALL_GRAPHER_CHART_TYPES,
DbEnrichedImageWithUserId,
DbPlainTag,
GRAPHER_MAP_TYPE,
GrapherChartOrMapType,
OwidGdocDataInsightIndexItem,
MinimalTag,
} from "@ourworldindata/types"
import {
copyToClipboard,
Expand All @@ -57,6 +64,7 @@ import {
} from "./imagesHelpers.js"
import { ReuploadImageForDataInsightModal } from "./ReuploadImageForDataInsightModal.js"
import { CreateDataInsightModal } from "./CreateDataInsightModal.js"
import { EditableTags } from "./EditableTags.js"

type NarrativeDataInsightIndexItem = RequiredBy<
OwidGdocDataInsightIndexItem,
Expand Down Expand Up @@ -87,9 +95,11 @@ const copyIcon = <FontAwesomeIcon icon={faCopy} size="sm" />
const panoramaIcon = <FontAwesomeIcon icon={faPanorama} size="sm" />
const plusIcon = <FontAwesomeIcon icon={faPlus} size="sm" />

const NotificationContext = React.createContext(null)
const NotificationContext = createContext(null)

function createColumns(ctx: {
availableTags: MinimalTag[]
updateTags: (gdocId: string, tags: MinimalTag[]) => Promise<void>
highlightFn: (
text: string | null | undefined
) => React.ReactElement | string
Expand Down Expand Up @@ -151,32 +161,29 @@ function createColumns(ctx: {
render: (authors: string[], dataInsight) => (
<>
{authors.map((author, index) => (
<React.Fragment key={author}>
<Fragment key={author}>
{ctx.highlightFn(author)}
{index < authors.length - 1 ? ", " : ""}
</React.Fragment>
</Fragment>
))}
{dataInsight.approvedBy &&
` (approved by ${dataInsight.approvedBy})`}
</>
),
},
{
title: "Topic tags",
title: "Tags",
dataIndex: "tags",
key: "tags",
render: (tags: DbPlainTag[]) =>
tags.map((tag) => (
<a
key={tag.name}
href={`/admin/tags/${tag.id}`}
target="_blank"
rel="noreferrer noopener"
style={{ display: "block" }}
>
{ctx.highlightFn(tag.name)}
</a>
)),
render: (tags, dataInsight) => (
<EditableTags
tags={tags}
onSave={(tags) =>
ctx.updateTags(dataInsight.id, tags as MinimalTag[])
}
suggestions={ctx.availableTags}
/>
),
},
{
title: "Published",
Expand Down Expand Up @@ -289,6 +296,8 @@ export function DataInsightIndexPage() {
OwidGdocDataInsightIndexItem[]
>([])

const [availableTags, setAvailableTags] = useState<MinimalTag[]>([])

const [searchValue, setSearchValue] = useState("")
const [chartTypeFilter, setChartTypeFilter] = useState<
GrapherChartOrMapType | "all"
Expand Down Expand Up @@ -359,6 +368,23 @@ export function DataInsightIndexPage() {
)
}, [dataInsights, chartTypeFilter, publicationFilter, searchWords])

const updateTags = useCallback(
async (gdocId: string, tags: MinimalTag[]) => {
const json = await admin.requestJSON(
`/api/gdocs/${gdocId}/setTags`,
{ tagIds: tags.map((t) => t.id) },
"POST"
)
if (json.success) {
const dataInsight = dataInsights.find(
(gdoc) => gdoc.id === gdocId
)
if (dataInsight) dataInsight.tags = tags
}
},
[admin, dataInsights]
)

const columns = useMemo(() => {
const highlightFn = highlightFunctionForSearchWords(searchWords)

Expand All @@ -367,10 +393,12 @@ export function DataInsightIndexPage() {
) => setDataInsightForImageUpload(dataInsight)

return createColumns({
availableTags,
updateTags,
highlightFn,
triggerImageUploadFlow,
})
}, [searchWords])
}, [searchWords, availableTags, updateTags])

const updateDataInsightPreview = (
dataInsightId: string,
Expand Down Expand Up @@ -428,6 +456,13 @@ export function DataInsightIndexPage() {
)
}, [admin])

useEffect(() => {
const fetchTags = async () =>
(await admin.getJSON("/api/tags.json")) as { tags: MinimalTag[] }

void fetchTags().then((result) => setAvailableTags(result.tags))
}, [admin])

return (
<AdminLayout title="Data insights">
<NotificationContext.Provider value={null}>
Expand Down

0 comments on commit a862c68

Please sign in to comment.