From 53c57dba0e63cd494ac3cdd95c2709eb11f49b27 Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Mon, 28 Aug 2023 22:47:17 +0700 Subject: [PATCH 1/5] quick fix hash --- src/pages/[...hash].tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/[...hash].tsx b/src/pages/[...hash].tsx index 833862c1..24cd900b 100644 --- a/src/pages/[...hash].tsx +++ b/src/pages/[...hash].tsx @@ -28,7 +28,7 @@ const ForwardURL = ({ history, hash, ip, error, redirect }: Props) => { const loading = forwardUrl.isLoading && !forwardUrl.isError; const url = history?.url; const ogTitle = history?.ogTitle || t('ogTitle', { hash }); - const ogDescription = history?.ogTitle || t('ogDescription'); + const ogDescription = history?.ogDescription || t('ogDescription'); useEffect(() => { if (!Window()) { From fec7758bc23d1c6c41566de80eabf603ed7b354d Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Tue, 29 Aug 2023 15:21:47 +0700 Subject: [PATCH 2/5] feature custom og --- .env.example | 2 +- .env.production.gpg | Bin 574 -> 653 bytes .env.test.gpg | Bin 558 -> 557 bytes package.json | 2 + src/api/requests.ts | 3 + src/components/atoms/Accordion.tsx | 2 +- src/components/atoms/UploadImage.tsx | 56 ++++++++++++++++ .../gadgets/AdvancedSettingUrlForm.tsx | 54 ++++++++++----- src/components/gadgets/FacebookPreview.tsx | 28 ++++---- src/components/gadgets/TwitterPreview.tsx | 28 ++++---- src/components/layouts/Header.tsx | 2 +- .../sections/URLAdvancedSetting.tsx | 4 +- src/components/sections/URLSharePreview.tsx | 2 +- src/controllers/cld.ts | 18 +++++ src/controllers/forward.ts | 2 + src/controllers/index.tsx | 1 + src/controllers/shorten/update.ts | 3 + src/pages/[...hash].tsx | 2 + src/pages/api/cld.ts | 3 + src/types/constants.ts | 2 +- src/utils/validateMiddleware.ts | 5 ++ yarn.lock | 62 +++++++++++++++++- 22 files changed, 232 insertions(+), 49 deletions(-) create mode 100644 src/components/atoms/UploadImage.tsx create mode 100644 src/controllers/cld.ts create mode 100644 src/pages/api/cld.ts diff --git a/.env.example b/.env.example index 06d71def..3db9c32f 100644 --- a/.env.example +++ b/.env.example @@ -2,4 +2,4 @@ DATABASE_URL="postgres://" REDIS_AUTH="xxxxxx" # NEXT_PUBLIC_MIX_PANEL_TOKEN="xxxxxx" NEXT_PUBLIC_PLATFORM_AUTH="xxxxxx" -NEXT_PUBLIC_SERVER_AUTH="xxxxxx" +SERVER_AUTH="xxxxxx" diff --git a/.env.production.gpg b/.env.production.gpg index e7edb2aa801a27ebb36def03e5120e47bf7cb95a..fa2800863f62f2fb364f11e0014f9822611fabfc 100644 GIT binary patch literal 653 zcmV;80&@L~4Fm}T0t2x@A|>!a9sknl0dwaOniHn3>}lypkbiUzyehuYGJPO%8T-)& z?G_FbW4gEY$mOUO>qGDp`mGh7W5MO>1b? zYr0_PeU&{iKlMsz3L?oaPO@5JIO+4q z&`gF3b|~Byj1?owgfvC&r)Xk7QZ8Wl5k8DYtKj}S2**b{G`V+T*4yt_0q--$eCSC# zfcELSeo94ho;0IyOxdhi67Nr}vr;mq-GT88)vKD*&UUEWTO-FWGP&wTA&{tBBgY{& zSZH?8YnWx1O`i1#CQ)kF`pY#I4an=NQx=O6%_h*u9liY{iW8>0o23o5Qg1-ssoF2S z6vBJ!_Q$E7XVNPzZVwY-GBNXjzN<3o*5jG4jnI0>KJvm0@31yW!dy0LYRo)1zsl}3 za*!_q)z&x%l19Lr z7P~@*_me>Kkk4LP!z0hs!E!?}PHnG!K$RySR|H~!gaB)>;w4%jfMx+F9?VUqC1_6b n3Ww=^$ literal 574 zcmV-E0>S-^4Fm}T0v4pl?=|9X;cW1 zo~QQnh4H=0+c{M3^Lh}h7aKaH4Tf9cU{&E0tBxb8IUjN@kC(6D+xx>4x(y4~yQ@3o zTT=S@*#0%Tt{F_DlFARoH5$&7Q51hy;lN%ql_#hjhv9o5$1Ti{f@Eu4o_ys{1%Mv0 ztlWk{DPP5Sxng!Go`Qf|4+>8HQ@m^D)|6TmNW*P6K3||ZJ&M(p|Nlp}vnBH0j~Ng& zvf8}?GF4nJ@9j?daZ8`N)+L|JLxW#wl6rAquuiRx^4AizrRi+XZn!VerJSCF6NXph zPCe-AK3>p%9*4X4v_pUojHg;ooc6>JC}c@f5PvmfvujV_Vt|U z(kyj&)$J;O!(PN9v&89wul!BgX+4btidl~gi*`-63%h7UuBbJ;y|Cj$mBmCOuqNK$ zTgL2$((Np-0h}RZZ*OqxEQxA9J9XdUc7{z|#pyv3NJLeuBT}9pC7wG9!c4Bb_|&%Jm`{xba|g1igTx~C{_8wg)+)bt1vQ&7eK79~r9P#NQ3BqnEmu<@w3mQBG+Q&)V zD8+MZi0$@xyX+BI!801$V^lEkdwjnl)XuV6u6A~o9@*rLYp@+Qd2`M8d$Mkosv`h6 zW)Xoy){n2w-F2w8O*fTF7NrLng&RP_0B^B7t%KF!T(CYGRj8D)>Ish#JwPr43CN!K z6!e)S6hi?23h@hOs~g0Z!c46Yp{IVvr?5_h5Qn+7ira+)n{G)n$$;BD#S`;_Eu2wx zD7LDD;uhn#k{aU`aGg~Js)*j=&tC9E|F28$q-%3AJRIvKeGoCs3h0IF*zSyhMe+v8 zc~$kv*|s<|aLbo#>_{T#dCsPC=F&-cwLQWFzB^e8(2B z2x6jQY(Yycy;{ugmXLw!E$A<|Vp%u~_`^!^*FlX`0^9B-O?y} vJ=?{#uXkU=i$XDi{h$Xk8?HOmzbq^J(1LGlKAtAa$xCu&qT@qFj{8Y6c8e0^ literal 558 zcmV+}0@3}94Fm}T0*)LeO5f#Z_y5xA0o)kFT^iBSuIBWiz#psNrilDoRV`2b$Df2s zwG}1inf^xqY2Dft(fp-zflp!xS}AiA+w7WpF4*R9RT0>Qa@~6U7N~lj;34>CdoFEhzwS|23wqC;n_Y zPA>W;d&fiy)3zcICkPMvs;wij7sykRoIoWui@nsS_*yIv?f%Y9HPL&OK_cW)n{SIQ zwn5L-@5h9PgQ zokkr<7aSfeW~)>FYZwW`xPnWs8=>pi!gTPr9`TBfE*s-?ZHwd?{;~`x{T { const rs = await API.put(`/api/shorten/update`, { @@ -29,6 +31,7 @@ export const updateShortenUrlRequest = async ({ hash, ogTitle, ogDescription, + ogImgSrc, }); const data = rs.data; return data as ShortenUrl; diff --git a/src/components/atoms/Accordion.tsx b/src/components/atoms/Accordion.tsx index 708f0d4e..621b5a1e 100644 --- a/src/components/atoms/Accordion.tsx +++ b/src/components/atoms/Accordion.tsx @@ -37,7 +37,7 @@ export const Accordion = ({ children, title }: Props) => { className="!visible hidden border-0" data-te-collapse-item aria-labelledby={`heading${id}`}> -
{children}
+ {children} diff --git a/src/components/atoms/UploadImage.tsx b/src/components/atoms/UploadImage.tsx new file mode 100644 index 00000000..0d5ff88a --- /dev/null +++ b/src/components/atoms/UploadImage.tsx @@ -0,0 +1,56 @@ +import { UploadCloud } from '@styled-icons/feather'; +import { CldUploadWidget } from 'next-cloudinary'; +import { MouseEventHandler, useState } from 'react'; +import { isProduction } from 'types/constants'; + +export const UploadImage = ({ onSuccess }: { onSuccess: (url: string) => void }) => { + const [resource, setResource] = useState(); + + return ( +
+ { + console.log('result', result); + setResource(result?.info); + const url = (result?.info as any)?.secure_url; + if (url) { + onSuccess(url); + } + widget.close(); + }}> + {({ open }) => { + const handleOnClick: MouseEventHandler = (e) => { + e.preventDefault(); + open(); + }; + return ( + + ); + }} + + {!isProduction && ( + + URL (debug): {resource?.secure_url.slice(-20) || '--'} + + )} +
+ ); +}; diff --git a/src/components/gadgets/AdvancedSettingUrlForm.tsx b/src/components/gadgets/AdvancedSettingUrlForm.tsx index dcc11727..c5f28529 100644 --- a/src/components/gadgets/AdvancedSettingUrlForm.tsx +++ b/src/components/gadgets/AdvancedSettingUrlForm.tsx @@ -5,6 +5,7 @@ import { useBearStore } from 'bear'; import { Button } from 'components/atoms/Button'; import { Input, Textarea } from 'components/atoms/Input'; import mixpanel from 'mixpanel-browser'; +import dynamic from 'next/dynamic'; import { useCallback, useEffect } from 'react'; import { SubmitHandler, useForm } from 'react-hook-form'; import { toast } from 'react-hot-toast'; @@ -19,6 +20,8 @@ import { QueryKey } from 'utils/requests'; type ShortenSettingPayload = Partial & { locale?: Locale }; +const UploadImage = dynamic(() => import('../atoms/UploadImage').then((mod) => mod.UploadImage)); + export const AdvancedSettingUrlForm = () => { const { t, locale } = useTrans(); const { shortenSlice } = useBearStore(); @@ -35,6 +38,7 @@ export const AdvancedSettingUrlForm = () => { const { register, + setValue, handleSubmit, formState: { errors }, watch, @@ -42,11 +46,16 @@ export const AdvancedSettingUrlForm = () => { defaultValues, }); + const onUpdateImgSrc = (url: string) => { + setValue('ogImgSrc', url); + setShortenHistoryForm({ ogImgSrc: url }); + }; + const handleUpdate = useCallback((history: ShortenSettingPayload) => { setShortenHistoryForm(history); }, []); - const debouncedUpdate = useCallback(debounce(handleUpdate, 1000), []); + const debouncedUpdate = useCallback(debounce(handleUpdate, 600), []); const [ogTitle, ogDescription] = watch(['ogTitle', 'ogDescription']); @@ -60,8 +69,9 @@ export const AdvancedSettingUrlForm = () => { useEffect(() => { if (shortenHistory) debouncedUpdate({ - ogTitle: shortenHistory.ogDescription || t('ogTitle', { hash: shortenHistory.hash ?? 'XXX' }), + ogTitle: shortenHistory.ogTitle || t('ogTitle', { hash: shortenHistory.hash ?? 'XXX' }), ogDescription: shortenHistory.ogDescription || t('ogDescription'), + ogImgSrc: shortenHistory.ogImgSrc, }); }, [shortenHistory]); @@ -87,6 +97,7 @@ export const AdvancedSettingUrlForm = () => { updateShortenUrl.mutate({ hash: shortenHistory.hash, locale, + ogImgSrc: values.ogImgSrc || undefined, ogDescription: values.ogDescription || undefined, ogTitle: values.ogTitle || undefined, }); @@ -98,21 +109,30 @@ export const AdvancedSettingUrlForm = () => {
- - -

{error.message}

} - /> + +
+ +
+
+ + +

{error.message}

} + /> +
diff --git a/src/components/gadgets/FacebookPreview.tsx b/src/components/gadgets/FacebookPreview.tsx index d90197dd..48babc06 100644 --- a/src/components/gadgets/FacebookPreview.tsx +++ b/src/components/gadgets/FacebookPreview.tsx @@ -4,7 +4,7 @@ import { BASE_URL, PLATFORM_AUTH, brandUrlShortDomain } from 'types/constants'; import { encrypt } from 'utils/crypto'; import { useTrans } from 'utils/i18next'; -export const FacebookPreview = ({ hash, ogTitle, ogDomain, ogDescription }: Partial) => { +export const FacebookPreview = ({ hash, ogTitle, ogDomain, ogDescription, ogImgSrc }: Partial) => { const { t, locale } = useTrans(); const title = ogTitle || t('ogTitle', { hash: hash || 'XXX' }); let encodeTitle = ''; @@ -12,17 +12,21 @@ export const FacebookPreview = ({ hash, ogTitle, ogDomain, ogDescription }: Part encodeTitle = encrypt(title); } return ( -
-
-
-