From 0c68bdb4f856c96ab5ac5ef101a2b1d415b5c9dd Mon Sep 17 00:00:00 2001 From: Ike Saunders Date: Tue, 5 Nov 2024 20:58:13 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A8=20remove=20grapher=20static=20expo?= =?UTF-8?q?rts,=20replace=20with=20CF=20worker=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adminSiteClient/ChartRow.tsx | 7 +- adminSiteServer/mockSiteRouter.tsx | 10 +- baker/GrapherBakingUtils.ts | 111 ----------------------- baker/SiteBaker.tsx | 43 ++------- baker/formatWordpressPost.tsx | 91 +++++++++---------- baker/siteRenderers.tsx | 46 ++-------- db/model/Chart.ts | 59 +----------- db/model/Gdoc/GdocBase.ts | 4 +- ops/buildkite/build-code | 7 -- settings/clientSettings.ts | 4 - site/GrapherImage.tsx | 41 ++++++--- site/InteractionNotice.tsx | 1 + site/blocks/RelatedCharts.jsdom.test.tsx | 4 +- site/css/content.scss | 6 ++ site/gdocs/components/Chart.tsx | 11 +-- site/gdocs/components/ProminentLink.tsx | 4 +- site/search/ChartHit.tsx | 5 +- 17 files changed, 110 insertions(+), 344 deletions(-) diff --git a/adminSiteClient/ChartRow.tsx b/adminSiteClient/ChartRow.tsx index e3fcefb6c01..13b8add92a7 100644 --- a/adminSiteClient/ChartRow.tsx +++ b/adminSiteClient/ChartRow.tsx @@ -6,10 +6,7 @@ import { Link } from "./Link.js" import { Timeago } from "./Forms.js" import { EditableTags } from "./EditableTags.js" import { AdminAppContext, AdminAppContextType } from "./AdminAppContext.js" -import { - BAKED_GRAPHER_EXPORTS_BASE_URL, - BAKED_GRAPHER_URL, -} from "../settings/clientSettings.js" +import { BAKED_GRAPHER_URL } from "../settings/clientSettings.js" import { ChartListItem, showChartType } from "./ChartList.js" import { TaggableType, DbChartTagJoin } from "@ourworldindata/utils" @@ -52,7 +49,7 @@ export class ChartRow extends React.Component<{ {chart.isPublished ? ( diff --git a/adminSiteServer/mockSiteRouter.tsx b/adminSiteServer/mockSiteRouter.tsx index 6cf086bf5ce..f3ba6975f60 100644 --- a/adminSiteServer/mockSiteRouter.tsx +++ b/adminSiteServer/mockSiteRouter.tsx @@ -24,7 +24,6 @@ import { import { BAKED_BASE_URL, BASE_DIR, - BAKED_SITE_DIR, LEGACY_WORDPRESS_IMAGE_URL, } from "../settings/serverSettings.js" @@ -435,16 +434,11 @@ mockSiteRouter.use( res.redirect(assetUrl) } ) -mockSiteRouter.use( - "/exports", - express.static(path.join(BAKED_SITE_DIR, "exports")) -) mockSiteRouter.use("/assets", express.static("dist/assets")) -// TODO: this used to be a mockSiteRouter.use call but otherwise it looked like a route and -// it didn't look like it was making use of any middleware - if this causese issues then -// this has to be reverted to a use call +// We've replaced static grapher exports with a Cloudflare Worker, so this is no longer "mocking" the real site +// But it's still useful to have for the /admin/charts page getPlainRouteWithROTransaction( mockSiteRouter, "/grapher/exports/:slug.svg", diff --git a/baker/GrapherBakingUtils.ts b/baker/GrapherBakingUtils.ts index b7f80eee83c..abf4f561f05 100644 --- a/baker/GrapherBakingUtils.ts +++ b/baker/GrapherBakingUtils.ts @@ -1,27 +1,9 @@ -import { glob } from "glob" -import path from "path" import * as lodash from "lodash" -import { - OPTIMIZE_SVG_EXPORTS, - BAKED_SITE_DIR, -} from "../settings/serverSettings.js" -import { BAKED_SITE_EXPORTS_BASE_URL } from "../settings/clientSettings.js" import * as db from "../db/db.js" -import { bakeGraphersToSvgs } from "../baker/GrapherImageBaker.js" -import { warn } from "../serverUtils/errorLog.js" -import { mapSlugsToIds } from "../db/model/Chart.js" import md5 from "md5" import { DbPlainTag, Url } from "@ourworldindata/utils" -interface ChartExportMeta { - key: string - svgUrl: string - version: number - width: number - height: number -} - // Splits a grapher URL like https://ourworldindata.org/grapher/soil-lifespans?tab=chart // into its slug (soil-lifespans) and queryStr (?tab=chart) export const grapherUrlToSlugAndQueryStr = (grapherUrl: string) => { @@ -48,99 +30,6 @@ export const grapherSlugToExportFileKey = ( return `${slug}${queryStr ? `${separator}${maybeHashedQueryStr}` : ""}` } -export interface GrapherExports { - get: (grapherUrl: string) => ChartExportMeta | undefined -} - -export const bakeGrapherUrls = async ( - knex: db.KnexReadonlyTransaction, - urls: string[] -) => { - const currentExports = await getGrapherExportsByUrl() - const slugToId = await mapSlugsToIds(knex) - const toBake = [] - - // Check that we need to bake this url, and don't already have an export - for (const url of urls) { - const current = currentExports.get(url) - if (!current) { - toBake.push(url) - continue - } - - const slug = lodash.last(Url.fromURL(url).pathname?.split("/")) - if (!slug) { - warn(`Invalid chart url ${url}`) - continue - } - - const chartId = slugToId[slug] - if (chartId === undefined) { - warn(`Couldn't find chart with slug ${slug}`) - continue - } - - const rows = await db.knexRaw<{ version: number }>( - knex, - `-- sql - SELECT cc.full->>"$.version" AS version - FROM charts c - JOIN chart_configs cc ON c.configId = cc.id - WHERE c.id=? - `, - [chartId] - ) - if (!rows.length) { - warn(`Mysteriously missing chart by id ${chartId}`) - continue - } - - if (rows[0].version > current.version) toBake.push(url) - } - - if (toBake.length > 0) { - await bakeGraphersToSvgs( - knex, - toBake, - `${BAKED_SITE_DIR}/exports`, - OPTIMIZE_SVG_EXPORTS - ) - } -} - -export const getGrapherExportsByUrl = async (): Promise => { - // Index the files to see what we have available, using the most recent version - // if multiple exports exist - const files = await glob(`${BAKED_SITE_DIR}/exports/*.svg`) - const exportsByKey = new Map() - for (const filepath of files) { - const filename = path.basename(filepath) - const [key, version, dims] = filename.toLowerCase().split("_") - const versionNumber = parseInt(version.split("v")[1]) - const [width, height] = dims.split("x") - - const current = exportsByKey.get(key) - if (!current || current.version < versionNumber) { - exportsByKey.set(key, { - key: key, - svgUrl: `${BAKED_SITE_EXPORTS_BASE_URL}/${filename}`, - version: versionNumber, - width: parseInt(width), - height: parseInt(height), - }) - } - } - - return { - get(grapherUrl: string) { - const { slug, queryStr } = grapherUrlToSlugAndQueryStr(grapherUrl) - return exportsByKey.get( - grapherSlugToExportFileKey(slug, queryStr).toLowerCase() - ) - }, - } -} - /** * Returns a map that can resolve Tag names and Tag IDs to the Tag's slug * e.g. diff --git a/baker/SiteBaker.tsx b/baker/SiteBaker.tsx index 6612688eadc..07d9d5d92c9 100644 --- a/baker/SiteBaker.tsx +++ b/baker/SiteBaker.tsx @@ -1,7 +1,7 @@ import fs from "fs-extra" import path from "path" import { glob } from "glob" -import { keyBy, without, uniq, mapValues, pick, chunk } from "lodash" +import { keyBy, without, mapValues, pick, chunk } from "lodash" import ProgressBar from "progress" import * as db from "../db/db.js" import { @@ -33,11 +33,6 @@ import { makeDataInsightsAtomFeed, renderGdocTombstone, } from "../baker/siteRenderers.js" -import { - bakeGrapherUrls, - getGrapherExportsByUrl, - GrapherExports, -} from "../baker/GrapherBakingUtils.js" import { makeSitemap } from "../baker/sitemap.js" import { bakeCountries } from "../baker/countryProfiles.js" import { bakeDriveImages } from "../baker/GDriveImagesBaker.js" @@ -86,14 +81,11 @@ import { GdocPost } from "../db/model/Gdoc/GdocPost.js" import { Image, getAllImages } from "../db/model/Image.js" import { generateEmbedSnippet } from "../site/viteUtils.js" import { logErrorAndMaybeSendToBugsnag } from "../serverUtils/errorLog.js" -import { - getChartEmbedUrlsInPublishedWordpressPosts, - mapSlugsToConfigs, -} from "../db/model/Chart.js" +import { mapSlugsToConfigs } from "../db/model/Chart.js" import { BAKED_BASE_URL, - BAKED_GRAPHER_EXPORTS_BASE_URL, FeatureFlagFeature, + GRAPHER_DYNAMIC_THUMBNAIL_URL, } from "../settings/clientSettings.js" import pMap from "p-map" import { GdocDataInsight } from "../db/model/Gdoc/GdocDataInsight.js" @@ -130,7 +122,6 @@ type PrefetchedAttachments = { const wordpressSteps = [ "assets", "blogIndex", - "embeds", "redirects", "rss", "wordpressPosts", @@ -186,7 +177,6 @@ function getProgressBarTotal(bakeSteps: BakeStepConfig): number { } export class SiteBaker { - private grapherExports!: GrapherExports private bakedSiteDir: string baseUrl: string progressBar: ProgressBar @@ -221,20 +211,6 @@ export class SiteBaker { // } } - private async bakeEmbeds(knex: db.KnexReadonlyTransaction) { - if (!this.bakeSteps.has("embeds")) return - - // Find all grapher urls used as embeds in all Wordpress posts on the site - const grapherUrls = uniq( - await getChartEmbedUrlsInPublishedWordpressPosts(knex) - ) - - await bakeGrapherUrls(knex, grapherUrls) - - this.grapherExports = await getGrapherExportsByUrl() - this.progressBar.tick({ name: "✅ baked embeds" }) - } - private async bakeCountryProfiles(knex: db.KnexReadonlyTransaction) { if (!this.bakeSteps.has("countryProfiles")) return await Promise.all( @@ -248,8 +224,7 @@ export class SiteBaker { const html = await renderCountryProfile( spec, country, - knex, - this.grapherExports + knex ).catch(() => console.error( `${country.name} country profile not baked for project "${spec.project}". Check that both pages "${spec.landingPageSlug}" and "${spec.genericProfileSlug}" exist and are published.` @@ -296,12 +271,7 @@ export class SiteBaker { // Bake an individual post/page private async bakePost(post: FullPost, knex: db.KnexReadonlyTransaction) { - const html = await renderPost( - post, - knex, - this.baseUrl, - this.grapherExports - ) + const html = await renderPost(post, knex, this.baseUrl) const outPath = path.join(this.bakedSiteDir, `${post.slug}.html`) await fs.mkdirp(path.dirname(outPath)) @@ -419,7 +389,7 @@ export class SiteBaker { resolvedUrl: `${BAKED_GRAPHER_URL}/${chart.config.slug}`, tab, title: chart.config.title || "", - thumbnail: `${BAKED_GRAPHER_EXPORTS_BASE_URL}/${chart.config.slug}.svg`, + thumbnail: `${GRAPHER_DYNAMIC_THUMBNAIL_URL}/${chart.config.slug}.svg`, indicatorId: datapageIndicator?.id, tags: [], }) @@ -1113,7 +1083,6 @@ export class SiteBaker { // somewhere inside it we fetch images. async bakeWordpressPages(knex: db.KnexReadWriteTransaction) { await this.bakeRedirects(knex) - await this.bakeEmbeds(knex) await this.bakeBlogIndex(knex) await this.bakeRSS(knex) await this.bakeAssets(knex) diff --git a/baker/formatWordpressPost.tsx b/baker/formatWordpressPost.tsx index 06681a0f2da..91a71d7867c 100644 --- a/baker/formatWordpressPost.tsx +++ b/baker/formatWordpressPost.tsx @@ -3,12 +3,10 @@ import urlSlug from "url-slug" import React from "react" import ReactDOMServer from "react-dom/server.js" import { HTTPS_ONLY } from "../settings/serverSettings.js" -import { GrapherExports } from "../baker/GrapherBakingUtils.js" import { FormattingOptions } from "@ourworldindata/types" -import { FormattedPost, FullPost, TocHeading } from "@ourworldindata/utils" +import { FormattedPost, FullPost, TocHeading, Url } from "@ourworldindata/utils" import { parseKeyValueArgs } from "../serverUtils/wordpressUtils.js" import { Footnote } from "../site/Footnote.js" -import { LoadingIndicator } from "@ourworldindata/grapher" import { PROMINENT_LINK_CLASSNAME } from "../site/blocks/ProminentLink.js" import { DataToken } from "../site/DataToken.js" import { DEEP_LINK_CLASS, formatImages } from "./formatting.js" @@ -26,12 +24,12 @@ import { INTERACTIVE_ICON_SVG } from "../site/InteractionNotice.js" import { renderProminentLinks } from "./siteRenderers.js" import { RELATED_CHARTS_CLASS_NAME } from "../site/blocks/RelatedCharts.js" import { KnexReadonlyTransaction } from "../db/db.js" +import { GRAPHER_DYNAMIC_THUMBNAIL_URL } from "../settings/clientSettings.js" export const formatWordpressPost = async ( post: FullPost, formattingOptions: FormattingOptions, - knex: KnexReadonlyTransaction, - grapherExports?: GrapherExports + knex: KnexReadonlyTransaction ): Promise => { let html = post.content @@ -152,53 +150,49 @@ export const formatWordpressPost = async ( // Replace URLs pointing to Explorer redirect URLs with the destination URLs replaceIframesWithExplorerRedirectsInWordPressPost(cheerioEl) - // Replace grapher iframes with static previews - if (grapherExports) { - const grapherIframes = cheerioEl("iframe") - .toArray() - .filter((el) => (el.attribs["src"] || "").match(/\/grapher\//)) - for (const el of grapherIframes) { - const $el = cheerioEl(el) - const src = el.attribs["src"].trim() - const chart = grapherExports.get(src) - if (chart) { - const output = ` + const grapherIframes = cheerioEl("iframe") + .toArray() + .filter((el) => (el.attribs["src"] || "").match(/\/grapher\//)) + + for (const el of grapherIframes) { + const $el = cheerioEl(el) + const src = el.attribs["src"].trim() + const url = Url.fromURL(src) + const output = `
-
+
${INTERACTIVE_ICON_SVG} Click to open interactive version
` - if (el.parent.tagName === "p") { - // We are about to replace

-->

- const $p = $el.parent() - $p.after(output) - $el.remove() - } else if (el.parent.tagName === "figure") { - // Support for -->
- const $figure = $el.parent() - $figure.after(output) - $figure.remove() - } else { - // No lifting up otherwise, just replacing -->
- $el.after(output) - $el.remove() - } - } + if (el.parent.tagName === "p") { + // We are about to replace

-->

+ const $p = $el.parent() + $p.after(output) + $el.remove() + } else if (el.parent.tagName === "figure") { + // Support for -->
+ const $figure = $el.parent() + $figure.after(output) + $figure.remove() + } else { + // No lifting up otherwise, just replacing -->
+ $el.after(output) + $el.remove() } } @@ -211,13 +205,15 @@ export const formatWordpressPost = async ( for (const el of explorerIframes) { const $el = cheerioEl(el) const src = el.attribs["src"].trim() + // const url = Url.fromURL(src) // set a default style if none exists on the existing iframe const style = el.attribs["style"] || "width: 100%; height: 600px;" const cssClass = el.attribs["class"] const $figure = cheerioEl( ReactDOMServer.renderToStaticMarkup(
- + {/* TODO: finish once https://github.com/owid/owid-grapher/pull/4031 is merged */} + {/* */}
) ) @@ -372,8 +368,7 @@ export const formatWordpressPost = async ( export const formatPost = async ( post: FullPost, formattingOptions: FormattingOptions, - knex: KnexReadonlyTransaction, - grapherExports?: GrapherExports + knex: KnexReadonlyTransaction ): Promise => { // No formatting applied, plain source HTML returned if (formattingOptions.raw) @@ -392,5 +387,5 @@ export const formatPost = async ( ...formattingOptions, } - return formatWordpressPost(post, options, knex, grapherExports) + return formatWordpressPost(post, options, knex) } diff --git a/baker/siteRenderers.tsx b/baker/siteRenderers.tsx index 787ded3f9a7..8ed0aed239a 100644 --- a/baker/siteRenderers.tsx +++ b/baker/siteRenderers.tsx @@ -13,11 +13,6 @@ import React from "react" import ReactDOMServer from "react-dom/server.js" import * as lodash from "lodash" import { formatCountryProfile, isCanonicalInternalUrl } from "./formatting.js" -import { - bakeGrapherUrls, - getGrapherExportsByUrl, - GrapherExports, -} from "../baker/GrapherBakingUtils.js" import cheerio from "cheerio" import { BAKED_BASE_URL, @@ -27,8 +22,8 @@ import { import { ADMIN_BASE_URL, BAKED_GRAPHER_URL, - BAKED_GRAPHER_EXPORTS_BASE_URL, RECAPTCHA_SITE_KEY, + GRAPHER_DYNAMIC_THUMBNAIL_URL, } from "../settings/clientSettings.js" import { FeedbackPage } from "../site/FeedbackPage.js" import { @@ -196,32 +191,12 @@ export const renderPreview = async ( export const renderPost = async ( post: FullPost, knex: KnexReadonlyTransaction, - baseUrl: string = BAKED_BASE_URL, - grapherExports?: GrapherExports + baseUrl: string = BAKED_BASE_URL ) => { - if (!grapherExports) { - const $ = cheerio.load(post.content) - - const grapherUrls = $("iframe") - .toArray() - .filter((el) => (el.attribs["src"] || "").match(/\/grapher\//)) - .map((el) => el.attribs["src"].trim()) - - // This can be slow if uncached! - await bakeGrapherUrls(knex, grapherUrls) - - grapherExports = await getGrapherExportsByUrl() - } - // Extract formatting options from post HTML comment (if any) const formattingOptions = extractFormattingOptions(post.content) - const formatted = await formatPost( - post, - formattingOptions, - knex, - grapherExports - ) + const formatted = await formatPost(post, formattingOptions, knex) const pageOverrides = await getPageOverrides(knex, post, formattingOptions) const citationStatus = @@ -474,8 +449,7 @@ export const feedbackPage = () => const getCountryProfilePost = memoize( async ( profileSpec: CountryProfileSpec, - knex: KnexReadonlyTransaction, - grapherExports?: GrapherExports + knex: KnexReadonlyTransaction ): Promise<[FormattedPost, FormattingOptions]> => { // Get formatted content from generic covid country profile page. const genericCountryProfilePost = await getFullPostBySlugFromSnapshot( @@ -489,8 +463,7 @@ const getCountryProfilePost = memoize( const formattedPost = await formatPost( genericCountryProfilePost, profileFormattingOptions, - knex, - grapherExports + knex ) return [formattedPost, profileFormattingOptions] @@ -507,13 +480,11 @@ const getCountryProfileLandingPost = memoize( export const renderCountryProfile = async ( profileSpec: CountryProfileSpec, country: Country, - knex: KnexReadonlyTransaction, - grapherExports?: GrapherExports + knex: KnexReadonlyTransaction ) => { const [formatted, formattingOptions] = await getCountryProfilePost( profileSpec, - knex, - grapherExports + knex ) const formattedCountryProfile = formatCountryProfile(formatted, country) @@ -549,7 +520,6 @@ export const countryProfileCountryPage = async ( const country = getCountryBySlug(countrySlug) if (!country) throw new JsonError(`No such country ${countrySlug}`, 404) - // Voluntarily not dealing with grapherExports on devServer for simplicity return renderCountryProfile(profileSpec, country, knex) } @@ -850,7 +820,7 @@ const getExplorerTitleByUrl = async ( const renderGrapherThumbnailByResolvedChartSlug = ( chartSlug: string ): string | null => { - return `` + return `` } const renderExplorerDefaultThumbnail = (): string => { diff --git a/db/model/Chart.ts b/db/model/Chart.ts index 637f3f8ccaf..436546f9e32 100644 --- a/db/model/Chart.ts +++ b/db/model/Chart.ts @@ -15,7 +15,6 @@ import { GrapherInterface, ChartTypeName, RelatedChart, - DbPlainPostLink, DbPlainChart, parseChartConfig, ChartRedirect, @@ -24,10 +23,7 @@ import { DbEnrichedChartConfig, } from "@ourworldindata/types" import { OpenAI } from "openai" -import { - BAKED_BASE_URL, - OPENAI_API_KEY, -} from "../../settings/serverSettings.js" +import { OPENAI_API_KEY } from "../../settings/serverSettings.js" // XXX hardcoded filtering to public parent tags export const PUBLIC_TAG_PARENT_IDS = [ @@ -608,59 +604,6 @@ export const getRelatedChartsForVariable = async ( ) } -export const getChartEmbedUrlsInPublishedWordpressPosts = async ( - knex: db.KnexReadonlyTransaction -): Promise => { - const chartSlugQueryString: Pick< - DbPlainPostLink, - "target" | "queryString" - >[] = await db.knexRaw( - knex, - `-- sql - SELECT - pl.target, - pl.queryString - FROM - posts_links pl - JOIN posts p ON p.id = pl.sourceId - WHERE - pl.linkType = "grapher" - AND pl.componentType = "src" - AND p.status = "publish" - AND p.type != 'wp_block' - AND p.slug NOT IN ( - -- We want to exclude the slugs of published gdocs, since they override the Wordpress posts - -- published under the same slugs. - SELECT - slug from posts_gdocs pg - WHERE - pg.slug = p.slug - AND pg.content ->> '$.type' <> 'fragment' - AND pg.published = 1 - ) - -- Commenting this out since we currently don't do anything with the baked embeds in gdocs posts - -- see https://github.com/owid/owid-grapher/issues/2992#issuecomment-1934690219 - -- Rename to getChartEmbedUrlsInPublishedPosts if we decide to use this - -- UNION - -- SELECT - -- pgl.target, - -- pgl.queryString - -- FROM - -- posts_gdocs_links pgl - -- JOIN posts_gdocs pg on pg.id = pgl.sourceId - -- WHERE - -- pgl.linkType = "grapher" - -- AND pgl.componentType = "chart" - -- AND pg.content ->> '$.type' <> 'fragment' - -- AND pg.published = 1 - ` - ) - - return chartSlugQueryString.map((row) => { - return `${BAKED_BASE_URL}/${row.target}${row.queryString}` - }) -} - export const getRedirectsByChartId = async ( knex: db.KnexReadonlyTransaction, chartId: number diff --git a/db/model/Gdoc/GdocBase.ts b/db/model/Gdoc/GdocBase.ts index 2e01233d0ad..49f4f93ed55 100644 --- a/db/model/Gdoc/GdocBase.ts +++ b/db/model/Gdoc/GdocBase.ts @@ -32,7 +32,7 @@ import { archieToEnriched } from "./archieToEnriched.js" import { getChartConfigById, mapSlugsToIds } from "../Chart.js" import { BAKED_BASE_URL, - BAKED_GRAPHER_EXPORTS_BASE_URL, + GRAPHER_DYNAMIC_THUMBNAIL_URL, } from "../../../settings/clientSettings.js" import { EXPLORERS_ROUTE_FOLDER } from "../../../explorer/ExplorerConstants.js" import { match, P } from "ts-pattern" @@ -604,7 +604,7 @@ export class GdocBase implements OwidGdocBaseInterface { title: resolvedTitle, tab, resolvedUrl: `${BAKED_GRAPHER_URL}/${resolvedSlug}`, - thumbnail: `${BAKED_GRAPHER_EXPORTS_BASE_URL}/${resolvedSlug}.svg`, + thumbnail: `${GRAPHER_DYNAMIC_THUMBNAIL_URL}/${resolvedSlug}.svg`, tags: [], indicatorId: datapageIndicator?.id, } diff --git a/ops/buildkite/build-code b/ops/buildkite/build-code index 03272ba6821..0c4346cdabb 100755 --- a/ops/buildkite/build-code +++ b/ops/buildkite/build-code @@ -55,13 +55,6 @@ update_env() { else sed -i "s|^BAKED_SITE_DIR=.*$|BAKED_SITE_DIR=/home/owid/live-data/bakedSite|" owid-grapher/.env fi - # redirect assets - if ! grep -q "^BAKED_GRAPHER_EXPORTS_BASE_URL=" owid-grapher/.env; then - echo "BAKED_GRAPHER_EXPORTS_BASE_URL=https://assets.ourworldindata.org/grapher/exports" >> owid-grapher/.env - fi - if ! grep -q "^BAKED_SITE_EXPORTS_BASE_URL=" owid-grapher/.env; then - echo "BAKED_SITE_EXPORTS_BASE_URL=https://assets.ourworldindata.org/exports" >> owid-grapher/.env - fi } diff --git a/settings/clientSettings.ts b/settings/clientSettings.ts index 2fbccb0cb4c..80cfaba2684 100644 --- a/settings/clientSettings.ts +++ b/settings/clientSettings.ts @@ -30,10 +30,6 @@ export const BAKED_BASE_URL: string = export const BAKED_GRAPHER_URL: string = process.env.BAKED_GRAPHER_URL ?? `${BAKED_BASE_URL}/grapher` -export const BAKED_GRAPHER_EXPORTS_BASE_URL: string = - process.env.BAKED_GRAPHER_EXPORTS_BASE_URL ?? `${BAKED_GRAPHER_URL}/exports` -export const BAKED_SITE_EXPORTS_BASE_URL: string = - process.env.BAKED_SITE_EXPORTS_BASE_URL ?? `${BAKED_BASE_URL}/exports` export const GRAPHER_DYNAMIC_THUMBNAIL_URL: string = process.env.GRAPHER_DYNAMIC_THUMBNAIL_URL ?? `${BAKED_GRAPHER_URL}` diff --git a/site/GrapherImage.tsx b/site/GrapherImage.tsx index 8d14c518b5e..a7c9009ffe1 100644 --- a/site/GrapherImage.tsx +++ b/site/GrapherImage.tsx @@ -4,29 +4,48 @@ import { DEFAULT_GRAPHER_HEIGHT, DEFAULT_GRAPHER_WIDTH, } from "@ourworldindata/grapher" -import { BAKED_GRAPHER_EXPORTS_BASE_URL } from "../settings/clientSettings.js" +import { GRAPHER_DYNAMIC_THUMBNAIL_URL } from "../settings/clientSettings.js" +import { Url } from "@ourworldindata/utils" -export default function GrapherImage({ - alt, - slug, - noFormatting, -}: { +export default function GrapherImage(props: { + url: string + alt?: string + noFormatting?: boolean +}): JSX.Element +export default function GrapherImage(props: { slug: string + queryString?: string + alt?: string + noFormatting?: boolean +}): JSX.Element +export default function GrapherImage(props: { + url?: string + slug?: string + queryString?: string alt?: string noFormatting?: boolean }) { + let slug: string = "" + let queryString: string = "" + if (props.url) { + const url = Url.fromURL(props.url) + slug = url.slug! + queryString = url.queryStr + } else { + slug = props.slug! + queryString = props.queryString ?? "" + } + return ( {alt} ) } diff --git a/site/InteractionNotice.tsx b/site/InteractionNotice.tsx index 00c9348ece7..fc22a842372 100644 --- a/site/InteractionNotice.tsx +++ b/site/InteractionNotice.tsx @@ -7,6 +7,7 @@ export const INTERACTIVE_ICON_SVG = ` ` +// shouldProgressiveEmbed is hardcoded to true, so this will only show if JS is disabled export default function InteractionNotice() { return (
diff --git a/site/blocks/RelatedCharts.jsdom.test.tsx b/site/blocks/RelatedCharts.jsdom.test.tsx index 6e49166210e..54658e9e588 100755 --- a/site/blocks/RelatedCharts.jsdom.test.tsx +++ b/site/blocks/RelatedCharts.jsdom.test.tsx @@ -7,7 +7,7 @@ import Enzyme from "enzyme" import Adapter from "@wojtekmaj/enzyme-adapter-react-17" import { BAKED_BASE_URL, - BAKED_GRAPHER_EXPORTS_BASE_URL, + GRAPHER_DYNAMIC_THUMBNAIL_URL, } from "../../settings/clientSettings.js" import { KeyChartLevel } from "@ourworldindata/utils" Enzyme.configure({ adapter: new Adapter() }) @@ -37,7 +37,7 @@ it("renders active chart links and loads respective chart on click", () => { .find("li") .first() .find( - `img[src="${BAKED_GRAPHER_EXPORTS_BASE_URL}/${charts[1].slug}.svg"]` + `img[src="${GRAPHER_DYNAMIC_THUMBNAIL_URL}/${charts[1].slug}.png"]` ) ).toHaveLength(1) diff --git a/site/css/content.scss b/site/css/content.scss index cc78dc62e44..816935f5b64 100644 --- a/site/css/content.scss +++ b/site/css/content.scss @@ -87,6 +87,12 @@ figure[data-explorer-src] { } } +// Doesn't make sense to show the notice if JavaScript is disabled +// As the grapher/data page will also be disabled +.js-disabled .interactionNotice { + display: none; +} + /******************************************************************************* * Tables */ diff --git a/site/gdocs/components/Chart.tsx b/site/gdocs/components/Chart.tsx index 38381b6825a..b678a28f031 100644 --- a/site/gdocs/components/Chart.tsx +++ b/site/gdocs/components/Chart.tsx @@ -41,7 +41,6 @@ export default function Chart({ const url = Url.fromURL(d.url) const resolvedUrl = linkedChart.resolvedUrl - const resolvedSlug = Url.fromURL(resolvedUrl).slug const isExplorer = url.isExplorer const hasControls = url.queryParams.hideControls !== "true" const isExplorerWithControls = isExplorer && hasControls @@ -116,12 +115,10 @@ export default function Chart({ {isExplorer ? (
) : ( - resolvedSlug && ( - - - - - ) + + + + )} {d.caption ? ( diff --git a/site/gdocs/components/ProminentLink.tsx b/site/gdocs/components/ProminentLink.tsx index d232de1ddc8..2e419bd8f58 100644 --- a/site/gdocs/components/ProminentLink.tsx +++ b/site/gdocs/components/ProminentLink.tsx @@ -8,7 +8,7 @@ import Image from "./Image.js" import { useLinkedChart, useLinkedDocument } from "../utils.js" import { DocumentContext } from "../OwidGdoc.js" import { BlockErrorFallback } from "./BlockErrorBoundary.js" -import { BAKED_GRAPHER_EXPORTS_BASE_URL } from "../../../settings/clientSettings.js" +import { GRAPHER_DYNAMIC_THUMBNAIL_URL } from "../../../settings/clientSettings.js" import { ARCHVED_THUMBNAIL_FILENAME, DEFAULT_THUMBNAIL_FILENAME, @@ -16,7 +16,7 @@ import { const Thumbnail = ({ thumbnail }: { thumbnail: string }) => { if ( - thumbnail.startsWith(BAKED_GRAPHER_EXPORTS_BASE_URL) || + thumbnail.startsWith(GRAPHER_DYNAMIC_THUMBNAIL_URL) || thumbnail.endsWith(ARCHVED_THUMBNAIL_FILENAME) || thumbnail.endsWith(DEFAULT_THUMBNAIL_FILENAME) ) { diff --git a/site/search/ChartHit.tsx b/site/search/ChartHit.tsx index a9b97fadeae..4eab62ca6db 100644 --- a/site/search/ChartHit.tsx +++ b/site/search/ChartHit.tsx @@ -5,7 +5,6 @@ import { IChartHit, SearchIndexName } from "./searchTypes.js" import { getEntityQueryStr, pickEntitiesForChartHit } from "./SearchUtils.js" import { HitAttributeHighlightResult } from "instantsearch.js" import { - BAKED_GRAPHER_EXPORTS_BASE_URL, BAKED_GRAPHER_URL, GRAPHER_DYNAMIC_THUMBNAIL_URL, } from "../../settings/clientSettings.js" @@ -52,9 +51,7 @@ export function ChartHit({ ] ) const queryStr = useMemo(() => getEntityQueryStr(entities), [entities]) - const previewUrl = queryStr - ? `${GRAPHER_DYNAMIC_THUMBNAIL_URL}/${hit.slug}.svg${queryStr}` - : `${BAKED_GRAPHER_EXPORTS_BASE_URL}/${hit.slug}.svg` + const previewUrl = `${GRAPHER_DYNAMIC_THUMBNAIL_URL}/${hit.slug}.png${queryStr}` useEffect(() => { setImgLoaded(false)