@@ -29,6 +29,7 @@ import {
2929import { Input } from "../ui/input" ;
3030import { Sheet , SheetContent } from "../ui/sheet" ;
3131import { Textarea } from "../ui/textarea" ;
32+ import { actionPromisify } from "@/lib/utils" ;
3233
3334interface Props {
3435 article : Article ;
@@ -43,9 +44,10 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
4344 const updateMyArticleMutation = useMutation ( {
4445 mutationFn : (
4546 input : z . infer < typeof ArticleRepositoryInput . updateMyArticleInput >
46- ) => {
47- return articleActions . updateMyArticle ( input ) ;
48- } ,
47+ ) =>
48+ actionPromisify ( articleActions . updateMyArticle ( input ) , {
49+ enableToast : true ,
50+ } ) ,
4951 onSuccess : ( ) => {
5052 router . refresh ( ) ;
5153 } ,
@@ -79,6 +81,7 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
7981 title : article ?. metadata ?. seo ?. title ?? "" ,
8082 description : article ?. metadata ?. seo ?. description ?? "" ,
8183 keywords : article ?. metadata ?. seo ?. keywords ?? [ ] ,
84+ canonical_url : article ?. metadata ?. seo ?. canonical_url ?? "" ,
8285 } ,
8386 } ,
8487 } ,
@@ -98,6 +101,7 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
98101 title : payload . metadata ?. seo ?. title ?? "" ,
99102 description : payload . metadata ?. seo ?. description ?? "" ,
100103 keywords : payload . metadata ?. seo ?. keywords ?? [ ] ,
104+ canonical_url : payload . metadata ?. seo ?. canonical_url ?? "" ,
101105 } ,
102106 } ,
103107 } ) ;
@@ -112,10 +116,10 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
112116 onSubmit = { form . handleSubmit ( handleOnSubmit ) }
113117 className = "flex flex-col gap-2"
114118 >
115- { JSON . stringify ( {
119+ { /* { JSON.stringify({
116120 errors: form.formState.errors,
117121 values: form.watch("tag_ids"),
118- } ) }
122+ }) } */ }
119123 { /* <pre>{JSON.stringify(article, null, 2)}</pre> */ }
120124 < div className = "flex flex-col gap-6" >
121125 < FormField
@@ -247,11 +251,9 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
247251 < FormItem >
248252 < FormLabel > { _t ( "SEO Title" ) } </ FormLabel >
249253 < FormDescription className = "text-xs" >
250- The "SEO title" will be shown in place of your
251- Title on search engine results pages, such as a Google
252- search. SEO titles between 40 and 50 characters with
253- commonly searched words have the best
254- click-through-rates.
254+ { _t (
255+ "Override your article title for Google search results and social media cards. Keep it 40-50 characters for best performance."
256+ ) }
255257 </ FormDescription >
256258 < FormControl >
257259 < Input { ...field } placeholder = { form . watch ( "title" ) } />
@@ -261,7 +263,7 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
261263 ) }
262264 />
263265
264- < FormField
266+ { /* <FormField
265267 control={form.control}
266268 name="metadata.seo.keywords"
267269 render={({ field }) => (
@@ -291,7 +293,7 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
291293 <FormMessage />
292294 </FormItem>
293295 )}
294- />
296+ /> */ }
295297
296298 < FormField
297299 control = { form . control }
@@ -300,10 +302,9 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
300302 < FormItem >
301303 < FormLabel > { _t ( "SEO Description" ) } </ FormLabel >
302304 < FormDescription className = "text-xs" >
303- The "SEO description" will be used in place of
304- your Subtitle on search engine results pages. Good SEO
305- descriptions utilize keywords, summarize the article and
306- are between 140-156 characters long.
305+ Override your article description for Google search
306+ results and social media cards. Keep it 140-156
307+ characters and include relevant keywords.
307308 </ FormDescription >
308309 < FormControl >
309310 < Textarea { ...field } />
@@ -312,6 +313,29 @@ const ArticleEditorDrawer: React.FC<Props> = ({ article, open, onClose }) => {
312313 </ FormItem >
313314 ) }
314315 />
316+
317+ < FormField
318+ control = { form . control }
319+ name = "metadata.seo.canonical_url"
320+ render = { ( { field } ) => (
321+ < FormItem >
322+ < FormLabel > { _t ( "Canonical URL" ) } </ FormLabel >
323+ < FormDescription className = "text-xs" >
324+ { _t (
325+ "Specify the preferred URL for this content to prevent duplicate content issues. Leave empty to use the default URL."
326+ ) }
327+ </ FormDescription >
328+ < FormControl >
329+ < Input
330+ { ...field }
331+ value = { field . value ?? "" }
332+ placeholder = "https://example.com/original-post"
333+ />
334+ </ FormControl >
335+ < FormMessage />
336+ </ FormItem >
337+ ) }
338+ />
315339 </ div >
316340
317341 < Button
0 commit comments