Skip to content

Commit

Permalink
Merge pull request #4342 from owid/persist-alt-text
Browse files Browse the repository at this point in the history
✨ persist alt text between image revisions
  • Loading branch information
ikesau authored Dec 20, 2024
2 parents 286627f + cb19d93 commit cfce1bb
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 25 deletions.
80 changes: 55 additions & 25 deletions adminSiteClient/ImagesIndexPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
Popover,
Table,
Upload,
notification,
} from "antd"
import { AdminLayout } from "./AdminLayout.js"
import { AdminAppContext } from "./AdminAppContext.js"
Expand All @@ -31,6 +32,7 @@ import { RcFile } from "antd/es/upload/interface.js"
import { CLOUDFLARE_IMAGES_URL } from "../settings/clientSettings.js"
import { Dictionary, keyBy } from "lodash"
import cx from "classnames"
import { NotificationInstance } from "antd/es/notification/interface.js"

type ImageMap = Record<string, DbEnrichedImageWithUserId>

Expand Down Expand Up @@ -237,10 +239,12 @@ function createColumns({
api,
users,
usage,
notificationApi,
}: {
api: ImageEditorApi
users: UserMap
usage: Dictionary<UsageInfo[]>
notificationApi: NotificationInstance
}): ColumnsType<DbEnrichedImageWithUserId> {
return [
{
Expand Down Expand Up @@ -376,7 +380,11 @@ function createColumns({
return (
<Flex vertical>
<UsageViewer usage={usage && usage[image.id]} />
<PutImageButton putImage={api.putImage} id={image.id} />
<PutImageButton
putImage={api.putImage}
notificationApi={notificationApi}
id={image.id}
/>
<Popconfirm
title="Are you sure?"
description="This will delete the image being used in production."
Expand Down Expand Up @@ -459,31 +467,48 @@ function PostImageButton({
function PutImageButton({
putImage,
id,
notificationApi,
}: {
putImage: ImageEditorApi["putImage"]
id: number
notificationApi: NotificationInstance
}) {
async function uploadImage({ file }: { file: File }) {
const result = await fileToBase64(file)
if (result) {
putImage(id, result)
await putImage(id, result)
notificationApi.info({
message: "Image replaced!",
description:
"Make sure you update the alt text if your revision has substantive changes",
placement: "bottomRight",
})
}
}
return (
<Upload
accept="image/*"
showUploadList={false}
customRequest={uploadImage}
>
<Button className="ImageIndexPage__update-image-button" type="text">
Upload new version
</Button>
</Upload>
<>
<Upload
accept="image/*"
showUploadList={false}
customRequest={uploadImage}
>
<Button
className="ImageIndexPage__update-image-button"
type="text"
>
Upload new version
</Button>
</Upload>
</>
)
}

const NotificationContext = React.createContext(null)

export function ImageIndexPage() {
const { admin } = useContext(AdminAppContext)
const [notificationApi, notificationContextHolder] =
notification.useNotification()
const [images, setImages] = useState<ImageMap>({})
const [users, setUsers] = useState<UserMap>({})
const [usage, setUsage] = useState<Dictionary<UsageInfo[]>>({})
Expand Down Expand Up @@ -605,8 +630,8 @@ export function ImageIndexPage() {
)

const columns = useMemo(
() => createColumns({ api, users, usage }),
[api, users, usage]
() => createColumns({ api, users, usage, notificationApi }),
[api, users, usage, notificationApi]
)

useEffect(() => {
Expand All @@ -617,18 +642,23 @@ export function ImageIndexPage() {

return (
<AdminLayout title="Images">
<main className="ImageIndexPage">
<Flex justify="space-between">
<Input
placeholder="Search by filename"
value={filenameSearchValue}
onChange={(e) => setFilenameSearchValue(e.target.value)}
style={{ width: 500, marginBottom: 20 }}
/>
<PostImageButton postImage={api.postImage} />
</Flex>
<Table columns={columns} dataSource={filteredImages} />
</main>
<NotificationContext.Provider value={null}>
{notificationContextHolder}
<main className="ImageIndexPage">
<Flex justify="space-between">
<Input
placeholder="Search by filename"
value={filenameSearchValue}
onChange={(e) =>
setFilenameSearchValue(e.target.value)
}
style={{ width: 500, marginBottom: 20 }}
/>
<PostImageButton postImage={api.postImage} />
</Flex>
<Table columns={columns} dataSource={filteredImages} />
</main>
</NotificationContext.Provider>
</AdminLayout>
)
}
2 changes: 2 additions & 0 deletions adminSiteServer/apiRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3241,6 +3241,7 @@ putRouteWithRWTransaction(apiRouter, "/images/:id", async (req, res, trx) => {

const originalCloudflareId = image.cloudflareId
const originalFilename = image.filename
const originalAltText = image.defaultAlt

if (!originalCloudflareId) {
throw new JsonError(
Expand All @@ -3262,6 +3263,7 @@ putRouteWithRWTransaction(apiRouter, "/images/:id", async (req, res, trx) => {
cloudflareId: newCloudflareId,
updatedAt: new Date().getTime(),
userId: res.locals.user.id,
defaultAlt: originalAltText,
hash,
version: image.version + 1,
})
Expand Down

0 comments on commit cfce1bb

Please sign in to comment.