Skip to content

Commit

Permalink
Add catalogPath to mdims
Browse files Browse the repository at this point in the history
* Catalog path will now be the main ID used by ETL
* It's temporarily allowed to be null; we'll disallow that once existing
  data is migrated
* Slug is now allowed to be null, since it will be only set in admin at
  some point
* For that reason we'll use the catalog path as a slug for previews of
  mdims in the admin, i.e. `/admin/grapher/{catalogPath}`
  • Loading branch information
rakyi committed Feb 26, 2025
1 parent 60c0d5d commit cb3b623
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 98 deletions.
57 changes: 41 additions & 16 deletions adminSiteClient/MultiDimIndexPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { AdminLayout } from "./AdminLayout.js"
import { AdminAppContext } from "./AdminAppContext.js"
import urljoin from "url-join"
import {
BAKED_BASE_URL,
ADMIN_BASE_URL,
BAKED_GRAPHER_URL,
GRAPHER_DYNAMIC_THUMBNAIL_URL,
} from "../settings/clientSettings.js"
Expand All @@ -28,6 +28,7 @@ import { Link } from "./Link.js"

type ApiMultiDim = {
id: number
catalogPath: string | null
title: string
slug: string
updatedAt: string
Expand Down Expand Up @@ -86,21 +87,31 @@ function createColumns(
render: (_, record) => {
return (
<a
href={urljoin(
BAKED_BASE_URL,
`/admin/grapher/${record.slug}`
)}
href={
record.catalogPath
? urljoin(
ADMIN_BASE_URL,
`/admin/grapher/${encodeURIComponent(
record.catalogPath
)}`
)
: undefined
}
target="_blank"
rel="noopener"
>
<img
src={urljoin(
GRAPHER_DYNAMIC_THUMBNAIL_URL,
`/${record.slug}.png?imHeight=400`
)}
style={{ height: "140px", width: "auto" }}
alt="Preview"
/>
{record.slug ? (
<img
src={urljoin(
GRAPHER_DYNAMIC_THUMBNAIL_URL,
`/${record.slug}.png?imHeight=400`
)}
style={{ height: "140px", width: "auto" }}
alt="Preview"
/>
) : (
"Preview"
)}
</a>
)
},
Expand All @@ -109,7 +120,6 @@ function createColumns(
title: "Title",
dataIndex: "title",
key: "title",
width: 280,
render: (text, record) =>
record.published ? (
<a
Expand All @@ -124,6 +134,20 @@ function createColumns(
),
sorter: (a, b) => a.title.localeCompare(b.title),
},
{
title: "Catalog path",
dataIndex: "catalogPath",
key: "catalogPath",
render: (catalogPath) =>
catalogPath && (
<Typography.Text copyable>{catalogPath}</Typography.Text>
),
sorter: (a, b) => {
if (a.catalogPath === null) return 1
if (b.catalogPath === null) return -1
return a.catalogPath.localeCompare(b.catalogPath)
},
},
{
title: "Slug",
dataIndex: "slug",
Expand Down Expand Up @@ -164,8 +188,9 @@ function createColumns(
<Switch
checked={published}
disabled={
publishMutation.isLoading &&
publishMutation.variables?.id === record.id
!record.slug ||
(publishMutation.isLoading &&
publishMutation.variables?.id === record.id)
}
/>
</Popconfirm>
Expand Down
14 changes: 9 additions & 5 deletions adminSiteServer/adminRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ import { getChartConfigBySlug } from "../db/model/Chart.js"
import { getVariableMetadata } from "../db/model/Variable.js"
import { DbPlainDatasetFile, DbPlainDataset } from "@ourworldindata/types"
import { getPlainRouteWithROTransaction } from "./plainRouterHelpers.js"
import { getMultiDimDataPageBySlug } from "../db/model/MultiDimDataPage.js"
import {
getMultiDimDataPageByCatalogPath,
getMultiDimDataPageBySlug,
} from "../db/model/MultiDimDataPage.js"
import { renderMultiDimDataPageFromConfig } from "../baker/MultiDimBaker.js"

// eslint-disable-next-line @typescript-eslint/no-require-imports
Expand Down Expand Up @@ -356,13 +359,14 @@ getPlainRouteWithROTransaction(
return
}

const mdd = await getMultiDimDataPageBySlug(trx, slug, {
onlyPublished: false,
})
const mdd =
(await getMultiDimDataPageBySlug(trx, slug, {
onlyPublished: false,
})) ?? (await getMultiDimDataPageByCatalogPath(trx, slug))
if (mdd) {
const renderedPage = await renderMultiDimDataPageFromConfig({
knex: trx,
slug,
slug: mdd.slug,
config: mdd.config,
isPreviewing: true,
})
Expand Down
6 changes: 5 additions & 1 deletion adminSiteServer/apiRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,11 @@ getRouteWithROTransaction(apiRouter, "/images/usage", getImageUsageHandler)

// Mdim routes
getRouteWithROTransaction(apiRouter, "/multi-dims.json", handleGetMultiDims)
putRouteWithRWTransaction(apiRouter, "/multi-dim/:slug", handlePutMultiDim)
putRouteWithRWTransaction(
apiRouter,
"/multi-dims/:catalogPath",
handlePutMultiDim
)
patchRouteWithRWTransaction(apiRouter, "/multi-dims/:id", handlePatchMultiDim)

// Misc routes
Expand Down
53 changes: 30 additions & 23 deletions adminSiteServer/apiRoutes/mdims.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import {
DbPlainMultiDimDataPage,
JsonError,
MultiDimDataPageConfigRaw,
MultiDimDataPagesTableName,
} from "@ourworldindata/types"
import { getMultiDimDataPageById } from "../../db/model/MultiDimDataPage.js"
import { expectInt } from "../../serverUtils/serverUtil.js"
import {
getMultiDimDataPageById,
multiDimDataPageExists,
} from "../../db/model/MultiDimDataPage.js"
import { expectInt, isValidSlug } from "../../serverUtils/serverUtil.js"
import {
upsertMultiDimConfig,
upsertMultiDim,
setMultiDimPublished,
setMultiDimSlug,
} from "../multiDim.js"
import { triggerStaticBuild } from "./routeUtils.js"
import { Request } from "../authentication.js"
import * as db from "../../db/db.js"
import { validateNewGrapherSlug, validateMultiDimSlug } from "../validation.js"
import {
validateNewGrapherSlug,
validateMultiDimSlug,
isValidCatalogPath,
} from "../validation.js"
import e from "express"

export async function handleGetMultiDims(
Expand All @@ -25,17 +27,17 @@ export async function handleGetMultiDims(
trx: db.KnexReadonlyTransaction
) {
try {
const results = await db.knexRaw<{
id: number
slug: string
title: string
updatedAt: string
published: number
}>(
const results = await db.knexRaw<
Pick<
DbPlainMultiDimDataPage,
"id" | "catalogPath" | "slug" | "updatedAt" | "published"
> & { title: string }
>(
trx,
`-- sql
SELECT
id,
catalogPath,
slug,
config->>'$.title.title' as title,
updatedAt,
Expand All @@ -57,20 +59,25 @@ export async function handlePutMultiDim(
res: e.Response<any, Record<string, any>>,
trx: db.KnexReadWriteTransaction
) {
const { slug } = req.params
if (!isValidSlug(slug)) {
throw new JsonError(`Invalid multi-dim slug ${slug}`)
const { catalogPath } = req.params
if (!isValidCatalogPath(catalogPath)) {
throw new JsonError(`Invalid multi-dim catalog path ${catalogPath}`)
}
if (!(await multiDimDataPageExists(trx, { slug }))) {
await validateNewGrapherSlug(trx, slug)
const { config: rawConfig } = req.body as {
config: MultiDimDataPageConfigRaw
}
const rawConfig = req.body as MultiDimDataPageConfigRaw
const id = await upsertMultiDimConfig(trx, slug, rawConfig)
const id = await upsertMultiDim(trx, catalogPath, rawConfig)

if (await multiDimDataPageExists(trx, { slug, published: true })) {
const { slug: publishedSlug } =
(await trx<DbPlainMultiDimDataPage>(MultiDimDataPagesTableName)
.select("slug")
.where("catalogPath", catalogPath)
.where("published", true)
.first()) ?? {}
if (publishedSlug) {
await triggerStaticBuild(
res.locals.user,
`Publishing multidimensional chart ${slug}`
`Publishing multidimensional chart ${publishedSlug}`
)
}
return { success: true, id }
Expand Down
8 changes: 4 additions & 4 deletions adminSiteServer/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,11 +492,12 @@ describe("OwidAdminApp: indicator-level chart configs", () => {
// create mdim config that uses both of the variables
await makeRequestAgainstAdminApi({
method: "PUT",
path: "/multi-dim/energy",
body: JSON.stringify(testMultiDimConfig),
path: "/multi-dims/test%2Fcatalog%23path",
body: JSON.stringify({ config: testMultiDimConfig }),
})
const mdim = await testKnexInstance!(MultiDimDataPagesTableName).first()
expect(mdim.slug).toBe("energy")
expect(mdim.catalogPath).toBe("test/catalog#path")
expect(mdim.slug).toBe(null)
const savedMdimConfig = JSON.parse(mdim.config)
// variableId should be normalized to an array
expect(savedMdimConfig.views[0].indicators.y).toBeInstanceOf(Array)
Expand All @@ -516,7 +517,6 @@ describe("OwidAdminApp: indicator-level chart configs", () => {
...mergedGrapherConfig,
title: "Total energy use",
selectedEntityNames: [], // mdims define their own default entities
slug: "energy",
}
const fullViewConfig1 = await testKnexInstance!(ChartConfigsTableName)
.where("id", mdxcc1.chartConfigId)
Expand Down
Loading

0 comments on commit cb3b623

Please sign in to comment.