From 1c6ca8fac346915e5e40c9ad1e3016b1d3a54a11 Mon Sep 17 00:00:00 2001 From: Ryan <962491243@qq.com> Date: Mon, 18 Sep 2023 18:25:52 +0800 Subject: [PATCH] update demo --- .../CommercialEmailEditorBanner/index.tsx | 48 - demo/src/components/Frame/index.tsx | 2 - demo/src/hooks/useShowCommercialEditor.ts | 2 +- demo/src/hooks/useShowLiveChat.ts | 17 + demo/src/pages/Editor/index.tsx | 6 +- nextjs-demo/.env.example | 20 + nextjs-demo/.gitignore | 3 + nextjs-demo/README.md | 16 + .../client/assets/images/empty-email.svg | 13 + nextjs-demo/client/assets/images/iphone.png | Bin 0 -> 10653 bytes .../components/CommercialBanner/index.tsx | 70 + .../components/FullScreenLoading/index.tsx | 29 + .../components/IframeComponent/index.tsx | 65 + .../client/components/Layout/NavBar/index.tsx | 51 + .../NavBar/style/icon-button.module.less | 8 + .../Layout/NavBar/style/index.module.less | 80 + .../components/Layout/index.module.less | 144 + .../client/components/Layout/index.tsx | 146 + nextjs-demo/client/hooks/api/api.ts | 27 + nextjs-demo/client/hooks/api/index.ts | 129 + nextjs-demo/client/hooks/index.ts | 2 + .../client/hooks/useMergeTagsModal.tsx | 64 + .../client/hooks/useShowCommercialEditor.ts | 20 + nextjs-demo/client/hooks/useShowLiveChat.ts | 17 + nextjs-demo/client/hooks/useUpload.ts | 22 + .../EmailPreviewModal/index.module.less | 5 + .../Emails/Create/EmailPreviewModal/index.tsx | 196 ++ .../pages/Emails/Create/index.module.css | 42 + .../client/pages/Emails/Create/index.tsx | 87 + .../Emails/Create/templates/template1.json | 683 ++++ .../Emails/Create/templates/template2.json | 757 +++++ .../Emails/Create/templates/template3.json | 404 +++ .../Emails/Create/templates/template4.json | 644 ++++ .../Emails/Create/templates/template5.json | 561 ++++ .../Emails/Create/templates/template6.json | 1382 ++++++++ .../Emails/Create/templates/template7.json | 1682 ++++++++++ .../Emails/Create/templates/template8.json | 957 ++++++ .../client/pages/Emails/Editor/index.tsx | 502 +++ .../pages/Emails/Editor/testMergeTags.ts | 165 + .../client/pages/Emails/Templates/index.tsx | 194 ++ nextjs-demo/client/pages/Login/index.css | 579 ++++ nextjs-demo/client/pages/Login/index.tsx | 63 + nextjs-demo/client/utils/Uploader.ts | 214 ++ nextjs-demo/client/utils/cookie.ts | 17 + nextjs-demo/client/utils/isDevelopment.ts | 1 + nextjs-demo/client/utils/posthog.ts | 10 + nextjs-demo/client/utils/pushEvent.ts | 12 + nextjs-demo/declaration.d.ts | 26 + nextjs-demo/docker-compose.yml | 14 + nextjs-demo/next-env.d.ts | 5 + nextjs-demo/next.config.js | 20 + nextjs-demo/package.json | 56 + nextjs-demo/pages/_app.tsx | 68 + nextjs-demo/pages/api/auth/[...nextauth].ts | 40 + nextjs-demo/pages/api/auth/prisma-adapter.ts | 71 + nextjs-demo/pages/api/email-template/[id].ts | 41 + nextjs-demo/pages/api/email-template/index.ts | 38 + nextjs-demo/pages/emails/create.tsx | 13 + nextjs-demo/pages/emails/editor/[id].tsx | 15 + nextjs-demo/pages/emails/index.tsx | 13 + nextjs-demo/pages/global.less | 29 + nextjs-demo/pages/index.tsx | 12 + nextjs-demo/pages/login/index.tsx | 12 + nextjs-demo/pnpm-lock.yaml | 2822 +++++++++++++++++ .../20220408154015_init/migration.sql | 84 + .../migration.sql | 30 + .../prisma/migrations/migration_lock.toml | 3 + nextjs-demo/prisma/prisma.ts | 22 + nextjs-demo/prisma/schema.prisma | 77 + nextjs-demo/renovate.json | 21 + nextjs-demo/tsconfig.json | 40 + .../components/blocks/Section/index.tsx | 92 +- 72 files changed, 13736 insertions(+), 86 deletions(-) delete mode 100644 demo/src/components/CommercialEmailEditorBanner/index.tsx create mode 100644 demo/src/hooks/useShowLiveChat.ts create mode 100644 nextjs-demo/.env.example create mode 100644 nextjs-demo/.gitignore create mode 100644 nextjs-demo/README.md create mode 100644 nextjs-demo/client/assets/images/empty-email.svg create mode 100644 nextjs-demo/client/assets/images/iphone.png create mode 100644 nextjs-demo/client/components/CommercialBanner/index.tsx create mode 100644 nextjs-demo/client/components/FullScreenLoading/index.tsx create mode 100644 nextjs-demo/client/components/IframeComponent/index.tsx create mode 100644 nextjs-demo/client/components/Layout/NavBar/index.tsx create mode 100644 nextjs-demo/client/components/Layout/NavBar/style/icon-button.module.less create mode 100644 nextjs-demo/client/components/Layout/NavBar/style/index.module.less create mode 100644 nextjs-demo/client/components/Layout/index.module.less create mode 100644 nextjs-demo/client/components/Layout/index.tsx create mode 100644 nextjs-demo/client/hooks/api/api.ts create mode 100644 nextjs-demo/client/hooks/api/index.ts create mode 100644 nextjs-demo/client/hooks/index.ts create mode 100644 nextjs-demo/client/hooks/useMergeTagsModal.tsx create mode 100644 nextjs-demo/client/hooks/useShowCommercialEditor.ts create mode 100644 nextjs-demo/client/hooks/useShowLiveChat.ts create mode 100644 nextjs-demo/client/hooks/useUpload.ts create mode 100644 nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.module.less create mode 100644 nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.tsx create mode 100644 nextjs-demo/client/pages/Emails/Create/index.module.css create mode 100644 nextjs-demo/client/pages/Emails/Create/index.tsx create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template1.json create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template2.json create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template3.json create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template4.json create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template5.json create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template6.json create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template7.json create mode 100644 nextjs-demo/client/pages/Emails/Create/templates/template8.json create mode 100644 nextjs-demo/client/pages/Emails/Editor/index.tsx create mode 100644 nextjs-demo/client/pages/Emails/Editor/testMergeTags.ts create mode 100644 nextjs-demo/client/pages/Emails/Templates/index.tsx create mode 100644 nextjs-demo/client/pages/Login/index.css create mode 100644 nextjs-demo/client/pages/Login/index.tsx create mode 100644 nextjs-demo/client/utils/Uploader.ts create mode 100644 nextjs-demo/client/utils/cookie.ts create mode 100644 nextjs-demo/client/utils/isDevelopment.ts create mode 100644 nextjs-demo/client/utils/posthog.ts create mode 100644 nextjs-demo/client/utils/pushEvent.ts create mode 100644 nextjs-demo/declaration.d.ts create mode 100644 nextjs-demo/docker-compose.yml create mode 100644 nextjs-demo/next-env.d.ts create mode 100644 nextjs-demo/next.config.js create mode 100644 nextjs-demo/package.json create mode 100644 nextjs-demo/pages/_app.tsx create mode 100644 nextjs-demo/pages/api/auth/[...nextauth].ts create mode 100644 nextjs-demo/pages/api/auth/prisma-adapter.ts create mode 100644 nextjs-demo/pages/api/email-template/[id].ts create mode 100644 nextjs-demo/pages/api/email-template/index.ts create mode 100644 nextjs-demo/pages/emails/create.tsx create mode 100644 nextjs-demo/pages/emails/editor/[id].tsx create mode 100644 nextjs-demo/pages/emails/index.tsx create mode 100644 nextjs-demo/pages/global.less create mode 100644 nextjs-demo/pages/index.tsx create mode 100644 nextjs-demo/pages/login/index.tsx create mode 100644 nextjs-demo/pnpm-lock.yaml create mode 100644 nextjs-demo/prisma/migrations/20220408154015_init/migration.sql create mode 100644 nextjs-demo/prisma/migrations/20230922085005_email_template/migration.sql create mode 100644 nextjs-demo/prisma/migrations/migration_lock.toml create mode 100755 nextjs-demo/prisma/prisma.ts create mode 100644 nextjs-demo/prisma/schema.prisma create mode 100644 nextjs-demo/renovate.json create mode 100644 nextjs-demo/tsconfig.json diff --git a/demo/src/components/CommercialEmailEditorBanner/index.tsx b/demo/src/components/CommercialEmailEditorBanner/index.tsx deleted file mode 100644 index 15e8f08f3..000000000 --- a/demo/src/components/CommercialEmailEditorBanner/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Alert } from '@arco-design/web-react'; -import { pushEvent } from '@demo/utils/pushEvent'; -import React, { useEffect, useState } from 'react'; -import { useLocalStorage } from 'react-use'; - -export const CommercialEmailEditorBanner = ({ page }: { page: 'HOME' | 'EDITOR' }) => { - const [visible, setVisible] = useLocalStorage( - 'commercialEmailEditorBannerVisible', - true, - ); - - useEffect(() => { - pushEvent({ event: `Show_Banner_at_${page}` }); - }, [page]); - - if (!visible) return null; - return ( - setVisible(false)} - style={{ - alignItems: 'flex-start', - }} - banner - content={ -
-
- Is the current Easy Email not meeting your requirements? - Interested in trying out our more powerful commercial version{' '} - of the email editor? -
-
- Reach out to us now to learn more details. Contact us at{' '} - { - pushEvent({ event: `Contact_at_${page}` }); - }} - target='_blank' - href='mailto:962491243@qq.com' - > - 962491243@qq.com - - . -
-
- } - >
- ); -}; diff --git a/demo/src/components/Frame/index.tsx b/demo/src/components/Frame/index.tsx index d6123aac5..e6de505e0 100644 --- a/demo/src/components/Frame/index.tsx +++ b/demo/src/components/Frame/index.tsx @@ -3,7 +3,6 @@ import { Layout, Menu, Breadcrumb } from '@arco-design/web-react'; import { Stack } from '../Stack'; import { pushEvent } from '@demo/utils/pushEvent'; import { githubButtonGenerate } from '@demo/utils/githubButtonGenerate'; -import { CommercialEmailEditorBanner } from '../CommercialEmailEditorBanner'; import { useShowCommercialEditor } from '@demo/hooks/useShowCommercialEditor'; const { SubMenu } = Menu; @@ -125,7 +124,6 @@ export default function Frame({ - {featureEnabled && } { }); }, []); - return { featureEnabled }; + return { featureEnabled: featureEnabled || process.env.NODE_ENV === 'development' }; }; diff --git a/demo/src/hooks/useShowLiveChat.ts b/demo/src/hooks/useShowLiveChat.ts new file mode 100644 index 000000000..cbe64261a --- /dev/null +++ b/demo/src/hooks/useShowLiveChat.ts @@ -0,0 +1,17 @@ +import { posthog } from '@demo/utils/posthog'; +import { useEffect, useState } from 'react'; + +export const useShowLiveChat = () => { + const [featureEnabled, setFeatureEnabled] = useState(false); + + useEffect(() => { + posthog.onFeatureFlags(function () { + console.log('posthog.show_live_chat', posthog.isFeatureEnabled('show_live_chat')); + if (posthog.isFeatureEnabled('show_live_chat')) { + setFeatureEnabled(true); + } + }); + }, []); + + return { showLiveChat: featureEnabled }; +}; diff --git a/demo/src/pages/Editor/index.tsx b/demo/src/pages/Editor/index.tsx index db9f648d9..284b3b2c9 100644 --- a/demo/src/pages/Editor/index.tsx +++ b/demo/src/pages/Editor/index.tsx @@ -67,7 +67,7 @@ import localesData from 'easy-email-localization/locales/locales.json'; import { Uploader } from '@demo/utils/Uploader'; import axios from 'axios'; import enUS from '@arco-design/web-react/es/locale/en-US'; -import { CommercialEmailEditorBanner } from '@demo/components/CommercialEmailEditorBanner'; + import { useShowCommercialEditor } from '@demo/hooks/useShowCommercialEditor'; console.log(localesData); @@ -518,7 +518,7 @@ export default function Editor() { } /> - {featureEnabled && } + + + + + + + + + + + + + diff --git a/nextjs-demo/client/assets/images/iphone.png b/nextjs-demo/client/assets/images/iphone.png new file mode 100644 index 0000000000000000000000000000000000000000..6cec3d4db34cb7ec83069b62eec2115679cc4bc6 GIT binary patch literal 10653 zcmeI2`BxLy`^RrUMP;*#ps2)JTWb-hDDbHwhzrz>AjmER7eELQ5FrpC2~xlo5fuT2 zLa=NqVNsT_CQ(!b1Z7Jk5E4b%VhBqDA?x?@Ip6=_^DA@CoSfXbb7$s0&wan=%m>ZMD!}%PEdWo`HRTsp1F+ld#4+1*(Fg&@27P|~LEFcGWPhrfXpLFH&w1h5 zCiO$zC$rCGp%VmGjS7RPsp9oJUA#P}ql_|4yjJ4^SB<(Agl8MCl37g@Y}b7G$M{<^ z@;qyN-^JU%-L3jtI6OT5d*Ri#Gf$-cmDY8yM`w2l1cQSfvWD`WD>ad`@cJab`*p~m z^gMd`A?AqkJhHm4udi?+>Oh`h=E2}|)3@1EvF5#t{65r_&EG9j-HT3S>_!0o?aw;+ z#F%wNS*o{SKBe2aExb&fwnj$KUTBfpNao=l*Wm*|eVV^_zsfODIb(sE#JVt8zSxA3 zlCNYIRX5dF1Jsw5h{N44DN_vQ-*p;aHBzJH)}%%OP+?YR{gCh31usf$4d*=;sCH7={t}~yr(y}7r}keLi3c? zSubb;p!NCd*RNI9hQ$;XC7z)PJ7zu9Try?F@1WNqxS>_&3Kf5aX#n4LCcf5Rpr-77 z^;iQ2#&x_PSw701t$t=_(P8j-R$1^`w)jQ7`UwD4Cqpu2>5J1G*_SV!*_en+k81BT zaL$Xnj@PS$s(hw@x&N2%B%xEvOYx0v0Qepf3ckJ_h+RW!Q9)&bOmoZ|X@GR>RjNL!^IKzc z9u9{a>UeAG@igiWqT(Xe(S{;4Eaq72175|H8nH52LC_b={KPu9($kTdKY5&F;AGRp z3KTMH;7Z?ofcXb+}p~1gW0%`!-SB zIrkFF9-l--6#!xUfra3`s<4fFxvtOnqq?ah)9zOom7gvS)EPPx-vw0qwBSQ~;h?yI z??Zl2y}HW^)+2=TU#JlVXGdPNSQ|d5QwL!lUA&aF}562^PV9tmfbLRpvoziP}0_v%Os&r0x zcH*XBHF{H%tZ2{lKR9QYMSA}0a(ANA)6?mD)Ia>9J~3S-jr6!_5vg)cTcqm);7;<`#iKFgN$5lYTEBuMvl%jp6*FLr@c3zENhPR4lhg0MhE9E)R7X z9dkwHQYdvjRWPbv*z^0usLA@-OG4TPOM3+D}_m&MF^7!(1Qm%!n%Ow=!+b zxn`_5YaOJ<&3mv^r1dCSR-KWNkpk17`L?^eyYHcp$1cA~oJmd8)sY;JGqP=l2|lg2 zVKxLw7(eP3XdRv8KQXX*RtFru&ZLxkcZStj`UdgjVU0q$|sqs8nzI_CW*W?^vjUQC5AIG^F!>&cIVb&n?qo*|woU2e3cBGfzN9M~-b-zRkv*nvk@yvzy;s*`LF|&fH>pF{E!%+Mb_v z!O9wLzrc*uY>r!+s~mEPmp1h}hfKGRjg6uGs|Q8#NZjZu!ibw%#Fbd#vP6X5sR%Fi z1GO#K;kXzqgY{8HQ0$cX0Ta*FfM*eucCdf)@A4L}M7r?OYs_d8M`_bTOVTVz~y;jNrvnwQEmC^nI^nlaN!NA4oN#FGsEcq@mC^E;;N^ z=<|yhw|sS*{stk`g_K>pc9EeP*Z&w56-C(Uo8iaI(^PeDmp87H6E+{#me~3vKt=hR z%{cmxHa(KV@u<|2BrpT=8^bmNQd5cdd$z^dlSH()I77H9j{2L;?n482RKB=kH9*>_ z9`bLncjR9FL4=Byw501Rh2onx;2C{mcU;K4hEP7d5xH0(I#()8{3l@@0FT$OlT`mY ze59JFUV0&*a4GbJUd1U3Cktu3|G)$YOVO^;`+I^|RNA7{N zu`>)-kDM?$DH8QdwE#Hpv}Gw~@^PIs_mIRAVZ%_y9yA_@8U(P{(uOfm<6E3-bK z&!YHH-p4uNCqhU17o)erna}hz(hYMio%g4&mH2!I#}+v+_a2}=;A@hI74PrmBZzoB ze)+aB107+a@inuH4- z{<#cQi6{(@4@!bBCu5F74MH9H<@3^g2^xU3bo!Ky*J$ee&e#p`?c_Id;N-(PnX7PJ zoMNXb)V`|kjd{C@Q=ks`xb?yzxAo#;{cdlIhDN5-H(9eNZ6LuxwyPNeaD6RoUAu#a z0NZb@G_Fj@N;0f0gcW62QNkY?N8doM{ zB^g#0!iqAisN#wvthnKd8?LzFiW{!D;ffosxZ#Q$uDId<~$ZHr*H6(JD zp5`Wui@K?D&~Df-PItz=Ysv~pdX_{4wD#7PwM5|K#s2zESv8WN4L zLUwn23b%Up^=muWEswV-wSWL;cw_ufgEqGf(&8!egvz>Q;N|>ZMiRhS^nUmtt<+_b zc<*y5gmU#vc&e}~GiTaf-|}ismLV*AAS^=}my{7%af*~n#&+Lq!V!Kwq*ZkjrVG`R z>u;E5r_z$7;_z|L6z!KkSwX5%e+2V|`L>um|4b8dr^rpDhC(%SOBWdxj=dX)cNW;qhdv0i50Da*M0NGnt(%3T>Svw6ug}7$;8Zy8;I> zhHxwpQmKa7O2VwiWB}&UrPl8ua_Cr+zHRM|h%Y(NEbsP0pzY`1okEEt>hHr@?^v3a zZs703dY4K0>*9o?JDYM32q2oSZw>lRs2w(65*7E^>*xYiji$Vqx=6$9H~vJ22sSJw zt!=dOBvBarMvhmrd1G+KGKmZyq&~4xkKm4f5~A!5Q{<756Z>=YW>GL|!?ux9>z8&N zqEFLh*!XFTwIqD9-2{HK!u2@zEwcO4E2K+C>a<%^bfebO9|bQU(J$4i{cCP&psclw zpzI)F^{eyq@)VAEvn0qzO#;Vhx?yvt=W7J-&Wkl!qo=73Z@G#_;Zn{-$33tDO(aov=Zfyv_>&y`{9kc za+1n4{D7soBvzfk*xl@60JFO|G;*xXj1(#*NNDL0KSJbB3? zR7x5Qw&1YYY-E~UMlV-bN2L;Dmgc^oAvXJSh{FkiT-a|D3gzIC&k@;LI`DF1eAdO0 zuzc#~1vpKswpZ_<7H^VWgP1Q`4{LJP*v?VQ3W@ljWz;^Fe zhmONR`qW8T@JKp+b_cT)VrwpyN*z*4v7NsWyll9iVZn+G45fQSQ&W@ih{`>AUL=u7 z5?u$z^BL$z&XOow{&3}nv6(8_5t!2KsT}cz&E3~VG~G;PJd)5gFxe`z-n(ZeR*#%s}zQJ5X1jHH#b-1Y@@P)k4$lI@)eJ?#Hw79y>kN%kw~N} zU}-JVDuM1;I-}uN?;L1iwJE)g81Zr^0AcQ%L|F@(g+*88n=cU{ig6I(?C-#hbSD5ZURZ> zv07WYf#jb>%c*0kT-wp8banzg*dljZ2o_5{p(Jb`p%1)kSuWC`FML7(_o7g)!e**3 zQ7XwcYqoD|Ym4AkO&)-C7bZi4gE5}yvvFtjT2I1Ns_8r$Pn_7YUvaYOO5|<9-REkw zmWzR>lmeYHzi^$PH#W-K2VD?=5$V~=3{%xvdw-Z(fNI&(-rip7x4k8bXNo!NtqLP& zengctd@b)2_M2)y=$_=4a2(@72925~0u0oda)1R@`Rha+4VwtYHKhk2@ zf;J?Sgo!=jp9mKoYExQ+Ap^T17yR2P(OciSw9zlhcZ3>v(shm)~FPz*Z2|e)LgEv8MUh1(+D~aycAMqI7KN*~O5q659R$ zJh4?}OQ-K>`XYc?jo{YYfe%D=a9WL2+HxK$#fmF=uaH zus5FK&!dArP^s0aDGUwZ-W-}k=(&-x@QCwaL{(JBF7j&kDNCjhOR!n-f-k-5G>=!W z$|3bGNJ3NadC#X`N`GLZYm`Ytg3Cy#jBn=ZYrj6J+wW?YK&N;;4vd}6Py>LEacxy} zvIXxt*N5EOnA_!V4^v!l?Y>~+R&!YVFdscq{+1#yd1yptp#2SW0V5}{jLW6qrwD@` zyJoT@`y>I8->QgWjsgx=Hvh=$fyYw6;#qAD1I^?-7yBkz64d}tCumXYNxCUZ{L5^u zwnTHeektRq6angs8^eg_niN%(r?t8g&DzmL%uAxtX9U>fbg~|OW1U3P6$8K~2Bq2B zW6Wc@NmHU}{F$E{U&;hv2H{yx-Lf~{tu@|N?bRB&9|zynDwQI}BA`<*O;58O+Cy&PJ { + const [visible, setVisible] = useSessionStorage( + 'commercialEmailEditorBannerVisible', + true, + ); + + const { showLiveChat } = useShowLiveChat(); + + useEffect(() => { + pushEvent({ event: `Show_Banner_at_${page}` }); + }, [page]); + + if (!visible) return null; + return ( + setVisible(false)} + style={{ + alignItems: 'flex-start', + }} + banner + content={ +
+
+ Is the current Easy Email not meeting your requirements ? + It's time to try our more powerful commercial version of the email editor.{' '} + + {showLiveChat ? ( + <> + { + pushEvent({ event: `Contact_at_${page}` }); + (window as any).$crisp?.push(['do', 'chat:open']); + }} + target='_blank' + style={{ fontSize: 16 }} + > + Open Live Chat + + + ) : ( + <> + Contact us for more information. Email:{' '} + { + pushEvent({ event: `Contact_at_${page}` }); + }} + target='_blank' + href='mailto:ch.mao@qq.com' + style={{ fontSize: 16 }} + > + ch.mao@qq.com + + . + + )} + +
+
+ } + >
+ ); +}; diff --git a/nextjs-demo/client/components/FullScreenLoading/index.tsx b/nextjs-demo/client/components/FullScreenLoading/index.tsx new file mode 100644 index 000000000..71750c69f --- /dev/null +++ b/nextjs-demo/client/components/FullScreenLoading/index.tsx @@ -0,0 +1,29 @@ +import { Spin } from "@arco-design/web-react"; +import { FC } from "react"; + +interface LoadingScreenProps { + size?: number; + isFullScreen?: boolean; +} + +const FullScreenLoading: FC = ({ + size = 40, + isFullScreen, +}) => { + return ( +
+ +
+ ); +}; + +export default FullScreenLoading; diff --git a/nextjs-demo/client/components/IframeComponent/index.tsx b/nextjs-demo/client/components/IframeComponent/index.tsx new file mode 100644 index 000000000..f29cf5644 --- /dev/null +++ b/nextjs-demo/client/components/IframeComponent/index.tsx @@ -0,0 +1,65 @@ +import React, { useState } from 'react'; +import { useInterval } from 'react-use'; +import { createPortal } from 'react-dom'; + +interface Props + extends React.DetailedHTMLProps< + React.IframeHTMLAttributes, + HTMLIFrameElement + > { + children: React.ReactNode; + title?: string; + onChangeHeight?: (val: number) => void; + windowRef?: (e: Window) => void; +} + +export const IframeComponent = ({ + children, + title, + windowRef, + style, + onChangeHeight, + ...props +}: Props) => { + const [mountNode, setMountNode] = useState(null); + const [height, setHeight] = useState(0); + + const onLoad: React.ReactEventHandler = evt => { + const contentWindow = (evt.target as any)?.contentWindow; + if (!contentWindow) return; + windowRef?.(contentWindow); + const innerBody = contentWindow.document.body; + innerBody.style.backgroundColor = 'transparent'; + setMountNode(innerBody); + }; + + useInterval(() => { + const scrollHeight = mountNode?.scrollHeight || 0; + if (scrollHeight > 0) { + setHeight(scrollHeight); + onChangeHeight && onChangeHeight(scrollHeight); + } + }, 1000); + + return ( + + ); +}; diff --git a/nextjs-demo/client/components/Layout/NavBar/index.tsx b/nextjs-demo/client/components/Layout/NavBar/index.tsx new file mode 100644 index 000000000..3e6b00c07 --- /dev/null +++ b/nextjs-demo/client/components/Layout/NavBar/index.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { Avatar, Dropdown, Menu } from '@arco-design/web-react'; +import { IconPoweroff } from '@arco-design/web-react/icon'; + +import styles from './style/index.module.less'; +import { signOut, useSession } from 'next-auth/react'; + +export const Navbar: React.FC = () => { + const { data } = useSession(); + + const user = data?.user; + const droplist = ( + + { + signOut(); + }} + > + + Logout + + {user?.email} + + ); + + return ( +
+
+
Easy Email
+
+
    + {user && ( +
  • + + + {(user.name || user.email)?.toUpperCase()} + + +
  • + )} +
+
+ ); +}; diff --git a/nextjs-demo/client/components/Layout/NavBar/style/icon-button.module.less b/nextjs-demo/client/components/Layout/NavBar/style/icon-button.module.less new file mode 100644 index 000000000..87345ddac --- /dev/null +++ b/nextjs-demo/client/components/Layout/NavBar/style/icon-button.module.less @@ -0,0 +1,8 @@ +.icon-button { + font-size: 16px; + border: 1px solid var(--color-border-2); + + > svg { + vertical-align: -3px; + } +} diff --git a/nextjs-demo/client/components/Layout/NavBar/style/index.module.less b/nextjs-demo/client/components/Layout/NavBar/style/index.module.less new file mode 100644 index 000000000..514556f62 --- /dev/null +++ b/nextjs-demo/client/components/Layout/NavBar/style/index.module.less @@ -0,0 +1,80 @@ +.navbar { + display: flex; + justify-content: space-between; + border-bottom: 1px solid rgb(229, 230, 235); + box-sizing: border-box; + background-color: #ffffff; + height: 100%; + height: 60px; +} + +.left { + display: flex; + align-items: center; +} + +.logo { + display: flex; + align-items: center; + width: 200px; + padding-left: 20px; + box-sizing: border-box; + font-weight: bold; + font-size: 28px; +} + +.logo-name { + color: var(--color-text-1); + font-weight: 500; + font-size: 20px; + margin-left: 10px; + font-family: "PingFang SC"; +} + +.right { + display: flex; + list-style: none; + padding-right: 20px; + + li { + padding: 0 8px; + display: flex; + align-items: center; + } + + a { + text-decoration: none; + color: var(--color-text-1); + } +} + +.username { + cursor: pointer; +} + +.round { + :global(.arco-input-inner-wrapper) { + border-radius: 16px; + } + + svg { + font-size: 16px; + } +} + +.dropdown-icon { + margin-right: 8px; + font-size: 16px; + vertical-align: text-bottom; +} + +.fixed-settings { + position: fixed; + top: 280px; + right: 0px; + + svg { + font-size: 18px; + vertical-align: -4px; + } +} diff --git a/nextjs-demo/client/components/Layout/index.module.less b/nextjs-demo/client/components/Layout/index.module.less new file mode 100644 index 000000000..8a210468e --- /dev/null +++ b/nextjs-demo/client/components/Layout/index.module.less @@ -0,0 +1,144 @@ +.layout { + width: 100%; + height: 100%; +} + +.layout-navbar { + position: fixed; + width: 100%; + min-width: 1100px; + top: 0; + left: 0; + height: 60px; + z-index: 100; +} + +.layout-sider { + position: fixed; + height: 100%; + top: 0; + left: 0; + z-index: 99; + box-sizing: border-box; +} + +.layout-sider { + position: fixed; + height: 100%; + top: 0; + left: 0; + z-index: 99; + box-sizing: border-box; + + ::-webkit-scrollbar { + width: 12px; + height: 4px; + } + + ::-webkit-scrollbar-thumb { + border: 4px solid transparent; + background-clip: padding-box; + border-radius: 7px; + background-color: var(--color-text-4); + } + + ::-webkit-scrollbar-thumb:hover { + background-color: var(--color-text-3); + } + + &::after { + content: ""; + display: block; + position: absolute; + top: 0; + right: -1px; + width: 1px; + height: 100%; + background-color: var(--color-border); + } + + :global(.arco-layout-sider-children) { + overflow-y: hidden; + } + + .collapse-btn { + height: 24px; + width: 24px; + background-color: var(--color-fill-1); + color: var(--color-text-3); + border-radius: 2px; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + // 位置 + position: absolute; + bottom: 12px; + right: 12px; + + &:hover { + background-color: var(--color-fill-3); + } + } +} + +.menu-wrapper { + overflow: auto; + height: 100%; + + :global(.arco-menu-item-inner > a::after), + :global(.arco-menu-item > a::after) { + content: ""; + display: block; + position: absolute; + width: 100%; + height: 100%; + left: 0; + right: 0; + top: 0; + bottom: 0; + } + + :global(.arco-menu-inline-header) { + font-weight: 500; + } +} + +.icon { + font-size: 18px; + vertical-align: text-bottom; +} + +.icon-empty { + width: 12px; + height: 18px; + display: inline-block; +} + +.layout-content { + background-color: var(--color-fill-2); + min-width: 1100px; + min-height: 100vh; + transition: padding-left 0.2s; + box-sizing: border-box; + padding: 16px 0px 0px 0; +} + +.layout-content-wrapper { + padding: 16px 20px 0; + height: 100%; + width: 100%; + box-sizing: border-box; +} + +.layout-breadcrumb { + margin-bottom: 16px; +} + +.spin { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + min-height: calc(100vh - 60px); +} diff --git a/nextjs-demo/client/components/Layout/index.tsx b/nextjs-demo/client/components/Layout/index.tsx new file mode 100644 index 000000000..a3e7cc061 --- /dev/null +++ b/nextjs-demo/client/components/Layout/index.tsx @@ -0,0 +1,146 @@ +import { Alert, Layout, Menu } from '@arco-design/web-react'; +import styles from './index.module.less'; +import cs from 'classnames'; +import qs from 'query-string'; +import { ReactNode, useEffect, useState } from 'react'; +import { IconEmail } from '@arco-design/web-react/icon'; +import { useRouter } from 'next/router'; +import Link from 'next/link'; +import { Navbar } from './NavBar'; + +interface Props { + children: React.ReactNode; + hideSidebar?: boolean; + hideNavbar?: boolean; +} + +const MenuItem = Menu.Item; +const SubMenu = Menu.SubMenu; + +const Sider = Layout.Sider; + +type NavMenuItem = { + label: string; + icon?: ReactNode; + children?: Array; + link: string; +}; + +const navigationMenus: Array = [ + { + label: 'Emails', + icon: , + children: [ + { + label: 'Templates', + link: '/emails', + }, + ], + link: '/emails', + }, +]; + +export default function PageLayout({ children, hideNavbar, hideSidebar }: Props) { + const router = useRouter(); + const pathname = router.pathname || '/emails'; + const currentComponent = qs.parseUrl(pathname).url.slice(1); + + const paths = currentComponent.split('/'); + const defaultSelectedKeys = paths[0] ? ['/' + paths[0]] : []; + + const [selectedKeys, setSelectedKeys] = useState([pathname]); + const [openKeys, setOpenKeys] = useState(defaultSelectedKeys); + const navbarHeight = 60; + const menuWidth = 220; + const paddingTop = !hideNavbar ? { paddingTop: navbarHeight } : {}; + const paddingLeft = !hideSidebar ? { paddingLeft: menuWidth } : {}; + const paddingStyle = { ...paddingLeft, ...paddingTop }; + + function onClickMenuItem(key: string) { + setSelectedKeys([key]); + } + + return ( + <> + {!hideNavbar && ( + +
+ +
+
+ )} + + {!hideSidebar && ( + +
+ { + setOpenKeys(openKeys); + }} + > + {navigationMenus.map(menu => { + if (menu.children && menu.children.length > 0) { + return ( + +
{menu.icon}
+
{menu.label}
+ + } + > + {menu.children.map(child => { + return ( + + {child.icon} + + {child.label} + + + ); + })} +
+ ); + } + return ( + + {menu.icon} + + {menu.label} + + + ); + })} +
+
+
+ )} + + + + {children} + + +
+ + ); +} diff --git a/nextjs-demo/client/hooks/api/api.ts b/nextjs-demo/client/hooks/api/api.ts new file mode 100644 index 000000000..637295df0 --- /dev/null +++ b/nextjs-demo/client/hooks/api/api.ts @@ -0,0 +1,27 @@ +import axios from 'axios'; + +const api = axios.create({}); +api.interceptors.request.use( + config => { + return config; + }, + error => { + return Promise.reject(error); + }, +); +api.interceptors.response.use( + config => { + return config; + }, + error => { + if (error?.response?.status === 401) { + window.location.href = '/login'; + } + if (error.response?.data?.message) { + return Promise.reject(new Error(error.response?.data?.message)); + } + return Promise.reject(error); + }, +); + +export { api }; diff --git a/nextjs-demo/client/hooks/api/index.ts b/nextjs-demo/client/hooks/api/index.ts new file mode 100644 index 000000000..4bc5dc721 --- /dev/null +++ b/nextjs-demo/client/hooks/api/index.ts @@ -0,0 +1,129 @@ +import { EmailTemplate } from '@prisma/client'; +import { IEmailTemplate } from 'easy-email-editor'; +import { useCallback, useEffect, useState } from 'react'; +import { api } from './api'; + +export const useGetEmailTemplateQuery = ({ id }: { id: string }) => { + const [fetching, setFetching] = useState(false); + const [data, setData] = useState(null); + + const getEmailTemplateQuery = useCallback( + async (id: string): Promise => { + setFetching(true); + try { + const { data } = await api.get(`/api/email-template/${id}`); + setData(data); + setFetching(false); + return data; + } catch (error) { + setFetching(false); + throw error; + } + }, + [], + ); + + useEffect(() => { + if (!id) return; + getEmailTemplateQuery(id); + }, [id]); + + return { fetching: fetching, data: data, getEmailTemplateQuery }; +}; + +export const useGetEmailTemplatesQuery = () => { + const [fetching, setFetching] = useState(false); + const [data, setData] = useState(null); + + const getEmailTemplatesQuery = useCallback(async (): Promise => { + setFetching(true); + try { + const { data } = await api.get('/api/email-template'); + setData(data); + setFetching(false); + return data; + } catch (error) { + setFetching(false); + throw error; + } + }, []); + + useEffect(() => { + getEmailTemplatesQuery(); + }, []); + + return { fetching: fetching, data: data, getEmailTemplatesQuery }; +}; + +export const useDeleteEmailTemplateMutation = () => { + const [fetching, setFetching] = useState(false); + const [data, setData] = useState(null); + + const deleteEmailTemplateMutation = async (payload: { + id: string; + }): Promise => { + setFetching(true); + try { + const { data } = await api.delete(`/api/email-template/${payload.id}`); + setData(data); + setFetching(false); + return data; + } catch (error) { + setFetching(false); + throw error; + } + }; + + return { fetching: fetching, data: data, deleteEmailTemplateMutation }; +}; + +export const useCreateEmailTemplateMutation = () => { + const [fetching, setFetching] = useState(false); + const [data, setData] = useState(null); + + const createEmailTemplateMutation = async (payload: { + subject: string; + content: IEmailTemplate['content']; + thumbnail: string; + }): Promise => { + setFetching(true); + try { + const { data } = await api.post('/api/email-template', payload); + setData(data); + setFetching(false); + return data; + } catch (error) { + setFetching(false); + throw error; + } + }; + + return { fetching: fetching, data: data, createEmailTemplateMutation }; +}; + +export const useUpdateEmailTemplateMutation = () => { + const [fetching, setFetching] = useState(false); + const [data, setData] = useState(null); + + const updateEmailTemplateMutation = async (payload: { + id: string; + data: { + subject: string; + content: IEmailTemplate['content']; + thumbnail: string; + }; + }): Promise => { + setFetching(true); + try { + const { data } = await api.patch(`/api/email-template/${payload.id}`, payload.data); + setData(data); + setFetching(false); + return data; + } catch (error) { + setFetching(false); + throw error; + } + }; + + return { fetching: fetching, data: data, updateEmailTemplateMutation }; +}; diff --git a/nextjs-demo/client/hooks/index.ts b/nextjs-demo/client/hooks/index.ts new file mode 100644 index 000000000..260324173 --- /dev/null +++ b/nextjs-demo/client/hooks/index.ts @@ -0,0 +1,2 @@ +export * from './useUpload'; +export * from './api'; diff --git a/nextjs-demo/client/hooks/useMergeTagsModal.tsx b/nextjs-demo/client/hooks/useMergeTagsModal.tsx new file mode 100644 index 000000000..871d6723d --- /dev/null +++ b/nextjs-demo/client/hooks/useMergeTagsModal.tsx @@ -0,0 +1,64 @@ +import { Message, Modal } from '@arco-design/web-react'; +import React, { useMemo, useState } from 'react'; +import { Form } from 'react-final-form'; +import { TextAreaField } from 'easy-email-extensions'; +import { Config } from 'final-form'; + +export function useMergeTagsModal(defaultMergeTags: Record) { + const [visible, setVisible] = useState(false); + const [mergeTags, setMergeTags] = useState(defaultMergeTags); + + const openModal = () => { + setVisible(true); + }; + const closeModal = () => { + setVisible(false); + }; + + const onSubmit: Config['onSubmit'] = values => { + try { + setMergeTags(JSON.parse(values.mergeTags)); + closeModal(); + } catch (error: any) { + Message.warning(error?.message || error); + } + }; + + const modal = useMemo(() => { + return ( +
+ {({ handleSubmit }) => ( + handleSubmit()} + onCancel={closeModal} + > + + + )} +
+ ); + }, [mergeTags, visible]); + + return { + modal, + openModal, + mergeTags, + setMergeTags, + }; +} diff --git a/nextjs-demo/client/hooks/useShowCommercialEditor.ts b/nextjs-demo/client/hooks/useShowCommercialEditor.ts new file mode 100644 index 000000000..d3af22753 --- /dev/null +++ b/nextjs-demo/client/hooks/useShowCommercialEditor.ts @@ -0,0 +1,20 @@ +import { useEffect, useState } from 'react'; +import { posthog } from '../utils/posthog'; + +export const useShowCommercialEditor = () => { + const [featureEnabled, setFeatureEnabled] = useState(false); + + useEffect(() => { + posthog.onFeatureFlags(function () { + console.log( + 'posthog.show_advanced_editor', + posthog.isFeatureEnabled('show_advanced_editor'), + ); + if (posthog.isFeatureEnabled('show_advanced_editor')) { + setFeatureEnabled(true); + } + }); + }, []); + + return { featureEnabled: featureEnabled || process.env.NODE_ENV === 'development' }; +}; diff --git a/nextjs-demo/client/hooks/useShowLiveChat.ts b/nextjs-demo/client/hooks/useShowLiveChat.ts new file mode 100644 index 000000000..ca0507da1 --- /dev/null +++ b/nextjs-demo/client/hooks/useShowLiveChat.ts @@ -0,0 +1,17 @@ +import posthog from 'posthog-js'; +import { useEffect, useState } from 'react'; + +export const useShowLiveChat = () => { + const [featureEnabled, setFeatureEnabled] = useState(false); + + useEffect(() => { + posthog.onFeatureFlags(function () { + console.log('posthog.show_live_chat', posthog.isFeatureEnabled('show_live_chat')); + if (posthog.isFeatureEnabled('show_live_chat')) { + setFeatureEnabled(true); + } + }); + }, []); + + return { showLiveChat: featureEnabled }; +}; diff --git a/nextjs-demo/client/hooks/useUpload.ts b/nextjs-demo/client/hooks/useUpload.ts new file mode 100644 index 000000000..7df6c800a --- /dev/null +++ b/nextjs-demo/client/hooks/useUpload.ts @@ -0,0 +1,22 @@ +import { useCallback } from 'react'; +import axios from 'axios'; + +const CLOUDINARY_URL = 'https://api.cloudinary.com/v1_1/dwkp0e1yo/image/upload'; + +export function useUpload() { + const upload = useCallback(async (file: Blob, organizationId: string) => { + if (!file || !organizationId) { + throw new Error('Missing file or organizationId'); + } + const data = new FormData(); + data.append('file', file); + data.append('upload_preset', 'easy-email-test'); + + const res = await axios.post<{ url: string }>(CLOUDINARY_URL, data); + return res.data.url; + }, []); + + return { + upload, + }; +} diff --git a/nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.module.less b/nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.module.less new file mode 100644 index 000000000..82b68b296 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.module.less @@ -0,0 +1,5 @@ +.emailPreviewModal { + :global(.arco-modal-content) { + padding-bottom: 0; + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.tsx b/nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.tsx new file mode 100644 index 000000000..97f575782 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/EmailPreviewModal/index.tsx @@ -0,0 +1,196 @@ +import { Button, Grid, List, Message, Modal, Space } from '@arco-design/web-react'; +import { useRouter } from 'next/router'; +import React, { useEffect, useMemo, useState } from 'react'; +import iphoneFrame from '@/client/assets/images/iphone.png'; +import { IframeComponent } from '@/client/components/IframeComponent'; +import mjml from 'mjml-browser'; +import { IconDesktop, IconMobile } from '@arco-design/web-react/icon'; +import styles from './index.module.less'; +import { IEmailTemplate } from 'easy-email-editor'; +import { JsonToMjml } from 'easy-email-core'; +import { useCreateEmailTemplateMutation } from '@/client/hooks'; + +const grid = '2vw'; +const MOBILE_WIDTH = 375; +const MOBILE_Height = 700; + +export const EmailPreviewModal: React.FC<{ + children: React.ReactNode; + item: IEmailTemplate & { thumbnail: string }; + wrapClassName?: string; +}> = ({ children, item, wrapClassName }) => { + const [isMobile, setIsMobile] = useState(false); + + const [visible, setVisible] = React.useState(false); + + const router = useRouter(); + + const { fetching, createEmailTemplateMutation } = useCreateEmailTemplateMutation(); + + const onCreate = async () => { + try { + const data = await createEmailTemplateMutation({ + subject: item.subject, + thumbnail: item.thumbnail, + content: item.content, + }); + if (data.id) { + router.replace(`/emails/editor/${data.id}`); + } + } catch (error) { + Message.error(String(error)); + } + }; + + return ( + <> + setVisible(false)} + okButtonProps={{ loading: fetching }} + > +
+ + + + + + +
+
+
+
+ +
+
+
setVisible(true)} + > + {children} +
+ + ); +}; + +function EmailItem({ item, isMobile }: { item: IEmailTemplate; isMobile: boolean }) { + const [height, setHeight] = useState(600); + + const [html, setHtml] = useState(''); + + useEffect(() => { + const mjmlStr = JsonToMjml({ + data: item.content, + mode: 'production', + }); + setHtml(mjml(mjmlStr).html); + }, [item.content]); + + return ( + + + +
+ {`Subject`} +
+
{item.subject}
+
+
+ +
{ + e.stopPropagation(); + e.preventDefault(); + }} + > +
+ + +
+ +
+
+ + + ); +} diff --git a/nextjs-demo/client/pages/Emails/Create/index.module.css b/nextjs-demo/client/pages/Emails/Create/index.module.css new file mode 100644 index 000000000..1ac9c7095 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/index.module.css @@ -0,0 +1,42 @@ +.container { + display: flex; + width: 100%; + flex-wrap: wrap; +} + +.wrap { + width: 25%; + min-width: 280px; + display: flex; + justify-content: center; + flex-wrap: wrap; + margin-bottom: 20px; + padding-left: 10px; + padding-right: 10px; + box-sizing: border-box; +} + +.wrapItem { + width: 280px; + height: 400px; + margin-top: 5px; + border: 1px solid #d9d5d1; + overflow: hidden; + position: relative; + cursor: pointer; +} + +.bottom { + position: absolute; + box-sizing: border-box; + bottom: 0; + left: 0; + padding: 20px 15px 20px 15px; + background-color: #fff; + justify-content: center; + flex-direction: column; + display: flex; + width: 100%; + border-top: 1px solid #d9d5d1; + text-align: left; +} diff --git a/nextjs-demo/client/pages/Emails/Create/index.tsx b/nextjs-demo/client/pages/Emails/Create/index.tsx new file mode 100644 index 000000000..90fb79d52 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/index.tsx @@ -0,0 +1,87 @@ +import { + Avatar, + Button, + Card, + Layout, + PageHeader, + Space, + Typography, +} from '@arco-design/web-react'; +import { useRouter } from 'next/router'; +import { EmailPreviewModal } from './EmailPreviewModal'; +import styles from './index.module.css'; +import template1 from './templates/template1.json'; +import template2 from './templates/template2.json'; +import template3 from './templates/template3.json'; +import template4 from './templates/template4.json'; +import template5 from './templates/template5.json'; +import template6 from './templates/template6.json'; +import template7 from './templates/template7.json'; +import template8 from './templates/template8.json'; + +const list = [ + template1, + template2, + template3, + template4, + template5, + template6, + template7, + template8, +]; + +function Index() { + const router = useRouter(); + + return ( + + + + { + router.push(`/emails`); + }} + /> + + + +
+ {list.map((item, index) => { + return ( + +
+
+ + {item.subject} + +
+
+
+ ); + })} +
+
+
+
+ ); +} + +export default Index; diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template1.json b/nextjs-demo/client/pages/Emails/Create/templates/template1.json new file mode 100644 index 000000000..2ec61b27e --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template1.json @@ -0,0 +1,683 @@ +{ + "subject": "St. Patrick's Day", + "thumbnail": "http://res.cloudinary.com/dwkp0e1yo/image/upload/v1685974059/beacas-test/mfi7gupvhrgdz4ihsqwz.png", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "14px", + "font-weight": "400", + "line-height": "1.7", + "headStyles": [ + { + "content": ".mjml-body { width: 600px; margin: 0px auto; }" + }, + { + "content": "a {color: inherit} a:hover {color: inherit} a:active {color: inherit}" + } + ], + "fonts": [], + "responsive": true, + "font-family": "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans','Helvetica Neue', sans-serif", + "text-color": "#000000" + } + }, + "attributes": { + "background-color": "#8C9A80", + "width": "600px", + "css-class": "mjbody" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "background-color": "#FFFFFF", + "font-family": "Arial, sans-serif" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "navbar", + "data": { + "value": { + "links": [ + { + "color": "#1890ff", + "font-size": "13px", + "target": "_blank", + "font-family": "Arial, sans-serif", + "content": "Shop", + "padding": "15px 10px 15px 10px" + }, + { + "color": "#1890ff", + "font-size": "13px", + "target": "_blank", + "font-family": "Arial, sans-serif", + "content": "About", + "padding": "15px 10px 15px 10px" + }, + { + "color": "#1890ff", + "font-size": "13px", + "target": "_blank", + "font-family": "Arial, sans-serif", + "content": "Contact", + "padding": "15px 10px 15px 10px" + }, + { + "color": "#1890ff", + "font-size": "13px", + "target": "_blank", + "font-family": "Arial, sans-serif", + "content": "Blog", + "padding": "15px 10px 15px 10px" + } + ] + } + }, + "attributes": { + "align": "center", + "font-family": "Arial, sans-serif" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#263D29", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "JOIN US FOR A FEAST ON" + } + }, + "attributes": { + "align": "left", + "color": "#FFFFFF", + "font-family": "Arial, sans-serif", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "St. Patrick's Day" + } + }, + "attributes": { + "align": "left", + "color": "#FFFFFF", + "font-family": "Arial, sans-serif", + "font-size": "36px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://d3k81ch9hvuctc.cloudfront.net/company/S7EvMw/images/29140463-2f83-49ea-922d-ac65063642cd.gif", + "font-family": "Arial, sans-serif", + "color": "#ffffff", + "background-color": "#1A1F25", + "grid-color": "#12304b", + "shadow-color": "#000000", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "SUMMER SALE" + } + }, + "attributes": { + "align": "center", + "color": "#ffffff", + "font-family": "Arial, sans-serif", + "font-size": "32px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "50% OFF" + } + }, + "attributes": { + "align": "center", + "color": "#ffffff", + "font-family": "Arial, sans-serif", + "font-size": "64px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#263D29", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "480px", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "From hearty stews and comforting shepherd's pie to classic fish and chips, we have something to satisfy every appetite." + } + }, + "attributes": { + "align": "left", + "color": "#FFFFFF", + "font-family": "Arial, sans-serif", + "padding": "10px 20px 10px 20px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#263D29", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://d3k81ch9hvuctc.cloudfront.net/company/S7EvMw/images/6644858a-f5af-4bff-917d-f13c5df516ce.png", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#263D29", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "button", + "data": { + "value": { + "content": "Book a table" + } + }, + "attributes": { + "align": "center", + "background-color": "#C5900C", + "color": "#ffffff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "#", + "font-family": "Arial, sans-serif", + "font-size": "16px", + "width": "100%", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "Book a table" + } + }, + "attributes": { + "align": "center", + "background-color": "#FCF0D3", + "color": "#C5900C", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "3px solid #C5900C", + "text-align": "center", + "href": "#", + "font-family": "Arial, sans-serif", + "font-size": "16px", + "width": "100%", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#FFFFFF", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "50%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "And of course, no Irish meal would be complete without a pint of Guinness or a dram of Irish whiskey to wash it down.

View drink menu" + } + }, + "attributes": { + "align": "left", + "font-family": "Arial, sans-serif", + "padding": "25px 25px 25px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "50%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://d3k81ch9hvuctc.cloudfront.net/company/S7EvMw/images/a096e725-a517-477e-bdb9-97211537aeb8.png", + "font-family": "Arial, sans-serif", + "padding": "25px 25px 25px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#C9CCCF", + "font-family": "Arial, sans-serif", + "padding": "10px 0px 10px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "rtl", + "text-align": "center", + "background-color": "#FFFFFF", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "50%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "And of course, no Irish meal would be complete without a pint of Guinness or a dram of Irish whiskey to wash it down.

View drink menu" + } + }, + "attributes": { + "align": "left", + "font-family": "Arial, sans-serif", + "padding": "25px 25px 25px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "50%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://d3k81ch9hvuctc.cloudfront.net/company/S7EvMw/images/f812b491-36cb-4a82-b2f0-eea60ed5eba9.png", + "font-family": "Arial, sans-serif", + "padding": "25px 25px 25px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#263D29", + "font-family": "Arial, sans-serif", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "font-family": "Arial, sans-serif", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "No longer want to receive these emails? unsubscribe" + } + }, + "attributes": { + "align": "left", + "color": "#FFFFFF", + "font-family": "Arial, sans-serif", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template2.json b/nextjs-demo/client/pages/Emails/Create/templates/template2.json new file mode 100644 index 000000000..a2e8d12e3 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template2.json @@ -0,0 +1,757 @@ +{ + "subject": "Arturia - Newsletter", + "thumbnail": "https://assets.maocanhua.cn/5523abbd-6484-40b0-a368-bbea5e647bf4-", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "14px", + "line-height": "1.7", + "headStyles": [], + "fonts": [], + "responsive": true, + "font-family": "lucida Grande,Verdana,Microsoft YaHei", + "text-color": "#000000" + } + }, + "attributes": { + "background-color": "#F2F2F2", + "width": "600px" + }, + "children": [ + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 0px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "vertical-align": "center" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "middle", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-black/Logo-Baseline-0.15x.png", + "width": "144px", + "href": "https://www.arturia.com", + "alt": "", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "NEWS
MARCH 2016" + } + }, + "attributes": { + "align": "left", + "font-family": "Helvetica,Arial,sans-serif", + "line-height": "120%", + "text-decoration": "underline", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#000001", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Dear {firstname},

You used to follow rhythm, now rhythm follows you, everywhere you go!
Discover iSpark, the mobile transposition of our renowned beat-making solution Spark." + } + }, + "attributes": { + "align": "left", + "color": "#FFFFFE", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "14px", + "line-height": "120%", + "padding": "0px 25px 0px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "background-color": "#FFFFFE", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/05.jpg", + "href": "https://www.arturia.com/products/ipad-synths/ispark/overview", + "alt": "", + "padding": "0px 0px 0px 0px" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "iSpark is a powerful mobile production tool allowing you to create and play rhythmic tracks, complex grooves and even complete songs. Its sonic strike force comes along with an unwavering workflow and a real flexibility." + } + }, + "attributes": { + "align": "left", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "14px", + "line-height": "120%", + "padding": "25px 25px 25px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "background-color": "#FFFFFE", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/06.jpg", + "href": "https://www.arturia.com/products/ipad-synths/ispark/overview", + "alt": "", + "padding": "0px 0px 0px 0px" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "Check out the iSpark introduction movie shot during the Arturia Experience event at the ADE featuring the Dutch beatmaker FilosofischeStilte." + } + }, + "attributes": { + "align": "left", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "14px", + "line-height": "120%", + "padding": "25px 25px 25px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "background-color": "#FFFFFE", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/07.jpg", + "href": "https://www.arturia.com/products/ipad-synths/ispark/details", + "alt": "", + "padding": "0px 0px 0px 0px" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "Follow Mauricio Garcia, Arturia Product Specialist, presenting you the many clever features of iSpark in this series of tutorials." + } + }, + "attributes": { + "align": "left", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "14px", + "line-height": "120%", + "padding": "25px 25px 25px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "background-color": "#FFFFFE", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/08.jpg", + "href": "https://www.arturia.com/products/ipad-synths/ispark/details", + "alt": "", + "padding": "0px 0px 0px 0px" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "iSpark includes a tremendous collection of factory kits and individual instruments covering most of the field of application of beat-making but it is also compatible with the existing Spark resources and Expansion Packs." + } + }, + "attributes": { + "align": "left", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "14px", + "line-height": "120%", + "padding": "25px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "advanced_button", + "data": { + "value": { + "content": "Learn more about iSpark" + } + }, + "attributes": { + "align": "center", + "background-color": "#2DDCB4", + "color": "#ffffff", + "font-weight": "normal", + "border-radius": "8px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://www.arturia.com/products/ipad-synths/ispark/overview", + "font-size": "14px", + "font-family": "Helvetica,Arial,sans-serif", + "padding": "10px 25px 25px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#000001", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Musically yours,
The Arturia Team" + } + }, + "attributes": { + "align": "left", + "color": "#FFFFFE", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "14px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/facebook_arturia.png", + "width": "86px", + "href": "http://www.facebook.com/arturia2", + "alt": "", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/youtube.png", + "width": "86px", + "href": "http://www.youtube.com/arturiaweb", + "alt": "", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/Soundcloud.png", + "width": "86px", + "href": "http://soundcloud.com/arturia-official", + "alt": "", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://www.arturia.com/images/newsletters/2016-02-ispark/twitter_arturia.png", + "width": "86px", + "href": "http://twitter.com/arturiaofficial", + "alt": "", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "See this email in your browser here" + } + }, + "attributes": { + "align": "center", + "font-family": "Helvetica,Arial,sans-serif", + "padding": "0px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "advanced_divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#C9CCCF", + "padding": "10px 0px 10px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Your email address is on this list as a result of a subscription, information request, competition, or other correspondence you may have had with us in the past. If you would like to be removed from our list, check the email address this newsletter\n was sent to and use the following link: Unsubscribe. Privacy policy available here." + } + }, + "attributes": { + "align": "left", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "10px", + "line-height": "12px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "ARTURIA: https://www.arturia.com - Contact: info
ARTURIA France: 30 chemin\n du vieux chêne, 38240 Meylan - FRANCE
ARTURIA US: : 5776-D Lindero Cyn Rd #239 -Westlake Village, CA 91362 - USA" + } + }, + "attributes": { + "align": "left", + "font-family": "Helvetica,Arial,sans-serif", + "font-size": "10px", + "line-height": "12px", + "padding": "10px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "advanced_divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#C9CCCF", + "padding": "10px 0px 10px 0px" + }, + "children": [] + } + ] + } + ] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template3.json b/nextjs-demo/client/pages/Emails/Create/templates/template3.json new file mode 100644 index 000000000..34f60b063 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template3.json @@ -0,0 +1,404 @@ +{ + "subject": "Dynamic rendering", + "thumbnail": "https://d3k81ch9hvuctc.cloudfront.net/company/S7EvMw/images/cae2b095-1326-4212-b241-2b6a32442efe.png", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "14px", + "line-height": "1.7", + "headStyles": [], + "fonts": [], + "responsive": true, + "font-family": "lucida Grande,Verdana,Microsoft YaHei", + "text-color": "#000000" + } + }, + "attributes": { + "background-color": "#efeeea", + "width": "600px" + }, + "children": [ + { + "type": "advanced_wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff" + }, + "children": [ + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "20px 25px 20px 25px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "advanced_group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top", + "width": "30%" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "{{user.avatar}}", + "width": "150px" + }, + "children": [] + } + ] + }, + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 20px", + "border": "none", + "vertical-align": "top", + "width": "70%" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Hello , my name is {{user.name}}
😃 welcome to {{user.project}}.
Today is {{date.today}}.
" + }, + "hidden": false + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "left", + "font-size": "21px", + "line-height": "2" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "Conditon block 1
Email wrong.
 This block will be hidden when previewing or sending an email.
", + "condition": { + "enabled": true, + "symbol": "and", + "groups": [ + { + "symbol": "and", + "groups": [ + { + "left": "user.name", + "operator": "==", + "right": "Ryan" + }, + { + "left": "user.email", + "operator": "==", + "right": "xx@gmail.com" + } + ] + }, + { + "symbol": "and", + "groups": [ + { + "left": "user.project", + "operator": "==", + "right": "Easy email" + } + ] + } + ] + } + }, + "hidden": false + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "center", + "font-size": "25px", + "color": "#ffffff", + "container-background-color": "#d0021b" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "
Conditon block 2
Condition match
This block will be show when previewing or sending an email.", + "condition": { + "enabled": true, + "symbol": "and", + "groups": [ + { + "symbol": "and", + "groups": [ + { + "left": "user.name", + "operator": "==", + "right": "Ryan" + }, + { + "left": "user.email", + "operator": "==", + "right": "easy-email@gmail.com" + } + ] + }, + { + "symbol": "and", + "groups": [ + { + "left": "user.project", + "operator": "==", + "right": "Easy email" + } + ] + } + ] + } + }, + "hidden": false + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "center", + "font-size": "25px", + "color": "#ffffff", + "container-background-color": "#4a90e2" + }, + "children": [] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#f69f40" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": { + "iteration": { + "enabled": true, + "dataSource": "product_list", + "itemName": "item", + "limit": 9999, + "mockQuantity": 2 + } + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top", + "width": "50%" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "10px 25px 10px 25px", + "src": "{{item.image}}", + "border-radius": "10px", + "href": "{{item.url}}" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "{{item.title}}
{{item.price}}
" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#7ed321" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": { + "iteration": { + "enabled": true, + "dataSource": "emptyList", + "itemName": "item", + "limit": 9999, + "mockQuantity": 2 + } + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top", + "width": "50%" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "10px 25px 10px 25px", + "src": "{{item.image}}", + "border-radius": "10px", + "href": "{{item.url}}" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "Empty lists won't show
{{item.title}}
{{item.price}}
" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "product_recommendation", + "data": { + "value": { + "title": "You might also like", + "buttonText": "Buy now", + "productList": [ + { + "image": "https://assets.maocanhua.cn/8e0e07e2-3f84-4426-84c1-2add355c558b-image.png", + "title": "Red Flock Buckle Winter Boots", + "price": "$59.99 HKD", + "url": "https://easy-email-m-ryan.vercel.app" + }, + { + "image": "https://assets.maocanhua.cn/8e0e07e2-3f84-4426-84c1-2add355c558b-image.png", + "title": "Thick Stretch Warm Fleece High Waist Pencil Pant", + "price": "$69.99 HKD", + "url": "https://easy-email-m-ryan.vercel.app" + }, + { + "image": "https://assets.maocanhua.cn/8e0e07e2-3f84-4426-84c1-2add355c558b-image.png", + "title": "Thick Velvet Grid Pant", + "price": "$29.99 HKD", + "url": "https://easy-email-m-ryan.vercel.app" + } + ] + } + }, + "attributes": { + "background-color": "#ffffff", + "button-text-color": "#ffffff", + "button-color": "#414141", + "product-name-color": "#414141", + "product-price-color": "#414141", + "title-color": "#222222" + }, + "children": [] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template4.json b/nextjs-demo/client/pages/Emails/Create/templates/template4.json new file mode 100644 index 000000000..579a0d3a2 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template4.json @@ -0,0 +1,644 @@ +{ + "subject": "SPRING PREVIEW SALE", + "thumbnail": "https://assets.maocanhua.cn/5b9d0408-0e14-4c9f-979e-f526187bd0ca-", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "14px", + "line-height": "1.7", + "headStyles": [], + "fonts": [], + "responsive": true, + "font-family": "lucida Grande,Verdana,Microsoft YaHei", + "text-color": "#000000" + } + }, + "attributes": { + "background-color": "#F4F4F4", + "width": "600px", + "css-class": "mjml-body" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "30px 0px 0px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "background-color": "#ffffff" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/b999e7e4-9242-4435-a4f6-c8f1d6fdfd96-image.png", + "target": "_blank", + "width": "214px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

Product | Concept | Contact

" + } + }, + "attributes": { + "align": "left", + "font-size": "13px", + "line-height": "22px", + "color": "#55575d", + "font-family": "Arial, sans-serif", + "padding": "0px 25px 15px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/ed0590da-b6dc-4d14-bfc7-6f1931a390fd-image.png", + "target": "_blank", + "width": "600px", + "padding": "0px 0px 0px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff", + "padding": "30px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

- Our Holiday Recipes -

" + } + }, + "attributes": { + "align": "left", + "font-size": "30px", + "line-height": "22px", + "color": "#55575d", + "font-family": "Arial, sans-serif", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff", + "padding": "20px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/be61d137-bb44-4358-a681-dea81d2a8ec1-image.png", + "target": "_blank", + "width": "1200px", + "padding": "0px 30px 20px 30px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

Cake Title

\n

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

\n

Choose me >

" + } + }, + "attributes": { + "align": "left", + "font-size": "13px", + "line-height": "22px", + "color": "#55575d", + "font-family": "Arial, sans-serif", + "padding": "0px 40px 0px 40px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "rtl", + "text-align": "center", + "background-color": "#ffffff", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/b3e16b18-9385-421e-b6a7-b28a749d6abf-image.png", + "target": "_blank", + "width": "1200px", + "padding": "20px 30px 20px 30px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

Cake Title

\n

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

\n

Choose me >

" + } + }, + "attributes": { + "align": "left", + "font-size": "13px", + "line-height": "22px", + "color": "#55575d", + "font-family": "Arial, sans-serif", + "padding": "0px 40px 0px 40px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/6c23a5d0-ec6c-4634-8753-49e4a2da407e-image.png", + "target": "_blank", + "width": "1200px", + "padding": "20px 30px 20px 30px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

Cake Title

\n

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

\n

Choose me >

" + } + }, + "attributes": { + "align": "left", + "font-size": "13px", + "line-height": "22px", + "color": "#55575d", + "font-family": "Arial, sans-serif", + "padding": "0px 40px 0px 40px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff", + "padding": "0px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "button", + "data": { + "value": { + "content": "Discover all desserts" + } + }, + "attributes": { + "align": "center", + "background-color": "#354552", + "color": "#ffffff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "#", + "font-size": "14px", + "font-family": "Georgia, Helvetica, Arial, sans-serif", + "text-decoration": "none", + "text-transform": "none", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/0a270377-104e-4ea8-bd94-3df6d7afaa01-image.png", + "target": "_blank", + "width": "600px", + "padding": "0px 0px 0px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#ffffff", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/a35965f4-900a-43a5-9c96-cef1e398e9c5-image.png", + "target": "_blank", + "width": "202px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "social", + "data": { + "value": { + "elements": [ + { + "href": "", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/93013b18-062d-48d7-ae00-4a5f0a9ac988.png", + "content": "Facebook", + "font-size": "13px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0", + "vertical-align": "middle", + "text-decoration": "none", + "color": "#333333", + "name": "facebook" + }, + { + "href": "", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/a81ddd4b-3a12-47be-91f3-28d71eced397.png", + "content": "Google", + "font-size": "13px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0", + "vertical-align": "middle", + "text-decoration": "none", + "color": "#333333", + "name": "pinterest" + }, + { + "href": "", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/0a411326-17c5-4814-ad3a-6927266f097e.png", + "content": "Twitter", + "font-size": "13px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0", + "vertical-align": "middle", + "text-decoration": "none", + "color": "#333333", + "name": "instagram" + } + ] + } + }, + "attributes": { + "align": "center", + "color": "#333333", + "mode": "horizontal", + "font-size": "13px", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0px", + "icon-padding": "0px", + "icon-size": "20px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template5.json b/nextjs-demo/client/pages/Emails/Create/templates/template5.json new file mode 100644 index 000000000..f143300c4 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template5.json @@ -0,0 +1,561 @@ +{ + "subject": "MJML Code - Newsletter", + "thumbnail": "https://d3k81ch9hvuctc.cloudfront.net/company/S7EvMw/images/de4d139c-a137-479f-99f1-80c971eb69b2.png", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "14px", + "line-height": "1.7", + "headStyles": [], + "fonts": [], + "responsive": true, + "font-family": "lucida Grande,Verdana,Microsoft YaHei", + "text-color": "#000000" + } + }, + "attributes": { + "background-color": "#E1E8ED", + "width": "600px" + }, + "children": [ + { + "type": "raw", + "data": { + "value": { + "content": "" + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "white", + "padding": "20px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://avatars0.githubusercontent.com/u/16115896?v=3&s=200", + "width": "50px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "advanced_divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#f8f8f8", + "horizontal-spacing": "0", + "vertical-spacing": "0", + "padding": "10px 0px 0px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fcfcfc", + "padding": "20px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Here is what you've missed" + } + }, + "attributes": { + "align": "center", + "font-size": "20px", + "color": "grey", + "font-family": "Helvetica Neue", + "font-weight": "200", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "advanced_divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#f8f8f8", + "horizontal-spacing": "0", + "vertical-spacing": "0", + "padding": "10px 0px 0px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "raw", + "data": { + "value": { + "content": "" + } + }, + "attributes": {}, + "children": [] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "white", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "130px", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://mjml.io/assets/img/responsive.png", + "width": "100px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "350px", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Sed ut perspiciatis" + } + }, + "attributes": { + "align": "left", + "font-size": "20px", + "color": "grey", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip" + } + }, + "attributes": { + "align": "left", + "color": "grey", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "raw", + "data": { + "value": { + "content": "" + } + }, + "attributes": {}, + "children": [] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#f3f3f3", + "padding": "20px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Explore our new features" + } + }, + "attributes": { + "align": "center", + "font-size": "20px", + "color": "rgb(165, 176, 184)", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#f3f3f3", + "padding": "0px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "100%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://cloud.githubusercontent.com/assets/6558790/12450760/ee034178-bf85-11e5-9dda-98d0c8f9f8d6.png", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fcfcfc", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "130px", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://mjml.io/assets/img/easy-and-quick.png", + "width": "100px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "350px", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Right on time!" + } + }, + "attributes": { + "align": "left", + "font-size": "20px", + "color": "grey", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "advanced_text", + "data": { + "value": { + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip" + } + }, + "attributes": { + "align": "left", + "color": "grey", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "advanced_section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#f3f3f3", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "advanced_column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "advanced_text", + "data": { + "value": { + "content": "Stay in touch!" + } + }, + "attributes": { + "align": "center", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "advanced_social", + "data": { + "value": { + "elements": [ + { + "href": "#", + "icon-size": "20px", + "target": "_blank", + "src": "https://easy-email-m-ryan.vercel.app/images/acbae5eb-efa4-4eb6-866c-f421e740b713-ad3c92b1-9cdb-4a7b-aad3-75ad809db8a3.png", + "content": "Facebook", + "name": "twitter" + }, + { + "href": "#", + "icon-size": "20px", + "target": "_blank", + "src": "https://easy-email-m-ryan.vercel.app/images/98520d6c-5cef-449e-bcbf-6316ccec2088-e8780361-0deb-4896-895e-e690c886cdf0.png", + "content": "Google", + "name": "facebook" + }, + { + "href": "", + "icon-size": "20px", + "target": "_blank", + "src": "https://easy-email-m-ryan.vercel.app/images/b064f705-34ba-4400-975e-9dd0cec21c30-cc9aa158-56bd-4bf1-b532-72390d25c864.png", + "content": "Twitter" + } + ] + } + }, + "attributes": { + "align": "center", + "color": "#333333", + "mode": "horizontal", + "font-size": "13px", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0px", + "icon-padding": "0px", + "icon-size": "20px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template6.json b/nextjs-demo/client/pages/Emails/Create/templates/template6.json new file mode 100644 index 000000000..cc6aefa00 --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template6.json @@ -0,0 +1,1382 @@ +{ + "subject": "Racoon - Ecommerce", + "thumbnail": "https://d3k81ch9hvuctc.cloudfront.net/company/S7EvMw/images/821cbaa1-ebcf-476e-acc2-bb97a1edd316.png", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "14px", + "line-height": "1.7", + "headStyles": [], + "fonts": [], + "responsive": true, + "font-family": "lucida Grande,Verdana,Microsoft YaHei", + "text-color": "#000000" + } + }, + "attributes": { + "background-color": "#d6dde5", + "width": "600px" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "background-color": "#ffffff" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "50%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4u.png", + "href": "https://mjml.io", + "alt": "Racoon logo", + "padding": "10px 10px 10px 10px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fa8739", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "200px", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

SPRING PROMO

\n

50%

\n

OFFER

\n

Lorem ipsum dolor sit amet, consectetur adipiscing elit

" + } + }, + "attributes": { + "align": "center", + "color": "#fff", + "font-size": "40px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "SHOP NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fff", + "color": "#fa8739", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "16px", + "padding": "15px 25px 40px 25px", + "inner-padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "400px", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "https://assets.maocanhua.cn/57b75a82-e8df-4281-9590-fb9487466d6e-image.png", + "alt": "Clothes set", + "border": "none", + "width": "400px", + "padding": "0px 0px 0px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#2f323b", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "middle", + "width": "25%", + "padding": "10px 0px 10px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4t.png", + "alt": "Box free shipping", + "border": "none", + "width": "42px", + "padding": "10px 0px 10px 0px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "middle", + "width": "75%", + "padding": "10px 0px 10px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

FREE SHIPPING ON ORDER OVER 55€

" + } + }, + "attributes": { + "align": "left", + "color": "#fff", + "font-size": "18px", + "padding": "0px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fff", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {}, + "hidden": false + }, + "attributes": { + "border": "none", + "vertical-align": "bottom", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4v.jpg", + "alt": "Chesterk tank", + "border": "none", + "width": "209px", + "padding": "30px 0px 20px 0px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

CHESTERK TANK

\n

15€

" + } + }, + "attributes": { + "align": "center", + "font-weight": "bold", + "color": "#000", + "font-size": "15px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "13px", + "padding": "0px 30px 10px 30px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "bottom", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4g.jpg", + "alt": "Beyond backpack", + "border": "none", + "width": "178px", + "padding": "10px 0px 20px 0px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

BEYOND BACKPACK

\n

20€

" + } + }, + "attributes": { + "align": "center", + "font-weight": "bold", + "color": "#000", + "font-size": "15px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#612d0a", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "13px", + "padding": "0px 30px 10px 30px", + "inner-padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fff", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "bottom", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x46.jpg", + "alt": "Jensen shorts", + "border": "none", + "width": "182px", + "padding": "30px 0px 20px 0px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

JENSEN SHORTS

\n

28€

" + } + }, + "attributes": { + "align": "center", + "font-weight": "bold", + "color": "#000", + "font-size": "15px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "13px", + "padding": "0px 30px 10px 30px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "bottom", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4h.jpg", + "alt": "Verdant cap", + "border": "none", + "width": "129px", + "padding": "20px 0px 20px 0px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

VERDANT CAP

\n

20€

" + } + }, + "attributes": { + "align": "center", + "font-weight": "bold", + "color": "#000", + "font-size": "15px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "13px", + "padding": "0px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "bottom", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4i.jpg", + "alt": "Blake polo shirt", + "border": "none", + "width": "208px", + "padding": "20px 0px 20px 0px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

BLAKE POLO SHIRT

\n

25€

" + } + }, + "attributes": { + "align": "center", + "font-weight": "bold", + "color": "#000", + "font-size": "15px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "13px", + "padding": "0px 30px 10px 30px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "bottom", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4j.jpg", + "alt": "Sketch floral", + "border": "none", + "width": "72px", + "padding": "20px 0px 20px 0px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

SKETCH FLORAL

\n

23€

" + } + }, + "attributes": { + "align": "center", + "font-weight": "bold", + "color": "#000", + "font-size": "15px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "13px", + "padding": "0px 30px 10px 30px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fa8739", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4k.jpg", + "alt": "Man 1", + "width": "301px", + "padding": "0px 0px 0px 0px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "width": "50%", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

ANDERSON SWEATER

\n

75€

\n

The Anderson Sweater features a floral all-over print with contrast colour.

" + } + }, + "attributes": { + "align": "left", + "color": "#fff", + "font-size": "13px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fff", + "color": "#fa8739", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "padding": "0px 30px 20px 30px", + "inner-padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#2f323b", + "padding": "0px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

ALDER TWO JONES JACKET

\n

100€

\n

Colour-block design, zip entry, oxford hood lining, side pockets & TC lining.

" + } + }, + "attributes": { + "align": "left", + "color": "#fff", + "font-size": "13px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "padding": "0px 30px 10px 30px", + "inner-padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/xj6.jpg", + "alt": "Man 2", + "border": "none", + "width": "302px", + "padding": "0px 0px 0px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fa8739", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "

DISCOVER OUR

\n

SUMMER COLLECTION

" + } + }, + "attributes": { + "align": "center", + "color": "#fff", + "font-size": "13px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fff", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4q.jpg", + "alt": "Topaz C3 shoes", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

TOPAZ C3 SHOES

\n

70€

" + } + }, + "attributes": { + "align": "center", + "color": "#000", + "font-size": "15px", + "font-weight": "bold", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "font-size": "13px", + "padding": "0px 30px 10px 30px", + "inner-padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4r.jpg", + "alt": "Camden backpack", + "border": "none", + "width": "199px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

CAMDEN BACKPACK

\n

50€

" + } + }, + "attributes": { + "align": "center", + "color": "#000", + "font-size": "15px", + "font-weight": "bold", + "padding": "0px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "BUY NOW" + } + }, + "attributes": { + "align": "center", + "background-color": "#fa8739", + "color": "#fff", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "https://mjml.io", + "padding": "0px 30px 10px 30px", + "inner-padding": "10px 25px 10px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#2f323b", + "padding": "20px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x47.png", + "alt": "Cards", + "width": "72px", + "padding": "10px 25px 10px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

PAYMENT METHODS

\n

We accept all majors payments options

" + } + }, + "attributes": { + "align": "center", + "color": "#fff", + "font-size": "13px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x48.png", + "alt": "Currencies", + "border": "none", + "width": "70px", + "padding": "10px 25px 0px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

CURRENCIES CHOICE

\n

You have the choice to pay with your own currencies

" + } + }, + "attributes": { + "align": "center", + "color": "#fff", + "font-size": "13px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "top", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x4y.png", + "alt": "Express", + "border": "none", + "width": "82px", + "padding": "10px 25px 8px 25px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "

EXPRESS SHIPPING

\n

Delivered tomorrow before noon

" + } + }, + "attributes": { + "align": "center", + "color": "#fff", + "font-size": "13px", + "padding": "0px 25px 0px 25px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fa8739", + "padding": "0px 0px 20px 0px" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "middle", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "src": "http://191n.mj.am/img/191n/3s/x49.png", + "alt": "Racoon logo", + "border": "none", + "width": "180px", + "padding": "10px 0px 0px 0px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "border": "none", + "vertical-align": "middle", + "padding": "0px 0px 0px 0px" + }, + "children": [ + { + "type": "social", + "data": { + "value": { + "elements": [ + { + "href": "[[SHORT_PERMALINK]]", + "icon-size": "20px", + "target": "_blank", + "src": "https://easy-email-m-ryan.vercel.app/images/acbae5eb-efa4-4eb6-866c-f421e740b713-ad3c92b1-9cdb-4a7b-aad3-75ad809db8a3.png", + "content": "Facebook", + "name": "facebook" + }, + { + "href": "[[SHORT_PERMALINK]]", + "icon-size": "20px", + "target": "_blank", + "src": "https://easy-email-m-ryan.vercel.app/images/98520d6c-5cef-449e-bcbf-6316ccec2088-e8780361-0deb-4896-895e-e690c886cdf0.png", + "content": "Google", + "name": "twitter" + }, + { + "href": "[[SHORT_PERMALINK]]", + "icon-size": "20px", + "target": "_blank", + "src": "https://easy-email-m-ryan.vercel.app/images/b064f705-34ba-4400-975e-9dd0cec21c30-cc9aa158-56bd-4bf1-b532-72390d25c864.png", + "content": "Twitter", + "name": "google" + } + ] + } + }, + "attributes": { + "align": "center", + "color": "#333333", + "mode": "horizontal", + "font-size": "13px", + "font-weight": "normal", + "border-radius": "3px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0px", + "icon-padding": "0px", + "icon-size": "20px", + "padding": "20px 25px 10px 25px", + "inner-padding": "4px 4px 4px 4px" + }, + "children": [] + } + ] + } + ] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template7.json b/nextjs-demo/client/pages/Emails/Create/templates/template7.json new file mode 100644 index 000000000..02188bc5a --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template7.json @@ -0,0 +1,1682 @@ +{ + "subject": "Real Estate.", + "thumbnail": "https://assets.maocanhua.cn/de29d529-1d64-460e-9fcf-65524b345a93-", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "15px", + "line-height": "1.8", + "headStyles": [], + "fonts": [], + "responsive": true, + "font-family": "'Lato', sans-serif", + "text-color": "#000000", + "content-background-color": "#fafafa" + } + }, + "attributes": { + "background-color": "#efeeea", + "width": "600px" + }, + "children": [ + { + "type": "wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Real Estate" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "30px", + "font-family": "'Playfair Display', sans-serif", + "font-weight": "700" + }, + "children": [] + }, + { + "type": "divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#807878", + "padding": "10px 0px" + }, + "children": [] + }, + { + "type": "navbar", + "data": { + "value": { + "links": [ + { + "href": "/gettings-started-onboard", + "content": "HOME", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + }, + { + "href": "/try-it-live", + "content": "PROPERTIES", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + }, + { + "href": "/templates", + "content": "CONTACT", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + } + ] + } + }, + "attributes": { + "align": "center", + "base-url": "https://mjml.io" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "hero", + "data": { + "value": {} + }, + "attributes": { + "background-color": "#ffffff", + "background-position": "center center", + "mode": "fluid-height", + "padding": "100px 0px 100px 0px", + "vertical-align": "top", + "background-url": "https://assets.maocanhua.cn/92a8e4ce-499a-4b7e-a0c6-38265f9589f2-image.png" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Real Estate" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "color": "#ffffff", + "font-size": "45px", + "line-height": "45px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their 
place and supplies it with the necessary 
regelialia.
" + } + }, + "attributes": { + "align": "center", + "background-color": "#414141", + "color": "#ffffff", + "font-weight": "normal", + "border-radius": "3px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "1.5", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "#", + "font-size": "14px" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "Browse Properties" + } + }, + "attributes": { + "align": "center", + "background-color": "#feb062", + "color": "#ffffff", + "font-size": "13px", + "font-weight": "normal", + "border-radius": "5px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "#" + }, + "children": [] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Buy House in Best Price" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "34px", + "font-weight": "300" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their place and supplies it with the necessary regelialia. It is a paradisematic country, in which roasted parts of sentences fly into your mouth." + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "Browse Properties" + } + }, + "attributes": { + "align": "center", + "background-color": "#000", + "color": "#ffffff", + "font-weight": "normal", + "border-radius": "0px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "none", + "text-align": "center", + "href": "#", + "font-size": "12px" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "20px 25px 20px 25px", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fafafa" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Our Services" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "28px", + "line-height": "1.4", + "font-weight": "400" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/2d1f8c3a-6c54-428a-9300-e171131001bd-image.png", + "width": "100px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Layout" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Far far away, behind the word mountains, far from the countries" + } + }, + "attributes": { + "padding": "10px 0px 10px 0px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/0697f2b4-791a-4dc6-822d-59c6abec0faf-image.png", + "width": "100px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Design" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Far far away, behind the word mountains, far from the countries" + } + }, + "attributes": { + "padding": "10px 0px 10px 0px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "20px 25px 20px 25px", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fafafa" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Properties For Sale" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "28px", + "line-height": "1.4", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their place and supplies it with the necessary regelialia." + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "1px solid #ccc", + "vertical-align": "top", + "width": "48%" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/c2fa56dd-c6d0-4dce-9aa5-d1de563320aa-image.png", + "width": "" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Residential House" + } + }, + "attributes": { + "padding": "10px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "100 sqft 2 Bed 2 bath" + } + }, + "attributes": { + "padding": "0px 0px 10px 0px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "$1,000,000" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Far far away, behind the word mountains, far from the countries" + } + }, + "attributes": { + "padding": "10px 5px 10px 5px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top", + "width": "4%" + }, + "children": [] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "1px solid #ccc", + "vertical-align": "top", + "width": "48%" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/8c8cca3a-d9c1-4ae4-bf49-1a0deca44c56-image.png", + "width": "" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Residential House" + } + }, + "attributes": { + "padding": "10px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "100 sqft 2 Bed 2 bath" + } + }, + "attributes": { + "padding": "0px 0px 10px 0px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "$1,000,000" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Far far away, behind the word mountains, far from the countries" + } + }, + "attributes": { + "padding": "10px 5px 10px 5px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "1px solid #ccc", + "vertical-align": "top", + "width": "48%" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/48d19e31-449f-453c-8c21-a10410575723-image.png", + "width": "" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Residential House" + } + }, + "attributes": { + "padding": "10px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "100 sqft 2 Bed 2 bath" + } + }, + "attributes": { + "padding": "0px 0px 10px 0px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "$1,000,000" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Far far away, behind the word mountains, far from the countries" + } + }, + "attributes": { + "padding": "10px 5px 10px 5px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top", + "width": "4%" + }, + "children": [] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "1px solid #ccc", + "vertical-align": "top", + "width": "48%" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/214fa0fd-afec-483f-a134-cb78305cad72-image.png", + "width": "" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Residential House" + } + }, + "attributes": { + "padding": "10px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "100 sqft 2 Bed 2 bath" + } + }, + "attributes": { + "padding": "0px 0px 10px 0px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "$1,000,000" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "center", + "font-size": "18px", + "font-weight": "400" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Far far away, behind the word mountains, far from the countries" + } + }, + "attributes": { + "padding": "10px 5px 10px 5px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "75px 0px 75px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-url": "https://assets.maocanhua.cn/ee1b8e88-a691-4ce5-ae45-b5b560f6cd13-image.png" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "200" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "center", + "font-size": "34px", + "font-weight": "700", + "color": "#ffffff" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Agents" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "center", + "font-size": "16px", + "color": "#ffffff" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "1200" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "center", + "font-size": "34px", + "font-weight": "700", + "color": "#ffffff" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "happy Clients" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "center", + "font-size": "16px", + "color": "#ffffff" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "1000" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "center", + "font-size": "34px", + "font-weight": "700", + "color": "#ffffff" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Sold Properties" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "center", + "font-size": "16px", + "color": "#ffffff" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "25px 25px 0px 25px", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Our Features" + } + }, + "attributes": { + "padding": "0px 25px 26px 0px", + "align": "left", + "font-size": "28px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Our Features" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "left", + "font-size": "18px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their" + } + }, + "attributes": { + "padding": "0px 25px 20px 0px", + "align": "left", + "font-size": "", + "color": "#807878" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Modern Design" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "left", + "font-size": "18px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their" + } + }, + "attributes": { + "padding": "0px 25px 20px 0px", + "align": "left", + "font-size": "", + "color": "#807878" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "Minimal Design" + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "align": "left", + "font-size": "18px" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their" + } + }, + "attributes": { + "padding": "0px 25px 0px 0px", + "align": "left", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/e49e99e4-e1a4-4a14-a3f2-885e7279a4d2-image.png" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "button", + "data": { + "value": { + "content": "Start Browsing" + } + }, + "attributes": { + "align": "center", + "background-color": "transparent", + "color": "#000000", + "font-weight": "700", + "border-radius": "0px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "2px solid #000", + "text-align": "center", + "href": "#", + "font-size": "" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#807878", + "padding": "10px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle", + "width": "60%" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Stay Updated On Newest Properties" + } + }, + "attributes": { + "padding": "0px 0px 0px 15px", + "align": "left", + "font-size": "20px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 15px 0px 0px", + "border": "none", + "vertical-align": "middle", + "width": "40%" + }, + "children": [ + { + "type": "social", + "data": { + "value": { + "elements": [ + { + "href": "#", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/5738124c-7dd0-4cde-9f24-dc713423ee36-image.png", + "content": "" + }, + { + "href": "#", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/fcce8406-c946-4ac5-a0cd-3982473be3e3-image.png", + "content": "" + }, + { + "href": "", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/2b845c8b-30d2-4326-a11f-48848dbadf7c-image.png", + "content": "" + } + ] + } + }, + "attributes": { + "align": "right", + "color": "#333333", + "mode": "horizontal", + "font-size": "13px", + "font-weight": "normal", + "border-radius": "3px", + "padding": "0px10px 0px 10px 0px", + "inner-padding": "4px 4px 4px 4px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0px", + "icon-padding": "0px", + "icon-size": "20px" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fafafa" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "No longer want to receive these email? You can Unsubscribe here" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "", + "color": "#807878" + }, + "children": [] + } + ] + } + ] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Create/templates/template8.json b/nextjs-demo/client/pages/Emails/Create/templates/template8.json new file mode 100644 index 000000000..0ef980c8c --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Create/templates/template8.json @@ -0,0 +1,957 @@ +{ + "subject": "Young Woman Dress", + "thumbnail": "https://assets.maocanhua.cn/42012a5b-c381-4c46-9a2e-c67daf610ccd-", + "content": { + "type": "page", + "data": { + "value": { + "breakpoint": "480px", + "headAttributes": "", + "font-size": "15px", + "line-height": "1.8", + "headStyles": [], + "fonts": [], + "responsive": true, + "font-family": "'Lato', sans-serif", + "text-color": "#000000", + "content-background-color": "#ffffff" + } + }, + "attributes": { + "background-color": "#efeeea", + "width": "600px" + }, + "children": [ + { + "type": "wrapper", + "data": { + "value": {} + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "button", + "data": { + "value": { + "content": "SHOPING" + } + }, + "attributes": { + "align": "center", + "background-color": "transparent", + "color": "#000000", + "font-weight": "700", + "border-radius": "0px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "2px solid #000", + "text-align": "center", + "href": "#", + "font-size": "20px" + }, + "children": [] + }, + { + "type": "divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#c2c2c2", + "padding": "10px 0px" + }, + "children": [] + }, + { + "type": "navbar", + "data": { + "value": { + "links": [ + { + "href": "/gettings-started-onboard", + "content": "HOME", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + }, + { + "href": "/try-it-live", + "content": "NEW", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + }, + { + "href": "/templates", + "content": "WOMEN", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + }, + { + "href": "/components", + "content": "KIDS", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + }, + { + "href": "/components", + "content": "BLOG", + "color": "#000000", + "font-size": "13px", + "target": "_blank", + "padding": "15px 10px 15px 10px" + } + ] + } + }, + "attributes": { + "align": "center", + "base-url": "https://mjml.io" + }, + "children": [] + }, + { + "type": "divider", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "border-width": "1px", + "border-style": "solid", + "border-color": "#c2c2c2", + "padding": "10px 0px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "We Are Shopping Website That Gives You An Affordable Prices & Discount" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "left", + "font-size": "30px", + "font-weight": "300" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Young Woman Dress" + } + }, + "attributes": { + "padding": "0px 25px 18px 25px", + "align": "left", + "font-size": "22px", + "line-height": "1.4" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their place and supplies it with the necessary regelialia." + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "left", + "font-size": "15px", + "line-height": "1.4", + "color": "#979494" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "Shop now" + } + }, + "attributes": { + "align": "center", + "background-color": "#f85e9f", + "color": "#ffffff", + "font-weight": "400", + "border-radius": "5px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "", + "text-align": "center", + "href": "#", + "font-size": "15px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/d56e3068-0985-4b86-b94e-2f6b375a6735-image.png" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/987f3337-ae63-41b4-a31b-d02f31c33061-image.png" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Young Woman Dress" + } + }, + "attributes": { + "padding": "0px 25px 18px 25px", + "align": "left", + "font-size": "22px", + "line-height": "1.4" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their place and supplies it with the necessary regelialia." + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "left", + "font-size": "15px", + "line-height": "1.4", + "color": "#979494" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "Shop now" + } + }, + "attributes": { + "align": "center", + "background-color": "#f85e9f", + "color": "#ffffff", + "font-weight": "400", + "border-radius": "5px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "", + "text-align": "center", + "href": "#", + "font-size": "15px" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Young Woman Dress" + } + }, + "attributes": { + "padding": "0px 25px 18px 25px", + "align": "left", + "font-size": "22px", + "line-height": "1.4" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their place and supplies it with the necessary regelialia." + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "left", + "font-size": "15px", + "line-height": "1.4", + "color": "#979494" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "Shop now" + } + }, + "attributes": { + "align": "center", + "background-color": "#f85e9f", + "color": "#ffffff", + "font-weight": "400", + "border-radius": "5px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "", + "text-align": "center", + "href": "#", + "font-size": "15px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/c4b825c3-89ba-46bc-9f1b-dc7a85b9dc68-image.png" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "image", + "data": { + "value": {} + }, + "attributes": { + "align": "center", + "height": "auto", + "padding": "0px 0px 0px 0px", + "src": "https://assets.maocanhua.cn/3da866d0-3ba8-4150-99fc-8ac4d7024621-image.png" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Young Woman Dress" + } + }, + "attributes": { + "padding": "0px 25px 18px 25px", + "align": "left", + "font-size": "22px", + "line-height": "1.4" + }, + "children": [] + }, + { + "type": "text", + "data": { + "value": { + "content": "A small river named Duden flows by their place and supplies it with the necessary regelialia." + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "left", + "font-size": "15px", + "line-height": "1.4", + "color": "#979494" + }, + "children": [] + }, + { + "type": "button", + "data": { + "value": { + "content": "Shop now" + } + }, + "attributes": { + "align": "center", + "background-color": "#f85e9f", + "color": "#ffffff", + "font-weight": "400", + "border-radius": "5px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "", + "text-align": "center", + "href": "#", + "font-size": "15px" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "20px 0px 20px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "button", + "data": { + "value": { + "content": "Start Shopping" + } + }, + "attributes": { + "align": "center", + "background-color": "#ffffff", + "color": "#000000", + "font-weight": "700", + "border-radius": "0px", + "padding": "10px 25px 10px 25px", + "inner-padding": "10px 25px 10px 25px", + "line-height": "120%", + "target": "_blank", + "vertical-align": "middle", + "border": "2px solid #000", + "text-align": "center", + "href": "#", + "font-size": "15px" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": true + } + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center" + }, + "children": [ + { + "type": "group", + "data": { + "value": {} + }, + "attributes": { + "vertical-align": "top", + "direction": "ltr" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle", + "width": "60%" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "Stay Updated On Our Shopping" + } + }, + "attributes": { + "padding": "0px 25px 0px 25px", + "align": "left", + "font-size": "20px", + "font-weight": "400", + "line-height": "36px" + }, + "children": [] + } + ] + }, + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "middle", + "width": "40%" + }, + "children": [ + { + "type": "social", + "data": { + "value": { + "elements": [ + { + "href": "#", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/b7cc7e4d-b6a3-45cb-a1a5-bec2fac278ad-image.png", + "content": "" + }, + { + "href": "#", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/f8644f58-ea6d-4b68-90c4-7b871f7ad702-image.png", + "content": "" + }, + { + "href": "", + "icon-size": "20px", + "target": "_blank", + "src": "https://assets.maocanhua.cn/fc295200-a262-4e3d-8310-e6dac278222e-image.png", + "content": "" + } + ] + } + }, + "attributes": { + "align": "center", + "color": "#333333", + "mode": "horizontal", + "font-size": "13px", + "font-weight": "normal", + "border-radius": "3px", + "padding": "10px 25px 10px 25px", + "inner-padding": "4px 4px 4px 4px", + "line-height": "22px", + "text-padding": "4px 4px 4px 0px", + "icon-padding": "0px", + "icon-size": "20px" + }, + "children": [] + } + ] + } + ] + } + ] + }, + { + "type": "section", + "data": { + "value": { + "noWrap": false + } + }, + "attributes": { + "padding": "10px 0px 10px 0px", + "background-repeat": "repeat", + "background-size": "auto", + "background-position": "top center", + "border": "none", + "direction": "ltr", + "text-align": "center", + "background-color": "#fafafa" + }, + "children": [ + { + "type": "column", + "data": { + "value": {} + }, + "attributes": { + "padding": "0px 0px 0px 0px", + "border": "none", + "vertical-align": "top" + }, + "children": [ + { + "type": "text", + "data": { + "value": { + "content": "No longer want to receive these email? You can Unsubscribe here" + } + }, + "attributes": { + "padding": "10px 25px 10px 25px", + "align": "center", + "font-size": "15px", + "line-height": "27px", + "color": "#c7bdbd" + }, + "children": [] + } + ] + } + ] + } + ] + } +} diff --git a/nextjs-demo/client/pages/Emails/Editor/index.tsx b/nextjs-demo/client/pages/Emails/Editor/index.tsx new file mode 100644 index 000000000..b9534f79a --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Editor/index.tsx @@ -0,0 +1,502 @@ +/* eslint-disable @next/next/no-img-element */ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { BlockManager, BasicType, AdvancedType, JsonToMjml } from 'easy-email-core'; +import { + EmailEditor, + EmailEditorProvider, + IEmailTemplate, + Stack, +} from 'easy-email-editor'; +import { ExtensionProps, MjmlToJson, StandardLayout } from 'easy-email-extensions'; +import { useWindowSize } from 'react-use'; +import { + Button, + ConfigProvider, + Dropdown, + Form, + Input, + Menu, + Message, + Modal, + PageHeader, + Select, + Space, + Spin, +} from '@arco-design/web-react'; +import 'easy-email-editor/lib/style.css'; +import 'easy-email-extensions/lib/style.css'; + +// theme, If you need to change the theme, you can make a duplicate in https://arco.design/themes/design/1799/setting/base/Color + +import { Config } from 'final-form'; +import mjml from 'mjml-browser'; +import { useGetEmailTemplateQuery, useUpdateEmailTemplateMutation } from '@/client/hooks'; +import { useRouter } from 'next/router'; +import FullScreenLoading from '@/client/components/FullScreenLoading'; +import { pushEvent } from '@/client/utils/pushEvent'; +import { Liquid } from 'liquidjs'; +import { saveAs } from 'file-saver'; +import { useMergeTagsModal } from '@/client/hooks/useMergeTagsModal'; +import { testMergeTags } from './testMergeTags'; +import { IconMoonFill, IconSunFill } from '@arco-design/web-react/icon'; +import { Uploader } from '@/client/utils/Uploader'; + +import blueTheme from '!!raw-loader!@arco-themes/react-easy-email-theme/css/arco.css'; +import purpleTheme from '!!raw-loader!@arco-themes/react-easy-email-theme-purple/css/arco.css'; +import greenTheme from '!!raw-loader!@arco-themes/react-easy-email-theme-green/css/arco.css'; +import { useSession } from 'next-auth/react'; +import { CommercialBanner } from '@/client/components/CommercialBanner'; + +const defaultCategories: ExtensionProps['categories'] = [ + { + label: 'Content', + active: true, + blocks: [ + { + type: AdvancedType.TEXT, + }, + { + type: AdvancedType.IMAGE, + payload: { attributes: { padding: '0px 0px 0px 0px' } }, + }, + { + type: AdvancedType.BUTTON, + }, + { + type: AdvancedType.SOCIAL, + }, + { + type: AdvancedType.DIVIDER, + }, + { + type: AdvancedType.SPACER, + }, + { + type: AdvancedType.HERO, + }, + { + type: AdvancedType.WRAPPER, + }, + ], + }, + { + label: 'Layout', + active: true, + displayType: 'column', + blocks: [ + { + title: '2 columns', + payload: [ + ['50%', '50%'], + ['33%', '67%'], + ['67%', '33%'], + ['25%', '75%'], + ['75%', '25%'], + ], + }, + { + title: '3 columns', + payload: [ + ['33.33%', '33.33%', '33.33%'], + ['25%', '25%', '50%'], + ['50%', '25%', '25%'], + ], + }, + { + title: '4 columns', + payload: [['25%', '25%', '25%', '25%']], + }, + ], + }, +]; + +export default function App() { + const { width } = useWindowSize(); + const [isDarkMode, setIsDarkMode] = useState(false); + const [theme, setTheme] = useState<'blue' | 'green' | 'purple'>('blue'); + const [locale, setLocale] = useState('en'); + const { + modal: mergeTagsModal, + openModal: openMergeTagsModal, + mergeTags, + setMergeTags, + } = useMergeTagsModal(testMergeTags); + + const session = useSession(); + const user = session.data?.user; + + const smallScene = width < 1400; + const router = useRouter(); + const id = router.query.id; + + const { data: template, fetching } = useGetEmailTemplateQuery({ + id: id as string, + }); + + const { fetching: updateLoading, updateEmailTemplateMutation } = + useUpdateEmailTemplateMutation(); + + useEffect(() => { + if (isDarkMode) { + document.body.setAttribute('arco-theme', 'dark'); + } else { + document.body.removeAttribute('arco-theme'); + } + }, [isDarkMode]); + + const themeStyleText = useMemo(() => { + if (theme === 'green') return greenTheme; + if (theme === 'purple') return purpleTheme; + return blueTheme; + }, [theme]); + + const onSubmit: Config['onSubmit'] = async values => { + try { + pushEvent({ + event: 'Save-Email', + }); + await updateEmailTemplateMutation({ + id: template!.id, + data: { + subject: values.subject, + content: values.content, + thumbnail: template!.thumbnail, + }, + }); + Message.success('Save succeed'); + } catch (error) { + Message.error(String(error)); + } + }; + + const onExportImage = async (values: IEmailTemplate) => { + Message.loading('Loading...'); + const html2canvas = (await import('html2canvas')).default; + const container = document.createElement('div'); + container.style.position = 'absolute'; + container.style.left = '-9999px'; + const mjmlString = JsonToMjml({ + data: values.content, + mode: 'production', + context: values.content, + dataSource: mergeTags, + }); + + const html = mjml(mjmlString, {}).html; + + container.innerHTML = html; + document.body.appendChild(container); + + const blob = await new Promise(resolve => { + html2canvas(container, { useCORS: true }).then(canvas => { + return canvas.toBlob(resolve, 'png', 0.1); + }); + }); + saveAs(blob, 'demo.png'); + Message.clear(); + }; + + const onChangeTheme = useCallback(t => { + setTheme(t); + }, []); + + const onExportMJML = (values: IEmailTemplate) => { + pushEvent({ + event: 'ExportMJM', + }); + const mjmlString = JsonToMjml({ + data: values.content, + mode: 'production', + context: values.content, + dataSource: mergeTags, + }); + + pushEvent({ event: 'MJMLExport', payload: { values, mergeTags } }); + navigator.clipboard.writeText(mjmlString); + saveAs(new Blob([mjmlString], { type: 'text/mjml' }), 'easy-email.mjml'); + }; + + const onExportHTML = (values: IEmailTemplate) => { + pushEvent({ + event: 'ExportHTML', + }); + const mjmlString = JsonToMjml({ + data: values.content, + mode: 'production', + context: values.content, + dataSource: mergeTags, + }); + + const html = mjml(mjmlString, {}).html; + + pushEvent({ event: 'HTMLExport', payload: { values, mergeTags } }); + navigator.clipboard.writeText(html); + saveAs(new Blob([html], { type: 'text/html' }), 'easy-email.html'); + }; + + const onExportJSON = (values: IEmailTemplate) => { + pushEvent({ + event: 'ExportJSON', + }); + navigator.clipboard.writeText(JSON.stringify(values, null, 2)); + saveAs( + new Blob([JSON.stringify(values, null, 2)], { type: 'application/json' }), + 'easy-email.json', + ); + }; + + const onImportMJML = async ({ + restart, + }: { + restart: (val: IEmailTemplate) => void; + }) => { + pushEvent({ + event: 'ImportMJM', + }); + const uploader = new Uploader(() => Promise.resolve(''), { + accept: 'text/mjml', + limit: 1, + }); + + const [file] = await uploader.chooseFile(); + const reader = new FileReader(); + const pageData = await new Promise<[string, IEmailTemplate['content']]>( + (resolve, reject) => { + reader.onload = function (evt) { + if (!evt.target) { + reject(); + return; + } + try { + const pageData = MjmlToJson(evt.target.result as any); + resolve([file.name, pageData]); + } catch (error) { + reject(); + } + }; + reader.readAsText(file); + }, + ); + + restart({ + subject: pageData[0], + content: pageData[1], + subTitle: '', + }); + }; + + const onImportJSON = async ({ + restart, + }: { + restart: (val: IEmailTemplate) => void; + }) => { + pushEvent({ + event: 'ImportJSON', + }); + const uploader = new Uploader(() => Promise.resolve(''), { + accept: 'application/json', + limit: 1, + }); + + const [file] = await uploader.chooseFile(); + const reader = new FileReader(); + const emailTemplate = await new Promise((resolve, reject) => { + reader.onload = function (evt) { + if (!evt.target) { + reject(); + return; + } + try { + const template = JSON.parse(evt.target.result as any) as IEmailTemplate; + resolve(template); + } catch (error) { + reject(); + } + }; + reader.readAsText(file); + }); + + restart({ + subject: emailTemplate.subject, + content: emailTemplate.content, + subTitle: emailTemplate.subTitle, + }); + }; + + if (!template || !user) return ; + + return ( + <> + + + {({ values }, { submit, restart }) => { + return ( + <> + router.push('/')} + extra={ + + {/* */} + + + + + {/* */} + + + onImportMJML({ restart })} + > + Import from MJML + + + onImportJSON({ restart })} + > + Import from JSON + + + } + > + + + + + onExportMJML(values)} + > + Export MJML + + onExportHTML(values)} + > + Export HTML + + onExportJSON(values)} + > + Export JSON + + onExportImage(values)} + > + Export Image + + + } + > + + + + + { + ev.preventDefault(); + pushEvent({ + event: 'Donate', + payload: { + user: user.email!, + }, + }); + window.open( + 'https://www.buymeacoffee.com/easyemail?utm_source=webside&utm_medium=button&utm_content=donate', + '_blank', + ); + }} + > + Buy Me A Coffee + + + } + /> + + + + + + ); + }} + + + ); +} diff --git a/nextjs-demo/client/pages/Emails/Editor/testMergeTags.ts b/nextjs-demo/client/pages/Emails/Editor/testMergeTags.ts new file mode 100644 index 000000000..1292adc2a --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Editor/testMergeTags.ts @@ -0,0 +1,165 @@ +export const testMergeTags = { + user: { + name: 'Ryan', + age: 26, + avatar: + 'http://res.cloudinary.com/dwkp0e1yo/image/upload/v1665841428/pnmyosjz0x0kmqlfxhrp.png', + email: 'easy-email@gmail.com', + project: 'Easy email', + }, + date: { + today: new Date().toDateString(), + }, + emptyList: [], + product_list: [ + { + id: 0, + image: + 'http://res.cloudinary.com/dwkp0e1yo/image/upload/v1665841462/l2hayusrfwffltdc105o.png', + title: 'Slim Fit Printed shirt', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 1, + image: + 'http://res.cloudinary.com/dwkp0e1yo/image/upload/v1665841503/uxkaqveakixnt5nvhnyf.png', + title: 'Casual Collar Youth Handsome', + price: '$39.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 2, + image: + 'http://res.cloudinary.com/dwkp0e1yo/image/upload/v1665841540/gc0dec0hisoyp0t2hgaf.png', + title: 'Shirt Business Casual', + price: '$49.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 3, + image: + 'http://res.cloudinary.com/dwkp0e1yo/image/upload/v1665841462/l2hayusrfwffltdc105o.png', + title: 'Slim Fit Printed shirt', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 4, + image: + 'http://res.cloudinary.com/dwkp0e1yo/image/upload/v1665841503/uxkaqveakixnt5nvhnyf.png', + title: 'Casual Collar Youth Handsome', + price: '$39.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 5, + image: + 'http://res.cloudinary.com/dwkp0e1yo/image/upload/v1665841540/gc0dec0hisoyp0t2hgaf.png', + title: 'Shirt Business Casual', + price: '$49.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + ], + company: { + name: 'Easy email', + member_list: [ + { + id: 1, + name: 'James', + hobby: 'Swimming', + age: 28, + product_list: [ + { + id: 0, + image: + 'https://assets.maocanhua.cn/da9b173d-b272-4101-aa25-4635ed95e9e3-image.png', + title: 'Slim Fit Printed shirt', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 1, + image: + 'https://assets.maocanhua.cn/4ef7cb65-ee1f-4b12-832c-17ab07a8b9ac-image.png', + title: 'Casual Collar Youth Handsome Slim Print Blazer', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 2, + image: + 'https://assets.maocanhua.cn/88fe9bfa-547f-4d5e-9ba5-ac6b91572dde-image.png', + title: 'Shirt Business Casual', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + ], + }, + { + id: 2, + name: 'Nick', + hobby: 'Coding', + age: 29, + product_list: [ + { + id: 0, + image: + 'https://assets.maocanhua.cn/da9b173d-b272-4101-aa25-4635ed95e9e3-image.png', + title: 'Slim Fit Printed shirt', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 1, + image: + 'https://assets.maocanhua.cn/4ef7cb65-ee1f-4b12-832c-17ab07a8b9ac-image.png', + title: 'Casual Collar Youth Handsome Slim Print Blazer', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 2, + image: + 'https://assets.maocanhua.cn/88fe9bfa-547f-4d5e-9ba5-ac6b91572dde-image.png', + title: 'Shirt Business Casual', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + ], + }, + { + id: 3, + name: 'Robert', + hobby: 'skiing', + age: 30, + product_list: [ + { + id: 0, + image: + 'https://assets.maocanhua.cn/da9b173d-b272-4101-aa25-4635ed95e9e3-image.png', + title: 'Slim Fit Printed shirt', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 1, + image: + 'https://assets.maocanhua.cn/4ef7cb65-ee1f-4b12-832c-17ab07a8b9ac-image.png', + title: 'Casual Collar Youth Handsome Slim Print Blazer', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + { + id: 2, + image: + 'https://assets.maocanhua.cn/88fe9bfa-547f-4d5e-9ba5-ac6b91572dde-image.png', + title: 'Shirt Business Casual', + price: '$59.99 HKD', + url: 'https://easy-email-m-ryan.vercel.app', + }, + ], + }, + ], + }, +}; diff --git a/nextjs-demo/client/pages/Emails/Templates/index.tsx b/nextjs-demo/client/pages/Emails/Templates/index.tsx new file mode 100644 index 000000000..120a4a2ae --- /dev/null +++ b/nextjs-demo/client/pages/Emails/Templates/index.tsx @@ -0,0 +1,194 @@ +import { CommercialBanner } from '@/client/components/CommercialBanner'; +import { + useCreateEmailTemplateMutation, + useDeleteEmailTemplateMutation, + useGetEmailTemplatesQuery, +} from '@/client/hooks'; +import { + Button, + Card, + Divider, + Dropdown, + Grid, + Layout, + Menu, + Message, + PageHeader, + Table, + TableColumnProps, +} from '@arco-design/web-react'; +import { IconMoreVertical } from '@arco-design/web-react/icon'; +import { EmailTemplate } from '@prisma/client'; +import Link from 'next/link'; + +function Index() { + const { fetching, data, getEmailTemplatesQuery } = useGetEmailTemplatesQuery(); + + const { fetching: deleteLoading, deleteEmailTemplateMutation } = + useDeleteEmailTemplateMutation(); + + const { fetching: createFetching, createEmailTemplateMutation } = + useCreateEmailTemplateMutation(); + + const onCreate = async (item: EmailTemplate) => { + try { + const data = await createEmailTemplateMutation({ + subject: item.subject + '-Copy', + thumbnail: item.thumbnail, + content: item.content as any, + }); + if (data.id) { + getEmailTemplatesQuery(); + } + } catch (error) { + Message.error(String(error)); + } + }; + + const onDeleteItem = async (id: string) => { + try { + await deleteEmailTemplateMutation({ id }); + getEmailTemplatesQuery(); + } catch (error) {} + }; + + const columns: TableColumnProps[] = [ + { + title: 'Name', + width: 150, + render(col, item, index) { + return ( + + + + {item.subject} + + + + ); + }, + }, + { + title: 'Thumbnail', + render(col, item, index) { + return ( + +
+ + ); + }, + }, + { + title: 'Created At', + dataIndex: 'createdAt', + render(col, item, index) { + return
{new Date(col).toLocaleString()}
; + }, + }, + { + title: 'Updated At', + dataIndex: 'updatedAt', + render(col, item, index) { + return
{new Date(col).toLocaleString()}
; + }, + }, + { + title: '', + render(col, item, index) { + const droplist = ( + + + Edit + + { + onCreate(item); + }} + > + Clone + + + { + onDeleteItem(item.id); + }} + > + Delete + + + ); + + return ( + + + + ); + }, + }, + ]; + + const list = data || []; + + return ( + <> +
+ +
+ + + + + Create Template + + } + /> + + + + record.id} + columns={columns} + data={list} + loading={deleteLoading || fetching} + /> + + + + + ); +} + +export default Index; diff --git a/nextjs-demo/client/pages/Login/index.css b/nextjs-demo/client/pages/Login/index.css new file mode 100644 index 000000000..e2332b3c5 --- /dev/null +++ b/nextjs-demo/client/pages/Login/index.css @@ -0,0 +1,579 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body, +html { + height: 100%; + font-family: Poppins-Regular, sans-serif; +} + +a { + font-size: 14px; + line-height: 1.7; + color: #666; + margin: 0; + transition: all 0.4s; + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + -moz-transition: all 0.4s; + text-decoration: none; +} + +a:focus { + outline: none !important; +} + +a:hover { + text-decoration: none; + color: #a64bf4; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; +} + +p { + font-size: 14px; + line-height: 1.7; + color: #666; + margin: 0; +} + +ul, +li { + margin: 0; + list-style-type: none; +} + +input { + outline: none; + border: none; +} + +textarea { + outline: none; + border: none; +} + +textarea:focus, +input:focus { + border-color: transparent !important; +} + +input:focus::-webkit-input-placeholder { + color: transparent; +} + +input:focus:-moz-placeholder { + color: transparent; +} + +input:focus::-moz-placeholder { + color: transparent; +} + +input:focus:-ms-input-placeholder { + color: transparent; +} + +textarea:focus::-webkit-input-placeholder { + color: transparent; +} + +textarea:focus:-moz-placeholder { + color: transparent; +} + +textarea:focus::-moz-placeholder { + color: transparent; +} + +textarea:focus:-ms-input-placeholder { + color: transparent; +} + +input::-webkit-input-placeholder { + color: #adadad; +} + +input:-moz-placeholder { + color: #adadad; +} + +input::-moz-placeholder { + color: #adadad; +} + +input:-ms-input-placeholder { + color: #adadad; +} + +textarea::-webkit-input-placeholder { + color: #adadad; +} + +textarea:-moz-placeholder { + color: #adadad; +} + +textarea::-moz-placeholder { + color: #adadad; +} + +textarea:-ms-input-placeholder { + color: #adadad; +} + +button { + outline: none !important; + border: none; + background: 0 0; +} + +button:hover { + cursor: pointer; +} + +iframe { + border: none !important; +} + +.txt1 { + font-size: 14px; + line-height: 1.5; + color: #666; +} + +.txt2 { + font-size: 14px; + line-height: 1.5; + color: #333; + text-transform: uppercase; +} + +.bg1 { + background-color: #3b5998; +} + +.bg2 { + background-color: #1da1f2; +} + +.bg3 { + background-color: #ea4335; +} + +.limiter { + width: 100%; + margin: 0 auto; +} + +.container-login100 { + width: 100%; + min-height: 100vh; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + background-repeat: no-repeat; + background-position: center; + background-size: cover; +} + +.wrap-login100 { + width: 500px; + background: #fff; + border-radius: 10px; + overflow: hidden; + padding: 55px; +} + +.login100-form { + width: 100%; +} + +.login100-form-title { + display: block; + font-family: Poppins-Bold; + font-size: 39px; + color: #333; + line-height: 1.2; + text-align: center; +} + +.wrap-input100 { + width: 100%; + position: relative; + border-bottom: 2px solid #d9d9d9; +} + +.label-input100 { + font-size: 14px; + color: #333; + line-height: 1.5; + padding-left: 7px; +} + +.input100 { + font-family: Poppins-Medium; + font-size: 16px; + color: #333; + line-height: 1.2; + display: block; + width: 100%; + height: 55px; + background: 0 0; + padding: 0 7px 0 43px; +} + +.focus-input100 { + position: absolute; + display: block; + width: 100%; + height: 100%; + top: 0; + left: 0; + pointer-events: none; +} + +.focus-input100::after { + content: attr(data-symbol); + font-family: Material-Design-Iconic-Font; + color: #adadad; + font-size: 22px; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + height: calc(100% - 20px); + bottom: 0; + left: 0; + padding-left: 13px; + padding-top: 3px; +} + +.focus-input100::before { + content: ''; + display: block; + position: absolute; + bottom: -2px; + left: 0; + width: 0; + height: 2px; + background: #7f7f7f; + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + -moz-transition: all 0.4s; + transition: all 0.4s; +} + +.input100:focus + .focus-input100::before { + width: 100%; +} + +.has-val.input100 + .focus-input100::before { + width: 100%; +} + +.input100:focus + .focus-input100::after { + color: #a64bf4; +} + +.has-val.input100 + .focus-input100::after { + color: #a64bf4; +} + +.container-login100-form-btn { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.wrap-login100-form-btn { + width: 100%; + display: block; + position: relative; + z-index: 1; + border-radius: 25px; + overflow: hidden; + margin: 0 auto; + box-shadow: 0 5px 30px 0 rgba(3, 216, 222, 0.2); + -moz-box-shadow: 0 5px 30px 0 rgba(3, 216, 222, 0.2); + -webkit-box-shadow: 0 5px 30px 0 rgba(3, 216, 222, 0.2); + -o-box-shadow: 0 5px 30px 0 rgba(3, 216, 222, 0.2); + -ms-box-shadow: 0 5px 30px 0 rgba(3, 216, 222, 0.2); +} + +.login100-form-bgbtn { + position: absolute; + z-index: -1; + width: 300%; + height: 100%; + background: #a64bf4; + background: -webkit-linear-gradient(right, #00dbde, #fc00ff, #00dbde, #fc00ff); + background: -o-linear-gradient(right, #00dbde, #fc00ff, #00dbde, #fc00ff); + background: -moz-linear-gradient(right, #00dbde, #fc00ff, #00dbde, #fc00ff); + background: linear-gradient(right, #00dbde, #fc00ff, #00dbde, #fc00ff); + top: 0; + left: -100%; + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + -moz-transition: all 0.4s; + transition: all 0.4s; +} + +.login100-form-btn { + font-family: Poppins-Medium; + font-size: 16px; + color: #fff; + line-height: 1.2; + text-transform: uppercase; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + justify-content: center; + align-items: center; + padding: 0 20px; + width: 100%; + height: 50px; +} + +.wrap-login100-form-btn:hover .login100-form-bgbtn { + left: 0; +} + +.validate-input { + position: relative; +} + +.alert-validate::before { + content: attr(data-validate); + position: absolute; + max-width: 70%; + background-color: #fff; + border: 1px solid #c80000; + border-radius: 2px; + padding: 4px 25px 4px 10px; + bottom: calc((100% - 20px) / 2); + -webkit-transform: translateY(50%); + -moz-transform: translateY(50%); + -ms-transform: translateY(50%); + -o-transform: translateY(50%); + transform: translateY(50%); + right: 2px; + pointer-events: none; + color: #c80000; + font-size: 13px; + line-height: 1.4; + text-align: left; + visibility: hidden; + opacity: 0; + -webkit-transition: opacity 0.4s; + -o-transition: opacity 0.4s; + -moz-transition: opacity 0.4s; + transition: opacity 0.4s; +} + +.alert-validate::after { + content: '\f06a'; + font-family: FontAwesome; + display: block; + position: absolute; + color: #c80000; + font-size: 16px; + bottom: calc((100% - 20px) / 2); + -webkit-transform: translateY(50%); + -moz-transform: translateY(50%); + -ms-transform: translateY(50%); + -o-transform: translateY(50%); + transform: translateY(50%); + right: 8px; +} + +.alert-validate:hover:before { + visibility: visible; + opacity: 1; +} + +@media (max-width: 992px) { + .alert-validate::before { + visibility: visible; + opacity: 1; + } +} + +.login100-social-item { + font-size: 25px; + color: #fff; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -ms-flexbox; + display: flex; + justify-content: center; + align-items: center; + width: 50px; + height: 50px; + border-radius: 50%; + margin: 5px; +} + +.login100-social-item:hover { + color: #fff; + background-color: #333; +} + +@media (max-width: 576px) { + .wrap-login100 { + padding-left: 15px; + padding-right: 15px; + } +} + +/* icon font */ + +@font-face { + font-family: 'FontAwesome'; + src: url('https://colorlib.com/etc/lf/Login_v4/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2?v=4.7.0'); + font-weight: normal; + font-style: normal; +} + +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} + +.fa-2x { + font-size: 2em; +} + +.fa-3x { + font-size: 3em; +} + +.fa-4x { + font-size: 4em; +} + +.fa-5x { + font-size: 5em; +} + +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.fa-facebook-square:before { + content: '\f082'; +} + +.fa-phone:before { + content: '\f095'; +} + +.fa-twitter:before { + content: '\f099'; +} + +.fa-facebook:before { + content: '\f09a'; +} + +.fa-google:before { + content: '\f1a0'; +} + +.fa-github:before { + content: '\f09b'; +} + +.flex-left { + width: 50%; + flex: 1; +} + +.flex-right { + width: 50%; + flex: 1; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background-color: #f5f5f5; + flex-direction: column; + position: relative; +} +.logo { + position: absolute; + top: 30px; + left: 30px; +} +.logo img { + width: 230px; +} + +.detail-container { + max-width: 1272px; + margin-left: auto; + margin-right: auto; + padding-left: 36px; + padding-right: 36px; + display: block; +} + +.div-block { + justify-content: flex-start; + align-items: center; + margin-bottom: 10px; + font-family: Open Sans, sans-serif; + display: flex; +} + +.image-3 { + max-width: 20px; + margin-right: 14px; +} +.content-pair.content-pair-reverse { +} +.content-pair { + min-height: 500px; + justify-content: space-around; + align-items: center; + padding-top: 20px; + padding-bottom: 20px; + display: flex; + flex-direction: column; +} +.card-image-wrapper { + margin-top: 20px; +} diff --git a/nextjs-demo/client/pages/Login/index.tsx b/nextjs-demo/client/pages/Login/index.tsx new file mode 100644 index 000000000..b19e1cfab --- /dev/null +++ b/nextjs-demo/client/pages/Login/index.tsx @@ -0,0 +1,63 @@ +import React, { useEffect } from 'react'; +import styleText from '!!raw-loader!./index.css'; +import { getProviders, signIn, ClientSafeProvider, useSession } from 'next-auth/react'; + +export default function Login() { + const { data, status } = useSession(); + + console.log(status === 'authenticated' && data.user); + + useEffect(() => { + if (status === 'authenticated' && data.user) { + window.location.href = '/'; + } + }, [status]); + + if (status === 'authenticated' && data.user) return null; + + return ( + <> + + + + ); +} diff --git a/nextjs-demo/client/utils/Uploader.ts b/nextjs-demo/client/utils/Uploader.ts new file mode 100644 index 000000000..181168b84 --- /dev/null +++ b/nextjs-demo/client/utils/Uploader.ts @@ -0,0 +1,214 @@ +import { uniqueId } from "lodash"; + +interface Options { + limit?: number; + accept?: string; + minSize?: number; + maxSize?: number; + autoUpload?: boolean; +} +interface UploaderOption extends Options { + limit: number; +} + +export type UploadItem = { + idx: string; + url: string; + status: "pending" | "done" | "error"; +}; + +export type UploaderEventMap = { + start: (data: UploadItem[]) => void; + progress: (data: UploadItem[]) => void; + end: (data: UploadItem[]) => void; +}; + +type UploaderEventMapHandle = { + [K in keyof UploaderEventMap]: UploaderEventMap[K][]; +}; + +export type UploaderServer = (file: File) => Promise; + +export class Uploader { + private options: UploaderOption; + private el: HTMLInputElement; + private uploadServer: UploaderServer; + private handler: UploaderEventMapHandle = { + start: [], + progress: [], + end: [], + }; + + constructor(uploadServer: UploaderServer, options: Options) { + this.options = { + limit: 1, + autoUpload: true, + ...options, + }; + this.uploadServer = uploadServer; + this.el = this.createInput(); + } + + private createInput() { + if (typeof document === "undefined") return {} as any; + Array.from(document.querySelectorAll(".uploader-form-input")).forEach( + (el) => { + el && document.body.removeChild(el); + } + ); + const el = document.createElement("input"); + el.className = "uploader-form-input"; + el.type = "file"; + el.style.display = "block"; + el.style.opacity = "0"; + el.style.width = "0"; + el.style.height = "0"; + el.style.position = "absolute"; + el.style.top = "0"; + el.style.left = "0"; + el.style.overflow = "hidden"; + el.multiple = this.options.limit > 1; + if (this.options.accept) { + el.accept = this.options.accept; + } + return el; + } + + public async uploadFiles(files: File[]) { + const results = files.map((file) => ({ file })); + const uploadList: UploadItem[] = results.map((item) => ({ + url: "", + status: "pending", + idx: `uploader-${uniqueId()}`, + })); + + // 开始上传 + this.handler.start.map((fn) => fn(uploadList)); + + await PromiseEach( + results.map(async (file, index) => { + try { + const url = await this.uploadFile(file); + uploadList[index].url = url; + uploadList[index].status = "done"; + } catch (error) { + uploadList[index].status = "error"; + } finally { + this.handler.progress.map((fn) => fn(uploadList)); + } + }) + ); + + // 上传完成 + this.handler.end.map((fn) => fn(uploadList)); + } + + private async uploadFile(result: { file: File }) { + return this.uploadServer(result.file); + } + + private checkFile(files: File[]) { + const typeError = this.checkTypes(files); + if (typeError) { + throw new Error(typeError); + } + + const sizeError = this.checkSize(files); + if (sizeError) { + throw new Error(sizeError); + } + } + + private checkTypes(files: File[]) { + const accept = this.options.accept; + if (accept) { + let fileType = ""; + if (accept.indexOf("image") !== -1) { + fileType = "image"; + } else if (accept.indexOf("video") !== -1) { + fileType = "video"; + } + for (const file of files) { + if (file.type.indexOf(fileType) !== 0) { + return "上传文件类型错误!"; + } + } + } + return null; + } + + private checkSize(files: File[]) { + const options = this.options; + for (const file of files) { + if (options.minSize && file.size < options.minSize) { + return `上传文件不能小于 ${options.minSize}`; + } + if (options.maxSize && file.size > options.maxSize) { + return `上传文件不能小于 ${options.maxSize}`; + } + } + return null; + } + + public chooseFile() { + return new Promise((resolve) => { + const el = this.el; + document.body.appendChild(el); + el.click(); + + el.onchange = async (e: any) => { + let files = e.target.files || []; + files = Array.prototype.slice.call(files); + if (files.length === 0) { + return; + } + this.checkFile(files); + if (this.options.autoUpload) { + this.uploadFiles(files); + } + el.onchange = null; + el.parentNode && el.parentNode.removeChild(el); + resolve(files); + }; + }); + } + + public on( + event: K, + fn: UploaderEventMap[K] + ) { + // UploaderEventMapHandle[K] === UploaderEventMap[K][] + const handler = this.handler[event] as UploaderEventMap[K][]; + handler.push(fn); + } + + public off( + event: K, + fn: UploaderEventMap[K] + ) { + const handles = this.handler[event] as UploaderEventMap[K][]; + this.handler[event] = handles.filter( + (item) => item !== fn + ) as UploaderEventMapHandle[K]; + } +} + +function PromiseEach(promiseLikes: PromiseLike[]) { + const datas: Array = []; + let count = 0; + return new Promise((resolve) => { + promiseLikes.forEach(async (promiseLike) => { + try { + const data = await promiseLike; + datas.push(data); + } catch (error) { + datas.push(error); + } finally { + count++; + if (count === promiseLikes.length) { + resolve(true); + } + } + }); + }); +} diff --git a/nextjs-demo/client/utils/cookie.ts b/nextjs-demo/client/utils/cookie.ts new file mode 100644 index 000000000..d85de2426 --- /dev/null +++ b/nextjs-demo/client/utils/cookie.ts @@ -0,0 +1,17 @@ +export function setCookie(name: string, value: string, timeout: number) { + const d = new Date(); + d.setTime(d.getTime() + timeout * 1000); + const expires = "expires=" + d.toUTCString(); + document.cookie = name + "=" + value + ";" + expires + ""; +} + +export function getCookie(key: string) { + let value = ""; + document.cookie.split(";").forEach((item) => { + const name = item.split("=")[0]; + if (name.trim() === key) { + value = item.replace(`${name}=`, ""); + } + }); + return value; +} diff --git a/nextjs-demo/client/utils/isDevelopment.ts b/nextjs-demo/client/utils/isDevelopment.ts new file mode 100644 index 000000000..a440fd19b --- /dev/null +++ b/nextjs-demo/client/utils/isDevelopment.ts @@ -0,0 +1 @@ +export const isDevelopment = process.env.NODE_ENV === 'development'; diff --git a/nextjs-demo/client/utils/posthog.ts b/nextjs-demo/client/utils/posthog.ts new file mode 100644 index 000000000..7d2ab8ee8 --- /dev/null +++ b/nextjs-demo/client/utils/posthog.ts @@ -0,0 +1,10 @@ +import posthog from 'posthog-js'; +import { isDevelopment } from './isDevelopment'; + +if (!isDevelopment) { + posthog.init('phc_RSmDefyNq21bbg6QZ4GzxfkbF5Aso1YqG5yUQvPaxBV', { + api_host: 'https://app.posthog.com', + }); +} + +export { posthog }; diff --git a/nextjs-demo/client/utils/pushEvent.ts b/nextjs-demo/client/utils/pushEvent.ts new file mode 100644 index 000000000..dfc79842d --- /dev/null +++ b/nextjs-demo/client/utils/pushEvent.ts @@ -0,0 +1,12 @@ +import { posthog } from './posthog'; + +export function pushEvent(params: { event: string; payload?: Record }) { + const dataLayer = (window as any).dataLayer as any[]; + if (!dataLayer) return; + + dataLayer.push({ + event: params.event, + payload: params.payload, + }); + posthog.capture(params.event, params.payload); +} diff --git a/nextjs-demo/declaration.d.ts b/nextjs-demo/declaration.d.ts new file mode 100644 index 000000000..f55ea1618 --- /dev/null +++ b/nextjs-demo/declaration.d.ts @@ -0,0 +1,26 @@ +declare module '*.svg' { + const content: { src: string }; + export default content; +} + +declare module '*.less' { + const classes: { [className: string]: string }; + export default classes; +} +declare module '!!raw-loader!*.css' { + const content: string; + export default content; +} + +declare module '*/settings.json' { + const value: { + colorWeek: boolean; + navbar: boolean; + menu: boolean; + footer: boolean; + themeColor: string; + menuWidth: number; + }; + + export default value; +} diff --git a/nextjs-demo/docker-compose.yml b/nextjs-demo/docker-compose.yml new file mode 100644 index 000000000..95909f109 --- /dev/null +++ b/nextjs-demo/docker-compose.yml @@ -0,0 +1,14 @@ +version: "3.7" +services: + postgres: + image: postgres:latest + restart: always + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + ports: + - "5432:5432" + volumes: + - postgres:/var/lib/postgresql/data +volumes: + postgres: diff --git a/nextjs-demo/next-env.d.ts b/nextjs-demo/next-env.d.ts new file mode 100644 index 000000000..4f11a03dc --- /dev/null +++ b/nextjs-demo/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/nextjs-demo/next.config.js b/nextjs-demo/next.config.js new file mode 100644 index 000000000..b4c91d0c7 --- /dev/null +++ b/nextjs-demo/next.config.js @@ -0,0 +1,20 @@ +const path = require('path'); +const withLess = require('next-with-less'); + +module.exports = withLess((phase, { defaultConfig }) => { + /** + * @type {import('next').NextConfig} + */ + const config = { + resolve: { + alias: {}, + }, + }; + config.resolve.alias['@/client'] = path.resolve(__dirname, './src/client'); + config.resolve.alias['react'] = path.resolve('./node_modules/react'); + config.resolve.alias['react-dom'] = path.resolve('./node_modules/react-dom'); + config.resolve.alias['@arco-design/web-react'] = path.resolve( + './node_modules/@arco-design/web-react', + ); + return config; +}); diff --git a/nextjs-demo/package.json b/nextjs-demo/package.json new file mode 100644 index 000000000..7a7a58c4b --- /dev/null +++ b/nextjs-demo/package.json @@ -0,0 +1,56 @@ +{ + "name": "easy-email-nextjs-demo", + "version": "1.0.0", + "description": "", + "keywords": [], + "license": "MIT", + "author": "", + "scripts": { + "dev": "next", + "build": "npx prisma generate && next build", + "start": "next start", + "db:up": "docker-compose up -d", + "db:down": "docker-compose down" + }, + "dependencies": { + "@arco-design/web-react": "^2.53.1", + "@arco-themes/react-easy-email-theme": "^0.0.3", + "@arco-themes/react-easy-email-theme-green": "^0.0.1", + "@arco-themes/react-easy-email-theme-purple": "^0.0.3", + "@next-auth/prisma-adapter": "1.0.7", + "@prisma/client": "4.2.0z", + "@types/passport-google-oauth20": "^2.0.12", + "@types/react-dom": "^18.2.7", + "axios": "^1.5.0", + "classnames": "^2.3.2", + "dayjs": "^1.11.9", + "easy-email-core": "^4.12.2", + "easy-email-editor": "^4.12.2", + "easy-email-extensions": "^4.14.1", + "final-form": "^4.20.10", + "google": "link:next-auth/providers/google", + "html2canvas": "^1.4.1", + "less": "^4.2.0", + "less-loader": "^11.1.3", + "next": "12.1.4", + "next-auth": "4.3.1", + "next-prisma-plugin-webpack5": "0.0.0-dripip", + "next-with-less": "^3.0.1", + "passport-google-oauth20": "^2.0.0", + "query-string": "^8.1.0", + "raw-loader": "^4.0.2", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-final-form": "^6.5.9", + "react-markdown": "8.0.2", + "react-use": "^17.4.0" + }, + "devDependencies": { + "@types/next-auth": "3.13.0", + "@types/node": "16.11.26", + "@types/react": "17.0.44", + "prisma": "4.2.0z", + "ts-node": "10.7.0", + "typescript": "4.6.3" + } +} diff --git a/nextjs-demo/pages/_app.tsx b/nextjs-demo/pages/_app.tsx new file mode 100644 index 000000000..88c00b9f7 --- /dev/null +++ b/nextjs-demo/pages/_app.tsx @@ -0,0 +1,68 @@ +import { SessionProvider } from 'next-auth/react'; + +import './global.less'; // 注意顺序,放后面可能会覆盖组件样式 +import '@arco-themes/react-easy-email-theme/css/arco.css'; +import type { AppProps } from 'next/app'; +import Layout from '../client/components/Layout'; +import { useRouter } from 'next/router'; +import Script from 'next/script'; +import enUS from '@arco-design/web-react/es/locale/en-US'; +import { ConfigProvider } from '@arco-design/web-react'; +import Head from 'next/head'; +const publicPages = ['/login']; + +function CustomApp({ + Component, + pageProps, +}: AppProps & { + pageProps: any; + Component: React.FC & { + hideSidebar?: boolean; + hideNavbar?: boolean; + hideLayout?: boolean; + }; +}) { + const router = useRouter(); + const pathname = router.pathname; + + const isPublicPage = publicPages.includes(pathname); + + return ( + + + + + + {isPublicPage ? ( + + ) : ( + <> + {Component?.hideLayout ? ( + + ) : ( + + + + )} + + )} + + + ); +} + +// CustomApp.getInitialProps = async (appContext: AppContext) => { +// return { props: { ...appContext.Component.getInitialProps } }; +// }; + +export default CustomApp; diff --git a/nextjs-demo/pages/api/auth/[...nextauth].ts b/nextjs-demo/pages/api/auth/[...nextauth].ts new file mode 100644 index 000000000..679d12166 --- /dev/null +++ b/nextjs-demo/pages/api/auth/[...nextauth].ts @@ -0,0 +1,40 @@ +import { NextApiHandler } from 'next'; +import NextAuth from 'next-auth'; +import GitHubProvider from 'next-auth/providers/github'; +import { PrismaAdapter } from './prisma-adapter'; +import GoogleProvider from 'next-auth/providers/google'; +import prisma from 'prisma/prisma'; + +const authHandler: NextApiHandler = (req, res) => + NextAuth(req, res, { + providers: [ + GitHubProvider({ + clientId: process.env.GITHUB_ID, + clientSecret: process.env.GITHUB_SECRET, + }), + GoogleProvider({ + clientId: process.env.GOOGLE_CLIENT_ID!, + clientSecret: process.env.GOOGLE_CLIENT_SECRET!, + }), + ], + adapter: PrismaAdapter(prisma), + secret: process.env.SECRET, + session: { + strategy: 'jwt', + }, + callbacks: { + session: async ({ session, token }: { session: any; token: any }) => { + if (session?.user) { + session.user.id = token.uid; + } + return session; + }, + jwt: async ({ user, token }: { user: any; token: any }) => { + if (user) { + token.uid = user.id; + } + return token; + }, + }, + } as any); +export default authHandler; diff --git a/nextjs-demo/pages/api/auth/prisma-adapter.ts b/nextjs-demo/pages/api/auth/prisma-adapter.ts new file mode 100644 index 000000000..05979a9ff --- /dev/null +++ b/nextjs-demo/pages/api/auth/prisma-adapter.ts @@ -0,0 +1,71 @@ +import type { PrismaClient, Prisma } from '@prisma/client'; +import { omit, pick } from 'lodash'; +import type { Adapter } from 'next-auth/adapters'; + +export function PrismaAdapter(p: PrismaClient): Adapter { + return { + createUser: data => p.user.create({ data: omit(data, 'loginType') }), // 改了这里 + getUser: id => p.user.findUnique({ where: { id } }), + getUserByEmail: email => p.user.findUnique({ where: { email } }), + async getUserByAccount(provider_providerAccountId) { + const account = await p.account.findUnique({ + where: { provider_providerAccountId }, + select: { user: true }, + }); + return account?.user ?? null; + }, + updateUser: ({ id, ...data }) => p.user.update({ where: { id }, data }), + deleteUser: id => p.user.delete({ where: { id } }), + linkAccount: data => { + return p.account.create({ + data: pick(data, [ + 'provider', + 'type', + 'providerAccountId', + 'access_token', + 'expires_at', + 'refresh_token', + 'token_type', + 'scope', + 'userId', + ]), + }) as any; + }, + unlinkAccount: provider_providerAccountId => + p.account.delete({ where: { provider_providerAccountId } }) as any, + async getSessionAndUser(sessionToken) { + const userAndSession = await p.session.findUnique({ + where: { sessionToken }, + include: { user: true }, + }); + if (!userAndSession) return null; + const { user, ...session } = userAndSession; + return { user, session }; + }, + createSession: data => p.session.create({ data }), + updateSession: data => + p.session.update({ where: { sessionToken: data.sessionToken }, data }), + deleteSession: sessionToken => p.session.delete({ where: { sessionToken } }), + async createVerificationToken(data) { + // @ts-ignore + const { id: _, ...verificationToken } = await p.verificationToken.create({ + data, + }); + return verificationToken; + }, + async useVerificationToken(identifier_token) { + try { + // @ts-ignore + const { id: _, ...verificationToken } = await p.verificationToken.delete({ + where: { identifier_token }, + }); + return verificationToken; + } catch (error) { + // If token already used/deleted, just return null + // https://www.prisma.io/docs/reference/api-reference/error-reference#p2025 + if ((error as Prisma.PrismaClientKnownRequestError).code === 'P2025') return null; + throw error; + } + }, + }; +} diff --git a/nextjs-demo/pages/api/email-template/[id].ts b/nextjs-demo/pages/api/email-template/[id].ts new file mode 100644 index 000000000..56d420262 --- /dev/null +++ b/nextjs-demo/pages/api/email-template/[id].ts @@ -0,0 +1,41 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import { getSession } from 'next-auth/react'; +import { get } from 'lodash'; +import prisma from 'prisma/prisma'; + +export default async function handle(req: NextApiRequest, res: NextApiResponse) { + const emailTemplateId = req.query.id; + + const session = await getSession({ req }); + const userId = get(session, 'user.id', '') as string; + if (!session || !userId) { + res.status(401).send({ message: 'Unauthorized' }); + return; + } + + if (req.method === 'DELETE') { + if (session) { + const emailTemplate = await prisma.emailTemplate.deleteMany({ + where: { id: String(emailTemplateId), userId }, + }); + res.json(emailTemplate); + } + } else if (req.method === 'GET') { + const result = await prisma.emailTemplate.findFirst({ + where: { + id: String(emailTemplateId), + userId: userId, + }, + }); + res.json(result); + } else if (req.method === 'PATCH') { + const result = await prisma.emailTemplate.updateMany({ + where: { + id: String(emailTemplateId), + userId: userId, + }, + data: req.body, + }); + res.json(result); + } +} diff --git a/nextjs-demo/pages/api/email-template/index.ts b/nextjs-demo/pages/api/email-template/index.ts new file mode 100644 index 000000000..290849423 --- /dev/null +++ b/nextjs-demo/pages/api/email-template/index.ts @@ -0,0 +1,38 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import { getSession } from 'next-auth/react'; +import { get } from 'lodash'; +import prisma from 'prisma/prisma'; + +export default async function handle(req: NextApiRequest, res: NextApiResponse) { + const session = await getSession({ req }); + const userId = get(session, 'user.id', '') as string; + if (!session || !userId) { + res.status(401).send({ message: 'Unauthorized' }); + return; + } + + if (req.method === 'POST') { + const { subject, content, thumbnail } = req.body; + + if (!subject || !content || !thumbnail) { + throw new Error('Invalid payload'); + } + + const result = await prisma.emailTemplate.create({ + data: { + subject: subject, + content: content, + thumbnail: thumbnail, + userId: userId, + }, + }); + res.json(result); + } else if (req.method === 'GET') { + const result = await prisma.emailTemplate.findMany({ + where: { + userId: userId, + }, + }); + res.json(result); + } +} diff --git a/nextjs-demo/pages/emails/create.tsx b/nextjs-demo/pages/emails/create.tsx new file mode 100644 index 000000000..eeba86f19 --- /dev/null +++ b/nextjs-demo/pages/emails/create.tsx @@ -0,0 +1,13 @@ +import dynamic from "next/dynamic"; + +const PageComponent = dynamic( + () => + import("@/client/pages/Emails/Create").then((lib) => lib.default) as any, + { ssr: false } +); + +const Index = () => { + return ; +}; + +export default Index; diff --git a/nextjs-demo/pages/emails/editor/[id].tsx b/nextjs-demo/pages/emails/editor/[id].tsx new file mode 100644 index 000000000..03707c47f --- /dev/null +++ b/nextjs-demo/pages/emails/editor/[id].tsx @@ -0,0 +1,15 @@ +import dynamic from "next/dynamic"; + +const PageComponent = dynamic( + () => + import("@/client/pages/Emails/Editor").then((lib) => lib.default) as any, + { ssr: false } +); + +const Index = () => { + return ; +}; + +Index.hideLayout = true; + +export default Index; diff --git a/nextjs-demo/pages/emails/index.tsx b/nextjs-demo/pages/emails/index.tsx new file mode 100644 index 000000000..122631376 --- /dev/null +++ b/nextjs-demo/pages/emails/index.tsx @@ -0,0 +1,13 @@ +import dynamic from "next/dynamic"; + +const PageComponent = dynamic( + () => + import("@/client/pages/Emails/Templates").then((lib) => lib.default) as any, + { ssr: false } +); + +const Index = () => { + return ; +}; + +export default Index; diff --git a/nextjs-demo/pages/global.less b/nextjs-demo/pages/global.less new file mode 100644 index 000000000..ffe36cb2c --- /dev/null +++ b/nextjs-demo/pages/global.less @@ -0,0 +1,29 @@ + +html, +body { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + text-size-adjust: 100%; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-family: "EuclidSquare", "system-ui", "-apple-system", BlinkMacSystemFont, + "segoe ui", Roboto, Helvetica, Arial, "sans-serif", "apple color emoji", + "segoe ui emoji", "segoe ui symbol"; + + color: rgb(32, 34, 35); + margin: 0; + padding: 0; +} + +#organization-layout .arco-page-header-head-wrapper { + padding-left: 0; +} + +.small-container { + width: 998px; + margin: auto; +} + +* { + box-sizing: border-box; +} \ No newline at end of file diff --git a/nextjs-demo/pages/index.tsx b/nextjs-demo/pages/index.tsx new file mode 100644 index 000000000..4ea709914 --- /dev/null +++ b/nextjs-demo/pages/index.tsx @@ -0,0 +1,12 @@ +import dynamic from 'next/dynamic'; + +const PageComponent = dynamic( + () => import('@/client/pages/Emails/Templates').then(lib => lib.default) as any, + { ssr: false }, +); + +const Index = () => { + return ; +}; + +export default Index; diff --git a/nextjs-demo/pages/login/index.tsx b/nextjs-demo/pages/login/index.tsx new file mode 100644 index 000000000..aaf41effa --- /dev/null +++ b/nextjs-demo/pages/login/index.tsx @@ -0,0 +1,12 @@ +import dynamic from 'next/dynamic'; + +const PageComponent = dynamic( + () => import('@/client/pages/Login').then(lib => lib.default) as any, + { ssr: false }, +); + +const Index = () => { + return ; +}; + +export default Index; diff --git a/nextjs-demo/pnpm-lock.yaml b/nextjs-demo/pnpm-lock.yaml new file mode 100644 index 000000000..2351b77fa --- /dev/null +++ b/nextjs-demo/pnpm-lock.yaml @@ -0,0 +1,2822 @@ +lockfileVersion: 5.4 + +specifiers: + '@arco-design/web-react': ^2.53.1 + '@arco-themes/react-easy-email-theme': ^0.0.3 + '@arco-themes/react-easy-email-theme-green': ^0.0.1 + '@arco-themes/react-easy-email-theme-purple': ^0.0.3 + '@next-auth/prisma-adapter': 1.0.7 + '@prisma/client': 4.2.0 + '@types/next-auth': 3.13.0 + '@types/node': 16.11.26 + '@types/passport-google-oauth20': ^2.0.12 + '@types/react': 17.0.44 + '@types/react-dom': ^18.2.7 + axios: ^1.5.0 + classnames: ^2.3.2 + dayjs: ^1.11.9 + easy-email-core: ^4.12.2 + easy-email-editor: ^4.12.2 + easy-email-extensions: ^4.14.1 + final-form: ^4.20.10 + google: link:next-auth/providers/google + html2canvas: ^1.4.1 + less: ^4.2.0 + less-loader: ^11.1.3 + next: 12.1.4 + next-auth: 4.3.1 + next-prisma-plugin-webpack5: 0.0.0-dripip + next-with-less: ^3.0.1 + passport-google-oauth20: ^2.0.0 + prisma: 4.2.0 + query-string: ^8.1.0 + raw-loader: ^4.0.2 + react: 18.2.0 + react-dom: 18.2.0 + react-final-form: ^6.5.9 + react-markdown: 8.0.2 + react-use: ^17.4.0 + ts-node: 10.7.0 + typescript: 4.6.3 + +dependencies: + '@arco-design/web-react': 2.53.1_2wutc2u2h62y4g5lm67m2634rq + '@arco-themes/react-easy-email-theme': 0.0.3_mfmf5on6o5e5av6mjwylnnhday + '@arco-themes/react-easy-email-theme-green': 0.0.1_mfmf5on6o5e5av6mjwylnnhday + '@arco-themes/react-easy-email-theme-purple': 0.0.3_mfmf5on6o5e5av6mjwylnnhday + '@next-auth/prisma-adapter': 1.0.7_n3q6jiznnpyzpjam722vwaia4q + '@prisma/client': 4.2.0_prisma@4.2.0 + '@types/passport-google-oauth20': 2.0.12 + '@types/react-dom': 18.2.7 + axios: 1.5.0 + classnames: 2.3.2 + dayjs: 1.11.10 + easy-email-core: 4.12.2_biqbaboplfbrettd7655fr4n2y + easy-email-editor: 4.12.2_m54xcoygdwshuio37wzr2fk7ue + easy-email-extensions: 4.14.1_p72j6yfq24valatajggkrctuqq + final-form: 4.20.10 + google: link:next-auth/providers/google + html2canvas: 1.4.1 + less: 4.2.0 + less-loader: 11.1.3_less@4.2.0 + next: 12.1.4_biqbaboplfbrettd7655fr4n2y + next-auth: 4.3.1_biqbaboplfbrettd7655fr4n2y + next-prisma-plugin-webpack5: 0.0.0-dripip + next-with-less: 3.0.1_pvwbzhsolcgcqgt45pfwdigxzi + passport-google-oauth20: 2.0.0 + query-string: 8.1.0 + raw-loader: 4.0.2 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-final-form: 6.5.9_anngbwyi5kay4c5jh7oectltc4 + react-markdown: 8.0.2_lwp2vdxnjqlnnpmgijegqsjvcq + react-use: 17.4.0_biqbaboplfbrettd7655fr4n2y + +devDependencies: + '@types/next-auth': 3.13.0 + '@types/node': 16.11.26 + '@types/react': 17.0.44 + prisma: 4.2.0 + ts-node: 10.7.0_3wvmryjdv2zgb5mgtbgo5b2ija + typescript: 4.6.3 + +packages: + + /@arco-design/color/0.4.0: + resolution: {integrity: sha512-s7p9MSwJgHeL8DwcATaXvWT3m2SigKpxx4JA1BGPHL4gfvaQsmQfrLBDpjOJFJuJ2jG2dMt3R3P8Pm9E65q18g==} + dependencies: + color: 3.2.1 + dev: false + + /@arco-design/web-react/2.53.1_2wutc2u2h62y4g5lm67m2634rq: + resolution: {integrity: sha512-ihXAq6FcfzfT7J6u7SAYwQkRq1s/1ApN8iexCf2/oLjzWdOYhWEpf9Tfnb0JzTiNO/+AC6OnCbnFHZ7vPoIg4g==} + peerDependencies: + react: '>=16' + react-dom: '>=16' + dependencies: + '@arco-design/color': 0.4.0 + '@babel/runtime': 7.22.15 + b-tween: 0.3.3 + b-validate: 1.5.3 + compute-scroll-into-view: 1.0.20 + dayjs: 1.11.10 + lodash: 4.17.21 + number-precision: 1.6.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-focus-lock: 2.9.5_lwp2vdxnjqlnnpmgijegqsjvcq + react-transition-group: 4.4.5_biqbaboplfbrettd7655fr4n2y + resize-observer-polyfill: 1.5.1 + scroll-into-view-if-needed: 2.2.20 + shallowequal: 1.1.0 + transitivePeerDependencies: + - '@types/react' + dev: false + + /@arco-themes/react-easy-email-theme-green/0.0.1_mfmf5on6o5e5av6mjwylnnhday: + resolution: {integrity: sha512-VHFgYCvnw/myVRj+k99DSP8t+Ol5D6qdeCNuvSrOYvYym3PXLJ9amSQSRIIGyS+zTRw8yH47Yx4OAPyE5lnXRw==} + peerDependencies: + '@arco-design/web-react': ^2.26.2 + dependencies: + '@arco-design/web-react': 2.53.1_2wutc2u2h62y4g5lm67m2634rq + dev: false + + /@arco-themes/react-easy-email-theme-purple/0.0.3_mfmf5on6o5e5av6mjwylnnhday: + resolution: {integrity: sha512-745j2ozqhYlnun8N1gEie4m17usBaLqAzbTbcdqU8GoT7GZGONlTnN71IdDb8ztOd8yFoVruz6FccxzREbqqRA==} + peerDependencies: + '@arco-design/web-react': ^2.26.2 + dependencies: + '@arco-design/web-react': 2.53.1_2wutc2u2h62y4g5lm67m2634rq + dev: false + + /@arco-themes/react-easy-email-theme/0.0.3_mfmf5on6o5e5av6mjwylnnhday: + resolution: {integrity: sha512-JZXavU2v7YK38KyoK3hUQ2bxpdD5JwPzjxFNftH6Dhiuv/CppK55/uWzDpQJIohcHM9BTRcYmgUA49OE2MHWqA==} + peerDependencies: + '@arco-design/web-react': ^2.27.0 + dependencies: + '@arco-design/web-react': 2.53.1_2wutc2u2h62y4g5lm67m2634rq + dev: false + + /@babel/runtime/7.17.9: + resolution: {integrity: sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.9 + dev: false + + /@babel/runtime/7.22.15: + resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.0 + dev: false + + /@cspotcode/source-map-consumer/0.8.0: + resolution: {integrity: sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==} + engines: {node: '>= 12'} + dev: true + + /@cspotcode/source-map-support/0.7.0: + resolution: {integrity: sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==} + engines: {node: '>=12'} + dependencies: + '@cspotcode/source-map-consumer': 0.8.0 + dev: true + + /@icons/material/0.2.4_react@18.2.0: + resolution: {integrity: sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==} + peerDependencies: + react: '*' + dependencies: + react: 18.2.0 + dev: false + + /@next-auth/prisma-adapter/1.0.7_n3q6jiznnpyzpjam722vwaia4q: + resolution: {integrity: sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==} + peerDependencies: + '@prisma/client': '>=2.26.0 || >=3' + next-auth: ^4 + dependencies: + '@prisma/client': 4.2.0_prisma@4.2.0 + next-auth: 4.3.1_biqbaboplfbrettd7655fr4n2y + dev: false + + /@next/env/12.1.4: + resolution: {integrity: sha512-7gQwotJDKnfMxxXd8xJ2vsX5AzyDxO3zou0+QOXX8/unypA6icw5+wf6A62yKZ6qQ4UZHHxS68pb6UV+wNneXg==} + dev: false + + /@next/swc-android-arm-eabi/12.1.4: + resolution: {integrity: sha512-FJg/6a3s2YrUaqZ+/DJZzeZqfxbbWrynQMT1C5wlIEq9aDLXCFpPM/PiOyJh0ahxc0XPmi6uo38Poq+GJTuKWw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@next/swc-android-arm64/12.1.4: + resolution: {integrity: sha512-LXraazvQQFBgxIg3Htny6G5V5he9EK7oS4jWtMdTGIikmD/OGByOv8ZjLuVLZLtVm3UIvaAiGtlQSLecxJoJDw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@next/swc-darwin-arm64/12.1.4: + resolution: {integrity: sha512-SSST/dBymecllZxcqTCcSTCu5o1NKk9I+xcvhn/O9nH6GWjgvGgGkNqLbCarCa0jJ1ukvlBA138FagyrmZ/4rQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@next/swc-darwin-x64/12.1.4: + resolution: {integrity: sha512-p1lwdX0TVjaoDXQVuAkjtxVBbCL/urgxiMCBwuPDO7TikpXtSRivi+mIzBj5q7ypgICFmIAOW3TyupXeoPRAnA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm-gnueabihf/12.1.4: + resolution: {integrity: sha512-67PZlgkCn3TDxacdVft0xqDCL7Io1/C4xbAs0+oSQ0xzp6OzN2RNpuKjHJrJgKd0DsE1XZ9sCP27Qv0591yfyg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm64-gnu/12.1.4: + resolution: {integrity: sha512-OnOWixhhw7aU22TQdQLYrgpgFq0oA1wGgnjAiHJ+St7MLj82KTDyM9UcymAMbGYy6nG/TFOOHdTmRMtCRNOw0g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm64-musl/12.1.4: + resolution: {integrity: sha512-UoRMzPZnsAavdWtVylYxH8DNC7Uy0i6RrvNwT4PyQVdfANBn2omsUkcH5lgS2O7oaz0nAYLk1vqyZDO7+tJotA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-x64-gnu/12.1.4: + resolution: {integrity: sha512-nM+MA/frxlTLUKLJKorctdI20/ugfHRjVEEkcLp/58LGG7slNaP1E5d5dRA1yX6ISjPcQAkywas5VlGCg+uTvA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-x64-musl/12.1.4: + resolution: {integrity: sha512-GoRHxkuW4u4yKw734B9SzxJwVdyEJosaZ62P7ifOwcujTxhgBt3y76V2nNUrsSuopcKI2ZTDjaa+2wd5zyeXbA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-arm64-msvc/12.1.4: + resolution: {integrity: sha512-6TQkQze0ievXwHJcVUrIULwCYVe3ccX6T0JgZ1SiMeXpHxISN7VJF/O8uSCw1JvXZYZ6ud0CJ7nfC5HXivgfPg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-ia32-msvc/12.1.4: + resolution: {integrity: sha512-CsbX/IXuZ5VSmWCpSetG2HD6VO5FTsO39WNp2IR2Ut/uom9XtLDJAZqjQEnbUTLGHuwDKFjrIO3LkhtROXLE/g==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-x64-msvc/12.1.4: + resolution: {integrity: sha512-JtYuWzKXKLDMgE/xTcFtCm1MiCIRaAc5XYZfYX3n/ZWSI1SJS/GMm+Su0SAHJgRFavJh6U/p998YwO/iGTIgqQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@one-ini/wasm/0.1.1: + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + dev: false + + /@panva/asn1.js/1.0.0: + resolution: {integrity: sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==} + engines: {node: '>=10.13.0'} + dev: true + + /@panva/hkdf/1.0.1: + resolution: {integrity: sha512-mMyQ9vjpuFqePkfe5bZVIf/H3Dmk6wA8Kjxff9RcO4kqzJo+Ek9pGKwZHpeMr7Eku0QhLXMCd7fNCSnEnRMubg==} + dev: false + + /@prisma/client/4.2.0_prisma@4.2.0: + resolution: {integrity: sha512-Q/X8fi1UBufCrkdLk188sC/roiGxEm1V3qU4uEP5SyleO5n2A+FyC62S7+4I0hu57CU3c7Ls3YjqPiZyTHVGOw==} + engines: {node: '>=14.17'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + '@prisma/engines-version': 4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826 + prisma: 4.2.0 + dev: false + + /@prisma/engines-version/4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826: + resolution: {integrity: sha512-tktkqdiwqE4QhmE088boPt+FwPj1Jub/zk+5F6sEfcRHzO5yz9jyMD5HFVtiwxZPLx/8Xg9ElnuTi8E5lWVQFQ==} + dev: false + + /@prisma/engines/4.2.0: + resolution: {integrity: sha512-tefRwCVDwLqk0WrBLErYR26uKKxzLSlKvRyADFiQn/fizJhqk9nxMXH8F6SE4w6r/szUQTzIJ4vheJKQ4dYKpw==} + requiresBuild: true + + /@sqltools/formatter/1.2.3: + resolution: {integrity: sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg==} + dev: true + + /@tsconfig/node10/1.0.8: + resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} + dev: true + + /@tsconfig/node12/1.0.9: + resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==} + dev: true + + /@tsconfig/node14/1.0.1: + resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==} + dev: true + + /@tsconfig/node16/1.0.2: + resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==} + dev: true + + /@types/body-parser/1.19.3: + resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} + dependencies: + '@types/connect': 3.4.36 + '@types/node': 16.11.26 + dev: false + + /@types/connect/3.4.36: + resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + dependencies: + '@types/node': 16.11.26 + dev: false + + /@types/debug/4.1.7: + resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + dependencies: + '@types/ms': 0.7.31 + dev: false + + /@types/express-serve-static-core/4.17.37: + resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} + dependencies: + '@types/node': 16.11.26 + '@types/qs': 6.9.8 + '@types/range-parser': 1.2.4 + '@types/send': 0.17.1 + dev: false + + /@types/express/4.17.18: + resolution: {integrity: sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==} + dependencies: + '@types/body-parser': 1.19.3 + '@types/express-serve-static-core': 4.17.37 + '@types/qs': 6.9.8 + '@types/serve-static': 1.15.2 + dev: false + + /@types/hast/2.3.4: + resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /@types/http-errors/2.0.2: + resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==} + dev: false + + /@types/js-cookie/2.2.7: + resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} + dev: false + + /@types/json-schema/7.0.13: + resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==} + dev: false + + /@types/mdast/3.0.10: + resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /@types/mdurl/1.0.2: + resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} + dev: false + + /@types/mime/1.3.2: + resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} + dev: false + + /@types/mime/3.0.1: + resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} + dev: false + + /@types/ms/0.7.31: + resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + dev: false + + /@types/next-auth/3.13.0: + resolution: {integrity: sha512-zkEVDyoKgRsHm3KUaZoOGSThTS9h0+HbFZctiYbB5MMU6/pUZuF5ozWrVG00jotQJuSEIlPWzdCIXKlaHctJgw==} + dependencies: + '@types/node': 16.11.26 + '@types/react': 17.0.44 + jose: 1.28.1 + typeorm: 0.2.45 + transitivePeerDependencies: + - '@sap/hana-client' + - better-sqlite3 + - hdb-pool + - ioredis + - mongodb + - mssql + - mysql2 + - oracledb + - pg + - pg-native + - pg-query-stream + - redis + - sql.js + - sqlite3 + - supports-color + - typeorm-aurora-data-api-driver + dev: true + + /@types/node/16.11.26: + resolution: {integrity: sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==} + + /@types/oauth/0.9.2: + resolution: {integrity: sha512-Nu3/abQ6yR9VlsCdX3aiGsWFkj6OJvJqDvg/36t8Gwf2mFXdBZXPDN3K+2yfeA6Lo2m1Q12F8Qil9TZ48nWhOQ==} + dependencies: + '@types/node': 16.11.26 + dev: false + + /@types/passport-google-oauth20/2.0.12: + resolution: {integrity: sha512-+MBVB8uYd8mMZYvTwYChCa2LBGVK9FMwdK5TtcNHMeTL6qBZ3QW0HeUtZiAlwgkw2LYM0Btlzyb19EA8ysm13g==} + dependencies: + '@types/express': 4.17.18 + '@types/passport': 1.0.13 + '@types/passport-oauth2': 1.4.13 + dev: false + + /@types/passport-oauth2/1.4.13: + resolution: {integrity: sha512-SKjbAFSgV2ys7Vf8+BbQ2Fq09CZGi72xaHqbWPEKhi7czPSC0ff4gXuQEY3XXAuTynPjwj6dlL3YAta9M2K0AQ==} + dependencies: + '@types/express': 4.17.18 + '@types/oauth': 0.9.2 + '@types/passport': 1.0.13 + dev: false + + /@types/passport/1.0.13: + resolution: {integrity: sha512-XXURryL+EZAWtbQFOHX1eNB+RJwz5XMPPz1xrGpEKr2xUZCXM4NCPkHMtZQ3B2tTSG/1IRaAcTHjczRA4sSFCw==} + dependencies: + '@types/express': 4.17.18 + dev: false + + /@types/prop-types/15.7.5: + resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + + /@types/qs/6.9.8: + resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==} + dev: false + + /@types/range-parser/1.2.4: + resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} + dev: false + + /@types/react-dom/18.2.7: + resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} + dependencies: + '@types/react': 17.0.44 + dev: false + + /@types/react/17.0.44: + resolution: {integrity: sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==} + dependencies: + '@types/prop-types': 15.7.5 + '@types/scheduler': 0.16.2 + csstype: 3.0.11 + + /@types/scheduler/0.16.2: + resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} + + /@types/send/0.17.1: + resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} + dependencies: + '@types/mime': 1.3.2 + '@types/node': 16.11.26 + dev: false + + /@types/serve-static/1.15.2: + resolution: {integrity: sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==} + dependencies: + '@types/http-errors': 2.0.2 + '@types/mime': 3.0.1 + '@types/node': 16.11.26 + dev: false + + /@types/unist/2.0.6: + resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + dev: false + + /@types/zen-observable/0.8.3: + resolution: {integrity: sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==} + dev: true + + /@xobotyi/scrollbar-width/1.9.5: + resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} + dev: false + + /abbrev/1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: false + + /acorn-walk/8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn/8.7.0: + resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv-keywords/3.5.2_ajv@6.12.6: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: false + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: false + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /any-promise/1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + + /app-root-path/3.0.0: + resolution: {integrity: sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==} + engines: {node: '>= 6.0.0'} + dev: true + + /arg/4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /asynckit/0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /axios/1.5.0: + resolution: {integrity: sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==} + dependencies: + follow-redirects: 1.15.3 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /b-tween/0.3.3: + resolution: {integrity: sha512-oEHegcRpA7fAuc9KC4nktucuZn2aS8htymCPcP3qkEGPqiBH+GfqtqoG2l7LxHngg6O0HFM7hOeOYExl1Oz4ZA==} + dev: false + + /b-validate/1.5.3: + resolution: {integrity: sha512-iCvCkGFskbaYtfQ0a3GmcQCHl/Sv1GufXFGuUQ+FE+WJa7A/espLOuFIn09B944V8/ImPj71T4+rTASxO2PAuA==} + dev: false + + /bail/2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + dev: false + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /base64-arraybuffer/1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + dev: false + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /base64url/3.0.1: + resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} + engines: {node: '>=6.0.0'} + dev: false + + /big.js/5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: false + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion/2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + + /buffer/6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /caniuse-lite/1.0.30001327: + resolution: {integrity: sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==} + dev: false + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /character-entities/2.0.1: + resolution: {integrity: sha512-OzmutCf2Kmc+6DrFrrPS8/tDh2+DpnrfzdICHWhcVC9eOd0N1PXmQEE1a8iM4IziIAG+8tmTq3K+oo0ubH6RRQ==} + dev: false + + /classnames/2.3.2: + resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + dev: false + + /cli-highlight/2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + dev: true + + /cliui/7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone-deep/4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + dev: false + + /codemirror/5.65.15: + resolution: {integrity: sha512-YC4EHbbwQeubZzxLl5G4nlbLc1T21QTrKGaOal/Pkm9dVDMZXMH7+ieSPEOZCtO9I68i8/oteJKOxzHC2zR+0g==} + dev: false + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /color-string/1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + + /color/3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + dev: false + + /color/4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + dev: false + + /combined-stream/1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /comma-separated-tokens/2.0.2: + resolution: {integrity: sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==} + dev: false + + /commander/10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: false + + /compute-scroll-into-view/1.0.11: + resolution: {integrity: sha512-uUnglJowSe0IPmWOdDtrlHXof5CTIJitfJEyITHBW6zDVOGu9Pjk5puaLM73SLcwak0L4hEjO7Td88/a6P5i7A==} + dev: false + + /compute-scroll-into-view/1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + dev: false + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /config-chain/1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + dev: false + + /cookie/0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + dev: false + + /copy-anything/2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + dependencies: + is-what: 3.14.1 + dev: false + + /copy-to-clipboard/3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + dependencies: + toggle-selection: 1.0.6 + dev: false + + /create-require/1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /css-in-js-utils/3.1.0: + resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} + dependencies: + hyphenate-style-name: 1.0.4 + dev: false + + /css-line-break/2.1.0: + resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + dependencies: + utrie: 1.0.2 + dev: false + + /css-tree/1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + dev: false + + /csstype/3.0.11: + resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} + + /dayjs/1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dev: false + + /debug/3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + optional: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /decode-named-character-reference/1.0.1: + resolution: {integrity: sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w==} + dependencies: + character-entities: 2.0.1 + dev: false + + /decode-uri-component/0.4.1: + resolution: {integrity: sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==} + engines: {node: '>=14.16'} + dev: false + + /delayed-stream/1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /dequal/2.0.2: + resolution: {integrity: sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==} + engines: {node: '>=6'} + dev: false + + /detect-node-es/1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + dev: false + + /diff/4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /diff/5.0.0: + resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} + engines: {node: '>=0.3.1'} + dev: false + + /dom-helpers/5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dependencies: + '@babel/runtime': 7.22.15 + csstype: 3.0.11 + dev: false + + /dotenv/8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + dev: true + + /easy-email-core/4.12.2_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-cfl09YInI4RYuNKhZJykQIMs22QbEYBo+BLtDcbiu2hBzJscPOLZ2mW0MQyhu0LJSiVkie+fmQLqmTXcmCCMfg==} + peerDependencies: + react: ^18.2.0 + react-dom: ^18.2.0 + dependencies: + he: 1.2.0 + js-beautify: 1.14.9 + lodash: 4.17.21 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + uuid: 8.3.2 + dev: false + + /easy-email-editor/4.12.2_m54xcoygdwshuio37wzr2fk7ue: + resolution: {integrity: sha512-DsGzjJtkxGaEVA+39d6uYd4TL5iUFiFvvq98ATmG+HJP8yvgBphEmGVJ6F8kduMewoEq17AYAwnrb29unvJWlQ==} + peerDependencies: + easy-email-core: ^4.3.6 + mjml-browser: ^4.10.4 + react: ^18.2.0 + react-dom: ^18.2.0 + react-final-form: ^6.5.7 + dependencies: + easy-email-core: 4.12.2_biqbaboplfbrettd7655fr4n2y + final-form: 4.20.10 + final-form-arrays: 3.1.0_final-form@4.20.10 + final-form-set-field-touched: 1.0.1_final-form@4.20.10 + is-hotkey: 0.2.0 + lodash: 4.17.21 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-final-form: 6.5.9_anngbwyi5kay4c5jh7oectltc4 + react-final-form-arrays: 3.1.4_kmr6azhn2v3y2ahfq4sxk65mkq + react-use: 17.4.0_biqbaboplfbrettd7655fr4n2y + dev: false + + /easy-email-extensions/4.14.1_p72j6yfq24valatajggkrctuqq: + resolution: {integrity: sha512-Ugptc5ivYeElO2HCf9lsCJ2WSEd+I2CyzdkCbCPhhj/d+DbxoN4SPyOIe7WfAwMmyKX6Qu/hxMBeB80bOdhiSA==} + peerDependencies: + easy-email-core: ^4.3.6 + easy-email-editor: ^4.3.6 + react: ^18.2.0 + react-dom: ^18.2.0 + react-final-form: ^6.5.7 + dependencies: + '@arco-design/web-react': 2.53.1_2wutc2u2h62y4g5lm67m2634rq + codemirror: 5.65.15 + color: 4.2.3 + easy-email-core: 4.12.2_biqbaboplfbrettd7655fr4n2y + easy-email-editor: 4.12.2_m54xcoygdwshuio37wzr2fk7ue + final-form: 4.20.10 + final-form-arrays: 3.1.0_final-form@4.20.10 + final-form-set-field-touched: 1.0.1_final-form@4.20.10 + is-hotkey: 0.2.0 + lodash: 4.17.21 + mjml-browser: 4.14.1 + overlayscrollbars: 1.13.3 + overlayscrollbars-react: 0.3.0_xe725h2d5kcgarcqbsx2itrmxy + react: 18.2.0 + react-codemirror2: 7.2.1_6af5glenfwdy3o6gdj2q5bzm54 + react-color: 2.19.3_react@18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-final-form: 6.5.9_anngbwyi5kay4c5jh7oectltc4 + react-final-form-arrays: 3.1.4_kmr6azhn2v3y2ahfq4sxk65mkq + react-use: 17.4.0_biqbaboplfbrettd7655fr4n2y + transitivePeerDependencies: + - '@types/react' + dev: false + + /editorconfig/1.0.4: + resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.1 + semver: 7.5.4 + dev: false + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emojis-list/3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: false + + /errno/0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + requiresBuild: true + dependencies: + prr: 1.0.1 + dev: false + optional: true + + /error-stack-parser/2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + dependencies: + stackframe: 1.3.4 + dev: false + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /extend/3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: false + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: false + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: false + + /fast-loops/1.1.3: + resolution: {integrity: sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==} + dev: false + + /fast-shallow-equal/1.0.0: + resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} + dev: false + + /fastest-stable-stringify/2.0.2: + resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} + dev: false + + /filter-obj/5.1.0: + resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==} + engines: {node: '>=14.16'} + dev: false + + /final-form-arrays/3.1.0_final-form@4.20.10: + resolution: {integrity: sha512-TWBvun+AopgBLw9zfTFHBllnKMVNEwCEyDawphPuBGGqNsuhGzhT7yewHys64KFFwzIs6KEteGLpKOwvTQEscQ==} + peerDependencies: + final-form: ^4.20.8 + dependencies: + final-form: 4.20.10 + dev: false + + /final-form-set-field-touched/1.0.1_final-form@4.20.10: + resolution: {integrity: sha512-yvE5AAs9U3OgJQ9YF8NhSF0I0mJEECvOpkaXNqovloxji5Q6gOZ0DCIAyLAKHluGSpsXKUGORyBm8Hq0beZIqQ==} + peerDependencies: + final-form: '>=1.2.0' + dependencies: + final-form: 4.20.10 + dev: false + + /final-form/4.20.10: + resolution: {integrity: sha512-TL48Pi1oNHeMOHrKv1bCJUrWZDcD3DIG6AGYVNOnyZPr7Bd/pStN0pL+lfzF5BNoj/FclaoiaLenk4XUIFVYng==} + engines: {node: '>=8'} + dependencies: + '@babel/runtime': 7.22.15 + dev: false + + /focus-lock/0.11.6: + resolution: {integrity: sha512-KSuV3ur4gf2KqMNoZx3nXNVhqCkn42GuTYCX4tXPEwf0MjpFQmNMiN6m7dXaUXgIoivL6/65agoUMg4RLS0Vbg==} + engines: {node: '>=10'} + dependencies: + tslib: 2.3.1 + dev: false + + /follow-redirects/1.15.3: + resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /form-data/4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + /get-caller-file/2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /glob/7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob/8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: false + + /graceful-fs/4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + requiresBuild: true + dev: false + optional: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /hast-util-whitespace/2.0.0: + resolution: {integrity: sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==} + dev: false + + /he/1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: false + + /highlight.js/10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + dev: true + + /html2canvas/1.4.1: + resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} + engines: {node: '>=8.0.0'} + dependencies: + css-line-break: 2.1.0 + text-segmentation: 1.0.3 + dev: false + + /hyphenate-style-name/1.0.4: + resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==} + dev: false + + /iconv-lite/0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + optional: true + + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /image-size/0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /ini/1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: false + + /inline-style-parser/0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + dev: false + + /inline-style-prefixer/6.0.4: + resolution: {integrity: sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==} + dependencies: + css-in-js-utils: 3.1.0 + fast-loops: 1.1.3 + dev: false + + /is-arrayish/0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + + /is-buffer/2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: false + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-hotkey/0.2.0: + resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==} + dev: false + + /is-plain-obj/4.0.0: + resolution: {integrity: sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw==} + engines: {node: '>=12'} + dev: false + + /is-plain-object/2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + + /is-what/3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + dev: false + + /isobject/3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: false + + /jose/1.28.1: + resolution: {integrity: sha512-6JK28rFu5ENp/yxMwM+iN7YeaInnY9B9Bggjkz5fuwLiJhbVrl2O4SJr65bdNBPl9y27fdC3Mymh+FVCvozLIg==} + engines: {node: '>=10.13.0'} + deprecated: this version is no longer supported + dependencies: + '@panva/asn1.js': 1.0.0 + dev: true + + /jose/4.6.0: + resolution: {integrity: sha512-0hNAkhMBNi4soKSAX4zYOFV+aqJlEz/4j4fregvasJzEVtjDChvWqRjPvHwLqr5hx28Ayr6bsOs1Kuj87V0O8w==} + deprecated: this version is no longer supported + dev: false + + /js-beautify/1.14.9: + resolution: {integrity: sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==} + engines: {node: '>=12'} + hasBin: true + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 8.1.0 + nopt: 6.0.0 + dev: false + + /js-cookie/2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + dev: false + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: false + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: false + + /json5/2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: false + + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + + /kleur/4.1.4: + resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==} + engines: {node: '>=6'} + dev: false + + /less-loader/11.1.3_less@4.2.0: + resolution: {integrity: sha512-A5b7O8dH9xpxvkosNrP0dFp2i/dISOJa9WwGF3WJflfqIERE2ybxh1BFDj5CovC2+jCE4M354mk90hN6ziXlVw==} + engines: {node: '>= 14.15.0'} + peerDependencies: + less: ^3.5.0 || ^4.0.0 + webpack: ^5.0.0 + dependencies: + less: 4.2.0 + dev: false + + /less/4.2.0: + resolution: {integrity: sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.3.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: false + + /loader-utils/2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + dev: false + + /lodash-es/4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /loose-envify/1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /make-dir/2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + pify: 4.0.1 + semver: 5.7.2 + dev: false + optional: true + + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /material-colors/1.2.6: + resolution: {integrity: sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==} + dev: false + + /mdast-util-definitions/5.1.0: + resolution: {integrity: sha512-5hcR7FL2EuZ4q6lLMUK5w4lHT2H3vqL9quPvYZ/Ku5iifrirfMHiGdhxdXMUbUkDmz5I+TYMd7nbaxUhbQkfpQ==} + dependencies: + '@types/mdast': 3.0.10 + '@types/unist': 2.0.6 + unist-util-visit: 3.1.0 + dev: false + + /mdast-util-from-markdown/1.2.0: + resolution: {integrity: sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==} + dependencies: + '@types/mdast': 3.0.10 + '@types/unist': 2.0.6 + decode-named-character-reference: 1.0.1 + mdast-util-to-string: 3.1.0 + micromark: 3.0.10 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-decode-string: 1.0.2 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + unist-util-stringify-position: 3.0.2 + uvu: 0.5.3 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-to-hast/12.1.1: + resolution: {integrity: sha512-qE09zD6ylVP14jV4mjLIhDBOrpFdShHZcEsYvvKGABlr9mGbV7mTlRWdoFxL/EYSTNDiC9GZXy7y8Shgb9Dtzw==} + dependencies: + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + '@types/mdurl': 1.0.2 + mdast-util-definitions: 5.1.0 + mdurl: 1.0.1 + micromark-util-sanitize-uri: 1.0.0 + unist-builder: 3.0.0 + unist-util-generated: 2.0.0 + unist-util-position: 4.0.3 + unist-util-visit: 4.1.0 + dev: false + + /mdast-util-to-string/3.1.0: + resolution: {integrity: sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==} + dev: false + + /mdn-data/2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + dev: false + + /mdurl/1.0.1: + resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + dev: false + + /micromark-core-commonmark/1.0.6: + resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==} + dependencies: + decode-named-character-reference: 1.0.1 + micromark-factory-destination: 1.0.0 + micromark-factory-label: 1.0.2 + micromark-factory-space: 1.0.0 + micromark-factory-title: 1.0.2 + micromark-factory-whitespace: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-chunked: 1.0.0 + micromark-util-classify-character: 1.0.0 + micromark-util-html-tag-name: 1.0.0 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-resolve-all: 1.0.0 + micromark-util-subtokenize: 1.0.2 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.3 + dev: false + + /micromark-factory-destination/1.0.0: + resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-factory-label/1.0.2: + resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.3 + dev: false + + /micromark-factory-space/1.0.0: + resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-types: 1.0.2 + dev: false + + /micromark-factory-title/1.0.2: + resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.3 + dev: false + + /micromark-factory-whitespace/1.0.0: + resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-character/1.1.0: + resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==} + dependencies: + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-chunked/1.0.0: + resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==} + dependencies: + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-classify-character/1.0.0: + resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-combine-extensions/1.0.0: + resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==} + dependencies: + micromark-util-chunked: 1.0.0 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-decode-numeric-character-reference/1.0.0: + resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==} + dependencies: + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-decode-string/1.0.2: + resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==} + dependencies: + decode-named-character-reference: 1.0.1 + micromark-util-character: 1.1.0 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-encode/1.0.1: + resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==} + dev: false + + /micromark-util-html-tag-name/1.0.0: + resolution: {integrity: sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g==} + dev: false + + /micromark-util-normalize-identifier/1.0.0: + resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==} + dependencies: + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-resolve-all/1.0.0: + resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==} + dependencies: + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-sanitize-uri/1.0.0: + resolution: {integrity: sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-encode: 1.0.1 + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-subtokenize/1.0.2: + resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==} + dependencies: + micromark-util-chunked: 1.0.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.3 + dev: false + + /micromark-util-symbol/1.0.1: + resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==} + dev: false + + /micromark-util-types/1.0.2: + resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==} + dev: false + + /micromark/3.0.10: + resolution: {integrity: sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==} + dependencies: + '@types/debug': 4.1.7 + debug: 4.3.4 + decode-named-character-reference: 1.0.1 + micromark-core-commonmark: 1.0.6 + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-chunked: 1.0.0 + micromark-util-combine-extensions: 1.0.0 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-encode: 1.0.1 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-resolve-all: 1.0.0 + micromark-util-sanitize-uri: 1.0.0 + micromark-util-subtokenize: 1.0.2 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.3 + transitivePeerDependencies: + - supports-color + dev: false + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime/1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + requiresBuild: true + dev: false + optional: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch/5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimatch/9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /mjml-browser/4.14.1: + resolution: {integrity: sha512-kkY43kYTGfw0qL251GrG3hdQvKeeKAzxgM+zFd97Pay2nZX06W9V6rm03zCfnOQdwGM90xMOBF+x9SIhRPkiJQ==} + dev: false + + /mkdirp/1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mri/1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: false + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /mz/2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: true + + /nano-css/5.3.5_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + css-tree: 1.1.3 + csstype: 3.0.11 + fastest-stable-stringify: 2.0.2 + inline-style-prefixer: 6.0.4 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + rtl-css-js: 1.16.1 + sourcemap-codec: 1.4.8 + stacktrace-js: 2.0.2 + stylis: 4.3.0 + dev: false + + /nanoid/3.3.2: + resolution: {integrity: sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: false + + /needle/3.2.0: + resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + requiresBuild: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.6.3 + sax: 1.2.4 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /next-auth/4.3.1_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-DBYEPBLq5naIqh/1i2zEHljcA1OXXecKW3NRU1W4s6R3UX3RdLZ2lWlqgBHUiZQ1zdNikFM/bYQxVGyG7bx8oA==} + engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0} + peerDependencies: + nodemailer: ^6.6.5 + react: ^17.0.2 || ^18.0.0-0 + react-dom: ^17.0.2 || ^18.0.0-0 + peerDependenciesMeta: + nodemailer: + optional: true + dependencies: + '@babel/runtime': 7.17.9 + '@panva/hkdf': 1.0.1 + cookie: 0.4.2 + jose: 4.6.0 + oauth: 0.9.15 + openid-client: 5.1.4 + preact: 10.7.1 + preact-render-to-string: 5.1.21_preact@10.7.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + uuid: 8.3.2 + dev: false + + /next-prisma-plugin-webpack5/0.0.0-dripip: + resolution: {integrity: sha512-Ms44uwOQTpxyLxEVfpyr6U/ATiUZIA2koud9W2V7yXUp58PQfHO1hrABbJ/q/TfWf9f/ovEizvFCed7ye4v1lg==} + dev: false + + /next-with-less/3.0.1_pvwbzhsolcgcqgt45pfwdigxzi: + resolution: {integrity: sha512-lVJQ+dNWGpR1ccWM/LjY+8i28DC2oPa1Ivrc+h4+DFPJJN6O2EGKZIFBGrd9GLbwAEjFzKPs7yUk6bnrbY0qcw==} + peerDependencies: + less: '*' + less-loader: '>= 7.0.0' + next: '>= 11.0.1' + dependencies: + clone-deep: 4.0.1 + less: 4.2.0 + less-loader: 11.1.3_less@4.2.0 + next: 12.1.4_biqbaboplfbrettd7655fr4n2y + dev: false + + /next/12.1.4_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-DA4g97BM4Z0nKtDvCTm58RxdvoQyYzeg0AeVbh0N4Y/D8ELrNu47lQeEgRGF8hV4eQ+Sal90zxrJQQG/mPQ8CQ==} + engines: {node: '>=12.22.0'} + hasBin: true + peerDependencies: + fibers: '>= 3.1.0' + node-sass: ^6.0.0 || ^7.0.0 + react: ^17.0.2 || ^18.0.0-0 + react-dom: ^17.0.2 || ^18.0.0-0 + sass: ^1.3.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + dependencies: + '@next/env': 12.1.4 + caniuse-lite: 1.0.30001327 + postcss: 8.4.5 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + styled-jsx: 5.0.1_react@18.2.0 + optionalDependencies: + '@next/swc-android-arm-eabi': 12.1.4 + '@next/swc-android-arm64': 12.1.4 + '@next/swc-darwin-arm64': 12.1.4 + '@next/swc-darwin-x64': 12.1.4 + '@next/swc-linux-arm-gnueabihf': 12.1.4 + '@next/swc-linux-arm64-gnu': 12.1.4 + '@next/swc-linux-arm64-musl': 12.1.4 + '@next/swc-linux-x64-gnu': 12.1.4 + '@next/swc-linux-x64-musl': 12.1.4 + '@next/swc-win32-arm64-msvc': 12.1.4 + '@next/swc-win32-ia32-msvc': 12.1.4 + '@next/swc-win32-x64-msvc': 12.1.4 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + dev: false + + /nopt/6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + + /number-precision/1.6.0: + resolution: {integrity: sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==} + dev: false + + /oauth/0.9.15: + resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} + dev: false + + /object-assign/4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + /object-hash/2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + dev: false + + /oidc-token-hash/5.0.1: + resolution: {integrity: sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ==} + engines: {node: ^10.13.0 || >=12.0.0} + dev: false + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /openid-client/5.1.4: + resolution: {integrity: sha512-36/PZY3rDgiIFj2uCL9a1fILPmIwu3HksoWO4mukgXe74ZOsEisJMMqTMfmPNw6j/7kO0mBc2xqy4eYRrB8xPA==} + engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0} + dependencies: + jose: 4.6.0 + lru-cache: 6.0.0 + object-hash: 2.2.0 + oidc-token-hash: 5.0.1 + dev: false + + /overlayscrollbars-react/0.3.0_xe725h2d5kcgarcqbsx2itrmxy: + resolution: {integrity: sha512-dV74p9VL/aImqJpeYz0vmpScZYu6UiNTmRKfyI4CS0OYUpYCUiTd723adY38Grz2W57hoNCECWDzkOJRFDQeZg==} + peerDependencies: + overlayscrollbars: ^1.10.0 + react: ^16.4.0 || ^17.0.0 || ^18.0.0 + dependencies: + overlayscrollbars: 1.13.3 + react: 18.2.0 + dev: false + + /overlayscrollbars/1.13.3: + resolution: {integrity: sha512-1nB/B5kaakJuHXaLXLRK0bUIilWhUGT6q5g+l2s5vqYdLle/sd0kscBHkQC1kuuDg9p9WR4MTdySDOPbeL/86g==} + dev: false + + /parse-node-version/1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + dev: false + + /parse5-htmlparser2-tree-adapter/6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + dependencies: + parse5: 6.0.1 + dev: true + + /parse5/5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + dev: true + + /parse5/6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: true + + /passport-google-oauth20/2.0.0: + resolution: {integrity: sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==} + engines: {node: '>= 0.4.0'} + dependencies: + passport-oauth2: 1.7.0 + dev: false + + /passport-oauth2/1.7.0: + resolution: {integrity: sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==} + engines: {node: '>= 0.4.0'} + dependencies: + base64url: 3.0.1 + oauth: 0.9.15 + passport-strategy: 1.0.0 + uid2: 0.0.4 + utils-merge: 1.0.1 + dev: false + + /passport-strategy/1.0.0: + resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==} + engines: {node: '>= 0.4.0'} + dev: false + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: false + + /pify/4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: false + optional: true + + /postcss/8.4.5: + resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.2 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + + /preact-render-to-string/5.1.21_preact@10.7.1: + resolution: {integrity: sha512-wbMtNU4JpfvbE04iCe7BZ1yLYN8i6NRrq+NhR0fUINjPXGu3ZIc4GM5ScOiwdIP1sPXv9SVETuud/tmQGMvdNQ==} + peerDependencies: + preact: '>=10' + dependencies: + preact: 10.7.1 + pretty-format: 3.8.0 + dev: false + + /preact/10.7.1: + resolution: {integrity: sha512-MufnRFz39aIhs9AMFisonjzTud1PK1bY+jcJLo6m2T9Uh8AqjD77w11eAAawmjUogoGOnipECq7e/1RClIKsxg==} + dev: false + + /pretty-format/3.8.0: + resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + dev: false + + /prisma/4.2.0: + resolution: {integrity: sha512-EswC2+mFi2oKQ/IDVkokDxwAsuiuYH4gKGkNNMAQ+86f3qwOo4tiVubCRxrQp5d61F+Yf+30f8Sv0zwWMnj0XQ==} + engines: {node: '>=14.17'} + hasBin: true + requiresBuild: true + dependencies: + '@prisma/engines': 4.2.0 + + /prop-types/15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: false + + /property-information/6.1.1: + resolution: {integrity: sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==} + dev: false + + /proto-list/1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + dev: false + + /proxy-from-env/1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /prr/1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + dev: false + optional: true + + /punycode/2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: false + + /query-string/8.1.0: + resolution: {integrity: sha512-BFQeWxJOZxZGix7y+SByG3F36dA0AbTy9o6pSmKFcFz7DAj0re9Frkty3saBn3nHo3D0oZJ/+rx3r8H8r8Jbpw==} + engines: {node: '>=14.16'} + dependencies: + decode-uri-component: 0.4.1 + filter-obj: 5.1.0 + split-on-first: 3.0.0 + dev: false + + /raw-loader/4.0.2: + resolution: {integrity: sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + dev: false + + /react-clientside-effect/1.2.6_react@18.2.0: + resolution: {integrity: sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==} + peerDependencies: + react: ^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.22.15 + react: 18.2.0 + dev: false + + /react-codemirror2/7.2.1_6af5glenfwdy3o6gdj2q5bzm54: + resolution: {integrity: sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==} + peerDependencies: + codemirror: 5.x + react: '>=15.5 <=16.x' + dependencies: + codemirror: 5.65.15 + react: 18.2.0 + dev: false + + /react-color/2.19.3_react@18.2.0: + resolution: {integrity: sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==} + peerDependencies: + react: '*' + dependencies: + '@icons/material': 0.2.4_react@18.2.0 + lodash: 4.17.21 + lodash-es: 4.17.21 + material-colors: 1.2.6 + prop-types: 15.8.1 + react: 18.2.0 + reactcss: 1.2.3_react@18.2.0 + tinycolor2: 1.6.0 + dev: false + + /react-dom/18.2.0_react@18.2.0: + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + + /react-final-form-arrays/3.1.4_kmr6azhn2v3y2ahfq4sxk65mkq: + resolution: {integrity: sha512-siVFAolUAe29rMR6u8VwepoysUcUdh6MLV2OWnCtKpsPRUdT9VUgECjAPaVMAH2GROZNiVB9On1H9MMrm9gdpg==} + peerDependencies: + final-form: ^4.15.0 + final-form-arrays: '>=1.0.4' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-final-form: ^6.2.1 + dependencies: + '@babel/runtime': 7.22.15 + final-form: 4.20.10 + final-form-arrays: 3.1.0_final-form@4.20.10 + react: 18.2.0 + react-final-form: 6.5.9_anngbwyi5kay4c5jh7oectltc4 + dev: false + + /react-final-form/6.5.9_anngbwyi5kay4c5jh7oectltc4: + resolution: {integrity: sha512-x3XYvozolECp3nIjly+4QqxdjSSWfcnpGEL5K8OBT6xmGrq5kBqbA6+/tOqoom9NwqIPPbxPNsOViFlbKgowbA==} + peerDependencies: + final-form: ^4.20.4 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.17.9 + final-form: 4.20.10 + react: 18.2.0 + dev: false + + /react-focus-lock/2.9.5_lwp2vdxnjqlnnpmgijegqsjvcq: + resolution: {integrity: sha512-h6vrdgUbsH2HeD5I7I3Cx1PPrmwGuKYICS+kB9m+32X/9xHRrAbxgvaBpG7BFBN9h3tO+C3qX1QAVESmi4CiIA==} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.15 + '@types/react': 17.0.44 + focus-lock: 0.11.6 + prop-types: 15.8.1 + react: 18.2.0 + react-clientside-effect: 1.2.6_react@18.2.0 + use-callback-ref: 1.3.0_lwp2vdxnjqlnnpmgijegqsjvcq + use-sidecar: 1.1.2_lwp2vdxnjqlnnpmgijegqsjvcq + dev: false + + /react-is/16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: false + + /react-is/18.0.0: + resolution: {integrity: sha512-yUcBYdBBbo3QiPsgYDcfQcIkGZHfxOaoE6HLSnr1sPzMhdyxusbfKOSUbSd/ocGi32dxcj366PsTj+5oggeKKw==} + dev: false + + /react-markdown/8.0.2_lwp2vdxnjqlnnpmgijegqsjvcq: + resolution: {integrity: sha512-WeXeDlCPFZBbN75AiLVEmN4gC6pNWadsZVWWxWpvrYQnUTHsB3l1PH60I1sbxTJr0oWOQc3zhxTrRQMTceNifw==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + dependencies: + '@types/hast': 2.3.4 + '@types/prop-types': 15.7.5 + '@types/react': 17.0.44 + '@types/unist': 2.0.6 + comma-separated-tokens: 2.0.2 + hast-util-whitespace: 2.0.0 + prop-types: 15.8.1 + property-information: 6.1.1 + react: 18.2.0 + react-is: 18.0.0 + remark-parse: 10.0.1 + remark-rehype: 10.1.0 + space-separated-tokens: 2.0.1 + style-to-object: 0.3.0 + unified: 10.1.2 + unist-util-visit: 4.1.0 + vfile: 5.3.2 + transitivePeerDependencies: + - supports-color + dev: false + + /react-transition-group/4.4.5_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + dependencies: + '@babel/runtime': 7.22.15 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + + /react-universal-interface/0.6.2_react@18.2.0+tslib@2.3.1: + resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} + peerDependencies: + react: '*' + tslib: '*' + dependencies: + react: 18.2.0 + tslib: 2.3.1 + dev: false + + /react-use/17.4.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@types/js-cookie': 2.2.7 + '@xobotyi/scrollbar-width': 1.9.5 + copy-to-clipboard: 3.3.3 + fast-deep-equal: 3.1.3 + fast-shallow-equal: 1.0.0 + js-cookie: 2.2.1 + nano-css: 5.3.5_biqbaboplfbrettd7655fr4n2y + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-universal-interface: 0.6.2_react@18.2.0+tslib@2.3.1 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + set-harmonic-interval: 1.0.1 + throttle-debounce: 3.0.1 + ts-easing: 0.2.0 + tslib: 2.3.1 + dev: false + + /react/18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + + /reactcss/1.2.3_react@18.2.0: + resolution: {integrity: sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==} + peerDependencies: + react: '*' + dependencies: + lodash: 4.17.21 + react: 18.2.0 + dev: false + + /reflect-metadata/0.1.13: + resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} + dev: true + + /regenerator-runtime/0.13.9: + resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} + dev: false + + /regenerator-runtime/0.14.0: + resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} + dev: false + + /remark-parse/10.0.1: + resolution: {integrity: sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-from-markdown: 1.2.0 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-rehype/10.1.0: + resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} + dependencies: + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + mdast-util-to-hast: 12.1.1 + unified: 10.1.2 + dev: false + + /require-directory/2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /resize-observer-polyfill/1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + dev: false + + /rtl-css-js/1.16.1: + resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} + dependencies: + '@babel/runtime': 7.22.15 + dev: false + + /sade/1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: false + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + optional: true + + /sax/1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + + /scheduler/0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /schema-utils/3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.13 + ajv: 6.12.6 + ajv-keywords: 3.5.2_ajv@6.12.6 + dev: false + + /screenfull/5.2.0: + resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + engines: {node: '>=0.10.0'} + dev: false + + /scroll-into-view-if-needed/2.2.20: + resolution: {integrity: sha512-P9kYMrhi9f6dvWwTGpO5I3HgjSU/8Mts7xL3lkoH5xlewK7O9Obdc5WmMCzppln7bCVGNmf3qfoZXrpCeyNJXw==} + dependencies: + compute-scroll-into-view: 1.0.11 + dev: false + + /semver/5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: false + optional: true + + /semver/7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /set-harmonic-interval/1.0.1: + resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} + engines: {node: '>=6.9'} + dev: false + + /sha.js/2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /shallow-clone/3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + dependencies: + kind-of: 6.0.3 + dev: false + + /shallowequal/1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + dev: false + + /simple-swizzle/0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: false + + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: false + + /source-map/0.5.6: + resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} + engines: {node: '>=0.10.0'} + dev: false + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: false + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: false + + /space-separated-tokens/2.0.1: + resolution: {integrity: sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==} + dev: false + + /split-on-first/3.0.0: + resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} + engines: {node: '>=12'} + dev: false + + /stack-generator/2.0.10: + resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} + dependencies: + stackframe: 1.3.4 + dev: false + + /stackframe/1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + dev: false + + /stacktrace-gps/3.1.2: + resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} + dependencies: + source-map: 0.5.6 + stackframe: 1.3.4 + dev: false + + /stacktrace-js/2.0.2: + resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + dependencies: + error-stack-parser: 2.1.4 + stack-generator: 2.0.10 + stacktrace-gps: 3.1.2 + dev: false + + /string-width/4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /style-to-object/0.3.0: + resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} + dependencies: + inline-style-parser: 0.1.1 + dev: false + + /styled-jsx/5.0.1_react@18.2.0: + resolution: {integrity: sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + dependencies: + react: 18.2.0 + dev: false + + /stylis/4.3.0: + resolution: {integrity: sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==} + dev: false + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /text-segmentation/1.0.3: + resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} + dependencies: + utrie: 1.0.2 + dev: false + + /thenify-all/1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: true + + /thenify/3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: true + + /throttle-debounce/3.0.1: + resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} + engines: {node: '>=10'} + dev: false + + /tinycolor2/1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + dev: false + + /toggle-selection/1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + dev: false + + /trough/2.1.0: + resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + dev: false + + /ts-easing/0.2.0: + resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} + dev: false + + /ts-node/10.7.0_3wvmryjdv2zgb5mgtbgo5b2ija: + resolution: {integrity: sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.7.0 + '@tsconfig/node10': 1.0.8 + '@tsconfig/node12': 1.0.9 + '@tsconfig/node14': 1.0.1 + '@tsconfig/node16': 1.0.2 + '@types/node': 16.11.26 + acorn: 8.7.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.6.3 + v8-compile-cache-lib: 3.0.0 + yn: 3.1.1 + dev: true + + /tslib/2.3.1: + resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} + + /typeorm/0.2.45: + resolution: {integrity: sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==} + hasBin: true + peerDependencies: + '@sap/hana-client': ^2.11.14 + better-sqlite3: ^7.1.2 + hdb-pool: ^0.1.6 + ioredis: ^4.28.3 + mongodb: ^3.6.0 + mssql: ^6.3.1 + mysql2: ^2.2.5 + oracledb: ^5.1.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 + sql.js: ^1.4.0 + sqlite3: ^5.0.2 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + typeorm-aurora-data-api-driver: + optional: true + dependencies: + '@sqltools/formatter': 1.2.3 + app-root-path: 3.0.0 + buffer: 6.0.3 + chalk: 4.1.2 + cli-highlight: 2.1.11 + debug: 4.3.4 + dotenv: 8.6.0 + glob: 7.2.0 + js-yaml: 4.1.0 + mkdirp: 1.0.4 + reflect-metadata: 0.1.13 + sha.js: 2.4.11 + tslib: 2.3.1 + uuid: 8.3.2 + xml2js: 0.4.23 + yargs: 17.4.0 + zen-observable-ts: 1.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /typescript/4.6.3: + resolution: {integrity: sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /uid2/0.0.4: + resolution: {integrity: sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==} + dev: false + + /unified/10.1.2: + resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + dependencies: + '@types/unist': 2.0.6 + bail: 2.0.2 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.0.0 + trough: 2.1.0 + vfile: 5.3.2 + dev: false + + /unist-builder/3.0.0: + resolution: {integrity: sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-generated/2.0.0: + resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==} + dev: false + + /unist-util-is/5.1.1: + resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==} + dev: false + + /unist-util-position/4.0.3: + resolution: {integrity: sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-stringify-position/3.0.2: + resolution: {integrity: sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-visit-parents/4.1.1: + resolution: {integrity: sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + dev: false + + /unist-util-visit-parents/5.1.0: + resolution: {integrity: sha512-y+QVLcY5eR/YVpqDsLf/xh9R3Q2Y4HxkZTp7ViLDU6WtJCEcPmRzW1gpdWDCDIqIlhuPDXOgttqPlykrHYDekg==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + dev: false + + /unist-util-visit/3.1.0: + resolution: {integrity: sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + unist-util-visit-parents: 4.1.1 + dev: false + + /unist-util-visit/4.1.0: + resolution: {integrity: sha512-n7lyhFKJfVZ9MnKtqbsqkQEk5P1KShj0+//V7mAcoI6bpbUjh3C/OG8HVD+pBihfh6Ovl01m8dkcv9HNqYajmQ==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + unist-util-visit-parents: 5.1.0 + dev: false + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: false + + /use-callback-ref/1.3.0_lwp2vdxnjqlnnpmgijegqsjvcq: + resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 17.0.44 + react: 18.2.0 + tslib: 2.3.1 + dev: false + + /use-sidecar/1.1.2_lwp2vdxnjqlnnpmgijegqsjvcq: + resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 17.0.44 + detect-node-es: 1.1.0 + react: 18.2.0 + tslib: 2.3.1 + dev: false + + /utils-merge/1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /utrie/1.0.2: + resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} + dependencies: + base64-arraybuffer: 1.0.2 + dev: false + + /uuid/8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + /uvu/0.5.3: + resolution: {integrity: sha512-brFwqA3FXzilmtnIyJ+CxdkInkY/i4ErvP7uV0DnUVxQcQ55reuHphorpF+tZoVHK2MniZ/VJzI7zJQoc9T9Yw==} + engines: {node: '>=8'} + hasBin: true + dependencies: + dequal: 2.0.2 + diff: 5.0.0 + kleur: 4.1.4 + sade: 1.8.1 + dev: false + + /v8-compile-cache-lib/3.0.0: + resolution: {integrity: sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==} + dev: true + + /vfile-message/3.1.2: + resolution: {integrity: sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==} + dependencies: + '@types/unist': 2.0.6 + unist-util-stringify-position: 3.0.2 + dev: false + + /vfile/5.3.2: + resolution: {integrity: sha512-w0PLIugRY3Crkgw89TeMvHCzqCs/zpreR31hl4D92y6SOE07+bfJe+dK5Q2akwS+i/c801kzjoOr9gMcTe6IAA==} + dependencies: + '@types/unist': 2.0.6 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.2 + vfile-message: 3.1.2 + dev: false + + /wrap-ansi/7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + /xml2js/0.4.23: + resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} + engines: {node: '>=4.0.0'} + dependencies: + sax: 1.2.4 + xmlbuilder: 11.0.1 + dev: true + + /xmlbuilder/11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + dev: true + + /y18n/5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yargs-parser/20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /yargs-parser/21.0.1: + resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==} + engines: {node: '>=12'} + dev: true + + /yargs/16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: true + + /yargs/17.4.0: + resolution: {integrity: sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA==} + engines: {node: '>=12'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.0.1 + dev: true + + /yn/3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + + /zen-observable-ts/1.1.0: + resolution: {integrity: sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==} + dependencies: + '@types/zen-observable': 0.8.3 + zen-observable: 0.8.15 + dev: true + + /zen-observable/0.8.15: + resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} + dev: true diff --git a/nextjs-demo/prisma/migrations/20220408154015_init/migration.sql b/nextjs-demo/prisma/migrations/20220408154015_init/migration.sql new file mode 100644 index 000000000..9bbdbfcd6 --- /dev/null +++ b/nextjs-demo/prisma/migrations/20220408154015_init/migration.sql @@ -0,0 +1,84 @@ +-- CreateTable +CREATE TABLE "Post" ( + "id" TEXT NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT, + "published" BOOLEAN NOT NULL DEFAULT false, + "authorId" TEXT, + + CONSTRAINT "Post_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "accounts" ( + "id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "type" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "provider_account_id" TEXT NOT NULL, + "refresh_token" TEXT, + "access_token" TEXT, + "expires_at" INTEGER, + "token_type" TEXT, + "scope" TEXT, + "id_token" TEXT, + "session_state" TEXT, + "oauth_token_secret" TEXT, + "oauth_token" TEXT, + + CONSTRAINT "accounts_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "sessions" ( + "id" TEXT NOT NULL, + "session_token" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "sessions_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "users" ( + "id" TEXT NOT NULL, + "name" TEXT, + "email" TEXT, + "email_verified" TIMESTAMP(3), + "image" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "users_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "verificationtokens" ( + "identifier" TEXT NOT NULL, + "token" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "accounts_provider_provider_account_id_key" ON "accounts"("provider", "provider_account_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "sessions_session_token_key" ON "sessions"("session_token"); + +-- CreateIndex +CREATE UNIQUE INDEX "users_email_key" ON "users"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "verificationtokens_token_key" ON "verificationtokens"("token"); + +-- CreateIndex +CREATE UNIQUE INDEX "verificationtokens_identifier_token_key" ON "verificationtokens"("identifier", "token"); + +-- AddForeignKey +ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "accounts" ADD CONSTRAINT "accounts_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/nextjs-demo/prisma/migrations/20230922085005_email_template/migration.sql b/nextjs-demo/prisma/migrations/20230922085005_email_template/migration.sql new file mode 100644 index 000000000..0583cfc10 --- /dev/null +++ b/nextjs-demo/prisma/migrations/20230922085005_email_template/migration.sql @@ -0,0 +1,30 @@ +/* + Warnings: + + - You are about to drop the `Post` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "Post" DROP CONSTRAINT "Post_authorId_fkey"; + +-- DropTable +DROP TABLE "Post"; + +-- CreateTable +CREATE TABLE "EmailTemplate" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "thumbnail" TEXT NOT NULL, + "subject" TEXT NOT NULL, + "content" JSONB NOT NULL, + "userId" TEXT NOT NULL, + + CONSTRAINT "EmailTemplate_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "EmailTemplate_userId_idx" ON "EmailTemplate"("userId"); + +-- AddForeignKey +ALTER TABLE "EmailTemplate" ADD CONSTRAINT "EmailTemplate_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/nextjs-demo/prisma/migrations/migration_lock.toml b/nextjs-demo/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..fbffa92c2 --- /dev/null +++ b/nextjs-demo/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/nextjs-demo/prisma/prisma.ts b/nextjs-demo/prisma/prisma.ts new file mode 100755 index 000000000..a292dbc71 --- /dev/null +++ b/nextjs-demo/prisma/prisma.ts @@ -0,0 +1,22 @@ +import { PrismaClient } from '@prisma/client'; + +// Make global.cachedPrisma work with TypeScript +declare global { + // NOTE: This actually needs to be a "var", let/const don't work here. + // eslint-disable-next-line no-var + var cachedPrisma: PrismaClient; +} + +// Workaround to make Prisma Client work well during "next dev" +// @see https://www.prisma.io/docs/support/help-articles/nextjs-prisma-client-dev-practices +let prisma: PrismaClient; +if (process.env.NODE_ENV === 'production') { + prisma = new PrismaClient(); +} else { + if (!global.cachedPrisma) { + global.cachedPrisma = new PrismaClient(); + } + prisma = global.cachedPrisma; +} + +export default prisma; diff --git a/nextjs-demo/prisma/schema.prisma b/nextjs-demo/prisma/schema.prisma new file mode 100644 index 000000000..3d9676c5c --- /dev/null +++ b/nextjs-demo/prisma/schema.prisma @@ -0,0 +1,77 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model EmailTemplate { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) + thumbnail String + subject String + content Json + userId String + user User @relation(fields: [userId], references: [id]) + + @@index([userId]) +} + +model Account { + id String @id @default(cuid()) + userId String @map("user_id") + type String + provider String + providerAccountId String @map("provider_account_id") + refresh_token String? + access_token String? + expires_at Int? + token_type String? + scope String? + id_token String? + session_state String? + oauth_token_secret String? + oauth_token String? + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([provider, providerAccountId]) + @@map("accounts") +} + +model Session { + id String @id @default(cuid()) + sessionToken String @unique @map("session_token") + userId String @map("user_id") + expires DateTime + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@map("sessions") +} + +model User { + id String @id @default(cuid()) + name String? + email String? @unique + emailVerified DateTime? @map("email_verified") + image String? + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @updatedAt @map(name: "updated_at") + emailTemplates EmailTemplate[] + accounts Account[] + sessions Session[] + + @@map(name: "users") +} + +model VerificationToken { + identifier String + token String @unique + expires DateTime + + @@unique([identifier, token]) + @@map("verificationtokens") +} diff --git a/nextjs-demo/renovate.json b/nextjs-demo/renovate.json new file mode 100644 index 000000000..b2bfb6500 --- /dev/null +++ b/nextjs-demo/renovate.json @@ -0,0 +1,21 @@ +{ + "extends": ["config:base"], + "automerge": true, + "major": { + "automerge": false + }, + "masterIssue": true, + "additionalReviewers": ["ruheni"], + "semanticCommits": "enabled", + "dependencyDashboard": true, + "timezone": "Europe/Berlin", + "baseBranches": [ "main"], + "packageRules": [ + { + "baseBranchList": ["main"], + "packageNames": ["prisma", "@prisma/client"], + "enabled": true, + "updateTypes": ["major"] + } + ] +} diff --git a/nextjs-demo/tsconfig.json b/nextjs-demo/tsconfig.json new file mode 100644 index 000000000..84ccbc342 --- /dev/null +++ b/nextjs-demo/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "target": "ES5", + "lib": [ + "DOM", + "DOM.Iterable", + "ESNext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "baseUrl": ".", + "paths": { + "@/client/*": [ + "./client/*" + ], + "mjml-browser": [ + "../node_modules/@types/mjml" + ] + } + }, + "exclude": [ + "node_modules" + ], + "include": [ + "next-env.d.ts", + "next-auth.d.ts", + "**/*.ts", + "**/*.tsx" + ] +} diff --git a/packages/easy-email-extensions/src/AttributePanel/components/blocks/Section/index.tsx b/packages/easy-email-extensions/src/AttributePanel/components/blocks/Section/index.tsx index 7aa4e4db2..745a4d402 100644 --- a/packages/easy-email-extensions/src/AttributePanel/components/blocks/Section/index.tsx +++ b/packages/easy-email-extensions/src/AttributePanel/components/blocks/Section/index.tsx @@ -4,48 +4,55 @@ import { Background } from '@extensions/AttributePanel/components/attributes/Bac import { Border } from '@extensions/AttributePanel/components/attributes/Border'; import { AttributesPanelWrapper } from '@extensions/AttributePanel/components/attributes/AttributesPanelWrapper'; import { Collapse, Grid, Space, Switch } from '@arco-design/web-react'; -import { Stack, useBlock } from 'easy-email-editor'; +import { Stack, useBlock, useFocusIdx } from 'easy-email-editor'; import { BasicType, BlockManager } from 'easy-email-core'; import { ClassName } from '../../attributes/ClassName'; import { CollapseWrapper } from '../../attributes/CollapseWrapper'; +import { TextField } from '@extensions/components/Form'; export function Section() { const { focusBlock, setFocusBlock } = useBlock(); - + const { focusIdx } = useFocusIdx(); const noWrap = focusBlock?.data.value.noWrap; - const onChange = useCallback((checked) => { - if (!focusBlock) return; - focusBlock.data.value.noWrap = checked; - if (checked) { - const children = [...focusBlock.children]; - for (let i = 0; i < children.length; i++) { - const child = children[i]; - if (!child) continue; - if (child.type === BasicType.GROUP) { - children.splice(i, 1, ...child.children); + const onChange = useCallback( + checked => { + if (!focusBlock) return; + focusBlock.data.value.noWrap = checked; + if (checked) { + const children = [...focusBlock.children]; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (!child) continue; + if (child.type === BasicType.GROUP) { + children.splice(i, 1, ...child.children); + } + } + focusBlock.children = [ + BlockManager.getBlockByType(BasicType.GROUP)!.create({ + children: children, + }), + ]; + } else { + if ( + focusBlock.children.length === 1 && + focusBlock.children[0].type === BasicType.GROUP + ) { + focusBlock.children = focusBlock.children[0]?.children || []; } } - focusBlock.children = [ - BlockManager.getBlockByType(BasicType.GROUP)!.create({ - children: children, - }), - ]; - } else { - if ( - focusBlock.children.length === 1 && - focusBlock.children[0].type === BasicType.GROUP - ) { - focusBlock.children = focusBlock.children[0]?.children || []; - } - } - setFocusBlock({ ...focusBlock }); - }, [focusBlock, setFocusBlock]); + setFocusBlock({ ...focusBlock }); + }, + [focusBlock, setFocusBlock], + ); return ( - + @@ -61,19 +68,40 @@ export function Section() { + + + + + + + - - + + - + - +