From 391a4d6d184d96c149ff353b8a31f54fdb50fbdb Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Fri, 11 Oct 2024 20:36:19 +0530 Subject: [PATCH 01/17] Fix Examples --- package.json | 1 + public/banner.png | Bin 0 -> 9861 bytes public/logo.png | Bin 0 -> 19718 bytes public/npm.svg | 4 + src/examples/AddResource.jsx | 162 ------------- src/examples/AddResourceForm.jsx | 19 -- src/examples/CellUnits.jsx | 113 ---------- src/examples/ComingSoon.jsx | 8 - src/examples/CustomEventStyle.jsx | 177 --------------- src/examples/CustomHeader.jsx | 164 -------------- src/examples/CustomPopoverStyle.jsx | 198 ---------------- src/examples/OverlapCheck.jsx | 142 ------------ src/examples/app.jsx | 81 +++++++ src/examples/components/Fallback.jsx | 16 ++ src/examples/components/Header.jsx | 26 +++ src/examples/components/Landing.jsx | 25 ++ src/examples/components/ResourceItem.jsx | 9 + src/examples/components/ResourceList.jsx | 16 ++ src/examples/components/Slider.jsx | 20 ++ src/examples/components/SourceCode.jsx | 15 ++ src/examples/components/TaskItem.jsx | 9 + src/examples/components/TaskList.jsx | 16 ++ src/examples/css/style.css | 164 ++++++++++++++ src/examples/helpers/DnDTypes.js | 1 + src/examples/index.jsx | 5 +- .../Add-More/class-based.jsx} | 14 +- .../pages/Add-More/functional-based.jsx | 198 ++++++++++++++++ src/examples/pages/Add-More/index.jsx | 20 ++ .../Basic/class-based.jsx} | 60 ++--- src/examples/pages/Basic/index.jsx | 18 ++ .../pages/Drag-And-Drop/class-based.jsx | 209 +++++++++++++++++ .../pages/Drag-And-Drop/functional-based.jsx | 213 ++++++++++++++++++ src/examples/pages/Drag-And-Drop/index.jsx | 20 ++ src/examples/pages/Home.jsx | 26 +++ src/examples/pages/Read-Only/class-based.jsx | 93 ++++++++ src/examples/pages/Read-Only/index.jsx | 18 ++ src/index.html | 1 + src/index.js | 12 +- src/main.jsx | 6 - webpack/webpack.dev.config.js | 10 +- 40 files changed, 1264 insertions(+), 1045 deletions(-) create mode 100644 public/banner.png create mode 100644 public/logo.png create mode 100644 public/npm.svg delete mode 100644 src/examples/AddResource.jsx delete mode 100644 src/examples/AddResourceForm.jsx delete mode 100644 src/examples/CellUnits.jsx delete mode 100644 src/examples/ComingSoon.jsx delete mode 100644 src/examples/CustomEventStyle.jsx delete mode 100644 src/examples/CustomHeader.jsx delete mode 100644 src/examples/CustomPopoverStyle.jsx delete mode 100644 src/examples/OverlapCheck.jsx create mode 100644 src/examples/app.jsx create mode 100644 src/examples/components/Fallback.jsx create mode 100644 src/examples/components/Header.jsx create mode 100644 src/examples/components/Landing.jsx create mode 100644 src/examples/components/ResourceItem.jsx create mode 100644 src/examples/components/ResourceList.jsx create mode 100644 src/examples/components/Slider.jsx create mode 100644 src/examples/components/SourceCode.jsx create mode 100644 src/examples/components/TaskItem.jsx create mode 100644 src/examples/components/TaskList.jsx create mode 100644 src/examples/css/style.css create mode 100644 src/examples/helpers/DnDTypes.js rename src/examples/{AddMore.jsx => pages/Add-More/class-based.jsx} (94%) create mode 100644 src/examples/pages/Add-More/functional-based.jsx create mode 100644 src/examples/pages/Add-More/index.jsx rename src/examples/{Basic.jsx => pages/Basic/class-based.jsx} (80%) create mode 100644 src/examples/pages/Basic/index.jsx create mode 100644 src/examples/pages/Drag-And-Drop/class-based.jsx create mode 100644 src/examples/pages/Drag-And-Drop/functional-based.jsx create mode 100644 src/examples/pages/Drag-And-Drop/index.jsx create mode 100644 src/examples/pages/Home.jsx create mode 100644 src/examples/pages/Read-Only/class-based.jsx create mode 100644 src/examples/pages/Read-Only/index.jsx delete mode 100644 src/main.jsx diff --git a/package.json b/package.json index ff212d6..ad58e79 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "react-dnd": "^14.0.5", "react-dnd-html5-backend": "^14.1.0", "react-dom": "^18.3.1", + "react-router-dom": "^6.26.2", "rrule": "^2.8.1" }, "devDependencies": { diff --git a/public/banner.png b/public/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..0aeea405a3b5d75468ae692335ea7418f6b30ca2 GIT binary patch literal 9861 zcmb`tbyQSu{69D%2#A1$Agv%J3`i;sN+Ttuq#_LtNOy~rbTebHJeBUW-qa$5!pk#hJf!e}~~# znn#tC&z5y-s#`?0FFr&z{LXB^HOSMOT||)RKnr|`qO2eugzX;PwLprvXvhyDWktwq z{Cy$w*2~kfmvs*5ot>Sx3CS35b82MWj);gTFs!vJP|p-C@IBc*m-&g`5z9hLLc@D| zZLEsc=V&u|A|W9`zBfYzvv!Atg&!ezH{XJ~%h}nveD3#0BVuCWq@-kuJ9jKa>_>Y} zcTxN&h3d1JT>}PK@ z#B0^s>AlAe+@GG$4GqOVVb?8?C!WSDia;8jsip9u6T&;=?mt7~!}8(%vQ!je?(1ou zCz#aw8yt~Hi~Y^UEoW}0m6a9qu}Tx;>yNR%%{FEfo~*Y;S^4PvPFISJ2j5qE#Jz*A8EPR@J1_qh}F~omx_46 z26=>+KmoaX?SEA`Z=^OHV6e*0uC6)5OVM}#9>AIp^eb1;b?=NSr~-c~P;qKdU%zo{ zHiNle`m7u~f#4t8HTe2kj)Io9L&PZ&-4(9*vdXyrg+_R-*PhikOB9Wm9F6*YRTs9m zZIbvT?1l5~Q7Ew*+c*8IBV{O?fxIAP6_vRwf}lrybm$&`7T@il*3(ZXgs$iWosank`-^Rv_!8g1#=c$>+Irk!bI*xtRg7xwOc6S z@b?kQ<4Kt>1qBhmg0pkAh{vX}|IzPcd?`9~_2B+|iK#IDFO(drU~95IQHI#5K93!q zmBmdmak5V3z~#)uCZyd`aggr3j&0`~7C zi$B*EZFjaHfA-m>qq z=}8k{g+kTI#vu?9L;U^22}jy8gQ_KHJSusp=JB-Wv;CE!kM@wb+!vo!BQU7csKrH# zX-cmePI#=$<;zK*t>*d3dY2{w$aOH8 z+sFYtXW7` z`&HX{+ewgK((~&Rr&-7tL^c&M?X6aBSQ}|SO*>%wFNR6NqLs+i0pE#GeW1<;&06VY zB-@3p3b-iqJljCj(?}BBq`qy5N=Y8_8SL@a&>A}f?d}Y95>7O0_C7$~5J#^S`jp@| zTicM?bK0N@Bek-xSy)*`4iD>AdfjDb3$U=Xe5DXcoi9(5lqVJ!M$Q7Ww6N&x8b8-- z@%6%7UVOr0ZKj2=bv{Qh%#3854Z46}Yf3C5J&8lb=Xma8g?(kcVtv5l0+UAfNj%3r z2|7}GVdayLLrfxe!(W$r(tpR&KY0M(eq$)uK&{TcCc*O+U}{n>yMnC=XiyyW zg=Y26m_^r{!hcBb8N03ytMHmM=<@AjZ#1~5KT~Mxsj}EVSOpbYtg;g;$`A5y{n0-n~FCxyL-0qXuLi%S)3JAoj zc@NkX%#zVl=AQ{){IjpZBuH%5FEb0cVznw)6v}vg(ibciM_CGAeYbKRZk?!X+!W_q z$@d9xqF^ro#pkRZ`%v$TQGvm{R#IPK4Vnk%RIJ{E24GM4Qz z-Ni2TukIa+-RT*qJ7l5KBUAp2D4WI3c;lhv;Zhyv?Q#P#4Mn3m2LO=!Vep8qke~!@ zUth^Fyk}G7HYRRPnyGvyNNQwK618@*22*AI+D}3jYP~XjOolYf_wxB0dBK9u(ZL@m z(Rp$qNSd@3zq9T)+_O1~pXhBRGV+bKVTXhb)Fy44|7v;0_II2GorkZVVbSmaEEB!W zv8izV%0#qxTV%>`7H2Q`<~G4RPcobwkO@s;C+o zBp=Hx<+(MzfbGQo{r1*)@Z$|A$Abq>&?n~R<`%Sg0i4ps8tE=eJ!tm^LN9n!pOAH5 zQgQobiCJrl@o)Z@N(!_C3#*%|vO^L+$#4tT`8Hy}2(I|Ge8cs-WmPTCz7=2eD-50I zf&ljJ(GZ0J_6y(NckL){cUAB2?F;wf)-8!EF|HRJ+s_-n-qfuv=)6Equ?{a#(`LDE zSZ4Ptl=$S3wg8@=YU-_`;r{uI^v0pE&48@KBvRXS59PReH^VwAML$=>USF9KO~9^} zvY5bZs-YOOBvgpTP{eGa*VkjGpxJb6btm+|zH?{meMJ9bbuw$+HPAD^kxa zK-9|lpI~Uk{Nqi9=s8t}Sad$>H-sp7JTKjI_^OH0#Wp{CE9RDeaMIks=-!#Ay*1s8 zi6;)Ey-zp3d^{=*31s-cM9}|CdH-pp|M{@{x$c0k8w%XkMvbp;ryR`$n5|DYXW9q- zX8hap323mxH)IYFNb3Fny9oQAFZ{px`Tu_$CjUy>xNmGZH-HZaz;==E3Q9^*R=pV! zpdO;q((X>LRss}_1fr?4bqFXiuQGp7zf`5ArL25>F$m-uAQ5x0*yeM;KFotsZ_;bE zuWHt>u|Ypg;?_~5=6xB5XyD=GRPwzz7&8Z_{`#qO-@ed z@q&Va^2>`eBc&L|Ieo&JorR8y;#~iK4~>yut3O?a@z)!!jaDou5lfp@*ZzrRacuAC z;F(xWL~KD|(Cv3Mq0Yt@tXvw~D=h9UtY z@ldC3#CCsm1l8T!i;?;`3aYETu<(JUM7CnB-AH+PIq$TK4SEJ)*6QEwo{-hx^#)32z$dFNrFL)8?QVND56+)Tsiu-J0IdfkT^x51f< z7VCy2%W32j{WkpoMX{H~4xaPgC^F5Zc{cO*~H4R=6e)0Sm3mdsM0%lT~&KWm$>wF>IA}KEJ2m4+U@2dp0 zzGN=#V6~-)$jIGBznz_(0@-UWGyXwMRl@L!(ITsimFJGPuChDA*K?y2*gSPvGe7z?5r+}5Hs zl1wq_7Ov;V?|0g$G@W`Gt6DD`UN*Wz$Fjcjs_kz~7-WgLgdx&`!kW&v03gVzxf=ZB%co#Ny|ZoF!FOo@0>ucv|YVIr(Z_LkBOL`PGvLY&YrO)_5P-!Q8etrkf{L$G;adau(a= zwrZE@L+yVC6Wmv;Q;KD-1v17QG!U*V+uGY-z3qsp1r`a^Wz=O32`yjE>ToICAy;J% zW3f1{eO8FGT<#nH#Z69Nph0s_WH9#wy=4w6+01O%YT>5(NKh#E`ZCYll+C;p8o%cdAGkx z`5cA=jPAVu7OaW$XVYTb75Ifcy=Q*}InTO(xOqo@Z>bmacf`oCS+5%`mx zFmB@Mb<2&Lsoe6niK@bgb;8eqk{m73hA*;aeGxTf1`0G)XJ(O53Aj*(-Y4EOen%1a zpM`anTCV5mAc3n0N5hr&XhZ-ue*HkBjXaw6Y42bO=rLN~V>%B18A2FEOvSOCB7?Iq zMwgdItx@$Z%g((rHRKtATJ4F6Wq0_DU%IXgD&T}n-=Sx($k?{#q=J3WyNNn=f0u!7 zT6gld*?E?!EZ*4rfWEKCr=@Y-q~Yz9dEXCUt({!v{N7T3F24c3nD;){m3%IMgq=>d z*zgpnQFm1Sw{PFhsg4F7OI5@wM&S+2L*~9pYL{>rz}e^xOJqMvY&GfhWIm3yPtCKi zFnD78LqkR78@Q=9C|Nd8gRfdb^Bv$a+D)GC?f*p6H60D)dwuo$xY{jx$^gi(8pmw@ zp#$k6_9?*47;sP6sD{qtiTZ82L3!o0^JK5tgU8==6eXD){YAIb{9=DdbMoH+d_?kv zj!yDBH%j4amq00bR^=;E{k=Nr56}k)cfR2mu+W@w9~8}@Nr9I9*TnxU2;h9f@f2Be zU?0wjXuTfNp((|S@{^weIgzwc%kYJkZU< z^hkr7eLe3OXuEPy-0x8b;?9fVdcYoAGT?n8WcCbX!LR~A00i=$r+4q~+gR=i2TmJ5 zLBoEOJZSQw>R$H+Ak^lh(lI^hLZc#M#&C!45pu;+0KO2H2UP*D>_^MztSRoEG6=u> zr+eZl9?bW~xKGGqXtQCBk1xIW*+(*C=NP_20{e01Vw{fTJLwo6D+j8y06b}9A(je% zH5BwDA-=?*DhGLay4D^}!Dc~j8*s2Pq*Pd3?4mAXhKCtc0EnsgMRzX2>x)5EANw*E zmRE}9vwZp#Z!C-3w8?W|)A^JwZj5)h&T)n>jFf@HxA^5Q$=mkGJLgnBroKB00`KSL zE9;*fw8+V@{Z>#=c;EH>vQG1$*M@TD)%Db0v`hlMIZ{T#wuAD=8VhYed@8_Td{?@k z8XP50788wK`g0Mk_xcGFw;qo8a4Qa}}@0AS7nokSY7u!U` zKY~UIOB1oDalB{-Vk4q2TLN`y06QDXy=?pMA~<)!zBhnKY{h1-u8)5=7E-&{ALWZn z7X(R|?f`?3WAVm)K80NX|^XF@c~3@y{%DQ$<}p8I^Vw)D-cl^RM&Dz82J}M5>P&0vXwIKG%3%@N+Nn>Tb027r`7f2gb*P6)GFzse z_ImuaKOy^&{BEC01kPClgu1+-5kR~;*O1$=8S=v-^jnOZ$f;VUZ+2H%#qyHttHOqrx$fdb6hsjqfU{?0ofaduKeGC8ug5fLU3I)t4v3 zI-2i$nZY{)ks2uMe$NV00rw(|#vn_MQ}_mDw&5< zHTfYs5F-!PgcE;)h~xa~YA~7zR{m(=Mh0b=)pa5ZRylB?R1=RWH|Hct6SexCKMV@0 zs*&MQQ46`IbiGPR$;s?vbZ|_PppZ~|wIyo3%7jI}U+O4pfn+p5wyTqG|A*qeb%I_M zb*eMR@#+sUQr-h`Hw_UjK$29FiaFB*oEs5b1o30g0JZR+Pc&vkqYZw-HYcFo>R`yZ z8}^Y(YM1PAvFGs(!QRZqw8>Z0+2y}zkm|2_JegSb|u!c2gwOOy?1^q zBWoQ*3AJQQ;%&Kc1LE)JL-i_+#Vn1cZW%73`(*!~&yGq5viKG&va+!~i)N9T4%gH0 z&9y`~dN|Ih-E3m_tp5I80ThJ8Gg%AOYGNhDaOK#N60WtK4i zH-w5bbNecG$P*~=-UwkgM?fsonR~;fCreC+Lq#t$gznBm-8fXv8A-7%L=>lNE5H8x z_Eu@y{Dxt$GKxFl#xUn9z{#Zy7Jrn=;cO=nMMQi;g87NG%{lj@4v>%VnkDGgiRsFD z&|H{MUk5bkmFKo*OIo{&LG959Y4JN4F83V$T!vbKoQ(oJLCLW!IYB&RFnFk)^76$t z9Qkip!4luGAFISbt-L_uabXC(+eIWBq?i}5k5>A_L_tA+U2(`YEi&d`2`c2RZ-bQ@ z(pacKkHYbAGE;*u`#7dW*g(doTQ^?AWztZ?SUDfMoS+S~au!`y&NF8dKqgN-9UI(-8@HMvm{wT z#QoV;4>7wRgp9V(hs-5W66{USOM z(bm=$SNSZLR{WMht(bAh648r%c>d;8BToQlRUUieSoy2pK0D-0CJ4I`)%q(ZKsbuq zLS4Dm2^1#AA|v1d1Eo)8Yirv?y9W~K;qW&^;=$r;7sm^+=RJG{nfQRX^e$tv^Db^U zS5#@{N_Ss`sSVgxndH>hntfKi!G`zz4D$U#TPQIVa;XyM9)5iwaZ%3&k@DXhl^;Nb1J`CO zNbdGxFSV;b3V(O<`J99|#no|#4APxKJz55r&75ojhMorji0kl?6$q&3BRF$rGa3^T z6WhVr?H5Ng{YLwSUteEK-CatzsBv4<=S#Qlh++EA11OXkXoWTcZ_FLLJ?*v3lpg1r zSE#OJ)-Snt%dx)t6T{<3pcd|NnaS@r$($@w)r&_wyubGPF`d^^1{z0=6~g@>UBoS1 zi%x!Ek)_iR;LzlEWQb#srytW@Fi%lyUtGzCoZ4cRmUiLi%u{|9#`V>^N3MhiuM8Vp zxn*`8Cy_5Tw%$lExk|a&=X!HwhVe!I!Ffje#~`q2_YoqT!Vr&Sp~T^Deute$`}cd; zS+=*eaRn$TX=$FK&VL!xPPIxe9rM1un-KL6<=N8}EQqm|Ip4mH z5Z%XKp8&eZ(kMH0m4SEo^k}OJ6mWYKe@kaS_6U$@)%lfpNK6v|Bg_Ii{yOvoei{G^ z-AZ~cy@|0QQu=1zp43XE+yuhwb0UK!P{ne4jcEfX@!oT*SU| z-Ldp@6r4K?K}p;N^A{T2yyx}L;B%cLMlomkb(I3JxZA3eN^gZm;7`R=Xi2~BP?5Tq+U4qK1&Up&FGnhKi@IJ}@%A^6B(|~R z=p_8~V9f>UOUf+yQbT7gbkjoqaDDtYJFp+&%4jtDq!Ql<$Zj!d-n);9CkIP)I0Zlg zP&uyjOx_i>^@k9AWFao*$Z1(D)`lxO2YX3ejS1s|5uIXn%0-!%$wTj=*x;25-0-kDlX^bk2a?;x~yIY z{Q?A1k5%P^${m6&@NYl3G$t${Yt8jLOh>ysL9Z+V0@~fEi_1kKpYW}?tPXSYm5Qk< zUS|2=rG>*p&O*F@@SC+v>IYpDP#y4-NYd$OU9B5y7U2r{QWvF;r;!ht-=3~dD1nHAQ&*gx3Aey01 zh5VWTMT#sWRIk(Adx`NFQ%)6l`zIU(?Jnw7AftJ&LazEZna5x$BV)lr-h&d-^m^l8 zt?}S;{zqoY?^eCelcj^DV16m^`UeCg)l{f=GcDQn-de1K-q$j zmh4`nQf_lMOz@;qL}jrrn~(+&0Zk06KPpL2 zCLrfTUSI;!eE844n^5uIFK8q!KMbUZ(KF+lXR{&X}(6>xQ-udh#Y zm2$@MJT1>bEpMlrr)ryRu@}u6lUl%i1KTYPH72^fsTj))&GFq;sU#pgfD{W@4o{q% zZMCL;7vx}P?^;tEPLD78LrOEFow+{H1g6Z>1^tK_fBULbcv}vQtdjFaeEJ%vMUW*NYws?NP1TS9U|8okJhN|s+YApteeIdiN z<}hpH=RsD|xhR-%St`ndy8?OyI5A z$KkTot@X~Y?-vxyfGg^5RmcPGx+m6LQ?}SPRB_>QS>`JK3NN$~bV}EI%lKKqz0M<4 z4W1h}4ClKjG*quK2$+WoO0eFZqft>&83n@UID5kcr~n=5046yTDi9;J$6CbJS;!mo z{3ogI;!(ijGcq1ZT=Twj;Pyhw(d0dlKD%t=#ZbEV5JGZ8AZWEj$-pDs&bE4qn>lzO zJS@PxD`)DmOhRl`JfXAS+Mm2@E)E6cW_u5-J5AUl_iS7g`V7Z`WHy6Vva42xo4|un# zfw7k0vVKTFLbJbSh$g7yVA}xc_79C^4pW%eI#qDr7uN0 zC1*l_H|H(L>Kavp6Iq;r;F1FrKZN=v-)2kuWz5VijemRl(G3Mfa7}C}KH%WEAvy4b zs|y>PE@a)USeA1OtSFGZdiK*zUgw*l*V&a<0~x8PK!9N+VA)L#3%UxqdTIfL1wQlRH#$-u z>dl)YPfEh_IX^-(wUp`<8*+1Vce~d!0i`$Ut}SEHg~e-FP#m&v5OD_0=sxK>q&~{v z*z|_!iBsSV=Cs13anu{=w5Q&P49e~Elf8O{AQCUZhFOrLCGFV_k(7GR6Uie9{9f8t zuF;x$%5lVkdC_*`lvqQP90GfGw8c^l&qFPAapo?LuFM@V{)H8IdD=#p+|1~E12$-! zQw45gBu;4`PdbHUk&BCoy#guni@v0cxVU>)pSh(pvYytdf)!#6#t+gh__9sPVWvZDY7BdtuX&{t!)>~P(}Xn1Ga7942KrbIrAXh znupF-0b2C3v$8L>lfjqV;0^2oMcE!qKq4P zI9zDh;JWh5=pH|iCrPwrA#RaT;LHz|e$O*S)o(G0>&h!A?C2wn!Tn-3&iSMln57(%|Xtg=CsBVQ}~ z&%7`xD}8oYIoMEf3zRlB*X??ikN;}zqrjN*!@f684M{e{2;;WJd`tNgqX71}+!X+u z8FoN$LwIl+cT-~s!Y3D^XXZIaAYj#Vcid+J1y1J#N|zHSkBpv@08{w}H`3Xj{khwh zIVR0IX5x|UiAgq)2a3xpiVlPoyEr8CN)q-vb$x$%?ln!H!$pjnb{BsB+_m!jd58u6 z>))Vv+W--AS@mUcgHA*l{eA}KeT&+rz-N7GQI561pZx*y9?ZrT;ExF0+{KQ$;n7t7 zGeUH;kB3+hFQd38E8Vr@AdPVwnn8~lKLg+0E>35>A6jsD4%k@{&Mf5}u8}R?#VzxT zIDtYo5bWTt)ZyYG)Hek!z!Lw)w z_l`Lz@;f`+(Y#0nnecL7(WR_#)ou2BkFAVv-Fd(kcrQ;{Z35w#8l}$o#7P!}7B4v} zhKe;&Puy0M&I5$SWU^ssiwkPu4}|P2s^Y@@iT~%k?-3*Z|8pbOwa{Z3t}1i35BHGK RVCxt}ML|Qp^6Bf~{{s*bSOfq7 literal 0 HcmV?d00001 diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..485be64e5271fa9bf81be22e7b275c0508d7ed1f GIT binary patch literal 19718 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 literal 0 HcmV?d00001 diff --git a/public/npm.svg b/public/npm.svg new file mode 100644 index 0000000..6f57583 --- /dev/null +++ b/public/npm.svg @@ -0,0 +1,4 @@ + + + diff --git a/src/examples/AddResource.jsx b/src/examples/AddResource.jsx deleted file mode 100644 index bd67a33..0000000 --- a/src/examples/AddResource.jsx +++ /dev/null @@ -1,162 +0,0 @@ -import React, { Component } from 'react'; -import dayjs from 'dayjs'; -import { SchedulerData, ViewType, DATE_FORMAT, DemoData, Scheduler, wrapperFun } from '../components/index'; -import AddResourceForm from './AddResourceForm'; - -class AddResource extends Component { - constructor(props) { - super(props); - const today = dayjs().format(DATE_FORMAT); - const schedulerData = new SchedulerData(today, ViewType.Week); - schedulerData.localeDayjs.locale('en'); - schedulerData.setResources(DemoData.resources); - schedulerData.setEvents(DemoData.events); - this.state = { - viewModel: schedulerData, - visible: false, - }; - } - - showModal = () => this.setState({ visible: true }); - - handleCancel = () => this.setState({ visible: false }); - - saveFormRef = form => (this.form = form); - - handleCreate = () => { - const { form } = this; - form.validateFields().then(values => { - this.addResource(values.name); - form.resetFields(); - this.setState({ visible: false }); - }); - }; - - render() { - const { viewModel } = this.state; - - const leftCustomHeader = ( -
- - Add a resource - - -
- ); - - return ( -
-
-

Add resource

- -
-
- ); - } - - prevClick = schedulerData => { - schedulerData.prev(); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - nextClick = schedulerData => { - schedulerData.next(); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - onViewChange = (schedulerData, view) => { - schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - onSelectDate = (schedulerData, date) => { - schedulerData.setDate(date); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - eventClicked = (schedulerData, event) => { - alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops1 = (schedulerData, event) => { - alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops2 = (schedulerData, event) => { - alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { - if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { - let newFreshId = 0; - schedulerData.events.forEach(item => { - if (item.id >= newFreshId) newFreshId = item.id + 1; - }); - - const newEvent = { id: newFreshId, title: 'New event you just created', start, end, resourceId: slotId, bgColor: 'purple' }; - schedulerData.addEvent(newEvent); - this.setState({ viewModel: schedulerData }); - } - }; - - updateEventStart = (schedulerData, event, newStart) => { - if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { - schedulerData.updateEventStart(event, newStart); - } - this.setState({ viewModel: schedulerData }); - }; - - updateEventEnd = (schedulerData, event, newEnd) => { - if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { - schedulerData.updateEventEnd(event, newEnd); - } - this.setState({ viewModel: schedulerData }); - }; - - moveEvent = (schedulerData, event, slotId, slotName, start, end) => { - if ( - confirm( - `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` - ) - ) { - schedulerData.moveEvent(event, slotId, slotName, start, end); - this.setState({ viewModel: schedulerData }); - } - }; - - addResource = resourceName => { - const schedulerData = this.state.viewModel; - const newFreshId = schedulerData.resources.length + 1; - const newFreshName = resourceName; - schedulerData.addResource({ id: newFreshId, name: newFreshName }); - this.setState({ viewModel: schedulerData }); - }; - - toggleExpandFunc = (schedulerData, slotId) => { - schedulerData.toggleExpandStatus(slotId); - this.setState({ viewModel: schedulerData }); - }; -} - -export default wrapperFun(AddResource); diff --git a/src/examples/AddResourceForm.jsx b/src/examples/AddResourceForm.jsx deleted file mode 100644 index 7353e7b..0000000 --- a/src/examples/AddResourceForm.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React, { forwardRef } from 'react'; -import { Modal, Form, Input } from 'antd'; - -const FormItem = Form.Item; - -const AddResourceForm = forwardRef((props, ref) => { - const { visible, onCancel, onCreate } = props; - return ( - -
- - - -
-
- ); -}); - -export default AddResourceForm; diff --git a/src/examples/CellUnits.jsx b/src/examples/CellUnits.jsx deleted file mode 100644 index 176e7d2..0000000 --- a/src/examples/CellUnits.jsx +++ /dev/null @@ -1,113 +0,0 @@ -import React, { Component } from 'react'; -import { Scheduler, SchedulerData, ViewType, CellUnit, DemoData, wrapperFun, DATE_FORMAT } from '../components/index'; - -class CellUnitComponent extends Component { - constructor(props) { - super(props); - - const schedulerData = new SchedulerData( - '2022-12-10', - ViewType.Custom, - false, - false, - { - customCellWidth: 150, - nonAgendaDayCellHeaderFormat: 'M/D|HH:mm', - views: [ - { viewName: 'Week', viewType: ViewType.Custom, showAgenda: false, isEventPerspective: false }, - { viewName: 'Month', viewType: ViewType.Custom1, showAgenda: false, isEventPerspective: false }, - { viewName: 'Year', viewType: ViewType.Custom2, showAgenda: false, isEventPerspective: false }, - ], - }, - { getCustomDateFunc: this.getCustomDate } - ); - schedulerData.localeDayjs.locale('en'); - schedulerData.setResources(DemoData.resources); - schedulerData.setEvents(DemoData.events); - this.state = { viewModel: schedulerData }; - } - - render() { - const { viewModel } = this.state; - return ( -
-

Custom time window

- -
- ); - } - - prevClick = schedulerData => { - schedulerData.prev(); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - nextClick = schedulerData => { - schedulerData.next(); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - onViewChange = (schedulerData, view) => { - schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); - schedulerData.config.customCellWidth = view.viewType === ViewType.Custom ? 30 : 80; - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - onSelectDate = (schedulerData, date) => { - schedulerData.setDate(date); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - getCustomDate = (schedulerData, num, date = undefined) => { - const { viewType } = schedulerData; - let selectDate = schedulerData.startDate; - if (date !== undefined) selectDate = date; - - let startDate = num === 0 - ? selectDate - : schedulerData - .localeDayjs(selectDate) - .add(2 * num, 'days') - .format(DATE_FORMAT); - let endDate = schedulerData.localeDayjs(startDate).add(1, 'week').format(DATE_FORMAT); - let cellUnit = CellUnit.Day; - if (viewType === ViewType.Custom) { - const monday = schedulerData.localeDayjs(selectDate).startOf('week').format(DATE_FORMAT); - startDate = num === 0 - ? monday - : schedulerData - .localeDayjs(monday) - .add(2 * num, 'weeks') - .format(DATE_FORMAT); - endDate = schedulerData.localeDayjs(startDate).add(12, 'months').endOf('week').format(DATE_FORMAT); - cellUnit = CellUnit.Week; - } else if (viewType === ViewType.Custom1) { - const firstDayOfMonth = schedulerData.localeDayjs(selectDate).startOf('month').format(DATE_FORMAT); - startDate = num === 0 - ? firstDayOfMonth - : schedulerData - .local2eMoment(firstDayOfMonth) - .add(2 * num, 'months') - .format(DATE_FORMAT); - endDate = schedulerData.localeDayjs(startDate).add(16, 'months').endOf('month').format(DATE_FORMAT); - cellUnit = CellUnit.Month; - } else if (viewType === ViewType.Custom2) { - const firstDayOfMonth = schedulerData.localeDayjs(selectDate).startOf('month').format(DATE_FORMAT); - startDate = num === 0 - ? firstDayOfMonth - : schedulerData - .localeDayjs(firstDayOfMonth) - .add(2 * num, 'months') - .format(DATE_FORMAT); - endDate = schedulerData.localeDayjs(startDate).add(60, 'months').endOf('month').format(DATE_FORMAT); - cellUnit = CellUnit.Year; - } - return { startDate, endDate, cellUnit }; - }; -} - -export default wrapperFun(CellUnitComponent); diff --git a/src/examples/ComingSoon.jsx b/src/examples/ComingSoon.jsx deleted file mode 100644 index a41f5c7..0000000 --- a/src/examples/ComingSoon.jsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { Result } from 'antd'; - -function ComingSoon() { - return ; -} - -export default ComingSoon; diff --git a/src/examples/CustomEventStyle.jsx b/src/examples/CustomEventStyle.jsx deleted file mode 100644 index 06a79bc..0000000 --- a/src/examples/CustomEventStyle.jsx +++ /dev/null @@ -1,177 +0,0 @@ -import React, { Component } from 'react'; -import { SchedulerData, ViewType, DemoData, Scheduler, wrapperFun } from '../components/index'; - -class CustomEventStyle extends Component { - constructor(props) { - super(props); - - const schedulerData = new SchedulerData('2022-12-18', ViewType.Week, false, false, { - views: [ - { viewName: 'Day(Agenda)', viewType: ViewType.Day, showAgenda: true, isEventPerspective: false }, - { viewName: 'Week', viewType: ViewType.Week, showAgenda: false, isEventPerspective: false }, - { viewName: 'Month(TaskView)', viewType: ViewType.Month, showAgenda: false, isEventPerspective: true }, - { viewName: 'Year', viewType: ViewType.Year, showAgenda: false, isEventPerspective: false }, - ], - }); - schedulerData.localeDayjs.locale('en'); - schedulerData.setResources(DemoData.resources); - schedulerData.setEvents(DemoData.eventsForCustomEventStyle); - this.state = { - viewModel: schedulerData, - }; - } - - render() { - const { viewModel } = this.state; - return ( -
-
-

Custom event style

- -
-
- ); - } - - prevClick = schedulerData => { - schedulerData.prev(); - schedulerData.setEvents(DemoData.eventsForCustomEventStyle); - this.setState({ - viewModel: schedulerData, - }); - }; - - nextClick = schedulerData => { - schedulerData.next(); - schedulerData.setEvents(DemoData.eventsForCustomEventStyle); - this.setState({ - viewModel: schedulerData, - }); - }; - - onViewChange = (schedulerData, view) => { - schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); - schedulerData.setEvents(DemoData.eventsForCustomEventStyle); - this.setState({ - viewModel: schedulerData, - }); - }; - - onSelectDate = (schedulerData, date) => { - schedulerData.setDate(date); - schedulerData.setEvents(DemoData.eventsForCustomEventStyle); - this.setState({ - viewModel: schedulerData, - }); - }; - - eventClicked = (schedulerData, event) => { - alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops1 = (schedulerData, event) => { - alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops2 = (schedulerData, event) => { - alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { - if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { - let newFreshId = 0; - schedulerData.eventsForCustomEventStyle?.forEach(item => { - if (item.id >= newFreshId) newFreshId = item.id + 1; - }); - - const newEvent = { - id: newFreshId, - title: 'New event you just created', - start, - end, - resourceId: slotId, - bgColor: 'purple', - }; - schedulerData.addEvent(newEvent); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - updateEventStart = (schedulerData, event, newStart) => { - if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { - schedulerData.updateEventStart(event, newStart); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - updateEventEnd = (schedulerData, event, newEnd) => { - if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { - schedulerData.updateEventEnd(event, newEnd); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - moveEvent = (schedulerData, event, slotId, slotName, start, end) => { - if ( - confirm( - `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` - ) - ) { - schedulerData.moveEvent(event, slotId, slotName, start, end); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - eventItemTemplateResolver = (schedulerData, event, bgColor, isStart, isEnd, mustAddCssClass, mustBeHeight, agendaMaxEventWidth) => { - const borderWidth = isStart ? '4' : '0'; - let borderColor = 'rgba(0,139,236,1)'; - let backgroundColor = '#80C5F6'; - const titleText = schedulerData.behaviors.getEventTextFunc(schedulerData, event); - if (event.type) { - borderColor = event.type === 1 ? 'rgba(0,139,236,1)' : event.type === 3 ? 'rgba(245,60,43,1)' : '#999'; - backgroundColor = event.type === 1 ? '#80C5F6' : event.type === 3 ? '#FA9E95' : '#D9D9D9'; - } - let divStyle = { borderLeft: `${borderWidth}px solid ${borderColor}`, backgroundColor, height: mustBeHeight }; - if (agendaMaxEventWidth) divStyle = { ...divStyle, maxWidth: agendaMaxEventWidth }; - - return ( -
- {titleText} -
- ); - }; - - toggleExpandFunc = (schedulerData, slotId) => { - schedulerData.toggleExpandStatus(slotId); - this.setState({ - viewModel: schedulerData, - }); - }; -} - -export default wrapperFun(CustomEventStyle); diff --git a/src/examples/CustomHeader.jsx b/src/examples/CustomHeader.jsx deleted file mode 100644 index be0eb5f..0000000 --- a/src/examples/CustomHeader.jsx +++ /dev/null @@ -1,164 +0,0 @@ -import React, { Component } from 'react'; -import { Scheduler, SchedulerData, ViewType, DemoData, wrapperFun } from '../components/index'; - -class CustomHeader extends Component { - constructor(props) { - super(props); - - const schedulerData = new SchedulerData('2022-12-18', ViewType.Week); - schedulerData.localeDayjs.locale('en'); - schedulerData.setResources(DemoData.resources); - schedulerData.setEvents(DemoData.events); - this.state = { - viewModel: schedulerData, - }; - } - - render() { - const { viewModel } = this.state; - - const leftCustomHeader = ( -
- Put your content here -
- ); - const rightCustomHeader = ( -
- or here -
- ); - - return ( -
-
-

Custom header

- -
-
- ); - } - - prevClick = schedulerData => { - schedulerData.prev(); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - nextClick = schedulerData => { - schedulerData.next(); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - onViewChange = (schedulerData, view) => { - schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - onSelectDate = (schedulerData, date) => { - schedulerData.setDate(date); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - eventClicked = (schedulerData, event) => { - alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops1 = (schedulerData, event) => { - alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops2 = (schedulerData, event) => { - alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { - if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { - let newFreshId = 0; - schedulerData.events.forEach(item => { - if (item.id >= newFreshId) newFreshId = item.id + 1; - }); - - const newEvent = { - id: newFreshId, - title: 'New event you just created', - start, - end, - resourceId: slotId, - bgColor: 'purple', - }; - schedulerData.addEvent(newEvent); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - updateEventStart = (schedulerData, event, newStart) => { - if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { - schedulerData.updateEventStart(event, newStart); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - updateEventEnd = (schedulerData, event, newEnd) => { - if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { - schedulerData.updateEventEnd(event, newEnd); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - moveEvent = (schedulerData, event, slotId, slotName, start, end) => { - if ( - confirm( - `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` - ) - ) { - schedulerData.moveEvent(event, slotId, slotName, start, end); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - toggleExpandFunc = (schedulerData, slotId) => { - schedulerData.toggleExpandStatus(slotId); - this.setState({ - viewModel: schedulerData, - }); - }; -} - -export default wrapperFun(CustomHeader); diff --git a/src/examples/CustomPopoverStyle.jsx b/src/examples/CustomPopoverStyle.jsx deleted file mode 100644 index 99d4fea..0000000 --- a/src/examples/CustomPopoverStyle.jsx +++ /dev/null @@ -1,198 +0,0 @@ -import React, { Component } from 'react'; -import { Col, Row, Button } from 'antd'; -import { Scheduler, SchedulerData, ViewType, DemoData, wrapperFun } from '../components/index'; - -class CustomPopoverStyle extends Component { - constructor(props) { - super(props); - - const schedulerData = new SchedulerData('2022-12-18', ViewType.Week); - schedulerData.localeDayjs.locale('en'); - schedulerData.setResources(DemoData.resources); - schedulerData.setEvents(DemoData.events); - this.state = { - viewModel: schedulerData, - }; - } - - render() { - const { viewModel } = this.state; - return ( -
-
-

Custom popover style example

- -
-
- ); - } - - prevClick = schedulerData => { - schedulerData.prev(); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - nextClick = schedulerData => { - schedulerData.next(); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - onViewChange = (schedulerData, view) => { - schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - onSelectDate = (schedulerData, date) => { - schedulerData.setDate(date); - schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); - }; - - eventClicked = (schedulerData, event) => { - alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops1 = (schedulerData, event) => { - alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops2 = (schedulerData, event) => { - alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { - if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { - let newFreshId = 0; - schedulerData.events.forEach(item => { - if (item.id >= newFreshId) newFreshId = item.id + 1; - }); - - const newEvent = { - id: newFreshId, - title: 'New event you just created', - start, - end, - resourceId: slotId, - bgColor: 'purple', - }; - schedulerData.addEvent(newEvent); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - updateEventStart = (schedulerData, event, newStart) => { - if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { - schedulerData.updateEventStart(event, newStart); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - updateEventEnd = (schedulerData, event, newEnd) => { - if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { - schedulerData.updateEventEnd(event, newEnd); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - moveEvent = (schedulerData, event, slotId, slotName, start, end) => { - if ( - confirm( - `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` - ) - ) { - schedulerData.moveEvent(event, slotId, slotName, start, end); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - eventItemPopoverTemplateResolver = (schedulerData, eventItem, title, start, end, statusColor) => ( -
- - -
- - - - {title} - - - - - -
- - - - {start.format('HH:mm')} - {' '} - - - {end.format('HH:mm')} - - - - - -
- - - - - -
- ); - - demoButtonClicked = eventItem => { - alert(`You just clicked demo button. event title: ${eventItem.title}`); - }; - - toggleExpandFunc = (schedulerData, slotId) => { - schedulerData.toggleExpandStatus(slotId); - this.setState({ - viewModel: schedulerData, - }); - }; -} - -export default wrapperFun(CustomPopoverStyle); diff --git a/src/examples/OverlapCheck.jsx b/src/examples/OverlapCheck.jsx deleted file mode 100644 index 7d281ef..0000000 --- a/src/examples/OverlapCheck.jsx +++ /dev/null @@ -1,142 +0,0 @@ -import React, { Component } from 'react'; -import { Scheduler, SchedulerData, ViewType, DemoData, wrapperFun } from '../components/index'; -import '../css/style.css'; - -class OverlapCheck extends Component { - constructor(props) { - super(props); - - const schedulerData = new SchedulerData('2022-12-18', ViewType.Week, false, false, { checkConflict: true }); - schedulerData.localeDayjs.locale('en'); - schedulerData.setResources(DemoData.resources); - schedulerData.setEvents(DemoData.events); - this.state = { viewModel: schedulerData }; - } - - render() { - const { viewModel } = this.state; - return ( -
-

Overlap check

- -
- ); - } - - prevClick = schedulerData => { - schedulerData.prev(); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - nextClick = schedulerData => { - schedulerData.next(); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - onViewChange = (schedulerData, view) => { - schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - onSelectDate = (schedulerData, date) => { - schedulerData.setDate(date); - schedulerData.setEvents(DemoData.events); - this.setState({ viewModel: schedulerData }); - }; - - eventClicked = (schedulerData, event) => { - alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops1 = (schedulerData, event) => { - alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - ops2 = (schedulerData, event) => { - alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); - }; - - newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { - if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { - let newFreshId = 0; - schedulerData.events.forEach(item => { - if (item.id >= newFreshId) newFreshId = item.id + 1; - }); - - const newEvent = { - id: newFreshId, - title: 'New event you just created', - start, - end, - resourceId: slotId, - bgColor: 'purple', - }; - schedulerData.addEvent(newEvent); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - updateEventStart = (schedulerData, event, newStart) => { - if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { - schedulerData.updateEventStart(event, newStart); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - updateEventEnd = (schedulerData, event, newEnd) => { - if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { - schedulerData.updateEventEnd(event, newEnd); - } - this.setState({ - viewModel: schedulerData, - }); - }; - - moveEvent = (schedulerData, event, slotId, slotName, start, end) => { - if ( - confirm( - `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` - ) - ) { - schedulerData.moveEvent(event, slotId, slotName, start, end); - this.setState({ - viewModel: schedulerData, - }); - } - }; - - conflictOccurred = (schedulerData, action, event, type, slotId, slotName, start, end) => { - alert(`Conflict occurred. {action: ${action}, event: ${event}`); - }; - - toggleExpandFunc = (schedulerData, slotId) => { - schedulerData.toggleExpandStatus(slotId); - this.setState({ viewModel: schedulerData }); - }; -} - -export default wrapperFun(OverlapCheck); diff --git a/src/examples/app.jsx b/src/examples/app.jsx new file mode 100644 index 0000000..d64920c --- /dev/null +++ b/src/examples/app.jsx @@ -0,0 +1,81 @@ +import { Result } from 'antd'; +import React, { Suspense, lazy } from 'react'; +import { createBrowserRouter, RouterProvider } from 'react-router-dom'; + +// Library Style +import '../css/style.css'; + +import './css/style.css'; + +import Fallback from './components/Fallback.jsx'; +import Landing from './components/Landing.jsx'; + +const Home = lazy(() => import('./pages/Home')); +const Basic = lazy(() => import('./pages/Basic')); +const ReadOnly = lazy(() => import('./pages/Read-Only')); +const AddMore = lazy(() => import('./pages/Add-More')); +const DragAndDrop = lazy(() => import('./pages/Drag-And-Drop')); + + +function App() { + const router = createBrowserRouter([ + { + path: '/', + element: , + children: [ + { + path: '/', + element: ( + }> + + + ), + }, + { + path: '/basic', + element: ( + }> + + + ), + }, + { + path: '/read-only', + element: ( + }> + + + ), + }, + { + path: '/add-more', + element: ( + }> + + + ), + }, + { + path: '/drag-and-drop', + element: ( + }> + + + ), + }, + { + path: '*', + element: , + }, + ], + }, + { + path: '*', + element: , + }, + ]); + + return ; +} + +export default App; diff --git a/src/examples/components/Fallback.jsx b/src/examples/components/Fallback.jsx new file mode 100644 index 0000000..bee5bf4 --- /dev/null +++ b/src/examples/components/Fallback.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Spin } from 'antd'; +import { LoadingOutlined } from '@ant-design/icons'; + +const antIcon = ; + +const Fallback = () => { + return ( +
+ +

Please wait while the component is being loaded.

+
+ ); +}; + +export default Fallback; diff --git a/src/examples/components/Header.jsx b/src/examples/components/Header.jsx new file mode 100644 index 0000000..9d3636f --- /dev/null +++ b/src/examples/components/Header.jsx @@ -0,0 +1,26 @@ +import { GithubOutlined } from '@ant-design/icons'; +import { Col, Row } from 'antd'; +import React from 'react'; +import { Link } from 'react-router-dom'; + +function Header() { + return ( + + + + Logo + + + + + npm-logo + + + + + + + ); +} + +export default Header; diff --git a/src/examples/components/Landing.jsx b/src/examples/components/Landing.jsx new file mode 100644 index 0000000..5a58bf2 --- /dev/null +++ b/src/examples/components/Landing.jsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Layout } from 'antd'; +import { Outlet } from 'react-router-dom'; +import Header from './Header'; +import Slider from './Slider'; + +function Landing() { + return ( + + +
+ + + + + + + + + + + ); +} + +export default Landing; diff --git a/src/examples/components/ResourceItem.jsx b/src/examples/components/ResourceItem.jsx new file mode 100644 index 0000000..e25cc42 --- /dev/null +++ b/src/examples/components/ResourceItem.jsx @@ -0,0 +1,9 @@ +import React from 'react'; + +function ResourceItem({ resource, isDragging, connectDragSource, connectDragPreview }) { + const dragContent =
  • {resource.name}
  • ; + + return isDragging ? null :
    {connectDragPreview(connectDragSource(dragContent))}
    ; +} + +export default ResourceItem; diff --git a/src/examples/components/ResourceList.jsx b/src/examples/components/ResourceList.jsx new file mode 100644 index 0000000..d939ae2 --- /dev/null +++ b/src/examples/components/ResourceList.jsx @@ -0,0 +1,16 @@ +import React from 'react'; + +function ResourceList({ schedulerData, newEvent, resourceDndSource }) { + const DnDResourceItem = resourceDndSource.getDragSource(); + const resources = schedulerData.resources; + + return ( +
      + {resources.map(resource => ( + + ))} +
    + ); +} + +export default ResourceList; diff --git a/src/examples/components/Slider.jsx b/src/examples/components/Slider.jsx new file mode 100644 index 0000000..0908aed --- /dev/null +++ b/src/examples/components/Slider.jsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Menu } from 'antd'; +import { useLocation, useNavigate } from 'react-router-dom'; + +const items = [ + { label: 'Home', key: 'home', path: '/' }, + { label: 'Basic', key: 'basic', path: '/basic' }, + { label: 'Read Only', key: 'read-only', path: '/read-only' }, + { label: 'Add More', key: 'add-more', path: '/add-more' }, + { label: 'Drag and Drop', key: 'drag-and-drop', path: '/drag-and-drop' }, +]; + +function Slider() { + const navigate = useNavigate(); + const { pathname } = useLocation(); + const activePath = pathname?.split('/')[1] || 'home'; + return ({ ...i, onClick: () => navigate(i.path) }))} />; +} + +export default Slider; diff --git a/src/examples/components/SourceCode.jsx b/src/examples/components/SourceCode.jsx new file mode 100644 index 0000000..ddd1552 --- /dev/null +++ b/src/examples/components/SourceCode.jsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { Row } from 'antd'; + +function SourceCode({ value }) { + return ( + + + </> Source Code + + + ); +} + +export default SourceCode; diff --git a/src/examples/components/TaskItem.jsx b/src/examples/components/TaskItem.jsx new file mode 100644 index 0000000..9a1d6a8 --- /dev/null +++ b/src/examples/components/TaskItem.jsx @@ -0,0 +1,9 @@ +import React from 'react'; + +function TaskItem({ task, isDragging, connectDragSource, connectDragPreview }) { + const dragContent =
  • {task.name}
  • ; + + return isDragging ? null : <>{connectDragPreview(connectDragSource(dragContent))}; +} + +export default TaskItem; diff --git a/src/examples/components/TaskList.jsx b/src/examples/components/TaskList.jsx new file mode 100644 index 0000000..1a3c0a2 --- /dev/null +++ b/src/examples/components/TaskList.jsx @@ -0,0 +1,16 @@ +import React from 'react'; + +function TaskList({ schedulerData, newEvent, taskDndSource }) { + const DnDTaskItem = taskDndSource.getDragSource(); + const tasks = schedulerData.eventGroups; + + return ( +
      + {tasks?.map(task => ( + + ))} +
    + ); +} + +export default TaskList; diff --git a/src/examples/css/style.css b/src/examples/css/style.css new file mode 100644 index 0000000..41e59f5 --- /dev/null +++ b/src/examples/css/style.css @@ -0,0 +1,164 @@ +/* Default Styling */ + +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); + +body { + margin: 0px; + font-family: 'Roboto', sans-serif; + font-size: 16px; + max-height: 100vh; + overflow: hidden; +} + +.m-0{ + margin: 0px; +} + +header { + text-align: center; + margin-bottom: 40px; +} + +.ant-layout-has-sider { + margin-bottom: 2px; +} + +.main-layout { + max-height: 100vh; + height: 100vh; + width: 100vw; + max-width: 100vw; + overflow: hidden; +} +.main-header { + background-color: #fff; + position: static !important; + margin-bottom: 0px; +} + +.main-content { + margin: 10px; + max-width: 100%; +} + +.ant-layout-header { + padding-inline: 30px; +} + +h1.header-title { + margin: 0px; + font-size: 2rem; + margin-bottom: 20px; +} + +.main_description { + .ant-typography { + font-weight: 500; + font-size: 1.25rem; + } +} + +.ant-layout-content { + height: 100%; + overflow: auto; +} + +::-webkit-scrollbar { + width: 0; + height: 0; +} + +::-webkit-scrollbar-track { + background-color: #f1f1f1; +} + +::-webkit-scrollbar-track:hover { + background-color: #eaeaea; +} + +::-webkit-scrollbar-thumb { + background-color: #888; +} + +::-webkit-scrollbar-thumb:hover { + background-color: #555; +} + +/* Header */ +.header-wrapper { + max-height: 64px; + overflow: hidden; +} + +.logo_img { + height: 60px; + cursor: pointer; +} + +.github-icon, +.npm-icon { + color: black; +} +.github-icon:hover { + color: gray; +} + +.github-icon svg, +.npm-icon img { + width: 35px; + height: 35px; +} + +.npm-icon { + margin-right: 20px; +} + +.title { + margin-bottom: 16px; + font-size: 32px; + font-weight: 700; +} + +.paragraph { + margin-bottom: 24px; + font-size: 18px; +} + +.button { + margin-top: 24px; +} + +section { + margin-bottom: 40px; +} + +ul { + list-style-type: disc; + margin-left: 24px; + margin-bottom: 16px; + font-size: 16px; +} + +ol { + list-style-type: decimal; + margin-left: 24px; + margin-bottom: 16px; + font-size: 16px; +} + +.pre { + background-color: #f7f7f7; + padding: 16px; + border-radius: 4px; +} + +.code { + font-family: monospace; +} + +/* Home page */ +.home-page { + max-width: 50vw; + margin: 0 auto; + padding: 10px 40px; +} diff --git a/src/examples/helpers/DnDTypes.js b/src/examples/helpers/DnDTypes.js new file mode 100644 index 0000000..beb4a01 --- /dev/null +++ b/src/examples/helpers/DnDTypes.js @@ -0,0 +1 @@ +export const DnDTypes = { TASK: 'task', RESOURCE: 'resource' }; \ No newline at end of file diff --git a/src/examples/index.jsx b/src/examples/index.jsx index bab5cc8..5a99f91 100644 --- a/src/examples/index.jsx +++ b/src/examples/index.jsx @@ -1,6 +1,5 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; -import Example from './Basic'; -import '../css/style.css'; +import App from './app'; -createRoot(document.getElementById('app')).render(); +createRoot(document.getElementById('app')).render(); diff --git a/src/examples/AddMore.jsx b/src/examples/pages/Add-More/class-based.jsx similarity index 94% rename from src/examples/AddMore.jsx rename to src/examples/pages/Add-More/class-based.jsx index a1bdfb7..7a854b7 100644 --- a/src/examples/AddMore.jsx +++ b/src/examples/pages/Add-More/class-based.jsx @@ -1,11 +1,13 @@ import React, { Component } from 'react'; -import { Scheduler, SchedulerData, ViewType, AddMorePopover, DemoData, wrapperFun } from '../components/index'; + +import { Scheduler, SchedulerData, ViewType, AddMorePopover, DemoData, wrapperFun } from '../../../index'; class AddMore extends Component { constructor(props) { super(props); - const schedulerData = new SchedulerData('2022-12-18', ViewType.Week, false, false, { + let schedulerData = new SchedulerData('2022-12-18', ViewType.Week, false, false, { + besidesWidth: 350, dayMaxEvents: 2, weekMaxEvents: 4, monthMaxEvents: 4, @@ -116,18 +118,18 @@ class AddMore extends Component { alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); }; - newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { + newEvent = (schedulerData, slotId = '', slotName = '', start = '', end = '', type = '', item = '') => { if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { let newFreshId = 0; schedulerData.events.forEach(item => { if (item.id >= newFreshId) newFreshId = item.id + 1; }); - const newEvent = { + let newEvent = { id: newFreshId, title: 'New event you just created', - start, - end, + start: start, + end: end, resourceId: slotId, bgColor: 'purple', }; diff --git a/src/examples/pages/Add-More/functional-based.jsx b/src/examples/pages/Add-More/functional-based.jsx new file mode 100644 index 0000000..6b86056 --- /dev/null +++ b/src/examples/pages/Add-More/functional-based.jsx @@ -0,0 +1,198 @@ +import React, { useEffect, useReducer, useState } from 'react'; +import { Scheduler, SchedulerData, ViewType, AddMorePopover, DemoData, wrapperFun } from '../../../index'; + +let schedulerData; + +const initialState = { + showScheduler: false, + viewModel: {}, +}; + +function reducer(state, action) { + switch (action.type) { + case 'INITIALIZE': + return { showScheduler: true, viewModel: action.payload }; + case 'UPDATE_SCHEDULER': + return { ...state, viewModel: action.payload }; + default: + return state; + } +} + +function AddMore() { + const [state, dispatch] = useReducer(reducer, initialState); + + const [popoverState, setPopoverState] = useState({ + headerItem: undefined, + left: 0, + top: 0, + height: 0, + }); + + useEffect(() => { + schedulerData = new SchedulerData('2022-12-18', ViewType.Week, false, false, { + besidesWidth: 350, + dayMaxEvents: 2, + weekMaxEvents: 4, + monthMaxEvents: 4, + quarterMaxEvents: 4, + yearMaxEvents: 4, + }); + schedulerData.localeDayjs.locale('en'); + schedulerData.setResources(DemoData.resources); + schedulerData.setEvents(DemoData.events); + + dispatch({ type: 'INITIALIZE', payload: schedulerData }); + }, []); + + const prevClick = schedulerData => { + schedulerData.prev(); + schedulerData.setEvents(DemoData.events); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const nextClick = schedulerData => { + schedulerData.next(); + schedulerData.setEvents(DemoData.events); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const onViewChange = (schedulerData, view) => { + schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); + schedulerData.setEvents(DemoData.events); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const onSelectDate = (schedulerData, date) => { + schedulerData.setDate(date); + schedulerData.setEvents(DemoData.events); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const eventClicked = (schedulerData, event) => { + alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); + }; + + const ops1 = (schedulerData, event) => { + alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + const ops2 = (schedulerData, event) => { + alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + const newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { + if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { + let newFreshId = 0; + schedulerData.events.forEach(item => { + if (item.id >= newFreshId) newFreshId = item.id + 1; + }); + + let newEvent = { + id: newFreshId, + title: 'New event you just created', + start: start, + end: end, + resourceId: slotId, + bgColor: 'purple', + }; + schedulerData.addEvent(newEvent); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + } + }; + + const updateEventStart = (schedulerData, event, newStart) => { + if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { + schedulerData.updateEventStart(event, newStart); + } + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const updateEventEnd = (schedulerData, event, newEnd) => { + if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { + schedulerData.updateEventEnd(event, newEnd); + } + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const moveEvent = (schedulerData, event, slotId, slotName, start, end) => { + if ( + confirm( + `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` + ) + ) { + schedulerData.moveEvent(event, slotId, slotName, start, end); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + } + }; + + const onSetAddMoreState = newState => { + if (newState === undefined) { + setPopoverState({ + headerItem: undefined, + left: 0, + top: 0, + height: 0, + }); + } else { + setPopoverState({ + ...newState, + }); + } + }; + + const toggleExpandFunc = (schedulerData, slotId) => { + schedulerData.toggleExpandStatus(slotId); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + let popover =
    ; + if (popoverState.headerItem !== undefined) { + popover = ( + + ); + } + + return ( + <> + {state.showScheduler && ( +
    + + {popover} +
    + )} + + ); +} + +export default wrapperFun(AddMore); diff --git a/src/examples/pages/Add-More/index.jsx b/src/examples/pages/Add-More/index.jsx new file mode 100644 index 0000000..eb67bd8 --- /dev/null +++ b/src/examples/pages/Add-More/index.jsx @@ -0,0 +1,20 @@ +import { Row, Typography } from 'antd'; +import React from 'react'; +import ClassBased from './class-based'; +import SourceCode from '../../components/SourceCode'; + +function Basic() { + return ( + <> + + + Add More Example + + + + + + ); +} + +export default Basic; diff --git a/src/examples/Basic.jsx b/src/examples/pages/Basic/class-based.jsx similarity index 80% rename from src/examples/Basic.jsx rename to src/examples/pages/Basic/class-based.jsx index 7e906f8..4e27091 100644 --- a/src/examples/Basic.jsx +++ b/src/examples/pages/Basic/class-based.jsx @@ -1,14 +1,15 @@ -import React, { Component } from 'react'; -import * as dayjsLocale from 'dayjs/locale/pt-br'; import * as antdLocale from 'antd/locale/pt_BR'; +import * as dayjsLocale from 'dayjs/locale/pt-br'; +import React, { Component } from 'react'; -import { Scheduler, SchedulerData, ViewType, DemoData, wrapperFun } from '../index'; +import { DemoData, Scheduler, SchedulerData, ViewType, wrapperFun } from '../../../index'; class Basic extends Component { constructor(props) { super(props); - const schedulerData = new SchedulerData('2022-12-02', ViewType.Month, false, false, { + let schedulerData = new SchedulerData('2022-12-22', ViewType.Week, false, false, { + besidesWidth: 300, dayMaxEvents: 99, weekMaxEvents: 9669, monthMaxEvents: 9669, @@ -16,7 +17,7 @@ class Basic extends Component { yearMaxEvents: 9956, customMaxEvents: 9965, eventItemPopoverTrigger: 'click', - schedulerContentHeight: '350px', + schedulerContentHeight: '100%', }); schedulerData.setSchedulerLocale(dayjsLocale); @@ -37,7 +38,6 @@ class Basic extends Component { nextClick={this.nextClick} onSelectDate={this.onSelectDate} onViewChange={this.onViewChange} - // eventItemClick={this.eventClicked} viewEventClick={this.ops1} viewEventText="Ops 1" viewEvent2Text="Ops 2" @@ -73,11 +73,11 @@ class Basic extends Component { schedulerData.setEvents(DemoData.events); this.setState({ viewModel: schedulerData }); function secondsBetween(date1, date2) { - const diff = Math.abs(date1.getTime() - date2.getTime()); + var diff = Math.abs(date1.getTime() - date2.getTime()); return diff / 1000; } - console.log(`Elapsed seconds: ${secondsBetween(start, new Date())}`); + console.log('Elapsed seconds: ' + secondsBetween(start, new Date())); }; onSelectDate = (schedulerData, date) => { @@ -107,18 +107,16 @@ class Basic extends Component { if (item.id >= newFreshId) newFreshId = item.id + 1; }); - const newEvent = { + let newEvent = { id: newFreshId, title: 'New event you just created', - start, - end, + start: start, + end: end, resourceId: slotId, bgColor: 'purple', }; schedulerData.addEvent(newEvent); - this.setState({ - viewModel: schedulerData, - }); + this.setState({ viewModel: schedulerData }); } }; @@ -126,18 +124,14 @@ class Basic extends Component { if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { schedulerData.updateEventStart(event, newStart); } - this.setState({ - viewModel: schedulerData, - }); + this.setState({ viewModel: schedulerData }); }; updateEventEnd = (schedulerData, event, newEnd) => { if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { schedulerData.updateEventEnd(event, newEnd); } - this.setState({ - viewModel: schedulerData, - }); + this.setState({ viewModel: schedulerData }); }; moveEvent = (schedulerData, event, slotId, slotName, start, end) => { @@ -147,9 +141,7 @@ class Basic extends Component { ) ) { schedulerData.moveEvent(event, slotId, slotName, start, end); - this.setState({ - viewModel: schedulerData, - }); + this.setState({ viewModel: schedulerData }); } }; @@ -157,39 +149,29 @@ class Basic extends Component { if (schedulerData.ViewTypes === ViewType.Day) { schedulerData.next(); schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); + this.setState({ viewModel: schedulerData }); schedulerContent.scrollLeft = maxScrollLeft - 10; } }; - onScrollLeft = (schedulerData, schedulerContent, maxScrollLeft) => { + onScrollLeft = (schedulerData, schedulerContent) => { if (schedulerData.ViewTypes === ViewType.Day) { schedulerData.prev(); schedulerData.setEvents(DemoData.events); - this.setState({ - viewModel: schedulerData, - }); + this.setState({ viewModel: schedulerData }); schedulerContent.scrollLeft = 10; } }; - onScrollTop = (schedulerData, schedulerContent, maxScrollTop) => { - console.log('onScrollTop'); - }; + onScrollTop = () => console.log('onScrollTop'); - onScrollBottom = (schedulerData, schedulerContent, maxScrollTop) => { - console.log('onScrollBottom'); - }; + onScrollBottom = () => console.log('onScrollBottom'); toggleExpandFunc = (schedulerData, slotId) => { schedulerData.toggleExpandStatus(slotId); - this.setState({ - viewModel: schedulerData, - }); + this.setState({ viewModel: schedulerData }); }; } diff --git a/src/examples/pages/Basic/index.jsx b/src/examples/pages/Basic/index.jsx new file mode 100644 index 0000000..c7fb357 --- /dev/null +++ b/src/examples/pages/Basic/index.jsx @@ -0,0 +1,18 @@ +import { Row, Typography } from 'antd'; +import React from 'react'; +import ClassBased from './class-based'; +import SourceCode from '../../components/SourceCode'; + +function Basic() { + return ( + <> + + Basic Example + + + + + ); +} + +export default Basic; diff --git a/src/examples/pages/Drag-And-Drop/class-based.jsx b/src/examples/pages/Drag-And-Drop/class-based.jsx new file mode 100644 index 0000000..812a741 --- /dev/null +++ b/src/examples/pages/Drag-And-Drop/class-based.jsx @@ -0,0 +1,209 @@ +import { Col, Row, Typography } from 'antd'; +import React, { Component } from 'react'; +import { DemoData, DnDSource, Scheduler, SchedulerData, ViewType, wrapperFun } from '../../../index'; +import ResourceItem from '../../components/ResourceItem.jsx'; +import ResourceList from '../../components/ResourceList.jsx'; +import TaskItem from '../../components/TaskItem.jsx'; +import TaskList from '../../components/TaskList.jsx'; +import { DnDTypes } from '../../helpers/DnDTypes.js'; + +class DragAndDrop extends Component { + constructor(props) { + super(props); + + let schedulerData = new SchedulerData('2022-12-18', ViewType.Month, false, false, { + schedulerMaxHeight: 500, + besidesWidth: window.innerWidth <= 1600 ? 400 : 500, + views: [ + { viewName: 'Agenda View', viewType: ViewType.Month, showAgenda: true, isEventPerspective: false }, + { viewName: 'Resource View', viewType: ViewType.Month, showAgenda: false, isEventPerspective: false }, + { viewName: 'Task View', viewType: ViewType.Month, showAgenda: false, isEventPerspective: true }, + ], + }); + schedulerData.localeDayjs.locale('en'); + schedulerData.setResources(DemoData.resources); + schedulerData.setEvents(DemoData.eventsForTaskView); + this.state = { + viewModel: schedulerData, + taskDndSource: new DnDSource(props => props.task, TaskItem, true, DnDTypes.TASK), + resourceDndSource: new DnDSource(props => props.resource, ResourceItem, true, DnDTypes.RESOURCE), + }; + } + + render() { + const { viewModel, taskDndSource, resourceDndSource } = this.state; + + return ( +
    + + + {viewModel.isEventPerspective + ? 'Drag a resource from outside and drop to the resource view.' + : 'Drag a task from outside and drop to the resource view'} + + + + + + + + {viewModel.isEventPerspective ? ( + + ) : ( + + )} + + +
    + ); + } + prevClick = schedulerData => { + schedulerData.prev(); + schedulerData.setEvents(DemoData.eventsForTaskView); + this.setState({ + viewModel: schedulerData, + }); + }; + + nextClick = schedulerData => { + schedulerData.next(); + schedulerData.setEvents(DemoData.eventsForTaskView); + this.setState({ + viewModel: schedulerData, + }); + }; + + onViewChange = (schedulerData, view) => { + schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); + schedulerData.config.creatable = !view.isEventPerspective; + schedulerData.setEvents(DemoData.eventsForTaskView); + this.setState({ + viewModel: schedulerData, + }); + }; + + onSelectDate = (schedulerData, date) => { + schedulerData.setDate(date); + schedulerData.setEvents(DemoData.eventsForTaskView); + this.setState({ + viewModel: schedulerData, + }); + }; + + eventClicked = (schedulerData, event) => { + alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); + }; + + ops1 = (schedulerData, event) => { + alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + ops2 = (schedulerData, event) => { + alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { + if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { + let newFreshId = 0; + schedulerData.events.forEach(item => { + if (item.id >= newFreshId) newFreshId = item.id + 1; + }); + + let newEvent = { + id: newFreshId, + title: 'New event you just created', + start: start, + end: end, + resourceId: slotId, + bgColor: 'purple', + }; + + if (type === DnDTypes.RESOURCE) { + newEvent = { + ...newEvent, + groupId: slotId, + groupName: slotName, + resourceId: item.id, + }; + } else if (type === DnDTypes.TASK) { + newEvent = { + ...newEvent, + groupId: item.id, + groupName: item.name, + }; + } + + schedulerData.addEvent(newEvent); + this.setState({ + viewModel: schedulerData, + }); + } + }; + + updateEventStart = (schedulerData, event, newStart) => { + if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { + schedulerData.updateEventStart(event, newStart); + } + this.setState({ + viewModel: schedulerData, + }); + }; + + updateEventEnd = (schedulerData, event, newEnd) => { + if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { + schedulerData.updateEventEnd(event, newEnd); + } + this.setState({ + viewModel: schedulerData, + }); + }; + + moveEvent = (schedulerData, event, slotId, slotName, start, end) => { + if ( + confirm( + `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` + ) + ) { + schedulerData.moveEvent(event, slotId, slotName, start, end); + this.setState({ + viewModel: schedulerData, + }); + } + }; + + movingEvent = (schedulerData, slotId, slotName, newStart, newEnd, action, type, item) => { + console.log('moving event', schedulerData, slotId, slotName, newStart, newEnd, action, type, item); + }; + + subtitleGetter = (schedulerData, event) => { + return schedulerData.isEventPerspective ? schedulerData.getResourceById(event.resourceId).name : event.groupName; + }; + + toggleExpandFunc = (schedulerData, slotId) => { + schedulerData.toggleExpandStatus(slotId); + this.setState({ + viewModel: schedulerData, + }); + }; +} + +export default wrapperFun(DragAndDrop); diff --git a/src/examples/pages/Drag-And-Drop/functional-based.jsx b/src/examples/pages/Drag-And-Drop/functional-based.jsx new file mode 100644 index 0000000..06b564f --- /dev/null +++ b/src/examples/pages/Drag-And-Drop/functional-based.jsx @@ -0,0 +1,213 @@ +import { Col, Row, Typography } from 'antd'; +import React, { useEffect, useReducer, useState } from 'react'; +import { DemoData, DnDSource, Scheduler, SchedulerData, ViewType, wrapperFun } from '../../../index'; +import ResourceItem from '../../components/ResourceItem'; +import ResourceList from '../../components/ResourceList'; +import TaskItem from '../../components/TaskItem'; +import TaskList from '../../components/TaskList'; +import { DnDTypes } from '../../helpers/DnDTypes'; + +const initialState = { + showScheduler: false, + viewModel: {}, +}; + +function reducer(state, action) { + switch (action.type) { + case 'INITIALIZE': + return { showScheduler: true, viewModel: action.payload }; + case 'UPDATE_SCHEDULER': + return { ...state, viewModel: action.payload }; + default: + return state; + } +} + +let schedulerData; +function DragAndDrop() { + const [state, dispatch] = useReducer(reducer, initialState); + const [taskDndSource, setTaskDndSource] = useState(new DnDSource(props => props.task, TaskItem, true, DnDTypes.TASK)); + const [resourceDndSource, setResourceDndSource] = useState(new DnDSource(props => props.resource, ResourceItem, true, DnDTypes.RESOURCE)); + + useEffect(() => { + schedulerData = new SchedulerData('2022-12-18', ViewType.Month, false, false, { + schedulerMaxHeight: 500, + besidesWidth: window.innerWidth <= 1600 ? 400 : 500, + views: [ + { viewName: 'Agenda View', viewType: ViewType.Month, showAgenda: true, isEventPerspective: false }, + { viewName: 'Resource View', viewType: ViewType.Month, showAgenda: false, isEventPerspective: false }, + { viewName: 'Task View', viewType: ViewType.Month, showAgenda: false, isEventPerspective: true }, + ], + }); + schedulerData.localeDayjs.locale('en'); + schedulerData.setResources(DemoData.resources); + schedulerData.setEvents(DemoData.eventsForTaskView); + + dispatch({ type: 'INITIALIZE', payload: schedulerData }); + setTaskDndSource(new DnDSource(props => props.task, TaskItem, true, DnDTypes.TASK)); + setResourceDndSource(new DnDSource(props => props.resource, ResourceItem, true, DnDTypes.RESOURCE)); + + return () => { + schedulerData = null; + }; + }, []); + + const prevClick = schedulerData => { + schedulerData.prev(); + schedulerData.setEvents(DemoData.eventsForTaskView); + this.setState({ viewModel: schedulerData }); + }; + + const nextClick = schedulerData => { + schedulerData.next(); + schedulerData.setEvents(DemoData.eventsForTaskView); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const onViewChange = (schedulerData, view) => { + schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); + schedulerData.config.creatable = !view.isEventPerspective; + schedulerData.setEvents(DemoData.eventsForTaskView); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const onSelectDate = (schedulerData, date) => { + schedulerData.setDate(date); + schedulerData.setEvents(DemoData.eventsForTaskView); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const eventClicked = (schedulerData, event) => { + alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); + }; + + const ops1 = (schedulerData, event) => { + alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + const ops2 = (schedulerData, event) => { + alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + const newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { + if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { + let newFreshId = 0; + schedulerData.events.forEach(item => { + if (item.id >= newFreshId) newFreshId = item.id + 1; + }); + + let newEvent = { + id: newFreshId, + title: 'New event you just created', + start: start, + end: end, + resourceId: slotId, + bgColor: 'purple', + }; + + if (type === DnDTypes.RESOURCE) { + newEvent = { + ...newEvent, + groupId: slotId, + groupName: slotName, + resourceId: item.id, + }; + } else if (type === DnDTypes.TASK) { + newEvent = { + ...newEvent, + groupId: item.id, + groupName: item.name, + }; + } + + schedulerData.addEvent(newEvent); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + } + }; + + const updateEventStart = (schedulerData, event, newStart) => { + if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { + schedulerData.updateEventStart(event, newStart); + } + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const updateEventEnd = (schedulerData, event, newEnd) => { + if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { + schedulerData.updateEventEnd(event, newEnd); + } + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + const moveEvent = (schedulerData, event, slotId, slotName, start, end) => { + if ( + confirm( + `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` + ) + ) { + schedulerData.moveEvent(event, slotId, slotName, start, end); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + } + }; + + const movingEvent = (schedulerData, slotId, slotName, newStart, newEnd, action, type, item) => { + console.log('moving event', schedulerData, slotId, slotName, newStart, newEnd, action, type, item); + }; + + const subtitleGetter = (schedulerData, event) => { + return schedulerData.isEventPerspective ? schedulerData.getResourceById(event.resourceId).name : event.groupName; + }; + + const toggleExpandFunc = (schedulerData, slotId) => { + schedulerData.toggleExpandStatus(slotId); + dispatch({ type: 'UPDATE_SCHEDULER', payload: schedulerData }); + }; + + return ( + <> + {state.showScheduler && ( + <> + + + {state.showScheduler && + (state.viewModel?.isEventPerspective ? 'Drag a resource from outside and drop to the resource view.' : 'Drag a task from outside and drop to the resource view')} + + + + + + + + {state.viewModel.isEventPerspective ? ( + + ) : ( + + )} + + + + )} + + ); +} + +export default wrapperFun(DragAndDrop); diff --git a/src/examples/pages/Drag-And-Drop/index.jsx b/src/examples/pages/Drag-And-Drop/index.jsx new file mode 100644 index 0000000..4cc03b5 --- /dev/null +++ b/src/examples/pages/Drag-And-Drop/index.jsx @@ -0,0 +1,20 @@ +import { Row, Typography } from 'antd'; +import React from 'react'; +import ClassBased from './class-based'; +import SourceCode from '../../components/SourceCode'; + +function Basic() { + return ( + <> + + + Drag and Drop Example + + + + + + ); +} + +export default Basic; diff --git a/src/examples/pages/Home.jsx b/src/examples/pages/Home.jsx new file mode 100644 index 0000000..aa9e820 --- /dev/null +++ b/src/examples/pages/Home.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Typography, Button } from 'antd'; +import { useNavigate } from 'react-router-dom'; + +const { Title, Paragraph } = Typography; + +const Home = () => { + const navigate = useNavigate(); + return ( +
    +
    + React Big Schedule + + React Big Schedule is a powerful and intuitive scheduler and resource planning solution built with React. Seamlessly integrate this modern, browser-compatible component + into your applications to effectively manage time, appointments, and resources. With drag-and-drop functionality, interactive UI, and granular views, React Big Schedule + empowers you to effortlessly schedule and allocate resources with precision. + + +
    +
    + ); +}; + +export default Home; diff --git a/src/examples/pages/Read-Only/class-based.jsx b/src/examples/pages/Read-Only/class-based.jsx new file mode 100644 index 0000000..216aebf --- /dev/null +++ b/src/examples/pages/Read-Only/class-based.jsx @@ -0,0 +1,93 @@ +import React, { Component } from 'react'; + +import { Scheduler, SchedulerData, ViewType, DemoData, wrapperFun } from '../../../index'; + +class Readonly extends Component { + constructor(props) { + super(props); + + let schedulerData = new SchedulerData('2022-12-22', ViewType.Week, false, false, { + besidesWidth: 350, + startResizable: false, + endResizable: false, + movable: false, + creatable: false, + }); + schedulerData.localeDayjs.locale('en'); + schedulerData.setResources(DemoData.resources); + schedulerData.setEvents(DemoData.events); + this.state = { + viewModel: schedulerData, + }; + } + + render() { + const { viewModel } = this.state; + return ( + + ); + } + + prevClick = schedulerData => { + schedulerData.prev(); + schedulerData.setEvents(DemoData.events); + this.setState({ + viewModel: schedulerData, + }); + }; + + nextClick = schedulerData => { + schedulerData.next(); + schedulerData.setEvents(DemoData.events); + this.setState({ + viewModel: schedulerData, + }); + }; + + onViewChange = (schedulerData, view) => { + schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); + schedulerData.setEvents(DemoData.events); + this.setState({ + viewModel: schedulerData, + }); + }; + + onSelectDate = (schedulerData, date) => { + schedulerData.setDate(date); + schedulerData.setEvents(DemoData.events); + this.setState({ + viewModel: schedulerData, + }); + }; + + eventClicked = (schedulerData, event) => { + alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); + }; + + ops1 = (schedulerData, event) => { + alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + ops2 = (schedulerData, event) => { + alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + toggleExpandFunc = (schedulerData, slotId) => { + schedulerData.toggleExpandStatus(slotId); + this.setState({ viewModel: schedulerData }); + }; +} + +export default wrapperFun(Readonly); diff --git a/src/examples/pages/Read-Only/index.jsx b/src/examples/pages/Read-Only/index.jsx new file mode 100644 index 0000000..8d6cb04 --- /dev/null +++ b/src/examples/pages/Read-Only/index.jsx @@ -0,0 +1,18 @@ +import { Row, Typography } from 'antd'; +import React from 'react'; +import ClassBased from './class-based'; +import SourceCode from '../../components/SourceCode'; + +function Basic() { + return ( + <> + + Read Only Example + + + + + ); +} + +export default Basic; diff --git a/src/index.html b/src/index.html index 5bde2c5..35c76ae 100644 --- a/src/index.html +++ b/src/index.html @@ -6,6 +6,7 @@ + React Big Schedule diff --git a/src/index.js b/src/index.js index 5bd85d3..bb451cd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,14 +1,14 @@ export { + AddMorePopover, + CellUnit, DATE_FORMAT, DATETIME_FORMAT, + DnDContext, + DnDSource, + DemoData, Scheduler, SchedulerData, - ViewType, - CellUnit, SummaryPos, - DnDSource, - DnDContext, - AddMorePopover, - DemoData, + ViewType, wrapperFun, } from './components/index'; diff --git a/src/main.jsx b/src/main.jsx deleted file mode 100644 index f996a7e..0000000 --- a/src/main.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './examples/AddMore'; -import './css/style.css'; - -ReactDOM.createRoot(document.getElementById('root')).render(); diff --git a/webpack/webpack.dev.config.js b/webpack/webpack.dev.config.js index f590e1e..ba1b28a 100644 --- a/webpack/webpack.dev.config.js +++ b/webpack/webpack.dev.config.js @@ -8,6 +8,7 @@ module.exports = { output: { path: path.resolve(__dirname, '..', 'dist'), filename: 'bundle.js', + publicPath: '/', }, module: { rules: [ @@ -20,6 +21,10 @@ module.exports = { test: /\.css$/, use: ['style-loader', 'css-loader'], }, + { + test: /\.(png|jpg|jpeg|gif|svg)$/i, + type: 'asset/resource', + }, ], }, resolve: { @@ -27,11 +32,12 @@ module.exports = { }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', title: 'React Big Schedule' }), - new ESLintWebpackPlugin({ emitError: true, emitWarning: false, failOnError: true, extensions: ['js', 'jsx'] }), + new ESLintWebpackPlugin({ emitError: false, emitWarning: false, failOnError: false, extensions: ['js', 'jsx'] }), ], devServer: { - static: { directory: path.join(__dirname, '..', 'dist') }, + static: { directory: path.join(__dirname, '..', 'public') }, compress: true, port: 8080, + historyApiFallback: true, }, }; From 546790e09aa6162dbe880b95b81722e429063ac5 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sat, 12 Oct 2024 04:02:09 +0530 Subject: [PATCH 02/17] Updated Build Script and Change from webpack to vite --- .gitignore | 2 +- src/index.html => index.html | 15 ++++++----- package.json | 36 ++++++++++++------------- scripts/{build.js => build.cjs} | 0 src/examples/components/Header.jsx | 7 +++-- src/examples/index.jsx | 3 +-- vite.config.js | 7 +++++ webpack/webpack.dev.config.js | 43 ------------------------------ 8 files changed, 39 insertions(+), 74 deletions(-) rename src/index.html => index.html (51%) rename scripts/{build.js => build.cjs} (100%) create mode 100644 vite.config.js delete mode 100644 webpack/webpack.dev.config.js diff --git a/.gitignore b/.gitignore index 9d574f4..265f50c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ pnpm-debug.log* lerna-debug.log* node_modules +dist dist-ssr *.local @@ -21,6 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? -dist package-lock.json \ No newline at end of file diff --git a/src/index.html b/index.html similarity index 51% rename from src/index.html rename to index.html index 35c76ae..19e63eb 100644 --- a/src/index.html +++ b/index.html @@ -1,15 +1,16 @@ - - - - - - + + + React Big Schedule + + + -
    +
    + diff --git a/package.json b/package.json index ad58e79..d1f81a9 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "README.md", "License" ], + "type": "module", "main": "dist/index.js", "homepage": "https://react-big-schedule.vercel.app", "repository": { @@ -52,45 +53,42 @@ "registry": "https://registry.npmjs.org/" }, "scripts": { - "build": "node scripts/build.js", - "start": "webpack serve --mode development --config ./webpack/webpack.dev.config.js", + "start": "vite", + "build": "vite build", + "build-lib": "node scripts/build.cjs", "clean": "rimraf ./dist && mkdir dist", - "lint": "eslint ./src", - "fix": "eslint ./" + "lint": "eslint ./src" }, "dependencies": { "@ant-design/icons": "^5.5.1", - "antd": "^5.21.2", + "@babel/cli": "^7.25.7", + "antd": "^5.21.3", "dayjs": "^1.11.13", "prop-types": "^15.8.1", "react": "^18.3.1", "react-dnd": "^14.0.5", "react-dnd-html5-backend": "^14.1.0", "react-dom": "^18.3.1", - "react-router-dom": "^6.26.2", + "react-router-dom": "^6.27.0", "rrule": "^2.8.1" }, "devDependencies": { - "@babel/cli": "^7.25.7", - "@babel/core": "^7.25.7", - "@babel/eslint-parser": "^7.25.7", - "@babel/preset-env": "^7.25.7", + "@babel/core": "^7.25.8", + "@babel/preset-env": "^7.25.8", "@babel/preset-react": "^7.25.7", - "babel-loader": "^9.2.1", - "copy-webpack-plugin": "^12.0.2", - "css-loader": "^7.1.2", + "@eslint/js": "^9.11.1", + "@types/react": "^18.3.10", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.2", + "babel-plugin-transform-runtime": "^6.23.0", "eslint": "^8.2.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.1", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-webpack-plugin": "^4.2.0", "fs-extra": "^11.2.0", - "html-webpack-plugin": "^5.6.0", - "style-loader": "^4.0.0", - "webpack": "^5.95.0", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.1.0" + "globals": "^15.9.0", + "vite": "^5.4.8" } } diff --git a/scripts/build.js b/scripts/build.cjs similarity index 100% rename from scripts/build.js rename to scripts/build.cjs diff --git a/src/examples/components/Header.jsx b/src/examples/components/Header.jsx index 9d3636f..1cd6b94 100644 --- a/src/examples/components/Header.jsx +++ b/src/examples/components/Header.jsx @@ -3,17 +3,20 @@ import { Col, Row } from 'antd'; import React from 'react'; import { Link } from 'react-router-dom'; +import logo from '/logo.png'; +import npm from '/npm.svg'; + function Header() { return ( - Logo + Logo - npm-logo + npm-logo diff --git a/src/examples/index.jsx b/src/examples/index.jsx index 5a99f91..f6f6c70 100644 --- a/src/examples/index.jsx +++ b/src/examples/index.jsx @@ -1,5 +1,4 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; import App from './app'; - -createRoot(document.getElementById('app')).render(); +createRoot(document.getElementById('root')).render(); diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..5a33944 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/webpack/webpack.dev.config.js b/webpack/webpack.dev.config.js deleted file mode 100644 index ba1b28a..0000000 --- a/webpack/webpack.dev.config.js +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const ESLintWebpackPlugin = require('eslint-webpack-plugin'); - -module.exports = { - entry: './src/examples/index.jsx', - output: { - path: path.resolve(__dirname, '..', 'dist'), - filename: 'bundle.js', - publicPath: '/', - }, - module: { - rules: [ - { - test: /\.(js|jsx)$/, - exclude: /node_modules/, - use: { loader: 'babel-loader' }, - }, - { - test: /\.css$/, - use: ['style-loader', 'css-loader'], - }, - { - test: /\.(png|jpg|jpeg|gif|svg)$/i, - type: 'asset/resource', - }, - ], - }, - resolve: { - extensions: ['.js', '.jsx'], - }, - plugins: [ - new HtmlWebpackPlugin({ template: './src/index.html', title: 'React Big Schedule' }), - new ESLintWebpackPlugin({ emitError: false, emitWarning: false, failOnError: false, extensions: ['js', 'jsx'] }), - ], - devServer: { - static: { directory: path.join(__dirname, '..', 'public') }, - compress: true, - port: 8080, - historyApiFallback: true, - }, -}; From 37ea63ebd717edbdb7e78d76536102bd800c5819 Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Fri, 11 Oct 2024 22:32:46 +0000 Subject: [PATCH 03/17] [CodeFactor] Apply fixes to commit 546790e [ci skip] [skip ci] --- vite.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vite.config.js b/vite.config.js index 5a33944..627a319 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,7 +1,7 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], -}) +}); From f8e2b038230a9ef4c95f3228003031a0f6cab4e7 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sat, 12 Oct 2024 04:03:35 +0530 Subject: [PATCH 04/17] Added semicolons to end of import statements and closing bracket in vite.config.js. --- vite.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vite.config.js b/vite.config.js index 5a33944..627a319 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,7 +1,7 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], -}) +}); From 13af7c94e125375fa4946acd3df0c25b154edd83 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sat, 12 Oct 2024 04:09:19 +0530 Subject: [PATCH 05/17] "Replace 'var' with 'const' in secondsBetween function" --- src/examples/pages/Basic/class-based.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/pages/Basic/class-based.jsx b/src/examples/pages/Basic/class-based.jsx index 4e27091..34c2391 100644 --- a/src/examples/pages/Basic/class-based.jsx +++ b/src/examples/pages/Basic/class-based.jsx @@ -73,7 +73,7 @@ class Basic extends Component { schedulerData.setEvents(DemoData.events); this.setState({ viewModel: schedulerData }); function secondsBetween(date1, date2) { - var diff = Math.abs(date1.getTime() - date2.getTime()); + const diff = Math.abs(date1.getTime() - date2.getTime()); return diff / 1000; } From f76de6e073cbc6fe6c2e9f1f77fa4531c8f0a0c9 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sun, 13 Oct 2024 01:35:29 +0530 Subject: [PATCH 06/17] Added Custom Time Example --- src/examples/app.jsx | 9 + src/examples/components/Slider.jsx | 1 + .../pages/Custom-Time/class-based.jsx | 185 ++++++++++++++++++ src/examples/pages/Custom-Time/index.jsx | 20 ++ 4 files changed, 215 insertions(+) create mode 100644 src/examples/pages/Custom-Time/class-based.jsx create mode 100644 src/examples/pages/Custom-Time/index.jsx diff --git a/src/examples/app.jsx b/src/examples/app.jsx index d64920c..7cd0143 100644 --- a/src/examples/app.jsx +++ b/src/examples/app.jsx @@ -15,6 +15,7 @@ const Basic = lazy(() => import('./pages/Basic')); const ReadOnly = lazy(() => import('./pages/Read-Only')); const AddMore = lazy(() => import('./pages/Add-More')); const DragAndDrop = lazy(() => import('./pages/Drag-And-Drop')); +const CustomTime = lazy(() => import('./pages/Custom-Time')); function App() { @@ -63,6 +64,14 @@ function App() { ), }, + { + path: '/custom-time', + element: ( + }> + + + ), + }, { path: '*', element: , diff --git a/src/examples/components/Slider.jsx b/src/examples/components/Slider.jsx index 0908aed..fa7141d 100644 --- a/src/examples/components/Slider.jsx +++ b/src/examples/components/Slider.jsx @@ -8,6 +8,7 @@ const items = [ { label: 'Read Only', key: 'read-only', path: '/read-only' }, { label: 'Add More', key: 'add-more', path: '/add-more' }, { label: 'Drag and Drop', key: 'drag-and-drop', path: '/drag-and-drop' }, + { label: 'Custom Time', key: 'custom-time', path: '/custom-time' }, ]; function Slider() { diff --git a/src/examples/pages/Custom-Time/class-based.jsx b/src/examples/pages/Custom-Time/class-based.jsx new file mode 100644 index 0000000..2dfd969 --- /dev/null +++ b/src/examples/pages/Custom-Time/class-based.jsx @@ -0,0 +1,185 @@ +import * as antdLocale from 'antd/locale/pt_BR'; +import * as dayjsLocale from 'dayjs/locale/pt-br'; +import React, { Component } from 'react'; + +import { DemoData, Scheduler, SchedulerData, ViewType, wrapperFun } from '../../../index'; + +const startHr = 8; + +class CustomTime extends Component { + constructor(props) { + super(props); + + let schedulerData = new SchedulerData( + '2022-12-22', + ViewType.Day, + false, + false, + { + besidesWidth: 300, + dayMaxEvents: 99, + dayStartFrom: 8, + dayStopTo: 18, + customMaxEvents: 9965, + eventItemPopoverTrigger: 'click', + schedulerContentHeight: '100%', + views: [], + }, + ); + + schedulerData.setSchedulerLocale(dayjsLocale); + schedulerData.setCalendarPopoverLocale(antdLocale); + schedulerData.setResources(DemoData.resources); + schedulerData.setEvents(DemoData.events); + this.state = { + viewModel: schedulerData, + }; + } + + render() { + const { viewModel } = this.state; + return ( + + ); + } + + prevClick = schedulerData => { + schedulerData.prev(); + schedulerData.setEvents(DemoData.events); + this.setState({ viewModel: schedulerData }); + }; + + nextClick = schedulerData => { + schedulerData.next(); + schedulerData.setEvents(DemoData.events); + this.setState({ viewModel: schedulerData }); + }; + + onViewChange = (schedulerData, view) => { + const start = new Date(); + schedulerData.setViewType(view.viewType, view.showAgenda, view.isEventPerspective); + schedulerData.setEvents(DemoData.events); + this.setState({ viewModel: schedulerData }); + function secondsBetween(date1, date2) { + const diff = Math.abs(date1.getTime() - date2.getTime()); + return diff / 1000; + } + + console.log('Elapsed seconds: ' + secondsBetween(start, new Date())); + }; + + onSelectDate = (schedulerData, date) => { + schedulerData.setDate(date); + schedulerData.setEvents(DemoData.events); + this.setState({ + viewModel: schedulerData, + }); + }; + + eventClicked = (schedulerData, event) => { + alert(`You just clicked an event: {id: ${event.id}, title: ${event.title}}`); + }; + + ops1 = (schedulerData, event) => { + alert(`You just executed ops1 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + ops2 = (schedulerData, event) => { + alert(`You just executed ops2 to event: {id: ${event.id}, title: ${event.title}}`); + }; + + newEvent = (schedulerData, slotId, slotName, start, end, type, item) => { + if (confirm(`Do you want to create a new event? {slotId: ${slotId}, slotName: ${slotName}, start: ${start}, end: ${end}, type: ${type}, item: ${item}}`)) { + let newFreshId = 0; + schedulerData.events.forEach(item => { + if (item.id >= newFreshId) newFreshId = item.id + 1; + }); + + let newEvent = { + id: newFreshId, + title: 'New event you just created', + start: start, + end: end, + resourceId: slotId, + bgColor: 'purple', + }; + schedulerData.addEvent(newEvent); + this.setState({ viewModel: schedulerData }); + } + }; + + updateEventStart = (schedulerData, event, newStart) => { + if (confirm(`Do you want to adjust the start of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newStart: ${newStart}}`)) { + schedulerData.updateEventStart(event, newStart); + } + this.setState({ viewModel: schedulerData }); + }; + + updateEventEnd = (schedulerData, event, newEnd) => { + if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { + schedulerData.updateEventEnd(event, newEnd); + } + this.setState({ viewModel: schedulerData }); + }; + + moveEvent = (schedulerData, event, slotId, slotName, start, end) => { + if ( + confirm( + `Do you want to move the event? {eventId: ${event.id}, eventTitle: ${event.title}, newSlotId: ${slotId}, newSlotName: ${slotName}, newStart: ${start}, newEnd: ${end}` + ) + ) { + schedulerData.moveEvent(event, slotId, slotName, start, end); + this.setState({ viewModel: schedulerData }); + } + }; + + onScrollRight = (schedulerData, schedulerContent, maxScrollLeft) => { + if (schedulerData.ViewTypes === ViewType.Day) { + schedulerData.next(); + schedulerData.setEvents(DemoData.events); + this.setState({ viewModel: schedulerData }); + + schedulerContent.scrollLeft = maxScrollLeft - 10; + } + }; + + onScrollLeft = (schedulerData, schedulerContent) => { + if (schedulerData.ViewTypes === ViewType.Day) { + schedulerData.prev(); + schedulerData.setEvents(DemoData.events); + this.setState({ viewModel: schedulerData }); + + schedulerContent.scrollLeft = 10; + } + }; + + onScrollTop = () => console.log('onScrollTop'); + + onScrollBottom = () => console.log('onScrollBottom'); + + toggleExpandFunc = (schedulerData, slotId) => { + schedulerData.toggleExpandStatus(slotId); + this.setState({ viewModel: schedulerData }); + }; +} + +export default wrapperFun(CustomTime); diff --git a/src/examples/pages/Custom-Time/index.jsx b/src/examples/pages/Custom-Time/index.jsx new file mode 100644 index 0000000..bf7cb02 --- /dev/null +++ b/src/examples/pages/Custom-Time/index.jsx @@ -0,0 +1,20 @@ +import { Row, Typography } from 'antd'; +import React from 'react'; +import ClassBased from './class-based'; +import SourceCode from '../../components/SourceCode'; + +function CustomTime() { + return ( + <> + + + Custom Time Example + + + + + + ); +} + +export default CustomTime; From aa491c9c16c548cb2bc7096da6b3063ac3c20f5e Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sun, 13 Oct 2024 01:46:47 +0530 Subject: [PATCH 07/17] Added Vercel Configuration --- vercel.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 vercel.json diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..572a48d --- /dev/null +++ b/vercel.json @@ -0,0 +1,3 @@ +{ + "rewrites": [{ "source": "/(.*)", "destination": "/" }] +} \ No newline at end of file From 67363f4d83b14c1320c71896834f80d6ae5ed792 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sun, 13 Oct 2024 01:58:35 +0530 Subject: [PATCH 08/17] Create eslint.yml --- .github/workflows/eslint.yml | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/eslint.yml diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml new file mode 100644 index 0000000..cadb26d --- /dev/null +++ b/.github/workflows/eslint.yml @@ -0,0 +1,52 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# ESLint is a tool for identifying and reporting on patterns +# found in ECMAScript/JavaScript code. +# More details at https://github.com/eslint/eslint +# and https://eslint.org + +name: ESLint + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '32 18 * * 4' + +jobs: + eslint: + name: Run eslint scanning + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install ESLint + run: | + npm install eslint@8.10.0 + npm install @microsoft/eslint-formatter-sarif@3.1.0 + + - name: Run ESLint + env: + SARIF_ESLINT_IGNORE_SUPPRESSED: "true" + run: npx eslint . + --config .eslintrc.js + --ext .js,.jsx,.ts,.tsx + --format @microsoft/eslint-formatter-sarif + --output-file eslint-results.sarif + continue-on-error: true + + - name: Upload analysis results to GitHub + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: eslint-results.sarif + wait-for-processing: true From 8f10a20507f325a1da1897f5cfd748f954495abe Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sun, 13 Oct 2024 02:03:09 +0530 Subject: [PATCH 09/17] Update eslint.yml --- .github/workflows/eslint.yml | 51 ------------------------------------ 1 file changed, 51 deletions(-) diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index cadb26d..8b13789 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -1,52 +1 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# ESLint is a tool for identifying and reporting on patterns -# found in ECMAScript/JavaScript code. -# More details at https://github.com/eslint/eslint -# and https://eslint.org -name: ESLint - -on: - push: - branches: [ "master" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "master" ] - schedule: - - cron: '32 18 * * 4' - -jobs: - eslint: - name: Run eslint scanning - runs-on: ubuntu-latest - permissions: - contents: read - security-events: write - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install ESLint - run: | - npm install eslint@8.10.0 - npm install @microsoft/eslint-formatter-sarif@3.1.0 - - - name: Run ESLint - env: - SARIF_ESLINT_IGNORE_SUPPRESSED: "true" - run: npx eslint . - --config .eslintrc.js - --ext .js,.jsx,.ts,.tsx - --format @microsoft/eslint-formatter-sarif - --output-file eslint-results.sarif - continue-on-error: true - - - name: Upload analysis results to GitHub - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: eslint-results.sarif - wait-for-processing: true From d0089d6d449843428bd59c5e5b7d761295c3fd33 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Sun, 13 Oct 2024 02:05:24 +0530 Subject: [PATCH 10/17] "Deleted .github/workflows/eslint.yml file" --- .github/workflows/eslint.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/workflows/eslint.yml diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml deleted file mode 100644 index 8b13789..0000000 --- a/.github/workflows/eslint.yml +++ /dev/null @@ -1 +0,0 @@ - From 0c34f5577dbd330e1a62847a40faede45af98424 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Fri, 25 Oct 2024 17:48:54 +0530 Subject: [PATCH 11/17] Change Typo of dragtype to dragType. Fix End Drag Issue --- src/components/EventItem.jsx | 51 ++++++++++++------------ src/examples/pages/Basic/class-based.jsx | 12 +++--- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/components/EventItem.jsx b/src/components/EventItem.jsx index 71834bc..b17e817 100644 --- a/src/components/EventItem.jsx +++ b/src/components/EventItem.jsx @@ -5,7 +5,7 @@ import { Popover } from 'antd'; import EventItemPopover from './EventItemPopover'; import { DnDTypes, CellUnit, DATETIME_FORMAT } from '../config/default'; -const stopDragHelper = ({ count, cellUnit, config, dragtype, eventItem, localeDayjs, value }) => { +const stopDragHelper = ({ count, cellUnit, config, dragType, eventItem, localeDayjs, value }) => { const whileTrue = true; let tCount = 0; let i = 0; @@ -14,7 +14,7 @@ const stopDragHelper = ({ count, cellUnit, config, dragtype, eventItem, localeDa if (count !== 0 && cellUnit !== CellUnit.Hour && config.displayWeekend === false) { while (whileTrue) { i = count > 0 ? i + 1 : i - 1; - const date = localeDayjs(new Date(eventItem[dragtype])).add(i, 'days'); + const date = localeDayjs(new Date(eventItem[dragType])).add(i, 'days'); const dayOfWeek = date.weekday(); if (dayOfWeek !== 0 && dayOfWeek !== 6) { @@ -30,15 +30,17 @@ const stopDragHelper = ({ count, cellUnit, config, dragtype, eventItem, localeDa }); }; -const startResizable = ({ eventItem, isInPopover, schedulerData }) => schedulerData.config.startResizable === true - && isInPopover === false - && (eventItem.resizable === undefined || eventItem.resizable !== false) - && (eventItem.startResizable === undefined || eventItem.startResizable !== false); +const startResizable = ({ eventItem, isInPopover, schedulerData }) => + schedulerData.config.startResizable === true && + isInPopover === false && + (eventItem.resizable === undefined || eventItem.resizable !== false) && + (eventItem.startResizable === undefined || eventItem.startResizable !== false); -const endResizable = ({ eventItem, isInPopover, schedulerData }) => schedulerData.config.endResizable === true - && isInPopover === false - && (eventItem.resizable === undefined || eventItem.resizable !== false) - && (eventItem.endResizable === undefined || eventItem.endResizable !== false); +const endResizable = ({ eventItem, isInPopover, schedulerData }) => + schedulerData.config.endResizable === true && + isInPopover === false && + (eventItem.resizable === undefined || eventItem.resizable !== false) && + (eventItem.endResizable === undefined || eventItem.endResizable !== false); class EventItem extends Component { constructor(props) { @@ -70,11 +72,11 @@ class EventItem extends Component { } } - resizerHelper = (dragtype, eventType = 'addEventListener') => { - const resizer = dragtype === 'start' ? this.startResizer : this.endResizer; - const doDrag = dragtype === 'start' ? this.doStartDrag : this.doEndDrag; - const stopDrag = dragtype === 'start' ? this.stopStartDrag : this.stopEndDrag; - const cancelDrag = dragtype === 'start' ? this.cancelStartDrag : this.cancelEndDrag; + resizerHelper = (dragType, eventType = 'addEventListener') => { + const resizer = dragType === 'start' ? this.startResizer : this.endResizer; + const doDrag = dragType === 'start' ? this.doStartDrag : this.doEndDrag; + const stopDrag = dragType === 'start' ? this.stopStartDrag : this.stopEndDrag; + const cancelDrag = dragType === 'start' ? this.cancelStartDrag : this.cancelEndDrag; if (this.supportTouch) { resizer[eventType]('touchmove', doDrag, false); resizer[eventType]('touchend', stopDrag, false); @@ -85,7 +87,7 @@ class EventItem extends Component { } }; - initDragHelper = (ev, dragtype) => { + initDragHelper = (ev, dragType) => { const { schedulerData, eventItem } = this.props; const slotId = schedulerData._getEventSlotId(eventItem); const slot = schedulerData.getSlotById(slotId); @@ -102,10 +104,10 @@ class EventItem extends Component { if (ev.buttons !== undefined && ev.buttons !== 1) return; clientX = ev.clientX; } - this.setState({ [dragtype === 'start' ? 'startX' : 'endX']: clientX }); + this.setState({ [dragType === 'start' ? 'startX' : 'endX']: clientX }); schedulerData._startResizing(); - this.resizerHelper(dragtype, 'addEventListener'); + this.resizerHelper(dragType, 'addEventListener'); document.onselectstart = () => false; document.ondragstart = () => false; }; @@ -192,7 +194,7 @@ class EventItem extends Component { config, eventItem, localeDayjs, - dragtype: 'start', + dragType: 'start', value: newStart, }); @@ -317,7 +319,7 @@ class EventItem extends Component { .add(cellUnit === CellUnit.Hour ? count * config.minuteStep : count, cellUnit === CellUnit.Hour ? 'minutes' : 'days') .format(DATETIME_FORMAT); newEnd = await stopDragHelper({ - dragtype: 'start', + dragType: 'end', cellUnit, config, count, @@ -351,7 +353,7 @@ class EventItem extends Component { if (conflictOccurred !== undefined) { conflictOccurred(schedulerData, 'EndResize', eventItem, DnDTypes.EVENT, slotId, slot ? slot.name : null, eventItem.start, newEnd); } else { - console.log('Conflict occurred, set conflictOccurred func in Scheduler to handle it'); + console.error('Conflict occurred, set conflictOccurred func in Scheduler to handle it'); } this.subscribeResizeEvent(this.props); } else if (updateEventEnd !== undefined) { @@ -448,8 +450,7 @@ class EventItem extends Component { style={{ left, width, top }} onClick={() => { if (eventItemClick) eventItemClick(schedulerData, eventItem); - }} - > + }}> {eventItemTemplate} {startResizeDiv} {endResizeDiv} @@ -506,8 +507,7 @@ class EventItem extends Component { placement={isPopoverPlacementMousePosition ? mousePositionPlacement : popoverPlacement} content={content} trigger={config.eventItemPopoverTrigger} - overlayClassName="scheduler-event-item-popover" - > + overlayClassName="scheduler-event-item-popover"> {aItem} ); @@ -515,6 +515,7 @@ class EventItem extends Component { } export default EventItem; + EventItem.propTypes = { schedulerData: PropTypes.object.isRequired, eventItem: PropTypes.object.isRequired, diff --git a/src/examples/pages/Basic/class-based.jsx b/src/examples/pages/Basic/class-based.jsx index 34c2391..8530e63 100644 --- a/src/examples/pages/Basic/class-based.jsx +++ b/src/examples/pages/Basic/class-based.jsx @@ -1,5 +1,5 @@ -import * as antdLocale from 'antd/locale/pt_BR'; -import * as dayjsLocale from 'dayjs/locale/pt-br'; +// import * as antdLocale from 'antd/locale/pt_BR'; +// import * as dayjsLocale from 'dayjs/locale/pt-br'; import React, { Component } from 'react'; import { DemoData, Scheduler, SchedulerData, ViewType, wrapperFun } from '../../../index'; @@ -10,6 +10,7 @@ class Basic extends Component { let schedulerData = new SchedulerData('2022-12-22', ViewType.Week, false, false, { besidesWidth: 300, + responsiveByParent: true, dayMaxEvents: 99, weekMaxEvents: 9669, monthMaxEvents: 9669, @@ -17,11 +18,11 @@ class Basic extends Component { yearMaxEvents: 9956, customMaxEvents: 9965, eventItemPopoverTrigger: 'click', - schedulerContentHeight: '100%', + displayWeekend: false, }); - schedulerData.setSchedulerLocale(dayjsLocale); - schedulerData.setCalendarPopoverLocale(antdLocale); + // schedulerData.setSchedulerLocale(dayjsLocale); + // schedulerData.setCalendarPopoverLocale(antdLocale); schedulerData.setResources(DemoData.resources); schedulerData.setEvents(DemoData.events); this.state = { @@ -129,6 +130,7 @@ class Basic extends Component { updateEventEnd = (schedulerData, event, newEnd) => { if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { + console.log(event, newEnd); schedulerData.updateEventEnd(event, newEnd); } this.setState({ viewModel: schedulerData }); From fbb6aeff2271371cd5e169be00c9fc3270cb3288 Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Fri, 25 Oct 2024 12:31:52 +0000 Subject: [PATCH 12/17] [CodeFactor] Apply fixes to commit 0c34f55 [ci skip] [skip ci] --- src/components/EventItem.jsx | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/EventItem.jsx b/src/components/EventItem.jsx index b17e817..bf7fc30 100644 --- a/src/components/EventItem.jsx +++ b/src/components/EventItem.jsx @@ -30,17 +30,15 @@ const stopDragHelper = ({ count, cellUnit, config, dragType, eventItem, localeDa }); }; -const startResizable = ({ eventItem, isInPopover, schedulerData }) => - schedulerData.config.startResizable === true && - isInPopover === false && - (eventItem.resizable === undefined || eventItem.resizable !== false) && - (eventItem.startResizable === undefined || eventItem.startResizable !== false); - -const endResizable = ({ eventItem, isInPopover, schedulerData }) => - schedulerData.config.endResizable === true && - isInPopover === false && - (eventItem.resizable === undefined || eventItem.resizable !== false) && - (eventItem.endResizable === undefined || eventItem.endResizable !== false); +const startResizable = ({ eventItem, isInPopover, schedulerData }) => schedulerData.config.startResizable === true + && isInPopover === false + && (eventItem.resizable === undefined || eventItem.resizable !== false) + && (eventItem.startResizable === undefined || eventItem.startResizable !== false); + +const endResizable = ({ eventItem, isInPopover, schedulerData }) => schedulerData.config.endResizable === true + && isInPopover === false + && (eventItem.resizable === undefined || eventItem.resizable !== false) + && (eventItem.endResizable === undefined || eventItem.endResizable !== false); class EventItem extends Component { constructor(props) { @@ -450,7 +448,8 @@ class EventItem extends Component { style={{ left, width, top }} onClick={() => { if (eventItemClick) eventItemClick(schedulerData, eventItem); - }}> + }} + > {eventItemTemplate} {startResizeDiv} {endResizeDiv} @@ -507,7 +506,8 @@ class EventItem extends Component { placement={isPopoverPlacementMousePosition ? mousePositionPlacement : popoverPlacement} content={content} trigger={config.eventItemPopoverTrigger} - overlayClassName="scheduler-event-item-popover"> + overlayClassName="scheduler-event-item-popover" + > {aItem} ); From ab36b2092e1e8d8e2929a5a93c793be1969ed580 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Fri, 25 Oct 2024 18:02:45 +0530 Subject: [PATCH 13/17] Change back the example --- src/examples/pages/Basic/class-based.jsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/examples/pages/Basic/class-based.jsx b/src/examples/pages/Basic/class-based.jsx index 8530e63..764c3ec 100644 --- a/src/examples/pages/Basic/class-based.jsx +++ b/src/examples/pages/Basic/class-based.jsx @@ -1,5 +1,5 @@ -// import * as antdLocale from 'antd/locale/pt_BR'; -// import * as dayjsLocale from 'dayjs/locale/pt-br'; +import * as antdLocale from 'antd/locale/pt_BR'; +import * as dayjsLocale from 'dayjs/locale/pt-br'; import React, { Component } from 'react'; import { DemoData, Scheduler, SchedulerData, ViewType, wrapperFun } from '../../../index'; @@ -10,7 +10,6 @@ class Basic extends Component { let schedulerData = new SchedulerData('2022-12-22', ViewType.Week, false, false, { besidesWidth: 300, - responsiveByParent: true, dayMaxEvents: 99, weekMaxEvents: 9669, monthMaxEvents: 9669, @@ -18,11 +17,11 @@ class Basic extends Component { yearMaxEvents: 9956, customMaxEvents: 9965, eventItemPopoverTrigger: 'click', - displayWeekend: false, + schedulerContentHeight: '100%', }); - // schedulerData.setSchedulerLocale(dayjsLocale); - // schedulerData.setCalendarPopoverLocale(antdLocale); + schedulerData.setSchedulerLocale(dayjsLocale); + schedulerData.setCalendarPopoverLocale(antdLocale); schedulerData.setResources(DemoData.resources); schedulerData.setEvents(DemoData.events); this.state = { @@ -130,7 +129,6 @@ class Basic extends Component { updateEventEnd = (schedulerData, event, newEnd) => { if (confirm(`Do you want to adjust the end of the event? {eventId: ${event.id}, eventTitle: ${event.title}, newEnd: ${newEnd}}`)) { - console.log(event, newEnd); schedulerData.updateEventEnd(event, newEnd); } this.setState({ viewModel: schedulerData }); @@ -177,4 +175,4 @@ class Basic extends Component { }; } -export default wrapperFun(Basic); +export default wrapperFun(Basic); \ No newline at end of file From cd3b313ecd81103cc5633ce4d5bf14ae27f184a1 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Fri, 25 Oct 2024 18:08:32 +0530 Subject: [PATCH 14/17] 4.4.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1f81a9..67b10ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-big-schedule", - "version": "4.4.1", + "version": "4.4.2", "description": "React Big Schedule is a powerful and intuitive scheduler and resource planning solution built with React. Seamlessly integrate this modern browser-compatible component into your applications to effectively manage time, appointments, and resources. With drag-and-drop functionality, interactive UI, and granular views, react-big-schedule empowers users to effortlessly schedule and allocate resources with precision. Enhance productivity and streamline your workflow with this React-based solution, designed to optimize time management and simplify calendar-based operations. Perfect for applications requiring advanced scheduling capabilities, react-big-schedule offers a seamless and intuitive experience for managing appointments, resource allocation, and time slots. Unlock the potential of your React projects with react-big-schedule and revolutionize the way you handle scheduling and resource planning. It is the updated version of react-big-scheduler", "keywords": [ "react-big-schedule", From 5b9f8664fb034bd925f59ca6155d29c4f82ec185 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Fri, 25 Oct 2024 18:16:07 +0530 Subject: [PATCH 15/17] Updated Change Log File --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2701db4..bced895 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,16 @@ +## [4.4.2](https://github.com/react-scheduler/react-big-schedule/compare/4.4.1...4.4.2) +`2024-10-25` + +- Fixed typo of `dragtype` to `dragType` by [@ansulagrawal](https://github.com/ansulagrawal) in [#171](https://github.com/react-scheduler/react-big-schedule/pull/171). +- Fixed `End Drag` bug [#167](https://github.com/react-scheduler/react-big-schedule/issues/167) by [@ansulagrawal](https://github.com/ansulagrawal) in [#171](https://github.com/react-scheduler/react-big-schedule/pull/171), thanks to [@Navid-gh](https://github.com/Navid-gh) for raising a bug. + ## [4.4.1](https://github.com/react-scheduler/react-big-schedule/compare/4.4.0...4.4.1) `2024-10-06` - Fix `CHANGELOG.MD` file. - Removed `default` keyword from Scheduler Class in `typing/index.d.ts` file of typescript by [@ansulagrawal](https://github.com/ansulagrawal) in [#154](https://github.com/react-scheduler/react-big-schedule/pull/154). - Updated utcOffset method calls to pass `new Date()` instead of `new Date().utcOffset` by [@ansulagrawal](https://github.com/ansulagrawal) in [#155](https://github.com/react-scheduler/react-big-schedule/pull/155). --Updated `node_modules` version by [@ansulagrawal](https://github.com/ansulagrawal). +- Updated `node_modules` version by [@ansulagrawal](https://github.com/ansulagrawal). ## [4.4.0](https://github.com/react-scheduler/react-big-schedule/compare/4.3.3...4.4.0) From 5cdd4f884140ae8adb69d0e3103c93642bd6cd94 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Fri, 25 Oct 2024 18:18:19 +0530 Subject: [PATCH 16/17] "Removed extra space in CHANGELOG.md" --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bced895..f9f764f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ `2024-10-25` - Fixed typo of `dragtype` to `dragType` by [@ansulagrawal](https://github.com/ansulagrawal) in [#171](https://github.com/react-scheduler/react-big-schedule/pull/171). -- Fixed `End Drag` bug [#167](https://github.com/react-scheduler/react-big-schedule/issues/167) by [@ansulagrawal](https://github.com/ansulagrawal) in [#171](https://github.com/react-scheduler/react-big-schedule/pull/171), thanks to [@Navid-gh](https://github.com/Navid-gh) for raising a bug. +- Fixed `End Drag` bug [#167](https://github.com/react-scheduler/react-big-schedule/issues/167) by [@ansulagrawal](https://github.com/ansulagrawal) in [#171](https://github.com/react-scheduler/react-big-schedule/pull/171), thanks to [@Navid-gh](https://github.com/Navid-gh) for raising a bug. ## [4.4.1](https://github.com/react-scheduler/react-big-schedule/compare/4.4.0...4.4.1) `2024-10-06` From 49782fbd25517cb852952a6dc092b75eeeb3b389 Mon Sep 17 00:00:00 2001 From: Ansul Agrawal Date: Fri, 25 Oct 2024 18:21:54 +0530 Subject: [PATCH 17/17] "Added 'Change Logs:' header to CHANGELOG.md" --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f764f..76b2067 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +# Change Logs: + ## [4.4.2](https://github.com/react-scheduler/react-big-schedule/compare/4.4.1...4.4.2) `2024-10-25`