Skip to content

Commit fe59476

Browse files
Ahtesham QuraishAhtesham Quraish
authored andcommitted
another review of chatgpt
1 parent 5ecbb03 commit fe59476

8 files changed

Lines changed: 66 additions & 32 deletions

File tree

frontends/main/src/app-pages/WebsiteContent/WebsiteContentDetail.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ const WebsiteContentDetail = ({
4242
return notFound()
4343
}
4444

45-
const Editor = article.content_type === "article" ? ArticleEditor : NewsEditor
46-
4745
return (
4846
<PageContainer>
4947
<LearningResourceProvider resourceIds={learningResourceIds}>
50-
<Editor article={article} readOnly />
48+
{article.content_type === "article" ? (
49+
<ArticleEditor article={article} readOnly />
50+
) : (
51+
<NewsEditor newsItem={article} readOnly />
52+
)}
5153
</LearningResourceProvider>
5254
</PageContainer>
5355
)

frontends/main/src/app-pages/WebsiteContent/WebsiteContentEditPage.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,17 @@ const PUBLISHED_VIEW_URL: Record<string, (slug: string) => string> = {
3535
const EDITORS: Record<
3636
string,
3737
React.ComponentType<{
38-
onSave?: (article: WebsiteContent) => void
38+
onSave?: (savedContent: WebsiteContent) => void
3939
readOnly?: boolean
40-
article?: WebsiteContent
40+
contentItem?: WebsiteContent
4141
}>
4242
> = {
43-
article: ArticleEditor,
44-
news: NewsEditor,
43+
article: ({ contentItem, ...props }) => (
44+
<ArticleEditor article={contentItem} {...props} />
45+
),
46+
news: ({ contentItem, ...props }) => (
47+
<NewsEditor newsItem={contentItem} {...props} />
48+
),
4549
}
4650

4751
interface WebsiteContentEditPageProps {
@@ -78,7 +82,7 @@ const WebsiteContentEditPage = ({
7882
<RestrictedRoute requires={Permission.ArticleEditor}>
7983
<PageContainer>
8084
<Editor
81-
article={article}
85+
contentItem={article}
8286
onSave={(saved) => {
8387
if (saved.is_published) {
8488
invariant(saved.slug, "Published content must have a slug")

frontends/main/src/app-pages/WebsiteContent/WebsiteContentNewPage.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ const PUBLISHED_VIEW_URL: Record<string, (slug: string) => string> = {
2626
const EDITORS: Record<
2727
string,
2828
React.ComponentType<{
29-
onSave?: (article: WebsiteContent) => void
29+
onSave?: (savedContent: WebsiteContent) => void
3030
readOnly?: boolean
31-
article?: WebsiteContent
31+
contentItem?: WebsiteContent
3232
}>
3333
> = {
34-
article: ArticleEditor,
35-
news: NewsEditor,
34+
article: ({ contentItem, ...props }) => (
35+
<ArticleEditor article={contentItem} {...props} />
36+
),
37+
news: ({ contentItem: _contentItem, ...props }) => <NewsEditor {...props} />,
3638
}
3739

3840
interface WebsiteContentNewPageProps {

frontends/main/src/page-components/TiptapEditor/NewsViewer.test.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ describe("NewsViewer", () => {
6464
},
6565
})
6666

67-
renderWithProviders(<NewsEditor article={newsItem} readOnly />)
67+
renderWithProviders(<NewsEditor newsItem={newsItem} readOnly />)
6868

6969
await screen.findByRole("heading", { name: "Test Title", level: 1 })
7070
await screen.findByText("Test subheading")
@@ -83,7 +83,7 @@ describe("NewsViewer", () => {
8383
author_name: authorName,
8484
})
8585

86-
renderWithProviders(<NewsEditor article={newsItem} readOnly />)
86+
renderWithProviders(<NewsEditor newsItem={newsItem} readOnly />)
8787

8888
await screen.findByText(`By ${authorName}`)
8989
})
@@ -202,7 +202,7 @@ describe("NewsViewer", () => {
202202
},
203203
})
204204

205-
renderWithProviders(<NewsEditor article={newsItem} readOnly />)
205+
renderWithProviders(<NewsEditor newsItem={newsItem} readOnly />)
206206

207207
await screen.findByRole("heading", { level: 1, name: "Heading Level 1" })
208208
await screen.findByRole("heading", { level: 2, name: "Heading Level 2" })
@@ -294,7 +294,7 @@ describe("NewsViewer", () => {
294294
},
295295
})
296296

297-
renderWithProviders(<NewsEditor article={newsItem} readOnly />)
297+
renderWithProviders(<NewsEditor newsItem={newsItem} readOnly />)
298298

299299
const firstUnordered = await screen.findByText("First unordered item")
300300
const secondUnordered = await screen.findByText("Second unordered item")
@@ -398,7 +398,7 @@ describe("NewsViewer", () => {
398398
},
399399
})
400400

401-
renderWithProviders(<NewsEditor article={newsItem} readOnly />)
401+
renderWithProviders(<NewsEditor newsItem={newsItem} readOnly />)
402402

403403
const boldText = await screen.findByText("bold text")
404404
expect(boldText).toBeInTheDocument()
@@ -486,7 +486,7 @@ describe("NewsViewer", () => {
486486
},
487487
})
488488

489-
renderWithProviders(<NewsEditor article={newsItem} readOnly />)
489+
renderWithProviders(<NewsEditor newsItem={newsItem} readOnly />)
490490

491491
const link = await screen.findByRole("link", { name: "example.com" })
492492
expect(link).toBeInTheDocument()
@@ -501,7 +501,7 @@ describe("NewsViewer", () => {
501501
})
502502
setMockResponse.get(urls.userMe.get(), user)
503503
const newsItem = factories.websiteContent.websiteContent()
504-
renderWithProviders(<NewsEditor article={newsItem} readOnly />)
504+
renderWithProviders(<NewsEditor newsItem={newsItem} readOnly />)
505505

506506
await screen.findByRole("link", { name: "Edit" })
507507
})

frontends/main/src/page-components/TiptapEditor/contentTypes/article/ArticleEditor.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ButtonLink } from "@mitodl/smoot-design"
66
import {
77
useWebsiteContentCreate,
88
useWebsiteContentPartialUpdate,
9+
useMediaUpload,
910
} from "api/hooks/website_content"
1011
import { Spacer } from "../../vendor/components/tiptap-ui-primitive/spacer"
1112
import { WebsiteContentEditor } from "../../core/WebsiteContentEditor"
@@ -50,6 +51,7 @@ const ArticleEditor = ({ onSave, readOnly, article }: ArticleEditorProps) => {
5051
// Swap these two lines when a dedicated UserArticle API exists.
5152
const createMutation = useWebsiteContentCreate()
5253
const updateMutation = useWebsiteContentPartialUpdate()
54+
const uploadImage = useMediaUpload()
5355

5456
const editUrl = article
5557
? `/website_content/article/${article.is_published ? article.slug : article.id}/edit`
@@ -78,6 +80,7 @@ const ArticleEditor = ({ onSave, readOnly, article }: ArticleEditorProps) => {
7880
toolbarSlot={toolbarSlot}
7981
extractExtraFields={extractArticleExtraFields}
8082
saveMutations={{ create: createMutation, update: updateMutation }}
83+
uploadImage={uploadImage}
8184
onSave={onSave}
8285
readOnly={readOnly}
8386
article={article}

frontends/main/src/page-components/TiptapEditor/contentTypes/news/NewsEditor.happydom.test.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ describe("NewsEditor - Content Editing and Saving", () => {
4444
})
4545
setMockResponse.get(urls.websiteContent.details(articleId), newsItem)
4646

47-
renderWithProviders(<NewsEditor article={newsItem} onSave={mockOnSave} />, {
48-
user,
49-
})
47+
renderWithProviders(
48+
<NewsEditor newsItem={newsItem} onSave={mockOnSave} />,
49+
{
50+
user,
51+
},
52+
)
5053

5154
await screen.findByTestId("editor")
5255
return newsItem
@@ -646,7 +649,7 @@ describe("NewsEditor - Document Rendering", () => {
646649
setMockResponse.get(urls.websiteContent.details(articleId), newsItem)
647650

648651
renderWithProviders(
649-
<NewsEditor article={newsItem} onSave={mockOnSave} readOnly />,
652+
<NewsEditor newsItem={newsItem} onSave={mockOnSave} readOnly />,
650653
{ user },
651654
)
652655

frontends/main/src/page-components/TiptapEditor/contentTypes/news/NewsEditor.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ButtonLink } from "@mitodl/smoot-design"
66
import {
77
useWebsiteContentCreate,
88
useWebsiteContentPartialUpdate,
9+
useMediaUpload,
910
} from "api/hooks/website_content"
1011
import { Spacer } from "../../vendor/components/tiptap-ui-primitive/spacer"
1112
import { WebsiteContentEditor } from "../../core/WebsiteContentEditor"
@@ -23,24 +24,25 @@ const extractNewsExtraFields = (content: {
2324
}
2425

2526
interface NewsEditorProps {
26-
onSave?: (article: WebsiteContent) => void
27+
onSave?: (savedContent: WebsiteContent) => void
2728
readOnly?: boolean
28-
article?: WebsiteContent
29+
newsItem?: WebsiteContent
2930
}
3031

3132
/**
3233
* Editor shell configured for the news content type (served under /news).
3334
* Owns its own save mutations (websiteContent API) and passes them to
3435
* WebsiteContentEditor — keeping the generic shell decoupled from any specific API.
3536
*/
36-
const NewsEditor = ({ onSave, readOnly, article }: NewsEditorProps) => {
37-
// News content type uses the websiteContent (articles) API.
37+
const NewsEditor = ({ onSave, readOnly, newsItem }: NewsEditorProps) => {
38+
// News content type uses the websiteContent API.
3839
// A different content type would call different hooks here.
3940
const createMutation = useWebsiteContentCreate()
4041
const updateMutation = useWebsiteContentPartialUpdate()
42+
const uploadImage = useMediaUpload()
4143

42-
const editUrl = article
43-
? `/website_content/news/${article.is_published ? article.slug : article.id}/edit`
44+
const editUrl = newsItem
45+
? `/website_content/news/${newsItem.is_published ? newsItem.slug : newsItem.id}/edit`
4446
: "/website_content/news/new"
4547

4648
const toolbarSlot = readOnly ? (
@@ -66,9 +68,10 @@ const NewsEditor = ({ onSave, readOnly, article }: NewsEditorProps) => {
6668
toolbarSlot={toolbarSlot}
6769
extractExtraFields={extractNewsExtraFields}
6870
saveMutations={{ create: createMutation, update: updateMutation }}
71+
uploadImage={uploadImage}
6972
onSave={onSave}
7073
readOnly={readOnly}
71-
article={article}
74+
article={newsItem}
7275
/>
7376
)
7477
}

frontends/main/src/page-components/TiptapEditor/core/WebsiteContentEditor.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
} from "ol-components"
1515
import { Alert, Button } from "@mitodl/smoot-design"
1616
import { useUserHasPermission, Permission } from "api/hooks/user"
17-
import { useMediaUpload } from "api/hooks/website_content"
1817
import dynamic from "next/dynamic"
1918

2019
import { Toolbar } from "../vendor/components/tiptap-ui-primitive/toolbar"
@@ -78,6 +77,18 @@ export type UploadHandler = (
7877
abortSignal?: AbortSignal,
7978
) => Promise<string>
8079

80+
/**
81+
* The minimal interface expected from a media upload mutation.
82+
* Matches the shape returned by `useMediaUpload` from `api/hooks/website_content`,
83+
* but callers may supply any compatible implementation.
84+
*/
85+
export interface MediaUpload {
86+
mutateAsync: (data: { file: File }) => Promise<{ url?: string }>
87+
setNextProgressCallback: (
88+
callback: ((percent: number) => void) | undefined,
89+
) => void
90+
}
91+
8192
/**
8293
* The data shape sent to the create/update API.
8394
* `[key: string]: unknown` allows per-type extra fields (e.g. author_name).
@@ -158,6 +169,12 @@ export interface WebsiteContentEditorProps {
158169
* WebsiteContentEditor stays decoupled from any specific API endpoint.
159170
*/
160171
saveMutations: SaveMutations
172+
/**
173+
* Upload mutation provided by the content-type wrapper.
174+
* Pass the return value of `useMediaUpload()` (or a compatible implementation)
175+
* so WebsiteContentEditor stays decoupled from any specific upload endpoint.
176+
*/
177+
uploadImage: MediaUpload
161178
onSave?: (article: WebsiteContent) => void
162179
readOnly?: boolean
163180
article?: WebsiteContent
@@ -173,6 +190,7 @@ const WebsiteContentEditor = ({
173190
className,
174191
extractExtraFields,
175192
saveMutations,
193+
uploadImage,
176194
onSave,
177195
readOnly,
178196
article,
@@ -193,7 +211,6 @@ const WebsiteContentEditor = ({
193211
const isPending = createMutation.isPending || updateMutation.isPending
194212
const saveError = createMutation.error || updateMutation.error
195213

196-
const uploadImage = useMediaUpload()
197214
// Keep a ref so the stable uploadHandler callback always calls the latest mutation.
198215
const uploadImageRef = useRef(uploadImage)
199216
uploadImageRef.current = uploadImage

0 commit comments

Comments
 (0)